9 "SELECT domain, software FROM instances WHERE software IN ('pleroma', 'mastodon', 'friendica', 'misskey', 'gotosocial')"
12 for blocker, software in fba.c.fetchall():
13 # NOISY-DEBUG: print("DEBUG: BEFORE-blocker,software:", blocker, software)
15 blocker = fba.tidyup(blocker)
16 # NOISY-DEBUG: print("DEBUG: AFTER-blocker,software:", blocker, software)
19 print("WARNING: blocker is now empty!")
22 if software == "pleroma":
23 print("INFO: blocker:", blocker)
26 federation = reqto.get(
27 f"https://{blocker}/nodeinfo/2.1.json", headers=fba.headers, timeout=5
28 ).json()["metadata"]["federation"]
30 if "mrf_simple" in federation:
31 for block_level, blocks in (
32 {**federation["mrf_simple"],
33 **{"quarantined_instances": federation["quarantined_instances"]}}
35 # NOISY-DEBUG: print("DEBUG: block_level, blocks():", block_level, len(blocks))
36 block_level = fba.tidyup(block_level)
37 # NOISY-DEBUG: print("DEBUG: BEFORE block_level:", block_level)
40 print("WARNING: block_level is now empty!")
43 for blocked in blocks:
44 # NOISY-DEBUG: print("DEBUG: BEFORE blocked:", blocked)
45 blocked = fba.tidyup(blocked)
46 # NOISY-DEBUG: print("DEBUG: AFTER blocked:", blocked)
49 print("WARNING: blocked is empty after fba.tidyup():", blocker, block_level)
52 if blocked.count("*") > 1:
53 # -ACK!-oma also started obscuring domains without hash
55 "SELECT domain FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", (blocked.replace("*", "_"),)
57 searchres = fba.c.fetchone()
58 # NOISY-DEBUG: print("DEBUG: searchres[]:", type(searchres))
60 blocked = searchres[0]
61 # NOISY-DEBUG: print("DEBUG: Looked up domain:", blocked)
63 # NOISY-DEBUG: print("DEBUG: Looking up instance by domain:", blocked)
65 "SELECT domain FROM instances WHERE domain = ?", (blocked,)
68 if fba.c.fetchone() == None:
69 # NOISY-DEBUG: print("DEBUG: Domain wasn't found, adding:", blocked)
70 fba.add_instance(blocked)
72 timestamp = int(time.time())
74 "SELECT * FROM blocks WHERE blocker = ? AND blocked = ? AND block_level = ?",
82 if fba.c.fetchone() == None:
83 # NOISY-DEBUG: print("DEBUG: Blocking:", blocker, blocked, block_level)
84 fba.block_instance(blocker, blocked, "unknown", block_level, timestamp, timestamp)
86 if block_level == "reject":
87 # NOISY-DEBUG: print("DEBUG: Adding to blockdict:", blocked)
94 # NOISY-DEBUG: print("DEBUG: Updating last_seen:", blocker, blocked, block_level)
95 fba.update_last_seen(timestamp, blocker, blocked, block_level)
100 if "mrf_simple_info" in federation:
101 # NOISY-DEBUG: print("DEBUG: Found mrf_simple_info:", blocker)
102 for block_level, info in (
103 {**federation["mrf_simple_info"],
104 **(federation["quarantined_instances_info"]
105 if "quarantined_instances_info" in federation
108 # NOISY-DEBUG: print("DEBUG: block_level, info.items():", block_level, len(info.items()))
109 block_level = fba.tidyup(block_level)
110 # NOISY-DEBUG: print("DEBUG: BEFORE block_level:", block_level)
112 if block_level == "":
113 print("WARNING: block_level is now empty!")
116 for blocked, reason in info.items():
117 # NOISY-DEBUG: print("DEBUG: BEFORE blocked:", blocked)
118 blocked = fba.tidyup(blocked)
119 # NOISY-DEBUG: print("DEBUG: AFTER blocked:", blocked)
122 print("WARNING: blocked is empty after fba.tidyup():", blocker, block_level)
124 elif blocked.count("*") > 1:
125 # same domain guess as above, but for reasons field
127 "SELECT domain FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", (blocked.replace("*", "_"),)
129 searchres = fba.c.fetchone()
131 if searchres != None:
132 blocked = searchres[0]
134 # NOISY-DEBUG: print("DEBUG: Updating block reason:", blocker, blocked, reason["reason"])
135 fba.update_block_reason(reason["reason"], blocker, blocked, block_level)
137 for entry in blockdict:
138 if entry["blocked"] == blocked:
139 # NOISY-DEBUG: print("DEBUG: Updating entry reason:", blocked)
140 entry["reason"] = reason["reason"]
143 except Exception as e:
144 print("error:", e, blocker, software)
145 elif software == "mastodon":
146 print("INFO: blocker:", blocker)
148 # json endpoint for newer mastodongs
153 "followers_only": [],
157 # handling CSRF, I've saw at least one server requiring it to access the endpoint
158 # NOISY-DEBUG: print("DEBUG: Fetching meta:", blocker)
159 meta = bs4.BeautifulSoup(
160 reqto.get(f"https://{blocker}/about", headers=fba.headers, timeout=5).text,
164 csrf = meta.find("meta", attrs={"name": "csrf-token"})["content"]
165 # NOISY-DEBUG: print("DEBUG: Adding CSRF token:", blocker, csrf)
166 reqheaders = {**fba.headers, **{"x-csrf-token": csrf}}
168 # NOISY-DEBUG: print("DEBUG: No CSRF token found, using normal headers:", blocker)
169 reqheaders = fba.headers
171 # NOISY-DEBUG: print("DEBUG: Quering API domain_blocks:", blocker)
173 f"https://{blocker}/api/v1/instance/domain_blocks", headers=reqheaders, timeout=5
176 # NOISY-DEBUG: print("DEBUG: blocks():", len(blocks))
179 'domain': block['domain'],
180 'hash': block['digest'],
181 'reason': block['comment']
184 # NOISY-DEBUG: print("DEBUG: severity,domain,hash,comment:", block['severity'], block['domain'], block['digest'], block['comment'])
185 if block['severity'] == 'suspend':
186 json['reject'].append(entry)
187 elif block['severity'] == 'silence':
188 json['followers_only'].append(entry)
189 elif block['severity'] == 'reject_media':
190 json['media_removal'].append(entry)
191 elif block['severity'] == 'reject_reports':
192 json['report_removal'].append(entry)
194 print("WARNING: Unknown severity:", block['severity'], block['domain'])
196 # NOISY-DEBUG: print("DEBUG: Failed, Trying mastodon-specific fetches:", blocker)
197 json = fba.get_mastodon_blocks(blocker)
199 # NOISY-DEBUG: print("DEBUG: json.items():", blocker, len(json.items()))
200 for block_level, blocks in json.items():
201 # NOISY-DEBUG: print("DEBUG: blocker,block_level,blocks():", blocker, block_level, len(blocks))
202 block_level = fba.tidyup(block_level)
203 # NOISY-DEBUG: print("DEBUG: AFTER-block_level:", block_level)
204 if block_level == "":
205 print("WARNING: block_level is empty, blocker:", blocker)
208 for instance in blocks:
209 blocked, blocked_hash, reason = instance.values()
210 # NOISY-DEBUG: print("DEBUG: blocked,hash,reason:", blocked, blocked_hash, reason)
211 blocked = fba.tidyup(blocked)
212 # NOISY-DEBUG: print("DEBUG: AFTER-blocked:", blocked)
215 print("WARNING: blocked is empty:", blocker)
217 elif blocked.count("*") < 1:
218 # No obsfucation for this instance
220 "SELECT hash FROM instances WHERE domain = ? LIMIT 1", (blocked,)
223 if fba.c.fetchone() == None:
224 # NOISY-DEBUG: print("DEBUG: Hash wasn't found, adding:", blocked)
225 fba.add_instance(blocked)
227 # Doing the hash search for instance names as well to tidy up DB
229 "SELECT domain FROM instances WHERE hash = ? LIMIT 1", (blocked_hash,)
231 searchres = fba.c.fetchone()
233 if searchres != None:
234 # NOISY-DEBUG: print("DEBUG: Updating domain: ", searchres[0])
235 blocked = searchres[0]
237 timestamp = int(time.time())
239 "SELECT * FROM blocks WHERE blocker = ? AND blocked = ? AND block_level = ?",
242 blocked if blocked.count("*") <= 1 else blocked_hash,
247 if fba.c.fetchone() == None:
248 fba.block_instance(blocker, blocked if blocked.count("*") <= 1 else blocked_hash, reason, block_level, timestamp, timestamp)
250 if block_level == "reject":
257 fba.update_last_seen(timestamp, blocker, blocked if blocked.count("*") <= 1 else blocked_hash, block_level)
260 # NOISY-DEBUG: print("DEBUG: Updating block reason:", blocker, blocked, reason)
261 fba.update_block_reason(reason, blocker, blocked if blocked.count("*") <= 1 else blocked_hash, block_level)
264 except Exception as e:
265 print("error:", e, blocker, software)
266 elif software == "friendica" or software == "misskey":
267 print("INFO: blocker:", blocker)
269 if software == "friendica":
270 json = fba.get_friendica_blocks(blocker)
271 elif software == "misskey":
272 json = fba.get_misskey_blocks(blocker)
274 for block_level, blocks in json.items():
275 # NOISY-DEBUG: print("DEBUG: blocker,block_level,blocks():", blocker, block_level, len(blocks))
276 block_level = fba.tidyup(block_level)
277 # NOISY-DEBUG: print("DEBUG: AFTER-block_level:", block_level)
278 if block_level == "":
279 print("WARNING: block_level is empty, blocker:", blocker)
282 for instance in blocks:
283 blocked, reason = instance.values()
284 # NOISY-DEBUG: print("DEBUG: BEFORE-blocked:", blocked)
285 blocked = fba.tidyup(blocked)
286 # NOISY-DEBUG: print("DEBUG: AFTER-blocked:", blocked)
289 print("WARNING: blocked is empty:", blocker)
291 if blocked.count("*") > 0:
292 # Some friendica servers also obscure domains without hash
294 "SELECT domain FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", (blocked.replace("*", "_"),)
296 searchres = fba.c.fetchone()
297 if searchres != None:
298 blocked = searchres[0]
300 if blocked.count("?") > 0:
301 # Some obscure them with question marks, not sure if that's dependent on version or not
303 "SELECT domain FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", (blocked.replace("?", "_"),)
305 searchres = fba.c.fetchone()
306 if searchres != None:
307 blocked = searchres[0]
309 # NOISY-DEBUG: print("DEBUG: AFTER-blocked:", blocked)
311 "SELECT domain FROM instances WHERE domain = ?", (blocked,)
314 if fba.c.fetchone() == None:
315 # NOISY-DEBUG: print("DEBUG: Hash wasn't found, adding:", blocked)
316 fba.add_instance(blocked)
318 timestamp = int(time.time())
320 "SELECT * FROM blocks WHERE blocker = ? AND blocked = ?",
323 if fba.c.fetchone() == None:
324 fba.block_instance(blocker, blocked, reason, block_level, timestamp, timestamp)
326 if block_level == "reject":
333 fba.update_last_seen(timestamp, blocker, blocked, block_level)
336 # NOISY-DEBUG: print("DEBUG: Updating block reason:", blocker, blocked, reason)
337 fba.update_block_reason(reason, blocker, blocked, block_level)
340 except Exception as e:
341 print("error:", e, blocker, software)
342 elif software == "gotosocial":
343 print("INFO: blocker:", blocker)
346 federation = reqto.get(
347 f"https://{blocker}/api/v1/instance/peers?filter=suspended", headers=fba.headers, timeout=5
350 if (federation == None):
351 print("WARNING: No valid response:", blocker);
352 elif "error" in federation:
353 print("WARNING: API returned error:", federation["error"])
355 for peer in federation:
356 blocked = peer["domain"].lower()
357 # NOISY-DEBUG: print("DEBUG: BEFORE-blocked:", blocked)
358 blocked = fba.tidyup(blocked)
359 # NOISY-DEBUG: print("DEBUG: AFTER-blocked:", blocked)
362 print("WARNING: blocked is empty:", blocker)
364 if blocked.count("*") > 0:
365 # GTS does not have hashes for obscured domains, so we have to guess it
367 "SELECT domain FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", (blocked.replace("*", "_"),)
369 searchres = fba.c.fetchone()
371 if searchres != None:
372 blocked = searchres[0]
375 "SELECT domain FROM instances WHERE domain = ?", (blocked,)
378 if fba.c.fetchone() == None:
379 # NOISY-DEBUG: print("DEBUG: Hash wasn't found, adding:", blocked)
380 fba.add_instance(blocked)
383 "SELECT * FROM blocks WHERE blocker = ? AND blocked = ? AND block_level = ?",
390 timestamp = int(time.time())
392 if fba.c.fetchone() == None:
393 fba.block_instance(blocker, blocked, "unknown", "reject", timestamp, timestamp)
401 fba.update_last_seen(timestamp, blocker, blocked, "reject")
403 if "public_comment" in peer:
404 reason = peer["public_comment"]
405 # NOISY-DEBUG: print("DEBUG: Updating block reason:", blocker, blocked, reason)
406 fba.update_block_reason(reason, blocker, blocked, "reject")
408 for entry in blockdict:
409 if entry["blocked"] == blocked:
410 entry["reason"] = reason
413 except Exception as e:
414 print("error:", e, blocker, software)
416 print("WARNING: Unknown software:", software)
418 if fba.config["bot_enabled"] and len(blockdict) > 0:
419 send_bot_post(blocker, blockdict)