Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Queue up invites

  • Loading branch information...
commit 578d83fdbd2dc6151c55c84bbe2bb8ba0183e54f 1 parent b9347a9
Mike Dirolf mdirolf authored

Showing 4 changed files with 73 additions and 22 deletions. Show diff stats Hide diff stats

  1. +13 0 db.py
  2. +2 4 github.py
  3. +7 0 test/test_www.py
  4. +51 18 www.py
13 db.py
@@ -51,3 +51,16 @@ def save_user(username, email_address, display_name):
51 51
52 52 def user(username):
53 53 return db.users.find_one({"_id": username})
  54 +
  55 +
  56 +# Invite queue
  57 +def pending_invite(repo_name, github_url, inviter, username, group_id):
  58 + db.invites.save({"repo_name": repo_name,
  59 + "github_url": github_url,
  60 + "inviter": inviter,
  61 + "username": username,
  62 + "group_id": group_id}, safe=True)
  63 +
  64 +
  65 +def next_invite():
  66 + return db.invites.find_and_modify(remove=True, sort={'_id': -1})
6 github.py
@@ -115,17 +115,15 @@ def current_user():
115 115 def user_info(username):
116 116 existing = db.user(username)
117 117 if existing:
118   - return existing
  118 + return existing, True
119 119
120 120 u = "http://github.com/api/v2/json/user/show/" + username
121 121 data = json.loads(urlopen(u).read())
122 122 if "error" in data:
123   - if "Rate Limit" in data["error"][0]:
124   - raise RateLimited()
125 123 raise Error("GitHub error: " + repr(data["error"]))
126 124 data = data["user"]
127 125 db.save_user(username, data.get("email", None), data.get("name", None))
128   - return data
  126 + return data, False
129 127
130 128
131 129 def repos(org=None):
7 test/test_www.py
@@ -2,6 +2,7 @@
2 2 import re
3 3 import StringIO
4 4 import sys
  5 +import time
5 6 import unittest
6 7 import urllib
7 8 sys.path[0:0] = [""]
@@ -21,6 +22,9 @@
21 22 RATE_LIMITED = False
22 23
23 24
  25 +www.SLEEP_INTERVAL = 0.1
  26 +
  27 +
24 28 # A little monkey-patching
25 29 def our_urlopen(url, params=None):
26 30 global GITHUB
@@ -130,6 +134,7 @@ def test_add_user_without_name(self):
130 134 res = self.submit(res.form)
131 135 self.assertIn("Gitlist has been created", res)
132 136
  137 + time.sleep(0.7)
133 138 mailbox = sandbox.mailbox()
134 139 self.assertEqual(2, len(mailbox))
135 140 self.assertEqual(1, len(mailbox["test@example.com"]))
@@ -156,6 +161,7 @@ def test_create_own_existing(self):
156 161 res = self.submit(res.form)
157 162 self.assertIn("Gitlist has been created", res)
158 163
  164 + time.sleep(0.7)
159 165 mailbox = sandbox.mailbox()
160 166 self.assertEqual(2, len(mailbox))
161 167 self.assertEqual(1, len(mailbox["test@example.com"]))
@@ -185,6 +191,7 @@ def test_create_other_existing(self):
185 191 res = self.submit(res.form)
186 192 self.assertIn("Gitlist has been created", res)
187 193
  194 + time.sleep(0.7)
188 195 mailbox = sandbox.mailbox()
189 196 self.assertEqual(2, len(mailbox))
190 197 self.assertEqual(1, len(mailbox["test@example.com"]))
69 www.py
@@ -3,6 +3,8 @@
3 3 import json
4 4 import re
5 5 import sys
  6 +import threading
  7 +import time
6 8 import urlparse
7 9
8 10 import decorator
@@ -36,6 +38,52 @@
36 38 smtp_server=settings.relay_host)
37 39
38 40
  41 +SLEEP_INTERVAL = 1
  42 +
  43 +class SendInvites(threading.Thread):
  44 + '''
  45 + We send invites from a separate thread to try to avoid going over
  46 + GH's rate limit (60 calls per minute for V2 API).
  47 + '''
  48 +
  49 + def run(self):
  50 + while True:
  51 + invite = db.next_invite()
  52 + if not invite:
  53 + time.sleep(SLEEP_INTERVAL)
  54 + continue
  55 +
  56 + repo_name = invite["repo_name"]
  57 + github_url = invite["github_url"]
  58 + inviter = invite["inviter"]
  59 + username = invite["username"]
  60 + group = fiesta.FiestaGroup.from_id(fiesta_api, invite["group_id"])
  61 +
  62 + welcome_message = {"subject": "Invitation to %s@gitlists.com" % repo_name,
  63 + "markdown": """
  64 +[%s](%s) invited you to a [Gitlist](https://gitlists.com) for [%s](%s). Gitlists are dead-simple mailing lists for GitHub projects.
  65 +
  66 +[Click here]($invite_url) to join the list. If you don't want to join, just ignore this message.
  67 +
  68 +Have a great day!
  69 +""" % (inviter, "http://github.com/" + inviter, repo_name, github_url)}
  70 +
  71 + user, cache = github.user_info(username)
  72 + if user.get("email", None):
  73 + group.add_member(user["email"],
  74 + display_name=user.get("name", ""),
  75 + welcome_message=welcome_message,
  76 + send_invite=True)
  77 +
  78 + if not cache:
  79 + time.sleep(SLEEP_INTERVAL)
  80 +
  81 +
  82 +# Invite thread
  83 +send_invites = SendInvites()
  84 +send_invites.start()
  85 +
  86 +
39 87 def gen_xsrf(actions):
40 88 xsrf = {}
41 89 for action in actions:
@@ -185,25 +233,9 @@ def repo_create(name, org=None):
185 233 display_name=user.get("name", ""),
186 234 welcome_message=welcome_message)
187 235
188   - welcome_message = {"subject": "Invitation to %s@gitlists.com" % repo["name"],
189   - "markdown": """
190   -[%s](%s) invited you to a [Gitlist](https://gitlists.com) for [%s](%s). Gitlists are dead-simple mailing lists for GitHub projects.
191   -
192   -[Click here]($invite_url) to join the list. If you don't want to join, just ignore this message.
193   -
194   -Have a great day!
195   -""" % (user["login"], "http://github.com/" + user["login"],
196   - repo["name"], github_url)}
197   -
198 236 for username in to_invite:
199   - member_user = github.user_info(username)
200   - if not member_user.get("email", None):
201   - continue
202   -
203   - group.add_member(member_user["email"],
204   - display_name=member_user.get("name", ""),
205   - welcome_message=welcome_message,
206   - send_invite=True)
  237 + db.pending_invite(repo["name"], github_url, user["login"],
  238 + username, group.id)
207 239
208 240 db.new_list(repo["name"], user["login"], group.id)
209 241 flask.flash("Your Gitlist has been created – check your email at '%s'." % user["email"])
@@ -265,6 +297,7 @@ def run(self):
265 297
266 298 if __name__ == '__main__':
267 299 port = 7176
  300 +
268 301 if len(sys.argv) > 2:
269 302 port = int(sys.argv[2])
270 303 if settings.env == "prod":

0 comments on commit 578d83f

Please sign in to comment.
Something went wrong with that request. Please try again.