Skip to content

Instantly share code, notes, and snippets.

@it-is-wednesday
Last active July 15, 2023 19:08
Show Gist options
  • Save it-is-wednesday/a476633eaa26beef5649c6163cdcc46c to your computer and use it in GitHub Desktop.
Save it-is-wednesday/a476633eaa26beef5649c6163cdcc46c to your computer and use it in GitHub Desktop.
קשה לי עם משרד הפנים
#!/bin/env python3
"""
Get alerts on new available slots for passport renewal.
Should be run via Termux on your Android phone prolly
You'll need to place a JWT token in a file named `jwt` in the script directory.
Login to myvisit.com, then try querying for dates and copy the cookies header
from the SearchAvailableSlots request.
Also you'll need a triumphant ringtone to be played when a match is found! Name
it `alarm.m4a` and place it along with the script =)
"""
import sys
from datetime import datetime
from itertools import cycle
from pathlib import Path
from random import randint
from subprocess import run
from time import sleep
import requests
LATEST_DATE = datetime(2022, 8, 20)
BASE = "https://central.qnomy.com/CentralAPI"
AVAIL_DATES = f"{BASE}/SearchAvailableDates"
COOKIE_PATH = Path("./cookie")
ALARM_PATH = Path("./alarm.m4a")
COOL_CITIES = [
("לשכת רמת גן-גבעתיים", 2095),
("לשכת תל אביב מרכז (קריית הממשלה)", 2099),
("לשכת פתח תקוה", 2113),
("לשכת חולון", 2153),
("לשכת ירושלים", 2155),
("לשכת ירושלים דרום-הר חומה", 2161),
("לשכת בני ברק", 2163),
('לשכת ת"א דרום (יפו)', 2165),
("לשכת ראשון לציון", 2241),
("לשכת הרצליה", 2245),
]
HEADERS = {
"authority": "central.qnomy.com",
"authorization": Path("./jwt").read_text(encoding="UTF-8").strip(),
"accept": "application/json, text/plain, */*",
"preparedvisittoken": "2d118806-7d87-412a-b319-46269159c0ba",
"application-api-key": "8640a12d-52a7-4c2a-afe1-4411e00e3ac4",
"accept-language": "en-US,en;q=0.5",
"user-agent": (
"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36"
),
"application-name": "myVisit.com v3.5",
"dnt": "1",
"origin": "https://myvisit.com",
"sec-fetch-site": "cross-site",
"sec-fetch-mode": "cors",
"sec-fetch-dest": "empty",
"referer": "https://myvisit.com/",
}
def notify(location_name):
"Wake me up to a notification featuring a cool city with an empty slot"
run(["termux-volume", "music", "15"], check=True)
run(["termux-media-player", "play", "alarm.m4a"], check=True)
run(["termux-notification", "--content", location_name], check=True)
def fetch_available_dates(location_id):
"Fetch available dates at location, return a list of datetime objects"
resp = requests.get(
AVAIL_DATES,
params={
"maxResults": "31",
"serviceId": location_id,
"startDate": datetime.now().strftime("%Y-%m-%d"),
},
headers=HEADERS,
)
print(resp.text)
resp = resp.json()
return [
datetime.fromisoformat(date["calendarDate"])
for date in (resp.get("Results") or [])
]
def main():
"Iterate forever on all the cool cities, wake me up if found a slot"
# Otherwise we can't play the alarm when the screen is turned off
run("termux-wake-lock", check=True)
for loc_name, loc_id in cycle(COOL_CITIES):
dates = fetch_available_dates(loc_id)
sleep(randint(20, 50))
print(loc_name, dates)
if len(dates) > 0 and dates[0] < LATEST_DATE:
notify(loc_name)
if __name__ == "__main__":
if not JWT_PATH.exists():
print(
"Please inspect the site via a browser and copy the whole JWT "
f"token from the header into a file named `{JWT_PATH}`!!!! "
"https://myvisit.com/#!/home/provider/56",
file=sys.stderr,
)
sys.exit(1)
if not ALARM_PATH.exists():
print(
"Just download an alarm tune and name it alarm.m4a in current dir",
file=sys.stderr,
)
sys.exit(2)
main()
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment