feishu

package
v0.18.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Mar 5, 2026 License: MIT Imports: 17 Imported by: 0

README

Feishu (Lark) Adapter for HotPlex

View other languages: 简体中文

Feishu (Lark) adapter providing Chinese enterprise IM integration capabilities for HotPlex.

Status: ✅ Phase 3 Production Ready
Test Coverage: 50.4%
Last Updated: 2026-03-03


📖 Table of Contents


🚀 Quick Start

1. Configure Environment Variables
# Required: Feishu application credentials
export FEISHU_APP_ID=cli_a1b2c3d4e5f6g7h8
export FEISHU_APP_SECRET=xxxxxxxxxxxxxxxx
export FEISHU_VERIFICATION_TOKEN=xxxxxxxx
export FEISHU_ENCRYPT_KEY=xxxxxxxxxxxxxxxx

# Optional: Server configuration
export FEISHU_SERVER_ADDR=:8082
export FEISHU_MAX_MESSAGE_LEN=4096
2. Create Adapter Instance
import (
    "context"
    "log"
    "os"
    
    "github.com/hrygo/hotplex/chatapps/feishu"
    "github.com/hrygo/hotplex/chatapps/base"
)

func main() {
    ctx := context.Background()
    logger := base.NewLogger()
    
    config := &feishu.Config{
        AppID:             os.Getenv("FEISHU_APP_ID"),
        AppSecret:         os.Getenv("FEISHU_APP_SECRET"),
        VerificationToken: os.Getenv("FEISHU_VERIFICATION_TOKEN"),
        EncryptKey:        os.Getenv("FEISHU_ENCRYPT_KEY"),
        ServerAddr:        os.Getenv("FEISHU_SERVER_ADDR"),
        MaxMessageLen:     4096,
    }
    
    adapter, err := feishu.NewAdapter(config, logger)
    if err != nil {
        log.Fatal(err)
    }
    
    // Set message handler
    adapter.SetHandler(myHandler)
    
    // Start adapter
    if err := adapter.Start(ctx); err != nil {
        log.Fatal(err)
    }
}
3. Verify Deployment
# Check endpoint accessibility
curl -X POST https://your-domain.com/feishu/events \
  -H "Content-Type: application/json" \
  -d '{"challenge": "test"}'

# Expected response: returns challenge value

⚙️ Configuration

Required Configuration
Config Environment Variable Description How to Obtain
AppID FEISHU_APP_ID Feishu App ID Feishu Developer Console → App Credentials
AppSecret FEISHU_APP_SECRET Feishu App Secret Feishu Developer Console → App Credentials
VerificationToken FEISHU_VERIFICATION_TOKEN Event Subscription Verification Token Feishu Developer Console → Event Subscription
EncryptKey FEISHU_ENCRYPT_KEY Message Encryption Key Feishu Developer Console → Event Subscription
Optional Configuration
Config Environment Variable Default Description
ServerAddr FEISHU_SERVER_ADDR :8082 Webhook server listen address
MaxMessageLen FEISHU_MAX_MESSAGE_LEN 4096 Maximum message length (bytes)
SystemPrompt - - System prompt (optional)
CommandRateLimit - 10.0 Command rate limit (requests/second)
CommandRateBurst - 20 Command burst capacity

🔧 Feishu Developer Console Setup

Step 1: Create Enterprise Self-Built App
  1. Login to Feishu Open Platform
  2. Go to "Enterprise Self-Built Apps" → "Create App"
  3. Fill in app name, icon, description
  4. Record App ID and App Secret
Step 2: Configure Permissions

Add the following permissions on "Permissions" page:

Permission Name Permission ID Purpose
Send Messages im:message Send messages to users/groups
Receive Messages im:message.receive_v1 Receive message events
Bot Configuration im:bot Configure bot capabilities
Step 3: Configure Event Subscription
  1. Go to "Event Subscription" page
  2. Enable "Event Subscription" switch
  3. Fill in request URL: https://your-domain.com/feishu/events
  4. Copy Verification Token and Encrypt Key
  5. Subscribe to the following events:
    • im.message.receive_v1 - Receive messages
    • im.message.read_v1 - Message read (optional)
Step 4: Configure Bot Commands
  1. Go to "Bot" → "Command Configuration"
  2. Add the following commands:
