APP-MANAGER 63 KB

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