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 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', 'Warning') 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 command_add(self, args): """ Add the specified JID to the roster, and automatically accept the reverse subscription """ if args is None: tab = self.core.tabs.current_tab ConversationTab = tabs.ConversationTab if isinstance(tab, ConversationTab): jid = tab.general_jid if jid in roster and roster[jid].subscription in ('to', 'both'): return self.core.information('Already subscribed.', 'Roster') roster.add(jid) roster.modified() return self.core.information( '%s was added to the roster' % jid, 'Roster') else: return self.core.information('No JID specified', 'Error') jid = safeJID(safeJID(args[0]).bare) if not str(jid): self.core.information( 'The provided JID (%s) is not valid' % (args[0], ), '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 join(self, the_input): """ Completion for /join Try to complete the MUC JID: if only a resource is provided, complete with the default nick if only a server is provided, complete with the rooms from the disco#items of that server if only a nodepart is provided, complete with the servers of the current joined rooms """ n = the_input.get_argument_position(quoted=True) args = common.shell_split(the_input.text) if n != 1: # we are not on the 1st argument of the command line return False if len(args) == 1: args.append('') jid = safeJID(args[1]) if args[1].endswith('@') and not jid.user and not jid.server: jid.user = args[1][:-1] relevant_rooms = [] relevant_rooms.extend(sorted(self.core.pending_invites.keys())) bookmarks = [(str(elem.jid) if not elem.nick else '%s/%s' % (elem.jid, elem.nick)) for elem in self.core.bookmarks] to_suggest = [] for bookmark in bookmarks: tab = self.core.tabs.by_name_and_class(bookmark, tabs.MucTab) if not tab or (tab and not tab.joined): to_suggest.append(bookmark) relevant_rooms.extend(sorted(to_suggest)) if the_input.last_completion: return Completion(the_input.new_completion, [], 1, quotify=True) if jid.user: # we are writing the server: complete the server serv_list = [] for tab in self.core.get_tabs(tabs.MucTab): if tab.joined: serv_list.append('%s@%s' % (jid.user, safeJID(tab.name).host)) serv_list.extend(relevant_rooms) return Completion(the_input.new_completion, serv_list, 1, quotify=True) elif args[1].startswith('/'): # we completing only a resource return Completion(the_input.new_completion, ['/%s' % self.core.own_nick], 1, quotify=True) else: return Completion(the_input.new_completion, relevant_rooms, 1, quotify=True)
def join(self, the_input): """ Completion for /join Try to complete the MUC JID: if only a resource is provided, complete with the default nick if only a server is provided, complete with the rooms from the disco#items of that server if only a nodepart is provided, complete with the servers of the current joined rooms """ n = the_input.get_argument_position(quoted=True) args = common.shell_split(the_input.text) if n != 1: # we are not on the 1st argument of the command line return False if len(args) == 1: args.append('') jid = safeJID(args[1]) if args[1].endswith('@') and not jid.user and not jid.server: jid.user = args[1][:-1] relevant_rooms = [] relevant_rooms.extend(sorted(self.core.pending_invites.keys())) bookmarks = [(str(elem.jid) if not elem.nick else '%s/%s' % (elem.jid, elem.nick)) for elem in self.core.bookmarks] to_suggest = [] for bookmark in bookmarks: tab = self.core.tabs.by_name_and_class(bookmark, tabs.MucTab) if not tab or (tab and not tab.joined): to_suggest.append(bookmark) relevant_rooms.extend(sorted(to_suggest)) if the_input.last_completion: return Completion(the_input.new_completion, [], 1, quotify=True) if jid.user: # we are writing the server: complete the server serv_list = [] for tab in self.core.get_tabs(tabs.MucTab): if tab.joined: serv_list.append( '%s@%s' % (jid.user, safeJID(tab.name).host)) serv_list.extend(relevant_rooms) return Completion( the_input.new_completion, serv_list, 1, quotify=True) elif args[1].startswith('/'): # we completing only a resource return Completion( the_input.new_completion, ['/%s' % self.core.own_nick], 1, quotify=True) else: return Completion( the_input.new_completion, relevant_rooms, 1, quotify=True)
def command_muc_ping(self, arg): if not arg: return user = self.api.current_tab().get_user_by_name(arg) if user: jid = safeJID(self.api.current_tab().name) jid.resource = user.nick else: jid = safeJID(arg) self.command_ping(jid.full)
def invite(self, args): """/invite <to> <room> [reason]""" if args is None: return self.help('invite') reason = args[2] to = safeJID(args[0]) room = safeJID(args[1]).bare self.core.invite(to.full, room, reason=reason) self.core.information('Invited %s to %s' % (to.bare, room), 'Info')
def match(self, xml): from_ = safeJID(xml['from']) to_ = safeJID(xml['to']) if self.jid.full == self.jid.bare: from_ = from_.bare to_ = to_.bare if self.dest == 'from': return from_ == self.jid elif self.dest == 'to': return to_ == self.jid return self.jid in (from_, to_)
def command_smp(self, args): """ /otrsmp <ask|answer|abort> [question] [secret] """ if args is None or not args: return self.core.command.help('otrsmp') length = len(args) action = args.pop(0) if length == 2: question = None secret = args.pop(0).encode('utf-8') elif length == 3: question = args.pop(0).encode('utf-8') secret = args.pop(0).encode('utf-8') else: question = secret = None tab = self.api.current_tab() name = tab.name if isinstance(tab, DynamicConversationTab) and tab.locked_resource: name = safeJID(tab.name) name.resource = tab.locked_resource name = name.full format_dict = { 'jid_c': '\x19%s}' % dump_tuple(get_theme().COLOR_MUC_JID), 'info': '\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT), 'jid': name, 'bare_jid': safeJID(name).bare } ctx = self.get_context(name) if ctx.state != STATE_ENCRYPTED: self.api.information('The current conversation is not encrypted', 'Error') return if action == 'ask': ctx.in_smp = True ctx.smp_own = True if question: ctx.smpInit(secret, question) else: ctx.smpInit(secret) tab.add_message(SMP_INITIATED % format_dict, typ=0) elif action == 'answer': ctx.smpGotSecret(secret) elif action == 'abort': if ctx.in_smp: ctx.smpAbort() tab.add_message(SMP_ABORTED % format_dict, typ=0) self.core.refresh_window()
def on_conversation_say(self, msg, tab): """ On message sent """ if isinstance(tab, DynamicConversationTab) and tab.locked_resource: jid = safeJID(tab.name) jid.resource = tab.locked_resource name = jid.full else: name = tab.name jid = safeJID(tab.name) format_dict = { 'jid_c': '\x19%s}' % dump_tuple(get_theme().COLOR_MUC_JID), 'info': '\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT), 'jid': name, } ctx = None default_ctx = self.get_context(name) if isinstance(tab, DynamicConversationTab) and not tab.locked_resource: log.debug('Unlocked tab %s found, falling back to the first encrypted chat we find.', name) ctx = self.find_encrypted_context_with_matching(jid.bare) if ctx is None: ctx = default_ctx if ctx and ctx.state == STATE_ENCRYPTED: ctx.sendMessage(0, msg['body'].encode('utf-8')) if not tab.send_chat_state('active'): tab.send_chat_state('inactive', always_send=True) tab.add_message(msg['body'], nickname=self.core.own_nick or tab.own_nick, nick_color=get_theme().COLOR_OWN_NICK, identifier=msg['id'], jid=self.core.xmpp.boundjid, typ=ctx.log) # remove everything from the message so that it doesn’t get sent del msg['body'] del msg['replace'] del msg['html'] elif ctx and ctx.getPolicy('REQUIRE_ENCRYPTION'): tab.add_message(MESSAGE_NOT_SENT % format_dict, typ=0) del msg['body'] del msg['replace'] del msg['html'] self.otr_start(tab, name, format_dict)
def command_name(self, args): """ Set a name for the specified JID in your roster """ def callback(iq): if not iq: self.core.information('The name could not be set.', 'Error') log.debug('Error in /name:\n%s', iq) if args is None: return self.core.command.help('name') jid = safeJID(args[0]).bare name = args[1] if len(args) == 2 else '' contact = roster[jid] if contact is None: self.core.information('No such JID in roster', 'Error') return groups = set(contact.groups) if 'none' in groups: groups.remove('none') subscription = contact.subscription self.core.xmpp.update_roster(jid, name=name, groups=groups, subscription=subscription, callback=callback)
def get_current_tab_irc_info(self): """ Return a tuple with the irc server and the gateway hostnames of the current tab. If the current tab is not an IRC channel or private conversation, a warning is displayed and None is returned """ gateway = self.config.get('gateway', 'irc.poez.io') current = self.core.current_tab() current_jid = common.safeJID(current.name) if not current_jid.server == gateway: self.api.information( 'The current tab does not appear to be an IRC one', 'Warning') return None if isinstance(current, tabs.OneToOneTab): if '%' not in current_jid.node: server = current_jid.node else: ignored, server = current_jid.node.rsplit('%', 1) elif isinstance(current, tabs.MucTab): if '%' not in current_jid.node: server = current_jid.node else: ignored, server = current_jid.node.rsplit('%', 1) else: self.api.information( 'The current tab does not appear to be an IRC one', 'Warning') return None return server, gateway
def __init__(self, core, name, nick): OneToOneTab.__init__(self, core, name) self.own_nick = nick self.name = name self.text_win = windows.TextWin() self._text_buffer.add_window(self.text_win) self.info_header = windows.PrivateInfoWin() self.input = windows.MessageInput() # keys self.key_func['^I'] = self.completion # commands self.register_command( 'info', self.command_info, desc= 'Display some information about the user in the MUC: its/his/her role, affiliation, status and status message.', shortdesc='Info about the user.') self.register_command( 'version', self.command_version, desc= 'Get the software version of the current interlocutor (usually its XMPP client and Operating System).', shortdesc='Get the software version of a jid.') self.resize() self.parent_muc = self.core.tabs.by_name_and_class( safeJID(name).bare, MucTab) self.on = True self.update_commands() self.update_keys()
def _empty_join(self): tab = self.core.tabs.current_tab if not isinstance(tab, (tabs.MucTab, tabs.PrivateTab)): return (None, None) room = safeJID(tab.name).bare nick = tab.own_nick return (room, nick)
def command_name(self, args): """ Set a name for the specified JID in your roster """ def callback(iq): if not iq: self.core.information('The name could not be set.', 'Error') log.debug('Error in /name:\n%s', iq) if args is None: return self.core.command.help('name') jid = safeJID(args[0]).bare name = args[1] if len(args) == 2 else '' contact = roster[jid] if contact is None: self.core.information('No such JID in roster', 'Error') return groups = set(contact.groups) if 'none' in groups: groups.remove('none') subscription = contact.subscription self.core.xmpp.update_roster( jid, name=name, groups=groups, subscription=subscription, callback=callback)
def server_cycle(self, args): """ Do a /cycle on each room of the given server. If none, do it on the server of the current tab """ tab = self.core.tabs.current_tab message = "" if args: try: domain = JID(args[0]).domain except InvalidJID: return self.core.information( "Invalid server domain: %s" % args[0], "Error" ) if len(args) == 2: message = args[1] else: if isinstance(tab, tabs.MucTab): domain = safeJID(tab.name).domain else: return self.core.information("No server specified", "Error") for tab in self.core.get_tabs(tabs.MucTab): if JID(tab.name).domain == domain: tab.leave_room(message) tab.join()
def set_user_affiliation( xmpp: ClientXMPP, muc_jid: JID, affiliation: str, callback: Callable[[Iq], None], nick: Optional[str] = None, jid: Optional[JID] = None, reason: Optional[str] = None ) -> None: """ (try to) Set the affiliation of a MUC user """ muc_jid = safeJID(muc_jid) query = ET.Element('{http://jabber.org/protocol/muc#admin}query') if nick: item = ET.Element('{http://jabber.org/protocol/muc#admin}item', { 'affiliation': affiliation, 'nick': nick }) else: item = ET.Element('{http://jabber.org/protocol/muc#admin}item', { 'affiliation': affiliation, 'jid': str(jid) }) if reason: reason_item = ET.Element( '{http://jabber.org/protocol/muc#admin}reason') reason_item.text = reason item.append(reason_item) query.append(item) iq = xmpp.make_iq_set(query) iq['to'] = muc_jid iq.send(callback=callback)
def log_message(self, txt, nickname, time=None, typ=1): """ Log the messages in the archives. """ name = safeJID(self.name).bare if not logger.log_message(name, nickname, txt, date=time, typ=typ): self.core.information('Unable to write in the log file', 'Error')
def set_user_affiliation(xmpp, muc_jid, affiliation, nick=None, jid=None, reason=None, callback=None): """ (try to) Set the affiliation of a MUC user """ muc_jid = safeJID(muc_jid) query = ET.Element('{http://jabber.org/protocol/muc#admin}query') if nick: item = ET.Element('{http://jabber.org/protocol/muc#admin}item', {'affiliation':affiliation, 'nick':nick}) else: item = ET.Element('{http://jabber.org/protocol/muc#admin}item', {'affiliation':affiliation, 'jid':str(jid)}) if reason: reason_item = ET.Element('{http://jabber.org/protocol/muc#admin}reason') reason_item.text = reason item.append(reason_item) query.append(item) iq = xmpp.make_iq_set(query) iq['to'] = muc_jid if callback: return iq.send(callback=callback) try: return xmpp.plugin['xep_0045'].setAffiliation(str(muc_jid), str(jid) if jid else None, nick, affiliation) except: import traceback log.debug('Error setting the affiliation: %s', traceback.format_exc()) return False
def _add_bookmark(self, jid, autojoin, password, method): nick = None if not jid: tab = self.core.tabs.current_tab roomname = tab.jid.bare if tab.joined and tab.own_nick != self.core.own_nick: nick = tab.own_nick if password is None and tab.password is not None: password = tab.password elif jid == '*': return self._add_wildcard_bookmarks(method) else: info = safeJID(jid) roomname, nick = info.bare, info.resource if roomname == '': tab = self.core.tabs.current_tab if not isinstance(tab, tabs.MucTab): return roomname = tab.jid.bare bookmark = self.core.bookmarks[roomname] if bookmark is None: bookmark = Bookmark(roomname) self.core.bookmarks.append(bookmark) bookmark.method = method bookmark.autojoin = autojoin if nick: bookmark.nick = nick if password: bookmark.password = password self.core.bookmarks.save_local() self.core.bookmarks.save_remote(self.core.xmpp, self.core.handler.on_bookmark_result)
def __init__(self, core, jid): assert (safeJID(jid).resource) ConversationTab.__init__(self, core, jid) self.info_header = windows.ConversationInfoWin() self.resize() self.update_commands() self.update_keys()
def version(self, args): """ /version <jid> """ def callback(res): "Callback for /version" if not res: return self.core.information('Could not get the software' ' version from %s' % jid, 'Warning') version = '%s is running %s version %s on %s' % ( jid, res.get('name') or 'an unknown software', res.get('version') or 'unknown', res.get('os') or 'an unknown platform') self.core.information(version, 'Info') if args is None: return self.help('version') jid = safeJID(args[0]) if jid.resource or jid not in roster or not roster[jid].resources: fixes.get_version(self.core.xmpp, jid, callback=callback) elif jid in roster: for resource in roster[jid].resources: fixes.get_version(self.core.xmpp, resource.jid, callback=callback)
def _add_bookmark(self, jid, autojoin, password, method): nick = None if not jid: tab = self.core.tabs.current_tab roomname = tab.name if tab.joined and tab.own_nick != self.core.own_nick: nick = tab.own_nick if password is None and tab.password is not None: password = tab.password elif jid == '*': return self._add_wildcard_bookmarks(method) else: info = safeJID(jid) roomname, nick = info.bare, info.resource if roomname == '': tab = self.core.tabs.current_tab if not isinstance(tab, tabs.MucTab): return roomname = tab.name bookmark = self.core.bookmarks[roomname] if bookmark is None: bookmark = Bookmark(roomname) self.core.bookmarks.append(bookmark) bookmark.method = method bookmark.autojoin = autojoin if nick: bookmark.nick = nick if password: bookmark.password = password self.core.bookmarks.save_local() self.core.bookmarks.save_remote(self.core.xmpp, self.core.handler.on_bookmark_result)
def write_room_name(self, name): jid = safeJID(name) room_name, nick = jid.bare, jid.resource theme = get_theme() self.addstr(nick, to_curses_attr(theme.COLOR_PRIVATE_NAME)) txt = ' from room %s' % room_name self.addstr(txt, to_curses_attr(theme.COLOR_INFORMATION_BAR))
def server_cycle(self, args): """ Do a /cycle on each room of the given server. If none, do it on the current tab """ tab = self.core.current_tab() message = "" if args: domain = args[0] if len(args) == 2: message = args[1] else: if isinstance(tab, tabs.MucTab): domain = safeJID(tab.name).domain else: return self.core.information("No server specified", "Error") for tab in self.core.get_tabs(tabs.MucTab): if tab.name.endswith(domain): if tab.joined: muc.leave_groupchat(tab.core.xmpp, tab.name, tab.own_nick, message) tab.joined = False if tab.name == domain: self.join('"@%s/%s"' %(tab.name, tab.own_nick)) else: self.join('"%s/%s"' %(tab.name, tab.own_nick))
def callback(iq): if iq['type'] != 'result': if iq['error']['type'] == 'auth': self.core.information( 'You are not allowed to see the activity of this contact.', 'Error') else: self.core.information('Error retrieving the activity', 'Error') return seconds = iq['last_activity']['seconds'] status = iq['last_activity']['status'] from_ = iq['from'] msg = '\x19%s}The last activity of %s was %s ago%s' if not safeJID(from_).user: msg = '\x19%s}The uptime of %s is %s.' % ( dump_tuple(get_theme().COLOR_INFORMATION_TEXT), from_, common.parse_secs_to_str(seconds)) else: msg = '\x19%s}The last activity of %s was %s ago%s' % ( dump_tuple(get_theme().COLOR_INFORMATION_TEXT), from_, common.parse_secs_to_str(seconds), (' and their last status was %s' % status) if status else '', ) self.add_message(msg) self.core.refresh_window()
def completion_server_part(self, the_input): serv_list = set() for tab in self.core.get_tabs(MucTab): if tab.joined: serv = safeJID(tab.name).server serv_list.add(serv) return Completion(the_input.new_completion, sorted(serv_list), 1, ' ')
def on_gain_focus(self): self.state = 'current' curses.curs_set(1) tab = self.core.get_tab_by_name(safeJID(self.name).bare, MucTab) if tab and tab.joined and config.get_by_tabname('send_chat_states', self.general_jid,) and not self.input.get_text() and self.on: self.send_chat_state('active')
def last_activity(self, args): """ /last_activity <jid> """ def callback(iq): "Callback for the last activity" if iq['type'] != 'result': if iq['error']['type'] == 'auth': self.core.information( 'You are not allowed to see the ' 'activity of this contact.', 'Error') else: self.core.information('Error retrieving the activity', 'Error') return seconds = iq['last_activity']['seconds'] status = iq['last_activity']['status'] from_ = iq['from'] if not safeJID(from_).user: msg = 'The uptime of %s is %s.' % ( from_, common.parse_secs_to_str(seconds)) else: msg = 'The last activity of %s was %s ago%s' % ( from_, common.parse_secs_to_str(seconds), (' and his/her last status was %s' % status) if status else '') self.core.information(msg, 'Info') if args is None: return self.help('last_activity') jid = safeJID(args[0]) self.core.xmpp.plugin['xep_0012'].get_last_activity( jid, callback=callback)
def message(self, args): """ /message <jid> [message] """ if args is None: return self.help('message') jid = safeJID(args[0]) if not jid.user and not jid.domain and not jid.resource: return self.core.information('Invalid JID.', 'Error') tab = self.core.get_conversation_by_jid( jid.full, False, fallback_barejid=False) muc = self.core.tabs.by_name_and_class(jid.bare, tabs.MucTab) if not tab and not muc: tab = self.core.open_conversation_window(jid.full, focus=True) elif muc: if jid.resource: tab = self.core.tabs.by_name_and_class(jid.full, tabs.PrivateTab) if tab: self.core.focus_tab(tab) else: tab = self.core.open_private_window(jid.bare, jid.resource) else: tab = muc else: self.core.focus_tab(tab) if len(args) == 2: tab.command_say(args[1])
def destroy_room(xmpp, room, reason='', altroom=''): """ destroy a room """ room = safeJID(room) if not room: return False iq = xmpp.make_iq_set() iq['to'] = room query = ET.Element('{%s}query' % NS_MUC_OWNER) destroy = ET.Element('{%s}destroy' % NS_MUC_OWNER) if altroom: destroy.attrib['jid'] = altroom if reason: xreason = ET.Element('{%s}reason' % NS_MUC_OWNER) xreason.text = reason destroy.append(xreason) query.append(destroy) iq.append(query) def callback(iq): if not iq or iq['type'] == 'error': xmpp.core.information('Unable to destroy room %s' % room, 'Info') else: xmpp.core.information('Room %s destroyed' % room, 'Info') iq.send(callback=callback) return True
def server_cycle(self, the_input): """Completion for /server_cycle""" serv_list = set() for tab in self.core.get_tabs(tabs.MucTab): serv = safeJID(tab.name).server serv_list.add(serv) return Completion(the_input.new_completion, sorted(serv_list), 1, ' ')
def refresh(self, jid, contact, window, chatstate, information): # contact can be None, if we receive a message # from someone not in our roster. In this case, we display # only the maximum information from the message we can get. log.debug('Refresh: %s', self.__class__.__name__) jid = safeJID(jid) if contact: if jid.resource: resource = contact[jid.full] else: resource = contact.get_highest_priority_resource() else: resource = None # if contact is None, then resource is None too: # user is not in the roster so we know almost nothing about it # If contact is a Contact, then # resource can now be a Resource: user is in the roster and online # or resource is None: user is in the roster but offline self._win.erase() if config.get('show_jid_in_conversations'): self.write_contact_jid(jid) self.write_contact_information(contact) self.write_resource_information(resource) self.print_scroll_position(window) self.write_chatstate(chatstate) self.write_additional_information(information, jid) self.finish_line(get_theme().COLOR_INFORMATION_BAR) self._refresh()
def bookmark_local(self, the_input): """Completion for /bookmark_local""" n = the_input.get_argument_position(quoted=True) args = common.shell_split(the_input.text) if n >= 2: return False if len(args) == 1: args.append('') jid = safeJID(args[1]) if jid.server and (jid.resource or jid.full.endswith('/')): tab = self.core.tabs.by_name_and_class(jid.bare, tabs.MucTab) nicks = [tab.own_nick] if tab else [] default = os.environ.get('USER') if os.environ.get( 'USER') else 'poezio' nick = config.get('default_nick') if not nick: if default not in nicks: nicks.append(default) else: if nick not in nicks: nicks.append(nick) jids_list = ['%s/%s' % (jid.bare, nick) for nick in nicks] return Completion( the_input.new_completion, jids_list, 1, quotify=True) muc_list = [tab.name for tab in self.core.get_tabs(tabs.MucTab)] muc_list.append('*') return Completion(the_input.new_completion, muc_list, 1, quotify=True)
def command_info(self): contact = roster[self.get_dest_jid()] jid = safeJID(self.get_dest_jid()) if contact: if jid.resource: resource = contact[jid.full] else: resource = contact.get_highest_priority_resource() else: resource = None if resource: status = ('Status: %s' % resource.status) if resource.status else '' self._text_buffer.add_message( "\x19%(info_col)s}Show: %(show)s, %(status)s\x19o" % { 'show': resource.presence or 'available', 'status': status, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT) }) return True else: self._text_buffer.add_message( "\x19%(info_col)s}No information available\x19o" % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) return True
def on_save(self): self.bookmarks_win.save() if find_duplicates(self.new_bookmarks): self.core.information( 'Duplicate bookmarks in list (saving aborted)', 'Error') return for bm in self.new_bookmarks: if safeJID(bm.jid): if not self.bookmarks[bm.jid]: self.bookmarks.append(bm) else: self.core.information( 'Invalid JID for bookmark: %s/%s' % (bm.jid, bm.nick), 'Error') return for bm in self.removed_bookmarks: if bm in self.bookmarks: self.bookmarks.remove(bm) def send_cb(success): if success: self.core.information('Bookmarks saved.', 'Info') else: self.core.information('Remote bookmarks not saved.', 'Error') self.bookmarks.save(self.core.xmpp, callback=send_cb) self.core.close_tab(self) return True
def get_current_tab_irc_info(self): """ Return a tuple with the irc server and the gateway hostnames of the current tab. If the current tab is not an IRC channel or private conversation, a warning is displayed and None is returned """ gateway = self.config.get('gateway', 'irc.poez.io') current = self.core.current_tab() current_jid = common.safeJID(current.name) if not current_jid.server == gateway: self.api.information('The current tab does not appear to be an IRC one', 'Warning') return None if isinstance(current, tabs.OneToOneTab): if not '%' in current_jid.node: server = current_jid.node else: ignored, server = current_jid.node.rsplit('%', 1) elif isinstance(current, tabs.MucTab): if not '%' in current_jid.node: server = current_jid.node else: ignored, server = current_jid.node.rsplit('%', 1) else: self.api.information('The current tab does not appear to be an IRC one', 'Warning') return None return server, gateway
def bookmark_local(self, the_input): """Completion for /bookmark_local""" n = the_input.get_argument_position(quoted=True) args = common.shell_split(the_input.text) if n >= 2: return False if len(args) == 1: args.append('') jid = safeJID(args[1]) if jid.server and (jid.resource or jid.full.endswith('/')): tab = self.core.get_tab_by_name(jid.bare, tabs.MucTab) nicks = [tab.own_nick] if tab else [] default = os.environ.get('USER') if os.environ.get('USER') else 'poezio' nick = config.get('default_nick') if not nick: if default not in nicks: nicks.append(default) else: if nick not in nicks: nicks.append(nick) jids_list = ['%s/%s' % (jid.bare, nick) for nick in nicks] return Completion(the_input.new_completion, jids_list, 1, quotify=True) muc_list = [tab.name for tab in self.core.get_tabs(tabs.MucTab)] muc_list.append('*') return Completion(the_input.new_completion, muc_list, 1, quotify=True)
def check_features(self): "check the features supported by the other party" if safeJID(self.get_dest_jid()).resource: self.core.xmpp.plugin['xep_0030'].get_info( jid=self.get_dest_jid(), timeout=5, callback=self.features_checked)
def callback(iq): if iq['type'] != 'result': if iq['error']['type'] == 'auth': self.core.information( 'You are not allowed to see the activity of this contact.', 'Error') else: self.core.information('Error retrieving the activity', 'Error') return seconds = iq['last_activity']['seconds'] status = iq['last_activity']['status'] from_ = iq['from'] msg = '\x19%s}The last activity of %s was %s ago%s' if not safeJID(from_).user: msg = '\x19%s}The uptime of %s is %s.' % ( dump_tuple(get_theme().COLOR_INFORMATION_TEXT), from_, common.parse_secs_to_str(seconds)) else: msg = '\x19%s}The last activity of %s was %s ago%s' % ( dump_tuple(get_theme().COLOR_INFORMATION_TEXT), from_, common.parse_secs_to_str(seconds), (' and his/her last status was %s' % status) if status else '', ) self.add_message(msg) self.core.refresh_window()
def command_info(self): contact = roster[self.get_dest_jid()] jid = safeJID(self.get_dest_jid()) if contact: if jid.resource: resource = contact[jid.full] else: resource = contact.get_highest_priority_resource() else: resource = None if resource: status = ( 'Status: %s' % resource.status) if resource.status else '' self._text_buffer.add_message( "\x19%(info_col)s}Show: %(show)s, %(status)s\x19o" % { 'show': resource.presence or 'available', 'status': status, 'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT) }) return True else: self._text_buffer.add_message( "\x19%(info_col)s}No information available\x19o" % {'info_col': dump_tuple(get_theme().COLOR_INFORMATION_TEXT)}) return True
def message(self, args): """ /message <jid> [message] """ if args is None: return self.help('message') jid = safeJID(args[0]) if not jid.user and not jid.domain and not jid.resource: return self.core.information('Invalid JID.', 'Error') tab = self.core.get_conversation_by_jid(jid.full, False, fallback_barejid=False) muc = self.core.get_tab_by_name(jid.bare, typ=tabs.MucTab) if not tab and not muc: tab = self.core.open_conversation_window(jid.full, focus=True) elif muc: if jid.resource: tab = self.core.get_tab_by_name(jid.full, typ=tabs.PrivateTab) if tab: self.core.focus_tab_named(tab.name) else: tab = self.core.open_private_window(jid.bare, jid.resource) else: tab = muc else: self.core.focus_tab_named(tab.name) if len(args) == 2: tab.command_say(args[1])
def last_activity(self, args): """ /last_activity <jid> """ def callback(iq): "Callback for the last activity" if iq['type'] != 'result': if iq['error']['type'] == 'auth': self.core.information( 'You are not allowed to see the ' 'activity of this contact.', 'Error') else: self.core.information('Error retrieving the activity', 'Error') return seconds = iq['last_activity']['seconds'] status = iq['last_activity']['status'] from_ = iq['from'] if not safeJID(from_).user: msg = 'The uptime of %s is %s.' % ( from_, common.parse_secs_to_str(seconds)) else: msg = 'The last activity of %s was %s ago%s' % ( from_, common.parse_secs_to_str(seconds), (' and his/her last status was %s' % status) if status else '') self.core.information(msg, 'Info') if args is None: return self.help('last_activity') jid = safeJID(args[0]) self.core.xmpp.plugin['xep_0012'].get_last_activity(jid, callback=callback)
def _empty_join(self): tab = self.core.current_tab() if not isinstance(tab, (tabs.MucTab, tabs.PrivateTab)): return (None, None) room = safeJID(tab.name).bare nick = tab.own_nick return (room, nick)
def on_conversation_say(self, msg, tab): """ On message sent """ name = tab.name jid = safeJID(tab.name) format_dict = { 'jid_c': '\x19%s}' % dump_tuple(get_theme().COLOR_MUC_JID), 'info': '\x19%s}' % dump_tuple(get_theme().COLOR_INFORMATION_TEXT), 'jid': name, } ctx = self.find_encrypted_context_with_matching(jid) default_ctx = self.get_context(name) if ctx is None: ctx = default_ctx if is_relevant(tab) and ctx and ctx.state == STATE_ENCRYPTED: ctx.sendMessage(0, msg['body'].encode('utf-8')) if not tab.send_chat_state('active'): tab.send_chat_state('inactive', always_send=True) tab.add_message( msg['body'], nickname=self.core.own_nick or tab.own_nick, nick_color=get_theme().COLOR_OWN_NICK, identifier=msg['id'], jid=self.core.xmpp.boundjid, typ=ctx.log) # remove everything from the message so that it doesn’t get sent del msg['body'] del msg['replace'] del msg['html'] elif is_relevant(tab) and ctx and ctx.getPolicy('REQUIRE_ENCRYPTION'): warning_msg = MESSAGE_NOT_SENT % format_dict tab.add_message(warning_msg, typ=0) del msg['body'] del msg['replace'] del msg['html'] self.otr_start(tab, name, format_dict) elif not is_relevant(tab) and ctx and ( ctx.state == STATE_ENCRYPTED or ctx.getPolicy('REQUIRE_ENCRYPTION')): contact = roster[tab.name] res = [] if contact: res = [resource.jid for resource in contact.resources] help_msg = '' if res: help_msg = TAB_HELP_RESOURCE % ''.join( ('\n - /message %s' % jid) for jid in res) format_dict['help'] = help_msg warning_msg = INCOMPATIBLE_TAB % format_dict tab.add_message(warning_msg, typ=0) del msg['body'] del msg['replace'] del msg['html']
def __init__(self, field) -> None: FieldInput.__init__(self, field) Input.__init__(self) jid = safeJID(field.jid) jid.resource = field.nick or None self.text = jid.full self.pos = len(self.text) self.color = get_theme().COLOR_NORMAL_TEXT