#!/usr/bin/env bash topspeedUser="topspeed" topspeedHome="/var/lib/topspeed" topspeedInstallDir="${topspeedHome}/server" topspeedRuntimeDir="${topspeedInstallDir}/topspeed" topspeedServiceFile="/etc/systemd/system/topspeed.service" topspeedServiceScript="${topspeedInstallDir}/topspeed-service.sh" topspeedStopScript="${topspeedInstallDir}/topspeed-stop.sh" topspeedBinaryPath="${topspeedRuntimeDir}/TopSpeed.Server" topspeedSessionName="topspeed" topspeedRepoApi="https://api.github.com/repos/diamondStar35/top_speed/releases" topspeedAssetPattern='^TopSpeed\.Server-linux-arm64-Release-v-.*\.zip$' topspeedServerPort="28630" topspeedDiscoveryPort="28631" package_installed() { local packageName="$1" pacman -Q "$packageName" &> /dev/null } ufw_installed() { pacman -Q ufw &> /dev/null } ensure_topspeed_dependencies() { local packagesToInstall=() local packageName="" for packageName in curl jq tmux unzip; do if ! package_installed "$packageName"; then packagesToInstall+=("$packageName") fi done if [[ "${#packagesToInstall[@]}" -gt 0 ]]; then if ! install_package "${packagesToInstall[@]}"; then msgbox "Failed to install the required Top Speed dependencies." return 1 fi fi return 0 } fetch_topspeed_asset() { local tempDir="" local metadataFile="" local assetName="" local assetUrl="" tempDir="$(mktemp -d)" metadataFile="${tempDir}/topspeed-release.json" if ! curl -fsSL -H "Accept: application/vnd.github+json" "$topspeedRepoApi" -o "$metadataFile"; then rm -rf "$tempDir" msgbox "Failed to fetch Top Speed release metadata from GitHub." return 1 fi assetName="$(jq -r --arg assetPattern "$topspeedAssetPattern" ' ([.[] | .assets[] | select(.name | test($assetPattern))] | .[0].name) // empty ' "$metadataFile")" assetUrl="$(jq -r --arg assetPattern "$topspeedAssetPattern" ' ([.[] | .assets[] | select(.name | test($assetPattern))] | .[0].browser_download_url) // empty ' "$metadataFile")" if [[ -z "$assetName" || -z "$assetUrl" || "$assetName" == "null" || "$assetUrl" == "null" ]]; then rm -rf "$tempDir" msgbox "Unable to find the latest Top Speed arm64 server download in GitHub release metadata." return 1 fi if ! curl -fL --retry 5 -o "${tempDir}/${assetName}" "$assetUrl"; then rm -rf "$tempDir" msgbox "Failed to download the Top Speed server archive." return 1 fi printf '%s\n' "${tempDir}/${assetName}" } ensure_topspeed_user() { if id -u "$topspeedUser" &> /dev/null; then return 0 fi # `sudoFlags` is initialized by the main launcher before sourcing this file. # shellcheck disable=SC2154 if ! sudo "${sudoFlags[@]}" useradd \ --system \ --home-dir "$topspeedHome" \ --create-home \ --shell /usr/bin/nologin \ "$topspeedUser"; then msgbox "Failed to create the topspeed service user." return 1 fi return 0 } stop_topspeed_service_if_present() { # `sudoFlags` is initialized by the main launcher before sourcing this file. # shellcheck disable=SC2154 if sudo "${sudoFlags[@]}" systemctl cat topspeed.service &> /dev/null; then # shellcheck disable=SC2154 sudo "${sudoFlags[@]}" systemctl stop topspeed.service &> /dev/null || true fi } install_topspeed_server() { local archivePath="" local archiveDir="" archivePath="$(fetch_topspeed_asset)" || return 1 archiveDir="$(dirname "$archivePath")" stop_topspeed_service_if_present # `sudoFlags` is initialized by the main launcher before sourcing this file. # shellcheck disable=SC2154 if ! sudo "${sudoFlags[@]}" install -d -o "$topspeedUser" -g "$topspeedUser" -m 755 "$topspeedRuntimeDir"; then rm -rf "$archiveDir" msgbox "Failed to create the Top Speed install directory." return 1 fi # shellcheck disable=SC2154 if ! sudo "${sudoFlags[@]}" unzip -o -d "$topspeedRuntimeDir" "$archivePath"; then rm -rf "$archiveDir" msgbox "Failed to extract the Top Speed server archive." return 1 fi # shellcheck disable=SC2154 if ! sudo "${sudoFlags[@]}" chown -R "${topspeedUser}:${topspeedUser}" "$topspeedHome"; then rm -rf "$archiveDir" msgbox "Failed to set ownership on the Top Speed files." return 1 fi # shellcheck disable=SC2154 if ! sudo "${sudoFlags[@]}" test -f "$topspeedBinaryPath"; then rm -rf "$archiveDir" msgbox "The Top Speed server archive did not contain ${topspeedBinaryPath}." return 1 fi # shellcheck disable=SC2154 if ! sudo "${sudoFlags[@]}" chmod 755 "$topspeedBinaryPath"; then rm -rf "$archiveDir" msgbox "Failed to make ${topspeedBinaryPath} executable." return 1 fi rm -rf "$archiveDir" return 0 } write_topspeed_runtime_scripts() { local tempServiceScript="" local tempStopScript="" tempServiceScript="$(mktemp)" tempStopScript="$(mktemp)" cat > "$tempServiceScript" < /dev/null; then tmux kill-session -t "\$sessionName" fi if [[ ! -x "\$binaryPath" ]]; then exit 1 fi tmux new-session -d -s "\$sessionName" /bin/bash -lc 'exec ./TopSpeed.Server' || exit 1 while tmux has-session -t "\$sessionName" &> /dev/null; do sleep 5 done exit 1 EOF cat > "$tempStopScript" < /dev/null; then tmux send-keys -t "\$sessionName" C-c sleep 2 if tmux has-session -t "\$sessionName" &> /dev/null; then tmux kill-session -t "\$sessionName" fi fi EOF # `sudoFlags` is initialized by the main launcher before sourcing this file. # shellcheck disable=SC2154 if ! sudo "${sudoFlags[@]}" install -o "$topspeedUser" -g "$topspeedUser" -m 755 "$tempServiceScript" "$topspeedServiceScript"; then rm -f "$tempServiceScript" "$tempStopScript" msgbox "Failed to install the Top Speed runtime script." return 1 fi # shellcheck disable=SC2154 if ! sudo "${sudoFlags[@]}" install -o "$topspeedUser" -g "$topspeedUser" -m 755 "$tempStopScript" "$topspeedStopScript"; then rm -f "$tempServiceScript" "$tempStopScript" msgbox "Failed to install the Top Speed stop script." return 1 fi rm -f "$tempServiceScript" "$tempStopScript" return 0 } write_topspeed_service() { local tempServiceFile="" tempServiceFile="$(mktemp)" cat > "$tempServiceFile" < /dev/null; then return 1 fi # `sudoFlags` is initialized by the main launcher before sourcing this file. # shellcheck disable=SC2154 sudo "${sudoFlags[@]}" -u "$topspeedUser" tmux has-session -t "$topspeedSessionName" &> /dev/null } attach_topspeed_console() { local attachStatus=0 if ! topspeed_session_running; then msgbox "Top Speed is not running." return 1 fi clear echo "Attaching to the Top Speed console." echo "To detach from the server and leave it running, press Ctrl+b followed by d." # `sudoFlags` is initialized by the main launcher before sourcing this file. # shellcheck disable=SC2154 sudo "${sudoFlags[@]}" -u "$topspeedUser" tmux attach-session -t "$topspeedSessionName" attachStatus=$? reset return "$attachStatus" } case "${1:-install}" in install) install_topspeed_flow ;; console) attach_topspeed_console ;; *) msgbox "Unknown Top Speed action: ${1}" return 1 ;; esac