jormungandr-bite/packages/backend/src/services/relay.ts

124 lines
3.1 KiB
TypeScript
Raw Normal View History

2023-01-12 21:40:33 -07:00
import { IsNull } from "typeorm";
import { renderFollowRelay } from "@/remote/activitypub/renderer/follow-relay.js";
import {
renderActivity,
attachLdSignature,
} from "@/remote/activitypub/renderer/index.js";
import renderUndo from "@/remote/activitypub/renderer/undo.js";
import { deliver } from "@/queue/index.js";
import type { ILocalUser, User } from "@/models/entities/user.js";
import { Users, Relays } from "@/models/index.js";
import { genId } from "@/misc/gen-id.js";
import { Cache } from "@/misc/cache.js";
import type { Relay } from "@/models/entities/relay.js";
import { createSystemUser } from "./create-system-user.js";
const ACTOR_USERNAME = "relay.actor" as const;
const relaysCache = new Cache<Relay[]>("relay", 60 * 60);
export async function getRelayActor(): Promise<ILocalUser> {
const user = await Users.findOneBy({
host: IsNull(),
2021-12-09 07:58:30 -07:00
username: ACTOR_USERNAME,
});
if (user) return user as ILocalUser;
const created = await createSystemUser(ACTOR_USERNAME);
return created as ILocalUser;
}
export async function addRelay(inbox: string) {
const relay = await Relays.insert({
id: genId(),
inbox,
2023-01-12 21:40:33 -07:00
status: "requesting",
}).then((x) => Relays.findOneByOrFail(x.identifiers[0]));
const relayActor = await getRelayActor();
2023-06-15 18:59:17 -06:00
const follow = renderFollowRelay(relay, relayActor);
const activity = renderActivity(follow);
deliver(relayActor, activity, relay.inbox);
return relay;
}
export async function removeRelay(inbox: string) {
const relay = await Relays.findOneBy({
2021-12-09 07:58:30 -07:00
inbox,
});
if (relay == null) {
2023-01-12 21:40:33 -07:00
throw new Error("relay not found");
}
const relayActor = await getRelayActor();
const follow = renderFollowRelay(relay, relayActor);
const undo = renderUndo(follow, relayActor);
const activity = renderActivity(undo);
deliver(relayActor, activity, relay.inbox);
await Relays.delete(relay.id);
2023-06-15 18:59:17 -06:00
await updateRelaysCache();
}
export async function listRelay() {
const relays = await Relays.find();
return relays;
}
2023-06-15 18:59:17 -06:00
export async function getCachedRelays(): Promise<Relay[]> {
return await relaysCache.fetch(null, () =>
Relays.findBy({
status: "accepted",
}),
);
}
export async function relayAccepted(id: string) {
const result = await Relays.update(id, {
2023-01-12 21:40:33 -07:00
status: "accepted",
});
2023-06-15 18:59:17 -06:00
await updateRelaysCache();
return JSON.stringify(result);
}
2023-06-15 18:59:17 -06:00
async function updateRelaysCache() {
const relays = await Relays.findBy({
status: "accepted",
});
2023-07-02 18:37:46 -06:00
await relaysCache.set(null, relays);
2023-06-15 18:59:17 -06:00
}
export async function relayRejected(id: string) {
const result = await Relays.update(id, {
2023-01-12 21:40:33 -07:00
status: "rejected",
});
return JSON.stringify(result);
}
2023-01-12 21:40:33 -07:00
export async function deliverToRelays(
user: { id: User["id"]; host: null },
activity: any,
) {
if (activity == null) return;
2023-06-15 18:59:17 -06:00
const relays = await getCachedRelays();
if (relays.length === 0) return;
2022-06-04 02:26:56 -06:00
// TODO
//const copy = structuredClone(activity);
const copy = JSON.parse(JSON.stringify(activity));
2023-01-12 21:40:33 -07:00
if (!copy.to) copy.to = ["https://www.w3.org/ns/activitystreams#Public"];
const signed = await attachLdSignature(copy, user);
for (const relay of relays) {
deliver(user, signed, relay.inbox);
}
}