You are browsing a read-only backup copy of Wikitech. The live site can be found at wikitech.wikimedia.org
Tool:Bridgebot: Difference between revisions
imported>BryanDavis (Update lots of things in the docs, but most importantly describe the ZNC bouncer added for phab:T292640) |
imported>BryanDavis (→Telegram: new way to get channel id!) |
||
Line 71: | Line 71: | ||
If one side of the bridge is Telegram you will need these things to be done: | If one side of the bridge is Telegram you will need these things to be done: | ||
# Have an admin of the Telegram channel invite the "@wmtelegram_bot" user to the channel | # Have an admin of the Telegram channel invite the "@wmtelegram_bot" user to the channel | ||
# Have someone in the Telegram channel post the message <code>/chatId</code> (This command is case-sensitive.) | |||
# Collect the Telegram "Channel" id number from @wmtelegram_bot's reply to the bot command | |||
Older method: | |||
# Follow the log output of the bot: `bin/bb.sh tail` | # Follow the log output of the bot: `bin/bb.sh tail` | ||
# Have someone in the Telegram channel talk to the bot | # Have someone in the Telegram channel talk to the bot |
Revision as of 17:17, 19 February 2022
![]() | |
---|---|
Description | A bot for bridging IRC and other chat platform channels |
Keywords | irc, golang |
Maintainer(s) | BryanDavis (View all) |
Source code | https://github.com/42wim/matterbridge |
License | Apache License 2.0 |
Issues | Open tasks · Report a bug |
Admin log | Tools.bridgebot/SAL |
Bridgebot is a deployment of the FLOSS matterbridge software. It can be used to relay messages between multiple different chat systems. The current deployment in Toolforge is bridging various Wikimedia related channels across platforms including Libera.Chat, Telegram, Discord, and Mattermost.
Bot accounts
The bot must be invited/added to chat channels in order to create bridges. Currently the bot has these accounts on various chat platforms:
- libera.chat IRC
-
- account: wm-bridgebot
- nicks: wm-bridgebot, wm-bb
- Telegram
-
- account: @wmtelegram_bot
- Discord
-
- bot account: wm-bb#9216
- invite link: https://discord.com/api/oauth2/authorize?client_id=744713247218860063&permissions=67497024&scope=bot
Maintenance
The bot runs from Toolforge under the "bridgebot" account as a kubernetes pod.
$ ssh login.toolforge.org
$ become bridgebot
:# Deploying
$ bin/bb.sh start
Starting bridgebot k8s deployment...
:# Quick restart (pod delete)
$ bin/bb.sh restart
Restarting bridgebot pod...
:# "Full" restart (Deployment delete; Deployment create)
$ bin/bb.sh stop
Stopping bridgebot k8s deployment...
$ bin/bb.sh start
Starting bridgebot k8s deployment...
:# Upgrading the golang binary
$ bin/bb.sh download $version
$ vim bb.sh
update the MATTERBRIDGE=... line to the new version
:wq
$ bin/bb.sh restart "Upgrading matterbridge to $version"
Joining a new channel
Maintainers of the tool can configure the bot to join a new channel:
$ ssh login.tools.wmflabs.org
$ become bridgebot
$ vim etc/matterbridge.toml
:# Add a new "[[gateway]]" section defining the gateway name and the channels to bridge
$ bin/bb.sh restart
Telegram
If one side of the bridge is Telegram you will need these things to be done:
- Have an admin of the Telegram channel invite the "@wmtelegram_bot" user to the channel
- Have someone in the Telegram channel post the message
/chatId
(This command is case-sensitive.) - Collect the Telegram "Channel" id number from @wmtelegram_bot's reply to the bot command
Older method:
- Follow the log output of the bot: `bin/bb.sh tail`
- Have someone in the Telegram channel talk to the bot
- Collect the Telegram "Channel" id number from the DEBUG log output
[85656] DEBUG telegram: <= Message is config.Message{Text:"@wmtelegram_bot I need you to see this message so I can finish https://phabricator.wikimedia.org/T258078", Channel:"-1001308089610", Username:"bd808", UserID:"419968011", Avatar:"https://tools-static.wmflabs.org/bridgebot/4a263e14/419968011.png", Account:"telegram.bridgebot", Event:"", Protocol:"", Gateway:"", ParentID:"", Timestamp:time.Time{wall:0x0, ext:0, loc:(*time.Location)(nil)}, ID:"86", Extra:map[string][]interface {}{}}
Discord
If one side of the bridge is Discord you will need these things to be done:
- Have an admin of the Discord server invite the bot to their server using the bot's invite link
Technical details
bin/bb.sh
To make operating the bot less complicated for maintainers, we have a bin/bb.sh script to wrap the various Kubernetes commands. This same script is used as the command inside the bot's container to setup and run the matterbridge software when invoked as bin/bb.sh run
. The run action copies the matterbridge binary and it's configuration into the container's /tmp directory so that while running there is no need to read or write to the tool's $HOME.
#!/usr/bin/env bash
# Management script for bridgebot kubernetes processes
set -e
MATTERBRIDGE=matterbridge-1.23.0-linux-64bit
DEPLOYMENT=bridgebot.bot
POD_NAME=bridgebot.bot
TOOL_DIR=$(cd $(dirname $0)/.. && pwd -P)
BIN_DIR=$TOOL_DIR/bin
CONFIG_DIR=$TOOL_DIR/etc
KUBECTL=/usr/bin/kubectl
_get_pod() {
$KUBECTL get pods \
--output=jsonpath={.items..metadata.name} \
--selector=name=${POD_NAME}
}
case "$1" in
start)
echo "Starting bridgebot k8s deployment..."
$KUBECTL create --validate=true -f ${CONFIG_DIR}/deployment.yaml
[[ -n $2 ]] && dologmsg "$2"
;;
run)
# Execute bot inside container
date +%Y-%m-%dT%H:%M:%S
echo "Bootstrapping container..."
cd ${TOOL_DIR}
cp ${BIN_DIR}/${MATTERBRIDGE} /tmp
chmod a+x /tmp/${MATTERBRIDGE}
cp ${CONFIG_DIR}/matterbridge.toml /tmp
cp ${CONFIG_DIR}/remotenickformat.tengo /tmp
echo "Starting bridgebot..."
cd /tmp
exec /tmp/${MATTERBRIDGE} -debug -conf /tmp/matterbridge.toml
;;
stop)
echo "Stopping bridgebot k8s deployment..."
$KUBECTL delete deployment ${DEPLOYMENT}
[[ -n $2 ]] && dologmsg "$2"
;;
restart)
echo "Restarting bridgebot pod..."
$KUBECTL delete pod $(_get_pod)
[[ -n $2 ]] && dologmsg "$2"
;;
status)
echo "Active pods:"
$KUBECTL get pods -l name=${POD_NAME}
;;
tail)
exec $KUBECTL logs -f $(_get_pod)
;;
attach)
echo "Attaching to pod..."
exec $KUBECTL exec -i -t $(_get_pod) -- /bin/bash
;;
version)
echo "${BIN_DIR}/${MATTERBRIDGE}"
"${BIN_DIR}/${MATTERBRIDGE}" -version
;;
download)
version=${2:?No version specified. Expected something like '1.22.1'}
baseurl="https://github.com/42wim/matterbridge/releases/download"
new="matterbridge-${version}-linux-64bit"
if [[ -f "${BIN_DIR}/${new}" ]]; then
read -p "${new} exists. Overwrite? [y/N]: " -n 1 -r
if [[ ! $REPLY =~ ^[Yy]$ ]]; then
exit 1
fi
echo
fi
echo "Downloading ${new}..."
wget -O "${BIN_DIR}/${new}" "${baseurl}/v${version}/${new}"
chmod a+x "${BIN_DIR}/${new}"
echo "Downloaded $("${BIN_DIR}/${new}" -version)"
;;
*)
echo "Usage: $0 {start
deployment.apps/bridgebot.bot
The bot's Kubernetes container is managed by a custom deployment defined in $HOME/etc/deployment.yaml and applied by bin/bb.sh.
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: bridgebot.bot
namespace: tool-bridgebot
labels:
name: bridgebot.bot
toolforge: tool
spec:
replicas: 1
selector:
matchLabels:
name: bridgebot.bot
toolforge: tool
template:
metadata:
labels:
name: bridgebot.bot
toolforge: tool
spec:
containers:
- name: bot
image: docker-registry.tools.wmflabs.org/toolforge-buster-sssd:latest
resources:
limits:
cpu: 1
memory: 1Gi
requests:
cpu: 1
memory: 1Gi
command:
- "/data/project/bridgebot/bin/bb.sh"
- "run"
workingDir: /data/project/bridgebot
env:
- name: HOME
value: /data/project/bridgebot
imagePullPolicy: Always
deployment.apps/bridgebot.bnc
After many issues with matterbridge's IRC client, we decided to place a bouncer (BNC) between matterbridge and libera.chat. This bouncer is running as a pod inside the tool's namespace and connected to a Kubernetes Service which allows the bot's pod to connect to it.
The specific BNC software currently used is ZNC. ZNC was compiled from inside a webservice ruby27 shell
(ruby27 just happened to have all the -dev packages needed) and installed to $HOME/.local/bin/znc. ZNC's runtime configuration is stored in $HOME/.znc.
Configuration for ZNC can be managed by connecting to it with an IRC client running inside the tool's namespace. kirc has been compiled and installed to $HOME/.local/bin/kirc for this purpose. The password used to connect to the bouncer can be found in the $HOME/etc/matterbridge.toml configuration file.
$ webservice shell
$ .local/bin/kirc -s bnc -p 6667 -n wm-bb -u wm-bridgebot/libera -k $password
?> @*status help
*status In the following list all occurrences of <#chan>
support wildcards (* and ?) except ListNicks
*status Version: Print which version of ZNC this is
*status ListMods: List all loaded modules
...
*status Shutdown [message]: Shut down ZNC completely
*status Restart [message]: Restart ZNC
?>
---
kind: Deployment
apiVersion: apps/v1
metadata:
name: bridgebot.bnc
namespace: tool-bridgebot
labels:
name: bridgebot.bnc
toolforge: tool
spec:
replicas: 1
selector:
matchLabels:
name: bridgebot.bnc
toolforge: tool
template:
metadata:
labels:
name: bridgebot.bnc
toolforge: tool
spec:
containers:
- name: bnc
image: docker-registry.tools.wmflabs.org/toolforge-bullseye-sssd:latest
resources:
limits:
cpu: 250m
memory: 256Mi
requests:
cpu: 100m
memory: 100Mi
command:
- /data/project/bridgebot/.local/bin/znc
- --foreground
- --datadir
- /data/project/bridgebot/.znc
workingDir: /data/project/bridgebot
env:
- name: HOME
value: /data/project/bridgebot
imagePullPolicy: Always
---
kind: Service
apiVersion: v1
metadata:
name: bnc
spec:
selector:
name: bridgebot.bnc
ports:
- protocol: TCP
port: 6667
targetPort: 6667
remotenickformat.tengo
A tengo script is used to do per-channel customization of nick formats used when cross-posting messages between services.
Note: Any syntax errors in the script will stop messages from passing across all bridges until they are corrected.
/**
* The script will have the following global variables:
* to modify: result
* to read: channel, bridge, gateway, protocol, nick
*/
ret := "[" + protocol + "] <" + nick + "> "
if gateway == "ukwiki-discord-telegram" {
protos := immutable({
discord: "дс",
telegram: "тг"
})
proto := protos[protocol]
ret = "[" + (proto == undefined ? protocol : proto) + "] <" + nick + "> "
} else if gateway == "wikipedia-abstract-irc-telegram" {
ret = "<" + nick + "> "
}
result = ret