Script: soju.py

Soju bouncer integration.
Author: Simon Ser — Version: 0.3.0 — License: AGPL3
For WeeChat ≥ 0.3.0.
Tags: irc, soju, bouncer, py2, py3
Added: 2021-06-12 — Updated: 2022-11-11

Download GitHub Repository

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
# Copyright (c) 2021 Simon Ser <contact@emersion.fr>
#
# License: GNU Affero General Public License version 3
# https://www.gnu.org/licenses/agpl-3.0.en.html

import weechat
import datetime

weechat.register("soju", "soju", "0.3.0", "AGPL3", "soju bouncer integration", "", "")

BOUNCER_CAP = "soju.im/bouncer-networks"

caps_option = weechat.config_get("irc.server_default.capabilities")
caps = weechat.config_string(caps_option)
if BOUNCER_CAP not in caps:
    if caps != "":
        caps += ","
    caps += BOUNCER_CAP
    weechat.config_option_set(caps_option, caps, 1)

main_server = None
added_networks = {}

def server_by_name(server_name):
    hdata = weechat.hdata_get("irc_server")
    server_list = weechat.hdata_get_list(hdata, "irc_servers")
    weechat_version = int(weechat.info_get("version_number", "") or 0)
    if weechat_version >= 0x03040000:
        return weechat.hdata_search(
            hdata,
            server_list,
            "${irc_server.name} == ${name}",
            {},
            {"name": server_name},
            {},
            1,
        )
    else:
        return weechat.hdata_search(
            hdata,
            server_list,
            "${irc_server.name} == " + server_name,
            1,
        )

def handle_isupport_end_msg(data, signal, signal_data):
    global main_server

    server_name = signal.split(",")[0]
    netid = weechat.info_get("irc_server_isupport_value", server_name + ",BOUNCER_NETID")

    if netid != "":
        added_networks[netid] = True

    server = server_by_name(server_name)

    hdata = weechat.hdata_get("irc_server")
    cap_list = weechat.hdata_hashtable(hdata, server, "cap_list")
    if not BOUNCER_CAP in cap_list:
        return weechat.WEECHAT_RC_OK

    if main_server is not None:
        return weechat.WEECHAT_RC_OK
    main_server = server_name

    weechat.command(weechat.buffer_search("irc", "server." + server_name), "/quote BOUNCER LISTNETWORKS")

    return weechat.WEECHAT_RC_OK

def handle_bouncer_msg(data, signal, signal_data):
    server_name = signal.split(",")[0]
    msg = weechat.info_get_hashtable("irc_message_parse", { "message": signal_data })

    args = msg["arguments"].split(" ")
    if args[0] != "NETWORK":
        return weechat.WEECHAT_RC_OK

    # Don't connect twice to the same network
    netid = args[1]
    if netid in added_networks:
        return weechat.WEECHAT_RC_OK_EAT

    # Retrieve the network name from the attributes
    net_name = None
    raw_attr_list = args[2].split(";")
    for raw_attr in raw_attr_list:
        k, v = raw_attr.split("=")
        if k == "name":
            net_name = v
            break

    check_char = lambda ch: ch.isalnum() or ch in ".-_"
    net_name = "".join(ch if check_char(ch) else "_" for ch in net_name)

    addr = weechat.config_string(weechat.config_get("irc.server." + server_name + ".addresses"))
    add_server = [
        "/server",
        "add",
        net_name,
        addr,
        "-temp",
        "-ssl",
    ]

    # User name settings need to be adapted for new networks
    for k in ["username", "sasl_username"]:
        v = weechat.config_string(weechat.config_get("irc.server." + server_name + "." + k))
        if not v:
            continue
        username = v.split("/", maxsplit=1)[0] + "/" + net_name
        add_server.append("-" + k + "=" + username)

    for k in ["password", "sasl_mechanism", "sasl_password"]:
        v = weechat.config_string(weechat.config_get("irc.server." + server_name + "." + k))
        add_server.append("-" + k + "=" + v)

    weechat.command(weechat.buffer_search("core", "weechat"), " ".join(add_server))
    weechat.command(weechat.buffer_search("core", "weechat"), "/connect " + net_name)

    return weechat.WEECHAT_RC_OK_EAT

weechat.hook_signal("*,irc_raw_in_376", "handle_isupport_end_msg", "") # RPL_ENDOFMOTD
weechat.hook_signal("*,irc_raw_in_422", "handle_isupport_end_msg", "") # ERR_NOMOTD
weechat.hook_signal("*,irc_raw_in_bouncer", "handle_bouncer_msg", "")