Skip to content

Commit

Permalink
initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Greg Hewgill committed Aug 5, 2010
0 parents commit a407b99
Show file tree
Hide file tree
Showing 2 changed files with 193 additions and 0 deletions.
4 changes: 4 additions & 0 deletions soirc.config.sample
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"port": 6668,
"cookie": "t=abc123abc123&s=xyz789xyz789"
}
189 changes: 189 additions & 0 deletions soirc.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
import cookielib
import json
import re
import select
import socket
import time
import urllib
import urllib2

Config = json.load(open("soirc.config"))

DEBUG = False

class IrcClient(object):
def __init__(self, server, s):
self.server = server
self.sock = s
self.data = ""
self.nick = None
self.user = None
self.lastactivity = time.time()
self.pingsent = False
def socket(self):
return self.sock
def tick(self):
silence = time.time() - self.lastactivity
if silence > 300:
self.sock.close()
self.server.remove(self)
elif silence > 150 and not self.pingsent:
self.sock.send("PING :soirc\r\n")
self.pingsent = True
def handle(self):
self.lastactivity = time.time()
try:
data = self.sock.recv(1024)
except socket.error:
self.sock.close()
self.server.remove(self)
return
if len(data) == 0:
self.sock.close()
self.server.remove(self)
return
for c in data:
if c == "\r":
continue
if c == "\n":
if DEBUG: print "<-", self.data
if ' ' in self.data:
command, params = self.data.split(" ", 1)
else:
command = self.data
params = ""
handler = getattr(self, "handle_" + command.lower(), None)
if handler is not None:
response = handler(params)
if response:
if DEBUG: print "->", response
self.sock.send(response + "\r\n")
else:
print "unknown command:", self.data
self.data = ""
else:
self.data += c
def handle_nick(self, params):
nick = params
if not re.match(r"[a-zA-Z0-9\-\[\]'`^{}_]+$", nick):
print "bad nick", nick
sys.exit(1)
self.nick = nick
return ":%s %s %s :soirc" % ("soirc", "001", self.nick)
def handle_user(self, params):
self.user, mode, _, realname = params.split(" ", 3)
return ":%s JOIN :%s" % (self.ident(), "#soirc")
def handle_ping(self, params):
return ":%s PONG %s" % ("soirc", params)
def handle_pong(self, params):
self.pingsent = False
def handle_privmsg(self, params):
channel, msg = params.split(" ", 1)
self.server.sender(self.nick, channel, msg[1:])
def handle_quit(self, params):
self.sock.close()
self.server.remove(self)
def handle_who(self, params):
for f in friends:
self.sock.send(":soirc 352 %s #soirc %s soirc soirc %s H :1 %s\r\n" % (self.nick, f['screen_name'], f['screen_name'], f['name']))
self.sock.send(":soirc 315 %s :End of /WHO list" % self.nick)
def handle_whois(self, params):
userinfo = load_json("http://twitter.com/users/show/%s.json" % params)
if 'error' in userinfo:
return "User %s %s.\r\n" % (params, userinfo['error'])
else:
self.sock.send("%s [%s]\r\n" % (userinfo['screen_name'], userinfo['id']))
for key, descr in (("name", "Real Name"),
("verified", "Verified"),
("location", "Location"),
("time_zone", "Time Zone"),
("description", "Description"),
("url", "Home Page"),
("followers_count", "Followers"),
("friends_count", "Following"),
("favourites_count", "Favourites")):
if key in userinfo:
self.sock.send(" %-12s : %s\r\n" % (descr, userinfo[key]))
if 'status' in userinfo and 'created_at' in userinfo['status']:
self.sock.send(" %-12s : %s\r\n" % ("Idle Since",userinfo['status']['created_at']))
return "End of WHOIS"
def ident(self):
return "%s!%s@%s" % (self.nick, self.user, "soirc")
def privmsg(self, user, channel, msg):
self.sock.send(":%s PRIVMSG %s %s\r\n" % (user, channel, msg))

class IrcServer(object):
def __init__(self, sender):
self.sender = sender
self.sock = socket.socket()
self.sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.sock.bind(("127.0.0.1", Config['port']))
self.sock.listen(5)
self.clients = []
def socket(self):
return self.sock
def tick(self):
pass
def handle(self):
t, a = self.sock.accept()
print "Client connect", a
self.clients.append(IrcClient(self, t))
def privmsg(self, user, channel, msg):
for x in self.clients:
x.privmsg(user, channel, msg)
def remove(self, client):
self.clients.remove(client)

class ChatServer(object):
def __init__(self, room, sender):
self.room = room
self.sender = sender
mainpage = opener.open("http://chat.meta.stackoverflow.com/rooms/%d/chat-feedback" % self.room).read()
print cj
assert "You must be" not in mainpage
self.fkey = re.search(r"""id="fkey".*value="(\w+)" """, mainpage).group(1)
print "fkey:", self.fkey
self.lasttime = 0
self.lasttick = 0
def post(self, msg):
opener.open("http://chat.meta.stackoverflow.com/chats/%d/messages/new" % self.room, urllib.urlencode({'fkey': self.fkey, 'text': msg}))
def socket(self):
return None
def tick(self):
now = time.time()
if now - self.lasttick < 2:
return
self.lasttick = now
jsdata = opener.open("http://chat.meta.stackoverflow.com/chats/%d/events?since=%d" % (self.room, self.lasttime), urllib.urlencode({'fkey': self.fkey})).read()
try:
data = json.loads(jsdata)
except Exception as x:
print x
print jsdata
self.lasttime = 0
return
if data['events']:
print data['time'], len(data['events'])
for e in data['events']:
if e['event_type'] in (1, 2):
self.sender(e['user_name'].replace(" ", ""), e['content'])
self.lasttime = data['time']

cj = cookielib.CookieJar()
cj.set_cookie(cookielib.Cookie(None, "somusr", Config['cookie'], None, False, ".meta.stackoverflow.com", True, True, "/", True, False, None, False, None, None, None))
opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cj))

server = IrcServer(lambda user, channel, msg: sources[0].post(msg))
sources = []
for room in (77,):
sources.append(ChatServer(room, lambda user, msg: server.privmsg("%s!%s@%s" % (user.encode("UTF-8"), user.encode("UTF-8"), "soirc"), "#soirc", msg.encode("UTF-8"))))

while True:
a = sources + [server] + server.clients
r, w, e = select.select([x.socket() for x in a if x.socket() is not None], [], [], 1)
for x in r:
for s in a:
if x is s.socket():
s.handle()
for s in a:
s.tick()

0 comments on commit a407b99

Please sign in to comment.