#!/usr/bin/env python3 import graphqlclient from os import environ import dotenv import tabulate import json import time import requests from datetime import datetime, timedelta from geopy.geocoders import Nominatim dotenv.load_dotenv() client = graphqlclient.GraphQLClient(environ.get("API")) locale = environ.get("LOCALE") geolocator = Nominatim(user_agent="ami") location = geolocator.geocode(environ.get("LOCATION"), addressdetails=True) client.inject_token(environ.get("AUTHORIZATION"), "authorization") def log_response(data): log = environ.get("LOG") if log is not None: with open(log, "a") as log_file: json.dump({"timestamp": datetime.now().isoformat(), "data": data}, log_file) log_file.write("\n") def notify(title, body, job_id=None): options = { "body": body, "title": title, "icon": "https://media.discordapp.net/stickers/860824030617272350.webp?size=160&quality=lossless", } if job_id is not None: options["url"] = ( f"https://hiring.amazon.com/app#/jobDetail?jobId={job_id}&locale={locale}" ) options["level"] = "timeSensitive" response = requests.post( f"https://api.day.app/{environ.get('BARK_KEY')}/", headers={"Content-Type": "application/json; charset=utf-8"}, json=options, ) return response.status_code, response.text def print_job_table(): contain_filters = [ { "key": "state", "val": [location.raw.get("address").get("ISO3166-2-lvl4").split("-")[1]], }, {"key": "isPrivateSchedule", "val": ["false"]}, ] if environ.get("SEARCH_CITIES") is not None: contain_filters.append({"key": "city", "val": environ.get("SEARCH_CITIES")}) equal_filters = [ {"key": "scheduleRequiredLanguage", "val": locale}, ] if environ.get("SHIFT_TYPE") is not None: equal_filters.append({"key": "shiftType", "val": environ.get("SHIFT_TYPE")}) else: equal_filters.append({"key": "shiftType", "val": "All"}) json_api_data = json.loads( client.execute( """ query searchJobCardsByLocation($searchJobRequest: SearchJobRequest!) { searchJobCardsByLocation(searchJobRequest: $searchJobRequest) { nextToken jobCards { jobId language dataSource requisitionType jobTitle jobType employmentType city state postalCode locationName totalPayRateMin totalPayRateMax tagLine bannerText image jobPreviewVideo distance featuredJob bonusJob bonusPay scheduleCount currencyCode geoClusterDescription surgePay jobTypeL10N employmentTypeL10N bonusPayL10N surgePayL10N totalPayRateMinL10N totalPayRateMaxL10N distanceL10N monthlyBasePayMin monthlyBasePayMinL10N monthlyBasePayMax monthlyBasePayMaxL10N jobContainerJobMetaL1 virtualLocation poolingEnabled __typename } __typename } } """, { "searchJobRequest": { "locale": locale, "country": location.raw.get("address").get("country"), "keyWords": environ.get("KEYWORDS"), "equalFilters": equal_filters, "containFilters": contain_filters, "rangeFilters": [ {"key": "hoursPerWeek", "range": {"minimum": 0, "maximum": 80}} ], "orFilters": [], "dateFilters": [ { "key": "firstDayOnSite", "range": { "startDate": ( datetime.now() + timedelta(days=1) ).strftime("%Y-%m-%d") }, } ], "sorters": [], "pageSize": 100, "geoQueryClause": { "lat": location.latitude, "lng": location.longitude, "unit": environ.get("DISTANCE_UNIT"), "distance": environ.get("DISTANCE"), }, "consolidateSchedule": True, } }, ) ) log_response(json_api_data) table_data = [] if json_api_data["data"]["searchJobCardsByLocation"]["jobCards"] is None: return for job in json_api_data["data"]["searchJobCardsByLocation"]["jobCards"]: table_data.append( [ job["jobId"], job["jobTitle"], job["city"], job["state"], f"${job['totalPayRateMin']} to ${job['totalPayRateMax']} {job['currencyCode']}", job["employmentTypeL10N"], job["distanceL10N"], ] ) print( tabulate.tabulate( table_data, headers=[ "Job ID", "Title", "City", "State", "Pay Rate", "Employment Type", "Distance (mi)", ], tablefmt="fancy_grid", ) ) for job in json_api_data["data"]["searchJobCardsByLocation"]["jobCards"]: for city in (environ.get("TARGET_CITIES") or "").split(","): fixed_city = city.strip() if job["city"] is not None and job["city"].lower() == fixed_city.lower(): notify( f"Found job in {fixed_city}", f"Job ID: {job['jobId']}\nTitle: {job['jobTitle']}\nCity: {job['city']}\nState: {job['state']}\nPay Rate: ${job['totalPayRateMin']} to ${job['totalPayRateMax']} {job['currencyCode']}\nEmployment Type: {job['employmentTypeL10N']}\nDistance: {job['distanceL10N']}", job["jobId"], ) break while True: print_job_table() interval_string = environ.get("INTERVAL") time.sleep(int(interval_string) if interval_string is not None else 60) print()