fix lint
This commit is contained in:
parent
8d04fb7403
commit
5fcf08ed09
7 changed files with 93 additions and 88 deletions
|
|
@ -35,4 +35,3 @@ func NewOnboardCommand() *cobra.Command {
|
||||||
|
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -116,7 +116,7 @@ func saveWeixinConfig(token, baseURL, proxy string) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func writeMinimalWeixinConfig(cfgPath, token, baseURL, proxy string) error {
|
func writeMinimalWeixinConfig(cfgPath, token, baseURL, proxy string) error {
|
||||||
if err := os.MkdirAll(internal.GetPicoclawHome(), 0755); err != nil {
|
if err := os.MkdirAll(internal.GetPicoclawHome(), 0o755); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -137,7 +137,7 @@ func writeMinimalWeixinConfig(cfgPath, token, baseURL, proxy string) error {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if err := os.WriteFile(cfgPath, data, 0600); err != nil {
|
if err := os.WriteFile(cfgPath, data, 0o600); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
fmt.Printf("✓ Created config at %s\n", cfgPath)
|
fmt.Printf("✓ Created config at %s\n", cfgPath)
|
||||||
|
|
|
||||||
|
|
@ -24,7 +24,7 @@ func NewApiClient(baseURL, token string, proxy string) (*ApiClient, error) {
|
||||||
if baseURL == "" {
|
if baseURL == "" {
|
||||||
baseURL = "https://ilinkai.weixin.qq.com/"
|
baseURL = "https://ilinkai.weixin.qq.com/"
|
||||||
}
|
}
|
||||||
|
|
||||||
client := &http.Client{
|
client := &http.Client{
|
||||||
// Default timeout; will be overridden per context
|
// Default timeout; will be overridden per context
|
||||||
}
|
}
|
||||||
|
|
@ -53,7 +53,7 @@ func randomWechatUIN() string {
|
||||||
return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%d", uint32Val)))
|
return base64.StdEncoding.EncodeToString([]byte(fmt.Sprintf("%d", uint32Val)))
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiClient) post(ctx context.Context, endpoint string, body interface{}, responseObj interface{}) error {
|
func (c *ApiClient) post(ctx context.Context, endpoint string, body any, responseObj any) error {
|
||||||
u, err := url.Parse(c.BaseURL)
|
u, err := url.Parse(c.BaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|
@ -72,16 +72,17 @@ func (c *ApiClient) post(ctx context.Context, endpoint string, body interface{},
|
||||||
|
|
||||||
req.Header.Set("Content-Type", "application/json")
|
req.Header.Set("Content-Type", "application/json")
|
||||||
if endpoint == "ilink/bot/get_bot_qrcode" || endpoint == "ilink/bot/get_qrcode_status" {
|
if endpoint == "ilink/bot/get_bot_qrcode" || endpoint == "ilink/bot/get_qrcode_status" {
|
||||||
// QR routes have different headers sometimes, but let's stick to base ones
|
// QR routes have different headers sometimes, but let's stick to base ones
|
||||||
if endpoint == "ilink/bot/get_qrcode_status" {
|
if endpoint == "ilink/bot/get_qrcode_status" {
|
||||||
req.Header.Set("iLink-App-ClientVersion", "1")
|
// Use direct map assignment to send exact header name the Tencent API expects
|
||||||
}
|
req.Header["iLink-App-ClientVersion"] = []string{"1"}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
req.Header.Set("AuthorizationType", "ilink_bot_token")
|
req.Header["AuthorizationType"] = []string{"ilink_bot_token"}
|
||||||
req.Header.Set("X-WECHAT-UIN", randomWechatUIN())
|
req.Header["X-WECHAT-UIN"] = []string{randomWechatUIN()}
|
||||||
if c.Token != "" {
|
if c.Token != "" {
|
||||||
req.Header.Set("Authorization", "Bearer "+c.Token)
|
req.Header.Set("Authorization", "Bearer "+c.Token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := c.HttpClient.Do(req)
|
resp, err := c.HttpClient.Do(req)
|
||||||
|
|
@ -140,7 +141,7 @@ func (c *ApiClient) SendTyping(ctx context.Context, req SendTypingReq) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiClient) GetQRCode(ctx context.Context, botType string) (*QRCodeResponse, error) {
|
func (c *ApiClient) GetQRCode(ctx context.Context, botType string) (*QRCodeResponse, error) {
|
||||||
// get_bot_qrcode is GET, not POST
|
// get_bot_qrcode is GET, not POST
|
||||||
u, err := url.Parse(c.BaseURL)
|
u, err := url.Parse(c.BaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -149,18 +150,18 @@ func (c *ApiClient) GetQRCode(ctx context.Context, botType string) (*QRCodeRespo
|
||||||
q := u.Query()
|
q := u.Query()
|
||||||
q.Set("bot_type", botType)
|
q.Set("bot_type", botType)
|
||||||
u.RawQuery = q.Encode()
|
u.RawQuery = q.Encode()
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := c.HttpClient.Do(req)
|
resp, err := c.HttpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
respBody, err := io.ReadAll(resp.Body)
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -168,7 +169,7 @@ func (c *ApiClient) GetQRCode(ctx context.Context, botType string) (*QRCodeRespo
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return nil, fmt.Errorf("get_bot_qrcode failed: %d %s", resp.StatusCode, string(respBody))
|
return nil, fmt.Errorf("get_bot_qrcode failed: %d %s", resp.StatusCode, string(respBody))
|
||||||
}
|
}
|
||||||
|
|
||||||
var qrcodeResp QRCodeResponse
|
var qrcodeResp QRCodeResponse
|
||||||
if err := json.Unmarshal(respBody, &qrcodeResp); err != nil {
|
if err := json.Unmarshal(respBody, &qrcodeResp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -177,7 +178,7 @@ func (c *ApiClient) GetQRCode(ctx context.Context, botType string) (*QRCodeRespo
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *ApiClient) GetQRCodeStatus(ctx context.Context, qrcode string) (*StatusResponse, error) {
|
func (c *ApiClient) GetQRCodeStatus(ctx context.Context, qrcode string) (*StatusResponse, error) {
|
||||||
// get_qrcode_status is GET
|
// get_qrcode_status is GET
|
||||||
u, err := url.Parse(c.BaseURL)
|
u, err := url.Parse(c.BaseURL)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -186,19 +187,19 @@ func (c *ApiClient) GetQRCodeStatus(ctx context.Context, qrcode string) (*Status
|
||||||
q := u.Query()
|
q := u.Query()
|
||||||
q.Set("qrcode", qrcode)
|
q.Set("qrcode", qrcode)
|
||||||
u.RawQuery = q.Encode()
|
u.RawQuery = q.Encode()
|
||||||
|
|
||||||
req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
|
req, err := http.NewRequestWithContext(ctx, "GET", u.String(), nil)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Header.Set("iLink-App-ClientVersion", "1")
|
req.Header["iLink-App-ClientVersion"] = []string{"1"}
|
||||||
|
|
||||||
resp, err := c.HttpClient.Do(req)
|
resp, err := c.HttpClient.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
|
|
||||||
respBody, err := io.ReadAll(resp.Body)
|
respBody, err := io.ReadAll(resp.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
@ -206,7 +207,7 @@ func (c *ApiClient) GetQRCodeStatus(ctx context.Context, qrcode string) (*Status
|
||||||
if resp.StatusCode != http.StatusOK {
|
if resp.StatusCode != http.StatusOK {
|
||||||
return nil, fmt.Errorf("get_qrcode_status failed: %d %s", resp.StatusCode, string(respBody))
|
return nil, fmt.Errorf("get_qrcode_status failed: %d %s", resp.StatusCode, string(respBody))
|
||||||
}
|
}
|
||||||
|
|
||||||
var statusResp StatusResponse
|
var statusResp StatusResponse
|
||||||
if err := json.Unmarshal(respBody, &statusResp); err != nil {
|
if err := json.Unmarshal(respBody, &statusResp); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|
|
||||||
|
|
@ -7,10 +7,11 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mdp/qrterminal/v3"
|
"github.com/mdp/qrterminal/v3"
|
||||||
|
|
||||||
"github.com/sipeed/picoclaw/pkg/logger"
|
"github.com/sipeed/picoclaw/pkg/logger"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AuthFlow opts
|
// AuthFlowOpts configures the interactive QR login flow.
|
||||||
type AuthFlowOpts struct {
|
type AuthFlowOpts struct {
|
||||||
BaseURL string
|
BaseURL string
|
||||||
BotType string
|
BotType string
|
||||||
|
|
@ -20,7 +21,10 @@ type AuthFlowOpts struct {
|
||||||
// PerformLoginInteractive starts the Weixin QR login flow and blocks until login is successful or times out.
|
// PerformLoginInteractive starts the Weixin QR login flow and blocks until login is successful or times out.
|
||||||
// It prints a QR code to the terminal for the user to scan.
|
// It prints a QR code to the terminal for the user to scan.
|
||||||
// Returns the BotToken, UserID, AccountID, and BaseUrl on success.
|
// Returns the BotToken, UserID, AccountID, and BaseUrl on success.
|
||||||
func PerformLoginInteractive(ctx context.Context, opts AuthFlowOpts) (botToken, userID, accountID, baseUrl string, err error) {
|
func PerformLoginInteractive(
|
||||||
|
ctx context.Context,
|
||||||
|
opts AuthFlowOpts,
|
||||||
|
) (botToken, userID, accountID, baseUrl string, err error) {
|
||||||
if opts.BaseURL == "" {
|
if opts.BaseURL == "" {
|
||||||
opts.BaseURL = "https://ilinkai.weixin.qq.com/"
|
opts.BaseURL = "https://ilinkai.weixin.qq.com/"
|
||||||
}
|
}
|
||||||
|
|
@ -46,11 +50,11 @@ func PerformLoginInteractive(ctx context.Context, opts AuthFlowOpts) (botToken,
|
||||||
fmt.Println("Please scan the following QR code with WeChat to login:")
|
fmt.Println("Please scan the following QR code with WeChat to login:")
|
||||||
fmt.Println("=======================================================")
|
fmt.Println("=======================================================")
|
||||||
fmt.Println()
|
fmt.Println()
|
||||||
|
|
||||||
// Create Small QR
|
// Create Small QR
|
||||||
qrconfig := qrterminal.Config{
|
qrconfig := qrterminal.Config{
|
||||||
Level: qrterminal.L,
|
Level: qrterminal.L,
|
||||||
Writer: os.Stdout,
|
Writer: os.Stdout,
|
||||||
HalfBlocks: true,
|
HalfBlocks: true,
|
||||||
}
|
}
|
||||||
qrterminal.GenerateWithConfig(qrResp.QrcodeImgContent, qrconfig)
|
qrterminal.GenerateWithConfig(qrResp.QrcodeImgContent, qrconfig)
|
||||||
|
|
@ -89,15 +93,15 @@ func PerformLoginInteractive(ctx context.Context, opts AuthFlowOpts) (botToken,
|
||||||
if statusResp.BotToken == "" || statusResp.IlinkBotID == "" {
|
if statusResp.BotToken == "" || statusResp.IlinkBotID == "" {
|
||||||
return "", "", "", "", fmt.Errorf("login confirmed but missing bot_token or ilink_bot_id")
|
return "", "", "", "", fmt.Errorf("login confirmed but missing bot_token or ilink_bot_id")
|
||||||
}
|
}
|
||||||
logger.InfoCF("weixin", "Login successful", map[string]interface{}{
|
logger.InfoCF("weixin", "Login successful", map[string]any{
|
||||||
"account_id": statusResp.IlinkBotID,
|
"account_id": statusResp.IlinkBotID,
|
||||||
})
|
})
|
||||||
|
|
||||||
return statusResp.BotToken, statusResp.IlinkUserID, statusResp.IlinkBotID, statusResp.Baseurl, nil
|
return statusResp.BotToken, statusResp.IlinkUserID, statusResp.IlinkBotID, statusResp.Baseurl, nil
|
||||||
case "expired":
|
case "expired":
|
||||||
return "", "", "", "", fmt.Errorf("qrcode expired, please try again")
|
return "", "", "", "", fmt.Errorf("qrcode expired, please try again")
|
||||||
default:
|
default:
|
||||||
logger.WarnCF("weixin", "Unknown QR code status", map[string]interface{}{
|
logger.WarnCF("weixin", "Unknown QR code status", map[string]any{
|
||||||
"status": statusResp.Status,
|
"status": statusResp.Status,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -14,18 +14,18 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type GetUploadUrlReq struct {
|
type GetUploadUrlReq struct {
|
||||||
Filekey string `json:"filekey,omitempty"`
|
Filekey string `json:"filekey,omitempty"`
|
||||||
MediaType int `json:"media_type,omitempty"`
|
MediaType int `json:"media_type,omitempty"`
|
||||||
ToUserID string `json:"to_user_id,omitempty"`
|
ToUserID string `json:"to_user_id,omitempty"`
|
||||||
Rawsize int64 `json:"rawsize,omitempty"`
|
Rawsize int64 `json:"rawsize,omitempty"`
|
||||||
RawfileMD5 string `json:"rawfilemd5,omitempty"`
|
RawfileMD5 string `json:"rawfilemd5,omitempty"`
|
||||||
Filesize int64 `json:"filesize,omitempty"`
|
Filesize int64 `json:"filesize,omitempty"`
|
||||||
ThumbRawsize int64 `json:"thumb_rawsize,omitempty"`
|
ThumbRawsize int64 `json:"thumb_rawsize,omitempty"`
|
||||||
ThumbRawfileMD5 string `json:"thumb_rawfilemd5,omitempty"`
|
ThumbRawfileMD5 string `json:"thumb_rawfilemd5,omitempty"`
|
||||||
ThumbFilesize int64 `json:"thumb_filesize,omitempty"`
|
ThumbFilesize int64 `json:"thumb_filesize,omitempty"`
|
||||||
NoNeedThumb bool `json:"no_need_thumb,omitempty"`
|
NoNeedThumb bool `json:"no_need_thumb,omitempty"`
|
||||||
Aeskey string `json:"aeskey,omitempty"` // base64
|
Aeskey string `json:"aeskey,omitempty"` // base64
|
||||||
BaseInfo BaseInfo `json:"base_info,omitempty"`
|
BaseInfo BaseInfo `json:"base_info,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetUploadUrlResp struct {
|
type GetUploadUrlResp struct {
|
||||||
|
|
@ -77,12 +77,12 @@ type ImageItem struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type VoiceItem struct {
|
type VoiceItem struct {
|
||||||
Media *CDNMedia `json:"media,omitempty"`
|
Media *CDNMedia `json:"media,omitempty"`
|
||||||
EncodeType int `json:"encode_type,omitempty"`
|
EncodeType int `json:"encode_type,omitempty"`
|
||||||
BitsPerSample int `json:"bits_per_sample,omitempty"`
|
BitsPerSample int `json:"bits_per_sample,omitempty"`
|
||||||
SampleRate int `json:"sample_rate,omitempty"`
|
SampleRate int `json:"sample_rate,omitempty"`
|
||||||
Playtime int `json:"playtime,omitempty"`
|
Playtime int `json:"playtime,omitempty"`
|
||||||
Text string `json:"text,omitempty"`
|
Text string `json:"text,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileItem struct {
|
type FileItem struct {
|
||||||
|
|
@ -109,34 +109,34 @@ type RefMessage struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type MessageItem struct {
|
type MessageItem struct {
|
||||||
Type int `json:"type,omitempty"`
|
Type int `json:"type,omitempty"`
|
||||||
CreateTimeMs int64 `json:"create_time_ms,omitempty"`
|
CreateTimeMs int64 `json:"create_time_ms,omitempty"`
|
||||||
UpdateTimeMs int64 `json:"update_time_ms,omitempty"`
|
UpdateTimeMs int64 `json:"update_time_ms,omitempty"`
|
||||||
IsCompleted bool `json:"is_completed,omitempty"`
|
IsCompleted bool `json:"is_completed,omitempty"`
|
||||||
MsgID string `json:"msg_id,omitempty"`
|
MsgID string `json:"msg_id,omitempty"`
|
||||||
RefMsg *RefMessage `json:"ref_msg,omitempty"`
|
RefMsg *RefMessage `json:"ref_msg,omitempty"`
|
||||||
TextItem *TextItem `json:"text_item,omitempty"`
|
TextItem *TextItem `json:"text_item,omitempty"`
|
||||||
ImageItem *ImageItem `json:"image_item,omitempty"`
|
ImageItem *ImageItem `json:"image_item,omitempty"`
|
||||||
VoiceItem *VoiceItem `json:"voice_item,omitempty"`
|
VoiceItem *VoiceItem `json:"voice_item,omitempty"`
|
||||||
FileItem *FileItem `json:"file_item,omitempty"`
|
FileItem *FileItem `json:"file_item,omitempty"`
|
||||||
VideoItem *VideoItem `json:"video_item,omitempty"`
|
VideoItem *VideoItem `json:"video_item,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type WeixinMessage struct {
|
type WeixinMessage struct {
|
||||||
Seq int `json:"seq,omitempty"`
|
Seq int `json:"seq,omitempty"`
|
||||||
MessageID int64 `json:"message_id,omitempty"`
|
MessageID int64 `json:"message_id,omitempty"`
|
||||||
FromUserID string `json:"from_user_id,omitempty"`
|
FromUserID string `json:"from_user_id,omitempty"`
|
||||||
ToUserID string `json:"to_user_id,omitempty"`
|
ToUserID string `json:"to_user_id,omitempty"`
|
||||||
ClientID string `json:"client_id,omitempty"`
|
ClientID string `json:"client_id,omitempty"`
|
||||||
CreateTimeMs int64 `json:"create_time_ms,omitempty"`
|
CreateTimeMs int64 `json:"create_time_ms,omitempty"`
|
||||||
UpdateTimeMs int64 `json:"update_time_ms,omitempty"`
|
UpdateTimeMs int64 `json:"update_time_ms,omitempty"`
|
||||||
DeleteTimeMs int64 `json:"delete_time_ms,omitempty"`
|
DeleteTimeMs int64 `json:"delete_time_ms,omitempty"`
|
||||||
SessionID string `json:"session_id,omitempty"`
|
SessionID string `json:"session_id,omitempty"`
|
||||||
GroupID string `json:"group_id,omitempty"`
|
GroupID string `json:"group_id,omitempty"`
|
||||||
MessageType int `json:"message_type,omitempty"`
|
MessageType int `json:"message_type,omitempty"`
|
||||||
MessageState int `json:"message_state,omitempty"`
|
MessageState int `json:"message_state,omitempty"`
|
||||||
ItemList []MessageItem `json:"item_list,omitempty"`
|
ItemList []MessageItem `json:"item_list,omitempty"`
|
||||||
ContextToken string `json:"context_token,omitempty"`
|
ContextToken string `json:"context_token,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type GetUpdatesReq struct {
|
type GetUpdatesReq struct {
|
||||||
|
|
|
||||||
|
|
@ -8,6 +8,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
|
|
||||||
"github.com/sipeed/picoclaw/pkg/bus"
|
"github.com/sipeed/picoclaw/pkg/bus"
|
||||||
"github.com/sipeed/picoclaw/pkg/channels"
|
"github.com/sipeed/picoclaw/pkg/channels"
|
||||||
"github.com/sipeed/picoclaw/pkg/config"
|
"github.com/sipeed/picoclaw/pkg/config"
|
||||||
|
|
@ -18,11 +19,11 @@ import (
|
||||||
// WeixinChannel is the Weixin channel implementation over Tencent iLink REST API.
|
// WeixinChannel is the Weixin channel implementation over Tencent iLink REST API.
|
||||||
type WeixinChannel struct {
|
type WeixinChannel struct {
|
||||||
*channels.BaseChannel
|
*channels.BaseChannel
|
||||||
api *ApiClient
|
api *ApiClient
|
||||||
config config.WeixinConfig
|
config config.WeixinConfig
|
||||||
ctx context.Context
|
ctx context.Context
|
||||||
cancel context.CancelFunc
|
cancel context.CancelFunc
|
||||||
bus *bus.MessageBus
|
bus *bus.MessageBus
|
||||||
// contextTokens stores the last context_token per user (from_user_id → context_token).
|
// contextTokens stores the last context_token per user (from_user_id → context_token).
|
||||||
// This is required by the iLink API to associate replies with the right chat session.
|
// This is required by the iLink API to associate replies with the right chat session.
|
||||||
contextTokens sync.Map
|
contextTokens sync.Map
|
||||||
|
|
@ -76,7 +77,7 @@ func (c *WeixinChannel) Stop(ctx context.Context) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// pollLoop is the long-poll receive loop. It runs until ctx is cancelled.
|
// pollLoop is the long-poll receive loop. It runs until ctx is canceled.
|
||||||
func (c *WeixinChannel) pollLoop(ctx context.Context) {
|
func (c *WeixinChannel) pollLoop(ctx context.Context) {
|
||||||
const (
|
const (
|
||||||
defaultPollTimeoutMs = 35_000
|
defaultPollTimeoutMs = 35_000
|
||||||
|
|
|
||||||
|
|
@ -501,12 +501,12 @@ type WeComAIBotConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type WeixinConfig struct {
|
type WeixinConfig struct {
|
||||||
Enabled bool `json:"enabled" env:"PICOCLAW_CHANNELS_WEIXIN_ENABLED"`
|
Enabled bool `json:"enabled" env:"PICOCLAW_CHANNELS_WEIXIN_ENABLED"`
|
||||||
Token string `json:"token" env:"PICOCLAW_CHANNELS_WEIXIN_TOKEN"`
|
Token string `json:"token" env:"PICOCLAW_CHANNELS_WEIXIN_TOKEN"`
|
||||||
BaseURL string `json:"base_url" env:"PICOCLAW_CHANNELS_WEIXIN_BASE_URL"`
|
BaseURL string `json:"base_url" env:"PICOCLAW_CHANNELS_WEIXIN_BASE_URL"`
|
||||||
Proxy string `json:"proxy" env:"PICOCLAW_CHANNELS_WEIXIN_PROXY"`
|
Proxy string `json:"proxy" env:"PICOCLAW_CHANNELS_WEIXIN_PROXY"`
|
||||||
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_WEIXIN_ALLOW_FROM"`
|
AllowFrom FlexibleStringSlice `json:"allow_from" env:"PICOCLAW_CHANNELS_WEIXIN_ALLOW_FROM"`
|
||||||
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_WEIXIN_REASONING_CHANNEL_ID"`
|
ReasoningChannelID string `json:"reasoning_channel_id" env:"PICOCLAW_CHANNELS_WEIXIN_REASONING_CHANNEL_ID"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type PicoConfig struct {
|
type PicoConfig struct {
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue