Skip to content

Commit af08ec7

Browse files
authored
Merge pull request #43 from hatnote/sendy
Add sendy integration
2 parents 0e002da + 276915f commit af08ec7

66 files changed

Lines changed: 1978 additions & 943 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

requirements.txt

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
1-
Werkzeug==0.9.4
2-
argparse==1.2.1
3-
-e git+https://github.com/mahmoud/clastic.git#egg=clastic
1+
ashes==0.7.6
2+
Babel==1.3
3+
certifi==2020.6.20
4+
chardet==3.0.4
5+
-e git+https://github.com/mahmoud/clastic.git@d6afb4ae849e8b463885465a01e28c1708d12a47#egg=clastic
46
docopt==0.4.0
7+
idna==2.10
58
mailchimp==2.0.7
6-
-e git+https://github.com/slaporte/wapiti.git#egg=wapiti
7-
wsgiref==0.1.2
8-
cronfed==0.2.1
9-
ashes==0.7.6
10-
PyYAML==3.11
119
python-dateutil==2.4.2
12-
Babel==2.0
10+
pytz==2014.7
11+
PyYAML==3.11
12+
readline==6.2.4.1
13+
requests==2.24.0
14+
sendypy==4.0.9
15+
six==1.9.0
16+
twitter==1.14.3
17+
urllib3==1.25.10
18+
Werkzeug==0.9.4

weeklypedia/bake.py

Lines changed: 14 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,30 @@
44
import json
55
from datetime import datetime, timedelta
66
from os.path import dirname, join as pjoin
7+
from boltons.fileutils import mkdir_p
78

89
from babel.dates import format_date
910
from babel import UnknownLocaleError
1011
from dateutil.parser import parse as parse_date
1112
from ashes import TemplateNotFound
1213

13-
from mail import Mailinglist, KEY
14+
from mail import sendy_send_campaign
1415
from fetch import get_latest_data_path
1516

16-
from common import (DATA_BASE_PATH,
17-
DEFAULT_LANGUAGE,
17+
from common import (DEFAULT_LANGUAGE,
1818
DEFAULT_INTRO,
1919
DEBUG,
2020
CUSTOM_INTRO_PATH,
2121
LANG_MAP,
2222
LOCAL_LANG_MAP,
2323
SUBJECT_TMPL,
2424
SUPPORTED_LANGS,
25-
SIGNUP_MAP,
26-
mkdir_p)
25+
SENDY_IDS)
2726

2827
_CUR_PATH = dirname(os.path.abspath(__file__))
2928

29+
ARCHIVE_URL = 'https://weekly.hatnote.com/archive/%s/index.html'
30+
3031
INDEX_PATH = pjoin(dirname(_CUR_PATH), 'static', 'index.html')
3132
ARCHIVE_BASE_PATH = pjoin(dirname(_CUR_PATH), 'static', 'archive')
3233
ARCHIVE_PATH_TMPL = '{lang_shortcode}/{date_str}{dev_flag}/weeklypedia_{date_str}{dev_flag}{email_flag}.{fmt}'
@@ -71,14 +72,9 @@ def read_html(self):
7172
def read_text(self):
7273
return open(self.text_path).read()
7374

74-
def send(self, list_id, send_key):
75-
mailinglist = Mailinglist(send_key + KEY)
76-
mailinglist.new_campaign(self.subject,
77-
self.read_html(),
78-
self.read_text(),
79-
list_id=list_id)
80-
mailinglist.send_next_campaign()
81-
return 'Success: sent issue %s' % self.lang
75+
def send(self, list_id):
76+
sendy_send_campaign(self.subject, self.read_text(), self.read_html(), list_id)
77+
return 'Success: sent issue %s via sendy' % self.lang
8278

8379

