支持qq推送与交互
This commit is contained in:
parent
a2b3bc14a9
commit
ffff6a9992
|
@ -49,6 +49,12 @@ type Config struct {
|
||||||
Port int `json:"port" yaml:"port" mapstructure:"port"`
|
Port int `json:"port" yaml:"port" mapstructure:"port"`
|
||||||
CommonUser map[string]string `json:"common_user" yaml:"common_user" mapstructure:"common_user"`
|
CommonUser map[string]string `json:"common_user" yaml:"common_user" mapstructure:"common_user"`
|
||||||
} `json:"web" yaml:"web" mapstructure:"web"`
|
} `json:"web" yaml:"web" mapstructure:"web"`
|
||||||
|
QQ struct {
|
||||||
|
Enable bool `json:"enable" mapstructure:"enable"`
|
||||||
|
PostAddr string `json:"post_addr" mapstructure:"post_addr"`
|
||||||
|
SuperUser int64 `json:"super_user" mapstructure:"super_user"`
|
||||||
|
WhiteList []int64 `json:"white_list" mapstructure:"white_list"`
|
||||||
|
}
|
||||||
Cron string `json:"cron" yaml:"cron" mapstructure:"cron"`
|
Cron string `json:"cron" yaml:"cron" mapstructure:"cron"`
|
||||||
CronRandomWait int `json:"cron_random_wait" yaml:"cron_random_wait" mapstructure:"cron_random_wait"`
|
CronRandomWait int `json:"cron_random_wait" yaml:"cron_random_wait" mapstructure:"cron_random_wait"`
|
||||||
EdgePath string `json:"edge_path" yaml:"edge_path" mapstructure:"edge_path"`
|
EdgePath string `json:"edge_path" yaml:"edge_path" mapstructure:"edge_path"`
|
||||||
|
|
|
@ -81,6 +81,15 @@ wechat:
|
||||||
# 微信管理员的openid,可点击关于按钮获得,配置后请重启程序
|
# 微信管理员的openid,可点击关于按钮获得,配置后请重启程序
|
||||||
super_open_id: ""
|
super_open_id: ""
|
||||||
|
|
||||||
|
# gocq推送配置
|
||||||
|
qq:
|
||||||
|
# 是否启用qq推送
|
||||||
|
enable: false
|
||||||
|
# gocq的监听地址
|
||||||
|
post_addr: "http://127.0.0.1:5700"
|
||||||
|
super_user: 123
|
||||||
|
white_list:
|
||||||
|
- 123
|
||||||
|
|
||||||
# pushDeer推送配置,详情参考psuhDeer官网:http://www.pushdeer.com/official.html
|
# pushDeer推送配置,详情参考psuhDeer官网:http://www.pushdeer.com/official.html
|
||||||
push_deer:
|
push_deer:
|
||||||
|
|
4
main.go
4
main.go
|
@ -149,6 +149,10 @@ func main() {
|
||||||
engine := web.RouterInit()
|
engine := web.RouterInit()
|
||||||
go func() {
|
go func() {
|
||||||
h := http.NewServeMux()
|
h := http.NewServeMux()
|
||||||
|
if config.QQ.Enable {
|
||||||
|
h.Handle("/qq", push.InitQQ())
|
||||||
|
log.Infoln(fmt.Sprintf("已开启qq配置,监听地址: ==》 %v:%v", config.Web.Host, config.Web.Port))
|
||||||
|
}
|
||||||
if config.Web.Enable {
|
if config.Web.Enable {
|
||||||
log.Infoln(fmt.Sprintf("已开启web配置,web监听地址 ==> %v:%v", config.Web.Host, config.Web.Port))
|
log.Infoln(fmt.Sprintf("已开启web配置,web监听地址 ==> %v:%v", config.Web.Host, config.Web.Port))
|
||||||
h.Handle("/", engine)
|
h.Handle("/", engine)
|
||||||
|
|
|
@ -69,7 +69,7 @@ func changeStatus(uid string, status int) {
|
||||||
func QueryFailUser() ([]*User, error) {
|
func QueryFailUser() ([]*User, error) {
|
||||||
var users []*User
|
var users []*User
|
||||||
_ = engine.Ping()
|
_ = engine.Ping()
|
||||||
err := engine.Where("status=", 0).Find(users)
|
err := engine.Where("status=?", 0).Find(&users)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return users, err
|
return users, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,6 +49,13 @@ func GetPush(config conf.Config) func(id string, kind string, message string) {
|
||||||
log.Infoln("已配置pushDeer推送")
|
log.Infoln("已配置pushDeer推送")
|
||||||
pushs = append(pushs, InitPushDeer())
|
pushs = append(pushs, InitPushDeer())
|
||||||
}
|
}
|
||||||
|
if config.QQ.Enable {
|
||||||
|
log.Infoln("已配置qq推送")
|
||||||
|
pushs = append(pushs, func(id, kind, message string) {
|
||||||
|
e := &Event{qq: qq}
|
||||||
|
e.sendPrivateMsg(conf.GetConfig().QQ.SuperUser, message)
|
||||||
|
})
|
||||||
|
}
|
||||||
pushs = append(pushs, func(id, kind, message string) {
|
pushs = append(pushs, func(id, kind, message string) {
|
||||||
log.Debugln(fmt.Sprintf("消息id: %v,消息类型:%v,消息内容:%v", id, kind, message))
|
log.Debugln(fmt.Sprintf("消息id: %v,消息类型:%v,消息内容:%v", id, kind, message))
|
||||||
})
|
})
|
||||||
|
|
|
@ -0,0 +1,333 @@
|
||||||
|
package push
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
|
||||||
|
"github.com/johlanse/study_xxqg/conf"
|
||||||
|
"github.com/johlanse/study_xxqg/lib"
|
||||||
|
"github.com/johlanse/study_xxqg/lib/state"
|
||||||
|
"github.com/johlanse/study_xxqg/model"
|
||||||
|
"github.com/johlanse/study_xxqg/utils"
|
||||||
|
)
|
||||||
|
|
||||||
|
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 {
|
||||||
|
if len(args) < 0 {
|
||||||
|
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)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func qqGetScore(event *Event, args []string) {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
event.Send(lib.FormatScore(score))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response, err := utils.GetClient().R().SetBodyJsonMarshal(map[string]any{
|
||||||
|
"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,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
response, err := utils.GetClient().R().SetBodyJsonMarshal(map[string]any{
|
||||||
|
"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())
|
||||||
|
}
|
Loading…
Reference in New Issue