From 35e74a7f861787e806663501c31209336f06149f Mon Sep 17 00:00:00 2001 From: bruno Date: Sat, 10 Oct 2026 08:13:19 -0400 Subject: [PATCH] Auto-backup: 207 scripts (@ 2026-10-10 08:13) --- .../briefing-quotidien/scripts/fetch_tasks.py | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 skills/productivity/briefing-quotidien/scripts/fetch_tasks.py diff --git a/skills/productivity/briefing-quotidien/scripts/fetch_tasks.py b/skills/productivity/briefing-quotidien/scripts/fetch_tasks.py new file mode 100644 index 0000000..1772ace --- /dev/null +++ b/skills/productivity/briefing-quotidien/scripts/fetch_tasks.py @@ -0,0 +1,58 @@ +#!/usr/bin/env python3 +"""Fetch open Google Tasks count for the daily briefing (fallback helper).""" +import json, urllib.request, urllib.parse +from pathlib import Path + +HERMES = Path.home() / ".hermes" +TOKEN_PATH = HERMES / "google_token.json" +CLIENT_PATH = HERMES / "google_client_secret.json" +SCOPES = ["https://www.googleapis.com/auth/tasks.readonly"] + +def get_access_token(): + # Try a refresh that explicitly requests the tasks scope + tok = json.loads(TOKEN_PATH.read_text()) + client = json.loads(CLIENT_PATH.read_text()) + c = client.get("installed", client.get("web", {})) + data = urllib.parse.urlencode({ + "client_id": c["client_id"], "client_secret": c["client_secret"], + "refresh_token": tok["refresh_token"], "grant_type": "refresh_token"}).encode() + resp = urllib.request.urlopen(urllib.request.Request( + "https://oauth2.googleapis.com/token", data=data), timeout=20) + payload = json.loads(resp.read()) + import sys + print("GRANTED_SCOPES: " + payload.get("scope", "(none reported)"), file=sys.stderr) + return payload["access_token"] + +def main(): + if not TOKEN_PATH.exists(): + print(json.dumps({"error": "no_token_file"})); return + tok = json.loads(TOKEN_PATH.read_text()) + headers = {"Authorization": "Bearer " + get_access_token()} + try: + lists = json.loads(urllib.request.urlopen(urllib.request.Request( + "https://tasks.googleapis.com/tasks/v1/users/@me/lists", headers=headers), timeout=20 + ).read()).get("items", []) + except urllib.error.HTTPError as e: + print(json.dumps({"error": "http_%s" % e.code, + "body": e.read().decode(errors="replace")[:500], + "saved_scope": tok.get("scope", "")}, ensure_ascii=False)) + return + total, details = 0, [] + for lst in lists: + u = ("https://tasks.googleapis.com/tasks/v1/lists/%s/tasks" + "?maxResults=50&showCompleted=false&showHidden=false" % lst["id"]) + try: + items = json.loads(urllib.request.urlopen( + urllib.request.Request(u, headers=headers), timeout=20 + ).read()).get("items", []) + except Exception: + items = [] + total += len(items) + for t in items[:10]: + details.append({"list": lst.get("title", "?"), + "title": t.get("title", ""), + "due": t.get("due", "")}) + print(json.dumps({"tasks": total, "details": details}, ensure_ascii=False)) + +if __name__ == "__main__": + main()