Compare commits

...

4 commits

Author SHA1 Message Date
211ef74410 v0.8.4
All checks were successful
Deploy To Production / build (push) Successful in 34s
Deploy To Production / deploy (push) Successful in 17s
2025-04-22 15:21:19 +01:00
51a8e177ae 0.8.4
All checks were successful
Test / build (push) Successful in 20s
2025-04-22 15:13:33 +01:00
9b34bc65a7 Fix droprarity and dropnumber commands (#431)
All checks were successful
Test / build (push) Successful in 20s
- Fix the droprarity and dropnumber commands with the changes previously made regarding image urls
- Add a `CatchError` function to the app logger to easily send caught errors to the error logs
- Add choices to the droprarity command to make them easier to select

#429

Reviewed-on: #431
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2025-04-22 15:12:10 +01:00
ad34cc7b7f Fix remote image urls not showing up in image grids (#430)
All checks were successful
Test / build (push) Successful in 22s
- Update the Image Grid helper to download images that are urls instead of trying (and failing) to load them locally

#425

Reviewed-on: #430
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2025-04-20 10:52:54 +01:00
9 changed files with 509 additions and 408 deletions

View file

@ -7,7 +7,7 @@
# any secret values. # any secret values.
BOT_TOKEN= BOT_TOKEN=
BOT_VER=0.8.3 BOT_VER=0.8.4
BOT_AUTHOR=Vylpes BOT_AUTHOR=Vylpes
BOT_OWNERID=147392775707426816 BOT_OWNERID=147392775707426816
BOT_CLIENTID=682942374040961060 BOT_CLIENTID=682942374040961060

View file

@ -18,7 +18,7 @@ jobs:
- name: Use Node.js - name: Use Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
node-version: 18.x node-version: 20.x
- run: yarn install --frozen-lockfile - run: yarn install --frozen-lockfile
- run: yarn build - run: yarn build
- run: yarn test - run: yarn test

View file

@ -1,6 +1,6 @@
{ {
"name": "card-drop", "name": "card-drop",
"version": "0.8.3", "version": "0.8.4",
"main": "./dist/bot.js", "main": "./dist/bot.js",
"typings": "./dist", "typings": "./dist",
"scripts": { "scripts": {
@ -30,6 +30,7 @@
"@types/express": "^4.17.20", "@types/express": "^4.17.20",
"@types/jest": "^29.0.0", "@types/jest": "^29.0.0",
"@types/uuid": "^9.0.0", "@types/uuid": "^9.0.0",
"axios": "^1.8.4",
"body-parser": "^1.20.2", "body-parser": "^1.20.2",
"canvas": "^2.11.2", "canvas": "^2.11.2",
"clone-deep": "^4.0.1", "clone-deep": "^4.0.1",
@ -40,7 +41,7 @@
"glob": "^10.3.10", "glob": "^10.3.10",
"jest": "^29.0.0", "jest": "^29.0.0",
"jest-mock-extended": "^3.0.0", "jest-mock-extended": "^3.0.0",
"jimp": "^0.22.12", "jimp": "^1.6.0",
"minimatch": "9.0.5", "minimatch": "9.0.5",
"mysql": "^2.18.1", "mysql": "^2.18.1",
"ts-jest": "^29.0.0", "ts-jest": "^29.0.0",

View file

@ -86,4 +86,12 @@ export default class AppLogger {
public static LogSilly(label: string, message: string) { public static LogSilly(label: string, message: string) {
AppLogger.Logger.silly({ label, message }); AppLogger.Logger.silly({ label, message });
} }
public static CatchError(label: string, error: unknown) {
if (error instanceof Error) {
AppLogger.Logger.error({ label, message: error.message });
} else {
AppLogger.Logger.error({ label, message: error });
}
}
} }

View file

@ -1,4 +1,4 @@
import { AttachmentBuilder, CacheType, CommandInteraction, DiscordAPIError, SlashCommandBuilder } from "discord.js"; import { AttachmentBuilder, CacheType, CommandInteraction, SlashCommandBuilder } from "discord.js";
import { Command } from "../../type/command"; import { Command } from "../../type/command";
import { readFileSync } from "fs"; import { readFileSync } from "fs";
import Inventory from "../../database/entities/app/Inventory"; import Inventory from "../../database/entities/app/Inventory";
@ -6,6 +6,7 @@ import { v4 } from "uuid";
import { CoreClient } from "../../client/client"; import { CoreClient } from "../../client/client";
import path from "path"; import path from "path";
import CardDropHelperMetadata from "../../helpers/CardDropHelperMetadata"; import CardDropHelperMetadata from "../../helpers/CardDropHelperMetadata";
import AppLogger from "../../client/appLogger";
export default class Dropnumber extends Command { export default class Dropnumber extends Command {
constructor() { constructor() {
@ -43,6 +44,12 @@ export default class Dropnumber extends Command {
const series = CoreClient.Cards const series = CoreClient.Cards
.find(x => x.cards.includes(card))!; .find(x => x.cards.includes(card))!;
const claimId = v4();
await interaction.deferReply();
try {
const files = []; const files = [];
let imageFileName = ""; let imageFileName = "";
@ -55,31 +62,21 @@ export default class Dropnumber extends Command {
files.push(attachment); files.push(attachment);
} }
await interaction.deferReply();
const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.id); const inventory = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, card.id);
const quantityClaimed = inventory ? inventory.Quantity : 0; const quantityClaimed = inventory ? inventory.Quantity : 0;
const embed = CardDropHelperMetadata.GenerateDropEmbed({ card, series }, quantityClaimed, imageFileName); const embed = CardDropHelperMetadata.GenerateDropEmbed({ card, series }, quantityClaimed, imageFileName);
const claimId = v4();
const row = CardDropHelperMetadata.GenerateDropButtons({ card, series }, claimId, interaction.user.id); const row = CardDropHelperMetadata.GenerateDropButtons({ card, series }, claimId, interaction.user.id);
try {
await interaction.editReply({ await interaction.editReply({
embeds: [ embed ], embeds: [ embed ],
files: files, files: files,
components: [ row ], components: [ row ],
}); });
} catch (e) { } catch (e) {
console.error(e); AppLogger.CatchError("Dropnumber", e);
await interaction.editReply("Unable to send next drop. Please try again, and report this if it keeps happening");
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");
}
} }
CoreClient.ClaimId = claimId; CoreClient.ClaimId = claimId;

View file

@ -1,12 +1,13 @@
import { AttachmentBuilder, CacheType, CommandInteraction, DiscordAPIError, SlashCommandBuilder } from "discord.js"; import { AttachmentBuilder, CacheType, CommandInteraction, SlashCommandBuilder } from "discord.js";
import { Command } from "../../type/command"; import { Command } from "../../type/command";
import { CardRarity, CardRarityParse } from "../../constants/CardRarity"; import { CardRarity, CardRarityChoices, CardRarityParse } from "../../constants/CardRarity";
import { readFileSync } from "fs"; import { readFileSync } from "fs";
import Inventory from "../../database/entities/app/Inventory"; import Inventory from "../../database/entities/app/Inventory";
import { v4 } from "uuid"; import { v4 } from "uuid";
import { CoreClient } from "../../client/client"; import { CoreClient } from "../../client/client";
import CardDropHelperMetadata from "../../helpers/CardDropHelperMetadata"; import CardDropHelperMetadata from "../../helpers/CardDropHelperMetadata";
import path from "path"; import path from "path";
import AppLogger from "../../client/appLogger";
export default class Droprarity extends Command { export default class Droprarity extends Command {
constructor() { constructor() {
@ -19,7 +20,8 @@ export default class Droprarity extends Command {
x x
.setName("rarity") .setName("rarity")
.setDescription("The rarity you want to summon") .setDescription("The rarity you want to summon")
.setRequired(true)); .setRequired(true)
.setChoices(CardRarityChoices));
} }
public override async execute(interaction: CommandInteraction<CacheType>) { public override async execute(interaction: CommandInteraction<CacheType>) {
@ -39,13 +41,18 @@ export default class Droprarity extends Command {
return; return;
} }
const card = await CardDropHelperMetadata.GetRandomCardByRarity(rarityType); const card = CardDropHelperMetadata.GetRandomCardByRarity(rarityType);
if (!card) { if (!card) {
await interaction.reply("Card not found"); await interaction.reply("Card not found");
return; return;
} }
const claimId = v4();
await interaction.deferReply();
try {
const files = []; const files = [];
let imageFileName = ""; let imageFileName = "";
@ -63,24 +70,16 @@ export default class Droprarity extends Command {
const embed = CardDropHelperMetadata.GenerateDropEmbed(card, quantityClaimed, imageFileName); const embed = CardDropHelperMetadata.GenerateDropEmbed(card, quantityClaimed, imageFileName);
const claimId = v4();
const row = CardDropHelperMetadata.GenerateDropButtons(card, claimId, interaction.user.id); const row = CardDropHelperMetadata.GenerateDropButtons(card, claimId, interaction.user.id);
try {
await interaction.editReply({ await interaction.editReply({
embeds: [ embed ], embeds: [ embed ],
files: files, files: files,
components: [ row ], components: [ row ],
}); });
} catch (e) { } catch (e) {
console.error(e); AppLogger.CatchError("Droprarity", e);
await interaction.editReply("Unable to send next drop. Please try again, and report this if it keeps happening");
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");
}
} }
CoreClient.ClaimId = claimId; CoreClient.ClaimId = claimId;

View file

@ -9,6 +9,29 @@ export enum CardRarity {
Legendary, Legendary,
} }
export const CardRarityChoices = [
{
name: "Bronze",
value: "bronze",
},
{
name: "Silver",
value: "silver",
},
{
name: "Gold",
value: "gold",
},
{
name: "Manga",
value: "manga",
},
{
name: "Legendary",
value: "legendary",
},
];
export function CardRarityToString(rarity: CardRarity): string { export function CardRarityToString(rarity: CardRarity): string {
switch (rarity) { switch (rarity) {
case CardRarity.Unknown: case CardRarity.Unknown:

View file

@ -3,7 +3,8 @@ import path from "path";
import AppLogger from "../client/appLogger"; import AppLogger from "../client/appLogger";
import {existsSync} from "fs"; import {existsSync} from "fs";
import Inventory from "../database/entities/app/Inventory"; import Inventory from "../database/entities/app/Inventory";
import Jimp from "jimp"; import { Bitmap, Jimp } from "jimp";
import axios from "axios";
interface CardInput { interface CardInput {
id: string; id: string;
@ -29,14 +30,24 @@ export default class ImageHelper {
const filePath = path.join(process.env.DATA_DIR!, "cards", card.path); const filePath = path.join(process.env.DATA_DIR!, "cards", card.path);
const exists = existsSync(filePath); let bitmap: Bitmap;
if (!exists) { if (existsSync(filePath)) {
const data = await Jimp.read(filePath);
bitmap = data.bitmap;
} else if (card.path.startsWith("http://") || card.path.startsWith("https://")) {
const response = await axios.get(card.path, { responseType: "arraybuffer" });
const buffer = Buffer.from(response.data);
const data = await Jimp.fromBuffer(buffer);
bitmap = data.bitmap;
} else {
AppLogger.LogError("ImageHelper/GenerateCardImageGrid", `Failed to load image from path ${card.path}`); AppLogger.LogError("ImageHelper/GenerateCardImageGrid", `Failed to load image from path ${card.path}`);
continue; continue;
} }
const imageData = await Jimp.read(filePath); const imageData = Jimp.fromBitmap(bitmap);
if (userId != null) { if (userId != null) {
const claimed = await Inventory.FetchOneByCardNumberAndUserId(userId, card.id); const claimed = await Inventory.FetchOneByCardNumberAndUserId(userId, card.id);
@ -46,7 +57,7 @@ export default class ImageHelper {
} }
} }
const image = await loadImage(await imageData.getBufferAsync("image/png")); const image = await loadImage(await imageData.getBuffer("image/png"));
const x = i % gridWidth; const x = i % gridWidth;
const y = Math.floor(i / gridWidth); const y = Math.floor(i / gridWidth);

748
yarn.lock

File diff suppressed because it is too large Load diff