Implements DiscordAdapter conforming to the ChannelAdapter interface, using Discord Incoming Webhooks for outbound messages and the Interactions endpoint for inbound slash commands. Changes: - platform/internal/channels/discord.go: DiscordAdapter + splitMessage helper (Discord enforces 2000-char limit; long messages are split at newline/space boundaries). ParseWebhook handles type-1 PING (returns nil so the router layer can respond), type-2 APPLICATION_COMMAND, and type-3 MESSAGE_COMPONENT payloads. ValidateConfig rejects non-discord webhook URLs (SSRF guard matches Slack pattern). - platform/internal/channels/discord_test.go: 20 unit tests covering Type/DisplayName, ValidateConfig (valid + 5 invalid cases), SendMessage error paths, ParseWebhook (PING / slash command / DM user / unknown type / invalid JSON), StartPolling, GetAdapter registry lookup, ListAdapters inclusion, and splitMessage edge cases. - platform/internal/channels/registry.go: register "discord" adapter. - .env.example: document DISCORD_WEBHOOK_URL. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
29 lines
790 B
Go
29 lines
790 B
Go
package channels
|
|
|
|
// Registry of all available channel adapters.
|
|
// To add a new platform: implement ChannelAdapter, register here.
|
|
var adapters = map[string]ChannelAdapter{
|
|
"telegram": &TelegramAdapter{},
|
|
"slack": &SlackAdapter{},
|
|
"lark": &LarkAdapter{},
|
|
"discord": &DiscordAdapter{},
|
|
}
|
|
|
|
// GetAdapter returns the adapter for a channel type.
|
|
func GetAdapter(channelType string) (ChannelAdapter, bool) {
|
|
a, ok := adapters[channelType]
|
|
return a, ok
|
|
}
|
|
|
|
// ListAdapters returns metadata about all available adapters.
|
|
func ListAdapters() []map[string]string {
|
|
result := make([]map[string]string, 0, len(adapters))
|
|
for _, a := range adapters {
|
|
result = append(result, map[string]string{
|
|
"type": a.Type(),
|
|
"display_name": a.DisplayName(),
|
|
})
|
|
}
|
|
return result
|
|
}
|