Last active
August 18, 2020 22:59
-
-
Save ncfavier/55c20a77a3fd72e00407f8889fc6e852 to your computer and use it in GitHub Desktop.
Syncplay<->IRC bridge
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# dependencies: bash 4+, jq | |
. ./config.sh | |
: "${verbose:=0}" | |
: "${syncplay_host:=syncplay.pl}" | |
: "${syncplay_port:=8999}" | |
: "${syncplay_nick:=syncplaybridge}" | |
: "${syncplay_room:?"can't be empty"}" | |
: "${irc_host:=chat.freenode.net}" | |
: "${irc_port:=6667}" | |
: "${irc_nick:=syncplaybridge}" | |
: "${irc_channel:?"can't be empty"}" | |
irc_send() { | |
local args=("$@") | |
args[0]=${args[0]^^} | |
if (( ${#args[@]} > 1 )); then | |
args[${#args[@]}-1]=:${args[${#args[@]}-1]} | |
fi | |
printf '%s\r\n' "${args[*]}" >&"$irc_fd" | |
(( verbose )) && printf 'IRC %s==>%s %s\n' "$(tput setaf 1)" "$(tput sgr0)" "${args[*]}" >&2 | |
} | |
irc_say() { | |
irc_send privmsg "$irc_channel" "$*" | |
} | |
irc_ctcp() { | |
local args=("$@") | |
args[0]=${args[0]^^} | |
irc_send notice "$sender_nick" $'\1'"${args[*]}"$'\1' | |
} | |
syncplay_send() { | |
local msg=$(jq -nc "$@") | |
printf '%s\r\n' "$msg" >&"$syncplay_fd" | |
(( verbose )) && printf 'syncplay %s==>%s %s\n' "$(tput setaf 1)" "$(tput sgr0)" "$msg" >&2 | |
} | |
syncplay_say() { | |
syncplay_send --arg message "$*" '{Chat: $message}' | |
} | |
on_exit() { | |
irc_send quit | |
kill $(jobs -p) | |
} | |
exec {irc_fd}<> /dev/tcp/"$irc_host"/"$irc_port" || exit | |
exec {syncplay_fd}<> /dev/tcp/"$syncplay_host"/"$syncplay_port" || exit | |
trap on_exit exit | |
irc_send nick "$irc_nick" | |
irc_send user "$irc_nick" 0 '*' 'Syncplay<->IRC' | |
syncplay_send --arg username "$syncplay_nick" --arg room "$syncplay_room" \ | |
'{Hello: {$username, room: {name: $room}, realversion: "1.6.5"}}' | |
while read -ru "$irc_fd" line; do | |
line=${line%$'\r'} | |
(( verbose )) && printf 'IRC %s<==%s %s\n' "$(tput setaf 2)" "$(tput sgr0)" "$line" >&2 | |
sender= sender_nick= | |
args=() | |
if [[ $line == :* ]]; then | |
sender=${line%% *} | |
sender=${sender#:} | |
sender_nick=${sender%%!*} | |
line=${line#* } | |
fi | |
while [[ $line == *' '* && $line != :* ]]; do | |
args+=("${line%% *}") | |
line=${line#* } | |
done | |
args+=("${line#:}") | |
cmd=${args[0]} | |
set -- "${args[@]:1}" | |
case ${cmd,,} in | |
001) irc_send join "$irc_channel";; | |
ping) irc_send pong "$1";; | |
privmsg) | |
target=$1 | |
message=$2 | |
if [[ $target == "$irc_nick" ]] && [[ $message =~ ^$'\1'(.*)$'\1'$ ]]; then | |
message=${BASH_REMATCH[1]} | |
read -r ctcp_cmd _ <<< "$message" | |
case ${ctcp_cmd,,} in | |
version) irc_ctcp version "syncplaybridge";; | |
esac | |
elif [[ $target == "$irc_channel" ]]; then | |
if [[ $message =~ ^$'\1ACTION '(.*)$'\1'$ ]]; then | |
syncplay_say "* $sender_nick ${BASH_REMATCH[1]}" | |
else | |
syncplay_say "<$sender_nick> $2" | |
fi | |
fi | |
esac | |
done & | |
while read -ru "$syncplay_fd" line; do | |
line=${line%$'\r'} | |
(( verbose )) && printf 'syncplay %s<==%s %s\n' "$(tput setaf 2)" "$(tput sgr0)" "$line" >&2 | |
. <(jq <<< "$line" -r --arg self "$syncplay_nick" ' | |
def irc($msg): @sh "irc_say \($msg)"; | |
(.State // empty | |
| @sh "syncplay_send \"{State: {}}\""), | |
(.Chat // empty | |
| select(.username != $self) | |
| irc("<\(.username)> \(.message)")), | |
(.Set // empty | |
| .user // empty | |
| keys[0] as $nick | |
| .[$nick] | |
| ( | |
(.event // empty | |
| irc("\($nick) \(if .joined then "joined" else "left" end)")), | |
(.file // empty | |
| irc("\($nick) is now playing \(.name)")) | |
) | |
) | |
') | |
done & | |
wait |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment