commit 3854359e8cb33c744fd4a1cee6d135deb9c38b77 Author: cdle <798731886@qq.com> Date: Sun Aug 15 09:48:05 2021 +0800 first commit diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..62d33bd --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +test +.DS_Store +*.db +config.sh +*.exe +list.sh +xdd_darwin_amd64 +xdd +test.go +vendor/ +.idea +.vscode +config.hjson +config.yml +session.token +device.json +data/ +logs/ diff --git a/conf/app.conf b/conf/app.conf new file mode 100755 index 0000000..edf7544 --- /dev/null +++ b/conf/app.conf @@ -0,0 +1,2 @@ +#扫码端口 +httpport = 8080 \ No newline at end of file diff --git a/conf/config.yaml b/conf/config.yaml new file mode 100755 index 0000000..7ea249e --- /dev/null +++ b/conf/config.yaml @@ -0,0 +1,23 @@ +mode: parallel +containers: + - address: http://192.168.31.233:5700 + username: admin + password: admin + weigth: + mode: parallel + limit: 9999 +theme: +static: ./static +master: +database: +qywx_key: +daily_push: +resident: +user_agent: +telegram_bot_token: +telegram_user_id: +qquid: +qqgid: +default_priority: +no_ghproxy: true +daily_asset_push_cron: diff --git a/conf/reply.php b/conf/reply.php new file mode 100644 index 0000000..af0baaa --- /dev/null +++ b/conf/reply.php @@ -0,0 +1,8 @@ +return reply( + [ + `你好` => `我不好`, + `早上好`=>`good morning` + `壁纸` => `https://acg.toubiec.cn/random.php` + `涩图` => `https://acg.toubiec.cn/random.php` + ] +) \ No newline at end of file diff --git a/controllers/account.go b/controllers/account.go new file mode 100644 index 0000000..c37c4fe --- /dev/null +++ b/controllers/account.go @@ -0,0 +1,77 @@ +package controllers + +import ( + "github.com/cdle/xdd/models" +) + +type AccountController struct { + BaseController +} + +func (c *AccountController) NextPrepare() { + c.Logined() +} + +func (c *AccountController) List() { + var page = c.GetQueryInt("page") + var limit = c.GetQueryInt("limit") + var cks = models.GetJdCookies() + if !c.Master { + tmp := cks + cks = []models.JdCookie{} + for _, ck := range tmp { + if ck.PtPin == c.PtPin { + cks = append(cks, ck) + break + } + } + } + var len = len(cks) + var total = []int{len} + if page == 0 { + page = 1 + } + if limit == 0 { + limit = 1 + } + var from = (page - 1) * limit + var to = page * limit + if from >= len-1 { + from = len - 1 + } + if to >= len { + to = len + } + if from < 0 { + from = 0 + } + var data = cks[from:to] + c.Data["json"] = map[string]interface{}{ + "code": 200, + "data": data, + "message": total, + } + c.ServeJSON() +} + +func (c *AccountController) CreateOrUpdate() { + ps := &models.JdCookie{} + c.Validate(ps) + if ps.PtPin != "" { + ps.Pool = "" + if !c.Master { + ps.Priority = 0 + ps.PtKey = "" + ps.PtPin = c.PtPin + } + ps.Updates(*ps) + } + go func() { + models.Save <- &models.JdCookie{} + }() + c.Response(nil, "操作成功") +} + +func (c *AccountController) Admin() { + c.Ctx.WriteString(models.Admin) +} diff --git a/controllers/base.go b/controllers/base.go new file mode 100644 index 0000000..2b99da9 --- /dev/null +++ b/controllers/base.go @@ -0,0 +1,202 @@ +package controllers + +import ( + "encoding/json" + "net/http" + "strconv" + "strings" + + beego "github.com/beego/beego/v2/server/web" + "github.com/cdle/xdd/models" + "github.com/go-playground/locales/zh" + ut "github.com/go-playground/universal-translator" + "gopkg.in/go-playground/validator.v9" + zh_translations "gopkg.in/go-playground/validator.v9/translations/zh" +) + +var validate *validator.Validate +var trans ut.Translator + +func init() { + //验证器注册翻译器 + var zhCh = zh.New() + validate = validator.New() + var uni = ut.New(zhCh) + trans, _ = uni.GetTranslator("zh") + zh_translations.RegisterDefaultTranslations(validate, trans) +} + +//BaseController 基础控制器 +type BaseController struct { + beego.Controller + PtPin string + Master bool +} + +//NextPrepare 下一个准备 +type NextPrepare interface { + NextPrepare() +} + +//Prepare 准备 +func (c *BaseController) Prepare() { + // c.Ctx.ResponseWriter.Header().Add("Master-IP-Address", models.GetMasteraddr()) + if app, ok := c.AppController.(NextPrepare); ok { + app.NextPrepare() + } +} + +//Response 响应 +func (c *BaseController) Response(ps ...interface{}) { //数据、信息、状态码 + rsp := struct { + //状态码 + Code int `json:"code"` // 0 成功 1 失败 + //数据 + Data interface{} `json:"data"` + //描述信息 + Msg string `json:"msg"` + }{} + switch len(ps) { + case 3: + rsp.Code = ps[2].(int) + fallthrough + case 2: + switch ps[1].(type) { + case string: + rsp.Msg = ps[1].(string) + case error: + rsp.Msg = ps[1].(error).Error() + } + fallthrough + case 1: + rsp.Data = ps[0] + } + c.Data["json"] = rsp + c.ServeJSON() + c.StopRun() +} + +//ResponseError 响应错误 +func (c *BaseController) ResponseError(ps ...interface{}) *BaseController { + if ps[0] == nil { + return c + } + // var status = http.StatusBadRequest + var text = "" + + for _, p := range ps { + switch t := p.(type) { + case int: //状态码 + // status = t + break + case error: //错误 + text = t.Error() + break + case string: //字符描述 + text = t + break + } + } + // c.Ctx.ResponseWriter.WriteHeader(status) + // if text != "" { + // c.Ctx.WriteString(text) + // } + c.Response(nil, text, 1) + // c.StopRun() + return nil +} + +//Logined 登录 +func (c *BaseController) Logined() *BaseController { + if models.ExecPath == "/Users/cdle/Desktop/xdd" { //作者调试 + c.Master = true + return c + } + if v := c.GetSession("pin"); v == nil { + c.Ctx.Redirect(302, "/") + c.StopRun() + } else { + c.PtPin = v.(string) + if strings.Contains(models.Config.Master, v.(string)) { + c.Master = true + } + } + return c +} + +//Validate 表单验证 +func (c *BaseController) Validate(ps interface{}) *BaseController { + c.ResponseError(json.Unmarshal(c.Ctx.Input.CopyBody(10000000), ps), http.StatusBadRequest) + if err := validate.Struct(ps); err != nil { + for _, err := range err.(validator.ValidationErrors) { + c.ResponseError(err.Translate(trans), http.StatusBadRequest) + } + } + return c +} + +//GetPathInt64 +func (c *BaseController) GetPathInt64(v string) int64 { + r := c.Ctx.Input.Param(":" + v) + if r == "" { + return 0 + } + i, err := strconv.Atoi(r) + c.ResponseError(err) + return int64(i) +} + +//GetPathInt +func (c *BaseController) GetPathInt(v string) int { + r := c.Ctx.Input.Param(":" + v) + if r == "" { + return 0 + } + i, err := strconv.Atoi(r) + c.ResponseError(err) + return i +} + +//GetPathInt32 +func (c *BaseController) GetPathInt32(v string) int32 { + r := c.Ctx.Input.Param(":" + v) + if r == "" { + return 0 + } + i, err := strconv.Atoi(r) + c.ResponseError(err) + return int32(i) +} + +//GetQueryInt64 +func (c *BaseController) GetQueryInt64(v string) int64 { + r := c.GetString(v) + if r == "" { + return 0 + } + i, err := strconv.Atoi(r) + c.ResponseError(err) + return int64(i) +} + +//GetQueryInt +func (c *BaseController) GetQueryInt(v string) int { + r := c.GetString(v) + if r == "" { + return 0 + } + i, err := strconv.Atoi(r) + c.ResponseError(err) + return i +} + +//GetQueryInt32 +func (c *BaseController) GetQueryInt32(v string) int32 { + r := c.GetString(v) + if r == "" { + return 0 + } + i, err := strconv.Atoi(r) + c.ResponseError(err) + return int32(i) +} diff --git a/controllers/login.go b/controllers/login.go new file mode 100644 index 0000000..f1d8773 --- /dev/null +++ b/controllers/login.go @@ -0,0 +1,314 @@ +package controllers + +import ( + "encoding/base64" + "encoding/json" + "fmt" + "io/ioutil" + "regexp" + "strings" + "sync" + "time" + + "github.com/beego/beego/v2/core/logs" + "github.com/cdle/xdd/models" + + "github.com/beego/beego/v2/client/httplib" + qrcode "github.com/skip2/go-qrcode" +) + +type LoginController struct { + BaseController +} + +type StepOne struct { + SToken string `json:"s_token"` +} + +type StepTwo struct { + Token string `json:"token"` +} + +type StepThree struct { + CheckIP int `json:"check_ip"` + Errcode int `json:"errcode"` + Message string `json:"message"` +} + +var JdCookieRunners sync.Map +var jdua = models.GetUserAgent + +func (c *LoginController) GetQrcode() { + if v := c.GetSession("jd_token"); v != nil { + token := v.(string) + if v, ok := JdCookieRunners.Load(token); ok { + if len(v.([]interface{})) >= 2 { + var url = `https://plogin.m.jd.com/cgi-bin/m/tmauth?appid=300&client_type=m&token=` + token + data, _ := qrcode.Encode(url, qrcode.Medium, 256) + c.Ctx.WriteString(`{"url":"` + url + `","img":"` + base64.StdEncoding.EncodeToString(data) + `"}`) + return + } + } + } + var state = time.Now().Unix() + var url = fmt.Sprintf(`https://plogin.m.jd.com/cgi-bin/mm/new_login_entrance?lang=chs&appid=300&returnurl=https://wq.jd.com/passport/LoginRedirect?state=%d&returnurl=https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport`, + state) + req := httplib.Get(url) + req.Header("Connection", "Keep-Alive") + req.Header("Content-Type", "application/x-www-form-urlencoded") + req.Header("Accept", "application/json, text/plain, */*") + req.Header("Accept-Language", "zh-cn") + req.Header("Referer", url) + req.Header("User-Agent", jdua()) + req.Header("Host", "plogin.m.jd.com") + rsp, err := req.Response() + if err != nil { + c.Ctx.WriteString(err.Error()) + return + } + data, err := ioutil.ReadAll(rsp.Body) + so := StepOne{} + err = json.Unmarshal(data, &so) + if err != nil { + c.Ctx.WriteString(err.Error()) + return + } + cookies := strings.Join(rsp.Header.Values("Set-Cookie"), " ") + var cookie = strings.Join([]string{ + "guid=" + FetchJdCookieValue("guid", cookies), + "lang=chs", + "lsid=" + FetchJdCookieValue("lsid", cookies), + "lstoken=" + FetchJdCookieValue("lstoken", cookies), + }, ";") + state = time.Now().Unix() + req = httplib.Post( + fmt.Sprintf(`https://plogin.m.jd.com/cgi-bin/m/tmauthreflogurl?s_token=%s&v=%d&remember=true`, + so.SToken, + state), + ) + req.Header("Connection", "Keep-Alive") + req.Header("Content-Type", "application/x-www-form-urlencoded; Charset=UTF-8") + req.Header("Accept", "application/json, text/plain, */*") + req.Header("Cookie", cookie) + req.Header("Referer", fmt.Sprintf(`https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=%d&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport`, + state), + ) + req.Header("User-Agent", jdua()) + req.Header("Host", "plogin.m.jd.com") + req.Body(fmt.Sprintf(`{ + 'lang': 'chs', + 'appid': 300, + 'returnurl': 'https://wqlogin2.jd.com/passport/LoginRedirect?state=%dreturnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport', + }`, state)) + rsp, err = req.Response() + if err != nil { + c.Ctx.WriteString(err.Error()) + return + } + data, err = ioutil.ReadAll(rsp.Body) + st := StepTwo{} + err = json.Unmarshal(data, &st) + if err != nil { + c.Ctx.WriteString(err.Error()) + return + } + url = `https://plogin.m.jd.com/cgi-bin/m/tmauth?client_type=m&appid=300&token=` + st.Token + cookies = strings.Join(rsp.Header.Values("Set-Cookie"), " ") + okl_token := FetchJdCookieValue("okl_token", cookies) + data, _ = qrcode.Encode(url, qrcode.Medium, 256) + tgid := c.GetQueryInt("tgid") + qqid := c.GetQueryInt("qqid") + qqgid := c.GetQueryInt("qqgid") + qqguid := c.GetQueryInt("qqguid") + id := 0 + bot := "" + if tgid != 0 { + bot = "tg" + id = tgid + } + if qqid != 0 { + bot = "qq" + id = qqid + } + if qqgid != 0 { + bot = "qqg" + id = qqgid + } + JdCookieRunners.Store(st.Token, []interface{}{cookie, okl_token, bot, id, qqguid}) + if bot != "" { + c.Ctx.ResponseWriter.Write(data) + return + } + + c.SetSession("jd_token", st.Token) + c.SetSession("jd_cookie", cookie) + c.SetSession("jd_okl_token", okl_token) + c.Ctx.WriteString(`{"url":"` + url + `","img":"` + base64.StdEncoding.EncodeToString(data) + `"}`) //"data:image/png;base64," + +} + +func init() { + go func() { + for { + time.Sleep(time.Second) + JdCookieRunners.Range(func(k, v interface{}) bool { + jd_token := k.(string) + vv := v.([]interface{}) + if len(vv) >= 2 { + cookie := vv[0].(string) + okl_token := vv[1].(string) + bot := vv[2].(string) + id := vv[3].(int) + guid := vv[4].(int) + // fmt.Println(jd_token, cookie, okl_token) + result, ck := CheckLogin(jd_token, cookie, okl_token) + // fmt.Println(result) + switch result { + case "成功": + if bot == "qq" { + go models.SendQQ(int64(id), "扫码成功") + ck.Update(models.QQ, id) + } else if bot == "tg" { + go models.SendTgMsg(int(id), "扫码成功") + } else if bot == "qqg" { + ck.Update(models.QQ, guid) + go models.SendQQGroup(int64(id), int64(guid), "扫码成功") + } + case "授权登录未确认": + case "": + default: //失效 + if bot == "qq" { + go models.SendQQ(int64(id), "扫码失败") + } else if bot == "tg" { + go models.SendTgMsg(int(id), "扫码失败") + } else if bot == "qqg" { + go models.SendQQGroup(int64(id), int64(guid), "扫码失败") + } + } + } + return true + }) + } + }() +} + +//Query 查询 +func (c *LoginController) Query() { + if v := c.GetSession("jd_token"); v == nil { + c.Ctx.WriteString("重新获取二维码") + return + } else { + token := v.(string) + if v, ok := JdCookieRunners.Load(token); !ok { + c.Ctx.WriteString("重新获取二维码") + return + } else { + if len(v.([]interface{})) >= 2 { + c.Ctx.WriteString("授权登录未确认") + return + } else { + pin := v.([]interface{})[0].(string) + c.SetSession("pin", pin) + if note := c.GetString("note"); note != "" { + if ck, err := models.GetJdCookie(pin); err == nil { + ck.Update(models.Note, note) + } + } + // if strings.Contains(models.Config.Master, pin) { + c.Ctx.WriteString("登录") + // } else { + // c.Ctx.WriteString("成功") + // } + return + } + } + } +} + +func CheckLogin(token, cookie, okl_token string) (string, *models.JdCookie) { + state := time.Now().Unix() + req := httplib.Post( + fmt.Sprintf(`https://plogin.m.jd.com/cgi-bin/m/tmauthchecktoken?&token=%s&ou_state=0&okl_token=%s`, + token, + okl_token, + ), + ) + req.Header("Referer", fmt.Sprintf(`https://plogin.m.jd.com/login/login?appid=300&returnurl=https://wqlogin2.jd.com/passport/LoginRedirect?state=%d&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action&source=wq_passport`, + state), + ) + req.Header("Cookie", cookie) + req.Header("Connection", "Keep-Alive") + req.Header("Content-Type", "application/x-www-form-urlencoded; Charset=UTF-8") + req.Header("Accept", "application/json, text/plain, */*") + req.Header("User-Agent", jdua()) + req.Header("Host", "plogin.m.jd.com") + + req.Param("lang", "chs") + req.Param("appid", "300") + req.Param("returnurl", fmt.Sprintf("https://wqlogin2.jd.com/passport/LoginRedirect?state=%d&returnurl=//home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&/myJd/home.action", state)) + req.Param("source", "wq_passport") + + rsp, err := req.Response() + if err != nil { + return "", nil //err.Error() + } + data, err := ioutil.ReadAll(rsp.Body) + sth := StepThree{} + err = json.Unmarshal(data, &sth) + if err != nil { + return "", nil //err.Error() + } + // fmt.Println(sth) + switch sth.Errcode { + case 0: + cookies := strings.Join(rsp.Header.Values("Set-Cookie"), " ") + pt_key := FetchJdCookieValue("pt_key", cookies) + pt_pin := FetchJdCookieValue("pt_pin", cookies) + if pt_pin == "" { + JdCookieRunners.Delete(token) + return sth.Message, nil + } + ck := models.JdCookie{ + PtKey: pt_key, + PtPin: pt_pin, + } + if nck, err := models.GetJdCookie(ck.PtPin); err == nil { + nck.InPool(ck.PtKey) + msg := fmt.Sprintf("更新账号,%s", ck.PtPin) + (&models.JdCookie{}).Push(msg) + logs.Info(msg) + } else { + models.NewJdCookie(&ck) + msg := fmt.Sprintf("添加账号,%s", ck.PtPin) + (&models.JdCookie{}).Push(msg) + logs.Info(msg) + } + go func() { + models.Save <- &ck + }() + JdCookieRunners.Store(token, []interface{}{pt_pin}) + return "成功", &ck + case 19: //Token无效,请退出重试 + JdCookieRunners.Delete(token) + return sth.Message, nil + case 21: //Token不存在,请退出重试 + JdCookieRunners.Delete(token) + return sth.Message, nil + case 176: //授权登录未确认 + return sth.Message, nil + case 258: //务异常,请稍后重试 + return "", nil + default: + JdCookieRunners.Delete(token) + fmt.Println(sth) + } + return "", nil +} + +func FetchJdCookieValue(key string, cookies string) string { + match := regexp.MustCompile(key + `=([^;]*);{0,1}\s`).FindStringSubmatch(cookies) + if len(match) == 2 { + return match[1] + } else { + return "" + } +} diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..351e559 --- /dev/null +++ b/go.mod @@ -0,0 +1,38 @@ +module github.com/cdle/xdd + +go 1.16 + +replace github.com/willf/bitset v1.2.0 => github.com/bits-and-blooms/bitset v1.2.0 + +replace github.com/Mrs4s/go-cqhttp v1.0.0-beta5 => github.com/cdle/go-cqhttp v1.1.2 + +require ( + github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f + github.com/Mrs4s/MiraiGo v0.0.0-20210726103104-1d68826cef0e + github.com/Mrs4s/go-cqhttp v1.0.0-beta5 + github.com/beego/beego/v2 v2.0.1 + github.com/buger/jsonparser v1.1.1 + github.com/go-playground/locales v0.13.0 + github.com/go-playground/universal-translator v0.17.0 + github.com/guonaihong/gout v0.2.1 + github.com/leodido/go-urn v1.2.1 // indirect + github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible + github.com/pkg/errors v0.9.1 + github.com/robfig/cron/v3 v3.0.1 + github.com/sirupsen/logrus v1.8.1 + github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e + github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 + github.com/tidwall/gjson v1.8.1 + github.com/tuotoo/qrcode v0.0.0-20190222102259-ac9c44189bf2 + golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e + golang.org/x/net v0.0.0-20210614182718-04defd469f4e // indirect + golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b + gopkg.in/go-playground/assert.v1 v1.2.1 // indirect + gopkg.in/go-playground/validator.v9 v9.31.0 + gopkg.in/tucnak/telebot.v2 v2.3.5 + gopkg.in/yaml.v2 v2.2.8 + gorm.io/driver/mysql v1.1.2 + gorm.io/driver/postgres v1.1.0 + gorm.io/driver/sqlite v1.1.4 + gorm.io/gorm v1.21.13 +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..22157c4 --- /dev/null +++ b/go.sum @@ -0,0 +1,739 @@ +cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= +github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f h1:2dk3eOnYllh+wUOuDhOoC2vUVoJF/5z478ryJ+wzEII= +github.com/Baozisoftware/qrcode-terminal-go v0.0.0-20170407111555-c0650d8dff0f/go.mod h1:4a58ifQTEe2uwwsaqbh3i2un5/CBPg+At/qHpt18Tmk= +github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= +github.com/Knetic/govaluate v3.0.0+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Knetic/govaluate v3.0.1-0.20171022003610-9aa49832a739+incompatible/go.mod h1:r7JcOSlj0wfOMncg0iLm8Leh48TZaKVeNIfJntJ2wa0= +github.com/Masterminds/semver/v3 v3.1.1 h1:hLg3sBzpNErnxhQtUy/mmLR2I9foDujNK030IGemrRc= +github.com/Masterminds/semver/v3 v3.1.1/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs= +github.com/Microsoft/go-winio v0.5.0 h1:Elr9Wn+sGKPlkaBvwu4mTrxtmOp3F3yV9qhaHbXGjwU= +github.com/Microsoft/go-winio v0.5.0/go.mod h1:JPGBdM1cNvN/6ISo+n8V5iA4v8pBzdOpzfwIujj1a84= +github.com/Mrs4s/MiraiGo v0.0.0-20210726103104-1d68826cef0e h1:PgFshw1L5TVdiDRLgr/bSotPGaGXYzbtn5cDBBvpL6U= +github.com/Mrs4s/MiraiGo v0.0.0-20210726103104-1d68826cef0e/go.mod h1:CPaznIPn415uQqxJgjyMHLqGLkvLS6R6+bkW3/fe08Q= +github.com/Shopify/sarama v1.19.0/go.mod h1:FVkBWblsNy7DGZRfXLU0O9RCGt5g3g3yEuWXgklEdEo= +github.com/Shopify/toxiproxy v2.1.4+incompatible/go.mod h1:OXgGpZ6Cli1/URJOF1DMxUHB2q5Ap20/P/eIdh4G0pI= +github.com/VividCortex/gohistogram v1.0.0/go.mod h1:Pf5mBqqDxYaXu3hDrrU+w6nw50o/4+TcAqDqk/vUH7g= +github.com/afex/hystrix-go v0.0.0-20180502004556-fa1af6a1f4f5/go.mod h1:SkGFH1ia65gfNATL8TAiHDNxPzPdmEL5uirI2Uyuz6c= +github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= +github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= +github.com/alicebob/gopher-json v0.0.0-20180125190556-5a6b3ba71ee6/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc= +github.com/alicebob/miniredis v2.5.0+incompatible/go.mod h1:8HZjEj4yU0dwhYHky+DxYx+6BMjkBbe5ONFIF1MXffk= +github.com/apache/thrift v0.12.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/apache/thrift v0.13.0/go.mod h1:cp2SuWMxlEZw2r+iP2GNCdIi4C1qmUzdZFSVb+bacwQ= +github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o= +github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY= +github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8= +github.com/aryann/difflib v0.0.0-20170710044230-e206f873d14a/go.mod h1:DAHtR1m6lCRdSC2Tm3DSWRPvIPr6xNKyeHdqDQSQT+A= +github.com/aws/aws-lambda-go v1.13.3/go.mod h1:4UKl9IzQMoD+QF79YdCuzCwp8VbmG4VAQwij/eHl5CU= +github.com/aws/aws-sdk-go v1.27.0/go.mod h1:KmX6BPdI08NWTb3/sm4ZGu5ShLoqVDhKgpiN924inxo= +github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g= +github.com/beego/beego/v2 v2.0.1 h1:07a7Z0Ok5vbqyqh+q53sDPl9LdhKh0ZDy3gbyGrhFnE= +github.com/beego/beego/v2 v2.0.1/go.mod h1:8zyHi1FnWO1mZLwTn62aKRIZF/aIKvkCBB2JYs+eqQI= +github.com/beego/goyaml2 v0.0.0-20130207012346-5545475820dd/go.mod h1:1b+Y/CofkYwXMUU0OhQqGvsY2Bvgr4j6jfT699wyZKQ= +github.com/beego/x2j v0.0.0-20131220205130-a0352aadc542/go.mod h1:kSeGC/p1AbBiEp5kat81+DSQrZenVBZXklMLaELspWU= +github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q= +github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= +github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= +github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs= +github.com/bits-and-blooms/bitset v1.2.0 h1:Kn4yilvwNtMACtf1eYDlG8H77R07mZSPbMjLyS07ChA= +github.com/bits-and-blooms/bitset v1.2.0/go.mod h1:gIdJ4wp64HaoK2YrL1Q5/N7Y16edYb8uY+O0FJTyyDA= +github.com/bradfitz/gomemcache v0.0.0-20180710155616-bc664df96737/go.mod h1:PmM6Mmwb0LSuEubjR8N7PtNe1KxZLtOUHtbeikc5h60= +github.com/buger/jsonparser v1.1.1 h1:2PnMjfWD7wBILjqQbt530v576A/cAbQvEW9gGIpYMUs= +github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx27UK13J/0= +github.com/casbin/casbin v1.7.0/go.mod h1:c67qKN6Oum3UF5Q1+BByfFxkwKvhwW57ITjqwtzR1KE= +github.com/casbin/casbin/v2 v2.1.2/go.mod h1:YcPU1XXisHhLzuxH9coDNf2FbKpjGlbCg3n9yuLkIJQ= +github.com/cdle/go-cqhttp v1.1.2 h1:intdqFjBydFQVZB3c64oLMHWxQeB4Z65AeE3gMuE6Ng= +github.com/cdle/go-cqhttp v1.1.2/go.mod h1:QeXWVo4SrtC+MgfduZOZH+zYNd/DYZOh5u9CqYFSUUc= +github.com/cenkalti/backoff v2.2.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM= +github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= +github.com/cespare/xxhash/v2 v2.1.1 h1:6MnRN8NT7+YBpUIWxHtefFZOKTAPgGjpQSxqLNn0+qY= +github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= +github.com/clbanning/x2j v0.0.0-20191024224557-825249438eec/go.mod h1:jMjuTZXRI4dUb/I5gc9Hdhagfvm9+RyrPryS/auMzxE= +github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/golz4 v0.0.0-20150217214814-ef862a3cdc58/go.mod h1:EOBUe0h4xcZ5GoxqC5SDxFQ8gwyZPKQoEzownBlhI80= +github.com/cockroachdb/apd v1.1.0 h1:3LFP3629v+1aKXU5Q37mxmRxX/pIu1nijXydLShEq5I= +github.com/cockroachdb/apd v1.1.0/go.mod h1:8Sl8LxpKi29FqWXR16WEFZRNSz3SoPzUzeMeY4+DwBQ= +github.com/cockroachdb/datadriven v0.0.0-20190809214429-80d97fb3cbaa/go.mod h1:zn76sxSg3SzpJ0PPJaLDCu+Bu0Lg3sKTORVIj19EIF8= +github.com/codahale/hdrhistogram v0.0.0-20161010025455-3a0bb77429bd/go.mod h1:sE/e/2PUdi/liOCUjSTXgM1o87ZssimdTWN964YiIeI= +github.com/coreos/etcd v3.3.25+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= +github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= +github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= +github.com/coreos/pkg v0.0.0-20160727233714-3ac0863d7acf/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/coreos/pkg v0.0.0-20180928190104-399ea9e2e55f/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA= +github.com/couchbase/go-couchbase v0.0.0-20200519150804-63f3cdb75e0d/go.mod h1:TWI8EKQMs5u5jLKW/tsb9VwauIrMIxQG1r5fMsswK5U= +github.com/couchbase/gomemcached v0.0.0-20200526233749-ec430f949808/go.mod h1:srVSlQLB8iXBVXHgnqemxUXqN6FCvClgCMPCsjBDR7c= +github.com/couchbase/goutils v0.0.0-20180530154633-e865a1461c8a/go.mod h1:BQwMFlJzDjFDG3DJUdU0KORxn88UlsOULuxLExMh3Hs= +github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= +github.com/creack/pty v1.1.7/go.mod h1:lj5s0c3V2DBrqTV7llrYr5NG6My20zk30Fl46Y7DoTY= +github.com/cupcake/rdb v0.0.0-20161107195141-43ba34106c76/go.mod h1:vYwsqCOLxGiisLwp9rITslkFNpZD5rz43tf41QFkTWY= +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/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ= +github.com/dustin/go-humanize v0.0.0-20171111073723-bb3d318650d4/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= +github.com/eapache/go-resiliency v1.1.0/go.mod h1:kFI+JgMyC7bLPUVY133qvEBtVayf5mFgVsvEsIPBvNs= +github.com/eapache/go-xerial-snappy v0.0.0-20180814174437-776d5712da21/go.mod h1:+020luEh2TKB4/GOp8oxxtq0Daoen/Cii55CzbTV6DU= +github.com/eapache/queue v1.1.0/go.mod h1:6eCeP0CKFpHLu8blIFXhExK/dRa7WDZfr6jVFPTqq+I= +github.com/edsrzf/mmap-go v0.0.0-20170320065105-0bce6a688712/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/edsrzf/mmap-go v1.0.0/go.mod h1:YO35OhQPt3KJa3ryjFM5Bs14WD66h8eGKpfaBNrHW5M= +github.com/elastic/go-elasticsearch/v6 v6.8.5/go.mod h1:UwaDJsD3rWLM5rKNFzv9hgox93HoX8utj1kxD9aFUcI= +github.com/elazarl/go-bindata-assetfs v1.0.0 h1:G/bYguwHIzWq9ZoyUQqrjTmJbbYn3j3CKKpKinvZLFk= +github.com/elazarl/go-bindata-assetfs v1.0.0/go.mod h1:v+YaWX3bdea5J/mo8dSETolEo7R71Vk1u8bnjau5yw4= +github.com/envoyproxy/go-control-plane v0.6.9/go.mod h1:SBwIajubJHhxtWwsL9s8ss4safvEdbitLhGGK48rN6g= +github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= +github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= +github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= +github.com/franela/goblin v0.0.0-20200105215937-c9ffbefa60db/go.mod h1:7dvUGVsVBjqR7JHJk0brhHOZYGmfBYOrK0ZhYMEtBr4= +github.com/franela/goreq v0.0.0-20171204163338-bcd34c9993f8/go.mod h1:ZhphrRTfi2rbfLwlschooIH4+wKKDR4Pdxhh+TRoA20= +github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= +github.com/gabriel-vasile/mimetype v1.3.1 h1:qevA6c2MtE1RorlScnixeG0VA1H4xrXyhyX3oWBynNQ= +github.com/gabriel-vasile/mimetype v1.3.1/go.mod h1:fA8fi6KUiG7MgQQ+mEWotXoEOvmxRtOJlERCzSmRvr8= +github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= +github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= +github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= +github.com/gin-gonic/gin v1.6.0 h1:Lb3veSYoGaNck69fV2+Vf2juLSsHpMTf3Vk5+X+EDJg= +github.com/gin-gonic/gin v1.6.0/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= +github.com/glendc/gopher-json v0.0.0-20170414221815-dc4743023d0c/go.mod h1:Gja1A+xZ9BoviGJNA2E9vFkPjjsl+CoJxSXiQM1UXtw= +github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= +github.com/go-kit/kit v0.10.0/go.mod h1:xUsJbQ/Fp4kEt7AFgCuvyX4a71u8h9jB8tj/ORgOZ7o= +github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE= +github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk= +github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG1KdI/P7A= +github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= +github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= +github.com/go-playground/locales v0.13.0/go.mod h1:taPMhCMXrRLJO55olJkUXHZBHCxTMfnGwq/HNwmWNS8= +github.com/go-playground/universal-translator v0.17.0 h1:icxd5fm+REJzpZx7ZfpaD876Lmtgy7VtROAbHHXk8no= +github.com/go-playground/universal-translator v0.17.0/go.mod h1:UkSxE5sNxxRwHyU+Scu5vgOQjsIJAF8j9muTVoKLVtA= +github.com/go-playground/validator/v10 v10.2.0 h1:KgJ0snyC2R9VXYN2rneOtQcw5aHQB1Vv0sFl1UcHBOY= +github.com/go-playground/validator/v10 v10.2.0/go.mod h1:uOYAAleCW8F/7oMFd6aG0GOhaH6EGOAJShg8Id5JGkI= +github.com/go-redis/redis v6.14.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA= +github.com/go-redis/redis/v7 v7.4.0/go.mod h1:JDNMw23GTyLNC4GZu9njt15ctBQVn7xjRfnwdHj/Dcg= +github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w= +github.com/go-sql-driver/mysql v1.5.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-sql-driver/mysql v1.6.0 h1:BCTh4TKNUYmOmMUcQ3IipzF5prigylS7XXjEkfCHuOE= +github.com/go-sql-driver/mysql v1.6.0/go.mod h1:DCzpHaOWr8IXmIStZouvnhqoel9Qv2LBy8hT2VhHyBg= +github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY= +github.com/gofrs/uuid v3.2.0+incompatible h1:y12jRkkFxsd7GpqdSZ+/KCs/fJbqpEXSGd4+jfEaewE= +github.com/gofrs/uuid v3.2.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= +github.com/gogo/googleapis v1.1.0/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= +github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.0/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ= +github.com/gogo/protobuf v1.2.1/go.mod h1:hp+jE20tsWTFYpLwKvXlhS1hjn+gTNwPg2I6zVXpSg4= +github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= +github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= +github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= +github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A= +github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U= +github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= +github.com/golang/protobuf v1.5.0 h1:LUVKkCeviFUMKqHa4tXIIij/lbhnMbP7Fn5wKdKkRh4= +github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/snappy v0.0.0-20170215233205-553a64147049/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db h1:woRePGFeVFfLKN/pOkfl+p/TAqKOfFu+7KPlMVpok/w= +github.com/golang/snappy v0.0.0-20180518054509-2e65f85255db/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/gomodule/redigo v2.0.0+incompatible/go.mod h1:B4C85qUVwatsJoIUNIfCRsp7qO0iAmpGFZ4EELWSbC4= +github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= +github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M= +github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= +github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= +github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI= +github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= +github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg= +github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/mux v1.7.3/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs= +github.com/gorilla/websocket v0.0.0-20170926233335-4201258b820c/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ= +github.com/gorilla/websocket v1.4.2 h1:+/TMaTYc4QFitKJxsQ7Yye35DkWvkdLcvGKqM+x0Ufc= +github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= +github.com/grpc-ecosystem/go-grpc-middleware v1.0.1-0.20190118093823-f849b5445de4/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs= +github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk= +github.com/grpc-ecosystem/grpc-gateway v1.9.5/go.mod h1:vNeuVxBJEsws4ogUvrchl83t/GYV9WGTSLVdBhOQFDY= +github.com/guonaihong/gout v0.2.1 h1:XnaS92y/Mpcu4MOQU5cx4hTKhbqFznbIE/uUI5sMY9E= +github.com/guonaihong/gout v0.2.1/go.mod h1:JkjNv1G2oRWvFgP/r4DUbYhoeIBB0zMP2j1ID+5CYpU= +github.com/hashicorp/consul/api v1.3.0/go.mod h1:MmDNSzIMUjNpY/mQ398R4bk2FnqQLoPndWW5VkKPlCE= +github.com/hashicorp/consul/sdk v0.3.0/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8= +github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4= +github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80= +github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60= +github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM= +github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk= +github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU= +github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU= +github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4= +github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro= +github.com/hashicorp/go-version v1.2.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= +github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90= +github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8= +github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc= +github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4= +github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64= +github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ= +github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I= +github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc= +github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI= +github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU= +github.com/hudl/fargo v1.3.0/go.mod h1:y3CKSmjA+wD2gak7sUSXTAoopbhU08POFhmITJgmKTg= +github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8= +github.com/influxdata/influxdb1-client v0.0.0-20191209144304-8bf82d3c094d/go.mod h1:qj24IKcXYK6Iy9ceXlo3Tc+vtHo9lIhSX5JddghvEPo= +github.com/jackc/chunkreader v1.0.0 h1:4s39bBR8ByfqH+DKm8rQA3E1LHZWB9XWcrz8fqaZbe0= +github.com/jackc/chunkreader v1.0.0/go.mod h1:RT6O25fNZIuasFJRyZ4R/Y2BbhasbmZXF9QQ7T3kePo= +github.com/jackc/chunkreader/v2 v2.0.0/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/chunkreader/v2 v2.0.1 h1:i+RDz65UE+mmpjTfyz0MoVTnzeYxroil2G82ki7MGG8= +github.com/jackc/chunkreader/v2 v2.0.1/go.mod h1:odVSm741yZoC3dpHEUXIqA9tQRhFrgOHwnPIn9lDKlk= +github.com/jackc/pgconn v0.0.0-20190420214824-7e0022ef6ba3/go.mod h1:jkELnwuX+w9qN5YIfX0fl88Ehu4XC3keFuOJJk9pcnA= +github.com/jackc/pgconn v0.0.0-20190824142844-760dd75542eb/go.mod h1:lLjNuW/+OfW9/pnVKPazfWOgNfH2aPem8YQ7ilXGvJE= +github.com/jackc/pgconn v0.0.0-20190831204454-2fabfa3c18b7/go.mod h1:ZJKsE/KZfsUgOEh9hBm+xYTstcNHg7UPMVJqRfQxq4s= +github.com/jackc/pgconn v1.4.0/go.mod h1:Y2O3ZDF0q4mMacyWV3AstPJpeHXWGEetiFttmq5lahk= +github.com/jackc/pgconn v1.5.0/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= +github.com/jackc/pgconn v1.5.1-0.20200601181101-fa742c524853/go.mod h1:QeD3lBfpTFe8WUnPZWN5KY/mB8FGMIYRdd8P8Jr0fAI= +github.com/jackc/pgconn v1.8.1 h1:ySBX7Q87vOMqKU2bbmKbUvtYhauDFclYbNDYIE1/h6s= +github.com/jackc/pgconn v1.8.1/go.mod h1:JV6m6b6jhjdmzchES0drzCcYcAHS1OPD5xu3OZ/lE2g= +github.com/jackc/pgio v1.0.0 h1:g12B9UwVnzGhueNavwioyEEpAmqMe1E/BN9ES+8ovkE= +github.com/jackc/pgio v1.0.0/go.mod h1:oP+2QK2wFfUWgr+gxjoBH9KGBb31Eio69xUb0w5bYf8= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2 h1:JVX6jT/XfzNqIjye4717ITLaNwV9mWbJx0dLCpcRzdA= +github.com/jackc/pgmock v0.0.0-20190831213851-13a1b77aafa2/go.mod h1:fGZlG77KXmcq05nJLRkk0+p82V8B8Dw8KN2/V9c/OAE= +github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= +github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg= +github.com/jackc/pgproto3 v1.1.0 h1:FYYE4yRw+AgI8wXIinMlNjBbp/UitDJwfj5LqqewP1A= +github.com/jackc/pgproto3 v1.1.0/go.mod h1:eR5FA3leWg7p9aeAqi37XOTgTIbkABlvcPB3E5rlc78= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190420180111-c116219b62db/go.mod h1:bhq50y+xrl9n5mRYyCBFKkpRVTLYJVWeCc+mEAI3yXA= +github.com/jackc/pgproto3/v2 v2.0.0-alpha1.0.20190609003834-432c2951c711/go.mod h1:uH0AWtUmuShn0bcesswc4aBTWGvw0cAxIJp+6OB//Wg= +github.com/jackc/pgproto3/v2 v2.0.0-rc3/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.0-rc3.0.20190831210041-4c03ce451f29/go.mod h1:ryONWYqW6dqSg1Lw6vXNMXoBJhpzvWKnT95C46ckYeM= +github.com/jackc/pgproto3/v2 v2.0.1/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgproto3/v2 v2.0.6 h1:b1105ZGEMFe7aCvrT1Cca3VoVb4ZFMaFJLJcg/3zD+8= +github.com/jackc/pgproto3/v2 v2.0.6/go.mod h1:WfJCnwN3HIg9Ish/j3sgWXnAfK8A9Y0bwXYU5xKaEdA= +github.com/jackc/pgservicefile v0.0.0-20200307190119-3430c5407db8/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b h1:C8S2+VttkHFdOOCXJe+YGfa4vHYwlt4Zx+IVXQ97jYg= +github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b/go.mod h1:vsD4gTJCa9TptPL8sPkXrLZ+hDuNrZCnj29CQpr4X1E= +github.com/jackc/pgtype v0.0.0-20190421001408-4ed0de4755e0/go.mod h1:hdSHsc1V01CGwFsrv11mJRHWJ6aifDLfdV3aVjFF0zg= +github.com/jackc/pgtype v0.0.0-20190824184912-ab885b375b90/go.mod h1:KcahbBH1nCMSo2DXpzsoWOAfFkdEtEJpPbVLq8eE+mc= +github.com/jackc/pgtype v0.0.0-20190828014616-a8802b16cc59/go.mod h1:MWlu30kVJrUS8lot6TQqcg7mtthZ9T0EoIBFiJcmcyw= +github.com/jackc/pgtype v1.2.0/go.mod h1:5m2OfMh1wTK7x+Fk952IDmI4nw3nPrvtQdM0ZT4WpC0= +github.com/jackc/pgtype v1.3.1-0.20200510190516-8cd94a14c75a/go.mod h1:vaogEUkALtxZMCH411K+tKzNpwzCKU+AnPzBKZ+I+Po= +github.com/jackc/pgtype v1.3.1-0.20200606141011-f6355165a91c/go.mod h1:cvk9Bgu/VzJ9/lxTO5R5sf80p0DiucVtN7ZxvaC4GmQ= +github.com/jackc/pgtype v1.7.0 h1:6f4kVsW01QftE38ufBYxKciO6gyioXSC0ABIRLcZrGs= +github.com/jackc/pgtype v1.7.0/go.mod h1:ZnHF+rMePVqDKaOfJVI4Q8IVvAQMryDlDkZnKOI75BE= +github.com/jackc/pgx/v4 v4.0.0-20190420224344-cc3461e65d96/go.mod h1:mdxmSJJuR08CZQyj1PVQBHy9XOp5p8/SHH6a0psbY9Y= +github.com/jackc/pgx/v4 v4.0.0-20190421002000-1b8f0016e912/go.mod h1:no/Y67Jkk/9WuGR0JG/JseM9irFbnEPbuWV2EELPNuM= +github.com/jackc/pgx/v4 v4.0.0-pre1.0.20190824185557-6972a5742186/go.mod h1:X+GQnOEnf1dqHGpw7JmHqHc1NxDoalibchSk9/RWuDc= +github.com/jackc/pgx/v4 v4.5.0/go.mod h1:EpAKPLdnTorwmPUUsqrPxy5fphV18j9q3wrfRXgo+kA= +github.com/jackc/pgx/v4 v4.6.1-0.20200510190926-94ba730bb1e9/go.mod h1:t3/cdRQl6fOLDxqtlyhe9UWgfIi9R8+8v8GKV5TRA/o= +github.com/jackc/pgx/v4 v4.6.1-0.20200606145419-4e5062306904/go.mod h1:ZDaNWkt9sW1JMiNn0kdYBaLelIhw7Pg4qd+Vk6tw7Hg= +github.com/jackc/pgx/v4 v4.11.0 h1:J86tSWd3Y7nKjwT/43xZBvpi04keQWx8gNC2YkdJhZI= +github.com/jackc/pgx/v4 v4.11.0/go.mod h1:i62xJgdrtVDsnL3U8ekyrQXEwGNTRoG7/8r+CIdYfcc= +github.com/jackc/puddle v0.0.0-20190413234325-e4ced69a3a2b/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v0.0.0-20190608224051-11cab39313c9/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.0/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.1/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jackc/puddle v1.1.3/go.mod h1:m4B5Dj62Y0fbyuIc15OsIqK0+JU8nkqQjsgx7dvjSWk= +github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= +github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= +github.com/jinzhu/now v1.1.1/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jinzhu/now v1.1.2 h1:eVKgfIdy9b6zbWBMgFpfDPoAMifwSZagU9HmEU6zgiI= +github.com/jinzhu/now v1.1.2/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= +github.com/jmespath/go-jmespath v0.0.0-20180206201540-c2b33e8439af/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= +github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= +github.com/jonboulle/clockwork v0.2.2 h1:UOGuzwb1PwsrDAObMuhUnj0p5ULPj8V/xJ7Kx9qUBdQ= +github.com/jonboulle/clockwork v0.2.2/go.mod h1:Pkfl5aHPm1nk2H9h0bjmnJD/BcgbGXUBGnn1kMkgxc8= +github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= +github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.8/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.10/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +github.com/json-iterator/go v1.1.11 h1:uVUAXhF2To8cbw/3xN3pxj6kk7TYKs98NIrTqPlMWAQ= +github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= +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/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 h1:iQTw/8FWTuc7uiaSepXwyf3o52HaUYcV+Tu66S3F5GA= +github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0/go.mod h1:1NbS8ALrpOvjt0rHPNLyCIeMtbizbir8U//inJ+zuB8= +github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvWXihfKN4Q= +github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= +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/konsorten/go-windows-terminal-sequences v1.0.2/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/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= +github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= +github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw= +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/ledisdb/ledisdb v0.0.0-20200510135210-d35789ec47e6/go.mod h1:n931TsDuKuq+uX4v1fulaMbA/7ZLLhjc85h7chZGBCQ= +github.com/leodido/go-urn v1.2.0/go.mod h1:+8+nEpDfqqsY+g338gtMEUOtuK+4dEMhiQEgxpxOKII= +github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w= +github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc h1:RKf14vYWi2ttpEmkA4aQ3j4u9dStX2t4M8UM6qqNsG8= +github.com/lestrrat-go/envload v0.0.0-20180220234015-a3eb8ddeffcc/go.mod h1:kopuH9ugFRkIXf3YoqHKyrJ9YfUFsckUU9S7B+XP+is= +github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible h1:Y6sqxHMyB1D2YSzWkLibYKgg+SwmyFU9dF2hn6MdTj4= +github.com/lestrrat-go/file-rotatelogs v2.4.0+incompatible/go.mod h1:ZQnN8lSECaebrkQytbHj4xNgtg8CR7RYXnPok8e0EHA= +github.com/lestrrat-go/strftime v1.0.4 h1:T1Rb9EPkAhgxKqbcMIPguPq8glqXTA1koF8n9BHElA8= +github.com/lestrrat-go/strftime v1.0.4/go.mod h1:E1nN3pCbtMSu1yjSVeyuRFVm/U0xoR76fd03sz+Qz4g= +github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lib/pq v1.3.0 h1:/qkRGz8zljWiDcFvgpwUpwIAPu3r07TDvs3Rws+o/pU= +github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo= +github.com/lightstep/lightstep-tracer-common/golang/gogo v0.0.0-20190605223551-bc2310a04743/go.mod h1:qklhhLq1aX+mtWk9cPHPzaBjWImj5ULL6C7HFJtXQMM= +github.com/lightstep/lightstep-tracer-go v0.18.1/go.mod h1:jlF1pusYV4pidLvZ+XD0UBX0ZE6WURAspgAczcDHrL4= +github.com/lyft/protoc-gen-validate v0.0.13/go.mod h1:XbGvPuh87YZc5TdIa2/I4pLk0QoUACkjt2znoq26NVQ= +github.com/maruel/rs v0.0.0-20150922171536-2c81c4312fe4 h1:u9jwvcKbQpghIXgNl/EOL8hzhAFXh4ePrEP493W3tNA= +github.com/maruel/rs v0.0.0-20150922171536-2c81c4312fe4/go.mod h1:kcRFpEzolcEklV6rD7W95mG49/sbdX/PlFmd7ni3RvA= +github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= +github.com/mattn/go-colorable v0.1.1/go.mod h1:FuOcm+DKB9mbwrcAfNl7/TZVBZ6rcnceauSikq3lYCQ= +github.com/mattn/go-colorable v0.1.2/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= +github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-colorable v0.1.8 h1:c1ghPdyEDarC70ftn0y+A/Ee++9zz8ljHG1b13eJ0s8= +github.com/mattn/go-colorable v0.1.8/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= +github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= +github.com/mattn/go-isatty v0.0.5/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= +github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= +github.com/mattn/go-isatty v0.0.12 h1:wuysRhFDzyxgEmMf5xjvJ2M9dZoWAXNNr5LSBS7uHXY= +github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= +github.com/mattn/go-runewidth v0.0.2/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= +github.com/mattn/go-sqlite3 v1.14.5/go.mod h1:WVKg1VTActs4Qso6iwGbiFih2UIHo0ENGwNd0Lj+XmI= +github.com/mattn/go-sqlite3 v2.0.3+incompatible h1:gXHsfypPkaMZrKbD5209QV9jbUTJKjyR5WD3HYQSd+U= +github.com/mattn/go-sqlite3 v2.0.3+incompatible/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc= +github.com/matttproud/golang_protobuf_extensions v1.0.1 h1:4hp9jkHxhMHkqkrB3Ix0jegS5sx/RkqARlsWZ6pIwiU= +github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= +github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg= +github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc= +github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= +github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI= +github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg= +github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY= +github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= +github.com/mitchellh/mapstructure v1.3.3 h1:SzB1nHZ2Xi+17FP0zVQBHIZqvwRN9408fJO8h+eeNA8= +github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= +github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= +github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= +github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9AWI= +github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0= +github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U= +github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= +github.com/nats-io/jwt v0.3.2/go.mod h1:/euKqTS1ZD+zzjYrY7pseZrTtWQSjujC7xjPc8wL6eU= +github.com/nats-io/nats-server/v2 v2.1.2/go.mod h1:Afk+wRZqkMQs/p45uXdrVLuab3gwv3Z8C4HTBu8GD/k= +github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= +github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nkeys v0.1.3/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= +github.com/nats-io/nuid v1.0.1/go.mod h1:19wcPz3Ph3q0Jbyiqsd0kePYG7A95tJPxeL+1OSON2c= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs= +github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= +github.com/oklog/oklog v0.3.2/go.mod h1:FCV+B7mhrz4o+ueLpx+KqkyXRGMWOYEvfiXtdGtbWGs= +github.com/oklog/run v1.0.0/go.mod h1:dlhp/R75TPv97u0XWUtDeV/lRKWPKSdTuV0TZvrmrQA= +github.com/olekukonko/tablewriter v0.0.0-20170122224234-a0225b3f23b5/go.mod h1:vsDQFd/mU46D+Z4whnwzcISnGGzXWMclvtLoiIKAKIo= +github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.7.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.10.1/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE= +github.com/onsi/ginkgo v1.12.0 h1:Iw5WCbBcaAAd0fpRb1c9r5YCylv4XDoCSigm1zLevwU= +github.com/onsi/ginkgo v1.12.0/go.mod h1:oUhWkIvk5aDxtKvDDuw8gItl8pKl42LzjC9KZE0HfGg= +github.com/onsi/gomega v1.4.3/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.0/go.mod h1:ex+gbHU/CVuBBDIJjb2X0qEXbFg53c61hWP/1CpauHY= +github.com/onsi/gomega v1.7.1 h1:K0jcRCwNQM3vFGh1ppMtDh/+7ApJrjldlX8fA0jDTLQ= +github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY= +github.com/op/go-logging v0.0.0-20160315200505-970db520ece7/go.mod h1:HzydrMdWErDVzsI23lYNej1Htcns9BCg93Dk0bBINWk= +github.com/opentracing-contrib/go-observer v0.0.0-20170622124052-a52f23424492/go.mod h1:Ngi6UdF0k5OKD5t5wlmGhe/EDKPoUM3BXZSSfIuJbis= +github.com/opentracing/basictracer-go v1.0.0/go.mod h1:QfBfYuafItcjQuMwinw9GhYKwFXS9KnPs5lxoYwgW74= +github.com/opentracing/opentracing-go v1.0.2/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.1.0/go.mod h1:UkNAQd3GIcIGf0SeVgPpRdFStlNbqXla1AfSYxPUl2o= +github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= +github.com/openzipkin-contrib/zipkin-go-opentracing v0.4.5/go.mod h1:/wsWhb9smxSfWAKL3wpBW7V8scJMt8N8gnaMCS9E/cA= +github.com/openzipkin/zipkin-go v0.1.6/go.mod h1:QgAqvLzwWbR/WpD4A3cGpPtJrZXNIiJc5AZX7/PBEpw= +github.com/openzipkin/zipkin-go v0.2.1/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/openzipkin/zipkin-go v0.2.2/go.mod h1:NaW6tEwdmWMaCDZzg8sh+IBNOxHMPnhQw8ySjnjRyN4= +github.com/pact-foundation/pact-go v1.0.4/go.mod h1:uExwJY4kCzNPcHRj+hCR/HBbOOIwwtUjcrb0b5/5kLM= +github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc= +github.com/pborman/uuid v1.2.0/go.mod h1:X/NO0urCmaxf9VXbdlT7C2Yzkj2IKimNn4k+gtPdI/k= +github.com/pelletier/go-toml v1.0.1/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= +github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= +github.com/performancecopilot/speed v3.0.0+incompatible/go.mod h1:/CLtqpZ5gBg1M9iaPbIdPPGyKcA8hKdoy6hAWba7Yac= +github.com/peterh/liner v1.0.1-0.20171122030339-3681c2a91233/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc= +github.com/pierrec/lz4 v1.0.2-0.20190131084431-473cd7ce01a1/go.mod h1:3/3N9NVKO0jef7pBehbT1qWhCMrIgbYNnFAZCqQ5LRc= +github.com/pierrec/lz4 v2.0.5+incompatible/go.mod h1:pdkljMzZIN41W+lC3N2tnIh5sFi+IEE17M5jbnwPHcY= +github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= +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/pkg/profile v1.2.1/go.mod h1:hJw3o1OdXxsrSjjVksARp5W95eeEaEfptyVZyv6JUPA= +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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI= +github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= +github.com/prometheus/client_golang v0.9.3-0.20190127221311-3c4408c8b829/go.mod h1:p2iRAGwDERtqlqzRXnrOVns+ignqQo//hLXqYxZYVNs= +github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= +github.com/prometheus/client_golang v1.3.0/go.mod h1:hJaj2vgQTGQmVCsAACORcieXFeDPbaTKGT+JTgUa3og= +github.com/prometheus/client_golang v1.7.0 h1:wCi7urQOGBsYcQROHqpUUX4ct84xp40t9R9JX0FuA/U= +github.com/prometheus/client_golang v1.7.0/go.mod h1:PY5Wy2awLA44sXw4AOSfFBetzPP4j5+D6mVACh+pe2M= +github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190115171406-56726106282f/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo= +github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.1.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/client_model v0.2.0 h1:uq5h0d+GuxiXLJLNABMgp2qUWDPiLvgCzz2dUR+/W/M= +github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA= +github.com/prometheus/common v0.2.0/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4= +github.com/prometheus/common v0.7.0/go.mod h1:DjGbpBbp5NYNiECxcL/VnbXCCaQpKd3tt26CguLLsqA= +github.com/prometheus/common v0.10.0 h1:RyRA7RzGXQZiW+tGMr7sxa85G1z0yOpM1qq5c8lNawc= +github.com/prometheus/common v0.10.0/go.mod h1:Tlit/dnDKsSWFlCLTWaA1cyBgKHSMdTB80sz/V91rCo= +github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.0-20190117184657-bf6a532e95b1/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk= +github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA= +github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A= +github.com/prometheus/procfs v0.1.3 h1:F0+tqvhOksq22sc6iCHF5WGlWjdwj92p0udFh1VFBS8= +github.com/prometheus/procfs v0.1.3/go.mod h1:lV6e/gmhEcM9IjHGsFOCxxuZ+z1YqCvr4OA4YeYWdaU= +github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk= +github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= +github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= +github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= +github.com/rogpeppe/fastuuid v0.0.0-20150106093220-6724a57986af/go.mod h1:XWv6SoW27p1b0cqNHllgS5HIMJraePCO15w5zCzIWYg= +github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4= +github.com/rs/xid v1.2.1/go.mod h1:+uKXf+4Djp6Md1KODXJxgGQPKngRmWyn10oCKFzNHOQ= +github.com/rs/zerolog v1.13.0/go.mod h1:YbFCdg8HfsridGWAh22vktObvhZbQsZXe4/zB0OKkWU= +github.com/rs/zerolog v1.15.0/go.mod h1:xYTKnLHcpfU2225ny5qZjxnj9NvkumZYjJHlAThCjNc= +github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= +github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= +github.com/samuel/go-zookeeper v0.0.0-20190923202752-2cc03de413da/go.mod h1:gi+0XIa01GRL2eRQVjQkKGqKF3SF9vZR/HnPullcV2E= +github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0= +github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc= +github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644 h1:X+yvsM2yrEktyI+b2qND5gpH8YhURn0k8OCaeRnkINo= +github.com/shiena/ansicolor v0.0.0-20151119151921-a422bbe96644/go.mod h1:nkxAfR/5quYxwPZhyDxgasBMnRtBZd0FCEpawpjMUFg= +github.com/shopspring/decimal v0.0.0-20180709203117-cd690d0c9e24/go.mod h1:M+9NzErvs504Cn4c5DxATwIqPbtswREoFCre64PpcG4= +github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc h1:jUIKcSPO9MoMJBbEoyE/RJoE8vz7Mb8AjvifMMwSyvY= +github.com/shopspring/decimal v0.0.0-20200227202807-02e2044944cc/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o= +github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= +github.com/siddontang/go v0.0.0-20170517070808-cb568a3e5cc0/go.mod h1:3yhqj7WBBfRhbBlzyOC3gUxftwsU0u8gqevxwIHQpMw= +github.com/siddontang/goredis v0.0.0-20150324035039-760763f78400/go.mod h1:DDcKzU3qCuvj/tPnimWSsZZzvk9qvkvrIL5naVBPh5s= +github.com/siddontang/rdb v0.0.0-20150307021120-fc89ed2e418d/go.mod h1:AMEsy7v5z92TR1JKMkLLoaOQk++LVnOKL3ScbJ8GNGA= +github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo= +github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q= +github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE= +github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/sirupsen/logrus v1.8.1 h1:dJKuHgqk1NNQlqoA6BTlM1Wf9DOH3NBjQyu0h9+AZZE= +github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e h1:MRM5ITcdelLK2j1vwZ3Je0FKVCfqOLp5zO6trqMLYs0= +github.com/skip2/go-qrcode v0.0.0-20200617195104-da1b6568686e/go.mod h1:XV66xRDqSt+GTGFMVlhk3ULuV0y9ZmzeVGR4mloJI3M= +github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= +github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA= +github.com/soheilhy/cmux v0.1.4/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM= +github.com/sony/gobreaker v0.4.1/go.mod h1:ZKptC7FHNvhBz7dN2LGjPVBz2sZJmc0/PkyDJOjmxWY= +github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= +github.com/spf13/pflag v1.0.1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4= +github.com/ssdb/gossdb v0.0.0-20180723034631-88f6b59b84ec/go.mod h1:QBvMkMya+gXctz3kmljlUCu/yB3GZ6oee+dUozsezQE= +github.com/streadway/amqp v0.0.0-20190404075320-75d898a42a94/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/amqp v0.0.0-20190827072141-edfb9018d271/go.mod h1:AZpEONHx3DKn8O/DFsRAY58/XVQiIPMTMB1SddzLXVw= +github.com/streadway/handy v0.0.0-20190108123426-d5acb3125c2a/go.mod h1:qNTQ5P5JnDBl6z3cMAg/SywNDC5ABu5ApDIw6lUbRmI= +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/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= +github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= +github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= +github.com/syndtr/goleveldb v0.0.0-20160425020131-cfa635847112/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/syndtr/goleveldb v0.0.0-20181127023241-353a9fca669c/go.mod h1:Z4AUp2Km+PwemOoO/VB5AOx9XSsIItzFjoJlOSiYmn0= +github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE= +github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= +github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816 h1:J6v8awz+me+xeb/cUTotKgceAYouhIB3pjzgRd6IlGk= +github.com/t-tomalak/logrus-easy-formatter v0.0.0-20190827215021-c074f06c5816/go.mod h1:tzym/CEb5jnFI+Q0k4Qq3+LvRF4gO3E2pxS8fHP8jcA= +github.com/tidwall/gjson v1.8.1 h1:8j5EE9Hrh3l9Od1OIEDAb7IpezNA20UdRngNAj5N0WU= +github.com/tidwall/gjson v1.8.1/go.mod h1:5/xDoumyyDNerp2U36lyolv46b3uF/9Bu6OfyQ9GImk= +github.com/tidwall/match v1.0.3 h1:FQUVvBImDutD8wJLN6c5eMzWtjgONK9MwIBCOrUJKeE= +github.com/tidwall/match v1.0.3/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= +github.com/tidwall/pretty v1.1.0 h1:K3hMW5epkdAVwibsQEfR/7Zj0Qgt4DxtNumTq/VloO8= +github.com/tidwall/pretty v1.1.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk= +github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U= +github.com/tuotoo/qrcode v0.0.0-20190222102259-ac9c44189bf2 h1:BWVtt2VBY+lmVDu9MGKqLGKl04B+iRHcrW1Ptyi/8tg= +github.com/tuotoo/qrcode v0.0.0-20190222102259-ac9c44189bf2/go.mod h1:lPnW9HVS0vJdeYyQtOvIvlXgZPNhUAhwz+z5r8AJk0Y= +github.com/ugorji/go v0.0.0-20171122102828-84cb69a8af83/go.mod h1:hnLbHMwcvSihnDhEfx2/BzKp2xb0Y+ErdfYcrs9tkJQ= +github.com/ugorji/go v1.1.7 h1:/68gy2h+1mWMrwZFeD1kQialdSzAb432dtpeJ42ovdo= +github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= +github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs= +github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= +github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= +github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= +github.com/wdvxdr1123/go-silk v0.0.0-20210316130616-d47b553def60 h1:lRKf10iIOW0VsH5WDF621ihzR+R2wEBZVtNRHuLLCb4= +github.com/wdvxdr1123/go-silk v0.0.0-20210316130616-d47b553def60/go.mod h1:ecFKZPX81BaB70I6ruUgEwYcDOtuNgJGnjdK+MIl5ko= +github.com/wendal/errors v0.0.0-20130201093226-f66c77a7882b/go.mod h1:Q12BUT7DqIlHRmgv3RskH+UCM/4eqVMgI0EMmlSpAXc= +github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= +github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= +github.com/yuin/gopher-lua v0.0.0-20171031051903-609c9cd26973/go.mod h1:aEV29XrmTYFr3CiRxZeGHpkvbwq+prZduBqMaascyCU= +github.com/zenazn/goji v0.9.0/go.mod h1:7S9M489iMyHBNxwZnk9/EHS098H4/F6TATF2mIxtB1Q= +go.etcd.io/bbolt v1.3.3/go.mod h1:IbVyRI1SCnLcuJnV2u8VeU0CEYM7e686BmAb1XKL+uU= +go.etcd.io/etcd v0.0.0-20191023171146-3cf2f69b5738/go.mod h1:dnLIgRNXwCJa5e+c6mIZCrds/GIG4ncV9HhK5PX7jPg= +go.etcd.io/etcd v3.3.25+incompatible/go.mod h1:yaeTdrJi5lOmYerz05bd8+V7KubZs8YSFZfzsF9A6aI= +go.opencensus.io v0.20.1/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.20.2/go.mod h1:6WKK9ahsWS3RSO+PY9ZHZUfv2irvY6gN279GOPZjmmk= +go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw= +go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= +go.uber.org/atomic v1.5.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/atomic v1.6.0/go.mod h1:sABNBOSYdrvTF6hTgEIbc7YasKWGhgEQZyfxyTvoXHQ= +go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= +go.uber.org/multierr v1.3.0/go.mod h1:VgVr7evmIr6uPjLBxg28wmKNXyqE9akIJ5XnfpiKl+4= +go.uber.org/multierr v1.5.0/go.mod h1:FeouvMocqHpRaaGuG9EjoKcStLC43Zu/fmqdUMPcKYU= +go.uber.org/tools v0.0.0-20190618225709-2cfd321de3ee/go.mod h1:vJERXedbb3MVM5f9Ejo0C68/HhF8uaILCdgjnY+goOA= +go.uber.org/zap v1.9.1/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= +go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM= +go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc= +golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4= +golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= +golang.org/x/crypto v0.0.0-20190411191339-88737f569e3a/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= +golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= +golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e h1:gsTQYXdTw2Gq7RBsWvlQ91b+aEQ6bXFUngBGuR8sPpI= +golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= +golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= +golang.org/x/image v0.0.0-20210628002857-a66eb6448b8d/go.mod h1:023OzeP/+EPmXeapQh35lcL3II3LrY8Ic+EFFKVhULM= +golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= +golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= +golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= +golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY= +golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc= +golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= +golang.org/x/mod v0.3.0 h1:RM4zey1++hCTbCVQfnWeKs9/IEsaBLA8vTkd0WVtmH4= +golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= +golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20181220203305-927f97764cc3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190125091013-d26f9f9a57f3/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= +golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= +golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= +golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= +golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210505024714-0287a6fb4125/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e h1:XpT3nA5TvE525Ne3hInMh6+GETgn27Zfm9dxsThnX2Q= +golang.org/x/net v0.0.0-20210614182718-04defd469f4e/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= +golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= +golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= +golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20181122145206-62eef0e2fa9b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= +golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20190826190057-c7b8b68b1456/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191010194322-b09406accb47/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191120155948-bd437916bb0e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20191220142924-d4481acd189f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200106162015-b016eb3dc98e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200615200032-f1bc736245b1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20201126233918-771906719818/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1 h1:SrN+KX8Art/Sf4HNj6Zcz06G7VEz+7w9tdXTPOZ7+l4= +golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b h1:9zKuko04nR4gjZ4+DNjHqRlAJqbJETHwiNKDqTfOjfE= +golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= +golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= +golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6 h1:Vv0JUPWTyeqUq42B2WJ1FeIDjjvGKoA2Ss+Ts0lAVbs= +golang.org/x/time v0.0.0-20210611083556-38a9dc6acbc6/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= +golang.org/x/tools v0.0.0-20180221164845-07fd8470d635/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180828015842-6cd1fcedba52/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= +golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY= +golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs= +golang.org/x/tools v0.0.0-20190425163242-31fd60d6bfdc/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= +golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= +golang.org/x/tools v0.0.0-20190823170909-c4a336ef6a2f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029041327-9cc4af7d6b2c/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191029190741-b9c20aec41a5/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= +golang.org/x/tools v0.0.0-20200103221440-774c71fcf114/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58 h1:1Bs6RVeBFtLZ8Yi1Hk07DiOqzvwLD/4hln4iahvFlag= +golang.org/x/tools v0.0.0-20201211185031-d93e913c1a58/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/xerrors v0.0.0-20190410155217-1f06c39b4373/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190513163551-3ee3066db522/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE= +golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= +google.golang.org/api v0.3.1/go.mod h1:6wY9I6uQWHQ8EM57III9mq/AjF+i8G65rmVagqKMtkk= +google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= +google.golang.org/appengine v1.2.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= +google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= +google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE= +google.golang.org/genproto v0.0.0-20190530194941-fb225487d101/go.mod h1:z3L6/3dTEVtUr6QSP8miRzeRqwQOioJ9I66odjN4I7s= +google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= +google.golang.org/grpc v1.17.0/go.mod h1:6QZJwpn2B+Zp71q/5VxRsJ6NXXVCE5NRUHRo+f3cWCs= +google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= +google.golang.org/grpc v1.20.0/go.mod h1:chYK+tFQF0nDUGJgXMSgLCQk3phJEuONr2DCgLDdAQM= +google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= +google.golang.org/grpc v1.21.0/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= +google.golang.org/grpc v1.22.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.23.1/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= +google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= +google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= +google.golang.org/protobuf v1.26.0 h1:bxAC2xTBsZGibn2RTntX0oH50xLsqy1OxA9tTL3p/lk= +google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= +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/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU= +gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= +gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= +gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= +gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4= +gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= +gopkg.in/gcfg.v1 v1.2.3/go.mod h1:yesOnuUOFQAhST5vPY4nbZsb/huCgGGXlipJsBn0b3o= +gopkg.in/go-playground/assert.v1 v1.2.1 h1:xoYuJVE7KT85PYWrN730RguIQO0ePzVRfFMXadIrXTM= +gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE= +gopkg.in/go-playground/validator.v9 v9.31.0 h1:bmXmP2RSNtFES+bn4uYuHT7iJFJv7Vj+an+ZQdDaD1M= +gopkg.in/go-playground/validator.v9 v9.31.0/go.mod h1:+c9/zcJMFNgbLvly1L1V+PpxWdVbfP1avr/N00E2vyQ= +gopkg.in/inconshreveable/log15.v2 v2.0.0-20180818164646-67afb5ed74ec/go.mod h1:aPpfJ7XW+gOuirDoZ8gHhLh3kZ1B08FtV2bbmy7Jv3s= +gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA= +gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ= +gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw= +gopkg.in/tucnak/telebot.v2 v2.3.5 h1:TdMJTlG8kvepsvZdy/gPeYEBdwKdwFFjH1AQTua9BOU= +gopkg.in/tucnak/telebot.v2 v2.3.5/go.mod h1:BgaIIx50PSRS9pG59JH+geT82cfvoJU/IaI5TJdN3v8= +gopkg.in/warnings.v0 v0.1.2/go.mod h1:jksf8JmL6Qr/oQM2OXTHunEvvTAsrWBLb6OOjuVWRNI= +gopkg.in/yaml.v2 v2.0.0-20170812160011-eb3733d160e7/go.mod h1:JAlM8MvJe8wmxCU4Bli9HhUf9+ttbYbLASfIpnQbh74= +gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v2 v2.2.8 h1:obN1ZagJSUGI0Ek/LBmuj4SNLPfIny3KsKFopxRdj10= +gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= +gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= +gorm.io/driver/mysql v1.1.2 h1:OofcyE2lga734MxwcCW9uB4mWNXMr50uaGRVwQL2B0M= +gorm.io/driver/mysql v1.1.2/go.mod h1:4P/X9vSc3WTrhTLZ259cpFd6xKNYiSSdSZngkSBGIMM= +gorm.io/driver/postgres v1.1.0 h1:afBljg7PtJ5lA6YUWluV2+xovIPhS+YiInuL3kUjrbk= +gorm.io/driver/postgres v1.1.0/go.mod h1:hXQIwafeRjJvUm+OMxcFWyswJ/vevcpPLlGocwAwuqw= +gorm.io/driver/sqlite v1.1.4 h1:PDzwYE+sI6De2+mxAneV9Xs11+ZyKV6oxD3wDGkaNvM= +gorm.io/driver/sqlite v1.1.4/go.mod h1:mJCeTFr7+crvS+TRnWc5Z3UvwxUN1BGBLMrf5LA9DYw= +gorm.io/gorm v1.20.7/go.mod h1:0HFTzE/SqkGTzK6TlDPPQbAYCluiVvhzoA1+aVyzenw= +gorm.io/gorm v1.21.9/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= +gorm.io/gorm v1.21.12/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= +gorm.io/gorm v1.21.13 h1:JU5A4yVemRjdMndJ0oZU7VX+Nr2ICE3C60U5bgR6mHE= +gorm.io/gorm v1.21.13/go.mod h1:F+OptMscr0P2F2qU97WT1WimdH9GaQPoDW7AYd5i2Y0= +honnef.co/go/tools v0.0.0-20180728063816-88497007e858/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= +honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg= +honnef.co/go/tools v0.0.1-2020.1.5/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k= +modernc.org/libc v1.8.1 h1:y9oPIhwcaFXxX7kMp6Qb2ZLKzr0mDkikWN3CV5GS63o= +modernc.org/libc v1.8.1/go.mod h1:U1eq8YWr/Kc1RWCMFUWEdkTg8OTcfLw2kY8EDwl039w= +modernc.org/mathutil v1.1.1/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/mathutil v1.2.2 h1:+yFk8hBprV+4c0U9GjFtL+dV3N8hOJ8JCituQcMShFY= +modernc.org/mathutil v1.2.2/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E= +modernc.org/memory v1.0.4 h1:utMBrFcpnQDdNsmM6asmyH/FM9TqLPS7XF7otpJmrwM= +modernc.org/memory v1.0.4/go.mod h1:nV2OApxradM3/OVbs2/0OsP6nPfakXpi50C7dcoHXlc= +sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o= +sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU= diff --git a/lastupdate.tmp b/lastupdate.tmp new file mode 100755 index 0000000..0433245 --- /dev/null +++ b/lastupdate.tmp @@ -0,0 +1 @@ +{"/Users/cdle/Desktop/jd_study/jdc/controllers":1627349014997994106} \ No newline at end of file diff --git a/main.go b/main.go new file mode 100644 index 0000000..1ee2d46 --- /dev/null +++ b/main.go @@ -0,0 +1,78 @@ +package main + +import ( + "io/ioutil" + "os" + "strings" + "time" + + "github.com/beego/beego/v2/client/httplib" + "github.com/beego/beego/v2/core/logs" + "github.com/beego/beego/v2/server/web/context" + + "github.com/beego/beego/v2/server/web" + "github.com/cdle/xdd/controllers" + "github.com/cdle/xdd/models" + "github.com/cdle/xdd/qbot" +) + +var theme = "" + +func main() { + go func() { + models.Save <- &models.JdCookie{} + }() + web.Get("/count", func(ctx *context.Context) { + ctx.WriteString(models.Count()) + }) + web.Get("/", func(ctx *context.Context) { + if models.Config.Theme == "" { + models.Config.Theme = models.GhProxy + "https://raw.githubusercontent.com/U188/web/main/random.html" + } + if theme != "" { + ctx.WriteString(theme) + return + } + if strings.Contains(models.Config.Theme, "http") { + logs.Info("下载最新主题") + s, _ := httplib.Get(models.Config.Theme).String() + if s != "" { + theme = s + ctx.WriteString(s) + return + } + logs.Warn("主题下载失败,使用默认主题") + } + f, err := os.Open(models.Config.Theme) + if err == nil { + d, _ := ioutil.ReadAll(f) + theme = string(d) + ctx.WriteString(string(d)) + return + } + }) + web.Router("/api/login/qrcode", &controllers.LoginController{}, "get:GetQrcode") + web.Router("/api/login/qrcode.png", &controllers.LoginController{}, "get:GetQrcode") + web.Router("/api/login/query", &controllers.LoginController{}, "get:Query") + web.Router("/api/account", &controllers.AccountController{}, "get:List") + web.Router("/api/account", &controllers.AccountController{}, "post:CreateOrUpdate") + web.Router("/admin", &controllers.AccountController{}, "get:Admin") + if models.Config.Static == "" { + models.Config.Static = "./static" + } + web.BConfig.WebConfig.StaticDir["/static"] = models.Config.Static + web.BConfig.AppName = models.AppName + web.BConfig.WebConfig.AutoRender = false + web.BConfig.CopyRequestBody = true + web.BConfig.WebConfig.Session.SessionOn = true + web.BConfig.WebConfig.Session.SessionGCMaxLifetime = 3600 + web.BConfig.WebConfig.Session.SessionName = models.AppName + go func() { + time.Sleep(time.Second * 4) + (&models.JdCookie{}).Push("小滴滴已启动") + }() + if models.Config.QQID != 0 || models.Config.QQGroupID != 0 { + go qbot.Main() + } + web.Run() +} diff --git a/models/admin.go b/models/admin.go new file mode 100644 index 0000000..d5394ad --- /dev/null +++ b/models/admin.go @@ -0,0 +1,219 @@ +package models + +import "fmt" + +var Admin = ` + + + + + 账号管理 + + + + + +
+ +
+
+
+
+
+ 啥都没有 +
+
+ + + + + ` + +func Count() string { + zs := 0 + yx := 0 + wx := 0 + tl := 0 + ts := 0 + tc := 0 + dt := Date() + cks := GetJdCookies() + for _, ck := range cks { + zs++ + if ck.Available == True { + yx++ + } else { + wx++ + } + if ck.CreateAt == dt { + tc++ + } + // if ck.ScanedAt == dt { + // ts++ + // } + // if ck.LoseAt == dt { + // tl++ + // } + } + return fmt.Sprintf("总数%d,有效%d,无效%d,今日失效%d,今日扫码%d,今日新增%d", zs, yx, wx, tc, ts, tl) +} diff --git a/models/asset.go b/models/asset.go new file mode 100644 index 0000000..6cbc299 --- /dev/null +++ b/models/asset.go @@ -0,0 +1,143 @@ +package models + +import ( + "encoding/json" + "fmt" + "net/url" + "strconv" + "strings" + "time" + + "github.com/beego/beego/v2/client/httplib" +) + +type Asset struct { + Nickname string + Bean struct { + Total int + TodayIn int + TodayOut int + YestodayIn int + YestodayOut int + MonthIn int + MonthOut int + ToExpire []int + } + RedPacket struct { + Total float64 + ToExpire float64 + ToExpireJd float64 + ToExpireJx float64 + ToExpireJs float64 + } +} + +var Int = func(s string) int { + i, _ := strconv.Atoi(s) + return i +} + +func DailyAssetsPush() { + for _, ck := range GetJdCookies() { + msg := ck.Query() + if ck.QQ != 0 && Config.QQID != 0 && SendQQ != nil { + SendQQ(int64(ck.QQ), msg) + } + if ck.PushPlus != "" { + pushPlus(ck.PushPlus, msg) + } + } +} + +func (ck *JdCookie) Query() string { + msgs := []string{} + asset := Asset{} + if CookieOK(ck) { + today := time.Now().Local().Format("2006-01-02") + yestoday := time.Now().Local().Add(-time.Hour * 24).Format("2006-01-02") + month := time.Now().Local().Format("2006-01") + page := 1 + end := false + for { + if end { + break + } + bds := getJingBeanBalanceDetail(page, fmt.Sprintf("pt_key=%s;pt_pin=%s;", ck.PtKey, ck.PtPin)) + if bds == nil { + end = true + break + } + for _, bd := range bds { + amount := Int(bd.Amount) + if !strings.Contains(bd.Date, month) { + end = true + break + } + if amount > 0 { + asset.Bean.MonthIn += amount + } else { + asset.Bean.MonthOut += -amount + } + if strings.Contains(bd.Date, today) { + if amount > 0 { + asset.Bean.TodayIn += amount + } else { + asset.Bean.TodayOut += -amount + } + } + if strings.Contains(bd.Date, yestoday) { + if amount > 0 { + asset.Bean.YestodayIn += amount + } else { + asset.Bean.YestodayOut += -amount + } + } + } + page++ + } + msgs = append(msgs, []string{ + fmt.Sprintf("当月收入:%d京豆", asset.Bean.MonthIn), + fmt.Sprintf("当月支出:%d京豆", asset.Bean.MonthOut), + fmt.Sprintf("昨日收入:%d京豆", asset.Bean.YestodayIn), + fmt.Sprintf("昨日支出:%d京豆", asset.Bean.YestodayOut), + fmt.Sprintf("今日收入:%d京豆", asset.Bean.TodayIn), + fmt.Sprintf("今日支出:%d京豆", asset.Bean.TodayOut), + }...) + } else { + msgs = append(msgs, []string{ + "提醒:该账号已过期,请重新登录", + }...) + } + ck.PtPin, _ = url.QueryUnescape(ck.PtPin) + return strings.Join(append([]string{ + fmt.Sprintf("账号:%s", ck.PtPin), + fmt.Sprintf("昵称:%s", ck.Nickname), + fmt.Sprintf("备注:%s", ck.Note), + }, append(msgs, fmt.Sprintf("当前京豆:%v京豆", ck.BeanNum))...), "\n") +} + +type BeanDetail struct { + Date string `json:"date"` + Amount string `json:"amount"` + EventMassage string `json:"eventMassage"` +} + +func getJingBeanBalanceDetail(page int, cookie string) []BeanDetail { + type AutoGenerated struct { + Code string `json:"code"` + DetailList []BeanDetail `json:"detailList"` + } + a := AutoGenerated{} + req := httplib.Post(`https://api.m.jd.com/client.action?functionId=getJingBeanBalanceDetail`) + req.Header("User-Agent", ua) + req.Header("Host", "api.m.jd.com") + req.Header("Content-Type", "application/x-www-form-urlencoded") + req.Header("Cookie", cookie) + req.Body(fmt.Sprintf(`body={"pageSize": "20", "page": "%d"}&appid=ld`, page)) + data, err := req.Bytes() + if err != nil { + return nil + } + json.Unmarshal(data, &a) + return a.DetailList +} diff --git a/models/available.go b/models/available.go new file mode 100644 index 0000000..654d969 --- /dev/null +++ b/models/available.go @@ -0,0 +1,178 @@ +package models + +import ( + "encoding/json" + "fmt" + + "github.com/beego/beego/v2/client/httplib" +) + +type UserInfoResult struct { + Data struct { + JdVvipCocoonInfo struct { + JdVvipCocoon struct { + DisplayType int `json:"displayType"` + HitTypeList []int `json:"hitTypeList"` + Link string `json:"link"` + Price string `json:"price"` + Qualification int `json:"qualification"` + SellingPoints string `json:"sellingPoints"` + } `json:"JdVvipCocoon"` + JdVvipCocoonStatus string `json:"JdVvipCocoonStatus"` + } `json:"JdVvipCocoonInfo"` + JdVvipInfo struct { + JdVvipStatus string `json:"jdVvipStatus"` + } `json:"JdVvipInfo"` + AssetInfo struct { + AccountBalance string `json:"accountBalance"` + BaitiaoInfo struct { + AvailableLimit string `json:"availableLimit"` + BaiTiaoStatus string `json:"baiTiaoStatus"` + Bill string `json:"bill"` + BillOverStatus string `json:"billOverStatus"` + Outstanding7Amount string `json:"outstanding7Amount"` + OverDueAmount string `json:"overDueAmount"` + OverDueCount string `json:"overDueCount"` + UnpaidForAll string `json:"unpaidForAll"` + UnpaidForMonth string `json:"unpaidForMonth"` + } `json:"baitiaoInfo"` + BeanNum string `json:"beanNum"` + CouponNum string `json:"couponNum"` + CouponRed string `json:"couponRed"` + RedBalance string `json:"redBalance"` + } `json:"assetInfo"` + FavInfo struct { + FavDpNum string `json:"favDpNum"` + FavGoodsNum string `json:"favGoodsNum"` + FavShopNum string `json:"favShopNum"` + FootNum string `json:"footNum"` + IsGoodsRed string `json:"isGoodsRed"` + IsShopRed string `json:"isShopRed"` + } `json:"favInfo"` + GrowHelperCoupon struct { + AddDays int `json:"addDays"` + BatchID int `json:"batchId"` + CouponKind int `json:"couponKind"` + CouponModel int `json:"couponModel"` + CouponStyle int `json:"couponStyle"` + CouponType int `json:"couponType"` + Discount float64 `json:"discount"` + LimitType int `json:"limitType"` + MsgType int `json:"msgType"` + Quota float64 `json:"quota"` + RoleID int `json:"roleId"` + State int `json:"state"` + Status int `json:"status"` + } `json:"growHelperCoupon"` + KplInfo struct { + KplInfoStatus string `json:"kplInfoStatus"` + Mopenbp17 string `json:"mopenbp17"` + Mopenbp22 string `json:"mopenbp22"` + } `json:"kplInfo"` + OrderInfo struct { + CommentCount string `json:"commentCount"` + Logistics []interface{} `json:"logistics"` + OrderCountStatus string `json:"orderCountStatus"` + ReceiveCount string `json:"receiveCount"` + WaitPayCount string `json:"waitPayCount"` + } `json:"orderInfo"` + PlusPromotion struct { + Status int `json:"status"` + } `json:"plusPromotion"` + UserInfo struct { + BaseInfo struct { + AccountType string `json:"accountType"` + BaseInfoStatus string `json:"baseInfoStatus"` + CurPin string `json:"curPin"` + DefinePin string `json:"definePin"` + HeadImageURL string `json:"headImageUrl"` + LevelName string `json:"levelName"` + Nickname string `json:"nickname"` + Pinlist string `json:"pinlist"` + UserLevel string `json:"userLevel"` + } `json:"baseInfo"` + IsHideNavi string `json:"isHideNavi"` + IsHomeWhite string `json:"isHomeWhite"` + IsJTH string `json:"isJTH"` + IsKaiPu string `json:"isKaiPu"` + IsPlusVip string `json:"isPlusVip"` + IsQQFans string `json:"isQQFans"` + IsRealNameAuth string `json:"isRealNameAuth"` + IsWxFans string `json:"isWxFans"` + Jvalue string `json:"jvalue"` + OrderFlag string `json:"orderFlag"` + PlusInfo struct { + } `json:"plusInfo"` + XbScore string `json:"xbScore"` + } `json:"userInfo"` + UserLifeCycle struct { + IdentityID string `json:"identityId"` + LifeCycleStatus string `json:"lifeCycleStatus"` + TrackID string `json:"trackId"` + } `json:"userLifeCycle"` + } `json:"data"` + Msg string `json:"msg"` + Retcode string `json:"retcode"` + Timestamp int64 `json:"timestamp"` +} + +func initCookie() { + cks := GetJdCookies() + l := len(cks) + for i := 0; i < l-1; i++ { + if cks[i].Available == True && !CookieOK(&cks[i]) { + if pt_key, err := cks[i].OutPool(); err == nil && pt_key != "" { + i-- + } + } + } + go func() { + Save <- &JdCookie{} + }() + +} + +func CookieOK(ck *JdCookie) bool { + if ck == nil { + return true + } + req := httplib.Get("https://me-api.jd.com/user_new/info/GetJDUserInfoUnion") + req.Header("Cookie", fmt.Sprintf("pt_key=%s;pt_pin=%s;", ck.PtKey, ck.PtPin)) + req.Header("Accept", "*/*") + req.Header("Accept-Language", "zh-cn,") + req.Header("Connection", "keep-alive,") + req.Header("Referer", "https://home.m.jd.com/myJd/newhome.action?sceneval=2&ufc=&") + req.Header("Host", "me-api.jd.com") + req.Header("User-Agent", "jdapp;iPhone;9.4.4;14.3;network/4g;Mozilla/5.0 (iPhone; CPU iPhone OS 14_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148;supportJDSHWK/1") + data, err := req.Bytes() + if err != nil { + return true + } + ui := &UserInfoResult{} + if nil != json.Unmarshal(data, ui) { + return true + } + switch ui.Retcode { + case "1001": //ck.BeanNum + if ui.Msg == "not login" { + if ck.Available == True { + ck.Push(fmt.Sprintf("失效账号,%s", ck.PtPin)) + } + return false + } + case "0": + if ui.Data.UserInfo.BaseInfo.Nickname != ck.Nickname || ui.Data.AssetInfo.BeanNum != ck.BeanNum { + ck.Updates(JdCookie{ + Nickname: ui.Data.UserInfo.BaseInfo.Nickname, + BeanNum: ui.Data.AssetInfo.BeanNum, + Available: True, + }) + ck.Nickname = ui.Data.UserInfo.BaseInfo.Nickname + ck.BeanNum = ui.Data.AssetInfo.BeanNum + + } + default: + + } + return true +} diff --git a/models/bot.go b/models/bot.go new file mode 100644 index 0000000..99ada34 --- /dev/null +++ b/models/bot.go @@ -0,0 +1,393 @@ +package models + +import ( + "fmt" + "io/ioutil" + "net/url" + "os" + "os/exec" + "regexp" + "strconv" + "strings" + + "github.com/beego/beego/v2/client/httplib" + "github.com/beego/beego/v2/core/logs" + "github.com/beego/beego/v2/server/web" +) + +var SendQQ func(int64, interface{}) +var SendQQGroup func(int64, int64, interface{}) +var ListenQQPrivateMessage = func(uid int64, msg string) { + SendQQ(uid, handleMessage(msg, "qq", int(uid))) +} + +var ListenQQGroupMessage = func(gid int64, uid int64, msg string) { + if gid == Config.QQGroupID { + if Config.QbotPublicMode { + SendQQGroup(gid, uid, handleMessage(msg, "qqg", int(gid), int(uid))) + } else { + SendQQ(uid, handleMessage(msg, "qq", int(uid))) + } + } +} + +var replies = map[string]string{} + +func InitReplies() { + f, err := os.Open(ExecPath + "/conf/reply.php") + if err == nil { + defer f.Close() + data, _ := ioutil.ReadAll(f) + ss := regexp.MustCompile("`([^`]+)`\\s*=>\\s*`([^`]+)`").FindAllStringSubmatch(string(data), -1) + for _, s := range ss { + replies[s[1]] = s[2] + } + } + if _, ok := replies["壁纸"]; !ok { + replies["壁纸"] = "https://acg.toubiec.cn/random.php" + } +} + +var sendMessagee = func(msg string, msgs ...interface{}) { + tp := msgs[1].(string) + id := msgs[2].(int) + switch tp { + case "tg": + SendTgMsg(id, msg) + case "qq": + SendQQ(int64(id), msg) + case "qqg": + SendQQGroup(int64(id), int64(msgs[3].(int)), msg) + } +} + +var sendAdminMessagee = func(msg string, msgs ...interface{}) { + tp := msgs[1].(string) + id := msgs[2].(int) + switch tp { + case "tg": + if Config.TelegramUserID == id { + SendTgMsg(id, msg) + } + case "qq": + if int(Config.QQID) == id { + SendQQ(int64(id), msg) + } + case "qqg": + uid := msgs[3].(int) + if int(Config.QQID) == uid { + SendQQGroup(int64(id), int64(uid), msg) + } + } +} + +var isAdmin = func(msgs ...interface{}) bool { + tp := msgs[1].(string) + id := msgs[2].(int) + switch tp { + case "tg": + if Config.TelegramUserID == id { + return true + } + case "qq": + if int(Config.QQID) == id { + return true + } + case "qqg": + uid := msgs[3].(int) + if int(Config.QQID) == uid { + return true + } + } + return false +} + +var handleMessage = func(msgs ...interface{}) interface{} { + msg := msgs[0].(string) + tp := msgs[1].(string) + id := msgs[2].(int) + switch msg { + case "status", "状态": + if !isAdmin(msgs...) { + return "你没有权限操作" + } + return Count() + case "qrcode", "扫码", "二维码": + url := "" + if tp == "qqg" { + url = fmt.Sprintf("http://127.0.0.1:%d/api/login/qrcode.png?%vid=%v&qqguid=%v", web.BConfig.Listen.HTTPPort, tp, id, msgs[3].(int)) + } else { + url = fmt.Sprintf("http://127.0.0.1:%d/api/login/qrcode.png?%vid=%v", web.BConfig.Listen.HTTPPort, tp, id) + } + rsp, err := httplib.Get(url).Response() + if err != nil { + return nil + } + return rsp + case "升级": + if !isAdmin(msgs...) { // + return "你没有权限操作" + } + sendMessagee("小滴滴开始拉取代码", msgs...) + rtn, err := exec.Command("sh", "-c", "cd "+ExecPath+" && git pull").Output() + if err != nil { + return err.Error() + } + t := string(rtn) + if !strings.Contains(t, "changed") { + if strings.Contains(t, "Already") || strings.Contains(t, "已经是最新") { + sendMessagee("小滴滴已是最新版啦", msgs...) + } else { + sendMessagee("小滴滴拉取代失败:", msgs...) + } + return nil + } else { + sendMessagee("小滴滴拉取代码成功", msgs...) + } + sendMessagee("小滴滴正在编译程序", msgs...) + rtn, err = exec.Command("sh", "-c", "cd "+ExecPath+" && go build -o "+pname).Output() + if err != nil { + sendMessagee("小滴滴编译失败:", msgs...) + return nil + } else { + sendAdminMessagee("小滴滴编译成功", msgs...) + } + fallthrough + case "重启": + if !isAdmin(msgs...) { + return "你没有权限操作" + } + sendAdminMessagee("小滴滴重启程序", msgs...) + Daemon() + return nil + case "查询", "query": + cks := GetJdCookies() + for _, ck := range cks { + if tp == "qq" { + if ck.QQ == id { + SendQQ(int64(id), ck.Query()) + } + } else if tp == "qqg" { + if ck.QQ == msgs[3].(int) { + SendQQGroup(int64(id), int64(msgs[3].(int)), ck.Query()) + } + } + + } + return nil + default: + { // + ss := regexp.MustCompile(`pt_key=([^;=\s]+);pt_pin=([^;=\s]+)`).FindAllStringSubmatch(msg, -1) + if len(ss) > 0 { + xyb := 0 + for _, s := range ss { + ck := JdCookie{ + PtKey: s[1], + PtPin: s[2], + } + if CookieOK(&ck) { + xyb++ + if tp == "qq" { + ck.QQ = id + + } else if tp == "tg" { + ck.Telegram = id + } else if tp == "qqg" { + ck.QQ = msgs[3].(int) + } + if nck, err := GetJdCookie(ck.PtPin); err == nil { + nck.InPool(ck.PtKey) + msg := fmt.Sprintf("更新账号,%s", ck.PtPin) + (&JdCookie{}).Push(msg) + sendMessagee("许愿币+1", msgs...) + logs.Info(msg) + } else { + NewJdCookie(&ck) + msg := fmt.Sprintf("添加账号,%s", ck.PtPin) + (&JdCookie{}).Push(msg) + sendMessagee("许愿币+1", msgs...) + logs.Info(msg) + } + } + } + go func() { + Save <- &JdCookie{} + }() + return nil + } + } + { + s := regexp.MustCompile(`([^\s]+)\s+(.*)`).FindStringSubmatch(msg) + if len(s) > 0 { + v := s[2] + switch s[1] { + case "查询", "query": + if !isAdmin(msgs...) { + return "你没有权限操作" + } + cks := GetJdCookies() + a := s[2] + { + if s := strings.Split(a, "-"); len(s) == 2 { + for i, ck := range cks { + if i+1 >= Int(s[0]) && i+1 <= Int(s[1]) { + switch tp { + case "tg": + tgBotNotify(ck.Query()) + case "qq": + if id == ck.QQ { + SendQQ(int64(id), ck.Query()) + } else { + SendQQ(Config.QQID, ck.Query()) + } + case "qqg": + uid := msgs[3].(int) + if uid == ck.QQ || uid == int(Config.QQID) { + SendQQGroup(int64(id), int64(msgs[3].(int)), ck.Query()) + } + } + } + } + return nil + } + } + { + if x := regexp.MustCompile(`^[\s\d,]+$`).FindString(a); x != "" { + xx := regexp.MustCompile(`(\d+)`).FindAllStringSubmatch(a, -1) + for i, ck := range cks { + for _, x := range xx { + if fmt.Sprint(i+1) == x[1] { + switch tp { + case "tg": + tgBotNotify(ck.Query()) + case "qq": + if id == ck.QQ { + SendQQ(int64(id), ck.Query()) + } else { + SendQQ(Config.QQID, ck.Query()) + } + case "qqg": + uid := msgs[3].(int) + if uid == ck.QQ || uid == int(Config.QQID) { + SendQQGroup(int64(id), int64(msgs[3].(int)), ck.Query()) + } + } + } + } + + } + return nil + } + } + { + a = strings.Replace(a, " ", "", -1) + for _, ck := range cks { + if strings.Contains(ck.Note, a) || strings.Contains(ck.Nickname, a) || strings.Contains(ck.PtPin, a) { + switch tp { + case "tg": + tgBotNotify(ck.Query()) + case "qq": + if id == ck.QQ { + SendQQ(int64(id), ck.Query()) + } else { + SendQQ(Config.QQID, ck.Query()) + } + case "qqg": + uid := msgs[3].(int) + if uid == ck.QQ || uid == int(Config.QQID) { + SendQQGroup(int64(id), int64(msgs[3].(int)), ck.Query()) + } + } + } + } + return nil + } + case "许愿": + if tp == "qqg" { + id = msgs[3].(int) + } + b := 0 + for _, ck := range GetJdCookies() { + if id == ck.QQ || id == ck.Telegram { + b++ + } + } + if b <= 0 { + return "许愿币不足" + } else { + (&JdCookie{}).Push(fmt.Sprintf("%d许愿%s,许愿币余额%d。", id, v, b)) + return "收到许愿" + } + case "扣除许愿币": + id, _ := strconv.Atoi(v) + b := 0 + k := 0 + for _, ck := range GetJdCookies() { + if id == ck.QQ || id == ck.Telegram { + if k <= 5 { + ck.Updates(map[string]interface{}{ + QQ: 0, + Telegram: 0, + }) + k++ + } else { + b++ + } + } + } + return fmt.Sprintf("操作成功,%d剩余许愿币%d", id, b) + } + + } + } + { + o := false + for _, v := range regexp.MustCompile(`京东账号\d*((.*))(.*)】(.*)`).FindAllStringSubmatch(msg, -1) { + if !strings.Contains(v[3], "种子") && !strings.Contains(v[3], "undefined") { + pt_pin := url.QueryEscape(v[1]) + for key, ss := range map[string][]string{ + "Fruit": {"京东农场", "东东农场"}, + "Pet": {"京东萌宠"}, + "Bean": {"种豆得豆"}, + "JdFactory": {"东东工厂"}, + "DreamFactory": {"京喜工厂"}, + "Jxnc": {"京喜农场"}, + "Jdzz": {"京东赚赚"}, + "Joy": {"crazyJoy"}, + "Sgmh": {"闪购盲盒"}, + "Cfd": {"财富岛"}, + "Cash": {"签到领现金"}, + } { + for _, s := range ss { + if strings.Contains(v[2], s) && v[3] != "" { + if ck, err := GetJdCookie(pt_pin); err == nil { + ck.Update(key, v[3]) + } + if !o { + o = true + } + } + } + } + } + } + if o { + return "导入互助码成功" + } + } + for k, v := range replies { + if regexp.MustCompile(k).FindString(msg) != "" { + if regexp.MustCompile(`^https{0,1}://[^\x{4e00}-\x{9fa5}\n\r\s]{3,}$`).FindString(v) != "" { + url := v + rsp, err := httplib.Get(url).Response() + if err != nil { + return nil + } + return rsp + } + return v + } + } + } + return nil +} diff --git a/models/config.go b/models/config.go new file mode 100644 index 0000000..59a59b2 --- /dev/null +++ b/models/config.go @@ -0,0 +1,109 @@ +package models + +import ( + "bufio" + "io" + "io/ioutil" + "os" + + "github.com/beego/beego/v2/client/httplib" + "github.com/beego/beego/v2/core/logs" + "gopkg.in/yaml.v2" +) + +type Container struct { + Type string + Name string + Default bool + Address string + Username string + Password string + Path string + Version string + Token string + Available bool + Delete []string + Weigth int + Mode string + Reader *bufio.Reader + Config string + Limit int +} +type Yaml struct { + Containers []Container + Qrcode string + Master string + Mode string + Static string + Database string + QywxKey string `yaml:"qywx_key"` + Resident string + UserAgent string `yaml:"user_agent"` + Theme string + TelegramBotToken string `yaml:"telegram_bot_token"` + TelegramUserID int `yaml:"telegram_user_id"` + QQID int64 `yaml:"qquid"` + QQGroupID int64 `yaml:"qqgid"` + DefaultPriority int `yaml:"default_priority"` + NoGhproxy bool `yaml:"no_ghproxy"` + QbotPublicMode bool `yaml:"qbot_public_mode"` + DailyAssetPushCron string `yaml:"daily_asset_push_cron"` + Version string `yaml:"version"` +} + +var Balance = "balance" +var Parallel = "parallel" +var GhProxy = "https://ghproxy.com/" +var Cdle = false + +var Config Yaml + +func initConfig() { + confDir := ExecPath + "/conf" + if _, err := os.Stat(confDir); err != nil { + os.MkdirAll(confDir, os.ModePerm) + } + for _, name := range []string{"app.conf", "config.yaml"} { + f, err := os.OpenFile(ExecPath+"/conf/"+name, os.O_RDWR|os.O_CREATE, 0777) + if err != nil { + logs.Warn(err) + } + s, _ := ioutil.ReadAll(f) + if len(s) == 0 { + logs.Info("下载配置%s", name) + r, err := httplib.Get(GhProxy + "https://raw.githubusercontent.com/cdle/xdd/main/conf/" + name).Response() + if err == nil { + io.Copy(f, r.Body) + } + } + f.Close() + } + content, err := ioutil.ReadFile(ExecPath + "/conf/config.yaml") + if err != nil { + logs.Warn("解析config.yaml读取错误: %v", err) + } + if yaml.Unmarshal(content, &Config) != nil { + logs.Warn("解析config.yaml出错: %v", err) + } + if Config.Master == "" { + Config.Master = "xxxx" + } + if Config.Mode != Parallel { + Config.Mode = Balance + } + if Config.Qrcode != "" { + Config.Theme = Config.Qrcode + } + //测试 + if ExecPath == "/Users/cdle/Desktop/xdd" { + Cdle = true + Config.QQID = 17745270 + Config.QQGroupID = 610790654 + } + if Config.NoGhproxy { + GhProxy = "" + } + if Config.Database == "" { + Config.Database = ExecPath + "/.xdd.db" + } +} diff --git a/models/container.go b/models/container.go new file mode 100644 index 0000000..f8f5690 --- /dev/null +++ b/models/container.go @@ -0,0 +1,491 @@ +package models + +import ( + "bufio" + "encoding/json" + "errors" + "fmt" + "io" + "io/ioutil" + "os" + "regexp" + "strings" + + "github.com/beego/beego/v2/client/httplib" + "github.com/beego/beego/v2/core/logs" + "github.com/buger/jsonparser" +) + +const ( + QL = "ql" + V4 = "v4" + LI = "li" +) + +func initContainer() { + for i := range Config.Containers { + if Config.Containers[i].Weigth == 0 { + Config.Containers[i].Weigth = 1 + } + Config.Containers[i].Type = "" + if Config.Containers[i].Address != "" { + vv := regexp.MustCompile(`^(https?://[\.\w]+:?\d*)`).FindStringSubmatch(Config.Containers[i].Address) + if len(vv) == 2 { + Config.Containers[i].Address = vv[1] + } else { + logs.Warn("%s地址错误", Config.Containers[i].Type) + } + version, err := GetQlVersion(Config.Containers[i].Address) + if err == nil { + if Config.Containers[i].getToken() == nil { + logs.Info("青龙" + version + "登录成功") + } else { + logs.Warn("青龙" + version + "登录失败") + } + Config.Containers[i].Type = "ql" + Config.Containers[i].Version = version + } else { + if err := Config.Containers[i].getSession(); err == nil { + logs.Info("v系登录成功") + } else { + logs.Info("v系登录失败") + } + Config.Containers[i].Type = "v4" + } + } else if Config.Containers[i].Path != "" { + f, err := os.Open(Config.Containers[i].Path) + if err != nil { + logs.Warn("无法打开%s,请检查路径是否正确", Config.Containers[i].Path) + } else { + rd := bufio.NewReader(f) + for { + line, err := rd.ReadString('\n') //以'\n'为结束符读入一行 + if err != nil || io.EOF == err { + break + } + if pt := regexp.MustCompile(`^pt_key=`).FindString(line); pt != "" { + Config.Containers[i].Type = "li" + break + } + if pt := regexp.MustCompile(`^Cookie\d+`).FindString(line); pt != "" { + Config.Containers[i].Type = "v4" + break + } + if strings.Contains(line, "TempBlockCookie") { + Config.Containers[i].Type = "v4" + break + } + if strings.Contains(line, "QYWX_KEY") { + Config.Containers[i].Type = "v4" + break + } + } + if Config.Containers[i].Type == "" { + Config.Containers[i].Type = "li" + } + f.Close() + logs.Info(Config.Containers[i].Type + "配置文件正确") + } + } + } + +} + +func (c *Container) write(cks []JdCookie) error { + switch c.Type { + case "ql": + + if c.Version == "2.8" { + if len(c.Delete) > 0 { + c.request("/api/envs", DELETE, fmt.Sprintf(`[%s]`, strings.Join(c.Delete, ","))) + } + d := "" + if len(cks) != 0 { + for _, ck := range cks { + if ck.Available == True { + d += fmt.Sprintf("pt_key=%s;pt_pin=%s;\\n", ck.PtKey, ck.PtPin) + } + } + c.request("/api/envs", POST, `{"name":"JD_COOKIE","value":"`+d+`"}`) + + type AutoGenerated struct { + Code int `json:"code"` + Data []struct { + Value string `json:"value"` + ID string `json:"_id"` + Created int64 `json:"created"` + Status int `json:"status"` + Timestamp string `json:"timestamp"` + Position float64 `json:"position"` + Name string `json:"name"` + Remarks string `json:"remarks,omitempty"` + } `json:"data"` + } + help := getQLHelp(len(cks)) + for k := range help { + var data, err = c.request("/api/envs?searchValue=" + k) + a := AutoGenerated{} + err = json.Unmarshal(data, &a) + if err != nil { + continue + } + toDelete := []string{} + for _, env := range a.Data { + toDelete = append(toDelete, fmt.Sprintf("\"%s\"", env.ID)) + } + if len(toDelete) > 0 { + c.request("/api/envs", DELETE, fmt.Sprintf(`[%s]`, strings.Join(toDelete, ","))) + } + } + for k, v := range help { + if v == "" { + v = "&" + } + r := map[string]string{ + "name": k, + "value": v, + } + d, _ := json.Marshal(r) + c.request("/api/envs", POST, string(d)) + } + + } + } else { + if len(c.Delete) > 0 { + c.request("/api/cookies", DELETE, fmt.Sprintf(`[%s]`, strings.Join(c.Delete, ","))) + } + d := []string{} + for _, ck := range cks { + if ck.Available == True { + d = append(d, fmt.Sprintf("\"pt_key=%s;pt_pin=%s;\"", ck.PtKey, ck.PtPin)) + } + } + if len(d) != 0 { + c.request("/api/cookies", POST, fmt.Sprintf(`[%s]`, strings.Join(d, ","))) + } + } + case "v4": + return c.postConfig(func(config string) string { + TempBlockCookie := "" + cookies := "" + for i, ck := range cks { + if ck.PtPin == "" || ck.PtKey == "" { + continue + } + if ck.Available == False { + TempBlockCookie += fmt.Sprintf("%d ", i+1) + } + cookies += fmt.Sprintf("Cookie%d=\"pt_key=%s;pt_pin=%s;\"\n", i+1, ck.PtKey, ck.PtPin) + } + config = fmt.Sprintf(`TempBlockCookie="%s"`, TempBlockCookie) + "\n" + cookies + getVhelpRule(len(cks)) + config + return config + }) + case "li": + config := "" + f, err := os.OpenFile(c.Path, os.O_RDWR|os.O_CREATE, 0777) //打开文件 |os.O_RDWR + if err != nil { + return err + } + defer f.Close() + rd := bufio.NewReader(f) + for { + line, err := rd.ReadString('\n') //以'\n'为结束符读入一行 + if err != nil || io.EOF == err { + break + } + if pt := regexp.MustCompile(`^pt_key=(.*);pt_pin=([^'";\s]+);?`).FindStringSubmatch(line); len(pt) != 0 { + continue + } + if pt := regexp.MustCompile(`^pt_key=(.*)`).FindStringSubmatch(line); len(pt) != 0 { + continue + } + config += line + } + for _, ck := range cks { + if ck.PtPin == "" || ck.PtKey == "" { + continue + } + if ck.Available == True { + config += fmt.Sprintf("pt_key=%s;pt_pin=%s\n", ck.PtKey, ck.PtPin) + } + } + f.Truncate(0) + f.Seek(0, 0) + if _, err := io.WriteString(f, config); err != nil { + return err + } + return nil + } + return nil +} + +func (c *Container) read() error { + c.Available = true + switch c.Type { + case "ql": + if c.Version == "2.8" { + type AutoGenerated struct { + Code int `json:"code"` + Data []struct { + Value string `json:"value"` + ID string `json:"_id"` + Created int64 `json:"created"` + Status int `json:"status"` + Timestamp string `json:"timestamp"` + Position float64 `json:"position"` + Name string `json:"name"` + Remarks string `json:"remarks,omitempty"` + } `json:"data"` + } + var data, err = c.request("/api/envs?searchValue=JD_COOKIE") + a := AutoGenerated{} + err = json.Unmarshal(data, &a) + if err != nil { + c.Available = false + return err + } + c.Delete = []string{} + + for _, env := range a.Data { + c.Delete = append(c.Delete, fmt.Sprintf("\"%s\"", env.ID)) + res := regexp.MustCompile(`pt_key=(\S+);pt_pin=([^\s;]+);?`).FindAllStringSubmatch(env.Value, -1) + for _, v := range res { + CheckIn(v[2], v[1]) + } + } + return nil + } else { + var data, err = c.request("/api/cookies") + if err != nil { + c.Available = false + return err + } + type AutoGenerated struct { + Code int `json:"code"` + Data []struct { + Value string `json:"value"` + ID string `json:"_id"` + Created int64 `json:"created"` + Status int `json:"status"` + Timestamp string `json:"timestamp"` + Position float64 `json:"position"` + Nickname string `json:"nickname"` + } `json:"data"` + } + var a = AutoGenerated{} + c.Delete = []string{} + json.Unmarshal(data, &a) + for _, vv := range a.Data { + c.Delete = append(c.Delete, fmt.Sprintf("\"%s\"", vv.ID)) + res := regexp.MustCompile(`pt_key=(\S+);pt_pin=([^\s;]+);?`).FindStringSubmatch(vv.Value) + if len(res) == 3 { + CheckIn(res[2], res[1]) + } + } + } + case "v4": + return c.getConfig(func(rd *bufio.Reader) string { + config := "" + for { + line, err := rd.ReadString('\n') //以'\n'为结束符读入一行 + if err != nil || io.EOF == err { + config += line + break + } + if pt := regexp.MustCompile(`^#?\s?Cookie(\d+)=\S+pt_key=(.+);pt_pin=([^'";\s]+);?`).FindStringSubmatch(line); len(pt) != 0 { + CheckIn(pt[3], pt[2]) + continue + } + if pt := regexp.MustCompile(`^ForOther`).FindString(line); pt != "" { + continue + } + if pt := regexp.MustCompile(`^My.*\d+=`).FindString(line); pt != "" { + continue + } + if pt := regexp.MustCompile(`^Cookie\d+`).FindString(line); pt != "" { + continue + } + if pt := regexp.MustCompile(`^TempBlockCookie`).FindString(line); pt != "" { + continue + } + config += line + } + return config + }) + case "li": + f, err := os.OpenFile(c.Path, os.O_RDWR|os.O_CREATE, 0777) //打开文件 |os.O_RDWR + if err != nil { + c.Available = false + return err + } + defer f.Close() + rd := bufio.NewReader(f) + for { + line, err := rd.ReadString('\n') //以'\n'为结束符读入一行 + if err != nil || io.EOF == err { + break + } + if pt := regexp.MustCompile(`^pt_key=(.+);pt_pin=([^'";\s]+);?`).FindStringSubmatch(line); len(pt) != 0 { + CheckIn(pt[2], pt[1]) + continue + } + } + } + return nil +} + +func (c *Container) getToken() error { + req := httplib.Post(c.Address + "/api/login") + req.Header("Content-Type", "application/json;charset=UTF-8") + req.Body(fmt.Sprintf(`{"username":"%s","password":"%s"}`, c.Username, c.Password)) + if rsp, err := req.Response(); err == nil { + data, err := ioutil.ReadAll(rsp.Body) + if err != nil { + return err + } + c.Token, _ = jsonparser.GetString(data, "token") + } else { + return err + } + return nil +} + +func (c *Container) request(ss ...string) ([]byte, error) { + var api, method, body string + for _, s := range ss { + if s == GET || s == POST || s == PUT || s == DELETE { + method = s + } else if strings.Contains(s, "/api/") { + api = s + } else { + body = s + } + } + var req *httplib.BeegoHTTPRequest + var i = 0 + for { + i++ + switch method { + case POST: + req = httplib.Post(c.Address + api) + case PUT: + req = httplib.Put(c.Address + api) + case DELETE: + req = httplib.Delete(c.Address + api) + default: + req = httplib.Get(c.Address + api) + } + req.Header("Authorization", "Bearer "+c.Token) + if body != "" { + req.Header("Content-Type", "application/json;charset=UTF-8") + req.Body(body) + } + if data, err := req.Bytes(); err == nil { + code, _ := jsonparser.GetInt(data, "code") + if code == 200 { + return data, nil + } else { + logs.Warn(string(data)) + if i >= 5 { + return nil, errors.New("异常") + } + c.getToken() + } + } + } + return []byte{}, nil +} + +func GetQlVersion(address string) (string, error) { + data, err := httplib.Get(address).String() + if err != nil { + return "", err + } + js := regexp.MustCompile(`/umi\.\w+\.js`).FindString(data) + if js == "" { + return "", errors.New("好像不是青龙面板") + } + data, err = httplib.Get(address + js).String() + if err != nil { + return "", err + } + v := "" + if strings.Contains(data, "v2.8") { + v = "2.8" + } else if strings.Contains(data, "v2.2") { + v = "2.2" + } + return v, nil +} + +const ( + GET = "GET" + POST = "POST" + PUT = "PUT" + DELETE = "DELETE" +) + +func (c *Container) getConfig(handle func(*bufio.Reader) string) error { + if c.Address == "" { + f, err := os.OpenFile(c.Path, os.O_RDWR|os.O_CREATE, 0777) //打开文件 |os.O_RDWR + if err != nil { + return err + } + defer f.Close() + c.Config = handle(bufio.NewReader(f)) + } else { + err := c.getSession() + if err != nil { + return err + } + req := httplib.Get(c.Address + "/api/config/config") + req.Header("Cookie", c.Token) + rsp, err := req.Response() + if err != nil { + return err + } + c.Config = handle(bufio.NewReader(rsp.Body)) + } + return nil +} + +func (c *Container) postConfig(handle func(config string) string) error { + if c.Address == "" { + f, err := os.OpenFile(c.Path, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777) + if err != nil { + return err + } + defer f.Close() + f.WriteString(handle(c.Config)) + } else { + req := httplib.Post(c.Address + "/api/save") + req.Header("Cookie", c.Token) + req.Param("content", handle(c.Config)) + req.Param("name", "config.sh") + _, err := req.Bytes() + if err != nil { + return err + } + } + return nil +} + +func (c *Container) getSession() error { + req := httplib.Post(c.Address + "/auth") + req.Param("username", c.Username) + req.Param("password", c.Password) + rsp, err := req.Response() + if err != nil { + return err + } + c.Token = rsp.Header.Get("Set-Cookie") + if data, err := ioutil.ReadAll(rsp.Body); err != nil { + return err + } else { + err, _ := jsonparser.GetInt(data, "err") + if err != 0 { + return errors.New(string(data)) + } + } + return nil +} diff --git a/models/cron.go b/models/cron.go new file mode 100644 index 0000000..65ea210 --- /dev/null +++ b/models/cron.go @@ -0,0 +1,22 @@ +package models + +import ( + "github.com/beego/beego/v2/adapter/logs" + "github.com/robfig/cron/v3" +) + +var c *cron.Cron + +func initCron() { + c = cron.New() + if Config.DailyAssetPushCron != "" { + _, err := c.AddFunc(Config.DailyAssetPushCron, DailyAssetsPush) + if err != nil { + logs.Warn("资产推送任务失败:%v", err) + } else { + logs.Info("资产推送任务就绪") + } + c.AddFunc("3 */1 * * *", initVersion) + } + c.Start() +} diff --git a/models/daily_push.go b/models/daily_push.go new file mode 100644 index 0000000..2640e7f --- /dev/null +++ b/models/daily_push.go @@ -0,0 +1 @@ +package models diff --git a/models/db.go b/models/db.go new file mode 100644 index 0000000..f2b1278 --- /dev/null +++ b/models/db.go @@ -0,0 +1,255 @@ +package models + +import ( + "fmt" + "strings" + "time" + + "gorm.io/driver/mysql" + "gorm.io/driver/postgres" + "gorm.io/driver/sqlite" + "gorm.io/gorm" + "gorm.io/gorm/logger" +) + +var db *gorm.DB +var JD_COOKIE = "JD_COOKIE" +var RECORD = "RECORD" +var ENV = "env" +var TASK = "TASK" +var keys map[string]bool +var pins map[string]bool + +func initDB() { + var err error + var c = &gorm.Config{ + Logger: logger.Default.LogMode(logger.Info), + } + if strings.Contains(Config.Database, "@tcp(") { + db, err = gorm.Open(mysql.Open(Config.Database), c) + } else if strings.Contains(Config.Database, "dbname=") { + db, err = gorm.Open(postgres.Open(Config.Database), c) + } else { + db, err = gorm.Open(sqlite.Open(Config.Database), c) + } + if err != nil { + panic(err) + } + db.AutoMigrate( + &JdCookie{}, + &JdCookiePool{}, + ) + keys = make(map[string]bool) + pins = make(map[string]bool) + jps := []JdCookiePool{} + db.Find(&jps) + for _, jp := range jps { + keys[jp.PtKey] = true + pins[jp.PtPin] = true + } +} + +func HasPin(pin string) bool { + if _, ok := pins[pin]; ok { + return ok + } + pins[pin] = true + return false +} + +func HasKey(key string) bool { + if _, ok := keys[key]; ok { + return ok + } + keys[key] = true + return false +} + +type JdCookie struct { + ID int `gorm:"column:ID;primaryKey"` + Priority int `gorm:"column:Priority;default:1"` + CreateAt string `gorm:"column:CreateAt"` + PtKey string `gorm:"column:PtKey"` + PtPin string `gorm:"column:PtPin;unique"` + Note string `gorm:"column:Note"` + Available string `gorm:"column:Available;default:true" validate:"oneof=true false"` + Nickname string `gorm:"column:Nickname"` + BeanNum string `gorm:"column:BeanNum"` + QQ int `gorm:"column:QQ"` + PushPlus string `gorm:"column:PushPlus"` + Telegram int `gorm:"column:Telegram"` + Fruit string `gorm:"column:Fruit"` + Pet string `gorm:"column:Pet"` + Bean string `gorm:"column:Bean"` + JdFactory string `gorm:"column:JdFactory"` + DreamFactory string `gorm:"column:DreamFactory"` + Jxnc string `gorm:"column:Jxnc"` + Jdzz string `gorm:"column:Jdzz"` + Joy string `gorm:"column:Joy"` + Sgmh string `gorm:"column:Sgmh"` + Cfd string `gorm:"column:Cfd"` + Cash string `gorm:"column:Cash"` + Help string `gorm:"column:Help;default:false" validate:"oneof=true false"` + Pool string `gorm:"-"` +} + +type JdCookiePool struct { + ID int `gorm:"column:ID;primaryKey"` + PtKey string `gorm:"column:PtKey;unique"` + PtPin string `gorm:"column:PtPin"` + LoseAt string `gorm:"column:LoseAt"` + CreateAt string `gorm:"column:CreateAt"` +} + +var ScanedAt = "ScanedAt" +var LoseAt = "LoseAt" +var CreateAt = "CreateAt" +var Note = "Note" +var Available = "Available" +var UnAvailable = "UnAvailable" +var PtKey = "PtKey" +var PtPin = "PtPin" +var Priority = "Priority" +var Nickname = "Nickname" +var BeanNum = "BeanNum" +var Pool = "Pool" +var True = "true" +var False = "false" +var QQ = "QQ" +var PushPlus = "PushPlus" +var Save chan *JdCookie +var ExecPath string +var Telegram = "Telegram" + +const ( + Fruit = "Fruit" + Pet = "Pet" + Bean = "Bean" + JdFactory = "JdFactory" + DreamFactory = "DreamFactory" + Jxnc = "Jxnc" + Jdzz = "Jdzz" + Joy = "Joy" + Sgmh = "Sgmh" + Cfd = "Cfd" + Cash = "Cash" + Help = "Help" +) + +func Date() string { + return time.Now().Local().Format("2006-01-02") +} + +func GetJdCookies() []JdCookie { + cks := []JdCookie{} + db.Order("priority desc").Find(&cks) + return cks +} + +func GetJdCookie(pin string) (*JdCookie, error) { + ck := &JdCookie{} + return ck, db.Where(PtPin+" = ?", pin).First(ck).Error +} + +func (ck *JdCookie) Updates(values interface{}) { + if ck.ID != 0 { + db.Model(ck).Updates(values) + } + if ck.PtPin != "" { + db.Model(ck).Where(PtPin+" = ?", ck.PtPin).Updates(values) + } +} +func (ck *JdCookie) Update(column string, value interface{}) { + if ck.ID != 0 { + db.Model(ck).Update(column, value) + } + if ck.PtPin != "" { + db.Model(ck).Where(PtPin+" = ?", ck.PtPin).Update(column, value) + } +} + +func (ck *JdCookie) InPool(pt_key string) error { + if ck.ID != 0 { + date := Date() + tx := db.Begin() + jp := &JdCookiePool{} + if tx.Where(fmt.Sprintf("%s = '%s' and %s = '%s'", PtPin, ck.PtPin, PtKey, pt_key)).First(jp).Error == nil { + return tx.Rollback().Error + } + if err := tx.Create(&JdCookiePool{ + PtPin: ck.PtPin, + PtKey: pt_key, + CreateAt: date, + }).Error; err != nil { + tx.Rollback() + return err + } + tx.Model(ck).Where(fmt.Sprintf("%s = '%s'", Available, False)).Updates(map[string]interface{}{ + Available: True, + PtKey: pt_key, + }) + return tx.Commit().Error + } + return nil +} + +func (ck *JdCookie) OutPool() (string, error) { + if ck.ID != 0 { + date := Date() + tx := db.Begin() + jp := &JdCookiePool{} + tx.Model(jp).Where(fmt.Sprintf("%s = '%s' and %s = '%s'", PtPin, ck.PtPin, PtKey, ck.PtKey)).Update(LoseAt, date) + us := map[string]interface{}{} + if tx.Where(fmt.Sprintf("%s = '%s' and %s = '%s'", PtPin, ck.PtPin, LoseAt, "")).First(jp).Error != nil { + us[Available] = False + us[PtKey] = "" + } else { + us[Available] = True + us[PtKey] = jp.PtKey + } + e := tx.Where(fmt.Sprintf("%s = '%s'", Available, True)).Model(ck).Updates(us).RowsAffected + if e == 0 { + tx.Rollback() + return "", nil + } + ck.Available = True + ck.PtKey = jp.PtKey + return jp.PtKey, tx.Commit().Error + } + return "", nil +} + +func NewJdCookie(ck *JdCookie) error { + ck.Priority = Config.DefaultPriority + date := Date() + ck.CreateAt = date + tx := db.Begin() + if err := tx.Create(ck).Error; err != nil { + tx.Rollback() + return err + } + if err := tx.Create(&JdCookiePool{ + PtPin: ck.PtPin, + PtKey: ck.PtKey, + CreateAt: date, + }).Error; err != nil { + tx.Rollback() + return err + } + return tx.Commit().Error +} + +func CheckIn(pin, key string) int { + if !HasPin(pin) { + NewJdCookie(&JdCookie{ + PtKey: key, + PtPin: pin, + }) + return 0 + } else if !HasKey(key) { + ck, _ := GetJdCookie(pin) + ck.InPool(key) + return 1 + } + return 2 +} diff --git a/models/deamon.go b/models/deamon.go new file mode 100644 index 0000000..0a6910c --- /dev/null +++ b/models/deamon.go @@ -0,0 +1,60 @@ +package models + +import ( + "fmt" + "os" + "os/exec" + "regexp" + "strings" + + "github.com/beego/beego/v2/adapter/logs" +) + +func Daemon() { + args := os.Args[1:] + execArgs := make([]string, 0) + l := len(args) + for i := 0; i < l; i++ { + if strings.Index(args[i], "-d") == 0 { + continue + } + + execArgs = append(execArgs, args[i]) + } + proc := exec.Command(os.Args[0], execArgs...) + err := proc.Start() + if err != nil { + panic(err) + } + logs.Info("小滴滴运行于deamon模式") + os.Exit(0) +} + +func killp() { + pids, err := ppid() + if err == nil { + if len(pids) == 0 { + return + } else { + exec.Command("sh", "-c", "kill -9 "+strings.Join(pids, " ")).Output() + } + } else { + return + } +} + +func ppid() ([]string, error) { + pid := fmt.Sprint(os.Getpid()) + pids := []string{} + rtn, err := exec.Command("sh", "-c", "pidof "+pname).Output() + if err != nil { + return pids, err + } + re := regexp.MustCompile(`[\d]+`) + for _, v := range re.FindAll(rtn, -1) { + if string(v) != pid { + pids = append(pids, string(v)) + } + } + return pids, nil +} diff --git a/models/handle.go b/models/handle.go new file mode 100644 index 0000000..b27b52e --- /dev/null +++ b/models/handle.go @@ -0,0 +1,139 @@ +package models + +import ( + "math" + "strings" + "time" +) + +func initHandle() { + //获取路径 + Save = make(chan *JdCookie) + go func() { + init := true + for { + get := <-Save + if get.Pool == "s" { + initCookie() + continue + } + cks := GetJdCookies() + tmp := []JdCookie{} + for _, ck := range cks { + if ck.Priority >= 0 { + tmp = append(tmp, ck) + } + } + cks = tmp + if Config.Mode == Parallel { + for i := range Config.Containers { + (&Config.Containers[i]).read() + } + for i := range Config.Containers { + (&Config.Containers[i]).write(cks) + } + } else { + resident := []JdCookie{} + if Config.Resident != "" { + tmp := cks + cks = []JdCookie{} + for _, ck := range tmp { + if strings.Contains(Config.Resident, ck.PtPin) { + resident = append(resident, ck) + } else { + cks = append(cks, ck) + } + } + } + type balance struct { + Container Container + Weigth float64 + Ready []JdCookie + Should int + } + availables := []Container{} + parallels := []Container{} + bs := []balance{} + for i := range Config.Containers { + (&Config.Containers[i]).read() + if Config.Containers[i].Available { + if Config.Containers[i].Mode == Parallel { + parallels = append(parallels, Config.Containers[i]) + } else { + availables = append(availables, Config.Containers[i]) + bs = append(bs, balance{ + Container: Config.Containers[i], + Weigth: float64(Config.Containers[i].Weigth), + }) + } + } + } + bat := cks + for { + left := []JdCookie{} + l := len(cks) + total := 0.0 + for i := range bs { + total += float64(bs[i].Weigth) + } + for i := range bs { + if bs[i].Weigth == 0 { + bs[i].Should = 0 + } else { + bs[i].Should = int(math.Ceil(bs[i].Weigth / total * float64(l))) + } + + } + a := 0 + for i := range bs { + j := bs[i].Should + if j == 0 { + continue + } + s := 0 + if bs[i].Container.Limit > 0 && j > bs[i].Container.Limit { + s = a + bs[i].Container.Limit + left = append(left, cks[s:a+j]...) + bs[i].Weigth = 0 + } else { + s = a + j + } + if s > l { + s = l + } + bs[i].Ready = append(bs[i].Ready, cks[a:s]...) + a += j + if a >= l-1 { + break + } + } + if len(left) != 0 { + cks = left + continue + } + break + } + + for i := range bs { + bs[i].Container.write(append(resident, bs[i].Ready...)) + } + for i := range parallels { + parallels[i].write(append(resident, bat...)) + } + } + if init { + go func() { + for { + Save <- &JdCookie{ + Pool: "s", + } + + time.Sleep(time.Minute * 30) + // time.Sleep(time.Second * 1) + } + }() + init = false + } + } + }() +} diff --git a/models/help.go b/models/help.go new file mode 100644 index 0000000..9865f57 --- /dev/null +++ b/models/help.go @@ -0,0 +1,182 @@ +package models + +import ( + "fmt" + "strings" +) + +func getVhelpRule(num int) string { + rules := "" + var codes = map[string][]string{ + "Fruit": {}, + "Pet": {}, + "Bean": {}, + "JdFactory": {}, + "DreamFactory": {}, + "Jxnc": {}, + "Jdzz": {}, + "Joy": {}, + "Sgmh": {}, + "Cfd": {}, + "Cash": {}, + } + cks := GetJdCookies() + for _, ck := range cks { + if ck.Help == True || Cdle { + for k := range codes { + switch k { + case "Fruit": + codes[k] = append(codes[k], ck.Fruit) + case "Pet": + codes[k] = append(codes[k], ck.Pet) + case "Bean": + codes[k] = append(codes[k], ck.Bean) + case "JdFactory": + codes[k] = append(codes[k], ck.JdFactory) + case "DreamFactory": + codes[k] = append(codes[k], ck.DreamFactory) + case "Jxnc": + codes[k] = append(codes[k], ck.Jxnc) + case "Jdzz": + codes[k] = append(codes[k], ck.Jdzz) + case "Joy": + codes[k] = append(codes[k], ck.Joy) + case "Sgmh": + codes[k] = append(codes[k], ck.Sgmh) + case "Cfd": + codes[k] = append(codes[k], ck.Cfd) + case "Cash": + codes[k] = append(codes[k], ck.Cash) + } + if len := len(codes[k]); len != 0 { + if codes[k][len-1] == "undefined" || codes[k][len-1] == "" || codes[k][len-1] == "--" { + codes[k] = codes[k][:len-1] + } + } + } + } + } + for k := range codes { + for i, code := range codes[k] { + code = strings.Replace(code, `"`, `\"`, -1) + rules += fmt.Sprintf("My%s%d=\"%s\"\n", k, i+1, code) + codes[k][i] = fmt.Sprintf("${My%s%d}", k, i+1) + } + } + for k := range codes { + for i := 0; i < num; i++ { + if len(codes[k]) > 0 { + rules += fmt.Sprintf("ForOther"+k+"%d=\"%s\"\n", i+1, strings.Join(codes[k], "@")) + } + } + } + return rules +} + +func getQLHelp(num int) map[string]string { + var codes = map[string][]string{ + "Fruit": {}, + "Pet": {}, + "Bean": {}, + "JdFactory": {}, + "DreamFactory": {}, + "Jxnc": {}, + "Jdzz": {}, + "Joy": {}, + "Sgmh": {}, + "Cfd": {}, + "Cash": {}, + } + cks := GetJdCookies() + for _, ck := range cks { + if ck.Help == True || Cdle { + for k := range codes { + switch k { + case "Fruit": + codes[k] = append(codes[k], ck.Fruit) + case "Pet": + codes[k] = append(codes[k], ck.Pet) + case "Bean": + codes[k] = append(codes[k], ck.Bean) + case "JdFactory": + codes[k] = append(codes[k], ck.JdFactory) + case "DreamFactory": + codes[k] = append(codes[k], ck.DreamFactory) + case "Jxnc": + codes[k] = append(codes[k], ck.Jxnc) + case "Jdzz": + codes[k] = append(codes[k], ck.Jdzz) + case "Joy": + codes[k] = append(codes[k], ck.Joy) + case "Sgmh": + codes[k] = append(codes[k], ck.Sgmh) + case "Cfd": + codes[k] = append(codes[k], ck.Cfd) + case "Cash": + codes[k] = append(codes[k], ck.Cash) + } + if len := len(codes[k]); len != 0 { + if codes[k][len-1] == "undefined" || codes[k][len-1] == "" || codes[k][len-1] == "--" { + codes[k] = codes[k][:len-1] + } + } + } + } + } + var e = map[string]string{ + "Fruit": "", + "Pet": "", + "Bean": "", + "JdFactory": "", + "DreamFactory": "", + "Jxnc": "", + "Jdzz": "", + "Joy": "", + "Sgmh": "", + "Cfd": "", + "Cash": "", + } + for k := range codes { + vv := codes[k] + for i := range vv { + vv[i] = strings.Replace(vv[i], `"`, `\"`, -1) + + } + e[k] += strings.Join(vv, "@") + } + for k := range e { + n := []string{} + for i := 0; i < num; i++ { + n = append(n, e[k]) + } + e[k] = strings.Join(n, "&") + } + var f = map[string]string{} + for k := range e { + switch k { + case "Fruit": + f["FRUITSHARECODES"] = e[k] + case "Pet": + f["PETSHARECODES"] = e[k] + case "Bean": + f["PLANT_BEAN_SHARECODES"] = e[k] + case "JdFactory": + f["DDFACTORY_SHARECODES"] = e[k] + case "DreamFactory": + f["DREAM_FACTORY_SHARE_CODES"] = e[k] + case "Jxnc": + f["JXNC_SHARECODES"] = e[k] + // case "Jdzz": + // f[k] = e[k] + // case "Joy": + // f[k] = e[k] + case "Sgmh": + f["JDSGMH_SHARECODES"] = e[k] + // case "Cfd": + // f[k] = e[k] + case "Cash": + f["JD_CASH_SHARECODES"] = e[k] + } + } + return f +} diff --git a/models/init.go b/models/init.go new file mode 100644 index 0000000..7218325 --- /dev/null +++ b/models/init.go @@ -0,0 +1,28 @@ +package models + +import ( + "os" + "path/filepath" + + "github.com/beego/beego/v2/core/logs" +) + +func init() { + killp() + for _, arg := range os.Args { + if arg == "-d" { + Daemon() + } + } + ExecPath, _ = filepath.Abs(filepath.Dir(os.Args[0])) + logs.Info("当前%s", ExecPath) + initConfig() + initDB() + go initVersion() + go initUserAgent() + initContainer() + initHandle() + initCron() + go initTgBot() + InitReplies() +} diff --git a/models/push.go b/models/push.go new file mode 100644 index 0000000..bb3b96a --- /dev/null +++ b/models/push.go @@ -0,0 +1,17 @@ +package models + +func (ck *JdCookie) Push(msg string) { + if Config.QywxKey != "" { + go qywxNotify(&QywxConfig{Content: msg}) + } + if Config.TelegramBotToken != "" { + go tgBotNotify(msg) + } + if Config.QQID != 0 { + go SendQQ(Config.QQID, msg) + go SendQQ(int64(ck.QQ), msg) + } + if ck.PushPlus != "" { + go pushPlus(ck.PushPlus, msg) + } +} diff --git a/models/pushplus.go b/models/pushplus.go new file mode 100644 index 0000000..390d628 --- /dev/null +++ b/models/pushplus.go @@ -0,0 +1,21 @@ +package models + +import ( + "encoding/json" + + "github.com/beego/beego/v2/client/httplib" +) + +func pushPlus(token string, content string) { + req := httplib.Post("http://pushplus.hxtrip.com/send") + req.Header("Content-Type", "application/json") + data, _ := json.Marshal(struct { + Token string `json:"token"` + Content string `json:"Content"` + }{ + Token: token, + Content: content, + }) + req.Body(data) + req.Response() +} diff --git a/models/qywx.go b/models/qywx.go new file mode 100644 index 0000000..9ddf129 --- /dev/null +++ b/models/qywx.go @@ -0,0 +1,40 @@ +package models + +import ( + "time" + + "github.com/beego/beego/v2/client/httplib" +) + +type QywxConfig struct { + QywxKey string + Content string +} + +type QywxNotifyMessage struct { + Msgtype string `json:"msgtype"` + Text struct { + Content string `json:"content"` + } `json:"text"` +} + +func qywxNotify(c *QywxConfig) { + // if Config.TelegramBotToken == "" { + + // } + if c.QywxKey == "" { + c.QywxKey = Config.QywxKey + } + if c.QywxKey == "" { + return + } + wx := QywxNotifyMessage{ + Msgtype: "text", + } + wx.Text.Content = c.Content + req := httplib.Post("https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + c.QywxKey) + req.Header("Content-Type", "application/json") + req, _ = req.JSONBody(wx) + req.SetTimeout(time.Second*2, time.Second*2) + req.Response() +} diff --git a/models/sf.go b/models/sf.go new file mode 100644 index 0000000..de8d93d --- /dev/null +++ b/models/sf.go @@ -0,0 +1,54 @@ +package models + +// import ( +// "reflect" +// "strconv" +// "strings" + +// "github.com/boltdb/bolt" +// ) + +// type Env struct { +// ID int +// Name string +// Value string +// } + +// type Bd struct { +// name string +// model interface{} +// } + +// func (sf *Bd) Name(name string) error { +// sf.name = name +// return nil +// } + +// func (sf *Bd) GetAll(is []interface{}) error { +// db.View(func(tx *bolt.Tx) error { +// b := tx.Bucket([]byte(sf.name)) +// b.ForEach(func(_, v []byte) error { +// i := is[0] +// var _v = reflect.ValueOf(&ck).Elem() +// for _, vv := range strings.Split(string(v), ";") { +// v := strings.Split(vv, "=") +// if len(v) == 2 { +// t := _v.FieldByName(v[0]) +// if t.CanSet() { +// switch t.Kind() { +// case reflect.Int: +// i, _ := strconv.Atoi(v[1]) +// t.SetInt(int64(i)) +// case reflect.String: +// t.SetString(v[1]) +// } +// } +// } +// } +// is = append(is, i) +// return nil +// }) +// return nil +// }) +// return nil +// } diff --git a/models/task.go b/models/task.go new file mode 100644 index 0000000..2640e7f --- /dev/null +++ b/models/task.go @@ -0,0 +1 @@ +package models diff --git a/models/tbot.go b/models/tbot.go new file mode 100644 index 0000000..97a99da --- /dev/null +++ b/models/tbot.go @@ -0,0 +1,57 @@ +package models + +import ( + "net/http" + "time" + + "github.com/beego/beego/v2/core/logs" + tb "gopkg.in/tucnak/telebot.v2" +) + +var b *tb.Bot + +func initTgBot() { + go func() { + if Config.TelegramBotToken == "" { + return + } + var err error + b, err = tb.NewBot(tb.Settings{ + Token: Config.TelegramBotToken, + Poller: &tb.LongPoller{Timeout: 10 * time.Second}, + }) + if err != nil { + logs.Warn("监听tgbot失败") + return + } + b.Handle(tb.OnText, func(m *tb.Message) { + rt := handleMessage(m.Text, "tg", m.Sender.ID) + switch rt.(type) { + case string: + b.Send(m.Sender, rt.(string)) + case *http.Response: + b.SendAlbum(m.Sender, tb.Album{&tb.Photo{File: tb.FromReader(rt.(*http.Response).Body)}}) + } + }) + logs.Info("监听tgbot") + b.Start() + }() +} + +func tgBotNotify(msg string) { + if b == nil { + return + } + if Config.TelegramUserID == 0 { + logs.Warn("tgbot未绑定用id") + return + } + b.Send(&tb.User{ID: Config.TelegramUserID}, msg) +} + +func SendTgMsg(id int, msg string) { + if b == nil || id == 0 { + return + } + b.Send(&tb.User{ID: id}, msg) +} diff --git a/models/ua.go b/models/ua.go new file mode 100644 index 0000000..d32dddb --- /dev/null +++ b/models/ua.go @@ -0,0 +1,27 @@ +package models + +import ( + "github.com/beego/beego/v2/adapter/logs" + "github.com/beego/beego/v2/client/httplib" +) + +var ua = "Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.14.0 main%2F1.0 baiduboxapp/11.18.0.16 (Baidu; P2 13.3.1) NABar/0.0" + +func initUserAgent() { + if Config.UserAgent != "" { + logs.Info("使用自定义User-Agent") + ua = Config.UserAgent + } else { + logs.Info("更新User-Agent") + var err error + ua, err = httplib.Get(GhProxy + "https://raw.githubusercontent.com/cdle/xdd/main/ua.txt").String() + if err != nil { + logs.Info("更新User-Agent失败") + } + } + +} + +func GetUserAgent() string { + return ua +} diff --git a/models/version.go b/models/version.go new file mode 100644 index 0000000..3e68a77 --- /dev/null +++ b/models/version.go @@ -0,0 +1,54 @@ +package models + +import ( + "io" + "os" + "regexp" + "runtime" + + "github.com/beego/beego/v2/client/httplib" + "github.com/beego/beego/v2/core/logs" +) + +var version = "2021081301" +var AppName = "xdd" +var pname = regexp.MustCompile(`/([^/\s]+)`).FindStringSubmatch(os.Args[0])[1] + +func initVersion() { + if Config.Version != "" { + version = Config.Version + } + logs.Info("检查更新" + version) + value, err := httplib.Get(GhProxy + "https://raw.githubusercontent.com/cdle/xdd/main/models/version.go").String() + if err != nil { + logs.Info("更新User-Agent失败") + } else { + name := AppName + "_" + runtime.GOOS + "_" + runtime.GOARCH + if match := regexp.MustCompile(`var version = "(\d{10})"`).FindStringSubmatch(value); len(match) != 0 { + if match[1] > version { + logs.Warn("版本过低,下载更新") + rsp, err := httplib.Get(GhProxy + "https://github.com/cdle/jd_study/releases/download/main/" + name).Response() + if err != nil { + logs.Warn("无法下载更新") + return + } + filename := ExecPath + "/." + pname + f, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE|os.O_TRUNC, 0777) + if err != nil { + logs.Warn("无法创建更新临时文件:%v"+filename, err) + return + } + _, err = io.Copy(f, rsp.Body) + f.Close() + if err != nil { + logs.Warn("下载更新失败") + return + } + if err := os.Rename(filename, ExecPath+"/"+pname); err != nil { + logs.Warn("移动临时更新文件失败") + } + Daemon() + } + } + } +} diff --git a/qbot/login.go b/qbot/login.go new file mode 100644 index 0000000..2783738 --- /dev/null +++ b/qbot/login.go @@ -0,0 +1,194 @@ +package qbot + +import ( + "bufio" + "bytes" + "os" + "strings" + "time" + + qrcodeTerminal "github.com/Baozisoftware/qrcode-terminal-go" + "github.com/Mrs4s/MiraiGo/client" + "github.com/pkg/errors" + log "github.com/sirupsen/logrus" + "github.com/tuotoo/qrcode" + + "github.com/Mrs4s/go-cqhttp/global" +) + +var console = bufio.NewReader(os.Stdin) + +var readLine = func() (str string) { + str, _ = console.ReadString('\n') + str = strings.TrimSpace(str) + return +} + +var readLineTimeout = func(t time.Duration, de string) (str string) { + r := make(chan string) + go func() { + select { + case r <- readLine(): + case <-time.After(t): + } + }() + str = de + select { + case str = <-r: + case <-time.After(t): + } + return +} + +var cli *client.QQClient + +// ErrSMSRequestError SMS请求出错 +var ErrSMSRequestError = errors.New("sms request error") + +func commonLogin() error { + res, err := cli.Login() + if err != nil { + return err + } + return loginResponseProcessor(res) +} + +func qrcodeLogin() error { + rsp, err := cli.FetchQRCode() + if err != nil { + return err + } + fi, err := qrcode.Decode(bytes.NewReader(rsp.ImageData)) + if err != nil { + return err + } + _ = os.WriteFile("qrcode.png", rsp.ImageData, 0o644) + defer func() { _ = os.Remove("qrcode.png") }() + if cli.Uin != 0 { + log.Infof("请使用账号 %v 登录手机QQ扫描二维码 (qrcode.png) : ", cli.Uin) + } else { + log.Infof("请使用手机QQ扫描二维码 (qrcode.png) : ") + } + time.Sleep(time.Second) + qrcodeTerminal.New().Get(fi.Content).Print() + s, err := cli.QueryQRCodeStatus(rsp.Sig) + if err != nil { + return err + } + prevState := s.State + for { + time.Sleep(time.Second) + s, _ = cli.QueryQRCodeStatus(rsp.Sig) + if s == nil { + continue + } + if prevState == s.State { + continue + } + prevState = s.State + switch s.State { + case client.QRCodeCanceled: + log.Fatalf("扫码被用户取消.") + case client.QRCodeTimeout: + log.Fatalf("二维码过期") + case client.QRCodeWaitingForConfirm: + log.Infof("扫码成功, 请在手机端确认登录.") + case client.QRCodeConfirmed: + res, err := cli.QRCodeLogin(s.LoginInfo) + if err != nil { + return err + } + return loginResponseProcessor(res) + case client.QRCodeImageFetch, client.QRCodeWaitingForScan: + // ignore + } + } +} + +func loginResponseProcessor(res *client.LoginResponse) error { + var err error + for { + if err != nil { + return err + } + if res.Success { + return nil + } + var text string + switch res.Error { + case client.SliderNeededError: + log.Warnf("登录需要滑条验证码. ") + log.Warnf("请参考文档 -> https://docs.go-cqhttp.org/faq/slider.html <- 进行处理") + log.Warnf("1. 自行抓包并获取 Ticket 输入.") + log.Warnf("2. 使用手机QQ扫描二维码登入. (推荐)") + log.Warn("请输入(1 - 2) (将在10秒后自动选择2):") + text = readLineTimeout(time.Second*10, "2") + if strings.Contains(text, "1") { + println() + log.Warnf("请用浏览器打开 -> %v <- 并获取Ticket.", res.VerifyUrl) + println() + log.Warn("请输入Ticket: (Enter 提交)") + text = readLine() + res, err = cli.SubmitTicket(text) + continue + } + cli.Disconnect() + cli.Release() + cli = client.NewClientEmpty() + return qrcodeLogin() + case client.NeedCaptcha: + log.Warnf("登录需要验证码.") + _ = os.WriteFile("captcha.jpg", res.CaptchaImage, 0o644) + log.Warnf("请输入验证码 (captcha.jpg): (Enter 提交)") + text = readLine() + global.DelFile("captcha.jpg") + res, err = cli.SubmitCaptcha(text, res.CaptchaSign) + continue + case client.SMSNeededError: + log.Warnf("账号已开启设备锁, 按 Enter 向手机 %v 发送短信验证码.", res.SMSPhone) + readLine() + if !cli.RequestSMS() { + log.Warnf("发送验证码失败,可能是请求过于频繁.") + return errors.WithStack(ErrSMSRequestError) + } + log.Warn("请输入短信验证码: (Enter 提交)") + text = readLine() + res, err = cli.SubmitSMS(text) + continue + case client.SMSOrVerifyNeededError: + log.Warnf("账号已开启设备锁,请选择验证方式:") + log.Warnf("1. 向手机 %v 发送短信验证码", res.SMSPhone) + log.Warnf("2. 使用手机QQ扫码验证.") + log.Warn("请输入(1 - 2) (将在10秒后自动选择2):") + text = readLineTimeout(time.Second*10, "2") + if strings.Contains(text, "1") { + if !cli.RequestSMS() { + log.Warnf("发送验证码失败,可能是请求过于频繁.") + return errors.WithStack(ErrSMSRequestError) + } + log.Warn("请输入短信验证码: (Enter 提交)") + text = readLine() + res, err = cli.SubmitSMS(text) + continue + } + fallthrough + case client.UnsafeDeviceError: + log.Warnf("账号已开启设备锁,请前往 -> %v <- 验证后重启Bot.", res.VerifyUrl) + log.Infof("按 Enter 或等待 5s 后继续....") + readLineTimeout(time.Second*5, "") + os.Exit(0) + case client.OtherLoginError, client.UnknownLoginError, client.TooManySMSRequestError: + msg := res.ErrorMessage + if strings.Contains(msg, "版本") { + msg = "密码错误或账号被冻结" + } + if strings.Contains(msg, "冻结") { + log.Fatalf("账号被冻结") + } + log.Warnf("登录失败: %v", msg) + log.Infof("按 Enter 或等待 5s 后继续....") + readLineTimeout(time.Second*5, "") + os.Exit(0) + } + } +} diff --git a/qbot/main.go b/qbot/main.go new file mode 100644 index 0000000..88afa2f --- /dev/null +++ b/qbot/main.go @@ -0,0 +1,687 @@ +package qbot + +import ( + "bufio" + "bytes" + "crypto/aes" + "crypto/md5" + "crypto/sha1" + "encoding/hex" + "flag" + "fmt" + "io/ioutil" + "net/http" + "os" + "os/exec" + "path" + "path/filepath" + "runtime" + "strings" + "sync" + "time" + + "github.com/Mrs4s/go-cqhttp/coolq" + "github.com/Mrs4s/go-cqhttp/global" + "github.com/Mrs4s/go-cqhttp/global/config" + "github.com/cdle/xdd/models" + + // "github.com/Mrs4s/go-cqhttp/global/terminal" + "github.com/Mrs4s/go-cqhttp/global/update" + "github.com/Mrs4s/go-cqhttp/server" + + "github.com/Mrs4s/MiraiGo/binary" + "github.com/Mrs4s/MiraiGo/client" + "github.com/Mrs4s/MiraiGo/message" + "github.com/guonaihong/gout" + rotatelogs "github.com/lestrrat-go/file-rotatelogs" + log "github.com/sirupsen/logrus" + easy "github.com/t-tomalak/logrus-easy-formatter" + "github.com/tidwall/gjson" + "golang.org/x/crypto/pbkdf2" + "golang.org/x/term" +) + +var ( + conf *config.Config + isFastStart = false + // PasswordHash 存储QQ密码哈希供登录使用 + PasswordHash [16]byte + + // AccountToken 存储AccountToken供登录使用 + AccountToken []byte + + // 允许通过配置文件设置的状态列表 + allowStatus = [...]client.UserOnlineStatus{ + client.StatusOnline, client.StatusAway, client.StatusInvisible, client.StatusBusy, + client.StatusListening, client.StatusConstellation, client.StatusWeather, client.StatusMeetSpring, + client.StatusTimi, client.StatusEatChicken, client.StatusLoving, client.StatusWangWang, client.StatusCookedRice, + client.StatusStudy, client.StatusStayUp, client.StatusPlayBall, client.StatusSignal, client.StatusStudyOnline, + client.StatusGaming, client.StatusVacationing, client.StatusWatchingTV, client.StatusFitness, + } +) + +var bot *coolq.CQBot + +func Main() { + time.Sleep(time.Second) + models.SendQQ = func(uid int64, msg interface{}) { + if bot == nil { + return + } + if uid == 0 { + return + } + switch msg.(type) { + case string: + if bot != nil { + bot.SendPrivateMessage(uid, models.Config.QQGroupID, &message.SendingMessage{Elements: []message.IMessageElement{&message.TextElement{Content: msg.(string)}}}) + } + case *http.Response: + data, _ := ioutil.ReadAll(msg.(*http.Response).Body) + bot.SendPrivateMessage(uid, models.Config.QQGroupID, &message.SendingMessage{Elements: []message.IMessageElement{&coolq.LocalImageElement{Stream: bytes.NewReader(data)}}}) + } + } + models.SendQQGroup = func(gid int64, uid int64, msg interface{}) { + if bot == nil { + return + } + switch msg.(type) { + case string: + if bot != nil { + bot.SendGroupMessage(gid, &message.SendingMessage{Elements: []message.IMessageElement{&message.AtElement{Target: uid}, &message.TextElement{Content: msg.(string)}}}) + } + case *http.Response: + data, _ := ioutil.ReadAll(msg.(*http.Response).Body) + bot.SendGroupMessage(gid, &message.SendingMessage{Elements: []message.IMessageElement{&message.AtElement{Target: uid}, &message.TextElement{Content: "\n"}, &coolq.LocalImageElement{Stream: bytes.NewReader(data)}}}) + } + } + coolq.PrivateMessageEventCallback = models.ListenQQPrivateMessage + coolq.GroupMessageEventCallback = models.ListenQQGroupMessage + // c := flag.String("c", config.DefaultConfigFile, "configuration filename default is config.hjson") + // d := flag.Bool("d", false, "running as a daemon") + // h := flag.Bool("h", false, "this help") + // wd := flag.String("w", "", "cover the working directory") + // debug := flag.Bool("D", false, "debug mode") + // flag.Parse() + + // switch { + // case *h: + // help() + // case *d:xs + // server.Daemon() + // case *wd != "": + // resetWorkDir(*wd) + // } + + // 通过-c 参数替换 配置文件路径 + // config.DefaultConfigFile = models.ExecPath + "/qbot" + // conf = config.Get() + + conf = &config.Config{} + // if *debug { + // conf.Output.Debug = true + // } + if conf.Output.Debug { + log.SetReportCaller(true) + } + + logFormatter := &easy.Formatter{ + TimestampFormat: "2006-01-02 15:04:05", + LogFormat: "[%time%] [%lvl%]: %msg% \n", + } + rotateOptions := []rotatelogs.Option{ + rotatelogs.WithRotationTime(time.Hour * 24), + } + + if conf.Output.LogAging > 0 { + rotateOptions = append(rotateOptions, rotatelogs.WithMaxAge(time.Hour*24*time.Duration(conf.Output.LogAging))) + } + if conf.Output.LogForceNew { + rotateOptions = append(rotateOptions, rotatelogs.ForceNewFile()) + } + + w, err := rotatelogs.New(path.Join("logs", "%Y-%m-%d.log"), rotateOptions...) + if err != nil { + log.Errorf("rotatelogs init err: %v", err) + panic(err) + } + + log.AddHook(global.NewLocalHook(w, logFormatter, global.GetLogLevel(conf.Output.LogLevel)...)) + + mkCacheDir := func(path string, _type string) { + if !global.PathExists(path) { + if err := os.MkdirAll(path, 0o755); err != nil { + log.Fatalf("创建%s缓存文件夹失败: %v", _type, err) + } + } + } + mkCacheDir(global.ImagePath, "图片") + mkCacheDir(global.VoicePath, "语音") + mkCacheDir(global.VideoPath, "视频") + mkCacheDir(global.CachePath, "发送图片") + + var byteKey []byte + arg := os.Args + if len(arg) > 1 { + for i := range arg { + switch arg[i] { + case "update": + if len(arg) > i+1 { + selfUpdate(arg[i+1]) + } else { + selfUpdate("") + } + case "key": + if len(arg) > i+1 { + byteKey = []byte(arg[i+1]) + } + case "faststart": + isFastStart = true + } + } + } + // if terminal.RunningByDoubleClick() && !isFastStart { + // log.Warning("警告: 强烈不推荐通过双击直接运行本程序, 这将导致一些非预料的后果.") + // log.Warning("将等待10s后启动") + // time.Sleep(time.Second * 10) + // } + + if (conf.Account.Uin == 0 || (conf.Account.Password == "" && !conf.Account.Encrypt)) && !global.PathExists("session.token") { + // log.Warn("账号密码未配置, 将使用二维码登录.") + // if !isFastStart { + // log.Warn("将在 5秒 后继续.") + // time.Sleep(time.Second * 5) + // } + } + + // log.Info("当前版本:", coolq.Version) + if conf.Output.Debug { + log.SetLevel(log.DebugLevel) + log.Warnf("已开启Debug模式.") + // log.Debugf("开发交流群: 192548878") + } + // log.Info("用户交流群: 721829413") + if !global.PathExists("device.json") { + log.Warn("虚拟设备信息不存在, 将自动生成随机设备.") + client.GenRandomDevice() + _ = os.WriteFile("device.json", client.SystemDeviceInfo.ToJson(), 0o644) + 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) + } + } + if conf.Account.Encrypt { + if !global.PathExists("password.encrypt") { + if conf.Account.Password == "" { + log.Error("无法进行加密,请在配置文件中的添加密码后重新启动.") + readLine() + os.Exit(0) + } + log.Infof("密码加密已启用, 请输入Key对密码进行加密: (Enter 提交)") + byteKey, _ = term.ReadPassword(int(os.Stdin.Fd())) + PasswordHash = md5.Sum([]byte(conf.Account.Password)) + _ = os.WriteFile("password.encrypt", []byte(PasswordHashEncrypt(PasswordHash[:], byteKey)), 0o644) + log.Info("密码已加密,为了您的账号安全,请删除配置文件中的密码后重新启动.") + readLine() + os.Exit(0) + } else { + if conf.Account.Password != "" { + log.Error("密码已加密,为了您的账号安全,请删除配置文件中的密码后重新启动.") + readLine() + os.Exit(0) + } + + if len(byteKey) == 0 { + log.Infof("密码加密已启用, 请输入Key对密码进行解密以继续: (Enter 提交)") + cancel := make(chan struct{}, 1) + state, _ := term.GetState(int(os.Stdin.Fd())) + go func() { + select { + case <-cancel: + return + case <-time.After(time.Second * 45): + log.Infof("解密key输入超时") + time.Sleep(3 * time.Second) + _ = term.Restore(int(os.Stdin.Fd()), state) + os.Exit(0) + } + }() + byteKey, _ = term.ReadPassword(int(os.Stdin.Fd())) + cancel <- struct{}{} + } else { + log.Infof("密码加密已启用, 使用运行时传递的参数进行解密,按 Ctrl+C 取消.") + } + + encrypt, _ := os.ReadFile("password.encrypt") + ph, err := PasswordHashDecrypt(string(encrypt), byteKey) + if err != nil { + log.Fatalf("加密存储的密码损坏,请尝试重新配置密码") + } + copy(PasswordHash[:], ph) + } + } else { + PasswordHash = md5.Sum([]byte(conf.Account.Password)) + } + // if !isFastStart { + // log.Info("Bot将在5秒后登录并开始信息处理, 按 Ctrl+C 取消.") + // time.Sleep(time.Second * 5) + // } + log.Info("开始尝试登录并同步消息...") + log.Infof("使用协议: %v", func() string { + switch client.SystemDeviceInfo.Protocol { + case client.IPad: + return "iPad" + case client.AndroidPhone: + return "Android Phone" + case client.AndroidWatch: + return "Android Watch" + case client.MacOS: + return "MacOS" + case client.QiDian: + return "企点" + } + return "未知" + }()) + cli = newClient() + global.Proxy = conf.Message.ProxyRewrite + isQRCodeLogin := (conf.Account.Uin == 0 || len(conf.Account.Password) == 0) && !conf.Account.Encrypt + isTokenLogin := false + saveToken := func() { + AccountToken = cli.GenToken() + _ = os.WriteFile("session.token", AccountToken, 0o644) + } + if global.PathExists("session.token") { + token, err := os.ReadFile("session.token") + if err == nil { + if conf.Account.Uin != 0 { + r := binary.NewReader(token) + cu := r.ReadInt64() + if cu != conf.Account.Uin { + log.Warnf("警告: 配置文件内的QQ号 (%v) 与缓存内的QQ号 (%v) 不相同", conf.Account.Uin, cu) + log.Warnf("1. 使用会话缓存继续.") + log.Warnf("2. 删除会话缓存并重启.") + log.Warnf("请选择: (5秒后自动选1)") + text := readLineTimeout(time.Second*5, "1") + if text == "2" { + _ = os.Remove("session.token") + os.Exit(0) + } + } + } + if err = cli.TokenLogin(token); err != nil { + _ = os.Remove("session.token") + log.Warnf("恢复会话失败: %v , 尝试使用正常流程登录.", err) + time.Sleep(time.Second) + cli.Disconnect() + cli.Release() + cli = newClient() + } else { + isTokenLogin = true + } + } + } + if conf.Account.Uin != 0 && PasswordHash != [16]byte{} { + cli.Uin = conf.Account.Uin + cli.PasswordMd5 = PasswordHash + } + if !isTokenLogin { + if !isQRCodeLogin { + if err := commonLogin(); err != nil { + log.Fatalf("登录时发生致命错误: %v", err) + } + } else { + if err := qrcodeLogin(); err != nil { + log.Fatalf("登录时发生致命错误: %v", err) + } + } + } + var times uint = 1 // 重试次数 + var reLoginLock sync.Mutex + cli.OnDisconnected(func(q *client.QQClient, e *client.ClientDisconnectedEvent) { + reLoginLock.Lock() + defer reLoginLock.Unlock() + times = 1 + if cli.Online { + return + } + log.Warnf("Bot已离线: %v", e.Message) + time.Sleep(time.Second * time.Duration(conf.Account.ReLogin.Delay)) + for { + if conf.Account.ReLogin.Disabled { + os.Exit(1) + } + if times > conf.Account.ReLogin.MaxTimes && conf.Account.ReLogin.MaxTimes != 0 { + log.Fatalf("Bot重连次数超过限制, 停止") + } + times++ + if conf.Account.ReLogin.Interval > 0 { + log.Warnf("将在 %v 秒后尝试重连. 重连次数:%v/%v", conf.Account.ReLogin.Interval, times, conf.Account.ReLogin.MaxTimes) + time.Sleep(time.Second * time.Duration(conf.Account.ReLogin.Interval)) + } else { + time.Sleep(time.Second) + } + log.Warnf("尝试重连...") + err := cli.TokenLogin(AccountToken) + if err == nil { + saveToken() + return + } + log.Warnf("快速重连失败: %v", err) + if isQRCodeLogin { + log.Fatalf("快速重连失败, 扫码登录无法恢复会话.") + } + log.Warnf("快速重连失败, 尝试普通登录. 这可能是因为其他端强行T下线导致的.") + time.Sleep(time.Second) + if err := commonLogin(); err != nil { + log.Errorf("登录时发生致命错误: %v", err) + } else { + saveToken() + break + } + } + }) + saveToken() + cli.AllowSlider = true + log.Infof("登录成功 欢迎使用: %v", cli.Nickname) + log.Info("开始加载好友列表...") + global.Check(cli.ReloadFriendList(), true) + log.Infof("共加载 %v 个好友.", len(cli.FriendList)) + log.Infof("开始加载群列表...") + global.Check(cli.ReloadGroupList(), true) + log.Infof("共加载 %v 个群.", len(cli.GroupList)) + if conf.Account.Status >= int32(len(allowStatus)) || conf.Account.Status < 0 { + conf.Account.Status = 0 + } + cli.SetOnlineStatus(allowStatus[int(conf.Account.Status)]) + bot = coolq.NewQQBot(cli, conf) + _ = bot.Client + if conf.Message.PostFormat != "string" && conf.Message.PostFormat != "array" { + log.Warnf("post-format 配置错误, 将自动使用 string") + coolq.SetMessageFormat("string") + } else { + coolq.SetMessageFormat(conf.Message.PostFormat) + } + coolq.IgnoreInvalidCQCode = conf.Message.IgnoreInvalidCQCode + coolq.SplitURL = conf.Message.FixURL + coolq.ForceFragmented = conf.Message.ForceFragment + coolq.RemoveReplyAt = conf.Message.RemoveReplyAt + coolq.ExtraReplyData = conf.Message.ExtraReplyData + coolq.SkipMimeScan = conf.Message.SkipMimeScan + for _, m := range conf.Servers { + if h, ok := m["http"]; ok { + hc := new(config.HTTPServer) + if err := h.Decode(hc); err != nil { + log.Warn("读取http配置失败 :", err) + } else { + go server.RunHTTPServerAndClients(bot, hc) + } + } + if s, ok := m["ws"]; ok { + sc := new(config.WebsocketServer) + if err := s.Decode(sc); err != nil { + log.Warn("读取正向Websocket配置失败 :", err) + } else { + go server.RunWebSocketServer(bot, sc) + } + } + if c, ok := m["ws-reverse"]; ok { + rc := new(config.WebsocketReverse) + if err := c.Decode(rc); err != nil { + log.Warn("读取反向Websocket配置失败 :", err) + } else { + go server.RunWebSocketClient(bot, rc) + } + } + if p, ok := m["pprof"]; ok { + pc := new(config.PprofServer) + if err := p.Decode(pc); err != nil { + log.Warn("读取pprof配置失败 :", err) + } else { + go server.RunPprofServer(pc) + } + } + if p, ok := m["lambda"]; ok { + lc := new(config.LambdaServer) + if err := p.Decode(lc); err != nil { + log.Warn("读取pprof配置失败 :", err) + } else { + go server.RunLambdaClient(bot, lc) + } + } + } + log.Info("资源初始化完成, 开始处理信息.") + log.Info("アトリは、高性能ですから!") + + // <-global.SetupMainSignalHandler() +} + +// PasswordHashEncrypt 使用key加密给定passwordHash +func PasswordHashEncrypt(passwordHash []byte, key []byte) string { + if len(passwordHash) != 16 { + panic("密码加密参数错误") + } + key = pbkdf2.Key(key, key, 114514, 32, sha1.New) + + cipher, _ := aes.NewCipher(key) + result := make([]byte, 16) + cipher.Encrypt(result, passwordHash) + + return hex.EncodeToString(result) +} + +// PasswordHashDecrypt 使用key解密给定passwordHash +func PasswordHashDecrypt(encryptedPasswordHash string, key []byte) ([]byte, error) { + ciphertext, err := hex.DecodeString(encryptedPasswordHash) + if err != nil { + return nil, err + } + + key = pbkdf2.Key(key, key, 114514, 32, sha1.New) + + cipher, _ := aes.NewCipher(key) + result := make([]byte, 16) + cipher.Decrypt(result, ciphertext) + + return result, nil +} + +func checkUpdate() { + log.Infof("正在检查更新.") + if coolq.Version == "(devel)" { + log.Warnf("检查更新失败: 使用的 Actions 测试版或自编译版本.") + return + } + var res string + if err := gout.GET("https://api.github.com/repos/Mrs4s/go-cqhttp/releases/latest").BindBody(&res).Do(); err != nil { + log.Warnf("检查更新失败: %v", err) + return + } + info := gjson.Parse(res) + if global.VersionNameCompare(coolq.Version, info.Get("tag_name").Str) { + log.Infof("当前有更新的 go-cqhttp 可供更新, 请前往 https://github.com/Mrs4s/go-cqhttp/releases 下载.") + log.Infof("当前版本: %v 最新版本: %v", coolq.Version, info.Get("tag_name").Str) + return + } + log.Infof("检查更新完成. 当前已运行最新版本.") +} + +func selfUpdate(imageURL string) { + log.Infof("正在检查更新.") + var res, r string + if err := gout.GET("https://api.github.com/repos/Mrs4s/go-cqhttp/releases/latest").BindBody(&res).Do(); err != nil { + log.Warnf("检查更新失败: %v", err) + return + } + info := gjson.Parse(res) + version := info.Get("tag_name").Str + if coolq.Version == version { + log.Info("当前版本已经是最新版本!") + goto wait + } + log.Info("当前最新版本为 ", version) + log.Warn("是否更新(y/N): ") + r = strings.TrimSpace(readLine()) + if r != "y" && r != "Y" { + log.Warn("已取消更新!") + } else { + log.Info("正在更新,请稍等...") + sumURL := fmt.Sprintf("%v/Mrs4s/go-cqhttp/releases/download/%v/go-cqhttp_checksums.txt", + func() string { + if imageURL != "" { + return imageURL + } + return "https://github.com" + }(), version) + closer, err := global.HTTPGetReadCloser(sumURL) + if err != nil { + log.Error("更新失败: ", err) + goto wait + } + rd := bufio.NewReader(closer) + binaryName := fmt.Sprintf("go-cqhttp_%v_%v.%v", runtime.GOOS, func() string { + if runtime.GOARCH == "arm" { + return "armv7" + } + return runtime.GOARCH + }(), func() string { + if runtime.GOOS == "windows" { + return "zip" + } + return "tar.gz" + }()) + var sum []byte + for { + str, err := rd.ReadString('\n') + if err != nil { + break + } + str = strings.TrimSpace(str) + if strings.HasSuffix(str, binaryName) { + sum, _ = hex.DecodeString(strings.TrimSuffix(str, " "+binaryName)) + break + } + } + url := fmt.Sprintf("%v/Mrs4s/go-cqhttp/releases/download/%v/%v", + func() string { + if imageURL != "" { + return imageURL + } + return "https://github.com" + }(), version, binaryName) + + err = update.Update(url, sum) + if err != nil { + log.Error("更新失败: ", err) + } else { + log.Info("更新成功!") + } + } +wait: + log.Info("按 Enter 继续....") + readLine() + os.Exit(0) +} + +/* +func restart(args []string) { + var cmd *exec.Cmd + if runtime.GOOS == "windows" { + file, err := exec.LookPath(args[0]) + if err != nil { + log.Errorf("重启失败:%s", err.Error()) + return + } + path, err := filepath.Abs(file) + if err != nil { + log.Errorf("重启失败:%s", err.Error()) + } + args = append([]string{"/c", "start ", path, "faststart"}, args[1:]...) + cmd = &exec.Cmd{ + Path: "cmd.exe", + Args: args, + Stderr: os.Stderr, + Stdout: os.Stdout, + } + } else { + args = append(args, "faststart") + cmd = &exec.Cmd{ + Path: args[0], + Args: args, + Stderr: os.Stderr, + Stdout: os.Stdout, + } + } + _ = cmd.Start() +} +*/ + +// help cli命令行-h的帮助提示 +func help() { + fmt.Printf(`go-cqhttp service +version: %s + +Usage: + +server [OPTIONS] + +Options: +`, coolq.Version) + + flag.PrintDefaults() + os.Exit(0) +} + +func resetWorkDir(wd string) { + args := make([]string, 0, len(os.Args)) + for i := 1; i < len(os.Args); i++ { + if os.Args[i] == "-w" { + i++ // skip value field + } else if !strings.HasPrefix(os.Args[i], "-w") { + args = append(args, os.Args[i]) + } + } + p, _ := filepath.Abs(os.Args[0]) + proc := exec.Command(p, args...) + proc.Stdin = os.Stdin + proc.Stdout = os.Stdout + proc.Stderr = os.Stderr + proc.Dir = wd + err := proc.Run() + if err != nil { + panic(err) + } + os.Exit(0) +} + +func newClient() *client.QQClient { + c := client.NewClientEmpty() + c.OnServerUpdated(func(bot *client.QQClient, e *client.ServerUpdatedEvent) bool { + if !conf.Account.UseSSOAddress { + log.Infof("收到服务器地址更新通知, 根据配置文件已忽略.") + return false + } + log.Infof("收到服务器地址更新通知, 将在下一次重连时应用. ") + return true + }) + if global.PathExists("address.txt") { + log.Infof("检测到 address.txt 文件. 将覆盖目标IP.") + addr := global.ReadAddrFile("address.txt") + if len(addr) > 0 { + cli.SetCustomServer(addr) + } + log.Infof("读取到 %v 个自定义地址.", len(addr)) + } + c.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) + } + }) + return c +} diff --git a/run.sh b/run.sh new file mode 100644 index 0000000..b0d1d32 --- /dev/null +++ b/run.sh @@ -0,0 +1,22 @@ +#!/bin/bash +arch=`uname -m` +case $arch in +x86_64) + arch="amd64" + ;; +aarch64) + arch="arm64" + ;; +*) + arch="arm" + ;; +esac +filename="xdd_linux_${arch}" +url="https://ghproxy.com/https://github.com/cdle/jd_study/releases/download/main/${filename}" +dirname="xdd" +cd $HOME +if [ ! -d dirname ];then + mkdir dirname +fi +cd xdd +curl -L $url -O $filename diff --git a/static/2233login.af9c53d.png b/static/2233login.af9c53d.png new file mode 100644 index 0000000..3d9ff56 Binary files /dev/null and b/static/2233login.af9c53d.png differ diff --git a/static/loadTV.99606e2.gif b/static/loadTV.99606e2.gif new file mode 100644 index 0000000..33ebcd8 Binary files /dev/null and b/static/loadTV.99606e2.gif differ diff --git a/static/ok.svg b/static/ok.svg new file mode 100644 index 0000000..0a116ee --- /dev/null +++ b/static/ok.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/test.txt b/static/test.txt new file mode 100644 index 0000000..6769dd6 --- /dev/null +++ b/static/test.txt @@ -0,0 +1 @@ +Hello world! \ No newline at end of file diff --git a/theme/bidong.html b/theme/bidong.html new file mode 100644 index 0000000..0eb23fe --- /dev/null +++ b/theme/bidong.html @@ -0,0 +1,161 @@ + + + + + + + 哔咚哔咚 + + + + +
+
+ +
+
+ +
+
扫描二维码登录
+ +
跳转登录
+
或扫码下载APP
+
+ +
+ +
+ + + + \ No newline at end of file diff --git a/theme/kuduan.html b/theme/kuduan.html new file mode 100644 index 0000000..f80b0d7 --- /dev/null +++ b/theme/kuduan.html @@ -0,0 +1,187 @@ + + + + + + + 何必烦忧 + + + + + + + + + + + + + +
+ + +
+ + +
+ +
+ + + + \ No newline at end of file diff --git a/theme/noodin.html b/theme/noodin.html new file mode 100644 index 0000000..9d62253 --- /dev/null +++ b/theme/noodin.html @@ -0,0 +1,130 @@ + + + + + + + 吃面啦 + + + +
+

+ +

+
+

+
+

+ 扫码登陆
+

+

+ 京东APP登陆 +
+

+

TG交流: + ✈️  好好学习 ✈️ +
+ 扫码程序: + + © + Cdle作者 +  网页源码: + + © + 不知道 +  最终修改: + + © + Eylin +
+ 程序版本 v1.0.1 +

+ +
+ + + + \ No newline at end of file diff --git a/theme/random.html b/theme/random.html new file mode 100644 index 0000000..e20f79b --- /dev/null +++ b/theme/random.html @@ -0,0 +1,147 @@ + + + + + + JD — 任务助手 + + + + + + + + + + + + + + + + + +
+ +
+ + + + \ No newline at end of file diff --git a/theme/summer.html b/theme/summer.html new file mode 100644 index 0000000..9ba8708 --- /dev/null +++ b/theme/summer.html @@ -0,0 +1,171 @@ + + + + + + + JD自动挂机 + + + + + + +
+ + +
+ + + + \ No newline at end of file diff --git a/theme/survey.html b/theme/survey.html new file mode 100644 index 0000000..c02f063 --- /dev/null +++ b/theme/survey.html @@ -0,0 +1,156 @@ + + + + + + 问卷调查 + + + + + + + \ No newline at end of file diff --git a/theme/wave.html b/theme/wave.html new file mode 100644 index 0000000..d0d8312 --- /dev/null +++ b/theme/wave.html @@ -0,0 +1,496 @@ + + + + + + + + + 东东邀约 + + + + +
+
+
+
+ +
+
+
+

