Files
clawdbot/extensions/twitch/src/config-schema.ts
jaydenfyi f5c90f0e5c feat: Twitch Plugin (#1612)
* wip

* copy polugin files

* wip type changes

* refactor: improve Twitch plugin code quality and fix all tests

- Extract client manager registry for centralized lifecycle management
- Refactor to use early returns and reduce mutations
- Fix status check logic for clientId detection
- Add comprehensive test coverage for new modules
- Remove tests for unimplemented features (index.test.ts, resolver.test.ts)
- Fix mock setup issues in test suite (149 tests now passing)
- Improve error handling with errorResponse helper in actions.ts
- Normalize token handling to eliminate duplication

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* use accountId

* delete md file

* delte tsconfig

* adjust log level

* fix probe logic

* format

* fix monitor

* code review fixes

* format

* no mutation

* less mutation

* chain debug log

* await authProvider setup

* use uuid

* use spread

* fix tests

* update docs and remove bot channel fallback

* more readme fixes

* remove comments + fromat

* fix tests

* adjust access control logic

* format

* install

* simplify config object

* remove duplicate log tags + log received messages

* update docs

* update tests

* format

* strip markdown in monitor

* remove strip markdown config, enabled by default

* default requireMention to true

* fix store path arg

* fix multi account id + add unit test

* fix multi account id + add unit test

* make channel required and update docs

* remove whisper functionality

* remove duplicate connect log

* update docs with convert twitch link

* make twitch message processing non blocking

* schema consistent casing

* remove noisy ignore log

* use coreLogger

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2026-01-26 13:48:10 -06:00

83 lines
2.9 KiB
TypeScript

import { MarkdownConfigSchema } from "clawdbot/plugin-sdk";
import { z } from "zod";
/**
* Twitch user roles that can be allowed to interact with the bot
*/
const TwitchRoleSchema = z.enum(["moderator", "owner", "vip", "subscriber", "all"]);
/**
* Twitch account configuration schema
*/
const TwitchAccountSchema = z.object({
/** Twitch username */
username: z.string(),
/** Twitch OAuth access token (requires chat:read and chat:write scopes) */
accessToken: z.string(),
/** Twitch client ID (from Twitch Developer Portal or twitchtokengenerator.com) */
clientId: z.string().optional(),
/** Channel name to join */
channel: z.string().min(1),
/** Enable this account */
enabled: z.boolean().optional(),
/** Allowlist of Twitch user IDs who can interact with the bot (use IDs for safety, not usernames) */
allowFrom: z.array(z.string()).optional(),
/** Roles allowed to interact with the bot (e.g., ["moderator", "vip", "subscriber"]) */
allowedRoles: z.array(TwitchRoleSchema).optional(),
/** Require @mention to trigger bot responses */
requireMention: z.boolean().optional(),
/** Twitch client secret (required for token refresh via RefreshingAuthProvider) */
clientSecret: z.string().optional(),
/** Refresh token (required for automatic token refresh) */
refreshToken: z.string().optional(),
/** Token expiry time in seconds (optional, for token refresh tracking) */
expiresIn: z.number().nullable().optional(),
/** Timestamp when token was obtained (optional, for token refresh tracking) */
obtainmentTimestamp: z.number().optional(),
});
/**
* Base configuration properties shared by both single and multi-account modes
*/
const TwitchConfigBaseSchema = z.object({
name: z.string().optional(),
enabled: z.boolean().optional(),
markdown: MarkdownConfigSchema.optional(),
});
/**
* Simplified single-account configuration schema
*
* Use this for single-account setups. Properties are at the top level,
* creating an implicit "default" account.
*/
const SimplifiedSchema = z.intersection(TwitchConfigBaseSchema, TwitchAccountSchema);
/**
* Multi-account configuration schema
*
* Use this for multi-account setups. Each key is an account ID (e.g., "default", "secondary").
*/
const MultiAccountSchema = z.intersection(
TwitchConfigBaseSchema,
z
.object({
/** Per-account configuration (for multi-account setups) */
accounts: z.record(z.string(), TwitchAccountSchema),
})
.refine((val) => Object.keys(val.accounts || {}).length > 0, {
message: "accounts must contain at least one entry",
}),
);
/**
* Twitch plugin configuration schema
*
* Supports two mutually exclusive patterns:
* 1. Simplified single-account: username, accessToken, clientId, channel at top level
* 2. Multi-account: accounts object with named account configs
*
* The union ensures clear discrimination between the two modes.
*/
export const TwitchConfigSchema = z.union([SimplifiedSchema, MultiAccountSchema]);