#!/bin/sh
# APEX (Alpine Preparer and EXtender): fully setup Alpine Linux for daily usage
# within limited CLI environments (containers, PRoot-Distro, iSH)
# Run as root from bare Alpine: wget -qO- luxferre.top/apex | sh
# Created by Luxferre in 2026, released into the public domain

PKGS='coreutils sudo bash nawk dialog rlwrap ed curl jq jimtcl jimtcl-sqlite3 gzip zip unzip p7zip unrar-free nmap nmap-ncat nmap-nping rsync openssh-client openssl gnupg pass git mc nano dtach lynx figlet frotz'

if [ -d "/ish" ]; then # running on iSH
  rm -rf /ish # cancel managed upgrades before updating repos
else # not on iSH, append multimedia packages
  PKGS="$PKGS sox mpg123 openmpt123"
fi

cat >/etc/apk/repositories <<'EOF'
https://dl-cdn.alpinelinux.org/alpine/edge/main
https://dl-cdn.alpinelinux.org/alpine/edge/community
https://dl-cdn.alpinelinux.org/alpine/edge/testing
EOF
apk upgrade -l
apk add $PKGS

sed -i'' 's;/bin/sh;/bin/bash;g' /etc/passwd
ln -sf /usr/bin/nawk /usr/bin/awk

# Local single-script installation helper
localinst() {
  local name="$1" url="$2"
  sudo curl -fsSL -o /usr/local/bin/$name "$url"
  sudo chmod +x /usr/local/bin/$name
}

# install GSocket
GSURL="$(curl -fsSL "https://api.github.com/repos/hackerschoice/gsocket/releases/latest" | jq -r '.assets[].browser_download_url' | grep "gsocket_linux-$(uname -m)")"
mkdir gsocket && cd gsocket
curl -fsSL -o gsocket.tgz "$GSURL"
tar xzf gsocket.tgz
rm gsocket.tgz
mv ./* /usr/local/bin/
cd ..
rm -rf gsocket

# install Outport, Multicities, Scoundrel-Bash
localinst outport 'https://codeberg.org/luxferre/sh-goodies/raw/branch/master/outport'
localinst cities 'https://codeberg.org/luxferre/sh-goodies/raw/branch/master/cities.sh'
localinst scoundrel 'https://codeberg.org/luxferre/bash-goodies/raw/branch/master/scoundrel'

echo 'Updating configs...'
mkdir -p /root/.local/bin
cat > /root/.bash_profile <<'EOF'
export LC_ALL=C.UTF-8
export LANG=C.UTF-8
export PATH="$PATH:/root/.local/bin"
[[ -f /root/.bashrc ]] && [[ $- == *i* ]] && . /root/.bashrc
EOF
cat > /root/.bashrc <<'EOF'
PS1='\W # '
. /root/.apexrc
EOF
cat > /root/.apexrc <<'EOF'
export EDITOR='nano -FEDSMAGic/max%_T2'
export PAGER='less -RXF'
# Core aliases
alias nn="$EDITOR"
alias pg="$PAGER"
alias reload-rc=". $BASH_SOURCE"
alias edit-rc="$EDITOR $BASH_SOURCE && . $BASH_SOURCE"
alias lastcmd='history | tail -q -n 2 | head -q -n 1 | sed "s/^[[:space:]]*[0-9]*[[:space:]]*//"'
alias defalias='___(){ __="$1";shift;alias $__="_$__(){ $*; };_$__";unset __; };___'
defalias toalias 'defalias "$1" "$(lastcmd)";alias "$1"'
defalias savealias "[ -n \"\$1\" ] && echo \"alias \$(alias \$1 | sed 's/^alias //')\" >> $BASH_SOURCE"
alias rw='rlwrap -R'
alias ee='rlwrap -R ed -p:'
defalias l 'ls -lahF --time-style=long-iso --color=always $* | less -RXF'
defalias sshed 'f="$(mktemp)";scp $1 $f && $EDITOR $f && scp $f $1 && rm -f $f && unset f'
alias dl='curl -fsSLO'
alias gcm='git commit -a -m'
alias gp='git push origin'
alias gpm='git push origin master'
alias sloc="awk 'BEGIN{s=u=0}{u++}/^\s*#/{s++}/^\s*$/{s++}END{print(u-s)}'"
alias pkgadd='apk add'
alias pkgdel='apk del'
alias pkgsearch='apk search'
alias sysup='apk upgrade'
alias sysclean='rm -rf /var/cache/apk/*'
# Fix Frotz not wanting to run as root
alias frotz='sudo -u games frotz'
# Fix Lynx not wanting to load the config
alias lynx='lynx -cfg=/root/.lynx.cfg'
# Termux-specific aliases
if [ -n "$ANDROID_ROOT" ]; then
  export TERMUX_HOME='/data/data/com.termux/files/home'
  alias tmhome="cd $TERMUX_HOME"
