| Trees | Indices | Help |
|
|---|
|
|
1 # -*- coding:utf-8 -*-
2 ## src/common/pep.py
3 ##
4 ## Copyright (C) 2007 Piotr Gaczkowski <doomhammerng AT gmail.com>
5 ## Copyright (C) 2007-2010 Yann Leboulanger <asterix AT lagaule.org>
6 ## Copyright (C) 2008 Brendan Taylor <whateley AT gmail.com>
7 ## Jean-Marie Traissard <jim AT lapin.org>
8 ## Jonathan Schleifer <js-common.gajim AT webkeks.org>
9 ## Stephan Erb <steve-e AT h3c.de>
10 ##
11 ## This file is part of Gajim.
12 ##
13 ## Gajim is free software; you can redistribute it and/or modify
14 ## it under the terms of the GNU General Public License as published
15 ## by the Free Software Foundation; version 3 only.
16 ##
17 ## Gajim is distributed in the hope that it will be useful,
18 ## but WITHOUT ANY WARRANTY; without even the implied warranty of
19 ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 ## GNU General Public License for more details.
21 ##
22 ## You should have received a copy of the GNU General Public License
23 ## along with Gajim. If not, see <http://www.gnu.org/licenses/>.
24 ##
25
26 MOODS = {
27 'afraid': _('Afraid'),
28 'amazed': _('Amazed'),
29 'amorous': _('Amorous'),
30 'angry': _('Angry'),
31 'annoyed': _('Annoyed'),
32 'anxious': _('Anxious'),
33 'aroused': _('Aroused'),
34 'ashamed': _('Ashamed'),
35 'bored': _('Bored'),
36 'brave': _('Brave'),
37 'calm': _('Calm'),
38 'cautious': _('Cautious'),
39 'cold': _('Cold'),
40 'confident': _('Confident'),
41 'confused': _('Confused'),
42 'contemplative': _('Contemplative'),
43 'contented': _('Contented'),
44 'cranky': _('Cranky'),
45 'crazy': _('Crazy'),
46 'creative': _('Creative'),
47 'curious': _('Curious'),
48 'dejected': _('Dejected'),
49 'depressed': _('Depressed'),
50 'disappointed': _('Disappointed'),
51 'disgusted': _('Disgusted'),
52 'dismayed': _('Dismayed'),
53 'distracted': _('Distracted'),
54 'embarrassed': _('Embarrassed'),
55 'envious': _('Envious'),
56 'excited': _('Excited'),
57 'flirtatious': _('Flirtatious'),
58 'frustrated': _('Frustrated'),
59 'grateful': _('Grateful'),
60 'grieving': _('Grieving'),
61 'grumpy': _('Grumpy'),
62 'guilty': _('Guilty'),
63 'happy': _('Happy'),
64 'hopeful': _('Hopeful'),
65 'hot': _('Hot'),
66 'humbled': _('Humbled'),
67 'humiliated': _('Humiliated'),
68 'hungry': _('Hungry'),
69 'hurt': _('Hurt'),
70 'impressed': _('Impressed'),
71 'in_awe': _('In Awe'),
72 'in_love': _('In Love'),
73 'indignant': _('Indignant'),
74 'interested': _('Interested'),
75 'intoxicated': _('Intoxicated'),
76 'invincible': _('Invincible'),
77 'jealous': _('Jealous'),
78 'lonely': _('Lonely'),
79 'lost': _('Lost'),
80 'lucky': _('Lucky'),
81 'mean': _('Mean'),
82 'moody': _('Moody'),
83 'nervous': _('Nervous'),
84 'neutral': _('Neutral'),
85 'offended': _('Offended'),
86 'outraged': _('Outraged'),
87 'playful': _('Playful'),
88 'proud': _('Proud'),
89 'relaxed': _('Relaxed'),
90 'relieved': _('Relieved'),
91 'remorseful': _('Remorseful'),
92 'restless': _('Restless'),
93 'sad': _('Sad'),
94 'sarcastic': _('Sarcastic'),
95 'satisfied': _('Satisfied'),
96 'serious': _('Serious'),
97 'shocked': _('Shocked'),
98 'shy': _('Shy'),
99 'sick': _('Sick'),
100 'sleepy': _('Sleepy'),
101 'spontaneous': _('Spontaneous'),
102 'stressed': _('Stressed'),
103 'strong': _('Strong'),
104 'surprised': _('Surprised'),
105 'thankful': _('Thankful'),
106 'thirsty': _('Thirsty'),
107 'tired': _('Tired'),
108 'undefined': _('Undefined'),
109 'weak': _('Weak'),
110 'worried': _('Worried')}
111
112 ACTIVITIES = {
113 'doing_chores': {'category': _('Doing Chores'),
114 'buying_groceries': _('Buying Groceries'),
115 'cleaning': _('Cleaning'),
116 'cooking': _('Cooking'),
117 'doing_maintenance': _('Doing Maintenance'),
118 'doing_the_dishes': _('Doing the Dishes'),
119 'doing_the_laundry': _('Doing the Laundry'),
120 'gardening': _('Gardening'),
121 'running_an_errand': _('Running an Errand'),
122 'walking_the_dog': _('Walking the Dog')},
123 'drinking': {'category': _('Drinking'),
124 'having_a_beer': _('Having a Beer'),
125 'having_coffee': _('Having Coffee'),
126 'having_tea': _('Having Tea')},
127 'eating': {'category': _('Eating'),
128 'having_a_snack': _('Having a Snack'),
129 'having_breakfast': _('Having Breakfast'),
130 'having_dinner': _('Having Dinner'),
131 'having_lunch': _('Having Lunch')},
132 'exercising': {'category': _('Exercising'),
133 'cycling': _('Cycling'),
134 'dancing': _('Dancing'),
135 'hiking': _('Hiking'),
136 'jogging': _('Jogging'),
137 'playing_sports': _('Playing Sports'),
138 'running': _('Running'),
139 'skiing': _('Skiing'),
140 'swimming': _('Swimming'),
141 'working_out': _('Working out')},
142 'grooming': {'category': _('Grooming'),
143 'at_the_spa': _('At the Spa'),
144 'brushing_teeth': _('Brushing Teeth'),
145 'getting_a_haircut': _('Getting a Haircut'),
146 'shaving': _('Shaving'),
147 'taking_a_bath': _('Taking a Bath'),
148 'taking_a_shower': _('Taking a Shower')},
149 'having_appointment': {'category': _('Having an Appointment')},
150 'inactive': {'category': _('Inactive'),
151 'day_off': _('Day Off'),
152 'hanging_out': _('Hanging out'),
153 'hiding': _('Hiding'),
154 'on_vacation': _('On Vacation'),
155 'praying': _('Praying'),
156 'scheduled_holiday': _('Scheduled Holiday'),
157 'sleeping': _('Sleeping'),
158 'thinking': _('Thinking')},
159 'relaxing': {'category': _('Relaxing'),
160 'fishing': _('Fishing'),
161 'gaming': _('Gaming'),
162 'going_out': _('Going out'),
163 'partying': _('Partying'),
164 'reading': _('Reading'),
165 'rehearsing': _('Rehearsing'),
166 'shopping': _('Shopping'),
167 'smoking': _('Smoking'),
168 'socializing': _('Socializing'),
169 'sunbathing': _('Sunbathing'),
170 'watching_tv': _('Watching TV'),
171 'watching_a_movie': _('Watching a Movie')},
172 'talking': {'category': _('Talking'),
173 'in_real_life': _('In Real Life'),
174 'on_the_phone': _('On the Phone'),
175 'on_video_phone': _('On Video Phone')},
176 'traveling': {'category': _('Traveling'),
177 'commuting': _('Commuting'),
178 'cycling': _('Cycling'),
179 'driving': _('Driving'),
180 'in_a_car': _('In a Car'),
181 'on_a_bus': _('On a Bus'),
182 'on_a_plane': _('On a Plane'),
183 'on_a_train': _('On a Train'),
184 'on_a_trip': _('On a Trip'),
185 'walking': _('Walking')},
186 'working': {'category': _('Working'),
187 'coding': _('Coding'),
188 'in_a_meeting': _('In a Meeting'),
189 'studying': _('Studying'),
190 'writing': _('Writing')}}
191
192 TUNE_DATA = ['artist', 'title', 'source', 'track', 'length']
193
194 LOCATION_DATA = ['accuracy', 'alt', 'area', 'bearing', 'building', 'country',
195 'countrycode', 'datum', 'description', 'error', 'floor', 'lat',
196 'locality', 'lon', 'postalcode', 'region', 'room', 'speed', 'street',
197 'text', 'timestamp', 'uri']
198
199 import gobject
200 import gtk
201
202 import logging
203 log = logging.getLogger('gajim.c.pep')
204
205 from common import helpers
206 from common import atom
207 from common import xmpp
208 from common import gajim
209
210 import gtkgui_helpers
214
215 type = ''
216 namespace = ''
217
218 @classmethod
220 items = event_tag.getTag('items', {'node': cls.namespace})
221 if items:
222 log.debug("Received PEP 'user %s' from %s" % (cls.type, jid))
223 return cls(jid, account, items)
224 else:
225 return None
226
228 self._pep_specific_data, self._retracted = self._extract_info(items)
229
230 self._update_contacts(jid, account)
231 if jid == gajim.get_jid_from_account(account):
232 self._update_account(account)
233
237
239 for contact in gajim.contacts.get_contacts(account, jid):
240 if self._retracted:
241 if self.type in contact.pep:
242 del contact.pep[self.type]
243 else:
244 contact.pep[self.type] = self
245
247 acc = gajim.connections[account]
248 if self._retracted:
249 if self.type in acc.pep:
250 del acc.pep[self.type]
251 else:
252 acc.pep[self.type] = self
253
257
261
264 '''XEP-0107: User Mood'''
265
266 type = 'mood'
267 namespace = xmpp.NS_MOOD
268
270 mood_dict = {}
271
272 for item in items.getTags('item'):
273 mood_tag = item.getTag('mood')
274 if mood_tag:
275 for child in mood_tag.getChildren():
276 name = child.getName().strip()
277 if name == 'text':
278 mood_dict['text'] = child.getData()
279 else:
280 mood_dict['mood'] = name
281
282 retracted = items.getTag('retract') or not 'mood' in mood_dict
283 return (mood_dict, retracted)
284
286 assert not self._retracted
287 received_mood = self._pep_specific_data['mood']
288 mood = received_mood if received_mood in MOODS else 'unknown'
289 pixbuf = gtkgui_helpers.load_mood_icon(mood).get_pixbuf()
290 return pixbuf
291
293 assert not self._retracted
294 untranslated_mood = self._pep_specific_data['mood']
295 mood = self._translate_mood(untranslated_mood)
296 markuptext = '<b>%s</b>' % gobject.markup_escape_text(mood)
297 if 'text' in self._pep_specific_data:
298 text = self._pep_specific_data['text']
299 markuptext += ' (%s)' % gobject.markup_escape_text(text)
300 return markuptext
301
307
310 '''XEP-0118: User Tune'''
311
312 type = 'tune'
313 namespace = xmpp.NS_TUNE
314
316 tune_dict = {}
317
318 for item in items.getTags('item'):
319 tune_tag = item.getTag('tune')
320 if tune_tag:
321 for child in tune_tag.getChildren():
322 name = child.getName().strip()
323 data = child.getData().strip()
324 if child.getName() in TUNE_DATA:
325 tune_dict[name] = data
326
327 retracted = items.getTag('retract') or not ('artist' in tune_dict or
328 'title' in tune_dict)
329 return (tune_dict, retracted)
330
332 import os
333 path = os.path.join(gajim.DATA_DIR, 'emoticons', 'static', 'music.png')
334 return gtk.gdk.pixbuf_new_from_file(path)
335
337 assert not self._retracted
338 tune = self._pep_specific_data
339
340 artist = tune.get('artist', _('Unknown Artist'))
341 artist = gobject.markup_escape_text(artist)
342
343 title = tune.get('title', _('Unknown Title'))
344 title = gobject.markup_escape_text(title)
345
346 source = tune.get('source', _('Unknown Source'))
347 source = gobject.markup_escape_text(source)
348
349 tune_string = _('<b>"%(title)s"</b> by <i>%(artist)s</i>\n'
350 'from <i>%(source)s</i>') % {'title': title,
351 'artist': artist, 'source': source}
352 return tune_string
353
356 '''XEP-0108: User Activity'''
357
358 type = 'activity'
359 namespace = xmpp.NS_ACTIVITY
360
362 activity_dict = {}
363
364 for item in items.getTags('item'):
365 activity_tag = item.getTag('activity')
366 if activity_tag:
367 for child in activity_tag.getChildren():
368 name = child.getName().strip()
369 data = child.getData().strip()
370 if name == 'text':
371 activity_dict['text'] = data
372 else:
373 activity_dict['activity'] = name
374 for subactivity in child.getChildren():
375 subactivity_name = subactivity.getName().strip()
376 activity_dict['subactivity'] = subactivity_name
377
378 retracted = items.getTag('retract') or not 'activity' in activity_dict
379 return (activity_dict, retracted)
380
382 assert not self._retracted
383 pep = self._pep_specific_data
384 activity = pep['activity']
385
386 has_known_activity = activity in ACTIVITIES
387 has_known_subactivity = (has_known_activity and ('subactivity' in pep)
388 and (pep['subactivity'] in ACTIVITIES[activity]))
389
390 if has_known_activity:
391 if has_known_subactivity:
392 subactivity = pep['subactivity']
393 return gtkgui_helpers.load_activity_icon(activity, subactivity).get_pixbuf()
394 else:
395 return gtkgui_helpers.load_activity_icon(activity).get_pixbuf()
396 else:
397 return gtkgui_helpers.load_activity_icon('unknown').get_pixbuf()
398
400 assert not self._retracted
401 pep = self._pep_specific_data
402 activity = pep['activity']
403 subactivity = pep['subactivity'] if 'subactivity' in pep else None
404 text = pep['text'] if 'text' in pep else None
405
406 if activity in ACTIVITIES:
407 # Translate standard activities
408 if subactivity in ACTIVITIES[activity]:
409 subactivity = ACTIVITIES[activity][subactivity]
410 activity = ACTIVITIES[activity]['category']
411
412 markuptext = '<b>' + gobject.markup_escape_text(activity)
413 if subactivity:
414 markuptext += ': ' + gobject.markup_escape_text(subactivity)
415 markuptext += '</b>'
416 if text:
417 markuptext += ' (%s)' % gobject.markup_escape_text(text)
418 return markuptext
419
422 '''XEP-0172: User Nickname'''
423
424 type = 'nickname'
425 namespace = xmpp.NS_NICK
426
428 nick = ''
429 for item in items.getTags('item'):
430 child = item.getTag('nick')
431 if child:
432 nick = child.getData()
433 break
434
435 retracted = items.getTag('retract') or not nick
436 return (nick, retracted)
437
439 nick = '' if self._retracted else self._pep_specific_data
440 for contact in gajim.contacts.get_contacts(account, jid):
441 contact.contact_name = nick
442
448
451 '''XEP-0080: User Location'''
452
453 type = 'location'
454 namespace = xmpp.NS_LOCATION
455
457 location_dict = {}
458
459 for item in items.getTags('item'):
460 location_tag = item.getTag('geoloc')
461 if location_tag:
462 for child in location_tag.getChildren():
463 name = child.getName().strip()
464 data = child.getData().strip()
465 if child.getName() in LOCATION_DATA:
466 location_dict[name] = data
467
468 retracted = items.getTag('retract') or not location_dict
469 return (location_dict, retracted)
470
472 AbstractPEP._update_account(self, account)
473 con = gajim.connections[account].location_info = \
474 self._pep_specific_data
475
477 path = gtkgui_helpers.get_icon_path('gajim-earth')
478 return gtk.gdk.pixbuf_new_from_file(path)
479
481 assert not self._retracted
482 location = self._pep_specific_data
483 location_string = ''
484
485 for entry in location.keys():
486 text = location[entry]
487 text = gobject.markup_escape_text(text)
488 location_string += '\n<b>%(tag)s</b>: %(text)s' % \
489 {'tag': entry.capitalize(), 'text': text}
490
491 return location_string.strip()
492
493
494 SUPPORTED_PERSONAL_USER_EVENTS = [UserMoodPEP, UserTunePEP, UserActivityPEP,
495 UserNicknamePEP, UserLocationPEP]
498
500 self._account = account
501 self._dispatcher = dispatcher
502 self._pubsub_connection = pubsub_connection
503 self.reset_awaiting_pep()
504
506 self.to_be_sent_activity = None
507 self.to_be_sent_mood = None
508 self.to_be_sent_tune = None
509 self.to_be_sent_nick = None
510 self.to_be_sent_location = None
511
513 """
514 Send pep info that were waiting for connection
515 """
516 if self.to_be_sent_activity:
517 self.send_activity(*self.to_be_sent_activity)
518 if self.to_be_sent_mood:
519 self.send_mood(*self.to_be_sent_mood)
520 if self.to_be_sent_tune:
521 self.send_tune(*self.to_be_sent_tune)
522 if self.to_be_sent_nick:
523 self.send_nick(self.to_be_sent_nick)
524 if self.to_be_sent_location:
525 self.send_location(self.to_be_sent_location)
526 self.reset_awaiting_pep()
527
529 ''' Called when we receive <message /> with pubsub event. '''
530 if not msg.getTag('event'):
531 return
532 if msg.getTag('error'):
533 log.debug('PubsubEventCB received error stanza. Ignoring')
534 raise xmpp.NodeProcessed
535
536 jid = helpers.get_full_jid_from_iq(msg)
537 event_tag = msg.getTag('event')
538
539 for pep_class in SUPPORTED_PERSONAL_USER_EVENTS:
540 pep = pep_class.get_tag_as_PEP(jid, self._account, event_tag)
541 if pep:
542 self._dispatcher.dispatch('PEP_RECEIVED', (jid, pep.type))
543
544 items = event_tag.getTag('items')
545 if items:
546 for item in items.getTags('item'):
547 entry = item.getTag('entry', namespace=xmpp.NS_ATOM)
548 if entry:
549 # for each entry in feed (there shouldn't be more than one,
550 # but to be sure...
551 self._dispatcher.dispatch('ATOM_ENTRY',
552 (atom.OldEntry(node=entry),))
553
554 raise xmpp.NodeProcessed
555
557 if self.connected == 1:
558 # We are connecting, keep activity in mem and send it when we'll be
559 # connected
560 self.to_be_sent_activity = (activity, subactivity, message)
561 return
562 if not self.pep_supported:
563 return
564 item = xmpp.Node('activity', {'xmlns': xmpp.NS_ACTIVITY})
565 if activity:
566 i = item.addChild(activity)
567 if subactivity:
568 i.addChild(subactivity)
569 if message:
570 i = item.addChild('text')
571 i.addData(message)
572 self._pubsub_connection.send_pb_publish('', xmpp.NS_ACTIVITY, item, '0')
573
575 if not self.pep_supported:
576 return
577 self.send_activity(None)
578 # not all client support new XEP, so we still retract
579 self._pubsub_connection.send_pb_retract('', xmpp.NS_ACTIVITY, '0')
580
582 if self.connected == 1:
583 # We are connecting, keep mood in mem and send it when we'll be
584 # connected
585 self.to_be_sent_mood = (mood, message)
586 return
587 if not self.pep_supported:
588 return
589 item = xmpp.Node('mood', {'xmlns': xmpp.NS_MOOD})
590 if mood:
591 item.addChild(mood)
592 if message:
593 i = item.addChild('text')
594 i.addData(message)
595 self._pubsub_connection.send_pb_publish('', xmpp.NS_MOOD, item, '0')
596
598 if not self.pep_supported:
599 return
600 self.send_mood(None)
601 # not all client support new XEP, so we still retract
602 self._pubsub_connection.send_pb_retract('', xmpp.NS_MOOD, '0')
603
606 if self.connected == 1:
607 # We are connecting, keep tune in mem and send it when we'll be
608 # connected
609 self.to_be_sent_tune = (artist, title, source, track, length, items)
610 return
611 if not self.pep_supported:
612 return
613 item = xmpp.Node('tune', {'xmlns': xmpp.NS_TUNE})
614 if artist:
615 i = item.addChild('artist')
616 i.addData(artist)
617 if title:
618 i = item.addChild('title')
619 i.addData(title)
620 if source:
621 i = item.addChild('source')
622 i.addData(source)
623 if track:
624 i = item.addChild('track')
625 i.addData(track)
626 if length:
627 i = item.addChild('length')
628 i.addData(length)
629 if items:
630 item.addChild(payload=items)
631 self._pubsub_connection.send_pb_publish('', xmpp.NS_TUNE, item, '0')
632
634 if not self.pep_supported:
635 return
636 self.send_tune(None)
637 # not all client support new XEP, so we still retract
638 self._pubsub_connection.send_pb_retract('', xmpp.NS_TUNE, '0')
639
641 if self.connected == 1:
642 # We are connecting, keep nick in mem and send it when we'll be
643 # connected
644 self.to_be_sent_nick = nick
645 return
646 if not self.pep_supported:
647 return
648 item = xmpp.Node('nick', {'xmlns': xmpp.NS_NICK})
649 item.addData(nick)
650 self._pubsub_connection.send_pb_publish('', xmpp.NS_NICK, item, '0')
651
653 if not self.pep_supported:
654 return
655 self.send_nickname(None)
656 # not all client support new XEP, so we still retract
657 self._pubsub_connection.send_pb_retract('', xmpp.NS_NICK, '0')
658
660 if self.connected == 1:
661 # We are connecting, keep location in mem and send it when we'll be
662 # connected
663 self.to_be_sent_location = info
664 return
665 if not self.pep_supported:
666 return
667 item = xmpp.Node('geoloc', {'xmlns': xmpp.NS_LOCATION})
668 for field in LOCATION_DATA:
669 if info.get(field, None):
670 i = item.addChild(field)
671 i.addData(info[field])
672 self._pubsub_connection.send_pb_publish('', xmpp.NS_LOCATION, item, '0')
673
675 if not self.pep_supported:
676 return
677 self.send_location({})
678 # not all client support new XEP, so we still retract
679 self._pubsub_connection.send_pb_retract('', xmpp.NS_LOCATION, '0')
680
| Trees | Indices | Help |
|
|---|
| Generated by Epydoc 3.0.1 on Thu Aug 12 02:07:58 2010 | http://epydoc.sourceforge.net |