···
1
1
import {
2
2
+
ChannelType,
2
3
Client,
3
4
Events,
4
5
GatewayIntentBits,
···
16
17
return fallback
17
18
}
18
19
20
20
+
function asString(value: unknown): string {
21
21
+
return typeof value === "string" ? value.trim() : ""
22
22
+
}
23
23
+
24
24
+
function asNumber(value: unknown): number | null {
25
25
+
if (typeof value === "number" && Number.isFinite(value)) return value
26
26
+
if (typeof value === "string") {
27
27
+
const parsed = Number.parseInt(value, 10)
28
28
+
return Number.isFinite(parsed) ? parsed : null
29
29
+
}
30
30
+
return null
31
31
+
}
32
32
+
19
33
function buildIngressPayload(message: Message): Record<string, unknown> {
20
34
const channelName =
21
35
message.channel && "name" in message.channel && typeof message.channel.name === "string"
···
71
85
export async function startDiscordGateway(): Promise<DiscordGatewayHandle | null> {
72
86
const enabled = asEnabled(process.env.DISCORD_GATEWAY_ENABLED, true)
73
87
const trace = asEnabled(process.env.DISCORD_GATEWAY_TRACE, false)
74
74
-
const rawFallback = asEnabled(process.env.DISCORD_GATEWAY_RAW_FALLBACK, false)
88
88
+
const rawFallback = asEnabled(process.env.DISCORD_GATEWAY_RAW_FALLBACK, true)
89
89
+
const rawFallbackAll = asEnabled(process.env.DISCORD_GATEWAY_RAW_FALLBACK_ALL, false)
75
90
if (!enabled) {
76
91
console.log("[discord gateway] disabled via DISCORD_GATEWAY_ENABLED=false")
77
92
return null
···
110
125
if (packet?.t !== "MESSAGE_CREATE") return
111
126
if (!rawFallback) return
112
127
const d = packet.d ?? {}
128
128
+
const channelId = asString(d.channel_id)
129
129
+
const guildId = asString(d.guild_id)
130
130
+
const channelType = asNumber(d.channel_type)
131
131
+
const cachedChannel = channelId ? client.channels.cache.get(channelId) : null
132
132
+
const cachedType = typeof cachedChannel?.type === "number" ? cachedChannel.type : null
133
133
+
const isDm =
134
134
+
!guildId &&
135
135
+
(channelType === ChannelType.DM ||
136
136
+
channelType === ChannelType.GroupDM ||
137
137
+
cachedType === ChannelType.DM ||
138
138
+
cachedType === ChannelType.GroupDM)
139
139
+
140
140
+
if (!rawFallbackAll && !isDm) {
141
141
+
if (trace) {
142
142
+
console.log(
143
143
+
`[discord gateway/raw] ignored MESSAGE_CREATE id=${String(d.id ?? "unknown")} channel=${channelId || "unknown"} guild=${guildId || "none"} type=${channelType ?? cachedType ?? "unknown"} reason=not_dm_fallback`,
144
144
+
)
145
145
+
}
146
146
+
return
147
147
+
}
148
148
+
113
149
const author = (d.author ?? {}) as Record<string, unknown>
114
150
let ingestResultText = ""
115
151
try {
116
116
-
const result = handleDiscordIngress(d)
152
152
+
const result = handleDiscordIngress({
153
153
+
...d,
154
154
+
is_dm: isDm,
155
155
+
})
117
156
ingestResultText = ` ingested=${result.ingested} woke=${result.woke} reason=${result.reason}`
118
157
} catch (err) {
119
158
ingestResultText = ` ingest_error=${err instanceof Error ? err.message : String(err)}`