[Pymoul-svn] SF.net SVN: pymoul: [295] pymoul/trunk/src/moul
Status: Alpha
Brought to you by:
tiran
|
From: <ti...@us...> - 2007-05-28 16:53:04
|
Revision: 295
http://pymoul.svn.sourceforge.net/pymoul/?rev=295&view=rev
Author: tiran
Date: 2007-05-28 09:53:00 -0700 (Mon, 28 May 2007)
Log Message:
-----------
Switching to a new implementation of the IRC chat relay system
Modified Paths:
--------------
pymoul/trunk/src/moul/chatrelay/__init__.py
pymoul/trunk/src/moul/chatrelay/io.py
pymoul/trunk/src/moul/chatrelay/ircclient.py
pymoul/trunk/src/moul/file/chatlog.py
Added Paths:
-----------
pymoul/trunk/src/moul/chatrelay/filter.py
pymoul/trunk/src/moul/chatrelay/formatter.py
pymoul/trunk/src/moul/chatrelay/interfaces.py
pymoul/trunk/src/moul/chatrelay/parser.py
Modified: pymoul/trunk/src/moul/chatrelay/__init__.py
===================================================================
--- pymoul/trunk/src/moul/chatrelay/__init__.py 2007-05-24 22:50:20 UTC (rev 294)
+++ pymoul/trunk/src/moul/chatrelay/__init__.py 2007-05-28 16:53:00 UTC (rev 295)
@@ -5,7 +5,7 @@
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
Added: pymoul/trunk/src/moul/chatrelay/filter.py
===================================================================
--- pymoul/trunk/src/moul/chatrelay/filter.py (rev 0)
+++ pymoul/trunk/src/moul/chatrelay/filter.py 2007-05-28 16:53:00 UTC (rev 295)
@@ -0,0 +1,56 @@
+from zope.interface import implements
+
+from moul.chatrelay.interfaces import ILineFilter
+from moul.chatrelay.interfaces import ISnoopyLineFilter
+from moul.file.chatlog import (CHAT_UNKNOWN, CHAT_PRIVMSG, CHAT_PRIVMSGTO,
+ CHAT_PRIVMSGFROM, CHAT_ACTION, CHAT_ERROR,
+ CHAT_MSG)
+
+__all__ = [obj for obj in globals() if ILineFilter.isImplementedBy(obj)]
+
+class NullFilter(object):
+ implements(ILineFilter)
+ name = 'Null filter'
+
+ def filter(self, line, **kwargs):
+ return line, kwargs
+
+class HightlightImportantFilter(object):
+ implements(ILineFilter)
+ name = 'Highlight important people'
+
+ def filter(self, line, **kwargs):
+ if kwargs.get('important', False):
+ kwargs['highlight'] = True
+ return line, kwargs
+
+class AbstractMessageFilter(object):
+ implements(ILineFilter)
+ name = None
+ msg_type = None
+
+ def __init__(self):
+ assert self.msg_type, "No message type applied"
+
+ def filter(self, line, **kwargs):
+ typ = kwargs.get('type', CHAT_UNKNOWN)
+ if typ & self.msg_type:
+ return None, None
+ return line, kwargs
+
+class PrivateMessageFilter(AbstractMessageFilter):
+ name = 'Private message filter'
+ msg_type = CHAT_PRIVMSG
+
+class ErrorMessageFilter(AbstractMessageFilter):
+ name = 'Error message filter'
+ msg_type = CHAT_ERROR
+
+class NonImportantFilter(object):
+ implements(ILineFilter)
+ name = 'Filter non important'
+
+ def filter(self, line, **kwargs):
+ if not kwargs.get('important', False):
+ return None, None
+ return line, kwargs
Property changes on: pymoul/trunk/src/moul/chatrelay/filter.py
___________________________________________________________________
Name: svn:keywords
+ 'Id Revision'
Name: svn:eol-style
+ native
Added: pymoul/trunk/src/moul/chatrelay/formatter.py
===================================================================
--- pymoul/trunk/src/moul/chatrelay/formatter.py (rev 0)
+++ pymoul/trunk/src/moul/chatrelay/formatter.py 2007-05-28 16:53:00 UTC (rev 295)
@@ -0,0 +1,32 @@
+from zope.interface import implements
+
+from moul.chatrelay.interfaces import IOutputFormatter
+from moul.file.chatlog import (CHAT_UNKNOWN, CHAT_PRIVMSG, CHAT_PRIVMSGTO,
+ CHAT_PRIVMSGFROM, CHAT_ACTION, CHAT_ERROR,
+ CHAT_MSG)
+
+__all__ = [obj for obj in globals() if IOutputFormatter.isImplementedBy(obj)]
+
+class NullFormatter(object):
+ implements(IOutputFormatter)
+ name = 'Null formatter'
+
+ def format(self, line, **kwargs):
+ return line
+
+class MOULFormatter(object):
+ implements(IOutputFormatter)
+ name = 'MOUL formatter'
+
+ def format(self, line, **kwargs):
+ typ = kwargs.get('type', CHAT_UNKNOWN)
+ highlight = kwargs.get('highlight', False)
+ if typ == CHAT_PRIVMSGTO:
+ line = "-> %s" % line
+ elif typ == CHAT_PRIVMSGFROM:
+ line = "<- %s" % line
+ elif typ == CHAT_ACTION:
+ line = "* %s" % line
+ if highlight:
+ line = "%B%s" % line
+ return line
Property changes on: pymoul/trunk/src/moul/chatrelay/formatter.py
___________________________________________________________________
Name: svn:keywords
+ 'Id Revision'
Name: svn:eol-style
+ native
Added: pymoul/trunk/src/moul/chatrelay/interfaces.py
===================================================================
--- pymoul/trunk/src/moul/chatrelay/interfaces.py (rev 0)
+++ pymoul/trunk/src/moul/chatrelay/interfaces.py 2007-05-28 16:53:00 UTC (rev 295)
@@ -0,0 +1,123 @@
+from zope.interface import Attribute
+from zope.interface import Interface
+
+class IFileAppendWatchService(Interface):
+ """A service which monitors text files and calls the callback for new lines
+ """
+
+ def monitorFile(path, callback, errback=None):
+ """Monitor a file
+
+ @param path: path to a file
+ @type path: string
+ @param callback: callback function(path, line)
+ @type callback: callable
+ @param errback: errback function(path, error)
+ @type errback: callable
+ """
+
+ def unmonitorFile(path):
+ """Stop monitoring files
+
+ @param path: path to a file
+ @type path: string
+ """
+
+ def listFiles():
+ """List monitored files
+
+ @return: a list of file names
+ @rtype: list
+ """
+
+class IInputParser(Interface):
+ """Parse input data
+ """
+ name = Attribute("name of the parser")
+
+ def parse(line):
+ """Parse a single line
+
+ @param line: input line
+ @type line: string
+ @return: parsed line, dict with additional information
+ @rtype: (string, dict)
+ """
+
+class ILineFilter(Interface):
+ """A line filter
+ """
+ name = Attribute("name of the filter")
+
+ def filter(line, **kwargs):
+ """
+
+ @param line: the line to filter
+ @type line: string
+ @param kwargs: additional information
+ @return: (filtered line, kwargs) or None, None
+ @rtype: (string, dict) / None, None
+ """
+
+class ISnoopyLineFilter(ILineFilter):
+ """A line filter that snoops the ongoing chat in the channel
+ """
+
+ def snoop(channel, user, msg):
+ """
+
+ @param channel: channel name
+ @type channel: string
+ @param user: user name with hostmask
+ @type user: string
+ @param msg: message
+ @type msg: string
+ @return: None
+ """
+
+class IOutputFormatter(Interface):
+ """A line formatter
+ """
+ name = Attribute("name of the output formatter")
+
+ def format(line, **kwargs):
+ """Format a line
+
+ @param line: the line to filter
+ @type line: string
+ @param kwargs: additional information
+ @return: a formatted line
+ @rtype: string
+ """
+
+class IChatRelay(Interface):
+ """A chat relay
+ """
+
+ def registerInputParser(parser):
+ """Register the input parser, overriding the old one
+
+ @param parser: an input parser object
+ @type parser: object providing IInputParser
+ """
+
+ def registerOutputFormatter(formatter):
+ """Register the output formatter, overriding the old one
+
+ @param formatter: an output formatter object
+ @type formatter: object providing IOutputFormatter
+ """
+
+ def registerFilters(*filters):
+ """
+
+ @param formatter: an output formatter object
+ @type formatter: object providing IOutputFormatter
+ """
+
+ def removeFilter(name):
+ """Remove a filter from the list of filters
+
+ @param name: name of the filter
+ @type name: string
+ """
Property changes on: pymoul/trunk/src/moul/chatrelay/interfaces.py
___________________________________________________________________
Name: svn:keywords
+ 'Id Revision'
Name: svn:eol-style
+ native
Modified: pymoul/trunk/src/moul/chatrelay/io.py
===================================================================
--- pymoul/trunk/src/moul/chatrelay/io.py 2007-05-24 22:50:20 UTC (rev 294)
+++ pymoul/trunk/src/moul/chatrelay/io.py 2007-05-28 16:53:00 UTC (rev 295)
@@ -5,7 +5,7 @@
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
@@ -34,7 +34,7 @@
class MOULLogFormatter(NullFormatter):
"""Formatter for MOUL
"""
-
+
def __init__(self, skipprivate=False, onlyimportant=False):
self.skipprivate = skipprivate
self.onlyimportant = onlyimportant
@@ -44,7 +44,7 @@
return None
typ = getattr(msg, 'typ', CHAT_UNKNOWN)
important = getattr(msg, 'important', False)
-
+
if self.onlyimportant and not important:
return None
if self.skipprivate and typ & CHAT_PRIVMSG:
@@ -74,7 +74,7 @@
def open(self):
self._fd = open(self._fname, 'r')
self._fd.seek(0, 2) # eof
-
+
def close(self):
if self._fd:
self._fd.close()
@@ -85,7 +85,7 @@
@property
def isOpen(self):
return self._fd is not None
-
+
def _read(self):
data = self._fd.read()
if not data:
@@ -104,7 +104,7 @@
return self._fifo.pop(0)
except IndexError:
raise StopIteration
-
+
class MessageWriter(object):
"""Write messages to a channel
"""
Modified: pymoul/trunk/src/moul/chatrelay/ircclient.py
===================================================================
--- pymoul/trunk/src/moul/chatrelay/ircclient.py 2007-05-24 22:50:20 UTC (rev 294)
+++ pymoul/trunk/src/moul/chatrelay/ircclient.py 2007-05-28 16:53:00 UTC (rev 295)
@@ -5,7 +5,7 @@
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.
-#
+#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
@@ -68,7 +68,7 @@
reader = None
writer = None
interval = 5
-
+
def __init__(self, nickname, channel, realname=None, username=None,
serverpasswd=None, nickpasswd=None, adminpasswd=None):
"""
@@ -80,7 +80,7 @@
self.password = serverpasswd
self.nickpasswd = nickpasswd
self.adminpasswd = adminpasswd
-
+
self.loop = LoopingCall(self.checkLogfile)
self.identified = []
@@ -95,7 +95,7 @@
def checkLogfile(self):
for line in iter(self.reader):
self.writer.log(line)
-
+
def start(self):
#if not self.reader.isOpen:
# return
@@ -117,10 +117,10 @@
def joined(self, channel):
log.msg("I have joined", channel)
-
+
def left(self, channel):
log.msg("I have left", channel)
-
+
def kickedFrom(self, channel, kicker, message):
log.msg("I have been kicked from %s by %s: %s" %
(channel, kicker, message))
@@ -172,7 +172,7 @@
#self.say(channel, "count %d" % self.counter)
#self.counter += 1
-
+
def reply(self, dest, message):
# maybe self.notice(dest, message) instead?
self.msg(dest, message)
@@ -210,7 +210,7 @@
commands.append(name)
commands.sort()
return commands
-
+
@usage("help <command> - Give help for <command>")
def command_HELP(self, user, reply, args):
args = args.split()
@@ -272,7 +272,7 @@
readerClass = LogFileReader
writerClass = MessageWriter
formatter = MOULLogFormatter(skipprivate=False, onlyimportant=False)
-
+
def __init__(self, nickname, channel, realname=None, username=None,
serverpasswd=None, nickpasswd=None, adminpasswd=None):
"""
@@ -289,7 +289,7 @@
d = self.__dict__.copy()
del d['p']
return d
-
+
def shutdown(self):
self.shuttingDown = True
if self.p:
Added: pymoul/trunk/src/moul/chatrelay/parser.py
===================================================================
--- pymoul/trunk/src/moul/chatrelay/parser.py (rev 0)
+++ pymoul/trunk/src/moul/chatrelay/parser.py 2007-05-28 16:53:00 UTC (rev 295)
@@ -0,0 +1,27 @@
+from zope.interface import implements
+
+from moul.file.chatlog import ChatlogParser
+
+from moul.chatrelay.interfaces import IInputParser
+
+__all__ = [obj for obj in globals() if IInputParser.isImplementedBy(obj)]
+
+class NullParser(object):
+ implements(IInputParser)
+ name = 'Null parser'
+
+ def __init__(self, *args, **kwargs):
+ pass
+
+ def parse(self, line):
+ return line, {}
+
+class MOULChatlogParser(ChatlogParser):
+ implements(IInputParser)
+ name = 'MOUL chatlog parser'
+
+ def __init__(self, year):
+ self.setYear(year)
+
+ def setYear(self, year):
+ self._year = int(year)
Property changes on: pymoul/trunk/src/moul/chatrelay/parser.py
___________________________________________________________________
Name: svn:keywords
+ 'Id Revision'
Name: svn:eol-style
+ native
Modified: pymoul/trunk/src/moul/file/chatlog.py
===================================================================
--- pymoul/trunk/src/moul/file/chatlog.py 2007-05-24 22:50:20 UTC (rev 294)
+++ pymoul/trunk/src/moul/file/chatlog.py 2007-05-28 16:53:00 UTC (rev 295)
@@ -53,17 +53,9 @@
CHAT_ACTION = 1 << 6
# users
-USER_CYAN = [
- 'gregbert', 'greydragon', 'Rand Miller', 'ResEng B. Mathias',
- 'ResEng B.Dreschel', 'ResEng C. Lambert', 'ResEng KJohnson',
- 'ResEng 102', 'ResEng 233',
- ]
-USER_DRC = [
- 'Cate Alexander', 'Dr. Kodama', 'Marie Sutherland', 'Michael Engberg',
- 'Victor Laxman', 'Wheely', 'Douglas Sharper', 'Phil Henderson',
- 'Nick White'
- ]
-
+USER_CYAN = ['gregbert', 'greydragon']
+USER_DRC = ['Marie Sutherland', 'Douglas Sharper', 'Nick White',
+ 'Dr. Kodama', 'Victor Laxman', 'Michael Engberg']
USER_IMPORTANT = USER_CYAN + USER_DRC
RE_FLAGS = re.LOCALE
@@ -357,7 +349,7 @@
New idea, new design
"""
- def __init__(self, iterable, year=2007):
+ def __init__(self, iterable=[], year=2007):
self._iterable = iterable
self._year = year # XXX
@@ -366,58 +358,42 @@
if mo is None:
return ChatLine(line, (1970, 1, 1, 0, 0, 0), CHAT_UNKNOWN)
d = mo.groupdict()
- date = (self._year, int(d['M']), int(d['D']),
- int(d['h']), int(d['m']), int(d['s']))
- typ = CHAT_UNKNOWN
+ dt = (self._year, int(d['M']), int(d['D']),
+ int(d['h']), int(d['m']), int(d['s']))
msg = d['msg']
- info = {}
- important = False
+ info = {'type' : CHAT_UNKNOWN, 'datetime' : dt, 'important' : False}
if len(d['space']) == 2:
- typ = CHAT_MSG
mo = MSG_RE.match(msg)
if mo is None:
- return ChatLine(msg, dte, CHAT_UNKNOWN)
- info = mo.groupdict()
+ return msg, info
+ info['type'] = CHAT_MSG
+ info.update(mo.groupdict())
else:
if msg == CHATLOG_START:
- typ = CHAT_START
+ info['type'] = CHAT_START
elif msg == CHATLOG_STOP:
- typ = CHAT_STOP
+ info['type'] = CHAT_STOP
else:
for t, r in ((CHAT_PRIVMSGFROM, PRIVMSGFROM_RE),
(CHAT_PRIVMSGTO, PRIVMSGTO_RE),
(CHAT_ERROR, ERROR_RE)):
mo = r.match(msg)
if mo:
- typ = t
- info = mo.groupdict()
+ info['type'] = t
+ info.update(mo.groupdict())
break
- if typ == CHAT_UNKNOWN: # XXX check this
- typ = CHAT_ACTION
+ if info['type'] == CHAT_UNKNOWN: # XXX check this
+ info['type'] = CHAT_ACTION
for user in USER_IMPORTANT:
if user in msg:
- important = True
+ info['important'] = True
user = info.get('user', None)
if user:
if user in USER_IMPORTANT:
- important = True
- return ChatLine(msg, date, typ, important, info)
+ info['important'] = True
+ return msg, info
def __iter__(self):
for line in self._iterable:
yield self.parse(line)
-
-class ChatLine(unicode):
- __slots__ = ('datetime', 'typ', 'important', 'info')
-
- def __new__(cls, ustr, datetime, typ=None, important=False, info={}):
- self = unicode.__new__(cls, ustr)
- self.datetime = datetime
- self.typ = typ
- self.important = important
- self.info = info
- return self
-
- def asDatetime(self):
- return datetime(*self.date)
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|