Skip to content

Commit 1d7e36b

Browse files
john-zhhclaude
andcommitted
feat: add bot gateway for remote monitoring via chat platforms
Implement Bot Agent system (Phase 1-4): - Add bot gateway with IPC communication via Unix socket - Support 5 chat platforms: Telegram, Discord, Slack, Lark, FB Messenger - Natural language intent parsing for commands - Process registry with auto-generated unique names - Session management and approval workflow - Bot configuration in zen.json with platform-specific settings Co-Authored-By: Claude (claude-opus-4-6) <noreply@anthropic.com>
1 parent 32b5a5f commit 1d7e36b

17 files changed

Lines changed: 4151 additions & 0 deletions

File tree

internal/bot/adapters/adapter.go

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
package adapters
2+
3+
import (
4+
"context"
5+
"time"
6+
)
7+
8+
// Platform represents a chat platform.
9+
type Platform string
10+
11+
const (
12+
PlatformTelegram Platform = "telegram"
13+
PlatformDiscord Platform = "discord"
14+
PlatformSlack Platform = "slack"
15+
PlatformLark Platform = "lark"
16+
PlatformFBMessenger Platform = "fbmessenger"
17+
)
18+
19+
// Message represents an incoming message from any platform.
20+
type Message struct {
21+
ID string `json:"id"`
22+
Platform Platform `json:"platform"`
23+
ChatID string `json:"chat_id"`
24+
UserID string `json:"user_id"`
25+
UserName string `json:"user_name"`
26+
Content string `json:"content"`
27+
ReplyTo string `json:"reply_to,omitempty"`
28+
ThreadID string `json:"thread_id,omitempty"`
29+
Timestamp time.Time `json:"timestamp"`
30+
IsMention bool `json:"is_mention"`
31+
IsDirectMsg bool `json:"is_direct_msg"`
32+
Metadata map[string]string `json:"metadata,omitempty"`
33+
}
34+
35+
// OutgoingMessage represents a message to be sent.
36+
type OutgoingMessage struct {
37+
Text string `json:"text"`
38+
Format string `json:"format"` // plain, markdown
39+
Buttons []Button `json:"buttons,omitempty"`
40+
}
41+
42+
// Button represents an interactive button.
43+
type Button struct {
44+
ID string `json:"id"`
45+
Label string `json:"label"`
46+
Style string `json:"style"` // primary, secondary, danger
47+
Data string `json:"data"`
48+
}
49+
50+
// ButtonClick represents a button click event.
51+
type ButtonClick struct {
52+
Platform Platform `json:"platform"`
53+
ChatID string `json:"chat_id"`
54+
UserID string `json:"user_id"`
55+
MessageID string `json:"message_id"`
56+
ButtonID string `json:"button_id"`
57+
Data string `json:"data"`
58+
}
59+
60+
// Adapter is the interface for chat platform adapters.
61+
type Adapter interface {
62+
// Platform returns the platform identifier.
63+
Platform() Platform
64+
65+
// Start starts the adapter and begins listening for messages.
66+
Start(ctx context.Context) error
67+
68+
// Stop stops the adapter.
69+
Stop() error
70+
71+
// SendMessage sends a message to a chat.
72+
SendMessage(chatID string, msg *OutgoingMessage) (string, error)
73+
74+
// SendReply sends a reply to a specific message.
75+
SendReply(chatID, replyTo string, msg *OutgoingMessage) (string, error)
76+
77+
// EditMessage edits an existing message.
78+
EditMessage(chatID, msgID string, msg *OutgoingMessage) error
79+
80+
// DeleteMessage deletes a message.
81+
DeleteMessage(chatID, msgID string) error
82+
83+
// SetMessageHandler sets the handler for incoming messages.
84+
SetMessageHandler(handler func(*Message))
85+
86+
// SetButtonHandler sets the handler for button clicks.
87+
SetButtonHandler(handler func(*ButtonClick))
88+
89+
// BotUserID returns the bot's user ID on this platform.
90+
BotUserID() string
91+
}
92+
93+
// AdapterConfig is the base configuration for adapters.
94+
type AdapterConfig struct {
95+
Enabled bool `json:"enabled"`
96+
AllowedUsers []string `json:"allowed_users,omitempty"`
97+
AllowedChannels []string `json:"allowed_channels,omitempty"`
98+
AllowedChats []string `json:"allowed_chats,omitempty"`
99+
}
100+
101+
// IsUserAllowed checks if a user is in the allowed list.
102+
func (c *AdapterConfig) IsUserAllowed(userID string) bool {
103+
if len(c.AllowedUsers) == 0 {
104+
return true
105+
}
106+
for _, u := range c.AllowedUsers {
107+
if u == userID {
108+
return true
109+
}
110+
}
111+
return false
112+
}
113+
114+
// IsChatAllowed checks if a chat/channel is in the allowed list.
115+
func (c *AdapterConfig) IsChatAllowed(chatID string) bool {
116+
// Check both channels and chats
117+
allowed := append(c.AllowedChannels, c.AllowedChats...)
118+
if len(allowed) == 0 {
119+
return true
120+
}
121+
for _, ch := range allowed {
122+
if ch == chatID {
123+
return true
124+
}
125+
}
126+
return false
127+
}
128+
129+
// TelegramConfig is the configuration for Telegram adapter.
130+
type TelegramConfig struct {
131+
AdapterConfig
132+
Token string `json:"token"`
133+
}
134+
135+
// DiscordConfig is the configuration for Discord adapter.
136+
type DiscordConfig struct {
137+
AdapterConfig
138+
Token string `json:"token"`
139+
AllowedGuilds []string `json:"allowed_guilds,omitempty"`
140+
}
141+
142+
// SlackConfig is the configuration for Slack adapter.
143+
type SlackConfig struct {
144+
AdapterConfig
145+
BotToken string `json:"bot_token"`
146+
AppToken string `json:"app_token"`
147+
}
148+
149+
// LarkConfig is the configuration for Lark/Feishu adapter.
150+
type LarkConfig struct {
151+
AdapterConfig
152+
AppID string `json:"app_id"`
153+
AppSecret string `json:"app_secret"`
154+
}
155+
156+
// FBMessengerConfig is the configuration for Facebook Messenger adapter.
157+
type FBMessengerConfig struct {
158+
AdapterConfig
159+
PageToken string `json:"page_token"`
160+
VerifyToken string `json:"verify_token"`
161+
AppSecret string `json:"app_secret,omitempty"`
162+
}

0 commit comments

Comments
 (0)