diff --git a/.github/workflows/pull.yml b/.github/workflows/pull.yml index 52b6d117c0..844d450d44 100644 --- a/.github/workflows/pull.yml +++ b/.github/workflows/pull.yml @@ -29,7 +29,9 @@ jobs: go-version: '1.20' - name: Check out code into the Go module directory - uses: actions/checkout@master + uses: actions/checkout@v4 + with: + ref: ${{ github.event.pull_request.head.sha }} - name: golangci-lint uses: golangci/golangci-lint-action@master diff --git a/.golangci.yml b/.golangci.yml index c464edfc74..e300f5612f 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -61,7 +61,8 @@ run: # output configuration options output: - formats: ["colored-line-number"] + formats: + - format: "colored-line-number" print-issued-lines: true print-linter-name: true uniq-by-line: true diff --git a/README.md b/README.md index 565835e8e2..5d2a092afb 100644 --- a/README.md +++ b/README.md @@ -900,7 +900,7 @@ print("run[CQ:image,file="+j["img"]+"]") - [x] 钓鱼商店 - [x] 购买xxx [数量] - - [x] 出售xxx [数量] + - [x] 出售[xxx [数量]|所有垃圾] - [x] 钓鱼背包 - [x] 装备[xx竿|三叉戟|美西螈] - [x] 附魔[诱钓|海之眷顾] @@ -1069,6 +1069,14 @@ print("run[CQ:image,file="+j["img"]+"]") - [x] 解签 + +
+ 抽扑克 + + `import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/poker"` + + - [x] 抽扑克牌 +
一群一天一夫一妻制群老婆 @@ -1135,6 +1143,14 @@ print("run[CQ:image,file="+j["img"]+"]") - 注:本插件来源于[tgbot](https://github.com/YukariChiba/tgbot/blob/main/modules/Reborn.py) +
+
+ 打劫 + +`import _ "github.com/FloatTech/ZeroBot-Plugin/plugin/robbery"` + +- [x] 打劫[对方Q号|@对方QQ] +
在线代码运行 diff --git a/data b/data index 9b983625ca..69b0c8a9fc 160000 --- a/data +++ b/data @@ -1 +1 @@ -Subproject commit 9b983625cad379783e3f9cda8026f9a7a6c38132 +Subproject commit 69b0c8a9fc24214db185aeccd6836ee9d38e7c3a diff --git a/main.go b/main.go index 929d8c778c..8c48fb8742 100644 --- a/main.go +++ b/main.go @@ -115,10 +115,12 @@ import ( // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/nsfw" // nsfw图片识别 // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/nwife" // 本地老婆 // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/omikuji" // 浅草寺求签 + // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/poker" // 抽扑克 // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/qqwife" // 一群一天一夫一妻制群老婆 // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/qzone" // qq空间表白墙 // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/realcugan" // realcugan清晰术 // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/reborn" // 投胎 + // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/robbery" // 打劫群友的ATRI币 // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/runcode" // 在线运行代码 // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/saucenao" // 以图搜图 // _ "github.com/FloatTech/ZeroBot-Plugin/plugin/score" // 分数 diff --git a/plugin/dish/dish.go b/plugin/dish/dish.go index dd70295e85..6fd9985837 100644 --- a/plugin/dish/dish.go +++ b/plugin/dish/dish.go @@ -77,7 +77,8 @@ func init() { } var d dish - if err := db.Find("dish", &d, fmt.Sprintf("WHERE name like %%%s%%", dishName)); err != nil { + if err := db.Find("dish", &d, fmt.Sprintf("WHERE name like '%%%s%%'", dishName)); err != nil { + ctx.SendChain(message.Text("客官,本店没有" + dishName)) return } @@ -86,7 +87,7 @@ func init() { "原材料:%s\n"+ "步骤:\n"+ "%s", - name, dishName, d.Materials, d.Steps), + name, d.Name, d.Materials, d.Steps), )) }) @@ -96,7 +97,7 @@ func init() { return } - name := ctx.NickName() + name := ctx.CardOrNickName(ctx.Event.UserID) var d dish if err := db.Pick("dish", &d); err != nil { ctx.SendChain(message.Text("小店好像出错了,暂时端不出菜来惹")) diff --git a/plugin/gif/context.go b/plugin/gif/context.go index 74613bc69a..a1161053fc 100644 --- a/plugin/gif/context.go +++ b/plugin/gif/context.go @@ -87,13 +87,13 @@ func dlrange(prefix string, end int, wg *sync.WaitGroup, exit func(error)) []str } // 新的上下文 -func newContext(user int64) *context { +func newContext(user int64, atUser int64) *context { c := new(context) - c.usrdir = datapath + "users/" + strconv.FormatInt(user, 10) + `/` + c.usrdir = datapath + "users/" + strconv.FormatInt(atUser, 10) + `/` _ = os.MkdirAll(c.usrdir, 0755) c.headimgsdir = make([]string, 2) - c.headimgsdir[0] = c.usrdir + "0.gif" - c.headimgsdir[1] = c.usrdir + "1.gif" + c.headimgsdir[0] = datapath + "users/" + strconv.FormatInt(atUser, 10) + ".gif" + c.headimgsdir[1] = datapath + "users/" + strconv.FormatInt(user, 10) + ".gif" return c } diff --git a/plugin/gif/logo.go b/plugin/gif/logo.go index 3d78726072..f0fe05b654 100644 --- a/plugin/gif/logo.go +++ b/plugin/gif/logo.go @@ -14,9 +14,9 @@ func (cc *context) prepareLogos(s ...string) error { for i, v := range s { _, err := strconv.Atoi(v) if err != nil { - err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.usrdir+strconv.Itoa(i)+".gif") + err = file.DownloadTo("https://gchat.qpic.cn/gchatpic_new//--"+strings.ToUpper(v)+"/0", cc.headimgsdir[i]) } else { - err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.usrdir+strconv.Itoa(i)+".gif") + err = file.DownloadTo("http://q4.qlogo.cn/g?b=qq&nk="+v+"&s=640", cc.headimgsdir[i]) } if err != nil { return err diff --git a/plugin/gif/run.go b/plugin/gif/run.go index bf9f036e3a..04524c2cd1 100644 --- a/plugin/gif/run.go +++ b/plugin/gif/run.go @@ -152,8 +152,9 @@ func init() { // 插件主体 datapath = file.BOTPATH + "/" + en.DataFolder() en.OnRegex(`^(` + strings.Join(cmd, "|") + `)[\s\S]*?(\[CQ:(image\,file=([0-9a-zA-Z]{32}).*|at.+?(\d{5,11}))\].*|(\d+))$`). SetBlock(true).Handle(func(ctx *zero.Ctx) { - c := newContext(ctx.Event.UserID) list := ctx.State["regex_matched"].([]string) + atUserID, _ := strconv.ParseInt(list[4]+list[5]+list[6], 10, 64) + c := newContext(ctx.Event.UserID, atUserID) err := c.prepareLogos(list[4]+list[5]+list[6], strconv.FormatInt(ctx.Event.UserID, 10)) if err != nil { ctx.SendChain(message.Text("ERROR: ", err)) diff --git a/plugin/guessmusic/guessmusic.go b/plugin/guessmusic/guessmusic.go index 34dc920a6b..07de481406 100644 --- a/plugin/guessmusic/guessmusic.go +++ b/plugin/guessmusic/guessmusic.go @@ -109,6 +109,12 @@ func init() { ctx.SendChain(message.Text(err)) return } + // 猜歌环节-提供猜歌选项 + files, err := os.ReadDir(pathOfMusic) + if err != nil { + return + } + getMusicSelect(ctx, files, musicName) // 进行猜歌环节 ctx.SendChain(message.Record("file:///" + file.BOTPATH + "/" + outputPath + "0.wav")) var next *zero.FutureEvent @@ -221,26 +227,8 @@ func musicLottery(musicPath, listName string) (pathOfMusic, musicName string, er } return } - // 进行随机抽取 - if playlistID == 0 || !cfg.API { - musicName = getLocalMusic(files, 10) - } else { - switch rand.Intn(3) { // 三分二概率抽取API的 - case 1: - musicName = getLocalMusic(files, 10) - default: - if cfg.APIURL == "" { - // 如果没有配置过API地址,尝试连接独角兽 - musicName, err = downloadByOvooa(playlistID, pathOfMusic) - } else { - // 从API中抽取歌曲 - musicName, err = drawByAPI(playlistID, pathOfMusic) - } - if err != nil { - musicName = getLocalMusic(files, 10) - } - } - } + // 只猜本地已经下好的歌曲 + musicName = getLocalMusic(files, 10) if musicName == "" { err = errors.New("抽取歌曲轮空了,请重试") } @@ -295,15 +283,13 @@ func cutMusic(musicName, pathOfMusic, outputPath string) (err error) { // 数据匹配(结果信息,答题次数,提示次数,是否结束游戏) func gameMatch(c *zero.Ctx, beginner int64, musicInfo []string, answerTimes, tickTimes int) (message.MessageSegment, int, int, bool) { answer := strings.Replace(c.Event.Message.String(), "-", "", 1) - // 大小写,简繁体转换 + // 回答内容转小写,比对时再把标准答案转小写 answer = ConvertText(answer) - for i, element := range musicInfo { - musicInfo[i] = ConvertText(element) - } + switch { case answer == "取消": if c.Event.UserID == beginner { - return message.Text("游戏已取消,猜歌答案是\n", musicInfo[len(musicInfo)-1], "\n\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true + return message.Text("游戏已取消,猜歌答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true } return message.Text("你无权限取消"), answerTimes, tickTimes, false case answer == "提示": @@ -312,11 +298,11 @@ func gameMatch(c *zero.Ctx, beginner int64, musicInfo []string, answerTimes, tic return message.Text("已经没有提示了哦"), answerTimes, tickTimes, false } return message.Text("再听这段音频,要仔细听哦"), answerTimes, tickTimes, false - case strings.Contains(musicInfo[0], answer) || strings.EqualFold(musicInfo[0], answer): + case strings.Contains(ConvertText(musicInfo[0]), answer) || strings.EqualFold(ConvertText(musicInfo[0]), answer): return message.Text("太棒了,你猜对歌曲名了!答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true - case strings.Contains(musicInfo[1], answer) || strings.EqualFold(musicInfo[1], answer): + case strings.Contains(ConvertText(musicInfo[1]), answer) || strings.EqualFold(ConvertText(musicInfo[1]), answer): return message.Text("太棒了,你猜对歌手名了!答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true - case len(musicInfo) == 4 && (strings.Contains(musicInfo[2], answer) || strings.EqualFold(musicInfo[2], answer)): + case len(musicInfo) == 4 && (strings.Contains(ConvertText(musicInfo[2]), answer) || strings.EqualFold(ConvertText(musicInfo[2]), answer)): return message.Text("太棒了,你猜对相关信息了!答案是\n", musicInfo[len(musicInfo)-1], "\n\n下面欣赏猜歌的歌曲"), answerTimes, tickTimes, true default: answerTimes++ @@ -343,3 +329,39 @@ func ConvertText(input string) string { } return toLower } + +func getMusicSelect(ctx *zero.Ctx, files []fs.DirEntry, musicName string) { + // 生成音乐选项 + var musicInfo []string + musicInfo = append(musicInfo, musicName) + for i := 1; i < 4; i++ { + musicInfo = append(musicInfo, getLocalMusic(files, 10)) + for musicInfo[0] == musicInfo[i] { + musicInfo[i] = getLocalMusic(files, 10) + } + } + // 对调正确答案 + j := rand.Intn(len(musicInfo)) + musicInfo[0], musicInfo[j] = musicInfo[j], musicInfo[0] + + musicNameSelect := "请选出正确歌曲:\n" + for i := 0; i < len(musicInfo); i++ { + // 解析歌曲信息 + music := strings.Split(musicInfo[i], ".") + // 获取音乐后缀 + musicType := music[len(music)-1] + if !strings.Contains(musictypelist, musicType) { + ctx.SendChain(message.Text("抽取到了歌曲:\n", + musicInfo[i], "\n该歌曲不是音乐后缀,请联系bot主人修改")) + } + // 获取音乐信息 + musicInfo := strings.Split(strings.ReplaceAll(musicInfo[i], "."+musicType, ""), " - ") + infoNum := len(musicInfo) + if infoNum == 1 { + ctx.SendChain(message.Text("抽取到了歌曲:\n", + musicInfo[i], "\n该歌曲命名不符合命名规则,请联系bot主人修改")) + } + musicNameSelect += musicInfo[0] + " 歌手:" + musicInfo[1] + "\n" + } + ctx.SendChain(message.Text(musicNameSelect)) +} diff --git a/plugin/guessmusic/main.go b/plugin/guessmusic/main.go index 061a94b352..211da1279c 100644 --- a/plugin/guessmusic/main.go +++ b/plugin/guessmusic/main.go @@ -32,7 +32,7 @@ var ( cfg config // 插件主体 engine = control.AutoRegister(&ctrl.Options[*zero.Ctx]{ - DisableOnDefault: false, + DisableOnDefault: true, Brief: "猜歌插件", Help: "------bot主人指令------\n" + "- 设置猜歌歌库路径 [绝对路径]\n" + diff --git a/plugin/mcfish/main.go b/plugin/mcfish/main.go index 150263db3f..8b58a58585 100644 --- a/plugin/mcfish/main.go +++ b/plugin/mcfish/main.go @@ -131,7 +131,7 @@ var ( DisableOnDefault: false, Brief: "钓鱼", Help: "一款钓鱼模拟器\n----------指令----------\n" + - "- 钓鱼看板/钓鱼商店\n- 购买xxx\n- 购买xxx [数量]\n- 出售xxx\n- 出售xxx [数量]\n" + + "- 钓鱼看板/钓鱼商店\n- 购买xxx\n- 购买xxx [数量]\n- 出售xxx\n- 出售xxx [数量]\n- 出售所有垃圾\n" + "- 钓鱼背包\n- 装备[xx竿|三叉戟|美西螈]\n- 附魔[诱钓|海之眷顾]\n- 修复鱼竿\n- 合成[xx竿|三叉戟]\n- 消除[绑定|宝藏]诅咒\n- 消除[绑定|宝藏]诅咒 [数量]\n" + "- 进行钓鱼\n- 进行n次钓鱼\n- 当前装备概率明细\n" + "规则V" + version + ":\n" + @@ -530,6 +530,26 @@ func (sql *fishdb) getNumberFor(uid int64, thing string) (number int, err error) return } +// 获取用户的某类物品信息 +func (sql *fishdb) getUserTypeInfo(uid int64, thingType string) (thingInfos []article, err error) { + name := strconv.FormatInt(uid, 10) + "Pack" + sql.Lock() + defer sql.Unlock() + userInfo := article{} + err = sql.db.Create(name, &userInfo) + if err != nil { + return + } + if !sql.db.CanFind(name, "where Type = '"+thingType+"'") { + return + } + err = sql.db.FindFor(name, &userInfo, "where Type = '"+thingType+"'", func() error { + thingInfos = append(thingInfos, userInfo) + return nil + }) + return +} + /*********************************************************/ /************************商店相关函数***********************/ /*********************************************************/ diff --git a/plugin/mcfish/store.go b/plugin/mcfish/store.go index a7d5935436..85e90dc2a6 100644 --- a/plugin/mcfish/store.go +++ b/plugin/mcfish/store.go @@ -306,6 +306,77 @@ func init() { } ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("出售成功,你赚到了", pice*number, msg))) }) + engine.OnRegex(`^出售所有垃圾`, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) { + uid := ctx.Event.UserID + + articles, err := dbdata.getUserTypeInfo(uid, "waste") + if err != nil { + ctx.SendChain(message.Text("[ERROR]:获取背包信息错误", err)) + return + } + if len(articles) == 0 { + ctx.SendChain(message.Text("你的背包不存在该物品")) + return + } + if len(articles) > 1 { + msg := make(message.Message, 0, 3+len(articles)) + msg = append(msg, message.Reply(ctx.Event.MessageID), message.Text("找到以下物品:\n")) + for i, info := range articles { + msg = append(msg, message.Text( + "[", i, "]", info.Name, " 数量: ", info.Number, "\n")) + } + ctx.Send(msg) + } + + pice := 0 + for _, info := range articles { + pice += (priceList[info.Name] * discountList[info.Name] / 100) * info.Number * 8 / 10 + } + + ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("是否接受商店将以", pice, "收购全部垃圾", "?\n回答\"是\"或\"否\""))) + // 等待用户下一步选择 + recv, cancel1 := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(是|否)$`), zero.CheckUser(ctx.Event.UserID)).Repeat() + defer cancel1() + buy := false + for { + select { + case <-time.After(time.Second * 60): + ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("等待超时,取消钓鱼"))) + return + case e := <-recv: + nextcmd := e.Event.Message.String() + if nextcmd == "否" { + ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("已取消出售"))) + return + } + buy = true + } + if buy { + break + } + } + + msg := "" + curse, err := dbdata.getNumberFor(uid, "宝藏诅咒") + if err != nil { + ctx.SendChain(message.Text("[ERROR at store.go.9.3]:", err)) + return + } + if curse != 0 { + msg = "\n(你身上绑定了" + strconv.Itoa(curse) + "层诅咒)" + pice = pice * (100 - 10*curse) / 100 + } + + for _, info := range articles { + info.Number = 0 + err = dbdata.updateUserThingInfo(uid, info) + if err != nil { + ctx.SendChain(message.Text("[ERROR at store.go.6]:", err)) + return + } + } + ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("出售成功,你赚到了", pice, msg))) + }) engine.OnRegex(`^购买(`+strings.Join(thingList, "|")+`)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) { uid := ctx.Event.UserID numberOfPole, err := dbdata.getNumberFor(uid, "竿") diff --git a/plugin/poker/poker.go b/plugin/poker/poker.go new file mode 100644 index 0000000000..32def3c247 --- /dev/null +++ b/plugin/poker/poker.go @@ -0,0 +1,53 @@ +// Package poker 抽扑克牌 +package poker + +import ( + "encoding/json" + "math/rand" + + fcext "github.com/FloatTech/floatbox/ctxext" + ctrl "github.com/FloatTech/zbpctrl" + "github.com/FloatTech/zbputils/control" + "github.com/FloatTech/zbputils/ctxext" + zero "github.com/wdvxdr1123/ZeroBot" + "github.com/wdvxdr1123/ZeroBot/message" +) + +// 图片来源 https://www.bilibili.com/opus/834601953403076633 + +var cardImgPathList []string + +func init() { + engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{ + DisableOnDefault: false, + Brief: "抽扑克牌", + Help: "- 抽扑克\n- poker", + PublicDataFolder: "Poker", + }).ApplySingle(ctxext.DefaultSingle) + + getImg := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool { + data, err := engine.GetLazyData("imgdata.json", true) + if err != nil { + ctx.SendChain(message.Text("ERROR:", err)) + return false + } + err = json.Unmarshal(data, &cardImgPathList) + if err != nil { + ctx.SendChain(message.Text("ERROR:", err)) + return false + } + return true + }) + + engine.OnFullMatchGroup([]string{"抽扑克", "poker"}, getImg).SetBlock(true). + Handle(func(ctx *zero.Ctx) { + randomIndex := rand.Intn(len(cardImgPathList)) + randomImgPath := cardImgPathList[randomIndex] + imgData, err := engine.GetLazyData(randomImgPath, true) + if err != nil { + ctx.Send("[poker]读取扑克图片失败") + return + } + ctx.Send(message.ImageBytes(imgData)) + }) +} diff --git a/plugin/robbery/robbery.go b/plugin/robbery/robbery.go new file mode 100644 index 0000000000..a4d3ec8c25 --- /dev/null +++ b/plugin/robbery/robbery.go @@ -0,0 +1,173 @@ +// Package robbery 打劫群友 基于“qqwife”插件魔改 +package robbery + +import ( + "math/rand" + "strconv" + "sync" + "time" + + fcext "github.com/FloatTech/floatbox/ctxext" + sql "github.com/FloatTech/sqlite" + ctrl "github.com/FloatTech/zbpctrl" + "github.com/FloatTech/zbputils/control" + "github.com/wdvxdr1123/ZeroBot/extension/single" + + "github.com/FloatTech/AnimeAPI/wallet" + "github.com/FloatTech/floatbox/math" + "github.com/FloatTech/zbputils/ctxext" + zero "github.com/wdvxdr1123/ZeroBot" + "github.com/wdvxdr1123/ZeroBot/message" +) + +type robberyRepo struct { + db *sql.Sqlite + sync.RWMutex +} + +type robberyRecord struct { + UserID int64 `db:"user_id"` // 劫匪 + VictimID int64 `db:"victim_id"` // 受害者 + Time string `db:"time"` // 时间 +} + +func init() { + police := &robberyRepo{ + db: &sql.Sqlite{}, + } + engine := control.AutoRegister(&ctrl.Options[*zero.Ctx]{ + DisableOnDefault: false, + Brief: "打劫别人的ATRI币", + Help: "- 打劫[对方Q号|@对方QQ]\n" + + "1. 受害者钱包少于1000不能被打劫\n" + + "2. 打劫成功率 40%\n" + + "4. 打劫失败罚款1000(钱不够不罚钱)\n" + + "5. 保险赔付0-80%\n" + + "6. 打劫成功获得对方0-5%+500的财产(最高1W)\n" + + "7. 每日可打劫或被打劫一次\n" + + "8. 打劫失败不计入次数\n", + PrivateDataFolder: "robbery", + }).ApplySingle(single.New( + single.WithKeyFn(func(ctx *zero.Ctx) int64 { return ctx.Event.GroupID }), + single.WithPostFn[int64](func(ctx *zero.Ctx) { + ctx.Send( + message.ReplyWithMessage(ctx.Event.MessageID, + message.Text("别着急,警察局门口排长队了!"), + ), + ) + }), + )) + getdb := fcext.DoOnceOnSuccess(func(ctx *zero.Ctx) bool { + police.db.DBPath = engine.DataFolder() + "robbery.db" + err := police.db.Open(time.Hour) + if err == nil { + // 创建CD表 + err = police.db.Create("criminal_record", &robberyRecord{}) + if err != nil { + ctx.SendChain(message.Text("[ERROR]:", err)) + return false + } + return true + } + ctx.SendChain(message.Text("[ERROR]:", err)) + return false + }) + + // 打劫功能 + engine.OnRegex(`^打劫\s?(\[CQ:at,qq=(\d+)\]|(\d+))`, getdb).SetBlock(true).Limit(ctxext.LimitByUser). + Handle(func(ctx *zero.Ctx) { + uid := ctx.Event.UserID + fiancee := ctx.State["regex_matched"].([]string) + victimID, _ := strconv.ParseInt(fiancee[2]+fiancee[3], 10, 64) + if victimID == uid { + ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.At(uid), message.Text("不能打劫自己"))) + return + } + + // 查询记录 + ok, err := police.getRecord(victimID, uid) + if err != nil { + ctx.SendChain(message.Text("[ERROR]:", err)) + return + } + if !ok { + ctx.SendChain(message.Text("你已经打劫过了/对方已经被打劫过了")) + return + } + + // 穷人保护 + victimWallet := wallet.GetWalletOf(victimID) + if victimWallet < 1000 { + ctx.SendChain(message.Text("对方太穷了!打劫失败")) + return + } + + // 判断打劫是否成功 + if rand.Intn(100) > 60 { + ctx.SendChain(message.Text("打劫失败,罚款1000")) + err := wallet.InsertWalletOf(uid, -1000) + if err != nil { + ctx.SendChain(message.Text("[ERROR]:罚款失败,钱包坏掉力:\n", err)) + return + } + return + } + userIncrMonry := math.Min(rand.Intn(victimWallet/20)+500, 10000) + victimDecrMonry := userIncrMonry / (rand.Intn(4) + 1) + + // 记录结果 + err = wallet.InsertWalletOf(victimID, -victimDecrMonry) + if err != nil { + ctx.SendChain(message.Text("[ERROR]:钱包坏掉力:\n", err)) + return + } + err = wallet.InsertWalletOf(uid, +userIncrMonry) + if err != nil { + ctx.SendChain(message.Text("[ERROR]:打劫失败,脏款掉入虚无\n", err)) + return + } + + // 写入记录 + err = police.insertRecord(victimID, uid) + if err != nil { + ctx.SendChain(message.At(uid), message.Text("[ERROR]:犯罪记录写入失败\n", err)) + } + + ctx.SendChain(message.At(uid), message.Text("打劫成功,钱包增加:", userIncrMonry, "ATRI币")) + ctx.SendChain(message.At(victimID), message.Text("保险公司对您进行了赔付,您实际损失:", victimDecrMonry, "ATRI币")) + }) +} + +func (sql *robberyRepo) getRecord(victimID, uid int64) (ok bool, err error) { + sql.Lock() + defer sql.Unlock() + // 创建群表格 + err = sql.db.Create("criminal_record", &robberyRecord{}) + if err != nil { + return false, err + } + limitID := "where victim_id is " + strconv.FormatInt(victimID, 10) + + " or user_id is " + strconv.FormatInt(uid, 10) + if !sql.db.CanFind("criminal_record", limitID) { + // 没有记录即不用比较 + return true, nil + } + cdinfo := robberyRecord{} + _ = sql.db.Find("criminal_record", &cdinfo, limitID) + if time.Now().Format("2006/01/02") != cdinfo.Time { + // // 如果跨天了就删除 + err = sql.db.Del("criminal_record", limitID) + return true, err + } + return false, nil +} + +func (sql *robberyRepo) insertRecord(vid int64, uid int64) error { + sql.Lock() + defer sql.Unlock() + return sql.db.Insert("criminal_record", &robberyRecord{ + UserID: uid, + VictimID: vid, + Time: time.Now().Format("2006/01/02"), + }) +}