Refactor ts-control with bashly

This commit is contained in:
Tobias Reisinger 2025-07-08 13:05:36 +02:00
parent 93ebbbd5d2
commit 7694bf365c
Signed by: serguzim
GPG key ID: 13AD60C237A28DFE
21 changed files with 217 additions and 175 deletions

1
.envrc Normal file
View file

@ -0,0 +1 @@
use nix

1
.gitignore vendored
View file

@ -1 +1,2 @@
/target
ts-control

1
bashly-settings.yml Normal file
View file

@ -0,0 +1 @@
source_dir: control_src

View file

@ -0,0 +1,20 @@
actions=(
"quick"
"move"
"fetch-client"
"fetch-channel"
"migrate"
"away"
"not-away"
"back"
"message"
"message-client"
"events"
"events-ntfy"
)
action=$(echo "${actions[@]}" | tr ' ' '\n' | $DMENU)
if [ -n "$action" ]; then
$0 "$action"
fi

View file

@ -0,0 +1,4 @@
message=$(_ts_control_get_message "${args[channel]}")
teamspeak-query-lib move "Away From Keyboard"
teamspeak-query-lib update --away "$message"
teamspeak-query-lib update --microphone=false --speakers=false --away "$message"

View file

@ -0,0 +1,3 @@
teamspeak-query-lib update --back
_ts_control_move_self "${args[channel]}"
teamspeak-query-lib update --microphone=true --speakers=true

59
control_src/bashly.yml Normal file
View file

@ -0,0 +1,59 @@
name: ts-control
help: Teamspeak query lib utility script
version: 0.1.0
environment_variables:
- name: ts3_client_api_key
help: Set your API key
required: true
commands:
- name: ask
default: force
- name: quick
- name: move
args:
- name: channel
required: false
- name: fetch-client
args:
- name: client
required: false
- name: fetch-channel
args:
- name: channel
required: false
- name: migrate
args:
- name: channel
required: false
- name: not-away
- name: away
args:
- name: message
required: false
- name: back
args:
- name: channel
required: false
- name: message
args:
- name: message
required: false
- name: message-client
args:
- name: client
required: false
- name: message
required: false
- name: events
- name: events-ntfy
environment_variables:
- name: ts3_ntfy_host
required: true
- name: ts3_ntfy_token
required: true
- name: ts3_ntfy_topic
required: true
- name: ts3_ntfy_webhook
required: true

View file

@ -0,0 +1,5 @@
teamspeak-query-lib events --filter=others \
NotifyClientMoved NotifyClientEnterView NotifyClientLeftView \
NotifyTextMessage NotifyClientPoke \
| jq -r --unbuffered '.message' \
| tee >(xargs -I{} notify-send "TS3 Event" "{}")

View file

@ -0,0 +1,52 @@
handle_ntfy_events() {
while read -r data; do
msg=$(echo "$data" | jq -r --unbuffered '.message')
type=$(echo "$data" | jq -r --unbuffered '.type')
mode=$(echo "$data" | jq -r --unbuffered '.params.targetmode')
client_nickname=$(echo "$data" | jq -r --unbuffered '.client.client_nickname')
echo "$data"
if [ "$type" = "NotifyTextMessage" ] && [ "$mode" != "1" ]; then
continue # Skip all messages that are not direct messages
fi
title="TS3 Event"
case $type in
"NotifyClientPoke")
title="TS3 Poke"
;;
"NotifyTextMessage")
title="TS3 Message"
;;
esac
echo "($title) $target: $msg"
payload=$(jq -n \
--arg topic "$TS3_NTFY_TOPIC" \
--arg webhook "$TS3_NTFY_WEBHOOK&client=$client_nickname" \
--arg msg "$msg" \
--arg type "$title" \
'{
topic: $topic,
message: $msg,
title: $type,
actions: [{
action: "http",
label: "TS response",
method: "POST",
url: $webhook,
clear: true
}]
}')
curl -sSL \
-H "Authorization: Bearer $TS3_NTFY_TOKEN" \
-d "$payload" \
"$TS3_NTFY_HOST"
done
}
teamspeak-query-lib events --filter=others NotifyClientPoke NotifyTextMessage \
| handle_ntfy_events

