Implement XEP-0012 (last activity) ; Fixes #1870
- Add a /activity command - Load xep_0012 on start - Add a 'l' shortcut in the roster to get the last activity - Using "/activity" in a direct conversation will add a message in the conversation, and not in the info buffer.
This commit is contained in:
parent
1d908702b1
commit
3897d131c1
4 changed files with 94 additions and 2 deletions
|
@ -233,6 +233,8 @@ def parse_secs_to_str(duration=0):
|
||||||
result += '%sh' % hours if hours else ''
|
result += '%sh' % hours if hours else ''
|
||||||
result += '%sm' % mins if mins else ''
|
result += '%sm' % mins if mins else ''
|
||||||
result += '%ss' % secs if secs else ''
|
result += '%ss' % secs if secs else ''
|
||||||
|
if not result:
|
||||||
|
result = '0s'
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def parse_command_args_to_alias(arg, strto):
|
def parse_command_args_to_alias(arg, strto):
|
||||||
|
|
|
@ -53,6 +53,7 @@ class Connection(sleekxmpp.ClientXMPP):
|
||||||
self.whitespace_keepalive_interval = int(interval)
|
self.whitespace_keepalive_interval = int(interval)
|
||||||
else:
|
else:
|
||||||
self.whitespace_keepalive_interval = 300
|
self.whitespace_keepalive_interval = 300
|
||||||
|
self.register_plugin('xep_0012')
|
||||||
self.register_plugin('xep_0030')
|
self.register_plugin('xep_0030')
|
||||||
self.register_plugin('xep_0004')
|
self.register_plugin('xep_0004')
|
||||||
self.register_plugin('xep_0045')
|
self.register_plugin('xep_0045')
|
||||||
|
|
38
src/core.py
38
src/core.py
|
@ -24,7 +24,7 @@ import logging
|
||||||
import singleton
|
import singleton
|
||||||
import collections
|
import collections
|
||||||
|
|
||||||
from sleekxmpp.xmlstream.stanzabase import JID
|
from sleekxmpp import JID, InvalidJID
|
||||||
from sleekxmpp.xmlstream.stanzabase import StanzaBase
|
from sleekxmpp.xmlstream.stanzabase import StanzaBase
|
||||||
from sleekxmpp.xmlstream.handler import Callback
|
from sleekxmpp.xmlstream.handler import Callback
|
||||||
|
|
||||||
|
@ -179,6 +179,7 @@ class Core(object):
|
||||||
'xml_tab': (self.command_xml_tab, _("Usage: /xml_tab\nXML Tab: Open an XML tab."), None),
|
'xml_tab': (self.command_xml_tab, _("Usage: /xml_tab\nXML Tab: Open an XML tab."), None),
|
||||||
'runkey': (self.command_runkey, _("Usage: /runkey <key>\nRunkey: Execute the action defined for <key>."), self.completion_runkey),
|
'runkey': (self.command_runkey, _("Usage: /runkey <key>\nRunkey: Execute the action defined for <key>."), self.completion_runkey),
|
||||||
'self': (self.command_self, _("Usage: /self\nSelf: Remind you of who you are."), None),
|
'self': (self.command_self, _("Usage: /self\nSelf: Remind you of who you are."), None),
|
||||||
|
'activity': (self.command_activity, _("Usage: /activity <jid>\nActivity: Informs you of the last activity of a JID."), self.completion_activity),
|
||||||
}
|
}
|
||||||
|
|
||||||
# We are invisible
|
# We are invisible
|
||||||
|
@ -1866,6 +1867,40 @@ class Core(object):
|
||||||
serv_list.append(serv)
|
serv_list.append(serv)
|
||||||
return the_input.auto_completion(serv_list, ' ')
|
return the_input.auto_completion(serv_list, ' ')
|
||||||
|
|
||||||
|
def command_activity(self, arg):
|
||||||
|
"""
|
||||||
|
/activity <jid>
|
||||||
|
"""
|
||||||
|
def callback(iq):
|
||||||
|
if iq['type'] != 'result':
|
||||||
|
if iq['error']['type'] == 'auth':
|
||||||
|
self.information('You are not allowed to see the activity of this contact.', 'Error')
|
||||||
|
else:
|
||||||
|
self.information('Error retrieving the activity', 'Error')
|
||||||
|
return
|
||||||
|
seconds = iq['last_activity']['seconds']
|
||||||
|
status = iq['last_activity']['status']
|
||||||
|
from_ = iq['from']
|
||||||
|
if not JID(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.information(msg, 'Info')
|
||||||
|
try:
|
||||||
|
jid = JID(arg)
|
||||||
|
except InvalidJID:
|
||||||
|
self.information('No valid JID given', 'Error')
|
||||||
|
return
|
||||||
|
self.xmpp.plugin['xep_0012'].get_last_activity(jid, block=False, callback=callback)
|
||||||
|
|
||||||
|
def completion_activity(self, the_input):
|
||||||
|
return the_input.auto_completion([jid for jid in roster.jids()], '', quotify=False)
|
||||||
|
|
||||||
def command_invite(self, arg):
|
def command_invite(self, arg):
|
||||||
"""/invite <to> <room> [reason]"""
|
"""/invite <to> <room> [reason]"""
|
||||||
args = common.shell_split(arg)
|
args = common.shell_split(arg)
|
||||||
|
@ -2607,6 +2642,7 @@ class Core(object):
|
||||||
"""
|
"""
|
||||||
We are sending a new stanza, write it in the xml buffer if needed.
|
We are sending a new stanza, write it in the xml buffer if needed.
|
||||||
"""
|
"""
|
||||||
|
self.xmpp.plugin['xep_0012'].set_last_activity()
|
||||||
if self.xml_tabs:
|
if self.xml_tabs:
|
||||||
self.add_message_to_text_buffer(self.xml_buffer, '\x191}<--\x19o %s' % stanza)
|
self.add_message_to_text_buffer(self.xml_buffer, '\x191}<--\x19o %s' % stanza)
|
||||||
if isinstance(self.current_tab(), tabs.XMLTab):
|
if isinstance(self.current_tab(), tabs.XMLTab):
|
||||||
|
|
55
src/tabs.py
55
src/tabs.py
|
@ -1842,6 +1842,7 @@ class RosterInfoTab(Tab):
|
||||||
self.key_func["M-Y"] = self.move_cursor_to_prev_group
|
self.key_func["M-Y"] = self.move_cursor_to_prev_group
|
||||||
self.key_func["M-[1;5B"] = self.move_cursor_to_next_group
|
self.key_func["M-[1;5B"] = self.move_cursor_to_next_group
|
||||||
self.key_func["M-[1;5A"] = self.move_cursor_to_prev_group
|
self.key_func["M-[1;5A"] = self.move_cursor_to_prev_group
|
||||||
|
self.key_func["l"] = self.command_activity
|
||||||
self.key_func["o"] = self.toggle_offline_show
|
self.key_func["o"] = self.toggle_offline_show
|
||||||
self.key_func["v"] = self.get_contact_version
|
self.key_func["v"] = self.get_contact_version
|
||||||
self.key_func["i"] = self.show_contact_info
|
self.key_func["i"] = self.show_contact_info
|
||||||
|
@ -1859,6 +1860,7 @@ class RosterInfoTab(Tab):
|
||||||
self.commands['export'] = (self.command_export, _("Usage: /export [/path/to/file]\nExport: Export your contacts into /path/to/file if specified, or $HOME/poezio_contacts if not."), self.completion_file)
|
self.commands['export'] = (self.command_export, _("Usage: /export [/path/to/file]\nExport: Export your contacts into /path/to/file if specified, or $HOME/poezio_contacts if not."), self.completion_file)
|
||||||
self.commands['import'] = (self.command_import, _("Usage: /import [/path/to/file]\nImport: Import your contacts from /path/to/file if specified, or $HOME/poezio_contacts if not."), self.completion_file)
|
self.commands['import'] = (self.command_import, _("Usage: /import [/path/to/file]\nImport: Import your contacts from /path/to/file if specified, or $HOME/poezio_contacts if not."), self.completion_file)
|
||||||
self.commands['clear_infos'] = (self.command_clear_infos, _("Usage: /clear_infos\nClear Infos: Use this command to clear the info buffer."), None)
|
self.commands['clear_infos'] = (self.command_clear_infos, _("Usage: /clear_infos\nClear Infos: Use this command to clear the info buffer."), None)
|
||||||
|
self.commands['activity'] = (self.command_activity, _("Usage: /activity <jid>\nActivity: Informs you of the last activity of a JID."), self.core.completion_activity)
|
||||||
self.core.xmpp.add_event_handler('session_start',
|
self.core.xmpp.add_event_handler('session_start',
|
||||||
lambda event: self.core.xmpp.plugin['xep_0030'].get_info(
|
lambda event: self.core.xmpp.plugin['xep_0030'].get_info(
|
||||||
jid=self.core.xmpp.boundjid.domain,
|
jid=self.core.xmpp.boundjid.domain,
|
||||||
|
@ -1968,7 +1970,6 @@ class RosterInfoTab(Tab):
|
||||||
if iq['type'] == 'error':
|
if iq['type'] == 'error':
|
||||||
return self.core.information('Could not retrieve the blocklist.', 'Error')
|
return self.core.information('Could not retrieve the blocklist.', 'Error')
|
||||||
s = 'List of blocked JIDs:\n'
|
s = 'List of blocked JIDs:\n'
|
||||||
log.debug('COCUCOCOCOCOCOCOC\n%s\n\n', iq['blocklist']['items'])
|
|
||||||
items = (str(item) for item in iq['blocklist']['items'])
|
items = (str(item) for item in iq['blocklist']['items'])
|
||||||
jids = '\n'.join(items)
|
jids = '\n'.join(items)
|
||||||
if jids:
|
if jids:
|
||||||
|
@ -1979,6 +1980,23 @@ class RosterInfoTab(Tab):
|
||||||
|
|
||||||
self.core.xmpp.plugin['xep_0191'].get_blocked(block=False, callback=callback)
|
self.core.xmpp.plugin['xep_0191'].get_blocked(block=False, callback=callback)
|
||||||
|
|
||||||
|
def command_activity(self, arg=None):
|
||||||
|
"""
|
||||||
|
/activity [jid]
|
||||||
|
"""
|
||||||
|
|
||||||
|
item = self.roster_win.selected_row
|
||||||
|
if arg:
|
||||||
|
jid = arg
|
||||||
|
elif isinstance(item, Contact):
|
||||||
|
jid = item.bare_jid
|
||||||
|
elif isinstance(item, Resource):
|
||||||
|
jid = item.jid.bare
|
||||||
|
else:
|
||||||
|
self.core.information('No JID selected.', 'Error')
|
||||||
|
return
|
||||||
|
self.core.command_activity(jid)
|
||||||
|
|
||||||
def resize(self):
|
def resize(self):
|
||||||
if not self.visible:
|
if not self.visible:
|
||||||
return
|
return
|
||||||
|
@ -2632,6 +2650,7 @@ class ConversationTab(ChatTab):
|
||||||
self.commands['close'] = (self.command_unquery, _("Usage: /close\Close: Close the tab."), None)
|
self.commands['close'] = (self.command_unquery, _("Usage: /close\Close: Close the tab."), None)
|
||||||
self.commands['version'] = (self.command_version, _('Usage: /version\nVersion: Get the software version of the current interlocutor (usually its XMPP client and Operating System).'), None)
|
self.commands['version'] = (self.command_version, _('Usage: /version\nVersion: Get the software version of the current interlocutor (usually its XMPP client and Operating System).'), None)
|
||||||
self.commands['info'] = (self.command_info, _('Usage: /info\nInfo: Get the status of the contact.'), None)
|
self.commands['info'] = (self.command_info, _('Usage: /info\nInfo: Get the status of the contact.'), None)
|
||||||
|
self.commands['activity'] = (self.command_activity, _('Usage: /activity [jid]\nActivity: Get the last activity of the given or the current contact.'), self.core.completion_activity)
|
||||||
self.resize()
|
self.resize()
|
||||||
self.update_commands()
|
self.update_commands()
|
||||||
self.update_keys()
|
self.update_keys()
|
||||||
|
@ -2680,6 +2699,40 @@ class ConversationTab(ChatTab):
|
||||||
self.text_win.refresh()
|
self.text_win.refresh()
|
||||||
self.input.refresh()
|
self.input.refresh()
|
||||||
|
|
||||||
|
def command_activity(self, arg):
|
||||||
|
"""
|
||||||
|
/activity [jid]
|
||||||
|
"""
|
||||||
|
if arg.strip():
|
||||||
|
return self.core.command_activity(arg)
|
||||||
|
|
||||||
|
def callback(iq):
|
||||||
|
if iq['type'] != 'result':
|
||||||
|
if iq['error']['type'] == 'auth':
|
||||||
|
self.information('You are not allowed to see the activity of this contact.', 'Error')
|
||||||
|
else:
|
||||||
|
self.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 JID(from_).user:
|
||||||
|
msg = '\x19%s}The uptime of %s is %s.' % (
|
||||||
|
get_theme().COLOR_INFORMATION_TEXT[0],
|
||||||
|
from_,
|
||||||
|
common.parse_secs_to_str(seconds))
|
||||||
|
else:
|
||||||
|
msg = '\x19%s}The last activity of %s was %s ago%s' % (
|
||||||
|
get_theme().COLOR_INFORMATION_TEXT[0],
|
||||||
|
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()
|
||||||
|
|
||||||
|
self.core.xmpp.plugin['xep_0012'].get_last_activity(self.general_jid, block=False, callback=callback)
|
||||||
|
|
||||||
def command_info(self, arg):
|
def command_info(self, arg):
|
||||||
contact = roster[self.get_name()]
|
contact = roster[self.get_name()]
|
||||||
jid = JID(self.get_name())
|
jid = JID(self.get_name())
|
||||||
|
|
Loading…
Reference in a new issue