def command_accept(self, args): """ Accept a JID from in roster. Authorize it AND subscribe to it """ if not args: item = self.roster_win.selected_row if isinstance(item, Contact): jid = item.bare_jid else: self.core.information('No subscription to accept') return else: jid = safeJID(args[0]).bare nodepart = safeJID(jid).user jid = safeJID(jid) # crappy transports putting resources inside the node part if '\\2f' in nodepart: jid.user = nodepart.split('\\2f')[0] contact = roster[jid] if contact is None: return contact.pending_in = False roster.modified() self.core.xmpp.send_presence(pto=jid, ptype='subscribed') self.core.xmpp.client_roster.send_last_presence() if contact.subscription in ('from', 'none') and not contact.pending_out: self.core.xmpp.send_presence(pto=jid, ptype='subscribe', pnick=self.core.own_nick) self.core.information('%s is now authorized' % jid, 'Roster')
def on_mood_event(self, message): """ Called when a pep notification for an user mood is received. """ contact = roster[message['from'].bare] if not contact: return roster.modified() item = message['pubsub_event']['items']['item'] old_mood = contact.mood if item.xml.find('{http://jabber.org/protocol/mood}mood'): mood = item['mood']['value'] if mood: mood = pep.MOODS.get(mood, mood) text = item['mood']['text'] if text: mood = '%s (%s)' % (mood, text) contact.mood = mood else: contact.mood = '' else: contact.mood = '' if contact.mood: logger.log_roster_change(contact.bare_jid, 'has now the mood: %s' % contact.mood) if old_mood != contact.mood and config.get_by_tabname('display_mood_notifications', contact.bare_jid): if contact.mood: self.information('Mood from '+ contact.bare_jid + ': ' + contact.mood, 'Mood') else: self.information(contact.bare_jid + ' stopped having his/her mood.', 'Mood')
def on_got_online(self, presence): """ A JID got online """ if presence.match('presence/muc') or presence.xml.find('{http://jabber.org/protocol/muc#user}x'): return jid = presence['from'] contact = roster[jid.bare] if contact is None: # Todo, handle presence coming from contacts not in roster return roster.modified() if not logger.log_roster_change(jid.bare, 'got online'): self.information(_('Unable to write in the log file'), 'Error') resource = Resource(jid.full, { 'priority': presence.get_priority() or 0, 'status': presence['status'], 'show': presence['show'], }) self.events.trigger('normal_presence', presence, resource) self.add_information_message_to_conversation_tab(jid.full, '\x195}%s is \x194}online' % (jid.full)) if time.time() - self.connection_time > 10: # We do not display messages if we recently logged in if presence['status']: self.information("\x193}%s \x195}is \x194}online\x195} (\x19o%s\x195})" % (safeJID(resource.jid).bare, presence['status']), "Roster") else: self.information("\x193}%s \x195}is \x194}online\x195}" % safeJID(resource.jid).bare, "Roster") self.add_information_message_to_conversation_tab(jid.bare, '\x195}%s is \x194}online' % (jid.bare)) if isinstance(self.current_tab(), tabs.RosterInfoTab): self.refresh_window()
def on_tune_event(self, message): """ Called when a pep notification for an user tune is received """ contact = roster[message['from'].bare] if not contact: return roster.modified() item = message['pubsub_event']['items']['item'] old_tune = contact.tune if item.xml.find('{http://jabber.org/protocol/tune}tune'): item = item['tune'] contact.tune = { 'artist': item['artist'], 'length': item['length'], 'rating': item['rating'], 'source': item['source'], 'title': item['title'], 'track': item['track'], 'uri': item['uri'] } else: contact.tune = {} if contact.tune: logger.log_roster_change(message['from'].bare, 'is now listening to %s' % common.format_tune_string(contact.tune)) if old_tune != contact.tune and config.get_by_tabname('display_tune_notifications', contact.bare_jid): if contact.tune: self.information( 'Tune from '+ message['from'].bare + ': ' + common.format_tune_string(contact.tune), 'Tune') else: self.information(contact.bare_jid + ' stopped listening to music.', 'Tune')
def command_groupmove(self, args): """ Remove the specified JID from the first specified group and add it to the second one """ if args is None: return self.core.command_help('groupmove') jid = safeJID(args[0]).bare group_from = args[1] group_to = args[2] contact = roster[jid] if not contact: self.core.information(_('No such JID in roster'), 'Error') return new_groups = set(contact.groups) if 'none' in new_groups: new_groups.remove('none') if group_to == 'none' or group_from == 'none': self.core.information(_('"none" is not a group.'), 'Error') return if group_from not in new_groups: self.core.information(_('JID not in first group'), 'Error') return if group_to in new_groups: self.core.information(_('JID already in second group'), 'Error') return if group_to == group_from: self.core.information(_('The groups are the same.'), 'Error') return roster.modified() new_groups.add(group_to) if 'none' in new_groups: new_groups.remove('none') new_groups.remove(group_from) name = contact.name subscription = contact.subscription def callback(iq): if iq: roster.update_contact_groups(contact) else: self.core.information('The group could not be set') log.debug('Error in groupmove:\n%s', iq) self.core.xmpp.update_roster(jid, name=name, groups=new_groups, subscription=subscription, callback=callback)
def on_subscription_remove(self, presence): """unsubscribe received""" jid = presence['from'].bare contact = roster[jid] if not contact: return roster.modified() self.information('%s does not want to receive your status anymore.' % jid, 'Roster') self.get_tab_by_number(0).state = 'highlight' if isinstance(self.current_tab(), tabs.RosterInfoTab): self.refresh_window()
def on_presence_error(self, presence): jid = presence['from'] contact = roster[jid.bare] if not contact: return roster.modified() contact.error = presence['error']['type'] + ': ' + presence['error']['condition'] # reset chat states status on presence error tab = self.get_tab_by_name(jid.full, tabs.ConversationTab) if tab: tab.remote_wants_chatstates = None
def toggle_offline_show(self): """ Show or hide offline contacts """ option = 'roster_show_offline' value = config.get(option) success = config.silent_set(option, str(not value)) roster.modified() if not success: self.core.information('Unable to write in the config file', 'Error') return True
def start_search(self): """ Start the search. The input should appear with a short instruction in it. """ curses.curs_set(1) self.input = windows.CommandInput("[Search]", self.on_search_terminate, self.on_search_terminate, self.set_roster_filter) self.input.resize(1, self.width, self.height-1, 0) self.input.disable_history() roster.modified() self.refresh() return True
def toggle_offline_show(self): """ Show or hide offline contacts """ option = 'roster_show_offline' value = config.get(option) success = config.silent_set(option, str(not value)) roster.modified() if not success: self.core.information(_('Unable to write in the config file'), 'Error') return True
def command_groupmove(self, args): """ Remove the specified JID from the first specified group and add it to the second one """ if args is None: return self.core.command_help('groupmove') jid = safeJID(args[0]).bare group_from = args[1] group_to = args[2] contact = roster[jid] if not contact: self.core.information('No such JID in roster', 'Error') return new_groups = set(contact.groups) if 'none' in new_groups: new_groups.remove('none') if group_to == 'none' or group_from == 'none': self.core.information('"none" is not a group.', 'Error') return if group_from not in new_groups: self.core.information('JID not in first group', 'Error') return if group_to in new_groups: self.core.information('JID already in second group', 'Error') return if group_to == group_from: self.core.information('The groups are the same.', 'Error') return roster.modified() new_groups.add(group_to) if 'none' in new_groups: new_groups.remove('none') new_groups.remove(group_from) name = contact.name subscription = contact.subscription def callback(iq): if iq: roster.update_contact_groups(contact) else: self.core.information('The group could not be set') log.debug('Error in groupmove:\n%s', iq) self.core.xmpp.update_roster(jid, name=name, groups=new_groups, subscription=subscription, callback=callback)
def on_subscription_authorized(self, presence): """subscribed received""" jid = presence['from'].bare contact = roster[jid] if contact.subscription not in ('both', 'from'): self.information('%s accepted your contact proposal' % jid, 'Roster') if contact.pending_out: contact.pending_out = False roster.modified() if isinstance(self.current_tab(), tabs.RosterInfoTab): self.refresh_window()
def on_disconnected(self, event): """ When we are disconnected from remote server """ # Stop the ping plugin. It would try to send stanza on regular basis self.xmpp.plugin['xep_0199'].disable_keepalive() roster.modified() for tab in self.get_tabs(tabs.MucTab): tab.disconnect() self.information(_("Disconnected from server."), _('Error')) if not self.legitimate_disconnect and config.get('auto_reconnect', True): self.information(_("Auto-reconnecting."), _('Info')) self.xmpp.connect()
def command_add(self, args): """ Add the specified JID to the roster, and set automatically accept the reverse subscription """ jid = safeJID(safeJID(args[0]).bare) if not jid: self.core.information(_('No JID specified'), 'Error') return if jid in roster and roster[jid].subscription in ('to', 'both'): return self.core.information('Already subscribed.', 'Roster') roster.add(jid) roster.modified() self.core.information('%s was added to the roster' % jid, 'Roster')
def start_search(self): """ Start the search. The input should appear with a short instruction in it. """ curses.curs_set(1) self.input = windows.CommandInput("[Search]", self.on_search_terminate, self.on_search_terminate, self.set_roster_filter) self.input.resize(1, self.width, self.height - 1, 0) self.input.disable_history() roster.modified() self.refresh() return True
def on_subscription_removed(self, presence): """unsubscribed received""" jid = presence['from'].bare contact = roster[jid] if not contact: return roster.modified() if contact.pending_out: self.information('%s rejected your contact proposal' % jid, 'Roster') contact.pending_out = False else: self.information('%s does not want you to receive his/her/its status anymore.'%jid, 'Roster') self.get_tab_by_number(0).state = 'highlight' if isinstance(self.current_tab(), tabs.RosterInfoTab): self.refresh_window()
def on_got_offline(self, presence): """ A JID got offline """ if presence.match('presence/muc') or presence.xml.find('{http://jabber.org/protocol/muc#user}x'): return jid = presence['from'] if not logger.log_roster_change(jid.bare, 'got offline'): self.information(_('Unable to write in the log file'), 'Error') # If a resource got offline, display the message in the conversation with this # precise resource. if jid.resource: self.add_information_message_to_conversation_tab(jid.full, '\x195}%s is \x191}offline' % (jid.full)) self.add_information_message_to_conversation_tab(jid.bare, '\x195}%s is \x191}offline' % (jid.bare)) self.information('\x193}%s \x195}is \x191}offline' % (jid.bare), 'Roster') roster.modified() if isinstance(self.current_tab(), tabs.RosterInfoTab): self.refresh_window()
def on_subscription_request(self, presence): """subscribe received""" jid = presence['from'].bare contact = roster[jid] if contact and contact.subscription in ('from', 'both'): return elif contact and contact.subscription == 'to': self.xmpp.sendPresence(pto=jid, ptype='subscribed') self.xmpp.sendPresence(pto=jid) else: if not contact: contact = roster.get_and_set(jid) roster.update_contact_groups(contact) contact.pending_in = True self.information('%s wants to subscribe to your presence' % jid, 'Roster') self.get_tab_by_number(0).state = 'highlight' roster.modified() if isinstance(self.current_tab(), tabs.RosterInfoTab): self.refresh_window()
def command_groupremove(self, args): """ Remove the specified JID from the specified group """ if args is None: return self.core.command_help('groupremove') jid = safeJID(args[0]).bare group = args[1] contact = roster[jid] if contact is None: self.core.information(_('No such JID in roster'), 'Error') return new_groups = set(contact.groups) try: new_groups.remove('none') except KeyError: pass if group not in new_groups: self.core.information(_('JID not in group'), 'Error') return roster.modified() new_groups.remove(group) name = contact.name subscription = contact.subscription def callback(iq): if iq: roster.update_contact_groups(jid) else: self.core.information('The group could not be set') log.debug('Error in groupremove:\n%s', iq) self.core.xmpp.update_roster(jid, name=name, groups=new_groups, subscription=subscription, callback=callback)
def on_presence(self, presence): if presence.match('presence/muc') or presence.xml.find('{http://jabber.org/protocol/muc#user}x'): return jid = presence['from'] contact = roster[jid.bare] tab = self.get_conversation_by_jid(jid, create=False) if isinstance(tab, tabs.DynamicConversationTab): if tab.get_dest_jid() != jid.full: tab.unlock(from_=jid.full) elif presence['type'] == 'unavailable': tab.unlock() if contact is None: return roster.modified() contact.error = None self.events.trigger('normal_presence', presence, contact[jid.full]) tab = self.get_conversation_by_jid(jid, create=False) if isinstance(self.current_tab(), tabs.RosterInfoTab): self.refresh_window() elif self.current_tab() == tab: tab.refresh() self.doupdate()
def on_space(self): if isinstance(self.input, windows.Input): return selected_row = self.roster_win.get_selected_row() if isinstance(selected_row, RosterGroup): selected_row.toggle_folded() roster.modified() return True elif isinstance(selected_row, Contact): group = "none" found_group = False pos = self.roster_win.pos while not found_group and pos >= 0: row = self.roster_win.roster_cache[pos] pos -= 1 if isinstance(row, RosterGroup): found_group = True group = row.name selected_row.toggle_folded(group) roster.modified() return True return False
def command_groupremove(self, args): """ Remove the specified JID from the specified group """ if args is None: return self.core.command_help('groupremove') jid = safeJID(args[0]).bare group = args[1] contact = roster[jid] if contact is None: self.core.information('No such JID in roster', 'Error') return new_groups = set(contact.groups) try: new_groups.remove('none') except KeyError: pass if group not in new_groups: self.core.information('JID not in group', 'Error') return roster.modified() new_groups.remove(group) name = contact.name subscription = contact.subscription def callback(iq): if iq: roster.update_contact_groups(jid) else: self.core.information('The group could not be set') log.debug('Error in groupremove:\n%s', iq) self.core.xmpp.update_roster(jid, name=name, groups=new_groups, subscription=subscription, callback=callback)
def on_activity_event(self, message): """ Called when a pep notification for an user activity is received. """ contact = roster[message['from'].bare] if not contact: return roster.modified() item = message['pubsub_event']['items']['item'] old_activity = contact.activity if item.xml.find('{http://jabber.org/protocol/activity}activity'): try: activity = item['activity']['value'] except ValueError: return if activity[0]: general = pep.ACTIVITIES.get(activity[0]) s = general['category'] if activity[1]: s = s + '/' + general.get(activity[1], 'other') text = item['activity']['text'] if text: s = '%s (%s)' % (s, text) contact.activity = s else: contact.activity = '' else: contact.activity = '' if contact.activity: logger.log_roster_change(contact.bare_jid, 'has now the activity %s' % contact.activity) if old_activity != contact.activity and config.get_by_tabname('display_activity_notifications', contact.bare_jid): if contact.activity: self.information('Activity from '+ contact.bare_jid + ': ' + contact.activity, 'Activity') else: self.information(contact.bare_jid + ' stopped doing his/her activity.', 'Activity')
def set_roster_filter(self, txt): roster.contact_filter = (jid_and_name_match, txt) roster.modified() self.refresh() return False
def on_search_terminate(self, txt): curses.curs_set(0) roster.contact_filter = None self.reset_help_message() roster.modified() return True