misskey/src/services/relay.ts

95 lines
2.4 KiB
TypeScript

import { createSystemUser } from './create-system-user';
import { renderFollowRelay } from '@/remote/activitypub/renderer/follow-relay';
import { renderActivity, attachLdSignature } from '@/remote/activitypub/renderer/index';
import renderUndo from '@/remote/activitypub/renderer/undo';
import { deliver } from '@/queue/index';
import { ILocalUser, User } from '@/models/entities/user';
import { Users, Relays } from '@/models/index';
import { genId } from '@/misc/gen-id';
const ACTOR_USERNAME = 'relay.actor' as const;
export async function getRelayActor(): Promise<ILocalUser> {
const user = await Users.findOne({
host: null,
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.save({
id: genId(),
inbox,
status: 'requesting'
});
const relayActor = await getRelayActor();
const follow = await renderFollowRelay(relay, relayActor);
const activity = renderActivity(follow);
deliver(relayActor, activity, relay.inbox);
return relay;
}
export async function removeRelay(inbox: string) {
const relay = await Relays.findOne({
inbox
});
if (relay == null) {
throw '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);
}
export async function listRelay() {
const relays = await Relays.find();
return relays;
}
export async function relayAccepted(id: string) {
const result = await Relays.update(id, {
status: 'accepted'
});
return JSON.stringify(result);
}
export async function relayRejected(id: string) {
const result = await Relays.update(id, {
status: 'rejected'
});
return JSON.stringify(result);
}
export async function deliverToRelays(user: { id: User['id']; host: null; }, activity: any) {
if (activity == null) return;
const relays = await Relays.find({
status: 'accepted'
});
if (relays.length === 0) return;
const copy = JSON.parse(JSON.stringify(activity));
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);
}
}