1 # Fedi API Block - An aggregator for fetching blocking data from fediverse nodes
2 # Copyright (C) 2023 Free Software Foundation
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published
6 # by the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <https://www.gnu.org/licenses/>.
19 from fba import blacklist
20 from fba import config
22 from fba import instances
24 def fetch_peers(domain: str) -> list:
25 # DEBUG: print(f"DEBUG: domain({len(domain)})={domain} - CALLED!")
26 if type(domain) != str:
27 raise ValueError(f"Parameter domain[]={type(domain)} is not 'str'")
29 raise ValueError(f"Parameter 'domain' is empty")
31 # DEBUG: print(f"DEBUG: domain='{domain}' is misskey, sending API POST request ...")
34 step = config.get("misskey_limit")
36 # iterating through all "suspended" (follow-only in its terminology)
37 # instances page-by-page, since that troonware doesn't support
38 # sending them all at once
40 # DEBUG: print(f"DEBUG: Fetching offset='{offset}' from '{domain}' ...")
42 fetched = fba.post_json_api(domain, "/api/federation/instances", json.dumps({
50 fetched = fba.post_json_api(domain, "/api/federation/instances", json.dumps({
59 # DEBUG: print(f"DEBUG: fetched()={len(fetched)}")
61 # DEBUG: print("DEBUG: Returned zero bytes, exiting loop:", domain)
63 elif len(fetched) != config.get("misskey_limit"):
64 # DEBUG: print(f"DEBUG: Fetched '{len(fetched)}' row(s) but expected: '{config.get('misskey_limit')}'")
65 offset = offset + (config.get("misskey_limit") - len(fetched))
67 # DEBUG: print("DEBUG: Raising offset by step:", step)
68 offset = offset + step
71 # DEBUG: print(f"DEBUG: fetched({len(fetched)})[]={type(fetched)}")
72 if isinstance(fetched, dict) and "error" in fetched and "message" in fetched["error"]:
73 print(f"WARNING: post_json_api() returned error: {fetched['error']['message']}")
74 instances.update_last_error(domain, fetched["error"]["message"])
79 # DEBUG: print(f"DEBUG: row():{len(row)}")
81 print(f"WARNING: row()={len(row)} does not contain key 'host': {row},domain='{domain}'")
83 elif type(row["host"]) != str:
84 print(f"WARNING: row[host][]={type(row['host'])} is not 'str'")
86 elif blacklist.is_blacklisted(row["host"]):
87 # DEBUG: print(f"DEBUG: row[host]='{row['host']}' is blacklisted. domain='{domain}'")
89 elif row["host"] in peers:
90 # DEBUG: print(f"DEBUG: Not adding row[host]='{row['host']}', already found.")
94 # DEBUG: print(f"DEBUG: Adding peer: '{row['host']}'")
95 peers.append(row["host"])
97 if already == len(fetched):
98 print(f"WARNING: Host returned same set of '{already}' instances, aborting loop!")
101 # DEBUG: print(f"DEBUG: Adding '{len(peers)}' for domain='{domain}'")
102 instances.set("total_peers", domain, len(peers))
104 # DEBUG: print(f"DEBUG: Updating last_instance_fetch for domain='{domain}' ...")
105 instances.update_last_instance_fetch(domain)
107 # DEBUG: print("DEBUG: Returning peers[]:", type(peers))