8480
def get_past_issue_paths(lang, include_dev=False):
@@ -156,7 +152,6 @@ def bake_latest_issue(issue_ashes_env,
156152
include_dev=DEBUG):
157153
ret = {'issues': []}
158154
issue_data = prep_latest_issue(lang, intro, include_dev)
159-
issue_data['signup_url'] = SIGNUP_MAP[lang]
160155
# this fmt is used to generate the path, as well
161156
for fmt in ('html', 'json', 'txt', 'email'):
162157
rendered = render_issue(issue_data, issue_ashes_env, format=fmt)
@@ -181,6 +176,9 @@ def render_issue(render_ctx, issue_ashes_env,
181176
lang = render_ctx['short_lang_name']
182177
env = issue_ashes_env
183178
ctx = localize_data(render_ctx, lang)
179+
ctx['list_id'] = SENDY_IDS[lang]
180+
ctx['archive_link'] = ARCHIVE_URL % lang
181+
184182
if format == 'html':
185183
ret = lang_fallback_render(env, lang, 'archive.html', ctx)
186184
elif format == 'email':
@@ -232,7 +230,7 @@ def render_archive(issue_ashes_env, lang):
232230
ret['issues'].insert(0, {'path': archive_path,
233231
'date': display_date})
234232
ret['lang'] = LANG_MAP[lang]
235-
ret['signup_url'] = SIGNUP_MAP[lang]
233+
ret['list_id'] = SENDY_IDS[lang]
236234
return issue_ashes_env.render('template_archive_index.html', ret)
237235

238236

@@ -253,6 +251,7 @@ def render_and_save_archives(issue_ashes_env):
253251
ret = []
254252
for lang in SUPPORTED_LANGS:
255253
out_path = ARCHIVE_INDEX_PATH_TMPL.format(lang_shortcode=lang)
254+
mkdir_p(pjoin(ARCHIVE_BASE_PATH, lang))
256255
out_file = open(out_path, 'w')
257256
with out_file:
258257
rendered = render_archive(issue_ashes_env, lang)

weeklypedia/common.py

Lines changed: 33 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -6,17 +6,18 @@
66

77
DEBUG = False
88

9+
SENDY_URL = 'https://mailer.hatnote.com/s/'
10+
911
DEFAULT_LANGUAGE = 'en'
1012
DEFAULT_INTRO = 'Hello there! Welcome to our weekly digest of Wikipedia activity.'
1113
SUBJECT_TMPL = 'Weeklypedia {lang_name} #{issue_number}'
1214

13-
DEBUG_LIST_ID = "a5ecbc7404"
14-
1515
_CUR_PATH = dirname(os.path.abspath(__file__))
1616

1717
LANG_MAP = json.load(open(pjoin(_CUR_PATH, 'language_codes.json')))
1818
LOCAL_LANG_MAP = {'en': u'English',
1919
'de': u'Deutsch',
20+
'eo': u'Esperanto',
2021
'fr': u'Français',
2122
'ko': u'한국어',
2223
'et': u'Eesti',
@@ -35,48 +36,40 @@
3536
'oc': 'Occitan',
3637
'ru': 'Russian',
3738
'uk': 'Ukrainian'}
38-
SENDKEY = json.load(open(os.path.join(_CUR_PATH, 'secrets.json'))).get('key')
39-
SUPPORTED_LANGS = ['en', 'de', 'fr', 'ko', 'et', 'sv', 'da', 'it', 'ca', 'es',
40-
'fa', 'zh', 'ur', 'kn', 'lv', 'el', 'te', 'oc', 'ru', 'uk']
41-
API_BASE_URL = 'http://weeklypedia.toolforge.org/fetch/'
4239

43-
ARCHIVE_BASE_PATH = pjoin(dirname(_CUR_PATH), 'static', 'archive')
40+
SENDY_KEY = json.load(open(os.path.join(_CUR_PATH, 'secrets.json'))).get('sendy_key')
41+
42+
SENDY_IDS = {'ca': '9sW1OtFlCbJlYgxSXuahHQ',
43+
'zh': 'aSQ6TT0VKpw0tmzBPaRZDg',
44+
'da': '0cs1zVQp3892EjjL0763350TeQ',
45+
#'en': 'ccIjgMNDQjgxlFR8MrQS3g', # load testing
46+
#'en': 'VN7NFOFUPp5WjrbMSH7Puw', # debug
47+
'en': 'rFf1E97OGw9qMfZh1F81KA',
48+
'es': 'HTPao3LPmzm0UrCNxfBUgA',
49+
'eo': 'H804892jOtJrNTukmVWOlrbA',
50+
'et': 'db8mkJ2Tl6pnNUIIVfMFog',
51+
'fr': 'ELz1OOSd3olC6LSCJmCqhw',
52+
'de': 't0892Imxu8HTkzoPkrow11MQ',
53+
'it': 'EkOruTQZ64fx7V5k9heZNw',
54+
'kn': 'Dn9KffuyqLRKSY9XAwPCHQ',
55+
'ko': '65Y8dYqreq2Frkav2WmJ9Q',
56+
'lv': 'zgfaJH8Jskz7VxNai9zc763A',
57+
'sv': 'bqpefw4ZBxMBHxrTz9dPKg',
58+
'fa': 'mRGhgpBb4RnwDe25RtP8fA',
59+
'el': 'Ts6mbUlmOCiD0mlWPL8T4A',
60+
'oc': 'OrhmrHkNlTRR9KWNMAgDMQ',
61+
'ru': 'IUDkAYoiJDQ7P3AQtLIAhQ',
62+
'es': '5EzGTlwChgHME1TDa763nncA',
63+
'te': 'rp4VkbQ1p2QXi560nIrF3w',
64+
'ur': 'QiUlnjE3S9kPdvpzWQdK5Q',
65+
'uk': 'gYfAtFPIVbJgVLkEfpO892Uw '}
66+
67+
SUPPORTED_LANGS = SENDY_IDS.keys()
68+
69+
API_BASE_URL = 'http://weeklypedia.toolforge.org/fetch/'
4470

4571
DATA_BASE_PATH = pjoin(dirname(_CUR_PATH), 'static', 'data')
4672
DATA_PATH_TMPL = '{lang_shortcode}/{date_str}{dev_flag}/weeklypedia_{lang_shortcode}_{date_str}{dev_flag}.json'
4773
DATA_PATH_TMPL = pjoin(DATA_BASE_PATH, DATA_PATH_TMPL)
4874

4975
CUSTOM_INTRO_PATH = pjoin(DATA_BASE_PATH, 'custom_intro.txt')
50-
51-
SIGNUP_MAP = {'en': 'http://eepurl.com/MMlpX',
52-
'de': 'http://eepurl.com/MMlG9',
53-
'fr': 'http://eepurl.com/MMmVX',
54-
'ko': 'http://eepurl.com/MMm8n',
55-
'et': 'http://eepurl.com/MMnlf',
56-
'sv': 'http://eepurl.com/MMTnP',
57-
'da': 'http://eepurl.com/Sko4L',
58-
'it': 'http://eepurl.com/MQTPb',
59-
'ca': 'http://eepurl.com/M7HU9',
60-
'eo': 'http://eepurl.com/_RE_X',
61-
'es': 'http://eepurl.com/br8NNj',
62-
'fa': 'http://eepurl.com/br8TlT',
63-
'zh': 'http://eepurl.com/bsmGhT',
64-
'ur': 'http://eepurl.com/bsmG1P',
65-
'kn': 'http://eepurl.com/buxugf',
66-
'lv': 'http://eepurl.com/b0V-yj',
67-
'el': 'http://eepurl.com/b0WcUr',
68-
'te': 'http://eepurl.com/b3EjMn',
69-
'oc': 'http://eepurl.com/dxJIYf',
70-
'ru': 'http://eepurl.com/dxJJGn',
71-
'uk': 'http://eepurl.com/dxJKwf'}
72-
73-
74-
def mkdir_p(path):
75-
# bolton
76-
import errno
77-
try:
78-
os.makedirs(path)
79-
except OSError as exc:
80-
if exc.errno == errno.EEXIST and os.path.isdir(path):
81-
return
82-
raise

weeklypedia/fetch.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
import json
55
import urllib2
66
from datetime import datetime
7-
7+
from boltons.fileutils import mkdir_p
88

99
from common import LANG_MAP, DEBUG, DEFAULT_LANGUAGE, API_BASE_URL
10-
from common import DATA_BASE_PATH, DATA_PATH_TMPL, mkdir_p
10+
from common import DATA_BASE_PATH, DATA_PATH_TMPL
1111

1212

1313
def fetch_rc(lang=DEFAULT_LANGUAGE):
@@ -75,7 +75,6 @@ def get_latest_data_path(lang, include_dev=DEBUG):
7575
return os.path.join(issue_path, latest_issue_fn)
7676

7777

78-
7978
def get_argparser():
8079
from argparse import ArgumentParser
8180
desc = "fetch json data from labs"

weeklypedia/issue_templates/base/archive.html

Lines changed: 64 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -12,57 +12,73 @@
1212
<title>$HEAD_TITLE$</title>
1313
</head>
1414
<body>
15-
<div class="header">
16-
<h1><span>$BODY_TITLE$</span></h1>
17-
<p>$DESCRIPTION$</p>
18-
<p>$DELIVERY_DESCRIPTION$</p>
19-
</div>
20-
<div class="announce">
21-
<ul class="breadcrumb">
22-
<li><a href="../../../index.html">$HOME_LINK$</a></li>
23-
<li><a href="../index.html">$ARCHIVE_LINK$</a></li>
24-
<li>$ISSUE_LABEL$</li>
25-
</ul>
26-
</div>
27-
<div class="main">
28-
<div class="content">
29-
<p id="intro">{intro|s}</p>
30-
<h2 id="articles">$ARTICLES_HEADING$</h2>
31-
<p>{#stats}$ARTICLES_SUMMARY${/stats} $ARTICLES_INTRO$:</p>
32-
<ol>
33-
{#mainspace}
34-
<li><a href="https://{short_lang_name}.wikipedia.org/wiki/{title}" target="_blank">{title_s}</a> <span dir="ltr">(<a href="https://{short_lang_name}.wikipedia.org/w/index.php?title={title}&diff={rev_ids.new}&oldid={rev_ids.old}">$DIFF_COUNT$</a> $DIFF_AUTHOR_COUNT$)</span></li>
35-
{/mainspace}
36-
</ol>
15+
<div class="container">
16+
<div class="header">
17+
<h1><span>$BODY_TITLE$</span></h1>
18+
<p>$DESCRIPTION$</p>
19+
<p>$DELIVERY_DESCRIPTION$</p>
20+
</div>
21+
<div class="announce">
22+
<ul class="breadcrumb">
23+
<li><a href="../../../index.html">$HOME_LINK$</a></li>
24+
<li><a href="../index.html">$ARCHIVE_LINK$</a></li>
25+
<li>$ISSUE_LABEL$</li>
26+
</ul>
27+
</div>
28+
<div class="main">
29+
<div class="content">
30+
<p id="intro">{intro|s}</p>
31+
<h2 id="articles">$ARTICLES_HEADING$</h2>
32+
<p>{#stats}$ARTICLES_SUMMARY${/stats} $ARTICLES_INTRO$:</p>
33+
<ol>
34+
{#mainspace}
35+
<li><a href="https://{short_lang_name}.wikipedia.org/wiki/{title}" target="_blank">{title_s}</a> <span dir="ltr">(<a href="https://{short_lang_name}.wikipedia.org/w/index.php?title={title}&diff={rev_ids.new}&oldid={rev_ids.old}">$DIFF_COUNT$</a> $DIFF_AUTHOR_COUNT$)</span></li>
36+
{/mainspace}
37+
</ol>
3738

38-
<h2 id="new-articles">$NEW_ARTICLES_HEADING$</h2>
39-
<p>$NEW_ARTICLES_INTRO$</p>
40-
<ol>
41-
{#new_articles}
42-
<li><a href="https://{short_lang_name}.wikipedia.org/wiki/{title}" target="_blank">{title_s}</a> <span dir="ltr">($DIFF_COUNT$ $DIFF_AUTHOR_COUNT$)</span></li>
43-
{/new_articles}
44-
</ol>
39+
<h2 id="new-articles">$NEW_ARTICLES_HEADING$</h2>
40+
<p>$NEW_ARTICLES_INTRO$</p>
41+
<ol>
42+
{#new_articles}
43+
<li><a href="https://{short_lang_name}.wikipedia.org/wiki/{title}" target="_blank">{title_s}</a> <span dir="ltr">($DIFF_COUNT$ $DIFF_AUTHOR_COUNT$)</span></li>
44+
{/new_articles}
45+
</ol>
4546

46-
<h2 id="discussions">$DISCUSSIONS_HEADING$</h2>
47-
<p>$DISCUSSIONS_INTRO$:</p>
48-
<ol>
49-
{#talkspace}
50-
<li><a href="https://{short_lang_name}.wikipedia.org/wiki/Talk:{title}" target="_blank">{title_s}</a></li>
51-
{/talkspace}
52-
</ol>
47+
<h2 id="discussions">$DISCUSSIONS_HEADING$</h2>
48+
<p>$DISCUSSIONS_INTRO$:</p>
49+
<ol>
50+
{#talkspace}
51+
<li><a href="https://{short_lang_name}.wikipedia.org/wiki/Talk:{title}" target="_blank">{title_s}</a></li>
52+
{/talkspace}
53+
</ol>
5354

54-
<h2 id="statistics">$STATS_HEADING$</h2>
55-
<p>$STATS_INTRO$:</p>
56-
<ul>
57-
<li>$USER_EDIT_COUNTS$</li>
58-
<li>$ANON_EDIT_COUNTS$</li>
59-
<li>$BOT_EDIT_COUNTS$</li>
60-
</ul>
61-
<a href="{signup_url}" class="signup"><span>$SIGNUP_LINK$</span></a>
62-
<div class="content">
63-
<h2>$ABOUT_HEADING$</h2>
64-
<p>$ABOUT_TEXT$</p>
65-
<p><a href="http://blog.hatnote.com/">$BLOG_LINK$</a>.</p>
55+
<h2 id="statistics">$STATS_HEADING$</h2>
56+
<p>$STATS_INTRO$:</p>
57+
<ul>
58+
<li>$USER_EDIT_COUNTS$</li>
59+
<li>$ANON_EDIT_COUNTS$</li>
60+
<li>$BOT_EDIT_COUNTS$</li>
61+
</ul>
62+
63+
<h2>$SIGNUP$</h2>
64+
<p>$PITCH$</p>
65+
66+
<form action="https://mailer.hatnote.com/s/subscribe" method="POST" accept-charset="utf-8">
67+
<label class="email-label" for="email">$EMAIL$</label>
68+
<input class="email-input" type="email" name="email" id="email"/>
69+
<div style="display:none;">
70+
<label for="hp">HP</label><br/>
71+
<input type="text" name="hp" id="hp"/></div>
72+
<input type="hidden" name="list" value="{list_id}"/>
73+
<input type="hidden" name="subform" value="yes"/>
74+
<input class="sub-button" type="submit" name="submit" value="$SUBSCRIBE$" id="submit"/>
75+
</form>
76+
77+
<div class="content">
78+
<h2>$ABOUT_HEADING$</h2>
79+
<p>$ABOUT_TEXT$</p>
80+
<p><a href="http://blog.hatnote.com/">$BLOG_LINK$</a>.</p>
81+
</div>
6682
</div>
6783
</div>
6884
<script>

weeklypedia/issue_templates/base/email.html

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,29 @@ <h2 style="margin: 40px 0 10px;padding: 0;font: 800 Sans-Serif;font-size: 28px;l
6262
<td style="margin: 0;padding: 0;font-family: Sans-Serif;font-size: 100%;line-height: 1.6;"></td>
6363
</tr>
6464
</table>
65+
66+
<table border="0" cellpadding="0" cellspacing="0" width="100%" style="background-color:#ffffff;border-top:1px solid #e5e5e5">
67+
<tbody><tr>
68+
<td align="center" valign="top" style="padding-top:20px;padding-bottom:20px">
69+
<table border="0" cellpadding="0" cellspacing="0">
70+
<tbody><tr>
71+
<td align="center" valign="top" style="color:#606060;font-family:Helvetica,Arial,sans-serif;font-size:11px;line-height:150%;padding-right:20px;padding-bottom:5px;padding-left:20px;text-align:center">
72+
$SENT_TO$ [Email]
73+
<br>
74+
<a href="{archive_link}" style="color:#404040!important" target="_blank">$SIGNUP$</a> · <a href="[unsubscribe]" style="color:#404040!important" target="_blank">$UNSUBSCRIBE$</a>
75+
<br>
76+
Hatnote · 558 N 3rd St. · San Jose, CA 95112 · USA
77+
<br>
78+
<br>
79+
80+
</td>
81+
</tr>
82+
</tbody></table>
83+
</td>
84+
</tr>
85+
</tbody>
86+
</table>
87+
6588
<!-- /body -->
6689

6790
</body>

0 commit comments

Comments
 (0)