diff --git a/jabber.py b/jabber.py
index 838778f..36bb9c4 100644
--- a/jabber.py
+++ b/jabber.py
@@ -16,253 +16,244 @@
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
-"""
-Jabber/XMPP protocol for WeeChat.
-(this script requires WeeChat 0.3.0 (or newer) and xmpppy library)
-
-This will use the value of the environment variable https_proxy
-(lowercase with the s) to set an HTTP proxy.
-
-For help, see /help jabber
-
-/jabber list
- add
- | [[:]]
- connect|disconnect|del []
- alias [add|del ]
- away []
- buddies
- priority []
- status []
- presence | [online|chat|away|xa|dnd]
-
-"""
-# History:
#
-SCRIPT_NAME = "jabber"
-SCRIPT_AUTHOR = "Sebastien Helleu "
-SCRIPT_VERSION = "2.0"
-SCRIPT_LICENSE = "GPL3"
-SCRIPT_DESC = "Jabber/XMPP protocol for WeeChat"
-SCRIPT_COMMAND = SCRIPT_NAME
+#
+# Jabber/XMPP protocol for WeeChat.
+# (this script requires WeeChat 0.3.0 (or newer) and xmpppy library)
+#
+# For help, see /help jabber
+# Happy chat, enjoy :)
+#
+# History:
+# 2013-09-30, Nils Görs :
+# version 1.6: add support of /secure for passwords and jid
+# : fix stdout/stderr when no JID was set
+# 2013-05-14, Billiam :
+# version 1.5: fix unicode encoding error in /jabber buddies
+# 2013-05-03, Sebastien Helleu :
+# version 1.4: add tags in user messages: notify_xxx, no_highlight,
+# nick_xxx, prefix_nick_xxx, log1
+# 2012-05-12, Sebastian Rydberg :
+# version 1.3: Added support for fetching names from roster
+# 2012-04-11, Sebastien Helleu :
+# version 1.2: fix deletion of server options
+# 2012-03-09, Sebastien Helleu :
+# version 1.1: fix reload of config file
+# 2012-01-03, Sebastien Helleu :
+# version 1.0: changes for future compatibility with Python 3.x
+# 2011-12-15, Sebastien Helleu :
+# version 0.9: fix utf-8 encoding problem on jid
+# 2011-03-21, Isaac Raway :
+# version 0.8: search chat buffer before opening it
+# 2011-02-13, Sebastien Helleu :
+# version 0.7: use new help format for command arguments
+# 2010-11-23, xt
+# version 0.6: change format of sent ping, to match RFC
+# 2010-10-05, xt,
+# version 0.5: no highlight for status/presence messages
+# 2010-10-01, xt,
+# version 0.4:
+# add kick and invite
+# 2010-08-03, Aleksey V. Zapparov :
+# version 0.3:
+# add /jabber priority [priority]
+# add /jabber status [message]
+# add /jabber presence [online|chat|away|xa|dnd]
+# 2010-08-02, Aleksey V. Zapparov :
+# version 0.2.1:
+# fix prexence is set for current resource instead of sending
+# special presences for all buddies
+# 2010-08-02, Aleksey V. Zapparov :
+# version 0.2:
+# add priority and away_priority of resource
+# 2010-08-02, Sebastien Helleu :
+# version 0.1: first official version
+# 2010-08-01, ixti :
+# fix bug with non-ascii resources
+# 2010-06-09, iiijjjiii :
+# add connect server and port options (required for google talk)
+# add private option permitting messages to be displayed in separate
+# chat buffers or in a single server buffer
+# add jid aliases
+# add keepalive ping
+# 2010-03-17, xt :
+# add autoreconnect option, autoreconnects on protocol error
+# 2010-03-17, xt :
+# add autoconnect option, add new command /jmsg with -server option
+# 2009-02-22, Sebastien Helleu :
+# first version (unofficial)
+#
-import os
import re
-import traceback
import warnings
+import_ok = True
+
try:
- import weechat as w
- weechat = w
- import_ok = True
+ import weechat
+ w = weechat
except:
print("This script must be run under WeeChat.")
print("Get WeeChat now at: http://www.weechat.org/")
import_ok = False
+from support_jabber import aget_proxy
+
# On import, xmpp may produce warnings about using hashlib instead of
# deprecated sha and md5. Since the code producing those warnings is
# outside this script, catch them and ignore.
original_filters = warnings.filters[:]
-warnings.filterwarnings("ignore", category=DeprecationWarning)
+warnings.filterwarnings("ignore",category=DeprecationWarning)
try:
import xmpp
-except:
- print("Package python-xmpp (xmpppy) must be installed to use Xmpp protocol.")
- print("Get xmpppy with your package manager, or at this URL: http://xmpppy.sourceforge.net/")
+ from xmpp import dispatcher
+ from xmpp import transports
+ dispatcher.DefaultTimeout = 60
+except ImportError as e:
+ print(f"Package python-xmpp (xmpppy) must be installed to use Jabber protocol. {e}")
import_ok = False
finally:
warnings.filters = original_filters
-def LOG_debug(what, level):
- if jabber_debug_enabled():
- w_prnt('', what)
-
-def w_prnt(where, what='', *args):
- if args:
- w.prnt('', w.prefix('!') + str(repr(args)))
- elif not what:
- w.prnt('', w.prefix('%') + str(where))
- elif type(what) != str or type(where) != str:
- w.prnt('', w.prefix('$') + str(where) + str(what))
- else:
- try:
- w.prnt(where, what)
- except Exception as e:
- w.prnt('', 'w_prnt: ' + str(e))
+SCRIPT_NAME = "jabber"
+SCRIPT_AUTHOR = "Sebastien Helleu "
+SCRIPT_VERSION = "1.7.01"
+SCRIPT_LICENSE = "GPL3"
+SCRIPT_DESC = "Jabber/XMPP protocol for WeeChat"
+SCRIPT_COMMAND = SCRIPT_NAME
+
+def LOG_debug(what, level='none'):
+ # if jabber_debug_enabled():
+ weechat.prnt('', what)
# ==============================[ global vars ]===============================
jabber_servers = []
jabber_server_options = {
"jid" : { "type" : "string",
- "desc": "xmpp id (user@server.tld)",
- "min": 0,
- "max": 0,
+ "desc" : "jabber id (user@server.tld)",
+ "min" : 0,
+ "max" : 0,
"string_values": "",
- "default": "",
- "value": "",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "",
+ "value" : "",
+ "check_cb" : "",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "priority": { "type": "integer",
- "desc": "Default resource priority",
- "min": 0,
- "max": 65535,
+ "priority" : { "type" : "integer",
+ "desc" : "Default resource priority",
+ "min" : 0,
+ "max" : 65535,
"string_values": "",
- "default": "8",
- "value": "8",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "8",
+ "value" : "8",
+ "check_cb" : "",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "away_priority": { "type": "integer",
- "desc": "Resource priority on away",
- "min": 0,
- "max": 65535,
+ "away_priority": { "type" : "integer",
+ "desc" : "Resource priority on away",
+ "min" : 0,
+ "max" : 65535,
"string_values": "",
- "default": "0",
- "value": "0",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "0",
+ "value" : "0",
+ "check_cb" : "",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "password": { "type": "string",
- "desc": "password for xmpp id on server",
- "min": 0,
- "max": 0,
+ "password" : { "type" : "string",
+ "desc" : "password for jabber id on server (evaluated)",
+ "min" : 0,
+ "max" : 0,
"string_values": "",
- "default": "",
- "value": "",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "",
+ "value" : "",
+ "check_cb" : "",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "server": { "type": "string",
- "desc": "connect server host or ip, eg. talk.google.com",
- "min": 0,
- "max": 0,
+ "server" : { "type" : "string",
+ "desc" : "connect server host or ip, eg. talk.google.com",
+ "min" : 0,
+ "max" : 0,
"string_values": "",
- "default": "",
- "value": "",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "",
+ "value" : "",
+ "check_cb" : "",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "ssl_ver": { "type": "string",
- "desc": "Miniumum SSL version - empty for no SSL, else tlsv1.1|tlsv1.2|tlsv1.3",
- "min": 0,
- "max": 0,
+ "port" : { "type" : "integer",
+ "desc" : "connect server port, eg. 5223",
+ "min" : 0,
+ "max" : 65535,
"string_values": "",
- "default": "",
- "value": "",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "5222",
+ "value" : "5222",
+ "check_cb" : "",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "port": { "type": "integer",
- "desc": "connect server port, eg. 5222 for not SSL",
- "min": 0,
- "max": 65535,
+ "autoconnect" : { "type" : "boolean",
+ "desc" : "automatically connect to server when script is starting",
+ "min" : 0,
+ "max" : 0,
"string_values": "",
- "default": "5222",
- "value": "5222",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "off",
+ "value" : "off",
+ "check_cb" : "",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "autoconnect": { "type": "boolean",
- "desc": "automatically connect to server when script is starting",
- "min": 0,
- "max": 0,
+ "autoreconnect": { "type" : "boolean",
+ "desc" : "automatically reconnect to server when disconnected",
+ "min" : 0,
+ "max" : 0,
"string_values": "",
- "default": "off",
- "value": "off",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "off",
+ "value" : "off",
+ "check_cb" : "",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "autoreconnect": { "type": "boolean",
- "desc": "automatically reconnect to server when disconnected",
- "min": 0,
- "max": 0,
+ "private" : { "type" : "boolean",
+ "desc" : "display messages in separate chat buffers instead of a single server buffer",
+ "min" : 0,
+ "max" : 0,
"string_values": "",
- "default": "off",
- "value": "off",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "on",
+ "value" : "on",
+ "check_cb" : "",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "private": { "type": "boolean",
- "desc": "display messages in separate chat buffers instead of a single server buffer",
- "min": 0,
- "max": 0,
+ "ping_interval": { "type" : "integer",
+ "desc" : "Number of seconds between server pings. 0 = disable",
+ "min" : 60,
+ "max" : 9999999,
"string_values": "",
- "default": "on",
- "value": "on",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "0",
+ "value" : "0",
+ "check_cb" : "ping_interval_check_cb",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "ping_interval": { "type": "integer",
- "desc": "Number of seconds between server pings. 0 = disable",
- "min": 0,
- "max": 9999999,
+ "ping_timeout" : { "type" : "integer",
+ "desc" : "Number of seconds to allow ping to respond before timing out",
+ "min" : 0,
+ "max" : 9999999,
"string_values": "",
- "default": "0",
- "value": "0",
- "check_cb": "ping_interval_check_cb",
- "change_cb": "",
- "delete_cb": "",
+ "default" : "10",
+ "value" : "10",
+ "check_cb" : "ping_timeout_check_cb",
+ "change_cb" : "",
+ "delete_cb" : "",
},
- "ping_timeout": { "type": "integer",
- "desc": "Number of seconds to allow ping to respond before timing out",
- "min": 0,
- "max": 9999999,
- "string_values": "",
- "default": "10",
- "value": "10",
- "check_cb": "ping_timeout_check_cb",
- "change_cb": "",
- "delete_cb": "",
- },
- "CAfile": { "type": "string",
- "desc": "CAfile - bundle of CA certificates in PEM",
- "min": 0,
- "max": 0,
- "string_values": "",
- "default": "/etc/ssl/certs/ca-certificates.crt",
- "value": "",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
- },
- "cert_file": { "type": "string",
- "desc": "client certificate file for authentication, in PEM",
- "min": 0,
- "max": 0,
- "string_values": "",
- "default": "",
- "value": "",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
- },
- "key_file": { "type": "string",
- "desc": "client private key file for authentication, in PEM",
- "min": 0,
- "max": 0,
- "string_values": "",
- "default": "",
- "value": "",
- "check_cb": "",
- "change_cb": "",
- "delete_cb": "",
- },
- "ciphers": { "type": "string",
- "desc": "ciphers for authentication, colon sep",
+ "proxy": { "type": "string",
+ "desc": "name of the weechat.proxy.* = or ''",
"min": 0,
"max": 0,
"string_values": "",
@@ -278,154 +269,63 @@ jabber_config_section = {}
jabber_config_option = {}
jabber_jid_aliases = {} # { 'alias1': 'jid1', 'alias2': 'jid2', ... }
-class WeechatWrapper(object):
- def __init__(self, wrapped_class):
- self.wrapped_class = wrapped_class
-
- # Helper method used to encode/decode method calls.
- def wrap_for_utf8(self, method):
- def hooked(*args, **kwargs):
- result = method(*encode_to_utf8(args), **encode_to_utf8(kwargs))
- # Prevent wrapped_class from becoming unwrapped
- if result == self.wrapped_class:
- return self
- return decode_from_utf8(result)
-
- return hooked
-
- # Encode and decode everything sent to/received from weechat. We use the
- # unicode type internally in wee-slack, but has to send utf8 to weechat.
- def __getattr__(self, attr):
- orig_attr = self.wrapped_class.__getattribute__(attr)
- if callable(orig_attr):
- return self.wrap_for_utf8(orig_attr)
- else:
- return decode_from_utf8(orig_attr)
-
- # Ensure all lines sent to weechat specifies a prefix. For lines after the
- # first, we want to disable the prefix, which we do by specifying the same
- # number of spaces, so it aligns correctly.
- def prnt_date_tags(self, buffer, date, tags, message):
- prefix, _, _ = message.partition("\t")
- prefix = w.string_remove_color(encode_to_utf8(prefix), "")
- prefix_spaces = " " * w.strlen_screen(prefix)
- message = message.replace("\n", "\n{}\t".format(prefix_spaces))
- return self.wrap_for_utf8(self.wrapped_class.prnt_date_tags)(
- buffer, date, tags, message
- )
-
-class ProxyWrapper(object):
- def __init__(self):
- self.proxy_name = w.config_string(w.config_get("weechat.network.proxy_curl"))
- self.proxy_string = ""
- self.proxy_type = ""
- self.proxy_address = ""
- self.proxy_port = ""
- self.proxy_user = ""
- self.proxy_password = ""
- self.has_proxy = False
-
- if self.proxy_name:
- self.proxy_string = "weechat.proxy.{}".format(self.proxy_name)
- self.proxy_type = w.config_string(
- w.config_get("{}.type".format(self.proxy_string))
- )
- if self.proxy_type == "http":
- self.proxy_address = w.config_string(
- w.config_get("{}.address".format(self.proxy_string))
- )
- self.proxy_port = w.config_integer(
- w.config_get("{}.port".format(self.proxy_string))
- )
- self.proxy_user = w.config_string(
- w.config_get("{}.username".format(self.proxy_string))
- )
- self.proxy_password = w.config_string(
- w.config_get("{}.password".format(self.proxy_string))
- )
- self.has_proxy = True
- else:
- w_prnt(
- "",
- "\nWarning: weechat.network.proxy_curl is set to {} type (name: {}, conf string: {}). Only HTTP proxy is supported.\n\n".format(
- self.proxy_type, self.proxy_name, self.proxy_string
- ),
- )
-
- def curl(self):
- if not self.has_proxy:
- return ""
-
- if self.proxy_user and self.proxy_password:
- user = "{}:{}@".format(self.proxy_user, self.proxy_password)
- else:
- user = ""
-
- if self.proxy_port:
- port = ":{}".format(self.proxy_port)
- else:
- port = ""
-
- return "-x{}{}{}".format(user, self.proxy_address, port)
-
-
# =================================[ config ]=================================
def jabber_config_init():
""" Initialize config file: create sections and options in memory. """
global jabber_config_file, jabber_config_section
- jabber_config_file = w.config_new("jabber", "jabber_config_reload_cb", "")
+ jabber_config_file = weechat.config_new("jabber", "jabber_config_reload_cb", "")
if not jabber_config_file:
return
# look
- jabber_config_section["look"] = w.config_new_section(
+ jabber_config_section["look"] = weechat.config_new_section(
jabber_config_file, "look", 0, 0, "", "", "", "", "", "", "", "", "", "")
if not jabber_config_section["look"]:
- w.config_free(jabber_config_file)
+ weechat.config_free(jabber_config_file)
return
- jabber_config_option["debug"] = w.config_new_option(
+ jabber_config_option["debug"] = weechat.config_new_option(
jabber_config_file, jabber_config_section["look"],
"debug", "boolean", "display debug messages", "", 0, 0,
"off", "off", 0, "", "", "", "", "", "")
# color
- jabber_config_section["color"] = w.config_new_section(
+ jabber_config_section["color"] = weechat.config_new_section(
jabber_config_file, "color", 0, 0, "", "", "", "", "", "", "", "", "", "")
if not jabber_config_section["color"]:
- w.config_free(jabber_config_file)
+ weechat.config_free(jabber_config_file)
return
- jabber_config_option["message_join"] = w.config_new_option(
+ jabber_config_option["message_join"] = weechat.config_new_option(
jabber_config_file, jabber_config_section["color"],
"message_join", "color", "color for text in join messages", "", 0, 0,
"green", "green", 0, "", "", "", "", "", "")
- jabber_config_option["message_quit"] = w.config_new_option(
+ jabber_config_option["message_quit"] = weechat.config_new_option(
jabber_config_file, jabber_config_section["color"],
"message_quit", "color", "color for text in quit messages", "", 0, 0,
"red", "red", 0, "", "", "", "", "", "")
# server
- jabber_config_section["server"] = w.config_new_section(
+ jabber_config_section["server"] = weechat.config_new_section(
jabber_config_file, "server", 0, 0,
"jabber_config_server_read_cb", "", "jabber_config_server_write_cb", "",
"", "", "", "", "", "")
if not jabber_config_section["server"]:
- w.config_free(jabber_config_file)
+ weechat.config_free(jabber_config_file)
return
- jabber_config_section["jid_aliases"] = w.config_new_section(
+ jabber_config_section["jid_aliases"] = weechat.config_new_section(
jabber_config_file, "jid_aliases", 0, 0,
"jabber_config_jid_aliases_read_cb", "",
"jabber_config_jid_aliases_write_cb", "",
"", "", "", "", "", "")
if not jabber_config_section["jid_aliases"]:
- w.config_free(jabber_config_file)
+ weechat.config_free(jabber_config_file)
return
def jabber_config_reload_cb(data, config_file):
""" Reload config file. """
- return w.config_reload(config_file)
+ return weechat.config_reload(config_file)
def jabber_config_server_read_cb(data, config_file, section, option_name, value):
""" Read server option in config file. """
global jabber_servers
- rc = w.WEECHAT_CONFIG_OPTION_SET_ERROR
+ rc = weechat.WEECHAT_CONFIG_OPTION_SET_ERROR
items = option_name.split(".", 1)
if len(items) == 2:
server = jabber_search_server_by_name(items[0])
@@ -433,52 +333,52 @@ def jabber_config_server_read_cb(data, config_file, section, option_name, value)
server = Server(items[0])
jabber_servers.append(server)
if server:
- rc = w.config_option_set(server.options[items[1]], value, 1)
+ rc = weechat.config_option_set(server.options[items[1]], value, 1)
return rc
def jabber_config_server_write_cb(data, config_file, section_name):
""" Write server section in config file. """
global jabber_servers
- w.config_write_line(config_file, section_name, "")
+ weechat.config_write_line(config_file, section_name, "")
for server in jabber_servers:
for name, option in sorted(server.options.items()):
- w.config_write_option(config_file, option)
- return w.WEECHAT_RC_OK
+ weechat.config_write_option(config_file, option)
+ return weechat.WEECHAT_RC_OK
def jabber_config_jid_aliases_read_cb(data, config_file, section, option_name, value):
""" Read jid_aliases option in config file. """
global jabber_jid_aliases
jabber_jid_aliases[option_name] = value
- option = w.config_new_option(
+ option = weechat.config_new_option(
config_file, section,
option_name, "string", "jid alias", "", 0, 0,
"", value, 0, "", "", "", "", "", "")
if not option:
- return w.WEECHAT_CONFIG_OPTION_SET_ERROR
- return w.WEECHAT_CONFIG_OPTION_SET_OK_CHANGED
+ return weechat.WEECHAT_CONFIG_OPTION_SET_ERROR
+ return weechat.WEECHAT_CONFIG_OPTION_SET_OK_CHANGED
def jabber_config_jid_aliases_write_cb(data, config_file, section_name):
""" Write jid_aliases section in config file. """
global jabber_jid_aliases
- w.config_write_line(config_file, section_name, "")
+ weechat.config_write_line(config_file, section_name, "")
for alias, jid in sorted(jabber_jid_aliases.items()):
- w.config_write_line(config_file, alias, jid)
- return w.WEECHAT_RC_OK
+ weechat.config_write_line(config_file, alias, jid)
+ return weechat.WEECHAT_RC_OK
def jabber_config_read():
""" Read jabber config file (jabber.conf). """
global jabber_config_file
- return w.config_read(jabber_config_file)
+ return weechat.config_read(jabber_config_file)
def jabber_config_write():
""" Write jabber config file (jabber.conf). """
global jabber_config_file
- return w.config_write(jabber_config_file)
+ return weechat.config_write(jabber_config_file)
def jabber_debug_enabled():
""" Return True if debug is enabled. """
global jabber_config_options
- if w.config_boolean(jabber_config_option["debug"]):
+ if weechat.config_boolean(jabber_config_option["debug"]):
return True
return False
@@ -486,336 +386,38 @@ def jabber_config_color(color):
""" Return color code for a jabber color option. """
global jabber_config_option
if color in jabber_config_option:
- return w.color(w.config_color(jabber_config_option[color]))
+ return weechat.color(weechat.config_color(jabber_config_option[color]))
return ""
def ping_timeout_check_cb(server_name, option, value):
global jabber_config_file, jabber_config_section
- ping_interval_option = w.config_search_option(
+ ping_interval_option = weechat.config_search_option(
jabber_config_file,
jabber_config_section["server"],
"%s.ping_interval" % (server_name)
)
- ping_interval = w.config_integer(ping_interval_option)
+ ping_interval = weechat.config_integer(ping_interval_option)
if int(ping_interval) and int(value) >= int(ping_interval):
- w_prnt("", "\njabber: unable to update 'ping_timeout' for server %s" % (server_name))
- w_prnt("", "jabber: to prevent multiple concurrent pings, ping_interval must be greater than ping_timeout")
- return w.WEECHAT_CONFIG_OPTION_SET_ERROR
- return w.WEECHAT_CONFIG_OPTION_SET_OK_CHANGED
+ weechat.prnt("", "\njabber: unable to update 'ping_timeout' for server %s" % (server_name))
+ weechat.prnt("", f"{SCRIPT_NAME}: to prevent multiple concurrent pings, ping_interval must be greater than ping_timeout")
+ return weechat.WEECHAT_CONFIG_OPTION_SET_ERROR
+ return weechat.WEECHAT_CONFIG_OPTION_SET_OK_CHANGED
def ping_interval_check_cb(server_name, option, value):
global jabber_config_file, jabber_config_section
- ping_timeout_option = w.config_search_option(
+ ping_timeout_option = weechat.config_search_option(
jabber_config_file,
jabber_config_section["server"],
"%s.ping_timeout" % (server_name)
)
- ping_timeout = w.config_integer(ping_timeout_option)
+ ping_timeout = weechat.config_integer(ping_timeout_option)
if int(value) and int(ping_timeout) >= int(value):
- w_prnt("", "\njabber: unable to update 'ping_interval' for server %s" % (server_name))
- w_prnt("", "jabber: to prevent multiple concurrent pings, ping_interval must be greater than ping_timeout")
- return w.WEECHAT_CONFIG_OPTION_SET_ERROR
- return w.WEECHAT_CONFIG_OPTION_SET_OK_CHANGED
+ weechat.prnt("", "\njabber: unable to update 'ping_interval' for server %s" % (server_name))
+ weechat.prnt("", f"{SCRIPT_NAME}: to prevent multiple concurrent pings, ping_interval must be greater than ping_timeout")
+ return weechat.WEECHAT_CONFIG_OPTION_SET_ERROR
+ return weechat.WEECHAT_CONFIG_OPTION_SET_OK_CHANGED
-import ssl
-from xmpp.client import PlugIn
-from xmpp.protocol import NodeProcessed
-class HTTPPROXYsocket(xmpp.transports.TCPsocket):
- """ HTTP (CONNECT) proxy connection class. Uses TCPsocket as the base class
- redefines only connect method. Allows to use HTTP proxies like squid with
- (optionally) simple authentication (using login and password). """
- def __init__(self, proxy, server, use_srv=True, buffer=None):
- """ Caches proxy and target addresses.
- 'proxy' argument is a dictionary with mandatory keys 'host' and 'port' (proxy address)
- and optional keys 'user' and 'password' to use for authentication.
- 'server' argument is a tuple of host and port - just like TCPsocket uses. """
- xmpp.transports.TCPsocket.__init__(self, server, use_srv)
- self.DBG_LINE = xmpp.transports.DBG_CONNECT_PROXY
- self._proxy = proxy
- self.buffer = buffer
-
- def connect(self, server=None):
- """ Starts connection. Connects to proxy, supplies login and password to it
- (if were specified while creating instance). Instructs proxy to make
- connection to the target server. Returns non-empty sting on success. """
- if not xmpp.transports.TCPsocket.connect(self,
- (self._proxy['host'],
- self._proxy['port'])):
- LOG_debug(f"Proxy not connect {(self._proxy['host'], self._proxy['port'])}",'start')
- if self.buffer:
- w_prnt(self.buffer,
- "%sjabber: could not TCPsocket.connect"
- % w.prefix("error"))
- return
- LOG_debug("Proxy server contacted, performing authentification",'start')
- if not server:
- server=self._server
- connector = ['CONNECT %s:%s HTTP/1.0'%server,
- 'Proxy-Connection: Keep-Alive',
- 'Pragma: no-cache',
- 'Host: %s:%s'%server,
- 'User-Agent: HTTPPROXYsocket/v0.1']
- if 'user' in self._proxy and 'password' in self._proxy:
- credentials = '%s:%s'%(self._proxy['user'],self._proxy['password'])
- credentials = base64.encodestring(credentials).strip()
- connector.append('Proxy-Authorization: Basic '+credentials)
- connector.append('\r\n')
- LOG_debug('Proxy sending connector','start')
- # bytes?
- self.send('\r\n'.join(connector))
- try:
- reply = self.receive().replace(b'\r','')
- reply = str(reply, 'UTF-8')
- except IOError:
- LOG_debug('Proxy suddenly disconnected','error')
- self._owner.disconnected()
- return
- try:
- proto, code, desc = reply.split('\n')[0].split(' ',2)
- except Exception as e:
- raise error(f'Invalid proxy reply {e}')
- if code!='200':
- LOG_debug('Invalid proxy reply: %s %s %s'%(proto,code,desc),'error')
- self._owner.disconnected()
- return
- while reply.find('\n\n') == -1:
- try:
- reply_more = self.receive().replace(b'\r','')
- reply += str(reply_more, 'UTF-8')
- except IOError:
- LOG_debug('Proxy suddenly disconnected','error')
- self._owner.disconnected()
- return
- LOG_debug("Authentification successfull. XMPP server contacted.",'ok')
- return 'ok'
-
-class TLS(xmpp.transports.PlugIn):
- """ TLS connection used to encrypts already estabilished tcp connection."""
-
- def PlugIn(self, owner, now=True, assl_dict=None):
- """ If the 'now' argument is true then starts using encryption immidiatedly.
- If 'now' in false then starts encryption as soon as TLS feature is
- declared by the server (if it were already declared - it is ok).
- """
- if 'TLS' in owner.__dict__:
- return # Already enabled.
- xmpp.client.PlugIn.PlugIn(self, owner)
- DBG_LINE = 'TLS'
- if now:
- if not assl_dict:
- assl_dict=dict(keyfile=None,
- certfile=None,
- cert_reqs=ssl.CERT_NONE,
- ssl_version=ssl.PROTOCOL_TLS,
- ca_certs=None,
- do_handshake_on_connect=True,
- suppress_ragged_eofs=True,
- ciphers=None)
- return self._startSSL(**assl_dict)
- if self._owner.Dispatcher.Stream.features:
- try:
- self.FeaturesHandler(self._owner.Dispatcher,
- self._owner.Dispatcher.Stream.features)
- except NodeProcessed:
- pass
- else:
- self._owner.RegisterHandlerOnce('features',
- self.FeaturesHandler,
- xmlns=xmpp.protocol.NS_STREAMS)
- self.starttls = None
-
- def _startSSL(self,
- keyfile=None,
- certfile=None,
- cert_reqs=ssl.CERT_NONE,
- ssl_version=ssl.PROTOCOL_TLS,
- ca_certs=None,
- do_handshake_on_connect=True,
- suppress_ragged_eofs=True,
- ciphers=None):
- """ Immidiatedly switch socket to TLS mode. Used internally.
- Here we should switch pending_data to hint mode."""
- if not ca_certs:
- ca_certs = w.config_string(self.options['CAfile'])
- tcpsock=self._owner.Connection
- tcpsock._sslObj = ssl.wrap_socket(tcpsock._sock,
- keyfile=None,
- certfile=certfile,
- cert_reqs=ssl.CERT_NONE,
- ssl_version=ssl.PROTOCOL_TLS,
- ca_certs=ca_certs,
- do_handshake_on_connect=True,
- suppress_ragged_eofs=True,
- ciphers=None)
- tcpsock._sslIssuer = tcpsock._sslObj.getpeercert().get('issuer')
- tcpsock._sslServer = tcpsock._sslObj.getpeercert().get('server')
- tcpsock._recv = tcpsock._sslObj.read
- tcpsock._send = tcpsock._sslObj.write
-
- tcpsock._seen_data = 1
- self._tcpsock=tcpsock
- tcpsock.pending_data=self.pending_data
- tcpsock._sslObj.setblocking(False)
-
- self.starttls='success'
-
-from xmpp import transports, dispatcher
-class CommonClient(xmpp.client.CommonClient):
-
- def __init__(self, server,
- port=5222,
- debug=[], # 'always', 'nodebuilder'
- buffer=None,
- assl_dict=None):
- xmpp.client.CommonClient.__init__(self, server, port, debug=debug)
- self.buffer = buffer
- self.assl_dict = assl_dict
-
- def connect(self,server_tuple=None, proxy=None, ssl=None,use_srv=False,transport=None):
- """ Make a tcp/ip connection, protect it with tls/ssl if possible and start XMPP stream.
- Returns None or 'tcp' or 'tls', depending on the result."""
- if not server_tuple:
- server_tuple=(self.Server, self.Port)
- self.assl_dict = None
-
- # bulletproofing
- assert type(server_tuple) == tuple, server_tuple
- assert len(server_tuple) >= 2, server_tuple
- assert type(server_tuple[1]) in [int, str], server_tuple
- assert type(server_tuple[0]) in [bytes, str], server_tuple
- assert server_tuple[0] and server_tuple[1], server_tuple
-
- if transport:
- pass
- elif proxy:
- transport = HTTPPROXYsocket(proxy, server_tuple, use_srv, )
- else:
- transport = xmpp.transports.TCPsocket(server_tuple, use_srv)
- if self.buffer:
- w_prnt(self.buffer,
- f"{w.prefix('network')}jabber: proxy: transport={transport}")
- connected = transport.PlugIn(self)
- if not connected:
- serr = f"Failed to transport.PlugIn(self)"
- LOG_debug(serr,'error')
- transport.PlugOut()
- return serr
- self.connected = 'tcp'
-
- self._server_tuple = server_tuple
- self._aProxy = proxy
- if (ssl is None and self.Connection.getPort() in (5223, 443)):
- ssl = True
- if ssl:
- try: # FIXME. This should be done in transports.py
- TLS().PlugIn(self, now=True, assl_dict=self.assl_dict)
- self.connected = 'ssl'
- except socket.sslerror as e:
- serr = f"Failed to transports.TLS().PlugIn(self, now=1)"
- LOG_debug(serr,'error')
- return serr
-
- dispatcher.Dispatcher().PlugIn(self)
- while self.Dispatcher.Stream._document_attrs is None:
- if not self.Process(1):
- serr = f"Failed to dispatcher.Dispatcher().PlugIn(self)"
- LOG_debug(serr,'error')
- return serr
-
- if 'version' in self.Dispatcher.Stream._document_attrs and self.Dispatcher.Stream._document_attrs['version']=='1.0':
- while not self.Dispatcher.Stream.features and self.Process(1):
- # If we get version 1.0 stream the features tag MUST BE presented
- pass
-
- return self.connected
-
-class Client(CommonClient):
- """ Example client class, based on CommonClient. """
- def __init__(self, server,
- port,
- debug=[], # 'always', 'nodebuilder']
- buffer=None,
- assl_dict=None):
- self.buffer = buffer
- if not assl_dict:
- assl_dict=dict(keyfile=None,
- certfile=None,
- cert_reqs=ssl.CERT_NONE,
- ssl_version=ssl.PROTOCOL_TLS,
- ca_certs=None,
- do_handshake_on_connect=True,
- suppress_ragged_eofs=True,
- ciphers=None)
- self.assl_dict = assl_dict
- # no ssl=
- CommonClient.__init__(self,
- server,
- port,
- buffer=self.buffer,
- debug=debug)
-
- def connect(self, server_tuple=None, proxy=None, secure=None, use_srv=False, transport=None):
- """Connect to XMPP server_tuple. If you want to specify different ip/port
- to connect to you can pass it as tuple as first parameter.
- If there is HTTP proxy between you and server
- specify it's address and credentials (if needed) in the second argument.
-
- If you want ssl/tls support to be discovered and enable
- automatically - leave third argument as None. (ssl will be
- autodetected only if port is 5223 or 443)
-
- If you want to force SSL start (i.e. if port 5223 or 443 is
- remapped to some non-standard port) then set it to 1.
-
- If you want to disable tls/ssl support completely, set it to 0.
-
- Example: connect(('192.168.5.5',5222),{'host':'proxy.my.net','port':8080,'user':'me','password':'secret'})
- Returns '' or 'tcp' or 'tls', depending on the result.
-
- """
- assert type(proxy) == dict
- try:
- cc = CommonClient(self)
- self.connected = cc.connect(server_tuple,
- proxy=proxy,
- ssl=secure,
- use_srv=use_srv,
- transport=transport)
- except Exception as e:
- if self.buffer:
- oerror = str(e) + ' ' + traceback.format_exc()
- w_prnt(self.buffer, f"Error CCconnect {oerror} proxy={proxy}")
- return ''
- self.connected = 'tcp'
-
- if self.connected not in ['ssl', 'tcp']:
- if self.buffer:
- w_prnt(self.buffer, f"Error NOT Connected to {server_tuple} {self.connected}")
- return ''
-
- if secure is not None and not secure:
- # 0 or False
- if self.buffer:
- w_prnt(self.buffer, f"Connected {self.connected} to {server_tuple} proxy={proxy}")
- return self.connected
-
- TLS().PlugIn(self, assl_dict=self.assl_dict)
-
- if 'version' not in self.Dispatcher.Stream._document_attrs or \
- not self.Dispatcher.Stream._document_attrs['version']=='1.0':
- return self.connected
-
- while not self.Dispatcher.Stream.features and self.Process(1):
- pass # If we get version 1.0 stream the features tag MUST BE presented
- if not self.Dispatcher.Stream.features.getTag('starttls'):
- return self.connected # TLS not supported by server
- while not self.TLS.starttls and self.Process(1):
- pass
- if not hasattr(self, 'TLS') or self.TLS.starttls != 'success':
- self.event('tls_failed')
- return self.connected
- self.connected = 'tls'
- return self.connected
+# ================================[ servers ]=================================
class Server:
""" Class to manage a server: buffer, connection, send/recv data. """
@@ -823,6 +425,8 @@ class Server:
def __init__(self, name, **kwargs):
""" Init server """
global jabber_config_file, jabber_config_section, jabber_server_options
+ if name and type(name) == bytes:
+ name = str(name, 'UTF-8')
self.name = name
# create options (user can set them with /set)
self.options = {}
@@ -833,22 +437,17 @@ class Server:
values['name'] = name
values.update(**kwargs)
for option_name, props in jabber_server_options.items():
- self.options[option_name] = w.config_new_option(
- jabber_config_file,
- jabber_config_section["server"],
- self.name + "." + option_name, props["type"],
- props["desc"],
- props["string_values"],
- props["min"],
- props["max"],
- props["default"],
- values[option_name], 0,
+ self.options[option_name] = weechat.config_new_option(
+ jabber_config_file, jabber_config_section["server"],
+ self.name + "." + option_name, props["type"], props["desc"],
+ props["string_values"], props["min"], props["max"],
+ props["default"], values[option_name], 0,
props["check_cb"], self.name, props["change_cb"], "",
props["delete_cb"], "")
# internal data
self.jid = None
self.client = None
- self.sock = None
+ self.sfn = None
self.hook_fd = None
self.buffer = ""
self.chats = []
@@ -862,203 +461,176 @@ class Server:
def option_string(self, option_name):
""" Return a server option, as string. """
- return w.config_string(self.options[option_name])
+ return weechat.config_string(self.options[option_name])
def option_boolean(self, option_name):
""" Return a server option, as boolean. """
- return w.config_boolean(self.options[option_name])
+ return weechat.config_boolean(self.options[option_name])
def option_integer(self, option_name):
""" Return a server option, as string. """
- return w.config_integer(self.options[option_name])
+ return weechat.config_integer(self.options[option_name])
- def make_proxy(self):
- proxy = {}
- pair = os.environ.get('https_proxy', '')
- pair = pair.replace('https://', '')
- pair = pair.replace('http://', '')
- if ':' in pair:
- phost, pport = pair.split(':', 1)
- # '127.0.0.1' 9128
- proxy = {'host': phost, 'port': int(pport)}
- return proxy
-
- def make_buffer(self):
- bufname = "%s.server.%s" % (SCRIPT_NAME, self.name)
- self.buffer = w.buffer_search("python", bufname)
- if not self.buffer:
- self.buffer = w.buffer_new(bufname,
- "jabber_buffer_input_cb", "",
- "jabber_buffer_close_cb", "")
- if self.buffer:
- w.buffer_set(self.buffer, "short_name", self.name)
- w.buffer_set(self.buffer, "localvar_set_type", "server")
- w.buffer_set(self.buffer, "localvar_set_server", self.name)
- w.buffer_set(self.buffer, "nicklist", "1")
- w.buffer_set(self.buffer, "nicklist_display_groups", "1")
- w.buffer_set(self.buffer, "display", "auto")
-
+ def DEBUG(self, *largs):
+ # if jabber_debug_enabled():
+ message = repr(largs)
+ if len(largs) == 1:
+ message = largs[0]
+ if type(message) == bytes:
+ message = str(message, 'UTF-8')
+ if len(largs) == 2:
+ next = largs[1]
+ if type(next) in [list, tuple]:
+ next = ' '.join(next)
+ if type(next) == bytes:
+ next = str(next, 'UTF-8')
+ message += ': ' + next
+ elif len(largs) == 3:
+ next = largs[2]
+ if type(next) == bytes:
+ next = str(next, 'UTF-8')
+ message += ' - ' + next
+ LOG_debug(message)
+
def connect(self):
- """ Connect to Jabber server. """
- try:
- self.connect_()
- except Exception as e:
- oerror = str(e) + ' ' + traceback.format_exc()
- w_prnt(self.buffer, f"%sError during connect {oerror}"
- % w.prefix("error"))
-
- def connect_(self):
""" Connect to Jabber server. """
if not self.buffer:
- self.make_buffer()
+ bufname = "%s.server.%s" % (SCRIPT_NAME, self.name)
+ self.buffer = weechat.buffer_search("python", bufname)
+ if not self.buffer:
+ self.buffer = weechat.buffer_new(bufname,
+ "jabber_buffer_input_cb", "",
+ "jabber_buffer_close_cb", "")
+ if self.buffer:
+ weechat.buffer_set(self.buffer, "short_name", self.name)
+ weechat.buffer_set(self.buffer, "localvar_set_type", "server")
+ weechat.buffer_set(self.buffer, "localvar_set_server", self.name)
+ weechat.buffer_set(self.buffer, "nicklist", "1")
+ weechat.buffer_set(self.buffer, "nicklist_display_groups", "1")
+ weechat.buffer_set(self.buffer, "display", "auto")
self.disconnect()
if not eval_expression(self.option_string("jid")):
- w_prnt(self.buffer, "%sjabber: JID must contain at least domain name"
- % w.prefix("error"))
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: JID must contain at least domain name"
+ % weechat.prefix("error"))
self.ping_up = False
self.client = None
return self.is_connected()
- # server: Server object instance
self.buddy = Buddy(jid=eval_expression(self.option_string("jid")), server=self)
+ transport = None
server = self.option_string("server")
port = self.option_integer("port")
+ aproxy = aget_proxy(self, ltypes=['http'])
+ if aproxy and 'type' in aproxy and aproxy['type'] in [0, 'http']:
+ lserver = (server, port,)
+ transport = transports.HTTPPROXYsocket(aproxy, lserver, use_srv=False)
- secure = False
- if port == 5222:
- secure = False
- elif port == 5223:
- secure = True
- elif ssl_ver != '':
- secure = True
-
- if secure is False:
- assl_dict = dict()
- else:
- ca_certs = w.config_string(self.options['CAfile'])
- certfile = w.config_string(self.options['cert_file'])
- keyfile = w.config_string(self.options['key_file'])
- ssl_ver = w.config_string(self.options['ssl_ver'])
- assert ssl_ver in ['', 'tlsv1.1', 'tlsv1.2', 'tlsv1.3']
- # CERT_NONE: 175f. (certificates ignored),
- # CERT_OPTIONAL: 1760. (not required, but validated if provided),
- # CERT_REQUIRED: 1761. (required and validated).
- if ssl_ver == 'tlsv1':
- cert_reqs = ssl.CERT_OPTIONAL
- elif keyfile or certfile:
- cert_reqs = ssl.CERT_REQUIRED
- else:
- cert_reqs = ssl.CERT_REQUIRED
- ciphers = w.config_string(self.options['ciphers'])
- # http://www.openssl.org/docs/apps/ciphers.html#CIPHER_LIST_FORMAT
- assl_dict = dict(keyfile=keyfile,
- certfile=certfile,
- cert_reqs=cert_reqs,
- ssl_version=ssl.PROTOCOL_TLS,
- ca_certs=ca_certs,
- do_handshake_on_connect=True,
- suppress_ragged_eofs=True,
- ciphers=ciphers)
- self.client = Client(self.buddy.domain,
- port,
- debug=[],
- buffer=self.buffer,
- assl_dict=assl_dict,
- )
conn = None
server_tuple = None
- if not server:
- # override
- # pulled up from self.client.connect
- server = self.buddy.domain
- if port:
- server_tuple = (server, int(port))
- else:
- # override
- # pulled up from self.client.connect
- server_tuple = (server, 5222)
-
- proxy = {}
- if os.environ.get('https_proxy', ''):
- proxy = self.make_proxy()
-
+ if server:
+ if port:
+ server_tuple = (server, port)
+ else:
+ server_tuple = (server)
+
+ debug=['always', 'nodebuilder']
+ self.client = xmpp.client.Client(server=self.buddy.domain,
+ debug=debug)
+ self.client.DEBUG = self.DEBUG
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: Server.connect {server_tuple} {aproxy} {self.client}"
+ % weechat.prefix("network"))
# self.client.connect() may produce a "socket.ssl() is deprecated"
# warning. Since the code producing the warning is outside this script,
# catch it and ignore.
original_filters = warnings.filters[:]
warnings.filterwarnings("ignore", category=DeprecationWarning)
- oerror = None
- conn = None
- use_srv = False
- if False and proxy:
- transport = HTTPPROXYsocket(proxy,
- server_tuple,
- use_srv=use_srv,
- buffer=self.buffer)
- w_prnt(self.buffer,
- f"{w.prefix('network')}jabber: proxy: transport={transport}"
- )
- else:
- transport = None
try:
- conn = self.client.connect(server_tuple,
- proxy=proxy,
- secure=secure,
- use_srv=False,
+ conn = self.client.connect(server=server_tuple,
+ proxy=aproxy,
+ secure=None,
+ use_srv=True,
transport=transport,
)
- except BaseException as e:
- oerror = str(e) + ' ' + traceback.format_exc()
+ except AttributeError as e:
+ # transports error
+ conn = ''
+ except Exception as e:
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: error in connect {e}"
+ % weechat.prefix("error"))
+ conn = ''
finally:
warnings.filters = original_filters
if not conn:
- w_prnt(self.buffer,
- f"{w.prefix('error')}jabber: could not connect: conn={conn} oerror={oerror}"
- )
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: could not connect"
+ % weechat.prefix("error"))
self.ping_up = False
self.client = None
+ return False
+
+ # dunno
+ if hasattr(self.client, 'Connection') and self.client.Connection and \
+ hasattr(self.client.Connection, '_tcpsock') and \
+ hasattr(self.client.Connection._tcpsock, '_sslObj'):
+ ok = f"_sslObj={self.client.Connection._tcpsock._sslObj.fileno()}"
+ elif hasattr(self.client.Connection, '_sock'):
+ ok = f"_sock={self.client.Connection._sock.fileno()}"
+ elif transport:
+ ok = f"transport={transport._sock.fileno()}"
else:
- w_prnt(self.buffer, "jabber: connection ok with %s" % conn)
- #?
- self.ping_up = True
- res = self.buddy.resource
- if not res:
- res = "WeeChat"
+ ok = 'ok'
- w_prnt(self.buffer, f"jabber: auth as {self.buddy.username} {dir(self.client)}")
- auth = self.client.auth(self.buddy.username,
- eval_expression(self.option_string("password")),
- res)
+ weechat.prnt(self.buffer, f"{SCRIPT_NAME}: connection {ok} with {conn}")
+ res = self.buddy.resource
+ if not res:
+ res = "WeeChat"
- if auth:
- w_prnt(self.buffer, f"{w.prefix('network')}authentication ok {auth}")
+ auth = self.client.auth(self.buddy.username,
+ eval_expression(self.option_string("password")),
+ res)
- self.roster = self.client.getRoster()
- self.client.RegisterHandler("presence", self.presence_handler)
- self.client.RegisterHandler("iq", self.iq_handler)
- self.client.RegisterHandler("message", self.message_handler)
- self.client.sendInitPresence(requestRoster=1)
- self.sock = self.client.Connection._sock.fileno()
- self.hook_fd = w.hook_fd(self.sock, 1, 0, 0, "jabber_fd_cb", "")
- w.buffer_set(self.buffer, "highlight_words", self.buddy.username)
- w.buffer_set(self.buffer, "localvar_set_nick", self.buddy.username);
- hook_away = w.hook_command_run("/away -all*", "jabber_away_command_run_cb", "")
-
-
- # setting initial presence
- priority = w.config_integer(self.options['priority'])
- self.set_presence(show="",priority=priority)
-
-
- self.ping_up = True
+ if auth:
+ if hasattr(self.client.Connection, '_sslObj'):
+ ok = f"_sslObj={self.client.Connection._sslObj.fileno()}"
+ self.sfn = self.client.Connection._sslObj.fileno()
+ elif hasattr(self.client.Connection, '_tcpsock'):
+ ok = f"_tcpsock={self.client.Connection._tcpsock.fileno()}"
+ self.sfn = self.client.Connection._sslObj.fileno()
+ elif hasattr(self.client.Connection, '_sock'):
+ ok = f"_sock={dir(self.client.Connection._sock)}"
+ self.sfn = self.client.Connection._sock.fileno()
else:
- w_prnt(self.buffer, "%sjabber: could not authenticate"
- % w.prefix("error"))
- self.ping_up = False
- self.client = None
+ ok = 'ok'
+ weechat.prnt(self.buffer, f"{SCRIPT_NAME}: authentication {ok} (using %s)" % auth)
+
+ self.roster = self.client.getRoster()
+ self.client.RegisterHandler("presence", self.presence_handler)
+ self.client.RegisterHandler("iq", self.iq_handler)
+ self.client.RegisterHandler("message", self.message_handler)
+ self.client.sendInitPresence(requestRoster=1)
+ if self.sfn < 0:
+ weechat.prnt(self.buffer, f"{SCRIPT_NAME}: NO hooking {self.sfn}")
+ else:
+ self.hook_fd = weechat.hook_fd(self.sfn, 1, 0, 0, "jabber_fd_cb", "")
+ weechat.prnt(self.buffer, f"{SCRIPT_NAME}: hooking {self.sfn}")
+ weechat.buffer_set(self.buffer, "highlight_words", self.buddy.username)
+ weechat.buffer_set(self.buffer, "localvar_set_nick", self.buddy.username);
+ hook_away = weechat.hook_command_run("/away -all*", "jabber_away_command_run_cb", "")
+
+
+ # setting initial presence
+ priority = weechat.config_integer(self.options['priority'])
+ self.set_presence(show="",priority=priority)
+
+
+ self.ping_up = True
+ else:
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: could not authenticate"
+ % weechat.prefix("error"))
+ self.ping_up = False
+ self.client = None
return self.is_connected()
def is_connected(self):
@@ -1068,6 +640,21 @@ class Server:
else:
return True
+ def display_roster(self):
+ """Return connect status"""
+ if not self.roster:
+ if hasattr(self.client, 'Roster'):
+ self.roster = self.client.Roster
+ else:
+ self.roster = self.client.getRoster()
+ weechat.prnt(self.buffer, "")
+ weechat.prnt(self.buffer, "Roster:")
+ for elt in self.roster.getItems():
+ weechat.prnt(self.buffer, repr(elt))
+
+ len_max = { 'alias': 5, 'jid': 5 }
+ return True
+
def add_chat(self, buddy):
"""Create a chat buffer for a buddy"""
chat = Chat(self, buddy, switch_to_buffer=False)
@@ -1087,7 +674,7 @@ class Server:
def print_debug_server(self, message):
""" Print debug message on server buffer. """
if jabber_debug_enabled():
- w_prnt(self.buffer, "%sjabber: %s" % (w.prefix("network"), message))
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: %s" % (weechat.prefix("network"), message))
def print_debug_handler(self, handler_name, node):
""" Print debug message for a handler on server buffer. """
@@ -1098,7 +685,7 @@ class Server:
def print_error(self, message):
""" Print error message on server buffer. """
if jabber_debug_enabled():
- w_prnt(self.buffer, "%sjabber: %s" % (w.prefix("error"), message))
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: %s" % (weechat.prefix("error"), message))
def presence_handler(self, conn, node):
self.print_debug_handler("presence", node)
@@ -1117,7 +704,7 @@ class Server:
if self.roster:
name = self.roster.getName(buddy.bare_jid)
if name:
- buddy.set_name(name.encode("utf-8"))
+ buddy.set_name(name)
buddy.set_status(status=status, away=away)
self.update_nicklist(buddy=buddy, action=action)
return
@@ -1125,7 +712,7 @@ class Server:
def iq_handler(self, conn, node):
""" Receive iq message. """
self.print_debug_handler("iq", node)
- #w_prnt(self.buffer, "jabber: iq handler")
+ #weechat.prnt(self.buffer, f"{SCRIPT_NAME}: iq handler")
if node.getFrom() == self.buddy.domain:
# type='result' => pong from server
# type='error' => error message from server
@@ -1136,13 +723,29 @@ class Server:
if node.getType() in ['result', 'error']:
self.delete_ping_timeout_timer() # Disable the timeout feature
self.ping_up = True
- if not self.client.isConnected() and w.config_boolean(self.options['autoreconnect']):
+ if not self.client.isConnected() and weechat.config_boolean(self.options['autoreconnect']):
self.connect()
def message_handler(self, conn, node):
""" Receive message. """
self.print_debug_handler("message", node)
node_type = node.getType()
+ if node_type in ['headline']: # MUC
+ a = """
+ jabber: message_handler, xml message: │
+ | b'\n \n \n - \n │
+ | \n \n │
+ | test_h\n\n \n test_ │
+ | h\n\n\n
\n\n\ │
+ | n \n │
+ | \n\n\n' """
+ return
if node_type not in ["message", "chat", None]:
self.print_error("unknown message type: '%s'" % node_type)
return
@@ -1157,7 +760,7 @@ class Server:
# buffer even if private is off. The buffer may have been created with
# /jchat.
recv_object = self
- if not buddy.chat and w.config_boolean(self.options['private']):
+ if not buddy.chat and weechat.config_boolean(self.options['private']):
self.add_chat(buddy)
if buddy.chat:
recv_object = buddy.chat
@@ -1165,35 +768,50 @@ class Server:
def recv(self):
""" Receive something from Jabber server. """
+ LOG_debug(f"recv: {self.client}")
if not self.client:
return
try:
self.client.Process(1)
except xmpp.protocol.StreamError as e:
- w_prnt('', '%s: Error from server: %s' %(SCRIPT_NAME, e))
+ weechat.prnt('', '%s: Error from server: %s' %(SCRIPT_NAME, e))
self.disconnect()
- if w.config_boolean(self.options['autoreconnect']):
+ if weechat.config_boolean(self.options['autoreconnect']):
autoreconnect_delay = 30
- w.command('', '/wait %s /%s connect %s' %
+ weechat.command('', '/wait %s /%s connect %s' %
(autoreconnect_delay, SCRIPT_COMMAND, self.name))
def recv_message(self, buddy, message):
""" Receive a message from buddy. """
- w_prnt_date_tags(self.buffer, 0,
- "notify_private,nick_%s,prefix_nick_%s,log1" %
- (buddy.alias,
- w.config_string(w.config_get("weechat.color.chat_nick_other"))),
- "%s%s\t%s" % (w.color("chat_nick_other"),
+ LOG_debug(f"recv_message: {message}")
+ if type(message) == bytes:
+ message = str(message, 'UTF-8')
+ if type(buddy.alias) == bytes:
+ buddy.alias = str(buddy.alias, 'UTF-8')
+ nickc = weechat.config_get("weechat.color.chat_nick_other")
+ weechat.prnt_date_tags(self.buffer,
+ 0,
+ f"notify_private,nick_{buddy.alias}" +
+ f",prefix_nick_%s,log1" %
+ (weechat.config_string(nickc)),
+ "%s%s\t%s" % (weechat.color("chat_nick_other"),
buddy.alias,
message))
def print_status(self, nickname, status):
""" Print a status in server window and in chat. """
- w_prnt_date_tags(self.buffer, 0, "no_highlight", "%s%s has status %s" %
- (w.prefix("action"),
+ if type(nickname) == bytes:
+ nickname = str(nickname, 'UTF-8')
+ weechat.prnt_date_tags(self.buffer,
+ 0,
+ "no_highlight",
+ "%s%s has status %s" %
+ (weechat.prefix("action"),
nickname,
status))
for chat in self.chats:
+ if type(chat.buddy.alias) == bytes:
+ chat.buddy.alias = str(chat.buddy.alias, 'UTF-8')
if nickname in chat.buddy.alias:
chat.print_status(status)
break
@@ -1208,28 +826,35 @@ class Server:
if isinstance(buddy, Buddy):
recipient = buddy.jid
if not self.ping_up:
- w_prnt(self.buffer, "%sjabber: unable to send message, connection is down"
- % w.prefix("error"))
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: unable to send message, connection is down"
+ % weechat.prefix("error"))
return
- if self.client:
+ if not self.client:
+ return
+ try:
+ # bytes?
msg = xmpp.protocol.Message(to=recipient, body=message, typ='chat')
self.client.send(msg)
+ except Exception as e:
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: send_message error {e}"
+ % weechat.prefix("error"))
def send_message_from_input(self, input=''):
""" Send a message from input text on server buffer. """
# Input must be of format "name: message" where name is a jid, bare_jid
# or alias. The colon can be replaced with a comma as well.
# Split input into name and message.
+ LOG_debug(f"send_message_from_input: {input}")
if not re.compile(r'.+[:,].+').match(input):
- w_prnt(self.buffer, "%sjabber: %s" % (w.prefix("network"),
- "Invalid send format. Use jid: message"
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: %s" % (weechat.prefix("network"),
+ "Invalid send format {input}. Use jid: message"
))
return
name, message = re.split('[:,]', input, maxsplit=1)
buddy = self.search_buddy_list(name, by='alias')
if not buddy:
- w_prnt(self.buffer,
- "%sjabber: Invalid jid: %s" % (w.prefix("network"),
+ weechat.prnt(self.buffer,
+ f"%s{SCRIPT_NAME}: Invalid jid: %s" % (weechat.prefix("network"),
name))
return
# Send activity indicates user is no longer away, set it so
@@ -1240,11 +865,14 @@ class Server:
sender = self.buddy.alias
except:
sender = self.jid
- w_prnt_date_tags(self.buffer, 0,
+ if type(sender) == bytes:
+ sender = str(sender, 'UTF-8')
+ weechat.prnt_date_tags(self.buffer,
+ 0,
"notify_none,no_highlight,nick_%s,prefix_nick_%s,log1" %
(sender,
- w.config_string(w.config_get("weechat.color.chat_nick_self"))),
- "%s%s\t%s" % (w.color("chat_nick_self"),
+ weechat.config_string(weechat.config_get("weechat.color.chat_nick_self"))),
+ "%s%s\t%s" % (weechat.color("chat_nick_self"),
sender,
message.strip()))
@@ -1257,12 +885,12 @@ class Server:
if message:
show = "xa"
status = message
- priority = w.config_integer(self.options['away_priority'])
+ priority = weechat.config_integer(self.options['away_priority'])
self.buddy.set_status(away=True, status=message)
else:
show = ""
status = None
- priority = w.config_integer(self.options['priority'])
+ priority = weechat.config_integer(self.options['priority'])
self.buddy.set_status(away=False)
self.set_presence(show, status, priority)
@@ -1280,8 +908,8 @@ class Server:
def display_buddies(self):
""" Display buddies. """
- w_prnt(self.buffer, "")
- w_prnt(self.buffer, "Buddies:")
+ weechat.prnt(self.buffer, "")
+ weechat.prnt(self.buffer, "Buddies:")
len_max = { 'alias': 5, 'jid': 5 }
lines = []
@@ -1289,7 +917,9 @@ class Server:
alias = ''
if buddy.alias != buddy.bare_jid:
alias = buddy.alias
- buddy_jid_string = buddy.jid.getStripped().encode('utf-8')
+ buddy_jid_string = buddy.jid.getStripped()
+ if type(buddy_jid_string) == bytes:
+ buddy_jid_string = str(buddy_jid_string, 'UTF-8')
lines.append( {
'jid': buddy_jid_string,
'alias': alias,
@@ -1300,9 +930,9 @@ class Server:
if len(buddy_jid_string) > len_max['jid']:
len_max['jid'] = len(buddy_jid_string)
prnt_format = " %s%-" + str(len_max['jid']) + "s %-" + str(len_max['alias']) + "s %s"
- w_prnt(self.buffer, prnt_format % ('', 'JID', 'Alias', 'Status'))
+ weechat.prnt(self.buffer, prnt_format % ('', 'JID', 'Alias', 'Status'))
for line in lines:
- w_prnt(self.buffer, prnt_format % (w.color("chat_nick"),
+ weechat.prnt(self.buffer, prnt_format % (weechat.color("chat_nick"),
line['jid'],
line['alias'],
line['status'],
@@ -1325,7 +955,7 @@ class Server:
if wresource and jid.resource:
# concatenate jid with resource delimiter first and encode them
# into utf-8, else it will raise UnicodeException becaouse of
- # slash character:((
+ # slash character :((
return (jid_str + '/').encode("utf-8") + jid.resource.encode("utf-8")
return jid_str.encode("utf-8")
@@ -1372,8 +1002,8 @@ class Server:
return
if not action in ['remove', 'update']:
return
- ptr_nick_gui = w.nicklist_search_nick(self.buffer, "", buddy.alias)
- w.nicklist_remove_nick(self.buffer, ptr_nick_gui)
+ ptr_nick_gui = weechat.nicklist_search_nick(self.buffer, "", buddy.alias)
+ weechat.nicklist_remove_nick(self.buffer, ptr_nick_gui)
msg = ''
prefix = ''
color = ''
@@ -1382,7 +1012,7 @@ class Server:
nick_color = "bar_fg"
if buddy.away:
nick_color = "weechat.color.nicklist_away"
- w.nicklist_add_nick(self.buffer, "", buddy.alias,
+ weechat.nicklist_add_nick(self.buffer, "", buddy.alias,
nick_color, "", "", 1)
if not ptr_nick_gui:
msg = 'joined'
@@ -1394,9 +1024,9 @@ class Server:
prefix = 'quit'
color = 'message_quit'
if msg:
- w_prnt(self.buffer, "%s%s%s%s has %s %s"
- % (w.prefix(prefix),
- w.color("chat_nick"),
+ weechat.prnt(self.buffer, "%s%s%s%s has %s %s"
+ % (weechat.prefix(prefix),
+ weechat.color("chat_nick"),
buddy.alias,
jabber_config_color(color),
msg,
@@ -1408,13 +1038,13 @@ class Server:
self.delete_ping_timer()
if not self.option_integer('ping_interval'):
return
- self.ping_timer = w.hook_timer( self.option_integer('ping_interval') * 1000,
+ self.ping_timer = weechat.hook_timer( self.option_integer('ping_interval') * 1000,
0, 0, "jabber_ping_timer", self.name)
return
def delete_ping_timer(self):
if self.ping_timer:
- w.unhook(self.ping_timer)
+ weechat.unhook(self.ping_timer)
self.ping_time = None
return
@@ -1423,14 +1053,14 @@ class Server:
self.delete_ping_timeout_timer()
if not self.option_integer('ping_timeout'):
return
- self.ping_timeout_timer = w.hook_timer(
+ self.ping_timeout_timer = weechat.hook_timer(
self.option_integer('ping_timeout') * 1000, 0, 1,
"jabber_ping_timeout_timer", self.name)
return
def delete_ping_timeout_timer(self):
if self.ping_timeout_timer:
- w.unhook(self.ping_timeout_timer)
+ weechat.unhook(self.ping_timeout_timer)
self.ping_timeout_timer = None
return
@@ -1461,21 +1091,21 @@ class Server:
def disconnect(self):
""" Disconnect from Jabber server. """
if self.hook_fd != None:
- w.unhook(self.hook_fd)
+ weechat.unhook(self.hook_fd)
self.hook_fd = None
if self.client != None:
#if self.client.isConnected():
# self.client.disconnect()
self.client = None
self.jid = None
- self.sock = None
+ self.sfn = None
self.buddy = None
- w.nicklist_remove_all(self.buffer)
+ weechat.nicklist_remove_all(self.buffer)
def close_buffer(self):
""" Close server buffer. """
if self.buffer != "":
- w.buffer_close(self.buffer)
+ weechat.buffer_close(self.buffer)
self.buffer = ""
def delete(self, deleteOptions=False):
@@ -1488,13 +1118,12 @@ class Server:
self.close_buffer()
if deleteOptions:
for name, option in self.options.items():
- w.config_option_free(option)
+ weechat.config_option_free(option)
def eval_expression(option_name):
""" Return a evaluated expression """
- version = int(w.info_get("version_number", "") or 0)
if int(version) >= 0x00040200:
- return w.string_eval_expression(option_name,{},{},{})
+ return weechat.string_eval_expression(option_name,{},{},{})
else:
return option_name
@@ -1525,7 +1154,7 @@ def jabber_search_context_by_name(server_name):
"""Search for buffer given name of server. """
bufname = "%s.server.%s" % (SCRIPT_NAME, server_name)
- return jabber_search_context(w.buffer_search("python", bufname))
+ return jabber_search_context(weechat.buffer_search("python", bufname))
# =================================[ chats ]==================================
@@ -1538,62 +1167,77 @@ class Chat:
self.server = server
self.buddy = buddy
buddy.chat = self
- bufname = "%s.%s.%s" % (SCRIPT_NAME, server.name, self.buddy.alias)
- self.buffer = w.buffer_search("python", bufname)
+ if type(buddy.alias) == bytes:
+ buddy.alias = str(buddy.alias, 'UTF-8')
+ alias = self.buddy.alias
+ bufname = "%s.%s.%s" % (SCRIPT_NAME, server.name, alias)
+ self.buffer = weechat.buffer_search("python", bufname)
if not self.buffer:
- self.buffer = w.buffer_new(bufname,
+ self.buffer = weechat.buffer_new(bufname,
"jabber_buffer_input_cb", "",
"jabber_buffer_close_cb", "")
self.buffer_title = self.buddy.alias
if self.buffer:
- w.buffer_set(self.buffer, "title", self.buffer_title)
- w.buffer_set(self.buffer, "short_name", self.buddy.alias)
- w.buffer_set(self.buffer, "localvar_set_type", "private")
- w.buffer_set(self.buffer, "localvar_set_server", server.name)
- w.buffer_set(self.buffer, "localvar_set_channel", self.buddy.alias)
- w.hook_signal_send("logger_backlog",
- w.WEECHAT_HOOK_SIGNAL_POINTER, self.buffer)
+ weechat.buffer_set(self.buffer, "title", self.buffer_title)
+ weechat.buffer_set(self.buffer, "short_name", self.buddy.alias)
+ weechat.buffer_set(self.buffer, "localvar_set_type", "private")
+ weechat.buffer_set(self.buffer, "localvar_set_server", server.name)
+ weechat.buffer_set(self.buffer, "localvar_set_channel", self.buddy.alias)
+ weechat.hook_signal_send("logger_backlog",
+ weechat.WEECHAT_HOOK_SIGNAL_POINTER, self.buffer)
if switch_to_buffer:
- w.buffer_set(self.buffer, "display", "auto")
+ weechat.buffer_set(self.buffer, "display", "auto")
def recv_message(self, buddy, message):
""" Receive a message from buddy. """
+ LOG_debug(f"recv_message: {message}")
+ if type(message) == bytes:
+ message = str(message, 'UTF-8')
+ if type(buddy.alias) == bytes:
+ buddy.alias = str(buddy.alias, 'UTF-8')
if buddy.alias != self.buffer_title:
self.buffer_title = buddy.alias
- w.buffer_set(self.buffer, "title", "%s" % self.buffer_title)
- w_prnt_date_tags(self.buffer, 0,
+ weechat.buffer_set(self.buffer, "title", "%s" % self.buffer_title)
+ weechat.prnt_date_tags(self.buffer, 0,
"notify_private,nick_%s,prefix_nick_%s,log1" %
(buddy.alias,
- w.config_string(w.config_get("weechat.color.chat_nick_other"))),
- "%s%s\t%s" % (w.color("chat_nick_other"),
+ weechat.config_string(weechat.config_get("weechat.color.chat_nick_other"))),
+ "%s%s\t%s" % (weechat.color("chat_nick_other"),
buddy.alias,
message))
def send_message(self, message):
""" Send message to buddy. """
if not self.server.ping_up:
- w_prnt(self.buffer, "%sxmpp: unable to send message, connection is down"
- % w.prefix("error"))
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: unable to send message, connection is down"
+ % weechat.prefix("error"))
return
- self.server.send_message(self.buddy, message)
- w_prnt_date_tags(self.buffer, 0,
- "notify_none,no_highlight,nick_%s,prefix_nick_%s,log1" %
- (self.server.buddy.alias,
- w.config_string(w.config_get("weechat.color.chat_nick_self"))),
- "%s%s\t%s" % (w.color("chat_nick_self"),
- self.server.buddy.alias,
- message))
+ if type(self.server.buddy.alias) == bytes:
+ self.server.buddy.alias = str(self.server.buddy.alias, 'UTF-8')
+ try:
+ self.server.send_message(self.buddy, message)
+ weechat.prnt_date_tags(self.buffer, 0,
+ "notify_none,no_highlight,nick_%s,prefix_nick_%s,log1" %
+ (self.server.buddy.alias,
+ weechat.config_string(weechat.config_get("weechat.color.chat_nick_self"))),
+ "%s%s\t%s" % (weechat.color("chat_nick_self"),
+ self.server.buddy.alias,
+ message))
+ except Exception as e:
+ weechat.prnt(self.buffer, f"%s{SCRIPT_NAME}: error sending message {e}"
+ % weechat.prefix("error"))
+
def print_status(self, status):
""" Print a status message in chat. """
- w_prnt(self.buffer, "%s%s has status %s" %
- (w.prefix("action"),
+ weechat.prnt(self.buffer, "%s%s has status %s" %
+ (weechat.prefix("action"),
self.buddy.alias,
status))
def close_buffer(self):
""" Close chat buffer. """
if self.buffer != "":
- w.buffer_close(self.buffer)
+ weechat.buffer_close(self.buffer)
self.buffer = ""
def delete(self):
@@ -1645,11 +1289,11 @@ class Buddy:
str_colon = ": "
if not self.status:
str_colon = ""
- return "%s(%saway%s%s%s)" % (w.color("chat_delimiters"),
- w.color("chat"),
+ return "%s(%saway%s%s%s)" % (weechat.color("chat_delimiters"),
+ weechat.color("chat"),
str_colon,
self.status.replace("\n", " "),
- w.color("chat_delimiters"))
+ weechat.color("chat_delimiters"))
def parse_jid(self):
"""Parse the jid property.
@@ -1682,6 +1326,8 @@ class Buddy:
if not self.bare_jid:
self.alias = ''
if self.name:
+ if type(name) == bytes:
+ name = str(name, 'UTF-8')
self.alias = self.name
global jabber_jid_aliases
for alias, jid in jabber_jid_aliases.items():
@@ -1691,6 +1337,8 @@ class Buddy:
return
def set_name(self, name=''):
+ if type(name) == bytes:
+ name = str(name, 'UTF-8')
self.name = name
self.set_alias()
return
@@ -1716,17 +1364,18 @@ class Buddy:
def jabber_hook_commands_and_completions():
""" Hook commands and completions. """
- w.hook_command(SCRIPT_COMMAND, "Manage Jabber servers",
+ weechat.hook_command(SCRIPT_COMMAND, "Manage Jabber servers",
"list || add [[:]]"
" || connect|disconnect|del [] || alias [add|del ]"
" || away [] || buddies || priority []"
" || status [] || presence [online|chat|away|xa|dnd]"
- " || debug || set []",
+ " || ping || debug || set []",
" list: list servers and chats\n"
" add: add a server\n"
" connect: connect to server using password\n"
"disconnect: disconnect from server\n"
" del: delete server\n"
+ " ping: ping server\n"
" alias: manage jid aliases\n"
" away: set away with a message (if no message, away is unset)\n"
" priority: set priority\n"
@@ -1761,45 +1410,47 @@ def jabber_hook_commands_and_completions():
" || del %(jabber_servers)"
" || alias add|del %(jabber_jid_aliases)"
" || away"
+ " || ping"
" || priority"
+ " || roster"
" || status"
" || presence online|chat|away|xa|dnd"
" || buddies"
" || debug",
"jabber_cmd_jabber", "")
- w.hook_command("jchat", "Chat with a Jabber buddy",
+ weechat.hook_command("jchat", "Chat with a Jabber buddy",
"",
"buddy: buddy id",
"",
"jabber_cmd_jchat", "")
- w.hook_command("jmsg", "Send a messge to a buddy",
+ weechat.hook_command("jmsg", "Send a messge to a buddy",
"[-server ] ",
"server: name of jabber server buddy is on\n"
" buddy: buddy id\n"
" text: text to send",
"",
"jabber_cmd_jmsg", "")
- w.hook_command("invite", "Add a buddy to your roster",
+ weechat.hook_command("invite", "Add a buddy to your roster",
"",
"buddy: buddy id",
"",
"jabber_cmd_invite", "")
- w.hook_command("kick", "Remove a buddy from your roster, or deny auth",
+ weechat.hook_command("kick", "Remove a buddy from your roster, or deny auth",
"",
"buddy: buddy id",
"",
"jabber_cmd_kick", "")
- w.hook_completion("jabber_servers", "list of jabber servers",
+ weechat.hook_completion("jabber_servers", "list of jabber servers",
"jabber_completion_servers", "")
- w.hook_completion("jabber_jid_aliases", "list of jabber jid aliases",
+ weechat.hook_completion("jabber_jid_aliases", "list of jabber jid aliases",
"jabber_completion_jid_aliases", "")
def jabber_list_servers_chats(name):
""" List servers and chats. """
global jabber_servers
- w_prnt("", "")
+ weechat.prnt("", "")
if len(jabber_servers) > 0:
- w_prnt("", "jabber servers:")
+ weechat.prnt("", "jabber servers:")
for server in jabber_servers:
if name == "" or server.name.find(name) >= 0:
conn_server = ''
@@ -1808,17 +1459,15 @@ def jabber_list_servers_chats(name):
(server.option_string("server"),
server.option_string("port")))
connected = ""
- if server.sock and server.sock >= 0:
+ if server.sfn and server.sfn >= 0:
connected = "(connected)"
- else:
- connected = "(not conn)"
- w_prnt("", " %s - %s %s %s" % (server.name,
+ weechat.prnt("", " %s - %s %s %s" % (server.name,
eval_expression(server.option_string("jid")), conn_server, connected))
for chat in server.chats:
- w_prnt("", " chat with %s" % (chat.buddy))
+ weechat.prnt("", " chat with %s" % (chat.buddy))
else:
- w_prnt("", "jabber: no server defined")
+ weechat.prnt("", f"{SCRIPT_NAME}: no server defined")
def jabber_cmd_jabber(data, buffer, args):
""" Command '/jabber'. """
@@ -1837,49 +1486,47 @@ def jabber_cmd_jabber(data, buffer, args):
if len(argv) >= 4:
server = jabber_search_server_by_name(argv[1])
if server:
- w_prnt("", "jabber: server '%s' already exists" % argv[1])
+ weechat.prnt("", f"{SCRIPT_NAME}: server '%s' already exists" % argv[1])
else:
kwargs = {'jid': argv[2], 'password': argv[3]}
if len(argv) > 4:
conn_server, _, conn_port = argv[4].partition(':')
if conn_port and not conn_port.isdigit():
- w_prnt("", "jabber: error, invalid port, digits only")
- return w.WEECHAT_RC_OK
+ weechat.prnt("", f"{SCRIPT_NAME}: error, invalid port, digits only")
+ return weechat.WEECHAT_RC_OK
if conn_server: kwargs['server'] = conn_server
if conn_port: kwargs['port'] = conn_port
server = Server(argv[1], **kwargs)
jabber_servers.append(server)
- w_prnt("", "jabber: server '%s' created" % argv[1])
+ weechat.prnt("", f"{SCRIPT_NAME}: server '%s' created" % argv[1])
else:
- w_prnt("", "jabber: unable to add server, missing arguments")
- w_prnt("", "jabber: usage: /jabber add name jid password [server[:port]]")
+ weechat.prnt("", f"{SCRIPT_NAME}: unable to add server, missing arguments")
+ weechat.prnt("", f"{SCRIPT_NAME}: usage: /jabber add name jid password [server[:port]]")
elif argv[0] == "alias":
alias_command = AliasCommand(buffer, argv=argv[1:])
alias_command.run()
-
elif argv[0] == "connect":
server = None
if len(argv) >= 2:
server = jabber_search_server_by_name(argv[1])
if not server:
- w_prnt("", "jabber: server '%s' not found" % argv[1])
+ weechat.prnt("", f"{SCRIPT_NAME}: server '%s' not found" % argv[1])
else:
context = jabber_search_context(buffer)
if context["server"]:
server = context["server"]
if server:
- if w.config_boolean(server.options['autoreconnect']):
+ if weechat.config_boolean(server.options['autoreconnect']):
server.ping() # This will connect and update ping status
server.add_ping_timer()
else:
server.connect()
-
elif argv[0] == "disconnect":
server = None
if len(argv) >= 2:
server = jabber_search_server_by_name(argv[1])
if not server:
- w_prnt("", "jabber: server '%s' not found" % argv[1])
+ weechat.prnt("", f"{SCRIPT_NAME}: server '%s' not found" % argv[1])
else:
context = jabber_search_context(buffer)
if context["server"]:
@@ -1894,9 +1541,9 @@ def jabber_cmd_jabber(data, buffer, args):
if server:
server.delete(deleteOptions=True)
jabber_servers.remove(server)
- w_prnt("", "jabber: server '%s' deleted" % argv[1])
+ weechat.prnt("", f"{SCRIPT_NAME}: server '%s' deleted" % argv[1])
else:
- w_prnt("", "jabber: server '%s' not found" % argv[1])
+ weechat.prnt("", f"{SCRIPT_NAME}: server '%s' not found" % argv[1])
elif argv[0] == "send":
if len(argv) >= 3:
context = jabber_search_context(buffer)
@@ -1914,27 +1561,28 @@ def jabber_cmd_jabber(data, buffer, args):
context = jabber_search_context(buffer)
if context["server"]:
if len(argv) == 1:
- w_prnt("", "jabber: priority = %d" % int(context["server"].presence.getPriority()))
+ weechat.prnt("", f"{SCRIPT_NAME}: priority = %d" % int(context["server"].presence.getPriority()))
elif len(argv) == 2 and argv[1].isdigit():
context["server"].set_presence(priority=int(argv[1]))
else:
- w_prnt("", "jabber: you need to specify priority as positive integer between 0 and 65535")
+ weechat.prnt("", f"{SCRIPT_NAME}: you need to specify priority as positive integer between 0 and 65535")
elif argv[0] == "status":
context = jabber_search_context(buffer)
if context["server"]:
if len(argv) == 1:
- w_prnt("", "jabber: status = %s" % context["server"].presence.getStatus())
+ weechat.prnt("", f"{SCRIPT_NAME}: status = %s" % context["server"].presence.getStatus())
else:
context["server"].set_presence(status=argv1eol)
+
elif argv[0] == "presence":
context = jabber_search_context(buffer)
if context["server"]:
if len(argv) == 1:
show = context["server"].presence.getShow()
if show == "": show = "online"
- w_prnt("", "jabber: presence = %s" % show)
+ weechat.prnt("", f"{SCRIPT_NAME}: presence = %s" % show)
elif not re.match(r'^(?:online|chat|away|xa|dnd)$', argv[1]):
- w_prnt("", "jabber: Presence should be one of: online, chat, away, xa, dnd")
+ weechat.prnt("", f"{SCRIPT_NAME}: Presence should be one of: online, chat, away, xa, dnd")
else:
if argv[1] == "online": show = ""
else: show = argv[1]
@@ -1943,16 +1591,23 @@ def jabber_cmd_jabber(data, buffer, args):
context = jabber_search_context(buffer)
if context["server"]:
context["server"].display_buddies()
-
+ elif argv[0] == "roster":
+ context = jabber_search_context(buffer)
+ if context["server"]:
+ context["server"].display_roster()
+ elif argv[0] == "ping":
+ context = jabber_search_context(buffer)
+ if context["server"]:
+ context["server"].ping()
elif argv[0] == "debug":
- w.config_option_set(jabber_config_option["debug"], "toggle", 1)
+ weechat.config_option_set(jabber_config_option["debug"], "toggle", 1)
if jabber_debug_enabled():
- w_prnt("", "jabber: debug is now ON")
+ weechat.prnt("", f"{SCRIPT_NAME}: debug is now ON")
else:
- w_prnt("", "jabber: debug is now off")
+ weechat.prnt("", f"{SCRIPT_NAME}: debug is now off")
else:
- w_prnt("", "jabber: unknown action")
- return w.WEECHAT_RC_OK
+ weechat.prnt("", f"{SCRIPT_NAME}: unknown action")
+ return weechat.WEECHAT_RC_OK
def jabber_cmd_jchat(data, buffer, args):
""" Command '/jchat'. """
@@ -1964,15 +1619,15 @@ def jabber_cmd_jchat(data, buffer, args):
buddy = context["server"].add_buddy(jid=args)
if not buddy.chat:
context["server"].add_chat(buddy)
- w.buffer_set(buddy.chat.buffer, "display", "auto")
- return w.WEECHAT_RC_OK
+ weechat.buffer_set(buddy.chat.buffer, "display", "auto")
+ return weechat.WEECHAT_RC_OK
def jabber_cmd_jmsg(data, buffer, args):
""" Command '/jmsg'. """
if args:
argv = args.split()
if len(argv) < 2:
- return w.WEECHAT_RC_OK
+ return weechat.WEECHAT_RC_OK
if argv[0] == '-server':
context = jabber_search_context_by_name(argv[1])
recipient = argv[2]
@@ -1985,7 +1640,7 @@ def jabber_cmd_jmsg(data, buffer, args):
buddy = context['server'].search_buddy_list(recipient, by='alias')
context["server"].send_message(buddy, message)
- return w.WEECHAT_RC_OK
+ return weechat.WEECHAT_RC_OK
def jabber_cmd_invite(data, buffer, args):
""" Command '/invite'. """
@@ -1993,7 +1648,7 @@ def jabber_cmd_invite(data, buffer, args):
context = jabber_search_context(buffer)
if context["server"]:
context["server"].add_buddy(args)
- return w.WEECHAT_RC_OK
+ return weechat.WEECHAT_RC_OK
def jabber_cmd_kick(data, buffer, args):
""" Command '/kick'. """
@@ -2001,7 +1656,7 @@ def jabber_cmd_kick(data, buffer, args):
context = jabber_search_context(buffer)
if context["server"]:
context["server"].del_buddy(args)
- return w.WEECHAT_RC_OK
+ return weechat.WEECHAT_RC_OK
def jabber_away_command_run_cb(data, buffer, command):
""" Callback called when /away -all command is run """
@@ -2014,7 +1669,7 @@ def jabber_away_command_run_cb(data, buffer, command):
message = words[2]
for server in jabber_servers:
server.set_away(message)
- return w.WEECHAT_RC_OK
+ return weechat.WEECHAT_RC_OK
class AliasCommand(object):
"""Class representing a jabber alias command, ie /jabber alias ..."""
@@ -2041,37 +1696,38 @@ class AliasCommand(object):
"""Run a "/jabber alias add" command"""
global jabber_jid_aliases
if not self.alias or not self.jid:
- w_prnt("", "\njabber: unable to add alias, missing arguments")
- w_prnt("", "jabber: usage: /jabber alias add alias_name jid")
+ weechat.prnt("", "\njabber: unable to add alias, missing arguments")
+ weechat.prnt("", f"{SCRIPT_NAME}: usage: /jabber alias add alias_name jid")
return
# Restrict the character set of aliases. The characters must be writable to
# config file.
invalid_re = re.compile(r'[^a-zA-Z0-9\[\]\\\^_\-{|}@\.]')
if invalid_re.search(self.alias):
- w_prnt("", "\njabber: invalid alias: %s" % self.alias)
- w_prnt("", "jabber: use only characters: a-z A-Z 0-9 [ \ ] ^ _ - { | } @ .")
+ weechat.prnt("", "\njabber: invalid alias: %s" % self.alias)
+ weechat.prnt("", f"{SCRIPT_NAME}: use only characters:" +
+ "a-z A-Z 0-9 [ \ ] ^ _ - { | } @ .")
return
# Ensure alias and jid are reasonable length.
max_len = 64
if len(self.alias) > max_len:
- w_prnt("", "\njabber: invalid alias: %s" % self.alias)
- w_prnt("", "jabber: must be no more than %s characters long" % max_len)
+ weechat.prnt("", "\njabber: invalid alias: %s" % self.alias)
+ weechat.prnt("", f"{SCRIPT_NAME}: must be no more than %s characters long" % max_len)
return
if len(self.jid) > max_len:
- w_prnt("", "\njabber: invalid jid: %s" % self.jid)
- w_prnt("", "jabber: must be no more than %s characters long" % max_len)
+ weechat.prnt("", "\njabber: invalid jid: %s" % self.jid)
+ weechat.prnt("", f"{SCRIPT_NAME}: must be no more than %s characters long" % max_len)
return
jid = self.jid.encode("utf-8")
alias = self.alias.encode("utf-8")
if alias in jabber_jid_aliases.keys():
- w_prnt("", "\njabber: unable to add alias: %s" % (alias))
- w_prnt("", "jabber: alias already exists, delete first")
+ weechat.prnt("", "\njabber: unable to add alias: %s" % (alias))
+ weechat.prnt("", f"{SCRIPT_NAME}: alias already exists, delete first")
return
if jid in jabber_jid_aliases.values():
- w_prnt("", "\njabber: unable to add alias: %s" % (alias))
+ weechat.prnt("", "\njabber: unable to add alias: %s" % (alias))
for a, j in jabber_jid_aliases.items():
if j == jid:
- w_prnt("", "jabber: jid '%s' is already aliased as '%s', delete first" %
+ weechat.prnt("", f"{SCRIPT_NAME}: jid '%s' is already aliased as '%s', delete first" %
(j, a))
break
jabber_jid_aliases[alias] = jid
@@ -2099,18 +1755,18 @@ class AliasCommand(object):
buddy.chat.delete()
new_chat = server.add_chat(buddy)
if switch_to_buffer:
- w.buffer_set(new_chat.buffer, "display", "auto")
+ weechat.buffer_set(new_chat.buffer, "display", "auto")
return
def delete(self):
"""Run a "/jabber alias del" command"""
global jabber_jid_aliases
if not self.alias:
- w_prnt("", "\njabber: unable to delete alias, missing arguments")
- w_prnt("", "jabber: usage: /jabber alias del alias_name")
+ weechat.prnt("", "\njabber: unable to delete alias, missing arguments")
+ weechat.prnt("", f"{SCRIPT_NAME}: usage: /jabber alias del alias_name")
return
if not self.alias in jabber_jid_aliases:
- w_prnt("", "\njabber: unable to delete alias '%s', not found" % (self.alias))
+ weechat.prnt("", "\njabber: unable to delete alias '%s', not found" % (self.alias))
return
jid = jabber_jid_aliases[self.alias]
del jabber_jid_aliases[self.alias]
@@ -2120,11 +1776,11 @@ class AliasCommand(object):
def list(self):
"""Run a "/jabber alias" command to list aliases"""
global jabber_jid_aliases
- w_prnt("", "")
+ weechat.prnt("", "")
if len(jabber_jid_aliases) <= 0:
- w_prnt("", "jabber: no aliases defined")
+ weechat.prnt("", f"{SCRIPT_NAME}: no aliases defined")
return
- w_prnt("", "jabber jid aliases:")
+ weechat.prnt("", "jabber jid aliases:")
len_alias = 5
len_jid = 5
for alias, jid in jabber_jid_aliases.items():
@@ -2133,9 +1789,9 @@ class AliasCommand(object):
if len_jid < len(jid):
len_jid = len(jid)
prnt_format = " %-" + str(len_alias) + "s %-" + str(len_jid) + "s"
- w_prnt("", prnt_format % ('Alias', 'JID'))
+ weechat.prnt("", prnt_format % ('Alias', 'JID'))
for alias, jid in sorted(jabber_jid_aliases.items()):
- w_prnt("", prnt_format % (alias, jid))
+ weechat.prnt("", prnt_format % (alias, jid))
return
def parse(self):
@@ -2163,27 +1819,28 @@ def jabber_completion_servers(data, completion_item, buffer, completion):
""" Completion with jabber server names. """
global jabber_servers
for server in jabber_servers:
- w.hook_completion_list_add(completion, server.name,
- 0, w.WEECHAT_LIST_POS_SORT)
- return w.WEECHAT_RC_OK
+ weechat.hook_completion_list_add(completion, server.name,
+ 0, weechat.WEECHAT_LIST_POS_SORT)
+ return weechat.WEECHAT_RC_OK
def jabber_completion_jid_aliases(data, completion_item, buffer, completion):
""" Completion with jabber alias names. """
global jabber_jid_aliases
for alias, jid in sorted(jabber_jid_aliases.items()):
- w.hook_completion_list_add(completion, alias,
- 0, w.WEECHAT_LIST_POS_SORT)
- return w.WEECHAT_RC_OK
+ weechat.hook_completion_list_add(completion, alias,
+ 0, weechat.WEECHAT_LIST_POS_SORT)
+ return weechat.WEECHAT_RC_OK
# ==================================[ fd ]====================================
def jabber_fd_cb(data, fd):
""" Callback for reading socket. """
global jabber_servers
+ weechat.prnt('', f"{SCRIPT_NAME}: jabber_fd_cb {fd}")
for server in jabber_servers:
- if server.sock == int(fd):
+ if server.sfn == int(fd):
server.recv()
- return w.WEECHAT_RC_OK
+ return weechat.WEECHAT_RC_OK
# ================================[ buffers ]=================================
@@ -2197,7 +1854,7 @@ def jabber_buffer_input_cb(data, buffer, input_data):
context["server"].display_buddies()
else:
context["server"].send_message_from_input(input=input_data)
- return w.WEECHAT_RC_OK
+ return weechat.WEECHAT_RC_OK
def jabber_buffer_close_cb(data, buffer):
""" Callback called when a jabber buffer is closed. """
@@ -2209,7 +1866,7 @@ def jabber_buffer_close_cb(data, buffer):
context["server"].chats.remove(context["chat"])
elif context["server"]:
context["server"].buffer = ""
- return w.WEECHAT_RC_OK
+ return weechat.WEECHAT_RC_OK
# ==================================[ timers ]==================================
@@ -2217,16 +1874,33 @@ def jabber_ping_timeout_timer(server_name, remaining_calls):
server = jabber_search_server_by_name(server_name)
if server:
server.ping_time_out()
- return w.WEECHAT_RC_OK
+ return weechat.WEECHAT_RC_OK
def jabber_ping_timer(server_name, remaining_calls):
server = jabber_search_server_by_name(server_name)
if server:
server.ping()
- return w.WEECHAT_RC_OK
+ return weechat.WEECHAT_RC_OK
# ==================================[ main ]==================================
+if __name__ == "__main__" and import_ok:
+ if weechat.register(SCRIPT_NAME, SCRIPT_AUTHOR, SCRIPT_VERSION,
+ SCRIPT_LICENSE, SCRIPT_DESC,
+ "jabber_unload_script", ""):
+
+ version = weechat.info_get("version_number", "") or 0
+ jabber_hook_commands_and_completions()
+ jabber_config_init()
+ jabber_config_read()
+ for server in jabber_servers:
+ if weechat.config_boolean(server.options['autoreconnect']):
+ server.ping() # This will connect and update ping status
+ server.add_ping_timer()
+ else:
+ if weechat.config_boolean(server.options['autoconnect']):
+ server.connect()
+
# ==================================[ end ]===================================
def jabber_unload_script():
@@ -2236,28 +1910,4 @@ def jabber_unload_script():
for server in jabber_servers:
server.disconnect()
server.delete()
- return w.WEECHAT_RC_OK
-
-if __name__ == "__main__":
- # WeechatWrapper
- w = weechat
-
- if w.register(SCRIPT_NAME,
- SCRIPT_AUTHOR,
- SCRIPT_VERSION,
- SCRIPT_LICENSE,
- SCRIPT_DESC,
- "jabber_unload_script", ""):
-
- weechat_version = int(w.info_get("version_number", "") or 0)
- jabber_hook_commands_and_completions()
- jabber_config_init()
- jabber_config_read()
- for server in jabber_servers:
- if w.config_boolean(server.options['autoreconnect']):
- server.ping() # This will connect and update ping status
- server.add_ping_timer()
- else:
- if w.config_boolean(server.options['autoconnect']):
- server.connect()
-
+ return weechat.WEECHAT_RC_OK
diff --git a/support_jabber.py b/support_jabber.py
new file mode 100644
index 0000000..b61aa37
--- /dev/null
+++ b/support_jabber.py
@@ -0,0 +1,133 @@
+import os
+
+import weechat
+w = weechat
+
+def LOG_debug(what, level='none'):
+ # if jabber_debug_enabled():
+ w.prnt('', what)
+
+class ProxyWrapper(object):
+ def __init__(self, name):
+ self.proxy_name = name
+ self.proxy_string = ""
+ self.proxy_type = ""
+ self.proxy_address = ""
+ self.proxy_port = ""
+ self.proxy_user = ""
+ self.proxy_password = ""
+ self.has_proxy = False
+
+ def configure(self):
+ if self.proxy_name:
+ self.proxy_string = "weechat.proxy.{}".format(self.proxy_name)
+ self.proxy_type = w.config_string(
+ w.config_get("{}.type".format(self.proxy_string))
+ )
+ if self.proxy_type in ['socks5', "http"]:
+ self.proxy_address = w.config_string(
+ w.config_get("{}.address".format(self.proxy_string))
+ )
+ self.proxy_port = w.config_integer(
+ w.config_get("{}.port".format(self.proxy_string))
+ )
+ self.proxy_user = w.config_string(
+ w.config_get("{}.username".format(self.proxy_string))
+ )
+ self.proxy_password = w.config_string(
+ w.config_get("{}.password".format(self.proxy_string))
+ )
+ self.has_proxy = True
+ else:
+ w_prnt(
+ "",
+ "\nWarning: weechat.network.proxy_curl is set to {} type (name: {}, conf string: {}). Only HTTP and SOCKS5 proxies are supported.\n\n".format(
+ self.proxy_type, self.proxy_name, self.proxy_string
+ ),
+ )
+
+ def curl(self):
+ if not self.has_proxy:
+ return ""
+
+ if self.proxy_user and self.proxy_password:
+ user = "{}:{}@".format(self.proxy_user, self.proxy_password)
+ else:
+ user = ""
+
+ if self.proxy_port:
+ port = ":{}".format(self.proxy_port)
+ else:
+ port = ""
+
+ return "-x{}{}{}".format(user, self.proxy_address, port)
+
+def make_proxy(self, sproxy):
+ proxy = {}
+ if sproxy.startswith('socks'):
+ pair = sproxy
+ pair = pair.replace('socks5h://', '')
+ pair = pair.replace('socks5://', '')
+ pair = pair.replace('socks4://', '')
+ pair = pair.replace('socks://', '')
+ if ':' in pair:
+ phost, pport = pair.split(':', 1)
+ # '127.0.0.1' 9050
+ proxy = {'host': phost, 'port': int(pport)}
+ elif sproxy.startswith('http'):
+ pair = sproxy
+ pair = pair.replace('https://', '')
+ pair = pair.replace('http://', '')
+ if ':' in pair:
+ phost, pport = pair.split(':', 1)
+ # '127.0.0.1' 9128
+ proxy = {'host': phost, 'port': int(pport)}
+ return proxy
+
+def aget_proxy(self, ltypes=None):
+ if ltypes is None:
+ ltypes = ['http', 'socks5']
+ aproxy = {}
+ elt = f"jabber.server.{self.name}.proxy"
+ stor = w.config_string(w.config_get(elt))
+ if stor:
+ saddress = w.config_string(w.config_get(f"weechat.proxy.{stor}.address"))
+ iport = w.config_integer(w.config_get(f"weechat.proxy.{stor}.port"))
+ itype = w.config_integer(w.config_get(f"weechat.proxy.{stor}.type"))
+ atypes = {0: 'http', 1: 'socks', 2: 'socks'}
+ stype = atypes[itype]
+ if stype in ltypes:
+ aproxy = {'host': saddress,
+ 'port': iport,
+ 'type': stype,
+ }
+ LOG_debug(f"aget_proxy proxy {stor} {aproxy}")
+ return aproxy
+ sproxy = w.config_string(w.config_get("weechat.network.proxy_curl"))
+ if sproxy:
+ oproxy = ProxyWrapper(sproxy)
+ if oproxy.proxy_type in ltypes:
+ oproxy.configure()
+ aproxy = {'host': oproxy.proxy_address,
+ 'port': int(oproxy.proxy_port),
+ 'type': oproxy.proxy_type,
+ }
+ LOG_debug(f"aget_proxy proxy {sproxy} {aproxy}")
+ return aproxy
+
+ if 'socks_proxy' in ltypes:
+ if os.environ.get('socks_proxy', ''):
+ sproxy = os.environ.get('socks_proxy', '')
+ aproxy = make_proxy(self, sproxy)
+ LOG_debug(f"proxy {aproxy}")
+ LOG_debug(f"aget_proxy proxy env={sproxy} {aproxy}")
+ return aproxy
+ if 'https_proxy' in ltypes:
+ sproxy = os.environ.get('https_proxy', '')
+ if sproxy:
+ aproxy = make_proxy(self, sproxy)
+ LOG_debug(f"proxy {aproxy}")
+ LOG_debug(f"aget_proxy proxy env={sproxy} {aproxy}")
+ return aproxy
+
+ return aproxy