Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
103 changes: 101 additions & 2 deletions hermes/chatroom.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
# This Python file uses the following encoding: utf-8
"""
hermes.chatroom
~~~~~~~~~~~~~~~
Expand All @@ -9,6 +10,9 @@
import re
import xmpp
import logging
import random

from collections import deque, namedtuple

logger = logging.getLogger(__name__)

Expand All @@ -20,14 +24,29 @@ class Chatroom(object):
#instead of the standard message-handling pipeline.
command_patterns = ()

base_command_patterns = ((r'^/list', 'list'),
(r'^(\w+)--', 'decrement'),
(r'^(\w+)\+\+', 'increment'),
(r'^/roll\s*(\d*)', 'roll'),
(r'^/links\s*(\d*)', 'links'),
(r'^/help', 'help'),
)

HistoryMessage = namedtuple('HistoryMessage', ['sender', 'body', 'html_body'])

def __init__(self, name, params):
self.command_patterns = []
for pattern in type(self).base_command_patterns:
self.command_patterns.append((re.compile(pattern[0]), pattern[1]))

for pattern in type(self).command_patterns:
self.command_patterns.append((re.compile(pattern[0]), pattern[1]))

self.name = name
self.params = params
self.jid = xmpp.protocol.JID(self.params['JID'])
self.counts = {}
self.history = deque(maxlen=200)

def connect(self):
"""Connect to the chatroom's server, sets up handlers, invites members as needed."""
Expand Down Expand Up @@ -190,10 +209,14 @@ def on_message(self, con, event):
nick = event.getFrom().getResource()
from_jid = event.getFrom().getStripped()
body = event.getBody()

html_body = event.getTag('html')

if msg_type == 'chat' and body is None:
return

if html_body:
html_body = unicode(html_body.getTag('body').getPayload().pop())

logger.debug('msg_type[%s] from[%s] nick[%s] body[%s]' % (msg_type, from_jid, nick, body,))

sender = filter(lambda m: m['JID'] == from_jid, self.params['MEMBERS'])
Expand All @@ -220,7 +243,83 @@ def on_message(self, con, event):
if command_handler:
return command_handler(sender, body, args)

historyMessage = self.HistoryMessage(sender=sender, body=body, html_body=html_body)
self.history.appendleft(historyMessage)
broadcast_body = '[%s] %s' % (sender['NICK'], body,)
return self.broadcast(broadcast_body, exclude=(sender,))
return self.broadcast(broadcast_body, exclude=(sender,), html_body=html_body)
except:
logger.exception('Error handling message [%s] from [%s]' % (body, sender['JID']))

def decrement(self, sender, body, match):
"""Performs an decrement on the given text"""
what = match.group(1)
self.counts[what] = self.counts.get(what, 0) - 1
body = '[%s] %s [ouch! now at %s]' % (sender['NICK'], match.group(0), str(self.counts[what]))
self.broadcast(body)

def increment(self, sender, body, match):
"""Performs an increment on the given text"""
what = match.group(1)
self.counts[what] = self.counts.get(what, 0) + 1
body = '[%s] %s [woot! now at %s]' % (sender['NICK'], match.group(0), str(self.counts[what]))
self.broadcast(body)

def help(self, sender, body, match):
"""Lists commands available on this server"""
body = 'Commands Available:\n\n'
for pattern in type(self).base_command_patterns:
body += '%s:\n\t%s\n\n' % (pattern[1], pattern[0])

for pattern in type(self).command_patterns:
body += '%s:\n\t%s\n\n' % (pattern[1], pattern[0])

self.send_message(body, sender)

def list(self, sender, body, match):
"""Lists the members of this chatroom"""
body = 'Chat Members:\n\n'
for member in self.params['MEMBERS']:
body += '%s\n' % (member['NICK'])

self.send_message(body, sender)

def links(self, sender, body, match):
"""Lists last X urls linked to in chat"""
max = match.group(1)
if not max:
max = 10

max = int(max)

# Please see http://daringfireball.net/2010/07/improved_regex_for_matching_urls
regex = re.compile(r'(?i)\b((?:https?://|www\d{0,3}[.]|[a-z0-9.\-]+[.][a-z]{2,4}/)(?:[^\s()<>]+|\(([^\s()<>]+|(\([^\s()<>]+\)))*\))+(?:\(([^\s()<>]+|(\([^\s()<>]+\)))*\)|[^\s`!()\[\]{};:\'".,<>?«»“”‘’]))')

count = 0
body = 'Last %d Links:\n\n' % (max)
for message in self.history:
if count >= max:
break

matches = []
if message.body:
matches = regex.findall(message.body)

if not matches and message.html_body:
matches = regex.findall(message.html_body)

for match in matches:
body += '%s\n' % (match[0])
count += 1
if count >= max:
break

self.send_message(body, sender)

def roll(self, sender, body, match):
"""Roll the dice! Outputs a random int from 0 to max"""
max = match.group(1)
if not max:
max = 100
body = '[%s] rolled %d' % (sender['NICK'], random.randrange(0, int(max)))
self.broadcast(body)

Loading