Skip to content

Instantly share code, notes, and snippets.

@HBIDamian
Created December 24, 2024 23:41
Show Gist options
  • Save HBIDamian/4385dde50d1c7a3011da77e7feaa49e2 to your computer and use it in GitHub Desktop.
Save HBIDamian/4385dde50d1c7a3011da77e7feaa49e2 to your computer and use it in GitHub Desktop.
A CLI Santa Tracker, because why not πŸ˜‚
import argparse
import sys
import curses
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import requests
import urllib.parse
# Function to convert longitude and latitude to a location
def longLatToLocation(longitude, latitude):
api_url = f"https://api.bigdatacloud.net/data/reverse-geocode-client?latitude={latitude}&longitude={longitude}&localityLanguage=en"
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.3"
}
response = requests.get(api_url, headers=headers)
return response.json()
def print_location_data(stdscr, lng_value, lat_value, ground_speed_value, use_reverse_api):
stdscr.clear()
stdscr.addstr(0, 0, f"Tracking the location of Santa's sleigh...\n")
stdscr.addstr(1, 0, f"Longitude: {lng_value}")
stdscr.addstr(2, 0, f"Latitude: {lat_value}")
stdscr.addstr(3, 0, f"Ground Speed: {ground_speed_value}\n")
if use_reverse_api:
location = longLatToLocation(lng_value, lat_value)
pluscode = location.get('plusCode', '')
urlencoded_pluscode = urllib.parse.quote_plus(pluscode)
pluscode_url = f"https://www.google.com/maps/place/{urlencoded_pluscode}"
def get_or_unknown(value):
return value if value else "Unknown"
stdscr.addstr(5, 0, f"Continent: {get_or_unknown(location.get('continent', 'Unknown'))}")
stdscr.addstr(6, 0, f"Country: {get_or_unknown(location.get('countryName', 'Unknown'))}")
stdscr.addstr(7, 0, f"Principal Subdivision: {get_or_unknown(location.get('principalSubdivision', 'Unknown'))}")
stdscr.addstr(8, 0, f"City: {get_or_unknown(location.get('city', 'Unknown'))}")
stdscr.addstr(9, 0, f"Google Maps: {pluscode_url}\n")
stdscr.addstr(10, 0, f"API Url: https://api.bigdatacloud.net/data/reverse-geocode-client?latitude={lng_value}&longitude={lat_value}&localityLanguage=en")
stdscr.refresh()
def main(stdscr):
# Parse command-line arguments
parser = argparse.ArgumentParser(description="Track Santa's sleigh using Flightradar24.", usage="%(prog)s [options]", epilog="Happy Holidays!", add_help=True, allow_abbrev=False, formatter_class=argparse.ArgumentDefaultsHelpFormatter, prog="track.py", prefix_chars="-", conflict_handler="resolve")
parser.add_argument("-l", "--loop", action="store_true", help="Run the tracker in a loop, refreshing results every 10 seconds.")
parser.add_argument("-r", "--noReverse", action="store_false", help="Do not use the reverse-geocode-client API.")
parser.add_argument("--lock", action="store_true", help="Prevent quitting the program, except with CTRL+C.")
# Check for help argument and show help if requested
if '-h' in sys.argv or '--help' in sys.argv:
parser.print_help()
sys.exit(0)
args = parser.parse_args()
loop_mode = args.loop # Handle the loop mode
use_reverse_api = args.noReverse
lock_mode = args.lock # Handle the lock mode
# Initialize the Selenium WebDriver, headless mode
options = webdriver.ChromeOptions()
options.add_argument("--headless")
options.add_argument("--no-sandbox")
driver = webdriver.Chrome(options=options)
# Configure the curses screen
stdscr.nodelay(True) # Make getch non-blocking
stdscr.clear()
stdscr.addstr(0, 0, "Loading... Please wait.")
stdscr.refresh()
try:
while True:
if not lock_mode:
key = stdscr.getch()
if key != -1: # If any key is pressed
break
# Open the website
url = "https://www.flightradar24.com/R3DN053/3875f013"
driver.get(url)
# Wait for the longitude, latitude, and ground speed elements
wait = WebDriverWait(driver, 30)
lng_element = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "p[data-testid='aircraft-panel__lng']"))
)
lat_element = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "p[data-testid='aircraft-panel__lat']"))
)
ground_speed_element = wait.until(
EC.presence_of_element_located((By.CSS_SELECTOR, "div[data-testid='aircraft-panel__ground-speed-tooltip'] div"))
)
# If the elements are not found, quit the program with an error message
if not lng_element or not lat_element or not ground_speed_element:
raise Exception("Could not find the required elements on the page")
# Extract values
lng_value = lng_element.text
lat_value = lat_element.text
ground_speed_value = ground_speed_element.get_attribute("innerText")
# Print the location data
print_location_data(stdscr, lng_value, lat_value, ground_speed_value, use_reverse_api)
# Break the loop if not in loop mode
if not loop_mode:
break
# Wait for 10 seconds before refreshing
time.sleep(10)
except Exception as e:
stdscr.addstr(11, 0, f"An error occurred: {e}")
stdscr.refresh()
time.sleep(3)
finally:
# Close the driver
driver.quit()
if __name__ == "__main__":
curses.wrapper(main)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment