From 90b2afee927cd7c06052dd1919a9aa6af6b527af Mon Sep 17 00:00:00 2001 From: Ash Keel Date: Sun, 5 Nov 2023 13:23:00 +0100 Subject: [PATCH] add v3.3 --- content/api/v31.md | 2 +- content/api/v33.md | 9 + data/api/v33/api.json | 1675 +++++++++++++++++++++++++++++++++++++++++ static/logviewer.html | 99 ++- 4 files changed, 1764 insertions(+), 21 deletions(-) create mode 100644 content/api/v33.md create mode 100644 data/api/v33/api.json diff --git a/content/api/v31.md b/content/api/v31.md index eb70ae3..ceee20b 100644 --- a/content/api/v31.md +++ b/content/api/v31.md @@ -1,7 +1,7 @@ --- menu: apiversions -title: v3.1 - v3.3 +title: v3.1 / v3.2 version: v31 aliases: - latest diff --git a/content/api/v33.md b/content/api/v33.md new file mode 100644 index 0000000..5d519ed --- /dev/null +++ b/content/api/v33.md @@ -0,0 +1,9 @@ +--- +menu: apiversions + +title: v3.3 +version: v33 +aliases: + - latest + - api/ +--- diff --git a/data/api/v33/api.json b/data/api/v33/api.json new file mode 100644 index 0000000..5231297 --- /dev/null +++ b/data/api/v33/api.json @@ -0,0 +1,1675 @@ +{ + "twitch/config": { + "description": "General configuration for the Twitch subsystem", + "schema": { + "name": "Config", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Enable subsystem", + "kind": "boolean" + }, + { + "name": "enable_bot", + "description": "Enable the chatbot", + "kind": "boolean" + }, + { + "name": "api_client_id", + "description": "Twitch API App Client ID", + "kind": "string" + }, + { + "name": "api_client_secret", + "description": "Twitch API App Client Secret", + "kind": "string" + } + ] + } + }, + "twitch/bot-custom-commands": { + "description": "Chatbot custom commands", + "schema": { + "name": "", + "kind": "dictionary", + "key": { + "name": "string", + "kind": "string" + }, + "element": { + "name": "BotCustomCommand", + "kind": "object", + "keys": [ + { + "name": "description", + "description": "Command description", + "kind": "string" + }, + { + "name": "access_level", + "description": "Minimum access level needed to use the command", + "kind": "enum", + "enumValues": [ + "everyone", + "subscriber", + "vip", + "moderators", + "streamer" + ] + }, + { + "name": "response", + "description": "Response template (in Go templating format)", + "kind": "string" + }, + { + "name": "enabled", + "description": "Is the command enabled?", + "kind": "boolean" + }, + { + "name": "response_type", + "description": "How to respond to the user", + "kind": "enum", + "enumValues": [ + "chat", + "reply", + "whisper", + "announce" + ] + } + ] + } + } + }, + "twitch/@send-chat-message": { + "description": "Send plain text chat message (this will be deprecated or renamed someday, please use the other one!)", + "schema": { + "name": "string", + "kind": "string" + }, + "tags": [ + "rpc" + ] + }, + "twitch/bot/@send-message": { + "description": "Send chat message with extra options (as reply, whisper, etc)", + "schema": { + "name": "WriteMessageRequest", + "kind": "object", + "keys": [ + { + "name": "message", + "description": "Chat message to send", + "kind": "string" + }, + { + "name": "reply_to", + "description": "If specified, send as reply to a message ID", + "kind": "string", + "isPointer": true + }, + { + "name": "whisper_to", + "description": "If specified, send as whisper to user ID", + "kind": "string", + "isPointer": true + }, + { + "name": "announce", + "description": "If true, send as announcement", + "kind": "boolean" + } + ] + }, + "tags": [ + "rpc" + ] + }, + "loyalty/@create-redeem": { + "description": "Create a new pending redeem", + "schema": { + "name": "Redeem", + "kind": "object", + "keys": [ + { + "name": "username", + "description": "Username of who redeemed the reward", + "kind": "string" + }, + { + "name": "display_name", + "description": "Display name of who redeemed the reward", + "kind": "string" + }, + { + "name": "reward", + "description": "Reward that was redeemed", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Is the reward enabled (redeemable)?", + "kind": "boolean" + }, + { + "name": "id", + "description": "Reward ID", + "kind": "string" + }, + { + "name": "name", + "description": "Name of the reward", + "kind": "string" + }, + { + "name": "description", + "description": "Description of the reward", + "kind": "string" + }, + { + "name": "image", + "description": "Reward icon URL", + "kind": "string" + }, + { + "name": "price", + "description": "How much does is cost", + "kind": "int" + }, + { + "name": "required_info", + "description": "If present, reward requires user input and this field is the help text", + "kind": "string" + }, + { + "name": "cooldown", + "description": "Time in seconds to wait before this reward can be redeemed again", + "kind": "int" + } + ] + }, + { + "name": "when", + "description": "Time of the redeem", + "kind": "datetime" + }, + { + "name": "request_text", + "description": "If the reward required user input it will be here", + "kind": "string" + } + ] + }, + "tags": [ + "rpc" + ] + }, + "twitch/bot-modules/alerts/config": { + "description": "Configuration of chat bot alerts", + "schema": { + "name": "BotAlertsConfig", + "kind": "object", + "keys": [ + { + "name": "follow", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Enable chat message alert on follow", + "kind": "boolean" + }, + { + "name": "messages", + "description": "List of message to write on follow, one at random will be picked", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + } + ] + }, + { + "name": "subscription", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Enable chat message alert on subscription", + "kind": "boolean" + }, + { + "name": "messages", + "description": "List of message to write on subscription, one at random will be picked", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + }, + { + "name": "variations", + "kind": "array", + "element": { + "name": "subscriptionVariation", + "kind": "object", + "keys": [ + { + "name": "min_streak", + "description": "Minimum streak to get this message", + "kind": "int", + "isPointer": true + }, + { + "name": "is_gifted", + "description": "If true, only gifted subscriptions will get these messages", + "kind": "boolean", + "isPointer": true + }, + { + "name": "messages", + "description": "List of message to write on subscription, one at random will be picked", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + } + ] + } + } + ] + }, + { + "name": "gift_sub", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Enable chat message alert on gifted subscription", + "kind": "boolean" + }, + { + "name": "messages", + "description": "List of message to write on gifted subscription, one at random will be picked", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + }, + { + "name": "variations", + "kind": "array", + "element": { + "name": "giftSubVariation", + "kind": "object", + "keys": [ + { + "name": "min_cumulative", + "description": "Minimum cumulative amount to get this message", + "kind": "int", + "isPointer": true + }, + { + "name": "is_anonymous", + "description": "If true, only anonymous gifts will get these messages", + "kind": "boolean", + "isPointer": true + }, + { + "name": "messages", + "description": "List of message to write on gifted subscription, one at random will be picked", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + } + ] + } + } + ] + }, + { + "name": "raid", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Enable chat message alert on raid", + "kind": "boolean" + }, + { + "name": "messages", + "description": "List of message to write on raid, one at random will be picked", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + }, + { + "name": "variations", + "kind": "array", + "element": { + "name": "raidVariation", + "kind": "object", + "keys": [ + { + "name": "min_viewers", + "description": "Minimum number of viewers to get this message", + "kind": "int", + "isPointer": true + }, + { + "name": "messages", + "description": "List of message to write on raid, one at random will be picked", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + } + ] + } + } + ] + }, + { + "name": "cheer", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Enable chat message alert on cheer", + "kind": "boolean" + }, + { + "name": "messages", + "description": "List of message to write on cheer, one at random will be picked", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + }, + { + "name": "variations", + "kind": "array", + "element": { + "name": "cheerVariation", + "kind": "object", + "keys": [ + { + "name": "min_amount", + "description": "Minimum amount to get this message", + "kind": "int", + "isPointer": true + }, + { + "name": "messages", + "description": "List of message to write on cheer, one at random will be picked", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + } + ] + } + } + ] + } + ] + } + }, + "twitch/eventsub-history": { + "description": "Last eventsub notifications received", + "schema": { + "name": "", + "kind": "array", + "element": { + "name": "NotificationMessagePayload", + "kind": "object", + "keys": [ + { + "name": "subscription", + "kind": "object", + "keys": [ + { + "name": "id", + "kind": "string" + }, + { + "name": "type", + "kind": "string" + }, + { + "name": "version", + "kind": "string" + }, + { + "name": "status", + "kind": "string" + }, + { + "name": "condition", + "kind": "object", + "keys": [ + { + "name": "broadcaster_user_id", + "kind": "string" + }, + { + "name": "from_broadcaster_user_id", + "kind": "string" + }, + { + "name": "moderator_user_id", + "kind": "string" + }, + { + "name": "to_broadcaster_user_id", + "kind": "string" + }, + { + "name": "reward_id", + "kind": "string" + }, + { + "name": "client_id", + "kind": "string" + }, + { + "name": "extension_client_id", + "kind": "string" + }, + { + "name": "user_id", + "kind": "string" + } + ] + }, + { + "name": "transport", + "kind": "object", + "keys": [ + { + "name": "method", + "kind": "string" + }, + { + "name": "callback", + "kind": "string" + }, + { + "name": "secret", + "kind": "string" + }, + { + "name": "session_id", + "kind": "string" + } + ] + }, + { + "name": "created_at", + "kind": "object", + "keys": [ + { + "name": "Time", + "kind": "datetime" + } + ] + }, + { + "name": "cost", + "kind": "int" + } + ] + }, + { + "name": "event", + "kind": "array", + "element": { + "name": "uint8", + "kind": "int" + } + }, + { + "name": "date", + "kind": "datetime" + } + ] + } + }, + "tags": [ + "history" + ] + }, + "loyalty/redeem-queue": { + "description": "All pending redeems", + "schema": { + "name": "", + "kind": "array", + "element": { + "name": "Redeem", + "kind": "object", + "keys": [ + { + "name": "username", + "description": "Username of who redeemed the reward", + "kind": "string" + }, + { + "name": "display_name", + "description": "Display name of who redeemed the reward", + "kind": "string" + }, + { + "name": "reward", + "description": "Reward that was redeemed", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Is the reward enabled (redeemable)?", + "kind": "boolean" + }, + { + "name": "id", + "description": "Reward ID", + "kind": "string" + }, + { + "name": "name", + "description": "Name of the reward", + "kind": "string" + }, + { + "name": "description", + "description": "Description of the reward", + "kind": "string" + }, + { + "name": "image", + "description": "Reward icon URL", + "kind": "string" + }, + { + "name": "price", + "description": "How much does is cost", + "kind": "int" + }, + { + "name": "required_info", + "description": "If present, reward requires user input and this field is the help text", + "kind": "string" + }, + { + "name": "cooldown", + "description": "Time in seconds to wait before this reward can be redeemed again", + "kind": "int" + } + ] + }, + { + "name": "when", + "description": "Time of the redeem", + "kind": "datetime" + }, + { + "name": "request_text", + "description": "If the reward required user input it will be here", + "kind": "string" + } + ] + } + } + }, + "loyalty/config": { + "description": "General configuration for the loyalty system", + "schema": { + "name": "Config", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Enable the loyalty system", + "kind": "boolean" + }, + { + "name": "currency", + "description": "Name of the currency", + "kind": "string" + }, + { + "name": "points", + "description": "Settings for distributing currency to online viewers", + "kind": "object", + "keys": [ + { + "name": "interval", + "description": "How often to distribute points, in seconds", + "kind": "int" + }, + { + "name": "amount", + "description": "How many points to award every interval", + "kind": "int" + }, + { + "name": "activity_bonus", + "description": "Extra points for active chatters", + "kind": "int" + } + ] + }, + { + "name": "banlist", + "description": "Usernames to exclude from currency distribution", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + } + ] + } + }, + "http/config": { + "description": "General server configuration", + "schema": { + "name": "ServerConfig", + "kind": "object", + "keys": [ + { + "name": "bind", + "kind": "string" + }, + { + "name": "enable_static_server", + "kind": "boolean" + }, + { + "name": "path", + "kind": "string" + }, + { + "name": "kv_password", + "kind": "string" + } + ] + } + }, + "twitch/ev/eventsub-event": { + "description": "On Eventsub event received", + "schema": { + "name": "NotificationMessagePayload", + "kind": "object", + "keys": [ + { + "name": "subscription", + "kind": "object", + "keys": [ + { + "name": "id", + "kind": "string" + }, + { + "name": "type", + "kind": "string" + }, + { + "name": "version", + "kind": "string" + }, + { + "name": "status", + "kind": "string" + }, + { + "name": "condition", + "kind": "object", + "keys": [ + { + "name": "broadcaster_user_id", + "kind": "string" + }, + { + "name": "from_broadcaster_user_id", + "kind": "string" + }, + { + "name": "moderator_user_id", + "kind": "string" + }, + { + "name": "to_broadcaster_user_id", + "kind": "string" + }, + { + "name": "reward_id", + "kind": "string" + }, + { + "name": "client_id", + "kind": "string" + }, + { + "name": "extension_client_id", + "kind": "string" + }, + { + "name": "user_id", + "kind": "string" + } + ] + }, + { + "name": "transport", + "kind": "object", + "keys": [ + { + "name": "method", + "kind": "string" + }, + { + "name": "callback", + "kind": "string" + }, + { + "name": "secret", + "kind": "string" + }, + { + "name": "session_id", + "kind": "string" + } + ] + }, + { + "name": "created_at", + "kind": "object", + "keys": [ + { + "name": "Time", + "kind": "datetime" + } + ] + }, + { + "name": "cost", + "kind": "int" + } + ] + }, + { + "name": "event", + "kind": "array", + "element": { + "name": "uint8", + "kind": "int" + } + }, + { + "name": "date", + "kind": "datetime" + } + ] + }, + "tags": [ + "event" + ] + }, + "twitch/bot-config": { + "description": "General configuration for the Twitch chatbot", + "schema": { + "name": "BotConfig", + "kind": "object", + "keys": [ + { + "name": "username", + "description": "Chatbot username (for internal use, ignored by Twitch)", + "kind": "string" + }, + { + "name": "oauth", + "description": "OAuth key for IRC authentication", + "kind": "string" + }, + { + "name": "channel", + "description": "Twitch channel to join and use", + "kind": "string" + }, + { + "name": "chat_history", + "description": "How many messages to keep in twitch/chat-history", + "kind": "int" + }, + { + "name": "command_cooldown", + "description": "Global command cooldown in seconds", + "kind": "int" + } + ] + } + }, + "loyalty/@remove-redeem": { + "description": "Remove a redeem from the queue", + "schema": { + "name": "Redeem", + "kind": "object", + "keys": [ + { + "name": "username", + "description": "Username of who redeemed the reward", + "kind": "string" + }, + { + "name": "display_name", + "description": "Display name of who redeemed the reward", + "kind": "string" + }, + { + "name": "reward", + "description": "Reward that was redeemed", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Is the reward enabled (redeemable)?", + "kind": "boolean" + }, + { + "name": "id", + "description": "Reward ID", + "kind": "string" + }, + { + "name": "name", + "description": "Name of the reward", + "kind": "string" + }, + { + "name": "description", + "description": "Description of the reward", + "kind": "string" + }, + { + "name": "image", + "description": "Reward icon URL", + "kind": "string" + }, + { + "name": "price", + "description": "How much does is cost", + "kind": "int" + }, + { + "name": "required_info", + "description": "If present, reward requires user input and this field is the help text", + "kind": "string" + }, + { + "name": "cooldown", + "description": "Time in seconds to wait before this reward can be redeemed again", + "kind": "int" + } + ] + }, + { + "name": "when", + "description": "Time of the redeem", + "kind": "datetime" + }, + { + "name": "request_text", + "description": "If the reward required user input it will be here", + "kind": "string" + } + ] + }, + "tags": [ + "rpc" + ] + }, + "twitch/ev/chat-message": { + "description": "On chat message received", + "schema": { + "name": "PrivateMessage", + "kind": "object", + "keys": [ + { + "name": "User", + "kind": "object", + "keys": [ + { + "name": "ID", + "kind": "string" + }, + { + "name": "Name", + "kind": "string" + }, + { + "name": "DisplayName", + "kind": "string" + }, + { + "name": "Color", + "kind": "string" + }, + { + "name": "Badges", + "kind": "dictionary", + "key": { + "name": "string", + "kind": "string" + }, + "element": { + "name": "int", + "kind": "int" + } + } + ] + }, + { + "name": "Raw", + "kind": "string" + }, + { + "name": "Type", + "kind": "int" + }, + { + "name": "RawType", + "kind": "string" + }, + { + "name": "Tags", + "kind": "dictionary", + "key": { + "name": "string", + "kind": "string" + }, + "element": { + "name": "string", + "kind": "string" + } + }, + { + "name": "Message", + "kind": "string" + }, + { + "name": "Channel", + "kind": "string" + }, + { + "name": "RoomID", + "kind": "string" + }, + { + "name": "ID", + "kind": "string" + }, + { + "name": "Time", + "kind": "datetime" + }, + { + "name": "Emotes", + "kind": "array", + "element": { + "name": "", + "kind": "object", + "keys": [ + { + "name": "Name", + "kind": "string" + }, + { + "name": "ID", + "kind": "string" + }, + { + "name": "Count", + "kind": "int" + }, + { + "name": "Positions", + "kind": "array", + "element": { + "name": "EmotePosition", + "kind": "object", + "keys": [ + { + "name": "Start", + "kind": "int" + }, + { + "name": "End", + "kind": "int" + } + ] + } + } + ], + "isPointer": true + } + }, + { + "name": "Bits", + "kind": "int" + }, + { + "name": "Action", + "kind": "boolean" + }, + { + "name": "FirstMessage", + "kind": "boolean" + }, + { + "name": "Reply", + "kind": "object", + "keys": [ + { + "name": "ParentMsgID", + "kind": "string" + }, + { + "name": "ParentUserID", + "kind": "string" + }, + { + "name": "ParentUserLogin", + "kind": "string" + }, + { + "name": "ParentDisplayName", + "kind": "string" + }, + { + "name": "ParentMsgBody", + "kind": "string" + } + ], + "isPointer": true + }, + { + "name": "CustomRewardID", + "kind": "string" + } + ] + }, + "tags": [ + "event" + ] + }, + "twitch/chat-history": { + "description": "Last chat messages received", + "schema": { + "name": "", + "kind": "array", + "element": { + "name": "PrivateMessage", + "kind": "object", + "keys": [ + { + "name": "User", + "kind": "object", + "keys": [ + { + "name": "ID", + "kind": "string" + }, + { + "name": "Name", + "kind": "string" + }, + { + "name": "DisplayName", + "kind": "string" + }, + { + "name": "Color", + "kind": "string" + }, + { + "name": "Badges", + "kind": "dictionary", + "key": { + "name": "string", + "kind": "string" + }, + "element": { + "name": "int", + "kind": "int" + } + } + ] + }, + { + "name": "Raw", + "kind": "string" + }, + { + "name": "Type", + "kind": "int" + }, + { + "name": "RawType", + "kind": "string" + }, + { + "name": "Tags", + "kind": "dictionary", + "key": { + "name": "string", + "kind": "string" + }, + "element": { + "name": "string", + "kind": "string" + } + }, + { + "name": "Message", + "kind": "string" + }, + { + "name": "Channel", + "kind": "string" + }, + { + "name": "RoomID", + "kind": "string" + }, + { + "name": "ID", + "kind": "string" + }, + { + "name": "Time", + "kind": "datetime" + }, + { + "name": "Emotes", + "kind": "array", + "element": { + "name": "", + "kind": "object", + "keys": [ + { + "name": "Name", + "kind": "string" + }, + { + "name": "ID", + "kind": "string" + }, + { + "name": "Count", + "kind": "int" + }, + { + "name": "Positions", + "kind": "array", + "element": { + "name": "EmotePosition", + "kind": "object", + "keys": [ + { + "name": "Start", + "kind": "int" + }, + { + "name": "End", + "kind": "int" + } + ] + } + } + ], + "isPointer": true + } + }, + { + "name": "Bits", + "kind": "int" + }, + { + "name": "Action", + "kind": "boolean" + }, + { + "name": "FirstMessage", + "kind": "boolean" + }, + { + "name": "Reply", + "kind": "object", + "keys": [ + { + "name": "ParentMsgID", + "kind": "string" + }, + { + "name": "ParentUserID", + "kind": "string" + }, + { + "name": "ParentUserLogin", + "kind": "string" + }, + { + "name": "ParentDisplayName", + "kind": "string" + }, + { + "name": "ParentMsgBody", + "kind": "string" + } + ], + "isPointer": true + }, + { + "name": "CustomRewardID", + "kind": "string" + } + ] + } + }, + "tags": [ + "history" + ] + }, + "twitch/auth-keys": { + "description": "User access token for the twitch subsystem", + "schema": { + "name": "AuthResponse", + "kind": "object", + "keys": [ + { + "name": "access_token", + "kind": "string" + }, + { + "name": "refresh_token", + "kind": "string" + }, + { + "name": "expires_in", + "kind": "int" + }, + { + "name": "scope", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + }, + { + "name": "Time", + "kind": "datetime" + } + ] + } + }, + "loyalty/rewards": { + "description": "List of available rewards", + "schema": { + "name": "", + "kind": "array", + "element": { + "name": "Reward", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Is the reward enabled (redeemable)?", + "kind": "boolean" + }, + { + "name": "id", + "description": "Reward ID", + "kind": "string" + }, + { + "name": "name", + "description": "Name of the reward", + "kind": "string" + }, + { + "name": "description", + "description": "Description of the reward", + "kind": "string" + }, + { + "name": "image", + "description": "Reward icon URL", + "kind": "string" + }, + { + "name": "price", + "description": "How much does is cost", + "kind": "int" + }, + { + "name": "required_info", + "description": "If present, reward requires user input and this field is the help text", + "kind": "string" + }, + { + "name": "cooldown", + "description": "Time in seconds to wait before this reward can be redeemed again", + "kind": "int" + } + ] + } + } + }, + "loyalty/goals": { + "description": "List of all goals", + "schema": { + "name": "", + "kind": "array", + "element": { + "name": "Goal", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Is the goal enabled?", + "kind": "boolean" + }, + { + "name": "id", + "description": "Community goal ID", + "kind": "string" + }, + { + "name": "name", + "description": "Name of the community goal", + "kind": "string" + }, + { + "name": "description", + "description": "Description of the goal", + "kind": "string" + }, + { + "name": "image", + "description": "Goal icon URL", + "kind": "string" + }, + { + "name": "total", + "description": "How many points does the goal need to be met in total", + "kind": "int" + }, + { + "name": "contributed", + "description": "How many points have been contributed so far", + "kind": "int" + }, + { + "name": "contributors", + "description": "Dictionary of how much every viewer has contributed", + "kind": "dictionary", + "key": { + "name": "string", + "kind": "string" + }, + "element": { + "name": "int64", + "kind": "int" + } + } + ] + } + } + }, + "twitch/chat-activity": { + "description": "Number of chat messages in the last minute", + "schema": { + "name": "int", + "kind": "int" + } + }, + "twitch/stream-info": { + "description": "List of active twitch streams (1 element if live, 0 otherwise)", + "schema": { + "name": "", + "kind": "array", + "element": { + "name": "Stream", + "kind": "object", + "keys": [ + { + "name": "id", + "kind": "string" + }, + { + "name": "user_id", + "kind": "string" + }, + { + "name": "user_login", + "kind": "string" + }, + { + "name": "user_name", + "kind": "string" + }, + { + "name": "game_id", + "kind": "string" + }, + { + "name": "game_name", + "kind": "string" + }, + { + "name": "tag_ids", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + }, + { + "name": "tags", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + }, + { + "name": "is_mature", + "kind": "boolean" + }, + { + "name": "type", + "kind": "string" + }, + { + "name": "title", + "kind": "string" + }, + { + "name": "viewer_count", + "kind": "int" + }, + { + "name": "started_at", + "kind": "datetime" + }, + { + "name": "language", + "kind": "string" + }, + { + "name": "thumbnail_url", + "kind": "string" + } + ] + } + } + }, + "twitch/bot-modules/timers/config": { + "description": "Configuration of chat bot timers", + "schema": { + "name": "BotTimersConfig", + "kind": "object", + "keys": [ + { + "name": "timers", + "description": "List of timers as a dictionary", + "kind": "dictionary", + "key": { + "name": "string", + "kind": "string" + }, + "element": { + "name": "BotTimer", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Enable the timer", + "kind": "boolean" + }, + { + "name": "name", + "description": "Timer name (must be unique)", + "kind": "string" + }, + { + "name": "minimum_chat_activity", + "description": "Minimum chat messages in the last 5 minutes for timer to trigger", + "kind": "int" + }, + { + "name": "minimum_delay", + "description": "Minimum amount of time (in seconds) that needs to pass before it triggers again", + "kind": "int" + }, + { + "name": "messages", + "description": "Messages to write (randomly chosen)", + "kind": "array", + "element": { + "name": "string", + "kind": "string" + } + } + ] + } + } + ] + } + }, + "loyalty/points/": { + "description": "Point entry for a given user", + "schema": { + "name": "PointsEntry", + "kind": "object", + "keys": [ + { + "name": "points", + "description": "Currency balance", + "kind": "int" + } + ] + } + }, + "loyalty/ev/new-redeem": { + "description": "On reward redeemed", + "schema": { + "name": "Redeem", + "kind": "object", + "keys": [ + { + "name": "username", + "description": "Username of who redeemed the reward", + "kind": "string" + }, + { + "name": "display_name", + "description": "Display name of who redeemed the reward", + "kind": "string" + }, + { + "name": "reward", + "description": "Reward that was redeemed", + "kind": "object", + "keys": [ + { + "name": "enabled", + "description": "Is the reward enabled (redeemable)?", + "kind": "boolean" + }, + { + "name": "id", + "description": "Reward ID", + "kind": "string" + }, + { + "name": "name", + "description": "Name of the reward", + "kind": "string" + }, + { + "name": "description", + "description": "Description of the reward", + "kind": "string" + }, + { + "name": "image", + "description": "Reward icon URL", + "kind": "string" + }, + { + "name": "price", + "description": "How much does is cost", + "kind": "int" + }, + { + "name": "required_info", + "description": "If present, reward requires user input and this field is the help text", + "kind": "string" + }, + { + "name": "cooldown", + "description": "Time in seconds to wait before this reward can be redeemed again", + "kind": "int" + } + ] + }, + { + "name": "when", + "description": "Time of the redeem", + "kind": "datetime" + }, + { + "name": "request_text", + "description": "If the reward required user input it will be here", + "kind": "string" + } + ] + }, + "tags": [ + "event" + ] + } +} diff --git a/static/logviewer.html b/static/logviewer.html index a76881f..88af008 100644 --- a/static/logviewer.html +++ b/static/logviewer.html @@ -73,8 +73,37 @@ const startingEl = document.getElementById("starting"); const tableEl = document.getElementById("logs"); + if (!mainEl || !startingEl || !tableEl) { + throw new Error("Missing elements"); + } + + /** + * Reads a log file and populates a table with the parsed logs. + * + * @param {File} file - The log file to be read. + * @return {void} + */ + function readLogFile(file) { + const reader = new FileReader(); + reader.addEventListener("load", (ev) => { + const logs = + ev.target?.result + ?.toString() + .split("\n") + .map((line) => line.trim()) + .filter((line) => line.length > 0) + .map((line) => { + return makeLog(JSON.parse(line)); + }) || []; + tableEl?.querySelector("tbody")?.replaceChildren(...logs); + tableEl?.classList.remove("hidden"); + startingEl?.classList.add("hidden"); + }); + reader.readAsText(file); + } + // Click handler (open file select) - startingEl?.addEventListener("click", (ev) => { + startingEl.addEventListener("click", (ev) => { // Create temporary file input and click it const fileSelect = document.createElement("input"); fileSelect.type = "file"; @@ -84,42 +113,72 @@ const file = ev.target.files[0]; startingEl.innerHTML = "Loading..."; if (file) { - const reader = new FileReader(); - reader.addEventListener("load", (ev) => { - const logs = - ev.target?.result - ?.toString() - .split("\n") - .map((line) => line.trim()) - .filter((line) => line.length > 0) - .map((line) => { - return makeLog(JSON.parse(line)); - }) || []; - tableEl?.querySelector("tbody")?.replaceChildren(...logs); - tableEl?.classList.remove("hidden"); - startingEl.classList.add("hidden"); - }); - reader.readAsText(file); + readLogFile(file); } } }); fileSelect.click(); }); + // Drag and drop handler + mainEl.addEventListener("dragover", (ev) => { + ev.preventDefault(); + }); + mainEl.addEventListener("drop", (ev) => { + ev.preventDefault(); + if (ev.dataTransfer?.files) { + const file = ev.dataTransfer.files[0]; + startingEl.innerHTML = "Loading..."; + if (file) { + readLogFile(file); + } + } + }); + + /** + * Creates a log entry as a table row element. + * + * @param log - An object representing a log entry with properties level, ts, caller, msg, and data. + * + * @returns A table row element representing the log entry. + */ function makeLog(log) { const tr = document.createElement("tr"); const { level, ts, caller, msg, ...data } = log; tr.appendChild(makeCell(level)); - tr.appendChild(makeCell(new Date(ts * 1000).toISOString())); + tr.appendChild(makeCell(makeDateElement(new Date(ts * 1000)))); tr.appendChild(makeCell(caller)); tr.appendChild(makeCell(msg)); tr.appendChild(makeCell(JSON.stringify(data))); return tr; } - function makeCell(text) { + /** + * Creates a new date element with the given date. + * + * @param {Date} date - The date to be used for the new date element. + * @returns {HTMLTimeElement} The newly created date element. + */ + function makeDateElement(date) { + const time = document.createElement("time"); + time.setAttribute("datetime", date.toISOString()); + time.appendChild(document.createTextNode(date.toLocaleTimeString())); + return time; + } + + /** + * Creates a table cell element with the given text as its content. + * + * @param {string | HTMLElement} el - A string or a DOM element to be used as the content of the cell. + * @returns {HTMLTableCellElement} - A table cell element with the given text as its content. + */ + function makeCell(el) { const td = document.createElement("td"); - td.appendChild(document.createTextNode(text)); + if (typeof el === "string") { + td.appendChild(document.createTextNode(el)); + } else { + td.appendChild(el); + } return td; }