From efa7a38276344494b09532975d88bd125f9f415c Mon Sep 17 00:00:00 2001 From: Melroy van den Berg Date: Thu, 24 Apr 2025 17:51:31 +0200 Subject: [PATCH] Improve readme and add CI --- .gitlab-ci.yml | 20 ++++++++++++++++++++ README.md | 35 ++++++++++++++++++++++++++--------- demo-fediresolve.png | Bin 0 -> 27497 bytes 3 files changed, 46 insertions(+), 9 deletions(-) create mode 100644 .gitlab-ci.yml create mode 100644 demo-fediresolve.png diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000..233032f --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,20 @@ +image: golang:latest + +stages: + - test + - build + +format: + stage: test + script: + - go fmt $(go list ./... | grep -v /vendor/) + - go vet $(go list ./... | grep -v /vendor/) + +build: + stage: build + script: + - go build + artifacts: + paths: + - fediresolve + expire_in: 1 week diff --git a/README.md b/README.md index 1721057..44143a2 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,32 @@ # FediResolve -FediResolve is a command-line tool for resolving and displaying Fediverse content. It can parse and display ActivityPub content from various Fediverse platforms including Mastodon, Mbin, Lemmy, PeerTube, and others. +FediResolve is a command-line tool for resolving and displaying Fediverse content. + +It can parse and display ActivityPub content from various Fediverse platforms including Mastodon, Mbin, Lemmy, PeerTube, and others. For easy reading or debugging purposes. + +~ Vibe coded within 2 hours. ## Features - Resolve Fediverse URLs to their ActivityPub representation - Resolve Fediverse handles (e.g., @username@domain.tld) - Display both the full JSON data and a human-readable summary -- Support for various ActivityPub types (Person, Note, Article, Create, Announce, etc.) +- Support for various ActivityPub types (Person, Page, Note, Article, etc.) - Automatic resolution of shared/forwarded content to the original source +![Demo of FediResolve](./demo-fediresolve.png) + +## Download + +[FediResolve for Linux](https://gitlab.melroy.org/melroy/fediresolve/-/releases) + ## Installation +Either download the prebuild binary from [releases](https://gitlab.melroy.org/melroy/fediresolve/-/releases) or build from source, see below. + ### Prerequisites -- Go 1.16 or later +- Go 1.21 or later ### Building from source @@ -39,26 +51,31 @@ go build ## Examples +### Resolving a Mbin thread + +```bash +./fediresolve https://kbin.melroy.org/m/til/t/875629/Context7-Up-to-date-documentation-for-LLMs-and-AI-code-editors +``` + ### Resolving a Mastodon post ```bash -./fediresolve https://mastodon.social/@Gargron/12345 +./fediresolve https://mastodon.melroy.org/@melroy/114297155915355913 ``` ### Resolving a user profile ```bash -./fediresolve @Gargron@mastodon.social +./fediresolve @melroy@melroy.org ``` ## How it works FediResolve uses the following process to resolve Fediverse content: -1. For handles (@username@domain.tld), it uses the WebFinger protocol to discover the ActivityPub actor URL -2. For URLs, it attempts to fetch the ActivityPub representation directly -3. It checks if the content is shared/forwarded and resolves to the original source if needed -4. It parses the ActivityPub JSON and displays both the raw data and a formatted summary +1. For handles (`@username@domain.tld`), it uses the WebFinger protocol to discover the ActivityPub actor URL +2. For URLs, it attempts to fetch the ActivityPub representation directly. Or if the content is needs to be resolved from another Fediverse instance. +3. Content is parsed and displays both the raw JSON object and a nice looking summary. ## License diff --git a/demo-fediresolve.png b/demo-fediresolve.png new file mode 100644 index 0000000000000000000000000000000000000000..32a3a232b651ed0de850b07952070a1e31c20976 GIT binary patch literal 27497 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 literal 0 HcmV?d00001