jabber_mirror: Dynamically join and leave MUCs

For personal mirrors, this means that the mirror should join all Jabber rooms
corresponding to their Zulip subscriptions.  For the public mirror, this means
that the mirror should join all Jabber rooms corresponding to Zulip streams that
end in "/xmpp".

(imported from commit 16ed9e3deee7e02b2ae0dd79925f0ed5c4acd044)
This commit is contained in:
Zev Benjamin 2014-03-02 00:49:46 -05:00
parent 2045b73ea4
commit f239b02027

View file

@ -53,7 +53,7 @@ def room_to_stream(room):
return str(room).rpartition("@")[0] + "/xmpp" return str(room).rpartition("@")[0] + "/xmpp"
def stream_to_room(stream): def stream_to_room(stream):
return stream.rpartition("/xmpp")[0] return stream.lower().rpartition("/xmpp")[0]
def jid_to_zulip(jid): def jid_to_zulip(jid):
return "%s@%s" % (str(jid).rpartition("@")[0], options.zulip_domain) return "%s@%s" % (str(jid).rpartition("@")[0], options.zulip_domain)
@ -64,7 +64,8 @@ class JabberToZulipBot(ClientXMPP):
jid = "%s@%s/jabber_mirror" % (nick, domain) jid = "%s@%s/jabber_mirror" % (nick, domain)
ClientXMPP.__init__(self, jid, password) ClientXMPP.__init__(self, jid, password)
self.password = password self.password = password
self.rooms = rooms self.rooms = set()
self.rooms_to_join = rooms
self.add_event_handler("session_start", self.session_start) self.add_event_handler("session_start", self.session_start)
self.add_event_handler("message", self.message) self.add_event_handler("message", self.message)
self.password = password self.password = password
@ -85,10 +86,25 @@ class JabberToZulipBot(ClientXMPP):
def session_start(self, event): def session_start(self, event):
self.get_roster() self.get_roster()
self.send_presence() self.send_presence()
for room in self.rooms: for room in self.rooms_to_join:
self.join_muc(room)
def join_muc(self, room):
if room in self.rooms:
return
logging.debug("Joining " + room)
self.rooms.add(room)
muc_jid = room + "@" + options.conference_domain muc_jid = room + "@" + options.conference_domain
self.plugin['xep_0045'].joinMUC(muc_jid, self.nick) self.plugin['xep_0045'].joinMUC(muc_jid, self.nick)
def leave_muc(self, room):
if room not in self.rooms:
return
logging.debug("Leaving " + room)
self.rooms.remove(room)
muc_jid = room + "@" + options.conference_domain
self.plugin['xep_0045'].leaveMUC(muc_jid, self.nick)
def message(self, msg): def message(self, msg):
try: try:
if msg["type"] == "groupchat": if msg["type"] == "groupchat":
@ -154,19 +170,23 @@ class ZulipToJabberBot(object):
def set_jabber_client(self, client): def set_jabber_client(self, client):
self.jabber = client self.jabber = client
def process_message(self, event): def process_event(self, event):
try: if event['type'] == 'message':
if event['type'] != 'message':
return
message = event["message"] message = event["message"]
if message['sender_email'] != self.client.email: if message['sender_email'] != self.client.email:
return return
try:
if message['type'] == 'stream': if message['type'] == 'stream':
self.stream_message(message) self.stream_message(message)
elif message['type'] == 'private': elif message['type'] == 'private':
self.private_message(message) self.private_message(message)
except: except:
logging.exception("Exception forwarding Zulip => Jabber") logging.exception("Exception forwarding Zulip => Jabber")
elif event['type'] == 'subscription':
self.process_subscription(event)
elif event['type'] == 'stream':
self.process_stream(event)
def stream_message(self, msg): def stream_message(self, msg):
stream = msg['display_recipient'] stream = msg['display_recipient']
@ -196,6 +216,30 @@ class ZulipToJabberBot(object):
outgoing['thread'] = u'\u1B80' outgoing['thread'] = u'\u1B80'
outgoing.send() outgoing.send()
def process_subscription(self, event):
if event['op'] == 'add':
streams = [s['name'].lower() for s in event['subscriptions']]
streams = [s for s in streams if s.endswith("/xmpp")]
for stream in streams:
self.jabber.join_muc(stream_to_room(stream))
if event['op'] == 'remove':
streams = [s['name'].lower() for s in event['subscriptions']]
streams = [s for s in streams if s.endswith("/xmpp")]
for stream in streams:
self.jabber.leave_muc(stream_to_room(stream))
def process_stream(self, event):
if event['op'] == 'occupy':
streams = [s['name'].lower() for s in event['streams']]
streams = [s for s in streams if s.endswith("/xmpp")]
for stream in streams:
self.jabber.join_muc(stream_to_room(stream))
if event['op'] == 'vacate':
streams = [s['name'].lower() for s in event['streams']]
streams = [s for s in streams if s.endswith("/xmpp")]
for stream in streams:
self.jabber.leave_muc(stream_to_room(stream))
def get_rooms(zulip): def get_rooms(zulip):
if options.mode == 'public': if options.mode == 'public':
stream_infos = zulip.client.get_streams()['streams'] stream_infos = zulip.client.get_streams()['streams']
@ -286,13 +330,16 @@ user and mirrors messages sent to Jabber rooms to Zulip.'''.replace("\n", " "))
xmpp.set_zulip_client(zulip) xmpp.set_zulip_client(zulip)
zulip.set_jabber_client(xmpp) zulip.set_jabber_client(xmpp)
if options.mode == 'public':
xmpp.process(block=True)
else:
xmpp.process(block=False) xmpp.process(block=False)
if options.mode == 'public':
event_types = ['stream']
else:
event_types = ['message', 'subscription']
try: try:
logging.info("Connecting to Zulip.") logging.info("Connecting to Zulip.")
zulip.client.call_on_each_event(zulip.process_message) zulip.client.call_on_each_event(zulip.process_event,
event_types=event_types)
except BaseException as e: except BaseException as e:
logging.exception("Exception in main loop") logging.exception("Exception in main loop")
xmpp.abort() xmpp.abort()