mirror of
https://github.com/FloatTech/ZeroBot-Plugin.git
synced 2025-12-19 05:30:07 +08:00
816 lines
25 KiB
Go
816 lines
25 KiB
Go
// Package mcfish 钓鱼模拟器
|
||
package mcfish
|
||
|
||
import (
|
||
"image"
|
||
"image/color"
|
||
"strconv"
|
||
"strings"
|
||
"time"
|
||
|
||
"github.com/FloatTech/AnimeAPI/wallet"
|
||
"github.com/FloatTech/floatbox/file"
|
||
"github.com/FloatTech/floatbox/math"
|
||
"github.com/FloatTech/gg"
|
||
"github.com/FloatTech/imgfactory"
|
||
"github.com/FloatTech/zbputils/control"
|
||
"github.com/FloatTech/zbputils/img/text"
|
||
"github.com/sirupsen/logrus"
|
||
zero "github.com/wdvxdr1123/ZeroBot"
|
||
"github.com/wdvxdr1123/ZeroBot/extension/rate"
|
||
"github.com/wdvxdr1123/ZeroBot/message"
|
||
)
|
||
|
||
var (
|
||
storeLimiter = rate.NewManager[int64](time.Second*3, 1)
|
||
refresh = false
|
||
timeNow = 0
|
||
refreshFish = func(ctx *zero.Ctx) bool {
|
||
if refresh && timeNow == time.Now().Day() {
|
||
return true
|
||
}
|
||
refresh, err := dbdata.refreshStroeInfo()
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.1]:", err))
|
||
return refresh
|
||
}
|
||
timeNow = time.Now().Day()
|
||
return refresh
|
||
}
|
||
)
|
||
|
||
func limitSet(ctx *zero.Ctx) *rate.Limiter {
|
||
return storeLimiter.Load(ctx.Event.UserID)
|
||
}
|
||
|
||
func init() {
|
||
engine.OnFullMatchGroup([]string{"钓鱼看板", "钓鱼商店"}, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) {
|
||
infos, err := dbdata.getStoreInfo()
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.2]:", err))
|
||
return
|
||
}
|
||
var picImage image.Image
|
||
if len(infos) == 0 {
|
||
picImage, err = drawStroeEmptyImage()
|
||
} else {
|
||
picImage, err = drawStroeInfoImage(infos)
|
||
}
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.3]:", err))
|
||
return
|
||
}
|
||
pic, err := imgfactory.ToBytes(picImage)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.4]:", err))
|
||
return
|
||
}
|
||
ctx.SendChain(message.ImageBytes(pic))
|
||
})
|
||
engine.OnRegex(`^出售(`+strings.Join(thingList, "|")+`)\s*(\d*)$`, getdb, refreshFish).SetBlock(true).Limit(limitSet).Handle(func(ctx *zero.Ctx) {
|
||
uid := ctx.Event.UserID
|
||
thingName := ctx.State["regex_matched"].([]string)[1]
|
||
number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[2])
|
||
if number == 0 || strings.Contains(thingName, "竿") {
|
||
number = 1
|
||
}
|
||
|
||
// 检测物品交易次数
|
||
if strings.Contains(thingName, "竿") {
|
||
number, err := dbdata.checkCanSalesFor(uid, thingName, number)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR,查询购买资质失败]:", err))
|
||
return
|
||
}
|
||
if number <= 0 {
|
||
ctx.SendChain(message.Text("一天只能交易10把鱼竿,明天再来售卖吧"))
|
||
return
|
||
}
|
||
}
|
||
|
||
articles, err := dbdata.getUserThingInfo(uid, thingName)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.5]:", err))
|
||
return
|
||
}
|
||
if len(articles) == 0 {
|
||
ctx.SendChain(message.Text("你的背包不存在该物品"))
|
||
return
|
||
}
|
||
index := 0
|
||
thing := article{}
|
||
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 {
|
||
if info.Other != "" && info.Name != "美西螈" {
|
||
msg = append(msg, message.Text("[", i, "] ", info.Name, "(", info.Other, ")\n"))
|
||
} else {
|
||
msg = append(msg, message.Text(
|
||
"[", i, "]", info.Name, " 数量: ", info.Number, "\n"))
|
||
}
|
||
}
|
||
msg = append(msg, message.Text("————————\n输入对应序号进行出售,或回复“取消”取消"))
|
||
ctx.Send(msg)
|
||
// 等待用户下一步选择
|
||
sell := false
|
||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||
defer cancel()
|
||
for {
|
||
select {
|
||
case <-time.After(time.Second * 120):
|
||
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
|
||
}
|
||
index, err = strconv.Atoi(nextcmd)
|
||
if err != nil || index > len(articles)-1 {
|
||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入正确的序号"))
|
||
continue
|
||
}
|
||
sell = true
|
||
}
|
||
if sell {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
thing = articles[index]
|
||
if thing.Number < number {
|
||
number = thing.Number
|
||
}
|
||
|
||
var pice int
|
||
if strings.Contains(thingName, "竿") || thingName == "三叉戟" {
|
||
poleInfo := strings.Split(articles[index].Other, "/")
|
||
durable, _ := strconv.Atoi(poleInfo[0])
|
||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||
pice = (priceList[thingName] - (durationList[thingName] - durable) - maintenance*2 +
|
||
induceLevel*600*discountList["诱钓"]/100 +
|
||
favorLevel*1800*discountList["海之眷顾"]/100) * discountList[thingName] / 100
|
||
} else {
|
||
pice = priceList[thingName] * discountList[thingName] / 100
|
||
}
|
||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("是否接受商店将以", pice*number*8/10, "收购", number, "个", thingName, "?\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
|
||
}
|
||
}
|
||
|
||
records, err := dbdata.getUserThingInfo(uid, "唱片")
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.9.1]:", err))
|
||
return
|
||
}
|
||
if len(records) != 0 {
|
||
recordInfo := records[0]
|
||
numberOfRecord := recordInfo.Number
|
||
if thingName == "唱片" {
|
||
numberOfRecord -= number
|
||
}
|
||
if numberOfRecord > 0 {
|
||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("是否使用唱片让价格翻倍?\n回答\"是\"或\"否\"")))
|
||
// 等待用户下一步选择
|
||
recv, cancel2 := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(是|否)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||
defer cancel2()
|
||
use := false
|
||
checkTime := false
|
||
for {
|
||
select {
|
||
case <-time.After(time.Second * 60):
|
||
checkTime = true
|
||
case e := <-recv:
|
||
nextcmd := e.Event.Message.String()
|
||
if nextcmd == "是" {
|
||
use = true
|
||
}
|
||
checkTime = true
|
||
}
|
||
if checkTime {
|
||
break
|
||
}
|
||
}
|
||
if use {
|
||
pice *= 2
|
||
if thingName == "唱片" {
|
||
thing.Number--
|
||
}
|
||
recordInfo.Number--
|
||
err = dbdata.updateUserThingInfo(uid, recordInfo)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.9.2]:", err))
|
||
return
|
||
}
|
||
}
|
||
}
|
||
}
|
||
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
|
||
}
|
||
thing.Number -= number
|
||
err = dbdata.updateUserThingInfo(uid, thing)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.6]:", err))
|
||
return
|
||
}
|
||
newCommodity := store{}
|
||
if strings.Contains(thing.Name, "竿") || thing.Name == "三叉戟" {
|
||
if pice >= priceList[thing.Name]*2 { // 无附魔的不要
|
||
newCommodity = store{
|
||
Duration: time.Now().Unix(),
|
||
Type: "pole",
|
||
Name: thing.Name,
|
||
Number: 1,
|
||
Price: pice,
|
||
Other: thing.Other,
|
||
}
|
||
polelist, _ := dbdata.getStoreThingInfo(thing.Name)
|
||
if len(polelist) > 5 { // 超出上限的不要
|
||
newCommodity.Type = "waste"
|
||
}
|
||
}
|
||
} else {
|
||
things, err1 := dbdata.getStoreThingInfo(thingName)
|
||
if err1 != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.8]:", err1))
|
||
return
|
||
}
|
||
if len(things) == 0 {
|
||
things = append(things, store{
|
||
Duration: time.Now().Unix(),
|
||
Name: thing.Name,
|
||
Price: pice,
|
||
Type: thing.Type,
|
||
})
|
||
}
|
||
newCommodity = things[0]
|
||
if newCommodity.Number < 255 {
|
||
newCommodity.Number += number
|
||
if newCommodity.Number > 255 {
|
||
newCommodity.Number = 255
|
||
}
|
||
}
|
||
}
|
||
if newCommodity != (store{}) && newCommodity.Type != "waste" { // 不收垃圾
|
||
err = dbdata.updateStoreInfo(newCommodity)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.9]:", err))
|
||
return
|
||
}
|
||
}
|
||
pice = pice * 8 / 10
|
||
err = wallet.InsertWalletOf(uid, pice*number)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.10]:", err))
|
||
return
|
||
}
|
||
if strings.Contains(thingName, "竿") {
|
||
err = dbdata.updateCurseFor(uid, "sell", 1)
|
||
if err != nil {
|
||
logrus.Warnln(err)
|
||
}
|
||
}
|
||
// 更新交易限制
|
||
err = dbdata.updateCanSalesFor(uid, thingName, number)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR,记录鱼类交易数量失败,此次交易不记录]:", err))
|
||
}
|
||
|
||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("成功出售", thingName, ":", number, "个", ",你赚到了", 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
|
||
}
|
||
}
|
||
err = wallet.InsertWalletOf(uid, pice)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR,出售垃圾失败,回收站卷款跑路了]:", 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
|
||
thingName := ctx.State["regex_matched"].([]string)[1]
|
||
number, _ := strconv.Atoi(ctx.State["regex_matched"].([]string)[2])
|
||
if number == 0 || strings.Contains(thingName, "竿") {
|
||
number = 1
|
||
}
|
||
|
||
numberOfPole, err := dbdata.getNumberFor(uid, "竿")
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.9.3]:", err))
|
||
return
|
||
}
|
||
if numberOfPole > 50 {
|
||
ctx.SendChain(message.Text("你有", numberOfPole, "支鱼竿,大于50支的玩家不允许购买东西"))
|
||
return
|
||
}
|
||
|
||
// 检测物品交易次数
|
||
number, err = dbdata.checkCanSalesFor(uid, thingName, number)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.75]:", err))
|
||
return
|
||
}
|
||
if number <= 0 {
|
||
var msg string
|
||
if strings.Contains(thingName, "竿") {
|
||
msg = "一天只能交易10把鱼竿,明天再来购买吧"
|
||
} else {
|
||
msg = "一天只能购买30次物品,明天再来吧~"
|
||
}
|
||
ctx.SendChain(message.Text(msg))
|
||
return
|
||
}
|
||
|
||
thingInfos, err := dbdata.getStoreThingInfo(thingName)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.11]:", err))
|
||
return
|
||
}
|
||
if len(thingInfos) == 0 {
|
||
ctx.SendChain(message.Text("当前商店并没有上架该物品"))
|
||
return
|
||
}
|
||
if thingName == "净化书" {
|
||
curse, err := dbdata.getNumberFor(uid, "宝藏诅咒")
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.303]:", err))
|
||
return
|
||
}
|
||
if curse == 0 {
|
||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你身上没有诅咒,不能购买该商品"))
|
||
return
|
||
}
|
||
bless, err := dbdata.getNumberFor(uid, "净化书")
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.303]:", err))
|
||
return
|
||
}
|
||
if bless >= curse {
|
||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你身上净化书已足够,不能购买该商品"))
|
||
return
|
||
}
|
||
if curse < number {
|
||
number = curse
|
||
}
|
||
}
|
||
index := 0
|
||
pice := make([]int, 0, len(thingInfos))
|
||
for _, info := range thingInfos {
|
||
if strings.Contains(thingName, "竿") || thingName == "三叉戟" {
|
||
poleInfo := strings.Split(info.Other, "/")
|
||
durable, _ := strconv.Atoi(poleInfo[0])
|
||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||
thingPice := (priceList[info.Name] - (durationList[info.Name] - durable) - maintenance*2 +
|
||
induceLevel*600*discountList["诱钓"]/100 +
|
||
favorLevel*1800*discountList["海之眷顾"]/100) * discountList[info.Name] / 100
|
||
if strings.Contains(thingName, "初始木竿"){
|
||
thingPice = priceList["木竿"]+priceList["木竿"] * discountList["木竿"]/100
|
||
}
|
||
pice = append(pice, thingPice)
|
||
} else {
|
||
thingPice := priceList[info.Name] * discountList[info.Name] / 100
|
||
pice = append(pice, thingPice)
|
||
}
|
||
}
|
||
if len(thingInfos) > 1 {
|
||
msg := make(message.Message, 0, 3+len(thingInfos))
|
||
msg = append(msg, message.Text("找到以下物品:\n"))
|
||
for i, info := range thingInfos {
|
||
if strings.Contains(thingName, "竿") || thingName == "三叉戟" {
|
||
msg = append(msg, message.Text(
|
||
"[", i, "]", info.Name, "(", info.Other, ") 价格:", pice[i], "\n"))
|
||
} else {
|
||
msg = append(msg, message.Text(
|
||
"[", i, "]", info.Name, " 数量:", info.Number, " 价格:", pice[i], "\n"))
|
||
}
|
||
}
|
||
msg = append(msg, message.Text("————————\n输入对应序号进行购买,或回复“取消”取消"))
|
||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, msg...))
|
||
// 等待用户下一步选择
|
||
sell := false
|
||
recv, cancel := zero.NewFutureEvent("message", 999, false, zero.RegexRule(`^(取消|\d+)$`), zero.CheckUser(ctx.Event.UserID)).Repeat()
|
||
defer cancel()
|
||
for {
|
||
select {
|
||
case <-time.After(time.Second * 120):
|
||
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
|
||
}
|
||
index, err = strconv.Atoi(nextcmd)
|
||
if err != nil || index > len(thingInfos)-1 {
|
||
ctx.SendChain(message.At(ctx.Event.UserID), message.Text("请输入正确的序号"))
|
||
continue
|
||
}
|
||
sell = true
|
||
}
|
||
if sell {
|
||
break
|
||
}
|
||
}
|
||
}
|
||
|
||
thing := thingInfos[index]
|
||
if thing.Number < number {
|
||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("商店数量不足")))
|
||
return
|
||
}
|
||
price := pice[index] * number
|
||
|
||
msg := ""
|
||
times := math.Min(3, number)
|
||
coupon, err := dbdata.useCouponAt(uid, times)
|
||
if err != nil {
|
||
logrus.Warnln(err)
|
||
}
|
||
if coupon != -1 {
|
||
msg += "\n(半价福利还有" + strconv.Itoa(3-coupon) + "次)"
|
||
price = pice[index]*(number-coupon) + (pice[index]/2)*coupon
|
||
} else {
|
||
err = dbdata.updateBuyTimeFor(uid, 1)
|
||
if err != nil {
|
||
logrus.Warnln(err)
|
||
}
|
||
}
|
||
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) + "层诅咒)"
|
||
price = price * (100 + 10*curse) / 100
|
||
}
|
||
|
||
money := wallet.GetWalletOf(uid)
|
||
if money < price {
|
||
ctx.SendChain(message.Text("你身上的钱(", money, ")不够支付", msg))
|
||
return
|
||
}
|
||
|
||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你确定花费", price, "购买", number, "个", thingName, "?", msg, "\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
|
||
}
|
||
}
|
||
|
||
ok, err := dbdata.checkStoreFor(thing, number)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.11]:", err))
|
||
return
|
||
}
|
||
if !ok {
|
||
ctx.SendChain(message.Reply(ctx.Event.MessageID), message.Text("你慢了一步,物品被别人买走了"))
|
||
return
|
||
}
|
||
thing.Number -= number
|
||
err = dbdata.updateStoreInfo(thing)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.12]:", err))
|
||
return
|
||
}
|
||
err = wallet.InsertWalletOf(uid, -price)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.13]:", err))
|
||
return
|
||
}
|
||
newCommodity := article{}
|
||
if strings.Contains(thingName, "竿") || thingName == "三叉戟" {
|
||
newCommodity = article{
|
||
Duration: time.Now().Unix(),
|
||
Type: thing.Type,
|
||
Name: thing.Name,
|
||
Number: 1,
|
||
Other: thing.Other,
|
||
}
|
||
if thingName == "初始木竿"{
|
||
newCommodity.Name = "木竿"
|
||
}
|
||
} else {
|
||
things, err1 := dbdata.getUserThingInfo(uid, thingName)
|
||
if err1 != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.15]:", err1))
|
||
return
|
||
}
|
||
if len(things) == 0 {
|
||
things = append(things, article{
|
||
Duration: time.Now().Unix(),
|
||
Name: thing.Name,
|
||
Type: thing.Type,
|
||
})
|
||
}
|
||
newCommodity = things[0]
|
||
newCommodity.Number += number
|
||
}
|
||
err = dbdata.updateUserThingInfo(uid, newCommodity)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR at store.go.14]:", err))
|
||
return
|
||
}
|
||
if strings.Contains(thingName, "竿") {
|
||
err = dbdata.updateCurseFor(uid, "buy", 1)
|
||
if err != nil {
|
||
logrus.Warnln(err)
|
||
}
|
||
}
|
||
// 更新交易限制
|
||
err = dbdata.updateCanSalesFor(uid, thingName, number)
|
||
if err != nil {
|
||
ctx.SendChain(message.Text("[ERROR,记录鱼类交易数量失败,此次交易不记录]:", err))
|
||
}
|
||
ctx.Send(message.ReplyWithMessage(ctx.Event.MessageID, message.Text("你用", price, "购买了", number, thingName)))
|
||
})
|
||
}
|
||
|
||
func drawStroeEmptyImage() (picImage image.Image, err error) {
|
||
fontdata, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
canvas := gg.NewContext(1000, 300)
|
||
// 画底色
|
||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||
canvas.SetRGBA255(255, 255, 255, 150)
|
||
canvas.Fill()
|
||
// 边框框
|
||
canvas.DrawRectangle(0, 0, 1000, 300)
|
||
canvas.SetLineWidth(3)
|
||
canvas.SetRGBA255(0, 0, 0, 255)
|
||
canvas.Stroke()
|
||
|
||
canvas.SetColor(color.Black)
|
||
err = canvas.ParseFontFace(fontdata, 100)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
textW, textH := canvas.MeasureString("价格信息")
|
||
canvas.DrawString("价格信息", 10, 10+textH*1.2)
|
||
canvas.DrawLine(10, textH*1.6, textW, textH*1.6)
|
||
canvas.SetLineWidth(3)
|
||
canvas.SetRGBA255(0, 0, 0, 255)
|
||
canvas.Stroke()
|
||
if err = canvas.ParseFontFace(fontdata, 50); err != nil {
|
||
return nil, err
|
||
}
|
||
canvas.DrawStringAnchored("当前商店并没有上架任何物品", 500, 10+textH*2+50, 0.5, 0)
|
||
return canvas.Image(), nil
|
||
}
|
||
|
||
func drawStroeInfoImage(stroeInfo []store) (picImage image.Image, err error) {
|
||
fontdata, err := file.GetLazyData(text.BoldFontFile, control.Md5File, true)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
canvas := gg.NewContext(1, 1)
|
||
err = canvas.ParseFontFace(fontdata, 100)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
titleW, titleH := canvas.MeasureString("价格信息")
|
||
|
||
err = canvas.ParseFontFace(fontdata, 50)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
_, textH := canvas.MeasureString("高度")
|
||
nameW, _ := canvas.MeasureString("下界合金竿(100/100/0/0)")
|
||
numberW, _ := canvas.MeasureString("10000")
|
||
priceW, _ := canvas.MeasureString("10000")
|
||
|
||
bolckW := int(10 + nameW + 50 + numberW + 50 + priceW + 10)
|
||
backY := 10 + int(titleH*2+10)*2 + 10 + (len(stroeInfo)+len(discountList)/2+2)*int(textH*2) + 10
|
||
canvas = gg.NewContext(bolckW, math.Max(backY, 500))
|
||
// 画底色
|
||
canvas.DrawRectangle(0, 0, float64(bolckW), float64(backY))
|
||
canvas.SetRGBA255(150, 150, 150, 255)
|
||
canvas.Fill()
|
||
|
||
// 放字
|
||
canvas.SetColor(color.Black)
|
||
err = canvas.ParseFontFace(fontdata, 100)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
canvas.DrawString("今日波动", 10, 10+titleH*1.2)
|
||
canvas.DrawLine(10, titleH*1.6, titleW, titleH*1.6)
|
||
canvas.SetLineWidth(3)
|
||
canvas.SetRGBA255(0, 0, 0, 255)
|
||
canvas.Stroke()
|
||
|
||
textDy := 10 + titleH*1.7
|
||
if err = canvas.ParseFontFace(fontdata, 35); err != nil {
|
||
return nil, err
|
||
}
|
||
textDx, textDh := canvas.MeasureString("下界合金竿(均价1000)")
|
||
valueDx, _ := canvas.MeasureString("+100%")
|
||
i := 0
|
||
for _, name := range thingList {
|
||
text := name + "(均价" + strconv.Itoa(priceList[name]) + ") "
|
||
|
||
if i == 2 {
|
||
i = 0
|
||
textDy += textDh * 2
|
||
}
|
||
canvas.SetColor(color.Black)
|
||
canvas.DrawStringAnchored(text, 20+(textDx+valueDx+10)*float64(i)+10, textDy+textDh/2, 0, 0.5)
|
||
if discountList[name]-100 > 0 {
|
||
canvas.SetRGBA255(200, 50, 50, 255)
|
||
text = "+" + strconv.Itoa(discountList[name]-100) + "%"
|
||
} else {
|
||
canvas.SetRGBA255(63, 133, 55, 255)
|
||
text = strconv.Itoa(discountList[name]-100) + "%"
|
||
}
|
||
canvas.DrawStringAnchored(text, 20+(textDx+valueDx+10)*float64(i)+10+textDx+10, textDy+textDh/2, 0, 0.5)
|
||
i++
|
||
}
|
||
canvas.SetColor(color.Black)
|
||
textDy += textDh * 2
|
||
canvas.DrawStringAnchored("注:出售商品将会额外扣除20%的税收,附魔鱼竿请按实际价格", 10, textDy+10+textDh/2, 0, 0.5)
|
||
|
||
textDy += textH * 2
|
||
err = canvas.ParseFontFace(fontdata, 100)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
canvas.DrawString("上架内容", 10, textDy+titleH*1.2)
|
||
canvas.DrawLine(10, textDy+titleH*1.6, titleW, textDy+titleH*1.6)
|
||
canvas.SetLineWidth(3)
|
||
canvas.SetRGBA255(0, 0, 0, 255)
|
||
canvas.Stroke()
|
||
|
||
textDy += 10 + titleH*1.7
|
||
if err = canvas.ParseFontFace(fontdata, 50); err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
canvas.DrawStringAnchored("名称", 10+nameW/2, textDy+textH/2, 0.5, 0.5)
|
||
canvas.DrawStringAnchored("数量", 10+nameW+10+numberW/2, textDy+textH/2, 0.5, 0.5)
|
||
canvas.DrawStringAnchored("价格", 10+nameW+10+numberW+50+priceW/2, textDy+textH/2, 0.5, 0.5)
|
||
|
||
for _, info := range stroeInfo {
|
||
textDy += textH * 2
|
||
name := info.Name
|
||
if info.Other != "" && info.Name != "美西螈" {
|
||
name += "(" + info.Other + ")"
|
||
}
|
||
numberStr := strconv.Itoa(info.Number)
|
||
pice := 0
|
||
if strings.Contains(name, "竿") {
|
||
poleInfo := strings.Split(info.Other, "/")
|
||
durable, _ := strconv.Atoi(poleInfo[0])
|
||
maintenance, _ := strconv.Atoi(poleInfo[1])
|
||
induceLevel, _ := strconv.Atoi(poleInfo[2])
|
||
favorLevel, _ := strconv.Atoi(poleInfo[3])
|
||
pice = (priceList[info.Name] - (durationList[info.Name] - durable) - maintenance*2 + induceLevel*600 + favorLevel*1800) * discountList[info.Name] / 100
|
||
if strings.Contains(name, "初始木竿"){
|
||
pice = priceList["木竿"]+priceList["木竿"] * discountList["木竿"]/100
|
||
}
|
||
} else {
|
||
pice = priceList[info.Name] * discountList[info.Name] / 100
|
||
}
|
||
|
||
canvas.DrawStringAnchored(name, 10+nameW/2, textDy+textH/2, 0.5, 0.5)
|
||
canvas.DrawStringAnchored(numberStr, 10+nameW+10+numberW/2, textDy+textH/2, 0.5, 0.5)
|
||
canvas.DrawStringAnchored(strconv.Itoa(pice), 10+nameW+10+numberW+50+priceW/2, textDy+textH/2, 0.5, 0.5)
|
||
}
|
||
return canvas.Image(), nil
|
||
}
|