Last active
August 23, 2023 15:40
-
-
Save joachimesque/237bda8712f8fd29d0aaccf1ac30d8a5 to your computer and use it in GitHub Desktop.
A simple command line utility that returns a JSON-formatted definitions list of the handle and url of a Fediverse address/handle/url
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"""Returns a JSON-formatted definitions list of the handle and url of a Fediverse address.""" | |
import json | |
import re | |
import click | |
import requests | |
API_ASK = ".well-known/webfinger?resource=acct:" | |
API_REL_PROFILE = "http://webfinger.net/rel/profile-page" | |
API_REL_SELF = "self" | |
# RegEx from https://regex101.com/library/ac4fG5 | |
FEDI_HANDLE_REGEX = r"@?\b([A-Z0-9._%+-]+)@([A-Z0-9.-]+\.[A-Z]{2,})\b" | |
FEDI_URL_REGEX = ( | |
r"(?:https:\/\/)?([-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,}\b)\/(?:@|user\/)?([\w]*)" | |
) | |
TYPE_HANDLE = "handle" | |
TYPE_URL = "url" | |
def kill(reason): | |
"""Exits the program in run from command line, or returns a boolean status + reason""" | |
if __name__ == "__main__": | |
click.echo(reason) | |
exit(1) | |
return (False, reason) | |
def get_url(name, domain): | |
"""Uses the name and domain to ask the mastodon server the valid url""" | |
ask_url = f"https://{domain}/{API_ASK}{name}@{domain}" | |
try: | |
r = requests.get(ask_url) | |
result = r.json() | |
except requests.exceptions.ConnectionError: | |
kill("Unexpected Error: Bad domain name. Please verify your informations.") | |
except requests.exceptions.JSONDecodeError: | |
kill("Unexpected Error: Bad username. Please verify your informations.") | |
except Exception as err: | |
kill(f"Unexpected {err=}, {type(err)=}") | |
if "aliases" in result: | |
return result["aliases"][0] | |
if "links" in result: | |
for link in result["links"]: | |
if link["rel"] == API_REL_PROFILE: | |
return link["href"] | |
for link in result["links"]: | |
if link["rel"] == API_REL_SELF: | |
return link["href"] | |
def get_handle(name, domain): | |
"""Uses the name and domain to create a simple Fediverse handle""" | |
return f"@{name}@{domain}" | |
def get_handle_parts(str_input): | |
"""Tests the input string against a handle and and URL regex, | |
and returns a dict containing the input type, the name and domain | |
""" | |
handle_test = re.match(FEDI_HANDLE_REGEX, str_input, re.IGNORECASE) | |
if handle_test: | |
input_type = TYPE_HANDLE | |
name = handle_test.group(1) | |
domain = handle_test.group(2) | |
return {"type": input_type, "name": name, "domain": domain} | |
url_test = re.match(FEDI_URL_REGEX, str_input, re.IGNORECASE) | |
if url_test: | |
input_type = TYPE_URL | |
name = url_test.group(2) | |
domain = url_test.group(1) | |
return {"type": input_type, "name": name, "domain": domain} | |
return {"type": None, "name": "", "domain": ""} | |
def get_handle_and_url(handle_or_url): | |
"""Returns a JSON-formatted definitions list of the handle and url of a Fediverse address. | |
HANDLE_OR_URL should be a valid Fediverse handle or profile URL in the form | |
- @username@domain for a handle | |
- [https://]domain/[@|user/]username (parts between brackets are optional) | |
""" | |
handle_parts = get_handle_parts(handle_or_url) | |
if not handle_parts["type"]: | |
kill( | |
"Unexpected Error: the string you supplied isn’t a recognizable handle or url" | |
) | |
url = get_url(handle_parts["name"], handle_parts["domain"]) | |
handle = get_handle(handle_parts["name"], handle_parts["domain"]) | |
json_export = json.dumps({"url": url, "handle": handle}) | |
if __name__ == "__main__": | |
click.echo(json_export) | |
return (True, str(json_export)) | |
@click.command() | |
@click.argument("handle_or_url", type=str) | |
def main(handle_or_url): | |
get_handle_and_url(handle_or_url) | |
if __name__ == "__main__": | |
main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Usage
Or
Requirements