mirror of
https://github.com/Mrs4s/go-cqhttp.git
synced 2025-05-05 03:23:49 +08:00
180 lines
6.1 KiB
Go
180 lines
6.1 KiB
Go
package main
|
||
|
||
import (
|
||
"bufio"
|
||
"bytes"
|
||
"encoding/json"
|
||
"fmt"
|
||
"github.com/Mrs4s/MiraiGo/client"
|
||
"github.com/Mrs4s/go-cqhttp/coolq"
|
||
"github.com/Mrs4s/go-cqhttp/global"
|
||
"github.com/Mrs4s/go-cqhttp/server"
|
||
rotatelogs "github.com/lestrrat-go/file-rotatelogs"
|
||
log "github.com/sirupsen/logrus"
|
||
easy "github.com/t-tomalak/logrus-easy-formatter"
|
||
"image/color"
|
||
"io"
|
||
"io/ioutil"
|
||
"os"
|
||
"os/signal"
|
||
"path"
|
||
"strings"
|
||
"time"
|
||
)
|
||
|
||
func init() {
|
||
log.SetFormatter(&easy.Formatter{
|
||
TimestampFormat: "2006-01-02 15:04:05",
|
||
LogFormat: "[%time%] [%lvl%]: %msg% \n",
|
||
})
|
||
w, err := rotatelogs.New(path.Join("logs", "%Y-%m-%d.log"), rotatelogs.WithRotationTime(time.Hour*24))
|
||
if err == nil {
|
||
log.SetOutput(io.MultiWriter(os.Stderr, w))
|
||
}
|
||
if !global.PathExists("data") {
|
||
if err := os.Mkdir("data", 0777); err != nil {
|
||
log.Fatalf("创建数据文件夹失败: %v", err)
|
||
}
|
||
if err := os.Mkdir(path.Join("data", "images"), 0777); err != nil {
|
||
log.Fatalf("创建图片缓存文件夹失败: %v", err)
|
||
}
|
||
}
|
||
if global.PathExists("cqhttp.json") {
|
||
log.Info("发现 cqhttp.json 将在五秒后尝试导入配置,按 Ctrl+C 取消.")
|
||
log.Warn("警告: 该操作会删除 cqhttp.json 并覆盖 config.json 文件.")
|
||
time.Sleep(time.Second * 5)
|
||
conf := global.CQHttpApiConfig{}
|
||
if err := json.Unmarshal([]byte(global.ReadAllText("cqhttp.json")), &conf); err != nil {
|
||
log.Fatalf("读取文件 cqhttp.json 失败: %v", err)
|
||
}
|
||
goConf := global.DefaultConfig()
|
||
goConf.AccessToken = conf.AccessToken
|
||
goConf.HttpConfig.Host = conf.Host
|
||
goConf.HttpConfig.Port = conf.Port
|
||
goConf.WSConfig.Host = conf.WSHost
|
||
goConf.WSConfig.Port = conf.WSPort
|
||
if conf.PostUrl != "" {
|
||
goConf.HttpConfig.PostUrls[conf.PostUrl] = conf.Secret
|
||
}
|
||
if conf.UseWsReverse {
|
||
goConf.ReverseServers[0].Enabled = true
|
||
goConf.ReverseServers[0].ReverseUrl = conf.WSReverseUrl
|
||
goConf.ReverseServers[0].ReverseApiUrl = conf.WSReverseApiUrl
|
||
goConf.ReverseServers[0].ReverseEventUrl = conf.WSReverseEventUrl
|
||
goConf.ReverseServers[0].ReverseReconnectInterval = conf.WSReverseReconnectInterval
|
||
}
|
||
if err := goConf.Save("config.json"); err != nil {
|
||
log.Fatalf("保存 config.json 时出现错误: %v", err)
|
||
}
|
||
_ = os.Remove("cqhttp.json")
|
||
}
|
||
}
|
||
|
||
func main() {
|
||
console := bufio.NewReader(os.Stdin)
|
||
conf := global.Load("config.json")
|
||
if conf == nil {
|
||
err := global.DefaultConfig().Save("config.json")
|
||
if err != nil {
|
||
log.Fatalf("创建默认配置文件时出现错误: %v", err)
|
||
return
|
||
}
|
||
log.Infof("默认配置文件已生成, 请编辑 config.json 后重启程序.")
|
||
return
|
||
}
|
||
if conf.Uin == 0 || conf.Password == "" {
|
||
log.Fatal("请修改 config.json 以添加账号密码.")
|
||
}
|
||
if !global.PathExists("device.json") {
|
||
log.Warn("虚拟设备信息不存在, 将自动生成随机设备,按 Enter 继续.")
|
||
_, _ = console.ReadString('\n')
|
||
client.GenRandomDevice()
|
||
_ = ioutil.WriteFile("device.json", client.SystemDeviceInfo.ToJson(), 0777)
|
||
log.Info("已生成设备信息并保存到 device.json 文件.")
|
||
} else {
|
||
log.Info("将使用 device.json 内的设备信息运行Bot.")
|
||
if err := client.SystemDeviceInfo.ReadJson([]byte(global.ReadAllText("device.json"))); err != nil {
|
||
log.Fatalf("加载设备信息失败: %v", err)
|
||
}
|
||
}
|
||
log.Info("Bot将在5秒后登录并开始信息处理, 按 Ctrl+C 取消.")
|
||
time.Sleep(time.Second * 5)
|
||
log.Info("开始尝试登录并同步消息...")
|
||
cli := client.NewClient(conf.Uin, conf.Password)
|
||
rsp, err := cli.Login()
|
||
for {
|
||
global.Check(err)
|
||
if !rsp.Success {
|
||
switch rsp.Error {
|
||
case client.NeedCaptcha:
|
||
art, _, err := global.Convert(bytes.NewReader(rsp.CaptchaImage), []string{" ", "1", "i", ":", "*", "|", "."}, 1, 1, false, global.Colors["gray"], color.RGBA{})
|
||
global.Check(err)
|
||
fmt.Println(art)
|
||
log.Warn("请输入验证码.")
|
||
text, _ := console.ReadString('\n')
|
||
rsp, err = cli.SubmitCaptcha(strings.ReplaceAll(text, "\n", ""), rsp.CaptchaSign)
|
||
continue
|
||
case client.UnsafeDeviceError:
|
||
log.Warnf("账号已开启设备锁,请前往 -> %v <- 验证.", rsp.VerifyUrl)
|
||
log.Info("按 Enter 继续")
|
||
_, _ = console.ReadString('\n')
|
||
rsp, err = cli.Login()
|
||
continue
|
||
case client.OtherLoginError, client.UnknownLoginError:
|
||
log.Fatalf("登录失败: %v", rsp.ErrorMessage)
|
||
}
|
||
}
|
||
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))
|
||
b := coolq.NewQQBot(cli, conf)
|
||
if conf.HttpConfig != nil && conf.HttpConfig.Enabled {
|
||
server.HttpServer.Run(fmt.Sprintf("%s:%d", conf.HttpConfig.Host, conf.HttpConfig.Port), conf.AccessToken, b)
|
||
for k, v := range conf.HttpConfig.PostUrls {
|
||
server.NewHttpClient().Run(k, v, b)
|
||
}
|
||
}
|
||
if conf.WSConfig != nil && conf.WSConfig.Enabled {
|
||
server.WebsocketServer.Run(fmt.Sprintf("%s:%d", conf.WSConfig.Host, conf.WSConfig.Port), conf.AccessToken, b)
|
||
}
|
||
for _, rc := range conf.ReverseServers {
|
||
server.NewWebsocketClient(rc, conf.AccessToken, b).Run()
|
||
}
|
||
log.Info("资源初始化完成, 开始处理信息.")
|
||
log.Info("アトリは、高性能ですから!")
|
||
cli.OnDisconnected(func(bot *client.QQClient, e *client.ClientDisconnectedEvent) {
|
||
if conf.ReLogin {
|
||
log.Warnf("Bot已离线,将在 %v 秒后尝试重连.", conf.ReLoginDelay)
|
||
time.Sleep(time.Second * time.Duration(conf.ReLoginDelay))
|
||
rsp, err := cli.Login()
|
||
if err != nil {
|
||
log.Fatalf("重连失败: %v", err)
|
||
}
|
||
if !rsp.Success {
|
||
switch rsp.Error {
|
||
case client.NeedCaptcha:
|
||
log.Fatalf("重连失败: 需要验证码. (验证码处理正在开发中)")
|
||
case client.UnsafeDeviceError:
|
||
log.Fatalf("重连失败: 设备锁")
|
||
default:
|
||
log.Fatalf("重连失败: %v", rsp.ErrorMessage)
|
||
}
|
||
}
|
||
return
|
||
}
|
||
b.Release()
|
||
log.Fatalf("Bot已离线:%v", e.Message)
|
||
})
|
||
c := make(chan os.Signal, 1)
|
||
signal.Notify(c, os.Interrupt, os.Kill)
|
||
<-c
|
||
b.Release()
|
||
}
|