Mercurial > libervia-backend
annotate src/plugins/plugin_xep_0045.py @ 297:c5554e2939dd
plugin XEP 0277: author for in request + author, updated management for out request
- a workaround is now used to parse "nick" tag (Jappix behaviour)
- author and updated can now be used in data when sendind microblog. Is no author is given, user jid is used, if no updated is given, current timestamp is used
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 18 Feb 2011 22:32:02 +0100 |
parents | 7c79d4a8c9e6 |
children | 5bb1cfc105d0 |
rev | line source |
---|---|
72 | 1 #!/usr/bin/python |
2 # -*- coding: utf-8 -*- | |
3 | |
4 """ | |
5 SAT plugin for managing xep-0045 | |
228 | 6 Copyright (C) 2009, 2010, 2011 Jérôme Poisson (goffi@goffi.org) |
72 | 7 |
8 This program is free software: you can redistribute it and/or modify | |
9 it under the terms of the GNU General Public License as published by | |
10 the Free Software Foundation, either version 3 of the License, or | |
11 (at your option) any later version. | |
12 | |
13 This program is distributed in the hope that it will be useful, | |
14 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
16 GNU General Public License for more details. | |
17 | |
18 You should have received a copy of the GNU General Public License | |
19 along with this program. If not, see <http://www.gnu.org/licenses/>. | |
20 """ | |
21 | |
22 from logging import debug, info, warning, error | |
23 from twisted.words.xish import domish | |
24 from twisted.internet import protocol, defer, threads, reactor | |
25 from twisted.words.protocols.jabber import client, jid, xmlstream | |
26 from twisted.words.protocols.jabber import error as jab_error | |
27 from twisted.words.protocols.jabber.xmlstream import IQ | |
28 import os.path | |
29 import pdb | |
30 | |
31 from zope.interface import implements | |
32 | |
33 from wokkel import disco, iwokkel, muc | |
34 | |
35 from base64 import b64decode | |
36 from hashlib import sha1 | |
37 from time import sleep | |
38 | |
39 try: | |
40 from twisted.words.protocols.xmlstream import XMPPHandler | |
41 except ImportError: | |
42 from wokkel.subprotocols import XMPPHandler | |
43 | |
44 PLUGIN_INFO = { | |
45 "name": "XEP 0045 Plugin", | |
291 | 46 "import_name": "XEP-0045", |
72 | 47 "type": "XEP", |
48 "protocols": ["XEP-0045"], | |
49 "dependencies": [], | |
50 "main": "XEP_0045", | |
51 "handler": "yes", | |
52 "description": _("""Implementation of Multi-User Chat""") | |
53 } | |
54 | |
55 class XEP_0045(): | |
56 | |
57 def __init__(self, host): | |
58 info(_("Plugin XEP_0045 initialization")) | |
59 self.host = host | |
60 self.clients={} | |
61 host.bridge.addMethod("joinMUC", ".communication", in_sign='ssss', out_sign='', method=self.join) | |
78
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
62 host.bridge.addMethod("getRoomJoined", ".communication", in_sign='s', out_sign='a(ssass)', method=self.getRoomJoined) |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
63 host.bridge.addMethod("getRoomSubjects", ".communication", in_sign='s', out_sign='a(sss)', method=self.getRoomSubjects) |
73 | 64 host.bridge.addSignal("roomJoined", ".communication", signature='ssasss') #args: room_id, room_service, room_nicks, user_nick, profile |
74
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
65 host.bridge.addSignal("roomUserJoined", ".communication", signature='sssa{ss}s') #args: room_id, room_service, user_nick, user_data, profile |
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
66 host.bridge.addSignal("roomUserLeft", ".communication", signature='sssa{ss}s') #args: room_id, room_service, user_nick, user_data, profile |
76 | 67 host.bridge.addSignal("roomNewSubject", ".communication", signature='ssss') #args: room_id, room_service, subject, profile |
72 | 68 |
69 def __check_profile(self, profile): | |
75 | 70 """check if profile is used and connected |
71 if profile known but disconnected, remove it from known profiles | |
72 @param profile: profile to check | |
73 @return: True if the profile is known and connected, else False""" | |
72 | 74 if not profile or not self.clients.has_key(profile) or not self.host.isConnected(profile): |
91 | 75 error (_('Unknown or disconnected profile (%s)') % profile) |
72 | 76 if self.clients.has_key(profile): |
77 del self.clients[profile] | |
78 return False | |
79 return True | |
80 | |
81 def __room_joined(self, room, profile): | |
82 """Called when the user is in the requested room""" | |
83 room_jid = room.roomIdentifier+'@'+room.service | |
84 self.clients[profile].joined_rooms[room_jid] = room | |
75 | 85 self.host.bridge.roomJoined(room.roomIdentifier, room.service, [user.nick for user in room.roster.values()], room.nick, profile) |
72 | 86 |
75 | 87 def __err_joining_room(self, failure, profile): |
72 | 88 """Called when something is going wrong when joining the room""" |
183
9ee4a1d0d7fb
Added auto(dis)connect params + misc
Goffi <goffi@goffi.org>
parents:
134
diff
changeset
|
89 mess = _("Error when joining the room") |
9ee4a1d0d7fb
Added auto(dis)connect params + misc
Goffi <goffi@goffi.org>
parents:
134
diff
changeset
|
90 error (mess) |
9ee4a1d0d7fb
Added auto(dis)connect params + misc
Goffi <goffi@goffi.org>
parents:
134
diff
changeset
|
91 self.host.bridge.newAlert(mess, _("Group chat error"), "ERROR", profile) |
72 | 92 |
78
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
93 def getRoomJoined(self, profile_key='@DEFAULT@'): |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
94 """Return room where user is""" |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
95 profile = self.host.memory.getProfileName(profile_key) |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
96 result = [] |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
97 if not self.__check_profile(profile): |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
98 return result |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
99 for room in self.clients[profile].joined_rooms.values(): |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
100 result.append((room.roomIdentifier, room.service, [user.nick for user in room.roster.values()], room.nick)) |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
101 return result |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
102 |
93 | 103 def getRoomNick(self, room_jid, profile_key='@DEFAULT@'): |
104 """return nick used in room by user | |
105 @param room_jid: unicode room id | |
106 @profile_key: profile | |
107 @return: nick or empty string in case of error""" | |
108 profile = self.host.memory.getProfileName(profile_key) | |
109 if not self.__check_profile(profile) or not self.clients[profile].joined_rooms.has_key(room_jid): | |
110 return '' | |
111 return self.clients[profile].joined_rooms[room_jid].nick | |
112 | |
113 | |
78
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
114 def getRoomSubjects(self, profile_key='@DEFAULT@'): |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
115 """Return received subjects of rooms""" |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
116 profile = self.host.memory.getProfileName(profile_key) |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
117 if not self.__check_profile(profile): |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
118 return [] |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
119 return self.clients[profile].rec_subjects.values() |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
120 |
72 | 121 def join(self, service, roomId, nick, profile_key='@DEFAULT@'): |
122 profile = self.host.memory.getProfileName(profile_key) | |
123 if not self.__check_profile(profile): | |
124 return | |
125 room_jid = roomId+'@'+service | |
126 if self.clients[profile].joined_rooms.has_key(room_jid): | |
127 warning(_('%(profile)s is already in room %(room_jid)s') % {'profile':profile, 'room_jid':room_jid}) | |
128 return | |
129 info (_("[%(profile)s] is joining room %(room)s with nick %(nick)s") % {'profile':profile,'room':roomId+'@'+service, 'nick':nick}) | |
220
c5274bf5e18b
plugin xep 0045: workaround for MUCClient exceptions
Goffi <goffi@goffi.org>
parents:
198
diff
changeset
|
130 try: |
c5274bf5e18b
plugin xep 0045: workaround for MUCClient exceptions
Goffi <goffi@goffi.org>
parents:
198
diff
changeset
|
131 self.clients[profile].join(service, roomId, nick).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile':profile}, errbackKeywords={'profile':profile}) |
c5274bf5e18b
plugin xep 0045: workaround for MUCClient exceptions
Goffi <goffi@goffi.org>
parents:
198
diff
changeset
|
132 except: |
c5274bf5e18b
plugin xep 0045: workaround for MUCClient exceptions
Goffi <goffi@goffi.org>
parents:
198
diff
changeset
|
133 #XXX: this is a ugly workaround as MUCClient thrown an error if there is invalid chars in the room jid (like with the default string) |
c5274bf5e18b
plugin xep 0045: workaround for MUCClient exceptions
Goffi <goffi@goffi.org>
parents:
198
diff
changeset
|
134 #FIXME: must be removed when MUCClient manage this better |
c5274bf5e18b
plugin xep 0045: workaround for MUCClient exceptions
Goffi <goffi@goffi.org>
parents:
198
diff
changeset
|
135 self.__err_joining_room(None, profile) |
72 | 136 |
137 def getHandler(self, profile): | |
138 self.clients[profile] = SatMUCClient(self) | |
139 return self.clients[profile] | |
140 | |
141 | |
142 | |
143 class SatMUCClient (muc.MUCClient): | |
144 #implements(iwokkel.IDisco) | |
145 | |
146 def __init__(self, plugin_parent): | |
147 self.plugin_parent = plugin_parent | |
148 self.host = plugin_parent.host | |
149 muc.MUCClient.__init__(self) | |
78
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
150 self.joined_rooms = {} |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
151 self.rec_subjects = {} |
72 | 152 print "init SatMUCClient OK" |
153 | |
154 def receivedGroupChat(self, room, user, body): | |
155 debug('receivedGroupChat: room=%s user=%s body=%s', room, user, body) | |
156 | |
74
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
157 def userJoinedRoom(self, room, user): |
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
158 debug (_("user %(nick)s has joined room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()}) |
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
159 user_data={'entity':user.entity or '', 'affiliation':user.affiliation, 'role':user.role} |
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
160 self.host.bridge.roomUserJoined(room.roomIdentifier, room.service, user.nick, user_data, self.parent.profile) |
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
161 |
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
162 def userLeftRoom(self, room, user): |
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
163 debug (_("user %(nick)s left room (%(room_id)s)") % {'nick':user.nick, 'room_id':room.occupantJID.userhost()}) |
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
164 user_data={'entity':user.entity or '', 'affiliation':user.affiliation, 'role':user.role} |
6e3a06b4dd36
plugin xep-0045: added roomUserJoined and roomUserLeft signals
Goffi <goffi@goffi.org>
parents:
73
diff
changeset
|
165 self.host.bridge.roomUserLeft(room.roomIdentifier, room.service, user.nick, user_data, self.parent.profile) |
72 | 166 |
77
1ae680f9682e
wix: MUC groupchat management + short nick shown in chat window instead of full jid when possible
Goffi <goffi@goffi.org>
parents:
76
diff
changeset
|
167 def userUpdatedStatus(self, room, user, show, status): |
1ae680f9682e
wix: MUC groupchat management + short nick shown in chat window instead of full jid when possible
Goffi <goffi@goffi.org>
parents:
76
diff
changeset
|
168 print("FIXME: MUC status not managed yet") |
1ae680f9682e
wix: MUC groupchat management + short nick shown in chat window instead of full jid when possible
Goffi <goffi@goffi.org>
parents:
76
diff
changeset
|
169 #FIXME: gof |
1ae680f9682e
wix: MUC groupchat management + short nick shown in chat window instead of full jid when possible
Goffi <goffi@goffi.org>
parents:
76
diff
changeset
|
170 |
198
3d7a06fe3997
plugin XEP-0045: fixed receivedSubject
Goffi <goffi@goffi.org>
parents:
183
diff
changeset
|
171 def receivedSubject(self, occupantJID, subject): |
3d7a06fe3997
plugin XEP-0045: fixed receivedSubject
Goffi <goffi@goffi.org>
parents:
183
diff
changeset
|
172 room = self._getRoom(occupantJID) |
76 | 173 debug (_("New subject for room (%(room_id)s): %(subject)s") % {'room_id':room.occupantJID.userhost(),'subject':subject}) |
78
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
174 room_jid = room.roomIdentifier+'@'+room.service |
ace2af8abc5a
Added method to know which MUC are joined, and which subjects were received.
Goffi <goffi@goffi.org>
parents:
77
diff
changeset
|
175 self.rec_subjects[room_jid] = (room.roomIdentifier, room.service, subject) |
76 | 176 self.host.bridge.roomNewSubject(room.roomIdentifier, room.service, subject, self.parent.profile) |
177 | |
72 | 178 #def connectionInitialized(self): |
179 #pass | |
180 | |
181 #def getDiscoInfo(self, requestor, target, nodeIdentifier=''): | |
182 #return [disco.DiscoFeature(NS_VCARD)] | |
183 | |
184 #def getDiscoItems(self, requestor, target, nodeIdentifier=''): | |
185 #return [] | |
186 |