123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293 |
- # Copyright (c) Twisted Matrix Laboratories.
- # See LICENSE for details.
- """
- IRC support for Instance Messenger.
- """
- from twisted.words.protocols import irc
- from twisted.words.im.locals import ONLINE
- from twisted.internet import defer, reactor, protocol
- from twisted.internet.defer import succeed
- from twisted.words.im import basesupport, interfaces, locals
- from zope.interface import implementer
- class IRCPerson(basesupport.AbstractPerson):
- def imperson_whois(self):
- if self.account.client is None:
- raise locals.OfflineError
- self.account.client.sendLine("WHOIS %s" % self.name)
- ### interface impl
- def isOnline(self):
- return ONLINE
- def getStatus(self):
- return ONLINE
- def setStatus(self,status):
- self.status=status
- self.chat.getContactsList().setContactStatus(self)
- def sendMessage(self, text, meta=None):
- if self.account.client is None:
- raise locals.OfflineError
- for line in text.split('\n'):
- if meta and meta.get("style", None) == "emote":
- self.account.client.ctcpMakeQuery(self.name,[('ACTION', line)])
- else:
- self.account.client.msg(self.name, line)
- return succeed(text)
- @implementer(interfaces.IGroup)
- class IRCGroup(basesupport.AbstractGroup):
- def imgroup_testAction(self):
- pass
- def imtarget_kick(self, target):
- if self.account.client is None:
- raise locals.OfflineError
- reason = "for great justice!"
- self.account.client.sendLine("KICK #%s %s :%s" % (
- self.name, target.name, reason))
- ### Interface Implementation
- def setTopic(self, topic):
- if self.account.client is None:
- raise locals.OfflineError
- self.account.client.topic(self.name, topic)
- def sendGroupMessage(self, text, meta={}):
- if self.account.client is None:
- raise locals.OfflineError
- if meta and meta.get("style", None) == "emote":
- self.account.client.ctcpMakeQuery(self.name,[('ACTION', text)])
- return succeed(text)
- #standard shmandard, clients don't support plain escaped newlines!
- for line in text.split('\n'):
- self.account.client.say(self.name, line)
- return succeed(text)
- def leave(self):
- if self.account.client is None:
- raise locals.OfflineError
- self.account.client.leave(self.name)
- self.account.client.getGroupConversation(self.name,1)
- class IRCProto(basesupport.AbstractClientMixin, irc.IRCClient):
- def __init__(self, account, chatui, logonDeferred=None):
- basesupport.AbstractClientMixin.__init__(self, account, chatui,
- logonDeferred)
- self._namreplies={}
- self._ingroups={}
- self._groups={}
- self._topics={}
- def getGroupConversation(self, name, hide=0):
- name = name.lower()
- return self.chat.getGroupConversation(self.chat.getGroup(name, self),
- stayHidden=hide)
- def getPerson(self,name):
- return self.chat.getPerson(name, self)
- def connectionMade(self):
- # XXX: Why do I duplicate code in IRCClient.register?
- try:
- self.performLogin = True
- self.nickname = self.account.username
- self.password = self.account.password
- self.realname = "Twisted-IM user"
- irc.IRCClient.connectionMade(self)
- for channel in self.account.channels:
- self.joinGroup(channel)
- self.account._isOnline=1
- if self._logonDeferred is not None:
- self._logonDeferred.callback(self)
- self.chat.getContactsList()
- except:
- import traceback
- traceback.print_exc()
- def setNick(self,nick):
- self.name=nick
- self.accountName="%s (IRC)"%nick
- irc.IRCClient.setNick(self,nick)
- def kickedFrom(self, channel, kicker, message):
- """
- Called when I am kicked from a channel.
- """
- return self.chat.getGroupConversation(
- self.chat.getGroup(channel[1:], self), 1)
- def userKicked(self, kickee, channel, kicker, message):
- pass
- def noticed(self, username, channel, message):
- self.privmsg(username, channel, message, {"dontAutoRespond": 1})
- def privmsg(self, username, channel, message, metadata=None):
- if metadata is None:
- metadata = {}
- username = username.split('!',1)[0]
- if username==self.name: return
- if channel[0]=='#':
- group=channel[1:]
- self.getGroupConversation(group).showGroupMessage(username, message, metadata)
- return
- self.chat.getConversation(self.getPerson(username)).showMessage(message, metadata)
- def action(self,username,channel,emote):
- username = username.split('!',1)[0]
- if username==self.name: return
- meta={'style':'emote'}
- if channel[0]=='#':
- group=channel[1:]
- self.getGroupConversation(group).showGroupMessage(username, emote, meta)
- return
- self.chat.getConversation(self.getPerson(username)).showMessage(emote,meta)
- def irc_RPL_NAMREPLY(self,prefix,params):
- """
- RPL_NAMREPLY
- >> NAMES #bnl
- << :Arlington.VA.US.Undernet.Org 353 z3p = #bnl :pSwede Dan-- SkOyg AG
- """
- group = params[2][1:].lower()
- users = params[3].split()
- for ui in range(len(users)):
- while users[ui][0] in ["@","+"]: # channel modes
- users[ui]=users[ui][1:]
- if group not in self._namreplies:
- self._namreplies[group]=[]
- self._namreplies[group].extend(users)
- for nickname in users:
- try:
- self._ingroups[nickname].append(group)
- except:
- self._ingroups[nickname]=[group]
- def irc_RPL_ENDOFNAMES(self,prefix,params):
- group=params[1][1:]
- self.getGroupConversation(group).setGroupMembers(self._namreplies[group.lower()])
- del self._namreplies[group.lower()]
- def irc_RPL_TOPIC(self,prefix,params):
- self._topics[params[1][1:]]=params[2]
- def irc_333(self,prefix,params):
- group=params[1][1:]
- self.getGroupConversation(group).setTopic(self._topics[group],params[2])
- del self._topics[group]
- def irc_TOPIC(self,prefix,params):
- nickname = prefix.split("!")[0]
- group = params[0][1:]
- topic = params[1]
- self.getGroupConversation(group).setTopic(topic,nickname)
- def irc_JOIN(self,prefix,params):
- nickname = prefix.split("!")[0]
- group = params[0][1:].lower()
- if nickname!=self.nickname:
- try:
- self._ingroups[nickname].append(group)
- except:
- self._ingroups[nickname]=[group]
- self.getGroupConversation(group).memberJoined(nickname)
- def irc_PART(self,prefix,params):
- nickname = prefix.split("!")[0]
- group = params[0][1:].lower()
- if nickname!=self.nickname:
- if group in self._ingroups[nickname]:
- self._ingroups[nickname].remove(group)
- self.getGroupConversation(group).memberLeft(nickname)
- def irc_QUIT(self,prefix,params):
- nickname = prefix.split("!")[0]
- if nickname in self._ingroups:
- for group in self._ingroups[nickname]:
- self.getGroupConversation(group).memberLeft(nickname)
- self._ingroups[nickname]=[]
- def irc_NICK(self, prefix, params):
- fromNick = prefix.split("!")[0]
- toNick = params[0]
- if fromNick not in self._ingroups:
- return
- for group in self._ingroups[fromNick]:
- self.getGroupConversation(group).memberChangedNick(fromNick, toNick)
- self._ingroups[toNick] = self._ingroups[fromNick]
- del self._ingroups[fromNick]
- def irc_unknown(self, prefix, command, params):
- pass
- # GTKIM calls
- def joinGroup(self,name):
- self.join(name)
- self.getGroupConversation(name)
- @implementer(interfaces.IAccount)
- class IRCAccount(basesupport.AbstractAccount):
- gatewayType = "IRC"
- _groupFactory = IRCGroup
- _personFactory = IRCPerson
- def __init__(self, accountName, autoLogin, username, password, host, port,
- channels=''):
- basesupport.AbstractAccount.__init__(self, accountName, autoLogin,
- username, password, host, port)
- self.channels = [channel.strip() for channel in channels.split(',')]
- if self.channels == ['']:
- self.channels = []
- def _startLogOn(self, chatui):
- logonDeferred = defer.Deferred()
- cc = protocol.ClientCreator(reactor, IRCProto, self, chatui,
- logonDeferred)
- d = cc.connectTCP(self.host, self.port)
- d.addErrback(logonDeferred.errback)
- return logonDeferred
|