Unverified Commit 93aa47b6 authored by Hong Minhee's avatar Hong Minhee
Browse files

actor-lookup-cli

parent 4175745c
Loading
Loading
Loading
Loading
+8 −0
Original line number Diff line number Diff line
@@ -13,6 +13,14 @@
  },
  "imports": {
    "@cfworker/json-schema": "npm:@cfworker/json-schema@^1.12.8",
    "@fedify/fedify": "./mod.ts",
    "@fedify/fedify/federation": "./federation/mod.ts",
    "@fedify/fedify/httpsig": "./httpsig/mod.ts",
    "@fedify/fedify/nodeinfo": "./nodeinfo/mod.ts",
    "@fedify/fedify/runtime": "./runtime/mod.ts",
    "@fedify/fedify/vocab": "./vocab/mod.ts",
    "@fedify/fedify/webfinger": "./webfinger/mod.ts",
    "@fedify/fedify/x/fresh": "./x/fresh.ts",
    "@js-temporal/polyfill": "npm:@js-temporal/polyfill@^0.4.4",
    "@phensley/language-tag": "npm:@phensley/language-tag@^1.8.0",
    "@std/assert": "jsr:@std/assert@^0.219.1",
+1 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@ This directory contains example applications built with the Fedify framework.
Currently, there is only one example application, but more examples will be 
added in the future.[^1]

  -  [Actor lookup CLI](./actor-lookup-cli/)
  -  [Federated single-user blog](./blog/)

[^1]: Contributions are welcome!  If you have built an application with the
+14 −0
Original line number Diff line number Diff line
actor-lookup-cli
================

This example is a simple CLI program that looks up an actor by their fediverse
handle (e.g. *@user@host*) and prints out their name, bio, stats, etc.  It uses
Fedify as a client library of ActivityPub, not as a server framework here.


Usage
-----

~~~~ sh
deno run -A ./main.ts @hongminhee@todon.eu
~~~~
+63 −0
Original line number Diff line number Diff line
import { getActorHandle, isActor, lookupObject } from "@fedify/fedify/vocab";
import { Temporal } from "@js-temporal/polyfill";
import { convert } from "npm:html-to-text@^9.0.5";

export interface Actor {
  handle: string;
  url: URL | null;
  name: string;
  bio: string;
  following: number | null;
  followers: number | null;
  posts: number | null;
  joined: Temporal.Instant | null;
}

async function lookupActor(handle: string): Promise<Actor> {
  const actor = await lookupObject(handle);
  if (!isActor(actor)) throw new TypeError("Not an actor!");
  const following = await actor.getFollowing();
  const followers = await actor.getFollowers();
  const posts = await actor.getOutbox();
  return {
    handle: await getActorHandle(actor),
    url: actor.url,
    name: actor.name ?? "",
    bio: convert(actor.summary ?? "", {
      selectors: [{ selector: "a", options: { ignoreHref: true } }],
    }),
    following: following?.totalItems,
    followers: followers?.totalItems,
    posts: posts?.totalItems,
    joined: actor.published,
  };
}

function displayActor(actor: Actor): void {
  console.log(actor.name);
  console.log(actor.handle);
  if (actor.url) console.log(actor.url.href);
  console.log();
  console.log(actor.bio);
  console.log();
  if (actor.joined) console.log(`Joined: ${actor.joined.toLocaleString()}`);
  if (actor.following) console.log(`Following: ${actor.following}`);
  if (actor.followers) console.log(`Followers: ${actor.followers}`);
  if (actor.posts) console.log(`Posts: ${actor.posts}`);
}

async function main() {
  if (Deno.args.length < 1) {
    console.error("Usage: deno run -A main.ts HANDLE");
    Deno.exit(1);
  }
  const handle = Deno.args[0];
  if (!handle.match(/^@?[^@]+@[^@]+$/)) {
    console.error("Invalid handle:", handle);
    Deno.exit(1);
  }
  const actor = await lookupActor(handle);
  displayActor(actor);
}

if (import.meta.main) await main();
+8 −7
Original line number Diff line number Diff line
{
  "imports": {
    "@cfworker/json-schema": "npm:@cfworker/json-schema@^1.12.8",
    "@fedify/fedify": "../../mod.ts",
    "@fedify/fedify/federation": "../../federation/mod.ts",
    "@fedify/fedify/httpsig": "../../httpsig/mod.ts",
    "@fedify/fedify/nodeinfo": "./nodeinfo/mod.ts",
    "@fedify/fedify/runtime": "../../runtime/mod.ts",
    "@fedify/fedify/vocab": "../../vocab/mod.ts",
    "@fedify/fedify/webfinger": "../../webfinger/mod.ts",
    "@fedify/fedify/x/fresh": "../../x/fresh.ts",
    "@js-temporal/polyfill": "npm:@js-temporal/polyfill@^0.4.4",
    "@phensley/language-tag": "npm:@phensley/language-tag@^1.8.0",
    "@std/assert": "jsr:@std/assert@^0.219.1",
@@ -26,13 +34,6 @@
    "@preact/signals": "https://esm.sh/*@preact/signals@1.2.1",
    "@preact/signals-core": "https://esm.sh/*@preact/signals-core@1.5.0",
    "@std/dotenv/load": "jsr:@std/dotenv@^0.219.1/load",
    "@fedify/fedify": "../../mod.ts",
    "@fedify/fedify/federation": "../../federation/mod.ts",
    "@fedify/fedify/httpsig": "../../httpsig/mod.ts",
    "@fedify/fedify/runtime": "../../runtime/mod.ts",
    "@fedify/fedify/vocab": "../../vocab/mod.ts",
    "@fedify/fedify/webfinger": "../../webfinger/mod.ts",
    "@fedify/fedify/x/fresh": "../../x/fresh.ts",
    "markdown-it": "npm:markdown-it@^14.0.0",
    "preact": "https://esm.sh/preact@10.19.2",
    "preact/": "https://esm.sh/preact@10.19.2/",