/ APP-MANAGER
APP-MANAGER
   1  #!/usr/bin/env bash
   2  
   3  AMVERSION="9.4.2"
   4  
   5  # Determine main repository and branch
   6  AMREPO="https://raw.githubusercontent.com/ivan-hc/AM/main"
   7  AMBRANCH=$(basename "$AMREPO")
   8  MODULES_SOURCE="$AMREPO/modules"
   9  
  10  # Determine the name of this script and its working directory
  11  export REALDIR="$PWD"
  12  DIR="$( cd "$( dirname "$0" )" && pwd )"
  13  CLI=$(basename "$0")
  14  
  15  # Determine system architecture and current user
  16  ARCH="$(uname -m)"
  17  [ "$ARCH" = "amd64" ] && ARCH=x86_64
  18  export ARCH
  19  
  20  # Fixes issue with less on bsd
  21  if uname | grep -q "BSD\|DragonFly\|DynFi\|FreeNAS\|helloSystem\|OPNsense\|pfSense\|TrueNAS\|XigmaNAS"; then
  22  	TERM=xterm-clear
  23  	export TERM
  24  fi
  25  
  26  # XDG Variables
  27  export BINDIR="${XDG_BIN_HOME:-$HOME/.local/bin}"
  28  export DATADIR="${XDG_DATA_HOME:-$HOME/.local/share}"
  29  export CONFIGDIR="${XDG_CONFIG_HOME:-$HOME/.config}"
  30  export CACHEDIR="${XDG_CACHE_HOME:-$HOME/.cache}"
  31  export APPMANCONFIG="$CONFIGDIR/appman"
  32  APPMANCONFIG="$CONFIGDIR/appman"
  33  SCRIPTDIR="${SCRIPTDIR:-$(xdg-user-dir DESKTOP 2>/dev/null)}"
  34  [ -d "$SCRIPTDIR" ] || SCRIPTDIR="$PWD"
  35  export SCRIPTDIR
  36  
  37  # Colors
  38  RED='\033[0;31m'
  39  Gold='\033[0;33m'
  40  Green='\033[0;32m'
  41  LightBlue='\033[1;34m'
  42  DIVIDING_LINE="-----------------------------------------------------------------------------"
  43  
  44  # Prevent the use of "sudo" ("AM")
  45  if [ -n "${SUDO_USER:-$DOAS_USER}" ]; then
  46  	printf "\n Please do not use \"sudo\" to execute \"%b\", try again.\n\n" "$CLI"
  47  	exit 1
  48  fi
  49  
  50  if ! sed --version 2>/dev/null | grep -qi "gnu"; then
  51  	NO_SED_I=true
  52  fi
  53  
  54  _create_cache_dir() {
  55  	AMCACHEDIR="$CACHEDIR/$AMCLI"
  56  	mkdir -p "$AMCACHEDIR"
  57  }
  58  
  59  _clean_amcachedir() {
  60  	[ "$AMCLI" = am ] && [ -d "$CACHEDIR"/am ] && rm -f "$CACHEDIR"/am/*
  61  	[ -d "$CACHEDIR"/appman ] && rm -f "$CACHEDIR"/appman/*
  62  }
  63  
  64  # Fit texts to an acceptable width
  65  _fit() {
  66  	fold -sw 77 | sed 's/^/ /g'
  67  }
  68  
  69  # Makes "less" optional
  70  less() {
  71  	if ! command less "$@" 2>/dev/null; then
  72  		while read -r line; do echo "$line"; done
  73  		echo "Install 'less' if you want to scroll this list"
  74  	fi
  75  }
  76  
  77  # Force usage of a GNU implementation of "sed"
  78  sed() {
  79  	if [ "$NO_SED_I" = true ] && [ "$1" = '-i' ]; then
  80  		if command -v gsed >/dev/null 2>&1; then
  81  			command gsed "$@"
  82  		else
  83  			shift
  84  			tmpsedYYY="$(command sed "$@" 2>/dev/null)"
  85  			while [ "$#" -gt 1 ]; do shift; done
  86  			if [ -n "$tmpsedYYY" ] && [ -f "$1" ]; then
  87  				echo "$tmpsedYYY" > "$1"
  88  				unset tmpsedYYY
  89  			else
  90  				>&2 echo " πŸ’€ ERROR: Your version of sed does not support '-i' flag"
  91  				>&2 echo " without extension, we tried to workaround and failed"
  92  				>&2 echo " Please install gsed"
  93  				unset tmpsedYYY
  94  				return 1
  95  			fi
  96  		fi
  97  	else
  98  		command sed "$@"
  99  	fi
 100  }
 101  
 102  ################################################################################
 103  #				AM/APPMAN
 104  ################################################################################
 105  
 106  # "APPMAN" CORE VARIABLES AND FUNCTIONS
 107  APPMAN_SETUP_MSG="Before proceeding with any task, where do you want to install apps?
 108  
 109  SYNTAX: /FULLPATH/TO/DIRNAME
 110  EXAMPLE: $HOME/My-apps
 111  
 112  NOTE: Any spaces in the path will be replaced for dashes
 113  NOTE: If no input is given then \"~/Applications\" will be used as default
 114  
 115  if you wish to later change the location, first remove all the programs and then edit the \"$APPMANCONFIG/appman-config\" file."
 116  
 117  _appman_check() {
 118  	if [ ! -f "$APPMANCONFIG"/appman-config ]; then
 119  		echo "$DIVIDING_LINE"
 120  		[ "$AMCLI" = am ] && echo ">>> Configure AppMan" || echo ">>> Thank you for choosing AppMan!"
 121  		echo "$DIVIDING_LINE"
 122  		echo "$APPMAN_SETUP_MSG" | _fit
 123  		echo "$DIVIDING_LINE"
 124  		read -r -ep " Write the path or just press enter to use default:$(printf "\n\n ")" location
 125  		location="$(echo "$location" | sed 's/[ \t]/-/g; s|^\./||' 2>/dev/null)"
 126  		[ -z "$location" ] && location="$HOME/Applications"
 127  		if ! echo "$location" | grep "^/" >/dev/null 2>&1; then
 128  			location="$HOME/$location"
 129  		fi
 130  		if echo "$location" | grep "$BINDIR" >/dev/null 2>&1; then
 131  			echo "$DIVIDING_LINE"
 132  			echo " πŸ’€ ERROR, you can't install applications in \"$BINDIR\""
 133  			echo " $BINDIR is normally used for executables, Please choose a different path and retry!"
 134  			echo "$DIVIDING_LINE"
 135  			exit  1
 136  		elif ! mkdir -p "$location" 2>/dev/null || [ ! -w "$location" ]; then
 137  			echo " πŸ’€ ERROR: You don't have write access to $location or it is invalid"
 138  			exit 1
 139  		fi
 140  		mkdir -p "$APPMANCONFIG" || exit 1
 141  		echo "${location%/}" > "$APPMANCONFIG"/appman-config || exit 1
 142  		echo "$DIVIDING_LINE"
 143  		echo " You are ready! Start installing your favorite apps locally!"
 144  		echo " All apps will be installed in $location"
 145  		echo " In case of problems, use the option \"-h\"."
 146  		echo "$DIVIDING_LINE"
 147  	fi
 148  }
 149  
 150  _appman() {
 151  	_appman_check
 152  	if ! grep -q "^/" "$APPMANCONFIG"/appman-config; then
 153  		APPSDIR="$HOME/$(head -1 "$APPMANCONFIG"/appman-config 2>/dev/null)"
 154  	else
 155  		APPSDIR="$(head -1 "$APPMANCONFIG"/appman-config 2>/dev/null)"
 156  	fi
 157  	[ -n "$APPSDIR" ] && mkdir -p "$APPSDIR"/appman || exit 1
 158  	mkdir -p "$BINDIR" "$DATADIR"/applications "$DATADIR"/icons || exit 1
 159  	AMCLI="appman"
 160  	AMCLIPATH="$DIR/$AMCLI"
 161  	SUDOCMD=""
 162  	APPSPATH="$APPSDIR"
 163  	AMPATH="$APPSDIR/$AMCLI"
 164  	_create_cache_dir
 165  	if [ ! -w "$APPSPATH" ]; then
 166  		echo "ERROR: You don't have write access to $APPSPATH" | _fit
 167  		exit 1
 168  	elif ! echo "$PATH" | grep "$BINDIR" >/dev/null 2>&1; then
 169  		echo "$DIVIDING_LINE"
 170  		printf "%b ⚠️ WARNING\033[0m: \"%b%b\033[0m\" is not in PATH, local apps may not run.\n" "${RED}" "${LightBlue}" "$BINDIR"
 171  	fi
 172  	MODULES_PATH="$AMPATH/modules"
 173  	mkdir -p "$MODULES_PATH" || exit 1
 174  }
 175  
 176  # "AM" CORE VARIABLES
 177  _am() {
 178  	AMCLI="am"
 179  	AMCLIPATH="$AMCLI"
 180  	if command -v sudo >/dev/null 2>&1; then
 181  		export SUDOCMD="sudo"
 182  	elif command -v doas >/dev/null 2>&1; then
 183  		export SUDOCMD="doas"
 184  	else
 185  		echo 'ERROR: No sudo or doas found'
 186  		exit 1
 187  	fi
 188  	APPSPATH="/opt"
 189  	AMPATH="$APPSPATH/$AMCLI"
 190  	_create_cache_dir
 191  	MODULES_PATH="$AMPATH/modules"
 192  }
 193  
 194  # DETERMINE WHEN TO USE "AM" OR "APPMAN"
 195  if [ "$(realpath "$0")" = "/opt/am/APP-MANAGER" ]; then
 196  	_am
 197  	mkdir -p "$MODULES_PATH" || exit 1
 198  elif [ "$(realpath "$0")" = "/usr/bin/am" ]; then
 199  	_am
 200  	AMPATH="$AMCACHEDIR"
 201  	MODULES_PATH="/usr/lib/am/modules"
 202  else
 203  	_appman
 204  fi
 205  
 206  _detect_appman_apps() {
 207  	[ -f "$APPMANCONFIG/appman-config" ] && APPMAN_APPSPATH=$(<"$APPMANCONFIG/appman-config")
 208  	if ! echo "$APPMAN_APPSPATH" | grep -q "^/"; then
 209  		[ -f "$APPMANCONFIG/appman-config" ] && APPMAN_APPSPATH="$HOME/$(<"$APPMANCONFIG/appman-config")"
 210  	fi
 211  }
 212  
 213  _determine_args() {
 214  	ARGPATHS=$(find "$APPSPATH" -maxdepth 2 -name 'remove' -print 2>/dev/null | sort -u | sed 's|/remove||g')
 215  	ARGS=$(echo "$ARGPATHS" | xargs -n 1 basename 2>/dev/null)
 216  	if [ "$AMCLI" = am ]; then
 217  		_detect_appman_apps
 218  		if [ -d "$APPMAN_APPSPATH" ]; then
 219  			APPMAN_PATHS=$(find "$APPMAN_APPSPATH" -maxdepth 2 -name 'remove' -print 2>/dev/null | sort -u | sed 's|/remove||g')
 220  			ARGPATHS=$(printf "%b\n%b" "$ARGPATHS" "$APPMAN_PATHS")
 221  			ARGS=$(echo "$ARGPATHS" | xargs -n 1 basename 2>/dev/null)
 222  		fi
 223  	fi
 224  	# use "argpath=$(echo "$ARGPATHS" | grep "/$arg$")" to determine the full path of "arg"
 225  }
 226  
 227  _icon_theme_export_to_datadir() {
 228  	PNG="$(file "$APPSPATH"/*/icons/* | grep -i '.png' | awk -F":" '{print $1}' | grep -vi .png)"
 229  	SVG="$(file "$APPSPATH"/*/icons/* | grep -i '.svg' | awk -F":" '{print $1}' | grep -vi .svg)"
 230  	for file in $PNG; do ln -s "$file" "${file}".png; done
 231  	for file in $SVG; do ln -s "$file" "${file}".svg; done
 232  	if [ -n "$APPMAN_APPSPATH" ]; then
 233  		PNG="$(file "$APPMAN_APPSPATH"/*/icons/* | grep -i '.png' | awk -F":" '{print $1}' | grep -vi .png)"
 234  		SVG="$(file "$APPMAN_APPSPATH"/*/icons/* | grep -i '.svg' | awk -F":" '{print $1}' | grep -vi .svg)"
 235  		for file in $PNG; do ln -s "$file" "${file}".png; done
 236  		for file in $SVG; do ln -s "$file" "${file}".svg; done
 237  	fi
 238  	mkdir -p "$DATADIR"/icons/hicolor/scalable/apps
 239  	find "$DATADIR"/icons/hicolor/scalable/apps -xtype l -exec rm {} \;
 240  	ln -s "$APPSPATH"/*/icons/*.* "$DATADIR"/icons/hicolor/scalable/apps
 241  	[ -n "$APPMAN_APPSPATH" ] && ln -s "$APPMAN_APPSPATH"/*/icons/*.* "$DATADIR"/icons/hicolor/scalable/apps
 242  }
 243  
 244  ################################################################################
 245  #				FINALIZE
 246  ################################################################################
 247  
 248  AMCLIUPPER=$(echo "$AMCLI" | tr '[:lower:]' '[:upper:]')
 249  
 250  # Create new data directory and move important files there
 251  AMDATADIR="$DATADIR/AM"
 252  mkdir -p "$AMDATADIR"
 253  
 254  # DEVELOPER MODE
 255  if [ -f "$AMDATADIR"/betatester ]; then
 256  	AMREPO="https://raw.githubusercontent.com/ivan-hc/AM/dev"
 257  	AMBRANCH=$(basename "$AMREPO")
 258  	MODULES_SOURCE="$AMREPO/modules"
 259  fi
 260  
 261  _betatester_message_on() {
 262  	if [ -f "$AMDATADIR"/betatester ]; then
 263  		echo "$DIVIDING_LINE"; echo "\"$AMCLIUPPER\" $AMVERSION: DEVELOPER MODE"; echo "$DIVIDING_LINE"
 264  	fi
 265  }
 266  
 267  ################################################################################
 268  #				APPS DATABASE
 269  ################################################################################
 270  
 271  # Apps database in use
 272  APPSDB="${APPSDB:-$AMREPO/programs/$ARCH}"
 273  APPSLISTDB="${APPSLISTDB:-$AMREPO/programs/$ARCH-apps}"
 274  
 275  # Determine catalogue in use
 276  export AMCATALOGUEMARKDOWNS="${AMCATALOGUEMARKDOWNS:-https://portable-linux-apps.github.io/apps}"
 277  export AMCATALOGUEICONS="${AMCATALOGUEICONS:-https://portable-linux-apps.github.io/icons}"
 278  
 279  ################################################################################
 280  #				SECURITY
 281  ################################################################################
 282  
 283  # SAFETY CHECKS
 284  _am_dependences_check() {
 285  	# Check for essential commands required by the application
 286  	missing_deps=""
 287  	AMDEPENDENCES="cat chmod chown curl file grep sed wget"
 288  	for name in $AMDEPENDENCES; do
 289  		if ! command -v "$name" >/dev/null 2>&1; then
 290  			missing_deps="$name $missing_deps"
 291  		fi
 292  	done
 293  
 294  	# Exit if any essential command is missing
 295  	if [ -n "$missing_deps" ]; then
 296  		echo "$DIVIDING_LINE"
 297  		printf " ${RED}πŸ’€ ERROR! MISSING ESSENTIAL COMMANDS\033[0m: %s\n\n Install the above and try again! \n" "${missing_deps[*]}"
 298  		echo "$DIVIDING_LINE"
 299  		printf "%bList of the %b core dependences\033[0m:\n\n%b\n" "${Green}" "$AMCLIUPPER $AMVERSION" "$AMDEPENDENCES" | _fit
 300  		echo "$DIVIDING_LINE"
 301  		printf "If this message appears it is because you are missing some dependency and if its the first time its because something new has been introduced.\n\n" | _fit
 302  		printf " See %bhttps://github.com/ivan-hc/AM#core-dependences\033[0m for more information\n" "${LightBlue}"
 303  		echo "$DIVIDING_LINE"
 304  		exit 1
 305  	fi
 306  }
 307  
 308  _check_ubuntu_mess() {
 309  	if command -v unshare >/dev/null 2>&1 && ! unshare --user -p /bin/true >/dev/null 2>&1; then
 310  		echo "$DIVIDING_LINE"
 311  		printf "\n %b⚠️ WARNING: ACCESS TO USER NAMESPACES IS RESTRICTED! \033[0m\n\n" "${RED}"
 312  		echo " Some apps may not run, you need to enable access to user namespaces, see"
 313  		printf " %bhttps://github.com/ivan-hc/AM/blob/main/docs/troubleshooting.md#ubuntu-mess\033[0m\n" "${LightBlue}"
 314  		echo " to know more."
 315  		echo ""
 316  		echo "$DIVIDING_LINE"
 317  	fi
 318  }
 319  
 320  _am_dependences_check
 321  _check_ubuntu_mess
 322  
 323  # Function to check online connections (uses github.com by default, as the database and CLI itself are stored/hosted there)
 324  _online_check() {
 325  	if ! wget -q --tries=10 --timeout=20 --spider https://github.com; then
 326  		printf "\n %b is offline, please check your internet connection and try again\n\n" "$AMCLI"
 327  		exit 0
 328  	fi
 329  }
 330  
 331  # BLACKLIST FILES
 332  appimagelauncher_msg="Your installation of AppImageLauncher may have been done via DEB, RPM, or AUR, which interrupts the \
 333  natural operation of \"systemd-binfmt\" in addition to launching the aforementioned daemon. To avoid problems with \"$AMCLIUPPER\" \
 334  and any other AppImages helper, it's preferable to use \"only\" the standalone AppImage of AppImageLauncher, whose official \
 335  updated release can also be installed via \"$AMCLIUPPER\". But as long as you have the currently installed version, you can't use this CLI."
 336  
 337  _blacklisted_file() {
 338  	printf "\n %bπŸ’€WARNING! Detected \"%b\"\033[0m\n\n" "${RED}" "$blacklisted_file"
 339  	echo "It will prevent \"$AMCLIUPPER\" from working correctly with AppImages, especially when extracting, integrating and updating them." | _fit
 340  	echo ""
 341  	if echo "$blacklisted_file" | grep -q appimagelauncherd; then
 342  		echo "$appimagelauncher_msg" | _fit
 343  		echo "" && echo " Please remove \"AppImageLauncher\", reboot and retry!"
 344  	else
 345  		echo " Please remove \"$blacklisted_file\", reboot and retry!"
 346  	fi
 347  	echo ""
 348  	exit 0
 349  }
 350  
 351  if command -v appimaged &>/dev/null; then
 352  	blacklisted_file=$(command -v appimaged)
 353  	_blacklisted_file
 354  elif command -v appimagelauncherd &>/dev/null; then
 355  	blacklisted_file=$(command -v appimagelauncherd)
 356  	_blacklisted_file
 357  fi
 358  
 359  ################################################################################
 360  #				3RD PARTY
 361  ################################################################################
 362  
 363  _use_newrepo() {
 364  	[ -z "$2" ] && echo " USAGE: $AMCLI $1 [ARGUMENT]" && exit 1
 365  	case $2 in
 366  	'add')
 367  		if [ -z "$3" ]; then
 368  			echo " USAGE:	$AMCLI $1 $2 /path/to/dir"; echo "	$AMCLI $1 $2 {URL}"; exit 1
 369  		else
 370  			echo "$3" >> "$AMDATADIR/newrepo-lists"
 371  		fi
 372  		;;
 373  	'enable'|'on')
 374  		[ ! -f "$AMDATADIR/newrepo-lists" ] && echo " ERROR, \"$AMDATADIR/newrepo-lists\" file not found" && exit 1
 375  		[ -f "$AMDATADIR/newrepo-off" ] && mv "$AMDATADIR/newrepo-off" "$AMDATADIR/newrepo-on" && echo " New repo ON!"
 376  		;;
 377  	'disable'|'off')
 378  		[ ! -f "$AMDATADIR/newrepo-lists" ] && echo " ERROR, \"$AMDATADIR/newrepo-lists\" file not found" && exit 1
 379  		[ -f "$AMDATADIR/newrepo-on" ] && mv "$AMDATADIR/newrepo-on" "$AMDATADIR/newrepo-off" && echo " New repo OFF!"
 380  		;;
 381  	'info')
 382  		printf " Source: %b\n Apps: %b\n List: %b\n" "$AMREPO" "$APPSDB" "$APPSLISTDB"
 383  		;;
 384  	'purge')
 385  		[ -f "$AMDATADIR/newrepo-lists" ] && rm -f "$AMDATADIR"/newrepo* && echo " Removed all 3rd party repositories"
 386  		;;
 387  	'select')
 388  		[ ! -f "$AMDATADIR/newrepo-lists" ] && echo " ERROR, \"$AMDATADIR/newrepo-lists\" file not found" && exit 1
 389  		printf "Select a repo from the list or press CTRL+C to abort:\n%b\n" "$DIVIDING_LINE"; sleep 1
 390  		select repo in $(sort -u "$AMDATADIR/newrepo-lists" | uniq); do
 391  			test -n "$repo" && break
 392  			echo ">>> Invalid Selection"
 393  		done
 394  		echo "$repo" > "$AMDATADIR/newrepo-on"
 395  		;;
 396  	esac
 397  }
 398  
 399  # 3RD PARTY DATABASES
 400  _am_newrepo_check() {
 401  	# Determine if the CLI uses the "main" branch of https://github.com/ivan-hc/AM or an alternative one
 402  	if [ -f "$AMDATADIR/newrepo-on" ]; then
 403  		if grep -q "^http" "$AMDATADIR/newrepo-on"; then
 404  			AMREPO=$(<"$AMDATADIR/newrepo-on")
 405  		elif grep -q "^/" "$AMDATADIR/newrepo-on"; then
 406  			AMREPO="file://$(<"$AMDATADIR/newrepo-on")"
 407  		fi
 408  		AMBRANCH=$(basename "$AMREPO")
 409  		export APPSDB="$AMREPO/programs/$ARCH"
 410  		export APPSLISTDB="$AMREPO/programs/$ARCH-apps"
 411  		export MODULES_PATH="$AMPATH/modules"
 412  		export AMCATALOGUEMARKDOWNS=""
 413  		export AMCATALOGUEICONS=""
 414  		if [ "$1" != "newrepo" ] && [ "$1" != "neodb" ]; then
 415  			echo "$DIVIDING_LINE"; echo " Source: $AMREPO"; echo "$DIVIDING_LINE"
 416  		fi
 417  	fi
 418  }
 419  
 420  _am_newrepo_check "$@"
 421  
 422  ################################################################################
 423  #				3RD PARTY SOURCES
 424  ################################################################################
 425  
 426  third_party_flags_message=""
 427  
 428  # APPBUNDLEHUB
 429  export appbundle_repo="https://github.com/xplshn/AppBundleHUB"
 430  appbundle_readme="https://raw.githubusercontent.com/xplshn/dbin-metadata/refs/heads/master/misc/cmd/AM-support/AM.txt"
 431  
 432  _sync_appbundle_list() {
 433  	rm -f "$AMDATADIR/$ARCH-appbundle"
 434  	[ -n "$appbundle_readme" ] && curl -Ls "$appbundle_readme" | grep -v "\.appimage \|?" | grep "\.appbundle " | cut -d":" -f1 | cut -d"@" -f2 \
 435  	| sed 's/^| /β—† /g; s/ https$//g; s/ :$//g; s/ | / : /g; s/ |$/./g; s/\.\.$/./g;' | sort > "$AMDATADIR/$ARCH-appbundle" \
 436  	|| touch "$AMDATADIR/$ARCH-appbundle"
 437  }
 438  
 439  # TOOLPACKS
 440  toolpack_repo="https://github.com/Azathothas/Toolpacks"
 441  toolpack_readme="https://bin.pkgforge.dev/${ARCH}/AM.txt"
 442  [ -n "$toolpack_readme" ] && third_party_flags="$third_party_flags --toolpack"
 443  [ -n "$toolpack_readme" ] && third_party_flags_message="$third_party_flags_message\n
 444  ${Gold}--toolpack\033[0m
 445  
 446  	${LightBlue}$AMCLI -i --toolpack {PROGRAM}\033[0m
 447  	${LightBlue}am -i --toolpack --user {PROGRAM}\033[0m
 448  	${LightBlue}$AMCLI -l --toolpack\033[0m
 449  	${LightBlue}$AMCLI -q --toolpack {KEYWORD}\033[0m
 450  
 451  Description: This is a flag to use in \"-i\" to install Toolpack programs, in \"-l\" to list all available \
 452  Toolpacks, and \"-q\" to search the Toolpack list. Toolpack is a collection of programs external to the \"AM\" \
 453  database. Visit $toolpack_repo to learn more.
 454  
 455  NOTE, for installations you can use \".toolpack\" as the package extension instead of using the flag.
 456  "
 457  
 458  _sync_toolpacks_list() {
 459  	rm -f "$AMDATADIR/$ARCH-toolpack"
 460  	[ -n "$toolpack_readme" ] && curl -Ls "$toolpack_readme" | grep -v "\.appimage \|.appbundle \|?" | cut -d":" -f1 | cut -d"@" -f2 \
 461  	| sed 's/^| /β—† /g; s/ | https$/. To install it use the "--toolpack" flag./g; s/ | / : /g' | sort > "$AMDATADIR/$ARCH-toolpack" \
 462  	|| touch "$AMDATADIR/$ARCH-toolpack"
 463  }
 464  
 465  ################################
 466  #	ALL THE ABOVE
 467  ################################
 468  
 469  export third_party_lists="appbundle toolpack"
 470  
 471  _completion_list_third_party() {
 472  	[ -f "$AMDATADIR"/"$ARCH"-appbundle ] && awk '{print $2}' "$AMDATADIR"/"$ARCH"-appbundle >> "$AMDATADIR"/list
 473  	[ -f "$AMDATADIR"/"$ARCH"-toolpack ] && awk '{print $2}' "$AMDATADIR"/"$ARCH"-toolpack | sed -e 's/$/.toolpack/' >> "$AMDATADIR"/list
 474  }
 475  
 476  _sync_third_party_lists() {
 477  	_sync_appbundle_list
 478  	_sync_toolpacks_list
 479  }
 480  
 481  export awk_name="1" awk_description="2" awk_site="3" awk_dl="4" awk_ver="5" # Numbers to use in "awk" to determine columns
 482  
 483  [ -z "$third_party_flags_message" ] && third_party_flags_message="none\n"
 484  
 485  ################################################################################
 486  #				UTILITIES
 487  ################################################################################
 488  
 489  # COMPLETION LIST
 490  available_options="about add apikey backup clean config disable downgrade download enable extra files home icons info \
 491  	install install-appimage launcher list lock neodb newrepo nolibfuse off on overwrite purge query remove sandbox \
 492  	select sync template test unlock update --all --appimages --apps --byname --config --convert --debug \
 493  	--devmode-disable --devmode-enable --disable-notifications --enable-notifications --force-latest --home --icons \
 494  	-ias --launcher --less --pkg --rollback --disable-sandbox --sandbox --system --user $third_party_flags"
 495  
 496  _completion_lists() {
 497  	# Remove existing lists and download new ones
 498  	curl -Ls "$APPSLISTDB" > "$AMDATADIR/$ARCH-apps"
 499  	awk -v FS="(β—† | : )" '{print $2}' <"$AMDATADIR"/"$ARCH"-apps > "$AMDATADIR"/list
 500  	_completion_list_third_party
 501  	# Append options to the list
 502  	for o in $available_options; do
 503  		echo "$o" >> "$AMDATADIR"/list
 504  	done
 505  }
 506  
 507  # BASH, FISH AND ZSH COMPLETION
 508  completion_file="$DATADIR/bash-completion/completions/$AMCLI"
 509  mkdir -p "$DATADIR/bash-completion/completions" || exit 1
 510  if ! grep -o " $AMCLI$" "$completion_file" >/dev/null 2>&1; then
 511  	echo "complete -W \"\$(cat $AMDATADIR/list 2>/dev/null)\" $AMCLI" >> "$completion_file"
 512  	if [ -f "${ZDOTDIR:-$HOME}"/.zshrc ] && echo "$SHELL" | grep -q "zsh"; then
 513  		cat <<-HEREDOC >> "${ZDOTDIR:-$HOME}"/.zshrc
 514  		autoload bashcompinit
 515  		bashcompinit
 516  		source "$completion_file"
 517  		HEREDOC
 518  	fi
 519  	echo "Shell completion has been enabled!"
 520  fi
 521  if [ -d "$DATADIR"/fish/completions ] || [ -d /etc/fish/completions ] || [ -d /usr/share/fish/completions ]; then
 522  	command -v fish 1>/dev/null && [ ! -f "$CONFIGDIR"/fish/completions/am.fish ] && mkdir -p "$CONFIGDIR"/fish/completions && echo "complete -c am -f -a \"(cat $DATADIR/AM/list 2>/dev/null)\"" > "$CONFIGDIR"/fish/completions/am.fish
 523  fi
 524  
 525  # VERSION OF THE INSTALLED APPS
 526  # Filters
 527  _check_version_filters() {
 528  	sed -E "s/$ARCH|amd64|x86-64|x64|basic|standard|full|help|Qt[0-9]//g; s/-/\n/g; s/_/\n/g;" |\
 529  	grep -vi "appimage\|$arg\|?\|tar." | grep "[0-9]" | head -1 | sed 's/^v//g; s/^\.//g; s/\.$//g;'
 530  }
 531  
 532  _check_version_grep_numbers() {
 533  	grep -Eo "([0-9]{1,}\.)+[0-9]{1,}" | head -1
 534  }
 535  
 536  # Versions
 537  _check_version_if_any_version_reference_is_somewhere() {
 538  	txt_files=$(file "$argpath"/* | awk -F: '/ASCII text/ {print $1}')
 539  	for txtf in $txt_files; do
 540  		if [ -f "$argpath"/tbb_version.json ] && grep -qi "\"version\":" "$argpath"/tbb_version.json; then
 541  			APPVERSION=$(sort "$argpath"/tbb_version.json | tr '"' '\n' | grep "^[0-9]" | head -1)
 542  		elif grep -qi "^version=" "$txtf" && grep -qi "^name=" "$txtf"; then
 543  			APPVERSION=$(grep -i "^version=" "$txtf" | cut -c 9- | tr -cd '[:alnum:]._-')
 544  		fi
 545  	done
 546  }
 547  
 548  _check_version_if_version_file_exists() {
 549  	APPVERSION=$(sort "$argpath"/version | head -1 | sed 's:.*/::' | _check_version_filters)
 550  	if [ -z "$APPVERSION" ]; then
 551  		if grep -q "download$" "$argpath"/version; then
 552  			APPVERSION=$(sort "$argpath"/version | tr '/' '\n' | _check_version_filters)
 553  		elif grep -q "://" "$argpath"/version; then
 554  			APPVERSION=$(sort "$argpath"/version | tr '/' '\n' | _check_version_grep_numbers)
 555  		elif grep -q "/v[0-9]*" "$argpath"/version; then
 556  			APPVERSION=$(sort "$argpath"/version | tr '/' '\n' | grep "^v[0-9]" | head -1 | sed 's/^v//g')
 557  		elif [ "$(sort "$argpath"/version | wc -w | sed 's/ //g')" = 1 ]; then
 558  			APPVERSION=$(sort "$argpath"/version | head -1)
 559  		fi
 560  	fi
 561  	if [ -z "$APPVERSION" ]; then
 562  		if grep -q "http.*download/.*[0-9].*/" "$argpath"/version; then
 563  			APPVERSION=$(sort "$argpath"/version | tr '/-' '\n' | grep "[0-9]" | _check_version_filters | tail -1)
 564  		fi
 565  	fi
 566  }
 567  
 568  _check_version_if_library() {
 569  	LIBNAME=$(sort "$argpath"/remove | tr ' ' '\n' | grep "usr/local/lib" | head -1 | sed 's:.*/::')
 570  	APPVERSION=$(find /usr/local/lib -type f -name "$LIBNAME" -type f | sed 's:.*.so.::' | tail -1)
 571  }
 572  
 573  _check_version_if_binary_in_place() {
 574  	APPVERSION=$(date -r "$argpath"/"$arg" "+%Y.%m.%d")
 575  }
 576  
 577  _check_version() {
 578  	rm -f "$AMCACHEDIR"/version-args
 579  	_determine_args
 580  	for arg in $ARGS; do
 581  		argpath=$(echo "$ARGPATHS" | grep "/$arg$")
 582  		if [ -f "$argpath"/remove ]; then
 583  			if [ -f "$argpath"/version ]; then
 584  				_check_version_if_version_file_exists
 585  			elif [ "$arg" = "$AMCLI" ]; then
 586  				APPVERSION="$AMVERSION"
 587  			elif echo "$arg" | grep -q "ffwa-"; then
 588  				APPVERSION="WebApp"
 589  			elif grep -q "usr/local/lib" "$argpath"/remove 2>/dev/null; then
 590  				_check_version_if_library
 591  			elif [ -f "$argpath"/updater ] || grep -qi "version=" "$argpath"/*; then
 592  				_check_version_if_any_version_reference_is_somewhere
 593  			else
 594  				APPVERSION="unknown"
 595  			fi
 596  			if [ -z "$APPVERSION" ]; then
 597  				[ -f "$argpath"/"$arg" ] && _check_version_if_binary_in_place || APPVERSION="unknown"
 598  			fi
 599  			echo " β—† $arg	|	$APPVERSION" >> "$AMCACHEDIR"/version-args
 600  		fi
 601  	done
 602  }
 603  
 604  _check_version_for_auto_updatable_apps() {
 605  	_determine_args
 606  	for arg in $ARGS; do
 607  		argpath=$(echo "$ARGPATHS" | grep "/$arg$")
 608  		if [ -f "$argpath"/updater ]; then
 609  			_check_version_if_any_version_reference_is_somewhere
 610  			if [ "$AMCLI" = am ] && [ -d "$CACHEDIR"/am ] && grep -q " β—† $arg	|" "$CACHEDIR"/am/version-args; then
 611  				OLDAPPVERSION=$(grep " β—† $arg	|" "$CACHEDIR"/am/version-args | awk 'END {print $NF}')
 612  				sed -i "/ β—† $arg	|/s#$OLDAPPVERSION#$APPVERSION#" "$CACHEDIR"/am/*args*
 613  			fi
 614  			if [ -d "$CACHEDIR"/appman ] && grep -q " β—† $arg	|" "$CACHEDIR"/appman/version-args; then
 615  				OLDAPPVERSION=$(grep " β—† $arg	|" "$CACHEDIR"/appman/version-args | awk 'END {print $NF}')
 616  				sed -i "/ β—† $arg	|/s#$OLDAPPVERSION#$APPVERSION#" "$CACHEDIR"/appman/*args*
 617  			fi
 618  		fi
 619  	done
 620  }
 621  
 622  if [ -f "$AMCACHEDIR"/version-args ]; then
 623  	_check_version_for_auto_updatable_apps 2>/dev/null
 624  fi
 625  
 626  # This function removes all info and versions from the register
 627  _remove_info_files() {
 628  	rm -f "$AMCACHEDIR"/files*
 629  	rm -f "$AMCACHEDIR"/version-args
 630  }
 631  
 632  ################################################################################
 633  #				APIKEY
 634  ################################################################################
 635  
 636  ghapikey_file="$AMDATADIR/ghapikey.txt"
 637  # Set header authorization if GitHub API key file exists
 638  [ -f "$ghapikey_file" ] && HeaderAuthWithGITPAT=" --header \"Authorization: token $(<"$ghapikey_file")\" "
 639  
 640  _use_apikey() {
 641  	case $2 in
 642  	'del'|'delete'|'remove')
 643  		[ -f "$ghapikey_file" ] || { echo " βœ– No file named $ghapikey_file has been found"; exit 1; }
 644  		rm -f "$ghapikey_file" && echo " βœ” $ghapikey_file has been removed"
 645  		exit 0
 646  	esac
 647  	if [[ "$2" =~ ^(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})$ ]]; then
 648  		test_apikey_output_with_wget=$(curl -Ls --header "Authorization: token $2" 'https://api.github.com/repos/ivan-hc/AM/releases' | head -1)
 649  		[ -n "$test_apikey_output_with_wget" ] && echo "$2" > "$ghapikey_file" \
 650  			&& echo "Validation successful!" || echo "ERROR: This is not a valid key!"
 651  	else
 652  		echo "ERROR: Wrong expression, validation failed!"
 653  	fi
 654  }
 655  
 656  _update_github_api_key_in_the_updater_files() {
 657  	if [ -f "$ghapikey_file" ]; then
 658  		ghapikey=$(<"$ghapikey_file")
 659  		updater_files=("$APPSPATH"/*/AM-updater) # Assuming AM-updater is one level deeper
 660  		for f in "${updater_files[@]}"; do
 661  			if [ -f "$f" ] && grep -q "https://api.github.com" "$f"; then
 662  				# Check if the file already contains a valid API key
 663  				if ! grep -qE "(gh[ps]_[a-zA-Z0-9]{36}|github_pat_[a-zA-Z0-9]{22}_[a-zA-Z0-9]{59})" "$f"; then
 664  					# Insert HeaderAuthWithGITPAT before the GitHub API URL
 665  					sed -i "s#https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" "$f"
 666  				else
 667  					# Replace existing API key with the one from ghapikey.txt
 668  					sed -i "s#\(gh[ps]_[a-zA-Z0-9]\{36\}\|github_pat_[a-zA-Z0-9]\{22\}_[a-zA-Z0-9]\{59\}\)#$ghapikey#g" "$f"
 669  				fi
 670  			fi
 671  		done
 672      	fi
 673  }
 674  
 675  ################################################################################
 676  #				APPMAN MODE
 677  ################################################################################
 678  
 679  APPMAN_MSG="$DIVIDING_LINE\n \"AM\" is running as \"AppMan\", use ${Green}am --system\033[0m to switch it back to \"AM\"\n$DIVIDING_LINE\n"
 680  APPMAN_MSG_OFF="$DIVIDING_LINE\n \"AppMan Mode\" disabled! \n$DIVIDING_LINE\n"
 681  APPMAN_MSG_THINK="$DIVIDING_LINE\nNOTE: You can also choose to simply use \"--user\" as a flag to install apps locally \
 682  (options \"-i\", \"-ia\" and \"-e\") instead of going fully into \"AppMan Mode\". \"AM\" can  handle local applications as well.\n$DIVIDING_LINE\n"
 683  
 684  _use_appman() {
 685  	_online_check
 686  	[ "$CLI" = appman ] && echo " This function only works for AM" && exit 0
 687  	printf "%b" "$APPMAN_MSG_THINK" | _fit
 688  	read -r -p " Do you wish to enter \"AppMan Mode\" (y,N)?" yn
 689  	if ! echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
 690  		echo "$DIVIDING_LINE"
 691  	else
 692  		[ ! -f "$APPMANCONFIG"/appman-mode ] && mkdir -p "$APPMANCONFIG" && touch "$APPMANCONFIG"/appman-mode
 693  		_appman && printf "%b" "$APPMAN_MSG"
 694  	fi
 695  }
 696  
 697  if [ "$AMCLI" = am ]; then
 698  	if [ -f "$APPMANCONFIG"/appman-mode ]; then
 699  		[ ! -f "$APPMANCONFIG"/appman-config ] && printf "%b" "$APPMAN_MSG"
 700  		_appman
 701  		AMCLIPATH="$(realpath "$0")"
 702  	elif [ ! -w "$AMPATH" ]; then
 703  		read -r -p " \"AM\" is read-only, want to use it in \"AppMan Mode\" (Y,n)? " yn
 704  		if echo "$yn" | grep -i '^n' >/dev/null 2>&1; then
 705  			exit 0
 706  		else
 707  			echo "$DIVIDING_LINE"; echo "\"AppMan Mode\" enabled!"; echo "$DIVIDING_LINE"
 708  			_use_appman 1>/dev/null
 709  		fi
 710  	fi
 711  fi
 712  
 713  ################################################################################
 714  #				CLEAN
 715  ################################################################################
 716  
 717  _clean_amcachedir_message() {
 718  	_clean_amcachedir
 719  	[ "$AMCLI" = am ] && [ -d "$CACHEDIR"/am ] && echo " βœ” Clear the contents of $CACHEDIR/am"
 720  	[ -d "$CACHEDIR"/appman ] && echo " βœ” Clear the contents of $CACHEDIR/appman"
 721  }
 722  
 723  _clean_all_home_cache_directories_of_appimages() {
 724  	for arg in $ARGPATHS; do
 725  		if test -d "$arg"/*.home/.cache; then
 726  			rm -Rf "$arg"/*/*.home/.cache/* && echo " βœ” Clear the contents of $arg/*.home/.cache"
 727  		fi
 728  	done
 729  }
 730  
 731  _clean_all_tmp_directories_from_appspath() {
 732  	_determine_args
 733  	for arg in $ARGPATHS; do
 734  		if [ -d "$arg"/tmp ]; then
 735  			rm -Rf "$arg"/tmp && echo " βœ” Removed $arg/tmp"
 736  		fi
 737  	done
 738  }
 739  
 740  _clean_launchers() {
 741  	if [ -d "$DATADIR"/applications/AppImages ]; then
 742  		rm -f "$AMCACHEDIR"/mountpoints
 743  		for var in "$DATADIR"/applications/AppImages/*.desktop; do
 744  			# full path to appimage
 745  			appimagename=$(awk -F'=| ' '/Exec=/{print $2; exit}' "$var" | sed 's/"//g; s/\s.*$//')
 746  			# name of the appimage
 747  			launcher2del=$(basename -- "$(echo "$appimagename" | tr '[:upper:]' '[:lower:]')")
 748  			# removable mount point where the appimage may be stored
 749  			mountpoint=$(echo "$appimagename" | cut -d'/' -f1-4)
 750  			if [ ! -f "$appimagename" ]; then
 751  				if echo "$appimagename" | grep -q "^/media/\|^/mnt/"; then
 752  					mountpoint=$(echo "$appimagename" | cut -d'/' -f1-4)
 753  					unmounted_point=$(echo "$mountpoint" | cut -d'/' -f1-2)
 754  				elif echo "$appimagename" | grep -q "^/run/media/"; then
 755  					mountpoint=$(echo "$appimagename" | cut -d'/' -f1-5)
 756  					unmounted_point="/run/media"
 757  				else
 758  					mountpoint=""
 759  				fi
 760  				if [ -n "$mountpoint" ] && [ ! -d "$mountpoint" ]; then
 761  					echo "$mountpoint" >> "$AMCACHEDIR"/mountpoints
 762  					echo " βœ– ERROR: cannot remove \"$(basename "$var")\""
 763  					echo "   related AppImage is located in an unmounted path of $unmounted_point"
 764  				else
 765  					rm -f "$var"
 766  					[ -n "$BINDIR" ] && [ -n "$launcher2del" ] && rm -f "$BINDIR"/"$launcher2del"*
 767  				fi
 768  			fi
 769  		done
 770  		if [ -f "$AMCACHEDIR"/mountpoints ]; then
 771  			mountpoints=$(sort "$AMCACHEDIR"/mountpoints)
 772  			for m in $mountpoints; do
 773  				[ ! -d "$m" ] && mountpoint_enabled=1
 774  			done
 775  		fi
 776  		[ -z "$mountpoint_enabled" ] && [ -n "$BINDIR" ] && cd "$BINDIR" && find . -xtype l -delete
 777  		rm -f "$AMCACHEDIR"/mountpoints
 778  		echo ' βœ” Removed orphaned launchers produced with the "--launcher" option'
 779  		rmdir "$DATADIR"/applications/AppImages
 780  	else
 781  		[ -n "$BINDIR" ] && cd "$BINDIR" && find . -xtype l -delete
 782  	fi
 783  }
 784  
 785  _clean_old_modules() {
 786  	MODULES=$(sort "$(realpath "$0")" | tr '"' '\n' | grep "[a-z]\.am$" | uniq)
 787  	[ -z "$MODULES_PATH" ] && exit 1
 788  	for m in "$MODULES_PATH"/*; do
 789  		if [[ "${MODULES}" != *"$(basename -- "$m")"* ]];then
 790  			rm -f "$m" 2>/dev/null
 791  			echo " βœ” Removed obsolete module named \"$(basename -- "$m")\""
 792  		fi
 793  	done
 794  }
 795  
 796  _use_clean() {
 797  	echo " Cleaning temporary files and folders..." && sleep 0.1
 798  	i=100 && while [ "$i" -ge 0 ]; do
 799  		printf " %03d\r" "$i" && sleep 0.0001 && i=$((i - 1))
 800  	done
 801  	_detect_appman_apps
 802  	_determine_args
 803  	_clean_amcachedir_message
 804  	_clean_all_home_cache_directories_of_appimages
 805  	_clean_all_tmp_directories_from_appspath
 806  	_clean_launchers 2>/dev/null
 807  	_clean_old_modules
 808  }
 809  
 810  ################################################################################
 811  #				SYNC
 812  ################################################################################
 813  
 814  _sync_installation_scripts() {
 815  	printf "%b\n Checking for changes of the installation scripts in the online database...\n" "$DIVIDING_LINE"
 816  	_determine_args
 817  	for arg in $ARGS; do
 818  		argpath=$(echo "$ARGPATHS" | grep "/$arg$")
 819  		if [ -f "$argpath"/AM-updater ]; then
 820  			mkdir -p "$argpath"/.am-installer
 821  			scriptname=$(ls "$argpath/.am-installer/" | head -1)
 822  			if [ -n "$scriptname" ]; then
 823  				CURRENT=$(cat "$argpath"/.am-installer/"$scriptname")
 824  				SOURCE=$(curl -Ls "$APPSDB"/"$scriptname")
 825  				if [ "$CURRENT" = "$SOURCE" ]; then
 826  					echo -ne "\r" 2>/dev/null
 827  				else
 828  					printf " β—† Changed https://github.com/ivan-hc/AM/blob/main/programs/%b/%b\n" "$ARCH" "$scriptname"
 829  				fi
 830  			else
 831  				if curl --output /dev/null --silent --head --fail "$APPSDB"/"$arg"  1>/dev/null; then
 832  					printf " β—† No installation script for %b, downloading one...\n" "$arg"
 833  					mkdir -p "$argpath"/.am-installer
 834  					wget -q "$APPSDB/$arg" -O "$argpath"/.am-installer/"$arg"
 835  				fi
 836  			fi
 837  		fi
 838  	done
 839  }
 840  
 841  _sync_appimages_list() {
 842  	APPIMAGES_LIST="${APPIMAGES_LIST:-$AMREPO/programs/$ARCH-appimages}"
 843  	curl -Ls "$APPIMAGES_LIST" > "$AMDATADIR/$ARCH-appimages"
 844  }
 845  
 846  _sync_databases() {
 847  	printf "%b\n Check and update offline lists of additional databases...\n" "$DIVIDING_LINE"
 848  	_sync_appimages_list
 849  	_sync_third_party_lists 2>/dev/null
 850  	_completion_lists
 851  }
 852  
 853  _sync_modules() {
 854  	printf "%b\n Check for updates in modules...\n" "$DIVIDING_LINE"
 855  	MODULES=$(curl -Ls "$AMREPO/APP-MANAGER" | tr '"' '\n' | grep "[a-z]\.am$")
 856  	for module_name in $MODULES; do
 857  		cd "$MODULES_PATH" || return 1
 858  		if ! test -f ./"$module_name"; then
 859  			echo " β—† Downloading $module_name (not previously installed)..."
 860  			curl -Os "$MODULES_SOURCE/$module_name" 2>/dev/null
 861  			chmod a+x ./"$MODULENAME"
 862  		fi
 863  		CURRENT=$(cat ./"$module_name" 2>/dev/null)
 864  		SOURCE=$(curl -Ls "$MODULES_SOURCE/$module_name")
 865  		if [ "$CURRENT" = "$SOURCE" ]; then
 866  			echo -ne "\r" 2>/dev/null
 867  		else
 868  			echo " β—† Updating $module_name..."
 869  			curl -Ls "$MODULES_SOURCE/$module_name" > ./"$module_name" 2>/dev/null
 870  		fi
 871  	done
 872  	_clean_old_modules
 873  }
 874  
 875  _sync_amcli() {
 876  	echo "$DIVIDING_LINE"
 877  	CURRENT_AM_VERSION="$AMVERSION"
 878  	echo -ne "\n β—† SYNCHRONIZING \"$AMCLIUPPER\" VERSION \"$CURRENT_AM_VERSION\"...\r" && sleep 0.25
 879  	_clean_amcachedir 1>/dev/null
 880  	cd "$AMCACHEDIR" || return 1
 881  	curl -Ls "$AMREPO"/APP-MANAGER > ./APP-MANAGER && chmod a+x ./APP-MANAGER
 882  	echo y | mv ./APP-MANAGER "$(realpath "$0")"
 883  	NEW_AM_VERSION=$("$AMCLIPATH" -v)
 884  	if [ ! "$CURRENT_AM_VERSION" = "$NEW_AM_VERSION" ]; then
 885  		echo -ne " A new release of \"$AMCLIUPPER\" is available, please wait...\r"
 886  		echo " β—† \"$AMCLIUPPER\" IS NOW UPDATED TO THE BRAND NEW \"$NEW_AM_VERSION\" VERSION!"
 887  		printf "\n  Replacement of version \"%b\" currently in use, COMPLETED! \n" "$CURRENT_AM_VERSION"
 888  		printf "\n See https://github.com/ivan-hc/AM/commits/main\n\n"
 889  	else
 890  		echo " β—† \"$AMCLIUPPER\" IS ALREADY UPDATED, CURRENT VERSION \"$CURRENT_AM_VERSION\""
 891  		printf "\n See https://github.com/ivan-hc/AM/commits/%b\n\n" "$AMBRANCH"
 892  	fi
 893  }
 894  
 895  _use_sync() {
 896  	_online_check
 897  	_betatester_message_on
 898  	_sync_installation_scripts
 899  	_sync_databases
 900  	if [ "$(realpath "$0")" != "/usr/bin/am" ] && [ "$AMSYNC" != 1 ]; then
 901  		_sync_modules
 902  		_sync_amcli
 903  	fi
 904  	echo "$DIVIDING_LINE"
 905  }
 906  
 907  ################################################################################
 908  #				UPDATE
 909  ################################################################################
 910  
 911  _update_updatable_apps_msg_head() {
 912  	printf " \"%b\" CAN MANAGE UPDATES FOR THE FOLLOWING PROGRAMS:\n%b\n\n" "$AMCLIUPPER" "$DIVIDING_LINE"
 913  	[ -f "$AMCACHEDIR/updatable-args-list" ] && grep "β—†" "$AMCACHEDIR/updatable-args-list" | sort || echo " None"
 914  	printf "\n All self-updatable programs are excluded\n"
 915  	echo "$DIVIDING_LINE"
 916  }
 917  
 918  _update_list_updatable_apps() {
 919  	_determine_args
 920  	_check_version
 921  	for arg in $ARGS; do
 922  		argpath=$(echo "$ARGPATHS" | grep "/$arg$")
 923  		if [ -d "$argpath" ]; then
 924  			if [ -f "$argpath/AM-updater" ]; then
 925  			 	app_version=$(grep -w " β—† $arg	|" "$AMCACHEDIR/version-args" | sed 's:.*|	::')
 926  				echo " β—† $arg $app_version" >> "$AMCACHEDIR"/updatable-args-list
 927  			fi
 928  		fi
 929  	done
 930  }
 931  
 932  _update_determine_apps_version_changes() {
 933  	[ -z "$debug_update" ] && echo "$DIVIDING_LINE"
 934  	if [ -f "$AMCACHEDIR"/updatable-args-list ]; then
 935  		mv "$AMCACHEDIR"/updatable-args-list "$AMCACHEDIR"/updatable-args-list-old
 936  		_update_list_updatable_apps
 937  		OLDVER="$AMCACHEDIR/updatable-args-list-old"
 938  		NEWVER="$AMCACHEDIR/updatable-args-list"
 939  		if cmp --silent -- "$NEWVER" "$OLDVER"; then
 940  			echo ' Nothing to do here!'
 941  		else
 942  			printf " The following apps have been updated:\n\n"
 943  			diff "$OLDVER" "$NEWVER" | grep "^>" | sed 's/^> //g'
 944  			echo ""
 945  		fi
 946  	else
 947  		echo ' No apps to update here!'
 948  	fi
 949  }
 950  
 951  _update_run_updater() {
 952  	if grep -q "api.github.com" "$argpath"/AM-updater; then
 953  		GH_API_ALLOWED=$(curl -Ls $HeaderAuthWithGITPAT https://api.github.com/repos/ivan-hc/AM/releases/latest | sed 's/[()",{} ]/\n/g' | grep "^ivan-hc" | head -1)
 954  		if [ -z "$GH_API_ALLOWED" ]; then
 955  			if command -v torsocks 1>/dev/null; then
 956  				if [ -z "$debug_update" ]; then
 957  					torsocks "$argpath"/AM-updater >/dev/null 2>&1
 958  				else
 959  					torsocks "$argpath"/AM-updater
 960  				fi
 961  			else
 962  				echo " βœ– $APPNAME cannot be updated, you have reached GitHub API limit. Install \"torsocks\" from your system package manager and retry!" \
 963  				| fold -sw 72 | sed 's/^/   /g; s/   βœ–/βœ–/g'
 964  			fi
 965  		else
 966  			if [ -z "$debug_update" ]; then
 967  				"$argpath"/AM-updater >/dev/null 2>&1
 968  			else
 969  				"$argpath"/AM-updater
 970  			fi
 971  		fi
 972  	else
 973  		if [ -z "$debug_update" ]; then
 974  			"$argpath"/AM-updater >/dev/null 2>&1
 975  		else
 976  			"$argpath"/AM-updater
 977  		fi
 978  	fi
 979  	end=$(date +%s)
 980  	echo " β—† $APPNAME is updated, $((end - start)) seconds elapsed!"
 981  	[ -n "$debug_update" ] && echo "$DIVIDING_LINE"
 982  }
 983  
 984  _update_app() {
 985  	APPNAME=$(echo "$arg" | tr '[:lower:]' '[:upper:]')
 986  	start=$(date +%s)
 987  	if [ -w "$argpath"/AM-updater ]; then
 988  		_update_run_updater &
 989  	else
 990  		echo " βœ– $APPNAME is read-only, cannot update it!"
 991  	fi
 992  }
 993  
 994  _update_all_apps() {
 995  	for arg in $ARGS; do
 996  		argpath=$(echo "$ARGPATHS" | grep "/$arg$")
 997  		cd "$argpath" || exit 1
 998  		arg=$(printf '%s\n' "${PWD##*/}")
 999  		if [ -f "$argpath"/AM-updater ]; then