登录成功

+

tips:

+

+ 京东👉我的👉更多👉(东东农场、东东萌宠、东东工厂、宠汪汪、金榜创造营、领现金、健康社区、种豆得豆)。
+

+

+ 下载【京喜App】👉我的👉(京喜农场、京喜工厂、京喜财富岛)。
+

+

+ 下载【京东金融】👉我的👉(种摇钱树、天天提鹅、养猪猪)。
+

+

每天可领取100+京豆和若干现金红包、优惠券等。

+

京东极速版APP-每天固定1.5汇率左右金币,可兑换红包。

+

一定要微信扫码订阅通知,不然东西好了你也不知道!过期不候

+
我知道了
+
+
+

+ 请使用京东扫码 +

+ + + + +
+
+
+
+

+ 请使用微信扫码 +

+ +
+
+
+
+
+ +
+
+
+
+
+
+
+
+
+
+
+ + + + \ No newline at end of file diff --git a/ua.txt b/ua.txt new file mode 100644 index 0000000..62254e2 --- /dev/null +++ b/ua.txt @@ -0,0 +1 @@ +Mozilla/5.0 (iPhone; CPU iPhone OS 13_3_1 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Mobile/15E148 SP-engine/2.14.0 main%2F1.0 baiduboxapp/11.18.0.16 (Baidu; P2 13.3.1) NABar/0.0 \ No newline at end of file