Command Description Permission
/reset Reset session context All members
/dc Disconnect current connection All members
Step 5: Publish App
  1. Go to "Version Management & Release"
  2. Create new version
  3. Submit for review (if required)
  4. Enable app

🎯 Core Features

1. CardBuilder - Card Builder

Provides type-safe Feishu interactive card building capabilities:

import "github.com/hrygo/hotplex/chatapps/feishu"

builder := feishu.NewCardBuilder()

// Build thinking card
thinkingCard := builder.BuildThinkingCard("Analyzing your question...")

// Build tool use card
toolCard := builder.BuildToolUseCard("search", "Searching for relevant information")

// Build permission request card
permCard := builder.BuildPermissionCard("Needs access to your calendar")

// Build answer card
answerCard := builder.BuildAnswerCard("This is the AI's response")

// Build error card
errorCard := builder.BuildErrorCard("Error occurred: Network connection failed")

// Build session stats card
statsCard := builder.BuildSessionStatsCard(
    feishu.SessionStats{
        TotalMessages: 100,
        TokenUsage:    5000,
        Duration:      "10m",
    },
)
2. InteractiveHandler - Interaction Handler

Handles Feishu card callback events:

// Automatically registered to adapter
adapter, _ := feishu.NewAdapter(config, logger)

// Internal processing logic:
// 1. URL verification (Feishu callback verification)
// 2. Button click callback
// 3. Form submission callback
// 4. Permission authorization callback

Supported Interaction Types:

Type Event Handler
URL Verification url_verification handleURLVerification
Button Callback interactive handleButtonCallback
Permission Authorization interactive handlePermissionCallback
3. CommandHandler - Command Handler

Handles Feishu bot commands:

// Built-in commands
/reset    - Reset session context
/dc       - Disconnect current connection

// Custom command registration
registry := command.NewRegistry()
registry.Register("status", handleStatusCommand)
adapter.SetCommandRegistry(registry)

Command Handler Features:

  • ✅ Rate limiting (default 10 req/s, burst 20)
  • ✅ Command mapping and routing
  • ✅ Error handling and user prompts
  • ✅ Support for custom command extension
4. EventHandler - Event Processing Layer

Unified Feishu event processing layer (DRY principle):

// Internal architecture:
// EventParser → EventHandler → CommandHandler/InteractiveHandler
//
// 1. EventParser: Parse Feishu raw events
// 2. EventHandler: Route to corresponding handlers
// 3. CommandHandler: Handle command events
// 4. InteractiveHandler: Handle interaction events

📚 API Reference

Adapter Interface
type Adapter interface {
    // Start adapter
    Start(ctx context.Context) error
    
    // Stop adapter
    Stop(ctx context.Context) error
    
    // Set message handler
    SetHandler(handler base.MessageHandler)
    
    // Send message to channel
    SendToChannel(ctx context.Context, chatID, text, threadID string) error
    
    // Send card message
    SendCard(ctx context.Context, chatID string, card *feishu.Card) error
    
    // Update message
    UpdateMessage(ctx context.Context, msgID, text string) error
    
    // Log
    Logger() *slog.Logger
}
Config Structure
type Config struct {
    AppID             string  // Required: App ID
    AppSecret         string  // Required: App Secret
    VerificationToken string  // Required: Verification Token
    EncryptKey        string  // Required: Encryption Key
    ServerAddr        string  // Optional: Server address (default :8082)
    MaxMessageLen     int     // Optional: Max message length (default 4096)
    CommandRateLimit  float64 // Optional: Command rate limit (default 10.0)
    CommandRateBurst  int     // Optional: Command burst capacity (default 20)
}

❌ Error Handling

Error Types
import (
    "errors"
    "github.com/hrygo/hotplex/chatapps/feishu"
)

if err != nil {
    var apiErr *feishu.APIError
    if errors.As(err, &apiErr) {
        // API error, check error code
        log.Printf("API error: code=%d, msg=%s", apiErr.Code, apiErr.Msg)
    } else if errors.Is(err, feishu.ErrInvalidSignature) {
        // Signature verification failed
        log.Println("Invalid signature")
    } else if errors.Is(err, feishu.ErrTokenExpired) {
        // Token expired
        log.Println("Token expired, will refresh")
    }
}
Common Error Codes
Error Code Description Solution
99991663 app access token invalid Check if AppID/AppSecret is correct
99991668 Invalid access token Token expired, wait for auto-refresh (30 min)
99991671 No permission Check app permission configuration, re-authorize
99991664 Invalid verification token Check Verification Token configuration
99991670 Encrypt key error Check Encrypt Key configuration
99991672 Webhook URL invalid Check if Webhook URL is accessible
Error Handling Best Practices
// 1. Authentication error - alert immediately
if errors.Is(err, feishu.ErrAuthFailed) {
    alertAdmin("Feishu auth failed, check credentials")
    return err
}