1000  			_update_app
1001  		fi
1002  	done
1003  	wait
1004  	_update_determine_apps_version_changes
1005  	rm -Rf "$APPSPATH"/*/tmp
1006  	[ -d "$APPMAN_APPSPATH" ] && rm -Rf "$APPMAN_APPSPATH"/*/tmp
1007  }
1008  
1009  _update_launchers_not_found_msg() {
1010  	MISSING_LAUNCHERS_MSG=" No launcher found."
1011  	printf "%b\n%b\n%b\n" "$DIVIDING_LINE" "$MISSING_LAUNCHERS_MSG" "$DIVIDING_LINE"
1012  }
1013  
1014  _update_launchers() {
1015  	_clean_launchers 2>/dev/null 1>/dev/null
1016  	MISSING_LAUNCHERS_MSG="No launcher found, use option \"--launcher\" to create them."
1017  	[ ! -d "$DATADIR"/applications/AppImages ] && _update_launchers_not_found_msg && exit 0
1018  	[ -d "$DATADIR"/applications/AppImages ] && [ -z "$( ls -A "$DATADIR"/applications/AppImages )" ] && _update_launchers_not_found_msg && exit 0
1019  	if ! command -v appimageupdatetool 1>/dev/null; then
1020  		update_launchers_error_message=" πŸ’€ ERROR! Missing command \"${RED}appimageupdatetool\033[0m\", install it and retry!"
1021  		printf "%b\n%b\n%b\n" "$DIVIDING_LINE" "$update_launchers_error_message" "$DIVIDING_LINE"
1022  	else
1023  		echo " β—† Update local AppImages integrated manually"
1024  		for var in "$DATADIR"/applications/AppImages/*.desktop; do
1025  			appimage_full_path=$(awk -F'=| ' '/Exec=/{print $2; exit}' "$var" | sed 's/"//g; s/\s.*$//')
1026  			appimagename=$(basename -- "$appimage_full_path")
1027  			appimage_path=$(echo "$appimage_full_path" | sed -E 's|/[^/]+$|/|; s/\/*$//g')
1028  			printf "%b\n File: %b%b\033[0m\n Path: %b" "$DIVIDING_LINE" "${Green}" "$appimagename" "$appimage_path"
1029  			if [ ! -f "$appimage_full_path" ]; then
1030  				echo "(unmounted)" | _fit
1031  			else
1032  				printf "\n\n"
1033  				appimageupdatetool -Or "$appimage_full_path"
1034  			fi
1035  		done
1036  	fi
1037  }
1038  
1039  _use_update() {
1040  	_online_check
1041  	_update_github_api_key_in_the_updater_files
1042  	_clean_all_tmp_directories_from_appspath >/dev/null
1043  
1044  	ENTRIES="$(echo "$@" | cut -f2- -d ' ' | tr ' ' '\n' | grep -v -- "^-\|^$1$")"
1045  	FLAGS=$(echo "$@" | tr ' ' '\n' | grep -- "--" | tr '\n ' ' ')
1046  	if echo "$FLAGS" | grep -q -- "--debug"; then
1047  		debug_update="1"
1048  	fi
1049  	if [ -z "$ENTRIES" ]; then
1050  		_clean_amcachedir
1051  		_update_list_updatable_apps
1052  		printf "%b\n >> START OF ALL PROCESSES << \n%b\n" "$DIVIDING_LINE" "$DIVIDING_LINE"
1053  		if echo "$FLAGS" | grep -q -- "--apps"; then
1054  			_update_updatable_apps_msg_head
1055  			_update_all_apps
1056  		elif echo "$FLAGS" | grep -q -- "--launcher"; then
1057  			_update_launchers
1058  		else
1059  			_update_updatable_apps_msg_head
1060  			_update_all_apps
1061  			_use_sync
1062  			printf " >> END OF ALL PROCESSES << \n%b\n" "$DIVIDING_LINE"
1063  			sleep 0.2
1064  			exit 0
1065  		fi
1066  		printf "%b\n >> END OF ALL PROCESSES << \n%b\n" "$DIVIDING_LINE" "$DIVIDING_LINE"
1067  		sleep 0.2
1068  		exit 0
1069  	else
1070  		[ -n "$debug_update" ] && echo "$DIVIDING_LINE"
1071  		_determine_args
1072  		for arg in $ENTRIES; do
1073  			argpath=$(echo "$ARGPATHS" | grep "/$arg$")
1074  			if [ -f "$argpath"/AM-updater ]; then
1075  				cd "$argpath" 2>/dev/null || exit 1
1076  				_update_app
1077  			else
1078  				UPDATERS=$(cd "$argpath" 2>/dev/null && find . -name "*update*" -print 2>/dev/null)
1079  				[ -n "$UPDATERS" ] && arg_autoupdatable=", it may have its update system"
1080  				echo " βœ– Cannot manage updates for \"$(echo "$arg" | tr '[:lower:]' '[:upper:]')\"$arg_autoupdatable"
1081  			fi
1082  		done
1083  		wait
1084  		exit 0
1085  	fi
1086  }
1087  
1088  _use_force_latest() {
1089    	_online_check
1090    	_determine_args
1091  	ENTRIES="$(echo "$@" | cut -f2- -d ' ')"
1092    	for arg in $ENTRIES; do
1093  	  	argpath=$(echo "$ARGPATHS" | grep "/$arg$")
1094  	  	if [ ! -d "$argpath" ]; then
1095  			echo " ERROR: \"$arg\" is not installed, see \"-f\""
1096  		elif [ ! -f "$argpath"/AM-updater ]; then
1097  			echo " ERROR: \"$AMCLI\" cannot manage updates for \"$arg\""
1098  		elif ! grep -q "api.github.com" "$argpath"/AM-updater; then
1099  			echo " ERROR: \"$arg\" source is not on Github"
1100  		elif ! grep -q "/releases | " "$argpath"/AM-updater; then
1101  			echo " ERROR: \"$arg\" does not redirect to a generic \"releases\""
1102  		else
1103  			sed -i 's#/releases | #/releases/latest | #g' "$argpath"/AM-updater
1104  			APPNAME=$(echo "$arg" | tr '[:lower:]' '[:upper:]')
1105  			start=$(date +%s)
1106  			_update_run_updater
1107  		fi
1108  	done
1109  }
1110  
1111  ################################################################################
1112  #				USAGE
1113  ################################################################################
1114  
1115  # HANDLE ALL THE EXTERNAL MODULES
1116  _use_module() {
1117  	# Test if module exists
1118  	if [ ! -f "$MODULES_PATH/$MODULE" ]; then
1119  		_online_check
1120  		if ! wget -q "$MODULES_SOURCE/$MODULE" -O "$MODULES_PATH/$MODULE"; then
1121  			echo " Module not found, run \"$AMCLI -s\" to update \"$AMCLIUPPER\""
1122  			exit 1
1123  		fi
1124  		chmod a+x "$MODULES_PATH/$MODULE"
1125  	fi
1126  	# Source module
1127  	source "$MODULES_PATH/$MODULE" "$@"
1128  }
1129  
1130  case "$1" in
1131  	'')
1132  		echo " USAGE: $AMCLI [OPTION]"
1133  		echo "        $AMCLI [OPTION] [ARGUMENT]"
1134  		echo ""
1135  		echo " Run the \"$AMCLI -h\" command to find out more"
1136  		exit 0
1137  		;;
1138  	'about'|'-a'|\
1139  	'files'|'-f'|'-fi'|\
1140  	'list'|'-l'|\
1141  	'query'|'-q')
1142  		MODULE="database.am"
1143  		if [ -t 1 ]; then _use_module "$@"; else _use_module "$@" | sed -e 's/\x1b\[[0-9;]*m//g'; fi
1144  		;;
1145  	'backup'|'-b'|\
1146  	'downgrade'|'--rollback'|\
1147  	'icons'|'--icons'|\
1148  	'launcher'|'--launcher'|\
1149  	'lock'|'unlock'|\
1150  	'nolibfuse'|\
1151  	'overwrite'|'-o'|\
1152  	'remove'|'-R'|'-r')
1153  		MODULE="management.am"
1154  		_use_module "$@"
1155  		;;
1156  	'config'|'-C'|'--config'|\
1157  	'home'|'-H'|'--home'|\
1158  	'sandbox'|'--sandbox'|\
1159  	'--disable-sandbox')
1160  		MODULE="sandboxes.am"
1161  		_use_module "$@"
1162  		;;
1163  	'download'|'-d'|\
1164  	'extra'|'-e'|\
1165  	'install'|'-i'|'-ias'|\
1166  	'install-appimage'|'-ia')
1167  		MODULE="install.am"
1168  		_online_check
1169  		[ "$CLI" = am ] && [ -f "$APPMANCONFIG"/appman-mode ] && printf "%b" "$APPMAN_MSG"
1170  		_use_module "$@"
1171  		;;
1172  	'template'|'-t')
1173  		MODULE="template.am"
1174  		_online_check
1175  		_use_module "$@"
1176  		;;
1177  	# INBUILT OPTIONS
1178  	'--devmode-disable'|'--devmode-enable')
1179  		[ "$1" = "--devmode-disable" ] && rm -f "$AMDATADIR"/betatester \
1180  		|| touch "$AMDATADIR"/betatester && _betatester_message_on
1181  		;;
1182  	'--force-latest')
1183  		_use_force_latest "$@"
1184  		;;
1185  	'--system')
1186  		[ -f "$APPMANCONFIG"/appman-mode ] && rm -f "$APPMANCONFIG"/appman-mode && printf "%b" "$APPMAN_MSG_OFF"
1187  		;;
1188  	'apikey')
1189  		_use_apikey "$@"
1190  		;;
1191  	'appman'|'--user')
1192  		_use_appman
1193  		;;
1194  	'clean'|'-c')
1195  		_use_clean
1196  		;;
1197  	'newrepo'|'neodb')
1198  		_use_newrepo "$@"
1199  		;;
1200  	'sync'|'-s')
1201  		_use_sync
1202  		;;
1203  	'update'|'-u'|'-U')
1204  		_use_update "$@"
1205  		;;
1206  	'version'|'-v'|'--version')
1207  		echo "$AMVERSION"
1208  		;;
1209  	'--disable-notifications')
1210  		_determine_args
1211  		for n in $ARGPATHS; do sed -e '/notify-send/ s/^#*/#/' -i "$n/AM-updater" 2>/dev/null; done
1212  		;;
1213  	'--enable-notifications')
1214  		_determine_args
1215  		for n in $ARGPATHS; do sed -e '/notify-send/ s/^#*//' -i "$n/AM-updater" 2>/dev/null; done
1216  		;;
1217  	'help'|'-h')
1218  		################################################################################
1219  		#				HELP
1220  		################################################################################
1221  
1222  		_use_help() {
1223  			[ "$CLI" = am ] && [ -f "$APPMANCONFIG"/appman-mode ] && printf "%b" "$APPMAN_MSG"
1224  			echo -e "
1225  			NAME: ${Green}$AMCLIUPPER\033[0m		VERSION: ${Green}$AMVERSION\033[0m
1226  
1227  			SYNOPSIS:	${LightBlue}$AMCLI {OPTION}\033[0m
1228  					${LightBlue}$AMCLI {OPTION} {PROGRAM}\033[0m
1229  
1230  			DESCRIPTION: A command line utility to install and manage AppImages and other portable programs for GNU/Linux thanks to its AUR-inspired database.
1231  
1232  			OPTIONS:
1233  
1234  			${Gold}about, -a\033[0m
1235  
1236  					${LightBlue}$AMCLI -a {PROGRAM}\033[0m
1237  
1238  			Description: Shows more info about one or more apps.
1239  
1240  			${Gold}apikey\033[0m
1241  
1242  					${LightBlue}$AMCLI apikey {Github Token}
1243  					${LightBlue}$AMCLI apikey delete\033[0m
1244  
1245  			Description: Accede to github APIs using your personal access tokens. The file named \"ghapikey.txt\" will be saved in $AMDATADIR. Use \"del\" to remove it.
1246  
1247  			${Gold}backup, -b\033[0m
1248  
1249  					${LightBlue}$AMCLI -b {PROGRAM}\033[0m
1250  
1251  			Description: Create a snapshot of the current version of an installed program.
1252  
1253  			${Gold}clean, -c\033[0m
1254  
1255  					${LightBlue}$AMCLI -c\033[0m
1256  
1257  			Description: Removes all the unnecessary files and folders.
1258  
1259  			${Gold}config, -C, --config\033[0m
1260  
1261  					${LightBlue}$AMCLI -C {PROGRAM}\033[0m
1262  
1263  			Description: Set a dedicated \$XDD_CONFIG_HOME for one or more AppImages.
1264  
1265  			${Gold}downgrade, --rollback\033[0m
1266  
1267  					${LightBlue}$AMCLI --rollback {PROGRAM}\033[0m
1268  
1269  			Description: Download an older or specific app version.
1270  
1271  			${Gold}download, -d\033[0m
1272  
1273  					${LightBlue}$AMCLI -d {PROGRAM}
1274  					${LightBlue}$AMCLI -d --convert {PROGRAM}\033[0m
1275  
1276  			Description: Download one or more installation scripts to your desktop or convert them to local installers for \"AppMan\". To test the scripts, use the \"${LightBlue}$AMCLI -i '/path/to/script'\033[0m\" command or enter the directory of the script and run the \"${LightBlue}$AMCLI -i ./script\033[0m\" command, even using dedicated flags, if necessary (see \"-i\").
1277  
1278  			${Gold}extra, -e\033[0m
1279  
1280  					${LightBlue}$AMCLI -e user/project {APPNAME}
1281  					${LightBlue}$AMCLI -e user/project {APPNAME} {KEYWORD}\033[0m
1282  
1283  			Description: Install AppImages from github.com, outside the database. This allows you to install, update and manage them all like the others. Where \"user/project\" can be the whole URL to the github repository, give a name to the program so that it can be used from the command line. Optionally, add an \"univoque\" keyword if multiple AppImages are listed.
1284  
1285  			${Gold}files, -f, -fi\033[0m
1286  
1287  					${LightBlue}$AMCLI -f
1288  					${LightBlue}$AMCLI -f --byname
1289  					${LightBlue}$AMCLI -f --less\033[0m
1290  
1291  			Description: Shows the list of all installed programs, with sizes. By default apps are sorted by size, use \"--byname\" to sort by name. With the option \"--less\" it shows only the number of installed apps. Option \"-fi\" only shows installed apps, not the AppImages integrated with the \"--launcher\" option.
1292  
1293  			${Gold}help, -h\033[0m
1294  
1295  					${LightBlue}$AMCLI -h\033[0m
1296  
1297  			Description: Prints this message.
1298  
1299  			${Gold}home, -H, --home\033[0m
1300  
1301  					${LightBlue}$AMCLI -H {PROGRAM}\033[0m
1302  
1303  			Description: Set a dedicated \$HOME directory for one or more AppImages.
1304  
1305  			${Gold}icons, --icons\033[0m
1306  
1307  					${LightBlue}$AMCLI --icons {PROGRAM}
1308  					${LightBlue}$AMCLI --icons --all\033[0m
1309  
1310  			Description: Allow installed apps to use system icon themes. You can specify the name of the apps to change or use the \"--all\" flag to change all of them at once. This will remove the icon path from the .desktop file and add the symbolic link of all available icons in the $DATADIR/icons/hicolor/scalable/apps directory. The \"--icons\" option can be used as \"flag\" in the \"-i\" and \"-ia\" options.
1311  
1312  			${Gold}install, -i\033[0m
1313  
1314  					${LightBlue}$AMCLI -i {PROGRAM}
1315  					${LightBlue}$AMCLI -i --debug {PROGRAM}
1316  					${LightBlue}$AMCLI -i --force-latest {PROGRAM}
1317  					${LightBlue}$AMCLI -i --icons {PROGRAM}
1318  					${LightBlue}$AMCLI -i --sandbox {PROGRAM}\033[0m
1319  
1320  			Description: Install one or more programs or libraries from the list. With the \"--debug\" option you can see log messages to debug the script. For more details on \"--force-latest\", see the dedicated option, below. Use the \"--icons\" flag to allow the program to use icon themes. It can also be extended with additional flags (see third-party flags, at the bottom of this message). The \"--sandbox\" flag allows you to set sandboxes for AppImage packages.
1321  
1322  			${Gold}install-appimage, -ia, -ias\033[0m
1323  
1324  					${LightBlue}$AMCLI -ia {PROGRAM}
1325  					${LightBlue}$AMCLI -ia --debug {PROGRAM}
1326  					${LightBlue}$AMCLI -ia --force-latest {PROGRAM}
1327  					${LightBlue}$AMCLI -ia --icons {PROGRAM}
1328  					${LightBlue}$AMCLI -ia --sandbox {PROGRAM}
1329  					${LightBlue}$AMCLI -ias {PROGRAM}\033[0m
1330  
1331  			Description: Same as \"install\" (see above) but for AppImages only. Option \"-ias\" (aka Install AppImage & Sandbox) is equivalent to \"-ia --sandbox\", to set sandboxes for AppImage packages.
1332  
1333  			${Gold}lock\033[0m
1334  
1335  					${LightBlue}$AMCLI lock {PROGRAM}\033[0m
1336  
1337  			Description: Prevent an application being updated, if it has an\"AM-updater\" script.
1338  
1339  			${Gold}list, -l\033[0m
1340  
1341  					${LightBlue}$AMCLI -l
1342  					${LightBlue}$AMCLI -l --all
1343  					${LightBlue}$AMCLI -l --appimages\033[0m
1344  
1345  			Description: Shows the list of all the apps available, or just the AppImages. It can also be extended with additional flags, the \"--all\" flag allows you to consult the set of all supported databases (see third-party flags, at the bottom of this message).
1346  
1347  			${Gold}newrepo, neodb\033[0m
1348  
1349  					${LightBlue}$AMCLI newrepo add {URL}\\{PATH}
1350  					${LightBlue}$AMCLI newrepo select
1351  					${LightBlue}$AMCLI newrepo on\\off
1352  					${LightBlue}$AMCLI newrepo purge
1353  					${LightBlue}$AMCLI newrepo info\033[0m
1354  
1355  			Description: Set a new default repo, use \"add\" to append the path to a local directory or an online URL, then use \"select\" to use it by default, a message will warn you about the usage of this repo instead of the default one. Use \"on\"/\"off\" to enable/disable it. Use \"purge\" to remove all 3rd party repos. Use \"info\" to see the source from where installation scripts and lists are taken.
1356  
1357  			${Gold}nolibfuse\033[0m
1358  
1359  					${LightBlue}$AMCLI nolibfuse {PROGRAM}\033[0m
1360  
1361  			Description: Convert old AppImages and get rid of \"libfuse2\" dependence.
1362  
1363  			${Gold}overwrite, -o\033[0m
1364  
1365  					${LightBlue}$AMCLI -o {PROGRAM}\033[0m
1366  
1367  			Description: Overwrite apps with snapshots saved previously (see \"-b\").
1368  
1369  			${Gold}query, -q\033[0m
1370  
1371  					${LightBlue}$AMCLI -q {KEYWORD}
1372  					${LightBlue}$AMCLI -q --all {KEYWORD}
1373  					${LightBlue}$AMCLI -q --appimages {KEYWORD}
1374  					${LightBlue}$AMCLI -q --pkg {PROGRAM1} {PROGRAM2}[0m
1375  
1376  			Description: Search for keywords in the list of available applications, add the \"--appimages\" option to list only the AppImages or add \"--pkg\" to list multiple programs at once. It can also be extended with additional flags, the \"--all\" flag allows you to consult the set of all supported databases (see third-party flags, at the bottom of this message).
1377  
1378  			${Gold}remove, -r\033[0m
1379  
1380  					${LightBlue}$AMCLI -r {PROGRAM}\033[0m
1381  
1382  			Description: Removes one or more apps, requires confirmation.
1383  
1384  			${Gold}-R\033[0m
1385  
1386  					${LightBlue}$AMCLI -R {PROGRAM}\033[0m
1387  
1388  			Description: Removes one or more apps without asking.
1389  
1390  			${Gold}sandbox, --sandbox\033[0m
1391  
1392  					${LightBlue}$AMCLI sandbox {PROGRAM}\033[0m
1393  
1394  			Description: Run an AppImage in a sandbox using Aisap.
1395  
1396  			NOTE, \"--sandbox\" can be used as a flag in \"-i\" and \"-ia\" or can be replaced using the option \"-ias\" (aka Install AppImage & Sandbox).
1397  
1398  			${Gold}sync, -s\033[0m
1399  
1400  					${LightBlue}$AMCLI -s\033[0m
1401  
1402  			Description: Updates this script to the latest version hosted.
1403  
1404  			${Gold}template, -t\033[0m
1405  
1406  					${LightBlue}$AMCLI -t {PROGRAM}\033[0m
1407  
1408  			Description: Generate a custom installation script. To test the scripts, use the \"${LightBlue}$AMCLI -i '/path/to/script'\033[0m\" command or enter the directory of the script and run the \"${LightBlue}$AMCLI -i ./script\033[0m\" command, even using dedicated flags, if necessary (see \"-i\").
1409  
1410  			${Gold}unlock\033[0m
1411  
1412  					${LightBlue}$AMCLI unlock {PROGRAM}\033[0m
1413  
1414  			Description: Unlock updates for the selected program (nulls \"lock\").
1415  
1416  			${Gold}update, -u, -U\033[0m
1417  
1418  					${LightBlue}$AMCLI -u
1419  					${LightBlue}$AMCLI -u --apps
1420  					${LightBlue}$AMCLI -u --debug
1421  					${LightBlue}$AMCLI -u --apps --debug
1422  					${LightBlue}$AMCLI -u {PROGRAM}\033[0m
1423  					${LightBlue}$AMCLI -u --debug {PROGRAM}
1424  					${LightBlue}$AMCLI -u --launcher\033[0m
1425  
1426  			Description: Update everything. Add \"--apps\" to update only the apps or write only the apps you want to update by adding their names. Add the \"--debug\" flag to view the output of AM-updater scripts. Add the \"--launcher\" flag to try to update only local AppImages integrated with the \"--launcher\" option (see \"--launcher\").
1427  
1428  			${Gold}version, -v\033[0m
1429  
1430  					${LightBlue}$AMCLI -v\033[0m
1431  
1432  			Description: Shows the version.
1433  
1434  			${Gold}--devmode-disable\033[0m
1435  
1436  					${LightBlue}$AMCLI --devmode-disable\033[0m
1437  
1438  			Description: Undo \"--devmode-enable\" (see below).
1439  
1440  			${Gold}--devmode-enable\033[0m
1441  
1442  					${LightBlue}$AMCLI --devmode-enable\033[0m
1443  
1444  			Description: Use the development branch (at your own risk).
1445  
1446  			${Gold}--disable-notifications\033[0m
1447  
1448  					${LightBlue}$AMCLI --disable-notifications\033[0m
1449  
1450  			Description: Disable notifications during apps update.
1451  
1452  			${Gold}--disable-sandbox\033[0m
1453  
1454  					${LightBlue}$AMCLI --disable-sandbox {PROGRAM}\033[0m
1455  
1456  			Description: Disable the sandbox for the selected app.
1457  
1458  			${Gold}--enable-notifications\033[0m
1459  
1460  					${LightBlue}$AMCLI --enable-notifications\033[0m
1461  
1462  			Description: Enable notifications during apps update (nulls \"--disable-notifications\").
1463  
1464  			${Gold}--force-latest\033[0m
1465  
1466  					${LightBlue}$AMCLI --force-latest {PROGRAM}\033[0m
1467  
1468  			Description: Downgrades an installed app from pre-release to \"latest\".
1469  
1470  			${Gold}--launcher\033[0m
1471  
1472  					${LightBlue}$AMCLI --launcher /path/to/\${APPIMAGE}\033[0m
1473  
1474  			Description: Drag/drop one or more AppImages in the terminal and embed them in the apps menu and customize a command to use from the CLI.
1475  
1476  			NOTE that \"--launcher\" can be used as a flag in \"-u\" to try to update the integrated AppImages (see \"-u\"). This works only if \"appimageupdatetool\" is installed and delta updates are supported. This flag does not work miracles, I strongly suggest to use options \"-ia\" and \"-e\" instead.
1477  
1478  			${Gold}--system\033[0m
1479  
1480  					${LightBlue}am --system\033[0m
1481  
1482  			${Gold}--user\033[0m
1483  
1484  					${LightBlue}am --user\033[0m
1485  
1486  			Description: Made \"AM\" run in \"AppMan Mode\", locally, useful for unprivileged users. This option only works with \"AM\".
1487  
1488  			The \"--user\" option can also be used just as a flag for installation options. For example:
1489  
1490  			- Use it to install applications locally, option \"-i\" or \"install\":
1491  
1492  				${LightBlue}am -i --user {PROGRAM}\033[0m
1493  
1494  			- Also suboptions of \"-i\" can work with this flag:
1495  
1496  				${LightBlue}am -i --user --debug {PROGRAM}\033[0m
1497  				${LightBlue}am -i --user --force-latest {PROGRAM}
1498  				${LightBlue}am -i --user --icons {PROGRAM}
1499  				${LightBlue}am -i --user --debug --force-latest {PROGRAM}
1500  				${LightBlue}am -i --user --debug --force-latest --icons {PROGRAM}\033[0m
1501  
1502  			- Same for AppImages only, option \"-ia\" or \"install-appimage\":
1503  
1504  				${LightBlue}am -ia --user {PROGRAM}\033[0m
1505  				${LightBlue}am -ia --user --debug {PROGRAM}
1506  				${LightBlue}am -ia --user --force-latest {PROGRAM}
1507  				${LightBlue}am -ia --user --icons {PROGRAM}
1508  				${LightBlue}am -ia --user --debug --force-latest {PROGRAM}\033[0m
1509  				${LightBlue}am -ia --user --debug --force-latest --icons {PROGRAM}\033[0m
1510  
1511  			- External AppImages can be installed like this as well, option \"-e\" or \"extra\":
1512  
1513  				${LightBlue}am -e --user user/project {APPNAME}\033[0m
1514  				${LightBlue}am -e --user user/project {APPNAME} {KEYWORD}\033[0m
1515  
1516  			NOTE, \"AM\" 9 or higher is also able to, update and manage apps locally, by default, and without having to switch to \"AppMan Mode\".
1517  
1518  			Description: Switch \"AM\" back to \"AM\" from \"AppMan Mode\" (see \"--user\").
1519  
1520  			$DIVIDING_LINE
1521  
1522  			THIRD-PARTY FLAGS: $third_party_flags_message
1523  			$DIVIDING_LINE
1524  
1525  			 SITES:
1526  
1527  			 https://github.com/ivan-hc/AM
1528  
1529  			 https://portable-linux-apps.github.io
1530  
1531  			\n" | sed 's/^			//g' | _fit | less -Ir
1532  		}
1533  
1534  		if [ -t 1 ]; then _use_help; else _use_help | sed -e 's/\x1b\[[0-9;]*m//g'; fi
1535  		;;
1536  	*)
1537  		exec "$AMCLIPATH"
1538  		;;
1539  esac
1540  
1541  # vim:tabstop=4:shiftwidth=4:expandtab