# 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 os
-import sys
-import tempfile
-import zc.lockfile
-from fba import fba
-
-# Lock file
-lockfile = tempfile.gettempdir() + '/fba.lock'
-LOCK = None
-
-def acquire_lock():
- global LOCK
- try:
- print(f"DEBUG: Acquiring lock: '{lockfile}'")
- LOCK = zc.lockfile.LockFile(lockfile)
- print("DEBUG: Lock obtained.")
-
- except zc.lockfile.LockError:
- print(f"ERROR: Cannot aquire lock: '{lockfile}'")
- sys.exit(100)
+import logging
+
+import argparse
+
+from fba import commands
+from fba import database
+
+from fba.helpers import locking
+
+logging.basicConfig(level=logging.INFO)
+logger = logging.getLogger(__name__)
+
+# Argument parser
+_PARSER = None
+
+def init_parser():
+ logger.debug("CALLED!")
+ global _PARSER
+
+ logger.debug("Initializing parser ...")
+ _PARSER = argparse.ArgumentParser(
+ description="Fetches block reasons from the fediverse",
+ epilog="Please note that some commands have optional arguments, you may want to try fba.py <command> --help to find them out. Please DO NOT overdose requests that are not limited by themselves. Typically parameters like --domain, --software and --all are unlimited. \"Unlimited\" here means that there is no \"is recently accessed?\" limitation.",
+ )
+
+ # Generic:
+ _PARSER.add_argument("--debug", action="store_const", dest="log_level", const=logging.DEBUG, help="Full debug output")
+
+ # Commands:
+ subparser_command = _PARSER.add_subparsers(
+ dest="command",
+ title="Commands to execute",
+ required=True,
+ help="Command to perform",
+ )
+
+ ### Check instance ###
+ parser = subparser_command.add_parser(
+ "check_instance",
+ help="Checks given instance if it exists and returns proper exit code"
+ )
+ parser.add_argument("--domain", required=True, help="Instance name (aka. domain) to check")
+ parser.set_defaults(command=commands.check_instance)
+
+ ### Fetch from bka.li ###
+ parser = subparser_command.add_parser(
+ "fetch_bkali",
+ help="Fetches domain names from bka.li API",
+ )
+ parser.set_defaults(command=commands.fetch_bkali)
+
+ ### Recheck instance's obfuscated peers ###
+ parser = subparser_command.add_parser(
+ "recheck_obfuscation",
+ help="Checks all instance's obfuscated peers if they can be de-obfuscated now.",
+ )
+ parser.add_argument("--domain", help="Instance name (aka. domain)")
+ parser.add_argument("--software", help="Name of software, e.g. 'lemmy'")
+ parser.add_argument("--all", action="store_true", help="Include also already existing instances, otherwise only new are checked")
+ parser.set_defaults(command=commands.recheck_obfuscation)
+
+ ### Fetch blocks from registered instances or given ###
+ parser = subparser_command.add_parser(
+ "fetch_blocks",
+ help="Fetches blocks from registered instances (run command fetch_instances first!).",
+ )
+ parser.add_argument("--domain", help="Instance name (aka. domain)")
+ parser.add_argument("--software", help="Name of software, e.g. 'lemmy'")
+ parser.set_defaults(command=commands.fetch_blocks)
+
+ ### Fetch blocks from chaos.social ###
+ parser = subparser_command.add_parser(
+ "fetch_cs",
+ help="Fetches blocks from chaos.social's meta sub domain.",
+ )
+ parser.set_defaults(command=commands.fetch_cs)
+
+ ### Fetch blocks from todon.eu wiki ###
+ parser = subparser_command.add_parser(
+ "fetch_todon_wiki",
+ help="Fetches blocks from todon.eu's wiki.",
+ )
+ parser.set_defaults(command=commands.fetch_todon_wiki)
+
+ ### Fetch blocks from a FBA-specific RSS feed ###
+ parser = subparser_command.add_parser(
+ "fetch_fba_rss",
+ help="Fetches domains from a FBA-specific RSS feed.",
+ )
+ parser.add_argument("--feed", required=True, help="RSS feed to fetch domains from (e.g. https://fba.ryoma.agency/rss?domain=foo.bar).")
+ parser.set_defaults(command=commands.fetch_fba_rss)
+
+ ### Fetch blocks from FBA's bot account ###
+ parser = subparser_command.add_parser(
+ "fetch_fbabot_atom",
+ help="Fetches ATOM feed with domains from FBA's bot account.",
+ )
+ parser.set_defaults(command=commands.fetch_fbabot_atom)
+
+ ### Fetch blocks from oliphant's GIT repository ###
+ parser = subparser_command.add_parser(
+ "fetch_oliphant",
+ help="Fetches CSV files (block recommendations) for more possible instances to disover",
+ )
+ parser.add_argument("--domain", help="Instance name (aka. domain) to check")
+ parser.set_defaults(command=commands.fetch_oliphant)
+
+ ### Fetch instances from given initial instance ###
+ parser = subparser_command.add_parser(
+ "fetch_instances",
+ help="Fetches instances (aka. \"domains\") from an initial instance. You may want to re-run this command several times (at least 3 with big instances) to have a decent amount of valid instances.",
+ )
+ parser.add_argument("--domain", required=True, help="Instance name (aka. domain) to fetch further instances from. Start with a large instance, e.g. mastodon.social .")
+ parser.add_argument("--single", action="store_true", help="Only fetch given instance.")
+ parser.set_defaults(command=commands.fetch_instances)
+
+ ### Fetch blocks from static text file(s) ###
+ parser = subparser_command.add_parser(
+ "fetch_txt",
+ help="Fetches text/plain files as simple domain lists",
+ )
+ parser.set_defaults(command=commands.fetch_txt)
+
+ ### Fetch blocks from joinfediverse.wiki ###
+ parser = subparser_command.add_parser(
+ "fetch_joinfediverse",
+ help="Fetches FediBlock page from joinfediverse.wiki",
+ )
+ parser.set_defaults(command=commands.fetch_joinfediverse)
+
+ ### Fetch blocks from fediverse.observer ###
+ parser = subparser_command.add_parser(
+ "fetch_observer",
+ help="Fetches blocks from fediverse.observer.",
+ )
+ parser.set_defaults(command=commands.fetch_observer)
+ parser.add_argument("--software", help="Name of software, e.g. 'lemmy'")
+
+ ### Fetch instances from fedipact.online ###
+ parser = subparser_command.add_parser(
+ "fetch_fedipact",
+ help="Fetches blocks from fedipact.online.",
+ )
+ parser.set_defaults(command=commands.fetch_fedipact)
+
+ ### Fetch from pixelfed.org's API ###
+ parser = subparser_command.add_parser(
+ "fetch_pixelfed_api",
+ help="Fetches domain names from pixelfed.org's API",
+ )
+ parser.set_defaults(command=commands.fetch_pixelfed_api)
+
+ ### Check nodeinfo ###
+ parser = subparser_command.add_parser(
+ "check_nodeinfo",
+ help="Checks if domain is part of nodeinfo.",
+ )
+ parser.set_defaults(command=commands.check_nodeinfo)
+
+ ### Fetch CSV from fedilist.com ###
+ parser = subparser_command.add_parser(
+ "fetch_fedilist",
+ help="Fetches CSV from fedilist.com",
+ )
+ parser.set_defaults(command=commands.fetch_fedilist)
+ parser.add_argument("--software", help="Name of software, e.g. 'lemmy'")
+ parser.add_argument("--all", action="store_true", help="Include also already existing instances, otherwise only new are checked")
+
+ ### Update nodeinfo ###
+ parser = subparser_command.add_parser(
+ "update_nodeinfo",
+ help="Updates nodeinfo for all instances",
+ )
+ parser.set_defaults(command=commands.update_nodeinfo)
+ parser.add_argument("--domain", help="Instance name (aka. domain)")
+ parser.add_argument("--software", help="Name of software, e.g. 'lemmy'")
+
+ ### Fetch instances from instances.social ###
+ parser = subparser_command.add_parser(
+ "fetch_instances_social",
+ help="Fetch instances from instances.social, you need an API key to access the API. Please consider donating to them when you want to more frequent use their API!",
+ )
+ parser.set_defaults(command=commands.fetch_instances_social)
+
+ logger.debug("EXIT!")
+
+def run_command():
+ logger.debug("CALLED!")
+ args = _PARSER.parse_args()
+
+ if args.log_level is not None:
+ loggers = [logging.getLogger(name) for name in logging.root.manager.loggerDict]
+ for _logger in loggers:
+ _logger.setLevel(args.log_level)
+
+ logger.debug("args[%s]='%s'", type(args), args)
+ status = args.command(args)
+
+ logger.debug("status=%d - EXIT!", status)
+ return status
def shutdown():
- print("DEBUG: Closing database connection ...")
- fba.connection.close()
- print("DEBUG: Releasing lock ...")
- LOCK.close()
- print(f"DEBUG: Deleting lockfile='{lockfile}' ...")
- os.remove(lockfile)
- print("DEBUG: Shutdown completed.")
+ logger.debug("Closing database connection ...")
+ database.connection.close()
+ locking.release()
+ logger.debug("Shutdown completed.")