fi

# OpenSSL-based vault helper
ovault() {
  local pw="$4"
  local op='-d'
  [ "$1" = 'e' ] && op='-e'
  if [ -z "$pw" ]; then
    read -rs -p 'Enter vault password: ' pw
  fi
  openssl aes-256-cbc $op -pbkdf2 -iter 100000 -pass pass:"$pw" -in "$2" -out "$3"
}

# dmux, a simple dtach based terminal session manager, as a Bash function
dmux() {
  local SDIR="$HOME/.dtsess" SPFILE="$SDIR/.list" sname
  local -a MENU
  mkdir -p "$SDIR"
  touch "$SPFILE"
  mapfile -t MENU < "$SPFILE"
  if [[ -z "$(ls -1 "$SDIR")" ]]; then
    for sname in "${MENU[@]}"; do
      dtach -n "$SDIR/$sname" $SHELL
    done
  fi
  PS3='Select a session: '
  while true; do
    select sname in "${MENU[@]}" New Quit; do break; done
    [[ "$sname" = 'Quit' ]] && printf '\033[0m' && break
    [[ "$sname" = 'New' ]] && read -r -p 'New session name: ' sname  
    [[ -n "$sname" ]] && printf '\033[0m' && dtach -A "$SDIR/$sname" $SHELL
    ls -1 "$SDIR" > "$SPFILE"
    mapfile -t MENU < "$SPFILE"
  done
}

# Generate a pseudorandom key from machine alias
gs-key() {
  echo "$*"|sha512sum -b|base64 -w0|tr -d -c a-z0-9|cut -c 1-22
}

# Enter the machine by its alias
gs-enter() {
  gs-netcat -i -s "$(gs-key "$*")"  
}

# Print out GS deployment/undeployment/access commands
gs-deploy-cmd() {
  machinekey="$(gs-key "$*")"
  printf 'Deploy on target:\ncurl -fsSL https://gsocket.io/y | X=%s bash\n' "$machinekey"
  printf 'Undeploy from target:\ncurl -fsSL https://gsocket.io/y | GS_UNDO=1 bash\n'
  printf 'Access:\ngs-enter %s\n' "$*"
}
EOF

# Write Lynx config
cat > /root/.lynx.cfg <<'EOF'
DEFAULT_USER_MODE:ADVANCED
STARTFILE:http://frogfind.com
VI_KEYS_ALWAYS_ON:TRUE
ASSUME_CHARSET:utf-8
PREFERRED_CHARSET:utf-8
ASSUME_LOCAL_CHARSET:utf-8
CHARACTER_SET:utf-8
REUSE_TEMPFILES:TRUE
AUTO_SESSION:TRUE
SESSION_FILE:~/.lynx_session
USE_MOUSE:TRUE
ACCEPT_ALL_COOKIES:TRUE
PERSISTENT_COOKIES:TRUE
SYSTEM_EDITOR:nano -FEDSMAGic/max%_T2
TAGSOUP:TRUE
ENABLE_LYNXRC:USERAGENT:ON
ENABLE_LYNXRC:SEND_USERAGENT:ON
DEFAULT_COLORS:OFF
COLOR_STYLE:
COLOR:0:white:black
COLOR:1:cyan:black
COLOR:2:yellow:black
COLOR:3:green:black
COLOR:4:green:black
COLOR:5:brightgreen:black
COLOR:6:brightcyan:black
COLOR:7:black:cyan
EOF

echo 'APEX setup complete. Restart to apply'
