-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathsave.py
executable file
·99 lines (85 loc) · 2.79 KB
/
save.py
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
#!/usr/bin/env python3
from __future__ import annotations
from dataclasses import dataclass
from datetime import datetime
import dateutil.parser
import json
from os import environ
from sys import argv
from collections import Counter
from mastodon import Mastodon
import typing
def acct_to_webfinger(acct: str) -> str:
if "@" in acct:
return acct
return f"{acct}@chaos.social"
@dataclass
class Toot:
id: str
author: str
content: str
timestamp: datetime
@classmethod
def from_api(cls, toot) -> Self:
return cls(
toot.uri,
acct_to_webfinger(toot.account.acct),
toot.content,
toot.created_at,
)
@classmethod
def from_json(cls, toot: dict[str, object]) -> Self:
toot["timestamp"] = datetime.fromisoformat(toot["timestamp"])
return cls(**toot)
def to_json(self) -> dict[str, object]:
d = self.__dict__.copy()
d["timestamp"] = self.timestamp.isoformat()
return d
def deserialize(input):
"""Deserialize the saved data."""
result = input.copy()
result["toots"] = {
id: Toot.from_json(toot)
for (id, toot) in input.get("toots", {}).items()
}
return result
def save(saved, toot):
if toot.id not in saved["toots"].keys():
print(f"Saving {toot.id}...")
saved["toots"][toot.id] = toot
if __name__ == "__main__":
try:
with open("dorfleaks-saved.json", "r") as saved_file:
saved = json.load(saved_file)
except FileNotFoundError:
saved = dict()
saved = deserialize(saved)
# fetching individual statuses requires authentication
mastodon = Mastodon(
api_base_url="https://chaos.social/",
client_id=environ.get("MASTODON_CLIENT_ID"),
client_secret=environ.get("MASTODON_CLIENT_SECRET"),
access_token=environ.get("MASTODON_ACCESS_TOKEN"),
)
mastodon.app_verify_credentials()
if len(argv) == 2:
id = argv[-1]
results = mastodon.search_v2(id, resolve=True, result_type="statuses", exclude_unreviewed=False)
result, = results["statuses"]
save(saved, Toot.from_api(result))
else:
# move all twitter data
if "twitter" not in saved.keys():
saved = {"twitter": saved}
# the actual logic:
# get all toots with this hashtag
# remove all non-relevant data
toots = map(Toot.from_api, mastodon.timeline_hashtag("dorfleaks"))
# merge with existing data
saved["toots"] = saved.get("toots", {})
for toot in toots:
save(saved, toot)
# serialize
saved["toots"] = {id: toot.to_json() for (id, toot) in saved["toots"].items()}
with open("dorfleaks-saved.json", "w") as saved_file:
json.dump(saved, saved_file)