Compare commits
9 Commits
Author | SHA1 | Date |
---|---|---|
|
b35ac045f3 | |
|
3de25244fb | |
|
1a9f605208 | |
|
2211488f9a | |
|
e97f048eb6 | |
|
e6aeb0158a | |
|
19508f38e8 | |
|
90c356584e | |
|
585445cb6a |
18
config.toml
18
config.toml
|
@ -1,18 +0,0 @@
|
||||||
# User Constants - Update as needed
|
|
||||||
batch_size = 500 # Max 500 messages per batch: https://postmarkapp.com/developer/api/templates-api#send-batch-with-templates
|
|
||||||
test_email = "" # Fill this in with your own email address
|
|
||||||
|
|
||||||
# Handmade Cities Credentials - DON'T TOUCH
|
|
||||||
[hmc]
|
|
||||||
api_url = "https://api.handmadecities.com/v1/meetups/subscribers"
|
|
||||||
shared_secret = "Land_OF_TERminA__MAJORAS_LAIR#666!"
|
|
||||||
city = "Termina"
|
|
||||||
|
|
||||||
# Postmark App Credentials - NO TOUCHY TOUCHY
|
|
||||||
[postmark]
|
|
||||||
server_token = "37967b9a-6b1c-430e-a65f-de043de3e568"
|
|
||||||
api_url = "https://api.postmarkapp.com/email/batchWithTemplates"
|
|
||||||
template_id = 35682307
|
|
||||||
sender_name = "Skull Kid"
|
|
||||||
sender_email = "majora@handmadecities.com"
|
|
||||||
message_stream = "termina"
|
|
58
main.go
58
main.go
|
@ -7,14 +7,14 @@
|
||||||
// ============================ Contributors =========================
|
// ============================ Contributors =========================
|
||||||
// Bug & warning fixes
|
// Bug & warning fixes
|
||||||
// Jacob Bell (@MysteriousJ)
|
// Jacob Bell (@MysteriousJ)
|
||||||
// Asaf Gartner
|
// Asaf Gartner (@AsafGartner)
|
||||||
|
// Joshua Barnett (@jshbrntt)
|
||||||
|
// Jack Punter (@TarriestPython)
|
||||||
//
|
//
|
||||||
// Emotional Support
|
// Emotional Support
|
||||||
// Cucui Ganon Rosario
|
// Cucui Ganon Rosario
|
||||||
// =========================================================================
|
// =========================================================================
|
||||||
|
|
||||||
// WARNING: This program requires a companion config.toml file provided by Abner. Without it we will crash!
|
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
@ -113,15 +113,21 @@ func retrieveSubscribers(cfg *Config) ([]string, error) {
|
||||||
return nil, errors.New("response format error: 'emails' field not found")
|
return nil, errors.New("response format error: 'emails' field not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Convert emails to []string */
|
/* De-duplicate emails using a map */
|
||||||
/* *** */
|
/* *** */
|
||||||
var subscribers []string
|
emailMap := make(map[string]bool)
|
||||||
for _, email := range emails {
|
for _, email := range emails {
|
||||||
if emailStr, ok := email.(string); ok {
|
if emailStr, ok := email.(string); ok {
|
||||||
subscribers = append(subscribers, emailStr)
|
emailMap[emailStr] = true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Convert the map keys back to a slice */
|
||||||
|
var subscribers []string
|
||||||
|
for email := range emailMap {
|
||||||
|
subscribers = append(subscribers, email)
|
||||||
|
}
|
||||||
|
|
||||||
return subscribers, nil
|
return subscribers, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -276,6 +282,13 @@ func blastMail(cfg *Config, logFile string, trackingFile string, audience []stri
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
existingReaderCount := len(sentToAddresses)
|
||||||
|
newReaderCount := 0
|
||||||
|
|
||||||
|
if existingReaderCount > 0 {
|
||||||
|
fmt.Println("Same email file specified: Sending only to new subscribers...")
|
||||||
|
}
|
||||||
|
|
||||||
var group []string
|
var group []string
|
||||||
for _, a := range audience {
|
for _, a := range audience {
|
||||||
if a == "" {
|
if a == "" {
|
||||||
|
@ -301,6 +314,7 @@ func blastMail(cfg *Config, logFile string, trackingFile string, audience []stri
|
||||||
for i, res := range results {
|
for i, res := range results {
|
||||||
log.WriteString(fmt.Sprintf("%s: %s\n", group[i], res.Message))
|
log.WriteString(fmt.Sprintf("%s: %s\n", group[i], res.Message))
|
||||||
}
|
}
|
||||||
|
newReaderCount += len(group)
|
||||||
group = group[0:0]
|
group = group[0:0]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -316,6 +330,16 @@ func blastMail(cfg *Config, logFile string, trackingFile string, audience []stri
|
||||||
for i, res := range results {
|
for i, res := range results {
|
||||||
log.WriteString(fmt.Sprintf("%s: %s\n", group[i], res.Message))
|
log.WriteString(fmt.Sprintf("%s: %s\n", group[i], res.Message))
|
||||||
}
|
}
|
||||||
|
newReaderCount += len(group)
|
||||||
|
}
|
||||||
|
|
||||||
|
if newReaderCount > 0 {
|
||||||
|
newSubscribers := existingReaderCount > 0
|
||||||
|
if newSubscribers {
|
||||||
|
fmt.Printf("Sent to %d new subscribers!\n", newReaderCount)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
fmt.Printf("Not sent (no new subscribers)\n")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -463,10 +487,10 @@ func main() {
|
||||||
Run: func(cmd *cobra.Command, args []string) {
|
Run: func(cmd *cobra.Command, args []string) {
|
||||||
fmt.Printf(`Instructions:
|
fmt.Printf(`Instructions:
|
||||||
1. Create an email file
|
1. Create an email file
|
||||||
* Name it whatever you want. Markdown is expected
|
* Call it whatever you want. Markdown format is expected
|
||||||
* Any newlines at the start or end of the file will be removed
|
* Newlines at the beginning and end will be trimmed
|
||||||
* The first line of the file will be used as {{ subject }} in the postmark template. It must start with the # symbol
|
* The first line is your email subject. It MUST start with the # symbol
|
||||||
* The rest of the file will be used as {{{ content_body }}}
|
* The rest of the file is your email's body
|
||||||
|
|
||||||
2. See who's subscribed
|
2. See who's subscribed
|
||||||
* ./meetupinvite2000 dump
|
* ./meetupinvite2000 dump
|
||||||
|
@ -475,15 +499,15 @@ func main() {
|
||||||
|
|
||||||
3. Do a test run
|
3. Do a test run
|
||||||
* ./meetupinvite2000 test [email file]
|
* ./meetupinvite2000 test [email file]
|
||||||
* You must send a test email before blasting it to everyone (update config.toml to change test recipient)
|
* You must send a test before blasting to everyone (please update config.toml to change test recipient)
|
||||||
* If you modify the email file after testing, you must test again. Otherwise MeetupInvite2000 will complain
|
* If you modify the email after testing, you must test again. Otherwise we will complain
|
||||||
|
|
||||||
4. Start blasting!
|
4. Start blasting!
|
||||||
* ./meetupinvite2000 blast [email file]
|
* ./meetupinvite2000 blast [email file]
|
||||||
* Will batch send your invite using our Email API (Postmark)
|
* Batch sends your invite using our Email API (Postmark)
|
||||||
* Will produce a .track file that will list all email addresses that we attempted to send to
|
* Produces .track file that tracks email addresses we attempted to send to
|
||||||
* In case of error, you can blast again. All emails listed in the .track file will be skipped
|
* Produces .log file with information received back from Postmark
|
||||||
* Will produce a .log file with information received back from Postmark
|
* In case of errors, you can always blast again. Addresses already in .track file will be skipped
|
||||||
`)
|
`)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
@ -505,7 +529,7 @@ func main() {
|
||||||
indexStr = strings.Repeat(" ", maxIndexWidth-len(indexStr)) + indexStr // Right-align the index
|
indexStr = strings.Repeat(" ", maxIndexWidth-len(indexStr)) + indexStr // Right-align the index
|
||||||
fmt.Printf("%s. \033[1m%s\033[0m\n", indexStr, email)
|
fmt.Printf("%s. \033[1m%s\033[0m\n", indexStr, email)
|
||||||
}
|
}
|
||||||
fmt.Printf("\nMailing list grows automatically as more subscribe at \033[1mhandmadecities.com/meetups\033[0m\n")
|
fmt.Printf("\nMailing list grows automatically as more subscribe at \033[1mhandmadecities.com/meetups/%s\033[0m\n", config.Postmark.MessageStream)
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue