Repository navigation
Expand file tree
/
Copy pathindex.ts
More file actions
58 lines (49 loc) · 2.12 KB
/
Copy pathindex.ts
File metadata and controls
58 lines (49 loc) · 2.12 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
6E9E
45
46
47
48
49
50
51
52
53
54
55
56
57
58
import { APActivity } from "@shootpub/activitypub-types/activity";
import type { Actor } from "../entity/actor.js";
import { Channel } from "../entity/channel.js";
import { Guild } from "../entity/guild.js";
import { User } from "../entity/user.js";
import { APError } from "../util/activitypub/error.js";
import { signWithHttpSignature } from "../util/activitypub/httpsig.js";
import { InstanceActor } from "../util/activitypub/instanceActor.js";
import { createLogger } from "../util/log.js";
const Log = createLogger("ap:distribute");
export const sendActivity = async (
targets: Actor | Actor[],
activity: APActivity,
sender: Actor = InstanceActor,
) => {
if (!activity.id) throw new Error("Tried to send activity without an ID", { cause: activity });
targets = Array.isArray(targets) ? targets : [targets];
const inboxes = targets.reduce<Set<string>>((ret, target) => {
const shared_inbox = target.collections?.shared_inbox;
const inbox = target.collections?.inbox;
// If the shared inbox doesn't exist, add the inbox
if (!shared_inbox && inbox) ret.add(inbox);
// If we have a shared inbox, and this activity is going to another actor with the same shared inbox, use that
else if (
shared_inbox &&
targets.filter((x) => x.collections?.shared_inbox === shared_inbox).length > 1
)
ret.add(shared_inbox);
// otherwise, just add the inbox
else if (inbox) ret.add(inbox);
return ret;
}, new Set());
for (const inbox of inboxes) {
const signed = signWithHttpSignature(inbox, "POST", sender, JSON.stringify(activity));
const res = await fetch(inbox, signed);
if (!res.ok) {
Log.error(
`Sending activity ${activity.id} to ${inbox} failed : ${res.status} ${await res.text()}`,
);
} else Log.verbose(`Sent activity ${activity.id} got response`, await res.text());
}
};
export const getExternalPathFromActor = (actor: Actor) => {
if (actor.id === InstanceActor.id) return "/actor";
if (actor instanceof Channel) return `/channel/${actor.id}`;
if (actor instanceof User) return `/users/${actor.name}`;
if (actor instanceof Guild) return `/guild/${actor.id}`;
throw new APError("unknown actor type");
};