Files
Sillyv2/adapters/qq/main.go
T
cdle ad6208bc43 x
2023-06-07 13:39:32 +08:00

308 lines
7.8 KiB
Go

package qq
import (
"encoding/json"
"fmt"
"net/http"
"regexp"
"strconv"
"strings"
"sync"
"time"
"github.com/cdle/sillyplus/core"
"github.com/cdle/sillyplus/core/logs"
"github.com/cdle/sillyplus/core/storage"
"github.com/cdle/sillyplus/utils"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket"
)
var qq = core.MakeBucket("qq")
type Result struct {
Data struct {
MessageID interface{} `json:"message_id"`
} `json:"data"`
Echo string `json:"echo"`
}
type GroupList struct {
Retcode int `json:"retcode"`
Status string `json:"status"`
Data []struct {
GroupID int `json:"group_id"`
GroupName string `json:"group_name"`
// MemberCount int `json:"member_count"`
// MaxMemberCount int `json:"max_member_count"`
// OwnerID int `json:"owner_id"`
// LastJoinTime int `json:"last_join_time"`
// ShutupTimeWhole int `json:"shutup_time_whole"`
// ShutupTimeMe int `json:"shutup_time_me"`
// AdminFlag bool `json:"admin_flag"`
// UpdateTime int `json:"update_time"`
} `json:"data"`
Error interface{} `json:"error"`
Echo string `json:"echo"`
}
type CallApi struct {
Action string `json:"action"`
Echo string `json:"echo"`
Params map[string]interface{} `json:"params"`
}
type sender struct {
Nickname string `json:"nickname"`
}
type Message struct {
GroupID interface{} `json:"group_id"`
Message string `json:"message"`
MessageID interface{} `json:"message_id"`
MessageType string `json:"message_type"`
PostType string `json:"post_type"`
RawMessage string `json:"raw_message"`
SelfID interface{} `json:"self_id"`
Sender sender `json:"sender"`
// SubType string `json:"sub_type"`
Time int `json:"time"`
UserID interface{} `json:"user_id"`
}
type GroupInfo struct {
GroupID string `json:"group_id"`
GroupName string `json:"group_name"`
}
type QQ struct {
conn *websocket.Conn
sync.RWMutex
id int
chans map[string]chan string
}
func (qq *QQ) WriteJSON(ca CallApi) (string, error) {
var err error
cy := make(chan string, 1)
defer close(cy)
func() {
qq.Lock()
defer qq.Unlock()
qq.id++
ca.Echo = fmt.Sprint(qq.id)
qq.chans[ca.Echo] = cy
err = qq.conn.WriteJSON(ca)
}()
if err != nil {
return "", err
}
select {
case v := <-cy:
return v, nil
case <-time.After(time.Second * 60):
}
return "", nil
}
var debug = qq.GetBool("debug", false)
func init() {
storage.Watch(qq, "debug", func(old, new, key string) *storage.Final {
now := ""
if new == "true" {
now = "true"
debug = true
} else {
now = "false"
debug = false
}
return &storage.Final{
Now: now,
}
})
go func() {
core.GinApi(core.GET, "/qq/receive", func(c *gin.Context) {
auth := c.GetHeader("Authorization")
token := qq.GetString("access_token")
if token == "" {
token = qq.GetString("token")
}
if token != "" && !strings.Contains(auth, token) {
core.Logs.Warn("Onebot机器人access_token不正确,小心有人攻击你的傻妞!!!%s ? %s", token, auth)
}
if token == "" {
core.Logs.Warn(`你需要在Onebot机器人配置access_token以及在傻妞配置对应的参数(set qq access_token ?)才能保证连接安全,如果不设置将会造成信息泄露和资产损失!!!`)
}
var upGrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
c.Writer.Write([]byte(err.Error()))
return
}
botID := c.GetHeader("X-Self-ID")
qqcon := &QQ{
conn: ws,
chans: make(map[string]chan string),
}
adapter := &core.Factory{}
adapter.Init("qq", botID)
defer adapter.Destroy()
adapter.SetGroupKick(func(uid string, gid string, reject_add_request bool) bool {
qqcon.WriteJSON(CallApi{
Action: "set_group_kick",
Params: map[string]interface{}{
"group_id": utils.Int(gid),
"user_id": utils.Int(uid),
"reject_add_request": reject_add_request,
},
})
return true
})
adapter.SetGroupBan(func(uid string, gid string, duration int) bool {
qqcon.WriteJSON(CallApi{
Action: "set_group_ban",
Params: map[string]interface{}{
"group_id": utils.Int(gid),
"user_id": utils.Int(uid),
"duration": duration,
},
})
return true
})
adapter.SetGroupUnban(func(uid string, gid string) bool {
qqcon.WriteJSON(CallApi{
Action: "set_group_ban",
Params: map[string]interface{}{
"group_id": utils.Int(gid),
"user_id": utils.Int(uid),
"duration": 1,
},
})
return true
})
adapter.SetReplyHandler(func(msg map[string]string) string {
if debug {
logs.Debug("QQ发送消息:", string(utils.JsonMarshal(msg)))
}
if utils.IsZeroOrEmpty(msg[core.CHAT_ID]) {
params := map[string]interface{}{
"user_id": msg[core.USER_ID],
"message": msg[core.CONETNT],
}
if debug {
logs.Debug("QQ实际私聊:", string(utils.JsonMarshal(params)))
}
id, err := qqcon.WriteJSON(CallApi{
Action: "send_private_msg",
Params: params,
})
if err != nil {
core.Logs.Warn("QQ发送私聊消息错误:", err)
}
return id
} else {
params := map[string]interface{}{
"group_id": msg[core.CHAT_ID],
"user_id": msg[core.USER_ID],
"message": msg[core.CONETNT],
}
if debug {
logs.Debug("QQ实际群聊:", string(utils.JsonMarshal(params)))
}
id, err := qqcon.WriteJSON(CallApi{
Action: "send_group_msg",
Params: params,
})
if err != nil {
core.Logs.Warn("QQ发送群组消息错误:", err)
}
return id
}
})
// qqcon.WriteJSON(CallApi{
// Action: "get_group_list",
// Params: map[string]interface{}{},
// })
go func() {
time.Sleep(time.Second * 3)
qqcon.WriteJSON(CallApi{
Action: "get_group_list",
Params: map[string]interface{}{},
})
}()
for {
_, data, err := ws.ReadMessage()
if err != nil {
ws.Close()
break
}
if debug {
logs.Debug("QQ接收消息:", string(data))
}
{
res := &GroupList{}
json.Unmarshal(data, res)
for _, group := range res.Data {
core.CreateNickName(&core.Nickname{
Group: true,
Value: group.GroupName,
ID: strconv.Itoa(group.GroupID),
Platform: "qq",
BotsID: []string{botID},
})
}
}
{
res := &Result{}
json.Unmarshal(data, res)
if res.Echo != "" {
func() {
qqcon.RLock()
defer qqcon.RUnlock()
if c, ok := qqcon.chans[res.Echo]; ok {
c <- fmt.Sprint(res.Data.MessageID)
}
}()
continue
}
}
msg := &Message{}
json.Unmarshal(data, msg)
// if msg.MessageType != "private"} //&& adapter.IsAdapter(botID) {
// continue
// }
if msg.SelfID == msg.UserID {
continue
}
msg.RawMessage = strings.ReplaceAll(msg.RawMessage, "\\r", "\n")
msg.RawMessage = regexp.MustCompile(`[\n\r]+`).ReplaceAllString(msg.RawMessage, "\n")
content := msg.RawMessage
content = strings.Replace(content, "amp;", "", -1)
content = strings.Replace(content, "&#91;", "[", -1)
content = strings.Replace(content, "&#93;", "]", -1)
content = strings.Trim(content, " ")
_msg := map[string]interface{}{
"user_id": fmt.Sprint(msg.UserID),
"chat_id": core.ChatID(msg.GroupID),
"user_name": msg.Sender.Nickname,
"chat_name": "",
"message_id": fmt.Sprint(msg.MessageID),
"content": content,
}
if debug {
logs.Debug("QQ处理消息:", string(utils.JsonMarshal(_msg)))
}
adapter.Receive(msg)
}
})
}()
}