-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpoll.py
More file actions
executable file
·104 lines (89 loc) · 3.31 KB
/
Copy pathpoll.py
File metadata and controls
executable file
·104 lines (89 loc) · 3.31 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
#!/usr/bin/env python3
"""Poll every Discord channel the bot can see and write a daily digest."""
from __future__ import annotations
import datetime as dt
import json
import os
import pathlib
import sys
import urllib.error
import urllib.parse
import urllib.request
API = "https://discord.com/api/v10"
TOKEN = os.environ["DISCORD_BOT_TOKEN"]
HEADERS = {
"Authorization": f"Bot {TOKEN}",
"User-Agent": "discord-niklas-digest (github actions, v1)",
}
LOOKBACK_HOURS = 24
def api_get(path: str):
req = urllib.request.Request(API + path, headers=HEADERS)
with urllib.request.urlopen(req, timeout=30) as r:
return json.loads(r.read().decode("utf-8"))
def recent_messages(channel_id: str, since_iso: str):
try:
msgs = api_get(f"/channels/{channel_id}/messages?limit=100")
except urllib.error.HTTPError as e:
if e.code in (403, 404):
return []
raise
return [m for m in msgs if m.get("timestamp", "") >= since_iso]
def main() -> int:
now = dt.datetime.now(dt.timezone.utc)
since = (now - dt.timedelta(hours=LOOKBACK_HOURS)).isoformat()
today = now.date().isoformat()
try:
guilds = api_get("/users/@me/guilds")
except urllib.error.HTTPError as e:
body = e.read().decode("utf-8", errors="replace")
print(f"ERROR fetching /users/@me/guilds: HTTP {e.code}\n{body}", file=sys.stderr)
if e.code in (401, 403):
print(
"Bot token rejected or bot not in any server. Invite it:\n"
" https://discord.com/api/oauth2/authorize"
"?client_id=1493705177050386562&scope=bot&permissions=66560",
file=sys.stderr,
)
return 1
lines = [f"# Discord digest — {today}", ""]
total = 0
if not guilds:
lines.append("_Bot is not in any server yet. Invite it and re-run._")
for g in guilds:
lines.append(f"## {g['name']}")
lines.append("")
try:
channels = api_get(f"/guilds/{g['id']}/channels")
except urllib.error.HTTPError as e:
lines.append(f"_(couldn't list channels: HTTP {e.code})_")
lines.append("")
continue
for ch in channels:
if ch.get("type") != 0: # 0 = GUILD_TEXT
continue
msgs = recent_messages(ch["id"], since)
if not msgs:
continue
lines.append(f"### #{ch['name']}")
lines.append("")
for m in reversed(msgs): # oldest first
author = m.get("author", {}).get("username", "?")
content = (m.get("content") or "").strip()
if not content:
continue
ts = m.get("timestamp", "")[:16].replace("T", " ")
lines.append(f"- **{author}** ({ts} UTC): {content}")
total += 1
lines.append("")
if total == 0:
lines.append("_No new messages in the last 24h._")
lines.append("")
body = "\n".join(lines)
out = pathlib.Path("digests")
out.mkdir(exist_ok=True)
(out / "latest.md").write_text(body, encoding="utf-8")
(out / f"{today}.md").write_text(body, encoding="utf-8")
print(f"Wrote digests/latest.md and digests/{today}.md ({total} messages).")
return 0
if __name__ == "__main__":
sys.exit(main())