feat(federation): Add ActivityPub bridge support with CLI command

This commit is contained in:
Jesse Wierzbinski 2024-07-16 23:29:20 +02:00
parent 153aa061f0
commit ff315af230
No known key found for this signature in database
13 changed files with 2337 additions and 15 deletions

View file

@ -1,9 +1,11 @@
import { parseUserAddress, userAddressValidator } from "@/api";
import { SignatureConstructor } from "@lysand-org/federation";
import { FederationRequester } from "@lysand-org/federation/requester";
import { Args } from "@oclif/core";
import chalk from "chalk";
import ora from "ora";
import { BaseCommand } from "~/cli/base";
import { Instance } from "~/packages/database-interface/instance";
import { User } from "~/packages/database-interface/user";
export default class FederationUserFetch extends BaseCommand<
@ -16,7 +18,7 @@ export default class FederationUserFetch extends BaseCommand<
}),
};
static override description = "Fetch the URL of remote users via WebFinger";
static override description = "Fetch remote users";
static override examples = ["<%= config.bin %> <%= command.id %>"];
@ -25,9 +27,21 @@ export default class FederationUserFetch extends BaseCommand<
public async run(): Promise<void> {
const { args } = await this.parse(FederationUserFetch);
const spinner = ora("Fetching user URI").start();
// Check if the address is valid
if (!args.address.match(userAddressValidator)) {
this.log(
"Invalid address. Please check the address format and try again. For example: name@host.com",
);
const [username, host] = args.address.split("@");
this.exit(1);
}
const spinner = ora("Fetching user").start();
const { username, domain: host } = parseUserAddress(args.address);
// Check instance exists, if not, create it
await Instance.resolve(`https://${host}`);
const requester = await User.getServerActor();
@ -42,9 +56,15 @@ export default class FederationUserFetch extends BaseCommand<
const uri = await manager.webFinger(username);
spinner.succeed("Fetched user URI");
const newUser = await User.resolve(uri);
this.log(`URI: ${chalk.blueBright(uri)}`);
if (newUser) {
spinner.succeed();
this.log(chalk.green(`User found: ${newUser.getUri()}`));
} else {
spinner.fail();
this.log(chalk.red("User not found"));
}
this.exit(0);
}

View file

@ -0,0 +1,65 @@
import { parseUserAddress, userAddressValidator } from "@/api";
import { SignatureConstructor } from "@lysand-org/federation";
import { FederationRequester } from "@lysand-org/federation/requester";
import { Args } from "@oclif/core";
import chalk from "chalk";
import ora from "ora";
import { BaseCommand } from "~/cli/base";
import { Instance } from "~/packages/database-interface/instance";
import { User } from "~/packages/database-interface/user";
export default class FederationUserFinger extends BaseCommand<
typeof FederationUserFinger
> {
static override args = {
address: Args.string({
description: "Address of remote user (name@host.com)",
required: true,
}),
};
static override description = "Fetch the URL of remote users via WebFinger";
static override examples = ["<%= config.bin %> <%= command.id %>"];
static override flags = {};
public async run(): Promise<void> {
const { args } = await this.parse(FederationUserFinger);
// Check if the address is valid
if (!args.address.match(userAddressValidator)) {
this.log(
"Invalid address. Please check the address format and try again. For example: name@host.com",
);
this.exit(1);
}
const spinner = ora("Fetching user URI").start();
const { username, domain: host } = parseUserAddress(args.address);
// Check instance exists, if not, create it
await Instance.resolve(`https://${host}`);
const requester = await User.getServerActor();
const signatureConstructor = await SignatureConstructor.fromStringKey(
requester.data.privateKey ?? "",
requester.getUri(),
);
const manager = new FederationRequester(
new URL(`https://${host}`),
signatureConstructor,
);
const uri = await manager.webFinger(username);
spinner.succeed("Fetched user URI");
this.log(`URI: ${chalk.blueBright(uri)}`);
this.exit(0);
}
}