mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-04 19:17:37 +08:00
687 lines
21 KiB
Go
687 lines
21 KiB
Go
package server
|
|
|
|
import (
|
|
"context"
|
|
"crypto/hmac"
|
|
"crypto/sha1"
|
|
"encoding/hex"
|
|
"net/http"
|
|
"os"
|
|
"strconv"
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/guonaihong/gout/dataflow"
|
|
|
|
"github.com/Mrs4s/go-cqhttp/coolq"
|
|
"github.com/Mrs4s/go-cqhttp/global"
|
|
"github.com/gin-gonic/gin"
|
|
"github.com/guonaihong/gout"
|
|
log "github.com/sirupsen/logrus"
|
|
"github.com/tidwall/gjson"
|
|
)
|
|
|
|
type httpServer struct {
|
|
engine *gin.Engine
|
|
bot *coolq.CQBot
|
|
HTTP *http.Server
|
|
}
|
|
|
|
type httpClient struct {
|
|
bot *coolq.CQBot
|
|
secret string
|
|
addr string
|
|
timeout int32
|
|
}
|
|
|
|
var cqHTTPServer = &httpServer{}
|
|
|
|
// Debug 是否启用Debug模式
|
|
var Debug = false
|
|
|
|
func (s *httpServer) Run(addr, authToken string, bot *coolq.CQBot) {
|
|
gin.SetMode(gin.ReleaseMode)
|
|
s.engine = gin.New()
|
|
s.bot = bot
|
|
s.engine.Use(func(c *gin.Context) {
|
|
if c.Request.Method != "GET" && c.Request.Method != "POST" {
|
|
log.Warnf("已拒绝客户端 %v 的请求: 方法错误", c.Request.RemoteAddr)
|
|
c.Status(404)
|
|
return
|
|
}
|
|
if c.Request.Method == "POST" && strings.Contains(c.Request.Header.Get("Content-Type"), "application/json") {
|
|
d, err := c.GetRawData()
|
|
if err != nil {
|
|
log.Warnf("获取请求 %v 的Body时出现错误: %v", c.Request.RequestURI, err)
|
|
c.Status(400)
|
|
return
|
|
}
|
|
if !gjson.ValidBytes(d) {
|
|
log.Warnf("已拒绝客户端 %v 的请求: 非法Json", c.Request.RemoteAddr)
|
|
c.Status(400)
|
|
return
|
|
}
|
|
c.Set("json_body", gjson.ParseBytes(d))
|
|
}
|
|
c.Next()
|
|
})
|
|
|
|
if authToken != "" {
|
|
s.engine.Use(func(c *gin.Context) {
|
|
if auth := c.Request.Header.Get("Authorization"); auth != "" {
|
|
if strings.SplitN(auth, " ", 2)[1] != authToken {
|
|
c.AbortWithStatus(401)
|
|
return
|
|
}
|
|
} else if c.Query("access_token") != authToken {
|
|
c.AbortWithStatus(401)
|
|
return
|
|
} else {
|
|
c.Next()
|
|
}
|
|
})
|
|
}
|
|
|
|
s.engine.Any("/:action", s.HandleActions)
|
|
|
|
go func() {
|
|
log.Infof("CQ HTTP 服务器已启动: %v", addr)
|
|
s.HTTP = &http.Server{
|
|
Addr: addr,
|
|
Handler: s.engine,
|
|
}
|
|
if err := s.HTTP.ListenAndServe(); err != nil && err != http.ErrServerClosed {
|
|
log.Error(err)
|
|
log.Infof("HTTP 服务启动失败, 请检查端口是否被占用.")
|
|
log.Warnf("将在五秒后退出.")
|
|
time.Sleep(time.Second * 5)
|
|
os.Exit(1)
|
|
}
|
|
}()
|
|
}
|
|
|
|
func newHTTPClient() *httpClient {
|
|
return &httpClient{}
|
|
}
|
|
|
|
func (c *httpClient) Run(addr, secret string, timeout int32, bot *coolq.CQBot) {
|
|
c.bot = bot
|
|
c.secret = secret
|
|
c.addr = addr
|
|
c.timeout = timeout
|
|
if c.timeout < 5 {
|
|
c.timeout = 5
|
|
}
|
|
bot.OnEventPush(c.onBotPushEvent)
|
|
log.Infof("HTTP POST上报器已启动: %v", addr)
|
|
}
|
|
|
|
func (c *httpClient) onBotPushEvent(m coolq.MSG) {
|
|
var res string
|
|
err := gout.POST(c.addr).SetJSON(m).BindBody(&res).SetHeader(func() gout.H {
|
|
h := gout.H{
|
|
"X-Self-ID": c.bot.Client.Uin,
|
|
"User-Agent": "CQHttp/4.15.0",
|
|
}
|
|
if c.secret != "" {
|
|
mac := hmac.New(sha1.New, []byte(c.secret))
|
|
_, err := mac.Write([]byte(m.ToJSON()))
|
|
if err != nil {
|
|
log.Error(err)
|
|
return nil
|
|
}
|
|
h["X-Signature"] = "sha1=" + hex.EncodeToString(mac.Sum(nil))
|
|
}
|
|
return h
|
|
}()).SetTimeout(time.Second * time.Duration(c.timeout)).F().Retry().Attempt(5).
|
|
WaitTime(time.Millisecond * 500).MaxWaitTime(time.Second * 5).
|
|
Func(func(con *dataflow.Context) error {
|
|
if con.Error != nil {
|
|
log.Warnf("上报Event到 HTTP 服务器 %v 时出现错误: %v 将重试.", c.addr, con.Error)
|
|
return con.Error
|
|
}
|
|
return nil
|
|
}).Do()
|
|
if err != nil {
|
|
log.Warnf("上报Event数据 %v 到 %v 失败: %v", m.ToJSON(), c.addr, err)
|
|
return
|
|
}
|
|
log.Debugf("上报Event数据 %v 到 %v", m.ToJSON(), c.addr)
|
|
if gjson.Valid(res) {
|
|
c.bot.CQHandleQuickOperation(gjson.Parse(m.ToJSON()), gjson.Parse(res))
|
|
}
|
|
}
|
|
|
|
func (s *httpServer) HandleActions(c *gin.Context) {
|
|
global.RateLimit(context.Background())
|
|
action := strings.ReplaceAll(c.Param("action"), "_async", "")
|
|
log.Debugf("HTTPServer接收到API调用: %v", action)
|
|
if f, ok := httpAPI[action]; ok {
|
|
f(s, c)
|
|
} else {
|
|
c.JSON(200, coolq.Failed(404))
|
|
}
|
|
}
|
|
|
|
// GetLoginInfo 获取登录号信息
|
|
func GetLoginInfo(s *httpServer, c *gin.Context) {
|
|
c.JSON(200, s.bot.CQGetLoginInfo())
|
|
}
|
|
|
|
// GetFriendList 获取好友列表
|
|
func GetFriendList(s *httpServer, c *gin.Context) {
|
|
c.JSON(200, s.bot.CQGetFriendList())
|
|
}
|
|
|
|
// GetGroupList 获取群列表
|
|
func GetGroupList(s *httpServer, c *gin.Context) {
|
|
nc := getParamOrDefault(c, "no_cache", "false")
|
|
c.JSON(200, s.bot.CQGetGroupList(nc == "true"))
|
|
}
|
|
|
|
// GetGroupInfo 获取群信息
|
|
func GetGroupInfo(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
nc := getParamOrDefault(c, "no_cache", "false")
|
|
c.JSON(200, s.bot.CQGetGroupInfo(gid, nc == "true"))
|
|
}
|
|
|
|
// GetGroupMemberList 获取群成员列表
|
|
func GetGroupMemberList(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
nc := getParamOrDefault(c, "no_cache", "false")
|
|
c.JSON(200, s.bot.CQGetGroupMemberList(gid, nc == "true"))
|
|
}
|
|
|
|
// GetGroupMemberInfo 获取群成员信息
|
|
func GetGroupMemberInfo(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQGetGroupMemberInfo(gid, uid))
|
|
}
|
|
|
|
// GetGroupFileSystemInfo 扩展API-获取群文件系统信息
|
|
func GetGroupFileSystemInfo(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQGetGroupFileSystemInfo(gid))
|
|
}
|
|
|
|
// GetGroupRootFiles 扩展API-获取群根目录文件列表
|
|
func GetGroupRootFiles(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQGetGroupRootFiles(gid))
|
|
}
|
|
|
|
// GetGroupFilesByFolderID 扩展API-获取群子目录文件列表
|
|
func GetGroupFilesByFolderID(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
folderID := getParam(c, "folder_id")
|
|
c.JSON(200, s.bot.CQGetGroupFilesByFolderID(gid, folderID))
|
|
}
|
|
|
|
// GetGroupFileURL 扩展API-获取群文件资源链接
|
|
func GetGroupFileURL(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
fid := getParam(c, "file_id")
|
|
busid, _ := strconv.ParseInt(getParam(c, "busid"), 10, 32)
|
|
c.JSON(200, s.bot.CQGetGroupFileURL(gid, fid, int32(busid)))
|
|
}
|
|
|
|
// UploadGroupFile 扩展API-上传群文件
|
|
func UploadGroupFile(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQUploadGroupFile(gid, getParam(c, "file"), getParam(c, "name"), getParam(c, "folder")))
|
|
}
|
|
|
|
// SendMessage 发送消息
|
|
//
|
|
// https://git.io/JtwTQ
|
|
func SendMessage(s *httpServer, c *gin.Context) {
|
|
if getParam(c, "message_type") == "private" {
|
|
SendPrivateMessage(s, c)
|
|
return
|
|
}
|
|
if getParam(c, "message_type") == "group" {
|
|
SendGroupMessage(s, c)
|
|
return
|
|
}
|
|
if getParam(c, "group_id") != "" {
|
|
SendGroupMessage(s, c)
|
|
return
|
|
}
|
|
if getParam(c, "user_id") != "" {
|
|
SendPrivateMessage(s, c)
|
|
}
|
|
}
|
|
|
|
// SendPrivateMessage 发送私聊消息
|
|
func SendPrivateMessage(s *httpServer, c *gin.Context) {
|
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
|
msg, t := getParamWithType(c, "message")
|
|
autoEscape := global.EnsureBool(getParam(c, "auto_escape"), false)
|
|
if t == gjson.JSON {
|
|
c.JSON(200, s.bot.CQSendPrivateMessage(uid, gjson.Parse(msg), autoEscape))
|
|
return
|
|
}
|
|
c.JSON(200, s.bot.CQSendPrivateMessage(uid, msg, autoEscape))
|
|
}
|
|
|
|
// SendGroupMessage 发送群消息
|
|
func SendGroupMessage(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
msg, t := getParamWithType(c, "message")
|
|
autoEscape := global.EnsureBool(getParam(c, "auto_escape"), false)
|
|
if t == gjson.JSON {
|
|
c.JSON(200, s.bot.CQSendGroupMessage(gid, gjson.Parse(msg), autoEscape))
|
|
return
|
|
}
|
|
c.JSON(200, s.bot.CQSendGroupMessage(gid, msg, autoEscape))
|
|
}
|
|
|
|
// SendGroupForwardMessage 扩展API-发送合并转发(群)
|
|
func SendGroupForwardMessage(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
msg := getParam(c, "messages")
|
|
c.JSON(200, s.bot.CQSendGroupForwardMessage(gid, gjson.Parse(msg)))
|
|
}
|
|
|
|
// GetImage 获取图片(修改自OneBot)
|
|
func GetImage(s *httpServer, c *gin.Context) {
|
|
file := getParam(c, "file")
|
|
c.JSON(200, s.bot.CQGetImage(file))
|
|
}
|
|
|
|
// GetMessage 获取消息
|
|
func GetMessage(s *httpServer, c *gin.Context) {
|
|
mid, _ := strconv.ParseInt(getParam(c, "message_id"), 10, 32)
|
|
c.JSON(200, s.bot.CQGetMessage(int32(mid)))
|
|
}
|
|
|
|
// GetGroupHonorInfo 获取群荣誉信息
|
|
func GetGroupHonorInfo(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQGetGroupHonorInfo(gid, getParam(c, "type")))
|
|
}
|
|
|
|
// ProcessFriendRequest 处理加好友请求
|
|
func ProcessFriendRequest(s *httpServer, c *gin.Context) {
|
|
flag := getParam(c, "flag")
|
|
approve := getParamOrDefault(c, "approve", "true")
|
|
c.JSON(200, s.bot.CQProcessFriendRequest(flag, approve == "true"))
|
|
}
|
|
|
|
// ProcessGroupRequest 处理加群请求/邀请
|
|
func ProcessGroupRequest(s *httpServer, c *gin.Context) {
|
|
flag := getParam(c, "flag")
|
|
subType := getParam(c, "sub_type")
|
|
if subType == "" {
|
|
subType = getParam(c, "type")
|
|
}
|
|
approve := getParamOrDefault(c, "approve", "true")
|
|
c.JSON(200, s.bot.CQProcessGroupRequest(flag, subType, getParam(c, "reason"), approve == "true"))
|
|
}
|
|
|
|
// SetGroupCard 设置群名片(群备注)
|
|
func SetGroupCard(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQSetGroupCard(gid, uid, getParam(c, "card")))
|
|
}
|
|
|
|
// SetSpecialTitle 设置群组专属头衔
|
|
func SetSpecialTitle(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQSetGroupSpecialTitle(gid, uid, getParam(c, "special_title")))
|
|
}
|
|
|
|
// SetGroupKick 群组踢人
|
|
func SetGroupKick(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
|
msg := getParam(c, "message")
|
|
block := getParamOrDefault(c, "reject_add_request", "false")
|
|
c.JSON(200, s.bot.CQSetGroupKick(gid, uid, msg, block == "true"))
|
|
}
|
|
|
|
// SetGroupBan 群组单人禁言
|
|
func SetGroupBan(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
|
i, _ := strconv.ParseInt(getParamOrDefault(c, "duration", "1800"), 10, 64)
|
|
c.JSON(200, s.bot.CQSetGroupBan(gid, uid, uint32(i)))
|
|
}
|
|
|
|
// SetWholeBan 群组全员禁言
|
|
func SetWholeBan(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQSetGroupWholeBan(gid, getParamOrDefault(c, "enable", "true") == "true"))
|
|
}
|
|
|
|
// SetGroupName 设置群名
|
|
func SetGroupName(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQSetGroupName(gid, getParam(c, "group_name")))
|
|
}
|
|
|
|
// SetGroupAdmin 群组设置管理员
|
|
func SetGroupAdmin(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQSetGroupAdmin(gid, uid, getParamOrDefault(c, "enable", "true") == "true"))
|
|
}
|
|
|
|
// SendGroupNotice 扩展API-发送群公告
|
|
func SendGroupNotice(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQSetGroupMemo(gid, getParam(c, "content")))
|
|
}
|
|
|
|
// SetGroupLeave 退出群组
|
|
func SetGroupLeave(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQSetGroupLeave(gid))
|
|
}
|
|
|
|
// SetRestart 重启 OneBot 实现
|
|
//
|
|
// https://git.io/JtwkJ
|
|
func SetRestart(s *httpServer, c *gin.Context) {
|
|
delay, _ := strconv.ParseInt(getParam(c, "delay"), 10, 64)
|
|
c.JSON(200, coolq.MSG{"data": nil, "retcode": 0, "status": "async"})
|
|
go func(delay int64) {
|
|
time.Sleep(time.Duration(delay) * time.Millisecond)
|
|
Restart <- struct{}{}
|
|
}(delay)
|
|
|
|
}
|
|
|
|
// GetForwardMessage 获取合并转发消息
|
|
func GetForwardMessage(s *httpServer, c *gin.Context) {
|
|
resID := getParam(c, "message_id")
|
|
if resID == "" {
|
|
resID = getParam(c, "id")
|
|
}
|
|
c.JSON(200, s.bot.CQGetForwardMessage(resID))
|
|
}
|
|
|
|
// GetGroupSystemMessage 扩展API-获取群文件系统消息
|
|
func GetGroupSystemMessage(s *httpServer, c *gin.Context) {
|
|
c.JSON(200, s.bot.CQGetGroupSystemMessages())
|
|
}
|
|
|
|
// DeleteMessage 撤回消息
|
|
func DeleteMessage(s *httpServer, c *gin.Context) {
|
|
mid, _ := strconv.ParseInt(getParam(c, "message_id"), 10, 32)
|
|
c.JSON(200, s.bot.CQDeleteMessage(int32(mid)))
|
|
}
|
|
|
|
// CanSendImage 检查是否可以发送图片(此处永远返回true)
|
|
func CanSendImage(s *httpServer, c *gin.Context) {
|
|
c.JSON(200, s.bot.CQCanSendImage())
|
|
}
|
|
|
|
// CanSendRecord 检查是否可以发送语音(此处永远返回true)
|
|
func CanSendRecord(s *httpServer, c *gin.Context) {
|
|
c.JSON(200, s.bot.CQCanSendRecord())
|
|
}
|
|
|
|
// GetStatus 获取运行状态
|
|
func GetStatus(s *httpServer, c *gin.Context) {
|
|
c.JSON(200, s.bot.CQGetStatus())
|
|
}
|
|
|
|
// GetVersionInfo 获取版本信息
|
|
func GetVersionInfo(s *httpServer, c *gin.Context) {
|
|
c.JSON(200, s.bot.CQGetVersionInfo())
|
|
}
|
|
|
|
// ReloadEventFilter 扩展API-重载事件过滤器
|
|
func ReloadEventFilter(s *httpServer, c *gin.Context) {
|
|
c.JSON(200, s.bot.CQReloadEventFilter())
|
|
}
|
|
|
|
// GetVipInfo 扩展API-获取VIP信息
|
|
func GetVipInfo(s *httpServer, c *gin.Context) {
|
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQGetVipInfo(uid))
|
|
}
|
|
|
|
// GetStrangerInfo 获取陌生人信息
|
|
func GetStrangerInfo(s *httpServer, c *gin.Context) {
|
|
uid, _ := strconv.ParseInt(getParam(c, "user_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQGetStrangerInfo(uid))
|
|
}
|
|
|
|
// GetGroupAtAllRemain 扩展API-获取群 @全体成员 剩余次数
|
|
func GetGroupAtAllRemain(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQGetAtAllRemain(gid))
|
|
}
|
|
|
|
// SetGroupAnonymousBan 群组匿名用户禁言
|
|
func SetGroupAnonymousBan(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
d, _ := strconv.ParseInt(getParam(c, "duration"), 10, 64)
|
|
flag := getParam(c, "flag")
|
|
if flag == "" {
|
|
flag = getParam(c, "anonymous_flag")
|
|
}
|
|
if flag == "" {
|
|
o := gjson.Parse(getParam(c, "anonymous"))
|
|
flag = o.Get("flag").String()
|
|
}
|
|
c.JSON(200, s.bot.CQSetGroupAnonymousBan(gid, flag, int32(d)))
|
|
}
|
|
|
|
// GetGroupMessageHistory 获取群消息历史记录
|
|
func GetGroupMessageHistory(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
seq, _ := strconv.ParseInt(getParam(c, "message_seq"), 10, 64)
|
|
c.JSON(200, s.bot.CQGetGroupMessageHistory(gid, seq))
|
|
}
|
|
|
|
// GetOnlineClients 扩展API-获取当前账号在线客户端列表
|
|
func GetOnlineClients(s *httpServer, c *gin.Context) {
|
|
c.JSON(200, s.bot.CQGetOnlineClients(getParamOrDefault(c, "no_cache", "false") == "true"))
|
|
}
|
|
|
|
// HandleQuickOperation 隐藏API-对事件执行快速操作
|
|
func HandleQuickOperation(s *httpServer, c *gin.Context) {
|
|
if c.Request.Method != "POST" {
|
|
c.AbortWithStatus(404)
|
|
return
|
|
}
|
|
if i, ok := c.Get("json_body"); ok {
|
|
body := i.(gjson.Result)
|
|
c.JSON(200, s.bot.CQHandleQuickOperation(body.Get("context"), body.Get("operation")))
|
|
}
|
|
}
|
|
|
|
// DownloadFile 扩展API-下载文件到缓存目录
|
|
func DownloadFile(s *httpServer, c *gin.Context) {
|
|
url := getParam(c, "url")
|
|
tc, _ := strconv.Atoi(getParam(c, "thread_count"))
|
|
h, t := getParamWithType(c, "headers")
|
|
headers := map[string]string{}
|
|
if t == gjson.Null || t == gjson.String {
|
|
lines := strings.Split(h, "\r\n")
|
|
for _, sub := range lines {
|
|
str := strings.SplitN(sub, "=", 2)
|
|
if len(str) == 2 {
|
|
headers[str[0]] = str[1]
|
|
}
|
|
}
|
|
}
|
|
if t == gjson.JSON {
|
|
arr := gjson.Parse(h)
|
|
for _, sub := range arr.Array() {
|
|
str := strings.SplitN(sub.String(), "=", 2)
|
|
if len(str) == 2 {
|
|
headers[str[0]] = str[1]
|
|
}
|
|
}
|
|
}
|
|
println(url, tc, h, t)
|
|
c.JSON(200, s.bot.CQDownloadFile(url, headers, tc))
|
|
}
|
|
|
|
// OcrImage 扩展API-图片OCR
|
|
func OcrImage(s *httpServer, c *gin.Context) {
|
|
img := getParam(c, "image")
|
|
c.JSON(200, s.bot.CQOcrImage(img))
|
|
}
|
|
|
|
// GetWordSlices 隐藏API-获取中文分词
|
|
func GetWordSlices(s *httpServer, c *gin.Context) {
|
|
content := getParam(c, "content")
|
|
c.JSON(200, s.bot.CQGetWordSlices(content))
|
|
}
|
|
|
|
// SetGroupPortrait 扩展API-设置群头像
|
|
func SetGroupPortrait(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
file := getParam(c, "file")
|
|
cache := getParam(c, "cache")
|
|
c.JSON(200, s.bot.CQSetGroupPortrait(gid, file, cache))
|
|
}
|
|
|
|
// SetEssenceMsg 扩展API-设置精华消息
|
|
func SetEssenceMsg(s *httpServer, c *gin.Context) {
|
|
mid, _ := strconv.ParseInt(getParam(c, "message_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQSetEssenceMessage(int32(mid)))
|
|
}
|
|
|
|
// DeleteEssenceMsg 扩展API-移出精华消息
|
|
func DeleteEssenceMsg(s *httpServer, c *gin.Context) {
|
|
mid, _ := strconv.ParseInt(getParam(c, "message_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQDeleteEssenceMessage(int32(mid)))
|
|
}
|
|
|
|
// GetEssenceMsgList 扩展API-获取精华消息列表
|
|
func GetEssenceMsgList(s *httpServer, c *gin.Context) {
|
|
gid, _ := strconv.ParseInt(getParam(c, "group_id"), 10, 64)
|
|
c.JSON(200, s.bot.CQGetEssenceMessageList(gid))
|
|
}
|
|
|
|
// CheckURLSafely 扩展API-检查链接安全性
|
|
func CheckURLSafely(s *httpServer, c *gin.Context) {
|
|
c.JSON(200, s.bot.CQCheckURLSafely(getParam(c, "url")))
|
|
}
|
|
|
|
func getParamOrDefault(c *gin.Context, k, def string) string {
|
|
r := getParam(c, k)
|
|
if r != "" {
|
|
return r
|
|
}
|
|
return def
|
|
}
|
|
|
|
func getParam(c *gin.Context, k string) string {
|
|
p, _ := getParamWithType(c, k)
|
|
return p
|
|
}
|
|
|
|
func getParamWithType(c *gin.Context, k string) (string, gjson.Type) {
|
|
if q := c.Query(k); q != "" {
|
|
return q, gjson.Null
|
|
}
|
|
if c.Request.Method == "POST" {
|
|
if h := c.Request.Header.Get("Content-Type"); h != "" {
|
|
if strings.Contains(h, "application/x-www-form-urlencoded") {
|
|
if p, ok := c.GetPostForm(k); ok {
|
|
return p, gjson.Null
|
|
}
|
|
}
|
|
if strings.Contains(h, "application/json") {
|
|
if obj, ok := c.Get("json_body"); ok {
|
|
res := obj.(gjson.Result).Get(k)
|
|
if res.Exists() {
|
|
switch res.Type {
|
|
case gjson.JSON:
|
|
return res.Raw, gjson.JSON
|
|
case gjson.String:
|
|
return res.Str, gjson.String
|
|
case gjson.Number:
|
|
return strconv.FormatInt(res.Int(), 10), gjson.Number // 似乎没有需要接受 float 类型的api
|
|
case gjson.True:
|
|
return "true", gjson.True
|
|
case gjson.False:
|
|
return "false", gjson.False
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return "", gjson.Null
|
|
}
|
|
|
|
var httpAPI = map[string]func(s *httpServer, c *gin.Context){
|
|
"get_login_info": GetLoginInfo,
|
|
"get_friend_list": GetFriendList,
|
|
"get_group_list": GetGroupList,
|
|
"get_group_info": GetGroupInfo,
|
|
"get_group_member_list": GetGroupMemberList,
|
|
"get_group_member_info": GetGroupMemberInfo,
|
|
"get_group_file_system_info": GetGroupFileSystemInfo,
|
|
"get_group_root_files": GetGroupRootFiles,
|
|
"get_group_files_by_folder": GetGroupFilesByFolderID,
|
|
"get_group_file_url": GetGroupFileURL,
|
|
"upload_group_file": UploadGroupFile,
|
|
"get_essence_msg_list": GetEssenceMsgList,
|
|
"send_msg": SendMessage,
|
|
"send_group_msg": SendGroupMessage,
|
|
"send_group_forward_msg": SendGroupForwardMessage,
|
|
"send_private_msg": SendPrivateMessage,
|
|
"delete_msg": DeleteMessage,
|
|
"delete_essence_msg": DeleteEssenceMsg,
|
|
"set_friend_add_request": ProcessFriendRequest,
|
|
"set_group_add_request": ProcessGroupRequest,
|
|
"set_group_card": SetGroupCard,
|
|
"set_group_special_title": SetSpecialTitle,
|
|
"set_group_kick": SetGroupKick,
|
|
"set_group_ban": SetGroupBan,
|
|
"set_group_whole_ban": SetWholeBan,
|
|
"set_group_name": SetGroupName,
|
|
"set_group_admin": SetGroupAdmin,
|
|
"set_essence_msg": SetEssenceMsg,
|
|
"set_restart": SetRestart,
|
|
"_send_group_notice": SendGroupNotice,
|
|
"set_group_leave": SetGroupLeave,
|
|
"get_image": GetImage,
|
|
"get_forward_msg": GetForwardMessage,
|
|
"get_msg": GetMessage,
|
|
"get_group_system_msg": GetGroupSystemMessage,
|
|
"get_group_honor_info": GetGroupHonorInfo,
|
|
"can_send_image": CanSendImage,
|
|
"can_send_record": CanSendRecord,
|
|
"get_status": GetStatus,
|
|
"get_version_info": GetVersionInfo,
|
|
"_get_vip_info": GetVipInfo,
|
|
"get_stranger_info": GetStrangerInfo,
|
|
"reload_event_filter": ReloadEventFilter,
|
|
"set_group_portrait": SetGroupPortrait,
|
|
"set_group_anonymous_ban": SetGroupAnonymousBan,
|
|
"get_group_msg_history": GetGroupMessageHistory,
|
|
"check_url_safely": CheckURLSafely,
|
|
"download_file": DownloadFile,
|
|
".handle_quick_operation": HandleQuickOperation,
|
|
".ocr_image": OcrImage,
|
|
"ocr_image": OcrImage,
|
|
"get_group_at_all_remain": GetGroupAtAllRemain,
|
|
"get_online_clients": GetOnlineClients,
|
|
".get_word_slices": GetWordSlices,
|
|
}
|
|
|
|
func (s *httpServer) ShutDown() {
|
|
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
|
|
defer cancel()
|
|
if err := s.HTTP.Shutdown(ctx); err != nil {
|
|
log.Fatal("http Server Shutdown:", err)
|
|
}
|
|
<-ctx.Done()
|
|
log.Println("timeout of 5 seconds.")
|
|
log.Println("http Server exiting")
|
|
}
|