265 lines
9.7 KiB
Bash
Executable File
265 lines
9.7 KiB
Bash
Executable File
#!/bin/bash
|
|
set -e
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
cd "$SCRIPT_DIR"
|
|
|
|
if [[ "$1" == "--link-steam-profiles" ]]; then
|
|
if [[ ! -f .env ]]; then
|
|
echo "No .env found yet. Run bash install.sh (with no flag) first to set up your keys."
|
|
exit 1
|
|
fi
|
|
echo "Installing dependencies..."
|
|
npm install --silent
|
|
node link-steam-profiles.js
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "$1" == "--bulk-own" ]]; then
|
|
if [[ ! -f .env ]]; then
|
|
echo "No .env found yet. Run bash install.sh (with no flag) first to set up your keys."
|
|
exit 1
|
|
fi
|
|
shift
|
|
echo "Installing dependencies..."
|
|
npm install --silent
|
|
node bulk-own.js "$@"
|
|
exit 0
|
|
fi
|
|
|
|
if [[ "$1" == "--sync-roles" ]]; then
|
|
if [[ ! -f .env ]]; then
|
|
echo "No .env found yet. Run bash install.sh (with no flag) first to set up your keys."
|
|
exit 1
|
|
fi
|
|
echo "Installing dependencies..."
|
|
npm install --silent
|
|
node sync-roles.js
|
|
exit 0
|
|
fi
|
|
|
|
OS_NAME="$(uname -s)"
|
|
|
|
if [[ "$OS_NAME" != "Darwin" && "$OS_NAME" != "Linux" ]]; then
|
|
echo "This installer is for macOS and Linux. On Windows, run install.ps1 in PowerShell instead."
|
|
exit 1
|
|
fi
|
|
|
|
set_env_value() {
|
|
local key="$1"
|
|
local value="$2"
|
|
if [[ -f .env ]] && grep -q "^${key}=" .env; then
|
|
grep -v "^${key}=" .env > .env.tmp
|
|
mv .env.tmp .env
|
|
fi
|
|
echo "${key}=${value}" >> .env
|
|
}
|
|
|
|
if [[ "$OS_NAME" == "Darwin" ]]; then
|
|
for OLD_LABEL in com.justinoros.discordgamepricebot com.justinoros.gamepricebot; do
|
|
OLD_PLIST="$HOME/Library/LaunchAgents/$OLD_LABEL.plist"
|
|
if [[ -f "$OLD_PLIST" ]]; then
|
|
echo "Found an old launchd service ($OLD_LABEL) from a previous version of this bot - switching it over to pm2 so you don't end up with two copies running."
|
|
launchctl unload "$OLD_PLIST" >/dev/null 2>&1 || true
|
|
rm -f "$OLD_PLIST"
|
|
fi
|
|
done
|
|
fi
|
|
|
|
if ! command -v node >/dev/null 2>&1; then
|
|
echo "Node.js was not found."
|
|
if command -v brew >/dev/null 2>&1; then
|
|
read -p "Install it now with Homebrew? [y/N] " answer
|
|
if [[ "$answer" == "y" || "$answer" == "Y" ]]; then
|
|
brew install node
|
|
else
|
|
echo "Install Node.js from https://nodejs.org (or your package manager) and run this script again."
|
|
exit 1
|
|
fi
|
|
else
|
|
echo "Install Node.js from https://nodejs.org (or your package manager, e.g. apt/dnf/pacman) and run this script again."
|
|
exit 1
|
|
fi
|
|
fi
|
|
|
|
echo "Installing dependencies..."
|
|
npm install --silent
|
|
|
|
if [[ ! -f .env ]]; then
|
|
cp .env.example .env
|
|
fi
|
|
|
|
if [[ ! -f games.json ]]; then
|
|
cp games.json.example games.json
|
|
fi
|
|
|
|
if [[ ! -f owned.json ]]; then
|
|
cp owned.json.example owned.json
|
|
fi
|
|
|
|
if [[ ! -f steamlinks.json ]]; then
|
|
cp steamlinks.json.example steamlinks.json
|
|
fi
|
|
|
|
if [[ ! -f memory.yaml ]]; then
|
|
cp memory.yaml.example memory.yaml
|
|
fi
|
|
|
|
if [[ ! -f scores.json ]]; then
|
|
cp scores.json.example scores.json
|
|
fi
|
|
|
|
if [[ ! -f roles.yaml ]]; then
|
|
cp roles.yaml.example roles.yaml
|
|
fi
|
|
|
|
CURRENT_TOKEN=$(grep -E "^DISCORD_BOT_TOKEN=" .env | cut -d "=" -f2-)
|
|
CURRENT_KEY=$(grep -E "^ITAD_API_KEY=" .env | cut -d "=" -f2-)
|
|
|
|
if [[ -z "$CURRENT_TOKEN" ]]; then
|
|
echo ""
|
|
echo "Need a Discord bot token:"
|
|
echo "1. Go to https://discord.com/developers/applications and sign in"
|
|
echo "2. Click New Application, name it anything, create it"
|
|
echo "3. Click Bot in the left sidebar"
|
|
echo "4. IMPORTANT - scroll to Privileged Gateway Intents, turn ON both Message Content Intent and Server Members Intent, then click the Save Changes button at the bottom."
|
|
echo " The toggles by themselves do not save. If you skip Save Changes, the bot will fail to log in with a disallowed intents error."
|
|
echo "5. Click Reset Token (or Copy) and copy the token"
|
|
echo "6. Click OAuth2 > URL Generator, check bot under Scopes, then check Send Messages, Read Message History, and Manage Roles under Bot Permissions"
|
|
echo "7. IMPORTANT - a URL appears at the bottom of that page. Copy it, paste it into your web browser, press Enter, pick your server, and click Authorize."
|
|
echo " Creating the bot does NOT add it to your server. It will not show up in your server until you open that URL and authorize it there."
|
|
echo ""
|
|
read -p "Paste your Discord bot token: " TOKEN_INPUT
|
|
set_env_value DISCORD_BOT_TOKEN "$TOKEN_INPUT"
|
|
fi
|
|
|
|
if [[ -z "$CURRENT_KEY" ]]; then
|
|
echo ""
|
|
echo "Need a free IsThereAnyDeal API key:"
|
|
echo "1. Register a free user account at https://isthereanydeal.com"
|
|
echo "2. Go to https://isthereanydeal.com/apps/"
|
|
echo "3. Click Register App, name it anything, submit"
|
|
echo "4. Copy the API key it shows you"
|
|
echo ""
|
|
read -p "Paste your IsThereAnyDeal API key: " KEY_INPUT
|
|
set_env_value ITAD_API_KEY "$KEY_INPUT"
|
|
fi
|
|
|
|
CURRENT_STEAM_KEY=$(grep -E "^STEAM_API_KEY=" .env | cut -d "=" -f2-)
|
|
|
|
if [[ -z "$CURRENT_STEAM_KEY" ]]; then
|
|
echo ""
|
|
echo "Optional - only needed for !my-steam-profile and automatic Steam ownership counts on !info:"
|
|
echo "1. Go to https://steamcommunity.com/dev/apikey and sign in"
|
|
echo "2. Enter any domain name (e.g. localhost), agree to the terms, and submit"
|
|
echo "3. Copy the API key it shows you"
|
|
echo ""
|
|
read -p "Paste your Steam Web API key, or press Enter to skip: " STEAM_KEY_INPUT
|
|
set_env_value STEAM_API_KEY "$STEAM_KEY_INPUT"
|
|
fi
|
|
|
|
CURRENT_TAVILY_KEY=$(grep -E "^TAVILY_API_KEY=" .env | cut -d "=" -f2-)
|
|
|
|
if [[ -z "$CURRENT_TAVILY_KEY" ]]; then
|
|
echo ""
|
|
echo "Optional - lets the AI chat look things up on the web (like exact item locations or boss strategies) instead of only relying on what the AI model already knows. Free, no credit card required:"
|
|
echo "1. Go to https://app.tavily.com/ and sign up"
|
|
echo "2. Copy the API key it shows you (starts with tvly-)"
|
|
echo ""
|
|
read -p "Paste your Tavily API key, or press Enter to skip: " TAVILY_KEY_INPUT
|
|
set_env_value TAVILY_API_KEY "$TAVILY_KEY_INPUT"
|
|
fi
|
|
|
|
CURRENT_ITAD_COUNTRY=$(grep -E "^ITAD_COUNTRY=" .env | cut -d "=" -f2-)
|
|
|
|
if [[ -z "$CURRENT_ITAD_COUNTRY" ]]; then
|
|
echo ""
|
|
echo "Optional - sets which country's prices and currency to use (2-letter code, e.g. US, GB, DE, CA, AU). Defaults to US if you skip this."
|
|
echo ""
|
|
read -p "Country code, or press Enter for US: " ITAD_COUNTRY_INPUT
|
|
set_env_value ITAD_COUNTRY "${ITAD_COUNTRY_INPUT:-US}"
|
|
fi
|
|
|
|
CURRENT_DOCKER_HOST=$(grep -E "^DOCKER_SSH_HOST=" .env | cut -d "=" -f2-)
|
|
|
|
if [[ -z "$CURRENT_DOCKER_HOST" ]]; then
|
|
echo ""
|
|
echo "Optional - lets people with a specific Discord role run !docker ps and !docker restart CONTAINER to manage Docker containers on a remote server over SSH (e.g. an Unraid box running your game servers). Requires SSH key access to that server already set up:"
|
|
echo ""
|
|
read -p "SSH host for the Docker server (e.g. chappie.local), or press Enter to skip: " DOCKER_HOST_INPUT
|
|
if [[ -n "$DOCKER_HOST_INPUT" ]]; then
|
|
set_env_value DOCKER_SSH_HOST "$DOCKER_HOST_INPUT"
|
|
read -p "SSH username (e.g. root): " DOCKER_USER_INPUT
|
|
set_env_value DOCKER_SSH_USER "$DOCKER_USER_INPUT"
|
|
read -p "Path to the SSH private key to use: " DOCKER_KEY_INPUT
|
|
set_env_value DOCKER_SSH_KEY_PATH "$DOCKER_KEY_INPUT"
|
|
read -p "Discord role ID allowed to use !docker (right-click the role in Discord, Copy Role ID): " DOCKER_ROLE_INPUT
|
|
set_env_value DOCKER_ROLE_ID "$DOCKER_ROLE_INPUT"
|
|
read -p "Container names to protect from !docker restart, comma-separated (e.g. Plex-Media-Server), or press Enter for none: " DOCKER_PROTECTED_INPUT
|
|
set_env_value DOCKER_PROTECTED_CONTAINERS "$DOCKER_PROTECTED_INPUT"
|
|
else
|
|
echo "Skipping - !docker won't be available. Run this script again any time to set it up."
|
|
fi
|
|
fi
|
|
|
|
if ! command -v ollama >/dev/null 2>&1; then
|
|
echo ""
|
|
read -p "Want the bot to use AI to give smarter, in-character answers when people chat with it? This is free - it installs Ollama and runs a small AI model locally on this machine, no API key or cost involved. [y/N] " AI_ANSWER
|
|
if [[ "$AI_ANSWER" == "y" || "$AI_ANSWER" == "Y" ]]; then
|
|
if command -v brew >/dev/null 2>&1; then
|
|
echo "Installing Ollama..."
|
|
brew install ollama
|
|
elif [[ "$OS_NAME" == "Linux" ]]; then
|
|
echo "Installing Ollama..."
|
|
curl -fsSL https://ollama.com/install.sh | sh
|
|
else
|
|
echo "Install it yourself from https://ollama.com/download, then run this script again to finish setting it up."
|
|
fi
|
|
else
|
|
echo "Skipping - the bot won't reply to chat mentions. Run this script again any time to set it up."
|
|
fi
|
|
fi
|
|
|
|
if command -v ollama >/dev/null 2>&1; then
|
|
CURRENT_OLLAMA_MODEL=$(grep -E "^OLLAMA_MODEL=" .env | cut -d "=" -f2-)
|
|
if [[ -z "$CURRENT_OLLAMA_MODEL" ]]; then
|
|
CURRENT_OLLAMA_MODEL="llama3.2"
|
|
set_env_value OLLAMA_MODEL "$CURRENT_OLLAMA_MODEL"
|
|
fi
|
|
|
|
if command -v brew >/dev/null 2>&1 && brew list ollama >/dev/null 2>&1; then
|
|
brew services start ollama >/dev/null 2>&1 || true
|
|
sleep 2
|
|
fi
|
|
|
|
if ! ollama list 2>/dev/null | grep -q "$CURRENT_OLLAMA_MODEL"; then
|
|
echo ""
|
|
echo "Downloading the $CURRENT_OLLAMA_MODEL model for the bot to use (one-time, may take a few minutes)..."
|
|
ollama pull "$CURRENT_OLLAMA_MODEL" || echo "Could not download the model automatically - make sure Ollama is running, then run: ollama pull $CURRENT_OLLAMA_MODEL"
|
|
fi
|
|
fi
|
|
|
|
if ! command -v pm2 >/dev/null 2>&1; then
|
|
echo ""
|
|
echo "Installing pm2 to keep the bot running in the background..."
|
|
npm install -g pm2
|
|
fi
|
|
|
|
APP_NAME="discord-bot"
|
|
|
|
pm2 delete "$APP_NAME" >/dev/null 2>&1 || true
|
|
pm2 start index.js --name "$APP_NAME" --cwd "$SCRIPT_DIR" --output "$SCRIPT_DIR/bot.log" --error "$SCRIPT_DIR/bot.error.log"
|
|
pm2 save
|
|
|
|
STARTUP_CMD=$(pm2 startup 2>/dev/null | grep "^sudo " || true)
|
|
if [[ -n "$STARTUP_CMD" ]]; then
|
|
eval "$STARTUP_CMD"
|
|
fi
|
|
|
|
echo ""
|
|
echo "Installed and running in the background."
|
|
echo "View logs: pm2 logs $APP_NAME"
|
|
echo "Check status: pm2 status"
|
|
echo "To stop it: pm2 stop $APP_NAME"
|
|
echo "To restart it after editing index.js: bash install.sh"
|