// 2. Rate limit - wait and retry
if errors.Is(err, feishu.ErrRateLimited) {
    time.Sleep(time.Second)
    return retry()
}

// 3. Network error - exponential backoff retry
if isNetworkError(err) {
    return retryWithBackoff()
}

🧪 Testing Guide

Run Unit Tests
# Run all tests
go test ./chatapps/feishu/... -v

# Run specific test
go test ./chatapps/feishu/... -run TestCardBuilder -v

# Generate coverage report
go test ./chatapps/feishu/... -coverprofile=coverage.out
go tool cover -html=coverage.out

# Run integration tests (requires real environment)
go test ./chatapps/feishu/... -tags=integration -v
Test Coverage
Module Coverage Test File
CardBuilder 85% card_builder_test.go
CommandHandler 72% command_handler_test.go
InteractiveHandler 68% interactive_handler_test.go
EventParser 90% event_parser_test.go
Signature 95% signature_test.go
Total 50.4% -
Pressure Tests
# Run pressure tests (requires real Feishu environment)
export FEISHU_APP_ID=xxx
export FEISHU_APP_SECRET=xxx
export FEISHU_VERIFICATION_TOKEN=xxx
export FEISHU_ENCRYPT_KEY=xxx

go test ./chatapps/feishu/... -tags=pressure -v

Pressure Test Scenarios:

  1. Concurrent Message Send: 100 concurrency, 1 minute duration
  2. Card Interaction Response: Measure P95/P99 latency
  3. Command Rate Limit: Verify rate limiting effect
  4. Long Connection Stability: 30 minutes continuous run

🤔 FAQ

Q1: Not receiving events?

Checklist:

  1. ✅ Feishu developer console event subscription is enabled
  2. ✅ Webhook URL is publicly accessible (test with ngrok)
  3. ✅ Verification Token is configured correctly
  4. ✅ No signature verification errors in server logs

Debug Commands:

# Check endpoint accessibility
curl -X POST https://your-domain.com/feishu/events \
  -H "Content-Type: application/json" \
  -d '{"challenge": "test"}'

# Check server logs
tail -f /var/log/hotplex/feishu.log | grep -i error
Q2: Card callbacks not triggering?

Possible Causes:

  1. Card action configuration error
  2. Callback URL not configured
  3. Signature verification failed

Solution:

// Ensure card action is configured correctly
card := builder.BuildAnswerCard("Content").
    AddButton("Click", "action_value").
    SetCallbackURL("/feishu/interactive")
Q3: Token frequently expires?

Cause: Feishu access_token validity is 2 hours

Solution:

  • ✅ Adapter implements auto-refresh (5 minutes before expiration)
  • ✅ Check logs to confirm refresh logic is working
  • ✅ If still expiring, check if system time is synchronized
Q4: Message send failed?

Troubleshooting Steps:

  1. Check error code (refer to error code table)
  2. Verify user/group ID format
  3. Confirm app permissions are granted
  4. Check if message content violates policies

📖 References

Official Documentation
Project Documentation

📊 Development Status

Phase Status Completion Date
Phase 1: Basic Communication (Adapter + API Client) ✅ Done 2026-03-03
Phase 2: Interactive Enhancement (CardBuilder + Handlers) ✅ Done 2026-03-03
Phase 3: Production Ready (Docs + Pressure Tests) 🔄 In Progress -

