1 # Copyright (c) 2001-2004 Twisted Matrix Laboratories.
2 # See LICENSE for details.
5 """IRC support for Instance Messenger."""
9 from protocols import irc
10 #from twisted.words.protocols import irc
11 #from twisted.words.im.locals import ONLINE
12 from twisted.internet import defer, reactor, protocol
13 from twisted.internet.defer import succeed
14 #from twisted.words.im import e2support, interfaces, locals
15 import e2support, interfaces,dreamIRCTools
16 from zope.interface import implements
19 class IRCPerson(e2support.AbstractPerson):
21 def imperson_whois(self):
22 if self.account.client is None:
23 raise locals.OfflineError
24 self.account.client.sendLine("WHOIS %s" % self.name)
34 def setStatus(self,status):
36 self.chat.getContactsList().setContactStatus(self)
38 def sendMessage(self, text, meta=None):
39 if self.account.client is None:
40 raise locals.OfflineError
41 for line in string.split(text, '\n'):
42 if meta and meta.get("style", None) == "emote":
43 self.account.client.ctcpMakeQuery(self.name,[('ACTION', line)])
45 self.account.client.msg(self.name, line)
49 if self.account.client is None:
52 self.account.client.quit("user logged off")
55 class IRCGroup(e2support.AbstractGroup):
57 implements(interfaces.IGroup)
59 def imgroup_testAction(self):
62 def imtarget_kick(self, target):
63 if self.account.client is None:
64 raise locals.OfflineError
65 reason = "... and justice for all!"
66 self.account.client.sendLine("KICK #%s %s :%s" % (
67 self.name, target.name, reason))
69 ### Interface Implementation
71 def setTopic(self, topic):
72 if self.account.client is None:
73 raise locals.OfflineError
74 self.account.client.topic(self.name, topic)
76 def sendGroupMessage(self, text, meta={}):
77 if self.account.client is None:
78 raise locals.OfflineError
79 if meta and meta.get("style", None) == "emote":
80 self.account.client.me(self.name,text)
82 #standard shmandard, clients don't support plain escaped newlines!
83 for line in string.split(text, '\n'):
84 self.account.client.say(self.name, line)
88 if self.account.client is None:
89 raise locals.OfflineError
90 self.account.client.leave(self.name)
91 self.account.client.getGroupConversation(self.name,1)
94 if self.account.client is None:
97 self.account.client.quit("user logged off")
100 class IRCProto(e2support.AbstractClientMixin, irc.IRCClient):
101 def __init__(self, account, chatui, logonDeferred=None):
102 e2support.AbstractClientMixin.__init__(self, account, chatui,
109 def getGroupConversation(self, name, hide=0):
110 name=string.lower(name)
111 return self.chat.getGroupConversation(self.chat.getGroup(name, self),
114 def getPerson(self,name):
115 return self.chat.getPerson(name, self)
117 def connectionMade(self):
118 # XXX: Why do I duplicate code in IRCClient.register?
120 print 'connection made on irc service!?', self
121 if self.account.password:
122 self.sendLine("PASS :%s" % self.account.password)
123 self.setNick(self.account.username)
124 self.sendLine("USER %s foo bar :dreamIRC e2 v1.0 user" % (self.nickname))
125 for channel in self.account.channels:
126 print "joining channel: %s" % channel
127 self.joinGroup(channel)
128 self.account._isOnline=1
129 print 'uh, registering irc acct'
130 if self._logonDeferred is not None:
131 self._logonDeferred.callback(self)
132 self.chat.getContactsList()
135 traceback.print_exc()
137 def setNick(self,nick):
139 self.accountName="%s (IRC)"%nick
140 irc.IRCClient.setNick(self,nick)
142 def quit(self,message='bye bye'):
143 # self.quit_str=str("QUIT :%s" % message)
144 self.sendLine("QUIT :%s" % message)
146 def kickedFrom(self, channel, kicker, message):
147 """Called when I am kicked from a channel.
149 print 'wow i was kicked', channel, kicker, message
150 return self.chat.getGroupConversation(
151 self.chat.getGroup(channel[1:], self), 1)
153 def userKicked(self, kickee, channel, kicker, message):
154 print 'whew somebody else', kickee, channel, kicker, message
156 def noticed(self, username, channel, message):
157 self.privmsg(username, channel, message, {"dontAutoRespond": 1})
159 def privmsg(self, username, channel, message, metadata=None):
162 username=string.split(username,'!',1)[0]
163 if username==self.name: return
166 self.getGroupConversation(group).showGroupMessage(username, message, metadata)
168 self.chat.getConversation(self.getPerson(username)).showMessage(message, metadata)
170 def action(self,username,channel,emote):
171 username=string.split(username,'!',1)[0]
172 if username==self.name: return
173 meta={'style':'emote'}
176 self.getGroupConversation(group).showGroupMessage(username, emote, meta)
178 self.chat.getConversation(self.getPerson(username)).showMessage(emote,meta)
180 def irc_RPL_NAMREPLY(self,prefix,params):
184 << :Arlington.VA.US.Undernet.Org 353 z3p = #bnl :pSwede Dan-- SkOyg AG
186 group=string.lower(params[2][1:])
187 users=string.split(params[3])
188 for ui in range(len(users)):
189 while users[ui][0] in ["@","+"]: # channel modes
190 users[ui]=users[ui][1:]
191 if not self._namreplies.has_key(group):
192 self._namreplies[group]=[]
193 self._namreplies[group].extend(users)
194 for nickname in users:
196 self._ingroups[nickname].append(group)
198 self._ingroups[nickname]=[group]
200 def irc_RPL_ENDOFNAMES(self,prefix,params):
202 self.getGroupConversation(group).setGroupMembers(self._namreplies[string.lower(group)])
203 del self._namreplies[string.lower(group)]
205 def irc_RPL_TOPIC(self,prefix,params):
206 self._topics[params[1][1:]]=params[2]
208 def irc_333(self,prefix,params):
210 self.getGroupConversation(group).setTopic(self._topics[group],params[2])
211 del self._topics[group]
213 def irc_TOPIC(self,prefix,params):
214 nickname = string.split(prefix,"!")[0]
215 group = params[0][1:]
217 self.getGroupConversation(group).setTopic(topic,nickname)
219 def irc_JOIN(self,prefix,params):
220 nickname=string.split(prefix,"!")[0]
221 group=string.lower(params[0][1:])
222 if nickname!=self.nickname:
224 self._ingroups[nickname].append(group)
226 self._ingroups[nickname]=[group]
227 self.getGroupConversation(group).memberJoined(nickname)
229 def irc_PART(self,prefix,params):
230 nickname=string.split(prefix,"!")[0]
231 group=string.lower(params[0][1:])
232 if nickname!=self.nickname:
233 if group in self._ingroups[nickname]:
234 self._ingroups[nickname].remove(group)
235 self.getGroupConversation(group).memberLeft(nickname)
237 print "%s left %s, but wasn't in the room."%(nickname,group)
239 def irc_QUIT(self,prefix,params):
240 nickname=string.split(prefix,"!")[0]
241 if self._ingroups.has_key(nickname):
242 for group in self._ingroups[nickname]:
243 self.getGroupConversation(group).memberLeft(nickname)
244 self._ingroups[nickname]=[]
246 print '*** WARNING: ingroups had no such key %s' % nickname
248 def irc_NICK(self, prefix, params):
249 fromNick = string.split(prefix, "!")[0]
251 if not self._ingroups.has_key(fromNick):
252 print "%s changed nick to %s. But she's not in any groups!?" % (fromNick, toNick)
254 for group in self._ingroups[fromNick]:
255 self.getGroupConversation(group).memberChangedNick(fromNick, toNick)
256 self._ingroups[toNick] = self._ingroups[fromNick]
257 del self._ingroups[fromNick]
259 def irc_unknown(self, prefix, command, params):
260 print "unknown message from IRCserver. prefix: %s, command: %s, params: %s" % (prefix, command, params)
263 def joinGroup(self,name):
265 self.getGroupConversation(name)
267 class IRCAccount(e2support.AbstractAccount):
268 implements(interfaces.IAccount)
271 _groupFactory = IRCGroup
272 _personFactory = IRCPerson
274 def __init__(self, accountName, autoLogin, username, password, host, port, channels=''):
275 e2support.AbstractAccount.__init__(self, accountName, autoLogin, username, password, host, port)
276 self.channels = map(string.strip,string.split(channels,','))
277 if self.channels == ['']:
280 def _startLogOn(self, chatui):
281 logonDeferred = defer.Deferred()
282 cc = protocol.ClientCreator(reactor, IRCProto, self, chatui, logonDeferred)
283 d = cc.connectTCP(self.host, self.port)
284 d.addErrback(logonDeferred.errback)