2013-04-13 20:33:06 +00:00
|
|
|
"""
|
|
|
|
This plugin allows you to ping an entity.
|
|
|
|
|
|
|
|
Command
|
|
|
|
-------
|
|
|
|
|
|
|
|
.. glossary::
|
|
|
|
|
|
|
|
/ping
|
|
|
|
**Usage (globally):** ``/ping <jid>``
|
|
|
|
|
|
|
|
**Usage (in a MUC tab):** ``/ping <jid or nick>``
|
|
|
|
|
|
|
|
**Usage (in a conversation tab):** ``/ping [jid]``
|
|
|
|
|
|
|
|
Globally, you can do ``/ping jid@example.com`` to get a ping.
|
|
|
|
|
|
|
|
In a MUC, you can either do it to a JID or a nick (``/ping nick`` or ``/ping
|
|
|
|
jid@example.com``).
|
|
|
|
|
|
|
|
In a private or a direct conversation, you can do ``/ping`` to ping
|
|
|
|
the current interlocutor.
|
|
|
|
"""
|
2021-01-30 12:59:42 +00:00
|
|
|
import asyncio
|
2013-04-13 20:33:06 +00:00
|
|
|
|
2019-05-11 17:46:12 +00:00
|
|
|
from slixmpp import InvalidJID, JID
|
2021-01-30 12:59:42 +00:00
|
|
|
from slixmpp.exceptions import IqTimeout
|
2016-06-27 23:10:52 +00:00
|
|
|
from poezio.decorators import command_args_parser
|
|
|
|
from poezio.plugin import BasePlugin
|
|
|
|
from poezio.roster import roster
|
|
|
|
from poezio.contact import Contact, Resource
|
2016-08-21 13:27:53 +00:00
|
|
|
from poezio.core.structs import Completion
|
2016-06-27 23:10:52 +00:00
|
|
|
from poezio import tabs
|
2013-10-06 16:03:24 +00:00
|
|
|
import time
|
2011-11-15 00:15:08 +00:00
|
|
|
|
|
|
|
|
|
|
|
class Plugin(BasePlugin):
|
|
|
|
def init(self):
|
2018-08-15 11:13:17 +00:00
|
|
|
self.api.add_command(
|
|
|
|
'ping',
|
|
|
|
self.command_ping,
|
|
|
|
usage='<jid>',
|
|
|
|
help='Send an XMPP ping to jid (see XEP-0199).',
|
|
|
|
short='Send a ping',
|
|
|
|
completion=self.completion_ping)
|
|
|
|
self.api.add_tab_command(
|
|
|
|
tabs.MucTab,
|
|
|
|
'ping',
|
|
|
|
self.command_muc_ping,
|
|
|
|
usage='<jid|nick>',
|
|
|
|
help='Send an XMPP ping to jid or nick (see XEP-0199).',
|
|
|
|
short='Send a ping.',
|
|
|
|
completion=self.completion_muc_ping)
|
|
|
|
self.api.add_tab_command(
|
|
|
|
tabs.RosterInfoTab,
|
|
|
|
'ping',
|
|
|
|
self.command_roster_ping,
|
|
|
|
usage='<jid>',
|
|
|
|
help='Send an XMPP ping to jid (see XEP-0199).',
|
|
|
|
short='Send a ping.',
|
|
|
|
completion=self.completion_ping)
|
2019-07-19 16:55:16 +00:00
|
|
|
for _class in (tabs.PrivateTab, tabs.DynamicConversationTab, tabs.StaticConversationTab):
|
2018-08-15 11:13:17 +00:00
|
|
|
self.api.add_tab_command(
|
|
|
|
_class,
|
|
|
|
'ping',
|
|
|
|
self.command_private_ping,
|
|
|
|
usage='[jid]',
|
|
|
|
help=
|
|
|
|
'Send an XMPP ping to the current interlocutor or the given JID.',
|
2013-03-01 18:25:31 +00:00
|
|
|
short='Send a ping',
|
|
|
|
completion=self.completion_ping)
|
2011-11-15 00:15:08 +00:00
|
|
|
|
2015-07-30 19:13:20 +00:00
|
|
|
@command_args_parser.raw
|
2021-01-30 12:59:42 +00:00
|
|
|
async def command_ping(self, arg):
|
2011-11-15 00:15:08 +00:00
|
|
|
if not arg:
|
2016-03-31 22:24:58 +00:00
|
|
|
return self.core.command.help('ping')
|
2019-10-14 13:03:09 +00:00
|
|
|
try:
|
|
|
|
jid = JID(arg)
|
|
|
|
except InvalidJID:
|
|
|
|
return self.api.information('Invalid JID: %s' % arg, 'Error')
|
2013-10-06 16:03:24 +00:00
|
|
|
start = time.time()
|
2018-08-15 11:13:17 +00:00
|
|
|
|
2021-01-30 12:59:42 +00:00
|
|
|
try:
|
|
|
|
iq = await self.core.xmpp.plugin['xep_0199'].send_ping(
|
|
|
|
jid=jid, timeout=10
|
|
|
|
)
|
2013-10-06 16:03:24 +00:00
|
|
|
delay = time.time() - start
|
2017-05-15 21:22:56 +00:00
|
|
|
error = False
|
|
|
|
reply = ''
|
|
|
|
if iq['type'] == 'error':
|
|
|
|
error_condition = iq['error']['condition']
|
|
|
|
reply = error_condition
|
2017-07-20 09:24:48 +00:00
|
|
|
# These IQ errors are not ping errors:
|
|
|
|
# 'service-unavailable': official "not supported" response as of RFC6120 (§8.4) and XEP-0199 (§4.1)
|
|
|
|
# 'feature-not-implemented': inoffcial not-supported response from many clients
|
2018-08-15 11:13:17 +00:00
|
|
|
if error_condition not in ('service-unavailable',
|
|
|
|
'feature-not-implemented'):
|
2017-05-15 21:22:56 +00:00
|
|
|
error = True
|
2017-07-20 09:24:48 +00:00
|
|
|
error_text = iq['error']['text']
|
|
|
|
if error_text:
|
|
|
|
reply = '%s: %s' % (error_condition, error_text)
|
2017-05-15 21:22:56 +00:00
|
|
|
if error:
|
|
|
|
message = '%s did not respond to ping: %s' % (jid, reply)
|
2013-10-06 16:03:24 +00:00
|
|
|
else:
|
2017-05-15 21:22:56 +00:00
|
|
|
reply = ' (%s)' % reply if reply else ''
|
2018-08-15 11:13:17 +00:00
|
|
|
message = '%s responded to ping after %ss%s' % (
|
|
|
|
jid, round(delay, 4), reply)
|
2017-05-15 21:22:56 +00:00
|
|
|
self.api.information(message, 'Info')
|
2021-01-30 12:59:42 +00:00
|
|
|
except IqTimeout:
|
2018-08-15 11:13:17 +00:00
|
|
|
self.api.information(
|
2021-01-30 12:59:42 +00:00
|
|
|
'%s did not respond to ping after 10s: timeout' % jid,
|
|
|
|
'Info'
|
|
|
|
)
|
2011-11-15 00:15:08 +00:00
|
|
|
|
|
|
|
def completion_muc_ping(self, the_input):
|
2013-03-08 21:53:35 +00:00
|
|
|
users = [user.nick for user in self.api.current_tab().users]
|
2015-07-30 19:13:20 +00:00
|
|
|
l = self.resources()
|
2011-11-15 00:15:08 +00:00
|
|
|
users.extend(l)
|
2016-08-21 13:27:53 +00:00
|
|
|
return Completion(the_input.auto_completion, users, '', quotify=False)
|
2011-11-15 00:15:08 +00:00
|
|
|
|
2015-07-30 19:13:20 +00:00
|
|
|
@command_args_parser.raw
|
2011-11-15 00:15:08 +00:00
|
|
|
def command_private_ping(self, arg):
|
2021-01-30 12:59:42 +00:00
|
|
|
jid = arg
|
|
|
|
if not arg:
|
|
|
|
jid = self.api.current_tab().jid
|
2021-11-18 14:23:46 +00:00
|
|
|
asyncio.create_task(
|
2021-01-30 12:59:42 +00:00
|
|
|
self.command_ping(jid)
|
|
|
|
)
|
2011-11-15 00:15:08 +00:00
|
|
|
|
2015-07-30 19:13:20 +00:00
|
|
|
@command_args_parser.raw
|
2011-11-15 00:15:08 +00:00
|
|
|
def command_muc_ping(self, arg):
|
2015-07-30 19:13:20 +00:00
|
|
|
if not arg:
|
2011-11-15 00:15:08 +00:00
|
|
|
return
|
2013-03-08 21:53:35 +00:00
|
|
|
user = self.api.current_tab().get_user_by_name(arg)
|
2011-11-15 00:15:08 +00:00
|
|
|
if user:
|
2019-04-28 00:02:49 +00:00
|
|
|
jid = self.api.current_tab().jid
|
2011-11-15 00:15:08 +00:00
|
|
|
jid.resource = user.nick
|
|
|
|
else:
|
2019-04-28 00:02:49 +00:00
|
|
|
try:
|
|
|
|
jid = JID(arg)
|
|
|
|
except InvalidJID:
|
|
|
|
return self.api.information('Invalid JID: %s' % arg, 'Error')
|
2021-11-18 14:23:46 +00:00
|
|
|
asyncio.create_task(
|
2021-01-30 12:59:42 +00:00
|
|
|
self.command_ping(jid.full)
|
|
|
|
)
|
2011-11-15 00:15:08 +00:00
|
|
|
|
2015-07-30 19:13:20 +00:00
|
|
|
@command_args_parser.raw
|
|
|
|
def command_roster_ping(self, arg):
|
|
|
|
if arg:
|
2021-01-30 12:59:42 +00:00
|
|
|
jid = arg
|
2015-07-30 19:13:20 +00:00
|
|
|
else:
|
|
|
|
current = self.api.current_tab().selected_row
|
|
|
|
if isinstance(current, Resource):
|
2021-01-30 12:59:42 +00:00
|
|
|
jid = current.jid
|
2015-07-30 19:13:20 +00:00
|
|
|
elif isinstance(current, Contact):
|
|
|
|
res = current.get_highest_priority_resource()
|
|
|
|
if res is not None:
|
2021-01-30 12:59:42 +00:00
|
|
|
jid =res.jid
|
2021-11-18 14:23:46 +00:00
|
|
|
asyncio.create_task(
|
2021-01-30 12:59:42 +00:00
|
|
|
self.command_ping(jid)
|
|
|
|
)
|
2015-07-30 19:13:20 +00:00
|
|
|
|
|
|
|
def resources(self):
|
|
|
|
l = []
|
|
|
|
for contact in roster.get_contacts():
|
|
|
|
for resource in contact.resources:
|
|
|
|
l.append(resource.jid)
|
|
|
|
return l
|
|
|
|
|
2011-11-15 00:15:08 +00:00
|
|
|
def completion_ping(self, the_input):
|
2018-08-15 11:13:17 +00:00
|
|
|
return Completion(
|
|
|
|
the_input.auto_completion, self.resources(), '', quotify=False)
|