From d77acb3dc0ab0be37d130c87aef559c4a8bf9322 Mon Sep 17 00:00:00 2001 From: Uthman Fatih Date: Thu, 8 Oct 2026 22:24:04 +0100 Subject: [PATCH] Finalise caching --- example.config.toml | 4 +- main.py | 103 +++++++++++++++++++++++++++++++++++--------- 2 files changed, 84 insertions(+), 23 deletions(-) diff --git a/example.config.toml b/example.config.toml index 3075901..6225d79 100644 --- a/example.config.toml +++ b/example.config.toml @@ -1,6 +1,6 @@ [anilist] -user_id = 8283179 -media_type = "ANIME" +userId = 8283179 +mediaType = "ANIME" [ical] # reserved for future use \ No newline at end of file diff --git a/main.py b/main.py index a5507d2..b10a1aa 100644 --- a/main.py +++ b/main.py @@ -12,63 +12,124 @@ if path.exists("config.toml"): else: raise RuntimeError("config.toml not found") -def getMediaListCollection(type=data["anilist"]["mediaType"], userId=data["anilist"]["userId"]): - if not type or not userId: +def getMediaListCollection( + mediaType=data["anilist"]["mediaType"], + userId=data["anilist"]["userId"], + *, + cachePath="data.json" +): + if not mediaType or not userId: raise RuntimeError("MediaType and UserId must be set") - + + if path.exists(cachePath): + with open(cachePath, "r") as f: + entries = json.load(f) + + if ( + "timestamp" in entries + and "ttl" in entries + and "response" in entries + and "params" in entries + ): + timestamp = float(entries["timestamp"]) + ttl = float(entries["ttl"]) + + cacheUserId = entries["params"].get("userId") + cacheMediaType = entries["params"].get("mediaType") + + cacheExpired = time.time() - timestamp > ttl + parametersChanged = ( + cacheUserId != userId + or cacheMediaType != mediaType + ) + + if not cacheExpired and not parametersChanged: + print("Cache is fresh, using cached data...") + return entries["response"] + + if cacheExpired: + print("Cache has gone stale, refreshing...") + elif parametersChanged: + print("Cache parameters changed, refreshing...") + + else: + print("Cache not found, refreshing...") + + # Fetch fresh data from AniList query = """ query ($type: MediaType!, $userId: Int!, $chunk: Int, $perChunk: Int) { - MediaListCollection(type: $type, userId: $userId, chunk: $chunk, perChunk: $perChunk) { - hasNextChunk - lists { - name - entries { - id - media { - id - title { - english - romaji - } + MediaListCollection( + type: $type, + userId: $userId, + chunk: $chunk, + perChunk: $perChunk + ) { + hasNextChunk + lists { + name + entries { + id + media { + id + title { + english + romaji + } + } + } } } - } - } } """ - entries = {} # keyed by entry id, dedupes custom-list repeats + entries = {} chunk = 1 while True: - variables = { 'type': type, 'userId': int(userId), 'chunk': chunk, 'perChunk': 500, } + variables = { + "type": mediaType, + "userId": int(userId), + "chunk": chunk, + "perChunk": 500, + } resp = requests.post( "https://graphql.anilist.co", - json={"query": query, "variables": variables}, + json={ + "query": query, + "variables": variables, + }, timeout=30, ) + resp.raise_for_status() + data = resp.json() if "errors" in data: raise RuntimeError(data["errors"]) collection = data["data"]["MediaListCollection"] + for lst in collection["lists"]: for entry in lst["entries"]: entries[entry["id"]] = entry if not collection["hasNextChunk"]: break + chunk += 1 form = { "timestamp": str(time.time()), "ttl": str(TTL), + "params": { + "mediaType": mediaType, + "userId": userId, + }, "response": list(entries.values()), } - + return form if __name__ == "__main__":