# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-import argparse
-import atoma
-import bs4
+import csv
import inspect
-import itertools
import json
-import re
-import reqto
import sys
import time
+
+import argparse
+import atoma
+import bs4
+import markdown
+import reqto
+import requests
import validators
from fba import blacklist
from fba import blocks
-from fba import boot
from fba import config
+from fba import federation
from fba import fba
from fba import instances
+from fba import locking
+from fba import network
-from fba.federation import *
+from fba.helpers import tidyup
+
+from fba.networks import friendica
+from fba.networks import mastodon
+from fba.networks import misskey
+from fba.networks import pleroma
def check_instance(args: argparse.Namespace) -> int:
# DEBUG: print(f"DEBUG: args.domain='{args.domain}' - CALLED!")
elif blacklist.is_blacklisted(args.domain):
print(f"WARNING: args.domain='{args.domain}' is blacklisted")
status = 101
- elif fba.is_instance_registered(args.domain):
+ elif instances.is_registered(args.domain):
print(f"WARNING: args.domain='{args.domain}' is already registered")
status = 102
else:
return status
def fetch_bkali(args: argparse.Namespace):
- # DEBUG: print(f"DEBUG: args[]={type(args)} - CALLED!")
+ # DEBUG: print(f"DEBUG: args[]='{type(args)}' - CALLED!")
domains = list()
try:
- fetched = fba.post_json_api("gql.api.bka.li", "/v1/graphql", json.dumps({
+ fetched = network.post_json_api("gql.api.bka.li", "/v1/graphql", json.dumps({
"query": "query domainlist {nodeinfo(order_by: {domain: asc}) {domain}}"
}))
# DEBUG: print(f"DEBUG: fetched({len(fetched)})[]='{type(fetched)}'")
if len(fetched) == 0:
raise Exception("WARNING: Returned no records")
- elif not "data" in fetched:
+ elif "data" not in fetched:
raise Exception(f"WARNING: fetched()={len(fetched)} does not contain key 'data'")
- elif not "nodeinfo" in fetched["data"]:
+ elif "nodeinfo" not in fetched["data"]:
raise Exception(f"WARNING: fetched()={len(fetched['data'])} does not contain key 'nodeinfo'")
for entry in fetched["data"]["nodeinfo"]:
# DEBUG: print(f"DEBUG: entry['{type(entry)}']='{entry}'")
if not "domain" in entry:
- print(f"WARNING: entry does not contain 'domain' - SKIPPED!")
+ print(f"WARNING: entry()={len(entry)} does not contain 'domain' - SKIPPED!")
continue
elif not validators.domain(entry["domain"]):
print(f"WARNING: domain='{entry['domain']}' is not a valid domain - SKIPPED!")
elif blacklist.is_blacklisted(entry["domain"]):
# DEBUG: print(f"DEBUG: domain='{entry['domain']}' is blacklisted - SKIPPED!")
continue
- elif fba.is_instance_registered(entry["domain"]):
+ elif instances.is_registered(entry["domain"]):
# DEBUG: print(f"DEBUG: domain='{entry['domain']}' is already registered - SKIPPED!")
continue
# DEBUG: print(f"DEBUG: Adding domain='{entry['domain']}' ...")
domains.append(entry["domain"])
- except BaseException as e:
- print(f"ERROR: Cannot fetch graphql,exception[{type(e)}]:'{str(e)}'")
+ except network.exceptions as exception:
+ print(f"ERROR: Cannot fetch graphql,exception[{type(exception)}]:'{str(exception)}'")
sys.exit(255)
# DEBUG: print(f"DEBUG: domains()={len(domains)}")
if len(domains) > 0:
- boot.acquire_lock()
+ locking.acquire()
print(f"INFO: Adding {len(domains)} new instances ...")
for domain in domains:
- print(f"INFO: Fetching instances from domain='{domain}' ...")
- fba.fetch_instances(domain, None, None, inspect.currentframe().f_code.co_name)
+ try:
+ print(f"INFO: Fetching instances from domain='{domain}' ...")
+ federation.fetch_instances(domain, None, None, inspect.currentframe().f_code.co_name)
+ except network.exceptions as exception:
+ print(f"WARNING: Exception '{type(exception)}' during fetching instances from domain='{domain}'")
+ instances.update_last_error(domain, exception)
# DEBUG: print("DEBUG: EXIT!")
def fetch_blocks(args: argparse.Namespace):
- # DEBUG: print(f"DEBUG: args[]={type(args)} - CALLED!")
- if args.domain != None and args.domain != "":
+ # DEBUG: print(f"DEBUG: args[]='{type(args)}' - CALLED!")
+ if args.domain is not None and args.domain != "":
+ # DEBUG: print(f"DEBUG: args.domain='{args.domain}' - checking ...")
if not validators.domain(args.domain):
print(f"WARNING: domain='{args.domain}' is not valid.")
return
elif blacklist.is_blacklisted(args.domain):
print(f"WARNING: domain='{args.domain}' is blacklisted, won't check it!")
return
- elif not fba.is_instance_registered(args.domain):
+ elif not instances.is_registered(args.domain):
print(f"WARNING: domain='{args.domain}' is not registered, please run ./fba.py fetch_instances {args.domain} first.")
return
- boot.acquire_lock()
+ locking.acquire()
- if args.domain != None and args.domain != "":
+ if args.domain is not None and args.domain != "":
+ # Re-check single domain
fba.cursor.execute(
- "SELECT domain, software, origin, nodeinfo_url FROM instances WHERE software IN ('pleroma', 'mastodon', 'friendica', 'misskey', 'gotosocial', 'bookwyrm', 'takahe') AND domain = ?", [args.domain]
+ "SELECT domain, software, origin, nodeinfo_url FROM instances WHERE software IN ('pleroma', 'mastodon', 'friendica', 'misskey', 'bookwyrm', 'takahe') AND domain = ?", [args.domain]
)
else:
+ # Re-check after "timeout" (aka. minimum interval)
fba.cursor.execute(
- "SELECT domain, software, origin, nodeinfo_url FROM instances WHERE software IN ('pleroma', 'mastodon', 'friendica', 'misskey', 'gotosocial', 'bookwyrm', 'takahe') AND (last_blocked IS NULL OR last_blocked < ?) ORDER BY rowid DESC", [time.time() - config.get("recheck_block")]
+ "SELECT domain, software, origin, nodeinfo_url FROM instances WHERE software IN ('pleroma', 'mastodon', 'friendica', 'misskey', 'bookwyrm', 'takahe') AND (last_blocked IS NULL OR last_blocked < ?) ORDER BY rowid DESC", [time.time() - config.get("recheck_block")]
)
rows = fba.cursor.fetchall()
for blocker, software, origin, nodeinfo_url in rows:
# DEBUG: print("DEBUG: BEFORE blocker,software,origin,nodeinfo_url:", blocker, software, origin, nodeinfo_url)
blockdict = list()
- blocker = fba.tidyup_domain(blocker)
+ blocker = tidyup.domain(blocker)
# DEBUG: print("DEBUG: AFTER blocker,software:", blocker, software)
if blocker == "":
mastodon.fetch_blocks(blocker, origin, nodeinfo_url)
elif software == "friendica" or software == "misskey":
print(f"INFO: blocker='{blocker}',software='{software}'")
- try:
- if software == "friendica":
- json = fba.fetch_friendica_blocks(blocker)
- elif software == "misskey":
- json = fba.fetch_misskey_blocks(blocker)
-
- print(f"INFO: Checking {len(json.items())} entries from blocker='{blocker}',software='{software}' ...")
- for block_level, blocks in json.items():
- # DEBUG: print("DEBUG: blocker,block_level,blocks():", blocker, block_level, len(blocks))
- block_level = fba.tidyup_domain(block_level)
- # DEBUG: print("DEBUG: AFTER-block_level:", block_level)
- if block_level == "":
- print("WARNING: block_level is empty, blocker:", blocker)
+
+ blocking = list()
+ if software == "friendica":
+ blocking = friendica.fetch_blocks(blocker)
+ elif software == "misskey":
+ blocking = misskey.fetch_blocks(blocker)
+
+ print(f"INFO: Checking {len(blocking.items())} entries from blocker='{blocker}',software='{software}' ...")
+ for block_level, blocklist in blocking.items():
+ # DEBUG: print("DEBUG: blocker,block_level,blocklist():", blocker, block_level, len(blocklist))
+ block_level = tidyup.domain(block_level)
+ # DEBUG: print("DEBUG: AFTER-block_level:", block_level)
+ if block_level == "":
+ print("WARNING: block_level is empty, blocker:", blocker)
+ continue
+
+ # DEBUG: print(f"DEBUG: Checking {len(blocklist)} entries from blocker='{blocker}',software='{software}',block_level='{block_level}' ...")
+ for block in blocklist:
+ blocked, reason = block.values()
+ # DEBUG: print(f"DEBUG: blocked='{blocked}',reason='{reason}' - BEFORE!")
+ blocked = tidyup.domain(blocked)
+ reason = tidyup.reason(reason) if reason is not None and reason != "" else None
+ # DEBUG: print(f"DEBUG: blocked='{blocked}',reason='{reason}' - AFTER!")
+
+ if blocked == "":
+ print("WARNING: blocked is empty:", blocker)
+ continue
+ elif blacklist.is_blacklisted(blocked):
+ # DEBUG: print(f"DEBUG: blocked='{blocked}' is blacklisted - skipping!")
continue
+ elif blocked.count("*") > 0:
+ # Some friendica servers also obscure domains without hash
+ fba.cursor.execute(
+ "SELECT domain, origin, nodeinfo_url FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", [blocked.replace("*", "_")]
+ )
- # DEBUG: print(f"DEBUG: Checking {len(blocks)} entries from blocker='{blocker}',software='{software}',block_level='{block_level}' ...")
- for block in blocks:
- blocked, reason = block.values()
- # DEBUG: print("DEBUG: BEFORE blocked:", blocked)
- blocked = fba.tidyup_domain(blocked)
- # DEBUG: print("DEBUG: AFTER blocked:", blocked)
+ searchres = fba.cursor.fetchone()
- if blocked == "":
- print("WARNING: blocked is empty:", blocker)
- continue
- elif blacklist.is_blacklisted(blocked):
- # DEBUG: print(f"DEBUG: blocked='{blocked}' is blacklisted - skipping!")
- continue
- elif blocked.count("*") > 0:
- # Some friendica servers also obscure domains without hash
- fba.cursor.execute(
- "SELECT domain, origin, nodeinfo_url FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", [blocked.replace("*", "_")]
- )
-
- searchres = fba.cursor.fetchone()
-
- if searchres == None:
- print(f"WARNING: Cannot deobsfucate blocked='{blocked}' - SKIPPED!")
- continue
-
- blocked = searchres[0]
- origin = searchres[1]
- nodeinfo_url = searchres[2]
- elif blocked.count("?") > 0:
- # Some obscure them with question marks, not sure if that's dependent on version or not
- fba.cursor.execute(
- "SELECT domain, origin, nodeinfo_url FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", [blocked.replace("?", "_")]
- )
-
- searchres = fba.cursor.fetchone()
-
- if searchres == None:
- print(f"WARNING: Cannot deobsfucate blocked='{blocked}' - SKIPPED!")
- continue
-
- blocked = searchres[0]
- origin = searchres[1]
- nodeinfo_url = searchres[2]
- elif not validators.domain(blocked):
- print(f"WARNING: blocked='{blocked}',software='{software}' is not a valid domain name - skipped!")
+ # DEBUG: print(f"DEBUG: searchres[]='{type(searchres)}'")
+ if searchres is None:
+ print(f"WARNING: Cannot deobsfucate blocked='{blocked}' - SKIPPED!")
continue
- # DEBUG: print("DEBUG: Looking up instance by domain:", blocked)
- if not validators.domain(blocked):
- print(f"WARNING: blocked='{blocked}',software='{software}' is not a valid domain name - skipped!")
- continue
- elif not fba.is_instance_registered(blocked):
- # DEBUG: print("DEBUG: Hash wasn't found, adding:", blocked, blocker)
- fba.add_instance(blocked, blocker, inspect.currentframe().f_code.co_name, nodeinfo_url)
-
- if not blocks.is_instance_blocked(blocker, blocked, block_level):
- blocks.add_instance(blocker, blocked, reason, block_level)
-
- if block_level == "reject":
- blockdict.append({
- "blocked": blocked,
- "reason" : reason
- })
- else:
- # DEBUG: print(f"DEBUG: Updating block last seen and reason for blocker='{blocker}',blocked='{blocked}' ...")
- fba.update_last_seen(blocker, blocked, block_level)
- blocks.update_reason(reason, blocker, blocked, block_level)
-
- # DEBUG: print("DEBUG: Committing changes ...")
- fba.connection.commit()
- except Exception as e:
- print(f"ERROR: blocker='{blocker}',software='{software}',exception[{type(e)}]:'{str(e)}'")
- elif software == "gotosocial":
- print(f"INFO: blocker='{blocker}',software='{software}'")
- try:
- # Blocks
- federation = fba.get_response(blocker, f"{fba.get_peers_url}?filter=suspended", fba.api_headers, (config.get("connection_timeout"), config.get("read_timeout"))).json()
-
- if (federation == None):
- print("WARNING: No valid response:", blocker);
- elif "error" in federation:
- print("WARNING: API returned error:", federation["error"])
- else:
- print(f"INFO: Checking {len(federation)} entries from blocker='{blocker}',software='{software}' ...")
- for peer in federation:
- blocked = peer["domain"].lower()
- # DEBUG: print("DEBUG: BEFORE blocked:", blocked)
- blocked = fba.tidyup_domain(blocked)
- # DEBUG: print("DEBUG: AFTER blocked:", blocked)
-
- if blocked == "":
- print("WARNING: blocked is empty:", blocker)
- continue
- elif blacklist.is_blacklisted(blocked):
- # DEBUG: print(f"DEBUG: blocked='{blocked}' is blacklisted - skipping!")
- continue
- elif blocked.count("*") > 0:
- # GTS does not have hashes for obscured domains, so we have to guess it
- fba.cursor.execute(
- "SELECT domain, origin, nodeinfo_url FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", [blocked.replace("*", "_")]
- )
- searchres = fba.cursor.fetchone()
-
- if searchres == None:
- print(f"WARNING: Cannot deobsfucate blocked='{blocked}' - SKIPPED!")
- continue
-
- blocked = searchres[0]
- origin = searchres[1]
- nodeinfo_url = searchres[2]
- elif not validators.domain(blocked):
- print(f"WARNING: blocked='{blocked}',software='{software}' is not a valid domain name - skipped!")
- continue
+ blocked = searchres[0]
+ origin = searchres[1]
+ nodeinfo_url = searchres[2]
+ elif blocked.count("?") > 0:
+ # Some obscure them with question marks, not sure if that's dependent on version or not
+ fba.cursor.execute(
+ "SELECT domain, origin, nodeinfo_url FROM instances WHERE domain LIKE ? ORDER BY rowid LIMIT 1", [blocked.replace("?", "_")]
+ )
+
+ searchres = fba.cursor.fetchone()
- # DEBUG: print("DEBUG: Looking up instance by domain:", blocked)
- if not validators.domain(blocked):
- print(f"WARNING: blocked='{blocked}',software='{software}' is not a valid domain name - skipped!")
+ # DEBUG: print(f"DEBUG: searchres[]='{type(searchres)}'")
+ if searchres is None:
+ print(f"WARNING: Cannot deobsfucate blocked='{blocked}' - SKIPPED!")
continue
- elif not fba.is_instance_registered(blocked):
- # DEBUG: print(f"DEBUG: Domain blocked='{blocked}' wasn't found, adding ..., blocker='{blocker}',origin='{origin}',nodeinfo_url='{nodeinfo_url}'")
- fba.add_instance(blocked, blocker, inspect.currentframe().f_code.co_name, nodeinfo_url)
- if not blocks.is_instance_blocked(blocker, blocked, "reject"):
- # DEBUG: print(f"DEBUG: blocker='{blocker}' is blocking '{blocked}' for unknown reason at this point")
- blocks.add_instance(blocker, blocked, "unknown", "reject")
+ blocked = searchres[0]
+ origin = searchres[1]
+ nodeinfo_url = searchres[2]
+ elif not validators.domain(blocked):
+ print(f"WARNING: blocked='{blocked}',software='{software}' is not a valid domain name - skipped!")
+ continue
+
+ # DEBUG: print("DEBUG: Looking up instance by domain:", blocked)
+ if not validators.domain(blocked):
+ print(f"WARNING: blocked='{blocked}',software='{software}' is not a valid domain name - skipped!")
+ continue
+ elif not instances.is_registered(blocked):
+ # DEBUG: print("DEBUG: Hash wasn't found, adding:", blocked, blocker)
+ instances.add(blocked, blocker, inspect.currentframe().f_code.co_name, nodeinfo_url)
+
+ if not blocks.is_instance_blocked(blocker, blocked, block_level):
+ blocks.add_instance(blocker, blocked, reason, block_level)
+ if block_level == "reject":
blockdict.append({
"blocked": blocked,
- "reason" : None
+ "reason" : reason
})
- else:
- # DEBUG: print(f"DEBUG: Updating block last seen for blocker='{blocker}',blocked='{blocked}' ...")
- fba.update_last_seen(blocker, blocked, "reject")
-
- if "public_comment" in peer:
- # DEBUG: print("DEBUG: Updating block reason:", blocker, blocked, peer["public_comment"])
- blocks.update_reason(peer["public_comment"], blocker, blocked, "reject")
-
- for entry in blockdict:
- if entry["blocked"] == blocked:
- # DEBUG: print(f"DEBUG: Setting block reason for blocked='{blocked}':'{peer['public_comment']}'")
- entry["reason"] = peer["public_comment"]
-
- # DEBUG: print("DEBUG: Committing changes ...")
- fba.connection.commit()
- except Exception as e:
- print(f"ERROR: blocker='{blocker}',software='{software}',exception[{type(e)}]:'{str(e)}'")
+ else:
+ # DEBUG: print(f"DEBUG: Updating block last seen and reason for blocker='{blocker}',blocked='{blocked}' ...")
+ blocks.update_last_seen(blocker, blocked, block_level)
+ blocks.update_reason(reason, blocker, blocked, block_level)
+
+ # DEBUG: print("DEBUG: Committing changes ...")
+ fba.connection.commit()
else:
print("WARNING: Unknown software:", blocker, software)
if config.get("bot_enabled") and len(blockdict) > 0:
- send_bot_post(blocker, blockdict)
-
- blockdict = []
+ network.send_bot_post(blocker, blockdict)
# DEBUG: print("DEBUG: EXIT!")
def fetch_cs(args: argparse.Namespace):
- # DEBUG: print(f"DEBUG: args[]={type(args)} - CALLED!")
+ # DEBUG: print(f"DEBUG: args[]='{type(args)}' - CALLED!")
+ extensions = [
+ 'extra',
+ 'abbr',
+ 'attr_list',
+ 'def_list',
+ 'fenced_code',
+ 'footnotes',
+ 'md_in_html',
+ 'admonition',
+ 'codehilite',
+ 'legacy_attrs',
+ 'legacy_em',
+ 'meta',
+ 'nl2br',
+ 'sane_lists',
+ 'smarty',
+ 'toc',
+ 'wikilinks'
+ ]
+
domains = {
"silenced": list(),
- "blocked": list(),
+ "reject" : list(),
}
- try:
- doc = bs4.BeautifulSoup(
- fba.get_response("meta.chaos.social", "/federation", fba.headers, (config.get("connection_timeout"), config.get("read_timeout"))).text,
- "html.parser",
- )
- # DEBUG: print(f"DEBUG: doc()={len(doc)}[]={type(doc)}")
- silenced = doc.find("h2", {"id": "silenced-instances"}).findNext("table")
+ raw = fba.fetch_url("https://raw.githubusercontent.com/chaossocial/meta/master/federation.md", network.web_headers, (config.get("connection_timeout"), config.get("read_timeout"))).text
+ # DEBUG: print(f"DEBUG: raw()={len(raw)}[]='{type(raw)}'")
- # DEBUG: print(f"DEBUG: silenced[]={type(silenced)}")
- domains["silenced"] = domains["silenced"] + find_domains(silenced)
- blocked = doc.find("h2", {"id": "blocked-instances"}).findNext("table")
+ doc = bs4.BeautifulSoup(markdown.markdown(raw, extensions=extensions), features='html.parser')
- # DEBUG: print(f"DEBUG: blocked[]={type(blocked)}")
- domains["blocked"] = domains["blocked"] + find_domains(blocked)
+ # DEBUG: print(f"DEBUG: doc()={len(doc)}[]='{type(doc)}'")
+ silenced = doc.find("h2", {"id": "silenced-instances"}).findNext("table").find("tbody")
+ # DEBUG: print(f"DEBUG: silenced[]='{type(silenced)}'")
+ domains["silenced"] = domains["silenced"] + federation.find_domains(silenced)
- except BaseException as e:
- print(f"ERROR: Cannot fetch from meta.chaos.social,exception[{type(e)}]:'{str(e)}'")
- sys.exit(255)
+ blocked = doc.find("h2", {"id": "blocked-instances"}).findNext("table").find("tbody")
+ # DEBUG: print(f"DEBUG: blocked[]='{type(blocked)}'")
+ domains["reject"] = domains["reject"] + federation.find_domains(blocked)
# DEBUG: print(f"DEBUG: domains()={len(domains)}")
if len(domains) > 0:
- boot.acquire_lock()
+ locking.acquire()
print(f"INFO: Adding {len(domains)} new instances ...")
for block_level in domains:
for row in domains[block_level]:
# DEBUG: print(f"DEBUG: row='{row}'")
- if not fba.is_instance_registered(row["domain"]):
- print(f"INFO: Fetching instances from domain='{row['domain']}' ...")
- fba.fetch_instances(row["domain"], None, None, inspect.currentframe().f_code.co_name)
-
if not blocks.is_instance_blocked('chaos.social', row["domain"], block_level):
# DEBUG: print(f"DEBUG: domain='{row['domain']}',block_level='{block_level}' blocked by chaos.social, adding ...")
blocks.add_instance('chaos.social', row["domain"], row["reason"], block_level)
+ if not instances.is_registered(row["domain"]):
+ try:
+ print(f"INFO: Fetching instances from domain='{row['domain']}' ...")
+ federation.fetch_instances(row["domain"], 'chaos.social', None, inspect.currentframe().f_code.co_name)
+ except network.exceptions as exception:
+ print(f"WARNING: Exception '{type(exception)}' during fetching instances from domain='{row['domain']}'")
+ instances.update_last_error(row["domain"], exception)
+
# DEBUG: print("DEBUG: Committing changes ...")
fba.connection.commit()
# DEBUG: print("DEBUG: EXIT!")
def fetch_fba_rss(args: argparse.Namespace):
- # DEBUG: print(f"DEBUG: args[]={type(args)} - CALLED!")
+ # DEBUG: print(f"DEBUG: args[]='{type(args)}' - CALLED!")
domains = list()
- try:
- print(f"INFO: Fetch FBA-specific RSS args.feed='{args.feed}' ...")
- response = fba.get_url(args.feed, fba.headers, (config.get("connection_timeout"), config.get("read_timeout")))
+ print(f"INFO: Fetch FBA-specific RSS args.feed='{args.feed}' ...")
+ response = fba.fetch_url(args.feed, network.web_headers, (config.get("connection_timeout"), config.get("read_timeout")))
- # DEBUG: print(f"DEBUG: response.ok={response.ok},response.status_code='{response.status_code}',response.text()={len(response.text)}")
- if response.ok and response.status_code < 300 and len(response.text) > 0:
- # DEBUG: print(f"DEBUG: Parsing RSS feed ...")
- rss = atoma.parse_rss_bytes(response.content)
+ # DEBUG: print(f"DEBUG: response.ok={response.ok},response.status_code='{response.status_code}',response.text()={len(response.text)}")
+ if response.ok and response.status_code < 300 and len(response.text) > 0:
+ # DEBUG: print(f"DEBUG: Parsing RSS feed ({len(response.text)} Bytes) ...")
+ rss = atoma.parse_rss_bytes(response.content)
- # DEBUG: print(f"DEBUG: rss[]={type(rss)}")
- for item in rss.items:
- # DEBUG: print(f"DEBUG: item={item}")
- domain = item.link.split("=")[1]
-
- if blacklist.is_blacklisted(domain):
- # DEBUG: print(f"DEBUG: domain='{domain}' is blacklisted - SKIPPED!")
- continue
- elif domain in domains:
- # DEBUG: print(f"DEBUG: domain='{domain}' is already added - SKIPPED!")
- continue
- elif fba.is_instance_registered(domain):
- # DEBUG: print(f"DEBUG: domain='{domain}' is already registered - SKIPPED!")
- continue
+ # DEBUG: print(f"DEBUG: rss[]='{type(rss)}'")
+ for item in rss.items:
+ # DEBUG: print(f"DEBUG: item={item}")
+ domain = item.link.split("=")[1]
- # DEBUG: print(f"DEBUG: Adding domain='{domain}'")
- domains.append(domain)
+ if blacklist.is_blacklisted(domain):
+ # DEBUG: print(f"DEBUG: domain='{domain}' is blacklisted - SKIPPED!")
+ continue
+ elif domain in domains:
+ # DEBUG: print(f"DEBUG: domain='{domain}' is already added - SKIPPED!")
+ continue
+ elif instances.is_registered(domain):
+ # DEBUG: print(f"DEBUG: domain='{domain}' is already registered - SKIPPED!")
+ continue
- except BaseException as e:
- print(f"ERROR: Cannot fetch feed='{feed}',exception[{type(e)}]:'{str(e)}'")
- sys.exit(255)
+ # DEBUG: print(f"DEBUG: Adding domain='{domain}'")
+ domains.append(domain)
# DEBUG: print(f"DEBUG: domains()={len(domains)}")
if len(domains) > 0:
- boot.acquire_lock()
+ locking.acquire()
print(f"INFO: Adding {len(domains)} new instances ...")
for domain in domains:
- print(f"INFO: Fetching instances from domain='{domain}' ...")
- fba.fetch_instances(domain, None, None, inspect.currentframe().f_code.co_name)
+ try:
+ print(f"INFO: Fetching instances from domain='{domain}' ...")
+ federation.fetch_instances(domain, None, None, inspect.currentframe().f_code.co_name)
+ except network.exceptions as exception:
+ print(f"WARNING: Exception '{type(exception)}' during fetching instances from domain='{domain}'")
+ instances.update_last_error(domain, exception)
# DEBUG: print("DEBUG: EXIT!")
def fetch_fbabot_atom(args: argparse.Namespace):
- # DEBUG: print(f"DEBUG: args[]={type(args)} - CALLED!")
+ # DEBUG: print(f"DEBUG: args[]='{type(args)}' - CALLED!")
feed = "https://ryona.agency/users/fba/feed.atom"
domains = list()
- try:
- print(f"INFO: Fetching ATOM feed='{feed}' from FBA bot account ...")
- response = fba.get_url(feed, fba.headers, (config.get("connection_timeout"), config.get("read_timeout")))
-
- # DEBUG: print(f"DEBUG: response.ok={response.ok},response.status_code='{response.status_code}',response.text()={len(response.text)}")
- if response.ok and response.status_code < 300 and len(response.text) > 0:
- # DEBUG: print(f"DEBUG: Parsing ATOM feed ...")
- atom = atoma.parse_atom_bytes(response.content)
-
- # DEBUG: print(f"DEBUG: atom[]={type(atom)}")
- for entry in atom.entries:
- # DEBUG: print(f"DEBUG: entry[]={type(entry)}")
- doc = bs4.BeautifulSoup(entry.content.value, "html.parser")
- # DEBUG: print(f"DEBUG: doc[]={type(doc)}")
- for element in doc.findAll("a"):
- for href in element["href"].split(","):
- # DEBUG: print(f"DEBUG: href[{type(href)}]={href}")
- domain = fba.tidyup_domain(href)
-
- # DEBUG: print(f"DEBUG: domain='{domain}'")
- if blacklist.is_blacklisted(domain):
- # DEBUG: print(f"DEBUG: domain='{domain}' is blacklisted - SKIPPED!")
- continue
- elif domain in domains:
- # DEBUG: print(f"DEBUG: domain='{domain}' is already added - SKIPPED!")
- continue
- elif fba.is_instance_registered(domain):
- # DEBUG: print(f"DEBUG: domain='{domain}' is already registered - SKIPPED!")
- continue
- # DEBUG: print(f"DEBUG: Adding domain='{domain}',domains()={len(domains)}")
- domains.append(domain)
+ print(f"INFO: Fetching ATOM feed='{feed}' from FBA bot account ...")
+ response = fba.fetch_url(feed, network.web_headers, (config.get("connection_timeout"), config.get("read_timeout")))
+
+ # DEBUG: print(f"DEBUG: response.ok={response.ok},response.status_code='{response.status_code}',response.text()={len(response.text)}")
+ if response.ok and response.status_code < 300 and len(response.text) > 0:
+ # DEBUG: print(f"DEBUG: Parsing ATOM feed ({len(response.text)} Bytes) ...")
+ atom = atoma.parse_atom_bytes(response.content)
+
+ # DEBUG: print(f"DEBUG: atom[]='{type(atom)}'")
+ for entry in atom.entries:
+ # DEBUG: print(f"DEBUG: entry[]='{type(entry)}'")
+ doc = bs4.BeautifulSoup(entry.content.value, "html.parser")
+ # DEBUG: print(f"DEBUG: doc[]='{type(doc)}'")
+ for element in doc.findAll("a"):
+ for href in element["href"].split(","):
+ # DEBUG: print(f"DEBUG: href[{type(href)}]={href}")
+ domain = tidyup.domain(href)
+
+ # DEBUG: print(f"DEBUG: domain='{domain}'")
+ if blacklist.is_blacklisted(domain):
+ # DEBUG: print(f"DEBUG: domain='{domain}' is blacklisted - SKIPPED!")
+ continue
+ elif domain in domains:
+ # DEBUG: print(f"DEBUG: domain='{domain}' is already added - SKIPPED!")
+ continue
+ elif instances.is_registered(domain):
+ # DEBUG: print(f"DEBUG: domain='{domain}' is already registered - SKIPPED!")
+ continue
- except BaseException as e:
- print(f"ERROR: Cannot fetch feed='{feed}',exception[{type(e)}]:'{str(e)}'")
- sys.exit(255)
+ # DEBUG: print(f"DEBUG: Adding domain='{domain}',domains()={len(domains)}")
+ domains.append(domain)
# DEBUG: print(f"DEBUG: domains({len(domains)})={domains}")
if len(domains) > 0:
- boot.acquire_lock()
+ locking.acquire()
print(f"INFO: Adding {len(domains)} new instances ...")
for domain in domains:
- print(f"INFO: Fetching instances from domain='{domain}' ...")
- fba.fetch_instances(domain, None, None, inspect.currentframe().f_code.co_name)
+ try:
+ print(f"INFO: Fetching instances from domain='{domain}' ...")
+ federation.fetch_instances(domain, None, None, inspect.currentframe().f_code.co_name)
+ except network.exceptions as exception:
+ print(f"WARNING: Exception '{type(exception)}' during fetching instances from domain='{domain}'")
+ instances.update_last_error(domain, exception)
# DEBUG: print("DEBUG: EXIT!")
def fetch_instances(args: argparse.Namespace):
- # DEBUG: print(f"DEBUG: args[]={type(args)} - CALLED!")
- boot.acquire_lock()
+ # DEBUG: print(f"DEBUG: args[]='{type(args)}' - CALLED!")
+ locking.acquire()
# Initial fetch
- fba.fetch_instances(args.domain, None, None, inspect.currentframe().f_code.co_name)
+ try:
+ print(f"INFO: Fetching instances from args.domain='{args.domain}' ...")
+ federation.fetch_instances(args.domain, None, None, inspect.currentframe().f_code.co_name)
+ except network.exceptions as exception:
+ print(f"WARNING: Exception '{type(exception)}' during fetching instances from args.domain='{args.domain}'")
+ instances.update_last_error(args.domain, exception)
+ return
if args.single:
- # DEBUG: print(f"DEBUG: Not fetching more instances - EXIT!")
+ # DEBUG: print("DEBUG: Not fetching more instances - EXIT!")
return
# Loop through some instances
fba.cursor.execute(
- "SELECT domain, origin, software, nodeinfo_url FROM instances WHERE software IN ('pleroma', 'mastodon', 'friendica', 'misskey', 'gotosocial', 'bookwyrm', 'takahe', 'lemmy') AND (last_instance_fetch IS NULL OR last_instance_fetch < ?) ORDER BY rowid DESC", [time.time() - config.get("recheck_instance")]
+ "SELECT domain, origin, software, nodeinfo_url FROM instances WHERE software IN ('pleroma', 'mastodon', 'friendica', 'misskey', 'bookwyrm', 'takahe', 'lemmy') AND (last_instance_fetch IS NULL OR last_instance_fetch < ?) ORDER BY rowid DESC", [time.time() - config.get("recheck_instance")]
)
rows = fba.cursor.fetchall()
print(f"INFO: Checking {len(rows)} entries ...")
for row in rows:
- # DEBUG: print("DEBUG: domain:", row[0])
+ # DEBUG: print(f"DEBUG: domain='{row[0]}'")
if blacklist.is_blacklisted(row[0]):
print("WARNING: domain is blacklisted:", row[0])
continue
- print(f"INFO: Fetching instances for instance '{row[0]}' ('{row[2]}') of origin='{row[1]}',nodeinfo_url='{row[3]}'")
- fba.fetch_instances(row[0], row[1], row[2], inspect.currentframe().f_code.co_name, row[3])
+ try:
+ print(f"INFO: Fetching instances for instance '{row[0]}' ('{row[2]}') of origin='{row[1]}',nodeinfo_url='{row[3]}'")
+ federation.fetch_instances(row[0], row[1], row[2], inspect.currentframe().f_code.co_name, row[3])
+ except network.exceptions as exception:
+ print(f"WARNING: Exception '{type(exception)}' during fetching instances from domain='{row[0]}'")
+ instances.update_last_error(row[0], exception)
+
+ # DEBUG: print("DEBUG: EXIT!")
+
+def fetch_federater(args: argparse.Namespace):
+ # DEBUG: print(f"DEBUG: args[]='{type(args)}' - CALLED!")
+ locking.acquire()
+
+ # Fetch this URL
+ response = fba.fetch_url("https://github.com/federater/blocks_recommended/raw/main/federater.csv", network.web_headers, (config.get("connection_timeout"), config.get("read_timeout")))
+ # DEBUG: print(f"DEBUG: response[]='{type(response)}'")
+ if response.ok and response.content != "":
+ # DEBUG: print(f"DEBUG: Fetched {len(response.content)} Bytes, parsing CSV ...")
+ ## DEBUG: print(f"DEBUG: response.content={response.content}")
+ reader = csv.DictReader(response.content.decode('utf-8').splitlines(), dialect='unix')
+ #, fieldnames='domain,severity,reject_media,reject_reports,public_comment,obfuscate'
+ # DEBUG: print(f"DEBUG: reader[]='{type(reader)}'")
+ for row in reader:
+ if not validators.domain(row["#domain"]):
+ print(f"WARNING: domain='{row['#domain']}' is not a valid domain - skipped!")
+ continue
+ elif blacklist.is_blacklisted(row["#domain"]):
+ print(f"WARNING: domain='{row['#domain']}' is blacklisted - skipped!")
+ continue
+ elif instances.is_registered(row["#domain"]):
+ # DEBUG: print(f"DEBUG: domain='{row['#domain']}' is already registered - skipped!")
+ continue
+
+ try:
+ print(f"INFO: Fetching instances for instane='{row['#domain']}' ...")
+ federation.fetch_instances(row["#domain"], None, None, inspect.currentframe().f_code.co_name)
+ except network.exceptions as exception:
+ print(f"WARNING: Exception '{type(exception)}' during fetching instances from domain='{row['#domain']}'")
+ instances.update_last_error(row["#domain"], exception)
# DEBUG: print("DEBUG: EXIT!")