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