diff --git a/api b/api
index d3ae8bd..d11827a 100755
--- a/api
+++ b/api
@@ -1,12 +1,15 @@
#!/bin/bash
-DIRECTORY="$(readlink -f "$(dirname "$0")")"
-
error() {
echo -e "\e[91m$1\e[39m" 1>&2
exit 1
}
+#if this script is being run standalone, not sourced
+if [[ "$0" == */api ]];then
+ DIRECTORY="$(readlink -f "$(dirname "$0")")"
+fi
+
#echo "API script thinks directory is $DIRECTORY" 1>&2
repo_url="$(cat "${DIRECTORY}/etc/git_url" || echo 'https://github.com/Botspot/pi-apps')"
@@ -314,13 +317,68 @@ runonce() { #run command only if it's never been run before. Useful for one-time
}
+format_log_file() { #remove ANSI escape sequences from a given file, and add OS information to beginning of file
+ [ -z "$1" ] && error "format_log_file: no filename given!"
+ [ ! -f "$1" ] && error "format_log_file: given filename ($1) does not exist or is not a file!"
+
+ echo -e "$(get_device_info)\n\nBEGINNING OF ERROR LOG:\n-----------------------\n\n$(cat "$1" | sed 's/\x1b\[[0-9;]*m//g' | sed 's/\x1b\[[0-9;]*//g')" > "$1"
+
+}
+
+get_device_info() { #returns information about current install and hardware
+ echo "OS: $(cat /etc/os-release | grep PRETTY_NAME | tr -d '"' | awk -F= '{print $2}')"
+ echo "Kernel: $(uname -m) $(uname -r)"
+ echo "Userland CPU architecture: ${arch}-bit"
+
+ if [ -f /etc/rpi-issue ];then
+ echo "Raspberry Pi OS image version: $(cat /etc/rpi-issue | grep 'Raspberry Pi reference' | sed 's/Raspberry Pi reference //g')"
+ fi
+
+ if [ -f "${DIRECTORY}/gui" ];then
+ echo "Pi-Apps gui script datestamp: $(date -r "${DIRECTORY}/gui")"
+ fi
+
+}
+
+send_error_report() { #non-interactively send a Pi-Apps error log file to the Botspot discord server
+ [ -z "$1" ] && error "send_error_report(): requires an argument"
+ [ ! -f "$1" ] && error "send_error_report(): '$1' is not a valid file."
+
+ command -v curl >/dev/null || error "send_error_report(): Cannot send report: curl command not found!"
+
+ errors="$(curl -F "file=@\"$1\";filename=\"$(basename "$1" | sed 's/\.log.*/.txt/g')\"" "$(wget -qO- https://raw.githubusercontent.com/Botspot/pi-apps-analytics/main/error-log-webhook | base64 -d)" 2>&1)"
+ [ $? != 0 ] && error "curl failed to upload log file!\nErrors:\n$errors"
+
+}
+
+send_error_report_gui() { #Ask user for permission to send error report
+ [ -z "$1" ] && error "send_error_report_gui(): requires an argument for error report file!"
+ [ ! -f "$1" ] && error "send_error_report_gui(): Given error report file ($1) does not exist!"
+ [ -z "$2" ] && error "send_error_report_gui(): requires an argument for window text!"
+
+ export -f text_editor
+ export DIRECTORY
+
+ yad --center --title="Send error report?" --window-icon="${DIRECTORY}/icons/logo.png" \
+ --text="$2"$'\n'"Send error report to Pi-Apps developers?"$'\n'"Help is available on Discord and Github." --on-top \
+ --button='Send report'!"${DIRECTORY}/icons/upload.png":0 \
+ --button='View report'!"${DIRECTORY}/icons/log-file.png"!"View the log file to be sent."$'\n'"Feel free to edit the file with more debug information to help us.":"bash -c 'text_editor "\""$1"\""'" \
+ --button="Don't send"!"${DIRECTORY}/icons/exit.png":1
+ button=$?
+ #echo "Button: $button"
+
+ if [ "$button" == 0 ];then
+ send_error_report "$1"
+ fi
+
+}
+
#if this script is being run standalone, not sourced
-if [[ "$0" == */api ]];then
- #if user input a function command, then run it with arguments.
+if [[ "$0" == */api ]];then
if [ ! -z "$1" ];then
+ #if user input a function command, then run it with arguments.
#Keep in mind this could run any command the user wanted, not necessarily exclusively function commands.
"$@"
- #"$1" "$2" "$3" "$4" "$5" "$6"
fi
fi
diff --git a/manage b/manage
index 1876368..5375817 100755
--- a/manage
+++ b/manage
@@ -14,14 +14,6 @@ if [ -z "$1" ];then
error "You need to specify an operation, and in most cases, which app to operate on."
fi
-rm_esc() { #remove ANSI escape sequences from a given file
- [ -z "$1" ] && error "rm_esc: no filename given!"
- [ ! -f "$1" ] && error "rm_esc: given filename ($1) does not exist or is not a file!"
-
- sed -i 's/\x1b\[[0-9;]*m//g' "$1"
-
-}
-
source "${DIRECTORY}/api" || error "failed to source ${DIRECTORY}/api"
mkdir -p "${DIRECTORY}/data/status" "${DIRECTORY}/data/update-status" "${DIRECTORY}/logs"
@@ -46,68 +38,60 @@ dirhash() {
}
if [ "$1" == 'multi-install' ];then
- failed=0
- PREIFS="$IFS"
+
+ failed_apps=''
+
IFS=$'\n'
for app in $2
do
"${DIRECTORY}/manage" install "$app"
if [ $? != 0 ];then
- failed=1
+ #this app failed to install - add it to the list of failed apps
+ failed_apps="$failed_apps
+$app"
+ fi
+ done
+ app_results="${app_results:1}" #remove first blank newline
+
+ for app in $failed_apps ;do
+ logfile="$(ls -dt "${DIRECTORY}/logs"/* | grep '\-'"${app}"'\.log' -m 1)" #sort logfiles by modification date, get the most recent one for the current app
+
+ #if logfile detected, exists, and is not empty, ask permission to send error report
+ if [ ! -z "$logfile" ] && [ -f "$logfile" ] && [ -s "$logfile" ];then
+ send_error_report_gui "$logfile" "$app failed to install."
fi
done
- IFS="$PREIFS"
- if [ $failed == 1 ];then
+ if [ ! -z "$failed_apps" ];then
exit 1
- #disable donate box
- elif false && [ "$(ls "${DIRECTORY}/data/status" | wc -l)" -ge 5 ] && [ "$(($(date --utc --date '' +%s)/86400-30))" -ge "$(cat "${DIRECTORY}/data/last-donate-ask" 2>/dev/null || echo "0")" ];then
- donatebox() {
- TEXT="$(wget -qO- https://raw.githubusercontent.com/Botspot/pi-apps-announcements/main/donate_message)"
- if [ -z "$TEXT" ];then
- TEXT=" Pi-Apps depends on you!
-
- I (Botspot) have spent over 300 hours programming Pi-Apps.
- Without financial support, I can't continue developing Pi-Apps as much as I have been. :(
- If every Pi-Apps user pitched in a mere 25 cents, I could work on open-source development full-time.
-
- If Pi-Apps has saved you time & effort, please consider donating. Any amount helps.
-"
- fi
- yad --title="Donations, anyone?" --center \
- --window-icon="${DIRECTORY}/icons/logo.png" \
- --text="$(echo -e "$TEXT")" \
- --button='Support Pi-Apps'!"${DIRECTORY}/icons/paypal.png":0 \
- --button='No thanks'!"${DIRECTORY}/icons/exit.png"!"I respect your decision.
-Pi-Apps will always be free, but if everyone clicks this button, it won"\'"t be maintained forever.":1
- button=$?
-
- if [ $button == 0 ];then
- #open donation page if button 0 clicked
- #x-www-browser 'https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=V6W8WM4GN8AJ2&item_name=Pi-Apps+development¤cy_code=USD'
- x-www-browser 'https://paypal.me/josephmarchand'
- fi
- #don't ask again for 30 days, no matter what button clicked
- echo "$(($(date --utc --date '' +%s)/86400))" > "${DIRECTORY}/data/last-donate-ask"
- }
- export -f donatebox
- export DIRECTORY
- setsid bash -c donatebox
fi
+
elif [ "$1" == 'multi-uninstall' ];then
- failed=0
- PREIFS="$IFS"
+ failed_apps=''
+
IFS=$'\n'
for app in $2
do
"${DIRECTORY}/manage" uninstall "$app"
if [ $? != 0 ];then
- failed=1
+ #this app failed to install - add it to the list of failed apps
+ failed_apps="$failed_apps
+$app"
fi
done
- IFS="$PREIFS"
- if [ $failed == 1 ];then
+ app_results="${app_results:1}" #remove first blank newline
+
+ for app in $failed_apps ;do
+ logfile="$(ls -dt "${DIRECTORY}/logs"/* | grep '\-'"${app}"'\.log' -m 1)" #sort logfiles by modification date, get the most recent one for the current app
+
+ #if logfile detected, exists, and is not empty, ask permission to send error report
+ if [ ! -z "$logfile" ] && [ -f "$logfile" ] && [ -s "$logfile" ];then
+ send_error_report_gui "$logfile" "$app failed to uninstall."
+ fi
+ done
+ if [ ! -z "$failed_apps" ];then
exit 1
fi
+
elif [ "$1" == 'install-if-not-installed' ];then
#if not installed
@@ -115,6 +99,7 @@ elif [ "$1" == 'install-if-not-installed' ];then
#install it
"${DIRECTORY}/manage" install "$2" || exit 1
fi
+
elif [ "$1" == 'install' ];then
#INSTALL
#for this operation, a program name must be specified.
@@ -151,13 +136,13 @@ elif [ "$1" == 'install' ];then
#determine path for log file to be created
logfile="${DIRECTORY}/logs/install-incomplete-${app}.log"
- if [ -f "$logfile" ] || [ -f "$(echo "$logfile" | sed 's+/-incomplete-+/-success-+g')" ] || [ -f "$(echo "$logfile" | sed 's+/-incomplete-+/-fail-+g')" ];then
+ if [ -f "$logfile" ] || [ -f "$(echo "$logfile" | sed 's+-incomplete-+-success-+g')" ] || [ -f "$(echo "$logfile" | sed 's+-incomplete-+-fail-+g')" ];then
#append a number to logfile's file-extension if the original filename already exists
i=1
while true;do
#if variable $i is 2, then example newlogfile value: /path/to/install-Discord.log2
newlogfile="$logfile$i"
- if [ ! -f "$newlogfile" ] && [ ! -f "$(echo "$newlogfile" | sed 's+/-incomplete-+/-success-+g')" ] && [ ! -f "$(echo "$newlogfile" | sed 's+/-incomplete-+/-fail-+g')" ];then
+ if [ ! -f "$newlogfile" ] && [ ! -f "$(echo "$newlogfile" | sed 's+/-incomplete-+-success-+g')" ] && [ ! -f "$(echo "$newlogfile" | sed 's+-incomplete-+-fail-+g')" ];then
logfile="${newlogfile}"
break
fi
@@ -176,7 +161,7 @@ elif [ "$1" == 'install' ];then
echo 'installed' > "${DIRECTORY}/data/status/${app}"
echo -e "\n\e[42m\e[30mInstalled ${app} successfully.\e[39m\e[49m" | tee -a "$logfile"
- rm_esc "$logfile" #remove escape sequences from logfile
+ format_log_file "$logfile" #remove escape sequences from logfile
mv "$logfile" "$(echo "$logfile" | sed 's+-incomplete-+-success-+g')" #
exit 0
else
@@ -185,7 +170,7 @@ elif [ "$1" == 'install' ];then
Please ask on Github: \e[94m\e[4mhttps://github.com/Botspot/pi-apps/issues/new/choose\e[24m\e[93m
Or on Discord: \e[94m\e[4mhttps://discord.gg/RXSTvaUvuu\e[24m\e[39m" | tee -a "$logfile"
- rm_esc "$logfile" #remove escape sequences from logfile
+ format_log_file "$logfile" #remove escape sequences from logfile
mv "$logfile" "$(echo "$logfile" | sed 's+-incomplete-+-fail-+g')"
exit 1
fi
@@ -236,7 +221,7 @@ elif [ "$1" == 'uninstall' ];then
if nice "${DIRECTORY}/apps/${app}/uninstall" 2>&1 | tee -a "$logfile"; then
echo 'uninstalled' > "${DIRECTORY}/data/status/${app}"
echo -e "\n\e[42m\e[30mUninstalled ${app} successfully.\e[39m\e[49m" | tee -a "$logfile"
- rm_esc "$logfile" #remove escape sequences from logfile
+ format_log_file "$logfile" #remove escape sequences from logfile
mv "$logfile" "$(echo "$logfile" | sed 's+-incomplete-+-success-+g')"
exit 0
else
@@ -244,10 +229,11 @@ elif [ "$1" == 'uninstall' ];then
\e[40m\e[93m\e[5m▲\e[25m\e[39m \e[49m\e[93mNeed help? Copy the \e[1mENTIRE\e[0m\e[49m\e[93m terminal output or take a screenshot.
Please ask on Github: \e[94m\e[4mhttps://github.com/Botspot/pi-apps/issues/new/choose\e[24m\e[93m
Or on Discord: \e[94m\e[4mhttps://discord.gg/RXSTvaUvuu\e[24m\e[39m" | tee -a "$logfile"
- rm_esc "$logfile" #remove escape sequences from logfile
+ format_log_file "$logfile" #remove escape sequences from logfile
mv "$logfile" "$(echo "$logfile" | sed 's+-incomplete-+-fail-+g')"
exit 1
fi
+
elif [ "$1" == 'update' ];then
#UPDATE
#for this operation, a program name must be specified.
@@ -301,7 +287,7 @@ elif [ "$1" == 'update' ];then
#move old program to trash
gio trash "${DIRECTORY}/apps/${app}" 2>/dev/null
#failsafe
- [ -d "${DIRECTORY}/apps/${app}" ] && error "${DIRECTORY}/apps/${app} still exists, despite trying to delete it!"
+ [ -d "${DIRECTORY}/apps/${app}" ] && rm -rf "${DIRECTORY}/apps/${app}"
#copy new version from update/ to apps/
cp -rf "${DIRECTORY}/update/pi-apps/apps/${app}" "${DIRECTORY}/apps/${app}"
@@ -312,6 +298,7 @@ elif [ "$1" == 'update' ];then
"${DIRECTORY}/manage" install "$app"
fi
echo -e "\e[92m${app} was updated successfully.\e[39m"
+
elif [ "$1" == 'check-all' ];then
#CHECK-ALL
#for this operation, a program name cannot be specified.
@@ -363,7 +350,6 @@ elif [ "$1" == 'check-all' ];then
#echo "App list: $applist" 1>&2
updatable=''
- PREIFS="$IFS"
IFS=$'\n'
for app in $applist
do
@@ -396,7 +382,6 @@ ${app}"
fi
done
- IFS="$PREIFS"
#remove initial newline character
updatable="${updatable:1}"
@@ -410,7 +395,6 @@ ${app}"
elif [ "$1" == 'update-all' ];then
#UPDATE-ALL
#for this operation, a program name cannot be specified.
- PREIFS="$IFS"
IFS=$'\n'
updatable="$("${DIRECTORY}/manage" check-all)"
if [ "$updatable" == '.' ];then
@@ -423,8 +407,7 @@ elif [ "$1" == 'update-all' ];then
#update it using a recursive script instance
echo "${DIRECTORY}/manage update $updateapp"
"${DIRECTORY}/manage" update "$updateapp" || exit 1
- done
- IFS="$PREIFS"
+ done
echo -e '\e[92mOperation completed successfully!\e[39m'
else
error "Did not understand $1. Allowed values: 'install', 'multi-install', 'install-if-not-installed', 'uninstall', 'multi-uninstall', 'update','update-all', or 'check-all'."