# Twisted, the Framework of Your Internet
# Copyright (C) 2001 Matthew W. Lefkowitz
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of version 2.1 of the GNU Lesser General Public
# License as published by the Free Software Foundation.
#
# This library 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
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
"""IRC interface to L{twisted.words}.
I implement an IRC server so you can connect to a L{twisted.words}
service with a regular IRC client.
"""
# XXX FIXME This will need to be fixed to work with multi-server twisted.words
# and database access
# System Imports
# import fnmatch # used in /list, which is disabled pending security
import string
import time
# Twisted Imports
from twisted.protocols import irc
from twisted.internet import protocol
from twisted.spread import pb
from twisted.python import log
from twisted import copyright
# sibling imports
import service
class IRCChatter(irc.IRC, service.WordsClient):
nickname = '*'
passwd = None
participant = None
pendingLogin = None
hostname = "nowhere"
servicename = "twisted.words"
def callRemote(self, key, *args, **kw):
apply(getattr(self, key), args, kw)
def receiveContactList(self, contactList):
for name, status in contactList:
self.notifyStatusChanged(name, status)
def notifyStatusChanged(self, name, status):
self.sendMessage('NOTICE', ":%s is %s"
% (name, service.statuses[status]),
prefix='ContactServ!services@%s'
% (self.servicename,))
## # This didn't work very well.
## if status is service.ONLINE:
## self.sendMessage(irc.RPL_ISON, ":%s" % (name,))
## elif status is service.AWAY:
## # self.sendMessage(irc.RPL_AWAY, ":%s is %s"
## irc.IRC.sendMessage(self, irc.RPL_AWAY, ":%s is %s"
## % (name, service.statuses[status]))
## elif status is service.OFFLINE:
## self.sendMessage('QUIT', ":offline",
## # irc.IRC.sendMessage(self, 'QUIT', ":offline",
## prefix="%s@%s!%s"
## % (name, name, self.servicename))
def memberJoined(self, member, group):
#>> :glyph_!glyph@adsl-64-123-27-108.dsl.austtx.swbell.net JOIN :#python
self.sendLine(":%s!%s@%s JOIN :#%s" %
(member, member, self.servicename, group))
def memberLeft(self, member, group):
#>> :glyph_!glyph@adsl-64-123-27-108.dsl.austtx.swbell.net PART #python :test
self.sendLine(":%s!%s@%s PART #%s :(leaving)" %
(member, member, self.servicename, group))
def receiveDirectMessage(self, senderName, message, metadata=None):
#>> :glyph_!glyph@adsl-64-123-27-108.dsl.austtx.swbell.net PRIVMSG glyph_ :hello
#>> :glyph!glyph@adsl-64-123-27-108.dsl.austtx.swbell.net PRIVMSG glyph_ :hello
if metadata is not None and metadata.has_key('style'):
message = irc.ctcpStringify([(wordsToCtcp(metadata['style']),
message)])
for line in string.split(message, '\n'):
self.sendLine(":%s!%s@%s PRIVMSG %s :%s" %
(senderName, senderName, self.servicename,
self.nickname, line))
def receiveGroupMessage(self, sender, group, message, metadata=None):
if metadata is not None and metadata.has_key('style'):
message = irc.ctcpStringify([(wordsToCtcp(metadata['style']),
message)])
if sender is not self:
for line in string.split(message, '\n'):
self.sendLine(":%s!%s@%s PRIVMSG #%s :%s" %
(sender, sender, self.servicename,
group, line))
def setGroupMetadata(self, metadata, groupName):
if metadata.has_key('topic'):
topic = metadata['topic']
sender = metadata['topic_author']
irc.IRC.sendMessage(self, 'TOPIC',
'#' + groupName,
':' + irc.lowQuote(topic),
prefix="%s@%s!%s" %
(sender, sender, self.servicename))
def connectionLost(self, reason):
log.msg( "%s lost connection" % self.nickname )
if self.participant:
self.participant.detached(self, self.identity)
def sendMessage(self, command, *parameter_list, **kw):
if not kw.has_key('prefix'):
kw['prefix'] = self.servicename
if not kw.has_key('to'):
kw['to'] = self.nickname
arglist = [self, command, kw['to']] + list(parameter_list)
#arglist = [self, command] + list(parameter_list)
apply(irc.IRC.sendMessage, arglist, kw)
def irc_unknown(self, prefix, command, params):
log.msg('unknown irc proto msg!')
def irc_PASS(self, prefix, params):
"""Password message -- Register a password.
Parameters: <password>
[REQUIRED]
Note that IRC requires the client send this *before* NICK
and USER.
"""
self.passwd = params[-1]
def irc_NICK(self, prefix, params):
"""Nick message -- Set your nickname.
Parameters: <nickname>
[REQUIRED]
This is also probably the first thing the client sends us
(except possibly PASS), so the rest of the sign-on junk is in
here.
"""
nickname = params[0]
if not self.participant and not self.pendingLogin:
# << NICK glyph
# >> :testNickChange!glyph@adsl-64-123-27-108.dsl.austtx.swbell.net NICK :glyph
# self.sendLine(":%s!nowhere NICK :%s" %(self.nickname, nickname))
try:
participant = self.service.getPerspectiveNamed(nickname)
except service.UserNonexistantError:
self.sendMessage(irc.ERR_ERRONEUSNICKNAME,
nickname, ":this username is invalid",
to=nickname)
# XXX - We should really let them have another shot at
# giving their nick instead of just terminating the
# connection.
self.transport.loseConnection()
else:
self.nickname = nickname
self.sendMessage(irc.RPL_WELCOME,
":connected to Twisted IRC")
self.sendMessage(irc.RPL_YOURHOST,
":Your host is %s, running version %s" %
(self.servicename, copyright.version))
self.sendMessage(irc.RPL_CREATED,
":This server was created %s" %
"by a very sick man." or 'XXX: on date')
# "Bummer. This server returned a worthless 004 numeric.
# I'll have to guess at all the values"
# -- epic
self.sendMessage(irc.RPL_MYINFO,
self.servicename, copyright.version,
'w', 'n') # user and channel modes
if self.passwd is None:
self.receiveDirectMessage("NickServ", "Password?")
self.pendingLogin = participant
else:
self.logInAs(participant, self.passwd)
else:
# XXX: Is this error string appropriate?
self.sendMessage(irc.ERR_NICKNAMEINUSE,
nickname, ":this username is invalid")
def logInAs(self, participant, password):
"""Spawn appropriate callbacks to log in as this participant.
"""
self.pendingLogin = participant
self.pendingPassword = password
req = participant.getIdentityRequest()
req.addCallbacks(self.loggedInAs, self.notLoggedIn)
def loggedInAs(self, ident):
"""Successfully logged in.
"""
pwrq = ident.verifyPlainPassword(self.pendingPassword)
pwrq.addCallback(self.successfulLogin, ident)
pwrq.addErrback(self.failedLogin)
def successfulLogin(self, msg, ident):
self.identity = ident
self.pendingLogin.attached(self, self.identity)
self.participant = self.pendingLogin
self.sendMessage('NOTICE', ":Authentication accepted. "
"Thank you.", prefix='NickServ!services@%s'
% (self.servicename,))
self.sendMessage('376', ':No /MOTD.',prefix=self.servicename)
del self.pendingLogin
del self.pendingPassword
def failedLogin(self, error):
self.notLoggedIn(error)
del self.pendingLogin
del self.pendingPassword
def notLoggedIn(self, message):
"""Login failed.
"""
self.receiveDirectMessage("NickServ", "Login failed: %s" % message)
def irc_USER(self, prefix, params):
"""User message -- Set your realname.
Parameters: <user> <mode> <unused> <realname>
[REQUIRED] for backwards compatibility to IRC clients.
"""
self.realname = params[-1]
def irc_OPER(self, prefix, params):
"""Oper message
Parameters: <name> <password>
[REQUIRED]
"""
self.sendMessage(irc.ERR_NOOPERHOST,
":O-lines not applicable to Words service.")
# Note: this is *user* MODE, but we also have channel MODE
# defined below.
def irc_MODE(self, prefix, params):
"""User mode message
Parameters: <nickname>
*( ( "+" / "-" ) *( "i" / "w" / "o" / "O" / "r" ) )
[REQUIRED]
"""
if string.lower(params[0]) != string.lower(self.nickname):
return self.irc_channelMODE(prefix, params)
def irc_SERVICE(self, prefix, params):
"""Service message
Parameters: <nickname> <reserved> <distribution> <type>
[REQUIRED]
"""
self.sendMessage(irc.ERR_NOSERVICEHOST,
":No support for signing up services "
"via the IRC interface.")
def irc_QUIT(self, prefix, params):
"""Quit
Parameters: [ <Quit Message> ]
[REQUIRED]
"""
self.sendMessage('ERROR', ":You QUIT")
self.transport.loseConnection()
def irc_SQUIT(self, prefix, params):
"""SQuit
Parameters: <server> <comment>
[REQUIRED]
"""
self.sendMessage(irc.ERR_NOPRIVILEGES, ":No.")
def irc_JOIN(self, prefix, params):
"""Join message
Parameters: ( <channel> *( "," <channel> ) [ <key> *( "," <key> ) ] )
[REQUIRED]
"""
try:
channame = params[0][1:]
self.participant.joinGroup(channame)
except pb.Error:
pass
else:
self.memberJoined(self.nickname, channame)
self.irc_NAMES('', [params[0]])
self.irc_TOPIC('', [params[0]])
def irc_PART(self, prefix, params):
"""Part message
Parameters: <channel> *( "," <channel> ) [ <Part Message> ]
[REQUIRED]
"""
#<< PART #java :test
#>> :niven.openprojects.net 442 glyph #java :You're not on that channel
channame = params[0][1:]
try:
self.participant.leaveGroup(channame)
except pb.Error, e:
self.sendMessage(irc.ERR_NOTONCHANNEL,
"#" + channame, ":%s" % (e,))
else:
self.memberLeft(self.nickname, channame)
# Channel mode, in contrast to setting user mode, defined in
# irc_MODE above. (That MODE passes the call to this one if the
# first parameter is not the user's nick.)
def irc_channelMODE(self, prefix, params):
"""Channel mode message
Parameters: <channel> *( ( "-" / "+" ) *<modes> *<modeparams> )
[REQUIRED]
"""
name = params[0]
log.msg('mode? %s %s' % (prefix, params))
if name[0] == '#':
# get the channel, maybe?
self.sendMessage(irc.RPL_CHANNELMODEIS, name, "+")
def irc_TOPIC(self, prefix, params):
"""Topic message
Parameters: <channel> [ <topic> ]
[REQUIRED]
"""
#<< TOPIC #python
#>> :benford.openprojects.net 332 glyph #python :<churchr> I really did. I sprained all my toes.
#>> :benford.openprojects.net 333 glyph #python itamar|nyc 994713482
### and
#<< TOPIC #divunal :foo
#>> :glyph!glyph@adsl-64-123-27-108.dsl.austtx.swbell.net TOPIC #divunal :foo
log.msg('topic %s %s' % (prefix, params))
if len(params) == 1:
if params[0][0] != '#':
self.receiveDirectMessage("*error*", "invalid channel name")
return
channame = params[0][1:]
group = self.service.getGroup(channame)
self.sendMessage(irc.RPL_TOPIC,
"#" + group.name, ":" + group.metadata['topic'])
self.sendMessage('333', # not in the RFC
"#" + group.name, group.metadata['topic_author'], "1")
else:
#<< TOPIC #qdf :test
#>> :glyph!glyph@adsl-64-123-27-108.dsl.austtx.swbell.net TOPIC #qdf :test
groupName = params[0][1:]
# XXX: Eek, invasion of privacy!
group = self.service.getGroup(groupName)
group.setMetadata({'topic': params[-1],
'topic_author': self.nickname})
def irc_NAMES(self, prefix, params):
"""Names message
Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
[REQUIRED]
"""
#<< NAMES #python
#>> :benford.openprojects.net 353 glyph = #python :Orban ... @glyph ... Zymurgy skreech
#>> :benford.openprojects.net 366 glyph #python :End of /NAMES list.
channame = params[-1][1:]
group = self.service.groups.get(channame)
if group:
# :servicename XYZ theirNick = #channel :names\r\n
prefixLength = len(self.servicename) + len(self.nickname) + 11
namesLength = 512 - prefixLength
names = [member.name for member in group.members]
lastName = 0
curLength = 0
for i, L in zip(range(len(names)), map(len, names)):
if curLength + L > namesLength:
self.sendMessage(
irc.RPL_NAMREPLY, "=", "#" + channame,
":" + ' '.join(names[lastName:i])
)
lastName = i
curLength = 0
else:
curLength = curLength + L
if curLength:
self.sendMessage(
irc.RPL_NAMREPLY, "=", "#" + channame,
":" + ' '.join(names[lastName:])
)
self.sendMessage(irc.RPL_ENDOFNAMES,
"#" + channame, ":End of /NAMES list.")
def irc_LIST(self, prefix, params):
"""List message
Parameters: [ <channel> *( "," <channel> ) [ <target> ] ]
[REQUIRED]
"""
log.msg('list %s %s' % (prefix, params))
## if params:
## group_masks = map(string.lower, string.split(params[0], ','))
## for mask in group.masks:
## if len(mask) > 1 and mask[0] in '#!+&':
## mask = mask[1:]
## else:
## group_masks = ['*']
## for group_name, group in self.service.groups.items():
## group_lname = string.lower(group_name)
## for mask in group_masks:
## if fnmatch.fnmatch(group_lname, mask):
## it_matches = 1
## break
## if it_matches:
## self.sendMessage(irc.RPL_LIST, group_name,
## str(len(group.members)),
## ":" + group.topic)
self.sendMessage(irc.RPL_LISTEND, ":End of LIST")
def irc_INVITE(self, prefix, params):
"""Invite message
Parameters: <nickname> <channel>
[REQUIRED]
"""
pass # XXX - NotImplementedError
def irc_KICK(self, prefix, params):
"""Kick command
Parameters: <channel> *( "," <channel> ) <user> *( "," <user> )
[REQUIRED]
"""
pass # XXX - NotImplementedError
def irc_PRIVMSG(self, prefix, params):
"""Send a (private) message.
Parameters: <msgtarget> <text to be sent>
[REQUIRED]
"""
name = params[0]
text = params[-1]
if self.participant:
# CTCP -> Words.metadata conversion
if text[0]==irc.X_DELIM:
if name[0] == '#':
name_ = name[1:]
msgMethod = self.participant.groupMessage
else:
name_ = name
msgMethod = self.participant.directMessage
m = irc.ctcpExtract(text)
for tag, data in m['extended']:
metadata = {'style': ctcpToWords(tag)}
try:
msgMethod(name_, data, metadata)
except pb.Error, e:
self.receiveDirectMessage("*error*", str(e))
log.msg('error sending CTCP query:',str(e))
if not m['normal']:
return
text = string.join(m['normal'], ' ')
## 'bot' handling
if string.lower(name) == 'contactserv':
# crude contacts interface
cmds = string.split(text, ' ', 1)
if cmds[0] == 'add':
self.participant.addContact(cmds[1])
elif cmds[0] == 'remove':
self.participant.removeContact(cmds[1])
else:
self.receiveDirectMessage("ContactServ", "unknown command")
elif name[0] == '#':
log.msg( 'talking to channel %s %s %s ' % (self.nickname, prefix, params ))
channame = name[1:]
try:
self.participant.groupMessage(channame, text)
except pb.Error, e:
self.receiveDirectMessage("*error*", str(e))
log.msg('error chatting to channel:',str(e))
else:
try:
self.participant.directMessage(name, text)
except service.WordsError, e:
### << PRIVMSG vasdfasdf :hi
### >> :niven.openprojects.net 401 glyph vasdfasdf :No such nick/channel
self.sendMessage(irc.ERR_NOSUCHNICK, name,
":%s" % (e,))
else:
if string.lower(name) == 'nickserv':
self.logInAs(self.pendingLogin, text)
else:
self.receiveDirectMessage("NickServ", "You haven't logged in yet.")
def irc_NOTICE(self, prefix, params):
"""Notice
Parameters: <msgtarget> <text>
[REQUIRED]
"""
pass # XXX - NotImplementedError
def irc_MOTD(self, prefix, params):
"""Motd message
Parameters: [ <target> ]
[REQUIRED]
"""
pass # XXX - NotImplementedError
def irc_LUSERS(self, prefix, params):
"""Lusers message
Parameters: [ <mask> [ <target> ] ]
[REQUIRED]
"""
self.sendMessage(irc.RPL_LUSERCLIENT,
":There are %s users on %s hosts." %
("some", "all the"))
self.sendMessage(irc.RPL_LUSERME,
":All your base are belong to us.")
def irc_VERSION(self, prefix, params):
"""Version message
Parameters: [ <target> ]
[REQUIRED]
"""
self.sendMessage(irc.RPL_VERSION, copyright.version,
self.servicename, ":http://twistedmatrix.com/")
def irc_STATS(self, prefix, params):
"""Stats message
Parameters: [ <query> [ <target> ] ]
[REQUIRED]
"""
if params:
letter = params[0]
else:
letter = ''
self.sendMessage(irc.RPL_ENDOFSTATS, letter,
":That is all.")
def irc_LINKS(self, prefix, params):
"""Links message
Parameters: [ [ <remote server> ] <server mask> ]
[REQUIRED]
"""
self.sendMessage(irc.RPL_ENDOFLINKS, '*',
":End of links.")
def irc_TIME(self, prefix, params):
"""Time message
Parameters: [ <target> ]
[REQUIRED]
"""
self.sendMessage(irc.RPL_TIME, ":%s" %
(time.asctime(time.localtime()),))
def irc_CONNECT(self, prefix, params):
"""Connect message
Parameters: <target server> <port> [ <remote server> ]
[REQUIRED]
"""
self.sendMessage(irc.ERR_NOPRIVILEGES, ":No.")
def irc_TRACE(self, prefix, params):
"""Trace message
Parameters: [ <target> ]
[REQUIRED]
"""
self.sendMessage(irc.RPL_TRACENEWTYPE, "Trace a path over")
self.sendMessage(irc.RPL_TRACEUNKNOWN, "references intangible,")
self.sendMessage(irc.RPL_TRACEEND, self.servicename,
copyright.version, ":internet come home.")
# This response does not conform strictly to RFC 2812,
# but it is haiku compliant.
def irc_INFO(self, prefix, params):
"""Admin command
Parameters: [ <target> ]
[REQUIRED]
"""
self.sendMessage(irc.RPL_INFO, ":Info requested")
self.sendMessage(irc.RPL_INFO, ":valuable commodity")
self.sendMessage(irc.RPL_ENDOFINFO, ":What's it worth to you?")
def irc_SERVLIST(self, prefix, params):
"""Servlist message
Parameters: [ <mask> [ <type> ] ]
[REQUIRED]
"""
self.sendMessage(irc.RPL_SERVLISTEND,
":I'd tell you, but this is an unsecured line.")
def irc_SQUERY(self, prefix, params):
"""Squery
Parameters: <servicename> <text>
[REQUIRED]
"""
pass
def irc_WHO(self, prefix, params):
"""Who query
Parameters: [ <mask> [ "o" ] ]
[REQUIRED]
"""
#<< who #python
#>> :benford.openprojects.net 352 glyph #python aquarius pc-62-31-193-114-du.blueyonder.co.uk forward.openprojects.net Aquarius H :3 Aquarius
# ...
#>> :benford.openprojects.net 352 glyph #python foobar europa.tranquility.net benford.openprojects.net skreech H :0 skreech
#>> :benford.openprojects.net 315 glyph #python :End of /WHO list.
### also
#<< who glyph
#>> :benford.openprojects.net 352 glyph #python glyph adsl-64-123-27-108.dsl.austtx.swbell.net benford.openprojects.net glyph H :0 glyph
#>> :benford.openprojects.net 315 glyph glyph :End of /WHO list.
if not params:
self.sendMessage(irc.RPL_ENDOFWHO, ":/WHO not supported.")
return
name = params[0]
if name[0] == '#':
channame = name[1:]
group = self.service.getGroup(channame)
for member in group.members:
self.sendMessage(irc.RPL_WHOREPLY, "#" + group.name,
member.name, self.servicename,
self.servicename, member.name,
"H",":0", member.name)
self.sendMessage(irc.RPL_ENDOFWHO, "#" + group.name,
":End of /WHO list.")
else:
self.sendMessage(irc.RPL_ENDOFWHO,
":User /WHO not implemented")
def irc_WHOIS(self, prefix, params):
"""Whois query
Parameters: [ <target> ] <mask> *( "," <mask> )
[REQUIRED]
"""
if params:
target = params[0]
else:
target = self.nickname
## try:
## participant = getParticipantNamed(target)
## except service.UserNonexistantError:
## self.sendMessage(irc.ERR_NOSUCHNICK,
## target, ":No such nickname.")
## return
## nick = participant.name
## user = participant.identityName
## # 'host' being the origin of this participant's connection,
## # the place sie calls home. Typically the FQDN of the machine
## # the user is running their client off of, but other
## # interpretations are imaginable, as some might say there are
## # privacy/security issues in making such information public.
## host = participant.XXX
## # The participant's "real" name. Usually contains nothing of
## # the sort, but rather any short bit of identifying
## # information which the nick doesn't convay on its own. Such
## # as "King of Spain" or "http://twistedmatrix.com/users/elrey/"
## real_name = getIdentityNamed(participant.identityName).realName
## # The server this participant is connecting through. For
## # answering questions such as "How can I use the server sie's
## # using?" and "That host is really poorly administered. What
## # should I put in my blacklist file?"
## server = XXX
## server_info = XXX.desc
## self.sendMessage(irc.RPL_WHOISUSER,
## nick, user, host, '*', ':' + real_name)
## self.sendMessage(irc.RPL_WHOISSERVER,
## nick, server, ':' + server_info)
## if participant.status is not service.ONLINE:
## away_message = XXX or service.statuses[participant.status]
## self.sendMessage(irc.RPL_AWAY,
## nick, ':' + away_message)
## if participant.idle_time:
## seconds_idle = time.time() - participant.idle_time:
## self.sendMessage(irc.RPL_WHOISIDLE, nick, seconds_idle,
## ':seconds idle')
## self.sendMessage(irc.RPL_ENDOFWHOIS, nick, ':end of WHOIS')
def irc_WHOWAS(self, prefix, params):
"""Whowas
Parameters: <nickname> *( "," <nickname> ) [ <count> [ <target> ] ]
[REQUIRED]
"""
pass # XXX - NotImplementedError
def irc_KILL(self, prefix, params):
"""Kill message
Parameters: <nickname> <comment>
[REQUIRED]
"""
if not params or not params[0]:
self.sendMessage(irc.ERR_NEEDMOREPARAMS,
':The voices... "kill," they say. "kill."')
else:
object = string.join(params)
self.sendMessage(irc.ERR_NOPRIVILEGES,
":I don't think the %s would "
"like that very much." % (object,))
def irc_PING(self, prefix, params):
"""Ping message
Parameters: <server1> [ <server2> ]
[REQUIRED]
"""
self.sendMessage('PONG', self.servicename)
def irc_PONG(self, prefix, params):
"""Pong message
Parameters: <server> [ <server2> ]
[REQUIRED]
"""
pass
def irc_ERROR(self, prefix, params):
"""Error
Parameters: <error message>
[REQUIRED]
"""
pass
def irc_AWAY(self, prefix, params):
"""Away
Parameters: [ <text> ]
[Optional]
"""
if params and params[0]: # there is an away message
self.participant.changeStatus(service.AWAY)
self.sendMessage(irc.RPL_NOWAWAY, "You are now away.")
else:
self.participant.changeStatus(service.ONLINE)
self.sendMessage(irc.RPL_UNAWAY, "You are no longer away.")
def irc_REHASH(self, prefix, params):
"""Rehash message
Parameters: None
[Optional]
"""
pass
def irc_DIE(self, prefix, params):
"""Die message
Parameters: None
[Optional]
"""
self.sendMessage(irc.ERR_NOPRIVILEGES, ":After you.")
def irc_RESTART(self, prefix, params):
"""Restart message
Parameters: None
[Optional]
"""
pass
def irc_SUMMON(self, prefix, params):
"""Summon message
Parameters: <user> [ <target> [ <channel> ] ]
[Optional]
"""
self.sendMessage(irc.ERR_SUMMONDISABLED,
":You don't have enough mana to cast that spell.")
def irc_USERS(self, prefix, params):
"""Users
Parameters: [ <target> ]
[Optional]
"""
pass
def irc_WALLOPS(self, prefix, params):
"""Operwall message
Parameters: <Text to be sent>
[Optional]
"""
pass
def irc_USERHOST(self, prefix, params):
"""Userhost message
Parameters: <nickname> *( SPACE <nickname> )
[Optional]
"""
pass
def irc_ISON(self, prefix, params):
"""Ison message
Parameters: <nickname> *( SPACE <nickname> )
[Optional]
"""
ison = params[:]
for nick in params:
# if not self.service.isOnline(nick):
# ison.remove(nick)
# self.sendMessage(irc.RPL_ISON, ":" + string.join(ison))
pass
class IRCGateway(protocol.Factory):
def __init__(self, service):
self.service = service
def buildProtocol(self, connection):
"""Build an IRC protocol to talk to my chat service.
"""
i = IRCChatter()
i.service = self.service
return i
mapCtcpToWords = {
'ACTION': 'emote',
}
mapWordsToCtcp = {}
for _k, _v in mapCtcpToWords.items():
mapWordsToCtcp[_v] = _k
def ctcpToWords(query_tag):
return mapCtcpToWords.get(query_tag, query_tag)
def wordsToCtcp(style):
return mapWordsToCtcp.get(style, style)
syntax highlighted by Code2HTML, v. 0.9.1