-
Notifications
You must be signed in to change notification settings - Fork 0
/
secret_santa.py
executable file
·106 lines (91 loc) · 3.28 KB
/
secret_santa.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
import config
import sys
from optparse import OptionParser
import simplejson
import random
import subprocess
import smtplib
import socket
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import datetime
### for generating pairings
def generateChain():
'''
Generate a single cycle of people. The logic is really dumb, so if
there are no possible cycles it probably recurses until stack overflow.
'''
chain = [random.choice(people.values())['name']]
while len(chain) < len(people.values()):
giver = chain[-1]
eligible = map(lambda p: p['name'],
filter(lambda p: giver not in p.get('block', []) and \
giver != p['name'] and \
p['name'] not in chain,
people.values()))
if not eligible:
return generateChain() # lazy, start over
chain.append(random.choice(eligible))
# make sure last and first person are compatible
if chain[-1] in people[chain[0]].get('block', []):
return generateChain()
return chain
### for sending email
def send_mail(to, subject, body):
msg = MIMEMultipart('alternative')
msg['subject'] = subject
msg['To'] = to
msg['From'] = config.SENDER
msg.attach(MIMEText(body, 'html'))
server = smtplib.SMTP(config.SMTP)
server.starttls()
server.login(config.SENDER, config.PASSWORD)
server.sendmail(config.SENDER, [to], msg.as_string())
server.quit()
def email_assignment(giver, recipient):
'''my formatting for sent emails'''
message = "Hi {0},<br>\
Your Secret Santee is <b>{1}</b>.<br>\
Roommates: {2}<br>\
Address: {3}<br>\
<br>\
Secret Santa is on Friday, Dec 20. God be with ye.<br>\
<br>\
This message is automatically generated, do not respond."
message = message.format(
giver['name'], recipient['name'],
recipient.get('roommates', ''),
recipient.get('address', '')
)
send_mail(giver['email'], "Secret Santa assignment", message)
### go
if __name__ == "__main__":
parser = OptionParser(usage = "usage: %prog [options] <input>")
parser.add_option("--fake",
dest="fake", default=False, action="store_true",
help=("Do a fake run -- generate a cycle without "
"actually sending emails."))
(options, args) = parser.parse_args()
if len(args)==0:
raise Exception("No input provided; please specify a valid JSON file.")
# load people info
f = open(args[0],'r')
global people
people = simplejson.loads(f.read())
for name, person in people.iteritems():
people[name]['name'] = name
# make blacklisting bidirectional
for name, person in people.iteritems():
for blockee_name in person.get('block', []):
if blockee_name in people:
people[blockee_name]['block'] = (
people[blockee_name].get('block', []) + [name])
# email each member of chain
chain = generateChain()
for i,giver_name in enumerate(chain):
recipient_name = chain[(i+1)%len(chain)]
if not options.fake:
email_assignment(people['giver_name'], people['recipient_name'])
print 'Sending email %d' % i
if options.fake:
print chain