dreamIRC initial check-in
[enigma2-plugins.git] / dreamirc / src / ircsupport.py
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 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
17
18
19 class IRCPerson(e2support.AbstractPerson):
20
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)
25
26     ### interface impl
27
28     def isOnline(self):
29         return ONLINE
30
31     def getStatus(self):
32         return ONLINE
33
34     def setStatus(self,status):
35         self.status=status
36         self.chat.getContactsList().setContactStatus(self)
37
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)])
44             else:
45                 self.account.client.msg(self.name, line)
46         return succeed(text)
47
48     def bye(self):
49         if self.account.client is None:
50             print "not connected"
51         else:
52                   self.account.client.quit("user logged off")             
53
54
55 class IRCGroup(e2support.AbstractGroup):
56
57     implements(interfaces.IGroup)
58
59     def imgroup_testAction(self):
60         print 'action test!'
61
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))
68
69     ### Interface Implementation
70
71     def setTopic(self, topic):
72         if self.account.client is None:
73             raise locals.OfflineError
74         self.account.client.topic(self.name, topic)
75
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)
81             return succeed(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)
85         return succeed(text)
86
87     def leave(self):
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)
92         
93     def bye(self):
94         if self.account.client is None:
95             print "not connected"
96         else:
97                         self.account.client.quit("user logged off")       
98
99
100 class IRCProto(e2support.AbstractClientMixin, irc.IRCClient):
101     def __init__(self, account, chatui, logonDeferred=None):
102         e2support.AbstractClientMixin.__init__(self, account, chatui,
103                                                  logonDeferred)
104         self._namreplies={}
105         self._ingroups={}
106         self._groups={}
107         self._topics={}
108
109     def getGroupConversation(self, name, hide=0):
110         name=string.lower(name)
111         return self.chat.getGroupConversation(self.chat.getGroup(name, self),
112                                               stayHidden=hide)
113
114     def getPerson(self,name):
115         return self.chat.getPerson(name, self)
116
117     def connectionMade(self):
118         # XXX: Why do I duplicate code in IRCClient.register?
119         try:
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()
133         except:
134             import traceback
135             traceback.print_exc()
136
137     def setNick(self,nick):
138         self.name=nick
139         self.accountName="%s (IRC)"%nick
140         irc.IRCClient.setNick(self,nick)
141         
142     def quit(self,message='bye bye'):
143 #         self.quit_str=str("QUIT :%s" % message)
144          self.sendLine("QUIT :%s" % message)
145
146     def kickedFrom(self, channel, kicker, message):
147         """Called when I am kicked from a channel.
148         """
149         print 'wow i was kicked', channel, kicker, message
150         return self.chat.getGroupConversation(
151             self.chat.getGroup(channel[1:], self), 1)
152
153     def userKicked(self, kickee, channel, kicker, message):
154         print 'whew somebody else', kickee, channel, kicker, message
155
156     def noticed(self, username, channel, message):
157         self.privmsg(username, channel, message, {"dontAutoRespond": 1})
158
159     def privmsg(self, username, channel, message, metadata=None):
160         if metadata is None:
161             metadata = {}
162         username=string.split(username,'!',1)[0]
163         if username==self.name: return
164         if channel[0]=='#':
165             group=channel[1:]
166             self.getGroupConversation(group).showGroupMessage(username, message, metadata)
167             return
168         self.chat.getConversation(self.getPerson(username)).showMessage(message, metadata)
169
170     def action(self,username,channel,emote):
171         username=string.split(username,'!',1)[0]
172         if username==self.name: return
173         meta={'style':'emote'}
174         if channel[0]=='#':
175             group=channel[1:]
176             self.getGroupConversation(group).showGroupMessage(username, emote, meta)
177             return
178         self.chat.getConversation(self.getPerson(username)).showMessage(emote,meta)
179
180     def irc_RPL_NAMREPLY(self,prefix,params):
181         """
182         RPL_NAMREPLY
183         >> NAMES #bnl
184         << :Arlington.VA.US.Undernet.Org 353 z3p = #bnl :pSwede Dan-- SkOyg AG
185         """
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:
195                 try:
196                     self._ingroups[nickname].append(group)
197                 except:
198                     self._ingroups[nickname]=[group]
199
200     def irc_RPL_ENDOFNAMES(self,prefix,params):
201         group=params[1][1:]
202         self.getGroupConversation(group).setGroupMembers(self._namreplies[string.lower(group)])
203         del self._namreplies[string.lower(group)]
204
205     def irc_RPL_TOPIC(self,prefix,params):
206         self._topics[params[1][1:]]=params[2]
207
208     def irc_333(self,prefix,params):
209         group=params[1][1:]
210         self.getGroupConversation(group).setTopic(self._topics[group],params[2])
211         del self._topics[group]
212
213     def irc_TOPIC(self,prefix,params):
214         nickname = string.split(prefix,"!")[0]
215         group = params[0][1:]
216         topic = params[1]
217         self.getGroupConversation(group).setTopic(topic,nickname)
218
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:
223             try:
224                 self._ingroups[nickname].append(group)
225             except:
226                 self._ingroups[nickname]=[group]
227             self.getGroupConversation(group).memberJoined(nickname)
228
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)
236             else:
237                 print "%s left %s, but wasn't in the room."%(nickname,group)
238
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]=[]
245         else:
246             print '*** WARNING: ingroups had no such key %s' % nickname
247
248     def irc_NICK(self, prefix, params):
249         fromNick = string.split(prefix, "!")[0]
250         toNick = params[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)
253             return
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]
258
259     def irc_unknown(self, prefix, command, params):
260         print "unknown message from IRCserver. prefix: %s, command: %s, params: %s" % (prefix, command, params)
261
262     # GTKIM calls
263     def joinGroup(self,name):
264         self.join(name)
265         self.getGroupConversation(name)
266
267 class IRCAccount(e2support.AbstractAccount):
268     implements(interfaces.IAccount)
269     gatewayType = "IRC"
270
271     _groupFactory = IRCGroup
272     _personFactory = IRCPerson
273
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 == ['']:
278             self.channels = []
279
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)
285         return logonDeferred
286