2012-10-02 14:09:24 -04:00
|
|
|
#!/usr/bin/python
|
|
|
|
import sys
|
|
|
|
import traceback
|
|
|
|
import simplejson
|
|
|
|
import re
|
|
|
|
import time
|
|
|
|
import subprocess
|
|
|
|
import optparse
|
|
|
|
import os
|
|
|
|
import datetime
|
|
|
|
import textwrap
|
2012-10-12 17:19:49 -04:00
|
|
|
import signal
|
2012-10-02 14:09:24 -04:00
|
|
|
|
2012-10-12 15:15:44 -04:00
|
|
|
root_path = "/mit/tabbott/for_friends"
|
2012-10-29 14:34:15 -04:00
|
|
|
sys.path.append(root_path)
|
2012-10-12 15:15:44 -04:00
|
|
|
sys.path.append(root_path + "/python-zephyr")
|
|
|
|
sys.path.append(root_path + "/python-zephyr/build/lib.linux-x86_64-2.6/")
|
2012-10-02 14:09:24 -04:00
|
|
|
|
|
|
|
parser = optparse.OptionParser()
|
|
|
|
parser.add_option('--forward-class-messages',
|
|
|
|
dest='forward_class_messages',
|
|
|
|
default=False,
|
2012-10-29 14:07:56 -04:00
|
|
|
help=optparse.SUPPRESS_HELP,
|
2012-10-02 14:09:24 -04:00
|
|
|
action='store_true')
|
|
|
|
parser.add_option('--resend-log',
|
|
|
|
dest='resend_log',
|
|
|
|
default=False,
|
2012-10-29 14:07:56 -04:00
|
|
|
help=optparse.SUPPRESS_HELP,
|
2012-10-02 14:09:24 -04:00
|
|
|
action='store_true')
|
|
|
|
parser.add_option('--enable-log',
|
|
|
|
dest='enable_log',
|
|
|
|
default=False,
|
2012-10-29 14:07:56 -04:00
|
|
|
help=optparse.SUPPRESS_HELP,
|
2012-10-02 14:09:24 -04:00
|
|
|
action='store_true')
|
|
|
|
parser.add_option('--no-forward-personals',
|
|
|
|
dest='forward_personals',
|
2012-10-29 14:07:56 -04:00
|
|
|
help=optparse.SUPPRESS_HELP,
|
2012-10-02 14:09:24 -04:00
|
|
|
default=True,
|
|
|
|
action='store_false')
|
|
|
|
parser.add_option('--forward-from-humbug',
|
2012-10-12 17:01:15 -04:00
|
|
|
dest='forward_from_humbug',
|
|
|
|
default=False,
|
2012-10-29 14:07:56 -04:00
|
|
|
help=optparse.SUPPRESS_HELP,
|
2012-10-12 17:01:15 -04:00
|
|
|
action='store_true')
|
2012-10-12 17:47:18 -04:00
|
|
|
parser.add_option('--verbose',
|
|
|
|
dest='verbose',
|
|
|
|
default=False,
|
2012-10-29 14:07:56 -04:00
|
|
|
help=optparse.SUPPRESS_HELP,
|
2012-10-12 17:47:18 -04:00
|
|
|
action='store_true')
|
2012-10-29 12:51:44 -04:00
|
|
|
parser.add_option('--sync-subscriptions',
|
|
|
|
dest='sync_subscriptions',
|
|
|
|
default=False,
|
|
|
|
action='store_true')
|
2012-10-02 15:47:59 -04:00
|
|
|
parser.add_option('--site',
|
|
|
|
dest='site',
|
2012-10-27 11:36:55 -04:00
|
|
|
default="https://humbughq.com",
|
2012-10-29 14:07:56 -04:00
|
|
|
help=optparse.SUPPRESS_HELP,
|
2012-10-02 15:47:59 -04:00
|
|
|
action='store')
|
2012-10-18 18:09:47 -04:00
|
|
|
parser.add_option('--user',
|
|
|
|
dest='user',
|
|
|
|
default=os.environ["USER"],
|
2012-10-29 14:07:56 -04:00
|
|
|
help=optparse.SUPPRESS_HELP,
|
2012-10-18 18:09:47 -04:00
|
|
|
action='store')
|
|
|
|
parser.add_option('--api-key-file',
|
|
|
|
dest='api_key_file',
|
|
|
|
default=os.path.join(os.environ["HOME"], "Private", ".humbug-api-key"),
|
2012-10-02 15:47:59 -04:00
|
|
|
action='store')
|
2012-10-02 14:09:24 -04:00
|
|
|
(options, args) = parser.parse_args()
|
|
|
|
|
2012-10-18 18:09:47 -04:00
|
|
|
api_key = file(options.api_key_file).read().strip()
|
2012-10-18 10:37:34 -04:00
|
|
|
|
2012-10-02 15:47:59 -04:00
|
|
|
import api.common
|
2012-10-18 18:09:47 -04:00
|
|
|
humbug_client = api.common.HumbugAPI(email=options.user + "@mit.edu",
|
|
|
|
api_key=api_key,
|
2012-10-02 15:47:59 -04:00
|
|
|
verbose=True,
|
2012-10-23 10:59:42 -04:00
|
|
|
client="zephyr_mirror",
|
2012-10-02 15:47:59 -04:00
|
|
|
site=options.site)
|
|
|
|
|
2012-10-12 14:51:57 -04:00
|
|
|
start_time = time.time()
|
2012-10-02 15:47:59 -04:00
|
|
|
|
2012-10-12 13:53:29 -04:00
|
|
|
def humbug_username(zephyr_username):
|
2012-10-02 14:09:24 -04:00
|
|
|
return zephyr_username.lower().split("@")[0] + "@mit.edu"
|
|
|
|
|
2012-10-23 11:22:51 -04:00
|
|
|
def unwrap_lines(body):
|
|
|
|
# Split into paragraphs at two consecutive newlines, or a newline followed
|
|
|
|
# by an indent.
|
|
|
|
return '\n\n'.join(p.replace('\n', ' ') for p in re.split(r'\n[ \t\n]', body))
|
|
|
|
|
2012-10-02 14:09:24 -04:00
|
|
|
def send_humbug(zeph):
|
2012-10-18 11:14:03 -04:00
|
|
|
if options.forward_class_messages:
|
|
|
|
zeph["forged"] = "yes"
|
2012-10-12 13:53:29 -04:00
|
|
|
zeph["sender"] = humbug_username(zeph["sender"])
|
2012-10-02 14:09:24 -04:00
|
|
|
zeph['fullname'] = username_to_fullname(zeph['sender'])
|
|
|
|
zeph['shortname'] = zeph['sender'].split('@')[0]
|
2012-10-10 18:01:39 -04:00
|
|
|
if "subject" in zeph:
|
2012-10-11 10:35:50 -04:00
|
|
|
zeph["subject"] = zeph["subject"][:60]
|
2012-10-16 14:57:42 -04:00
|
|
|
if zeph['type'] == 'stream':
|
|
|
|
# Forward messages sent to -c foo -i bar to stream bar subject "instance"
|
|
|
|
if zeph["stream"] == "message":
|
|
|
|
zeph['stream'] = zeph['subject']
|
|
|
|
zeph['subject'] = "instance %s" % (zeph['stream'])
|
|
|
|
elif zeph["stream"] == "tabbott-test5":
|
|
|
|
zeph['stream'] = zeph['subject']
|
|
|
|
zeph['subject'] = "test instance %s" % (zeph['stream'])
|
2012-10-02 14:09:24 -04:00
|
|
|
|
|
|
|
for key in zeph.keys():
|
|
|
|
if isinstance(zeph[key], unicode):
|
2012-10-03 16:32:50 -04:00
|
|
|
zeph[key] = zeph[key].encode("utf-8")
|
2012-10-02 14:09:24 -04:00
|
|
|
elif isinstance(zeph[key], str):
|
2012-10-03 16:32:50 -04:00
|
|
|
zeph[key] = zeph[key].decode("utf-8")
|
2012-10-02 14:09:24 -04:00
|
|
|
|
2012-10-23 11:22:51 -04:00
|
|
|
zeph['content'] = unwrap_lines(zeph['content'])
|
2012-10-04 16:13:47 -04:00
|
|
|
return humbug_client.send_message(zeph)
|
2012-10-02 14:09:24 -04:00
|
|
|
|
|
|
|
def fetch_fullname(username):
|
|
|
|
try:
|
|
|
|
match_user = re.match(r'([a-zA-Z0-9_]+)@mit\.edu', username)
|
|
|
|
if match_user:
|
2012-10-12 13:53:29 -04:00
|
|
|
proc = subprocess.Popen(['hesinfo', match_user.group(1), 'passwd'],
|
2012-10-12 15:46:42 -04:00
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
stderr=subprocess.PIPE)
|
2012-10-02 14:09:24 -04:00
|
|
|
out, _err_unused = proc.communicate()
|
|
|
|
if proc.returncode == 0:
|
|
|
|
return out.split(':')[4].split(',')[0]
|
|
|
|
except:
|
2012-10-12 15:45:14 -04:00
|
|
|
print >>sys.stderr, '%s: zephyr=>humbug: Error getting fullname for %s' % \
|
|
|
|
(datetime.datetime.now(), username)
|
2012-10-02 14:09:24 -04:00
|
|
|
traceback.print_exc()
|
|
|
|
|
2012-10-12 13:21:21 -04:00
|
|
|
domains = [
|
|
|
|
("@CS.CMU.EDU", " (CMU)"),
|
|
|
|
("@ANDREW.CMU.EDU", " (CMU)"),
|
|
|
|
("@IASTATE.EDU", " (IASTATE)"),
|
|
|
|
("@1TS.ORG", " (1TS)"),
|
|
|
|
("@DEMENTIA.ORG", " (DEMENTIA)"),
|
|
|
|
("@MIT.EDU", ""),
|
|
|
|
]
|
|
|
|
for (domain, tag) in domains:
|
|
|
|
if username.upper().endswith(domain):
|
|
|
|
return username.split("@")[0] + tag
|
2012-10-12 11:45:41 -04:00
|
|
|
return username
|
2012-10-02 14:09:24 -04:00
|
|
|
|
|
|
|
fullnames = {}
|
|
|
|
def username_to_fullname(username):
|
|
|
|
if username not in fullnames:
|
|
|
|
fullnames[username] = fetch_fullname(username)
|
|
|
|
return fullnames[username]
|
|
|
|
|
2012-10-11 14:39:52 -04:00
|
|
|
current_zephyr_subs = {}
|
|
|
|
def ensure_subscribed(sub):
|
|
|
|
if sub in current_zephyr_subs:
|
|
|
|
return
|
|
|
|
subs.add((sub, '*', '*'))
|
|
|
|
current_zephyr_subs[sub] = True
|
|
|
|
|
|
|
|
def update_subscriptions_from_humbug():
|
|
|
|
try:
|
|
|
|
res = humbug_client.get_public_streams()
|
|
|
|
streams = res["streams"]
|
|
|
|
except:
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s: Error getting public streams:" % (datetime.datetime.now())
|
2012-10-11 14:39:52 -04:00
|
|
|
traceback.print_exc()
|
|
|
|
return
|
|
|
|
for stream in streams:
|
|
|
|
ensure_subscribed(stream)
|
2012-10-02 14:09:24 -04:00
|
|
|
|
2012-10-12 14:51:57 -04:00
|
|
|
def maybe_restart_mirroring_script():
|
2012-10-29 14:11:24 -04:00
|
|
|
if os.stat(root_path + "/stamps/restart_stamp").st_mtime > start_time or \
|
2012-10-29 14:34:24 -04:00
|
|
|
((options.user == "tabbott" or options.user == "tabbott/extra") and
|
2012-10-29 14:11:24 -04:00
|
|
|
os.stat(root_path + "/stamps/tabbott_stamp").st_mtime > start_time):
|
2012-10-12 17:47:18 -04:00
|
|
|
print
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s: zephyr mirroring script has been updated; restarting..." % \
|
|
|
|
(datetime.datetime.now())
|
2012-10-12 17:19:49 -04:00
|
|
|
os.kill(child_pid, signal.SIGKILL)
|
2012-10-12 15:13:14 -04:00
|
|
|
while True:
|
|
|
|
try:
|
2012-10-29 17:06:58 -04:00
|
|
|
os.execvp(root_path + "/user_root/zephyr_mirror.py", sys.argv)
|
2012-10-12 15:13:14 -04:00
|
|
|
except:
|
|
|
|
print "Error restarting, trying again."
|
|
|
|
traceback.print_exc()
|
|
|
|
time.sleep(10)
|
2012-10-12 14:51:57 -04:00
|
|
|
|
2012-10-02 14:09:24 -04:00
|
|
|
def process_loop(log):
|
2012-10-11 14:39:52 -04:00
|
|
|
sleep_count = 0
|
|
|
|
sleep_time = 0.1
|
2012-10-02 14:09:24 -04:00
|
|
|
while True:
|
2012-10-11 14:39:52 -04:00
|
|
|
notice = zephyr.receive(block=False)
|
2012-10-12 14:51:28 -04:00
|
|
|
if notice is not None:
|
|
|
|
try:
|
|
|
|
process_notice(notice, log)
|
|
|
|
except:
|
2012-10-12 15:45:14 -04:00
|
|
|
print >>sys.stderr, '%s: zephyr=>humbug: Error relaying zephyr' % \
|
|
|
|
(datetime.datetime.now())
|
2012-10-12 14:51:28 -04:00
|
|
|
traceback.print_exc()
|
|
|
|
time.sleep(2)
|
|
|
|
|
2012-10-12 14:51:57 -04:00
|
|
|
maybe_restart_mirroring_script()
|
|
|
|
|
2012-10-12 14:51:28 -04:00
|
|
|
time.sleep(sleep_time)
|
|
|
|
sleep_count += sleep_time
|
|
|
|
if sleep_count > 15:
|
|
|
|
sleep_count = 0
|
|
|
|
if options.forward_class_messages:
|
|
|
|
# Ask the Humbug server about any new classes to subscribe to
|
|
|
|
update_subscriptions_from_humbug()
|
|
|
|
continue
|
2012-10-02 14:09:24 -04:00
|
|
|
|
2012-10-12 14:39:47 -04:00
|
|
|
def process_notice(notice, log):
|
2012-10-19 13:13:52 -04:00
|
|
|
try:
|
|
|
|
zsig, body = notice.message.split("\x00", 1)
|
|
|
|
except ValueError:
|
|
|
|
body = notice.message
|
|
|
|
zsig = ""
|
2012-10-12 14:39:47 -04:00
|
|
|
is_personal = False
|
|
|
|
is_huddle = False
|
|
|
|
|
|
|
|
if notice.opcode == "PING":
|
|
|
|
# skip PING messages
|
|
|
|
return
|
|
|
|
|
|
|
|
if isinstance(zsig, str):
|
|
|
|
# Check for width unicode character u'\u200B'.encode("utf-8")
|
|
|
|
if u'\u200B'.encode("utf-8") in zsig:
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s: zephyr=>humbug: Skipping message from Humbug!" % \
|
|
|
|
(datetime.datetime.now())
|
2012-10-12 14:39:47 -04:00
|
|
|
return
|
|
|
|
|
|
|
|
sender = notice.sender.lower().replace("athena.mit.edu", "mit.edu")
|
|
|
|
recipient = notice.recipient.lower().replace("athena.mit.edu", "mit.edu")
|
2012-10-16 14:39:53 -04:00
|
|
|
zephyr_class = notice.cls.lower()
|
|
|
|
instance = notice.instance.lower()
|
2012-10-12 14:39:47 -04:00
|
|
|
|
2012-10-17 11:20:52 -04:00
|
|
|
if (zephyr_class == "message" and recipient != ""):
|
2012-10-12 14:39:47 -04:00
|
|
|
is_personal = True
|
|
|
|
if body.startswith("CC:"):
|
|
|
|
is_huddle = True
|
|
|
|
# Map "CC: sipbtest espuser" => "starnine@mit.edu,espuser@mit.edu"
|
|
|
|
huddle_recipients_list = [humbug_username(x.strip()) for x in
|
|
|
|
body.split("\n")[0][4:].split()]
|
|
|
|
if sender not in huddle_recipients_list:
|
|
|
|
huddle_recipients_list.append(sender)
|
|
|
|
huddle_recipients = ",".join(huddle_recipients_list)
|
2012-10-16 14:39:53 -04:00
|
|
|
if (zephyr_class == "mail" and instance == "inbox"):
|
2012-10-12 14:39:47 -04:00
|
|
|
is_personal = True
|
|
|
|
|
|
|
|
# Drop messages not to the listed subscriptions
|
2012-10-16 14:39:53 -04:00
|
|
|
if (zephyr_class not in current_zephyr_subs) and not \
|
2012-10-12 14:39:47 -04:00
|
|
|
(is_personal and options.forward_personals):
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s: zephyr=>humbug: Skipping ... %s/%s/%s" % \
|
2012-10-16 14:39:53 -04:00
|
|
|
(datetime.datetime.now(), zephyr_class, instance, is_personal)
|
2012-10-12 14:39:47 -04:00
|
|
|
return
|
|
|
|
|
|
|
|
if is_huddle:
|
|
|
|
zeph = { 'type' : 'personal',
|
|
|
|
'time' : str(notice.time),
|
|
|
|
'sender' : sender,
|
|
|
|
'recipient' : huddle_recipients,
|
|
|
|
'zsig' : zsig, # logged here but not used by app
|
|
|
|
'content' : body.split("\n", 1)[1] }
|
|
|
|
elif is_personal:
|
|
|
|
zeph = { 'type' : 'personal',
|
|
|
|
'time' : str(notice.time),
|
|
|
|
'sender' : sender,
|
|
|
|
'recipient' : humbug_username(recipient),
|
|
|
|
'zsig' : zsig, # logged here but not used by app
|
|
|
|
'content' : body }
|
|
|
|
else:
|
|
|
|
zeph = { 'type' : 'stream',
|
|
|
|
'time' : str(notice.time),
|
|
|
|
'sender' : sender,
|
2012-10-16 14:39:53 -04:00
|
|
|
'stream' : zephyr_class,
|
|
|
|
'subject' : instance,
|
2012-10-12 14:39:47 -04:00
|
|
|
'zsig' : zsig, # logged here but not used by app
|
|
|
|
'content' : body }
|
|
|
|
|
2012-10-17 11:20:52 -04:00
|
|
|
# Add instances in for instanced personals
|
|
|
|
if zeph['type'] == "personal" and instance != "personal":
|
|
|
|
zeph["content"] = "[-i %s]" % (instance,) + "\n" + zeph["content"]
|
|
|
|
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s: zephyr=>humbug: received a message on %s/%s from %s..." % \
|
2012-10-16 14:39:53 -04:00
|
|
|
(datetime.datetime.now(), zephyr_class, instance, notice.sender)
|
2012-10-12 14:39:47 -04:00
|
|
|
log.write(simplejson.dumps(zeph) + '\n')
|
|
|
|
log.flush()
|
|
|
|
|
|
|
|
res = send_humbug(zeph)
|
|
|
|
if res.get("result") != "success":
|
|
|
|
print >>sys.stderr, 'Error relaying zephyr'
|
|
|
|
print zeph
|
|
|
|
print res
|
|
|
|
|
2012-10-02 14:09:24 -04:00
|
|
|
|
|
|
|
def zephyr_to_humbug(options):
|
|
|
|
if options.forward_class_messages:
|
2012-10-15 13:13:57 -04:00
|
|
|
update_subscriptions_from_humbug()
|
2012-10-02 14:09:24 -04:00
|
|
|
if options.forward_personals:
|
2012-10-18 18:09:47 -04:00
|
|
|
subs.add(("message", "*", options.user + "@ATHENA.MIT.EDU"))
|
2012-10-12 13:40:57 -04:00
|
|
|
if subscribed_to_mail_messages():
|
2012-10-18 18:09:47 -04:00
|
|
|
subs.add(("mail", "inbox", options.user + "@ATHENA.MIT.EDU"))
|
2012-10-02 14:09:24 -04:00
|
|
|
|
|
|
|
if options.resend_log:
|
2012-10-29 14:01:51 -04:00
|
|
|
with open('/mit/tabbott/Private/zephyrs', 'r') as log:
|
2012-10-02 14:09:24 -04:00
|
|
|
for ln in log:
|
|
|
|
try:
|
|
|
|
zeph = simplejson.loads(ln)
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s: zephyr=>humbug: sending saved message to %s from %s..." % \
|
|
|
|
(datetime.datetime.now(), zeph.get('class', zeph.get('recipient')),
|
|
|
|
zeph['sender'])
|
2012-10-02 14:09:24 -04:00
|
|
|
send_humbug(zeph)
|
|
|
|
except:
|
|
|
|
print >>sys.stderr, 'Could not send saved zephyr'
|
|
|
|
traceback.print_exc()
|
|
|
|
time.sleep(2)
|
|
|
|
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s: zephyr=>humbug: Starting receive loop." % (datetime.datetime.now(),)
|
2012-10-02 14:09:24 -04:00
|
|
|
|
|
|
|
if options.enable_log:
|
2012-10-29 14:01:51 -04:00
|
|
|
log_file = "/mit/tabbott/Private/zephyrs"
|
2012-10-02 14:09:24 -04:00
|
|
|
else:
|
|
|
|
log_file = "/dev/null"
|
|
|
|
|
|
|
|
with open(log_file, 'a') as log:
|
|
|
|
process_loop(log)
|
|
|
|
|
2012-10-02 15:47:59 -04:00
|
|
|
def forward_to_zephyr(message):
|
2012-10-02 14:09:24 -04:00
|
|
|
zsig = u"%s\u200B" % (username_to_fullname(message["sender_email"]))
|
|
|
|
if ' dot ' in zsig:
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s: humbug=>zephyr: ERROR! Couldn't compute zsig for %s!" % \
|
|
|
|
(datetime.datetime.now(), message["sender_email"])
|
2012-10-02 14:09:24 -04:00
|
|
|
return
|
|
|
|
|
|
|
|
wrapped_content = "\n".join("\n".join(textwrap.wrap(line))
|
2012-10-11 13:34:30 -04:00
|
|
|
for line in message["content"].split("\n"))
|
2012-10-02 14:09:24 -04:00
|
|
|
|
2012-10-12 13:53:29 -04:00
|
|
|
sender_email = message["sender_email"].replace("mit.edu", "ATHENA.MIT.EDU")
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s: humbug=>zephyr: Forwarding message from %s" % \
|
|
|
|
(datetime.datetime.now(), sender_email)
|
2012-10-10 16:57:21 -04:00
|
|
|
if message['type'] == "stream":
|
2012-10-16 14:57:42 -04:00
|
|
|
zephyr_class = message["display_recipient"]
|
|
|
|
instance = message["subject"]
|
|
|
|
if (instance == "instance %s" % (zephyr_class,) or
|
|
|
|
instance == "test instance %s" % (zephyr_class,)):
|
|
|
|
# Forward messages to e.g. -c -i white-magic back from the
|
|
|
|
# place we forward them to
|
|
|
|
if instance.startswith("test"):
|
|
|
|
instance = zephyr_class
|
|
|
|
zephyr_class = "tabbott-test5"
|
|
|
|
else:
|
|
|
|
instance = zephyr_class
|
|
|
|
zephyr_class = "message"
|
2012-10-12 13:53:29 -04:00
|
|
|
zeph = zephyr.ZNotice(sender=sender_email, auth=True,
|
2012-10-16 14:57:42 -04:00
|
|
|
cls=zephyr_class, instance=instance)
|
2012-10-02 14:09:24 -04:00
|
|
|
body = "%s\0%s" % (zsig, wrapped_content)
|
|
|
|
zeph.setmessage(body)
|
|
|
|
zeph.send()
|
|
|
|
elif message['type'] == "personal":
|
2012-10-12 13:53:29 -04:00
|
|
|
recipient = message["display_recipient"]["email"]
|
2012-10-16 20:56:29 -04:00
|
|
|
recipient = recipient.replace("@mit.edu", "@ATHENA.MIT.EDU")
|
2012-10-12 13:53:29 -04:00
|
|
|
zeph = zephyr.ZNotice(sender=sender_email,
|
|
|
|
auth=True, recipient=recipient,
|
2012-10-02 14:09:24 -04:00
|
|
|
cls="message", instance="personal")
|
|
|
|
body = "%s\0%s" % (zsig, wrapped_content)
|
|
|
|
zeph.setmessage(body)
|
|
|
|
zeph.send()
|
|
|
|
elif message['type'] == "huddle":
|
|
|
|
cc_list = ["CC:"]
|
|
|
|
cc_list.extend([user["email"].replace("@mit.edu", "")
|
|
|
|
for user in message["display_recipient"]])
|
|
|
|
body = "%s\0%s\n%s" % (zsig, " ".join(cc_list), wrapped_content)
|
|
|
|
for r in message["display_recipient"]:
|
2012-10-12 13:53:29 -04:00
|
|
|
recipient = r["email"].replace("mit.edu", "ATHENA.MIT.EDU")
|
|
|
|
zeph = zephyr.ZNotice(sender=sender_email, auth=True,
|
|
|
|
recipient=recipient, cls="message",
|
|
|
|
instance="personal")
|
2012-10-02 14:09:24 -04:00
|
|
|
zeph.setmessage(body)
|
|
|
|
zeph.send()
|
|
|
|
|
2012-10-02 15:47:59 -04:00
|
|
|
def maybe_forward_to_zephyr(message):
|
2012-10-18 18:09:47 -04:00
|
|
|
if message["sender_email"] == options.user + "@mit.edu":
|
2012-10-12 13:53:29 -04:00
|
|
|
timestamp_now = datetime.datetime.now().strftime("%s")
|
|
|
|
if float(message["timestamp"]) < float(timestamp_now) - 15:
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s humbug=>zephyr: Alert! Out of order message: %s < %s" % \
|
|
|
|
(datetime.datetime.now(), message["timestamp"], timestamp_now)
|
2012-10-02 15:47:59 -04:00
|
|
|
return
|
|
|
|
forward_to_zephyr(message)
|
|
|
|
|
2012-10-02 14:09:24 -04:00
|
|
|
def humbug_to_zephyr(options):
|
|
|
|
# Sync messages from zephyr to humbug
|
2012-10-12 15:45:14 -04:00
|
|
|
print "%s: humbug=>zephyr: Starting syncing messages." % (datetime.datetime.now(),)
|
2012-10-02 15:47:59 -04:00
|
|
|
humbug_client.call_on_each_message(maybe_forward_to_zephyr,
|
2012-10-19 15:37:37 -04:00
|
|
|
options={"mirror": 'zephyr_mirror'})
|
2012-10-02 14:09:24 -04:00
|
|
|
|
2012-10-12 13:40:57 -04:00
|
|
|
def subscribed_to_mail_messages():
|
|
|
|
for (cls, instance, recipient) in parse_zephyr_subs(verbose=False):
|
|
|
|
if (cls.lower() == "mail" and instance.lower() == "inbox"):
|
|
|
|
return True
|
|
|
|
return False
|
|
|
|
|
2012-10-29 12:51:44 -04:00
|
|
|
def add_humbug_subscriptions(verbose):
|
2012-10-12 13:40:57 -04:00
|
|
|
zephyr_subscriptions = set()
|
2012-10-29 12:51:44 -04:00
|
|
|
skipped = set()
|
|
|
|
for (cls, instance, recipient) in parse_zephyr_subs(verbose=verbose):
|
2012-10-16 14:57:42 -04:00
|
|
|
if cls == "message" and recipient == "*":
|
|
|
|
if instance == "*":
|
|
|
|
continue
|
|
|
|
# If you're on -i white-magic on zephyr, get on stream white-magic on humbug
|
2012-10-29 12:51:44 -04:00
|
|
|
# instead of subscribing to stream "message" on humbug
|
2012-10-16 14:57:42 -04:00
|
|
|
zephyr_subscriptions.add(instance)
|
|
|
|
continue
|
2012-10-29 12:51:44 -04:00
|
|
|
elif cls == "mail" and recipient == "inbox":
|
|
|
|
continue
|
2012-10-16 14:57:42 -04:00
|
|
|
elif instance != "*" or recipient != "*":
|
2012-10-29 12:51:44 -04:00
|
|
|
skipped.add((cls, instance, recipient))
|
2012-10-12 13:40:57 -04:00
|
|
|
continue
|
|
|
|
zephyr_subscriptions.add(cls)
|
2012-10-29 12:51:44 -04:00
|
|
|
|
2012-10-12 13:40:57 -04:00
|
|
|
if len(zephyr_subscriptions) != 0:
|
2012-10-29 12:51:44 -04:00
|
|
|
res = humbug_client.subscribe(list(zephyr_subscriptions))
|
|
|
|
already = res.get("already_subscribed")
|
|
|
|
new = res.get("subscribed")
|
|
|
|
if verbose:
|
|
|
|
if already is not None and len(already) > 0:
|
|
|
|
print
|
|
|
|
print "Already subscribed to:", ", ".join(already)
|
|
|
|
if new is not None and len(new) > 0:
|
|
|
|
print
|
|
|
|
print "Successfully subscribed to:", ", ".join(new)
|
|
|
|
|
|
|
|
if len(skipped) > 0:
|
|
|
|
if verbose:
|
|
|
|
print
|
|
|
|
print "\n".join(textwrap.wrap("""\
|
|
|
|
You have some lines in ~/.zephyr.subs that could not be
|
|
|
|
synced to your Humbug subscriptions because they do not
|
|
|
|
use "*" as both the instance and recipient and not one of
|
|
|
|
the special cases (e.g. personals and mail zephyrs) that
|
|
|
|
Humbug has a mechanism for forwarding. Humbug does not
|
|
|
|
allow subscribing to only some subjects on a Humbug
|
|
|
|
stream, so this tool has not created a corresponding
|
|
|
|
Humbug subscription to these lines in ~/.zephyr.subs:
|
|
|
|
"""))
|
|
|
|
print
|
|
|
|
|
|
|
|
for (cls, instance, recipient) in skipped:
|
|
|
|
if verbose:
|
|
|
|
print " [%s,%s,%s]" % (cls, instance, recipient)
|
|
|
|
if len(skipped) > 0:
|
|
|
|
if verbose:
|
|
|
|
print
|
|
|
|
print "\n".join(textwrap.wrap("""\
|
|
|
|
If you wish to be subscribed to any Humbug streams related
|
|
|
|
to these .zephyrs.subs lines, please do so via the Humbug
|
|
|
|
web interface.
|
|
|
|
"""))
|
|
|
|
print
|
2012-10-12 13:40:57 -04:00
|
|
|
|
|
|
|
def parse_zephyr_subs(verbose=False):
|
2012-10-11 16:20:38 -04:00
|
|
|
zephyr_subscriptions = set()
|
|
|
|
subs_file = os.path.join(os.environ["HOME"], ".zephyr.subs")
|
|
|
|
if not os.path.exists(subs_file):
|
2012-10-12 13:40:57 -04:00
|
|
|
if verbose:
|
|
|
|
print >>sys.stderr, "Couldn't find .zephyr.subs!"
|
|
|
|
print >>sys.stderr, "Do you mean to run with --no-auto-subscribe?"
|
2012-10-18 18:09:47 -04:00
|
|
|
return []
|
2012-10-11 16:20:38 -04:00
|
|
|
|
|
|
|
for line in file(subs_file, "r").readlines():
|
|
|
|
line = line.strip()
|
|
|
|
if len(line) == 0:
|
|
|
|
continue
|
|
|
|
try:
|
|
|
|
(cls, instance, recipient) = line.split(",")
|
|
|
|
except:
|
2012-10-12 13:40:57 -04:00
|
|
|
if verbose:
|
|
|
|
print >>sys.stderr, "Couldn't parse ~/.zephyr.subs line: [%s]" % (line,)
|
|
|
|
continue
|
2012-10-16 14:57:42 -04:00
|
|
|
zephyr_subscriptions.add((cls.strip(), instance.strip(), recipient.strip()))
|
2012-10-12 13:40:57 -04:00
|
|
|
return zephyr_subscriptions
|
2012-10-11 16:20:38 -04:00
|
|
|
|
2012-10-29 12:51:44 -04:00
|
|
|
if options.sync_subscriptions:
|
|
|
|
print "Syncing your ~/.zephyr.subs to your Humbug Subscriptions!"
|
|
|
|
add_humbug_subscriptions(True)
|
|
|
|
sys.exit(0)
|
|
|
|
|
2012-10-12 17:01:15 -04:00
|
|
|
if options.forward_from_humbug:
|
2012-10-12 17:19:49 -04:00
|
|
|
print "This option is obsolete."
|
|
|
|
sys.exit(0)
|
|
|
|
|
2012-10-25 17:40:30 -04:00
|
|
|
# First check that there are no other bots running
|
|
|
|
cmdline = " ".join(sys.argv)
|
|
|
|
proc = subprocess.Popen(['pgrep', '-U', os.environ["USER"], "-f", cmdline],
|
|
|
|
stdout=subprocess.PIPE,
|
|
|
|
stderr=subprocess.PIPE)
|
|
|
|
out, _err_unused = proc.communicate()
|
|
|
|
for pid in out.split():
|
|
|
|
if int(pid.strip()) != os.getpid():
|
|
|
|
# Another copy of zephyr_mirror.py! Kill it.
|
|
|
|
print "Killing duplicate zephyr_mirror process %s" % pid
|
|
|
|
os.kill(int(pid), signal.SIGKILL)
|
|
|
|
|
2012-10-12 17:19:49 -04:00
|
|
|
child_pid = os.fork()
|
|
|
|
if child_pid == 0:
|
|
|
|
# Run the humbug => zephyr mirror in the child
|
|
|
|
import zephyr
|
|
|
|
zephyr.init()
|
2012-10-02 14:09:24 -04:00
|
|
|
humbug_to_zephyr(options)
|
2012-10-12 17:19:49 -04:00
|
|
|
sys.exit(0)
|
|
|
|
|
|
|
|
import zephyr
|
|
|
|
zephyr.init()
|
|
|
|
subs = zephyr.Subscriptions()
|
|
|
|
zephyr_to_humbug(options)
|