source: indico/indico/MaKaC/plugins/InstantMessaging/XMPP/components.py @ 9264b3

hello-world-walkthroughipv6v0.98-seriesv0.98.2v0.98.3v0.98b2v0.99v1.0v1.1
Last change on this file since 9264b3 was 9264b3, checked in by Jose Benito <jose.benito.gonzalez@…>, 2 years ago

[REF] indico.core.api to indico.core.extpoint

  • Property mode set to 100644
File size: 14.5 KB
Line 
1# -*- coding: utf-8 -*-
2##
3##
4## This file is part of CDS Indico.
5## Copyright (C) 2002, 2003, 2004, 2005, 2006, 2007 CERN.
6##
7## CDS Indico is free software; you can redistribute it and/or
8## modify it under the terms of the GNU General Public License as
9## published by the Free Software Foundation; either version 2 of the
10## License, or (at your option) any later version.
11##
12## CDS Indico is distributed in the hope that it will be useful, but
13## WITHOUT ANY WARRANTY; without even the implied warranty of
14## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15## General Public License for more details.
16##
17## You should have received a copy of the GNU General Public License
18## along with CDS Indico; if not, write to the Free Software Foundation, Inc.,
19## 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
20
21from MaKaC.plugins.InstantMessaging.notificationComponents import IInstantMessagingListener
22from MaKaC.plugins.base import Observable, PluginsHolder
23from MaKaC.plugins.util import PluginsWrapper, PluginFieldsWrapper
24from MaKaC.plugins.InstantMessaging.XMPP.helpers import GeneralLinkGenerator
25from MaKaC.plugins.helpers import DBHelpers, MailHelper
26from MaKaC.plugins.InstantMessaging.indexes import IndexByConf, IndexByCRName, IndexByID, IndexByUser
27from MaKaC.plugins.InstantMessaging import urlHandlers
28from MaKaC.i18n import _
29from MaKaC.conference import ConferenceHolder
30from MaKaC.common.contextManager import ContextManager
31from MaKaC.common.externalOperationsManager import ExternalOperationsManager
32from MaKaC.common.mail import GenericMailer
33from MaKaC.common.info import HelperMaKaCInfo
34from MaKaC.webinterface import wcomponents
35from MaKaC.webinterface.mail import GenericNotification
36from MaKaC.services.interface.rpc.common import ServiceError, NoReportError
37import zope.interface
38
39from indico.core.extpoint import Component
40from indico.core.extpoint.conference import INavigationContributor
41
42
43class ChatSMContributor(Component, Observable):
44
45    zope.interface.implements(INavigationContributor)
46
47    """ChatSideMenuContributor. Fills the side menu of the conference's management menu when
48    the chat plugin is active"""
49
50    @classmethod
51    def fillManagementSideMenu(cls, obj, params={}):
52        params['Instant Messaging'] = wcomponents.SideMenuItem(_("Chat Rooms"),
53                                                               urlHandlers.UHConfModifChat.getURL( obj._conf ))
54
55    @classmethod
56    def getActiveNavigationItem(cls, obj, params={}):
57        pass
58
59    @classmethod
60    def confDisplaySMFillDict(cls, obj, params):
61        sideMenuItemsDict = params['dict']
62        conf = params['conf']
63
64        sideMenuItemsDict["instantMessaging"] =  { \
65                "caption": _("Chat Rooms"), \
66                "URL": str(urlHandlers.UHConferenceInstantMessaging.getURL(conf)), \
67                "staticURL": "", \
68                "parent": ""}
69
70    @classmethod
71    def confDisplaySMFillOrderedKeys(cls, obj, list):
72        list.append("instantMessaging")
73
74
75    @classmethod
76    def confDisplaySMShow(cls, obj, params):
77        obj._instantMessaging = obj._sectionMenu.getLinkByName("instantMessaging")
78        if not DBHelpers.roomsToShow(obj._conf):
79            obj._instantMessaging.setVisible(False)
80
81
82    @classmethod
83    def meetingAndLectureDisplay(cls, obj, params):
84        out = params['out']
85        conf = params['conf']
86        if DBHelpers.roomsToShow(conf):
87            linksList = PluginsHolder().getPluginType('InstantMessaging').getOption('customLinks').getValue()
88            out.openTag("chatrooms")
89            for chatroom in DBHelpers.getShowableRooms(conf):
90                out.openTag("chatroom")
91
92                out.writeTag("id", chatroom.getId())
93                out.writeTag("name", chatroom.getTitle())
94                out.writeTag("server", 'conference.' + chatroom.getHost() if chatroom.getCreatedInLocalServer() else chatroom.getHost())
95                out.writeTag("description", chatroom.getDescription())
96                out.writeTag("reqPassword", _('Yes') if chatroom.getPassword() else _('No'))
97                out.writeTag("showPassword", chatroom.getShowPass())
98                out.writeTag("password", chatroom.getPassword())
99                out.writeTag("createdInLocalServer", chatroom.getCreatedInLocalServer())
100                out.openTag("links")
101                if linksList.__len__() > 0:
102                    out.writeTag("linksToShow", 'true')
103                else:
104                    out.writeTag("linksToShow", 'false')
105
106                for link in linksList:
107                    out.openTag("customLink")
108                    out.writeTag("name", link['name'])
109                    out.writeTag("structure", GeneralLinkGenerator(chatroom, link['structure']).generate())
110                    out.closeTag("customLink")
111
112                out.closeTag("links")
113                out.closeTag("chatroom")
114            out.closeTag("chatrooms")
115
116            out.writeTag("how2connect", PluginFieldsWrapper('InstantMessaging', 'XMPP').getOption('ckEditor'))
117
118    @classmethod
119    def addCheckBox2CloneConf(cls, obj, list):
120        """ we show the clone checkbox if:
121            * The XMPP Plugin is active.
122            * There are rooms in the event created by the user who wants to clone
123        """
124        #list of creators of the chat rooms
125        ownersList = [cr.getOwner() for cr in DBHelpers().getChatroomList(obj._conf)]
126        if PluginsWrapper('InstantMessaging', 'XMPP').isActive() and obj._rh._aw._currentUser in ownersList:
127            list['cloneOptions'] += _("""<li><input type="checkbox" name="cloneChatrooms" id="cloneChatrooms" value="1" />_("Chat Rooms")</li>""")
128
129    @classmethod
130    def fillCloneDict(self, obj, params):
131        options = params['options']
132        paramNames = params['paramNames']
133        options['chatrooms'] = 'cloneChatrooms' in paramNames
134
135    @classmethod
136    def cloneEvent(cls, confToClone, params):
137        """ we'll clone only the chat rooms created by the user who is cloning the conference """
138        conf = params['conf']
139        user = params['user']
140        options = params['options']
141        ContextManager.getdefault('mailHelper', MailHelper())
142
143        if options.get("chatrooms", True):
144            crList = DBHelpers().getChatroomList(confToClone)
145            ownersList = [cr.getOwner() for cr in crList]
146            if PluginsWrapper('InstantMessaging', 'XMPP').isActive():
147                 for cr in crList:
148                     if user is cr.getOwner():
149                         cls()._notify('addConference2Room', {'room':cr, 'conf':conf.getId()})
150
151        ContextManager.get('mailHelper').sendMails()
152
153
154class ChatroomStorage(Component):
155    zope.interface.implements(IInstantMessagingListener)
156
157    def __init__(self):
158        #it's the first thing to do when having these events
159        self.priority=1
160
161    @classmethod
162    def createChatroom(cls, obj, params):
163        """ Inserts the object in the database according to all the kind of indexing types, in this case:
164        -Chat rooms by conference
165        -Chat rooms by user
166        -Chat rooms by name (to check if there's already a chat room with that name in our XMPP server)
167        -Chat rooms by ID (to access faster to the object when querying)
168        """
169        room = params['room']
170
171        conference = params['conference']
172
173        # index by conference id
174        confIndex = IndexByConf()
175        room.setId(DBHelpers.newID())
176        confIndex.index(conference.getId(), room)
177
178        # Index by chat room's name
179        crNameIndex = IndexByCRName()
180        crNameIndex.index(room)
181
182        # Index by id
183        idIndex = IndexByID()
184        idIndex.index(room)
185
186        # Index by room creator
187        userIndex = IndexByUser()
188        userIndex.index(room.getOwner().getId(), room)
189
190    @classmethod
191    def editChatroom(self, obj, params):
192        oldTitle = params['oldTitle']
193        newRoom = params['newRoom']
194        #we have an index by the chat room name. If, while editing, someone changes the chat room name, we'll have to update the index
195        if oldTitle != newRoom.getTitle():
196            #the title has been changed. Get rid of the old index and substitute it for the new one
197            crNameIndex = IndexByCRName()
198            crNameIndex.unindex(newRoom, oldTitle)
199            crNameIndex.index(newRoom)
200
201    @classmethod
202    def deleteChatroom(cls, obj, params):
203        """ Deletes the chat room in the database according to all kind of indexing types"""
204
205        chatroom = params['room']
206
207        confId = obj._conferenceID
208        #if we have the same room used in two or more different conferences, we just delete it from the
209        #conferences list in the chat room and from the IndexByConf index
210        chatroom.getConferences().pop(confId)
211        confIndex = IndexByConf()
212        confIndex.unindex(confId, chatroom)
213
214        if len(chatroom.getConferences()) is 0:
215            #there are no more references to the chat room, we completely delete it
216            crNameIndex = IndexByCRName()
217            crNameIndex.unindex(chatroom)
218
219            idIndex = IndexByID()
220            idIndex.unindex(chatroom)
221
222            userIndex = IndexByUser()
223            userIndex.unindex(chatroom.getOwner().getId(), chatroom)
224
225    @classmethod
226    def addConference2Room(cls, obj, params):
227        """ When we re use a chat room for another conference(s), this is the method called.
228            It may be called from the AJAX service, but also from the clone event. Since we
229            don't know it, we have to check the parameters accordingly"""
230        room = params['room']
231        confId = params['conf']
232
233        confIndex = IndexByConf()
234        confIndex.index(confId, room)
235
236
237class ChatroomMailer(Component):
238    """ Sends emails to the administrators when a chat room related event happens"""
239
240    zope.interface.implements(IInstantMessagingListener)
241
242    @classmethod
243    def createChatroom(cls, obj, params):
244        room = params['room']
245        # we give this operation the name createSomething in the externaloperationsmanager
246        # we will execute the method performOperation in a chat room creation, which will send an email to all the requested users
247        # saying that a chat room was created. We pass the 2 mandatory arguments and finally the arguments required for performOperation
248        # (in this case, only one argument)
249        ExternalOperationsManager.execute(cls, "create_"+str(cls.__class__)+str(room.getId()), cls.performOperation, 'create', room.getConferences().values()[0], room, room)
250
251    @classmethod
252    def editChatroom(cls, obj, params):
253        room = params['newRoom']
254        conf = ConferenceHolder().getById(obj._conferenceID)
255        ExternalOperationsManager.execute(cls, "edit_"+str(cls.__class__)+str(room.getId()), cls.performOperation, 'edit', conf, room, room, conf)
256
257    @classmethod
258    def deleteChatroom(cls, obj, params):
259        room = params['room']
260        conf = ConferenceHolder().getById(obj._conferenceID)
261        ExternalOperationsManager.execute(cls, "delete_"+str(cls.__class__)+str(room.getId()), cls.performOperation, 'delete', conf, room, room, conf)
262
263    @classmethod
264    def addConference2Room(cls, obj, params):
265        room = params['room']
266        conf = ConferenceHolder().getById(params['conf'])
267        #without the number added it would only send 1 mail, because for every new chat room it'd think that there has been a retry
268        ExternalOperationsManager.execute(cls, "add_"+str(cls.__class__)+str(room.getId()), cls.performOperation, 'create', conf, room, room, conf)
269
270    @classmethod
271    def performOperation(cls, operation, conf, room, *args):
272        """ The 4 operations of this class are quite the same, so we pass the name of the operation, the conference they belong to,
273            the chat room for which we are creating the operation and, finally, a list of the arguments needed for the operation"""
274
275        # get the list of users that will receive emails
276        pf = PluginFieldsWrapper('InstantMessaging', 'XMPP')
277        userList = list(pf.getOption('additionalEmails'))
278        if pf.getOption('sendMailNotifications'):
279            userList.extend( [user.getEmail() for user in pf.getOption('admins')] )
280        if not len(userList) is 0:
281            try:
282                cn = ChatroomsNotification(room, userList)
283                ContextManager.get('mailHelper').newMail(GenericMailer.sendAndLog, getattr(cn, operation)(*args), \
284                                         conf, \
285                                         "MaKaC/plugins/InstantMessaging/XMPP/components.py", \
286                                         room.getOwner())
287            except Exception, e:
288                raise ServiceError(message=_('There was an error while contacting the mail server. No notifications were sent: %s'%e))
289
290
291class ChatroomsNotification(GenericNotification):
292    """ Template to build an email notification for a given chat room. """
293
294    def __init__(self, room, userList):
295        GenericNotification.__init__(self)
296        self.setFromAddr("Indico Mailer<%s>"%HelperMaKaCInfo.getMaKaCInfoInstance().getSupportEmail())
297        self.setToList(userList)
298
299    def create(self, room, conference=None):
300        """ If conference is None it means we're creating the chat room for the first time
301        if not it means we're re-using an existing chat room """
302        if conference is None:
303            conference = room.getConferences().values()[0]
304        self.setSubject("[Indico] [IM] Chat room created in conference %s: %s" % (conference.getId(), room.getTitle()))
305        self.setBody("""    Dear Indico user,
306The chat room with name %s has been successfully created in the conference %s (id: %s)
307by the user %s.
308
309Thank you for using our system.""" %(room.getTitle(), conference.getTitle(), conference.getId(), room.getOwner().getFullName()))
310        return self
311
312    def edit(self, room, conference):
313        self.setSubject("[Indico] [IM] Chat room edited in conference %s: %s" % (conference.getId(), room.getTitle()))
314        self.setBody("""    Dear Indico user,
315The chat room with name %s has been successfully edited in the conference %s (id: %s)
316by the user %s.
317
318Thank you for using our system.""" %(room.getTitle(), conference.getTitle(), conference.getId(), room.getOwner().getFullName()))
319        return self
320
321    def delete(self, room, conference):
322        self.setSubject("[Indico] [IM] Chat room deleted in conference %s: %s" % (conference.getId(), room.getTitle()))
323        self.setBody("""    Dear Indico user,
324The chat room with name %s has been successfully deleted from the conference %s (id: %s)
325by the user %s.
326
327Thank you for using our system.""" %(room.getTitle(), conference.getTitle(), conference.getId(), room.getOwner().getFullName()))
328        return self
Note: See TracBrowser for help on using the repository browser.