View file

@ -0,0 +1 @@
_ts_control_fetch channel "${args[channel]}"

View file

@ -0,0 +1 @@
_ts_control_fetch client "${args[client]}"

0
control_src/lib/ntfy.sh Normal file
View file

46
control_src/lib/simple.sh Normal file
View file

@ -0,0 +1,46 @@
_ts_control_get_entity() {
entity=$(_ts_control_single_or_dmenu "$(teamspeak-query-lib "$1s")" "$2")
if [ -z "$entity" ]; then
exit 1
fi
echo "$entity"
}
_ts_control_get_message() {
if [ -n "$1" ];
then
message="$1"
else
message=$(printf "\n" | $DMENU -p "message")
fi
if [ -z "$message" ]; then
exit 1
fi
echo "$message"
}
_ts_control_move_self() {
channel=$(_ts_control_get_entity channel "$1" "$2")
teamspeak-query-lib move --strict-channel "$channel"
}
_ts_control_fetch() {
target=$(_ts_control_get_entity "$1" "$2")
teamspeak-query-lib fetch "--strict-$1" "--$1" "$target"
}
_ts_control_single_or_dmenu() {
filter="$2"
if [ "$filter" == "^$" ]; then
filter=""
fi
options=$(echo "$1" | grep "$filter")
count=$(echo "$options" | wc -l)
if [ "$count" -eq 1 ]; then
echo "$options"
else
echo "$1" | $DMENU
fi
}

View file

@ -0,0 +1,3 @@
client=$(_ts_control_get_entity client "${args[client]}")
message=$(_ts_control_get_message "${args[message]}")
teamspeak-query-lib message --strict-client --client "$client" "$message"

View file

@ -0,0 +1,2 @@
message=$(_ts_control_get_message "${args[message]}")
teamspeak-query-lib message "$message"

View file

@ -0,0 +1,4 @@
target=$(_ts_control_get_entity "channel" "$1")
current_channel=$(teamspeak-query-lib info | grep "Channel: " | sed 's/Channel: //')
_ts_control_move_self "$target"
teamspeak-query-lib fetch "--strict-channel" "--channel" "$current_channel"

View file

@ -0,0 +1 @@
_ts_control_move_self "${args[channel]}"

View file

@ -0,0 +1,2 @@
teamspeak-query-lib move "Not Away From Keyboard"
teamspeak-query-lib update --microphone=false --speakers=false

View file

@ -0,0 +1,5 @@
action=$($DMENU < "$XDG_CONFIG_HOME/ts-control-quick")
if [ -z "$action" ]; then
exit 1
fi
eval "$0 $action"

6
shell.nix Normal file
View file

@ -0,0 +1,6 @@
with import <nixpkgs> {};
mkShell {
nativeBuildInputs = [
bashly
];
}

View file