Next Steps: Pressure Tests (#142) → Production Deployment Checklist (#143)


📝 Changelog

v0.3.0 (2026-03-03)
  • ✅ Phase 2.3: CommandHandler + Adapter Integration
  • ✅ DRY/SOLID Architecture Refactoring
  • ✅ Test coverage improved to 50.4%
v0.2.0 (2026-03-03)
  • ✅ Phase 2.1: CardBuilder Card Builder
  • ✅ Phase 2.2: InteractiveHandler Interaction Handler
v0.1.0 (2026-03-03)
  • ✅ Phase 1: Feishu Adapter Basic Framework

Maintainer: HotPlex Team
License: MIT

Documentation

Index

Constants

View Source
const (
	CardTemplateBlue   = "blue"
	CardTemplateWathet = "wathet"
	CardTemplateGreen  = "green"
	CardTemplateYellow = "yellow"
	CardTemplateOrange = "orange"
	CardTemplateRed    = "red"
	Purple             = "purple"
	Grey               = "grey"
)

Card colors (templates)

View Source
const (
	TextTypePlainText = "plain_text"
	TextTypeLarkMD    = "lark_md"
)

Text types

View Source
const (
	ElementDiv      = "div"
	ElementNote     = "note"
	ElementAlert    = "alert"
	ElementAction   = "action"
	ElementButton   = "button"
	ElementMarkdown = "markdown"
)

Element types

View Source
const (
	ButtonTypeDefault = "default"
	ButtonTypePrimary = "primary"
	ButtonTypeDanger  = "danger"
)

Button types

Variables

View Source
var (
	ErrConfigMissingAppID             = fmt.Errorf("feishu: app_id is required")
	ErrConfigMissingAppSecret         = fmt.Errorf("feishu: app_secret is required")
	ErrConfigMissingVerificationToken = fmt.Errorf("feishu: verification_token is required")
	ErrConfigMissingEncryptKey        = fmt.Errorf("feishu: encrypt_key is required")

	ErrInvalidSignature     = fmt.Errorf("feishu: invalid signature")
	ErrInvalidChallenge     = fmt.Errorf("feishu: invalid challenge")
	ErrEventParseFailed     = fmt.Errorf("feishu: failed to parse event")
	ErrUnsupportedEventType = fmt.Errorf("feishu: unsupported event type")

	ErrTokenFetchFailed    = fmt.Errorf("feishu: failed to fetch access token")
	ErrMessageSendFailed   = fmt.Errorf("feishu: failed to send message")
	ErrMessageUpdateFailed = fmt.Errorf("feishu: failed to update message")
	ErrMessageDeleteFailed = fmt.Errorf("feishu: failed to delete message")
)

Feishu adapter errors

Functions

func EncodeActionValue

func EncodeActionValue(action, sessionID, messageID string) (string, error)

EncodeActionValue encodes an action value for button callback

Types

type APIError

type APIError struct {
	Code int    `json:"code"`
	Msg  string `json:"msg"`
}

APIError represents a Feishu API error response

func (*APIError) Error

func (e *APIError) Error() string

type ActionValue

type ActionValue struct {
	Action    string `json:"action"`
	SessionID string `json:"session_id"`
	MessageID string `json:"message_id,omitempty"`
}

ActionValue represents the decoded action value from button click

func DecodeActionValue

func DecodeActionValue(value string) (*ActionValue, error)

DecodeActionValue decodes an action value from button callback

type Adapter

type Adapter struct {
	*base.Adapter
	// contains filtered or unexported fields
}

Adapter implements the Feishu (Lark) chat adapter

func NewAdapter

func NewAdapter(config *Config, logger *slog.Logger, opts ...base.AdapterOption) (*Adapter, error)

NewAdapter creates a new Feishu adapter

func (*Adapter) GetAppToken

func (a *Adapter) GetAppToken() (string, error)

GetAppToken gets or caches the app access token

func (*Adapter) GetAppTokenWithContext

func (a *Adapter) GetAppTokenWithContext(ctx context.Context) (string, error)

GetAppTokenWithContext gets or caches the app access token with context

func (*Adapter) SendMessage

func (a *Adapter) SendMessage(ctx context.Context, sessionID string, msg *base.ChatMessage) error

SendMessage sends a message to Feishu

func (*Adapter) SetSender

func (a *Adapter) SetSender(fn func(ctx context.Context, sessionID string, msg *base.ChatMessage) error)

SetSender sets the message sender function

type CardAction

type CardAction struct {
	Type  string      `json:"tag"`
	Text  *Text       `json:"text,omitempty"`
	Value interface{} `json:"value,omitempty"`
	URL   string      `json:"url,omitempty"`
}

CardAction defines an interactive action (button, etc.)

type CardBlock

type CardBlock struct {
	Type     string        `json:"tag"`
	Text     *Text         `json:"text,omitempty"`
	Content  string        `json:"content,omitempty"`
	Elements []CardElement `json:"elements,omitempty"`
	Actions  []CardAction  `json:"actions,omitempty"`
}

CardBlock represents a card block

type CardBuilder

type CardBuilder struct {
	// contains filtered or unexported fields
}

CardBuilder builds Feishu interactive cards for HotPlex events

func NewCardBuilder

func NewCardBuilder(sessionID string) *CardBuilder

NewCardBuilder creates a new card builder

func (*CardBuilder) BuildAnswerCard

func (b *CardBuilder) BuildAnswerCard(content string) (string, error)

BuildAnswerCard builds an answer card with Markdown support Event: answer - Final answer with Markdown

func (*CardBuilder) BuildErrorCard

func (b *CardBuilder) BuildErrorCard(errorMsg string) (string, error)

BuildErrorCard builds an error/warning card Event: error - Red alert box

func (*CardBuilder) BuildPermissionCard

func (b *CardBuilder) BuildPermissionCard(title, description, riskLevel string) (string, error)

BuildPermissionCard builds a permission request card with Allow/Deny buttons Event: permission_request - Interactive card with buttons

func (*CardBuilder) BuildSessionStatsCard

func (b *CardBuilder) BuildSessionStatsCard(duration string, tokenUsage int, otherStats map[string]string) (string, error)

BuildSessionStatsCard builds a session statistics card Event: session_stats - Gray note with stats

func (*CardBuilder) BuildThinkingCard

func (b *CardBuilder) BuildThinkingCard(message string) (string, error)

BuildThinkingCard builds a thinking state card Event: thinking - Shows "🤔 Thinking..." with loading animation

func (*CardBuilder) BuildToolUseCard

func (b *CardBuilder) BuildToolUseCard(toolName, toolInput string) (string, error)

BuildToolUseCard builds a tool execution card Event: tool_use - Shows "🛠️ Executing: Bash"

type CardConfig

type CardConfig struct {
	WideScreenMode bool `json:"wide_screen_mode,omitempty"`
	EnableForward  bool `json:"enable_forward,omitempty"`
}

CardConfig defines card configuration

type CardElement

type CardElement struct {
	Type     string        `json:"tag"`
	Text     *Text         `json:"text,omitempty"`
	Content  string        `json:"content,omitempty"`
	Elements []CardElement `json:"elements,omitempty"`
	Actions  []CardAction  `json:"actions,omitempty"`
}

CardElement represents a card element (markdown, note, alert, etc.)

type CardHeader

type CardHeader struct {
	Template string `json:"template,omitempty"`
	Title    *Text  `json:"title,omitempty"`
}

CardHeader defines card header

type CardTemplate

type CardTemplate struct {
	Config   *CardConfig   `json:"config,omitempty"`
	Header   *CardHeader   `json:"header,omitempty"`
	Elements []CardElement `json:"elements,omitempty"`
	Cards    []CardBlock   `json:"cards,omitempty"`
}

CardTemplate defines a Feishu interactive card template

type Client

type Client struct {
	// contains filtered or unexported fields
}

Client wraps the Feishu Open API

func NewClient

func NewClient(appID, appSecret string, logger *slog.Logger) *Client

NewClient creates a new Feishu API client

func (*Client) GetAppToken

func (c *Client) GetAppToken() (string, int, error)

GetAppToken fetches a new app access token

func (*Client) GetAppTokenWithContext

func (c *Client) GetAppTokenWithContext(ctx context.Context) (string, int, error)

GetAppTokenWithContext fetches a new app access token with context

func (*Client) SendInteractiveMessage

func (c *Client) SendInteractiveMessage(ctx context.Context, token, chatID, cardJSON string) (string, error)

SendInteractiveMessage sends an interactive card message This is a placeholder for Phase 2 implementation

func (*Client) SendMessage

func (c *Client) SendMessage(ctx context.Context, token, chatID, msgType string, content map[string]string) (string, error)

SendMessage sends a message with specified type and content This is the generic message sending method for extensibility

func (*Client) SendTextMessage

func (c *Client) SendTextMessage(ctx context.Context, token, chatID, text string) (string, error)

SendTextMessage sends a text message

type CommandContent

type CommandContent struct {
	Text string `json:"text"`
}

CommandContent represents the command content

type CommandEvent

type CommandEvent struct {
	Header *CommandHeader    `json:"header"`
	Event  *CommandEventData `json:"event"`
	Token  string            `json:"token"`
}

CommandEvent represents a Feishu command event

type CommandEventData

type CommandEventData struct {
	AppID      string          `json:"app_id"`
	TenantKey  string          `json:"tenant_key"`
	OperatorID *UserID         `json:"operator_id"`
	Name       string          `json:"name"`
	Content    *CommandContent `json:"content"`
}

CommandEventData represents the command event data

type CommandHandler

type CommandHandler struct {
	// contains filtered or unexported fields
}

CommandHandler handles Feishu bot commands (/reset, /dc)

func NewCommandHandler

func NewCommandHandler(adapter *Adapter, registry *command.Registry) *CommandHandler

NewCommandHandler creates a new command handler

func (*CommandHandler) HandleCommand

func (h *CommandHandler) HandleCommand(w http.ResponseWriter, r *http.Request)

HandleCommand handles incoming command events

type CommandHeader

type CommandHeader struct {
	EventID    string `json:"event_id"`
	EventType  string `json:"event_type"`
	CreateTime string `json:"create_time"`
	AppID      string `json:"app_id"`
	TenantKey  string `json:"tenant_key"`
}

CommandHeader represents the command event header

type Config

type Config struct {
	// App credentials
	AppID     string `json:"app_id" yaml:"app_id"`
	AppSecret string `json:"app_secret" yaml:"app_secret"`

	// Event subscription
	VerificationToken string `json:"verification_token" yaml:"verification_token"`
	EncryptKey        string `json:"encrypt_key" yaml:"encrypt_key"`

	// Server configuration
	ServerAddr    string `json:"server_addr" yaml:"server_addr"`
	MaxMessageLen int    `json:"max_message_len" yaml:"max_message_len"`

	// System prompt
	SystemPrompt string `json:"system_prompt" yaml:"system_prompt"`
}

Config holds Feishu (Lark) adapter configuration

func (*Config) Validate

func (c *Config) Validate() error

Validate validates the configuration

type Event

type Event struct {
	Schema    string       `json:"schema"`
	Header    *EventHeader `json:"header"`
	Event     *EventData   `json:"event"`
	Token     string       `json:"token"`
	Type      string       `json:"type"`
	Challenge string       `json:"challenge"`
}

Event represents a Feishu webhook event

type EventData

type EventData struct {
	Message *Message `json:"message"`
}

EventData contains the actual event payload

type EventHandler

type EventHandler struct {
	// contains filtered or unexported fields
}

EventHandler provides common event handling logic (DRY principle)

func NewEventHandler

func NewEventHandler(adapter *Adapter) *EventHandler

NewEventHandler creates a new event handler

func (*EventHandler) HandleURLVerification

func (h *EventHandler) HandleURLVerification(w http.ResponseWriter, token string, eventType string) bool

HandleURLVerification handles URL verification for Feishu webhooks

func (*EventHandler) ProcessEvent

func (h *EventHandler) ProcessEvent(w http.ResponseWriter, r *http.Request, parseFunc func([]byte) (interface{}, error), handleFunc func(interface{}) error)

ProcessEvent is a common event processing pipeline

func (*EventHandler) WriteJSONResponse

func (h *EventHandler) WriteJSONResponse(w http.ResponseWriter, data interface{})

WriteJSONResponse writes a JSON response

func (*EventHandler) WriteOKResponse

func (h *EventHandler) WriteOKResponse(w http.ResponseWriter)

WriteOKResponse writes a simple OK response

type EventHeader

type EventHeader struct {
	EventType  string `json:"event_type"`
	EventID    string `json:"event_id"`
	CreateTime int64  `json:"create_time"`
	TenantKey  string `json:"tenant_key"`
	AppID      string `json:"app_id"`
}

EventHeader contains event metadata

type FeishuAPIClient

type FeishuAPIClient interface {
	GetAppTokenWithContext(ctx context.Context) (string, int, error)
	SendMessage(ctx context.Context, token, chatID, msgType string, content map[string]string) (string, error)
	SendTextMessage(ctx context.Context, token, chatID, text string) (string, error)
	SendInteractiveMessage(ctx context.Context, token, chatID, cardJSON string) (string, error)
}

FeishuAPIClient defines the interface for Feishu API operations (SOLID: Dependency Inversion)

type InteractiveAction

type InteractiveAction struct {
	Value string `json:"value"`
	Tag   string `json:"tag"`
}

InteractiveAction represents the button action

type InteractiveEvent

type InteractiveEvent struct {
	Header *InteractiveHeader    `json:"header"`
	Event  *InteractiveEventData `json:"event"`
	Token  string                `json:"token"`
}

InteractiveEvent represents a Feishu interactive event

type InteractiveEventData

type InteractiveEventData struct {
	Message *InteractiveMessage `json:"message"`
	User    *InteractiveUser    `json:"user"`
	Action  *InteractiveAction  `json:"action"`
}

InteractiveEventData represents the event data

type InteractiveHandler

type InteractiveHandler struct {
	// contains filtered or unexported fields
}

InteractiveHandler handles Feishu interactive card callbacks

func NewInteractiveHandler

func NewInteractiveHandler(adapter *Adapter) *InteractiveHandler

NewInteractiveHandler creates a new interactive handler

func (*InteractiveHandler) HandleInteractive

func (h *InteractiveHandler) HandleInteractive(w http.ResponseWriter, r *http.Request)

HandleInteractive handles incoming interactive events

func (*InteractiveHandler) UpdatePermissionCard

func (h *InteractiveHandler) UpdatePermissionCard(ctx context.Context, messageID, chatID, result string) error

UpdatePermissionCard updates a permission card with the result

type InteractiveHeader

type InteractiveHeader struct {
	EventID    string `json:"event_id"`
	EventType  string `json:"event_type"`
	CreateTime string `json:"create_time"`
	Token      string `json:"token"`
	AppID      string `json:"app_id"`
	TenantKey  string `json:"tenant_key"`
}

InteractiveHeader represents the event header

type InteractiveMessage

type InteractiveMessage struct {
	MessageID   string `json:"message_id"`
	ChatID      string `json:"chat_id"`
	MessageType string `json:"message_type"`
}

InteractiveMessage represents the message in the event

type InteractiveUser

type InteractiveUser struct {
	UserID string `json:"user_id"`
}

InteractiveUser represents the user who triggered the event

type Message

type Message struct {
	MessageID   string          `json:"message_id"`
	UnionID     string          `json:"union_id"`
	SenderID    string          `json:"sender_id"`
	ChatID      string          `json:"chat_id"`
	Content     *MessageContent `json:"content"`
	CreateTime  int64           `json:"create_time"`
	TenantKey   string          `json:"tenant_key"`
	MessageType string          `json:"message_type"`
}

Message represents a Feishu message

type MessageContent

type MessageContent struct {
	Type string `json:"type"`
	Text string `json:"text"`
}

MessageContent represents message content

type MessageData

type MessageData struct {
	MessageID string `json:"message_id"`
}

MessageData represents message data in response

type RateLimiter

type RateLimiter struct {
	// contains filtered or unexported fields
}

RateLimiter implements simple rate limiting for commands

func NewRateLimiter

func NewRateLimiter(duration time.Duration) *RateLimiter

NewRateLimiter creates a new rate limiter

func (*RateLimiter) Allow

func (r *RateLimiter) Allow(key string) bool

Allow checks if a request is allowed

type SendMessageRequest

type SendMessageRequest struct {
	ReceiveID string `json:"receive_id"`
	MsgType   string `json:"msg_type"`
	Content   string `json:"content"`
}

SendMessageRequest represents a message send request

type SendMessageResponse

type SendMessageResponse struct {
	Code int          `json:"code"`
	Msg  string       `json:"msg"`
	Data *MessageData `json:"data"`
}

SendMessageResponse represents a message send response

type Text

type Text struct {
	Content string `json:"content,omitempty"`
	Tag     string `json:"tag,omitempty"`
}

Text defines text content with escaping

type TokenResponse

type TokenResponse struct {
	Code           int    `json:"code"`
	Msg            string `json:"msg"`
	AppAccessToken string `json:"app_access_token"`
	Expire         int    `json:"expire"`
}

TokenResponse represents the app access token response

type UserID

type UserID struct {
	UserID string `json:"user_id"`
}

UserID represents a user identifier

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL