Skip to content

Commit

Permalink
Improve setup process, add Wifi Only downloading
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremiah-k committed Oct 19, 2024
1 parent e59d350 commit be1245c
Show file tree
Hide file tree
Showing 4 changed files with 87 additions and 51 deletions.
15 changes: 14 additions & 1 deletion app/cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import argparse
from . import downloader
from . import setup_config
import subprocess

def main():
parser = argparse.ArgumentParser(description="Fetchtastic - Meshtastic Firmware and APK Downloader")
Expand Down Expand Up @@ -33,14 +34,20 @@ def main():
# Run the downloader
downloader.main()
elif args.command == 'topic':
# Display the NTFY topic
# Display the NTFY topic and prompt to copy to clipboard
config = setup_config.load_config()
if config and config.get('NTFY_SERVER') and config.get('NTFY_TOPIC'):
ntfy_server = config['NTFY_SERVER'].rstrip('/')
ntfy_topic = config['NTFY_TOPIC']
full_url = f"{ntfy_server}/{ntfy_topic}"
print(f"Current NTFY topic URL: {full_url}")
print(f"Topic name: {ntfy_topic}")
copy_to_clipboard = input("Do you want to copy the topic name to the clipboard? [y/n] (default: yes): ").strip().lower() or 'y'
if copy_to_clipboard == 'y':
copy_to_clipboard_termux(ntfy_topic)
print("Topic name copied to clipboard.")
else:
print("You can copy the topic name from above.")
else:
print("Notifications are not set up. Run 'fetchtastic setup' to configure notifications.")
elif args.command == 'clean':
Expand All @@ -53,5 +60,11 @@ def main():
else:
parser.print_help()

def copy_to_clipboard_termux(text):
try:
subprocess.run(['termux-clipboard-set'], input=text.encode('utf-8'), check=True)
except Exception as e:
print(f"An error occurred while copying to clipboard: {e}")

if __name__ == "__main__":
main()
23 changes: 20 additions & 3 deletions app/downloader.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ def main():
firmware_versions_to_keep = config.get("FIRMWARE_VERSIONS_TO_KEEP", 2)
auto_extract = config.get("AUTO_EXTRACT", False)
extract_patterns = config.get("EXTRACT_PATTERNS", [])
wifi_only = config.get("WIFI_ONLY", True)

selected_apk_patterns = config.get('SELECTED_APK_ASSETS', [])
selected_firmware_patterns = config.get('SELECTED_FIRMWARE_ASSETS', [])
Expand Down Expand Up @@ -77,7 +78,7 @@ def download_file(url, download_path):
adapter = HTTPAdapter(max_retries=retry)
session.mount('https://', adapter)
session.mount('http://', adapter)

try:
if not os.path.exists(download_path):
log_message(f"Downloading {url}")
Expand All @@ -92,6 +93,17 @@ def download_file(url, download_path):
except requests.exceptions.RequestException as e:
log_message(f"Error downloading {url}: {e}")

def is_connected_to_wifi():
try:
result = os.popen('termux-wifi-connectioninfo').read()
if '"connected":true' in result:
return True
else:
return False
except Exception as e:
log_message(f"Error checking Wi-Fi connection: {e}")
return False

