9 "SELECT domain, software FROM instances WHERE software IN ('pleroma', 'mastodon', 'friendica', 'misskey', 'gotosocial') AND (last_blocked IS NULL OR last_blocked < ?) ORDER BY rowid DESC", [time.time() - fba.config["recheck_block"]]
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 fba.update_last_blocked(blocker)
24 if software == "pleroma":
25 print("INFO: blocker:", blocker)
28 json = fba.fetch_nodeinfo(blocker)
30 print("WARNING: Could not fetch nodeinfo from blocker:", blocker)
33 federation = json["metadata"]["federation"]
35 if "enabled" in federation:
36 # NOISY-DEBUG: print("DEBUG: Instance has no block list to analyze:", blocker)
39 if "mrf_simple" in federation:
40 for block_level, blocks in (
41 {**federation["mrf_simple"],
42 **{"quarantined_instances": federation["quarantined_instances"]}}
44 # NOISY-DEBUG: print("DEBUG: block_level, blocks():", block_level, len(blocks))
45 block_level = fba.tidyup(block_level)
46 # NOISY-DEBUG: print("DEBUG: BEFORE block_level:", block_level)
49 print("WARNING: block_level is now empty!")
52 for blocked in blocks:
53 # NOISY-DEBUG: print("DEBUG: BEFORE blocked:", blocked)
54 blocked = fba.tidyup(blocked)
55 # NOISY-DEBUG: print("DEBUG: AFTER blocked:", blocked)
58 print("WARNING: blocked is empty after fba.tidyup():", blocker, block_level)
61 if blocked.count("*") > 1:
62 # -ACK!-oma also started obscuring domains without hash
64 "SELECT domain FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", [blocked.replace("*", "_")]
66 searchres = fba.c.fetchone()
67 # NOISY-DEBUG: print("DEBUG: searchres[]:", type(searchres))
69 blocked = searchres[0]
70 # NOISY-DEBUG: print("DEBUG: Looked up domain:", blocked)
72 # NOISY-DEBUG: print("DEBUG: Looking up instance by domain:", blocked)
74 "SELECT domain FROM instances WHERE domain = ?", [blocked]
77 if fba.c.fetchone() == None:
78 # NOISY-DEBUG: print("DEBUG: Domain wasn't found, adding:", blocked, blocker)
79 fba.add_instance(blocked, blocker, argv[0])
82 "SELECT * FROM blocks WHERE blocker = ? AND blocked = ? AND block_level = ?",
90 if fba.c.fetchone() == None:
91 # NOISY-DEBUG: print("DEBUG: Blocking:", blocker, blocked, block_level)
92 fba.block_instance(blocker, blocked, "unknown", block_level)
94 if block_level == "reject":
95 # NOISY-DEBUG: print("DEBUG: Adding to blockdict:", blocked)
102 # NOISY-DEBUG: print("DEBUG: Updating last_seen:", blocker, blocked, block_level)
103 fba.update_last_seen(blocker, blocked, block_level)
108 if "mrf_simple_info" in federation:
109 # NOISY-DEBUG: print("DEBUG: Found mrf_simple_info:", blocker)
110 for block_level, info in (
111 {**federation["mrf_simple_info"],
112 **(federation["quarantined_instances_info"]
113 if "quarantined_instances_info" in federation
116 # NOISY-DEBUG: print("DEBUG: block_level, info.items():", block_level, len(info.items()))
117 block_level = fba.tidyup(block_level)
118 # NOISY-DEBUG: print("DEBUG: BEFORE block_level:", block_level)
120 if block_level == "":
121 print("WARNING: block_level is now empty!")
124 for blocked, reason in info.items():
125 # NOISY-DEBUG: print("DEBUG: BEFORE blocked:", blocked)
126 blocked = fba.tidyup(blocked)
127 # NOISY-DEBUG: print("DEBUG: AFTER blocked:", blocked)
130 print("WARNING: blocked is empty after fba.tidyup():", blocker, block_level)
132 elif blocked.count("*") > 1:
133 # same domain guess as above, but for reasons field
135 "SELECT domain FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", [blocked.replace("*", "_")]
137 searchres = fba.c.fetchone()
139 if searchres != None:
140 blocked = searchres[0]
142 # NOISY-DEBUG: print("DEBUG: Updating block reason:", blocker, blocked, reason["reason"])
143 fba.update_block_reason(reason["reason"], blocker, blocked, block_level)
145 for entry in blockdict:
146 if entry["blocked"] == blocked:
147 # NOISY-DEBUG: print("DEBUG: Updating entry reason:", blocked)
148 entry["reason"] = reason["reason"]
151 except Exception as e:
152 print("error:", e, blocker, software)
153 elif software == "mastodon":
154 print("INFO: blocker:", blocker)
156 # json endpoint for newer mastodongs
161 "followers_only": [],
165 # handling CSRF, I've saw at least one server requiring it to access the endpoint
166 # NOISY-DEBUG: print("DEBUG: Fetching meta:", blocker)
167 meta = bs4.BeautifulSoup(
168 reqto.get(f"https://{blocker}/about", headers=fba.headers, timeout=fba.config["timeout"]).text,
172 csrf = meta.find("meta", attrs={"name": "csrf-token"})["content"]
173 # NOISY-DEBUG: print("DEBUG: Adding CSRF token:", blocker, csrf)
174 reqheaders = {**fba.headers, **{"x-csrf-token": csrf}}
176 # NOISY-DEBUG: print("DEBUG: No CSRF token found, using normal headers:", blocker)
177 reqheaders = fba.headers
179 # NOISY-DEBUG: print("DEBUG: Quering API domain_blocks:", blocker)
180 blocks = reqto.get(f"https://{blocker}/api/v1/instance/domain_blocks", headers=reqheaders, timeout=fba.config["timeout"]).json()
182 # NOISY-DEBUG: print("DEBUG: blocks():", len(blocks))
185 'domain': block['domain'],
186 'hash': block['digest'],
187 'reason': block['comment']
190 # NOISY-DEBUG: print("DEBUG: severity,domain,hash,comment:", block['severity'], block['domain'], block['digest'], block['comment'])
191 if block['severity'] == 'suspend':
192 json['reject'].append(entry)
193 elif block['severity'] == 'silence':
194 json['followers_only'].append(entry)
195 elif block['severity'] == 'reject_media':
196 json['media_removal'].append(entry)
197 elif block['severity'] == 'reject_reports':
198 json['report_removal'].append(entry)
200 print("WARNING: Unknown severity:", block['severity'], block['domain'])
202 # NOISY-DEBUG: print("DEBUG: Failed, Trying mastodon-specific fetches:", blocker)
203 json = fba.get_mastodon_blocks(blocker)
205 # NOISY-DEBUG: print("DEBUG: json.items():", blocker, len(json.items()))
206 for block_level, blocks in json.items():
207 # NOISY-DEBUG: print("DEBUG: blocker,block_level,blocks():", blocker, block_level, len(blocks))
208 block_level = fba.tidyup(block_level)
209 # NOISY-DEBUG: print("DEBUG: AFTER-block_level:", block_level)
210 if block_level == "":
211 print("WARNING: block_level is empty, blocker:", blocker)
214 for instance in blocks:
215 blocked, blocked_hash, reason = instance.values()
216 # NOISY-DEBUG: print("DEBUG: blocked,hash,reason:", blocked, blocked_hash, reason)
217 blocked = fba.tidyup(blocked)
218 # NOISY-DEBUG: print("DEBUG: AFTER-blocked:", blocked)
221 print("WARNING: blocked is empty:", blocker)
223 elif blocked.count("*") < 1:
224 # No obsfucation for this instance
226 "SELECT hash FROM instances WHERE domain = ? LIMIT 1", [blocked]
229 if fba.c.fetchone() == None:
230 # NOISY-DEBUG: print("DEBUG: Hash wasn't found, adding:", blocked, blocker)
231 fba.add_instance(blocked, blocker, argv[0])
233 # Doing the hash search for instance names as well to tidy up DB
235 "SELECT domain FROM instances WHERE hash = ? LIMIT 1", [blocked_hash]
237 searchres = fba.c.fetchone()
239 if searchres != None:
240 # NOISY-DEBUG: print("DEBUG: Updating domain: ", searchres[0])
241 blocked = searchres[0]
244 "SELECT * FROM blocks WHERE blocker = ? AND blocked = ? AND block_level = ?",
247 blocked if blocked.count("*") <= 1 else blocked_hash,
252 if fba.c.fetchone() == None:
253 fba.block_instance(blocker, blocked if blocked.count("*") <= 1 else blocked_hash, reason, block_level)
255 if block_level == "reject":
262 fba.update_last_seen(blocker, blocked if blocked.count("*") <= 1 else blocked_hash, block_level)
265 # NOISY-DEBUG: print("DEBUG: Updating block reason:", blocker, blocked, reason)
266 fba.update_block_reason(reason, blocker, blocked if blocked.count("*") <= 1 else blocked_hash, block_level)
269 except Exception as e:
270 print("error:", e, blocker, software)
271 elif software == "friendica" or software == "misskey":
272 print("INFO: blocker:", blocker)
274 if software == "friendica":
275 json = fba.get_friendica_blocks(blocker)
276 elif software == "misskey":
277 json = fba.get_misskey_blocks(blocker)
279 for block_level, blocks in json.items():
280 # NOISY-DEBUG: print("DEBUG: blocker,block_level,blocks():", blocker, block_level, len(blocks))
281 block_level = fba.tidyup(block_level)
282 # NOISY-DEBUG: print("DEBUG: AFTER-block_level:", block_level)
283 if block_level == "":
284 print("WARNING: block_level is empty, blocker:", blocker)
287 for instance in blocks:
288 blocked, reason = instance.values()
289 # NOISY-DEBUG: print("DEBUG: BEFORE-blocked:", blocked)
290 blocked = fba.tidyup(blocked)
291 # NOISY-DEBUG: print("DEBUG: AFTER-blocked:", blocked)
294 print("WARNING: blocked is empty:", blocker)
296 if blocked.count("*") > 0:
297 # Some friendica servers also obscure domains without hash
299 "SELECT domain FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", [blocked.replace("*", "_")]
301 searchres = fba.c.fetchone()
302 if searchres != None:
303 blocked = searchres[0]
305 if blocked.count("?") > 0:
306 # Some obscure them with question marks, not sure if that's dependent on version or not
308 "SELECT domain FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", [blocked.replace("?", "_")]
310 searchres = fba.c.fetchone()
311 if searchres != None:
312 blocked = searchres[0]
314 # NOISY-DEBUG: print("DEBUG: AFTER-blocked:", blocked)
316 "SELECT domain FROM instances WHERE domain = ?", [blocked]
319 if fba.c.fetchone() == None:
320 # NOISY-DEBUG: print("DEBUG: Hash wasn't found, adding:", blocked, blocker)
321 fba.add_instance(blocked, blocker)
324 "SELECT * FROM blocks WHERE blocker = ? AND blocked = ?",
327 if fba.c.fetchone() == None:
328 fba.block_instance(blocker, blocked, reason, block_level)
330 if block_level == "reject":
337 fba.update_last_seen(blocker, blocked, block_level)
340 # NOISY-DEBUG: print("DEBUG: Updating block reason:", blocker, blocked, reason)
341 fba.update_block_reason(reason, blocker, blocked, block_level)
344 except Exception as e:
345 print("error:", e, blocker, software)
346 elif software == "gotosocial":
347 print("INFO: blocker:", blocker)
350 federation = reqto.get(f"https://{blocker}/api/v1/instance/peers?filter=suspended", headers=fba.headers, timeout=fba.config["timeout"]).json()
352 if (federation == None):
353 print("WARNING: No valid response:", blocker);
354 elif "error" in federation:
355 print("WARNING: API returned error:", federation["error"])
357 # NOISY-DEBUG: print("DEBUG: Checking fenderation():", len(federation))
358 for peer in federation:
359 blocked = peer["domain"].lower()
360 # NOISY-DEBUG: print("DEBUG: BEFORE-blocked:", blocked)
361 blocked = fba.tidyup(blocked)
362 # NOISY-DEBUG: print("DEBUG: AFTER-blocked:", blocked)
365 print("WARNING: blocked is empty:", blocker)
367 if blocked.count("*") > 0:
368 # GTS does not have hashes for obscured domains, so we have to guess it
370 "SELECT domain FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", [blocked.replace("*", "_")]
372 searchres = fba.c.fetchone()
374 if searchres != None:
375 blocked = searchres[0]
378 "SELECT domain FROM instances WHERE domain = ?", [blocked]
381 if fba.c.fetchone() == None:
382 # NOISY-DEBUG: print("DEBUG: Updating block reason:", blocker, blocked, reason)
383 fba.update_block_reason(reason, blocker, blocked, block_level)
386 "SELECT * FROM blocks WHERE blocker = ? AND blocked = ? AND block_level = ?",
394 if fba.c.fetchone() == None:
395 fba.block_instance(blocker, blocked, "unknown", "reject")
403 fba.update_last_seen(blocker, blocked, "reject")
405 if "public_comment" in peer:
406 reason = peer["public_comment"]
407 # NOISY-DEBUG: print("DEBUG: Updating block reason:", blocker, blocked, reason)
408 fba.update_block_reason(reason, blocker, blocked, "reject")
410 for entry in blockdict:
411 if entry["blocked"] == blocked:
412 entry["reason"] = reason
415 except Exception as e:
416 print("error:", e, blocker, software)
418 print("WARNING: Unknown software:", software)
420 if fba.config["bot_enabled"] and len(blockdict) > 0:
421 send_bot_post(blocker, blockdict)