funny-nation / Funny-Nation

This is a money-centric "Metaverse" within a Discord server.
https://www.funnynation.org/
MIT License
126 stars 37 forks source link

Refector Gift System #148

Open plbin97 opened 2 years ago

plbin97 commented 2 years ago

重构礼物系统

需要把你之前的礼物系统重构一下

Database

model Inventory {
    id Int @id @default(autoincrement())
    name String // 比如说:飞机
    inventoryValue BigInt
    category InventoryCategory @default(gift)
    ownerID String
    owner User @relation(fields: [ownerID], references: [id])
    createdAt DateTime @default(now())
    guildID String
    guild Guild @relation(fields: [guildID], references: [id])
}

其中的概念是这样的:

Use Case 1 - 管理员创建礼物

User Story

作为一名管理员, 我需要新建一个礼物, 于是我输入命令

/gift create [礼物名称(String)] [礼物emoji(string)]

则弹出一个modal,其中modal里面包含几个text input:

当我输入完,点击submit, 礼物将会被写入数据库,并且bot在当前频道reply一句

礼物已创建

之后,bot播报一下,新的礼物已产生

Acceptance Criteria

当我创建礼物时, 如果我不是管理员,reply。 系统需要监测礼物名称是否重复,礼物emoji是否重复, 如果有重复,reply。 如果该guild有20个礼物,reply 如果该guild在1分钟之内更新过一次command,reply 以上没有问题,就弹出modal。

在modal中添加text input 的constraint, 礼物价格必须时0以上的number,

当我输入完,点击submit, 系统需要再次监测一下我是不是admin 然后再次监测礼物的name和emoji是否重复 然后再添加进数据库

然后,开始播报新的礼物, 如果我在guild中设置过announcementChanne的话(Guild底下的announcementChanneID字段不为null), Bot在announcement channel中发送一个embed, 里面含有新的礼物名称,礼物介绍,礼物emoji, 如果我没设置announcementChannel的话,则发送在当前这个频道。 最后,该频道的commands需要被更新(执行/src/commands-manager底下的setUpCommandsForGuild

Use Case 2 - 用户发送礼物

User Story

作为一名用户, 我想送礼物给我心仪的人, 于是我输入命令:

/gift send [礼物名称(option)] [礼物接收者(user)]

我的账户会扣除相应的金额,礼物接收者inventory会多一份那个礼物,同时我和ta的经验值增加。

Bot 回复道 “礼物已发送”。

回复之后,再进行礼物播报。

Acceptance Criteria

命令创建相对会多一些东西, 命令中的礼物名称,需要从数据库中获取, 于是在commands.ts文件中,在newCommand的异步函数中,guild ID 会从参数中传过来,然后通过该参数需要查询数据库中该guild的礼物,从而构建command的options。

newCommand(
  (language, guildID) => {
    const giftList = getGiftList(guildID)
    new SlashCommandBuilder()
    // Set up commands
  }

这就是为啥每次创建礼物和删除礼物的时候,需要更新该频道的礼物数据

当用户发送礼物:

如果用户不够钱,则reply错误 如果够钱,那么数据库中inventory添加一条数据, 然后发送者扣钱, 同时发送者和接受者的经验值增加, 增加礼物价值的百分之20。 之后,reply“送礼成功” 之后开始礼物播报,如下:

如果该guild的announcementChannelID为空, 则在当前频道发送一条带embed的消息, 如果announcementChannelID不为空,则在announcementChannel 发送。

消息为:

// 记得,不是reply,是send,因为reply在一个交互中只能用一次
channel.send({
    contents: `<@123321>给老板<@1233333>送上了一架飞机`,
    embeds: [new MessageEmbed()]
})

embed中只需要展示一个礼物的emoji,就行了 content中的<@xxx>是代表@某人, 其中xxx为某用户的ID, 然后,content的内容是从数据表Gift中的字段giftAnnouncement获取, 其中字段的内容需要被解析,从:

<@sender>给老板<@receiver>送上了一架飞机

解析成

<@123321>给老板<@1233333>送上了一架飞机

Use Case 3 - 管理员删除礼物

User Story

作为一名管理员, 本Guild不再需要某个礼物了, 于是我输入命令

/gift remove [礼物名称(option)]

来删除某个礼物

Acceptance Criteria

礼物options跟上一个Use Case一样,需要从数据库获取。

我删除礼物时, 如果我不是管理员,则reply 如果我礼物不存在,则reply

条件满足,则从Gift数据表中删除礼物。

然后,reply“删除成功”

然后,更新命令,因为礼物发生了更新。

注意

plbin97 commented 2 years ago

https://vimeo.com/manage/videos/739332384/d19ca0de83