/ modules / install.am
install.am
  1  #!/bin/sh
  2  
  3  #############################################################################
  4  # THIS MODULE IS USED TO INSTALL APPS FROM THE DATABASE OR FROM LOCAL SCRIPTS
  5  #############################################################################
  6  
  7  AMCLIPATH_ORIGIN="$AMCLIPATH"
  8  BINDIR="${XDG_BIN_HOME:-$HOME/.local/bin}"
  9  
 10  ################################################################################
 11  #				DOWNLOAD
 12  ################################################################################
 13  
 14  _convert_to_appman_compatible_script() {
 15  	_detect_appman_apps
 16  	_appman
 17  	if [ -d "$APPMAN_APPSPATH" ]; then
 18  		sed -i "s# /usr/local/bin# $BINDIR#g" ./"$arg"
 19  		sed -i "s# /usr/local/share/applications# $DATADIR/applications#g" ./"$arg"
 20  		sed -i "s# /opt# $APPMAN_APPSPATH#g" ./"$arg"
 21  		sed -i "s# https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" ./"$arg"
 22  		cat <<-HEREDOC >> ./"$arg"
 23  
 24  		# POST INSTALLATION PATCH FOR ALL LAUNCHERS
 25  		sed -i "s#Exec=\$APP#Exec=$BINDIR/\$APP#g" $DATADIR/applications/*-AM.desktop
 26  		sed -i "s#Exec=/usr/bin/#Exec=$BINDIR/#g" $DATADIR/applications/*-AM.desktop
 27  		sed -i "s#Exec=/opt/#Exec=$HOME/$APPSDIR#g" $DATADIR/applications/*-AM.desktop
 28  		sed -i "s#Icon=/opt/#Icon=$HOME/$APPSDIR#g" $DATADIR/applications/*-AM.desktop
 29  
 30  		HEREDOC
 31  		printf " Converting %s to an AppMan-compatible script.\r" "$arg" && sleep 0.25 &&
 32  		printf "                                                                           \r"
 33  	else
 34  		echo ' 💀 ERROR: "--convert" requires a configuration file in ~/.config/appman'
 35  	fi
 36  }
 37  
 38  _download() {
 39  	if curl --output /dev/null --silent --head --fail "$APPSDB/$arg"  1>/dev/null; then
 40  		cd "$SCRIPTDIR" || return 1
 41  		if [ -f ./"$arg" ] || [ -d ./"$arg" ]; then
 42  			echo "✖ \"$SCRIPTDIR/$arg\" already exists!" | _fit && return 1
 43  		else
 44  			wget -q "$APPSDB/$arg" && echo "◆ \"$arg\" installation script downloaded to \"$SCRIPTDIR\"! " | _fit
 45  		fi
 46  	else
 47  		echo " 💀 ERROR: \"$arg\" is NOT a valid argument"
 48  	fi
 49  }
 50  
 51  ################################################################################
 52  #				INSTALL
 53  ################################################################################
 54  
 55  _check_if_optional_dependences_are_needed() {
 56  	# Determine generic build utils
 57  	app_deps="ar gcc glib-compile-schemas make tar unzip"
 58  	script_content=$(cat ./"$arg")
 59  	# Determine if this is an AppImage that can be compiled on-the-fly
 60  	if grep -qi "^wget.*.sh.*chmod.*&&" ./"$arg"; then
 61  		appimage_bulder_script=$(grep "^wget " ./"$arg" | tr '"' '\n' | grep -i "^http" | sed "s/\$APP/$arg/g")
 62  		if curl --output /dev/null --silent --head --fail "$appimage_bulder_script" 1> /dev/null; then
 63  			script_content=$(curl -Ls "$appimage_bulder_script")
 64  			if echo "$script_content" | grep -ie "appimagetool\|pkg2appimage" 1>/dev/null; then
 65  				if ! command -v convert >/dev/null 2>&1; then
 66  					echo " 💀 ERROR: cannot create \"$arg\" without \"convert\" (from \"imagemagick\")"
 67  					return 1
 68  				fi
 69  			fi
 70  		else
 71  			echo " 💀 ERROR: cannot create \"$arg\", the builder does not exists"
 72  			return 1
 73  		fi
 74  	fi
 75  	# Determine if this script installs a Firefox webapp
 76  	if grep -q 'ffwa-' ./"$arg"; then
 77  		ffbrowser=$(find ${PATH//:/ } -maxdepth 1 -name "firefox*" | sort | head -1)
 78  		if [ -z "$ffbrowser" ]; then
 79  			echo " 💀 ERROR: you cannot install \"$arg\" without installing \"firefox\""
 80  			return 1
 81  		else
 82  			sed -i 's#firefox --class#'"$(echo "$ffbrowser" | xargs -L 1 basename)"' --class#g' ./"$arg"
 83  		fi
 84  	fi
 85  	# Check missing dependency
 86  	for name in $app_deps; do
 87  		dependency_name="$name"
 88  		[ "$name" = "ar" ] && dependency_name="binutils"
 89  		if echo "$script_content" | grep -q "^$name" && ! command -v "$name" >/dev/null 2>&1; then
 90  			echo " 💀 ERROR: cannot install \"$arg\" without \"$dependency_name\""
 91  			return 1
 92  		fi
 93  	done
 94  }
 95  
 96  _check_if_script_installs_a_metapackage() {
 97  	# Check if the installation script is a metapackage (example one of the 40+ kdegames scripts)
 98  	[ ! -f "$AMDATADIR/$ARCH-apps" ] && _completion_lists
 99  	for metapackage in $METAPACKAGES; do
100  		if grep "◆ $arg : " "$AMDATADIR/$ARCH-apps" | grep -q "\"$metapackage\""; then
101  			if [ -d "$APPSPATH"/"$metapackage"/tmp ]; then
102  				$SUDOCMD "$APPSPATH"/"$metapackage"/remove 2> /dev/null
103  			fi
104  			if [ -d "$APPSPATH"/"$metapackage" ] || command -v "$metapackage" >/dev/null 2>&1; then
105  				LASTDIR=$(echo "$metapackage" | tr '[:lower:]' '[:upper:]')
106  				echo " ◆ $APPNAME IS PART OF \"$LASTDIR\", ALREADY INSTALLED"
107  				return 1
108  			fi
109  		fi
110  	done
111  	metapkg_error_msg=" 💀 ERROR: \"$pure_arg\" also provides \"SCMD\", already in \$PATH"
112  	if [ "$pure_arg" = node ] && command -v npm >/dev/null 2>&1; then
113  		echo "$metapkg_error_msg" | tr '[:lower:]' '[:upper:]' | sed 's/SCMD/npm/g'
114  		return 1
115  	elif [ "$pure_arg" = platform-tools ] || [ "$pure_arg" = adb ] || [ "$pure_arg" = fastboot ]; then
116  		if command -v adb >/dev/null 2>&1; then
117  			echo "$metapkg_error_msg" | tr '[:lower:]' '[:upper:]' | sed 's/SCMD/adb/g'
118  			return 1
119  		elif command -v fastboot >/dev/null 2>&1; then
120  			echo "$metapkg_error_msg" | tr '[:lower:]' '[:upper:]' | sed 's/SCMD/fastboot/g'
121  			return 1
122  		fi
123  	fi
124  	
125  }
126  
127  _check_if_spooky_flag_exists() {
128  	# Determine if an installation script is flagged as "spooky"
129  	if grep -i spooky ./"$arg" >/dev/null 2>&1; then
130  		printf "%b%b" " ${RED}WARNING:" " \"$arg\" does not have a transparent build process! \033[0m\n"
131  		printf "\n We can't be sure as to what is inside the application\n We highly recommend that you sandbox this application\n\n"
132  		read -r -p " Do you wish to continue? (N/y): " yn
133  		if ! echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
134  			printf "\n INSTALLATION ABORTED! \n"
135  			return 1
136  		fi
137  	fi
138  }
139  
140  _check_kind_of_installation_script() {
141  	# Check if you are installing an app or a library
142  	echo " ◆ $APPNAME: starting installation script"
143  	if grep -qi "^wget.*.sh.*chmod.*&&" ./"$arg"; then
144  		printf "\n This script will create an AppImage on the fly, please wait...\n"
145  	elif grep -q "/usr/local/lib" ./"$arg"; then
146  		[ "$arg" = libfuse2 ] && [ -f /usr/local/lib/libfuse.so.2 ] && echo " 💀 ERROR: \"$arg\" already exists in /usr/local/lib" && return 1
147  		printf "\n ⚠️ This script will install a system library in /usr/local/lib\n\n"
148  		read -r -p " Do you wish to continue? (N/y): " yn
149  		if ! echo "$yn" | grep -i '^y' >/dev/null 2>&1; then
150  			printf "\n INSTALLATION ABORTED! \n"
151  			return 1
152  		fi
153  	fi
154  }
155  
156  _apply_patches() {
157  	# Patch "wget" (version 1.x) to have a progress bar and fix errors when applying patches
158  	if ! echo "$FLAGS" | grep -q -- "--debug" && wget --version | head -1 | grep -q ' 1.'; then
159  		sed -i "s#wget #wget -q --no-verbose --show-progress --progress=bar #g" ./"$arg"
160  	fi
161  	# Install the app so that it can rely on an icon theme (if available)
162  	if echo "$FLAGS" | grep -q -- '--icons'; then
163  		sed -i "s#Icon=/opt/\$APP/icons/#Icon=#g" ./"$arg"
164  	fi
165  	# If you use the --latest option, add the "latest" flag to scripts that point to a very common "release"
166  	if echo "$FLAGS" | grep -q -- '--force-latest'; then
167  		sed -i 's#/releases #/releases/latest #g' ./"$arg"
168  	fi
169  	# Patches /usr/local for $HOME equivalent for AppMan
170  	if [ "$AMCLI" = "appman" ]; then
171  		sed -i "s#/usr/local/bin#$BINDIR#g" ./"$arg"
172  		sed -i "s#/usr/local/share#$DATADIR#g" ./"$arg"
173  		sed -i "s#/opt/#$APPSPATH/#g" ./"$arg"
174  	else
175  		"$SUDOCMD" mkdir -p /usr/local/share/applications /usr/local/bin
176  	fi
177  	# Patch to apply to installation scripts
178  	sed -i "s# https://api.github.com#$HeaderAuthWithGITPAT https://api.github.com#g" ./"$arg"
179  	sed -i "s#DirIcon\$#DirIcon  2>/dev/null#g" ./"$arg"
180  	sed -i "s#DirIcon ./icons/\"\$APP\" 1#DirIcon ./icons/\"\$APP\" 2#g" ./"$arg"
181  	echo ""
182  	# Use GNU implementation of "sed"
183  	if [ "$NO_SED_I" = true ]; then
184  		if command -v gsed >/dev/null 2>&1; then
185  			sed -i "s/sed -i/gsed -i/g" ./"$arg"
186  		else
187  			sed -i "s/sed -i/sed -i'' -e/g" ./"$arg"
188  		fi
189  	fi
190  }
191  
192  _torsocks_error_message() {
193  	echo "💀 Cannot install \"$arg\", $TORSOCKS_MESSAGE"
194  	printf "\nInstall \"torsocks\" from your system package manager and retry! \n"
195  }
196  
197  _post_installation_processes() {
198  	LASTDIR=$(ls -td "$APPSPATH"/* | head -1 | sed 's:.*/::')
199  	LASTDIRPATH="${APPSPATH}/${LASTDIR}"
200  	# Put permission check in remove script and change ownership of directory
201  	if [ "$AMCLI" = am ]; then
202  		$SUDOCMD sed -i "1 a [ \"\$(id -u)\" -ne 0 ] && echo "Permission denied" && exit 1" \
203  			"${LASTDIRPATH}"/remove 2>/dev/null
204  		$SUDOCMD chown -R "$USER" "${LASTDIRPATH}" 2>/dev/null
205  	fi
206  	# Check for AM-updater script sothat CLI can manage updates
207  	[ -f "${LASTDIRPATH}"/AM-updater ] && mkdir "${LASTDIRPATH}"/.am-installer 2>/dev/null \
208  		&& curl -Ls "$APPSDB"/"$arg" > "${LASTDIRPATH}"/.am-installer/"$arg"
209  	find "${LASTDIRPATH}"/icons/* -xtype l -delete 2>/dev/null # Removes broken links
210  	# If you have a broken or missing icon in your "icons" directory, download one from the catalog
211  	[ -z "$(ls -A "${LASTDIRPATH}"/icons 2>/dev/null)" ] \
212  		&& wget -q "$AMCATALOGUEICONS"/"$arg".png -O "${LASTDIRPATH}"/icons/"$arg" 2>/dev/null
213  	# Patch .desktop to change paths if the app is installed locally
214  	if [ "$AMCLI" = "appman" ]; then
215  		for a in $DATADIR/applications/*-AM.desktop; do
216  			sed -i "s#Exec=$arg#Exec=$BINDIR/$arg#g" "$a" 2>/dev/null
217  			sed -i "s#Exec=/usr/bin/#Exec=$BINDIR/#g" "$a" 2>/dev/null
218  			sed -i "s#Exec=/opt/#Exec=$BINDIR/#g" "$a" 2>/dev/null
219  		done
220  	fi
221  	# Export all icons for hicolor theme usage
222  	if echo "$FLAGS" | grep -q -- '--icons'; then
223  		_icon_theme_export_to_datadir 2>/dev/null
224  	fi
225  }
226  
227  _ending_the_installation() {
228  	LASTDIR=$(ls -td "$APPSPATH"/* | head -1 | sed 's:.*/::')
229  	if [ -f "${LASTDIRPATH}"/remove ]; then
230  		if test -d "${LASTDIRPATH}"/tmp; then
231  			echo " 💀 ERROR DURING INSTALLATION, REMOVED $APPNAME!"
232  			$SUDOCMD "$APPSPATH/$LASTDIR/remove" 1>/dev/null
233  		elif test -f "$APPSPATH/$LASTDIR/version" && [ -z "$(cat "$APPSPATH/$LASTDIR/version")" ]; then
234  			echo " 💀 ERROR DURING INSTALLATION, REMOVED $APPNAME!"
235  			$SUDOCMD "$APPSPATH/$LASTDIR/remove" 1> /dev/null
236  		else
237  			APPSIZE=$(du -sm "${LASTDIRPATH}" | awk '{print $1}' )
238  			LASTDIRNAME=$(echo "\"$LASTDIR\"" | tr '[:lower:]' '[:upper:]')
239  			printf "%b%b%s\n" " ${Green}" "$LASTDIRNAME INSTALLED\033[0m" " ($APPSIZE MB OF DISK SPACE)"
240  			$SUDOCMD rm "$AMCACHEDIR"/"$arg"
241  			_check_version
242  			app_version=$(grep -w " ◆ $LASTDIR	|" 0<"$AMCACHEDIR"/version-args | sed 's:.*|	::')
243  			echo " ◆ $LASTDIR $app_version" >> "$AMCACHEDIR"/installed
244  		fi
245  	else
246  		echo " INSTALLATION ABORTED!"
247  	fi
248  }
249  
250  _install_arg() {
251  	# This function is needed to parse the installation script and then execute it
252  	APPNAME=$(echo "\"$pure_arg\"" | tr '[:lower:]' '[:upper:]')
253  	chmod a+x ./"$arg"
254  	_check_if_optional_dependences_are_needed || return 1
255  	_check_if_script_installs_a_metapackage || return 1
256  	_check_if_spooky_flag_exists || return 1
257  	_check_kind_of_installation_script || return 1
258  	_apply_patches
259  	# Determine if Torsocks is needed
260  	if command -v torsocks 1>/dev/null; then
261  		TORSOCKS="1"
262  	fi
263  	if grep -q "https://repology.org" ./"$arg"; then
264  		REPOLOGY_API_ALLOWED=$(curl -Ls https://repology.org/)
265  		TORSOCKS_MESSAGE="you have no access to https://repology.org, needed to check the version of this program."
266  		if grep -q "https://repology.org" ./"$arg" && [ -z "$REPOLOGY_API_ALLOWED" ] && [ -n "$TORSOCKS" ]; then
267  			sed -i "s/version=\$(wget/version=\$(torsocks wget/g" ./"$arg"
268  		fi
269  		[ -z "$REPOLOGY_API_ALLOWED" ] && [ -z "$TORSOCKS" ] && _torsocks_error_message | fold -sw 72 | sed 's/^/   /g; s/   ✖/✖/g' && return 0
270  	elif grep -q "api.github.com" ./"$arg"; then
271  		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)
272  		TORSOCKS_MESSAGE="you have reached GitHub API limit."
273  		[ -z "$GH_API_ALLOWED" ] && [ -z "$TORSOCKS" ] && _torsocks_error_message | fold -sw 72 | sed 's/^/   /g; s/   ✖/✖/g' && return 0
274  	fi
275  	# Install script
276  	if grep -q "api.github.com" ./"$arg" && [ -z "$GH_API_ALLOWED" ] && [ -n "$TORSOCKS" ]; then
277  		$SUDOCMD torsocks ./"$arg"
278  	else
279  		$SUDOCMD ./"$arg"
280  	fi
281  	echo ""
282  	_post_installation_processes
283  	_ending_the_installation
284  }
285  
286  ################################################################################
287  #			INSTALLATION CASES
288  ################################################################################
289  
290  _determine_pure_arg_name() {
291  	pure_arg=$(echo "$arg" | sed 's/\.toolpack//g; s/\.dwfs.appbundle$//g; s/\.appbundle$//g; s/\.nixappimage//g')
292  	pure_arg=$(echo "$pure_arg" | sed 's/\.appimage//g; s/\^debian-testing-//g; s/\-appimage$//g' | sed 's:.*/::')
293  	echo "$arg" | grep -q -- "-appimage$" && curl -Ls "$APPSDB"/"$arg" | grep -q "APP=.*-appimage$" && pure_arg="$arg"
294  }
295  
296  _install_appimage() {
297  	# This function is ment to select and install only AppImages
298  	rm -f "$AMCACHEDIR"/install-args
299  	_sync_appimages_list
300  	for arg in $entries; do
301  		if grep -q "^◆ $arg : " "$AMDATADIR/$ARCH-appimages"; then
302  			echo "$arg" >> "$AMCACHEDIR"/install-args
303  		else
304  			arg="$arg-appimage"
305  			if ! grep -q "^◆ $arg : " "$AMDATADIR/$ARCH-appimages"; then
306  				echo "$DIVIDING_LINE"
307  				echo " ✖ \"$(echo "$arg" | sed 's/-appimage//g')\" is not an Appimage"
308  				echo "$DIVIDING_LINE"
309  			else
310  				echo "$arg" >> "$AMCACHEDIR"/install-args
311  			fi
312  		fi
313  	done
314  	entries=$(cat "$AMCACHEDIR"/install-args 2>/dev/null)
315  }
316  
317  _install_local_script() {
318  	# This function is for local installation scripts
319  	path2arg="$arg"
320  	arg=$(echo "$path2arg" | sed 's:.*/::')
321  	mkdir -p "$AMCACHEDIR"/tmp && rm -f "$AMCACHEDIR"/tmp/* || return 1
322  	cp "$path2arg" "$AMCACHEDIR"/tmp/"$arg" && cd "$AMCACHEDIR" && mv ./tmp/"$arg" ./"$arg" && rmdir ./tmp || return 1
323  	if ! test -d "$APPSPATH"/"$arg"; then
324  		_install_arg
325  	fi
326  }
327  
328  _install_normally() {
329  	# This is for scripts hosted on the official online database
330  	mkdir -p "$AMCACHEDIR"/tmp && rm -f "$AMCACHEDIR"/tmp/* || return 1
331  	curl -Ls "$APPSDB"/"$arg" > "$AMCACHEDIR"/tmp/"$arg" || return 1
332  	cd "$AMCACHEDIR" && mv ./tmp/"$arg" ./"$arg" && rmdir ./tmp || return 1
333  	_install_arg
334  }
335  
336  ################################################################################
337  #			THIRD PARTY DATABASES
338  ################################################################################
339  
340  _3rd_party_check() {
341  	echo "$@" | grep -q -- "--toolpack" || echo "$arg" | grep -q ".toolpack$" || echo "$arg" | grep -q ".appbundle$"
342  }
343  
344  _3rd_party_apps_handler() {
345  	# This function is needed to handle programs from third-party supported databases
346  	mkdir -p "$CACHEDIR/extra"
347  	if echo "$arg" | grep -q "appbundle$"; then
348  		[ -n "$appbundle_readme" ] && third_party_readme="$appbundle_readme"
349  	else
350  		[ -n "$toolpack_readme" ] && third_party_readme="$toolpack_readme"
351  	fi
352  	awk_version="curl -Ls $third_party_readme | grep -i \"^| $arg \" | tr '|' '\\\n' | cut -c 2- | grep . | awk -F: \"NR==$awk_ver\""
353  	third_party_url="curl -Ls $third_party_readme | grep -i \"^| $arg \" | tr '|' '\\\n' | cut -c 2- | grep . | awk -F: \"NR==$awk_dl\""
354  	if echo "$arg" | grep -q "appbundle$"; then
355  		curl -Ls "$AMREPO"/templates/AM-SAMPLE-AppBundle > "$CACHEDIR/extra/$arg.toolpack" || exit 1
356  		sed -i "s#APP=SAMPLE#APP=$arg#g; s#FUNCTION#$awk_version#g; s#wget \"\$version\"#wget \$($third_party_url)#g" "$CACHEDIR/extra/$arg.toolpack"
357  		sed -i 's/\.dwfs.appbundle$//g; s/\.appbundle$//g' "$CACHEDIR/extra/$arg.toolpack"
358  	elif echo "$arg" | grep -q "nixappimage$"; then
359  		curl -Ls "$AMREPO"/templates/AM-SAMPLE-AppImage > "$CACHEDIR/extra/$arg.toolpack" || exit 1
360  		sed -i "s#APP=SAMPLE#APP=$arg#g; s#FUNCTION#$awk_version#g; s#wget \"\$version\"#wget \$($third_party_url)#g" "$CACHEDIR/extra/$arg.toolpack"
361  		sed -i 's/\.nixappimage$//g' "$CACHEDIR/extra/$arg.toolpack"
362  	else
363  		curl -Ls "$AMREPO"/templates/AM-SAMPLE-Archive > "$CACHEDIR/extra/$arg.toolpack" || exit 1
364  		sed -i "s#APP=SAMPLE#APP=$arg#g; s#FUNCTION#$awk_version#g; s#wget \"\$version\"#wget \$($third_party_url)#g" "$CACHEDIR/extra/$arg.toolpack"
365  		sed -e '/\[ -e/ s/^#*/#/' -i "$CACHEDIR/extra/$arg.toolpack" 2>/dev/null
366  	fi
367  	chmod a+x "$CACHEDIR/extra/$arg.toolpack"
368  	arg="$CACHEDIR/extra/$arg.toolpack"
369  }
370  
371  _install_3rd_party_app() {
372  	arg=$(echo "$arg" | sed 's/\.toolpack//g; s/\.appimage//g')
373  	if curl -Ls "$appbundle_readme" 2>/dev/null | grep -q "^| $arg " || curl -Ls "$toolpack_readme" 2>/dev/null | grep -q "^| $arg "; then
374  		_3rd_party_apps_handler
375  		_install_local_script
376  	else
377  		echo " 💀 ERROR, \"$arg\" does NOT exist in 3rd-party databases:"
378  		printf "\nTry without the \"--toolpack\" flag or run \"%b$AMCLIPATH_ORIGIN -l --all\033[0m\" to check all lists.\n" "${Gold}" | fold -sw 72 | sed 's/^/ /g'
379  	fi
380  }
381  
382  ################################################################################
383  #				USAGE
384  ################################################################################
385  
386  case "$1" in
387  	'-d'|'download')
388  		case $2 in
389  		'--convert')
390  			[ -z "$3" ] && echo " USAGE: $AMCLI $1 $2 [ARGUMENT]" && exit 1
391  			;;
392  		'')
393  			echo " USAGE: $AMCLI $1 [ARGUMENT]"
394  			echo " USAGE: $AMCLI $1 --convert [ARGUMENT]"
395  			exit 1
396  			;;
397  		esac
398  		if [ "$2" = "--convert" ]; then
399  			entries="$(echo "$@" | cut -f3- -d ' ')"
400  			for arg in $entries; do
401  				_download
402  				_convert_to_appman_compatible_script
403  			done
404  		else
405  			entries="$(echo "$@" | cut -f2- -d ' ')"
406  			for arg in $entries; do
407  				_download
408  			done
409  		fi
410  		;;
411  
412  	'install'|'-i'|'-ias'|\
413  	'install-appimage'|'-ia')
414  		[ "$AMCLI" = "am" ] && echo "$@" | grep -q -- "--user" && _appman
415  
416  		case $2 in
417  		'')
418  			echo " USAGE: $AMCLI $1 [ARGUMENT]"
419  			echo " USAGE: $AMCLI $1 --debug [ARGUMENT]"
420  			echo " USAGE: $AMCLI $1 --force-latest [ARGUMENT]"
421  			echo " USAGE: $AMCLI $1 --icons [ARGUMENT]"
422  			echo " USAGE: $AMCLI $1 --sandbox [ARGUMENT]"
423  			[ "$AMCLI" = "am" ] && echo " USAGE: $AMCLI $1 --user [ARGUMENT]"
424  			exit 1
425  			;;
426  		esac
427  
428  		[ "$AMCLI" = "am" ] && { $SUDOCMD printf "\r" || exit 1; }
429  
430  		echo "============================================================================"
431  		printf "\n                  %bSTART OF ALL INSTALLATION PROCESSES\033[0m\n\n" "${LightBlue}"
432  		echo "============================================================================"
433  		_clean_amcachedir 2>/dev/null
434  
435  		entries="$(echo "$@" | cut -f2- -d ' ' | tr ' ' '\n' | grep -v -- "--")"
436  		FLAGS=$(echo "$@" | tr ' ' '\n' | grep -- "--" | tr '\n ' ' ')
437  		METAPACKAGES="kdegames kdeutils node platform-tools"
438  
439  		if [ "$1" = "-ia" ] || [ "$1" = "install-appimage" ]; then _install_appimage; fi
440  		if [ "$1" = "-ias" ]; then FLAGS=$(printf "%b\n--sandbox\n" "$FLAGS"); _install_appimage; fi
441  
442  		for arg in $entries; do
443  			echo ""
444  			cd "$REALDIR" || return 1
445  			# If the "tmp" directory is not removed, the installation failed, so remove the app
446  			[ -d "$APPSPATH"/"$arg"/tmp ] && $SUDOCMD "$APPSPATH"/"$arg"/remove 2> /dev/null
447  
448  			# Check if the app wil be installed with the same name as the argument
449  			_determine_pure_arg_name
450  
451  			# Test if a symlink is broken
452  			[ -n "$BINDIR" ] && find "$BINDIR" -xtype l -name "$pure_arg" -delete 2>/dev/null
453  			# Various cases that may occur during installation
454  			if test -f "$APPSPATH"/"$pure_arg"/remove; then
455  				echo " ◆ \"$pure_arg\" is already installed!" | tr '[:lower:]' '[:upper:]'
456  			elif [ -n "$(PATH=/usr/local/bin command -v "$pure_arg" 2>/dev/null)" ] && [ "$AMCLI" = am ]; then
457  				echo " 💀 ERROR: \"$pure_arg\" command already exists!"
458  			elif echo "$arg" | grep -q "/"; then
459  				if test -f "$arg" 2> /dev/null; then
460  					_install_local_script
461  				else
462  					echo " 💀 ERROR: the file \"$arg\" does NOT exist"
463  				fi
464  			elif _3rd_party_check "$@"; then
465  				_install_3rd_party_app
466  			elif curl --output /dev/null --silent --head --fail "$APPSDB"/"$arg" 1>/dev/null; then
467  				_install_normally
468  			else
469  				echo "💀 ERROR: \"$arg\" does NOT exist in the \"AM\" database, $(printf "please check the list, run the \"%b$AMCLIPATH_ORIGIN -l\033[0m\" command.\n\n" "${Gold}")" | fold -sw 72 | sed 's/^/ /g'
470  			fi
471  			# Sandbox argument
472  			if echo "$FLAGS" | grep -q -- "--sandbox" && [ "$LASTDIR" != aisap ]; then
473  				if [ -f "$APPSPATH/$LASTDIR/$LASTDIR" ]; then
474  					if ! command -v aisap >/dev/null 2>&1; then
475  						mv "$AMCACHEDIR"/installed "$CACHEDIR"/installed.backup.am 2>/dev/null
476  						"$AMCLIPATH_ORIGIN" --sandbox "$LASTDIR"
477  						sort "$AMCACHEDIR"/installed >> "$CACHEDIR"/installed.backup.am 2>/dev/null
478  						mv "$CACHEDIR"/installed.backup.am "$AMCACHEDIR"/installed 2>/dev/null
479  					else
480  						echo ""
481  						"$AMCLIPATH_ORIGIN" --sandbox "$LASTDIR"
482  					fi
483  				else
484  					printf "\n ERROR: \"%b\" is NOT an AppImage\n" "$LASTDIR"
485  				fi
486  			fi
487  			echo "____________________________________________________________________________"
488  		done
489  		echo "============================================================================"
490  		printf "\n                  %bEND OF ALL INSTALLATION PROCESSES\n\033[0m" "${LightBlue}"
491  		[ -f "$AMCACHEDIR"/installed ] && printf "\n             The following new programs have been installed:\n\n" \
492  		&& sort "$AMCACHEDIR"/installed | grep -w -v "◆ am"
493  		printf "\n============================================================================\n"
494  		exit 0
495  		;;
496  
497  	'-e'|'extra')
498  		if [ -z "$2" ] || [ -z "$3" ]; then
499  			echo " USAGE: $AMCLI $1 user/project [ARGUMENT]"
500  			echo " USAGE: $AMCLI $1 user/project [ARGUMENT] [KEYWORD]"
501  			[ "$AMCLI" = "am" ] && echo " USAGE: $AMCLI $1 --user user/project [ARGUMENT]"
502  			[ "$AMCLI" = "am" ] && echo " USAGE: $AMCLI $1 --user user/project [ARGUMENT] [KEYWORD]"
503  			exit 1
504  		fi
505  		case $2 in
506  		'--user')
507  			USER_PROJECT=$(echo "$3" | sed 's#https://github.com/##g' | cut -f1,2 -d'/')
508  			EXTERNAL_APP_NAME="$4"
509  			APP_KEYWORD="$5"
510  			;;
511  		*)
512  			USER_PROJECT=$(echo "$2" | sed 's#https://github.com/##g' | cut -f1,2 -d'/')
513  			EXTERNAL_APP_NAME="$3"
514  			APP_KEYWORD="$4"
515  			;;
516  		esac
517  		mkdir -p "$CACHEDIR/extra"
518  		curl -Ls "$AMREPO"/templates/AM-SAMPLE-AppImage > "$CACHEDIR/extra/$EXTERNAL_APP_NAME" || exit 1
519  		sed -i "s#APP=SAMPLE#APP=$EXTERNAL_APP_NAME#g" "$CACHEDIR/extra/$EXTERNAL_APP_NAME"
520  		API_GITHUB_REPO="https://api.github.com/repos/$USER_PROJECT/releases"
521  		sed -i "s#REPLACETHIS#$USER_PROJECT#g" "$CACHEDIR/extra/$EXTERNAL_APP_NAME"
522  		q="'"
523  		if [ "$ARCH" = "x86_64" ]; then
524  			FILTER=' | grep -vi "i386\\|i686\\|i586\\|i486\\|aarch64\\|arm64\\|armv7l"'
525  		elif [ "$ARCH" = "i686" ]; then
526  			FILTER=' | grep -ie "i386\\|i686\\|i586\\|i486" '
527  		elif [ "$ARCH" = "aarch64" ]; then
528  			FILTER=' | grep -ie "aarch64\\|arm64" '
529  		fi
530  		FUNCTION='curl -Ls '"$API_GITHUB_REPO"' | sed '"$q"'s/[()",{} ]/\\n/g'"$q"' | grep -oi "https.*mage$"'"$FILTER"' | head -1'
531  		sed -i "s#FUNCTION)#$FUNCTION)#g" "$CACHEDIR/extra/$EXTERNAL_APP_NAME"
532  		[ -n "$APP_KEYWORD" ] && sed -i "s# head -1# grep -i \"$APP_KEYWORD\" | head -1#g" "$CACHEDIR/extra/$EXTERNAL_APP_NAME"
533  		chmod a+x "$CACHEDIR/extra/$EXTERNAL_APP_NAME"
534  		[ "$AMCLI" = "am" ] && [ "$2" = "--user" ] && "$AMCLIPATH_ORIGIN" -i --user "$CACHEDIR/extra/$EXTERNAL_APP_NAME" \
535  		|| "$AMCLIPATH_ORIGIN" -i "$CACHEDIR/extra/$EXTERNAL_APP_NAME"
536  		exit 1
537  		;;
538  esac