#!/bin/sh
# Steam Library Hardware Check - hardware detector (Linux / macOS)
# Reads only CPU, GPU, RAM, free disk space and the numbers of installed Steam games - no files, passwords or browser data.
# Shows the result first and only sends it after you press Enter.
# The result goes only to the website: in the URL fragment and, when started from the site, to the page that started it.
SITE='https://doesitrun.com'
CODE=''
OS=$(uname -s)

json_escape() { printf '%s' "$1" | sed 's/\\/\\\\/g; s/"/\\"/g' | tr -d '\n\r'; }

if [ "$OS" = "Darwin" ]; then
  CPU=$(sysctl -n machdep.cpu.brand_string 2>/dev/null)
  THREADS=$(sysctl -n hw.logicalcpu 2>/dev/null)
  RAM=$(awk -v b="$(sysctl -n hw.memsize)" 'BEGIN{printf "%.1f", b/1073741824}')
  MEMINFO=$(system_profiler SPMemoryDataType 2>/dev/null)
  RT=$(printf '%s' "$MEMINFO" | grep -oE 'DDR[345]' | head -1)
  RS=$(printf '%s' "$MEMINFO" | awk -F': ' '/Speed:/{print $2; exit}' | grep -oE '[0-9]+' | head -1)
  GPUS=$(system_profiler SPDisplaysDataType 2>/dev/null | awk -F': ' '/Chipset Model/{print $2}')
  FREE=$(df -k "$HOME" | awk 'NR==2{printf "%d", $4/1048576}')
  STEAM_DIRS="$HOME/Library/Application Support/Steam"
  OSN=mac
else
  CPU=$(awk -F': ' '/model name/{print $2; exit}' /proc/cpuinfo)
  THREADS=$(nproc 2>/dev/null || grep -c ^processor /proc/cpuinfo)
  RAM=$(awk '/MemTotal/{printf "%.1f", $2/1048576}' /proc/meminfo)
  GPUS=$(lspci 2>/dev/null | grep -iE 'vga|3d controller|display' | sed -E 's/.*: //; s/ \(rev .*\)$//' | sed -E 's/.*\[([^]]+)\].*$/\1/')
  FREE=$(df -k "$HOME" | awk 'NR==2{printf "%d", $4/1048576}')
  STEAM_DIRS="$HOME/.steam/steam
$HOME/.local/share/Steam
$HOME/.var/app/com.valvesoftware.Steam/.local/share/Steam"
  OSN=linux
fi

GPU_JSON=""
if command -v nvidia-smi >/dev/null 2>&1; then
  NV=$(nvidia-smi --query-gpu=name,memory.total --format=csv,noheader,nounits 2>/dev/null)
fi
OLDIFS=$IFS; IFS='
'
for g in $GPUS; do
  [ -z "$g" ] && continue
  V=null
  GPU_JSON="$GPU_JSON{\"n\":\"$(json_escape "$g")\",\"v\":$V},"
done
for line in $NV; do
  n=$(printf '%s' "$line" | cut -d, -f1 | sed 's/^ *//; s/ *$//')
  m=$(printf '%s' "$line" | cut -d, -f2 | tr -d ' ')
  v=$(awk -v m="$m" 'BEGIN{printf "%.1f", m/1024}')
  GPU_JSON="$GPU_JSON{\"n\":\"$(json_escape "$n")\",\"v\":$v},"
done

APPS=""
for d in $STEAM_DIRS; do
  vdf="$d/steamapps/libraryfolders.vdf"
  [ -f "$vdf" ] || continue
  LIBS="$d
$(sed -n 's/.*"path"[[:space:]]*"\([^"]*\)".*/\1/p' "$vdf")"
  for lib in $LIBS; do
    for f in "$lib"/steamapps/appmanifest_*.acf; do
      [ -f "$f" ] || continue
      id=$(basename "$f" | sed 's/appmanifest_\([0-9]*\)\.acf/\1/')
      APPS="$APPS$id,"
    done
  done
done
IFS=$OLDIFS
APPS=$(printf '%s' "$APPS" | tr ',' '\n' | sort -un | tr '\n' ',' | sed 's/^,//; s/,$//')
GPU_JSON=$(printf '%s' "$GPU_JSON" | sed 's/,$//')

[ -z "$RS" ] && RS=0
JSON="{\"v\":1,\"os\":\"$OSN\",\"cpu\":\"$(json_escape "$CPU")\",\"t\":$THREADS,\"ram\":$RAM,\"rt\":\"$RT\",\"rs\":$RS,\"gpus\":[$GPU_JSON],\"free\":$FREE,\"inst\":\"$APPS\"}"
B64=$(printf '%s' "$JSON" | base64 | tr -d '\n=' | tr '+/' '-_')

echo ""
echo "  CPU:  $CPU ($THREADS threads)"
printf '%s\n' "$GPUS" | sed 's/^/  GPU:  /'
echo "  RAM:  $RAM GB"
echo "  Disk: $FREE GB free"
echo "  Installed Steam games: $(printf '%s' "$APPS" | tr ',' '\n' | grep -c .)"
echo ""
echo "  That is everything that will be sent - nothing else."
echo ""
HOSTNAME_ONLY=$(printf '%s' "$SITE" | sed -E 's#^[a-z]+://##; s#/.*$##')
echo "  ============================================================"
echo "   >>  Press ENTER to send this to the website  <<"
echo "       $HOSTNAME_ONLY"
echo "       (or type n and press Enter to cancel)"
echo "  ============================================================"
printf '  '
ANSWER=""
if [ -r /dev/tty ]; then read -r ANSWER </dev/tty; fi
case "$ANSWER" in n*|N*)
  echo "  Cancelled - nothing was sent."
  # only tell the waiting browser tab that you cancelled (no hardware data)
  if [ -n "$CODE" ] && command -v curl >/dev/null 2>&1; then curl -fsS -m 10 -X POST -H 'Content-Type: text/plain' --data 'cancelled_by_user' "$SITE/api/hwdrop?c=$CODE" >/dev/null 2>&1; fi
  exit 0;;
esac
URL="$SITE/#hw=$B64"
SENT=0
if [ -n "$CODE" ]; then
  # hand the result to the browser tab that downloaded the detector - no second browser window
  if command -v curl >/dev/null 2>&1; then curl -fsS -m 15 -X POST -H 'Content-Type: text/plain' --data "$B64" "$SITE/api/hwdrop?c=$CODE" >/dev/null 2>&1 && SENT=1
  elif command -v wget >/dev/null 2>&1; then wget -q -T 15 -O /dev/null --header='Content-Type: text/plain' --post-data="$B64" "$SITE/api/hwdrop?c=$CODE" && SENT=1; fi
fi
if [ "$SENT" = 1 ]; then
  echo "  Done - your hardware now appears in the browser tab you started this from."
elif [ "$OS" = "Darwin" ]; then open "$URL"; else xdg-open "$URL" >/dev/null 2>&1 || echo "Open this link: $URL"; fi
