WeKnora deployment source with the reviewed wiki identity, summary and recovery fixes
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
Anydoc / anydoc parser engine (push) Canceled after 0s
App / Format, vet, test, and build (push) Canceled after 0s
CLI / test (macos-latest / go 1.26) (push) Canceled after 0s
CLI / test (ubuntu-latest / go 1.26) (push) Canceled after 0s
CLI / test (windows-latest / go 1.26) (push) Canceled after 0s
Build and Push Docker Image / build-ui (push) Canceled after 0s
Build and Push Docker Image / build-docreader (push) Canceled after 0s
Build and Push Docker Image / build-sandbox (push) Canceled after 0s
Build and Push Docker Image / build-app (amd64, linux/amd64, ubuntu-latest) (push) Canceled after 0s
Build and Push Docker Image / build-app (arm64, linux/arm64, ubuntu-24.04-arm) (push) Canceled after 0s
DocReader / Python tests and Go client tests (push) Canceled after 0s
Build & Publish (dsh-weknora) / Typecheck, test, pack (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (pinned) (push) Canceled after 0s
Build & Publish (dsh-weknora) / End-to-end inside dsh (latest, advisory) (push) Canceled after 0s
Frontend / Test, type-check, and build (push) Canceled after 0s
Go Lint Cache / warm lint cache (.) (push) Canceled after 0s
Go Lint Cache / warm lint cache (cli) (push) Canceled after 0s
Go Lint Cache / warm lint cache (client) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.10) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.11) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.12) (push) Canceled after 0s
Build & Publish (mcp-server) / Test (Python 3.13) (push) Canceled after 0s
Build and Push Docker Image / merge (push) Canceled after 0s
Build & Publish (dsh-weknora) / Publish to npm (push) Canceled after 0s
Build & Publish (mcp-server) / Build sdist + wheel (push) Canceled after 0s
Build & Publish (mcp-server) / Publish to PyPI (push) Canceled after 0s
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
package qqbot
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"strings"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
|
||||
"github.com/Tencent/WeKnora/internal/im"
|
||||
)
|
||||
|
||||
var _ im.Adapter = (*Adapter)(nil)
|
||||
|
||||
type Adapter struct {
|
||||
client *Client
|
||||
}
|
||||
|
||||
func NewAdapter(client *Client) *Adapter {
|
||||
return &Adapter{client: client}
|
||||
}
|
||||
|
||||
func (a *Adapter) Platform() im.Platform {
|
||||
return im.PlatformQQBot
|
||||
}
|
||||
|
||||
func (a *Adapter) HandleURLVerification(c *gin.Context) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (a *Adapter) VerifyCallback(c *gin.Context) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (a *Adapter) ParseCallback(c *gin.Context) (*im.IncomingMessage, error) {
|
||||
bodyBytes, err := io.ReadAll(c.Request.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("read body: %w", err)
|
||||
}
|
||||
c.Request.Body = io.NopCloser(bytes.NewReader(bodyBytes))
|
||||
|
||||
var payload gatewayPayload
|
||||
if err := json.Unmarshal(bodyBytes, &payload); err != nil {
|
||||
return nil, fmt.Errorf("parse payload: %w", err)
|
||||
}
|
||||
return parseGatewayPayload(&payload)
|
||||
}
|
||||
|
||||
func (a *Adapter) SendReply(ctx context.Context, incoming *im.IncomingMessage, reply *im.ReplyMessage) error {
|
||||
content := strings.TrimSpace(im.FormatIMDisplayContent(reply.Content, im.StreamDisplayFinal))
|
||||
if content == "" {
|
||||
return nil
|
||||
}
|
||||
msgID := ""
|
||||
if incoming.Extra != nil {
|
||||
msgID = incoming.Extra[extraKeyMessageID]
|
||||
}
|
||||
if incoming.ChatType == im.ChatTypeGroup {
|
||||
return a.client.SendGroupMessage(ctx, incoming.ChatID, content, msgID)
|
||||
}
|
||||
return a.client.SendC2CMessage(ctx, incoming.UserID, content, msgID)
|
||||
}
|
||||
|
||||
func parseGatewayPayload(payload *gatewayPayload) (*im.IncomingMessage, error) {
|
||||
if payload == nil || payload.Op != opDispatch {
|
||||
return nil, nil
|
||||
}
|
||||
var event messageEvent
|
||||
if err := json.Unmarshal(payload.D, &event); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
switch payload.T {
|
||||
case eventC2CMessageCreate:
|
||||
return parseC2CMessage(&event), nil
|
||||
case eventGroupAtMessageCreate:
|
||||
return parseGroupMessage(&event), nil
|
||||
default:
|
||||
return nil, nil
|
||||
}
|
||||
}
|
||||
|
||||
func parseC2CMessage(event *messageEvent) *im.IncomingMessage {
|
||||
userID := firstNonEmpty(event.Author.UserOpenID, event.Author.ID)
|
||||
return &im.IncomingMessage{
|
||||
Platform: im.PlatformQQBot,
|
||||
MessageType: im.MessageTypeText,
|
||||
UserID: userID,
|
||||
UserName: event.Author.Username,
|
||||
ChatID: "",
|
||||
ChatType: im.ChatTypeDirect,
|
||||
Content: strings.TrimSpace(event.Content),
|
||||
MessageID: event.ID,
|
||||
Extra: map[string]string{
|
||||
extraKeyMessageID: event.ID,
|
||||
extraKeyChatKind: "c2c",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func parseGroupMessage(event *messageEvent) *im.IncomingMessage {
|
||||
return &im.IncomingMessage{
|
||||
Platform: im.PlatformQQBot,
|
||||
MessageType: im.MessageTypeText,
|
||||
UserID: firstNonEmpty(event.Author.MemberOpenID, event.Author.UserOpenID, event.Author.ID),
|
||||
UserName: event.Author.Username,
|
||||
ChatID: event.GroupOpenID,
|
||||
ChatType: im.ChatTypeGroup,
|
||||
Content: strings.TrimSpace(event.Content),
|
||||
MessageID: event.ID,
|
||||
Extra: map[string]string{
|
||||
extraKeyMessageID: event.ID,
|
||||
extraKeyChatKind: "group",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func firstNonEmpty(values ...string) string {
|
||||
for _, value := range values {
|
||||
if strings.TrimSpace(value) != "" {
|
||||
return strings.TrimSpace(value)
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
Reference in New Issue
Block a user