diff --git a/.gitignore b/.gitignore index 93e5a6e..4cfd383 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,5 @@ config.yml #Goreleaser /dist #Logs -/log \ No newline at end of file +/log +/.idea \ No newline at end of file diff --git a/bots/bots.go b/bots/bots.go new file mode 100644 index 0000000..d9b9b39 --- /dev/null +++ b/bots/bots.go @@ -0,0 +1,132 @@ +package bots + +import ( + "database/sql" + "fmt" + "github.com/robfig/cron/v3" + "github.com/spf13/viper" + "golang.org/x/net/proxy" + tb "gopkg.in/tucnak/telebot.v2" + "main/logger" + "net/http" + "strconv" + "strings" + "time" +) + +var ( + BotToken string + Socks5 string + bot *tb.Bot + //logger *log.Logger +) + +const ( + dbDriverName = "mysql" + logo = ` + ______ _____ _____ _ ____ _ + | ____| ____/ ____| | | | _ \ | | + | |__ | |__| (___ _ _| |__ | |_) | ___ | |_ + | __| |___ \\___ \| | | | '_ \| _ < / _ \| __| + | |____ ___) |___) | |_| | |_) | |_) | (_) | |_ + |______|____/_____/ \__,_|_.__/|____/ \___/ \__| +` +) + +var dbPath string + +func BotStart() { + MakeHandle() + TaskLaunch() + logger.Println("Bot Start") + fmt.Println("------------") + bot.Start() +} +func MakeHandle() { + logger.Println("Make Handle……") + //所有用户 + bot.Handle("/start", bStart) + bot.Handle("/my", bMy) + bot.Handle("/bind", bBind1) + bot.Handle("/unbind", bUnBind) + bot.Handle("/export", bExport) + bot.Handle("/help", bHelp) + bot.Handle(tb.OnText, bOnText) + //管理员 + bot.Handle("/task", bTask) + bot.Handle("/log", bLog) +} +func TaskLaunch() { + task := cron.New() + //每三小时执行一次 + task.AddFunc(viper.GetString("cron"), SignTask) + //log分为每天 + //task.AddFunc(" 0 0 * * *", InitLogger) + // */1 * * * * 1 */3 * * * + logger.Println("Cron Task Start……") + task.Start() +} +func init() { + fmt.Println(logo) + + //read config + logger.Println("Read Config……") + viper.SetConfigName("config") + viper.AddConfigPath(".") + err := viper.ReadInConfig() + if err != nil { + logger.Println(err) + } + host := viper.GetString("mysql.host") + user := viper.GetString("mysql.user") + port := viper.GetString("mysql.port") + pwd := viper.GetString("mysql.password") + database := viper.GetString("mysql.database") + dbPath = strings.Join([]string{user, ":", pwd, "@tcp(", host, ":", port, ")/", database, "?charset=utf8"}, "") + //fmt.Println(path) + db, err := sql.Open(dbDriverName, dbPath) + if err != nil { + logger.Println(err) + } + logger.Println("Connect MySQL Success!") + if ok, err := CreateTB(); !ok { + logger.Println(err) + } + defer db.Close() + BotToken = viper.GetString("bot_token") + Socks5 = viper.GetString("socks5") + //set bot + logger.Println("Bot Settings……") + Poller := &tb.LongPoller{Timeout: 15 * time.Second} + spamProtected := tb.NewMiddlewarePoller(Poller, func(upd *tb.Update) bool { + if upd.Message == nil { + return true + } + if !upd.Message.Private() { + return false + } + return true + }) + botsettings := tb.Settings{ + Token: BotToken, + Poller: spamProtected, + } + //set socks5 + if Socks5 != "" { + logger.Println("Proxy:" + Socks5) + dialer, err := proxy.SOCKS5("tcp", Socks5, nil, proxy.Direct) + if err != nil { + logger.Println(err) + } + httpTransport := &http.Transport{} + httpClient := &http.Client{Transport: httpTransport} + httpTransport.Dial = dialer.Dial + botsettings.Client = httpClient + } + //create bot + bot, err = tb.NewBot(botsettings) + if err != nil { + logger.Println(err) + } + logger.Println("Bot: " + strconv.Itoa(bot.Me.ID) + " " + bot.Me.Username) +} diff --git a/control.go b/bots/control.go similarity index 52% rename from control.go rename to bots/control.go index 2187998..b93e2f5 100644 --- a/control.go +++ b/bots/control.go @@ -1,4 +1,4 @@ -package main +package bots import ( "errors" @@ -6,9 +6,10 @@ import ( "github.com/spf13/viper" "github.com/tidwall/gjson" tb "gopkg.in/tucnak/telebot.v2" - "io" - "log" - "os" + "main/db" + "main/logger" + "main/outlook" + "main/util" "strconv" "strings" "time" @@ -18,69 +19,69 @@ var SignOk map[int64]int //If Successfully return "",else return error information func BindUser(m *tb.Message, cid, cse string) error { - logger.Printf("%d Begin Bind\n", m.Chat.ID) + logger.Println("%d Begin Bind\n", m.Chat.ID) tmp := strings.Split(m.Text, " ") if len(tmp) != 2 { - logger.Printf("%d Bind error:Wrong Bind Format\n", m.Chat.ID) + logger.Println("%d Bind error:Wrong Bind Format\n", m.Chat.ID) return errors.New("绑定格式错误") } - logger.Println("alias: " + tmp[1]) - alias := tmp[1] - code := GetURLValue(tmp[0], "code") + logger.Println("Alias: " + tmp[1]) + Alias := tmp[1] + code := util.GetURLValue(tmp[0], "code") //fmt.Println(code) - access, refresh, err := MSFirGetToken(code, cid, cse) + access, refresh, err := outlook.MSFirGetToken(code, cid, cse) if err != nil { - logger.Printf("%d Bind error:GetRefreshToken %s \n", m.Chat.ID, err.Error()) + logger.Println("%d Bind error:GetRefreshToken %s \n", m.Chat.ID, err.Error()) return err } //token has gotten bot.Send(m.Chat, "Token获取成功!") - info, err := MSGetUserInfo(access) - //fmt.Printf("TGID:%d Refresh Token: %s\n", m.Chat.ID, refresh) + info, err := outlook.MSGetUserInfo(access) + //fmt.Println("TgId:%d Refresh Token: %s\n", m.Chat.ID, refresh) if err != nil { - logger.Printf("%d Bind error:Getinfo %s \n", m.Chat.ID, err.Error()) + logger.Println("%d Bind error:Getinfo %s \n", m.Chat.ID, err.Error()) return err } - var u MSData - u.tgId = m.Chat.ID - u.refreshToken = refresh - //TG的Data传递最高64bytes,一些msid超过了报错BUTTON_DATA_INVALID (0),采取md5 - u.msId = Get16MD5Encode(gjson.Get(info, "id").String()) - u.uptime = time.Now().Unix() - logger.Println(u.uptime) - u.alias = alias - u.clientId = cid - u.clientSecret = cse - u.other = "" + var u db.MSData + u.TgId = m.Chat.ID + u.RefreshToken = refresh + //TG的Data传递最高64bytes,一些MsId超过了报错BUTTON_DATA_INVALID (0),采取md5 + u.MsId = util.Get16MD5Encode(gjson.Get(info, "id").String()) + u.Uptime = time.Now().Unix() + logger.Println(u.Uptime) + u.Alias = Alias + u.ClientId = cid + u.ClientSecret = cse + u.Other = "" //MS User Is Exist - if MSAppIsExist(u.tgId, u.clientId) { - logger.Printf("%d Bind error:MSUserHasExisted\n", m.Chat.ID) + if MSAppIsExist(u.TgId, u.ClientId) { + logger.Println("%d Bind error:MSUserHasExisted\n", m.Chat.ID) return errors.New("该应用已经绑定过了,无需重复绑定") } //MS information has gotten - bot.Send(m.Chat, "MS_ID(MD5): "+u.msId+"\nuserPrincipalName: "+gjson.Get(info, "userPrincipalName").String()+"\ndisplayName: "+gjson.Get(info, "displayName").String()+"\n") - if ok, err := AddData(u); !ok { - logger.Printf("%d Bind error: %s\n", m.Chat.ID, err) + bot.Send(m.Chat, "MS_ID(MD5): "+u.MsId+"\nuserPrincipalName: "+gjson.Get(info, "userPrincipalName").String()+"\ndisplayName: "+gjson.Get(info, "displayName").String()+"\n") + if ok, err := db.AddData(u); !ok { + logger.Println("%d Bind error: %s\n", m.Chat.ID, err) return err } - logger.Printf("%d Bind Successfully!\n", m.Chat.ID) + logger.Println("%d Bind Successfully!\n", m.Chat.ID) return nil } //get bind num -func GetBindNum(tgId int64) int { - data := QueryDataByTG(tgId) +func GetBindNum(TgId int64) int { + data := db.QueryDataByTG(TgId) return len(data) } //return true => exist -func MSAppIsExist(tgId int64, clientId string) bool { - data := QueryDataByTG(tgId) - var res MSData +func MSAppIsExist(TgId int64, ClientId string) bool { + data := db.QueryDataByTG(TgId) + var res db.MSData for _, res = range data { - if res.clientId == clientId { + if res.ClientId == ClientId { return true } } @@ -98,52 +99,52 @@ func SignTask() { SignOk = make(map[int64]int) fmt.Println("----Task Begin----") fmt.Println("Time:" + time.Now().Format("2006-01-02 15:04:05")) - data := QueryDataAll() + data := db.QueryDataAll() num = len(data) fmt.Println("Start Sign") //签到任务 for _, u := range data { - pre := "您的账户: " + u.alias + "\n在任务执行时出现了错误!\n错误:" - chat, err := bot.ChatByID(strconv.FormatInt(u.tgId, 10)) + pre := "您的账户: " + u.Alias + "\n在任务执行时出现了错误!\n错误:" + chat, err := bot.ChatByID(strconv.FormatInt(u.TgId, 10)) if err != nil { logger.Println(err) continue } //生成解绑按钮 var inlineKeys [][]tb.InlineButton - UnBindBtn := tb.InlineButton{Unique: "un" + u.msId, Text: "点击解绑该账户", Data: u.msId} + UnBindBtn := tb.InlineButton{Unique: "un" + u.MsId, Text: "点击解绑该账户", Data: u.MsId} bot.Handle(&UnBindBtn, bUnBindInlineBtn) inlineKeys = append(inlineKeys, []tb.InlineButton{UnBindBtn}) tmpBtn := &tb.ReplyMarkup{InlineKeyboard: inlineKeys} - se := u.msId + " ( @" + chat.Username + " )" - access, newRefreshToken, err := MSGetToken(u.refreshToken, u.clientId, u.clientSecret) + se := u.MsId + " ( @" + chat.Username + " )" + access, newRefreshToken, err := outlook.MSGetToken(u.RefreshToken, u.ClientId, u.ClientSecret) if err != nil { - logger.Println(u.msId+" ", err) + logger.Println(u.MsId+" ", err) bot.Send(chat, pre+gjson.Get(err.Error(), "error").String(), tmpBtn) SignErr = append(SignErr, se) - ErrorTimes[u.msId]++ + ErrorTimes[u.MsId]++ continue } - if ok, err := OutLookGetMails(access); !ok { - logger.Println(u.msId+" ", err) + if ok, err := outlook.OutLookGetMails(access); !ok { + logger.Println(u.MsId+" ", err) bot.Send(chat, pre+gjson.Get(err.Error(), "error").String(), tmpBtn) - ErrorTimes[u.msId]++ + ErrorTimes[u.MsId]++ SignErr = append(SignErr, se) continue } - u.uptime = time.Now().Unix() - u.refreshToken = newRefreshToken - if ok, err := UpdateData(u); !ok { - logger.Println(u.msId+" ", err) + u.Uptime = time.Now().Unix() + u.RefreshToken = newRefreshToken + if ok, err := db.UpdateData(u); !ok { + logger.Println(u.MsId+" ", err) bot.Send(chat, pre+err.Error(), tmpBtn) SignErr = append(SignErr, se) - ErrorTimes[u.msId]++ + ErrorTimes[u.MsId]++ continue } - fmt.Println(u.msId + " Sign OK!") - SignOk[u.tgId]++ + fmt.Println(u.MsId + " Sign OK!") + SignOk[u.TgId]++ signOk++ } fmt.Println("Sign End,Start Send") @@ -151,32 +152,32 @@ func SignTask() { isSend = make(map[int64]bool) //用户任务反馈 for _, u := range data { - chat, err := bot.ChatByID(strconv.FormatInt(u.tgId, 10)) + chat, err := bot.ChatByID(strconv.FormatInt(u.TgId, 10)) if err != nil { logger.Println("Send Result ERROR: ", err) continue } //错误上限账户清退 - if ErrorTimes[u.msId] == ErrMaxTimes { - logger.Println(u.msId + " Error Limit") - if ok, err := DelData(u.msId); !ok { + if ErrorTimes[u.MsId] == ErrMaxTimes { + logger.Println(u.MsId + " Error Limit") + if ok, err := db.DelData(u.MsId); !ok { logger.Println(err) } else { - UnbindUser = append(UnbindUser, u.msId+" ( @"+chat.Username+" )") - _, err = bot.Send(chat, "您的账户因达到错误上限而被自动解绑\n后会有期!\n\n别名: "+u.alias+"\nclient_id: "+u.clientId+"\nclient_secret: "+u.clientSecret) + UnbindUser = append(UnbindUser, u.MsId+" ( @"+chat.Username+" )") + _, err = bot.Send(chat, "您的账户因达到错误上限而被自动解绑\n后会有期!\n\n别名: "+u.Alias+"\nclient_id: "+u.ClientId+"\nclient_secret: "+u.ClientSecret) if err != nil { logger.Println(err) } } } - if !isSend[u.tgId] { + if !isSend[u.TgId] { //静默发送,过多消息很烦 - _, err = bot.Send(chat, "任务反馈\n时间: "+time.Now().Format("2006-01-02 15:04:05")+"\n结果: "+strconv.Itoa(SignOk[u.tgId])+"/"+strconv.Itoa(GetBindNum(u.tgId)), &tb.SendOptions{DisableNotification: true}) + _, err = bot.Send(chat, "任务反馈\n时间: "+time.Now().Format("2006-01-02 15:04:05")+"\n结果: "+strconv.Itoa(SignOk[u.TgId])+"/"+strconv.Itoa(GetBindNum(u.TgId)), &tb.SendOptions{DisableNotification: true}) if err != nil { logger.Println(err) } - isSend[u.tgId] = true + isSend[u.TgId] = true } } //管理员任务反馈 @@ -207,19 +208,20 @@ func GetAdmin() []int64 { } return result } -func InitLogger() { - if !PathExists(bLogBasePath) { - os.Mkdir(bLogBasePath, 0773) - } - path := bLogBasePath + time.Now().Format("2006-01-02") + ".log" - f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0773) - if err != nil { - logger.Println(err) - } - writers := []io.Writer{ - f, - os.Stdout} - faoWriter := io.MultiWriter(writers...) - logger = log.New(faoWriter, "【E5Sub】", log.Ldate|log.Ltime|log.Lshortfile) -} +//func InitLogger() { +// if !util.PathExists(bLogBasePath) { +// os.Mkdir(bLogBasePath, 0773) +// } +// +// path := bLogBasePath + time.Now().Format("2006-01-02") + ".log" +// f, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0773) +// if err != nil { +// logger.Println(err) +// } +// writers := []io.Writer{ +// f, +// os.Stdout} +// faoWriter := io.MultiWriter(writers...) +// //logger = log.New(faoWriter, "【E5Sub】", log.Ldate|log.Ltime|log.Lshortfile) +//} diff --git a/handle.go b/bots/handle.go similarity index 86% rename from handle.go rename to bots/handle.go index f8b111b..ba7c696 100644 --- a/handle.go +++ b/bots/handle.go @@ -1,4 +1,4 @@ -package main +package bots import ( "encoding/json" @@ -6,6 +6,10 @@ import ( "github.com/spf13/viper" tb "gopkg.in/tucnak/telebot.v2" "io/ioutil" + "main/db" + "main/logger" + "main/outlook" + "main/util" "os" "path/filepath" "strconv" @@ -51,7 +55,7 @@ func init() { viper.SetConfigName("config") viper.AddConfigPath(".") err := viper.ReadInConfig() - CheckErr(err) + util.CheckErr(err) viper.SetDefault("errlimit", 5) viper.SetDefault("bindmax", 5) @@ -82,13 +86,13 @@ func bStart(m *tb.Message) { func bMy(m *tb.Message) { logger.Println(strconv.FormatInt(m.Chat.ID, 10) + " Start Manager Users") - data := QueryDataByTG(m.Chat.ID) + data := db.QueryDataByTG(m.Chat.ID) var inlineKeys [][]tb.InlineButton for _, u := range data { inlineBtn := tb.InlineButton{ - Unique: "my" + u.msId, - Text: u.alias, - Data: u.msId, + Unique: "my" + u.MsId, + Text: u.Alias, + Data: u.MsId, } bot.Handle(&inlineBtn, bMyInlineBtn) inlineKeys = append(inlineKeys, []tb.InlineButton{inlineBtn}) @@ -97,16 +101,16 @@ func bMy(m *tb.Message) { } func bMyInlineBtn(c *tb.Callback) { logger.Println(strconv.FormatInt(c.Message.Chat.ID, 10) + " Get User Info") - r := QueryDataByMS(c.Data) + r := db.QueryDataByMS(c.Data) u := r[0] - bot.Send(c.Message.Chat, "信息\n别名:"+u.alias+"\nMS_ID(MD5): "+u.msId+"\nclient_id: "+u.clientId+"\nclient_secret: "+u.clientSecret+"\n最近更新时间: "+time.Unix(u.uptime, 0).Format("2006-01-02 15:04:05")) + bot.Send(c.Message.Chat, "信息\n别名:"+u.Alias+"\nMS_ID(MD5): "+u.MsId+"\nclient_id: "+u.ClientId+"\nclient_secret: "+u.ClientSecret+"\n最近更新时间: "+time.Unix(u.Uptime, 0).Format("2006-01-02 15:04:05")) bot.Respond(c) } func bBind1(m *tb.Message) { logger.Println(strconv.FormatInt(m.Chat.ID, 10) + " Start Bind") logger.Println("ReApp: " + strconv.FormatInt(m.Chat.ID, 10)) - bot.Send(m.Chat, "应用注册: [点击直达]("+MSGetReAppUrl()+")", tb.ModeMarkdown) + bot.Send(m.Chat, "应用注册: [点击直达]("+outlook.MSGetReAppUrl()+")", tb.ModeMarkdown) _, err := bot.Send(m.Chat, "请回复client_id+空格+client_secret", &tb.ReplyMarkup{ForceReply: true}) if err != nil { logger.Println(err) @@ -120,14 +124,14 @@ func bBind2(m *tb.Message) { logger.Println("Auth: " + strconv.FormatInt(m.Chat.ID, 10)) tmp := strings.Split(m.Text, " ") if len(tmp) != 2 { - logger.Printf("%d Bind error:Wrong Bind Format\n", m.Chat.ID) + logger.Println("%d Bind error:Wrong Bind Format\n", m.Chat.ID) bot.Send(m.Chat, "错误的格式") return } logger.Println("client_id: " + tmp[0] + " client_secret: " + tmp[1]) cid := tmp[0] cse := tmp[1] - bot.Send(m.Chat, "授权账户: [点击直达]("+MSGetAuthUrl(cid)+")", tb.ModeMarkdown) + bot.Send(m.Chat, "授权账户: [点击直达]("+outlook.MSGetAuthUrl(cid)+")", tb.ModeMarkdown) _, err := bot.Send(m.Chat, "请回复http://localhost/…… + 空格 + 别名(用于管理)", &tb.ReplyMarkup{ForceReply: true}) if err != nil { logger.Println(err) @@ -140,13 +144,13 @@ func bBind2(m *tb.Message) { func bUnBind(m *tb.Message) { logger.Println(strconv.FormatInt(m.Chat.ID, 10) + " Start Unbind") - data := QueryDataByTG(m.Chat.ID) + data := db.QueryDataByTG(m.Chat.ID) var inlineKeys [][]tb.InlineButton for _, u := range data { inlineBtn := tb.InlineButton{ - Unique: "unbind" + u.msId, - Text: u.alias, - Data: u.msId, + Unique: "unbind" + u.MsId, + Text: u.Alias, + Data: u.MsId, } bot.Handle(&inlineBtn, bUnBindInlineBtn) inlineKeys = append(inlineKeys, []tb.InlineButton{inlineBtn}) @@ -155,14 +159,14 @@ func bUnBind(m *tb.Message) { } func bUnBindInlineBtn(c *tb.Callback) { logger.Println(strconv.FormatInt(c.Message.Chat.ID, 10) + " Unbind: " + c.Data) - r := QueryDataByMS(c.Data) + r := db.QueryDataByMS(c.Data) u := r[0] - if ok, _ := DelData(u.msId); !ok { - logger.Println(u.msId + " UnBind ERROR") + if ok, _ := db.DelData(u.MsId); !ok { + logger.Println(u.MsId + " UnBind ERROR") bot.Send(c.Message.Chat, "解绑失败!") return } - logger.Println(u.msId + " UnBind Success") + logger.Println(u.MsId + " UnBind Success") bot.Send(c.Message.Chat, "解绑成功!") bot.Respond(c) } @@ -176,18 +180,18 @@ func bExport(m *tb.Message) { Other string } var MsMini []MsMiniData - data := QueryDataByTG(m.Chat.ID) + data := db.QueryDataByTG(m.Chat.ID) if len(data) == 0 { bot.Send(m.Chat, "你还没有绑定过账户嗷~") return } for _, u := range data { var ms MsMiniData - ms.RefreshToken = u.refreshToken - ms.Alias = u.alias - ms.ClientId = u.clientId - ms.ClientSecret = u.clientSecret - ms.Other = u.other + ms.RefreshToken = u.RefreshToken + ms.Alias = u.Alias + ms.ClientId = u.ClientId + ms.ClientSecret = u.ClientSecret + ms.Other = u.Other MsMini = append(MsMini, ms) } //MarshalIndent是为json+美化,/t表缩进 @@ -278,7 +282,7 @@ func bLog(m *tb.Message) { bot.Send(m.Chat, "您没有权限执行此操作~") return } - logs := GetRecentLogs(bLogBasePath, 5) + logs := util.GetRecentLogs(bLogBasePath, 5) var inlineKeys [][]tb.InlineButton for _, log := range logs { inlineBtn := tb.InlineButton{ diff --git a/mysql.go b/db/mysql.go similarity index 86% rename from mysql.go rename to db/mysql.go index af0f152..b2c5cef 100644 --- a/mysql.go +++ b/db/mysql.go @@ -1,19 +1,21 @@ -package main +package db import ( "database/sql" _ "github.com/go-sql-driver/mysql" + "main/logger" + "main/util" ) type MSData struct { - tgId int64 - refreshToken string - msId string - uptime int64 - alias string - clientId string - clientSecret string - other string + TgId int64 + RefreshToken string + MsId string + Uptime int64 + Alias string + ClientId string + ClientSecret string + Other string } //update data by msId @@ -28,7 +30,7 @@ func UpdateData(u MSData) (bool, error) { if err != nil { return false, err } - _, err = stmt.Exec(u.tgId, u.refreshToken, u.uptime, u.alias, u.clientId, u.clientSecret, u.other, u.msId) + _, err = stmt.Exec(u.TgId, u.RefreshToken, u.Uptime, u.Alias, u.ClientId, u.ClientSecret, u.Other, u.MsId) if err != nil { return false, err } @@ -49,7 +51,7 @@ func AddData(u MSData) (bool, error) { if err != nil { return false, err } - _, err = stmt.Exec(u.tgId, u.refreshToken, u.msId, u.uptime, u.alias, u.clientId, u.clientSecret, u.other) + _, err = stmt.Exec(u.TgId, u.RefreshToken, u.MsId, u.Uptime, u.Alias, u.ClientId, u.ClientSecret, u.Other) if err != nil { return false, err } @@ -100,7 +102,7 @@ func QueryDataByMS(msId string) []MSData { } defer db.Close() rows, err := db.Query("select * from users where ms_id = ?", msId) - CheckErr(err) + util.CheckErr(err) return QueryData(rows) } @@ -111,7 +113,7 @@ func QueryDataAll() []MSData { } defer db.Close() rows, err := db.Query("select * from users ") - CheckErr(err) + util.CheckErr(err) return QueryData(rows) } @@ -123,7 +125,7 @@ func QueryDataByTG(tgId int64) []MSData { } defer db.Close() rows, err := db.Query("select * from users where tg_id = ?", tgId) - CheckErr(err) + util.CheckErr(err) return QueryData(rows) } func CreateTB() (bool, error) { diff --git a/go.mod b/go.mod index 772d1bd..b9d45ad 100644 --- a/go.mod +++ b/go.mod @@ -9,6 +9,8 @@ require ( github.com/spf13/viper v1.6.2 github.com/tidwall/gjson v1.6.0 github.com/tidwall/pretty v1.0.1 // indirect + go.uber.org/zap v1.10.0 golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e + gopkg.in/natefinch/lumberjack.v2 v2.0.0 gopkg.in/tucnak/telebot.v2 v2.0.0-20200328014118-dd123e949ee1 ) diff --git a/go.sum b/go.sum index c334d46..ff6aebd 100644 --- a/go.sum +++ b/go.sum @@ -20,6 +20,7 @@ github.com/Azure/azure-sdk-for-go v30.1.0+incompatible/go.mod h1:9XXNKU+eRnpl9mo github.com/Azure/azure-service-bus-go v0.9.1/go.mod h1:yzBx6/BUGfjfeqbRZny9AQIbIe3AcV9WZbAdpkoXOa0= github.com/Azure/azure-storage-blob-go v0.8.0/go.mod h1:lPI3aLPpuLTeUwh1sViKXFxwl2B6teiRqI0deQUvsw0= github.com/Azure/go-autorest v12.0.0+incompatible/go.mod h1:r+4oMnoxhatjLLJ6zxSWATqVooLgysK6ZNox3g/xq24= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/GoogleCloudPlatform/cloudsql-proxy v0.0.0-20191009163259-e802c2cb94ae/go.mod h1:mjwGPas4yKduTyubHvD1Atl9r1rUq8DfVy+gkVvZ+oo= @@ -63,6 +64,7 @@ github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3Ee github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/devigned/tab v0.1.1/go.mod h1:XG9mPq0dFghrYvoBF3xdRrJzSTX1b7IQrvaL9mzjeJY= github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= @@ -119,6 +121,7 @@ github.com/google/wire v0.3.0/go.mod h1:i1DMg/Lu8Sz5yYl25iOdmc5CT5qusaa+zmRWs167 github.com/googleapis/gax-go v2.0.2+incompatible/go.mod h1:SFVmujtThgffbyetf+mdk2eWhX2bMyUtNHzFKcPA9HY= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/goreleaser/goreleaser v0.129.0 h1:hJHsgxxNck3oe/MU4K+yznH2qgAVGNcxARTRP8ODSRk= github.com/goreleaser/goreleaser v0.129.0/go.mod h1:tzHV+xcU9AJMYNby0QS0lHm1DRrTCBkJXW9ic2reepY= @@ -148,6 +151,7 @@ github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqx github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jpillora/backoff v0.0.0-20180909062703-3050d21c67d7/go.mod h1:2iMrUgbbvHEiQClaW2NsSzMyGHqN+rDFqY705q49KG0= github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU= +github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo= github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU= github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w= github.com/kamilsk/retry/v4 v4.7.2 h1:8C33aqTQtTSvPf7MpLZ4xSY4JZK2YCvY+hTlsbiHNq8= @@ -156,8 +160,10 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc= +github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= github.com/magiconair/properties v1.8.1 h1:ZC2Vc7/ZFkGmsVC9KvOjumD+G5lXy2RtTKyzRKO2BQ4= @@ -197,6 +203,7 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.3/go.mod h1:/TN21ttK/J9q6uSwhBd54HahCDft0ttaMvbicHlPoso= @@ -216,9 +223,11 @@ github.com/rogpeppe/fastuuid v1.1.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6L github.com/sassoftware/go-rpmutils v0.0.0-20190420191620-a8f1baeba37b/go.mod h1:am+Fp8Bt506lA3Rk3QCmSqmYmLMnPDhdDUcosQCAx+I= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= github.com/smartystreets/assertions v1.0.0/go.mod h1:kHHU4qYBaI3q23Pp3VPrmWhuIUrLW/7eUrw0BU5VaoM= github.com/smartystreets/go-aws-auth v0.0.0-20180515143844-0c1422d1fdb9/go.mod h1:SnhjPscd9TpLiy1LpzGSKh3bXCfxxXuqd9xmQJy3slM= +github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s= github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= github.com/smartystreets/gunit v1.0.0/go.mod h1:qwPWnhz6pn0NnRBP++URONOVyNkPyr4SauJk4cUOwJs= github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= @@ -236,6 +245,7 @@ github.com/spf13/viper v1.6.2/go.mod h1:t3iDnF5Jlj76alVNuyFBk5oUMCvsrkbvZK0WQdfD github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.2.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE= +github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4= @@ -270,8 +280,11 @@ go.opencensus.io v0.15.0/go.mod h1:UffZAU+4sDEINUGP/B7UfBBkq4fqLu9zXAX7ke6CHW0= go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU= go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8= go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= gocloud.dev v0.19.0 h1:EDRyaRAnMGSq/QBto486gWFxMLczAfIYUmusV7XLNBM= gocloud.dev v0.19.0/go.mod h1:SmKwiR8YwIMMJvQBKLsC3fHNyMwXLw3PMDO+VVteJMI= @@ -393,11 +406,14 @@ google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ij gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc= gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/ini.v1 v1.51.0 h1:AQvPpx3LzTDM0AjnIRlVFwFFGC+npRopjZxLJj6gdno= gopkg.in/ini.v1 v1.51.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= +gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8= +gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= gopkg.in/tucnak/telebot.v2 v2.0.0-20200301001213-9852df39ae6c h1:+7l/yyky9hchNME0hDMl+cA+wVlHQGte/5EwKHeSqoc= diff --git a/logger/logger.go b/logger/logger.go new file mode 100644 index 0000000..dfe5543 --- /dev/null +++ b/logger/logger.go @@ -0,0 +1,41 @@ +package logger + +import ( + "go.uber.org/zap" + "go.uber.org/zap/zapcore" + "gopkg.in/natefinch/lumberjack.v2" + "os" +) + +func Println(a ...interface{}) { + return +} + +// 日志切割设置 +func getLogWriter() zapcore.WriteSyncer { + lumberJackLogger := &lumberjack.Logger{ + Filename: "./log/latest.log", // 日志文件位置 + MaxSize: 1, // 日志文件最大大小(MB) + MaxBackups: 5, // 保留旧文件最大数量 + MaxAge: 30, // 保留旧文件最长天数 + Compress: true, // 是否压缩旧文件 + } + return zapcore.NewMultiWriteSyncer(zapcore.AddSync(os.Stdout), zapcore.AddSync(lumberJackLogger)) +} + +// 编码器 +func getEncoder() zapcore.Encoder { + // 使用默认的JSON编码 + encoderConfig := zap.NewDevelopmentEncoderConfig() + encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder + encoderConfig.EncodeLevel = zapcore.CapitalLevelEncoder + return zapcore.NewJSONEncoder(encoderConfig) +} + +// InitLogger 初始化Logger +func InitLogger() { + writeSyncer := getLogWriter() + encoder := getEncoder() + core := zapcore.NewCore(encoder, writeSyncer, zapcore.DebugLevel) + zap.ReplaceGlobals(zap.New(core, zap.AddCaller())) +} diff --git a/main.go b/main.go index f8da15c..82e01da 100644 --- a/main.go +++ b/main.go @@ -1,135 +1,7 @@ package main -import ( - "database/sql" - "fmt" - "github.com/robfig/cron/v3" - "github.com/spf13/viper" - "golang.org/x/net/proxy" - tb "gopkg.in/tucnak/telebot.v2" - "log" - "net/http" - "strconv" - "strings" - "time" -) - -var ( - BotToken string - Socks5 string - bot *tb.Bot - logger *log.Logger -) - -const ( - dbDriverName = "mysql" - logo = ` - ______ _____ _____ _ ____ _ - | ____| ____/ ____| | | | _ \ | | - | |__ | |__| (___ _ _| |__ | |_) | ___ | |_ - | __| |___ \\___ \| | | | '_ \| _ < / _ \| __| - | |____ ___) |___) | |_| | |_) | |_) | (_) | |_ - |______|____/_____/ \__,_|_.__/|____/ \___/ \__| -` -) - -var dbPath string +import "main/bots" func main() { - BotStart() -} -func BotStart() { - MakeHandle() - TaskLaunch() - logger.Println("Bot Start") - fmt.Println("------------") - bot.Start() -} -func MakeHandle() { - logger.Println("Make Handle……") - //所有用户 - bot.Handle("/start", bStart) - bot.Handle("/my", bMy) - bot.Handle("/bind", bBind1) - bot.Handle("/unbind", bUnBind) - bot.Handle("/export", bExport) - bot.Handle("/help", bHelp) - bot.Handle(tb.OnText, bOnText) - //管理员 - bot.Handle("/task", bTask) - bot.Handle("/log", bLog) -} -func TaskLaunch() { - task := cron.New() - //每三小时执行一次 - task.AddFunc(viper.GetString("cron"), SignTask) - //log分为每天 - task.AddFunc(" 0 0 * * *", InitLogger) - // */1 * * * * 1 */3 * * * - logger.Println("Cron Task Start……") - task.Start() -} -func init() { - fmt.Println(logo) - InitLogger() - //read config - logger.Println("Read Config……") - viper.SetConfigName("config") - viper.AddConfigPath(".") - err := viper.ReadInConfig() - if err != nil { - logger.Fatal(err) - } - host := viper.GetString("mysql.host") - user := viper.GetString("mysql.user") - port := viper.GetString("mysql.port") - pwd := viper.GetString("mysql.password") - database := viper.GetString("mysql.database") - dbPath = strings.Join([]string{user, ":", pwd, "@tcp(", host, ":", port, ")/", database, "?charset=utf8"}, "") - //fmt.Println(path) - db, err := sql.Open(dbDriverName, dbPath) - if err != nil { - logger.Fatal(err) - } - logger.Println("Connect MySQL Success!") - if ok, err := CreateTB(); !ok { - logger.Fatal(err) - } - defer db.Close() - BotToken = viper.GetString("bot_token") - Socks5 = viper.GetString("socks5") - //set bot - logger.Println("Bot Settings……") - Poller := &tb.LongPoller{Timeout: 15 * time.Second} - spamProtected := tb.NewMiddlewarePoller(Poller, func(upd *tb.Update) bool { - if upd.Message == nil { - return true - } - if !upd.Message.Private() { - return false - } - return true - }) - botsettings := tb.Settings{ - Token: BotToken, - Poller: spamProtected, - } - //set socks5 - if Socks5 != "" { - logger.Println("Proxy:" + Socks5) - dialer, err := proxy.SOCKS5("tcp", Socks5, nil, proxy.Direct) - if err != nil { - logger.Println(err) - } - httpTransport := &http.Transport{} - httpClient := &http.Client{Transport: httpTransport} - httpTransport.Dial = dialer.Dial - botsettings.Client = httpClient - } - //create bot - bot, err = tb.NewBot(botsettings) - if err != nil { - logger.Fatal(err) - } - logger.Println("Bot: " + strconv.Itoa(bot.Me.ID) + " " + bot.Me.Username) + bots.BotStart() } diff --git a/outlook.go b/outlook/outlook.go similarity index 99% rename from outlook.go rename to outlook/outlook.go index 02e8703..521e7ea 100644 --- a/outlook.go +++ b/outlook/outlook.go @@ -1,9 +1,10 @@ -package main +package outlook import ( "errors" "github.com/tidwall/gjson" "io/ioutil" + "main/logger" "net/http" "net/url" "strings" diff --git a/util.go b/util/util.go similarity index 99% rename from util.go rename to util/util.go index 52b0e2e..be3aa34 100644 --- a/util.go +++ b/util/util.go @@ -1,4 +1,4 @@ -package main +package util import ( "crypto/md5"