study_xxqg/push/wx.go

724 lines
16 KiB
Go
Raw Normal View History

2022-08-15 07:07:03 +00:00
package push
import (
2022-07-31 12:33:39 +00:00
"encoding/json"
"fmt"
"net/http"
2022-07-31 12:33:39 +00:00
"strings"
"sync"
"time"
2022-07-31 12:33:39 +00:00
"github.com/johlanse/wechat/mp"
"github.com/johlanse/wechat/mp/request"
log "github.com/sirupsen/logrus"
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"
"github.com/sjkhsl/study_xxqg/utils/update"
)
var (
2022-07-31 12:33:39 +00:00
wx *mp.WeiXin
lastNonce = ""
2022-08-15 07:07:03 +00:00
wxPush func(id, kind, message string)
)
2022-07-31 12:33:39 +00:00
const (
2022-08-15 07:07:03 +00:00
loginBtn = "loginBtn"
2022-07-31 12:33:39 +00:00
StartStudy = "start_study"
2022-08-12 01:32:37 +00:00
getUser = "get_user"
2022-07-31 12:33:39 +00:00
SCORE = "score"
checkUpdate = "check_update"
updateBtn = "updateBtn"
restart = "restart"
getOpenID = "get_open_id"
useRequest = "use_request"
2022-07-31 12:33:39 +00:00
)
type WechatHandler func(id string, msg string)
2022-08-12 01:32:37 +00:00
var (
handlers sync.Map
)
func RegisterHandler(key string, action WechatHandler) {
handlers.Store(key, action)
}
2022-08-15 07:07:03 +00:00
func initWx() {
once := sync.Once{}
once.Do(initWechat)
}
2022-07-31 12:33:39 +00:00
func initWechat() {
config := conf.GetConfig()
2022-07-31 12:33:39 +00:00
if !config.Wechat.Enable {
return
}
2022-08-12 01:32:37 +00:00
if config.Wechat.SuperOpenID == "" {
log.Warningln("你还未配置super_open_id选项")
}
2022-08-12 01:32:37 +00:00
// 注册插件
2022-08-15 07:07:03 +00:00
RegisterHandler(loginBtn, handleLogin)
2022-08-12 01:32:37 +00:00
RegisterHandler(StartStudy, handleStartStudy)
RegisterHandler(getUser, handleGetUser)
RegisterHandler(SCORE, handleScore)
RegisterHandler(checkUpdate, handleCheckUpdate)
RegisterHandler(updateBtn, handleUpdate)
RegisterHandler(restart, handleRestart)
RegisterHandler(getOpenID, handleGetOpenID)
RegisterHandler(useRequest, handleEventUseRequest)
RegisterHandler("发送", handleTextSendMsg)
RegisterHandler("申请使用", handleEventUseRequest)
RegisterHandler("通过", handleTextPass)
RegisterHandler("拒绝", handleTextReject)
RegisterHandler("使用用户列表", handleTextUserList)
// 发送”/remark test即可添加备注信息”
RegisterHandler("/remark", handleTextRemark)
2022-08-12 01:32:37 +00:00
wx = mp.New(config.Wechat.Token, config.Wechat.AppID, config.Wechat.Secret, "123", "123")
err := wx.CreateMenu(mean)
2022-07-31 12:33:39 +00:00
if err != nil {
log.Errorln("设置自定义菜单出现异常" + err.Error())
return
}
list, err := wx.GetKFList()
if err != nil {
log.Errorln("获取客服列表错误" + err.Error())
return
}
if len(list.KF_list) < 1 {
err := wx.AddKFAccount("xxqg@xxqg", "xxqg", utils.StrMd5("123"))
if err != nil {
log.Errorln("添加客服失败" + err.Error())
return
}
} else {
2022-07-31 12:33:39 +00:00
}
wx.HandleFunc("eventCLICK", func(wx *mp.WeiXin, w http.ResponseWriter, r *request.WeiXinRequest, timestamp, nonce string) {
2022-07-31 12:33:39 +00:00
if lastNonce == nonce {
return
}
log.Infoln("收到微信点击事件:" + r.EventKey)
2022-07-31 12:33:39 +00:00
lastNonce = nonce
if !checkPermission(r.FromUserName, r.EventKey) {
log.Infoln("未通过权限检测的用户事件!")
return
}
2022-08-12 01:32:37 +00:00
value, ok := handlers.Load(r.EventKey)
if !ok {
log.Warningln("未注册key为" + r.EventKey + "的调用方法")
return
2022-07-31 12:33:39 +00:00
}
2022-08-12 01:32:37 +00:00
go func() {
defer func() {
err := recover()
if err != nil {
log.Errorln("处理微信事件错误")
log.Errorln(err)
}
}()
(value.(WechatHandler))(r.FromUserName, "")
2022-08-12 01:32:37 +00:00
}()
})
wx.HandleFunc(mp.GenHttpRouteKey(mp.MsgTypeEvent, mp.EventSubscribe), func(wx *mp.WeiXin, w http.ResponseWriter, r *request.WeiXinRequest, timestamp, nonce string) {
sendMsg(r.FromUserName, "你已关注该公众号,请发送申请使用向管理员申请权限吧!")
})
2022-09-03 12:01:51 +00:00
wx.HandleFunc("text", func(wx *mp.WeiXin, w http.ResponseWriter, r *request.WeiXinRequest, timestamp, nonce string) {
log.Infoln(fmt.Sprintf("收到了来自用户%v的文本消息%v", r.FromUserName, r.Content))
key := strings.Split(r.Content, " ")[0]
2022-09-03 12:01:51 +00:00
if !checkPermission(r.FromUserName, key) {
log.Infoln("未通过权限检测的用户事件!")
2022-09-03 12:01:51 +00:00
return
}
value, ok := handlers.Load(key)
if !ok {
log.Warningln("未注册key为" + r.EventKey + "的调用方法")
2022-09-03 12:01:51 +00:00
return
}
go func() {
defer func() {
err := recover()
if err != nil {
log.Errorln("处理微信事件错误")
log.Errorln(err)
2022-09-03 12:01:51 +00:00
}
}()
(value.(WechatHandler))(r.FromUserName, r.Content)
}()
})
}
func checkPermission(id string, key string) bool {
// 这三个不检查权限
keys := []string{"use_request", "get_open_id", "/remark"}
// 通过管理员所有权限
if conf.GetConfig().Wechat.SuperOpenID == id {
return true
}
for _, k := range keys {
if k == key {
return true
}
}
user, err := model.FindWechatUser(id)
if err != nil {
log.Errorln("获取用户出现错误" + err.Error())
sendMsg(id, "请发送申请使用向管理员申请权限!")
return false
}
if user == nil {
log.Errorln("不存在该用户!")
sendMsg(id, "请发送申请使用向管理员申请权限!")
return false
}
if user.Status != 1 {
return false
} else {
return true
}
}
// handleTextUserList
/* @Description: 获取当前使用用户列表的处理器
* @param id
* @param msg
*/
func handleTextUserList(id, msg string) {
if id != conf.GetConfig().Wechat.SuperOpenID {
return
}
users, err := model.QueryWechatUser()
if err != nil {
log.Errorln("获取用户列表出现错误" + err.Error())
return
}
message := ""
for _, user := range users {
message += fmt.Sprintf("open_id:%v\n\n备注%v\n\n状态:%d", user.OpenId, user.Remark, user.Status)
}
sendMsg(id, message)
}
func handleTextReject(id, msg string) {
if id != conf.GetConfig().Wechat.SuperOpenID {
return
}
openID := strings.Split(msg, " ")[1]
user, err := model.FindWechatUser(openID)
if err != nil {
log.Errorln("查询wechat用户出现错误" + err.Error())
return
}
user.Status = -1
err = model.UpdateWechatUser(user)
if err != nil {
log.Errorln("更新用户信息出现错误" + err.Error())
return
}
sendMsg(user.OpenId, "管理员已拒绝了你的使用申请!")
sendMsg(id, fmt.Sprintf("已拒绝用户(%v)%v使用", user.Remark, user.OpenId))
}
func handleTextPass(id, msg string) {
if id != conf.GetConfig().Wechat.SuperOpenID {
return
}
openID := strings.Split(msg, " ")[1]
user, err := model.FindWechatUser(openID)
if err != nil {
log.Errorln("查询wechat用户出现错误" + err.Error())
return
}
user.Status = 1
err = model.UpdateWechatUser(user)
if err != nil {
log.Errorln("更新用户信息出现错误" + err.Error())
return
}
sendMsg(user.OpenId, "管理员已通过了你的使用申请!")
sendMsg(id, fmt.Sprintf("已允许用户(%v)%v使用", user.Remark, user.OpenId))
}
// handleEventUseRequest
/* @Description: 处理申请使用的点击事件
* @param id
* @param msg
*/
func handleEventUseRequest(id, msg string) {
2022-09-10 10:04:38 +00:00
user, err := model.FindWechatUser(id)
if user.OpenId == "" {
err := model.AddWechatUser(&model.WechatUser{
OpenId: id,
Remark: "",
Status: 0,
LastRequestTime: time.Now().Unix(),
})
if err != nil {
log.Errorln("添加用户出现错误" + err.Error())
return
}
sendMsg(conf.GetConfig().Wechat.SuperOpenID, fmt.Sprintf("用户%v申请使用测试号通过则回复信息\n通过 %v\n\n拒绝则回复:\n拒绝 %v", id, id, id))
2022-09-10 10:04:38 +00:00
} else {
if err != nil {
log.Errorln("查询wechat用户错误" + err.Error())
return
}
if user.Status == 1 {
sendMsg(id, "你已拥有使用权!")
return
} else if user.Status == -1 {
sendMsg(id, "你已被拉黑,请联系管理员!")
return
}
if (time.Now().Unix()-user.LastRequestTime)/3600 < 1 {
sendMsg(id, fmt.Sprintf("你已在%v申请过使用权了请一个小时后再申请", time.Unix(user.LastRequestTime, 0).Format("2006-01-02 15:04:05")))
return
}
if user.LastRequestTime == 0 {
user.LastRequestTime = time.Now().Unix()
err := model.UpdateWechatUser(user)
if err != nil {
log.Errorln("更新信息出现错误" + err.Error())
return
2022-09-03 12:01:51 +00:00
}
}
sendMsg(conf.GetConfig().Wechat.SuperOpenID, fmt.Sprintf("用户(%v)%v申请使用测试号通过则回复信息\n通过 %v\n\n拒绝则回复:\n拒绝 %v", user.Remark, id, id, id))
}
}
// handleTextRemark
/* @Description: 添加备注信息
* @param id
* @param msg
*/
func handleTextRemark(id, msg string) {
data := strings.Split(msg, " ")[1]
count := model.WechatUserCount(id)
if count < 1 {
err := model.AddWechatUser(&model.WechatUser{
OpenId: id,
Remark: data,
Status: 0,
LastRequestTime: 0,
})
if err != nil {
log.Errorln("remark出现错误" + err.Error())
return
}
} else {
user, err := model.FindWechatUser(id)
if err != nil {
log.Errorln("查找用户失败" + err.Error())
return
}
user.Remark = data
err = model.UpdateWechatUser(user)
if err != nil {
log.Errorln("remark出现错误" + err.Error())
return
}
}
sendMsg(id, "添加备注信息成功!")
}
// handleTextSendMsg
/* @Description: 自定义发送消息
* @param id
* @param content
*/
func handleTextSendMsg(id string, content string) {
if conf.GetConfig().Wechat.SuperOpenID != id {
return
}
msg := strings.SplitN(content, " ", 3)
if len(msg) < 3 {
return
} else {
if msg[0] == "发送" {
if msg[1] == "all" || msg[1] == "所有" {
sendMsg("all", msg[2])
} else {
sendMsg(msg[1], msg[2])
}
}
}
}
func handleGetOpenID(id string, msg string) {
sendMsg(id, "你的open_id为"+id)
}
//
// handleCheckUpdate
// @Description: 检查更新
// @param id
//
func handleCheckUpdate(id string, msg string) {
about := utils.GetAbout()
sendMsg(id, about)
}
//
// handleUpdate
// @Description: 开始更新
// @param id
//
func handleUpdate(id string, msg string) {
if conf.GetConfig().Wechat.SuperOpenID != id {
sendMsg(id, "请联系管理员处理!")
return
}
update.SelfUpdate("", conf.GetVersion())
sendMsg(id, "检查更新已完成,即将重启程序")
utils.Restart()
}
//
// handleRestart
// @Description: 重启程序
// @param id
//
func handleRestart(id string, msg string) {
if conf.GetConfig().Wechat.SuperOpenID != id {
sendMsg(id, "请联系管理员处理!")
return
}
sendMsg(id, "即将重启程序")
utils.Restart()
}
//
// sendMsg
// @Description: 发送消息
// @param id
// @param message
//
2022-07-31 12:33:39 +00:00
func sendMsg(id, message string) {
2022-09-03 12:01:51 +00:00
if wx == nil {
initWx()
}
2022-09-03 12:01:51 +00:00
if id == "all" {
userList, err := wx.GetUserList("")
if err != nil {
log.Errorln("获取关注列表错误")
return
}
url := ""
color := ""
if strings.Contains(message, "$$$") {
splits := strings.Split(message, "$$$")
message = splits[0]
url = splits[1]
if len(splits) == 3 {
color = splits[2]
}
}
for _, user := range userList.Data.OpenId {
m := map[string]interface{}{
"data": map[string]string{
"value": message,
},
}
data, _ := json.Marshal(m)
_, err = wx.SendTemplateMessage(&mp.TemplateMessage{
ToUser: user,
TemplateId: conf.GetConfig().Wechat.NormalTempID,
URL: url,
TopColor: color,
RawJSONData: data,
})
if err != nil {
log.Errorln("向用户" + user + "推送消息错误")
continue
}
}
}
if id == "" {
id = conf.GetConfig().Wechat.SuperOpenID
}
// 登录消息单独采用模板发送
if strings.Contains(message, "login.xuexi.cn") {
_, err := wx.SendTemplateMessage(&mp.TemplateMessage{
ToUser: id,
TemplateId: conf.GetConfig().Wechat.LoginTempID,
URL: message,
TopColor: "",
RawJSONData: nil,
})
if err != nil {
log.Errorln(err.Error())
return
}
return
}
err := wx.PostText(id, message, "xxqg@xxqg")
2022-07-31 12:33:39 +00:00
if err != nil {
log.Errorln("发送客服消息错误" + err.Error())
log.Warningln("开始尝试使用模板消息发送")
m := map[string]interface{}{
"data": map[string]string{
"value": message,
},
}
data, _ := json.Marshal(m)
_, err = wx.SendTemplateMessage(&mp.TemplateMessage{
ToUser: id,
TemplateId: conf.GetConfig().Wechat.NormalTempID,
URL: "",
TopColor: "",
RawJSONData: data,
})
if err != nil {
return
}
2022-07-31 12:33:39 +00:00
return
}
2022-07-31 12:33:39 +00:00
}
// HandleWechat
/* @Description:处理wechat的请求接口
2022-07-31 12:33:39 +00:00
* @param rep
* @param req
*/
func HandleWechat(rep http.ResponseWriter, req *http.Request) {
2022-08-12 01:46:33 +00:00
if wx == nil {
2022-08-15 07:07:03 +00:00
initWx()
2022-08-12 01:46:33 +00:00
}
wx.ServeHTTP(rep, req)
}
2022-07-31 12:33:39 +00:00
//
// handleLogin
// @Description: 用户登录
// @param id
//
func handleLogin(id string, msg string) {
2022-08-15 07:07:03 +00:00
core := &lib.Core{Push: func(id1 string, kind, message string) {
2022-08-20 04:27:18 +00:00
if kind == "flush" && strings.Contains(message, "login.xuexi.cn") {
2022-07-31 12:33:39 +00:00
_, err := wx.SendTemplateMessage(&mp.TemplateMessage{
ToUser: id,
TemplateId: conf.GetConfig().Wechat.LoginTempID,
2022-08-20 04:27:18 +00:00
URL: message,
2022-07-31 12:33:39 +00:00
TopColor: "",
RawJSONData: nil,
})
if err != nil {
log.Errorln(err.Error())
return
}
}
}}
_, err := core.L(0, id)
if err != nil {
return
}
sendMsg(id, "登录成功")
}
//
// handleStartStudy
// @Description: 开始学习
// @param id
//
func handleStartStudy(id string, msg string) {
2022-07-31 12:33:39 +00:00
users, err := model.QueryByPushID(id)
if err != nil {
return
}
if users == nil {
log.Warningln("还未存在绑定的用户登录")
sendMsg(id, "你还没有已登陆的用户,请点击下方登录按钮登录!")
return
}
2022-08-15 07:07:03 +00:00
core := &lib.Core{ShowBrowser: conf.GetConfig().ShowBrowser, Push: func(id1 string, kind, msg string) {
2022-07-31 12:33:39 +00:00
}}
core.Init()
defer core.Quit()
for i, user := range users {
if state.IsStudy(user.Uid) {
log.Infoln("该用户已经在学习中了,跳过学习")
2022-07-31 12:33:39 +00:00
continue
} else {
state.Add(user.Uid, core)
2022-07-31 12:33:39 +00:00
}
sendMsg(id, fmt.Sprintf("开始学习第%d个用户用户名%v", i+1, user.Nick))
core.LearnArticle(user)
core.LearnVideo(user)
if conf.GetConfig().Model == 2 {
core.RespondDaily(user, "daily")
} else if conf.GetConfig().Model == 3 {
core.RespondDaily(user, "weekly")
core.RespondDaily(user, "special")
}
state.Delete(user.Uid)
2022-07-31 12:33:39 +00:00
score, _ := lib.GetUserScore(user.ToCookies())
sendMsg(id, fmt.Sprintf("第%d个用户%v学习完成学习积分\n%v", i+1, user.Nick, lib.FormatScore(score)))
}
}
func handleGetUser(id string, msg string) {
2022-07-31 12:33:39 +00:00
users, err := model.Query()
if err != nil {
return
}
if users == nil {
log.Warningln("还未存在绑定的用户登录")
sendMsg(id, "你还没有已登陆的用户,请点击下方登录按钮登录!")
return
}
message := ""
config := conf.GetConfig()
2022-07-31 12:33:39 +00:00
for _, user := range users {
if config.Wechat.SuperOpenID == id {
message += fmt.Sprintf("%v ==> %v", user.Nick, time.Unix(user.LoginTime, 0).Format("2006-01-02"))
if user.PushId == id {
message += "(已绑定)\r\n"
}
} else {
if user.PushId == id {
message += fmt.Sprintf("%v ==> %v", user.Nick, time.Unix(user.LoginTime, 0).Format("2006-01-02"))
}
2022-07-31 12:33:39 +00:00
}
2022-07-31 12:33:39 +00:00
}
if message == "" {
log.Warningln("还未存在绑定的用户登录")
sendMsg(id, "你还没有已登陆的用户,请点击下方登录按钮登录!")
return
}
2022-07-31 12:33:39 +00:00
sendMsg(id, message)
}
func handleScore(id string, msg string) {
2022-07-31 12:33:39 +00:00
users, err := model.Query()
if err != nil {
return
}
if users == nil {
log.Warningln("还未存在绑定的用户登录")
sendMsg(id, "你还没有已登陆的用户,请点击下方登录按钮登录!")
return
}
config := conf.GetConfig()
2022-07-31 12:33:39 +00:00
for _, user := range users {
score, _ := lib.GetUserScore(user.ToCookies())
if config.Wechat.SuperOpenID == id {
sendMsg(id, "用户:"+user.Nick+"\n"+lib.FormatScore(score))
} else {
if user.PushId == id {
sendMsg(id, "用户:"+user.Nick+"\n"+lib.FormatScore(score))
}
}
2022-07-31 12:33:39 +00:00
}
}
var (
mean = &mp.Menu{Buttons: []mp.MenuButton{
{
Name: "登录",
Type: "click",
Key: loginBtn,
Url: "",
MediaId: "",
SubButtons: nil,
},
{
Name: "学习管理",
Type: "click",
Key: "study",
Url: "",
MediaId: "",
SubButtons: []mp.MenuButton{
{
Name: "开始学习",
Type: "click",
Key: StartStudy,
},
{
Name: "获取用户",
Type: "click",
Key: getUser,
},
{
Name: "积分查询",
Type: "click",
Key: SCORE,
},
},
},
{
Name: "关于",
Type: "click",
SubButtons: []mp.MenuButton{
{
Name: "检查更新",
Type: "click",
Key: checkUpdate,
},
{
Name: "重启程序",
Type: "click",
Key: restart,
},
{
Name: "更新程序",
Type: "click",
Key: updateBtn,
},
{
Name: "获取open_id",
Type: "click",
Key: getOpenID,
},
{
Name: "申请使用",
Type: "click",
Key: useRequest,
},
},
},
}}
)