source: indico/indico/MaKaC/plugins/Collaboration/EVO/collaboration.py @ d3cb3f

burotelhello-world-walkthroughipv6new-webexv0.97-seriesv0.98-seriesv0.98.2v0.98.3v0.98b1v0.98b2v0.99v1.0v1.1
Last change on this file since d3cb3f was d3cb3f, checked in by Jose Benito <jose.benito.gonzalez@…>, 3 years ago

[FIX] Status message was stored transalted

  • Property mode set to 100644
File size: 20.9 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 datetime import timedelta
22from MaKaC.common.PickleJar import Retrieves
23from MaKaC.common.utils import formatDateTime
24from MaKaC.common.timezoneUtils import nowutc, unixTimeToDatetime
25from MaKaC.plugins.Collaboration.base import CSBookingBase
26from MaKaC.plugins.Collaboration.EVO.common import EVOControlledException, getEVOAnswer, parseEVOAnswer, EVOException, \
27    getMinStartDate, getMaxEndDate, OverlappedError, EVOError, ChangesFromEVOError, getRequestURL, EVOWarning, getEVOOptionValueByName
28from MaKaC.plugins.Collaboration.EVO.mail import NewEVOMeetingNotificationAdmin, EVOMeetingModifiedNotificationAdmin, EVOMeetingRemovalNotificationAdmin
29#    NewEVOMeetingNotificationManager, EVOMeetingModifiedNotificationManager,\
30#    EVOMeetingRemovalNotificationManager
31from MaKaC.common.mail import GenericMailer
32from MaKaC.common.logger import Logger
33from MaKaC.i18n import _
34from MaKaC.plugins.Collaboration.collaborationTools import MailTools
35from MaKaC.plugins.Collaboration.EVO.fossils import ICSBookingConfModifFossil,\
36    ICSBookingIndexingFossil
37from MaKaC.common.fossilize import fossilizes
38
39class CSBooking(CSBookingBase): #already Fossilizable
40    fossilizes(ICSBookingConfModifFossil, ICSBookingIndexingFossil)
41
42    _hasTitle = True
43    _hasStart = True
44    _hasStop = False
45    _hasCheckStatus = True
46
47    _requiresServerCallForStart = True
48    _requiresClientCallForStart = True
49
50    _needsBookingParamsCheck = True
51    _needsToBeNotifiedOnView = True
52
53    _hasEventDisplay = True
54
55    _commonIndexes = ["All Videoconference"]
56
57    _simpleParameters = {
58        "communityId": (str, ''),
59        "meetingTitle": (str, ''),
60        "meetingDescription": (str, None),
61        "sendMailToManagers": (bool, False),
62        "type": (int, 0),
63        "displayPhoneBridgeId": (bool, True),
64        "displayPassword": (bool, False),
65        "displayPhonePassword": (bool, False),
66        "displayPhoneBridgeNumbers": (bool, True),
67        "displayURL": (bool, True)}
68
69    _complexParameters = ["communityName", "accessPassword", "hasAccessPassword"]
70
71    def __init__(self, type, conf):
72        CSBookingBase.__init__(self, type, conf)
73        self._accessPassword = None
74        self._EVOID = None
75        self._url = None
76        self._phoneBridgeId = None
77        self._phoneBridgePassword = None
78
79        self._created = False
80        self._error = False
81        self._errorMessage = None
82        self._errorDetails = None
83        self._changesFromEVO = []
84
85        self._lastCheck = nowutc()
86        self._checksDone = []
87
88    def getCommunityName(self):
89        try:
90            return self.getPluginOptionByName("communityList").getValue()[self._bookingParams["communityId"]]
91        except KeyError:
92            return _("Non-existant community")
93
94    def getAccessPassword(self):
95        """ This method returns the access password that will be displayed in the indico page
96        """
97        if self._accessPassword is None:
98            return ""
99        else:
100            return self._accessPassword
101
102    def setAccessPassword(self, accessPassword):
103        if accessPassword.strip() == "":
104            self._accessPassword = None
105        else:
106            self._accessPassword = accessPassword
107
108    def getHasAccessPassword(self):
109        return self._accessPassword is not None
110
111    def getUrl(self):
112        if self._url.startswith("meeting"): #the first part of the URL is not there
113            self._url = getEVOOptionValueByName("koalaLocation") + '?' + self._url
114        return self._url
115
116    def getPhoneBridgeId(self):
117        if not hasattr(self, '_phoneBridgeId'):
118            self._phoneBridgeId = None
119        return self._phoneBridgeId
120
121    def getPhoneBridgePassword(self):
122        if not hasattr(self, '_phoneBridgePassword'):
123            self._phoneBridgePassword = None
124        return self._phoneBridgePassword
125
126    def getErrorMessage(self):
127        return self._errorMessage
128
129    def getErrorDetails(self):
130        return self._errorDetails
131
132    def getChangesFromEVO(self):
133        return self._changesFromEVO
134
135    def getLastCheck(self):
136        if not hasattr(self, "_lastCheck"): #TODO: remove when safe
137            self._lastCheck = nowutc()
138            self._checksDone = []
139        return self._lastCheck
140
141    ## overriding methods
142    def _getTitle(self):
143        return self._bookingParams["meetingTitle"]
144
145
146    def _checkBookingParams(self):
147        if self._bookingParams["communityId"] not in self._EVOOptions["communityList"].getValue(): #change when list of community names is ok
148            raise EVOException("communityId parameter (" + str(self._bookingParams["communityId"]) +" ) does not correspond to one of the available communities for booking with id: " + str(self._id))
149
150        if len(self._bookingParams["meetingTitle"].strip()) == 0:
151            raise EVOException("meetingTitle parameter (" + str(self._bookingParams["meetingTitle"]) +" ) is empty for booking with id: " + str(self._id))
152
153        if len(self._bookingParams["meetingDescription"].strip()) == 0:
154            raise EVOException("meetingDescription parameter (" + str(self._bookingParams["meetingDescription"]) +" ) is empty for booking with id: " + str(self._id))
155
156        if self._startDate > self._endDate:
157            raise EVOException("Start date of booking cannot be after end date. Booking id: " + str(self._id))
158
159        allowedStartMinutes = self._EVOOptions["allowedPastMinutes"].getValue()
160        if self.getAdjustedStartDate('UTC')  < (nowutc() - timedelta(minutes = allowedStartMinutes )):
161            raise EVOException("Cannot create booking before the past %s minutes. Booking id: %s"% (allowedStartMinutes, str(self._id)))
162
163        minStartDate = getMinStartDate(self.getConference())
164        if self.getAdjustedStartDate() < minStartDate:
165            raise EVOException("Cannot create a booking %s minutes before the Indico event's start date. Please create it after %s"%(self._EVOOptions["extraMinutesBefore"].getValue(), formatDateTime(minStartDate)))
166
167        maxEndDate = getMaxEndDate(self.getConference())
168        if self.getAdjustedEndDate() > maxEndDate:
169            raise EVOException("Cannot create a booking %s minutes after before the Indico event's end date. Please create it before %s"%(self._EVOOptions["extraMinutesAfter"].getValue(), formatDateTime(maxEndDate)))
170
171        if False: #for now, we don't detect overlapping
172            for booking in self.getBookingsOfSameType():
173                if self._id != booking.getId():
174                    if not ((self._startDate < booking.getStartDate() and self._endDate <= booking.getStartDate()) or
175                            (self._startDate >= booking.getEndDate() and self._endDate > booking.getEndDate())):
176                        return OverlappedError(booking)
177
178        return False
179
180
181    def _create(self):
182        """ Creates a booking in the EVO server if all conditions are met.
183        """
184        arguments = self.getCreateModifyArguments()
185
186        try:
187            requestURL = getRequestURL("create", arguments)
188            answer = getEVOAnswer("create", arguments, self.getConference().getId(), self._id)
189
190            returnedAttributes = parseEVOAnswer(answer)
191
192            self._EVOID = returnedAttributes["meet"]
193            self._url = returnedAttributes["url"]
194            self._phoneBridgeId = returnedAttributes.get("phone", None)
195            self._phoneBridgePassword = returnedAttributes.get("phonepass", None)
196
197            self.bookingOK()
198            self.checkCanStart()
199
200            if MailTools.needToSendEmails('EVO'):
201                try:
202                    notification = NewEVOMeetingNotificationAdmin(self)
203                    GenericMailer.sendAndLog(notification, self.getConference(),
204                                         "MaKaC/plugins/Collaboration/EVO/collaboration.py",
205                                         self.getConference().getCreator())
206                except Exception,e:
207                    Logger.get('EVO').error(
208                        """Could not send NewEVOMeetingNotificationAdmin for booking with id %s of event with id %s, exception: %s""" %
209                        (self.getId(), self.getConference().getId(), str(e)))
210
211#            if self._bookingParams["sendMailToManagers"]:
212#                try:
213#                    notification = NewEVOMeetingNotificationManager(self)
214#                    GenericMailer.sendAndLog(notification, self.getConference(),
215#                                             "MaKaC/plugins/Collaboration/EVO/collaboration.py",
216#                                             self.getConference().getCreator())
217#                except Exception,e:
218#                    Logger.get('EVO').error(
219#                        """Could not send NewEVOMeetingNotificationManager for booking with id %s , exception: %s""" % (self._id, str(e)))
220
221
222        except EVOControlledException, e:
223            if e.message == "ALREADY_EXIST":
224                return EVOError('duplicated', str(requestURL))
225            if e.message == "START_IN_PAST":
226                return EVOError('start_in_past', str(requestURL))
227            else:
228                raise EVOException(_("The booking could not be created due to a problem with the EVO Server\n.The EVO Server sent the following error message: ") + e.message, e)
229
230
231
232    def _modify(self, oldBookingParams):
233        """ Modifies a booking in the EVO server if all conditions are met.
234        """
235        if self._created:
236            arguments = self.getCreateModifyArguments()
237            arguments["meet"] = self._EVOID
238
239            try:
240                requestURL = getRequestURL("modify", arguments)
241                answer = getEVOAnswer("modify", arguments, self.getConference().getId(), self._id)
242                returnedAttributes = parseEVOAnswer(answer)
243
244                self._EVOID = returnedAttributes["meet"]
245                self._url = returnedAttributes["url"]
246                self._phoneBridgeId = returnedAttributes.get("phone", None)
247                self._phoneBridgePassword = returnedAttributes.get("phonepass", None)
248
249                self.bookingOK()
250                self.checkCanStart()
251
252                if MailTools.needToSendEmails('EVO'):
253                    try:
254                        notification = EVOMeetingModifiedNotificationAdmin(self)
255                        GenericMailer.sendAndLog(notification, self.getConference(),
256                                             "MaKaC/plugins/Collaboration/EVO/collaboration.py",
257                                             self.getConference().getCreator())
258                    except Exception,e:
259                        Logger.get('EVO').error(
260                            """Could not send EVOMeetingModifiedNotificationAdmin for booking with id %s of event with id %s, exception: %s""" %
261                            (self.getId(), self.getConference().getId(), str(e)))
262
263#                if self._bookingParams["sendMailToManagers"]:
264#                    try:
265#                        notification = EVOMeetingModifiedNotificationManager(self)
266#                        GenericMailer.sendAndLog(notification, self.getConference(),
267#                                             "MaKaC/plugins/Collaboration/EVO/collaboration.py",
268#                                             self.getConference().getCreator())
269#                    except Exception,e:
270#                        Logger.get('EVO').error(
271#                            """Could not send EVOMeetingModifiedNotificationManager for booking with id %s , exception: %s""" % (self._id, str(e)))
272
273
274            except EVOControlledException, e:
275                if e.message == "ALREADY_EXIST":
276                    return EVOError('duplicated', str(requestURL))
277                if e.message == "START_IN_PAST":
278                    return EVOError('start_in_past', str(requestURL))
279                if e.message == "UNKNOWN_MEETING":
280                    return EVOError('deletedByEVO', str(requestURL), _('This EVO meeting could not be modified because it was deleted in the EVO system'))
281                if e.message == "END_BEFORE_START":
282                    return EVOError('end_before_start', str(requestURL),
283                                    _("This EVO meeting could not be moved because it would have been resulting in the end date being before the start date"))
284
285                raise EVOException(_("The booking could not be modified due to a problem with the EVO Server\n.The EVO Server sent the following error message: ") + e.message, e)
286
287        else:
288            self._create()
289
290    def _start(self):
291        """ Starts an EVO meeting.
292            A last check on the EVO server is performed.
293        """
294        self._checkStatus()
295        if self._canBeStarted:
296            self._permissionToStart = True
297
298    def _notifyOnView(self):
299        """ This method is called every time that the user sees a booking.
300            It will check the booking status according to the times defined in the 'verifyMinutes' option.
301            If a check must be done, the EVO Server will be contacted.
302        """
303        checksToDo = [timedelta(minutes = int(minutes)) for minutes in self._EVOOptions["verifyMinutes"].getValue()]
304        checksToDo.sort()
305
306        remainingTime = self.getAdjustedStartDate('UTC') - nowutc()
307
308        checkDone = False
309
310        for index, check in enumerate(checksToDo):
311            if remainingTime < check and not check in self._checksDone:
312                self._checkStatus()
313                self._checksDone.extend(checksToDo[index:])
314                checkDone = True
315                break
316
317        if not checkDone:
318            self.checkCanStart()
319
320    def _checkStatus(self):
321        if self._created:
322            arguments = {"meet": self._EVOID}
323            try:
324                requestURL = getRequestURL("getInfo", arguments)
325                answer = getEVOAnswer("getInfo", arguments , self.getConference().getId(), self._id)
326                returnedAttributes = parseEVOAnswer(answer)
327
328                self.assignAttributes(returnedAttributes)
329                self.checkCanStart()
330
331            except EVOControlledException, e:
332                if e.message == "UNKNOWN_MEETING":
333                    return EVOError('deletedByEVO', str(requestURL))
334                else:
335                    raise EVOException(_("Information could not be retrieved due to a problem with the EVO Server\n.The EVO Server sent the following error message: ") + e.message, e)
336
337    def _delete(self):
338        if self._created:
339            arguments = {"meet": self._EVOID}
340            try:
341                requestURL = getRequestURL("delete", arguments)
342                getEVOAnswer("delete", arguments, self.getConference().getId(), self._id)
343
344                if MailTools.needToSendEmails('EVO'):
345                    try:
346                        notification = EVOMeetingRemovalNotificationAdmin(self)
347                        GenericMailer.sendAndLog(notification, self.getConference(),
348                                             "MaKaC/plugins/Collaboration/EVO/collaboration.py",
349                                             self.getConference().getCreator())
350                    except Exception,e:
351                        Logger.get('EVO').error(
352                            """Could not send EVOMeetingRemovalNotificationAdmin for booking with id %s of event with id %s, exception: %s""" %
353                            (self.getId(), self.getConference().getId(), str(e)))
354
355#                if self._bookingParams["sendMailToManagers"]:
356#                    try:
357#                        notification = EVOMeetingRemovalNotificationManager(self)
358#                        GenericMailer.sendAndLog(notification, self.getConference(),
359#                                             "MaKaC/plugins/Collaboration/EVO/collaboration.py",
360#                                             self.getConference().getCreator())
361#                    except Exception,e:
362#                        Logger.get('EVO').error(
363#                            """Could not send EVOMeetingRemovalNotificationManager for booking with id %s , exception: %s""" % (self._id, str(e)))
364
365            except EVOControlledException, e:
366                if e.message == "DELETE_MEETING_OVER":
367                    return EVOError('cannotDeleteOld', str(requestURL))
368                if e.message == "DELETE_MEETING_ONGOING":
369                    return EVOError('cannotDeleteOngoing', str(requestURL))
370                if e.message == "DELETE_MEETING_NO_ID":
371                    self._warning = EVOWarning('cannotDeleteNonExistant')
372                else:
373                    raise EVOException(_("The booking could not be deleted due to a problem with the EVO Server\n.The EVO Server sent the following error message: ") + e.message, e)
374
375        self._error = False
376
377
378    def _getLaunchDisplayInfo(self):
379        return {'launchText' : _("Join Now!"),
380                'launchLink' : str(self.getUrl()),
381                'launchTooltip': _("Click here to join the EVO meeting!")}
382
383    ## end of overrigind methods
384
385    def getCreateModifyArguments(self):
386        arguments = {
387            "title" : self._bookingParams["meetingTitle"],
388            "desc" : self._bookingParams["meetingDescription"],
389            "start": int(self.getStartDateTimestamp() * 1000), #milliseconds
390            "end": int(self.getEndDateTimestamp() * 1000), #milliseconds
391            "type": 0,
392            "com": self._bookingParams["communityId"]
393        }
394        if self.getHasAccessPassword():
395            arguments["pwd"] = self._accessPassword
396        else:
397            arguments["pwd"] = ''
398
399        return arguments
400
401    def assignAttributes(self, attributes):
402
403        verboseKeyNames = {
404            "meet": "EVO Meeting ID",
405            "url": "Koala URL",
406            "title": "Title",
407            "desc": "Description",
408            "start": "Start time",
409            "end": "End time",
410            "type": "Meeting type",
411            "com": "Community",
412            "phone": "Phone Bridge ID",
413            "phonepass": "Phone Bridge password"
414        }
415
416        oldArguments = self.getCreateModifyArguments()
417        oldArguments["phone"] = self.getPhoneBridgeId()
418        if self.getHasAccessPassword():
419            oldArguments["phonepass"] = self.getPhoneBridgePassword()
420
421        changesFromEVO = []
422
423        for key in oldArguments:
424            if (not key in attributes or attributes[key] != str(oldArguments[key])) and key in verboseKeyNames:
425                changesFromEVO.append(verboseKeyNames[key])
426
427        self._changesFromEVO = changesFromEVO
428
429        self._EVOID = attributes["meet"]
430        self._url = attributes["url"]
431        self._phoneBridgeId = attributes.get("phone", None)
432        self._phoneBridgePassword = attributes.get("phonepass", None)
433
434        self._bookingParams["meetingTitle"] = attributes["title"]
435        self._bookingParams["meetingDescription"] = attributes["desc"]
436        self.setStartDate(unixTimeToDatetime(int(attributes["start"]) / 1000.0, "UTC"))
437        self.setEndDate(unixTimeToDatetime(int(attributes["end"]) / 1000.0, "UTC"))
438        self._bookingParams["type"] = attributes["type"]
439        self._bookingParams["communityId"] = attributes["com"]
440
441        self.checkCanStart()
442
443        if changesFromEVO:
444            return ChangesFromEVOError(changesFromEVO)
445
446    def bookingOK(self):
447        self._statusMessage = "Booking created"
448        self._statusClass = "statusMessageOK"
449        self._created = True
450
451    def checkCanStart(self, changeMessage = True):
452        if self._created:
453            now = nowutc()
454            self._canBeDeleted = True
455            self._canBeNotifiedOfEventDateChanges = CSBooking._canBeNotifiedOfEventDateChanges
456            if self.getStartDate() < now and self.getEndDate() > now:
457                self._canBeStarted = True
458                self._canBeDeleted = False
459                if changeMessage:
460                    self._statusMessage = "Ready to start!"
461                    self._statusClass = "statusMessageOK"
462            else:
463                self._canBeStarted = False
464                if now > self.getEndDate() and changeMessage:
465                    self._canBeDeleted = False
466                    self._statusMessage = "Already took place"
467                    self._statusClass = "statusMessageOther"
468                    self._needsToBeNotifiedOfDateChanges = False
469                    self._canBeNotifiedOfEventDateChanges = False
470                elif changeMessage:
471                    self.bookingOK()
Note: See TracBrowser for help on using the repository browser.