mm-shell-bot/main.sh

113 lines
2.8 KiB
Bash
Executable File

#!/bin/sh
# MM Shell bot
# By 0xDEADCADE
# Config
MM="${HOME}/go/bin/mm"
MMDIR="mm"
CMDDIR="bin"
HOMESERVER="https://matrix.example.org"
USERNAME="user"
MMCONF="${PWD}/mm.yml"
PREFIX="\\"
TIMEOUT=60
# Ensure access to ADMIN env var to subprocesses
export ADMIN="@deadcade:deadca.de"
# Create mm directory
mkdir -p "${MMDIR}"
# Ensure real paths instead of relative
MMDIR=$(readlink -nf "${MMDIR}")
CMDDIR=$(readlink -nf "${CMDDIR}")
# Generate mm config
if [ ! -f "${MMCONF}" ]; then
# No config was found, create a new one
PASSWORD=$(pass "${HOMESERVER}/${USERNAME}")
echo "server: ${HOMESERVER}
username: ${USERNAME}
password: ${PASSWORD}
certificate: ''
directory: ${MMDIR}
login:
userid: ''
deviceid: ''
accesstoken: ''
" > "${MMCONF}"
unset PASSWORD
fi
# Start mm
cd "${MMDIR}" || exit
$MM -c "${MMCONF}" 2>> "${MMDIR}/log" 1>> "${MMDIR}/out" &
MMPID="${!}"
# Ensure mm is started
sleep 3
# Remove password from file (otherwise password would be stored in plaintext)
grep -vF "password" "${MMCONF}" > /tmp/mm.yml
cp /tmp/mm.yml "${MMCONF}"
rm /tmp/mm.yml
# Get some variables from created config
HOMESERVER=$(echo "${HOMESERVER}" | cut -d "/" -f 3)
USERID=$(grep "userid" "${MMCONF}" | awk '{ print $2 }' | cut -d "'" -f 2)
# Ensure log in was successful
cd "${MMDIR}/${HOMESERVER}/${USERID}" || exit
# Separate function to execute the command, for async support
execute() {
CMD=$1
# Grab args without command
ARGS=$(printf '%s' "$MESSAGE" | tail -c"+$((${#PREFIX} + ${#CMD} + 2))")
# Execute command, keeping every Matrix command argument as a shell command argument
# shellcheck disable=SC2086
OUT=$(timeout "$((TIMEOUT + 5))" timeout -s INT "${TIMEOUT}" "${CMDDIR}/${CMD}" ${ARGS} 2>&1)
if [ "$OUT" != "" ]; then
# Send back output
printf '%s' "${OUT}" > "${INFILE}"
fi
}
# Process a message
message() {
while read -r MSG; do
cd "${MMDIR}/${HOMESERVER}/${USERID}" || exit
# Give detail about message to subprocess
FILE="!"$(echo "${MSG}" | cut -d "!" -f 2)
MESSAGE=$(cat "${FILE}")
ROOMID=$(echo "${FILE}" | cut -d "/" -f 1)
SENDER=$(echo "${FILE}" | cut -d "/" -f 2)
INFILE="${MMDIR}/${HOMESERVER}/${USERID}/${ROOMID}/in"
export FILE MESSAGE ROOMID SENDER INFILE
# If this message is a command
case "${MESSAGE}" in
"${PREFIX}"*)
cd "${CMDDIR}" || exit
for CMD in *; do
# Check if the command is valid, either with args or exact
if [ "${MESSAGE}" = "${PREFIX}${CMD}" ]; then
execute "${CMD}" &
fi
case "${MESSAGE}" in
"${PREFIX}${CMD} "*)
execute "${CMD}" &
;;
esac
done
esac
done
}
# Ensure ctrl+c continues the script
trap true INT
# Give new messages to message function
tail -n0 -f "${MMDIR}/out" | message
# Kill the mm instance after ctrl+c
kill "${MMPID}"