#!/usr/bin/env python3 import json import requests import datetime import time CONFIG_FILE = "aocDiscordConfig.json" DATA_FILE = "aocDiscordData.json" def get_star_state(n, day, is_part_two): target_bit = ((day - 1) * 2) + (1 if is_part_two else 0) return (n & (1 << target_bit)) != 0 def count_stars(n): x = 0 while n != 0: if n & 1 == 1: x += 1 n = n >> 1 return x def transform_response(x): res = {} for user_id in x["members"]: n = 0 for day_number in x["members"][user_id]["completion_day_level"]: day = int(day_number) if "1" in x["members"][user_id]["completion_day_level"][day_number]: n = n | (1 << ((day - 1) * 2)) if "2" in x["members"][user_id]["completion_day_level"][day_number]: n = n | (1 << (((day - 1) * 2) + 1)) res[user_id] = n return res def dump_data(dat): f = open(DATA_FILE, "w") json.dump(transform_response(dat), f) f.close() def make_embed(player, day, part, time): return { "title": f"{player} solved day {day}, part {part}!", "color": 0xFFFF66 if part == "2" else 0x9999CC, "timestamp": datetime.datetime.fromtimestamp(int(time)).isoformat(), } def send_embeds(url, embeds): while len(embeds) != 0: time.sleep(1) n = 10 if len(embeds) < n: n = len(embeds) requests.post(url, json={"embeds": embeds[:n]}).raise_for_status() embeds = embeds[n:] def main(): # load settings with open(CONFIG_FILE) as f: raw_json = json.load(f) SESSION_TOKEN = raw_json["session"] LEADERBOARD_ID = raw_json["leaderboardID"] WEBHOOK_URL = raw_json["webhook"] EMAIL_ADDR = raw_json["email_address"] r = requests.get( f"https://adventofcode.com/2022/leaderboard/private/view/{LEADERBOARD_ID}.json", cookies={"session": SESSION_TOKEN}, headers={"User-Agent": EMAIL_ADDR}, ) r.raise_for_status() response = r.json() # load cache file try: f = open(DATA_FILE) historial_data = json.load(f) f.close() except FileNotFoundError: dump_data(response) return embeds = [] for user_id in response["members"]: n = historial_data.get(user_id, 0) historical_num_stars = count_stars(n) current_num_stars = response["members"][user_id]["stars"] if current_num_stars != historical_num_stars: for day_number in response["members"][user_id]["completion_day_level"]: day = int(day_number) ds = response["members"][user_id]["completion_day_level"][day_number] to_make = [] if not get_star_state(n, day, False) and "1" in ds: to_make.append("1") if not get_star_state(n, day, True) and "2" in ds: to_make.append("2") for ds in to_make: embeds.append( make_embed( response["members"][user_id]["name"], day_number, ds, response["members"][user_id]["completion_day_level"][ day_number ][ds]["get_star_ts"], ) ) send_embeds(WEBHOOK_URL, embeds) dump_data(response) if __name__ == "__main__": main()