@ -1,175 +0,0 @@
#!/usr/bin/env bash
actions="quick
move
fetch-client
fetch-channel
migrate
away
not away
back
message
message-user
events
ntfy-events"
_ts_control_get_entity() {
entity=$(_ts_control_single_or_dmenu "$(teamspeak-query-lib "$1s")" "$2")
if [ -z "$entity" ]; then
exit 1
fi
echo "$entity"
}
_ts_control_get_message() {
if [ -n "$1" ];
then
message="$1"
else
message=$(printf "\n" | $DMENU -p "message")
fi
if [ -z "$message" ]; then
exit 1
fi
echo "$message"
}
_ts_control_move_self() {
channel=$(_ts_control_get_entity channel "$1" "$2")
teamspeak-query-lib move --strict-channel "$channel"
}
_ts_control_fetch() {
target=$(_ts_control_get_entity "$1" "$2")
teamspeak-query-lib fetch "--strict-$1" "--$1" "$target"
}
_ts_control_migrate() {
target=$(_ts_control_get_entity "channel" "$1")
current_channel=$(teamspeak-query-lib info | grep "Channel: " | sed 's/Channel: //')
_ts_control_move_self "$target"
teamspeak-query-lib fetch "--strict-channel" "--channel" "$current_channel"
}
_ts_control_single_or_dmenu() {
filter="$2"
if [ "$filter" == "^$" ]; then
filter=""
fi
options=$(echo "$1" | grep "$filter")
count=$(echo "$options" | wc -l)
if [ "$count" -eq 1 ]; then
echo "$options"
else
echo "$1" | $DMENU
fi
}
handle_ntfy_events() {
while read -r data; do
msg=$(echo "$data" | jq -r --unbuffered '.message')
type=$(echo "$data" | jq -r --unbuffered '.type')
mode=$(echo "$data" | jq -r --unbuffered '.params.targetmode')
client_nickname=$(echo "$data" | jq -r --unbuffered '.client.client_nickname')
echo "$data"
if [ "$type" = "NotifyTextMessage" ] && [ "$mode" != "1" ]; then
continue # Skip all messages that are not direct messages
fi
title="TS3 Event"
case $type in
"NotifyClientPoke")
title="TS3 Poke"
;;
"NotifyTextMessage")
title="TS3 Message"
;;
esac
echo "($title) $target: $msg"
payload=$(jq -n \
--arg topic "$TS3_NTFY_TOPIC" \
--arg webhook "$TS3_NTFY_WEBHOOK&client=$client_nickname" \
--arg msg "$msg" \
--arg type "$title" \
'{
topic: $topic,
message: $msg,
title: $type,
actions: [{
action: "http",
label: "TS response",
method: "POST",
url: $webhook,
clear: true
}]
}')
curl -sSL \
-H "Authorization: Bearer $TS3_NTFY_TOKEN" \
-d "$payload" \
"$TS3_NTFY_HOST"
done
}
action=$(_ts_control_single_or_dmenu "$actions" "^$1$")
case $action in
"quick")
action=$($DMENU < "$XDG_CONFIG_HOME/ts-control-quick")
if [ -z "$action" ]; then
exit 1
fi
eval "$0 $action"
;;
"move")
_ts_control_move_self "$2"
;;
"fetch-client")
_ts_control_fetch client "$2"
;;
"fetch-channel")
_ts_control_fetch channel "$2"
;;
"migrate")
_ts_control_migrate "$2"
;;
"not away")
teamspeak-query-lib move "Not Away From Keyboard"
teamspeak-query-lib update --microphone=false --speakers=false
;;
"away")
message=$(_ts_control_get_message)
teamspeak-query-lib move "Away From Keyboard"
teamspeak-query-lib update --away "$message"
teamspeak-query-lib update --microphone=false --speakers=false --away "$message"
;;
"back")
teamspeak-query-lib update --back
_ts_control_move_self "$2"
teamspeak-query-lib update --microphone=true --speakers=true
;;
"message")
message=$(_ts_control_get_message "$2")
teamspeak-query-lib message "$message"
;;
"message-user")
user=$(_ts_control_get_entity client "$2")
message=$(_ts_control_get_message "$3")
teamspeak-query-lib message --strict-client --client "$user" "$message"
;;
"events")
teamspeak-query-lib events --filter=others NotifyClientMoved NotifyClientEnterView NotifyClientLeftView NotifyTextMessage NotifyClientPoke \
| jq -r --unbuffered '.message' \
| tee >(xargs -I{} notify-send "TS3 Event" "{}")
;;
"ntfy-events")
teamspeak-query-lib events --filter=others NotifyClientPoke NotifyTextMessage \
| handle_ntfy_events
;;
esac