@fedify/botkit 0.3.0-dev.108
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +661 -0
- package/README.md +75 -0
- package/dist/bot-impl.d.ts +111 -0
- package/dist/bot-impl.d.ts.map +1 -0
- package/dist/bot-impl.js +602 -0
- package/dist/bot-impl.js.map +1 -0
- package/dist/bot-impl.test.d.ts +2 -0
- package/dist/bot-impl.test.js +1642 -0
- package/dist/bot-impl.test.js.map +1 -0
- package/dist/bot.d.ts +270 -0
- package/dist/bot.d.ts.map +1 -0
- package/dist/bot.js +118 -0
- package/dist/bot.js.map +1 -0
- package/dist/bot.test.d.ts +2 -0
- package/dist/bot.test.js +80 -0
- package/dist/bot.test.js.map +1 -0
- package/dist/components/Layout.d.ts +26 -0
- package/dist/components/Layout.d.ts.map +1 -0
- package/dist/components/Layout.js +36 -0
- package/dist/components/Layout.js.map +1 -0
- package/dist/components/Message.d.ts +21 -0
- package/dist/components/Message.d.ts.map +1 -0
- package/dist/components/Message.js +99 -0
- package/dist/components/Message.js.map +1 -0
- package/dist/components/Message.test.d.ts +2 -0
- package/dist/components/Message.test.js +32 -0
- package/dist/components/Message.test.js.map +1 -0
- package/dist/deno.js +73 -0
- package/dist/deno.js.map +1 -0
- package/dist/emoji.d.ts +87 -0
- package/dist/emoji.d.ts.map +1 -0
- package/dist/emoji.js +37 -0
- package/dist/emoji.js.map +1 -0
- package/dist/emoji.test.d.ts +2 -0
- package/dist/emoji.test.js +109 -0
- package/dist/emoji.test.js.map +1 -0
- package/dist/events.d.ts +110 -0
- package/dist/events.d.ts.map +1 -0
- package/dist/events.js +4 -0
- package/dist/follow-impl.d.ts +23 -0
- package/dist/follow-impl.d.ts.map +1 -0
- package/dist/follow-impl.js +51 -0
- package/dist/follow-impl.js.map +1 -0
- package/dist/follow-impl.test.d.ts +2 -0
- package/dist/follow-impl.test.js +110 -0
- package/dist/follow-impl.test.js.map +1 -0
- package/dist/follow.d.ts +44 -0
- package/dist/follow.d.ts.map +1 -0
- package/dist/follow.js +4 -0
- package/dist/message-impl.d.ts +54 -0
- package/dist/message-impl.d.ts.map +1 -0
- package/dist/message-impl.js +439 -0
- package/dist/message-impl.js.map +1 -0
- package/dist/message-impl.test.d.ts +2 -0
- package/dist/message-impl.test.js +519 -0
- package/dist/message-impl.test.js.map +1 -0
- package/dist/message.d.ts +223 -0
- package/dist/message.d.ts.map +1 -0
- package/dist/message.js +8 -0
- package/dist/mod.d.ts +13 -0
- package/dist/mod.js +13 -0
- package/dist/pages.d.ts +20 -0
- package/dist/pages.d.ts.map +1 -0
- package/dist/pages.js +361 -0
- package/dist/pages.js.map +1 -0
- package/dist/reaction.d.ts +90 -0
- package/dist/reaction.d.ts.map +1 -0
- package/dist/reaction.js +7 -0
- package/dist/repository.d.ts +323 -0
- package/dist/repository.d.ts.map +1 -0
- package/dist/repository.js +483 -0
- package/dist/repository.js.map +1 -0
- package/dist/repository.test.d.ts +2 -0
- package/dist/repository.test.js +336 -0
- package/dist/repository.test.js.map +1 -0
- package/dist/session-impl.d.ts +32 -0
- package/dist/session-impl.d.ts.map +1 -0
- package/dist/session-impl.js +195 -0
- package/dist/session-impl.js.map +1 -0
- package/dist/session-impl.test.d.ts +20 -0
- package/dist/session-impl.test.d.ts.map +1 -0
- package/dist/session-impl.test.js +464 -0
- package/dist/session-impl.test.js.map +1 -0
- package/dist/session.d.ts +139 -0
- package/dist/session.d.ts.map +1 -0
- package/dist/session.js +4 -0
- package/dist/text.d.ts +391 -0
- package/dist/text.d.ts.map +1 -0
- package/dist/text.js +640 -0
- package/dist/text.js.map +1 -0
- package/dist/text.test.d.ts +2 -0
- package/dist/text.test.js +473 -0
- package/dist/text.test.js.map +1 -0
- package/package.json +137 -0
package/dist/follow.d.ts
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { Temporal, toTemporalInstant } from "@js-temporal/polyfill";
|
|
2
|
+
Date.prototype.toTemporalInstant = toTemporalInstant;
|
|
3
|
+
import { Actor, Follow } from "@fedify/fedify/vocab";
|
|
4
|
+
|
|
5
|
+
//#region src/follow.d.ts
|
|
6
|
+
/**
|
|
7
|
+
* A follow request to the bot.
|
|
8
|
+
*/
|
|
9
|
+
interface FollowRequest {
|
|
10
|
+
/**
|
|
11
|
+
* The URI of the follow request.
|
|
12
|
+
*/
|
|
13
|
+
readonly id: URL;
|
|
14
|
+
/**
|
|
15
|
+
* The raw follow request object.
|
|
16
|
+
*/
|
|
17
|
+
readonly raw: Follow;
|
|
18
|
+
/**
|
|
19
|
+
* The follower actor.
|
|
20
|
+
*/
|
|
21
|
+
readonly follower: Actor;
|
|
22
|
+
/**
|
|
23
|
+
* The state of the follow request.
|
|
24
|
+
*
|
|
25
|
+
* - `"pending"`: The follow request is pending.
|
|
26
|
+
* - `"accepted"`: The follow request is accepted.
|
|
27
|
+
* - `"rejected"`: The follow request is rejected.
|
|
28
|
+
*/
|
|
29
|
+
readonly state: "pending" | "accepted" | "rejected";
|
|
30
|
+
/**
|
|
31
|
+
* Accepts the follow request.
|
|
32
|
+
* @throws {TypeError} The follow request is not pending.
|
|
33
|
+
*/
|
|
34
|
+
accept(): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Rejects the follow request.
|
|
37
|
+
* @throws {TypeError} The follow request is not pending.
|
|
38
|
+
*/
|
|
39
|
+
reject(): Promise<void>;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=follow.d.ts.map
|
|
42
|
+
//#endregion
|
|
43
|
+
export { FollowRequest };
|
|
44
|
+
//# sourceMappingURL=follow.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"follow.d.ts","names":[],"sources":["../src/follow.ts"],"sourcesContent":[],"mappings":";;;;;;;;UAoBiB,aAAA;;;AAAjB;EAA8B,SAAA,EAAA,EAIf,GAJe;EAAA;;;EAcJ,SAed,GAAA,EApBI,MAoBJ;EAAO;AAMA;;qBArBE;;;;;;;;;;;;;YAeT;;;;;YAMA"}
|
package/dist/follow.js
ADDED
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { Temporal, toTemporalInstant } from "@js-temporal/polyfill";
|
|
2
|
+
Date.prototype.toTemporalInstant = toTemporalInstant;
|
|
3
|
+
import { AuthorizedLike, AuthorizedReaction } from "./reaction.js";
|
|
4
|
+
import { Text } from "./text.js";
|
|
5
|
+
import { AuthorizedMessage, AuthorizedSharedMessage, Message, MessageClass, MessageShareOptions, MessageVisibility } from "./message.js";
|
|
6
|
+
import { SessionPublishOptions, SessionPublishOptionsWithClass } from "./session.js";
|
|
7
|
+
import { DeferredCustomEmoji, Emoji } from "./emoji.js";
|
|
8
|
+
import { SessionImpl } from "./session-impl.js";
|
|
9
|
+
import { Actor, Article, ChatMessage, Document, Emoji as Emoji$1, Hashtag, Link, Note, Object as Object$1, Question } from "@fedify/fedify/vocab";
|
|
10
|
+
import { LanguageTag } from "@phensley/language-tag";
|
|
11
|
+
|
|
12
|
+
//#region src/message-impl.d.ts
|
|
13
|
+
declare const messageClasses: (typeof Article | typeof ChatMessage | typeof Note | typeof Question)[];
|
|
14
|
+
declare function isMessageObject(value: unknown): value is MessageClass;
|
|
15
|
+
declare function getMessageClass(value: MessageClass): (typeof Article | typeof ChatMessage | typeof Note | typeof Question) & {
|
|
16
|
+
typeId: URL;
|
|
17
|
+
};
|
|
18
|
+
declare class MessageImpl<T extends MessageClass, TContextData> implements Message<T, TContextData> {
|
|
19
|
+
readonly session: SessionImpl<TContextData>;
|
|
20
|
+
raw: T;
|
|
21
|
+
readonly id: URL;
|
|
22
|
+
readonly actor: Actor;
|
|
23
|
+
readonly visibility: MessageVisibility;
|
|
24
|
+
readonly language?: LanguageTag | undefined;
|
|
25
|
+
text: string;
|
|
26
|
+
html: string;
|
|
27
|
+
readonly replyTarget?: Message<MessageClass, TContextData> | undefined;
|
|
28
|
+
readonly quoteTarget?: Message<MessageClass, TContextData> | undefined;
|
|
29
|
+
mentions: readonly Actor[];
|
|
30
|
+
hashtags: readonly Hashtag[];
|
|
31
|
+
readonly attachments: readonly Document[];
|
|
32
|
+
readonly published?: Temporal.Instant;
|
|
33
|
+
updated?: Temporal.Instant;
|
|
34
|
+
constructor(session: SessionImpl<TContextData>, message: Omit<Message<T, TContextData>, "delete" | "reply" | "share" | "like" | "react">);
|
|
35
|
+
reply(text: Text<"block", TContextData>, options?: SessionPublishOptions<TContextData>): Promise<AuthorizedMessage<Note, TContextData>>;
|
|
36
|
+
reply<T extends MessageClass>(text: Text<"block", TContextData>, options?: SessionPublishOptionsWithClass<T, TContextData> | undefined): Promise<AuthorizedMessage<T, TContextData>>;
|
|
37
|
+
share(options?: MessageShareOptions): Promise<AuthorizedSharedMessage<T, TContextData>>;
|
|
38
|
+
like(): Promise<AuthorizedLike<TContextData>>;
|
|
39
|
+
react(emoji: Emoji | Emoji$1 | DeferredCustomEmoji<TContextData>): Promise<AuthorizedReaction<TContextData>>;
|
|
40
|
+
}
|
|
41
|
+
declare class AuthorizedMessageImpl<T extends MessageClass, TContextData> extends MessageImpl<T, TContextData> implements AuthorizedMessage<T, TContextData> {
|
|
42
|
+
update(text: Text<"block", TContextData>): Promise<void>;
|
|
43
|
+
delete(): Promise<void>;
|
|
44
|
+
}
|
|
45
|
+
declare const textXss: any;
|
|
46
|
+
declare function createMessage<T extends MessageClass, TContextData>(raw: T, session: SessionImpl<TContextData>, cachedObjects: Record<string, Object$1>, replyTarget?: Message<MessageClass, TContextData>, quote?: Message<MessageClass, TContextData>, authorized?: true): Promise<AuthorizedMessage<T, TContextData>>;
|
|
47
|
+
declare function createMessage<T extends MessageClass, TContextData>(raw: T, session: SessionImpl<TContextData>, cachedObjects: Record<string, Object$1>, replyTarget?: Message<MessageClass, TContextData>, quote?: Message<MessageClass, TContextData>, authorized?: boolean): Promise<Message<T, TContextData>>;
|
|
48
|
+
declare function getMessageVisibility(toIds: URL[], ccIds: URL[], actor: Actor, mentionedActorIds?: Set<string>): MessageVisibility;
|
|
49
|
+
declare function isQuoteLink(tag: Link): boolean;
|
|
50
|
+
//# sourceMappingURL=message-impl.d.ts.map
|
|
51
|
+
|
|
52
|
+
//#endregion
|
|
53
|
+
export { AuthorizedMessageImpl, MessageImpl, createMessage, getMessageClass, getMessageVisibility, isMessageObject, isQuoteLink, messageClasses, textXss };
|
|
54
|
+
//# sourceMappingURL=message-impl.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-impl.d.ts","names":[],"sources":["../src/message-impl.ts"],"sourcesContent":[],"mappings":"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"}
|
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
|
|
2
|
+
import { Temporal, toTemporalInstant } from "@js-temporal/polyfill";
|
|
3
|
+
Date.prototype.toTemporalInstant = toTemporalInstant;
|
|
4
|
+
|
|
5
|
+
import { Announce, Article, ChatMessage, Create, Delete, Document, EmojiReact, Hashtag, Like, Link, Mention, Note, PUBLIC_COLLECTION, Question, Tombstone, Undo, Update, isActor } from "@fedify/fedify/vocab";
|
|
6
|
+
import { LanguageString } from "@fedify/fedify/runtime";
|
|
7
|
+
import { decode } from "html-entities";
|
|
8
|
+
import { v7 } from "uuid";
|
|
9
|
+
import xss from "xss";
|
|
10
|
+
|
|
11
|
+
//#region src/message-impl.ts
|
|
12
|
+
const messageClasses = [
|
|
13
|
+
Article,
|
|
14
|
+
ChatMessage,
|
|
15
|
+
Note,
|
|
16
|
+
Question
|
|
17
|
+
];
|
|
18
|
+
function isMessageObject(value) {
|
|
19
|
+
return messageClasses.some((cls) => value instanceof cls);
|
|
20
|
+
}
|
|
21
|
+
function getMessageClass(value) {
|
|
22
|
+
return value instanceof Article ? Article : value instanceof ChatMessage ? ChatMessage : value instanceof Note ? Note : Question;
|
|
23
|
+
}
|
|
24
|
+
var MessageImpl = class {
|
|
25
|
+
session;
|
|
26
|
+
raw;
|
|
27
|
+
id;
|
|
28
|
+
actor;
|
|
29
|
+
visibility;
|
|
30
|
+
language;
|
|
31
|
+
text;
|
|
32
|
+
html;
|
|
33
|
+
replyTarget;
|
|
34
|
+
quoteTarget;
|
|
35
|
+
mentions;
|
|
36
|
+
hashtags;
|
|
37
|
+
attachments;
|
|
38
|
+
published;
|
|
39
|
+
updated;
|
|
40
|
+
constructor(session, message) {
|
|
41
|
+
this.session = session;
|
|
42
|
+
this.raw = message.raw;
|
|
43
|
+
this.id = message.id;
|
|
44
|
+
this.actor = message.actor;
|
|
45
|
+
this.visibility = message.visibility;
|
|
46
|
+
this.language = message.language;
|
|
47
|
+
this.text = message.text;
|
|
48
|
+
this.html = message.html;
|
|
49
|
+
this.replyTarget = message.replyTarget;
|
|
50
|
+
this.quoteTarget = message.quoteTarget;
|
|
51
|
+
this.mentions = message.mentions;
|
|
52
|
+
this.hashtags = message.hashtags;
|
|
53
|
+
this.attachments = message.attachments;
|
|
54
|
+
this.published = message.published;
|
|
55
|
+
this.updated = message.updated;
|
|
56
|
+
}
|
|
57
|
+
reply(text, options) {
|
|
58
|
+
return this.session.publish(text, {
|
|
59
|
+
visibility: this.visibility === "unknown" ? "direct" : this.visibility,
|
|
60
|
+
...options,
|
|
61
|
+
replyTarget: this
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
async share(options = {}) {
|
|
65
|
+
const published = /* @__PURE__ */ new Date();
|
|
66
|
+
const id = v7({ msecs: +published });
|
|
67
|
+
const visibility = options.visibility ?? this.visibility;
|
|
68
|
+
const originalActor = this.actor.id == null ? [] : [this.actor.id];
|
|
69
|
+
const uri = this.session.context.getObjectUri(Announce, { id });
|
|
70
|
+
const announce = new Announce({
|
|
71
|
+
id: uri,
|
|
72
|
+
actor: this.session.context.getActorUri(this.session.bot.identifier),
|
|
73
|
+
published: published.toTemporalInstant(),
|
|
74
|
+
object: this.id,
|
|
75
|
+
tos: visibility === "public" ? [PUBLIC_COLLECTION] : visibility === "unlisted" || visibility === "followers" ? [this.session.context.getFollowersUri(this.session.bot.identifier)] : [],
|
|
76
|
+
ccs: visibility === "public" ? [this.session.context.getFollowersUri(this.session.bot.identifier), ...originalActor] : visibility === "unlisted" ? [PUBLIC_COLLECTION, ...originalActor] : originalActor
|
|
77
|
+
});
|
|
78
|
+
await this.session.bot.repository.addMessage(id, announce);
|
|
79
|
+
await this.session.context.sendActivity(this.session.bot, "followers", announce, {
|
|
80
|
+
preferSharedInbox: true,
|
|
81
|
+
excludeBaseUris: [new URL(this.session.context.origin)]
|
|
82
|
+
});
|
|
83
|
+
await this.session.context.sendActivity(this.session.bot, this.actor, announce, {
|
|
84
|
+
preferSharedInbox: true,
|
|
85
|
+
excludeBaseUris: [new URL(this.session.context.origin)],
|
|
86
|
+
fanout: "skip"
|
|
87
|
+
});
|
|
88
|
+
const actor = announce.actorId?.href === this.session.actorId.href ? await this.session.getActor() : await announce.getActor(this.session.context);
|
|
89
|
+
if (actor == null) throw new TypeError("The actor is required.");
|
|
90
|
+
return {
|
|
91
|
+
raw: announce,
|
|
92
|
+
id: uri,
|
|
93
|
+
actor,
|
|
94
|
+
visibility,
|
|
95
|
+
original: this,
|
|
96
|
+
unshare: async () => {
|
|
97
|
+
await this.session.bot.repository.removeMessage(id);
|
|
98
|
+
const undo = new Undo({
|
|
99
|
+
id: new URL("#delete", uri),
|
|
100
|
+
actor: this.session.context.getActorUri(this.session.bot.identifier),
|
|
101
|
+
tos: announce.toIds,
|
|
102
|
+
ccs: announce.ccIds,
|
|
103
|
+
object: announce
|
|
104
|
+
});
|
|
105
|
+
await this.session.context.sendActivity(this.session.bot, "followers", undo, {
|
|
106
|
+
preferSharedInbox: true,
|
|
107
|
+
excludeBaseUris: [new URL(this.session.context.origin)]
|
|
108
|
+
});
|
|
109
|
+
await this.session.context.sendActivity(this.session.bot, this.actor, undo, {
|
|
110
|
+
preferSharedInbox: true,
|
|
111
|
+
excludeBaseUris: [new URL(this.session.context.origin)],
|
|
112
|
+
fanout: "skip"
|
|
113
|
+
});
|
|
114
|
+
}
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
async like() {
|
|
118
|
+
const uuid = crypto.randomUUID();
|
|
119
|
+
const actor = this.session.context.getActorUri(this.session.bot.identifier);
|
|
120
|
+
const id = new URL(`#like/${uuid}`, actor);
|
|
121
|
+
const activity = new Like({
|
|
122
|
+
id,
|
|
123
|
+
actor,
|
|
124
|
+
object: this.id
|
|
125
|
+
});
|
|
126
|
+
await this.session.context.sendActivity(this.session.bot, "followers", activity, {
|
|
127
|
+
preferSharedInbox: true,
|
|
128
|
+
excludeBaseUris: [new URL(this.session.context.origin)]
|
|
129
|
+
});
|
|
130
|
+
await this.session.context.sendActivity(this.session.bot, this.actor, activity, {
|
|
131
|
+
preferSharedInbox: true,
|
|
132
|
+
excludeBaseUris: [new URL(this.session.context.origin)],
|
|
133
|
+
fanout: "skip"
|
|
134
|
+
});
|
|
135
|
+
return {
|
|
136
|
+
raw: activity,
|
|
137
|
+
id,
|
|
138
|
+
actor: await this.session.getActor(),
|
|
139
|
+
message: this,
|
|
140
|
+
unlike: async () => {
|
|
141
|
+
const undo = new Undo({
|
|
142
|
+
id: new URL(`#unlike/${uuid}`, actor),
|
|
143
|
+
actor,
|
|
144
|
+
object: activity
|
|
145
|
+
});
|
|
146
|
+
await this.session.context.sendActivity(this.session.bot, "followers", undo, {
|
|
147
|
+
preferSharedInbox: true,
|
|
148
|
+
excludeBaseUris: [new URL(this.session.context.origin)]
|
|
149
|
+
});
|
|
150
|
+
await this.session.context.sendActivity(this.session.bot, this.actor, undo, {
|
|
151
|
+
preferSharedInbox: true,
|
|
152
|
+
excludeBaseUris: [new URL(this.session.context.origin)],
|
|
153
|
+
fanout: "skip"
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
async react(emoji) {
|
|
159
|
+
const uuid = crypto.randomUUID();
|
|
160
|
+
const actor = this.session.context.getActorUri(this.session.bot.identifier);
|
|
161
|
+
const id = new URL(`#react/${uuid}`, actor);
|
|
162
|
+
if (typeof emoji === "function") emoji = await emoji(this.session);
|
|
163
|
+
const activity = new EmojiReact({
|
|
164
|
+
id,
|
|
165
|
+
actor,
|
|
166
|
+
object: this.id,
|
|
167
|
+
name: typeof emoji === "string" ? emoji : emoji.name,
|
|
168
|
+
tags: typeof emoji === "string" ? [] : [emoji]
|
|
169
|
+
});
|
|
170
|
+
await this.session.context.sendActivity(this.session.bot, "followers", activity, {
|
|
171
|
+
preferSharedInbox: true,
|
|
172
|
+
excludeBaseUris: [new URL(this.session.context.origin)]
|
|
173
|
+
});
|
|
174
|
+
await this.session.context.sendActivity(this.session.bot, this.actor, activity, {
|
|
175
|
+
preferSharedInbox: true,
|
|
176
|
+
excludeBaseUris: [new URL(this.session.context.origin)],
|
|
177
|
+
fanout: "skip"
|
|
178
|
+
});
|
|
179
|
+
return {
|
|
180
|
+
raw: activity,
|
|
181
|
+
id,
|
|
182
|
+
actor: await this.session.getActor(),
|
|
183
|
+
message: this,
|
|
184
|
+
emoji,
|
|
185
|
+
unreact: async () => {
|
|
186
|
+
const undo = new Undo({
|
|
187
|
+
id: new URL(`#unreact/${uuid}`, actor),
|
|
188
|
+
actor,
|
|
189
|
+
object: activity,
|
|
190
|
+
name: typeof emoji === "string" ? emoji : emoji.name,
|
|
191
|
+
tags: typeof emoji === "string" ? [] : [emoji]
|
|
192
|
+
});
|
|
193
|
+
await this.session.context.sendActivity(this.session.bot, "followers", undo, {
|
|
194
|
+
preferSharedInbox: true,
|
|
195
|
+
excludeBaseUris: [new URL(this.session.context.origin)]
|
|
196
|
+
});
|
|
197
|
+
await this.session.context.sendActivity(this.session.bot, this.actor, undo, {
|
|
198
|
+
preferSharedInbox: true,
|
|
199
|
+
excludeBaseUris: [new URL(this.session.context.origin)],
|
|
200
|
+
fanout: "skip"
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
};
|
|
204
|
+
}
|
|
205
|
+
};
|
|
206
|
+
var AuthorizedMessageImpl = class extends MessageImpl {
|
|
207
|
+
async update(text) {
|
|
208
|
+
const parsed = this.session.context.parseUri(this.id);
|
|
209
|
+
if (parsed?.type !== "object" || !messageClasses.some((cls) => parsed.class === cls)) return;
|
|
210
|
+
const { id } = parsed.values;
|
|
211
|
+
let existingMentions = [];
|
|
212
|
+
let mentionedActors = [];
|
|
213
|
+
let update;
|
|
214
|
+
const updated = await this.session.bot.repository.updateMessage(id, async (create) => {
|
|
215
|
+
if (create instanceof Announce) return;
|
|
216
|
+
const message = await create.getObject(this.session.context);
|
|
217
|
+
if (message == null || !isMessageObject(message)) return;
|
|
218
|
+
let contentHtml = "";
|
|
219
|
+
for await (const chunk of text.getHtml(this.session)) contentHtml += chunk;
|
|
220
|
+
const tags = await Array.fromAsync(text.getTags(this.session));
|
|
221
|
+
const mentionedActorIds = [];
|
|
222
|
+
const hashtags = [];
|
|
223
|
+
for (const tag of tags) if (tag instanceof Mention && tag.href != null) mentionedActorIds.push(tag.href);
|
|
224
|
+
else if (tag instanceof Hashtag) hashtags.push(tag);
|
|
225
|
+
const cachedObjects = {};
|
|
226
|
+
for (const cachedObject of text.getCachedObjects()) {
|
|
227
|
+
if (cachedObject.id == null) continue;
|
|
228
|
+
cachedObjects[cachedObject.id.href] = cachedObject;
|
|
229
|
+
}
|
|
230
|
+
const documentLoader = await this.session.context.getDocumentLoader(this.session.bot);
|
|
231
|
+
const promises = [];
|
|
232
|
+
for (const uri of mentionedActorIds) {
|
|
233
|
+
const cachedObject = cachedObjects[uri.href];
|
|
234
|
+
const promise = cachedObject == null ? this.session.context.lookupObject(uri, { documentLoader }) : Promise.resolve(cachedObject);
|
|
235
|
+
promises.push(promise);
|
|
236
|
+
}
|
|
237
|
+
const objects = await Promise.all(promises);
|
|
238
|
+
mentionedActors = objects.filter(isActor);
|
|
239
|
+
this.html = contentHtml;
|
|
240
|
+
this.text = decode(textXss.process(contentHtml));
|
|
241
|
+
existingMentions = this.mentions;
|
|
242
|
+
this.mentions = mentionedActors;
|
|
243
|
+
this.hashtags = hashtags;
|
|
244
|
+
const updated$1 = Temporal.Now.instant();
|
|
245
|
+
this.updated = updated$1;
|
|
246
|
+
const newMessage = message.clone({
|
|
247
|
+
contents: this.language == null ? [contentHtml] : [new LanguageString(contentHtml, this.language), contentHtml],
|
|
248
|
+
tags,
|
|
249
|
+
tos: this.visibility === "public" ? [PUBLIC_COLLECTION, ...mentionedActorIds] : this.visibility === "unlisted" || this.visibility === "followers" ? [this.session.context.getFollowersUri(this.session.bot.identifier), ...mentionedActorIds] : mentionedActorIds,
|
|
250
|
+
ccs: this.visibility === "public" ? [this.session.context.getFollowersUri(this.session.bot.identifier)] : this.visibility === "unlisted" ? [PUBLIC_COLLECTION] : [],
|
|
251
|
+
updated: updated$1
|
|
252
|
+
});
|
|
253
|
+
this.raw = newMessage;
|
|
254
|
+
create = create.clone({
|
|
255
|
+
object: newMessage,
|
|
256
|
+
updated: updated$1
|
|
257
|
+
});
|
|
258
|
+
const to = create.toIds.map((url) => url.href);
|
|
259
|
+
for (const url of newMessage.toIds) if (!to.includes(url.href)) to.push(url.href);
|
|
260
|
+
const cc = create.ccIds.map((url) => url.href);
|
|
261
|
+
for (const url of newMessage.ccIds) if (!cc.includes(url.href)) cc.push(url.href);
|
|
262
|
+
update = new Update({
|
|
263
|
+
id: new URL(`#updated/${updated$1.toString()}`, this.session.context.getObjectUri(Create, { id })),
|
|
264
|
+
actors: newMessage.attributionIds,
|
|
265
|
+
tos: to.map((url) => new URL(url)),
|
|
266
|
+
ccs: cc.map((url) => new URL(url)),
|
|
267
|
+
object: newMessage,
|
|
268
|
+
updated: updated$1
|
|
269
|
+
});
|
|
270
|
+
return create;
|
|
271
|
+
});
|
|
272
|
+
if (!updated || update == null) return;
|
|
273
|
+
const preferSharedInbox = this.visibility === "public" || this.visibility === "unlisted" || this.visibility === "followers";
|
|
274
|
+
const excludeBaseUris = [new URL(this.session.context.origin)];
|
|
275
|
+
if (preferSharedInbox) await this.session.context.sendActivity(this.session.bot, "followers", update, {
|
|
276
|
+
preferSharedInbox,
|
|
277
|
+
excludeBaseUris
|
|
278
|
+
});
|
|
279
|
+
await this.session.context.sendActivity(this.session.bot, [...existingMentions, ...mentionedActors], update, {
|
|
280
|
+
preferSharedInbox,
|
|
281
|
+
excludeBaseUris
|
|
282
|
+
});
|
|
283
|
+
if (this.replyTarget != null) await this.session.context.sendActivity(this.session.bot, this.replyTarget.actor, update, {
|
|
284
|
+
preferSharedInbox: true,
|
|
285
|
+
excludeBaseUris,
|
|
286
|
+
fanout: "skip"
|
|
287
|
+
});
|
|
288
|
+
if (this.quoteTarget != null) await this.session.context.sendActivity(this.session.bot, this.quoteTarget.actor, update, {
|
|
289
|
+
preferSharedInbox: true,
|
|
290
|
+
excludeBaseUris,
|
|
291
|
+
fanout: "skip"
|
|
292
|
+
});
|
|
293
|
+
}
|
|
294
|
+
async delete() {
|
|
295
|
+
const parsed = this.session.context.parseUri(this.id);
|
|
296
|
+
if (parsed?.type !== "object" || !messageClasses.some((cls) => parsed.class === cls)) return;
|
|
297
|
+
const { id } = parsed.values;
|
|
298
|
+
const create = await this.session.bot.repository.removeMessage(id);
|
|
299
|
+
if (create == null) return;
|
|
300
|
+
const message = await create.getObject(this.session.context);
|
|
301
|
+
if (message == null) return;
|
|
302
|
+
const mentionedActorIds = /* @__PURE__ */ new Set();
|
|
303
|
+
for await (const tag of message.getTags(this.session.context)) if (tag instanceof Mention && tag.href != null) mentionedActorIds.add(tag.href.href);
|
|
304
|
+
const promises = [];
|
|
305
|
+
const documentLoader = await this.session.context.getDocumentLoader(this.session.bot);
|
|
306
|
+
for (const uri of mentionedActorIds) promises.push(this.session.context.lookupObject(uri, { documentLoader }));
|
|
307
|
+
const mentionedActors = (await Promise.all(promises)).filter(isActor);
|
|
308
|
+
const activity = new Delete({
|
|
309
|
+
id: new URL("#delete", this.id),
|
|
310
|
+
actor: this.session.context.getActorUri(this.session.bot.identifier),
|
|
311
|
+
tos: create.toIds,
|
|
312
|
+
ccs: create.ccIds,
|
|
313
|
+
object: new Tombstone({ id: this.id })
|
|
314
|
+
});
|
|
315
|
+
const excludeBaseUris = [new URL(this.session.context.origin)];
|
|
316
|
+
await this.session.context.sendActivity(this.session.bot, "followers", activity, {
|
|
317
|
+
preferSharedInbox: true,
|
|
318
|
+
excludeBaseUris
|
|
319
|
+
});
|
|
320
|
+
if (mentionedActors.length > 0) await this.session.context.sendActivity(this.session.bot, mentionedActors, activity, {
|
|
321
|
+
preferSharedInbox: true,
|
|
322
|
+
excludeBaseUris
|
|
323
|
+
});
|
|
324
|
+
if (this.replyTarget != null) await this.session.context.sendActivity(this.session.bot, this.replyTarget.actor, activity, {
|
|
325
|
+
preferSharedInbox: true,
|
|
326
|
+
excludeBaseUris,
|
|
327
|
+
fanout: "skip"
|
|
328
|
+
});
|
|
329
|
+
if (this.quoteTarget != null) await this.session.context.sendActivity(this.session.bot, this.quoteTarget.actor, activity, {
|
|
330
|
+
preferSharedInbox: true,
|
|
331
|
+
excludeBaseUris,
|
|
332
|
+
fanout: "skip"
|
|
333
|
+
});
|
|
334
|
+
}
|
|
335
|
+
};
|
|
336
|
+
const allowList = xss.getDefaultWhiteList();
|
|
337
|
+
const htmlXss = new xss.FilterXSS({ allowList: {
|
|
338
|
+
...allowList,
|
|
339
|
+
a: [
|
|
340
|
+
...allowList.a ?? [],
|
|
341
|
+
"class",
|
|
342
|
+
"translate"
|
|
343
|
+
]
|
|
344
|
+
} });
|
|
345
|
+
const textXss = new xss.FilterXSS({
|
|
346
|
+
allowList: {},
|
|
347
|
+
stripIgnoreTag: true
|
|
348
|
+
});
|
|
349
|
+
async function createMessage(raw, session, cachedObjects, replyTarget, quoteTarget, authorized = false) {
|
|
350
|
+
if (raw.id == null) throw new TypeError("The raw.id is required.");
|
|
351
|
+
else if (raw.content == null) throw new TypeError("The raw.content is required.");
|
|
352
|
+
const documentLoader = await session.context.getDocumentLoader(session.bot);
|
|
353
|
+
const options = {
|
|
354
|
+
contextLoader: session.context.contextLoader,
|
|
355
|
+
documentLoader,
|
|
356
|
+
suppressError: true
|
|
357
|
+
};
|
|
358
|
+
const actor = raw.attributionId?.href === session.actorId?.href ? await session.getActor() : await raw.getAttribution(options);
|
|
359
|
+
if (actor == null) throw new TypeError("The raw.attributionId is required.");
|
|
360
|
+
const content = raw.content.toString();
|
|
361
|
+
const text = textXss.process(content);
|
|
362
|
+
const html = htmlXss.process(content);
|
|
363
|
+
const mentions = [];
|
|
364
|
+
const mentionedActorIds = /* @__PURE__ */ new Set();
|
|
365
|
+
const hashtags = [];
|
|
366
|
+
const quoteLinks = [];
|
|
367
|
+
for await (const tag of raw.getTags(options)) if (tag instanceof Mention && tag.href != null) {
|
|
368
|
+
const obj = tag.href.href === session.actorId?.href ? await session.getActor() : cachedObjects[tag.href.href] == null ? await session.context.lookupObject(tag.href, options) : cachedObjects[tag.href.href];
|
|
369
|
+
if (isActor(obj)) mentions.push(obj);
|
|
370
|
+
mentionedActorIds.add(tag.href.href);
|
|
371
|
+
} else if (tag instanceof Hashtag) hashtags.push(tag);
|
|
372
|
+
else if (tag instanceof Link && isQuoteLink(tag)) quoteLinks.push(tag);
|
|
373
|
+
const attachments = [];
|
|
374
|
+
for await (const attachment of raw.getAttachments(options)) if (attachment instanceof Document) attachments.push(attachment);
|
|
375
|
+
if (replyTarget == null) {
|
|
376
|
+
let rt;
|
|
377
|
+
const parsed = session.context.parseUri(raw.replyTargetId);
|
|
378
|
+
if (parsed?.type === "object" && messageClasses.includes(parsed.class)) {
|
|
379
|
+
const cls = parsed.class;
|
|
380
|
+
rt = await session.bot.dispatchMessage(cls, session.context, parsed.values.id);
|
|
381
|
+
} else rt = await raw.getReplyTarget(options);
|
|
382
|
+
if (rt instanceof Article || rt instanceof ChatMessage || rt instanceof Note || rt instanceof Question) replyTarget = await createMessage(rt, session, cachedObjects);
|
|
383
|
+
}
|
|
384
|
+
if (quoteTarget == null) {
|
|
385
|
+
let quoteUrl = null;
|
|
386
|
+
for (const quoteLink of quoteLinks) {
|
|
387
|
+
if (quoteLink.href == null) continue;
|
|
388
|
+
quoteUrl = quoteLink.href;
|
|
389
|
+
break;
|
|
390
|
+
}
|
|
391
|
+
if (quoteUrl == null) quoteUrl = raw.quoteUrl;
|
|
392
|
+
let qt = null;
|
|
393
|
+
const parsed = session.context.parseUri(quoteUrl);
|
|
394
|
+
if (parsed?.type === "object" && messageClasses.includes(parsed.class)) {
|
|
395
|
+
const cls = parsed.class;
|
|
396
|
+
qt = await session.bot.dispatchMessage(cls, session.context, parsed.values.id);
|
|
397
|
+
} else if (quoteUrl != null) qt = await session.context.lookupObject(quoteUrl, options);
|
|
398
|
+
if (qt instanceof Article || qt instanceof ChatMessage || qt instanceof Note || qt instanceof Question) quoteTarget = await createMessage(qt, session, cachedObjects);
|
|
399
|
+
}
|
|
400
|
+
return new (authorized ? AuthorizedMessageImpl : MessageImpl)(session, {
|
|
401
|
+
raw,
|
|
402
|
+
id: raw.id,
|
|
403
|
+
actor,
|
|
404
|
+
visibility: getMessageVisibility(raw.toIds, raw.ccIds, actor, mentionedActorIds),
|
|
405
|
+
language: raw.content instanceof LanguageString ? raw.content.language : void 0,
|
|
406
|
+
text: decode(text),
|
|
407
|
+
html,
|
|
408
|
+
replyTarget,
|
|
409
|
+
quoteTarget,
|
|
410
|
+
mentions,
|
|
411
|
+
hashtags,
|
|
412
|
+
attachments,
|
|
413
|
+
published: raw.published ?? void 0,
|
|
414
|
+
updated: raw.updated ?? void 0
|
|
415
|
+
});
|
|
416
|
+
}
|
|
417
|
+
function getMessageVisibility(toIds, ccIds, actor, mentionedActorIds) {
|
|
418
|
+
const to = toIds.map((url) => url.href);
|
|
419
|
+
const cc = ccIds.map((url) => url.href);
|
|
420
|
+
const recipients = new Set([...to, ...cc]);
|
|
421
|
+
return to.includes(PUBLIC_COLLECTION.href) ? "public" : cc.includes(PUBLIC_COLLECTION.href) ? "unlisted" : actor.followersId != null && (to.includes(actor.followersId.href) || cc.includes(actor.followersId.href)) ? "followers" : recipients.size > 0 && recipients.intersection(mentionedActorIds ?? /* @__PURE__ */ new Set()).size === recipients.size ? "direct" : "unknown";
|
|
422
|
+
}
|
|
423
|
+
function isQuoteLink(tag) {
|
|
424
|
+
if (tag.rel === "https://misskey-hub.net/ns#_misskey_quote") return true;
|
|
425
|
+
else if (tag.mediaType == null) return false;
|
|
426
|
+
const parsed = tag.mediaType.split(";");
|
|
427
|
+
const type = parsed[0].trim();
|
|
428
|
+
if (type === "application/activity+json") return true;
|
|
429
|
+
const params = {};
|
|
430
|
+
for (let i = 1; i < parsed.length; i++) {
|
|
431
|
+
const param = parsed[i].trim().split("=");
|
|
432
|
+
if (param.length === 2) params[param[0]] = param[1].replace(/"/g, "");
|
|
433
|
+
}
|
|
434
|
+
return type === "application/ld+json" && params.profile === "https://www.w3.org/ns/activitystreams";
|
|
435
|
+
}
|
|
436
|
+
|
|
437
|
+
//#endregion
|
|
438
|
+
export { AuthorizedMessageImpl, MessageImpl, createMessage, getMessageClass, getMessageVisibility, isMessageObject, isQuoteLink, messageClasses, textXss };
|
|
439
|
+
//# sourceMappingURL=message-impl.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-impl.js","names":["value: unknown","value: MessageClass","session: SessionImpl<TContextData>","message: Omit<\n Message<T, TContextData>,\n \"delete\" | \"reply\" | \"share\" | \"like\" | \"react\"\n >","text: Text<\"block\", TContextData>","options?:\n | SessionPublishOptions<TContextData>\n | SessionPublishOptionsWithClass<MessageClass, TContextData>","options: MessageShareOptions","RawLike","emoji: Emoji | CustomEmoji | DeferredCustomEmoji<TContextData>","existingMentions: readonly Actor[]","mentionedActors: Actor[]","update: Update | undefined","mentionedActorIds: URL[]","hashtags: Hashtag[]","cachedObjects: Record<string, Object>","promises: Promise<Object | null>[]","updated","mentionedActorIds: Set<string>","raw: T","replyTarget?: Message<MessageClass, TContextData>","quoteTarget?: Message<MessageClass, TContextData>","authorized: boolean","mentions: Actor[]","quoteLinks: Link[]","attachments: Document[]","rt: Link | Object | null","cls: new (values: any) => T","quoteUrl: URL | null","qt: Object | null","toIds: URL[]","ccIds: URL[]","actor: Actor","mentionedActorIds?: Set<string>","tag: Link","params: Record<string, string>"],"sources":["../src/message-impl.ts"],"sourcesContent":["// BotKit by Fedify: A framework for creating ActivityPub bots\n// Copyright (C) 2025 Hong Minhee <https://hongminhee.org/>\n//\n// This program is free software: you can redistribute it and/or modify\n// it under the terms of the GNU Affero General Public License as\n// published by the Free Software Foundation, either version 3 of the\n// License, or (at your option) any later version.\n//\n// This program is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU Affero General Public License for more details.\n//\n// You should have received a copy of the GNU Affero General Public License\n// along with this program. If not, see <https://www.gnu.org/licenses/>.\nimport { LanguageString } from \"@fedify/fedify/runtime\";\nimport {\n type Actor,\n Announce,\n Article,\n ChatMessage,\n Create,\n Delete,\n Document,\n type Emoji as CustomEmoji,\n EmojiReact,\n Hashtag,\n isActor,\n Like as RawLike,\n Link,\n Mention,\n Note,\n type Object,\n PUBLIC_COLLECTION,\n Question,\n Tombstone,\n Undo,\n Update,\n} from \"@fedify/fedify/vocab\";\nimport type { LanguageTag } from \"@phensley/language-tag\";\nimport { decode } from \"html-entities\";\nimport { v7 as uuidv7 } from \"uuid\";\nimport xss from \"xss\";\nimport type { DeferredCustomEmoji, Emoji } from \"./emoji.ts\";\nimport type {\n AuthorizedMessage,\n AuthorizedSharedMessage,\n Message,\n MessageClass,\n MessageShareOptions,\n MessageVisibility,\n} from \"./message.ts\";\nimport type { AuthorizedLike, AuthorizedReaction } from \"./reaction.ts\";\nimport type { Uuid } from \"./repository.ts\";\nimport type { SessionImpl } from \"./session-impl.ts\";\nimport type {\n SessionPublishOptions,\n SessionPublishOptionsWithClass,\n} from \"./session.ts\";\nimport type { Text } from \"./text.ts\";\n\nexport const messageClasses = [Article, ChatMessage, Note, Question];\n\nexport function isMessageObject(value: unknown): value is MessageClass {\n return messageClasses.some((cls) => value instanceof cls);\n}\n\nexport function getMessageClass(\n value: MessageClass,\n): (typeof Article | typeof ChatMessage | typeof Note | typeof Question) & {\n typeId: URL;\n} {\n return value instanceof Article\n ? Article\n : value instanceof ChatMessage\n ? ChatMessage\n : value instanceof Note\n ? Note\n : Question;\n}\n\nexport class MessageImpl<T extends MessageClass, TContextData>\n implements Message<T, TContextData> {\n readonly session: SessionImpl<TContextData>;\n raw: T;\n readonly id: URL;\n readonly actor: Actor;\n readonly visibility: MessageVisibility;\n readonly language?: LanguageTag | undefined;\n text: string;\n html: string;\n readonly replyTarget?: Message<MessageClass, TContextData> | undefined;\n readonly quoteTarget?: Message<MessageClass, TContextData> | undefined;\n mentions: readonly Actor[];\n hashtags: readonly Hashtag[];\n readonly attachments: readonly Document[];\n readonly published?: Temporal.Instant;\n updated?: Temporal.Instant;\n\n constructor(\n session: SessionImpl<TContextData>,\n message: Omit<\n Message<T, TContextData>,\n \"delete\" | \"reply\" | \"share\" | \"like\" | \"react\"\n >,\n ) {\n this.session = session;\n this.raw = message.raw;\n this.id = message.id;\n this.actor = message.actor;\n this.visibility = message.visibility;\n this.language = message.language;\n this.text = message.text;\n this.html = message.html;\n this.replyTarget = message.replyTarget;\n this.quoteTarget = message.quoteTarget;\n this.mentions = message.mentions;\n this.hashtags = message.hashtags;\n this.attachments = message.attachments;\n this.published = message.published;\n this.updated = message.updated;\n }\n\n reply(\n text: Text<\"block\", TContextData>,\n options?: SessionPublishOptions<TContextData>,\n ): Promise<AuthorizedMessage<Note, TContextData>>;\n reply<T extends MessageClass>(\n text: Text<\"block\", TContextData>,\n options?: SessionPublishOptionsWithClass<T, TContextData> | undefined,\n ): Promise<AuthorizedMessage<T, TContextData>>;\n reply(\n text: Text<\"block\", TContextData>,\n options?:\n | SessionPublishOptions<TContextData>\n | SessionPublishOptionsWithClass<MessageClass, TContextData>,\n ): Promise<AuthorizedMessage<MessageClass, TContextData>> {\n return this.session.publish(text, {\n visibility: this.visibility === \"unknown\" ? \"direct\" : this.visibility,\n ...options,\n replyTarget: this,\n });\n }\n\n async share(\n options: MessageShareOptions = {},\n ): Promise<AuthorizedSharedMessage<T, TContextData>> {\n const published = new Date();\n const id = uuidv7({ msecs: +published }) as Uuid;\n const visibility = options.visibility ?? this.visibility;\n const originalActor = this.actor.id == null ? [] : [this.actor.id];\n const uri = this.session.context.getObjectUri(Announce, { id });\n const announce = new Announce({\n id: uri,\n actor: this.session.context.getActorUri(this.session.bot.identifier),\n published: published.toTemporalInstant(),\n object: this.id,\n tos: visibility === \"public\"\n ? [PUBLIC_COLLECTION]\n : visibility === \"unlisted\" || visibility === \"followers\"\n ? [\n this.session.context.getFollowersUri(this.session.bot.identifier),\n ]\n : [],\n ccs: visibility === \"public\"\n ? [\n this.session.context.getFollowersUri(this.session.bot.identifier),\n ...originalActor,\n ]\n : visibility === \"unlisted\"\n ? [PUBLIC_COLLECTION, ...originalActor]\n : originalActor,\n });\n await this.session.bot.repository.addMessage(id, announce);\n await this.session.context.sendActivity(\n this.session.bot,\n \"followers\",\n announce,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n },\n );\n await this.session.context.sendActivity(\n this.session.bot,\n this.actor,\n announce,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n fanout: \"skip\",\n },\n );\n const actor = announce.actorId?.href === this.session.actorId.href\n ? await this.session.getActor()\n : await announce.getActor(this.session.context);\n if (actor == null) throw new TypeError(\"The actor is required.\");\n return {\n raw: announce,\n id: uri,\n actor,\n visibility,\n original: this,\n unshare: async () => {\n await this.session.bot.repository.removeMessage(id);\n const undo = new Undo({\n id: new URL(\"#delete\", uri),\n actor: this.session.context.getActorUri(\n this.session.bot.identifier,\n ),\n tos: announce.toIds,\n ccs: announce.ccIds,\n object: announce,\n });\n await this.session.context.sendActivity(\n this.session.bot,\n \"followers\",\n undo,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n },\n );\n await this.session.context.sendActivity(\n this.session.bot,\n this.actor,\n undo,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n fanout: \"skip\",\n },\n );\n },\n };\n }\n\n async like(): Promise<AuthorizedLike<TContextData>> {\n const uuid = crypto.randomUUID();\n const actor = this.session.context.getActorUri(this.session.bot.identifier);\n const id = new URL(`#like/${uuid}`, actor);\n const activity = new RawLike({\n id,\n actor,\n object: this.id,\n });\n await this.session.context.sendActivity(\n this.session.bot,\n \"followers\",\n activity,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n },\n );\n await this.session.context.sendActivity(\n this.session.bot,\n this.actor,\n activity,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n fanout: \"skip\",\n },\n );\n return {\n raw: activity,\n id,\n actor: await this.session.getActor(),\n message: this,\n unlike: async () => {\n const undo = new Undo({\n id: new URL(`#unlike/${uuid}`, actor),\n actor,\n object: activity,\n });\n await this.session.context.sendActivity(\n this.session.bot,\n \"followers\",\n undo,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n },\n );\n await this.session.context.sendActivity(\n this.session.bot,\n this.actor,\n undo,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n fanout: \"skip\",\n },\n );\n },\n };\n }\n\n async react(\n emoji: Emoji | CustomEmoji | DeferredCustomEmoji<TContextData>,\n ): Promise<AuthorizedReaction<TContextData>> {\n const uuid = crypto.randomUUID();\n const actor = this.session.context.getActorUri(this.session.bot.identifier);\n const id = new URL(`#react/${uuid}`, actor);\n if (typeof emoji === \"function\") {\n emoji = await emoji(this.session);\n }\n const activity = new EmojiReact({\n id,\n actor,\n object: this.id,\n name: typeof emoji === \"string\" ? emoji : emoji.name,\n tags: typeof emoji === \"string\" ? [] : [emoji],\n });\n await this.session.context.sendActivity(\n this.session.bot,\n \"followers\",\n activity,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n },\n );\n await this.session.context.sendActivity(\n this.session.bot,\n this.actor,\n activity,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n fanout: \"skip\",\n },\n );\n return {\n raw: activity,\n id,\n actor: await this.session.getActor(),\n message: this,\n emoji,\n unreact: async () => {\n const undo = new Undo({\n id: new URL(`#unreact/${uuid}`, actor),\n actor,\n object: activity,\n name: typeof emoji === \"string\" ? emoji : emoji.name,\n tags: typeof emoji === \"string\" ? [] : [emoji],\n });\n await this.session.context.sendActivity(\n this.session.bot,\n \"followers\",\n undo,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n },\n );\n await this.session.context.sendActivity(\n this.session.bot,\n this.actor,\n undo,\n {\n preferSharedInbox: true,\n excludeBaseUris: [new URL(this.session.context.origin)],\n fanout: \"skip\",\n },\n );\n },\n };\n }\n}\n\nexport class AuthorizedMessageImpl<T extends MessageClass, TContextData>\n extends MessageImpl<T, TContextData>\n implements AuthorizedMessage<T, TContextData> {\n async update(text: Text<\"block\", TContextData>): Promise<void> {\n const parsed = this.session.context.parseUri(this.id);\n if (\n parsed?.type !== \"object\" ||\n !messageClasses.some((cls) => parsed.class === cls)\n ) {\n return;\n }\n const { id } = parsed.values;\n let existingMentions: readonly Actor[] = [];\n let mentionedActors: Actor[] = [];\n let update: Update | undefined;\n const updated = await this.session.bot.repository.updateMessage(\n id as Uuid,\n async (create) => {\n if (create instanceof Announce) return;\n const message = await create.getObject(this.session.context);\n if (message == null || !isMessageObject(message)) return;\n let contentHtml = \"\";\n for await (const chunk of text.getHtml(this.session)) {\n contentHtml += chunk;\n }\n const tags = await Array.fromAsync(text.getTags(this.session));\n const mentionedActorIds: URL[] = [];\n const hashtags: Hashtag[] = [];\n for (const tag of tags) {\n if (tag instanceof Mention && tag.href != null) {\n mentionedActorIds.push(tag.href);\n } else if (tag instanceof Hashtag) {\n hashtags.push(tag);\n }\n }\n const cachedObjects: Record<string, Object> = {};\n for (const cachedObject of text.getCachedObjects()) {\n if (cachedObject.id == null) continue;\n cachedObjects[cachedObject.id.href] = cachedObject;\n }\n const documentLoader = await this.session.context.getDocumentLoader(\n this.session.bot,\n );\n const promises: Promise<Object | null>[] = [];\n for (const uri of mentionedActorIds) {\n const cachedObject = cachedObjects[uri.href];\n const promise = cachedObject == null\n ? this.session.context.lookupObject(uri, { documentLoader })\n : Promise.resolve(cachedObject);\n promises.push(promise);\n }\n const objects = await Promise.all(promises);\n mentionedActors = objects.filter(isActor);\n this.html = contentHtml;\n this.text = decode(textXss.process(contentHtml));\n existingMentions = this.mentions;\n this.mentions = mentionedActors;\n this.hashtags = hashtags;\n const updated = Temporal.Now.instant();\n this.updated = updated;\n const newMessage = message.clone({\n contents: this.language == null\n ? [contentHtml]\n : [new LanguageString(contentHtml, this.language), contentHtml],\n tags,\n tos: this.visibility === \"public\"\n ? [PUBLIC_COLLECTION, ...mentionedActorIds]\n : this.visibility === \"unlisted\" || this.visibility === \"followers\"\n ? [\n this.session.context.getFollowersUri(this.session.bot.identifier),\n ...mentionedActorIds,\n ]\n : mentionedActorIds,\n ccs: this.visibility === \"public\"\n ? [\n this.session.context.getFollowersUri(this.session.bot.identifier),\n ]\n : this.visibility === \"unlisted\"\n ? [PUBLIC_COLLECTION]\n : [],\n updated,\n });\n this.raw = newMessage as T;\n create = create.clone({ object: newMessage, updated });\n const to = create.toIds.map((url) => url.href);\n for (const url of newMessage.toIds) {\n if (!to.includes(url.href)) to.push(url.href);\n }\n const cc = create.ccIds.map((url) => url.href);\n for (const url of newMessage.ccIds) {\n if (!cc.includes(url.href)) cc.push(url.href);\n }\n update = new Update({\n id: new URL(\n `#updated/${updated.toString()}`,\n this.session.context.getObjectUri(Create, { id }),\n ),\n actors: newMessage.attributionIds,\n tos: to.map((url) => new URL(url)),\n ccs: cc.map((url) => new URL(url)),\n object: newMessage,\n updated,\n });\n return create;\n },\n );\n if (!updated || update == null) return;\n const preferSharedInbox = this.visibility === \"public\" ||\n this.visibility === \"unlisted\" || this.visibility === \"followers\";\n const excludeBaseUris = [new URL(this.session.context.origin)];\n if (preferSharedInbox) {\n await this.session.context.sendActivity(\n this.session.bot,\n \"followers\",\n update,\n { preferSharedInbox, excludeBaseUris },\n );\n }\n await this.session.context.sendActivity(\n this.session.bot,\n [...existingMentions, ...mentionedActors],\n update,\n { preferSharedInbox, excludeBaseUris },\n );\n if (this.replyTarget != null) {\n await this.session.context.sendActivity(\n this.session.bot,\n this.replyTarget.actor,\n update,\n { preferSharedInbox: true, excludeBaseUris, fanout: \"skip\" },\n );\n }\n if (this.quoteTarget != null) {\n await this.session.context.sendActivity(\n this.session.bot,\n this.quoteTarget.actor,\n update,\n { preferSharedInbox: true, excludeBaseUris, fanout: \"skip\" },\n );\n }\n }\n\n async delete(): Promise<void> {\n const parsed = this.session.context.parseUri(this.id);\n if (\n parsed?.type !== \"object\" ||\n !messageClasses.some((cls) => parsed.class === cls)\n ) {\n return;\n }\n const { id } = parsed.values;\n const create = await this.session.bot.repository.removeMessage(id as Uuid);\n if (create == null) return;\n const message = await create.getObject(this.session.context);\n if (message == null) return;\n const mentionedActorIds: Set<string> = new Set();\n for await (const tag of message.getTags(this.session.context)) {\n if (tag instanceof Mention && tag.href != null) {\n mentionedActorIds.add(tag.href.href);\n }\n }\n const promises: Promise<Object | null>[] = [];\n const documentLoader = await this.session.context.getDocumentLoader(\n this.session.bot,\n );\n for (const uri of mentionedActorIds) {\n promises.push(this.session.context.lookupObject(uri, { documentLoader }));\n }\n const mentionedActors = (await Promise.all(promises)).filter(isActor);\n const activity = new Delete({\n id: new URL(\"#delete\", this.id),\n actor: this.session.context.getActorUri(this.session.bot.identifier),\n tos: create.toIds,\n ccs: create.ccIds,\n object: new Tombstone({\n id: this.id,\n }),\n });\n const excludeBaseUris = [new URL(this.session.context.origin)];\n await this.session.context.sendActivity(\n this.session.bot,\n \"followers\",\n activity,\n { preferSharedInbox: true, excludeBaseUris },\n );\n if (mentionedActors.length > 0) {\n await this.session.context.sendActivity(\n this.session.bot,\n mentionedActors,\n activity,\n { preferSharedInbox: true, excludeBaseUris },\n );\n }\n if (this.replyTarget != null) {\n await this.session.context.sendActivity(\n this.session.bot,\n this.replyTarget.actor,\n activity,\n { preferSharedInbox: true, excludeBaseUris, fanout: \"skip\" },\n );\n }\n if (this.quoteTarget != null) {\n await this.session.context.sendActivity(\n this.session.bot,\n this.quoteTarget.actor,\n activity,\n { preferSharedInbox: true, excludeBaseUris, fanout: \"skip\" },\n );\n }\n }\n}\n\n// @ts-ignore: The `xss` module has `getDefaultWhiteList` function.\nconst allowList = xss.getDefaultWhiteList();\n// @ts-ignore: The `xss` module has `FilterXSS` class.\nconst htmlXss = new xss.FilterXSS({\n allowList: {\n ...allowList,\n a: [...allowList.a ?? [], \"class\", \"translate\"],\n },\n});\n// @ts-ignore: The `xss` module has `FilterXSS` class.\nexport const textXss = new xss.FilterXSS({\n allowList: {},\n stripIgnoreTag: true,\n});\n\nexport async function createMessage<T extends MessageClass, TContextData>(\n raw: T,\n session: SessionImpl<TContextData>,\n cachedObjects: Record<string, Object>,\n replyTarget?: Message<MessageClass, TContextData>,\n quote?: Message<MessageClass, TContextData>,\n authorized?: true,\n): Promise<AuthorizedMessage<T, TContextData>>;\nexport async function createMessage<T extends MessageClass, TContextData>(\n raw: T,\n session: SessionImpl<TContextData>,\n cachedObjects: Record<string, Object>,\n replyTarget?: Message<MessageClass, TContextData>,\n quote?: Message<MessageClass, TContextData>,\n authorized?: boolean,\n): Promise<Message<T, TContextData>>;\nexport async function createMessage<T extends MessageClass, TContextData>(\n raw: T,\n session: SessionImpl<TContextData>,\n cachedObjects: Record<string, Object>,\n replyTarget?: Message<MessageClass, TContextData>,\n quoteTarget?: Message<MessageClass, TContextData>,\n authorized: boolean = false,\n): Promise<Message<T, TContextData>> {\n if (raw.id == null) throw new TypeError(\"The raw.id is required.\");\n else if (raw.content == null) {\n throw new TypeError(\"The raw.content is required.\");\n }\n const documentLoader = await session.context.getDocumentLoader(session.bot);\n const options = {\n contextLoader: session.context.contextLoader,\n documentLoader,\n suppressError: true,\n };\n const actor = raw.attributionId?.href === session.actorId?.href\n ? await session.getActor()\n : await raw.getAttribution(options);\n if (actor == null) {\n throw new TypeError(\"The raw.attributionId is required.\");\n }\n const content = raw.content.toString();\n const text = textXss.process(content);\n const html = htmlXss.process(content);\n const mentions: Actor[] = [];\n const mentionedActorIds = new Set<string>();\n const hashtags: Hashtag[] = [];\n const quoteLinks: Link[] = [];\n for await (const tag of raw.getTags(options)) {\n if (tag instanceof Mention && tag.href != null) {\n const obj = tag.href.href === session.actorId?.href\n ? await session.getActor()\n : cachedObjects[tag.href.href] == null\n ? await session.context.lookupObject(tag.href, options)\n : cachedObjects[tag.href.href];\n if (isActor(obj)) mentions.push(obj);\n mentionedActorIds.add(tag.href.href);\n } else if (tag instanceof Hashtag) {\n hashtags.push(tag);\n } else if (tag instanceof Link && isQuoteLink(tag)) {\n quoteLinks.push(tag);\n }\n }\n const attachments: Document[] = [];\n for await (const attachment of raw.getAttachments(options)) {\n if (attachment instanceof Document) attachments.push(attachment);\n }\n if (replyTarget == null) {\n let rt: Link | Object | null;\n const parsed = session.context.parseUri(raw.replyTargetId);\n // @ts-ignore: The `class` property satisfies the `MessageClass` type.\n if (parsed?.type === \"object\" && messageClasses.includes(parsed.class)) {\n // @ts-ignore: The `class` property satisfies the `MessageClass` type.\n // deno-lint-ignore no-explicit-any\n const cls: new (values: any) => T = parsed.class;\n rt = await session.bot.dispatchMessage(\n cls,\n session.context,\n parsed.values.id,\n );\n } else {\n rt = await raw.getReplyTarget(options);\n }\n if (\n rt instanceof Article || rt instanceof ChatMessage ||\n rt instanceof Note || rt instanceof Question\n ) {\n replyTarget = await createMessage(rt, session, cachedObjects);\n }\n }\n if (quoteTarget == null) {\n let quoteUrl: URL | null = null;\n for (const quoteLink of quoteLinks) {\n if (quoteLink.href == null) continue;\n quoteUrl = quoteLink.href;\n break;\n }\n if (quoteUrl == null) quoteUrl = raw.quoteUrl;\n let qt: Object | null = null;\n const parsed = session.context.parseUri(quoteUrl);\n // @ts-ignore: The `class` property satisfies the `MessageClass` type.\n if (parsed?.type === \"object\" && messageClasses.includes(parsed.class)) {\n // @ts-ignore: The `class` property satisfies the `MessageClass` type.\n // deno-lint-ignore no-explicit-any\n const cls: new (values: any) => T = parsed.class;\n qt = await session.bot.dispatchMessage(\n cls,\n session.context,\n parsed.values.id,\n );\n } else if (quoteUrl != null) {\n qt = await session.context.lookupObject(quoteUrl, options);\n }\n if (\n qt instanceof Article || qt instanceof ChatMessage ||\n qt instanceof Note || qt instanceof Question\n ) {\n quoteTarget = await createMessage(qt, session, cachedObjects);\n }\n }\n return new (authorized ? AuthorizedMessageImpl : MessageImpl)(session, {\n raw,\n id: raw.id,\n actor,\n visibility: getMessageVisibility(\n raw.toIds,\n raw.ccIds,\n actor,\n mentionedActorIds,\n ),\n language: raw.content instanceof LanguageString\n ? raw.content.language\n : undefined,\n text: decode(text),\n html,\n replyTarget,\n quoteTarget,\n mentions,\n hashtags,\n attachments,\n published: raw.published ?? undefined,\n updated: raw.updated ?? undefined,\n });\n}\n\nexport function getMessageVisibility(\n toIds: URL[],\n ccIds: URL[],\n actor: Actor,\n mentionedActorIds?: Set<string>,\n): MessageVisibility {\n const to = toIds.map((url) => url.href);\n const cc = ccIds.map((url) => url.href);\n const recipients = new Set([...to, ...cc]);\n return to.includes(PUBLIC_COLLECTION.href)\n ? \"public\"\n : cc.includes(PUBLIC_COLLECTION.href)\n ? \"unlisted\"\n : actor.followersId != null &&\n (to.includes(actor.followersId.href) ||\n cc.includes(actor.followersId.href))\n ? \"followers\"\n : recipients.size > 0 &&\n recipients.intersection(mentionedActorIds ?? new Set()).size ===\n recipients.size\n ? \"direct\"\n : \"unknown\";\n}\n\nexport function isQuoteLink(tag: Link): boolean {\n if (tag.rel === \"https://misskey-hub.net/ns#_misskey_quote\") return true;\n else if (tag.mediaType == null) return false;\n // FIXME: Properly parse the media type\n const parsed = tag.mediaType.split(\";\");\n const type = parsed[0].trim();\n if (type === \"application/activity+json\") return true;\n const params: Record<string, string> = {};\n for (let i = 1; i < parsed.length; i++) {\n const param = parsed[i].trim().split(\"=\");\n if (param.length === 2) {\n params[param[0]] = param[1].replace(/\"/g, \"\");\n }\n }\n return type === \"application/ld+json\" &&\n params.profile === \"https://www.w3.org/ns/activitystreams\";\n}\n"],"mappings":"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"}
|