chore: update dependencies and refactor webhook handling
- Added new dependencies for SQLite support and improved HTTP client functionality in go.mod and go.sum. - Refactored webhook server implementation to utilize a simplified version, enhancing code maintainability. - Updated API client to leverage a generic request method, streamlining API interactions. - Modified configuration to include access token for webhook server, improving security. - Enhanced event handling and request processing in the API client for better performance.
This commit is contained in:
@@ -1,115 +1,60 @@
|
||||
package milky
|
||||
|
||||
import (
|
||||
"cellbot/pkg/net"
|
||||
"fmt"
|
||||
|
||||
"github.com/bytedance/sonic"
|
||||
"github.com/valyala/fasthttp"
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
// WebhookServer Webhook 服务器
|
||||
// 用于接收协议端 POST 推送的事件
|
||||
// 使用 pkg/net.SimpleWebhookServer 实现,避免重复的 fasthttp 代码
|
||||
type WebhookServer struct {
|
||||
server *fasthttp.Server
|
||||
eventChan chan []byte
|
||||
logger *zap.Logger
|
||||
addr string
|
||||
server *net.SimpleWebhookServer
|
||||
logger *zap.Logger
|
||||
addr string
|
||||
}
|
||||
|
||||
// NewWebhookServer 创建 Webhook 服务器
|
||||
func NewWebhookServer(addr string, logger *zap.Logger) *WebhookServer {
|
||||
func NewWebhookServer(addr string, accessToken string, logger *zap.Logger) *WebhookServer {
|
||||
eventChan := make(chan []byte, 100)
|
||||
|
||||
config := net.SimpleWebhookConfig{
|
||||
Addr: addr,
|
||||
AccessToken: accessToken,
|
||||
EventChannel: eventChan,
|
||||
}
|
||||
|
||||
return &WebhookServer{
|
||||
eventChan: make(chan []byte, 100),
|
||||
logger: logger.Named("webhook-server"),
|
||||
addr: addr,
|
||||
server: net.NewSimpleWebhookServer(config, logger),
|
||||
logger: logger.Named("webhook-server"),
|
||||
addr: addr,
|
||||
}
|
||||
}
|
||||
|
||||
// Start 启动服务器
|
||||
func (s *WebhookServer) Start() error {
|
||||
s.server = &fasthttp.Server{
|
||||
Handler: s.handleRequest,
|
||||
MaxConnsPerIP: 1000,
|
||||
MaxRequestsPerConn: 1000,
|
||||
}
|
||||
|
||||
s.logger.Info("Starting webhook server", zap.String("addr", s.addr))
|
||||
|
||||
go func() {
|
||||
if err := s.server.ListenAndServe(s.addr); err != nil {
|
||||
s.logger.Error("Webhook server error", zap.Error(err))
|
||||
}
|
||||
}()
|
||||
if err := s.server.Start(); err != nil {
|
||||
return fmt.Errorf("failed to start webhook server: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// handleRequest 处理请求
|
||||
func (s *WebhookServer) handleRequest(ctx *fasthttp.RequestCtx) {
|
||||
// 只接受 POST 请求
|
||||
if !ctx.IsPost() {
|
||||
s.logger.Warn("Received non-POST request",
|
||||
zap.String("method", string(ctx.Method())))
|
||||
ctx.Error("Method Not Allowed", fasthttp.StatusMethodNotAllowed)
|
||||
return
|
||||
}
|
||||
|
||||
// 检查 Content-Type
|
||||
contentType := string(ctx.Request.Header.ContentType())
|
||||
if contentType != "application/json" {
|
||||
s.logger.Warn("Invalid content type",
|
||||
zap.String("content_type", contentType))
|
||||
ctx.Error("Unsupported Media Type", fasthttp.StatusUnsupportedMediaType)
|
||||
return
|
||||
}
|
||||
|
||||
// 获取请求体
|
||||
body := ctx.PostBody()
|
||||
if len(body) == 0 {
|
||||
s.logger.Warn("Empty request body")
|
||||
ctx.Error("Bad Request", fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
// 验证 JSON 格式
|
||||
var event Event
|
||||
if err := sonic.Unmarshal(body, &event); err != nil {
|
||||
s.logger.Error("Failed to parse event", zap.Error(err))
|
||||
ctx.Error("Bad Request", fasthttp.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
s.logger.Debug("Received webhook event",
|
||||
zap.String("event_type", event.EventType),
|
||||
zap.Int64("self_id", event.SelfID))
|
||||
|
||||
// 发送到事件通道
|
||||
select {
|
||||
case s.eventChan <- body:
|
||||
default:
|
||||
s.logger.Warn("Event channel full, dropping event")
|
||||
}
|
||||
|
||||
// 返回成功响应
|
||||
ctx.SetContentType("application/json")
|
||||
ctx.SetStatusCode(fasthttp.StatusOK)
|
||||
ctx.SetBodyString(`{"status":"ok"}`)
|
||||
}
|
||||
|
||||
// Events 获取事件通道
|
||||
func (s *WebhookServer) Events() <-chan []byte {
|
||||
return s.eventChan
|
||||
return s.server.Events()
|
||||
}
|
||||
|
||||
// Stop 停止服务器
|
||||
func (s *WebhookServer) Stop() error {
|
||||
if s.server != nil {
|
||||
s.logger.Info("Stopping webhook server")
|
||||
if err := s.server.Shutdown(); err != nil {
|
||||
return fmt.Errorf("failed to shutdown webhook server: %w", err)
|
||||
}
|
||||
s.logger.Info("Stopping webhook server")
|
||||
|
||||
if err := s.server.Stop(); err != nil {
|
||||
return fmt.Errorf("failed to stop webhook server: %w", err)
|
||||
}
|
||||
close(s.eventChan)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user