329 lines
8.6 KiB
Bash
Executable File
329 lines
8.6 KiB
Bash
Executable File
#!/bin/bash
|
|
|
|
REQUIRED_TOOLS=("android-tools" "ideviceinstaller" "usbmuxd" "gum" "idevice_id")
|
|
|
|
echo -n "📦 Checking and installing dependencies... "
|
|
# OS Detection
|
|
if [ -f /etc/os-release ]; then
|
|
. /etc/os-release
|
|
OS=$ID
|
|
else
|
|
echo "Unsupported OS. Manual installation required."
|
|
exit 1
|
|
fi
|
|
|
|
# Install dependancies
|
|
install_tool() {
|
|
local tool=$1
|
|
echo "--- Tool '$tool' is missing. ---"
|
|
read -p "Would you like to install $tool? (y/n): " confirm
|
|
|
|
if [[ $confirm == [yY] || $confirm == [yY][eE][sS] ]]; then
|
|
case $OS in
|
|
ubuntu|debian|kali|pop|mint|linuxmint|kubuntu|xubuntu|lubuntu|elementary|zorin)
|
|
sudo apt update && sudo apt install -y "$tool"
|
|
echo "'$tool' Installed"
|
|
;;
|
|
fedora|rhel|centos)
|
|
sudo dnf install -y "$tool" > /dev/null 2>&1
|
|
;;
|
|
*)
|
|
echo "Package manager for '$OS' not defined in this script."
|
|
exit 1
|
|
;;
|
|
esac
|
|
else
|
|
echo "Exiting: $tool is required for this script."
|
|
exit 1
|
|
fi
|
|
}
|
|
|
|
# Confirm everything installed correctly
|
|
for tool in "${REQUIRED_TOOLS[@]}"; do
|
|
if ! command -v "$tool" &> /dev/null; then
|
|
install_tool "$tool"
|
|
fi
|
|
done
|
|
|
|
ORANGE="#FFA500"
|
|
GREY="#808080"
|
|
|
|
export GUM_STYLE_BORDER_FOREGROUND="$ORANGE"
|
|
export GUM_STYLE_LABEL_FOREGROUND="$ORANGE"
|
|
export GUM_STYLE_PROMPT_FOREGROUND="$ORANGE"
|
|
export GUM_STYLE_CURSOR_FOREGROUND="$ORANGE"
|
|
export GUM_STYLE_SELECTED_FOREGROUND="$ORANGE"
|
|
export GUM_STYLE_FOREGROUND="$GREY"
|
|
|
|
IPA_DIR="$HOME/Documents/Mobile_Apps/IPA"
|
|
APK_DIR="$HOME/Documents/Mobile_Apps/APK"
|
|
|
|
# Create folders if they don't exist
|
|
mkdir -p "$IPA_DIR"
|
|
mkdir -p "$APK_DIR"
|
|
|
|
clear
|
|
|
|
# Title
|
|
gum style \
|
|
--border double \
|
|
--padding "1 4" \
|
|
--margin "1 2" \
|
|
--align center \
|
|
--foreground "$ORANGE" \
|
|
"📱 Linux Mobile App Installer"
|
|
|
|
|
|
check_ios() {
|
|
if ! idevice_id -l | grep -q .; then
|
|
gum style --foreground "$ORANGE" --border rounded --padding "1 2" \
|
|
"❌ iPhone not found."
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
check_android() {
|
|
if ! adb devices | grep -w "device" | grep -v "List" >/dev/null; then
|
|
gum style --foreground "$ORANGE" --border rounded --padding "1 2" \
|
|
"❌ Android device not found."
|
|
return 1
|
|
fi
|
|
return 0
|
|
}
|
|
|
|
|
|
ios_view_apps() {
|
|
check_ios || return
|
|
|
|
RAW=$(gum spin --spinner dot --title "Scanning apps..." -- \
|
|
ideviceinstaller list 2>/dev/null)
|
|
|
|
APPS=$(echo "$RAW")
|
|
|
|
if [ -z "$APPS" ]; then
|
|
gum style --foreground "$GREY" "No apps found."
|
|
else
|
|
echo "$APPS" | gum pager
|
|
fi
|
|
}
|
|
|
|
ios_install() {
|
|
check_ios || return
|
|
|
|
METHOD=$(printf "From IPA folder\nBrowse files" | gum choose)
|
|
|
|
if [[ "$METHOD" == "From IPA folder" ]]; then
|
|
FILE=$(ls "$IPA_DIR"/*.{ipa,tar.bz2} 2>/dev/null | gum choose)
|
|
else
|
|
FILE=$(gum file)
|
|
fi
|
|
|
|
[ ! -f "$FILE" ] && gum style --foreground "$ORANGE" "❌ Invalid file." && return
|
|
|
|
TMP_DIR=""
|
|
INSTALL_FILE="$FILE"
|
|
|
|
if [[ "$FILE" == *.tar.bz2 ]]; then
|
|
TMP_DIR=$(mktemp -d)
|
|
|
|
gum spin --spinner dot --title "Extracting File..." -- \
|
|
bash -c "tar -xjf \"$FILE\" -C \"$TMP_DIR\" >/dev/null 2>&1"
|
|
|
|
INSTALL_FILE=$(find "$TMP_DIR" -name "*.ipa" | head -n 1)
|
|
|
|
[ -z "$INSTALL_FILE" ] && gum style --foreground "$ORANGE" "❌ No IPA found." && return
|
|
fi
|
|
|
|
OUTPUT=$(mktemp)
|
|
|
|
gum spin --spinner dot --title "Installing app..." -- \
|
|
bash -c "ideviceinstaller install \"$INSTALL_FILE\" > \"$OUTPUT\" 2>&1"
|
|
|
|
if grep -q "Install: Complete" "$OUTPUT"; then
|
|
gum style --foreground "$ORANGE" --border rounded --padding "1 2" \
|
|
"✅ Installation successful!"
|
|
else
|
|
gum style --foreground "$ORANGE" --border rounded --padding "1 2" \
|
|
"⚠️ Installation may have failed.\n\n$(tail -n 5 "$OUTPUT")"
|
|
fi
|
|
|
|
rm -f "$OUTPUT"
|
|
[ -n "$TMP_DIR" ] && rm -rf "$TMP_DIR"
|
|
}
|
|
|
|
ios_uninstall() {
|
|
check_ios || return
|
|
|
|
RAW=$(gum spin --spinner dot --title "Loading apps..." -- \
|
|
ideviceinstaller list 2>/dev/null)
|
|
|
|
APPS=$(echo "$RAW")
|
|
|
|
[ -z "$APPS" ] && gum style --foreground "$GREY" "No apps found." && return
|
|
|
|
SELECT=$(echo "$APPS" | gum choose)
|
|
BUNDLE=$(echo "$SELECT" | cut -d',' -f1)
|
|
|
|
if gum confirm "Uninstall $BUNDLE?"; then
|
|
OUT=$(mktemp)
|
|
|
|
gum spin --spinner dot --title "Uninstalling..." -- \
|
|
bash -c "ideviceinstaller uninstall \"$BUNDLE\" > \"$OUT\" 2>&1"
|
|
|
|
if grep -q "Complete" "$OUT"; then
|
|
gum style --foreground "$ORANGE" --border rounded --padding "1 2" \
|
|
"✅ Uninstall successful!"
|
|
else
|
|
gum style --foreground "$ORANGE" --border rounded --padding "1 2" \
|
|
"⚠️ Uninstall may have failed."
|
|
fi
|
|
|
|
rm -f "$OUT"
|
|
fi
|
|
}
|
|
|
|
|
|
android_view_apps() {
|
|
check_android || return
|
|
|
|
APPS=$(gum spin --spinner dot --title "Scanning apps..." -- \
|
|
adb shell pm list packages --user 0)
|
|
|
|
[ -z "$APPS" ] && gum style --foreground "$GREY" "No apps found." || echo "$APPS" | gum pager
|
|
}
|
|
|
|
android_install() {
|
|
check_android || return
|
|
|
|
METHOD=$(printf "From APK folder\nBrowse files" | gum choose)
|
|
|
|
if [[ "$METHOD" == "From APK folder" ]]; then
|
|
FILE=$(ls "$APK_DIR"/*.{apk,tar.bz2} 2>/dev/null | gum choose)
|
|
else
|
|
FILE=$(gum file)
|
|
fi
|
|
|
|
[ ! -f "$FILE" ] && gum style --foreground "$ORANGE" "❌ Invalid file." && return
|
|
|
|
TMP_DIR=""
|
|
INSTALL_FILE="$FILE"
|
|
|
|
# Handle tar.bz2
|
|
if [[ "$FILE" == *.tar.bz2 ]]; then
|
|
TMP_DIR=$(mktemp -d)
|
|
|
|
gum spin --spinner dot --title "Extracting File..." -- \
|
|
bash -c "tar -xjf \"$FILE\" -C \"$TMP_DIR\" >/dev/null 2>&1"
|
|
|
|
INSTALL_FILE=$(find "$TMP_DIR" -name "*.apk" | head -n 1)
|
|
|
|
if [ -z "$INSTALL_FILE" ]; then
|
|
gum style --foreground "$ORANGE" "❌ No APK found in archive."
|
|
rm -rf "$TMP_DIR"
|
|
return
|
|
fi
|
|
fi
|
|
|
|
OUT=$(mktemp)
|
|
|
|
gum spin --spinner dot --title "Installing APK..." -- \
|
|
bash -c "adb install \"$INSTALL_FILE\" > \"$OUT\" 2>&1"
|
|
|
|
if grep -q "Success" "$OUT"; then
|
|
gum style \
|
|
--foreground "$ORANGE" \
|
|
--border rounded \
|
|
--padding "1 2" \
|
|
"✅ Installation successful!"
|
|
else
|
|
gum style \
|
|
--foreground "$ORANGE" \
|
|
--border rounded \
|
|
--padding "1 2" \
|
|
"⚠️ Install may have failed.\n\n$(tail -n 5 "$OUT")"
|
|
fi
|
|
|
|
rm -f "$OUT"
|
|
[ -n "$TMP_DIR" ] && rm -rf "$TMP_DIR"
|
|
}
|
|
|
|
android_uninstall() {
|
|
check_android || return
|
|
|
|
METHOD=$(printf "View all\nSearch" | gum choose)
|
|
|
|
if [[ "$METHOD" == "Search" ]]; then
|
|
SEARCH_TERM=$(gum input --placeholder "Search app (e.g., netflix)")
|
|
[ -z "$SEARCH_TERM" ] && return
|
|
|
|
APPS=$(adb shell pm list packages --user 0 | grep -i "$SEARCH_TERM")
|
|
else
|
|
APPS=$(adb shell pm list packages --user 0)
|
|
fi
|
|
|
|
[ -z "$APPS" ] && gum style --foreground "$GREY" "No apps found." && return
|
|
|
|
SELECT=$(echo "$APPS" | gum choose)
|
|
|
|
[ -z "$SELECT" ] && return
|
|
|
|
PKG=$(echo "$SELECT" | sed 's/package://')
|
|
PKG=$(echo "$PKG" | tr -d '\r')
|
|
|
|
if gum confirm "Uninstall $PKG?"; then
|
|
OUT=$(mktemp)
|
|
|
|
gum spin --spinner dot --title "Uninstalling..." -- \
|
|
bash -c "adb shell pm uninstall -k --user 0 \"$PKG\" > \"$OUT\" 2>&1"
|
|
|
|
if grep -q "Success" "$OUT"; then
|
|
gum style --foreground "$ORANGE" --border rounded --padding "1 2" \
|
|
"✅ Uninstall successful!"
|
|
else
|
|
gum style --foreground "$ORANGE" --border rounded --padding "1 2" \
|
|
"⚠️ Uninstall may have failed.\n\n$(cat "$OUT")"
|
|
fi
|
|
|
|
rm -f "$OUT"
|
|
fi
|
|
}
|
|
|
|
|
|
ios_menu() {
|
|
while true; do
|
|
CHOICE=$(printf "View installed apps\nInstall IPA\nUninstall app\nBack" | gum choose)
|
|
case "$CHOICE" in
|
|
"View installed apps") ios_view_apps ;;
|
|
"Install IPA") ios_install ;;
|
|
"Uninstall app") ios_uninstall ;;
|
|
"Back") return ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
android_menu() {
|
|
while true; do
|
|
CHOICE=$(printf "View installed apps\nInstall APK\nUninstall app\nBack" | gum choose)
|
|
case "$CHOICE" in
|
|
"View installed apps") android_view_apps ;;
|
|
"Install APK") android_install ;;
|
|
"Uninstall app") android_uninstall ;;
|
|
"Back") return ;;
|
|
esac
|
|
done
|
|
}
|
|
|
|
|
|
while true; do
|
|
|
|
CHOICE=$(printf "iPhone\nAndroid\nExit" | gum choose)
|
|
|
|
case "$CHOICE" in
|
|
"iPhone") ios_menu ;;
|
|
"Android") android_menu ;;
|
|
"Exit") clear; exit 0 ;;
|
|
esac
|
|
|
|
done
|