comparison plugins/plugin_xep_0045.py @ 72:f271fff3a713

MUC implementation: first draft /!\ the experimental muc branche of wokkel must be used - bridge: new roomJoined signal - wix: contact list widget is now in a separate file, and manage different kinds of presentation - wix: chat window now manage group chat (first draft, not working yet) - wix: constants are now in a separate class, so then can be accessible from everywhere - wix: new menu to join room (do nothing yet, except entering in a test room) - new plugin for xep 0045 (MUC), use wokkel experimental MUC branch - plugins: the profile is now given for get_handler, cause it can be used internally by a plugin (e.g.: xep-0045 plugin)
author Goffi <goffi@goffi.org>
date Sun, 21 Mar 2010 10:28:55 +1100
parents
children 9d113b5471e6
comparison
equal deleted inserted replaced
71:efe81b61673c 72:f271fff3a713
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 """
5 SAT plugin for managing xep-0045
6 Copyright (C) 2009, 2010 Jérôme Poisson (goffi@goffi.org)
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 AVATAR_PATH = "/avatars"
45
46 IQ_GET = '/iq[@type="get"]'
47 NS_VCARD = 'vcard-temp'
48 VCARD_REQUEST = IQ_GET + '/vCard[@xmlns="' + NS_VCARD + '"]' #TODO: manage requests
49
50 PRESENCE = '/presence'
51 NS_VCARD_UPDATE = 'vcard-temp:x:update'
52 VCARD_UPDATE = PRESENCE + '/x[@xmlns="' + NS_VCARD_UPDATE + '"]'
53
54 PLUGIN_INFO = {
55 "name": "XEP 0045 Plugin",
56 "import_name": "XEP_0045",
57 "type": "XEP",
58 "protocols": ["XEP-0045"],
59 "dependencies": [],
60 "main": "XEP_0045",
61 "handler": "yes",
62 "description": _("""Implementation of Multi-User Chat""")
63 }
64
65 class XEP_0045():
66
67 def __init__(self, host):
68 info(_("Plugin XEP_0045 initialization"))
69 self.host = host
70 self.clients={}
71 host.bridge.addMethod("joinMUC", ".communication", in_sign='ssss', out_sign='', method=self.join)
72
73 def __check_profile(self, profile):
74 if not profile or not self.clients.has_key(profile) or not self.host.isConnected(profile):
75 error (_('Unknown or disconnected profile'))
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 print "room joined (profile = %s)" % profile
84 room_jid = room.roomIdentifier+'@'+room.service
85 self.clients[profile].joined_rooms[room_jid] = room
86 self.host.bridge.roomJoined(room.roomIdentifier, room.service, room.roster.keys(), room.nick, profile)
87
88 def __err_joining_room(self, failure, profile): #, profile):
89 """Called when something is going wrong when joining the room"""
90 error ("Error when joining the room")
91 pdb.set_trace()
92
93 def join(self, service, roomId, nick, profile_key='@DEFAULT@'):
94 profile = self.host.memory.getProfileName(profile_key)
95 if not self.__check_profile(profile):
96 return
97 room_jid = roomId+'@'+service
98 if self.clients[profile].joined_rooms.has_key(room_jid):
99 warning(_('%(profile)s is already in room %(room_jid)s') % {'profile':profile, 'room_jid':room_jid})
100 return
101 info (_("[%(profile)s] is joining room %(room)s with nick %(nick)s") % {'profile':profile,'room':roomId+'@'+service, 'nick':nick})
102 self.clients[profile].join(service, roomId, nick).addCallbacks(self.__room_joined, self.__err_joining_room, callbackKeywords={'profile':profile}, errbackKeywords={'profile':profile})
103
104 def getHandler(self, profile):
105 #reactor.callLater(15,self.join,"conference.necton2.int", "test", "Goffi \o/", profile)
106 self.clients[profile] = SatMUCClient(self)
107 return self.clients[profile]
108
109
110
111 class SatMUCClient (muc.MUCClient):
112 #implements(iwokkel.IDisco)
113
114 def __init__(self, plugin_parent):
115 self.plugin_parent = plugin_parent
116 self.host = plugin_parent.host
117 muc.MUCClient.__init__(self)
118 self.joined_rooms = {} #FIXME gof: check if necessary
119 print "init SatMUCClient OK"
120
121 def receivedGroupChat(self, room, user, body):
122 debug('receivedGroupChat: room=%s user=%s body=%s', room, user, body)
123
124
125 #def connectionInitialized(self):
126 #pass
127
128 #def getDiscoInfo(self, requestor, target, nodeIdentifier=''):
129 #return [disco.DiscoFeature(NS_VCARD)]
130
131 #def getDiscoItems(self, requestor, target, nodeIdentifier=''):
132 #return []
133