Created
February 25, 2018 20:35
-
-
Save nloadholtes/253fe1673b006dffda5847a83ed22fab to your computer and use it in GitHub Desktop.
The script I am using to generate daily emails for my Stoic Inspiration mailing list.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from mailchimp3 import MailChimp | |
import os | |
import sys | |
import datetime | |
import gspread | |
from oauth2client.service_account import ServiceAccountCredentials | |
import random | |
from functools import partial | |
import json | |
USERNAME = os.environ.get("MC_USERNAME", "") | |
SECRET_KEY = os.environ.get("MC_SECRET_KEY", "") | |
client = MailChimp(USERNAME, SECRET_KEY) | |
# Quote sheet for testing: | |
# https://docs.google.com/spreadsheets/d/126_iTXN0eQQSW9w8tUCcVBgQU9-7XPiRybOKpS5ZUKc/edit#gid=0 | |
scope = ['https://spreadsheets.google.com/feeds'] | |
credentials = ServiceAccountCredentials.from_json_keyfile_name(os.environ.get("GOOGLE_CREDS"), scope) | |
def get_quotes(qty, start_date): | |
"""Get a list of <qty> items from the spreadsheet""" | |
gc = gspread.authorize(credentials) | |
sh = gc.open_by_key(YOUR-SPREADSHEET-ID-GOES-HERE) | |
quotes = sh.get_worksheet(0) | |
results = _list_recent_quotes(quotes.get_all_records(), qty) | |
_update_quotes_date_used(quotes, results, start_date) | |
return results | |
def _filter_by_date(older_than, quote): | |
"""Check each quote to see if is eligable""" | |
if "date_used" in quote: | |
try: | |
result = datetime.datetime.strptime(quote["date_used"], "%m/%d/%Y") < older_than | |
return result | |
except: | |
print("Bad quote date: %s" % quote) | |
return False | |
def _list_recent_quotes(quotes, qty, older_than=90): | |
"""Return a list of <qty> that are older than <older_than> days """ | |
today = datetime.datetime.now() | |
max_age = today - datetime.timedelta(days=older_than) | |
candidates = filter(partial(_filter_by_date, max_age), quotes) | |
return random.sample(list(candidates), qty) | |
def _update_quotes_date_used(quotes, selected_quotes, start_date): | |
"""Update the worksheet to make sure the quotes are using are marked | |
as being used. Also, update the date_used in the quotes themselves.""" | |
for day_count, quote in enumerate(selected_quotes): | |
cell_row = quotes.findall(r'%s' % quote["quote_id"])[0].row | |
updated_value = start_date + datetime.timedelta(days=day_count) | |
formatted_date = datetime.datetime.strftime(updated_value, "%m/%d/%Y") | |
quotes.update_cell(cell_row, | |
2, | |
formatted_date) | |
quote["date_used"] = formatted_date | |
def get_list_id(list_name): | |
"""Get the id for a given list name""" | |
lists = client.lists.all() | |
for l in lists.get("lists", []): | |
if l.get("name", "") == list_name: | |
return l.get("id") | |
def create_campaign(campaign_data): | |
""" | |
Create a campaign | |
""" | |
camp = client.campaigns.create(campaign_data) | |
# print(camp) | |
return camp | |
def populate_campagin_data(list_id, author, quote, date, auto_tweet=False): | |
campaign_data = {"settings": {"title": "S.I. %s" % date, | |
"subject_line": "Today's Stoic Inspiration from %s" % author, | |
"from_name": A-NAME-FOR-THE-FROM-TEXT, | |
"reply_to": YOUR-EMAIL-ADDRESS-HERE, | |
"auto_tweet": auto_tweet | |
}, | |
"recipients": {"list_id": list_id}, | |
"type": "regular"} | |
return campaign_data | |
def populate_content(campaign_id, quote, author): | |
""" | |
Put the content of the email into the campaign | |
:param campaign: The struct genereated by :create_campaign: | |
:param quote: | |
:return: | |
""" | |
data = { "html": _htmlized(quote, author), | |
"plain_text": "\n\n%s\n\n-%s" % (quote, author)} | |
result = client.campaigns.content.update(campaign_id=campaign_id, data=data) | |
print("\n\nResult:") | |
print(result) | |
return result | |
def _htmlized(quote, author): | |
""" | |
Let's keep this abomination private | |
:param quote: | |
:param author: | |
:return: | |
""" | |
html = """<!doctype html><html><h1 style="color: #202020;font-family: Helvetica;font-size: 26px;font-style: normal;">%s</h1> | |
<br><h1 style="color: #202020;font-family: Helvetica;font-size: 26px;font-style: normal;">—%s</h1></html>""" % (quote, author) | |
return html | |
if __name__ == "__main__": | |
list_name = "Stoic emails" | |
if len(sys.argv) == 2: | |
start_date = datetime.datetime.strptime(sys.argv[1], '%m/%d/%Y') | |
data = get_quotes(5, start_date) | |
# Save the quotes so I can feed them back in if needed | |
with open("blah.json", "w") as f: | |
f.write(json.dumps(data)) | |
else: | |
data = json.load(open("blah.json", "r")) | |
# Start | |
list_id = get_list_id(list_name) | |
for day in data: | |
campaign_data = populate_campagin_data(list_id, day["author"], day["quote"], day["date_used"]) | |
camp = create_campaign(campaign_data) | |
populate_content(camp["id"], day["quote"], day["author"]) | |
when_to_send = datetime.datetime.strptime(day["date_used"] + " 10:00", "%m/%d/%Y %H:%M").replace(tzinfo=datetime.timezone.utc) | |
client.campaigns.actions.schedule( | |
camp["id"], | |
{"schedule_time": when_to_send}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment