~ubuntu-branches/ubuntu/oneiric/emesene/oneiric

« back to all changes in this revision

Viewing changes to plugins_base/LogConversation.py

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2010-04-14 01:33:51 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20100414013351-r2icbt5gs4ai71j8
Tags: 1.6.1-0ubuntu1
* New upstream release (LP: #562646).
* Fix missing-debian-source-format lintian warning.
* Refresh 20_dont_build_own_libmimic.patch patch.
* Bump Standards-Version to 3.8.4.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
#    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
16
16
 
17
17
#Changelog:
 
18
#0.5.1:
 
19
#-Don't log "conversation started/closed" if just open an close conversation
 
20
#-Fix a bug at stop of the plugin
 
21
 
 
22
#0.5:
 
23
#-Log all offline messages
 
24
#-Fixed user menu for the new logs directories structure (dates)
 
25
#-A lot of refactor
 
26
 
18
27
#0.4.8:
19
28
#-Fix Back consinstency for PyGtk in setting tooltips of a ToolItem
20
29
 
42
51
 
43
52
VERSION = '0.4.8'
44
53
import Plugin
45
 
import dialog
46
54
import os
47
55
import time
48
56
import emesenelib
49
57
import desktop
50
58
import gtk
 
59
import gobject
51
60
 
52
61
#From aaPluginDownloader
53
62
try:
63
72
 
64
73
    def __init__(self,controller,conversation,MainClass,addButton = True):
65
74
        '''Save the identifier of this conversation and begin to log message'''
 
75
        self.controller = controller
 
76
        self.mainClass = MainClass
 
77
        self.stopped = False
66
78
 
67
79
        #This identifier enable the check of members change!
68
80
        self.members = conversation.getMembers()
69
81
        self.idMyLog = self.members[0]
70
82
        for mem in self.members[1:len(self.members)]:
71
83
            self.idMyLog = self.idMyLog + '-' + mem
 
84
        self.lastUserName = ''
72
85
 
73
86
        #The identifier of this conversation is the id of conversation
74
87
        self.idConv = id(conversation)
75
88
        self.conversation = conversation
76
89
 
77
 
        self.mainClass = MainClass
78
 
        #self.mainClass.activeLogger.append(self)
79
 
        self.stopped = False
80
 
 
81
 
        self.convId = conversation
82
 
        self.controller = controller
83
 
        #Every time the conversationManager send a close-conversation-ui
84
 
        #execute stop
85
 
        self.convmanagerId = self.controller.conversationManager.connect('close-conversation-ui', self.stop)
86
 
 
87
 
        #We need to remember last username to show group conversation.
88
 
        #Patched by Nelson (nelson at csie dot us)
89
 
        self.lastUserName = ''
90
 
 
91
90
        #We would save logs in :
92
 
        #paths.CONFIG_DIR join controller.config.getCurrentUser() join html_logs
93
 
        self.logDir = os.path.join(CONFIG_PATH, \
94
 
            controller.config.getCurrentUser()) #this dir exist!
95
 
        maybeFaultDir = os.path.join(self.logDir, \
96
 
            'html_logs') #This is created at the first run
 
91
        self.logDir = os.path.join(self.mainClass.logsDir, \
 
92
                        time.strftime('%B_%Y', time.localtime(time.time()))) #This is created at the first run
97
93
 
98
94
        #If the log dir not exist create it
99
 
        if os.path.exists(maybeFaultDir):
100
 
            self.logDir = maybeFaultDir
101
 
        else:
102
 
            os.mkdir(maybeFaultDir)
103
 
            # ugly, but "if os.mkdir(..)" doesn't work :S
104
 
            if os.path.exists(maybeFaultDir):
105
 
                self.logDir = maybeFaultDir
106
 
                # if we can't create the dir, we put the file directly
107
 
                # in logDir
108
 
 
 
95
        if not os.path.exists(self.logDir):
 
96
            try:
 
97
                os.mkdir(self.logDir)
 
98
            except: #in case we can't create the dir with the date
 
99
                self.logDir = self.mainClass.logsDir 
109
100
 
110
101
        #Create the log FileName
111
102
        self.logFileName = os.path.join(self.logDir, \
125
116
            else:
126
117
                #Last time we have not closed the file in the right way
127
118
                #We put a br..
 
119
                self.logFile.seek(0,2)
128
120
                self.logFile.write('\n<span><br/></span>\n')
129
121
        else:
130
122
            self.logFile = open(self.logFileName,'w')
134
126
            convwith = _('Conversation with %s') % self.idMyLog
135
127
            self.logFile.write('<title>'+ convwith +'</title>\n</head>\n<body>\n')
136
128
 
137
 
        #self.mainClass.debug('[LogConv] Logging in :' + self.logFileName)
138
 
 
139
 
        #First string
140
 
        started = _('Started at: ') 
141
 
        self.logFile.write('<hr align=\"left\" />\n')
142
 
        self.logFile.write('\n<span><span style=\"font-size: 10pt;font-weight: bold;\"> ' + started)
143
 
        self.logFile.write(time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime(time.time())))
144
 
        self.logFile.write('.<br/></span></span>\n')
145
 
        self.logFile.flush()
 
129
        self.modified = False
146
130
 
147
131
        #For file send and receive logging
148
132
        self.p2p = controller.msn.p2p[conversation.switchboard.firstUser]
151
135
        self.sendmessageId = self.controller.conversationManager.connect( \
152
136
                                    'send-message', self.logSendMessage)
153
137
        self.receivemessageId = self.controller.conversationManager.connect( \
154
 
                                    'receive-message', self.logReceivedMessage)
155
 
        self.receiveOffmessageId = self.mainClass.connect( \
156
 
                                    'offline-message-received', self.logOffReceivedMessage)
157
 
        self.fileTransferId = self.p2p.connect('file-transfer-accepted',self.logFileTransfer)
 
138
                             'receive-message', self.logReceivedMessage)
 
139
        self.fileTransferId = self.p2p.connect('file-transfer-accepted',\
 
140
                                                   self.logFileTransfer)
 
141
        #Every time the conversationManager send a close-conversation-ui
 
142
        #execute stop
 
143
        self.closeUIId = self.controller.conversationManager.connect(\
 
144
                                     'close-conversation-ui', self.stop)
158
145
 
159
146
        if addButton:
160
147
            #Add a button to the toolbar of this conversation:
161
 
            self.logButton = gtk.ToolButton()
162
 
            self.logButton.set_label(_('Logs'))
 
148
            self.logButton = gtk.ToolButton(label=_('Logs'))
163
149
            self.logButton.set_stock_id(gtk.STOCK_DND)
164
150
            if self.controller.theme.getImage('log'):
165
151
                imagelog = gtk.Image()
166
152
                imagelog.set_from_pixbuf(self.controller.theme.getImage('log'))
167
153
                imagelog.show()
168
154
                self.logButton.set_icon_widget(imagelog)
169
 
            self.logButton.connect('clicked',self.viewLog)
 
155
            self.logButton.connect('clicked', self.mainClass.viewLog, self.logFileName)
170
156
 
171
157
            self.logButton.set_tooltip_text(_('View the logs of this conversation'))
172
158
 
173
159
            conversation.ui.input.toolbar.insert(gtk.SeparatorToolItem(), -1)
174
160
            conversation.ui.input.toolbar.insert(self.logButton, -1)
175
 
 
176
161
            conversation.ui.input.toolbar.show_all()
177
 
 
178
 
 
179
 
    def viewLog(self, *args):
180
 
        desktop.open(self.logFileName)
 
162
            
 
163
    def start_conv_log(self):
 
164
        #First string
 
165
        started = _('Started at: ') 
 
166
        self.logFile.write('<hr align=\"left\" />\n')
 
167
        self.logFile.write('\n<span><span style=\"font-size: 10pt;font-weight: bold;\"> ' + started)
 
168
        self.logFile.write(time.strftime('%a, %d %b %Y %H:%M:%S', time.localtime(time.time())))
 
169
        self.logFile.write('.<br/></span></span>\n')
 
170
        self.logFile.flush()
 
171
        self.modified = True
181
172
 
182
173
    def logSendMessage(self, obj, conversation, message):
183
174
        '''message is a list of string'''
184
 
 
185
175
        idThisLog = id(conversation)
186
176
 
187
177
        #Log this message if the id match
188
178
        if idThisLog == self.idConv:
 
179
            if not self.modified:
 
180
                self.start_conv_log()
189
181
            #Members have changed??
190
182
            members = conversation.getMembers()
191
183
            mbThisLog = members[0]
195
187
            if mbThisLog != self.idMyLog:
196
188
                self.stop()
197
189
                self.__init__(self.controller,self.conversation,self.mainClass,False)
 
190
                self.mainClass.activeLoggers.append(self)
198
191
 
199
192
            self.appendOutputText(conversation.getUser(), message, 'outgoing')
200
193
 
201
194
    def logReceivedMessage(self, cm, conversation, mail, nick, message, format, charset, p4c):
202
 
 
203
195
        idThisLog = id(conversation)
204
196
 
205
197
        #Log this message if the id match
206
198
        if idThisLog == self.idConv:
 
199
            if not self.modified:
 
200
                self.start_conv_log()
207
201
            #Members have changed??
208
202
            members = conversation.getMembers()
209
203
            mbThisLog = members[0]
213
207
            if mbThisLog != self.idMyLog:
214
208
                self.stop()
215
209
                self.__init__(self.controller,self.conversation,self.mainClass,False)
 
210
                self.mainClass.activeLoggers.append(self)
216
211
 
217
212
            self.appendOutputText(mail, message, 'incoming', \
218
213
                conversation.parseFormat(mail, format))
219
214
 
220
 
    def logOffReceivedMessage(self, msnp, oim):
221
 
        '''called when someone sent an offline message'''
222
 
 
223
 
        user, date, message = oim
224
 
        mail = user['addr']
225
 
 
226
 
        result = self.controller.conversationManager.getOpenConversation(mail)
227
 
        if result != None:
228
 
            idThisLog = id(result[1]) #conversation
229
 
            if idThisLog == self.idConv:
230
 
                self.appendOutputText(mail, message, 'offline_incoming', \
231
 
                                time.mktime(date))
232
 
 
233
215
    def logFileTransfer(self, p2p, session, context, sender):
234
216
 
235
217
        mail = sender
238
220
        self.members = self.conversation.getMembers()
239
221
        for mem in self.members:
240
222
            if (mail == mem) or (mail == 'Me'):
 
223
                if not self.modified:
 
224
                    self.start_conv_log()
241
225
                self.appendOutputText(None, \
242
226
                        _('Starting transfer of %s') % context.filename, \
243
227
                        'information')
246
230
    #From in Conversation.py with another end
247
231
    def appendOutputText(self, username, text, type, style = None, timestamp = None):
248
232
        '''append the given text to the outputFile type is in[incoming:outgoing]'''
249
 
 
 
233
        if not self.modified:
 
234
            self.start_conv_log()
250
235
        if type.startswith('ink_'):
251
236
            type = type[4:]
252
237
            ink = True
253
238
        else:
254
239
            ink = False
255
240
 
256
 
        if username == self.convId.switchboard.user:
 
241
        if username == self.conversation.switchboard.user:
257
242
            nick = emesenelib.common.escape(self.controller.msn.nick)
258
243
        elif username != None:
259
244
            nick = emesenelib.common.escape( \
265
250
            timestamp = time.time()
266
251
 
267
252
        if self.lastUserName == username:
 
253
            if type != "offline_incoming":
 
254
                type = "consecutive_"+type
268
255
            displayedText = self.controller.conversationLayoutManager.layout(\
269
 
                username, text, style, self.convId, 'consecutive_' + type, timestamp, ink)
 
256
                username, text, style, self.conversation, type, timestamp, ink)
270
257
        else:
271
258
            self.lastUserName = username
272
259
            displayedText = self.controller.conversationLayoutManager.layout(\
273
 
                username, text, style, self.convId, type, timestamp, ink)
 
260
                username, text, style, self.conversation, type, timestamp, ink)
274
261
 
275
262
        #erase custom emoticons
276
263
        displayedText = self.fromCustomEmoticonsToText(displayedText)
277
 
 
278
264
        self.logFile.write('<!---->' + displayedText)
279
265
        self.logFile.write('\n')
280
266
        self.logFile.flush()
281
267
 
282
268
    def stop(self, conversationManager = None, conversation = None, window = None):
283
269
        '''Close this logger if the id of the conversation closed match with self.idMyLog'''
284
 
 
285
270
        if self.stopped:
286
271
            return
287
272
 
293
278
        #Close this logger if the id match
294
279
        if idThisLog == self.idConv:
295
280
            #Last String
296
 
            closed = _('Closed at: ')
297
 
            self.logFile.write('\n<span><span style=\"font-size: 10pt;font-weight: bold;\">'+ closed)
298
 
            self.logFile.write(time.strftime('%a, %d %b %Y %H:%M:%S',time.localtime(time.time())))
299
 
            self.logFile.write('.<br/></span></span>\n')
300
 
            #Tail of the document
301
 
            self.logFile.write('\n</body></html>\n')
 
281
            if self.modified:
 
282
                closed = _('Closed at: ')
 
283
                self.logFile.write('\n<span><span style=\"font-size: 10pt;font-weight: bold;\">'+ closed)
 
284
                self.logFile.write(time.strftime('%a, %d %b %Y %H:%M:%S',time.localtime(time.time())))
 
285
                self.logFile.write('.<br/></span></span>\n')
 
286
                #Tail of the document
 
287
                self.logFile.write('\n</body></html>\n')
302
288
 
303
289
            self.logFile.close()
304
290
 
305
291
            self.controller.conversationManager.disconnect(self.sendmessageId)
306
292
            self.controller.conversationManager.disconnect(self.receivemessageId)
307
 
            self.controller.conversationManager.disconnect(self.convmanagerId)
308
 
            self.mainClass.disconnect(self.receiveOffmessageId)
 
293
            self.controller.conversationManager.disconnect(self.closeUIId)
309
294
            self.p2p.disconnect(self.fileTransferId)
310
295
            self.stopped = True
 
296
            self.mainClass.activeLoggers.remove(self)
311
297
 
312
298
    def fromCustomEmoticonsToText(self,message):
313
299
 
365
351
class MainClass(Plugin.Plugin):
366
352
    '''Main plugin class'''
367
353
 
368
 
    description = _('Log every session with friendEmail in:\n' +\
369
 
                    '~/.config/emesene1.0/<address>/html_logs/friendEmail.html')
370
 
    authors = { 'Marramao' : 'maramaopercheseimorto@gmail.com'}
 
354
    description = _('Log every session with friendEmail in:\n' + \
 
355
      '~/.config/emesene1.0/<address>/html_logs/month_year/friendEmail.html')
 
356
    authors = { 'Marramao' : 'maramaopercheseimorto@gmail.com', \
 
357
                'arielj' : 'arieljuod@gmail.com' }
371
358
    website = 'emesene.org'
372
359
    displayName = _('Conversation Logger')
373
360
    name = 'LogConversation'
374
361
 
375
 
    activeLogger = []
376
 
 
377
362
    def __init__(self, controller, msn):
378
363
        '''Contructor'''
379
364
        Plugin.Plugin.__init__(self, controller, msn)
380
365
 
381
 
        self.description = _('Log every session with friendEmail in:\n' +\
382
 
                    '~/.config/emesene1.0/<address>/html_logs/friendEmail.html')
383
 
        self.authors = { 'Marramao' : 'maramaopercheseimorto@gmail.com'}
384
 
        self.website = 'emesene.org'
385
 
        self.displayName = _('Conversation Logger')
386
 
        self.name = 'LogConversation'
387
 
 
388
366
        self.controller = controller
389
367
        self.config = controller.config
390
368
        self.config.readPluginConfig(self.name)
391
 
        self.enabled = False
392
 
 
393
 
        self.convmanagerId = 0
394
 
        #self.debug( '[LogConv] Initialized.\n')
395
 
 
396
 
        #self.start()
 
369
 
 
370
        self.activeLoggers = []
397
371
 
398
372
    def start(self):
399
373
        '''start the plugin'''
400
 
        if self.enabled ==False:
401
 
            self.convmanagerId = self.controller.conversationManager.connect( \
 
374
        self.convmanagerId = self.controller.conversationManager.connect( \
402
375
                'new-conversation-ui', self.connectLogger)
403
 
            self.menuItemId = self.controller.connect("usermenu-item-add", self.add_usermenu_item)
 
376
        self.menuItemId = self.controller.connect("usermenu-item-add", \
 
377
                                                  self.add_usermenu_item)
 
378
        self.offlineMessages = self.connect('offline-message-received', \
 
379
                                              self.logOffReceivedMessage)
 
380
 
 
381
        self.logsDir = os.path.join(CONFIG_PATH, \
 
382
                 self.controller.config.getCurrentUser(), 'html_logs')
 
383
 
 
384
        if not os.path.isdir(self.logsDir):
 
385
            os.mkdir(self.logsDir)
404
386
 
405
387
        self.enabled = True
406
388
 
407
 
        #self.debug( '[LogConv] Started.\n')
408
 
 
409
389
    def connectLogger (self, conversationManager, conversation, window):
410
 
        self.newLogger = MyLogger(self.controller,conversation,self)
411
 
    
 
390
        self.activeLoggers.append(MyLogger(self.controller,conversation,self))
 
391
 
 
392
    def logOffReceivedMessage(self, msnp, oim):
 
393
        '''used when a new conversation is opened by an offline message'''
 
394
        def check(oim):
 
395
            user, date, message = oim
 
396
            mail = user['addr']
 
397
            result = self.controller.conversationManager.getOpenConversation(mail)
 
398
            
 
399
            if result is not None:
 
400
                conversation = result[1]
 
401
                for logger in self.activeLoggers:
 
402
                    if logger.conversation == conversation:
 
403
 
 
404
                        try:
 
405
                            logger.appendOutputText(mail, message, 'offline_incoming', \
 
406
                                time.mktime(date))
 
407
                            return False
 
408
                        except:
 
409
                            pass
 
410
                return True
 
411
            return True
 
412
 
 
413
        gobject.timeout_add(500, check, oim)
 
414
 
412
415
    def add_usermenu_item(self, controller, userMenu):
413
 
        logDir = os.path.join(CONFIG_PATH, \
414
 
            controller.config.getCurrentUser())
415
 
        maybeFaultDir = os.path.join(logDir, \
416
 
            'html_logs')
417
 
        if os.path.exists(maybeFaultDir):
418
 
            logDir = maybeFaultDir
419
 
        else:
420
 
            os.mkdir(maybeFaultDir)
421
 
            if os.path.exists(maybeFaultDir):
422
 
                self.logDir = maybeFaultDir
423
 
        self.logFileName = os.path.join(logDir, \
424
 
            userMenu.user.email + '.html')
425
 
            
426
 
        if os.path.exists(self.logFileName):
427
 
            self.logMenuItem = userMenu.newImageMenuItem( _( "Logs of this conversation" ),
428
 
                gtk.STOCK_DND )
429
 
            if self.controller.theme.getImage('log'):
430
 
                imagelog = gtk.Image()
431
 
                imagelog.set_from_pixbuf(self.controller.theme.getImage('log'))
432
 
                imagelog.show()
433
 
                self.logMenuItem.set_icon_widget(imagelog)
434
 
            userMenu.viewMenu.add( self.logMenuItem )
435
 
            self.logMenuItem.show()
436
 
            self.logMenuItem.connect( 'activate', self.viewLog )
437
 
 
438
 
    def viewLog(self, *args):
439
 
        desktop.open(self.logFileName)
 
416
        dates = os.listdir(self.logsDir)
 
417
        logMenuItem = userMenu.newImageMenuItem( _( "Logs of this user" ),
 
418
                                                           gtk.STOCK_DND )
 
419
        if self.controller.theme.getImage('log'):
 
420
            imagelog = gtk.Image()
 
421
            imagelog.set_from_pixbuf(self.controller.theme.getImage('log'))
 
422
            imagelog.show()
 
423
            logMenuItem.set_icon_widget(imagelog)
 
424
 
 
425
        submenu = gtk.Menu()
 
426
        logsAvailables = False
 
427
        for date in dates:
 
428
            logFileName = os.path.join(self.logsDir, date, \
 
429
                                       userMenu.user.email + '.html')
 
430
            if os.path.exists(logFileName):
 
431
                newMenuItem = gtk.MenuItem(label=date)
 
432
                newMenuItem.connect( 'activate', self.viewLog, logFileName )
 
433
                submenu.append(newMenuItem)
 
434
                logsAvailables = True
 
435
 
 
436
        if logsAvailables:
 
437
            logMenuItem.set_submenu(submenu)
 
438
            userMenu.viewMenu.add(logMenuItem)
 
439
            logMenuItem.show_all()
 
440
 
 
441
    def viewLog(self, menuitem, logFileName):
 
442
        desktop.open(logFileName)
440
443
 
441
444
    def stop(self):
442
445
        '''stop the plugin'''
443
446
        self.controller.conversationManager.disconnect(self.convmanagerId)
444
 
        #print '[LogConv]I\'m going to close %d active loggers.' % len(self.activeLogger)
445
447
        self.controller.disconnect(self.menuItemId)
 
448
        self.disconnect(self.offlineMessages)
446
449
 
447
 
        if len(self.activeLogger) > 0:
448
 
            for myLogger in self.activeLogger:
449
 
                myLogger.stop()
 
450
        for myLogger in self.activeLoggers:
 
451
            myLogger.stop()
450
452
        
451
453
        self.enabled = False
452
 
        #self.debug( '[LogConv] Stopped.\n')
453
454
 
454
455
    def check(self):
455
456
        return (True, 'Ok')