Add list moons command (#449)
- Add concept of moons to the database - Add the list moons command to view a user's moons - This command is paginated using buttons #195 Reviewed-on: #449 Reviewed-by: VylpesTester <tester@vylpes.com> Co-authored-by: Ethan Lane <ethan@vylpes.com> Co-committed-by: Ethan Lane <ethan@vylpes.com>
This commit is contained in:
parent
8e87fd6618
commit
e2ec042fcd
10 changed files with 235 additions and 3 deletions
|
@ -7,7 +7,7 @@
|
|||
# any secret values.
|
||||
|
||||
BOT_TOKEN=
|
||||
BOT_VER=3.2.1
|
||||
BOT_VER=3.3.0
|
||||
BOT_AUTHOR=Vylpes
|
||||
BOT_OWNERID=147392775707426816
|
||||
BOT_CLIENTID=682942374040961060
|
||||
|
@ -23,4 +23,6 @@ DB_NAME=vylbot
|
|||
DB_AUTH_USER=dev
|
||||
DB_AUTH_PASS=dev
|
||||
DB_SYNC=true
|
||||
DB_LOGGING=true
|
||||
DB_LOGGING=true
|
||||
DB_ROOT_HOST=0.0.0.0
|
||||
DB_DATA_LOCATION=./.temp/database
|
||||
|
|
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -106,4 +106,4 @@ dist
|
|||
config.json
|
||||
.DS_Store
|
||||
ormconfig.json
|
||||
.temp/
|
||||
.temp/
|
||||
|
|
10
database/3.3.0/1719856023429-CreateMoon/Up/01-Moon.sql
Normal file
10
database/3.3.0/1719856023429-CreateMoon/Up/01-Moon.sql
Normal file
|
@ -0,0 +1,10 @@
|
|||
CREATE TABLE `moon` (
|
||||
`Id` varchar(255) NOT NULL,
|
||||
`WhenCreated` datetime NOT NULL,
|
||||
`WhenUpdated` datetime NOT NULL,
|
||||
`MoonNumber` int NOT NULL,
|
||||
`UserId` varchar(255) NOT NULL,
|
||||
`Description` varchar(255) NOT NULL
|
||||
`WhenArchived` datetime NULL,
|
||||
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;
|
||||
|
14
src/buttonEvents/moons.ts
Normal file
14
src/buttonEvents/moons.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
import {ButtonInteraction} from "discord.js";
|
||||
import {ButtonEvent} from "../type/buttonEvent";
|
||||
import List from "./moons/list";
|
||||
|
||||
export default class Moons extends ButtonEvent {
|
||||
public override async execute(interaction: ButtonInteraction): Promise<void> {
|
||||
const action = interaction.customId.split(" ")[1];
|
||||
|
||||
switch (action) {
|
||||
case "list":
|
||||
await List(interaction);
|
||||
}
|
||||
}
|
||||
}
|
53
src/buttonEvents/moons/list.ts
Normal file
53
src/buttonEvents/moons/list.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
import {ActionRowBuilder, ButtonBuilder, ButtonInteraction, ButtonStyle, EmbedBuilder} from "discord.js";
|
||||
import Moon from "../../database/entities/Moon";
|
||||
import EmbedColours from "../../constants/EmbedColours";
|
||||
|
||||
export default async function List(interaction: ButtonInteraction) {
|
||||
if (!interaction.guild) return;
|
||||
|
||||
const userId = interaction.customId.split(" ")[2];
|
||||
const page = interaction.customId.split(" ")[3];
|
||||
|
||||
if (!userId || !page) return;
|
||||
|
||||
const pageNumber = Number(page);
|
||||
|
||||
const member = interaction.guild.members.cache.find(x => x.user.id == userId);
|
||||
|
||||
const pageLength = 10;
|
||||
|
||||
const moons = await Moon.FetchPaginatedMoonsByUserId(userId, pageLength, pageNumber);
|
||||
|
||||
if (!moons || moons[0].length == 0) {
|
||||
await interaction.reply(`${member?.user.username ?? "This user"} does not have any moons or page is invalid.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const totalPages = Math.ceil(moons[1] / pageLength);
|
||||
|
||||
const description = moons[0].flatMap(x => `${x.MoonNumber}. ${x.Description.slice(0, 15)}`);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${member?.user.username}'s Moons`)
|
||||
.setColor(EmbedColours.Ok)
|
||||
.setDescription(description.join("\n"))
|
||||
.setFooter({ text: `Page ${page + 1} of ${totalPages} · ${moons[1]} moons` });
|
||||
|
||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId(`moons list ${userId} ${pageNumber - 1}`)
|
||||
.setLabel("Previous")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(pageNumber == 0),
|
||||
new ButtonBuilder()
|
||||
.setCustomId(`moons list ${userId} ${pageNumber + 1}`)
|
||||
.setLabel("Next")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(pageNumber + 1 == totalPages));
|
||||
|
||||
await interaction.update({
|
||||
embeds: [ embed ],
|
||||
components: [ row ],
|
||||
});
|
||||
}
|
35
src/commands/304276391837302787/moons.ts
Normal file
35
src/commands/304276391837302787/moons.ts
Normal file
|
@ -0,0 +1,35 @@
|
|||
import { Command } from "../../type/command";
|
||||
import { CommandInteraction, SlashCommandBuilder } from "discord.js";
|
||||
import ListMoons from "./moons/list";
|
||||
|
||||
export default class Moons extends Command {
|
||||
constructor() {
|
||||
super();
|
||||
|
||||
this.CommandBuilder = new SlashCommandBuilder()
|
||||
.setName("moons")
|
||||
.setDescription("View and create moons")
|
||||
.addSubcommand(subcommand =>
|
||||
subcommand
|
||||
.setName('list')
|
||||
.setDescription('List moons you have obtained')
|
||||
.addUserOption(option =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("The user to view (Defaults to yourself)"))
|
||||
.addNumberOption(option =>
|
||||
option
|
||||
.setName("page")
|
||||
.setDescription("The page to start with")));
|
||||
}
|
||||
|
||||
public override async execute(interaction: CommandInteraction) {
|
||||
if (!interaction.isChatInputCommand()) return;
|
||||
|
||||
switch (interaction.options.getSubcommand()) {
|
||||
case "list":
|
||||
await ListMoons(interaction);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
45
src/commands/304276391837302787/moons/list.ts
Normal file
45
src/commands/304276391837302787/moons/list.ts
Normal file
|
@ -0,0 +1,45 @@
|
|||
import {ActionRowBuilder, ButtonBuilder, ButtonStyle, CommandInteraction, EmbedBuilder} from "discord.js";
|
||||
import Moon from "../../../database/entities/Moon";
|
||||
import EmbedColours from "../../../constants/EmbedColours";
|
||||
|
||||
export default async function ListMoons(interaction: CommandInteraction) {
|
||||
const user = interaction.options.get("user")?.user ?? interaction.user;
|
||||
const page = interaction.options.get("page")?.value as number ?? 0;
|
||||
|
||||
const pageLength = 10;
|
||||
|
||||
const moons = await Moon.FetchPaginatedMoonsByUserId(user.id, pageLength, page);
|
||||
|
||||
if (!moons || moons[0].length == 0) {
|
||||
await interaction.reply(`${user.username} does not have any moons or page is invalid.`);
|
||||
return;
|
||||
}
|
||||
|
||||
const totalPages = Math.ceil(moons[1] / pageLength);
|
||||
|
||||
const description = moons[0].flatMap(x => `${x.MoonNumber}. ${x.Description.slice(0, 15)}`);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setTitle(`${user.username}'s Moons`)
|
||||
.setColor(EmbedColours.Ok)
|
||||
.setDescription(description.join("\n"))
|
||||
.setFooter({ text: `Page ${page + 1} of ${totalPages} · ${moons[1]} moons` });
|
||||
|
||||
const row = new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId(`moons list ${user.id} ${page - 1}`)
|
||||
.setLabel("Previous")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(page == 0),
|
||||
new ButtonBuilder()
|
||||
.setCustomId(`moons list ${user.id} ${page + 1}`)
|
||||
.setLabel("Next")
|
||||
.setStyle(ButtonStyle.Primary)
|
||||
.setDisabled(page + 1 == totalPages));
|
||||
|
||||
await interaction.reply({
|
||||
embeds: [ embed ],
|
||||
components: [ row ],
|
||||
});
|
||||
}
|
49
src/database/entities/Moon.ts
Normal file
49
src/database/entities/Moon.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
import { Column, Entity, IsNull } from "typeorm";
|
||||
import BaseEntity from "../../contracts/BaseEntity";
|
||||
import AppDataSource from "../dataSources/appDataSource";
|
||||
|
||||
@Entity()
|
||||
export default class Moon extends BaseEntity {
|
||||
constructor(moonNumber: number, description: string, userId: string) {
|
||||
super();
|
||||
|
||||
this.MoonNumber = moonNumber;
|
||||
this.Description = description;
|
||||
this.UserId = userId;
|
||||
}
|
||||
|
||||
@Column()
|
||||
MoonNumber: number;
|
||||
|
||||
@Column()
|
||||
Description: string;
|
||||
|
||||
@Column({ nullable: true })
|
||||
WhenArchived?: Date;
|
||||
|
||||
@Column()
|
||||
UserId: string;
|
||||
|
||||
public static async FetchMoonsByUserId(userId: string): Promise<Moon[] | null> {
|
||||
const repository = AppDataSource.getRepository(Moon);
|
||||
|
||||
const all = await repository.find({ where: { UserId: userId } });
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
public static async FetchPaginatedMoonsByUserId(userId: string, pageLength: number, page: number): Promise<[ Moon[], number ]> {
|
||||
const rangeStart = page * pageLength;
|
||||
|
||||
const repository = AppDataSource.getRepository(Moon);
|
||||
|
||||
const moons = await repository.findAndCount({
|
||||
where: { UserId: userId, WhenArchived: IsNull() },
|
||||
order: { MoonNumber: "ASC" },
|
||||
skip: rangeStart,
|
||||
take: pageLength,
|
||||
});
|
||||
|
||||
return moons;
|
||||
}
|
||||
}
|
15
src/database/migrations/3.3/1719856023429-CreateMoon.ts
Normal file
15
src/database/migrations/3.3/1719856023429-CreateMoon.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { MigrationInterface, QueryRunner } from "typeorm"
|
||||
import MigrationHelper from "../../../helpers/MigrationHelper"
|
||||
|
||||
export class CreateMoon1719856023429 implements MigrationInterface {
|
||||
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
MigrationHelper.Up('1719856023429-CreateMoon', '3.3.0', [
|
||||
"01-Moon",
|
||||
], queryRunner);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
}
|
||||
|
||||
}
|
|
@ -28,6 +28,9 @@ import AddLobby from "./commands/501231711271780357/Lobby/add";
|
|||
import RemoveLobby from "./commands/501231711271780357/Lobby/remove";
|
||||
import ListLobby from "./commands/501231711271780357/Lobby/list";
|
||||
|
||||
// Command Imports: Potato Talk
|
||||
import Moons from "./commands/304276391837302787/moons";
|
||||
|
||||
// Event Imports
|
||||
import GuildMemberAdd from "./events/MemberEvents/GuildMemberAdd";
|
||||
import GuildMemberRemove from "./events/MemberEvents/GuildMemberRemove";
|
||||
|
@ -38,6 +41,7 @@ import MessageCreate from "./events/MessageEvents/MessageCreate";
|
|||
|
||||
// Button Event Imports
|
||||
import Verify from "./buttonEvents/verify";
|
||||
import MoonsButtonEvent from "./buttonEvents/moons";
|
||||
|
||||
export default class Registry {
|
||||
public static RegisterCommands() {
|
||||
|
@ -68,12 +72,16 @@ export default class Registry {
|
|||
CoreClient.RegisterCommand("listlobby", new ListLobby(), "501231711271780357");
|
||||
CoreClient.RegisterCommand("entry", new Entry(), "501231711271780357");
|
||||
|
||||
// Exclusive Commands: Potato Talk
|
||||
CoreClient.RegisterCommand("moons", new Moons(), "304276391837302787");
|
||||
|
||||
// Add Exclusive Commands to Test Server
|
||||
CoreClient.RegisterCommand("lobby", new Lobby(), "442730357897429002");
|
||||
CoreClient.RegisterCommand("addlobby", new AddLobby(), "442730357897429002");
|
||||
CoreClient.RegisterCommand("removelobby", new RemoveLobby(), "442730357897429002");
|
||||
CoreClient.RegisterCommand("listlobby", new ListLobby(), "442730357897429002");
|
||||
CoreClient.RegisterCommand("entry", new Entry(), "442730357897429002");
|
||||
CoreClient.RegisterCommand("moons", new Moons(), "442730357897429002");
|
||||
}
|
||||
|
||||
public static RegisterEvents() {
|
||||
|
@ -88,5 +96,6 @@ export default class Registry {
|
|||
|
||||
public static RegisterButtonEvents() {
|
||||
CoreClient.RegisterButtonEvent("verify", new Verify());
|
||||
CoreClient.RegisterButtonEvent("moons", new MoonsButtonEvent());
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue