mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-18 20:50:12 +08:00
413 lines
14 KiB
Go
413 lines
14 KiB
Go
// Package niuniu 牛牛大作战
|
||
package niuniu
|
||
|
||
import (
|
||
"fmt"
|
||
"math/rand"
|
||
"strconv"
|
||
"time"
|
||
|
||
"github.com/FloatTech/AnimeAPI/niu"
|
||
"github.com/FloatTech/AnimeAPI/wallet"
|
||
ctrl "github.com/FloatTech/zbpctrl"
|
||
"github.com/FloatTech/zbputils/control"
|
||
"github.com/FloatTech/zbputils/ctxext"
|
||
"github.com/RomiChan/syncx"
|
||
zero "github.com/wdvxdr1123/ZeroBot"
|
||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||
"github.com/wdvxdr1123/ZeroBot/message"
|
||
)
|
||
|
||
type lastLength struct {
|
||
TimeLimit time.Time
|
||
Count int
|
||
Length float64
|
||
}
|
||
|
||
var (
|
||
en = control.AutoRegister(&ctrl.Options[*zero.Ctx]{
|
||
DisableOnDefault: false,
|
||
Brief: "牛牛大作战",
|
||
Help: "- 打胶\n" +
|
||
"- 使用[道具名称]打胶\n" +
|
||
"- jj@xxx\n" +
|
||
"- 使用[道具名称]jj@xxx\n" +
|
||
"- 注册牛牛\n" +
|
||
"- 赎牛牛(cd:60分钟)\n" +
|
||
"- 出售牛牛\n" +
|
||
"- 牛牛拍卖行\n" +
|
||
"- 牛牛商店\n" +
|
||
"- 牛牛背包\n" +
|
||
"- 注销牛牛\n" +
|
||
"- 查看我的牛牛\n" +
|
||
"- 牛子长度排行\n" +
|
||
"- 牛子深度排行\n" +
|
||
"\n ps : 出售后的牛牛都会进入牛牛拍卖行哦",
|
||
PrivateDataFolder: "niuniu",
|
||
})
|
||
dajiaoLimiter = rate.NewManager[string](time.Second*90, 1)
|
||
jjLimiter = rate.NewManager[string](time.Second*150, 1)
|
||
jjCount = syncx.Map[string, *lastLength]{}
|
||
register = syncx.Map[string, *lastLength]{}
|
||
)
|
||
|
||
func init() {
|
||
en.OnFullMatch("牛牛拍卖行", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||
gid := ctx.Event.GroupID
|
||
uid := ctx.Event.UserID
|
||
auction, err := niu.ShowAuction(gid)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR:", err))
|
||
return
|
||
}
|
||
|
||
var messages message.Message
|
||
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text("牛牛拍卖行有以下牛牛")))
|
||
for _, info := range auction {
|
||
msg := fmt.Sprintf("商品序号: %d\n牛牛原所属: %d\n牛牛价格: %d%s\n牛牛大小: %.2fcm",
|
||
info.ID+1, info.UserID, info.Money, wallet.GetWalletName(), info.Length)
|
||
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text(msg)))
|
||
}
|
||
if id := ctx.Send(messages).ID(); id == 0 {
|
||
ctx.Send(message.Text("发送拍卖行失败"))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Reply(ctx.Event.Message), message.Text("请输入对应序号进行购买"))
|
||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.CheckUser(uid), zero.CheckGroup(gid), zero.RegexRule(`^(\d+)$`)).Repeat()
|
||
defer cancel()
|
||
timer := time.NewTimer(120 * time.Second)
|
||
answer := ""
|
||
defer timer.Stop()
|
||
for {
|
||
select {
|
||
case <-timer.C:
|
||
ctx.SendChain(message.At(uid), message.Text(" 超时,已自动取消"))
|
||
return
|
||
case r := <-recv:
|
||
answer = r.Event.Message.String()
|
||
n, err := strconv.Atoi(answer)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
return
|
||
}
|
||
n--
|
||
msg, err := niu.Auction(gid, uid, n)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR:", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Reply(ctx.Event.Message), message.Text(msg))
|
||
return
|
||
}
|
||
}
|
||
})
|
||
en.OnFullMatch("出售牛牛", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||
gid := ctx.Event.GroupID
|
||
uid := ctx.Event.UserID
|
||
sell, err := niu.Sell(gid, uid)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR:", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(sell))
|
||
})
|
||
en.OnFullMatch("牛牛背包", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||
gid := ctx.Event.GroupID
|
||
uid := ctx.Event.UserID
|
||
bag, err := niu.Bag(gid, uid)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR:", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(bag))
|
||
})
|
||
en.OnFullMatch("牛牛商店", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||
gid := ctx.Event.GroupID
|
||
uid := ctx.Event.UserID
|
||
|
||
if _, err := niu.GetWordNiuNiu(gid, uid); err != nil {
|
||
ctx.SendChain(message.Text(niu.ErrNoNiuNiu))
|
||
return
|
||
}
|
||
|
||
propMap := map[int]struct {
|
||
name string
|
||
cost int
|
||
scope string
|
||
description string
|
||
count int
|
||
}{
|
||
1: {"伟哥", 300, "打胶", "可以让你打胶每次都增长", 5},
|
||
2: {"媚药", 300, "打胶", "可以让你打胶每次都减少", 5},
|
||
3: {"击剑神器", 500, "jj", "可以让你每次击剑都立于不败之地", 2},
|
||
4: {"击剑神稽", 500, "jj", "可以让你每次击剑都失败", 2},
|
||
}
|
||
|
||
var messages message.Message
|
||
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text("牛牛商店当前售卖的物品如下")))
|
||
for id := range propMap {
|
||
product := propMap[id]
|
||
productInfo := fmt.Sprintf("商品%d\n商品名: %s\n商品价格: %dATRI币\n商品作用域: %s\n商品描述: %s\n使用次数:%d",
|
||
id, product.name, product.cost, product.scope, product.description, product.count)
|
||
messages = append(messages, ctxext.FakeSenderForwardNode(ctx, message.Text(productInfo)))
|
||
}
|
||
if id := ctx.Send(messages).ID(); id == 0 {
|
||
ctx.Send(message.Text("发送商店失败"))
|
||
return
|
||
}
|
||
|
||
ctx.SendChain(message.Text("输入对应序号进行购买商品"))
|
||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.CheckUser(uid), zero.CheckGroup(gid), zero.RegexRule(`^(\d+)$`)).Repeat()
|
||
defer cancel()
|
||
timer := time.NewTimer(120 * time.Second)
|
||
answer := ""
|
||
defer timer.Stop()
|
||
for {
|
||
select {
|
||
case <-timer.C:
|
||
ctx.SendChain(message.At(uid), message.Text(" 超时,已自动取消"))
|
||
return
|
||
case r := <-recv:
|
||
answer = r.Event.Message.String()
|
||
n, err := strconv.Atoi(answer)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
return
|
||
}
|
||
|
||
if err = niu.Store(gid, uid, n); err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
return
|
||
}
|
||
|
||
ctx.SendChain(message.Text("购买成功!"))
|
||
return
|
||
}
|
||
}
|
||
})
|
||
en.OnFullMatch("赎牛牛", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||
gid := ctx.Event.GroupID
|
||
uid := ctx.Event.UserID
|
||
last, ok := jjCount.Load(fmt.Sprintf("%d_%d", gid, uid))
|
||
|
||
if !ok {
|
||
ctx.SendChain(message.Text("你还没有被厥呢"))
|
||
return
|
||
}
|
||
|
||
if time.Since(last.TimeLimit) > time.Hour {
|
||
ctx.SendChain(message.Text("时间已经过期了,牛牛已被收回!"))
|
||
jjCount.Delete(fmt.Sprintf("%d_%d", gid, uid))
|
||
return
|
||
}
|
||
|
||
if last.Count < 4 {
|
||
ctx.SendChain(message.Text("你还没有被厥够4次呢,不能赎牛牛"))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Text("再次确认一下哦,这次赎牛牛,牛牛长度将会变成", last.Length, "cm\n还需要嘛【是|否】"))
|
||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.CheckUser(uid), zero.CheckGroup(gid), zero.RegexRule(`^(是|否)$`)).Repeat()
|
||
defer cancel()
|
||
timer := time.NewTimer(2 * time.Minute)
|
||
defer timer.Stop()
|
||
for {
|
||
select {
|
||
case <-timer.C:
|
||
ctx.SendChain(message.Text("操作超时,已自动取消"))
|
||
return
|
||
case c := <-recv:
|
||
answer := c.Event.Message.String()
|
||
if answer == "否" {
|
||
ctx.SendChain(message.Text("取消成功!"))
|
||
return
|
||
}
|
||
|
||
if err := niu.Redeem(gid, uid, last.Length); err == nil {
|
||
ctx.SendChain(message.Text("ERROR:", err))
|
||
return
|
||
}
|
||
|
||
jjCount.Delete(fmt.Sprintf("%d_%d", gid, uid))
|
||
|
||
ctx.SendChain(message.At(uid), message.Text(fmt.Sprintf("恭喜你!成功赎回牛牛,当前长度为:%.2fcm", last.Length)))
|
||
return
|
||
}
|
||
}
|
||
})
|
||
en.OnFullMatch("牛子长度排行", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||
gid := ctx.Event.GroupID
|
||
infos, err := niu.GetRankingInfo(gid, true)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
return
|
||
}
|
||
img, err := processRankingImg(infos, ctx, true)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.ImageBytes(img))
|
||
})
|
||
en.OnFullMatch("牛子深度排行", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||
gid := ctx.Event.GroupID
|
||
infos, err := niu.GetRankingInfo(gid, false)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
return
|
||
}
|
||
img, err := processRankingImg(infos, ctx, false)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.ImageBytes(img))
|
||
})
|
||
en.OnFullMatch("查看我的牛牛", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||
uid := ctx.Event.UserID
|
||
gid := ctx.Event.GroupID
|
||
view, err := niu.View(gid, uid, ctx.CardOrNickName(uid))
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(view))
|
||
})
|
||
en.OnRegex(`^(?:.*使用(.*))??打胶$`, zero.OnlyGroup).SetBlock(true).Limit(func(ctx *zero.Ctx) *rate.Limiter {
|
||
lt := dajiaoLimiter.Load(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID))
|
||
ctx.State["dajiao_last_touch"] = lt.LastTouch()
|
||
return lt
|
||
}, func(ctx *zero.Ctx) {
|
||
timePass := int(time.Since(time.Unix(ctx.State["dajiao_last_touch"].(int64), 0)).Seconds())
|
||
ctx.SendChain(message.Text(randomChoice([]string{
|
||
fmt.Sprintf("才过去了%ds时间,你就又要打🦶了,身体受得住吗", timePass),
|
||
fmt.Sprintf("不行不行,你的身体会受不了的,歇%ds再来吧", 90-timePass),
|
||
fmt.Sprintf("休息一下吧,会炸膛的!%ds后再来吧", 90-timePass),
|
||
fmt.Sprintf("打咩哟,你的牛牛会爆炸的,休息%ds再来吧", 90-timePass),
|
||
})))
|
||
}).Handle(func(ctx *zero.Ctx) {
|
||
// 获取群号和用户ID
|
||
gid := ctx.Event.GroupID
|
||
uid := ctx.Event.UserID
|
||
fiancee := ctx.State["regex_matched"].([]string)
|
||
|
||
msg, err := niu.HitGlue(gid, uid, fiancee[1])
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
dajiaoLimiter.Delete(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(msg))
|
||
})
|
||
en.OnFullMatch("注册牛牛", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||
gid := ctx.Event.GroupID
|
||
uid := ctx.Event.UserID
|
||
msg, err := niu.Register(gid, uid)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(msg))
|
||
})
|
||
en.OnMessage(zero.NewPattern(nil).Text(`^(?:.*使用(.*))??jj`).At().AsRule(),
|
||
zero.OnlyGroup).SetBlock(true).Limit(func(ctx *zero.Ctx) *rate.Limiter {
|
||
lt := jjLimiter.Load(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID))
|
||
ctx.State["jj_last_touch"] = lt.LastTouch()
|
||
return lt
|
||
}, func(ctx *zero.Ctx) {
|
||
timePass := int(time.Since(time.Unix(ctx.State["jj_last_touch"].(int64), 0)).Seconds())
|
||
ctx.SendChain(message.Text(randomChoice([]string{
|
||
fmt.Sprintf("才过去了%ds时间,你就又要击剑了,真是饥渴难耐啊", timePass),
|
||
fmt.Sprintf("不行不行,你的身体会受不了的,歇%ds再来吧", 150-timePass),
|
||
fmt.Sprintf("你这种男同就应该被送去集中营!等待%ds再来吧", 150-timePass),
|
||
fmt.Sprintf("打咩哟!你的牛牛会炸的,休息%ds再来吧", 150-timePass),
|
||
})))
|
||
},
|
||
).Handle(func(ctx *zero.Ctx) {
|
||
patternParsed := ctx.State[zero.KeyPattern].([]zero.PatternParsed)
|
||
adduser, err := strconv.ParseInt(patternParsed[1].At(), 10, 64)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
jjLimiter.Delete(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID))
|
||
return
|
||
}
|
||
uid := ctx.Event.UserID
|
||
gid := ctx.Event.GroupID
|
||
msg, length, err := niu.JJ(gid, uid, adduser, patternParsed[0].Text()[1])
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
jjLimiter.Delete(fmt.Sprintf("%d_%d", ctx.Event.GroupID, ctx.Event.UserID))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(msg))
|
||
j := fmt.Sprintf("%d_%d", gid, adduser)
|
||
count, ok := jjCount.Load(j)
|
||
var c lastLength
|
||
// 按照最后一次被jj时的时间计算,超过60分钟则重置
|
||
if !ok {
|
||
c = lastLength{
|
||
TimeLimit: time.Now(),
|
||
Count: 1,
|
||
Length: length,
|
||
}
|
||
} else {
|
||
c = lastLength{
|
||
TimeLimit: time.Now(),
|
||
Count: count.Count + 1,
|
||
Length: count.Length,
|
||
}
|
||
if time.Since(c.TimeLimit) > time.Hour {
|
||
c = lastLength{
|
||
TimeLimit: time.Now(),
|
||
Count: 1,
|
||
Length: length,
|
||
}
|
||
}
|
||
}
|
||
|
||
jjCount.Store(j, &c)
|
||
if c.Count > 2 {
|
||
ctx.SendChain(message.Text(randomChoice([]string{
|
||
fmt.Sprintf("你们太厉害了,对方已经被你们打了%d次了,你们可以继续找他🤺", c.Count),
|
||
"你们不要再找ta🤺啦!"},
|
||
)))
|
||
|
||
if c.Count >= 4 {
|
||
id := ctx.SendPrivateMessage(adduser,
|
||
message.Text(fmt.Sprintf("你在%d群里已经被厥冒烟了,快去群里赎回你原本的牛牛!\n发送:`赎牛牛`即可!", gid)))
|
||
if id == 0 {
|
||
ctx.SendChain(message.At(adduser), message.Text("快发送`赎牛牛`来赎回你原本的牛牛!"))
|
||
}
|
||
}
|
||
}
|
||
})
|
||
en.OnFullMatch("注销牛牛", zero.OnlyGroup).SetBlock(true).Handle(func(ctx *zero.Ctx) {
|
||
uid := ctx.Event.UserID
|
||
gid := ctx.Event.GroupID
|
||
key := fmt.Sprintf("%d_%d", gid, uid)
|
||
data, ok := register.Load(key)
|
||
switch {
|
||
case !ok || time.Since(data.TimeLimit) > time.Hour*12:
|
||
data = &lastLength{
|
||
TimeLimit: time.Now(),
|
||
Count: 1,
|
||
}
|
||
default:
|
||
if err := wallet.InsertWalletOf(uid, -data.Count*50); err != nil {
|
||
ctx.SendChain(message.Text("你的钱不够你注销牛牛了,这次注销需要", data.Count*50, wallet.GetWalletName()))
|
||
return
|
||
}
|
||
}
|
||
register.Store(key, data)
|
||
msg, err := niu.Cancel(gid, uid)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("ERROR: ", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text(msg))
|
||
})
|
||
}
|
||
|
||
func randomChoice(options []string) string {
|
||
return options[rand.Intn(len(options))]
|
||
}
|