opencode-discord-bot 0.0.11 → 0.1.0
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/package.json
CHANGED
|
@@ -3,7 +3,7 @@ import { basename } from "node:path"
|
|
|
3
3
|
import { createDiscordAdapter, type DiscordThreadId } from "@chat-adapter/discord"
|
|
4
4
|
import type { AdapterPostableMessage, FetchOptions, FetchResult, Message, PostableRaw, RawMessage } from "chat"
|
|
5
5
|
import { Duration, Effect } from "effect"
|
|
6
|
-
import type { DiscordAttachment, DiscordMessage, DiscordScope } from "../Schema.ts"
|
|
6
|
+
import type { DiscordAttachment, DiscordMessage, DiscordReaction, DiscordScope } from "../Schema.ts"
|
|
7
7
|
import { DiscordError, type DiscordService } from "./DiscordPort.ts"
|
|
8
8
|
|
|
9
9
|
type ChatDiscordAdapter = {
|
|
@@ -52,6 +52,23 @@ const attachments = (message: Message<unknown>): ReadonlyArray<DiscordAttachment
|
|
|
52
52
|
url: item.url ?? ""
|
|
53
53
|
}))
|
|
54
54
|
|
|
55
|
+
const reactionEmoji = (value: unknown): string => {
|
|
56
|
+
if (!isRecord(value)) return "unknown"
|
|
57
|
+
const name = typeof value.name === "string" && value.name.length > 0 ? value.name : undefined
|
|
58
|
+
const id = typeof value.id === "string" && value.id.length > 0 ? value.id : undefined
|
|
59
|
+
if (id !== undefined && name !== undefined) return `${value.animated === true ? "a:" : ""}${name}:${id}`
|
|
60
|
+
return name ?? id ?? "unknown"
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const reactions = (message: Message<unknown>): ReadonlyArray<DiscordReaction> => {
|
|
64
|
+
if (!isRecord(message.raw)) return []
|
|
65
|
+
const rawReactions: ReadonlyArray<unknown> = Array.isArray(message.raw.reactions) ? message.raw.reactions : []
|
|
66
|
+
return rawReactions.flatMap((item) => {
|
|
67
|
+
if (!isRecord(item) || typeof item.count !== "number" || !Number.isFinite(item.count) || item.count < 0) return []
|
|
68
|
+
return [{ emoji: reactionEmoji(item.emoji), count: item.count }]
|
|
69
|
+
})
|
|
70
|
+
}
|
|
71
|
+
|
|
55
72
|
const fromChatMessage = (scope: DiscordScope, message: Message<unknown>, nickname?: string | undefined): DiscordMessage => ({
|
|
56
73
|
id: message.id,
|
|
57
74
|
guildId: scope.guildId,
|
|
@@ -70,7 +87,7 @@ const fromChatMessage = (scope: DiscordScope, message: Message<unknown>, nicknam
|
|
|
70
87
|
everyoneMention: message.text.includes("@everyone"),
|
|
71
88
|
hereMention: message.text.includes("@here"),
|
|
72
89
|
attachments: attachments(message),
|
|
73
|
-
reactions:
|
|
90
|
+
reactions: reactions(message),
|
|
74
91
|
channelType: "guild"
|
|
75
92
|
})
|
|
76
93
|
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { describe, expect, test } from "bun:test"
|
|
2
|
+
import type { DiscordThreadId } from "@chat-adapter/discord"
|
|
3
|
+
import type { AdapterPostableMessage, FetchOptions, FetchResult, RawMessage } from "chat"
|
|
4
|
+
import { Message, parseMarkdown } from "chat"
|
|
5
|
+
import { Effect } from "effect"
|
|
6
|
+
import type { DiscordScope } from "../Schema.ts"
|
|
7
|
+
import { makeChatSdkDiscord } from "./ChatSdkDiscord.ts"
|
|
8
|
+
|
|
9
|
+
const scope: DiscordScope = { guildId: "g1", channelId: "c1" }
|
|
10
|
+
|
|
11
|
+
const makeMessage = (threadId: string, raw: unknown): Message<unknown> =>
|
|
12
|
+
new Message({
|
|
13
|
+
id: "m1",
|
|
14
|
+
threadId,
|
|
15
|
+
text: "hello",
|
|
16
|
+
formatted: parseMarkdown("hello"),
|
|
17
|
+
raw,
|
|
18
|
+
author: { userId: "u1", userName: "alice", fullName: "Alice", isBot: false, isMe: false },
|
|
19
|
+
metadata: { dateSent: new Date("2026-06-05T14:03:00.000Z"), edited: false },
|
|
20
|
+
attachments: []
|
|
21
|
+
})
|
|
22
|
+
|
|
23
|
+
class ReactionAdapter {
|
|
24
|
+
encodeThreadId(input: DiscordThreadId): string {
|
|
25
|
+
return `discord:${input.guildId}:${input.channelId}`
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
fetchMessages(threadId: string, _options?: FetchOptions): Promise<FetchResult<unknown>> {
|
|
29
|
+
return Promise.resolve({
|
|
30
|
+
messages: [
|
|
31
|
+
makeMessage(threadId, {
|
|
32
|
+
reactions: [
|
|
33
|
+
{ count: 3, emoji: { id: null, name: "\u{1F680}" } },
|
|
34
|
+
{ count: 2, emoji: { id: "custom1", name: "party_blob", animated: false } },
|
|
35
|
+
{ count: 1, emoji: { id: "anim1", name: "dance", animated: true } },
|
|
36
|
+
{ count: "bad", emoji: { id: null, name: "ignored" } },
|
|
37
|
+
{ count: -1, emoji: { id: null, name: "ignored" } }
|
|
38
|
+
]
|
|
39
|
+
})
|
|
40
|
+
]
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
postMessage(threadId: string, _message: AdapterPostableMessage): Promise<RawMessage<unknown>> {
|
|
45
|
+
return Promise.resolve({ id: "posted", raw: {}, threadId })
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
editMessage(threadId: string, messageId: string, _message: AdapterPostableMessage): Promise<RawMessage<unknown>> {
|
|
49
|
+
return Promise.resolve({ id: messageId, raw: {}, threadId })
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
deleteMessage(_threadId: string, _messageId: string): Promise<void> {
|
|
53
|
+
return Promise.resolve()
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
startTyping(_threadId: string, _status?: string): Promise<void> {
|
|
57
|
+
return Promise.resolve()
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
addReaction(_threadId: string, _messageId: string, _emoji: string): Promise<void> {
|
|
61
|
+
return Promise.resolve()
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
describe("makeChatSdkDiscord reactions", () => {
|
|
66
|
+
test("maps aggregate reactions from raw Discord messages", async () => {
|
|
67
|
+
const discord = makeChatSdkDiscord(new ReactionAdapter())
|
|
68
|
+
|
|
69
|
+
const context = await Effect.runPromise(discord.fetchContext(scope, 30))
|
|
70
|
+
|
|
71
|
+
expect(context[0]?.reactions).toEqual([
|
|
72
|
+
{ emoji: "\u{1F680}", count: 3 },
|
|
73
|
+
{ emoji: "party_blob:custom1", count: 2 },
|
|
74
|
+
{ emoji: "a:dance:anim1", count: 1 }
|
|
75
|
+
])
|
|
76
|
+
})
|
|
77
|
+
})
|