mirror of
https://github.com/stronk-dev/RandomChad.git
synced 2025-07-05 02:35:08 +02:00
✨ changin room email notification system
This commit is contained in:
parent
0b47dfb4cb
commit
2db757e2f4
@ -20,3 +20,9 @@ exports.mainnetMetadata = functions.runWith( runtime ).https.onRequest( mainnetA
|
|||||||
const { handleQueuedRocketeerOutfit } = require( './nft-media/changing-room' )
|
const { handleQueuedRocketeerOutfit } = require( './nft-media/changing-room' )
|
||||||
exports.mainnetGenerateOutfitsOnQueue = functions.runWith( runtime ).firestore.document( `mainnetQueueOutfitGeneration/{rocketeerId}` ).onWrite( handleQueuedRocketeerOutfit )
|
exports.mainnetGenerateOutfitsOnQueue = functions.runWith( runtime ).firestore.document( `mainnetQueueOutfitGeneration/{rocketeerId}` ).onWrite( handleQueuedRocketeerOutfit )
|
||||||
exports.rinkebyGenerateOutfitsOnQueue = functions.runWith( runtime ).firestore.document( `rinkebyQueueOutfitGeneration/{rocketeerId}` ).onWrite( handleQueuedRocketeerOutfit )
|
exports.rinkebyGenerateOutfitsOnQueue = functions.runWith( runtime ).firestore.document( `rinkebyQueueOutfitGeneration/{rocketeerId}` ).onWrite( handleQueuedRocketeerOutfit )
|
||||||
|
|
||||||
|
/* ///////////////////////////////
|
||||||
|
// Daemons
|
||||||
|
// /////////////////////////////*/
|
||||||
|
const { notify_holders_of_changing_room_updates } = require( './integrations/changingroom' )
|
||||||
|
exports.notify_holders_of_changing_room_updates = functions.pubsub.schedule( '0 0 * * *' ).onRun( notify_holders_of_changing_room_updates )
|
@ -1,5 +1,8 @@
|
|||||||
const { generateNewOutfitFromId, queueRocketeersOfAddressForOutfitChange } = require( '../nft-media/changing-room' )
|
const { generateNewOutfitFromId, queueRocketeersOfAddressForOutfitChange } = require( '../nft-media/changing-room' )
|
||||||
const { db, dataFromSnap } = require( '../modules/firebase' )
|
const { db, dataFromSnap, FieldPath } = require( '../modules/firebase' )
|
||||||
|
const { dev, log } = require( '../modules/helpers' )
|
||||||
|
const { ask_signer_is_for_available_emails } = require( './signer_is' )
|
||||||
|
const { send_outfit_available_email } = require( './ses' )
|
||||||
|
|
||||||
// Web3 APIs
|
// Web3 APIs
|
||||||
const { getOwingAddressOfTokenId } = require( '../modules/contract' )
|
const { getOwingAddressOfTokenId } = require( '../modules/contract' )
|
||||||
@ -197,4 +200,71 @@ exports.setPrimaryOutfit = async function( req, res ) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ///////////////////////////////
|
||||||
|
// Notify of changing room updates
|
||||||
|
// /////////////////////////////*/
|
||||||
|
exports.notify_holders_of_changing_room_updates = async context => {
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Get all Rocketeers with outfits available
|
||||||
|
const network = dev ? `rinkeby` : `mainnet`
|
||||||
|
const limit = dev ? 50 : 2000
|
||||||
|
log( `Getting ${ limit } rocketeers on ${ network }` )
|
||||||
|
const all_rocketeers = await db.collection( `${ network }Rocketeers` )
|
||||||
|
.limit( limit ).get().then( dataFromSnap )
|
||||||
|
log( `Got ${ all_rocketeers.length } Rocketeers` )
|
||||||
|
const has_outfit_available = all_rocketeers.filter( rocketeer => {
|
||||||
|
|
||||||
|
const { attributes } = rocketeer
|
||||||
|
const outfit_available = attributes.find( ( { trait_type } ) => trait_type == 'last outfit change' )
|
||||||
|
// If outfit available is in the past, keep it
|
||||||
|
if( outfit_available?.value < Date.now() ) return true
|
||||||
|
|
||||||
|
// If outfit available in the future, discard
|
||||||
|
return false
|
||||||
|
|
||||||
|
} )
|
||||||
|
|
||||||
|
const owners = await Promise.all( has_outfit_available.map( async ( { uid } ) => {
|
||||||
|
log( `Getting owner of `, uid )
|
||||||
|
const owning_address = await getOwingAddressOfTokenId( uid )
|
||||||
|
return { uid, owning_address }
|
||||||
|
} ) )
|
||||||
|
|
||||||
|
const owners_with_signer_email = await ask_signer_is_for_available_emails( owners.map( ( { owning_address } ) => owning_address ) )
|
||||||
|
|
||||||
|
const rocketeers_by_address = has_outfit_available.reduce( ( wallets, rocketeer ) => {
|
||||||
|
|
||||||
|
const new_wallet_list = { ...wallets }
|
||||||
|
const { owning_address } = owners.find( ( { uid } ) => uid == rocketeer.uid )
|
||||||
|
|
||||||
|
// If this owner has no email, ignore it
|
||||||
|
if( !owners_with_signer_email.includes( owning_address ) ) return new_wallet_list
|
||||||
|
|
||||||
|
// If the wallet object does now have this one yet, add an empty array
|
||||||
|
if( !new_wallet_list[ owning_address ] ) new_wallet_list[owning_address] = []
|
||||||
|
|
||||||
|
new_wallet_list[owning_address] = [ ...new_wallet_list[owning_address], rocketeer ]
|
||||||
|
return new_wallet_list
|
||||||
|
|
||||||
|
}, {} )
|
||||||
|
|
||||||
|
const owners_to_email = Object.keys( rocketeers_by_address )
|
||||||
|
|
||||||
|
// Send emails to the relevant owners
|
||||||
|
await Promise.all( owners_to_email.map( async owning_address => {
|
||||||
|
|
||||||
|
const rocketeers = rocketeers_by_address[ owning_address ]
|
||||||
|
await send_outfit_available_email( rocketeers, `${ owning_address }@signer.is` )
|
||||||
|
|
||||||
|
} ) )
|
||||||
|
|
||||||
|
|
||||||
|
} catch( e ) {
|
||||||
|
console.error( `notify_holders_of_changing_room_updates error: `, e )
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
70
functions/integrations/ses.js
Normal file
70
functions/integrations/ses.js
Normal file
@ -0,0 +1,70 @@
|
|||||||
|
const AWS = require('aws-sdk')
|
||||||
|
const functions = require( 'firebase-functions' )
|
||||||
|
const { aws } = functions.config()
|
||||||
|
const { log } = require( '../modules/helpers' )
|
||||||
|
const SES_CONFIG = {
|
||||||
|
accessKeyId: aws?.ses?.keyid,
|
||||||
|
secretAccessKey: aws?.ses?.secretkey,
|
||||||
|
region: aws?.ses?.region,
|
||||||
|
}
|
||||||
|
const AWS_SES = new AWS.SES( SES_CONFIG )
|
||||||
|
|
||||||
|
// Email templates
|
||||||
|
const pug = require('pug')
|
||||||
|
const { promises: fs } = require( 'fs' )
|
||||||
|
const csso = require('csso')
|
||||||
|
const juice = require('juice')
|
||||||
|
|
||||||
|
async function compile_pug_to_email( pugFile, data ) {
|
||||||
|
|
||||||
|
const [ emailPug, inlineNormalise, styleExtra, styleOutlook, rocketeerStyles ] = await Promise.all( [
|
||||||
|
fs.readFile( pugFile ),
|
||||||
|
fs.readFile( `${ __dirname }/../templates/css-resets/normalize.css`, 'utf8' ),
|
||||||
|
fs.readFile( `${ __dirname }/../templates/css-resets/extra.css`, 'utf8' ),
|
||||||
|
fs.readFile( `${ __dirname }/../templates/css-resets/outlook.css`, 'utf8' ),
|
||||||
|
fs.readFile( `${ __dirname }/../templates/rocketeers.css`, 'utf8' )
|
||||||
|
] )
|
||||||
|
|
||||||
|
const { css } = csso.minify( [ styleExtra, styleOutlook, inlineNormalise, rocketeerStyles ].join( '\n' ) )
|
||||||
|
const html = pug.render( emailPug, { data, headStyles: css } )
|
||||||
|
const emailifiedHtml = juice.inlineContent( html, [ inlineNormalise, rocketeerStyles ].join( '\n' ), { removeStyleTags: false } )
|
||||||
|
|
||||||
|
return emailifiedHtml
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async function send_email( recipient, subject, html, text ) {
|
||||||
|
|
||||||
|
const options = {
|
||||||
|
Source: aws.ses.fromemail,
|
||||||
|
Destination: {
|
||||||
|
ToAddresses: [ recipient ]
|
||||||
|
},
|
||||||
|
ReplyToAddresses: [],
|
||||||
|
Message: {
|
||||||
|
Body: {
|
||||||
|
Html: { Charset: 'UTF-8', Data: html },
|
||||||
|
Text: { Charset: 'UTF-8', Data: text }
|
||||||
|
},
|
||||||
|
Subject: { Charset: 'UTF-8', Data: subject }
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
log( `Sending email "${ options.Message.Subject.Data }" from ${ options.Source } to ${ options.Destination.ToAddresses[0] }` )
|
||||||
|
|
||||||
|
return AWS_SES.sendEmail( options ).promise()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
exports.send_outfit_available_email = async ( rocketeers, email ) => {
|
||||||
|
|
||||||
|
|
||||||
|
const email_html = await compile_pug_to_email( `${ __dirname }/../templates/outfit_available.email.pug`, rocketeers )
|
||||||
|
const email_text = ( await fs.readFile( `${ __dirname }/../templates/outfit_available.email.txt`, 'utf8' ) )
|
||||||
|
// .replace( '%%address%%', email_data.address )
|
||||||
|
|
||||||
|
return send_email( email, `Your Rocketeer${rocketeers.length > 1 ? 's' : '' } ${rocketeers.length > 1 ? 'have outfits' : 'has an outfit' } available!`, email_html, email_text )
|
||||||
|
|
||||||
|
|
||||||
|
}
|
23
functions/integrations/signer_is.js
Normal file
23
functions/integrations/signer_is.js
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
const fetch = require( 'isomorphic-fetch' )
|
||||||
|
|
||||||
|
exports.ask_signer_is_for_available_emails = async function( addresses ) {
|
||||||
|
|
||||||
|
/* ///////////////////////////////
|
||||||
|
// Check available email addresses */
|
||||||
|
const endpoint = `https://signer.is/check_availability/`
|
||||||
|
const options = {
|
||||||
|
method: 'POST',
|
||||||
|
headers:{
|
||||||
|
'Content-Type': 'application/json'
|
||||||
|
},
|
||||||
|
body: JSON.stringify( {
|
||||||
|
addresses
|
||||||
|
} )
|
||||||
|
}
|
||||||
|
|
||||||
|
const res = await fetch( endpoint, options )
|
||||||
|
const available_addresses = await res.json()
|
||||||
|
|
||||||
|
return available_addresses?.emails_available || []
|
||||||
|
|
||||||
|
}
|
@ -1,7 +1,7 @@
|
|||||||
// ///////////////////////////////
|
// ///////////////////////////////
|
||||||
// Helper functions
|
// Helper functions
|
||||||
// ///////////////////////////////
|
// ///////////////////////////////
|
||||||
|
exports.dev = !!process.env.development
|
||||||
exports.log = ( ...messages ) => {
|
exports.log = ( ...messages ) => {
|
||||||
if( process.env.development ) console.log( ...messages )
|
if( process.env.development ) console.log( ...messages )
|
||||||
}
|
}
|
||||||
|
21
functions/modules/templates/css-resets/LICENSE.md
Normal file
21
functions/modules/templates/css-resets/LICENSE.md
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
# The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright © Arthur Koch
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||||
|
of the Software, and to permit persons to whom the Software is furnished to do
|
||||||
|
so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
67
functions/modules/templates/css-resets/README.md
Normal file
67
functions/modules/templates/css-resets/README.md
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
# normalize.email.css
|
||||||
|
|
||||||
|
CSS resets for HTML emails
|
||||||
|
|
||||||
|
It's just a little css library for best default email compatibility. You can use it with your favourite email framework and self-coded templates.
|
||||||
|
|
||||||
|
## What does it do?
|
||||||
|
|
||||||
|
- Preserves useful defaults for most email clients
|
||||||
|
- Makes native platform font styling
|
||||||
|
- Corrects some popular bugs
|
||||||
|
- Explains what code does using comments
|
||||||
|
|
||||||
|
Please let me know if comments not informative and must be detailed
|
||||||
|
|
||||||
|
## Contents
|
||||||
|
|
||||||
|
- normalize.css - must be inlined to your newsletter in production
|
||||||
|
- extra.css - must be placed between `<style>` tags in `<head>` of your newsletter in production
|
||||||
|
- outlook.css - must be placed between `<style>` tags with conditional comment in `<head>` of your newsletter in production. Check out example.html to learn correct code
|
||||||
|
|
||||||
|
## Example
|
||||||
|
|
||||||
|
``` html
|
||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
||||||
|
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<!-- normalize.css contents must be inlined to newsletter -->
|
||||||
|
<link href="normalize.css" rel="stylesheet">
|
||||||
|
<link href="extra.css" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
/* Put extra.css contents here */
|
||||||
|
</style>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<link href="outlook.css" rel="stylesheet">
|
||||||
|
/* Put outlook.css contents here */
|
||||||
|
<![endif]-->
|
||||||
|
<!-- Left title element empty to prevent viewing this text in subject line on Android 4 email clients -->
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="body">
|
||||||
|
<div class="webkit">
|
||||||
|
<!-- An example of bulletproof container with limited row length -->
|
||||||
|
<table width="100%" border="0" cellpadding="0" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<!-- Add here this element -->
|
||||||
|
<!-- <th></th> -->
|
||||||
|
<!-- to align container to center -->
|
||||||
|
<th width="500" align="left">
|
||||||
|
<!-- Content here -->
|
||||||
|
<!-- You can use any HTML code which you prefer -->
|
||||||
|
</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
|
|
||||||
|
```
|
59
functions/modules/templates/css-resets/example.html
Normal file
59
functions/modules/templates/css-resets/example.html
Normal file
@ -0,0 +1,59 @@
|
|||||||
|
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
|
||||||
|
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<!-- normalize.css contents must be inlined to newsletter -->
|
||||||
|
<link href="normalize.css" rel="stylesheet">
|
||||||
|
<link href="extra.css" rel="stylesheet">
|
||||||
|
<style>
|
||||||
|
/* Put extra.css contents here */
|
||||||
|
</style>
|
||||||
|
<!--[if (gte mso 9)|(IE)]>
|
||||||
|
<link href="outlook.css" rel="stylesheet">
|
||||||
|
/* Put outlook.css contents here */
|
||||||
|
<![endif]-->
|
||||||
|
<!-- Left title element empty to prevent viewing this text in subject line on Android 4 email clients -->
|
||||||
|
<title></title>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body class="body">
|
||||||
|
<div class="webkit">
|
||||||
|
<!-- An example of bulletproof container with limited row length -->
|
||||||
|
<table width="100%" border="0" cellpadding="0" cellspacing="0">
|
||||||
|
<tr>
|
||||||
|
<!-- Add here this element -->
|
||||||
|
<!-- <th></th> -->
|
||||||
|
<!-- to align container to center -->
|
||||||
|
<th width="500" align="left">
|
||||||
|
<p>You are receiving this because a known security researcher submitted proof of finding credentials for your npm user account on the internet.</p>
|
||||||
|
|
||||||
|
<p>In order to prevent unauthorized access, we've changed the password to your account and invalidated all of your active npm tokens.</p>
|
||||||
|
|
||||||
|
<p>Please click on the following link, or paste this into your browser to reset your password:</p>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
<li><a href="https://www.npmjs.com/forgot">https://www.npmjs.com/forgot</a></li>
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
<p>When you reset your password please do not set it back to the old value.</p>
|
||||||
|
|
||||||
|
<p>We have no reason to believe that your account was compromised, but cannot be certain of this. This reset is preemptive, to prevent future compromise.</p>
|
||||||
|
|
||||||
|
<p>If you have questions:</p>
|
||||||
|
<ol>
|
||||||
|
<li>You can reply to this message or email <a href="support@npmjs.com">support@npmjs.com</a>.</li>
|
||||||
|
<li>You can also read more about this undertaking in our <a href="http://blog.npmjs.org/post/161515829950/credentials-resets">blog post</a>.</li>
|
||||||
|
</ol>
|
||||||
|
|
||||||
|
<p>Npm loves you.</p>
|
||||||
|
</th>
|
||||||
|
<th></th>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
29
functions/modules/templates/css-resets/extra.css
Normal file
29
functions/modules/templates/css-resets/extra.css
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/* Extra.css */
|
||||||
|
/* Contents of this file must be placed between <style> tags in <head> of your newsletter in production */
|
||||||
|
|
||||||
|
@media screen and (max-width: 600px) {
|
||||||
|
u + .body {
|
||||||
|
/* iOS Gmail viewport fix */
|
||||||
|
/* Make sure that your body element has .body class */
|
||||||
|
width: 100vw !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
a[x-apple-data-detectors=true] {
|
||||||
|
/* Set default text color inheritance for auto-detected iOS links like date, time, address, etc */
|
||||||
|
color: inherit !important;
|
||||||
|
text-decoration: inherit !important;
|
||||||
|
border-bottom: none !important;
|
||||||
|
}
|
||||||
|
body {
|
||||||
|
/* Set native platform font styling */
|
||||||
|
font-family: -apple-system, BlinkMacSystemFont, Roboto, Helvetica, Arial, sans-serif;
|
||||||
|
font-size: 16px;
|
||||||
|
color: black;
|
||||||
|
}
|
||||||
|
.webkit {
|
||||||
|
/* Webkit and Microsoft font-size fix */
|
||||||
|
width: 100%;
|
||||||
|
table-layout: fixed;
|
||||||
|
-webkit-text-size-adjust: 100%;
|
||||||
|
-ms-text-size-adjust: 100%;
|
||||||
|
}
|
64
functions/modules/templates/css-resets/normalize.css
vendored
Normal file
64
functions/modules/templates/css-resets/normalize.css
vendored
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
/* Normalize.css */
|
||||||
|
/* Contents of this file must be inlined to your newsletter in production */
|
||||||
|
|
||||||
|
h1 a,
|
||||||
|
h2 a,
|
||||||
|
h3 a,
|
||||||
|
h4 a,
|
||||||
|
h5 a,
|
||||||
|
h6 a,
|
||||||
|
li a,
|
||||||
|
p a {
|
||||||
|
/* Set sexy underline styling for links except images */
|
||||||
|
text-decoration: none;
|
||||||
|
color: #2837b8 !important;
|
||||||
|
border-bottom: #d3d6f0 1px solid;
|
||||||
|
}
|
||||||
|
h1 {
|
||||||
|
/* Mail.ru <h1> styling fix */
|
||||||
|
font-size: 2em;
|
||||||
|
line-height: initial;
|
||||||
|
margin: 0.67em 0;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
/* Null tables spaces */
|
||||||
|
border-spacing: 0;
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
||||||
|
table td {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
table th {
|
||||||
|
padding: 0;
|
||||||
|
font-weight: normal;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
/* Flexible images fix + prevent any borders for images */
|
||||||
|
max-width: 100%;
|
||||||
|
border: 0;
|
||||||
|
outline: 0;
|
||||||
|
/* Set image's ALT text styling */
|
||||||
|
color: #2837b8;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
ol,
|
||||||
|
ul {
|
||||||
|
/* We don't touch horizontal margins to prevent hiding bullets in Oultook */
|
||||||
|
margin-top: 1em;
|
||||||
|
margin-bottom: 2em;
|
||||||
|
}
|
||||||
|
ol li,
|
||||||
|
ul li {
|
||||||
|
line-height: 1.6em;
|
||||||
|
margin: 0.5em 0;
|
||||||
|
}
|
||||||
|
p {
|
||||||
|
line-height: 1.6em;
|
||||||
|
margin: 1em 0;
|
||||||
|
}
|
||||||
|
span.code {
|
||||||
|
/* Monospace emphasis for code examples */
|
||||||
|
font-family: consolas, courier, monospace;
|
||||||
|
color: grey;
|
||||||
|
}
|
24
functions/modules/templates/css-resets/outlook.css
Normal file
24
functions/modules/templates/css-resets/outlook.css
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
/* Outlook.css */
|
||||||
|
/* Contents of this file must be placed between <style> tags with conditional comment in <head> of your newsletter in production */
|
||||||
|
|
||||||
|
body {
|
||||||
|
/* Reset font styling. Useful when we links custom fonts to our newsletter */
|
||||||
|
font-family: Helvetica, Arial, sans-serif;
|
||||||
|
}
|
||||||
|
a {
|
||||||
|
/* Reset default links styling */
|
||||||
|
color: #2837b8;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
h1, h2, h3, h4, h5, h6 {
|
||||||
|
/* Reset default headings margin */
|
||||||
|
margin: .5em 0;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
/* Scaled images fix */
|
||||||
|
-ms-interpolation-mode: bicubic;
|
||||||
|
}
|
||||||
|
table {
|
||||||
|
/* Null tables spaces */
|
||||||
|
border-collapse: collapse;
|
||||||
|
}
|
83
functions/modules/templates/signer.css
Normal file
83
functions/modules/templates/signer.css
Normal file
@ -0,0 +1,83 @@
|
|||||||
|
/*:root {
|
||||||
|
--color-primary: #8076fa;
|
||||||
|
--color-text: rgb(77, 86, 128);
|
||||||
|
--color-accent: rgb( 248, 117, 136 );
|
||||||
|
--color-backdrop: rgba( 0, 0, 0, .05 );
|
||||||
|
}*/
|
||||||
|
|
||||||
|
/* Note that web fonts DO NOT WORK in most email clients */
|
||||||
|
@import url('https://fonts.googleapis.com/css2?family=Archivo&family=Comfortaa:wght@500&display=swap');
|
||||||
|
|
||||||
|
body {
|
||||||
|
margin: 0;
|
||||||
|
font-family: 'Archivo', 'Helvetica Neue', sans-serif;
|
||||||
|
font-weight: 400;
|
||||||
|
-webkit-font-smoothing: antialiased;
|
||||||
|
-moz-osx-font-smoothing: grayscale;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ///////////////////////////////
|
||||||
|
// Flow text
|
||||||
|
// /////////////////////////////*/
|
||||||
|
html {
|
||||||
|
font-size: calc( 18px + .1vw );
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ///////////////////////////////
|
||||||
|
// Brand styles
|
||||||
|
// /////////////////////////////*/
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
font-size: 2.5rem;
|
||||||
|
font-weight: 500;
|
||||||
|
line-height: 1.2;
|
||||||
|
font-family: 'Comfortaa', sans-serif;
|
||||||
|
text-align: left;
|
||||||
|
/*color: var( --color-primary );*/
|
||||||
|
color: #8076fa;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
font-size: 1.5rem;
|
||||||
|
margin: 0 0 1rem;
|
||||||
|
line-height: 1.2;
|
||||||
|
font-weight: 400;
|
||||||
|
text-align: left;
|
||||||
|
/*color: var( --color-accent );*/
|
||||||
|
color: rgb( 248, 117, 136 );
|
||||||
|
}
|
||||||
|
|
||||||
|
p {
|
||||||
|
font-size: 1rem;
|
||||||
|
margin: 1rem 0;
|
||||||
|
line-height: 1.5rem;
|
||||||
|
/*color: var( --color-text );*/
|
||||||
|
color: rgb(77, 86, 128);
|
||||||
|
text-align: left
|
||||||
|
}
|
||||||
|
|
||||||
|
a.button {
|
||||||
|
display: inline-block;
|
||||||
|
padding: 1rem 2rem;
|
||||||
|
margin: .5rem;
|
||||||
|
margin-left: 0;
|
||||||
|
text-decoration: none;
|
||||||
|
/*border: 2px solid var( --color-primary );*/
|
||||||
|
border: 2px solid #8076fa;
|
||||||
|
/*color: var( --color-primary );*/
|
||||||
|
color: #8076fa;
|
||||||
|
font-size: 1rem;
|
||||||
|
background: none;
|
||||||
|
border-radius: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
input {
|
||||||
|
/*background: var( --color-backdrop );*/
|
||||||
|
background: rgba( 0, 0, 0, .05 );
|
||||||
|
border: none;
|
||||||
|
/*border-left: 2px solid var( --color-primary );*/
|
||||||
|
border-left: 2px solid #8076fa;
|
||||||
|
padding: 1rem;
|
||||||
|
margin: 1rem 10% 1rem 0;
|
||||||
|
width: 90%;
|
||||||
|
}
|
13
functions/modules/templates/verify.email.pug
Normal file
13
functions/modules/templates/verify.email.pug
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
doctype html
|
||||||
|
html( lang='en' )
|
||||||
|
head
|
||||||
|
style= headStyles
|
||||||
|
body
|
||||||
|
p Hello,
|
||||||
|
p Someone requested for emails to #{ data.address }@signer.is (and #{ data.ENS } ENS) to be delivered to this email address.
|
||||||
|
p If this was not you, you can safely ignore this email.
|
||||||
|
p To receive emails at this address, please verify your ownership of this email by clicking the link below.
|
||||||
|
a( href=data.verification_link ) Click here to verify your email address.
|
||||||
|
p Is the above link not working? Visit this page manually: #{ data.verification_link }
|
||||||
|
p Have a great day,
|
||||||
|
p ~ Signer.is
|
13
functions/modules/templates/verify.email.txt
Normal file
13
functions/modules/templates/verify.email.txt
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
Hello,
|
||||||
|
|
||||||
|
Someone requested for emails to %%address%%@signer.is (and %%ENS%% ENS) to be delivered to this email address.
|
||||||
|
|
||||||
|
If this was not you, you can safely ignore this email.
|
||||||
|
|
||||||
|
To receive emails at this address, please verify your ownership of this email by clicking the link below.
|
||||||
|
|
||||||
|
Open this link to verify your email address: %%verification_link%%.
|
||||||
|
|
||||||
|
Have a great day,
|
||||||
|
|
||||||
|
~ Signer.is
|
190
functions/package-lock.json
generated
190
functions/package-lock.json
generated
@ -6,12 +6,13 @@
|
|||||||
"": {
|
"": {
|
||||||
"name": "functions",
|
"name": "functions",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"aws-sdk": "^2.1149.0",
|
||||||
"body-parser": "^1.19.1",
|
"body-parser": "^1.19.1",
|
||||||
"color": "^4.0.2",
|
"color": "^4.0.2",
|
||||||
"color-namer": "^1.4.0",
|
"color-namer": "^1.4.0",
|
||||||
"convert-svg-to-jpeg": "^0.5.0",
|
"convert-svg-to-jpeg": "^0.5.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"csso": "^5.0.2",
|
"csso": "^5.0.3",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"firebase-admin": "^10.0.0",
|
"firebase-admin": "^10.0.0",
|
||||||
"firebase-functions": "^3.11.0",
|
"firebase-functions": "^3.11.0",
|
||||||
@ -1508,6 +1509,62 @@
|
|||||||
"url": "https://github.com/sponsors/ljharb"
|
"url": "https://github.com/sponsors/ljharb"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/aws-sdk": {
|
||||||
|
"version": "2.1149.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1149.0.tgz",
|
||||||
|
"integrity": "sha512-wNb3YMLhXoK4UkjXhGAWMjRdrXT/Zhv3KdgPmd7VWlr3nXMViLwVJEEYdVmALUdkzCefdzY1JUTRLMgCxtn9EA==",
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": "4.9.2",
|
||||||
|
"events": "1.1.1",
|
||||||
|
"ieee754": "1.1.13",
|
||||||
|
"jmespath": "0.16.0",
|
||||||
|
"querystring": "0.2.0",
|
||||||
|
"sax": "1.2.1",
|
||||||
|
"url": "0.10.3",
|
||||||
|
"uuid": "8.0.0",
|
||||||
|
"xml2js": "0.4.19"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/aws-sdk/node_modules/buffer": {
|
||||||
|
"version": "4.9.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
|
||||||
|
"integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
|
||||||
|
"dependencies": {
|
||||||
|
"base64-js": "^1.0.2",
|
||||||
|
"ieee754": "^1.1.4",
|
||||||
|
"isarray": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/aws-sdk/node_modules/ieee754": {
|
||||||
|
"version": "1.1.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
|
||||||
|
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
|
||||||
|
},
|
||||||
|
"node_modules/aws-sdk/node_modules/punycode": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="
|
||||||
|
},
|
||||||
|
"node_modules/aws-sdk/node_modules/url": {
|
||||||
|
"version": "0.10.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
|
||||||
|
"integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=",
|
||||||
|
"dependencies": {
|
||||||
|
"punycode": "1.3.2",
|
||||||
|
"querystring": "0.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/aws-sdk/node_modules/uuid": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw==",
|
||||||
|
"bin": {
|
||||||
|
"uuid": "dist/bin/uuid"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/aws-sign2": {
|
"node_modules/aws-sign2": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||||
@ -2611,9 +2668,9 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/csso": {
|
"node_modules/csso": {
|
||||||
"version": "5.0.2",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/csso/-/csso-5.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/csso/-/csso-5.0.3.tgz",
|
||||||
"integrity": "sha512-llFAe1UfFHy38ziX+YrPMGkn5MxdjzYtz0drvgnjRY/tLPmBRxotYTGO51BsKe9voQA074pEb0udV+piXH4scQ==",
|
"integrity": "sha512-93gBHTJ6EQlLNhIX5Ho8VAJD2t2T2wg1xHDjbIUm/oQ7iFiSUTo9jSojiQK0pEZ3lMhYDrQO7Rcd70M68+VrtA==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"css-tree": "~2.0.4"
|
"css-tree": "~2.0.4"
|
||||||
},
|
},
|
||||||
@ -3702,6 +3759,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
|
||||||
"integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ=="
|
"integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ=="
|
||||||
},
|
},
|
||||||
|
"node_modules/events": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=0.4.x"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/evp_bytestokey": {
|
"node_modules/evp_bytestokey": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
|
||||||
@ -5171,6 +5236,14 @@
|
|||||||
"node": ">= 4"
|
"node": ">= 4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/jmespath": {
|
||||||
|
"version": "0.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz",
|
||||||
|
"integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 0.6.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/jose": {
|
"node_modules/jose": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz",
|
||||||
@ -7198,6 +7271,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
|
"node_modules/sax": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
|
||||||
|
"integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
|
||||||
|
},
|
||||||
"node_modules/saxes": {
|
"node_modules/saxes": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
|
||||||
@ -9148,6 +9226,23 @@
|
|||||||
"node": ">=12"
|
"node": ">=12"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/xml2js": {
|
||||||
|
"version": "0.4.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
|
||||||
|
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
|
||||||
|
"dependencies": {
|
||||||
|
"sax": ">=0.6.0",
|
||||||
|
"xmlbuilder": "~9.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/xmlbuilder": {
|
||||||
|
"version": "9.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
||||||
|
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0=",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=4.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/xmlchars": {
|
"node_modules/xmlchars": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||||
@ -10352,6 +10447,58 @@
|
|||||||
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
|
||||||
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
|
"integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw=="
|
||||||
},
|
},
|
||||||
|
"aws-sdk": {
|
||||||
|
"version": "2.1149.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/aws-sdk/-/aws-sdk-2.1149.0.tgz",
|
||||||
|
"integrity": "sha512-wNb3YMLhXoK4UkjXhGAWMjRdrXT/Zhv3KdgPmd7VWlr3nXMViLwVJEEYdVmALUdkzCefdzY1JUTRLMgCxtn9EA==",
|
||||||
|
"requires": {
|
||||||
|
"buffer": "4.9.2",
|
||||||
|
"events": "1.1.1",
|
||||||
|
"ieee754": "1.1.13",
|
||||||
|
"jmespath": "0.16.0",
|
||||||
|
"querystring": "0.2.0",
|
||||||
|
"sax": "1.2.1",
|
||||||
|
"url": "0.10.3",
|
||||||
|
"uuid": "8.0.0",
|
||||||
|
"xml2js": "0.4.19"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"buffer": {
|
||||||
|
"version": "4.9.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
|
||||||
|
"integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
|
||||||
|
"requires": {
|
||||||
|
"base64-js": "^1.0.2",
|
||||||
|
"ieee754": "^1.1.4",
|
||||||
|
"isarray": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ieee754": {
|
||||||
|
"version": "1.1.13",
|
||||||
|
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.1.13.tgz",
|
||||||
|
"integrity": "sha512-4vf7I2LYV/HaWerSo3XmlMkp5eZ83i+/CDluXi/IGTs/O1sejBNhTtnxzmRZfvOUqj7lZjqHkeTvpgSFDlWZTg=="
|
||||||
|
},
|
||||||
|
"punycode": {
|
||||||
|
"version": "1.3.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
|
||||||
|
"integrity": "sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw=="
|
||||||
|
},
|
||||||
|
"url": {
|
||||||
|
"version": "0.10.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/url/-/url-0.10.3.tgz",
|
||||||
|
"integrity": "sha1-Ah5NnHcF8hu/N9A861h2dAJ3TGQ=",
|
||||||
|
"requires": {
|
||||||
|
"punycode": "1.3.2",
|
||||||
|
"querystring": "0.2.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uuid": {
|
||||||
|
"version": "8.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/uuid/-/uuid-8.0.0.tgz",
|
||||||
|
"integrity": "sha512-jOXGuXZAWdsTH7eZLtyXMqUb9EcWMGZNbL9YcGBJl4MH4nrxHmZJhEHvyLFrkxo+28uLb/NYRcStH48fnD0Vzw=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"aws-sign2": {
|
"aws-sign2": {
|
||||||
"version": "0.7.0",
|
"version": "0.7.0",
|
||||||
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
|
||||||
@ -11257,9 +11404,9 @@
|
|||||||
"integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw=="
|
"integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw=="
|
||||||
},
|
},
|
||||||
"csso": {
|
"csso": {
|
||||||
"version": "5.0.2",
|
"version": "5.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/csso/-/csso-5.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/csso/-/csso-5.0.3.tgz",
|
||||||
"integrity": "sha512-llFAe1UfFHy38ziX+YrPMGkn5MxdjzYtz0drvgnjRY/tLPmBRxotYTGO51BsKe9voQA074pEb0udV+piXH4scQ==",
|
"integrity": "sha512-93gBHTJ6EQlLNhIX5Ho8VAJD2t2T2wg1xHDjbIUm/oQ7iFiSUTo9jSojiQK0pEZ3lMhYDrQO7Rcd70M68+VrtA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"css-tree": "~2.0.4"
|
"css-tree": "~2.0.4"
|
||||||
}
|
}
|
||||||
@ -12126,6 +12273,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
|
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.4.tgz",
|
||||||
"integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ=="
|
"integrity": "sha512-rlaVLnVxtxvoyLsQQFBx53YmXHDxRIzzTLbdfxqi4yocpSjAxXwkU0cScM5JgSKMqEhrZpnvQ2D9gjylR0AimQ=="
|
||||||
},
|
},
|
||||||
|
"events": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/events/-/events-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-kEcvvCBByWXGnZy6JUlgAp2gBIUjfCAV6P6TgT1/aaQKcmuAEC4OZTV1I4EWQLz2gxZw76atuVyvHhTxvi0Flw=="
|
||||||
|
},
|
||||||
"evp_bytestokey": {
|
"evp_bytestokey": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
|
"resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
|
||||||
@ -13204,6 +13356,11 @@
|
|||||||
"is-object": "^1.0.1"
|
"is-object": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jmespath": {
|
||||||
|
"version": "0.16.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jmespath/-/jmespath-0.16.0.tgz",
|
||||||
|
"integrity": "sha512-9FzQjJ7MATs1tSpnco1K6ayiYE3figslrXA72G2HQ/n76RzvYlofyi5QM+iX4YRs/pu3yzxlVQSST23+dMDknw=="
|
||||||
|
},
|
||||||
"jose": {
|
"jose": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/jose/-/jose-2.0.5.tgz",
|
||||||
@ -14828,6 +14985,11 @@
|
|||||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||||
},
|
},
|
||||||
|
"sax": {
|
||||||
|
"version": "1.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/sax/-/sax-1.2.1.tgz",
|
||||||
|
"integrity": "sha1-e45lYZCyKOgaZq6nSEgNgozS03o="
|
||||||
|
},
|
||||||
"saxes": {
|
"saxes": {
|
||||||
"version": "5.0.1",
|
"version": "5.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/saxes/-/saxes-5.0.1.tgz",
|
||||||
@ -16354,6 +16516,20 @@
|
|||||||
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
|
||||||
"integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw=="
|
"integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw=="
|
||||||
},
|
},
|
||||||
|
"xml2js": {
|
||||||
|
"version": "0.4.19",
|
||||||
|
"resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.19.tgz",
|
||||||
|
"integrity": "sha512-esZnJZJOiJR9wWKMyuvSE1y6Dq5LCuJanqhxslH2bxM6duahNZ+HMpCLhBQGZkbX6xRf8x1Y2eJlgt2q3qo49Q==",
|
||||||
|
"requires": {
|
||||||
|
"sax": ">=0.6.0",
|
||||||
|
"xmlbuilder": "~9.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"xmlbuilder": {
|
||||||
|
"version": "9.0.7",
|
||||||
|
"resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-9.0.7.tgz",
|
||||||
|
"integrity": "sha1-Ey7mPS7FVlxVfiD0wi35rKaGsQ0="
|
||||||
|
},
|
||||||
"xmlchars": {
|
"xmlchars": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/xmlchars/-/xmlchars-2.2.0.tgz",
|
||||||
|
@ -15,12 +15,13 @@
|
|||||||
},
|
},
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
"aws-sdk": "^2.1149.0",
|
||||||
"body-parser": "^1.19.1",
|
"body-parser": "^1.19.1",
|
||||||
"color": "^4.0.2",
|
"color": "^4.0.2",
|
||||||
"color-namer": "^1.4.0",
|
"color-namer": "^1.4.0",
|
||||||
"convert-svg-to-jpeg": "^0.5.0",
|
"convert-svg-to-jpeg": "^0.5.0",
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"csso": "^5.0.2",
|
"csso": "^5.0.3",
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"firebase-admin": "^10.0.0",
|
"firebase-admin": "^10.0.0",
|
||||||
"firebase-functions": "^3.11.0",
|
"firebase-functions": "^3.11.0",
|
||||||
|
@ -1,17 +0,0 @@
|
|||||||
doctype html
|
|
||||||
html( lang='en' )
|
|
||||||
head
|
|
||||||
style= headStyles
|
|
||||||
body
|
|
||||||
h1 Outfit available for #{ rocketeer.name }
|
|
||||||
h2 Monthly outfit available for generation now.
|
|
||||||
|
|
||||||
p Your Rocketeer is eligible for a new outfit. You can generate it for free at the changing room.
|
|
||||||
img.avatar( src=rocketeer.image )
|
|
||||||
a.button( href='https://tools.rocketeer.fans/#/outfits/' + rocketeer.uid ) View #{ rocketeer.first_name }'s changing room
|
|
||||||
a.button( href='https://tools.rocketeer.fans/#/outfits/' ) View all available outfits
|
|
||||||
|
|
||||||
p If you have any questions or suggestions, please have a look at the FAQ here: https://rocketeer.fans/changingroom.
|
|
||||||
p For other questions or suggestions, please do not hesitate to reach out to us on discord: https://discord.gg/rocketeers
|
|
||||||
p ~ rocketeers.eth
|
|
||||||
|
|
@ -1,5 +0,0 @@
|
|||||||
Rocketeer %%name%% has a new outfit available!
|
|
||||||
|
|
||||||
You can generate it at https://tools.rocketeer.fans
|
|
||||||
|
|
||||||
Have fun!
|
|
10
functions/templates/outfit_available.email.pug
Normal file
10
functions/templates/outfit_available.email.pug
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
doctype html
|
||||||
|
html( lang='en' )
|
||||||
|
head
|
||||||
|
style= headStyles
|
||||||
|
body
|
||||||
|
p Hello!
|
||||||
|
p Your Rocketeers have new outfits available.
|
||||||
|
p To generate new outfits, visit the changing room here: https://mint.rocketeer.fans/#/outfits
|
||||||
|
p Have a great day,
|
||||||
|
p ~ Rocketeer HQ
|
9
functions/templates/outfit_available.email.txt
Normal file
9
functions/templates/outfit_available.email.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Hello!
|
||||||
|
|
||||||
|
Your Rocketeers have new outfits available.
|
||||||
|
|
||||||
|
To generate new outfits, visit the changing room here: https://mint.rocketeer.fans/#/outfits
|
||||||
|
|
||||||
|
Have a great day,
|
||||||
|
|
||||||
|
~ Rocketeer HQ
|
@ -1,10 +0,0 @@
|
|||||||
<svg width="71" height="55" viewBox="0 0 71 55" fill="none" xmlns="http://www.w3.org/2000/svg">
|
|
||||||
<g clip-path="url(#clip0)">
|
|
||||||
<path d="M60.1045 4.8978C55.5792 2.8214 50.7265 1.2916 45.6527 0.41542C45.5603 0.39851 45.468 0.440769 45.4204 0.525289C44.7963 1.6353 44.105 3.0834 43.6209 4.2216C38.1637 3.4046 32.7345 3.4046 27.3892 4.2216C26.905 3.0581 26.1886 1.6353 25.5617 0.525289C25.5141 0.443589 25.4218 0.40133 25.3294 0.41542C20.2584 1.2888 15.4057 2.8186 10.8776 4.8978C10.8384 4.9147 10.8048 4.9429 10.7825 4.9795C1.57795 18.7309 -0.943561 32.1443 0.293408 45.3914C0.299005 45.4562 0.335386 45.5182 0.385761 45.5576C6.45866 50.0174 12.3413 52.7249 18.1147 54.5195C18.2071 54.5477 18.305 54.5139 18.3638 54.4378C19.7295 52.5728 20.9469 50.6063 21.9907 48.5383C22.0523 48.4172 21.9935 48.2735 21.8676 48.2256C19.9366 47.4931 18.0979 46.6 16.3292 45.5858C16.1893 45.5041 16.1781 45.304 16.3068 45.2082C16.679 44.9293 17.0513 44.6391 17.4067 44.3461C17.471 44.2926 17.5606 44.2813 17.6362 44.3151C29.2558 49.6202 41.8354 49.6202 53.3179 44.3151C53.3935 44.2785 53.4831 44.2898 53.5502 44.3433C53.9057 44.6363 54.2779 44.9293 54.6529 45.2082C54.7816 45.304 54.7732 45.5041 54.6333 45.5858C52.8646 46.6197 51.0259 47.4931 49.0921 48.2228C48.9662 48.2707 48.9102 48.4172 48.9718 48.5383C50.038 50.6034 51.2554 52.5699 52.5959 54.435C52.6519 54.5139 52.7526 54.5477 52.845 54.5195C58.6464 52.7249 64.529 50.0174 70.6019 45.5576C70.6551 45.5182 70.6887 45.459 70.6943 45.3942C72.1747 30.0791 68.2147 16.7757 60.1968 4.9823C60.1772 4.9429 60.1437 4.9147 60.1045 4.8978ZM23.7259 37.3253C20.2276 37.3253 17.3451 34.1136 17.3451 30.1693C17.3451 26.225 20.1717 23.0133 23.7259 23.0133C27.308 23.0133 30.1626 26.2532 30.1066 30.1693C30.1066 34.1136 27.28 37.3253 23.7259 37.3253ZM47.3178 37.3253C43.8196 37.3253 40.9371 34.1136 40.9371 30.1693C40.9371 26.225 43.7636 23.0133 47.3178 23.0133C50.9 23.0133 53.7545 26.2532 53.6986 30.1693C53.6986 34.1136 50.9 37.3253 47.3178 37.3253Z" fill="#23272A"/>
|
|
||||||
</g>
|
|
||||||
<defs>
|
|
||||||
<clipPath id="clip0">
|
|
||||||
<rect width="71" height="55" fill="white"/>
|
|
||||||
</clipPath>
|
|
||||||
</defs>
|
|
||||||
</svg>
|
|
Before Width: | Height: | Size: 2.0 KiB |
Loading…
x
Reference in New Issue
Block a user