You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Botspot-Pi-Apps/manage

301 lines
12 KiB
Plaintext

4 years ago
#!/bin/bash
4 years ago
#$1 is an action, like install
#$2 is app name, like Arduino
4 years ago
DIRECTORY="$(readlink -f "$(dirname "$0")")"
function error {
4 years ago
echo -e "\e[91m$1\e[39m"
4 years ago
exit 1
}
if [ -z "$1" ];then
4 years ago
error "You need to specify an operation, and in most cases, which app to operate on."
4 years ago
fi
mkdir -p "${DIRECTORY}/data/status" "${DIRECTORY}/data/update-status"
4 years ago
#determine if host system is 64 bit arm64 or 32 bit armhf
if [ ! -z "$(file "$(readlink -f "/sbin/init")" | grep 64)" ];then
arch=64
elif [ ! -z "$(file "$(readlink -f "/sbin/init")" | grep 32)" ];then
arch=32
else
error "Failed to detect OS CPU architecture! Something is very wrong."
fi
dirhash() {
#find "${DIRECTORY}/update/pi-apps/apps/${2}" -type f -print0
#echo "Hashing this dir: $1" 1>&2
#------ hash every file in the folder ---------------- and add to it the filesystem list ------ hash it again
hash="$(echo -e "$(find "$1" -type f -print0 | xargs -0 sha1sum | awk '{print $1}')$(find "$1" -type f -exec basename {} \;)" | sha1sum | awk '{print $1}')"
echo "$hash"
echo "$hash" 1>&2
}
4 years ago
if [ "$1" == 'install' ];then
4 years ago
#INSTALL
4 years ago
#for this operation, a program name must be specified.
app="$2"
if [ -z "$app" ];then
4 years ago
error "For this operation, you must specify which app to operate on."
elif [ ! -d "${DIRECTORY}/apps/$app" ];then
error "${DIRECTORY}/apps/$app does not exist!"
4 years ago
fi
4 years ago
#ensure an install script is not already running
if ps -C install &>/dev/null || ps -C install-32 &>/dev/null || ps -C install-64 &>/dev/null;then
4 years ago
echo "An install script is already running.
Pi-Apps will wait until that one finishes before installing $app." | yad --text-info \
4 years ago
--title="Waiting" --window-icon="${DIRECTORY}/icons/logo.png" --center --width=500 --height=100 \
--button=OK!"${DIRECTORY}/icons/check.png":0 --fontname=12 --timeout=10 --timeout-indicator=top
while ps -C install &>/dev/null || ps -C install-32 &>/dev/null || ps -C install-64 &>/dev/null;do sleep 1; done
4 years ago
fi
#if already installed then ask for confirmation
if [ "$(cat "${DIRECTORY}/data/status/${app}" )" == 'installed' ];then
yad --text="$app is already installed. Are you sure you want to install it again?" \
4 years ago
--text-align=center --center --title='Quick question' --window-icon="${DIRECTORY}/icons/logo.png" \
--button=No!"${DIRECTORY}/icons/exit.png":1 --button=Yes!"${DIRECTORY}/icons/check.png":0 || exit 0
fi
4 years ago
#analytics
if [ "$(cat "${DIRECTORY}/data/settings/Enable analytics")" == 'Yes' ];then
#this is used to let Botspot see the daily installs for each app.
#Botspot created an individual bitly link for each app. When you install an app, the cooresponding bit.ly link is "clicked" by a headless chromium-browser instance.
#Chromium accesses the bit.ly link, then exits.
#Allowing analytics does not identify you, or any personal information about you. Botspot can only see the number of "clicks" per day, as well as the top 10 countries of origin.
bitlylink="https://bit.ly/pi-apps-install-$(echo "$app" | tr -d ' ' | sed 's/[^a-zA-Z]//g')"
4 years ago
chromium-browser --headless "$bitlylink" &>/dev/null &
fi
#determine which script to run
if [ -f "${DIRECTORY}/apps/${app}/install-32" ] && [ $arch == 32 ];then
installscript="${DIRECTORY}/apps/${app}/install-32"
scriptname='install-32'
elif [ -f "${DIRECTORY}/apps/${app}/install-64" ] && [ $arch == 64 ];then
installscript="${DIRECTORY}/apps/${app}/install-64"
scriptname='install-64'
elif [ -f "${DIRECTORY}/apps/${app}/install" ];then
installscript="${DIRECTORY}/apps/${app}/install"
scriptname='install'
else
error "It appears $app does not have an install-${arch} script suitable for your ${arch}-bit OS."
fi
echo -e "\e[96mInstalling $app with $scriptname script\e[39m"
cd $HOME
echo 'corrupted' > "${DIRECTORY}/data/status/${app}"
if "$installscript" ; then
echo 'installed' > "${DIRECTORY}/data/status/${app}"
echo -en "\n\e[42m\e[30mInstalled ${app} successfully.\e[39m\e[49m"
exit 0
else
echo -en "\n\e[41m\e[30mFailed to install ${app} with $scriptname script!\e[39m\e[49m"
exit 1
fi
4 years ago
elif [ "$1" == 'uninstall' ];then
4 years ago
#UNINSTALL
4 years ago
#for this operation, a program name must be specified.
app="$2"
if [ -z "$app" ];then
4 years ago
error "For this operation, you must specify which app to operate on."
elif [ ! -d "${DIRECTORY}/apps/$app" ];then
error "${DIRECTORY}/apps/$app does not exist!"
4 years ago
fi
4 years ago
#ensure an uninstall script is not already running
4 years ago
if ps -C uninstall &>/dev/null;then
4 years ago
echo "An uninstall script is already running.
Pi-Apps will wait until that one finishes before starting this one." | yad --text-info \
--title="Waiting" --window-icon="${DIRECTORY}/icons/logo.png" --center --width=500 --height=100 \
--button=OK!"${DIRECTORY}/icons/check.png":0 --fontname=12 --timeout=10 --timeout-indicator=top
while ps -C uninstall &>/dev/null;do sleep 1; done
4 years ago
fi
#if already uninstalled then ask for confirmation
if [ "$(cat "${DIRECTORY}/data/status/${app}" )" == 'uninstalled' ];then
yad --text="$app is already uninstalled. Are you sure you want to uninstall it again?" \
4 years ago
--text-align=center --center --title='Quick question' --window-icon="${DIRECTORY}/icons/logo.png" \
--button=No!"${DIRECTORY}/icons/exit.png":1 --button=Yes!"${DIRECTORY}/icons/check.png":0 || exit 0
fi
echo -e "\e[96mUninstalling $app\e[39m"
cd $HOME
echo 'corrupted' > "${DIRECTORY}/data/status/${app}"
if "${DIRECTORY}/apps/${app}/uninstall" ; then
echo 'uninstalled' > "${DIRECTORY}/data/status/${app}"
echo -en "\n\e[42m\e[30mUninstalled ${app} successfully.\e[39m\e[49m"
exit 0
else
echo -en "\n\e[41m\e[30mFailed to uninstall ${app}!\e[39m\e[49m"
exit 1
fi
4 years ago
elif [ "$1" == 'update' ];then
4 years ago
#UPDATE
4 years ago
#for this operation, a program name must be specified.
app="$2"
if [ -z "$app" ];then
4 years ago
error "For this operation, you must specify which app to operate on."
fi
4 years ago
#HIDDEN FEATURE - if $3 equals nofetch, then don't download github repo. Useful for updating multiple apps at maximum speed
if [ "$3" == 'nofetch' ] && [ -d "${DIRECTORY}/update" ];then
true
else
rm -rf "${DIRECTORY}/update" && mkdir "${DIRECTORY}/update" && cd "${DIRECTORY}/update" || error "failed to enter the update directory!"
git clone "$(cat "${DIRECTORY}/etc/git_url")" || error "failed to clone repository!"
4 years ago
fi
4 years ago
newhash="$(dirhash "${DIRECTORY}/update/pi-apps/apps/${app}")"
oldhash="$(dirhash "${DIRECTORY}/apps/${app}")"
4 years ago
#detect which installation script exists and get the hash for that one
if [ -f "${DIRECTORY}/update/pi-apps/apps/${app}/install-32" ];then
scriptname='install-32'
elif [ -f "${DIRECTORY}/update/pi-apps/apps/${app}/install-64" ];then
scriptname='install-64'
elif [ -f "${DIRECTORY}/update/pi-apps/apps/${app}/install" ];then
scriptname='install'
else
error "No install script found for the $app app! Please report this to Botspot."
fi
newinstallhash=$(sha1sum "${DIRECTORY}/update/pi-apps/apps/${app}/${scriptname}" | awk '{print $1}')
oldinstallhash=$(sha1sum "${DIRECTORY}/apps/${app}/${scriptname}" | awk '{print $1}')
#echo -e "newinstallhash: $newinstallhash\noldinstallhash: $oldinstallhash"
#echo -e "newhash: $newhash\noldhash: $oldhash"
4 years ago
if [ "$newhash" == "$oldhash" ];then
echo "$app is identical to the online version. Nothing to do!"
4 years ago
exit 0
else
echo "$app is not identical to the online version. Reinstalling..."
4 years ago
fi
#else
installback=no
#if install was changed
if [ ! "$newinstallhash" == "$oldinstallhash" ];then
#if installed already
if [ "$(cat "${DIRECTORY}/data/status/${app}")" == 'installed' ];then
installback=yes
#uninstall it using a recursive script instance
"${DIRECTORY}/manage" uninstall "$app"
fi
4 years ago
fi
#move old program to trash
gio trash "${DIRECTORY}/apps/${app}" 2>/dev/null
4 years ago
#failsafe
[ -d "${DIRECTORY}/apps/${app}" ] && error "${DIRECTORY}/apps/${app} still exists, despite trying to delete it!"
4 years ago
#copy new version to apps/
cp -rf "${DIRECTORY}/update/pi-apps/apps/${app}" "${DIRECTORY}/apps/${app}"
4 years ago
if [ "$installback" == 'yes' ] && [ "$(cat "${DIRECTORY}/data/settings/Reinstall after update")" != 'No' ];then
echo "$app was originally installed before updating. Reinstalling the new version now."
4 years ago
#install it using a recursive script instance
"${DIRECTORY}/manage" install "$app"
4 years ago
fi
echo -e "\e[92m${app} was updated successfully.\e[39m"
4 years ago
elif [ "$1" == 'check-all' ];then
#CHECK-ALL
4 years ago
#for this operation, a program name cannot be specified.
4 years ago
#hidden flag: if $2 is 'installedonly', then only check for updates for those apps that are installed
if [ "$2" == 'installedonly' ];then
installedonly=1
else
installedonly=0
fi
rm -rf "${DIRECTORY}/update" && mkdir "${DIRECTORY}/update" && cd "${DIRECTORY}/update" || error "failed to enter the update directory!"
git clone "$(cat "${DIRECTORY}/etc/git_url")" || error "failed to clone repository!"
#generate entire app list, combine local apps and online apps to one list
applist="$(echo -e "$(ls "${DIRECTORY}/update/pi-apps/apps")\n$(ls "${DIRECTORY}/apps")" | sort | uniq)"
#installedonly flag enabled. Remove apps that are uninstalled
if [ $installedonly == 1 ];then
echo "installedonly flag set to 1" 1>&2
PREIFS="$IFS"
IFS=$'\n'
for app in $applist
do
if [ ! -f "${DIRECTORY}/data/status/${app}" ] || [ "$(cat "${DIRECTORY}/data/status/${app}")" == 'uninstalled' ];then
#if app is uninstalled, then remove it from the list.
applist="$(echo "$applist" | grep -vx "$app")"
echo "Removing ${app} from list because it is uninstalled." 1>&2
fi
done
IFS="$PREIFS"
fi
applist="$(echo "$applist" | tr '\n' '|')"
#echo "App list: $applist" 1>&2
4 years ago
updatable=''
PREIFS="$IFS"
IFS="|"
for app in $applist
4 years ago
do
#echo "app: $app"
newhash="$(dirhash "${DIRECTORY}/update/pi-apps/apps/${app}")"
oldhash="$(dirhash "${DIRECTORY}/apps/${app}")"
#echo -e "newhash: $newhash\noldhash: $oldhash" 1>&2
4 years ago
if [ "$newhash" == "$oldhash" ];then
echo -e "${app} is identical\e[90m to the online version. Nothing to do!\e[39m" 1>&2
echo 'latest' > "${DIRECTORY}/data/update-status/${app}"
4 years ago
else
if [ ! -d "${DIRECTORY}/apps/${app}" ];then
echo -e "\e[97m${app} does not exist locally.\e[39m Adding to updatable list." 1>&2
echo 'new' > "${DIRECTORY}/data/update-status/${app}"
4 years ago
#in this case, add to updatable list
updatable="${updatable}|${app}"
elif [ ! -d "${DIRECTORY}/update/pi-apps/apps/${app}" ];then
echo -e "\e[97m${app} only exists locally.\e[39m Will not add to updatable list." 1>&2
echo 'local' > "${DIRECTORY}/data/update-status/${app}"
4 years ago
#in this case, do not add to updatable list
else
echo -e "\e[97m${app} exists in both locations, but online version is newer\e[39m. Adding to updatable list." 1>&2
echo 'updatable' > "${DIRECTORY}/data/update-status/${app}"
4 years ago
#in this case, add to updatable list
updatable="${updatable}|${app}"
4 years ago
fi
4 years ago
fi
4 years ago
done
IFS="$PREIFS"
4 years ago
#remove initial '|' character
updatable="${updatable:1}"
if [ -z "$updatable" ];then
updatable='.'
fi
4 years ago
echo -e "\e[97mThese apps can be updated:\n${updatable}"
4 years ago
elif [ "$1" == 'update-all' ];then
4 years ago
#UPDATE-ALL
4 years ago
#for this operation, a program name cannot be specified.
PREIFS="$IFS"
IFS='|'
updatable="$("${DIRECTORY}/manage" check-all | tail -1)"
echo "Updatable: ${updatable}EOU"
for updateapp in $updatable
do
echo "updating $updateapp"
#update it using a recursive script instance
echo "${DIRECTORY}/manage update $updateapp"
4 years ago
"${DIRECTORY}/manage" update "$updateapp" || exit 1
4 years ago
done
IFS="$PREIFS"
4 years ago
echo -e '\e[92mOperation completed successfully!\e[39m'
4 years ago
else
4 years ago
error "Did not understand ${1}. It must be either "\'"install"\'", "\'"uninstall"\'", "\'"update"\'", "\'"check-all"\'", or "\'"update-all"\'"."
4 years ago
fi