add web (launcher)

This commit is contained in:
avaksru 2026-03-23 10:37:13 +03:00
parent 64c6e38428
commit 14e80919a8
8 changed files with 1471 additions and 467 deletions

File diff suppressed because it is too large Load diff

View file

@ -29,6 +29,7 @@ var channelCatalog = []channelCatalogItem{
{Name: "maixcam", ConfigKey: "maixcam"},
{Name: "matrix", ConfigKey: "matrix"},
{Name: "irc", ConfigKey: "irc"},
{Name: "mqtt", ConfigKey: "mqtt"},
}
// registerChannelRoutes binds read-only channel catalog endpoints to the ServeMux.

View file

@ -189,6 +189,19 @@ func validateConfig(cfg *config.Config) []string {
errs = append(errs, "channels.discord.token is required when discord channel is enabled")
}
// MQTT: broker and client_id required when enabled
if cfg.Channels.MQTT.Enabled {
if cfg.Channels.MQTT.Broker == "" {
errs = append(errs, "channels.mqtt.broker is required when mqtt channel is enabled")
}
if cfg.Channels.MQTT.ClientID == "" {
errs = append(errs, "channels.mqtt.client_id is required when mqtt channel is enabled")
}
if len(cfg.Channels.MQTT.SubscribeTopics) == 0 {
errs = append(errs, "channels.mqtt.subscribe_topics is required when mqtt channel is enabled")
}
}
if cfg.Tools.Exec.Enabled {
if cfg.Tools.Exec.EnableDenyPatterns {
errs = append(

View file

@ -166,6 +166,8 @@ function isConfigured(
)
case "irc":
return asString(config.server) !== ""
case "mqtt":
return asString(config.broker) !== "" && asString(config.client_id) !== ""
default:
return false
}
@ -205,6 +207,8 @@ function getRequiredFieldKeys(channelName: string): string[] {
return ["homeserver", "user_id", "access_token"]
case "irc":
return ["server"]
case "mqtt":
return ["broker", "client_id", "subscribe_topics"]
default:
return []
}

View file

@ -31,6 +31,9 @@ const SECRET_FIELDS = new Set([
"password",
"nickserv_password",
"sasl_password",
"tls_ca",
"tls_cert",
"tls_key",
])
// Fields to skip in the generic form (handled by enabled toggle or internal).
@ -139,6 +142,15 @@ export function GenericForm({
channels: t("channels.form.desc.channels"),
request_caps: t("channels.form.desc.requestCaps"),
max_base64_file_size_mib: t("channels.form.desc.maxBase64FileSizeMiB"),
broker: t("channels.form.desc.broker"),
subscribe_topics: t("channels.form.desc.subscribeTopics"),
subscribe_json_key: t("channels.form.desc.subscribeJsonKey"),
reply_topic: t("channels.form.desc.replyTopic"),
reply_json_key: t("channels.form.desc.replyJsonKey"),
qos: t("channels.form.desc.qos"),
retain: t("channels.form.desc.retain"),
prefix: t("channels.form.desc.prefix"),
instruction: t("channels.form.desc.instruction"),
}
return (
descriptions[key] ??

View file

@ -44,6 +44,7 @@ const CHANNEL_IMPORTANCE_ORDER = [
"pico",
"maixcam",
"irc",
"mqtt",
"whatsapp",
"whatsapp_native",
]

View file

@ -240,7 +240,8 @@
"pico": "Web",
"maixcam": "MaixCam",
"matrix": "Matrix",
"irc": "IRC"
"irc": "IRC",
"mqtt": "MQTT"
},
"field": {
"token": "Bot Token",
@ -328,6 +329,15 @@
"channels": "IRC channels to join.",
"requestCaps": "IRC capability list requested on connect.",
"maxBase64FileSizeMiB": "Maximum size in MiB for converting local files to base64 before upload. 0 means unlimited. Applies only to local files, not URL uploads.",
"broker": "MQTT broker URL (e.g. tcp://broker.emqx.io:1883).",
"subscribeTopics": "MQTT topics to subscribe to, separated by commas.",
"subscribeJsonKey": "JSON key to extract from incoming messages. Leave empty to use raw payload.",
"replyTopic": "Default topic for publishing replies.",
"replyJsonKey": "JSON key to wrap reply content. Leave empty to send plain text.",
"qos": "Quality of Service level (0, 1, or 2).",
"retain": "Whether to retain published messages on the broker.",
"prefix": "URL prefix for the channel.",
"instruction": "System instruction prepended to incoming messages.",
"genericField": "Used to configure {{field}}."
}
},

View file

@ -240,7 +240,8 @@
"pico": "Web",
"maixcam": "MaixCam",
"matrix": "Matrix",
"irc": "IRC"
"irc": "IRC",
"mqtt": "MQTT"
},
"field": {
"token": "Bot Token",
@ -328,6 +329,15 @@
"channels": "要加入的 IRC 频道列表。",
"requestCaps": "连接时请求的 IRC 扩展能力列表。",
"maxBase64FileSizeMiB": "本地文件转为 base64 上传的最大体积,单位 MiB0 表示不限制,仅影响本地文件,不影响 URL 直传。",
"broker": "MQTT 代理地址(例如 tcp://broker.emqx.io:1883。",
"subscribeTopics": "要订阅的 MQTT 主题,多个值用逗号分隔。",
"subscribeJsonKey": "从接收消息中提取的 JSON 键名。留空则使用原始内容。",
"replyTopic": "发布回复的默认主题。",
"replyJsonKey": "用于包装回复内容的 JSON 键名。留空则发送纯文本。",
"qos": "服务质量等级0、1 或 2。",
"retain": "是否在代理上保留已发布的消息。",
"prefix": "频道 URL 前缀。",
"instruction": "附加到接收消息前的系统指令。",
"genericField": "用于配置{{field}}。"
}
},