# Updated extract_files function
def extract_files(zip_path, extract_dir, patterns):
try:
Expand Down Expand Up @@ -158,7 +170,12 @@ def check_and_download(releases, latest_release_file, release_type, download_dir
else:
# Proceed to download this version
os.makedirs(release_dir, exist_ok=True)
log_message(f"Downloading new version: {release_tag}")
log_message(f"New {release_type} version {release_tag} is available.")
# Check Wi-Fi connection before downloading
if wifi_only and not is_connected_to_wifi():
log_message("Not connected to Wi-Fi. Skipping download.")
send_ntfy_notification(f"New {release_type} version {release_tag} is available, but not connected to Wi-Fi. Download will proceed when connected.")
continue # Skip downloading this release
for asset in release['assets']:
file_name = asset['name']
# Modify the matching logic here
Expand Down Expand Up @@ -252,7 +269,7 @@ def check_and_download(releases, latest_release_file, release_type, download_dir
else:
if latest_firmware_releases or latest_android_releases:
message = (
f"All Firmware and Android APK versions are up to date.\n"
f"No new downloads. All Firmware and Android APK versions are up to date or waiting for Wi-Fi connection.\n"
f"Latest Firmware releases: {', '.join(release['tag_name'] for release in latest_firmware_releases[:versions_to_download])}\n"
f"Latest Android APK releases: {', '.join(release['tag_name'] for release in latest_android_releases[:versions_to_download])}\n"
f"{datetime.now()}"
Expand Down
98 changes: 52 additions & 46 deletions app/setup_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import subprocess
import random
import string
import shutil # Added for shutil.which()
import shutil
from . import menu_apk
from . import menu_firmware
from . import downloader # Import downloader to perform first run
Expand Down Expand Up @@ -34,28 +34,23 @@ def get_downloads_dir():
def config_exists():
return os.path.exists(CONFIG_FILE)

def check_storage_setup():
# Check if the Termux storage directory and Downloads are set up and writable
storage_dir = os.path.expanduser("~/storage")
storage_downloads = os.path.expanduser("~/storage/downloads")

# If ~/storage or ~/storage/downloads doesn't exist or isn't writable, exit
if not os.path.exists(storage_dir) or not os.path.exists(storage_downloads) or not os.access(storage_downloads, os.W_OK):
print("Storage access is required to continue.")
print("Please run 'termux-setup-storage' and restart Termux before running this setup again.")
exit() # Exit the script as storage is not set up
print("Storage access has been successfully verified.")
return True
def is_termux():
return 'com.termux' in os.environ.get('PREFIX', '')

def run_setup():
# First, check if Termux storage has been set up
if is_termux() and not check_storage_setup():
print("Setup cannot continue without proper storage access.")
return

# The rest of your setup process continues here
print("Running Fetchtastic Setup...")

# Install required Termux packages first
if is_termux():
install_termux_packages()
# Run termux-setup-storage
setup_storage()
# After setting up storage, inform the user and exit
print("Termux storage has been set up, and required packages have been installed.")
print("Please restart Termux and run 'fetchtastic setup' again to continue.")
exit()

# The rest of your setup process continues here
if not os.path.exists(DEFAULT_CONFIG_DIR):
os.makedirs(DEFAULT_CONFIG_DIR)

Expand Down Expand Up @@ -121,6 +116,10 @@ def run_setup():
else:
config['AUTO_EXTRACT'] = False

# Ask if the user wants to only download when connected to Wi-Fi
wifi_only = input("Do you want to only download when connected to Wi-Fi? [y/n] (default: yes): ").strip().lower() or 'y'
config['WIFI_ONLY'] = True if wifi_only == 'y' else False

# Set the download directory to the same as the config directory
download_dir = DEFAULT_CONFIG_DIR
config['DOWNLOAD_DIR'] = download_dir
Expand Down Expand Up @@ -182,21 +181,42 @@ def run_setup():
else:
print("Setup complete. Run 'fetchtastic download' to start downloading.")

def is_termux():
return 'com.termux' in os.environ.get('PREFIX', '')

def copy_to_clipboard_termux(text):
try:
subprocess.run(['termux-clipboard-set'], input=text.encode('utf-8'), check=True)
except Exception as e:
print(f"An error occurred while copying to clipboard: {e}")

def install_termux_packages():
# Install termux-api and termux-services if they are not installed
packages_to_install = []
# Check for termux-api
if shutil.which('termux-battery-status') is None:
packages_to_install.append('termux-api')
# Check for termux-services
if shutil.which('sv-enable') is None:
packages_to_install.append('termux-services')
if packages_to_install:
print("Installing required Termux packages...")
subprocess.run(['pkg', 'install'] + packages_to_install + ['-y'], check=True)
print("Required Termux packages installed.")
else:
print("All required Termux packages are already installed.")

def setup_storage():
# Run termux-setup-storage
print("Setting up Termux storage access...")
subprocess.run(['termux-setup-storage'], check=True)

def install_crond():
try:
crond_path = shutil.which('crond')
if crond_path is None:
print("Installing crond...")
subprocess.run(['pkg', 'install', 'termux-services', '-y'], check=True)
# Ensure termux-services is installed
if shutil.which('sv-enable') is None:
subprocess.run(['pkg', 'install', 'termux-services', '-y'], check=True)
# Enable crond service
subprocess.run(['sv-enable', 'crond'], check=True)
print("crond installed and started.")
else:
Expand All @@ -221,35 +241,21 @@ def setup_cron_job():
if keep_cron == 'n':
# Remove existing fetchtastic cron jobs
new_cron = '\n'.join([line for line in existing_cron.split('\n') if 'fetchtastic download' not in line])
# Add new cron job
new_cron += f"\n0 3 * * * fetchtastic download\n"
# Update crontab
process = subprocess.Popen(['crontab', '-'], stdin=subprocess.PIPE, text=True)
process.communicate(input=new_cron)
print("Existing Fetchtastic cron job removed.")
# Ask if they want to add a new cron job
add_cron = input("Would you like to schedule Fetchtastic to run daily at 3 AM? [y/n] (default: yes): ").strip().lower() or 'y'
if add_cron == 'y':
# Add new cron job
new_cron += f"\n0 3 * * * fetchtastic download\n"
# Update crontab
process = subprocess.Popen(['crontab', '-'], stdin=subprocess.PIPE, text=True)
process.communicate(input=new_cron)
print("New cron job added.")
else:
print("Skipping cron job installation.")
print("Cron job updated.")
else:
print("Keeping existing crontab entry.")
else:
# No existing fetchtastic cron job
add_cron = input("Would you like to schedule Fetchtastic to run daily at 3 AM? [y/n] (default: yes): ").strip().lower() or 'y'
if add_cron == 'y':
# Add new cron job
new_cron = existing_cron.strip() + f"\n0 3 * * * fetchtastic download\n"
# Update crontab
process = subprocess.Popen(['crontab', '-'], stdin=subprocess.PIPE, text=True)
process.communicate(input=new_cron)
print("Cron job added to run Fetchtastic daily at 3 AM.")
else:
print("Skipping cron job installation.")
# Add new cron job
new_cron = existing_cron.strip() + f"\n0 3 * * * fetchtastic download\n"
# Update crontab
process = subprocess.Popen(['crontab', '-'], stdin=subprocess.PIPE, text=True)
process.communicate(input=new_cron)
print("Cron job added to run Fetchtastic daily at 3 AM.")
except Exception as e:
print(f"An error occurred while setting up the cron job: {e}")

Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = fetchtastic
version = 0.1.5
version = 0.1.6
author = Jeremiah K
author_email = [email protected]
description = Meshtastic Firmware and APK Downloader
Expand Down

0 comments on commit be1245c

Please sign in to comment.