Compare commits
No commits in common. "2ddb170b48f0b827341321dd8d34256f4901db8e" and "b9c0151285d3e1a97e8e5835f61112513a6319ed" have entirely different histories.
2ddb170b48
...
b9c0151285
26 changed files with 6134 additions and 10530 deletions
2
.dev.env
2
.dev.env
|
@ -7,7 +7,7 @@
|
|||
# any secret values.
|
||||
|
||||
BOT_TOKEN=
|
||||
BOT_VER=0.3.0 DEV
|
||||
BOT_VER=0.2.1 DEV
|
||||
BOT_AUTHOR=Vylpes
|
||||
BOT_OWNERID=147392775707426816
|
||||
BOT_CLIENTID=682942374040961060
|
||||
|
|
|
@ -51,14 +51,14 @@ steps:
|
|||
- name: build
|
||||
image: node
|
||||
commands:
|
||||
- npm ci
|
||||
- npm run build
|
||||
- yarn install --frozen-lockfile
|
||||
- yarn build
|
||||
|
||||
- name: test
|
||||
image: node
|
||||
commands:
|
||||
- npm ci
|
||||
- npm test
|
||||
- yarn install --frozen-lockfile
|
||||
- yarn test
|
||||
|
||||
trigger:
|
||||
branch:
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# any secret values.
|
||||
|
||||
BOT_TOKEN=
|
||||
BOT_VER=0.3.0
|
||||
BOT_VER=0.2.1
|
||||
BOT_AUTHOR=Vylpes
|
||||
BOT_OWNERID=147392775707426816
|
||||
BOT_CLIENTID=1093810443589529631
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
# any secret values.
|
||||
|
||||
BOT_TOKEN=
|
||||
BOT_VER=0.3.0 BETA
|
||||
BOT_VER=0.2.1 BETA
|
||||
BOT_AUTHOR=Vylpes
|
||||
BOT_OWNERID=147392775707426816
|
||||
BOT_CLIENTID=1147976642942214235
|
||||
|
|
10331
package-lock.json
generated
10331
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "card-drop",
|
||||
"version": "0.3.0",
|
||||
"version": "0.2.1",
|
||||
"main": "./dist/bot.js",
|
||||
"typings": "./dist",
|
||||
"scripts": {
|
||||
|
@ -31,11 +31,11 @@
|
|||
"discord.js": "^14.3.0",
|
||||
"dotenv": "^16.0.0",
|
||||
"express": "^4.18.2",
|
||||
"glob": "^10.3.10",
|
||||
"jest": "^29.0.0",
|
||||
"jest-mock-extended": "^3.0.0",
|
||||
"minimatch": "9.0.3",
|
||||
"mysql": "^2.18.1",
|
||||
"sqlite3": "^5.1.6",
|
||||
"ts-jest": "^29.0.0",
|
||||
"typeorm": "0.3.17"
|
||||
},
|
||||
|
|
|
@ -13,11 +13,11 @@ cd ~/apps/card-drop/card-drop_prod \
|
|||
&& (pm2 stop card-drop_prod || true) \
|
||||
&& (pm2 delete card-drop_prod || true) \
|
||||
&& cp .prod.env .env \
|
||||
&& npm run clean \
|
||||
&& npm ci \
|
||||
&& npm run build \
|
||||
&& yarn clean \
|
||||
&& yarn install --frozen-lockfile \
|
||||
&& yarn build \
|
||||
&& docker compose --file docker-compose.prod.yml up -d \
|
||||
&& echo "Sleeping for 10 seconds to let database load..." \
|
||||
&& sleep 10 \
|
||||
&& npm run db:up \
|
||||
&& yarn run db:up \
|
||||
&& NODE_ENV=production pm2 start --name card-drop_prod dist/bot.js
|
|
@ -13,11 +13,11 @@ cd ~/apps/card-drop/card-drop_stage \
|
|||
&& (pm2 stop card-drop_stage || true) \
|
||||
&& (pm2 delete card-drop_stage || true) \
|
||||
&& cp .stage.env .env \
|
||||
&& npm run clean \
|
||||
&& npm ci \
|
||||
&& npm run build \
|
||||
&& yarn clean \
|
||||
&& yarn install --frozen-lockfile \
|
||||
&& yarn build \
|
||||
&& docker compose --file docker-compose.stage.yml up -d \
|
||||
&& echo "Sleeping for 10 seconds to let database load..." \
|
||||
&& sleep 10 \
|
||||
&& npm run db:up \
|
||||
&& yarn run db:up \
|
||||
&& NODE_ENV=production pm2 start --name card-drop_stage dist/bot.js
|
|
@ -1,41 +0,0 @@
|
|||
import { readFileSync } from "fs";
|
||||
import path from "path";
|
||||
import Config from "../database/entities/app/Config";
|
||||
import { glob } from "glob";
|
||||
import SeriesMetadata from "../contracts/SeriesMetadata";
|
||||
import { CoreClient } from "../client/client";
|
||||
|
||||
export default class CardMetadataFunction {
|
||||
public static async Execute(overrideSafeMode: boolean = false): Promise<boolean> {
|
||||
if (!overrideSafeMode && await Config.GetValue('safemode') == "true") return false;
|
||||
|
||||
try {
|
||||
CoreClient.Cards = await this.FindMetadataJSONs();
|
||||
|
||||
console.log(`Loaded ${CoreClient.Cards.flatMap(x => x.cards).length} cards to database`);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
await Config.SetValue('safemode', 'true');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static async FindMetadataJSONs(): Promise<SeriesMetadata[]> {
|
||||
const res: SeriesMetadata[] = [];
|
||||
|
||||
const seriesJSONs = await glob(path.join(process.cwd(), 'cards', '/**/*.json'));
|
||||
|
||||
for (let jsonPath of seriesJSONs) {
|
||||
console.log(`Reading file ${jsonPath}`);
|
||||
const jsonFile = readFileSync(jsonPath);
|
||||
const parsedJson: SeriesMetadata[] = JSON.parse(jsonFile.toString());
|
||||
|
||||
res.push(...parsedJson);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
}
|
105
src/Functions/CardSetupFunction.ts
Normal file
105
src/Functions/CardSetupFunction.ts
Normal file
|
@ -0,0 +1,105 @@
|
|||
import { existsSync, readdirSync } from "fs";
|
||||
import CardDataSource from "../database/dataSources/cardDataSource";
|
||||
import Card from "../database/entities/card/Card";
|
||||
import Series from "../database/entities/card/Series";
|
||||
import path from "path";
|
||||
import { CardRarity, CardRarityToString } from "../constants/CardRarity";
|
||||
import Config from "../database/entities/app/Config";
|
||||
|
||||
export default class CardSetupFunction {
|
||||
public static async Execute(): Promise<boolean> {
|
||||
if (await Config.GetValue('safemode') == "true") return false;
|
||||
|
||||
try {
|
||||
await this.ClearDatabase();
|
||||
await this.ReadSeries();
|
||||
await this.ReadCards();
|
||||
} catch {
|
||||
await Config.SetValue('safemode', 'true');
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static async ClearDatabase() {
|
||||
const cardRepository = CardDataSource.getRepository(Card);
|
||||
await cardRepository.clear();
|
||||
|
||||
const seriesRepository = CardDataSource.getRepository(Series);
|
||||
await seriesRepository.clear();
|
||||
}
|
||||
|
||||
private static async ReadSeries() {
|
||||
const seriesDir = readdirSync(path.join(process.cwd(), 'cards'));
|
||||
|
||||
const seriesRepository = CardDataSource.getRepository(Series);
|
||||
|
||||
const seriesToSave: Series[] = [];
|
||||
|
||||
for (let dir of seriesDir) {
|
||||
const dirPart = dir.split(' ');
|
||||
|
||||
const seriesId = dirPart.shift();
|
||||
const seriesName = dirPart.join(' ');
|
||||
|
||||
const series = new Series(seriesId!, seriesName, dir);
|
||||
|
||||
seriesToSave.push(series);
|
||||
}
|
||||
|
||||
await seriesRepository.save(seriesToSave);
|
||||
}
|
||||
|
||||
private static async ReadCards() {
|
||||
const loadedSeries = await Series.FetchAll(Series, [ "Cards", "Cards.Series" ]);
|
||||
|
||||
const cardRepository = CardDataSource.getRepository(Card);
|
||||
|
||||
const cardsToSave: Card[] = [];
|
||||
|
||||
for (let series of loadedSeries) {
|
||||
const cardDirBronze = this.GetCardFiles(CardRarity.Bronze, series);
|
||||
const cardDirGold = this.GetCardFiles(CardRarity.Gold, series);
|
||||
const cardDirLegendary = this.GetCardFiles(CardRarity.Legendary, series);
|
||||
const cardDirSilver = this.GetCardFiles(CardRarity.Silver, series);
|
||||
const cardDirManga = this.GetCardFiles(CardRarity.Manga, series);
|
||||
|
||||
cardsToSave.push(
|
||||
...this.GenerateCardData(cardDirBronze, CardRarity.Bronze, series),
|
||||
...this.GenerateCardData(cardDirGold, CardRarity.Gold, series),
|
||||
...this.GenerateCardData(cardDirLegendary, CardRarity.Legendary, series),
|
||||
...this.GenerateCardData(cardDirSilver, CardRarity.Silver, series),
|
||||
...this.GenerateCardData(cardDirManga, CardRarity.Manga, series)
|
||||
);
|
||||
}
|
||||
|
||||
await cardRepository.save(cardsToSave);
|
||||
|
||||
console.log(`Loaded ${cardsToSave.length} cards to database`);
|
||||
}
|
||||
|
||||
private static GenerateCardData(files: string[], rarity: CardRarity, series: Series): Card[] {
|
||||
const result: Card[] = [];
|
||||
|
||||
for (let file of files.filter(x => !x.startsWith('.') && (x.endsWith('.png') || x.endsWith('.jpg') || x.endsWith('.gif')))) {
|
||||
const filePart = file.split('.');
|
||||
|
||||
const cardId = filePart[0];
|
||||
const cardName = filePart[0];
|
||||
|
||||
const card = new Card(cardId, cardName, rarity, path.join(process.cwd(), 'cards', series.Path, CardRarityToString(rarity).toUpperCase(), file), file, series);
|
||||
|
||||
result.push(card);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static GetCardFiles(rarity: CardRarity, series: Series): string[] {
|
||||
const folder = path.join(process.cwd(), 'cards', series.Path, CardRarityToString(rarity).toUpperCase());
|
||||
const folderExists = existsSync(folder);
|
||||
|
||||
return folderExists ? readdirSync(folder) : [];
|
||||
}
|
||||
}
|
|
@ -1,12 +1,11 @@
|
|||
import { AttachmentBuilder, ButtonInteraction, DiscordAPIError } from "discord.js";
|
||||
import { ButtonEvent } from "../type/buttonEvent";
|
||||
import CardDropHelper from "../helpers/CardDropHelper";
|
||||
import { readFileSync } from "fs";
|
||||
import { v4 } from "uuid";
|
||||
import { CoreClient } from "../client/client";
|
||||
import Inventory from "../database/entities/app/Inventory";
|
||||
import Config from "../database/entities/app/Config";
|
||||
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
|
||||
import path from "path";
|
||||
|
||||
export default class Reroll extends ButtonEvent {
|
||||
public override async execute(interaction: ButtonInteraction) {
|
||||
|
@ -15,40 +14,34 @@ export default class Reroll extends ButtonEvent {
|
|||
return;
|
||||
}
|
||||
|
||||
if (await Config.GetValue('safemode') == "true") {
|
||||
await interaction.reply('Safe Mode has been activated, please resync to continue.');
|
||||
if (await Config.GetValue('safemode') == "true")
|
||||
{
|
||||
await interaction.reply('Safe Mode has been activated, please resync to contunue.');
|
||||
return;
|
||||
}
|
||||
|
||||
const randomCard = CardDropHelperMetadata.GetRandomCard();
|
||||
if (!interaction.guild || !interaction.guildId) return;
|
||||
|
||||
if (!randomCard) {
|
||||
await interaction.reply('Unable to fetch card, please try again.');
|
||||
return;
|
||||
let randomCard = await CardDropHelper.GetRandomCard();
|
||||
|
||||
if (process.env.DROP_RARITY && Number(process.env.DROP_RARITY) > 0) {
|
||||
randomCard = await CardDropHelper.GetRandomCardByRarity(Number(process.env.DROP_RARITY));
|
||||
}
|
||||
|
||||
let image: Buffer;
|
||||
const imageFileName = randomCard.card.path.split("/").pop()!;
|
||||
|
||||
try {
|
||||
image = readFileSync(path.join(process.cwd(), 'cards', randomCard.card.path));
|
||||
} catch {
|
||||
await interaction.reply(`Unable to fetch image for card ${randomCard.card.id}`);
|
||||
return;
|
||||
}
|
||||
const image = readFileSync(randomCard.Path);
|
||||
|
||||
await interaction.deferReply();
|
||||
|
||||
const attachment = new AttachmentBuilder(image, { name: imageFileName });
|
||||
const attachment = new AttachmentBuilder(image, { name: randomCard.FileName });
|
||||
|
||||
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id);
|
||||
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.CardNumber);
|
||||
const quantityClaimed = inventory ? inventory.Quantity : 0;
|
||||
|
||||
const embed = CardDropHelperMetadata.GenerateDropEmbed(randomCard, quantityClaimed, imageFileName);
|
||||
const embed = CardDropHelper.GenerateDropEmbed(randomCard, quantityClaimed || 0);
|
||||
|
||||
const claimId = v4();
|
||||
|
||||
const row = CardDropHelperMetadata.GenerateDropButtons(randomCard, claimId, interaction.user.id);
|
||||
const row = CardDropHelper.GenerateDropButtons(randomCard, claimId, interaction.user.id);
|
||||
|
||||
try {
|
||||
await interaction.editReply({
|
||||
|
|
|
@ -7,13 +7,13 @@ import { Command } from "../type/command";
|
|||
|
||||
import { Events } from "./events";
|
||||
import { Util } from "./util";
|
||||
import CardSetupFunction from "../Functions/CardSetupFunction";
|
||||
import CardDataSource from "../database/dataSources/cardDataSource";
|
||||
import IButtonEventItem from "../contracts/IButtonEventItem";
|
||||
import { ButtonEvent } from "../type/buttonEvent";
|
||||
import AppDataSource from "../database/dataSources/appDataSource";
|
||||
import { Environment } from "../constants/Environment";
|
||||
import Webhooks from "../webhooks";
|
||||
import CardMetadataFunction from "../Functions/CardMetadataFunction";
|
||||
import SeriesMetadata from "../contracts/SeriesMetadata";
|
||||
|
||||
export class CoreClient extends Client {
|
||||
private static _commandItems: ICommandItem[];
|
||||
|
@ -27,7 +27,6 @@ export class CoreClient extends Client {
|
|||
public static ClaimId: string;
|
||||
public static Environment: Environment;
|
||||
public static AllowDrops: boolean;
|
||||
public static Cards: SeriesMetadata[];
|
||||
|
||||
public static get commandItems(): ICommandItem[] {
|
||||
return this._commandItems;
|
||||
|
@ -69,10 +68,14 @@ export class CoreClient extends Client {
|
|||
.then(() => console.log("App Data Source Initialised"))
|
||||
.catch(err => console.error("Error initialising App Data Source", err));
|
||||
|
||||
await CardDataSource.initialize()
|
||||
.then(() => console.log("Card Data Source Initialised"))
|
||||
.catch(err => console.error("Error initialising Card Data Source", err));
|
||||
|
||||
super.on("interactionCreate", this._events.onInteractionCreate);
|
||||
super.on("ready", this._events.onReady);
|
||||
|
||||
await CardMetadataFunction.Execute(true);
|
||||
await CardSetupFunction.Execute();
|
||||
|
||||
this._util.loadEvents(this, CoreClient._eventItems);
|
||||
this._util.loadSlashCommands(this);
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { AttachmentBuilder, CommandInteraction, DiscordAPIError, SlashCommandBuilder } from "discord.js";
|
||||
import { Command } from "../type/command";
|
||||
import CardDropHelper from "../helpers/CardDropHelper";
|
||||
import { readFileSync } from "fs";
|
||||
import { CoreClient } from "../client/client";
|
||||
import { v4 } from "uuid";
|
||||
import Inventory from "../database/entities/app/Inventory";
|
||||
import Config from "../database/entities/app/Config";
|
||||
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
|
||||
import path from "path";
|
||||
|
||||
export default class Drop extends Command {
|
||||
constructor() {
|
||||
|
@ -23,40 +22,28 @@ export default class Drop extends Command {
|
|||
return;
|
||||
}
|
||||
|
||||
if (await Config.GetValue('safemode') == "true") {
|
||||
await interaction.reply('Safe Mode has been activated, please resync to continue.');
|
||||
if (await Config.GetValue('safemode') == "true")
|
||||
{
|
||||
await interaction.reply('Safe Mode has been activated, please resync to contunue.');
|
||||
return;
|
||||
}
|
||||
|
||||
const randomCard = CardDropHelperMetadata.GetRandomCard();
|
||||
const randomCard = await CardDropHelper.GetRandomCard();
|
||||
|
||||
if (!randomCard) {
|
||||
await interaction.reply('Unable to fetch card, please try again.');
|
||||
return;
|
||||
}
|
||||
|
||||
let image: Buffer;
|
||||
const imageFileName = randomCard.card.path.split("/").pop()!;
|
||||
|
||||
try {
|
||||
image = readFileSync(path.join(process.cwd(), 'cards', randomCard.card.path));
|
||||
} catch {
|
||||
await interaction.reply(`Unable to fetch image for card ${randomCard.card.id}`);
|
||||
return;
|
||||
}
|
||||
const image = readFileSync(randomCard.Path);
|
||||
|
||||
await interaction.deferReply();
|
||||
|
||||
const attachment = new AttachmentBuilder(image, { name: imageFileName });
|
||||
const attachment = new AttachmentBuilder(image, { name: randomCard.FileName });
|
||||
|
||||
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.card.id);
|
||||
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, randomCard.CardNumber);
|
||||
const quantityClaimed = inventory ? inventory.Quantity : 0;
|
||||
|
||||
const embed = CardDropHelperMetadata.GenerateDropEmbed(randomCard, quantityClaimed, imageFileName);
|
||||
const embed = CardDropHelper.GenerateDropEmbed(randomCard, quantityClaimed || 0);
|
||||
|
||||
const claimId = v4();
|
||||
|
||||
const row = CardDropHelperMetadata.GenerateDropButtons(randomCard, claimId, interaction.user.id);
|
||||
const row = CardDropHelper.GenerateDropButtons(randomCard, claimId, interaction.user.id);
|
||||
|
||||
try {
|
||||
await interaction.editReply({
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
import { CacheType, CommandInteraction, PermissionsBitField, SlashCommandBuilder } from "discord.js";
|
||||
import { Command } from "../type/command";
|
||||
import { ExecException, exec } from "child_process";
|
||||
import CardSetupFunction from "../Functions/CardSetupFunction";
|
||||
import { CoreClient } from "../client/client";
|
||||
import Config from "../database/entities/app/Config";
|
||||
import CardMetadataFunction from "../Functions/CardMetadataFunction";
|
||||
|
||||
export default class Gdrivesync extends Command {
|
||||
constructor() {
|
||||
|
@ -34,8 +34,7 @@ export default class Gdrivesync extends Command {
|
|||
await interaction.editReply(`Error while running sync command. Safe Mode has been activated. Code: ${error.code}`);
|
||||
await Config.SetValue('safemode', 'true');
|
||||
} else {
|
||||
await CardMetadataFunction.Execute();
|
||||
|
||||
await CardSetupFunction.Execute();
|
||||
await interaction.editReply('Synced successfully.');
|
||||
|
||||
CoreClient.AllowDrops = true;
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import { CacheType, CommandInteraction, PermissionsBitField, SlashCommandBuilder } from "discord.js";
|
||||
import { Command } from "../type/command";
|
||||
import CardSetupFunction from "../Functions/CardSetupFunction";
|
||||
import Config from "../database/entities/app/Config";
|
||||
import CardMetadataFunction from "../Functions/CardMetadataFunction";
|
||||
|
||||
export default class Resync extends Command {
|
||||
constructor() {
|
||||
|
@ -23,9 +23,7 @@ export default class Resync extends Command {
|
|||
return;
|
||||
}
|
||||
|
||||
let result = await CardMetadataFunction.Execute(true);
|
||||
|
||||
if (result) {
|
||||
if (await CardSetupFunction.Execute()) {
|
||||
if (await Config.GetValue('safemode') == "true") {
|
||||
await Config.SetValue('safemode', 'false');
|
||||
await interaction.reply("Resynced database and disabled safe mode.");
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
import { AttachmentBuilder, CacheType, CommandInteraction, DiscordAPIError, SlashCommandBuilder } from "discord.js";
|
||||
import { Command } from "../../type/command";
|
||||
import Card from "../../database/entities/card/Card";
|
||||
import { readFileSync } from "fs";
|
||||
import Inventory from "../../database/entities/app/Inventory";
|
||||
import CardDropHelper from "../../helpers/CardDropHelper";
|
||||
import { v4 } from "uuid";
|
||||
import { CoreClient } from "../../client/client";
|
||||
import path from "path";
|
||||
import CardDropHelperMetadata from "../../helpers/CardDropHelperMetadata";
|
||||
|
||||
export default class Dropnumber extends Command {
|
||||
constructor() {
|
||||
|
@ -31,40 +31,29 @@ export default class Dropnumber extends Command {
|
|||
return;
|
||||
}
|
||||
|
||||
const card = CoreClient.Cards
|
||||
.flatMap(x => x.cards)
|
||||
.find(x => x.id == cardNumber.value);
|
||||
const card = await Card.FetchOneByCardNumber(cardNumber.value.toString(), [
|
||||
"Series"
|
||||
]);
|
||||
|
||||
if (!card) {
|
||||
await interaction.reply('Card not found');
|
||||
return;
|
||||
}
|
||||
|
||||
const series = CoreClient.Cards
|
||||
.find(x => x.cards.includes(card))!;
|
||||
|
||||
let image: Buffer;
|
||||
const imageFileName = card.path.split("/").pop()!;
|
||||
|
||||
try {
|
||||
image = readFileSync(path.join(process.cwd(), 'cards', card.path));
|
||||
} catch {
|
||||
await interaction.reply(`Unable to fetch image for card ${card.id}`);
|
||||
return;
|
||||
}
|
||||
const image = readFileSync(card.Path);
|
||||
|
||||
await interaction.deferReply();
|
||||
|
||||
const attachment = new AttachmentBuilder(image, { name: imageFileName });
|
||||
const attachment = new AttachmentBuilder(image, { name: card.FileName });
|
||||
|
||||
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.id);
|
||||
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.CardNumber);
|
||||
const quantityClaimed = inventory ? inventory.Quantity : 0;
|
||||
|
||||
const embed = CardDropHelperMetadata.GenerateDropEmbed({ card, series }, quantityClaimed, imageFileName);
|
||||
const embed = CardDropHelper.GenerateDropEmbed(card, quantityClaimed || 0);
|
||||
|
||||
const claimId = v4();
|
||||
|
||||
const row = CardDropHelperMetadata.GenerateDropButtons({ card, series }, claimId, interaction.user.id);
|
||||
const row = CardDropHelper.GenerateDropButtons(card, claimId, interaction.user.id);
|
||||
|
||||
try {
|
||||
await interaction.editReply({
|
||||
|
@ -78,7 +67,7 @@ export default class Dropnumber extends Command {
|
|||
if (e instanceof DiscordAPIError) {
|
||||
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: ${e.code}`);
|
||||
} else {
|
||||
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: UNKNOWN`);
|
||||
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening.Code: UNKNOWN`);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,12 +1,11 @@
|
|||
import { AttachmentBuilder, CacheType, CommandInteraction, DiscordAPIError, SlashCommandBuilder } from "discord.js";
|
||||
import { Command } from "../../type/command";
|
||||
import { CardRarity, CardRarityParse } from "../../constants/CardRarity";
|
||||
import CardDropHelper from "../../helpers/CardDropHelper";
|
||||
import { readFileSync } from "fs";
|
||||
import Inventory from "../../database/entities/app/Inventory";
|
||||
import { v4 } from "uuid";
|
||||
import { CoreClient } from "../../client/client";
|
||||
import CardDropHelperMetadata from "../../helpers/CardDropHelperMetadata";
|
||||
import path from "path";
|
||||
|
||||
export default class Droprarity extends Command {
|
||||
constructor() {
|
||||
|
@ -39,35 +38,27 @@ export default class Droprarity extends Command {
|
|||
return;
|
||||
}
|
||||
|
||||
const card = await CardDropHelperMetadata.GetRandomCardByRarity(rarityType);
|
||||
const card = await CardDropHelper.GetRandomCardByRarity(rarityType);
|
||||
|
||||
if (!card) {
|
||||
await interaction.reply('Card not found');
|
||||
return;
|
||||
}
|
||||
|
||||
let image: Buffer;
|
||||
const imageFileName = card.card.path.split("/").pop()!;
|
||||
|
||||
try {
|
||||
image = readFileSync(path.join(process.cwd(), 'cards', card.card.path));
|
||||
} catch {
|
||||
await interaction.reply(`Unable to fetch image for card ${card.card.id}`);
|
||||
return;
|
||||
}
|
||||
const image = readFileSync(card.Path);
|
||||
|
||||
await interaction.deferReply();
|
||||
|
||||
const attachment = new AttachmentBuilder(image, { name: imageFileName });
|
||||
const attachment = new AttachmentBuilder(image, { name: card.FileName });
|
||||
|
||||
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.card.id);
|
||||
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.CardNumber);
|
||||
const quantityClaimed = inventory ? inventory.Quantity : 0;
|
||||
|
||||
const embed = CardDropHelperMetadata.GenerateDropEmbed(card, quantityClaimed, imageFileName);
|
||||
const embed = CardDropHelper.GenerateDropEmbed(card, quantityClaimed || 0);
|
||||
|
||||
const claimId = v4();
|
||||
|
||||
const row = CardDropHelperMetadata.GenerateDropButtons(card, claimId, interaction.user.id);
|
||||
const row = CardDropHelper.GenerateDropButtons(card, claimId, interaction.user.id);
|
||||
|
||||
try {
|
||||
await interaction.editReply({
|
||||
|
|
60
src/contracts/CardBaseEntity.ts
Normal file
60
src/contracts/CardBaseEntity.ts
Normal file
|
@ -0,0 +1,60 @@
|
|||
import { Column, DeepPartial, EntityTarget, PrimaryColumn, ObjectLiteral, FindOptionsWhere } from "typeorm";
|
||||
import { v4 } from "uuid";
|
||||
import AppDataSource from "../database/dataSources/appDataSource";
|
||||
import CardDataSource from "../database/dataSources/cardDataSource";
|
||||
|
||||
export default class CardBaseEntity {
|
||||
constructor() {
|
||||
this.Id = v4();
|
||||
|
||||
this.WhenCreated = new Date();
|
||||
this.WhenUpdated = new Date();
|
||||
}
|
||||
|
||||
@PrimaryColumn()
|
||||
Id: string;
|
||||
|
||||
@Column()
|
||||
WhenCreated: Date;
|
||||
|
||||
@Column()
|
||||
WhenUpdated: Date;
|
||||
|
||||
public async Save<T extends CardBaseEntity>(target: EntityTarget<T>, entity: DeepPartial<T>): Promise<void> {
|
||||
this.WhenUpdated = new Date();
|
||||
|
||||
const repository = CardDataSource.getRepository<T>(target);
|
||||
|
||||
await repository.save(entity);
|
||||
}
|
||||
|
||||
public static async Remove<T extends CardBaseEntity>(target: EntityTarget<T>, entity: T): Promise<void> {
|
||||
const repository = CardDataSource.getRepository<T>(target);
|
||||
|
||||
await repository.remove(entity);
|
||||
}
|
||||
|
||||
public static async FetchAll<T extends CardBaseEntity>(target: EntityTarget<T>, relations?: string[]): Promise<T[]> {
|
||||
const repository = CardDataSource.getRepository<T>(target);
|
||||
|
||||
const all = await repository.find({ relations: relations || [] });
|
||||
|
||||
return all;
|
||||
}
|
||||
|
||||
public static async FetchOneById<T extends CardBaseEntity>(target: EntityTarget<T>, id: string, relations?: string[]): Promise<T | null> {
|
||||
const repository = CardDataSource.getRepository<T>(target);
|
||||
|
||||
const single = await repository.findOne({ where: ({ Id: id } as FindOptionsWhere<T>), relations: relations || {} });
|
||||
|
||||
return single;
|
||||
}
|
||||
|
||||
public static async Any<T extends ObjectLiteral>(target: EntityTarget<T>): Promise<boolean> {
|
||||
const repository = CardDataSource.getRepository<T>(target);
|
||||
|
||||
const any = await repository.find();
|
||||
|
||||
return any.length > 0;
|
||||
}
|
||||
}
|
|
@ -1,19 +0,0 @@
|
|||
import { CardRarity } from "../constants/CardRarity";
|
||||
|
||||
export default interface SeriesMetadata {
|
||||
id: number,
|
||||
name: string,
|
||||
cards: CardMetadata[],
|
||||
}
|
||||
|
||||
export interface CardMetadata {
|
||||
id: string,
|
||||
name: string,
|
||||
type: CardRarity,
|
||||
path: string,
|
||||
}
|
||||
|
||||
export interface DropResult {
|
||||
series: SeriesMetadata,
|
||||
card: CardMetadata,
|
||||
}
|
22
src/database/dataSources/cardDataSource.ts
Normal file
22
src/database/dataSources/cardDataSource.ts
Normal file
|
@ -0,0 +1,22 @@
|
|||
import { DataSource } from "typeorm";
|
||||
import * as dotenv from "dotenv";
|
||||
|
||||
dotenv.config();
|
||||
|
||||
const CardDataSource = new DataSource({
|
||||
type: "sqlite",
|
||||
database: process.env.DB_CARD_FILE!,
|
||||
synchronize: true,
|
||||
logging: process.env.DB_LOGGING == "true",
|
||||
entities: [
|
||||
"dist/database/entities/card/**/*.js",
|
||||
],
|
||||
migrations: [
|
||||
"dist/database/migrations/card/**/*.js",
|
||||
],
|
||||
subscribers: [
|
||||
"dist/database/subscribers/card/**/*.js",
|
||||
],
|
||||
});
|
||||
|
||||
export default CardDataSource;
|
53
src/database/entities/card/Card.ts
Normal file
53
src/database/entities/card/Card.ts
Normal file
|
@ -0,0 +1,53 @@
|
|||
import { Column, Entity, ManyToOne } from "typeorm";
|
||||
import CardBaseEntity from "../../../contracts/CardBaseEntity";
|
||||
import { CardRarity } from "../../../constants/CardRarity";
|
||||
import Series from "./Series";
|
||||
import CardDataSource from "../../dataSources/cardDataSource";
|
||||
|
||||
@Entity()
|
||||
export default class Card extends CardBaseEntity {
|
||||
constructor(cardNumber: string, name: string, rarity: CardRarity, path: string, fileName: string, series: Series) {
|
||||
super();
|
||||
|
||||
this.CardNumber = cardNumber;
|
||||
this.Name = name;
|
||||
this.Rarity = rarity;
|
||||
this.Path = path;
|
||||
this.FileName = fileName;
|
||||
this.Series = series;
|
||||
}
|
||||
|
||||
@Column()
|
||||
CardNumber: string;
|
||||
|
||||
@Column()
|
||||
Name: string;
|
||||
|
||||
@Column()
|
||||
Rarity: CardRarity;
|
||||
|
||||
@Column()
|
||||
Path: string;
|
||||
|
||||
@Column()
|
||||
FileName: string;
|
||||
|
||||
@ManyToOne(() => Series, x => x.Cards)
|
||||
Series: Series;
|
||||
|
||||
public static async FetchOneByCardNumber(cardNumber: string, relations?: string[]): Promise<Card | null> {
|
||||
const repository = CardDataSource.getRepository(Card);
|
||||
|
||||
const single = await repository.findOne({ where: { CardNumber: cardNumber }, relations: relations || [] });
|
||||
|
||||
return single;
|
||||
}
|
||||
|
||||
public static async FetchAllByRarity(rarity: CardRarity, relations?: string[]): Promise<Card[]> {
|
||||
const repository = CardDataSource.getRepository(Card);
|
||||
|
||||
const all = await repository.find({ where: { Rarity: rarity }, relations: relations || [] });
|
||||
|
||||
return all;
|
||||
}
|
||||
}
|
23
src/database/entities/card/Series.ts
Normal file
23
src/database/entities/card/Series.ts
Normal file
|
@ -0,0 +1,23 @@
|
|||
import { Column, Entity, OneToMany } from "typeorm";
|
||||
import CardBaseEntity from "../../../contracts/CardBaseEntity";
|
||||
import Card from "./Card";
|
||||
|
||||
@Entity()
|
||||
export default class Series extends CardBaseEntity {
|
||||
constructor(id: string, name: string, path: string) {
|
||||
super();
|
||||
|
||||
this.Id = id;
|
||||
this.Name = name;
|
||||
this.Path = path;
|
||||
}
|
||||
|
||||
@Column()
|
||||
Name: string;
|
||||
|
||||
@Column()
|
||||
Path: string;
|
||||
|
||||
@OneToMany(() => Card, x => x.Series)
|
||||
Cards: Card[];
|
||||
}
|
0
src/database/migrations/card/.gitkeep
Normal file
0
src/database/migrations/card/.gitkeep
Normal file
|
@ -1,11 +1,10 @@
|
|||
import { ActionRowBuilder, ButtonBuilder, ButtonStyle, EmbedBuilder } from "discord.js";
|
||||
import { CardRarity, CardRarityToColour, CardRarityToString } from "../constants/CardRarity";
|
||||
import CardRarityChances from "../constants/CardRarityChances";
|
||||
import { DropResult } from "../contracts/SeriesMetadata";
|
||||
import { CoreClient } from "../client/client";
|
||||
import Card from "../database/entities/card/Card";
|
||||
|
||||
export default class CardDropHelperMetadata {
|
||||
public static GetRandomCard(): DropResult | undefined {
|
||||
export default class CardDropHelper {
|
||||
public static async GetRandomCard(): Promise<Card> {
|
||||
const randomRarity = Math.random() * 100;
|
||||
|
||||
let cardRarity: CardRarity;
|
||||
|
@ -21,50 +20,39 @@ export default class CardDropHelperMetadata {
|
|||
else if (randomRarity < mangaChance) cardRarity = CardRarity.Manga;
|
||||
else cardRarity = CardRarity.Legendary;
|
||||
|
||||
const randomCard = this.GetRandomCardByRarity(cardRarity);
|
||||
const randomCard = await this.GetRandomCardByRarity(cardRarity);
|
||||
|
||||
return randomCard;
|
||||
}
|
||||
|
||||
public static GetRandomCardByRarity(rarity: CardRarity): DropResult | undefined {
|
||||
const allCards = CoreClient.Cards
|
||||
.flatMap(x => x.cards)
|
||||
.filter(x => x.type == rarity);
|
||||
public static async GetRandomCardByRarity(rarity: CardRarity): Promise<Card> {
|
||||
const allCards = await Card.FetchAllByRarity(rarity, [ "Series" ]);
|
||||
|
||||
const randomCardIndex = Math.floor(Math.random() * allCards.length);
|
||||
|
||||
const card = allCards[randomCardIndex];
|
||||
const series = CoreClient.Cards
|
||||
.find(x => x.cards.includes(card));
|
||||
|
||||
if (!series) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return {
|
||||
series: series,
|
||||
card: card,
|
||||
};
|
||||
return card;
|
||||
}
|
||||
|
||||
public static GenerateDropEmbed(drop: DropResult, quantityClaimed: Number, imageFileName: string): EmbedBuilder {
|
||||
public static GenerateDropEmbed(card: Card, quantityClaimed: Number): EmbedBuilder {
|
||||
let description = "";
|
||||
description += `Series: ${drop.series.name}\n`;
|
||||
description += `Series: ${card.Series.Name}\n`;
|
||||
description += `Claimed: ${quantityClaimed}\n`;
|
||||
|
||||
return new EmbedBuilder()
|
||||
.setTitle(drop.card.name)
|
||||
.setTitle(card.Name)
|
||||
.setDescription(description)
|
||||
.setFooter({ text: CardRarityToString(drop.card.type) })
|
||||
.setColor(CardRarityToColour(drop.card.type))
|
||||
.setImage(`attachment://${imageFileName}`);
|
||||
.setFooter({ text: CardRarityToString(card.Rarity) })
|
||||
.setColor(CardRarityToColour(card.Rarity))
|
||||
.setImage(`attachment://${card.FileName}`);
|
||||
}
|
||||
|
||||
public static GenerateDropButtons(drop: DropResult, claimId: string, userId: string): ActionRowBuilder<ButtonBuilder> {
|
||||
public static GenerateDropButtons(card: Card, claimId: string, userId: string): ActionRowBuilder<ButtonBuilder> {
|
||||
return new ActionRowBuilder<ButtonBuilder>()
|
||||
.addComponents(
|
||||
new ButtonBuilder()
|
||||
.setCustomId(`claim ${drop.card.id} ${claimId} ${userId}`)
|
||||
.setCustomId(`claim ${card.CardNumber} ${claimId} ${userId}`)
|
||||
.setLabel("Claim")
|
||||
.setStyle(ButtonStyle.Primary),
|
||||
new ButtonBuilder()
|
|
@ -1,10 +1,10 @@
|
|||
import { Request, Response } from "express";
|
||||
import CardMetadataFunction from "../Functions/CardMetadataFunction";
|
||||
import CardSetupFunction from "../Functions/CardSetupFunction";
|
||||
|
||||
export default async function ReloadDB(req: Request, res: Response) {
|
||||
console.log('Reloading Card DB...');
|
||||
|
||||
await CardMetadataFunction.Execute();
|
||||
await CardSetupFunction.Execute();
|
||||
|
||||
res.sendStatus(200);
|
||||
}
|
Loading…
Reference in a new issue