Initial import to Tizen
[profile/ivi/python-twisted.git] / twisted / words / im / ircsupport.py
1 # Copyright (c) Twisted Matrix Laboratories.
2 # See LICENSE for details.
3
4 """
5 IRC support for Instance Messenger.
6 """
7
8 import string
9
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 basesupport, interfaces, locals
15 from zope.interface import implements
16
17
18 class IRCPerson(basesupport.AbstractPerson):
19
20     def imperson_whois(self):
21         if self.account.client is None:
22             raise locals.OfflineError
23         self.account.client.sendLine("WHOIS %s" % self.name)
24
25     ### interface impl
26
27     def isOnline(self):
28         return ONLINE
29
30     def getStatus(self):
31         return ONLINE
32
33     def setStatus(self,status):
34         self.status=status
35         self.chat.getContactsList().setContactStatus(self)
36
37     def sendMessage(self, text, meta=None):
38         if self.account.client is None:
39             raise locals.OfflineError
40         for line in string.split(text, '\n'):
41             if meta and meta.get("style", None) == "emote":
42                 self.account.client.ctcpMakeQuery(self.name,[('ACTION', line)])
43             else:
44                 self.account.client.msg(self.name, line)
45         return succeed(text)
46
47 class IRCGroup(basesupport.AbstractGroup):
48
49     implements(interfaces.IGroup)
50
51     def imgroup_testAction(self):
52         pass
53
54     def imtarget_kick(self, target):
55         if self.account.client is None:
56             raise locals.OfflineError
57         reason = "for great justice!"
58         self.account.client.sendLine("KICK #%s %s :%s" % (
59             self.name, target.name, reason))
60
61     ### Interface Implementation
62
63     def setTopic(self, topic):
64         if self.account.client is None:
65             raise locals.OfflineError
66         self.account.client.topic(self.name, topic)
67
68     def sendGroupMessage(self, text, meta={}):
69         if self.account.client is None:
70             raise locals.OfflineError
71         if meta and meta.get("style", None) == "emote":
72             self.account.client.me(self.name,text)
73             return succeed(text)
74         #standard shmandard, clients don't support plain escaped newlines!
75         for line in string.split(text, '\n'):
76             self.account.client.say(self.name, line)
77         return succeed(text)
78
79     def leave(self):
80         if self.account.client is None:
81             raise locals.OfflineError
82         self.account.client.leave(self.name)
83         self.account.client.getGroupConversation(self.name,1)
84
85
86 class IRCProto(basesupport.AbstractClientMixin, irc.IRCClient):
87     def __init__(self, account, chatui, logonDeferred=None):
88         basesupport.AbstractClientMixin.__init__(self, account, chatui,
89                                                  logonDeferred)
90         self._namreplies={}
91         self._ingroups={}
92         self._groups={}
93         self._topics={}
94
95     def getGroupConversation(self, name, hide=0):
96         name=string.lower(name)
97         return self.chat.getGroupConversation(self.chat.getGroup(name, self),
98                                               stayHidden=hide)
99
100     def getPerson(self,name):
101         return self.chat.getPerson(name, self)
102
103     def connectionMade(self):
104         # XXX: Why do I duplicate code in IRCClient.register?
105         try:
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" % (
110                 self.account.username,))
111             for channel in self.account.channels:
112                 self.joinGroup(channel)
113             self.account._isOnline=1
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         """
128         Called when I am kicked from a channel.
129         """
130         return self.chat.getGroupConversation(
131             self.chat.getGroup(channel[1:], self), 1)
132
133     def userKicked(self, kickee, channel, kicker, message):
134         pass
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, meta)
157             return
158         self.chat.getConversation(self.getPerson(username)).showMessage(emote,meta)
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
217     def irc_QUIT(self,prefix,params):
218         nickname=string.split(prefix,"!")[0]
219         if self._ingroups.has_key(nickname):
220             for group in self._ingroups[nickname]:
221                 self.getGroupConversation(group).memberLeft(nickname)
222             self._ingroups[nickname]=[]
223
224     def irc_NICK(self, prefix, params):
225         fromNick = string.split(prefix, "!")[0]
226         toNick = params[0]
227         if not self._ingroups.has_key(fromNick):
228             return
229         for group in self._ingroups[fromNick]:
230             self.getGroupConversation(group).memberChangedNick(fromNick, toNick)
231         self._ingroups[toNick] = self._ingroups[fromNick]
232         del self._ingroups[fromNick]
233
234     def irc_unknown(self, prefix, command, params):
235         pass
236
237     # GTKIM calls
238     def joinGroup(self,name):
239         self.join(name)
240         self.getGroupConversation(name)
241
242 class IRCAccount(basesupport.AbstractAccount):
243     implements(interfaces.IAccount)
244     gatewayType = "IRC"
245
246     _groupFactory = IRCGroup
247     _personFactory = IRCPerson
248
249     def __init__(self, accountName, autoLogin, username, password, host, port,
250                  channels=''):
251         basesupport.AbstractAccount.__init__(self, accountName, autoLogin,
252                                              username, password, host, port)
253         self.channels = map(string.strip,string.split(channels,','))
254         if self.channels == ['']:
255             self.channels = []
256
257     def _startLogOn(self, chatui):
258         logonDeferred = defer.Deferred()
259         cc = protocol.ClientCreator(reactor, IRCProto, self, chatui,
260                                     logonDeferred)
261         d = cc.connectTCP(self.host, self.port)
262         d.addErrback(logonDeferred.errback)
263         return logonDeferred