-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathparty-zephyr.py
179 lines (154 loc) · 5.48 KB
/
party-zephyr.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
import jabberbot
import logging
import re
import threading
import signal
import zephyr
import sys
import select
import Queue
import yaml
import os.path
import time
import xmpp
SHUTDOWN = False
JOIN_ALERT = re.compile(r"""^You have joined '([^']+)' with the alias '([^']+)'$""")
CHAT_MESSAGE = re.compile(r"""^\[([^]]+)\]\s*(.*)$""", re.S|re.M)
CONF_FILE = sys.argv[1] if len(sys.argv) > 1 else os.path.join(os.path.dirname(__file__),
'partychat.yml')
CONF = yaml.safe_load(open(CONF_FILE))
jabber_chats = CONF['chats']
zephyr_classes = dict(map(reversed, jabber_chats.items()))
USER = CONF['creds']['user']
PASS = CONF['creds']['pass']
from_zephyr_q = Queue.Queue()
from_jabber_q = Queue.Queue()
PARTYCHAT_HOST = 'im.partych.at'
KEEPALIVE_INTERVAL = 60
class BridgeBot(jabberbot.JabberBot):
def __init__(self, user, pw):
self.last_keepalive = time.time()
super(BridgeBot, self).__init__(user, pw)
# chandler = logging.StreamHandler()
# formatter = logging.Formatter("%(asctime)s - %(name)s - %(levelname)s - %(message)s")
# chandler.setFormatter(formatter)
# self.log.addHandler(chandler)
# self.log.setLevel(logging.DEBUG)
def chat_to_jid(self, chat):
return chat + '@' + PARTYCHAT_HOST
def joined_chat(self, chat):
self.send(self.chat_to_jid(chat), "/nick z")
if chat in jabber_chats:
self.send(self.chat_to_jid(chat),
"This chat is now being mirrored to -c %s" %
(jabber_chats[chat],))
def callback_message(self, conn, mess):
if not mess.getFrom().getDomain() == PARTYCHAT_HOST:
return
from_ = str(mess.getFrom())
chat = from_[:from_.rindex('@')]
body = mess.getBody()
logging.debug("JABBER: %s: %s", from_, body)
m = JOIN_ALERT.search(body)
if m:
self.joined_chat(chat)
return
m = CHAT_MESSAGE.search(body)
if m:
who = m.group(1)
if who == 'z':
# If we get a message from ourself echoed back,
# squelch it.
return
body = m.group(2)
from_jabber_q.put((chat, who, body))
def callback_presence(self, conn, presence):
jid, type_, show, status = presence.getFrom(), \
presence.getType(), presence.getShow(), \
presence.getStatus()
if type_ == 'subscribe':
self.roster.Authorize(jid)
else:
super(BridgeBot, self).callback_presence(conn, presence)
def idle_proc(self):
super(BridgeBot, self).idle_proc()
if SHUTDOWN:
self.quit()
if time.time() - self.last_keepalive > KEEPALIVE_INTERVAL:
logging.debug("Sending jabber keepalive ping.")
self._send_status()
self.last_keepalive = time.time()
while True:
try:
m = from_zephyr_q.get(False)
except Queue.Empty:
return
(cls, sender, msg) = m
if cls not in zephyr_classes: return
self.send(self.chat_to_jid(zephyr_classes[cls]), "[%s] %s" % (sender, msg))
def on_connect(self):
for who in jabber_chats.values():
self.send(self.chat_to_jid(who), '/nick z')
def run_jabber():
while not SHUTDOWN:
try:
logging.info("Connecting to Jabber...")
bot = BridgeBot(USER, PASS)
bot.serve_forever(connect_callback = bot.on_connect)
except Exception, e:
logging.error("IOError in Jabber thread", exc_info=True)
time.sleep(60)
def run_zephyr():
zephyr.init()
subs = zephyr.Subscriptions()
logging.info("Subscribing to: " + ','.join(zephyr_classes.keys()))
for c in zephyr_classes.keys():
subs.add((c, '*', ''))
while not SHUTDOWN:
while True:
try:
m = from_jabber_q.get(False)
except Queue.Empty:
break
(src, sender, msg) = m
if src not in jabber_chats:
continue
note = zephyr.ZNotice()
note.fields = [src, msg]
note.sender = sender
note.auth = False
note.cls = jabber_chats[src]
note.instance = ''
note.opcode = 'jabber'
note.send()
note = zephyr.receive(False)
if note:
body = note.fields[1] if len(note.fields) > 1 else ''
logging.debug("ZEPHYR: %s/%s[%s]: %s",
note.sender, note.cls, note.opcode,
body)
if note.opcode.lower() not in ('jabber', 'ping'):
from_zephyr_q.put((note.cls, note.sender.split('@')[0],
body))
else:
select.select([zephyr._z.getFD()], [], [], 1)
def main():
global SHUTDOWN
logging.basicConfig(level = logging.DEBUG,
format = "[%(asctime)-15s] %(levelname)s:%(name)s: %(message)s")
jabber_thread = threading.Thread(target = run_jabber)
zephyr_thread = threading.Thread(target = run_zephyr)
threads = [jabber_thread, zephyr_thread]
for t in threads:
t.start()
while True:
try:
signal.pause()
except KeyboardInterrupt:
break
SHUTDOWN = True
for t in threads:
t.join()
return 0
if __name__ == '__main__':
sys.exit(main())