OLD | NEW |
| (Empty) |
1 # Copyright (c) 2001-2004 Twisted Matrix Laboratories. | |
2 # See LICENSE for details. | |
3 | |
4 | |
5 """IRC support for Instance Messenger.""" | |
6 | |
7 import string | |
8 | |
9 from twisted.words.protocols import irc | |
10 from twisted.words.im.locals import ONLINE | |
11 from twisted.internet import defer, reactor, protocol | |
12 from twisted.internet.defer import succeed | |
13 from twisted.words.im import basesupport, interfaces, locals | |
14 from zope.interface import implements | |
15 | |
16 | |
17 class IRCPerson(basesupport.AbstractPerson): | |
18 | |
19 def imperson_whois(self): | |
20 if self.account.client is None: | |
21 raise locals.OfflineError | |
22 self.account.client.sendLine("WHOIS %s" % self.name) | |
23 | |
24 ### interface impl | |
25 | |
26 def isOnline(self): | |
27 return ONLINE | |
28 | |
29 def getStatus(self): | |
30 return ONLINE | |
31 | |
32 def setStatus(self,status): | |
33 self.status=status | |
34 self.chat.getContactsList().setContactStatus(self) | |
35 | |
36 def sendMessage(self, text, meta=None): | |
37 if self.account.client is None: | |
38 raise locals.OfflineError | |
39 for line in string.split(text, '\n'): | |
40 if meta and meta.get("style", None) == "emote": | |
41 self.account.client.ctcpMakeQuery(self.name,[('ACTION', line)]) | |
42 else: | |
43 self.account.client.msg(self.name, line) | |
44 return succeed(text) | |
45 | |
46 class IRCGroup(basesupport.AbstractGroup): | |
47 | |
48 implements(interfaces.IGroup) | |
49 | |
50 def imgroup_testAction(self): | |
51 print 'action test!' | |
52 | |
53 def imtarget_kick(self, target): | |
54 if self.account.client is None: | |
55 raise locals.OfflineError | |
56 reason = "for great justice!" | |
57 self.account.client.sendLine("KICK #%s %s :%s" % ( | |
58 self.name, target.name, reason)) | |
59 | |
60 ### Interface Implementation | |
61 | |
62 def setTopic(self, topic): | |
63 if self.account.client is None: | |
64 raise locals.OfflineError | |
65 self.account.client.topic(self.name, topic) | |
66 | |
67 def sendGroupMessage(self, text, meta={}): | |
68 if self.account.client is None: | |
69 raise locals.OfflineError | |
70 if meta and meta.get("style", None) == "emote": | |
71 self.account.client.me(self.name,text) | |
72 return succeed(text) | |
73 #standard shmandard, clients don't support plain escaped newlines! | |
74 for line in string.split(text, '\n'): | |
75 self.account.client.say(self.name, line) | |
76 return succeed(text) | |
77 | |
78 def leave(self): | |
79 if self.account.client is None: | |
80 raise locals.OfflineError | |
81 self.account.client.leave(self.name) | |
82 self.account.client.getGroupConversation(self.name,1) | |
83 | |
84 | |
85 class IRCProto(basesupport.AbstractClientMixin, irc.IRCClient): | |
86 def __init__(self, account, chatui, logonDeferred=None): | |
87 basesupport.AbstractClientMixin.__init__(self, account, chatui, | |
88 logonDeferred) | |
89 self._namreplies={} | |
90 self._ingroups={} | |
91 self._groups={} | |
92 self._topics={} | |
93 | |
94 def getGroupConversation(self, name, hide=0): | |
95 name=string.lower(name) | |
96 return self.chat.getGroupConversation(self.chat.getGroup(name, self), | |
97 stayHidden=hide) | |
98 | |
99 def getPerson(self,name): | |
100 return self.chat.getPerson(name, self) | |
101 | |
102 def connectionMade(self): | |
103 # XXX: Why do I duplicate code in IRCClient.register? | |
104 try: | |
105 print 'connection made on irc service!?', self | |
106 if self.account.password: | |
107 self.sendLine("PASS :%s" % self.account.password) | |
108 self.setNick(self.account.username) | |
109 self.sendLine("USER %s foo bar :Twisted-IM user" % (self.nickname,)) | |
110 for channel in self.account.channels: | |
111 self.joinGroup(channel) | |
112 self.account._isOnline=1 | |
113 print 'uh, registering irc acct' | |
114 if self._logonDeferred is not None: | |
115 self._logonDeferred.callback(self) | |
116 self.chat.getContactsList() | |
117 except: | |
118 import traceback | |
119 traceback.print_exc() | |
120 | |
121 def setNick(self,nick): | |
122 self.name=nick | |
123 self.accountName="%s (IRC)"%nick | |
124 irc.IRCClient.setNick(self,nick) | |
125 | |
126 def kickedFrom(self, channel, kicker, message): | |
127 """Called when I am kicked from a channel. | |
128 """ | |
129 print 'ono i was kicked', channel, kicker, message | |
130 return self.chat.getGroupConversation( | |
131 self.chat.getGroup(channel[1:], self), 1) | |
132 | |
133 def userKicked(self, kickee, channel, kicker, message): | |
134 print 'whew somebody else', kickee, channel, kicker, message | |
135 | |
136 def noticed(self, username, channel, message): | |
137 self.privmsg(username, channel, message, {"dontAutoRespond": 1}) | |
138 | |
139 def privmsg(self, username, channel, message, metadata=None): | |
140 if metadata is None: | |
141 metadata = {} | |
142 username=string.split(username,'!',1)[0] | |
143 if username==self.name: return | |
144 if channel[0]=='#': | |
145 group=channel[1:] | |
146 self.getGroupConversation(group).showGroupMessage(username, message,
metadata) | |
147 return | |
148 self.chat.getConversation(self.getPerson(username)).showMessage(message,
metadata) | |
149 | |
150 def action(self,username,channel,emote): | |
151 username=string.split(username,'!',1)[0] | |
152 if username==self.name: return | |
153 meta={'style':'emote'} | |
154 if channel[0]=='#': | |
155 group=channel[1:] | |
156 self.getGroupConversation(group).showGroupMessage(username, emote, m
eta) | |
157 return | |
158 self.chat.getConversation(self.getPerson(username)).showMessage(emote,me
ta) | |
159 | |
160 def irc_RPL_NAMREPLY(self,prefix,params): | |
161 """ | |
162 RPL_NAMREPLY | |
163 >> NAMES #bnl | |
164 << :Arlington.VA.US.Undernet.Org 353 z3p = #bnl :pSwede Dan-- SkOyg AG | |
165 """ | |
166 group=string.lower(params[2][1:]) | |
167 users=string.split(params[3]) | |
168 for ui in range(len(users)): | |
169 while users[ui][0] in ["@","+"]: # channel modes | |
170 users[ui]=users[ui][1:] | |
171 if not self._namreplies.has_key(group): | |
172 self._namreplies[group]=[] | |
173 self._namreplies[group].extend(users) | |
174 for nickname in users: | |
175 try: | |
176 self._ingroups[nickname].append(group) | |
177 except: | |
178 self._ingroups[nickname]=[group] | |
179 | |
180 def irc_RPL_ENDOFNAMES(self,prefix,params): | |
181 group=params[1][1:] | |
182 self.getGroupConversation(group).setGroupMembers(self._namreplies[string
.lower(group)]) | |
183 del self._namreplies[string.lower(group)] | |
184 | |
185 def irc_RPL_TOPIC(self,prefix,params): | |
186 self._topics[params[1][1:]]=params[2] | |
187 | |
188 def irc_333(self,prefix,params): | |
189 group=params[1][1:] | |
190 self.getGroupConversation(group).setTopic(self._topics[group],params[2]) | |
191 del self._topics[group] | |
192 | |
193 def irc_TOPIC(self,prefix,params): | |
194 nickname = string.split(prefix,"!")[0] | |
195 group = params[0][1:] | |
196 topic = params[1] | |
197 self.getGroupConversation(group).setTopic(topic,nickname) | |
198 | |
199 def irc_JOIN(self,prefix,params): | |
200 nickname=string.split(prefix,"!")[0] | |
201 group=string.lower(params[0][1:]) | |
202 if nickname!=self.nickname: | |
203 try: | |
204 self._ingroups[nickname].append(group) | |
205 except: | |
206 self._ingroups[nickname]=[group] | |
207 self.getGroupConversation(group).memberJoined(nickname) | |
208 | |
209 def irc_PART(self,prefix,params): | |
210 nickname=string.split(prefix,"!")[0] | |
211 group=string.lower(params[0][1:]) | |
212 if nickname!=self.nickname: | |
213 if group in self._ingroups[nickname]: | |
214 self._ingroups[nickname].remove(group) | |
215 self.getGroupConversation(group).memberLeft(nickname) | |
216 else: | |
217 print "%s left %s, but wasn't in the room."%(nickname,group) | |
218 | |
219 def irc_QUIT(self,prefix,params): | |
220 nickname=string.split(prefix,"!")[0] | |
221 if self._ingroups.has_key(nickname): | |
222 for group in self._ingroups[nickname]: | |
223 self.getGroupConversation(group).memberLeft(nickname) | |
224 self._ingroups[nickname]=[] | |
225 else: | |
226 print '*** WARNING: ingroups had no such key %s' % nickname | |
227 | |
228 def irc_NICK(self, prefix, params): | |
229 fromNick = string.split(prefix, "!")[0] | |
230 toNick = params[0] | |
231 if not self._ingroups.has_key(fromNick): | |
232 print "%s changed nick to %s. But she's not in any groups!?" % (from
Nick, toNick) | |
233 return | |
234 for group in self._ingroups[fromNick]: | |
235 self.getGroupConversation(group).memberChangedNick(fromNick, toNick) | |
236 self._ingroups[toNick] = self._ingroups[fromNick] | |
237 del self._ingroups[fromNick] | |
238 | |
239 def irc_unknown(self, prefix, command, params): | |
240 print "unknown message from IRCserver. prefix: %s, command: %s, params:
%s" % (prefix, command, params) | |
241 | |
242 # GTKIM calls | |
243 def joinGroup(self,name): | |
244 self.join(name) | |
245 self.getGroupConversation(name) | |
246 | |
247 class IRCAccount(basesupport.AbstractAccount): | |
248 implements(interfaces.IAccount) | |
249 gatewayType = "IRC" | |
250 | |
251 _groupFactory = IRCGroup | |
252 _personFactory = IRCPerson | |
253 | |
254 def __init__(self, accountName, autoLogin, username, password, host, port, | |
255 channels=''): | |
256 basesupport.AbstractAccount.__init__(self, accountName, autoLogin, | |
257 username, password, host, port) | |
258 self.channels = map(string.strip,string.split(channels,',')) | |
259 if self.channels == ['']: | |
260 self.channels = [] | |
261 | |
262 def _startLogOn(self, chatui): | |
263 logonDeferred = defer.Deferred() | |
264 cc = protocol.ClientCreator(reactor, IRCProto, self, chatui, | |
265 logonDeferred) | |
266 d = cc.connectTCP(self.host, self.port) | |
267 d.addErrback(logonDeferred.errback) | |
268 return logonDeferred | |
OLD | NEW |