mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-04 19:17:37 +08:00
566 lines
17 KiB
Go
566 lines
17 KiB
Go
package server
|
||
|
||
import (
|
||
"bufio"
|
||
"bytes"
|
||
"encoding/base64"
|
||
"encoding/json"
|
||
"fmt"
|
||
"github.com/Mrs4s/MiraiGo/client"
|
||
"github.com/Mrs4s/go-cqhttp/coolq"
|
||
"github.com/Mrs4s/go-cqhttp/global"
|
||
"github.com/gin-gonic/gin"
|
||
log "github.com/sirupsen/logrus"
|
||
"github.com/tidwall/gjson"
|
||
"github.com/yinghau76/go-ascii-art"
|
||
"image"
|
||
"io/ioutil"
|
||
"net/http"
|
||
"os"
|
||
"os/signal"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
var WebInput = make(chan string, 1) //长度1,用于阻塞
|
||
|
||
var Console = make(chan os.Signal, 1)
|
||
|
||
var JsonConfig *global.JsonConfig
|
||
|
||
type webServer struct {
|
||
engine *gin.Engine
|
||
bot *coolq.CQBot
|
||
Cli *client.QQClient
|
||
Conf *global.JsonConfig //old config
|
||
Console *bufio.Reader
|
||
}
|
||
|
||
var WebServer = &webServer{}
|
||
|
||
// admin 子站的 路由映射
|
||
var HttpuriAdmin = map[string]func(s *webServer, c *gin.Context){
|
||
"do_restart": AdminDoRestart, //热重启
|
||
"get_web_write": AdminWebWrite, //获取是否验证码输入
|
||
"do_web_write": AdminDoWebWrite, //web上进行输入操作
|
||
"do_restart_docker": AdminDoRestartDocker, //直接停止(依赖supervisord/docker)重新拉起
|
||
"do_config_base": AdminDoConfigBase, //修改config.json中的基础部分
|
||
"do_config_http": AdminDoConfigHttp, //修改config.json的http部分
|
||
"do_config_ws": AdminDoConfigWs, //修改config.json的正向ws部分
|
||
"do_config_reverse": AdminDoConfigReverse, //修改config.json 中的反向ws部分
|
||
"do_config_json": AdminDoConfigJson, //直接修改 config.json配置
|
||
"get_config_json": AdminGetConfigJson, //拉取 当前的config.json配置
|
||
}
|
||
|
||
func Failed(code int, msg string) coolq.MSG {
|
||
return coolq.MSG{"data": nil, "retcode": code, "status": "failed", "msg": msg}
|
||
}
|
||
|
||
func (s *webServer) Run(addr string, cli *client.QQClient) *coolq.CQBot {
|
||
s.Cli = cli
|
||
s.Conf = GetConf()
|
||
JsonConfig = s.Conf
|
||
gin.SetMode(gin.ReleaseMode)
|
||
s.engine = gin.New()
|
||
|
||
s.engine.Use(AuthMiddleWare())
|
||
|
||
//通用路由
|
||
s.engine.Any("/admin/:action", s.admin)
|
||
|
||
go func() {
|
||
//开启端口监听
|
||
if s.Conf.WebUi.Enabled {
|
||
log.Infof("Admin API 服务器已启动: %v", addr)
|
||
err := s.engine.Run(addr)
|
||
if err != nil {
|
||
log.Error(err)
|
||
log.Infof("请检查端口是否被占用.")
|
||
c := make(chan os.Signal, 1)
|
||
signal.Notify(c, os.Interrupt, os.Kill)
|
||
<-c
|
||
os.Exit(1)
|
||
}
|
||
} else {
|
||
//关闭端口监听
|
||
c := make(chan os.Signal, 1)
|
||
signal.Notify(c, os.Interrupt, os.Kill)
|
||
<-c
|
||
os.Exit(1)
|
||
}
|
||
}()
|
||
s.Dologin()
|
||
s.UpServer()
|
||
b := s.bot //外部引入 bot对象,用于操作bot
|
||
return b
|
||
}
|
||
|
||
func (s *webServer) Dologin() {
|
||
s.Console = bufio.NewReader(os.Stdin)
|
||
readLine := func() (str string) {
|
||
str, _ = s.Console.ReadString('\n')
|
||
return
|
||
}
|
||
conf := GetConf()
|
||
cli := s.Cli
|
||
cli.AllowSlider = true
|
||
rsp, err := cli.Login()
|
||
for {
|
||
global.Check(err)
|
||
var text string
|
||
if !rsp.Success {
|
||
switch rsp.Error {
|
||
case client.SliderNeededError:
|
||
if client.SystemDeviceInfo.Protocol == client.AndroidPhone {
|
||
log.Warnf("警告: Android Phone 强制要求暂不支持的滑条验证码, 请开启设备锁或切换到Watch协议验证通过后再使用.")
|
||
log.Infof("按 Enter 继续....")
|
||
readLine()
|
||
os.Exit(0)
|
||
}
|
||
cli.AllowSlider = false
|
||
cli.Disconnect()
|
||
rsp, err = cli.Login()
|
||
continue
|
||
case client.NeedCaptcha:
|
||
_ = ioutil.WriteFile("captcha.jpg", rsp.CaptchaImage, 0644)
|
||
img, _, _ := image.Decode(bytes.NewReader(rsp.CaptchaImage))
|
||
fmt.Println(asciiart.New("image", img).Art)
|
||
if conf.WebUi.WebInput {
|
||
log.Warnf("请输入验证码 (captcha.jpg): (http://%s:%d/admin/do_web_write 输入)", conf.WebUi.Host, conf.WebUi.WebUiPort)
|
||
text = <-WebInput
|
||
} else {
|
||
log.Warn("请输入验证码 (captcha.jpg): (Enter 提交)")
|
||
text = readLine()
|
||
}
|
||
rsp, err = cli.SubmitCaptcha(strings.ReplaceAll(text, "\n", ""), rsp.CaptchaSign)
|
||
global.DelFile("captcha.jpg")
|
||
continue
|
||
case client.SMSNeededError:
|
||
log.Warnf("账号已开启设备锁, 按下 Enter 向手机 %v 发送短信验证码.", rsp.SMSPhone)
|
||
readLine()
|
||
if !cli.RequestSMS() {
|
||
log.Warnf("发送验证码失败,可能是请求过于频繁.")
|
||
time.Sleep(time.Second * 5)
|
||
os.Exit(0)
|
||
}
|
||
log.Warn("请输入短信验证码: (Enter 提交)")
|
||
text = readLine()
|
||
rsp, err = cli.SubmitSMS(strings.ReplaceAll(strings.ReplaceAll(text, "\n", ""), "\r", ""))
|
||
continue
|
||
case client.SMSOrVerifyNeededError:
|
||
log.Warnf("账号已开启设备锁,请选择验证方式:")
|
||
log.Warnf("1. 向手机 %v 发送短信验证码", rsp.SMSPhone)
|
||
log.Warnf("2. 使用手机QQ扫码验证.")
|
||
log.Warn("请输入(1 - 2): ")
|
||
text = readLine()
|
||
if strings.Contains(text, "1") {
|
||
if !cli.RequestSMS() {
|
||
log.Warnf("发送验证码失败,可能是请求过于频繁.")
|
||
time.Sleep(time.Second * 5)
|
||
os.Exit(0)
|
||
}
|
||
log.Warn("请输入短信验证码: (Enter 提交)")
|
||
text = readLine()
|
||
rsp, err = cli.SubmitSMS(strings.ReplaceAll(strings.ReplaceAll(text, "\n", ""), "\r", ""))
|
||
continue
|
||
}
|
||
log.Warnf("请前往 -> %v <- 验证并重启Bot.", rsp.VerifyUrl)
|
||
log.Infof("按 Enter 继续....")
|
||
readLine()
|
||
os.Exit(0)
|
||
return
|
||
case client.UnsafeDeviceError:
|
||
log.Warnf("账号已开启设备锁,请前往 -> %v <- 验证并重启Bot.", rsp.VerifyUrl)
|
||
if conf.WebUi.WebInput {
|
||
log.Infof(" (http://%s:%d/admin/do_web_write 确认后继续)....", conf.WebUi.Host, conf.WebUi.WebUiPort)
|
||
text = <-WebInput
|
||
} else {
|
||
log.Infof("按 Enter 继续....")
|
||
readLine()
|
||
}
|
||
log.Info(text)
|
||
os.Exit(0)
|
||
return
|
||
case client.OtherLoginError, client.UnknownLoginError:
|
||
msg := rsp.ErrorMessage
|
||
if strings.Contains(msg, "版本") {
|
||
msg = "密码错误或账号被冻结"
|
||
}
|
||
log.Warnf("登录失败: %v", msg)
|
||
log.Infof("按 Enter 继续....")
|
||
readLine()
|
||
os.Exit(0)
|
||
return
|
||
}
|
||
}
|
||
break
|
||
}
|
||
log.Infof("登录成功 欢迎使用: %v", cli.Nickname)
|
||
time.Sleep(time.Second)
|
||
log.Info("开始加载好友列表...")
|
||
global.Check(cli.ReloadFriendList())
|
||
log.Infof("共加载 %v 个好友.", len(cli.FriendList))
|
||
log.Infof("开始加载群列表...")
|
||
global.Check(cli.ReloadGroupList())
|
||
log.Infof("共加载 %v 个群.", len(cli.GroupList))
|
||
s.bot = coolq.NewQQBot(cli, conf)
|
||
if conf.PostMessageFormat != "string" && conf.PostMessageFormat != "array" {
|
||
log.Warnf("post_message_format 配置错误, 将自动使用 string")
|
||
coolq.SetMessageFormat("string")
|
||
} else {
|
||
coolq.SetMessageFormat(conf.PostMessageFormat)
|
||
}
|
||
if conf.RateLimit.Enabled {
|
||
global.InitLimiter(conf.RateLimit.Frequency, conf.RateLimit.BucketSize)
|
||
}
|
||
log.Info("正在加载事件过滤器.")
|
||
global.BootFilter()
|
||
global.InitCodec()
|
||
coolq.IgnoreInvalidCQCode = conf.IgnoreInvalidCQCode
|
||
coolq.ForceFragmented = conf.ForceFragmented
|
||
log.Info("资源初始化完成, 开始处理信息.")
|
||
log.Info("アトリは、高性能ですから!")
|
||
cli.OnDisconnected(func(bot *client.QQClient, e *client.ClientDisconnectedEvent) {
|
||
if conf.ReLogin.Enabled {
|
||
var times uint = 1
|
||
for {
|
||
if cli.Online {
|
||
log.Warn("Bot已登录")
|
||
return
|
||
}
|
||
if times > conf.ReLogin.MaxReloginTimes && conf.ReLogin.MaxReloginTimes != 0 {
|
||
break
|
||
}
|
||
log.Warnf("Bot已离线 (%v),将在 %v 秒后尝试重连. 重连次数:%v",
|
||
e.Message, conf.ReLogin.ReLoginDelay, times)
|
||
times++
|
||
time.Sleep(time.Second * time.Duration(conf.ReLogin.ReLoginDelay))
|
||
rsp, err := cli.Login()
|
||
if err != nil {
|
||
log.Errorf("重连失败: %v", err)
|
||
continue
|
||
}
|
||
if !rsp.Success {
|
||
switch rsp.Error {
|
||
case client.NeedCaptcha:
|
||
log.Fatalf("重连失败: 需要验证码. (验证码处理正在开发中)")
|
||
case client.UnsafeDeviceError:
|
||
log.Fatalf("重连失败: 设备锁")
|
||
default:
|
||
log.Errorf("重连失败: %v", rsp.ErrorMessage)
|
||
cli.Disconnect()
|
||
continue
|
||
}
|
||
}
|
||
log.Info("重连成功")
|
||
return
|
||
}
|
||
log.Fatal("重连失败: 重连次数达到设置的上限值")
|
||
}
|
||
s.bot.Release()
|
||
log.Fatalf("Bot已离线:%v", e.Message)
|
||
})
|
||
}
|
||
|
||
func (s *webServer) admin(c *gin.Context) {
|
||
action := c.Param("action")
|
||
log.Debugf("WebServer接收到cgi调用: %v", action)
|
||
if f, ok := HttpuriAdmin[action]; ok {
|
||
f(s, c)
|
||
} else {
|
||
c.JSON(200, coolq.Failed(404))
|
||
}
|
||
}
|
||
|
||
// 获取当前配置文件信息
|
||
func GetConf() *global.JsonConfig {
|
||
if JsonConfig != nil {
|
||
return JsonConfig
|
||
}
|
||
conf := global.Load("config.json")
|
||
return conf
|
||
}
|
||
|
||
// admin 控制器 登录验证
|
||
func AuthMiddleWare() gin.HandlerFunc {
|
||
return func(c *gin.Context) {
|
||
conf := GetConf()
|
||
//处理跨域问题
|
||
c.Header("Access-Control-Allow-Origin", "*")
|
||
c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token")
|
||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, PATCH, DELETE")
|
||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
|
||
c.Header("Access-Control-Allow-Credentials", "true")
|
||
// 放行所有OPTIONS方法,因为有的模板是要请求两次的
|
||
if c.Request.Method == "OPTIONS" {
|
||
c.AbortWithStatus(http.StatusNoContent)
|
||
}
|
||
// 处理请求
|
||
if c.Request.Method != "GET" && c.Request.Method != "POST" {
|
||
log.Warnf("已拒绝客户端 %v 的请求: 方法错误", c.Request.RemoteAddr)
|
||
c.Status(404)
|
||
c.Abort()
|
||
}
|
||
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)
|
||
c.Abort()
|
||
}
|
||
if !gjson.ValidBytes(d) {
|
||
log.Warnf("已拒绝客户端 %v 的请求: 非法Json", c.Request.RemoteAddr)
|
||
c.Status(400)
|
||
c.Abort()
|
||
}
|
||
c.Set("json_body", gjson.ParseBytes(d))
|
||
}
|
||
authToken := conf.AccessToken
|
||
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()
|
||
}
|
||
}
|
||
}
|
||
|
||
func (s *webServer) DoReLogin() { // TODO: 协议层的 ReLogin
|
||
JsonConfig = nil
|
||
conf := GetConf()
|
||
OldConf := s.Conf
|
||
cli := client.NewClient(conf.Uin, conf.Password)
|
||
log.Info("开始尝试登录并同步消息...")
|
||
log.Infof("使用协议: %v", func() string {
|
||
switch client.SystemDeviceInfo.Protocol {
|
||
case client.AndroidPad:
|
||
return "Android Pad"
|
||
case client.AndroidPhone:
|
||
return "Android Phone"
|
||
case client.AndroidWatch:
|
||
return "Android Watch"
|
||
}
|
||
return "未知"
|
||
}())
|
||
cli.OnLog(func(c *client.QQClient, e *client.LogEvent) {
|
||
switch e.Type {
|
||
case "INFO":
|
||
log.Info("Protocol -> " + e.Message)
|
||
case "ERROR":
|
||
log.Error("Protocol -> " + e.Message)
|
||
case "DEBUG":
|
||
log.Debug("Protocol -> " + e.Message)
|
||
}
|
||
})
|
||
cli.OnServerUpdated(func(bot *client.QQClient, e *client.ServerUpdatedEvent) bool {
|
||
if !conf.UseSSOAddress {
|
||
log.Infof("收到服务器地址更新通知, 根据配置文件已忽略.")
|
||
return false
|
||
}
|
||
log.Infof("收到服务器地址更新通知, 将在下一次重连时应用. ")
|
||
return true
|
||
})
|
||
s.Cli = cli
|
||
s.Dologin()
|
||
//关闭之前的 server
|
||
if OldConf.HttpConfig != nil && OldConf.HttpConfig.Enabled {
|
||
HttpServer.ShutDown()
|
||
}
|
||
//if OldConf.WSConfig != nil && OldConf.WSConfig.Enabled {
|
||
// server.WsShutdown()
|
||
//}
|
||
//s.UpServer()
|
||
s.ReloadServer()
|
||
s.Conf = conf
|
||
}
|
||
|
||
func (s *webServer) UpServer() {
|
||
conf := GetConf()
|
||
if conf.HttpConfig != nil && conf.HttpConfig.Enabled {
|
||
go HttpServer.Run(fmt.Sprintf("%s:%d", conf.HttpConfig.Host, conf.HttpConfig.Port), conf.AccessToken, s.bot)
|
||
for k, v := range conf.HttpConfig.PostUrls {
|
||
NewHttpClient().Run(k, v, conf.HttpConfig.Timeout, s.bot)
|
||
}
|
||
}
|
||
if conf.WSConfig != nil && conf.WSConfig.Enabled {
|
||
go WebsocketServer.Run(fmt.Sprintf("%s:%d", conf.WSConfig.Host, conf.WSConfig.Port), conf.AccessToken, s.bot)
|
||
}
|
||
for _, rc := range conf.ReverseServers {
|
||
go NewWebsocketClient(rc, conf.AccessToken, s.bot).Run()
|
||
}
|
||
}
|
||
|
||
// 暂不支持ws服务的重启
|
||
func (s *webServer) ReloadServer() {
|
||
conf := GetConf()
|
||
if conf.HttpConfig != nil && conf.HttpConfig.Enabled {
|
||
go HttpServer.Run(fmt.Sprintf("%s:%d", conf.HttpConfig.Host, conf.HttpConfig.Port), conf.AccessToken, s.bot)
|
||
for k, v := range conf.HttpConfig.PostUrls {
|
||
NewHttpClient().Run(k, v, conf.HttpConfig.Timeout, s.bot)
|
||
}
|
||
}
|
||
for _, rc := range conf.ReverseServers {
|
||
go NewWebsocketClient(rc, conf.AccessToken, s.bot).Run()
|
||
}
|
||
}
|
||
|
||
// 热重启
|
||
func AdminDoRestart(s *webServer, c *gin.Context) {
|
||
s.bot.Release()
|
||
s.bot = nil
|
||
s.Cli = nil
|
||
s.DoReLogin()
|
||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||
return
|
||
}
|
||
|
||
// 冷重启
|
||
func AdminDoRestartDocker(s *webServer, c *gin.Context) {
|
||
Console <- os.Kill
|
||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||
return
|
||
}
|
||
|
||
// web输入 html 页面
|
||
func AdminWebWrite(s *webServer, c *gin.Context) {
|
||
pic := global.ReadAllText("captcha.jpg")
|
||
var picbase64 string
|
||
var ispic = false
|
||
if pic != "" {
|
||
input := []byte(pic)
|
||
// base64编码
|
||
picbase64 = base64.StdEncoding.EncodeToString(input)
|
||
ispic = true
|
||
}
|
||
c.JSON(200, coolq.OK(coolq.MSG{
|
||
"ispic": ispic, //为空则为 设备锁 或者没有需要输入
|
||
"picbase64": picbase64, //web上显示图片
|
||
}))
|
||
}
|
||
|
||
// web输入 处理
|
||
func AdminDoWebWrite(s *webServer, c *gin.Context) {
|
||
input := c.PostForm("input")
|
||
WebInput <- input
|
||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||
}
|
||
|
||
// 普通配置修改
|
||
func AdminDoConfigBase(s *webServer, c *gin.Context) {
|
||
conf := GetConf()
|
||
conf.Uin, _ = strconv.ParseInt(c.PostForm("uin"), 10, 64)
|
||
conf.Password = c.PostForm("password")
|
||
if c.PostForm("enable_db") == "true" {
|
||
conf.EnableDB = true
|
||
} else {
|
||
conf.EnableDB = false
|
||
}
|
||
conf.AccessToken = c.PostForm("access_token")
|
||
if err := conf.Save("config.json"); err != nil {
|
||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
||
} else {
|
||
JsonConfig = nil
|
||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||
}
|
||
}
|
||
|
||
// http配置修改
|
||
func AdminDoConfigHttp(s *webServer, c *gin.Context) {
|
||
conf := GetConf()
|
||
p, _ := strconv.ParseUint(c.PostForm("port"), 10, 16)
|
||
conf.HttpConfig.Port = uint16(p)
|
||
conf.HttpConfig.Host = c.PostForm("host")
|
||
if c.PostForm("enable") == "true" {
|
||
conf.HttpConfig.Enabled = true
|
||
} else {
|
||
conf.HttpConfig.Enabled = false
|
||
}
|
||
t, _ := strconv.ParseInt(c.PostForm("timeout"), 10, 32)
|
||
conf.HttpConfig.Timeout = int32(t)
|
||
if c.PostForm("post_url") != "" {
|
||
conf.HttpConfig.PostUrls[c.PostForm("post_url")] = c.PostForm("post_secret")
|
||
}
|
||
if err := conf.Save("config.json"); err != nil {
|
||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
||
} else {
|
||
JsonConfig = nil
|
||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||
}
|
||
}
|
||
|
||
// ws配置修改
|
||
func AdminDoConfigWs(s *webServer, c *gin.Context) {
|
||
conf := GetConf()
|
||
p, _ := strconv.ParseUint(c.PostForm("port"), 10, 16)
|
||
conf.WSConfig.Port = uint16(p)
|
||
conf.WSConfig.Host = c.PostForm("host")
|
||
if c.PostForm("enable") == "true" {
|
||
conf.WSConfig.Enabled = true
|
||
} else {
|
||
conf.WSConfig.Enabled = false
|
||
}
|
||
if err := conf.Save("config.json"); err != nil {
|
||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
||
} else {
|
||
JsonConfig = nil
|
||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||
}
|
||
}
|
||
|
||
// 反向ws配置修改
|
||
func AdminDoConfigReverse(s *webServer, c *gin.Context) {
|
||
conf := GetConf()
|
||
conf.ReverseServers[0].ReverseApiUrl = c.PostForm("reverse_api_url")
|
||
conf.ReverseServers[0].ReverseUrl = c.PostForm("reverse_url")
|
||
conf.ReverseServers[0].ReverseEventUrl = c.PostForm("reverse_event_url")
|
||
t, _ := strconv.ParseUint(c.PostForm("reverse_reconnect_interval"), 10, 16)
|
||
conf.ReverseServers[0].ReverseReconnectInterval = uint16(t)
|
||
if c.PostForm("enable") == "true" {
|
||
conf.ReverseServers[0].Enabled = true
|
||
} else {
|
||
conf.ReverseServers[0].Enabled = false
|
||
}
|
||
if err := conf.Save("config.json"); err != nil {
|
||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
||
} else {
|
||
JsonConfig = nil
|
||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||
}
|
||
}
|
||
|
||
// config.json配置修改
|
||
func AdminDoConfigJson(s *webServer, c *gin.Context) {
|
||
conf := GetConf()
|
||
Json := c.PostForm("json")
|
||
err := json.Unmarshal([]byte(Json), &conf)
|
||
if err != nil {
|
||
log.Warnf("尝试加载配置文件 %v 时出现错误: %v", "config.json", err)
|
||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
||
return
|
||
}
|
||
if err := conf.Save("config.json"); err != nil {
|
||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
||
c.JSON(200, Failed(502, "保存 config.json 时出现错误:"+fmt.Sprintf("%v", err)))
|
||
} else {
|
||
JsonConfig = nil
|
||
c.JSON(200, coolq.OK(coolq.MSG{}))
|
||
}
|
||
}
|
||
|
||
// 拉取config.json配置
|
||
func AdminGetConfigJson(s *webServer, c *gin.Context) {
|
||
conf := GetConf()
|
||
c.JSON(200, coolq.OK(coolq.MSG{"config": conf}))
|
||
|
||
}
|