2022-11-08 12:22:58 +00:00
|
|
|
package push
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/json"
|
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"net/http"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus"
|
|
|
|
"github.com/tidwall/gjson"
|
|
|
|
|
2022-12-14 07:43:39 +00:00
|
|
|
"github.com/sjkhsl/study_xxqg/conf"
|
|
|
|
"github.com/sjkhsl/study_xxqg/lib"
|
|
|
|
"github.com/sjkhsl/study_xxqg/lib/state"
|
|
|
|
"github.com/sjkhsl/study_xxqg/model"
|
|
|
|
"github.com/sjkhsl/study_xxqg/utils"
|
2022-11-08 12:22:58 +00:00
|
|
|
)
|
|
|
|
|
|
|
|
var (
|
|
|
|
qq *QQ
|
|
|
|
)
|
|
|
|
|
|
|
|
type qqPlugin func(event *Event, args []string)
|
|
|
|
|
|
|
|
type QQ struct {
|
|
|
|
postAdd string
|
|
|
|
plugins map[string]qqPlugin
|
|
|
|
}
|
|
|
|
|
|
|
|
func InitQQ() *QQ {
|
|
|
|
config := conf.GetConfig()
|
|
|
|
q := new(QQ)
|
|
|
|
qq = q
|
|
|
|
q.postAdd = config.QQ.PostAddr
|
|
|
|
q.plugins = make(map[string]qqPlugin, 1)
|
|
|
|
q.newPlugin("user", qqGetUser)
|
|
|
|
q.newPlugin("score", qqGetScore)
|
|
|
|
q.newPlugin("fail", qqGetFailUser)
|
|
|
|
q.newPlugin("study", qqStudy)
|
|
|
|
q.newPlugin("login", qqLogin)
|
|
|
|
q.newPlugin("help", qqHelp)
|
|
|
|
return q
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *QQ) newPlugin(text string, plugin qqPlugin) {
|
|
|
|
q.plugins[text] = plugin
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *QQ) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
|
|
|
|
data, _ := io.ReadAll(request.Body)
|
|
|
|
go q.handle(data)
|
|
|
|
writer.WriteHeader(204)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (q *QQ) handle(data []byte) {
|
|
|
|
defer func() {
|
|
|
|
err := recover()
|
|
|
|
if err != nil {
|
|
|
|
log.Errorln("qq消息处理错误")
|
|
|
|
}
|
|
|
|
}()
|
|
|
|
config := conf.GetConfig()
|
|
|
|
e := new(Event)
|
|
|
|
err := json.Unmarshal(data, e)
|
|
|
|
if err != nil {
|
|
|
|
log.Errorln(err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
e.qq = q
|
|
|
|
if e.PostType == "message" {
|
|
|
|
log.Infoln("收到qq消息 ==》 " + e.Message)
|
|
|
|
// 遍历白名单列表
|
|
|
|
for _, id := range config.QQ.WhiteList {
|
|
|
|
if e.GroupId == id || e.UserId == id {
|
|
|
|
for text, plugin := range q.plugins {
|
|
|
|
messages := strings.Split(e.Message, " ")
|
|
|
|
if messages[0] == "."+text {
|
|
|
|
plugin(e, messages[1:])
|
|
|
|
return
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
log.Infoln("消息来源不在白名单中!")
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func qqHelp(event *Event, _ []string) {
|
|
|
|
help := ".user 查询用户\n.fail 查询过期用户\n.study 对一个用户进行学习\n.score 查询用户分数\n.login 登录一个用户"
|
|
|
|
event.Send(help)
|
|
|
|
}
|
|
|
|
|
|
|
|
func qqLogin(event *Event, _ []string) {
|
|
|
|
core := &lib.Core{ShowBrowser: conf.GetConfig().ShowBrowser, Push: func(id string, kind string, message string) {
|
|
|
|
if kind == "flush" {
|
|
|
|
event.Send(message)
|
|
|
|
} else {
|
|
|
|
if conf.GetConfig().LogLevel == "debug" {
|
|
|
|
event.Send(message)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
_, err := core.L(conf.GetConfig().Retry.Times, "")
|
|
|
|
if err != nil {
|
|
|
|
event.Send(err.Error())
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func qqStudy(event *Event, args []string) {
|
|
|
|
users, err := model.Query()
|
|
|
|
if err != nil {
|
|
|
|
event.Send(err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
var user *model.User
|
|
|
|
if len(users) == 1 {
|
|
|
|
user = users[0]
|
|
|
|
} else {
|
2023-08-21 09:33:11 +00:00
|
|
|
if len(args) <= 0 {
|
2022-11-08 12:22:58 +00:00
|
|
|
event.Send("缺少序号参数,请输入 .study 序号")
|
|
|
|
return
|
|
|
|
} else {
|
|
|
|
index, err := strconv.Atoi(args[0])
|
|
|
|
if err != nil {
|
|
|
|
event.Send(err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
user = users[index]
|
|
|
|
}
|
|
|
|
}
|
|
|
|
core := &lib.Core{ShowBrowser: conf.GetConfig().ShowBrowser, Push: func(id string, kind string, message string) {
|
|
|
|
if kind == "flush" {
|
|
|
|
event.Send(message)
|
|
|
|
} else {
|
|
|
|
if conf.GetConfig().LogLevel == "debug" {
|
|
|
|
event.Send(message)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}}
|
|
|
|
core.Init()
|
|
|
|
state.Add(user.Uid, core)
|
|
|
|
defer state.Delete(user.Uid)
|
|
|
|
defer core.Quit()
|
|
|
|
lib.Study(core, user)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-11-09 00:20:20 +00:00
|
|
|
func qqGetScore(event *Event, _ []string) {
|
2022-11-08 12:22:58 +00:00
|
|
|
users, err := model.Query()
|
|
|
|
if err != nil {
|
|
|
|
event.Send(err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
for _, user := range users {
|
|
|
|
score, err := lib.GetUserScore(user.ToCookies())
|
|
|
|
if err != nil {
|
|
|
|
event.Send(err.Error())
|
|
|
|
continue
|
|
|
|
}
|
2022-11-08 13:17:38 +00:00
|
|
|
event.Send(user.Nick + "\n" + lib.FormatScore(score))
|
2022-11-08 12:22:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func qqGetFailUser(event *Event, _ []string) {
|
|
|
|
user, err := model.QueryFailUser()
|
|
|
|
if err != nil {
|
|
|
|
event.Send(err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
result := ""
|
|
|
|
for i, user := range user {
|
|
|
|
result += fmt.Sprintf("%d %v %v\n", i, user.Nick, utils.Stamp2Str(user.LoginTime))
|
|
|
|
}
|
|
|
|
event.Send(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
func qqGetUser(event *Event, _ []string) {
|
|
|
|
users, err := model.Query()
|
|
|
|
if err != nil {
|
|
|
|
event.Send(err.Error())
|
|
|
|
return
|
|
|
|
}
|
|
|
|
result := ""
|
|
|
|
for i, user := range users {
|
|
|
|
result += fmt.Sprintf("%d %v %v\n", i, user.Nick, utils.Stamp2Str(user.LoginTime))
|
|
|
|
}
|
|
|
|
event.Send(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
type (
|
|
|
|
anonymous struct {
|
|
|
|
Id int `json:"id"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
Flag string `json:"flag"`
|
|
|
|
}
|
|
|
|
|
|
|
|
Files struct {
|
|
|
|
Id string `json:"id"`
|
|
|
|
Name string `json:"name"`
|
|
|
|
Size int64 `json:"size"`
|
|
|
|
Busid int64 `json:"busid"`
|
|
|
|
FileUrl string `json:"url"`
|
|
|
|
}
|
|
|
|
|
|
|
|
Status struct {
|
|
|
|
AppEnabled bool `json:"app_enabled"`
|
|
|
|
AppGood bool `json:"app_good"`
|
|
|
|
AppInitialized bool `json:"app_initialized"`
|
|
|
|
Good bool `json:"good"`
|
|
|
|
Online bool `json:"online"`
|
|
|
|
PluginsGood interface{} `json:"plugins_good"`
|
|
|
|
Stat struct {
|
|
|
|
PacketReceived int `json:"packet_received"`
|
|
|
|
PacketSent int `json:"packet_sent"`
|
|
|
|
PacketLost int `json:"packet_lost"`
|
|
|
|
MessageReceived int `json:"message_received"`
|
|
|
|
MessageSent int `json:"message_sent"`
|
|
|
|
DisconnectTimes int `json:"disconnect_times"`
|
|
|
|
LostTimes int `json:"lost_times"`
|
|
|
|
LastMessageTime int `json:"last_message_time"`
|
|
|
|
} `json:"stat"`
|
|
|
|
}
|
|
|
|
|
|
|
|
MessageIds struct {
|
|
|
|
MessageID int32 `json:"message_id"`
|
|
|
|
}
|
|
|
|
|
|
|
|
Senders struct {
|
|
|
|
Age int `json:"age"`
|
|
|
|
Area string `json:"area"`
|
|
|
|
Card string `json:"card"`
|
|
|
|
Level string `json:"level"`
|
|
|
|
NickName string `json:"nickname"`
|
|
|
|
Role string `json:"role"`
|
|
|
|
Sex string `json:"sex"`
|
|
|
|
Title string `json:"title"`
|
|
|
|
UserId int `json:"user_id"`
|
|
|
|
}
|
|
|
|
|
|
|
|
// Event
|
|
|
|
/*
|
|
|
|
* 事件
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
Event struct {
|
|
|
|
qq *QQ
|
|
|
|
Anonymous anonymous `json:"anonymous"`
|
|
|
|
Font int `json:"font"`
|
|
|
|
GroupId int64 `json:"group_id"`
|
|
|
|
Message string `json:"message"`
|
|
|
|
MessageType string `json:"message_type"`
|
|
|
|
PostType string `json:"post_type"`
|
|
|
|
RawMessage string `json:"raw_message"`
|
|
|
|
SelfId int64 `json:"self_id"`
|
|
|
|
Sender Senders `json:"sender"`
|
|
|
|
SubType string `json:"sub_type"`
|
|
|
|
UserId int64 `json:"user_id"`
|
|
|
|
Time int `json:"time"`
|
|
|
|
NoticeType string `json:"notice_type"`
|
|
|
|
RequestType string `json:"request_type"`
|
|
|
|
Comment string `json:"comment"`
|
|
|
|
Flag string `json:"flag"`
|
|
|
|
OperatorID int `json:"operator_id"`
|
|
|
|
File Files `json:"file"`
|
|
|
|
Duration int64 `json:"duration"`
|
|
|
|
TargetId int64 `json:"target_id"` // 运气王id
|
|
|
|
HonorType string `json:"honor_type"`
|
|
|
|
MetaEventType string `json:"meta_event_type"`
|
|
|
|
Status Status `json:"status"`
|
|
|
|
Interval int `json:"interval"`
|
|
|
|
CardNew string `json:"card_new"` // 新名片
|
|
|
|
CardOld string `json:"card_old"` // 旧名片
|
|
|
|
MessageIds
|
|
|
|
|
|
|
|
GuildID int64 `json:"guild_id"`
|
|
|
|
ChannelID int64 `json:"channel_id"`
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
|
|
|
func (e *Event) sendGroupMsg(groupId int64, message any) int {
|
|
|
|
if _, ok := message.(string); ok {
|
|
|
|
message = map[string]any{
|
|
|
|
"type": "text",
|
|
|
|
"data": map[string]any{
|
|
|
|
"text": message,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2022-11-08 12:28:37 +00:00
|
|
|
response, err := utils.GetClient().R().SetHeader("Authorization", conf.GetConfig().QQ.AccessToken).SetBodyJsonMarshal(map[string]any{
|
2022-11-08 12:22:58 +00:00
|
|
|
"action": "send_group_msg",
|
|
|
|
"params": map[string]any{
|
|
|
|
"group_id": groupId,
|
|
|
|
"message": message,
|
|
|
|
},
|
|
|
|
}).Post(e.qq.postAdd)
|
|
|
|
if err != nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return int(gjson.GetBytes(response.Bytes(), "data").Int())
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Event) Send(message any) {
|
|
|
|
if e.MessageType == "group" {
|
|
|
|
e.sendGroupMsg(e.GroupId, message)
|
|
|
|
} else {
|
|
|
|
e.sendPrivateMsg(e.UserId, message)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (e *Event) sendPrivateMsg(userId int64, message any) int {
|
|
|
|
if _, ok := message.(string); ok {
|
|
|
|
message = map[string]any{
|
|
|
|
"type": "text",
|
|
|
|
"data": map[string]any{
|
|
|
|
"text": message,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
2022-11-08 12:28:37 +00:00
|
|
|
response, err := utils.GetClient().R().SetHeader("Authorization", conf.GetConfig().QQ.AccessToken).SetBodyJsonMarshal(map[string]any{
|
2022-11-08 12:22:58 +00:00
|
|
|
"action": "send_private_msg",
|
|
|
|
"params": map[string]any{
|
|
|
|
"user_id": userId,
|
|
|
|
"message": message,
|
|
|
|
},
|
|
|
|
}).Post(e.qq.postAdd)
|
|
|
|
if err != nil {
|
|
|
|
return 0
|
|
|
|
}
|
|
|
|
return int(gjson.GetBytes(response.Bytes(), "data").Int())
|
|
|
|
}
|