Files
openclaw/extensions/discord/src/components-registry.ts
scoootscooob 5682ec37fa refactor: move Discord channel implementation to extensions/ (#45660)
* refactor: move Discord channel implementation to extensions/discord/src/

Move all Discord source files from src/discord/ to extensions/discord/src/,
following the extension migration pattern. Source files in src/discord/ are
replaced with re-export shims. Channel-plugin files from
src/channels/plugins/*/discord* are similarly moved and shimmed.

- Copy all .ts source files preserving subdirectory structure (monitor/, voice/)
- Move channel-plugin files (actions, normalize, onboarding, outbound, status-issues)
- Fix all relative imports to use correct paths from new location
- Create re-export shims at original locations for backward compatibility
- Delete test files from shim locations (tests live in extension now)
- Update tsconfig.plugin-sdk.dts.json rootDir from "src" to "." to accommodate
  extension files outside src/
- Update write-plugin-sdk-entry-dts.ts to match new declaration output paths

* fix: add importOriginal to thread-bindings session-meta mock for extensions test

* style: fix formatting in thread-bindings lifecycle test
2026-03-14 02:53:57 -07:00

90 lines
2.3 KiB
TypeScript

import type { DiscordComponentEntry, DiscordModalEntry } from "./components.js";
const DEFAULT_COMPONENT_TTL_MS = 30 * 60 * 1000;
const componentEntries = new Map<string, DiscordComponentEntry>();
const modalEntries = new Map<string, DiscordModalEntry>();
function isExpired(entry: { expiresAt?: number }, now: number) {
return typeof entry.expiresAt === "number" && entry.expiresAt <= now;
}
function normalizeEntryTimestamps<T extends { createdAt?: number; expiresAt?: number }>(
entry: T,
now: number,
ttlMs: number,
): T {
const createdAt = entry.createdAt ?? now;
const expiresAt = entry.expiresAt ?? createdAt + ttlMs;
return { ...entry, createdAt, expiresAt };
}
export function registerDiscordComponentEntries(params: {
entries: DiscordComponentEntry[];
modals: DiscordModalEntry[];
ttlMs?: number;
messageId?: string;
}): void {
const now = Date.now();
const ttlMs = params.ttlMs ?? DEFAULT_COMPONENT_TTL_MS;
for (const entry of params.entries) {
const normalized = normalizeEntryTimestamps(
{ ...entry, messageId: params.messageId ?? entry.messageId },
now,
ttlMs,
);
componentEntries.set(entry.id, normalized);
}
for (const modal of params.modals) {
const normalized = normalizeEntryTimestamps(
{ ...modal, messageId: params.messageId ?? modal.messageId },
now,
ttlMs,
);
modalEntries.set(modal.id, normalized);
}
}
export function resolveDiscordComponentEntry(params: {
id: string;
consume?: boolean;
}): DiscordComponentEntry | null {
const entry = componentEntries.get(params.id);
if (!entry) {
return null;
}
const now = Date.now();
if (isExpired(entry, now)) {
componentEntries.delete(params.id);
return null;
}
if (params.consume !== false) {
componentEntries.delete(params.id);
}
return entry;
}
export function resolveDiscordModalEntry(params: {
id: string;
consume?: boolean;
}): DiscordModalEntry | null {
const entry = modalEntries.get(params.id);
if (!entry) {
return null;
}
const now = Date.now();
if (isExpired(entry, now)) {
modalEntries.delete(params.id);
return null;
}
if (params.consume !== false) {
modalEntries.delete(params.id);
}
return entry;
}
export function clearDiscordComponentEntries(): void {
componentEntries.clear();
modalEntries.clear();
}