Compare commits

..

6 commits

Author SHA1 Message Date
4a0050eb70 WIP: Start of logging
Some checks failed
ci/woodpecker/push/woodpecker Pipeline failed
2024-03-12 17:42:02 +00:00
f40328b795 Merge branch 'develop' into feature/146-logger 2024-03-05 18:42:12 +00:00
2377397a2e Update dependency express to v4.18.3 (#180)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [express](http://expressjs.com/) ([source](https://github.com/expressjs/express)) | dependencies | patch | [`4.18.2` -> `4.18.3`](https://renovatebot.com/diffs/npm/express/4.18.2/4.18.3) |

---

### Release Notes

<details>
<summary>expressjs/express (express)</summary>

### [`v4.18.3`](https://github.com/expressjs/express/blob/HEAD/History.md#4183--2024-02-26)

[Compare Source](https://github.com/expressjs/express/compare/4.18.2...4.18.3)

\==========

-   Fix routing requests without method
-   deps: body-parser@1.20.2
    -   Fix strict json error message on Node.js 19+
    -   deps: content-type@~1.0.5
    -   deps: raw-body@2.5.2

</details>

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: https://gitea.vylpes.xyz/External/card-drop/pulls/180
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-03-05 18:39:23 +00:00
0c94c5817f Update dependency @types/node to v20.11.24 (#179)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
This PR contains the following updates:

| Package | Type | Update | Change |
|---|---|---|---|
| [@types/node](https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node) ([source](https://github.com/DefinitelyTyped/DefinitelyTyped)) | devDependencies | patch | [`20.11.20` -> `20.11.24`](https://renovatebot.com/diffs/npm/@types%2fnode/20.11.20/20.11.24) |

---

### Configuration

📅 **Schedule**: Branch creation - At any time (no schedule defined), Automerge - At any time (no schedule defined).

🚦 **Automerge**: Disabled by config. Please merge this manually once you are satisfied.

♻ **Rebasing**: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 **Ignore**: Close this PR and you won't be reminded about this update again.

---

 - [ ] <!-- rebase-check -->If you want to rebase/retry this PR, check this box

---

This PR has been generated by [Renovate Bot](https://github.com/renovatebot/renovate).
<!--renovate-debug:eyJjcmVhdGVkSW5WZXIiOiIzNy4wLjAiLCJ1cGRhdGVkSW5WZXIiOiIzNy4wLjAiLCJ0YXJnZXRCcmFuY2giOiJkZXZlbG9wIn0=-->

Reviewed-on: https://gitea.vylpes.xyz/External/card-drop/pulls/179
Reviewed-by: Vylpes <ethan@vylpes.com>
Co-authored-by: Renovate Bot <renovate@vylpes.com>
Co-committed-by: Renovate Bot <renovate@vylpes.com>
2024-03-05 18:38:18 +00:00
42883c3a99 Fix give command using the wrong username (#178)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Fix the give command incorrectly using the username of the user who used the command instead of the user who it was actually given to

#174

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: https://gitea.vylpes.xyz/External/card-drop/pulls/178
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-03-01 20:03:34 +00:00
2f9d80f430 Fix trade command (#177)
All checks were successful
ci/woodpecker/push/woodpecker Pipeline was successful
# Description

Please include a summary of the change and which issue is fixed. Please also include relevant motivation and context. List any dependencies that are required for this change.

- Fix the decline button not working for the initiating user
- Update labels on embed to follow "I Receive" and "You Receive"

#165

## Type of change

Please delete options that are not relevant.

- [x] Bug fix (non-breaking change which fixes an issue)

# How Has This Been Tested?

Please describe the tests that you ran to verify the changes. Provide instructions so we can reproduce. Please also list any relevant details to your test configuration.

# Checklist

- [ ] My code follows the style guidelines of this project
- [ ] I have performed a self-review of my own code
- [ ] I have commented my code, particularly in hard-to-understand areas
- [ ] I have made corresponding changes to the documentation
- [ ] My changes generate no new warnings
- [ ] I have added tests that provde my fix is effective or that my feature works
- [ ] New and existing unit tests pass locally with my changes
- [ ] Any dependent changes have been merged and published in downstream modules

Reviewed-on: https://gitea.vylpes.xyz/External/card-drop/pulls/177
Reviewed-by: VylpesTester <tester@vylpes.com>
Co-authored-by: Ethan Lane <ethan@vylpes.com>
Co-committed-by: Ethan Lane <ethan@vylpes.com>
2024-03-01 20:02:11 +00:00
18 changed files with 157 additions and 84 deletions

48
package-lock.json generated
View file

@ -1900,9 +1900,9 @@
"license": "MIT" "license": "MIT"
}, },
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "20.11.20", "version": "20.11.24",
"resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.20.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.24.tgz",
"integrity": "sha512-7/rR21OS+fq8IyHTgtLkDK949uzsa6n8BkziAKtPVpugIkO6D+/ooXMvzXxDnZrmtXVfjb1bKQafYpb8s89LOg==", "integrity": "sha512-Kza43ewS3xoLgCEpQrsT+xRo/EJej1y0kVYGiLFE1NEODXGzTfwiC6tXTLMQskn1X4/Rjlh0MQUvx9W+L9long==",
"dependencies": { "dependencies": {
"undici-types": "~5.26.4" "undici-types": "~5.26.4"
} }
@ -4766,12 +4766,13 @@
} }
}, },
"node_modules/express": { "node_modules/express": {
"version": "4.18.2", "version": "4.18.3",
"license": "MIT", "resolved": "https://registry.npmjs.org/express/-/express-4.18.3.tgz",
"integrity": "sha512-6VyCijWQ+9O7WuVMTRBTl+cjNNIzD5cY5mQ1WM8r/LEkI2u8EYpOotESNwzNlyCn3g+dmjKYI6BmNneSr/FSRw==",
"dependencies": { "dependencies": {
"accepts": "~1.3.8", "accepts": "~1.3.8",
"array-flatten": "1.1.1", "array-flatten": "1.1.1",
"body-parser": "1.20.1", "body-parser": "1.20.2",
"content-disposition": "0.5.4", "content-disposition": "0.5.4",
"content-type": "~1.0.4", "content-type": "~1.0.4",
"cookie": "0.5.0", "cookie": "0.5.0",
@ -4805,41 +4806,6 @@
"node": ">= 0.10.0" "node": ">= 0.10.0"
} }
}, },
"node_modules/express/node_modules/body-parser": {
"version": "1.20.1",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"content-type": "~1.0.4",
"debug": "2.6.9",
"depd": "2.0.0",
"destroy": "1.2.0",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"on-finished": "2.4.1",
"qs": "6.11.0",
"raw-body": "2.5.1",
"type-is": "~1.6.18",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8",
"npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/express/node_modules/raw-body": {
"version": "2.5.1",
"license": "MIT",
"dependencies": {
"bytes": "3.1.2",
"http-errors": "2.0.0",
"iconv-lite": "0.4.24",
"unpipe": "1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
"node_modules/external-editor": { "node_modules/external-editor": {
"version": "3.1.0", "version": "3.1.0",
"dev": true, "dev": true,

View file

@ -3,6 +3,7 @@ import { ButtonEvent } from "../type/buttonEvent";
import Inventory from "../database/entities/app/Inventory"; import Inventory from "../database/entities/app/Inventory";
import { CoreClient } from "../client/client"; import { CoreClient } from "../client/client";
import { default as eClaim } from "../database/entities/app/Claim"; import { default as eClaim } from "../database/entities/app/Claim";
import AppLogger from "../client/appLogger";
export default class Claim extends ButtonEvent { export default class Claim extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) { public override async execute(interaction: ButtonInteraction) {
@ -13,6 +14,8 @@ export default class Claim extends ButtonEvent {
const droppedBy = interaction.customId.split(" ")[3]; const droppedBy = interaction.customId.split(" ")[3];
const userId = interaction.user.id; const userId = interaction.user.id;
AppLogger.LogSilly("Button/Claim", `Parameters: cardNumber=${cardNumber}, claimId=${claimId}, droppedBy=${droppedBy}, userId=${userId}`);
await interaction.deferReply(); await interaction.deferReply();
const claimed = await eClaim.FetchOneByClaimId(claimId); const claimed = await eClaim.FetchOneByClaimId(claimId);

View file

@ -1,6 +1,7 @@
import { ButtonInteraction } from "discord.js"; import { ButtonInteraction } from "discord.js";
import { ButtonEvent } from "../type/buttonEvent"; import { ButtonEvent } from "../type/buttonEvent";
import InventoryHelper from "../helpers/InventoryHelper"; import InventoryHelper from "../helpers/InventoryHelper";
import AppLogger from "../client/appLogger";
export default class Inventory extends ButtonEvent { export default class Inventory extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) { public override async execute(interaction: ButtonInteraction) {
@ -9,6 +10,8 @@ export default class Inventory extends ButtonEvent {
const userid = interaction.customId.split(" ")[1]; const userid = interaction.customId.split(" ")[1];
const page = interaction.customId.split(" ")[2]; const page = interaction.customId.split(" ")[2];
AppLogger.LogSilly("Button/Inventory", `Parameters: userid=${userid}, page=${page}`);
const member = interaction.guild.members.cache.find(x => x.id == userid) || await interaction.guild.members.fetch(userid); const member = interaction.guild.members.cache.find(x => x.id == userid) || await interaction.guild.members.fetch(userid);
if (!member) { if (!member) {
@ -17,6 +20,8 @@ export default class Inventory extends ButtonEvent {
} }
try { try {
AppLogger.LogVerbose("Button/Inventory", `Generating inventory page ${page} for ${member.user.username} with id ${member.user.id}`);
const embed = await InventoryHelper.GenerateInventoryPage(member.user.username, member.user.id, Number(page)); const embed = await InventoryHelper.GenerateInventoryPage(member.user.username, member.user.id, Number(page));
await interaction.update({ await interaction.update({
@ -24,7 +29,8 @@ export default class Inventory extends ButtonEvent {
components: [ embed.row ], components: [ embed.row ],
}); });
} catch (e) { } catch (e) {
console.error(e); AppLogger.LogError("Button/Inventory", `Error generating inventory page for ${member.user.username} with id ${member.user.id}: ${e}`);
await interaction.reply("No page for user found."); await interaction.reply("No page for user found.");
} }
} }

View file

@ -7,6 +7,7 @@ import Inventory from "../database/entities/app/Inventory";
import Config from "../database/entities/app/Config"; import Config from "../database/entities/app/Config";
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 Reroll extends ButtonEvent { export default class Reroll extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) { public override async execute(interaction: ButtonInteraction) {
@ -16,6 +17,8 @@ export default class Reroll extends ButtonEvent {
} }
if (await Config.GetValue("safemode") == "true") { if (await Config.GetValue("safemode") == "true") {
AppLogger.LogWarn("Button/Reroll", "Safe Mode is active, refusing to send next drop.");
await interaction.reply("Safe Mode has been activated, please resync to continue."); await interaction.reply("Safe Mode has been activated, please resync to continue.");
return; return;
} }
@ -30,6 +33,8 @@ export default class Reroll extends ButtonEvent {
await interaction.deferReply(); await interaction.deferReply();
try { try {
AppLogger.LogVerbose("Button/Reroll", `Sending next drop: ${randomCard.card.id} (${randomCard.card.name})`);
const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", randomCard.card.path)); const image = readFileSync(path.join(process.env.DATA_DIR!, "cards", randomCard.card.path));
const imageFileName = randomCard.card.path.split("/").pop()!; const imageFileName = randomCard.card.path.split("/").pop()!;
@ -51,9 +56,8 @@ export default class Reroll extends ButtonEvent {
}); });
CoreClient.ClaimId = claimId; CoreClient.ClaimId = claimId;
} catch (e) { } catch (e) {
console.error(e); AppLogger.LogError("Button/Reroll", `Error sending next drop for card ${randomCard.card.id}: ${e}`);
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. (${randomCard.card.id})`); await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. (${randomCard.card.id})`);
} }

View file

@ -3,11 +3,14 @@ import { ButtonEvent } from "../type/buttonEvent";
import { CoreClient } from "../client/client"; import { CoreClient } from "../client/client";
import Inventory from "../database/entities/app/Inventory"; import Inventory from "../database/entities/app/Inventory";
import EmbedColours from "../constants/EmbedColours"; import EmbedColours from "../constants/EmbedColours";
import AppLogger from "../client/appLogger";
export default class Trade extends ButtonEvent { export default class Trade extends ButtonEvent {
public override async execute(interaction: ButtonInteraction) { public override async execute(interaction: ButtonInteraction) {
const action = interaction.customId.split(" ")[1]; const action = interaction.customId.split(" ")[1];
AppLogger.LogSilly("Button/Trade", `Parameters: action=${action}`);
switch (action) { switch (action) {
case "accept": case "accept":
await this.AcceptTrade(interaction); await this.AcceptTrade(interaction);
@ -26,6 +29,8 @@ export default class Trade extends ButtonEvent {
const expiry = interaction.customId.split(" ")[6]; const expiry = interaction.customId.split(" ")[6];
const timeoutId = interaction.customId.split(" ")[7]; const timeoutId = interaction.customId.split(" ")[7];
AppLogger.LogSilly("Button/Trade/AcceptTrade", `Parameters: giveUserId=${giveUserId}, receiveUserId=${receiveUserId}, giveCardNumber=${giveCardNumber}, receiveCardNumber=${receiveCardNumber}, expiry=${expiry}, timeoutId=${timeoutId}`);
const expiryDate = new Date(expiry); const expiryDate = new Date(expiry);
if (expiryDate < new Date()) { if (expiryDate < new Date()) {
@ -100,13 +105,13 @@ export default class Trade extends ButtonEvent {
.setImage("https://i.imgur.com/9w5f1ls.gif") .setImage("https://i.imgur.com/9w5f1ls.gif")
.addFields([ .addFields([
{ {
name: `${receiveUser.username} is giving`, name: "I receieve",
value: `${giveItem.id}: ${giveItem.name}`, value: `${receiveItem.id}: ${receiveItem.name}`,
inline: true, inline: true,
}, },
{ {
name: `${giveUser.username} is giving`, name: "You receieve",
value: `${receiveItem.id}: ${receiveItem.name}`, value: `${giveItem.id}: ${giveItem.name}`,
inline: true, inline: true,
}, },
{ {
@ -140,7 +145,9 @@ export default class Trade extends ButtonEvent {
// No need to get expiry date // No need to get expiry date
const timeoutId = interaction.customId.split(" ")[7]; const timeoutId = interaction.customId.split(" ")[7];
if (interaction.user.id !== receiveUserId || interaction.user.id !== giveUserId) { AppLogger.LogSilly("Button/Trade/DeclineTrade", `Parameters: giveUserId=${giveUserId}, receiveUserId=${receiveUserId}, giveCardNumber=${giveCardNumber}, receiveCardNumber=${receiveCardNumber}, timeoutId=${timeoutId}`);
if (interaction.user.id != receiveUserId && interaction.user.id !==giveUserId) {
await interaction.reply("You are not the user who the trade is intended for"); await interaction.reply("You are not the user who the trade is intended for");
return; return;
} }
@ -170,13 +177,13 @@ export default class Trade extends ButtonEvent {
.setImage("https://i.imgur.com/9w5f1ls.gif") .setImage("https://i.imgur.com/9w5f1ls.gif")
.addFields([ .addFields([
{ {
name: `${receiveUser.username} is giving`, name: "I Receive",
value: `${giveItem.id}: ${giveItem.name}`, value: `${receiveItem.id}: ${receiveItem.name}`,
inline: true, inline: true,
}, },
{ {
name: `${giveUser.username} is giving`, name: "You Receive",
value: `${receiveItem.id}: ${receiveItem.name}`, value: `${giveItem.id}: ${giveItem.name}`,
inline: true, inline: true,
}, },
{ {

View file

@ -1,8 +1,9 @@
import { Logger, createLogger, format, transports } from "winston"; import { Logger, createLogger, format, transports } from "winston";
import { CoreClient } from "./client";
export default class AppLogger { export default class AppLogger {
public static InitialiseLogger(logLevel: string, outputToConsole: boolean): Logger { public static Logger: Logger;
public static InitialiseLogger(logLevel: string, outputToConsole: boolean) {
const customFormat = format.printf(({ level, message, timestamp, label }) => { const customFormat = format.printf(({ level, message, timestamp, label }) => {
return `${timestamp} [${label}] ${level}: ${message}`; return `${timestamp} [${label}] ${level}: ${message}`;
}); });
@ -33,30 +34,30 @@ export default class AppLogger {
)})); )}));
} }
return logger; AppLogger.Logger = logger;
} }
public static LogError(label: string, message: string) { public static LogError(label: string, message: string) {
CoreClient.Logger.error({ label, message }); AppLogger.Logger.error({ label, message });
} }
public static LogWarn(label: string, message: string) { public static LogWarn(label: string, message: string) {
CoreClient.Logger.warn({ label, message }); AppLogger.Logger.warn({ label, message });
} }
public static LogInfo(label: string, message: string) { public static LogInfo(label: string, message: string) {
CoreClient.Logger.info({ label, message }); AppLogger.Logger.info({ label, message });
} }
public static LogVerbose(label: string, message: string) { public static LogVerbose(label: string, message: string) {
CoreClient.Logger.verbose({ label, message }); AppLogger.Logger.verbose({ label, message });
} }
public static LogDebug(label: string, message: string) { public static LogDebug(label: string, message: string) {
CoreClient.Logger.debug({ label, message }); AppLogger.Logger.debug({ label, message });
} }
public static LogSilly(label: string, message: string) { public static LogSilly(label: string, message: string) {
CoreClient.Logger.silly({ label, message }); AppLogger.Logger.silly({ label, message });
} }
} }

View file

@ -13,7 +13,6 @@ import { Environment } from "../constants/Environment";
import Webhooks from "../webhooks"; import Webhooks from "../webhooks";
import CardMetadataFunction from "../Functions/CardMetadataFunction"; import CardMetadataFunction from "../Functions/CardMetadataFunction";
import { SeriesMetadata } from "../contracts/SeriesMetadata"; import { SeriesMetadata } from "../contracts/SeriesMetadata";
import { Logger } from "winston";
import AppLogger from "./appLogger"; import AppLogger from "./appLogger";
export class CoreClient extends Client { export class CoreClient extends Client {
@ -29,7 +28,6 @@ export class CoreClient extends Client {
public static Environment: Environment; public static Environment: Environment;
public static AllowDrops: boolean; public static AllowDrops: boolean;
public static Cards: SeriesMetadata[]; public static Cards: SeriesMetadata[];
public static Logger: Logger;
public static get commandItems(): ICommandItem[] { public static get commandItems(): ICommandItem[] {
return this._commandItems; return this._commandItems;
@ -49,7 +47,9 @@ export class CoreClient extends Client {
CoreClient.Environment = Number(process.env.BOT_ENV); CoreClient.Environment = Number(process.env.BOT_ENV);
CoreClient.Logger = AppLogger.InitialiseLogger(process.env.BOT_VERBOSE == "true" ? "verbose" : "info", CoreClient.Environment == Environment.Local); AppLogger.InitialiseLogger(process.env.BOT_VERBOSE == "true" ? "verbose" : "info", CoreClient.Environment == Environment.Local);
AppLogger.LogInfo("Client", "Initialising Client");
CoreClient._commandItems = []; CoreClient._commandItems = [];
CoreClient._buttonEvents = []; CoreClient._buttonEvents = [];
@ -58,20 +58,24 @@ export class CoreClient extends Client {
this._util = new Util(); this._util = new Util();
this._webhooks = new Webhooks(); this._webhooks = new Webhooks();
console.log(`Bot Environment: ${CoreClient.Environment}`); AppLogger.LogInfo("Client", `Environment: ${CoreClient.Environment}`);
CoreClient.AllowDrops = true; CoreClient.AllowDrops = true;
} }
public async start() { public async start() {
if (!process.env.BOT_TOKEN) { if (!process.env.BOT_TOKEN) {
console.error("BOT_TOKEN is not defined in .env"); AppLogger.LogError("Client", "BOT_TOKEN is not defined in .env");
return; return;
} }
await AppDataSource.initialize() await AppDataSource.initialize()
.then(() => console.log("App Data Source Initialised")) .then(() => AppLogger.LogInfo("Client", "App Data Source Initialised"))
.catch(err => console.error("Error initialising App Data Source", err)); .catch(err => {
AppLogger.LogError("Client", "App Data Source Initialisation Failed");
AppLogger.LogError("Client", err);
throw err;
});
super.on("interactionCreate", this._events.onInteractionCreate); super.on("interactionCreate", this._events.onInteractionCreate);
super.on("ready", this._events.onReady); super.on("ready", this._events.onReady);
@ -96,6 +100,8 @@ export class CoreClient extends Client {
if ((environment & CoreClient.Environment) == CoreClient.Environment) { if ((environment & CoreClient.Environment) == CoreClient.Environment) {
CoreClient._commandItems.push(item); CoreClient._commandItems.push(item);
AppLogger.LogVerbose("Client", `Registered Command: ${name}`);
} }
} }
@ -118,6 +124,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Channel Create Event`);
} }
public static RegisterChannelDeleteEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) { public static RegisterChannelDeleteEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) {
@ -139,6 +147,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Channel Delete Event`);
} }
public static RegisterChannelUpdateEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) { public static RegisterChannelUpdateEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) {
@ -160,6 +170,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Channel Update Event`);
} }
public static RegisterGuildBanAddEvent(fn: (ban: GuildBan) => void) { public static RegisterGuildBanAddEvent(fn: (ban: GuildBan) => void) {
@ -181,6 +193,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Guild Ban Add Event`);
} }
public static RegisterGuildBanRemoveEvent(fn: (channel: GuildBan) => void) { public static RegisterGuildBanRemoveEvent(fn: (channel: GuildBan) => void) {
@ -202,6 +216,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Guild Ban Remove Event`);
} }
public static RegisterGuildCreateEvent(fn: (guild: Guild) => void) { public static RegisterGuildCreateEvent(fn: (guild: Guild) => void) {
@ -223,6 +239,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Guild Create Event`);
} }
public static RegisterGuildMemberAddEvent(fn: (member: GuildMember) => void) { public static RegisterGuildMemberAddEvent(fn: (member: GuildMember) => void) {
@ -244,6 +262,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Guild Member Add Event`);
} }
public static RegisterGuildMemberRemoveEvent(fn: (member: GuildMember | PartialGuildMember) => void) { public static RegisterGuildMemberRemoveEvent(fn: (member: GuildMember | PartialGuildMember) => void) {
@ -265,6 +285,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Guild Member Remove Event`);
} }
public static GuildMemebrUpdate(fn: (oldMember: GuildMember | PartialGuildMember, newMember: GuildMember) => void) { public static GuildMemebrUpdate(fn: (oldMember: GuildMember | PartialGuildMember, newMember: GuildMember) => void) {
@ -286,6 +308,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Guild Member Update Event`);
} }
public static RegisterMessageCreateEvent(fn: (message: Message<boolean>) => void) { public static RegisterMessageCreateEvent(fn: (message: Message<boolean>) => void) {
@ -307,6 +331,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Message Create Event`);
} }
public static RegisterMessageDeleteEvent(fn: (message: Message<boolean> | PartialMessage) => void) { public static RegisterMessageDeleteEvent(fn: (message: Message<boolean> | PartialMessage) => void) {
@ -328,6 +354,8 @@ export class CoreClient extends Client {
MessageUpdate: [], MessageUpdate: [],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Message Delete Event`);
} }
public static RegisterMessageUpdateEvent(fn: (oldMessage: Message<boolean> | PartialMessage, newMessage: Message<boolean> | PartialMessage) => void) { public static RegisterMessageUpdateEvent(fn: (oldMessage: Message<boolean> | PartialMessage, newMessage: Message<boolean> | PartialMessage) => void) {
@ -349,6 +377,8 @@ export class CoreClient extends Client {
MessageUpdate: [ fn ], MessageUpdate: [ fn ],
}; };
} }
AppLogger.LogVerbose("Client", `Registered Message Update Event`);
} }
public static RegisterButtonEvent(buttonId: string, event: ButtonEvent, environment: Environment = Environment.All) { public static RegisterButtonEvent(buttonId: string, event: ButtonEvent, environment: Environment = Environment.All) {
@ -360,6 +390,8 @@ export class CoreClient extends Client {
if ((environment & CoreClient.Environment) == CoreClient.Environment) { if ((environment & CoreClient.Environment) == CoreClient.Environment) {
CoreClient._buttonEvents.push(item); CoreClient._buttonEvents.push(item);
AppLogger.LogVerbose("Client", `Registered Button Event: ${buttonId}`);
} }
} }
} }

View file

@ -1,22 +1,25 @@
import { Interaction } from "discord.js"; import { Interaction } from "discord.js";
import ChatInputCommand from "./interactionCreate/ChatInputCommand"; import ChatInputCommand from "./interactionCreate/ChatInputCommand";
import Button from "./interactionCreate/Button"; import Button from "./interactionCreate/Button";
import AppLogger from "./appLogger";
export class Events { export class Events {
public async onInteractionCreate(interaction: Interaction) { public async onInteractionCreate(interaction: Interaction) {
if (!interaction.guildId) return; if (!interaction.guildId) return;
if (interaction.isChatInputCommand()) { if (interaction.isChatInputCommand()) {
AppLogger.LogVerbose("Client", `ChatInputCommand: ${interaction.commandName}`);
ChatInputCommand.onChatInput(interaction); ChatInputCommand.onChatInput(interaction);
} }
if (interaction.isButton()) { if (interaction.isButton()) {
AppLogger.LogVerbose("Client", `Button: ${interaction.customId}`);
Button.onButtonClicked(interaction); Button.onButtonClicked(interaction);
} }
} }
// Emit when bot is logged in and ready to use // Emit when bot is logged in and ready to use
public onReady() { public onReady() {
console.log("Ready"); AppLogger.LogInfo("Client", "Ready");
} }
} }

View file

@ -1,5 +1,6 @@
import { ButtonInteraction } from "discord.js"; import { ButtonInteraction } from "discord.js";
import { CoreClient } from "../client"; import { CoreClient } from "../client";
import AppLogger from "../appLogger";
export default class Button { export default class Button {
public static async onButtonClicked(interaction: ButtonInteraction) { public static async onButtonClicked(interaction: ButtonInteraction) {
@ -8,14 +9,19 @@ export default class Button {
const item = CoreClient.buttonEvents.find(x => x.ButtonId == interaction.customId.split(" ")[0]); const item = CoreClient.buttonEvents.find(x => x.ButtonId == interaction.customId.split(" ")[0]);
if (!item) { if (!item) {
AppLogger.LogVerbose("Button", `Event not found: ${interaction.customId}`);
await interaction.reply("Event not found"); await interaction.reply("Event not found");
return; return;
} }
try { try {
AppLogger.LogDebug("Button", `Executing ${interaction.customId}`);
item.Event.execute(interaction); item.Event.execute(interaction);
} catch (e) { } catch (e) {
console.error(e); AppLogger.LogError("Button", `Error occurred while executing event: ${interaction.customId}`);
AppLogger.LogError("Button", e as string);
await interaction.reply("An error occurred while executing the event"); await interaction.reply("An error occurred while executing the event");
} }

View file

@ -1,6 +1,7 @@
import { Interaction } from "discord.js"; import { Interaction } from "discord.js";
import { CoreClient } from "../client"; import { CoreClient } from "../client";
import ICommandItem from "../../contracts/ICommandItem"; import ICommandItem from "../../contracts/ICommandItem";
import AppLogger from "../appLogger";
export default class ChatInputCommand { export default class ChatInputCommand {
public static async onChatInput(interaction: Interaction) { public static async onChatInput(interaction: Interaction) {
@ -13,6 +14,8 @@ export default class ChatInputCommand {
if (!itemForServer) { if (!itemForServer) {
if (!item) { if (!item) {
AppLogger.LogVerbose("ChatInputCommand", `Command not found: ${interaction.commandName}`);
await interaction.reply("Command not found"); await interaction.reply("Command not found");
return; return;
} }
@ -23,9 +26,12 @@ export default class ChatInputCommand {
} }
try { try {
AppLogger.LogDebug("Command", `Executing ${interaction.commandName}`);
itemToUse.Command.execute(interaction); itemToUse.Command.execute(interaction);
} catch (e) { } catch (e) {
console.error(e); AppLogger.LogError("ChatInputCommand", `Error occurred while executing command: ${interaction.commandName}`);
AppLogger.LogError("ChatInputCommand", e as string);
await interaction.reply("An error occurred while executing the command"); await interaction.reply("An error occurred while executing the command");
} }

View file

@ -1,6 +1,7 @@
import { Client, REST, Routes, SlashCommandBuilder } from "discord.js"; import { Client, REST, Routes, SlashCommandBuilder } from "discord.js";
import EventExecutors from "../contracts/EventExecutors"; import EventExecutors from "../contracts/EventExecutors";
import { CoreClient } from "./client"; import { CoreClient } from "./client";
import AppLogger from "./appLogger";
export class Util { export class Util {
public loadSlashCommands(client: Client) { public loadSlashCommands(client: Client) {
@ -29,6 +30,8 @@ export class Util {
const rest = new REST({ version: "10" }).setToken(process.env.BOT_TOKEN!); const rest = new REST({ version: "10" }).setToken(process.env.BOT_TOKEN!);
AppLogger.LogVerbose("Util", `REST PUT: ${globalCommandData.flatMap(x => x.name).join(", ")}`);
rest.put( rest.put(
Routes.applicationCommands(process.env.BOT_CLIENTID!), Routes.applicationCommands(process.env.BOT_CLIENTID!),
{ {
@ -49,6 +52,8 @@ export class Util {
if (!client.guilds.cache.has(guild)) continue; if (!client.guilds.cache.has(guild)) continue;
AppLogger.LogVerbose("Util", `REST PUT: ${guild} - ${guildCommandData.flatMap(x => x.name).join(", ")}`);
rest.put( rest.put(
Routes.applicationGuildCommands(process.env.BOT_CLIENTID!, guild), Routes.applicationGuildCommands(process.env.BOT_CLIENTID!, guild),
{ {

View file

@ -7,6 +7,7 @@ import Inventory from "../database/entities/app/Inventory";
import Config from "../database/entities/app/Config"; import Config from "../database/entities/app/Config";
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 Drop extends Command { export default class Drop extends Command {
constructor() { constructor() {
@ -24,6 +25,8 @@ export default class Drop extends Command {
} }
if (await Config.GetValue("safemode") == "true") { if (await Config.GetValue("safemode") == "true") {
AppLogger.LogWarn("Commands/Drop", "Safe Mode is active, refusing to send next drop.");
await interaction.reply("Safe Mode has been activated, please resync to continue."); await interaction.reply("Safe Mode has been activated, please resync to continue.");
return; return;
} }
@ -61,7 +64,7 @@ export default class Drop extends Command {
CoreClient.ClaimId = claimId; CoreClient.ClaimId = claimId;
} catch (e) { } catch (e) {
console.error(e); AppLogger.LogError("Commands/Drop", `Error sending next drop for card ${randomCard.card.id}: ${e}`);
await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. (${randomCard.card.id})`); await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. (${randomCard.card.id})`);
} }

View file

@ -4,6 +4,7 @@ import { ExecException, exec } from "child_process";
import { CoreClient } from "../client/client"; import { CoreClient } from "../client/client";
import Config from "../database/entities/app/Config"; import Config from "../database/entities/app/Config";
import CardMetadataFunction from "../Functions/CardMetadataFunction"; import CardMetadataFunction from "../Functions/CardMetadataFunction";
import AppLogger from "../client/appLogger";
export default class Gdrivesync extends Command { export default class Gdrivesync extends Command {
constructor() { constructor() {
@ -32,19 +33,28 @@ export default class Gdrivesync extends Command {
CoreClient.AllowDrops = false; CoreClient.AllowDrops = false;
AppLogger.LogInfo("Commands/GDriveSync", "Syncing google drive to the bot");
exec(`rclone sync card-drop-gdrive: ${process.env.DATA_DIR}/cards`, async (error: ExecException | null) => { exec(`rclone sync card-drop-gdrive: ${process.env.DATA_DIR}/cards`, async (error: ExecException | null) => {
if (error) { if (error) {
AppLogger.LogError("Commands/GDriveSync", `Error while running sync command: ${error.code}, ${error.message}`);
AppLogger.LogWarn("Commands/GDriveSync", "Safe mode activated");
await interaction.editReply(`Error while running sync command. Safe Mode has been activated. Code: ${error.code}`); await interaction.editReply(`Error while running sync command. Safe Mode has been activated. Code: ${error.code}`);
await Config.SetValue("safemode", "true"); await Config.SetValue("safemode", "true");
} else { } else {
const result = await CardMetadataFunction.Execute(true); const result = await CardMetadataFunction.Execute(true);
if (result.IsSuccess) { if (result.IsSuccess) {
AppLogger.LogInfo("Commands/GDriveSync", "Synced successfully");
await interaction.editReply("Synced successfully."); await interaction.editReply("Synced successfully.");
CoreClient.AllowDrops = true; CoreClient.AllowDrops = true;
await Config.SetValue("safemode", "false"); await Config.SetValue("safemode", "false");
} else { } else {
AppLogger.LogError("Commands/GDriveSync", `Error while running sync command: ${result.ErrorMessage}`);
await interaction.editReply(`Sync failed \`\`\`${result.ErrorMessage}\`\`\``); await interaction.editReply(`Sync failed \`\`\`${result.ErrorMessage}\`\`\``);
} }
} }

View file

@ -4,6 +4,7 @@ import { CoreClient } from "../client/client";
import Config from "../database/entities/app/Config"; import Config from "../database/entities/app/Config";
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
import Inventory from "../database/entities/app/Inventory"; import Inventory from "../database/entities/app/Inventory";
import AppLogger from "../client/appLogger";
export default class Give extends Command { export default class Give extends Command {
constructor() { constructor() {
@ -46,6 +47,8 @@ export default class Give extends Command {
const cardNumber = interaction.options.get("cardnumber", true); const cardNumber = interaction.options.get("cardnumber", true);
const user = interaction.options.getUser("user", true); const user = interaction.options.getUser("user", true);
AppLogger.LogSilly("Commands/Give", `Parameters: cardNumber=${cardNumber.value}, user=${user.id}`);
const card = CardDropHelperMetadata.GetCardByCardNumber(cardNumber.value!.toString()); const card = CardDropHelperMetadata.GetCardByCardNumber(cardNumber.value!.toString());
if (!card) { if (!card) {
@ -63,6 +66,6 @@ export default class Give extends Command {
await inventory.Save(Inventory, inventory); await inventory.Save(Inventory, inventory);
await interaction.reply(`${card.name} given to ${interaction.user}, they now have ${inventory.Quantity}`); await interaction.reply(`${card.name} given to ${user.username}, they now have ${inventory.Quantity}`);
} }
} }

View file

@ -1,6 +1,7 @@
import { CommandInteraction, SlashCommandBuilder } from "discord.js"; import { CommandInteraction, SlashCommandBuilder } from "discord.js";
import { Command } from "../type/command"; import { Command } from "../type/command";
import InventoryHelper from "../helpers/InventoryHelper"; import InventoryHelper from "../helpers/InventoryHelper";
import AppLogger from "../client/appLogger";
export default class Inventory extends Command { export default class Inventory extends Command {
constructor() { constructor() {
@ -23,6 +24,8 @@ export default class Inventory extends Command {
const page = interaction.options.get("page"); const page = interaction.options.get("page");
const user = interaction.options.getUser("user") || interaction.user; const user = interaction.options.getUser("user") || interaction.user;
AppLogger.LogSilly("Commands/Inventory", `Parameters: page=${page?.value}, user=${user.id}`);
try { try {
let pageNumber = 0; let pageNumber = 0;

View file

@ -2,6 +2,7 @@ import { CacheType, CommandInteraction, PermissionsBitField, SlashCommandBuilder
import { Command } from "../type/command"; import { Command } from "../type/command";
import Config from "../database/entities/app/Config"; import Config from "../database/entities/app/Config";
import CardMetadataFunction from "../Functions/CardMetadataFunction"; import CardMetadataFunction from "../Functions/CardMetadataFunction";
import AppLogger from "../client/appLogger";
export default class Resync extends Command { export default class Resync extends Command {
constructor() { constructor() {
@ -23,6 +24,8 @@ export default class Resync extends Command {
return; return;
} }
AppLogger.LogInfo("Commands/Resync", "Resyncing database");
const result = await CardMetadataFunction.Execute(true); const result = await CardMetadataFunction.Execute(true);
if (result) { if (result) {
@ -34,6 +37,8 @@ export default class Resync extends Command {
} }
await interaction.reply("Resynced database."); await interaction.reply("Resynced database.");
} else { } else {
AppLogger.LogWarn("Commands/Resync", "Resync failed, safe mode activated");
await interaction.reply("Resync failed, safe mode has been activated until successful resync."); await interaction.reply("Resync failed, safe mode has been activated until successful resync.");
} }
} }

View file

@ -3,6 +3,7 @@ import { Command } from "../type/command";
import Inventory from "../database/entities/app/Inventory"; import Inventory from "../database/entities/app/Inventory";
import { CoreClient } from "../client/client"; import { CoreClient } from "../client/client";
import EmbedColours from "../constants/EmbedColours"; import EmbedColours from "../constants/EmbedColours";
import AppLogger from "../client/appLogger";
export default class Trade extends Command { export default class Trade extends Command {
constructor() { constructor() {
@ -33,6 +34,8 @@ export default class Trade extends Command {
const give = interaction.options.get("give")!; const give = interaction.options.get("give")!;
const receive = interaction.options.get("receive")!; const receive = interaction.options.get("receive")!;
AppLogger.LogSilly("Commands/Trade", `Parameters: user=${user.id}, give=${give.value}, receive=${receive.value}`);
const giveItemEntity = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, give.value!.toString()); const giveItemEntity = await Inventory.FetchOneByCardNumberAndUserId(interaction.user.id, give.value!.toString());
const receiveItemEntity = await Inventory.FetchOneByCardNumberAndUserId(user.id, receive.value!.toString()); const receiveItemEntity = await Inventory.FetchOneByCardNumberAndUserId(user.id, receive.value!.toString());
@ -63,19 +66,19 @@ export default class Trade extends Command {
const expiry = now.setMinutes(now.getMinutes() + 15); const expiry = now.setMinutes(now.getMinutes() + 15);
const tradeEmbed = new EmbedBuilder() const tradeEmbed = new EmbedBuilder()
.setTitle("Trade Offer") .setTitle("⚠️ Trade Offer ⚠️")
.setDescription(`Trade initiated between ${interaction.user.username} and ${user.username}`) .setDescription(`Trade initiated between ${interaction.user.username} and ${user.username}`)
.setColor(EmbedColours.Grey) .setColor(EmbedColours.Grey)
.setImage("https://media1.tenor.com/m/KkZwKl2AQ2QAAAAd/trade-offer.gif") .setImage("https://media1.tenor.com/m/KkZwKl2AQ2QAAAAd/trade-offer.gif")
.addFields([ .addFields([
{ {
name: `${interaction.user.username} is giving`, name: "I Receive",
value: `${giveItem.id}: ${giveItem.name}`, value: `${receiveItem.id}: ${receiveItem.name}`,
inline: true, inline: true,
}, },
{ {
name: `${user.username} is giving`, name: "You Receive",
value: `${receiveItem.id}: ${receiveItem.name}`, value: `${giveItem.id}: ${giveItem.name}`,
inline: true, inline: true,
}, },
{ {
@ -102,6 +105,8 @@ export default class Trade extends Command {
} }
private async autoDecline(interaction: CommandInteraction, giveUsername: string, receiveUsername: string, giveCardNumber: string, receiveCardNumber: string, giveCardName: string, receiveCardName: string) { private async autoDecline(interaction: CommandInteraction, giveUsername: string, receiveUsername: string, giveCardNumber: string, receiveCardNumber: string, giveCardName: string, receiveCardName: string) {
AppLogger.LogSilly("Commands/Trade/AutoDecline", `Auto declining trade between ${giveUsername} and ${receiveUsername}`);
const tradeEmbed = new EmbedBuilder() const tradeEmbed = new EmbedBuilder()
.setTitle("Trade Expired") .setTitle("Trade Expired")
.setDescription(`Trade initiated between ${receiveUsername} and ${giveUsername}`) .setDescription(`Trade initiated between ${receiveUsername} and ${giveUsername}`)
@ -109,13 +114,13 @@ export default class Trade extends Command {
.setImage("https://media1.tenor.com/m/KkZwKl2AQ2QAAAAd/trade-offer.gif") .setImage("https://media1.tenor.com/m/KkZwKl2AQ2QAAAAd/trade-offer.gif")
.addFields([ .addFields([
{ {
name: `${receiveUsername} is giving`, name: "I Receive",
value: `${giveCardNumber}: ${giveCardName}`, value: `${receiveCardNumber}: ${receiveCardName}`,
inline: true, inline: true,
}, },
{ {
name: `${giveUsername} is giving`, name: "You Receive",
value: `${receiveCardNumber}: ${receiveCardName}`, value: `${giveCardNumber}: ${giveCardName}`,
inline: true, inline: true,
}, },
{ {

View file

@ -5,6 +5,7 @@ import { readFileSync } from "fs";
import path from "path"; import path from "path";
import Inventory from "../database/entities/app/Inventory"; import Inventory from "../database/entities/app/Inventory";
import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata";
import AppLogger from "../client/appLogger";
export default class View extends Command { export default class View extends Command {
constructor() { constructor() {
@ -23,6 +24,8 @@ export default class View extends Command {
public override async execute(interaction: CommandInteraction) { public override async execute(interaction: CommandInteraction) {
const cardNumber = interaction.options.get("cardnumber"); const cardNumber = interaction.options.get("cardnumber");
AppLogger.LogSilly("Commands/View", `Parameters: cardNumber=${cardNumber?.value}`);
if (!cardNumber || !cardNumber.value) { if (!cardNumber || !cardNumber.value) {
await interaction.reply("Card number is required."); await interaction.reply("Card number is required.");
return; return;
@ -46,6 +49,8 @@ export default class View extends Command {
try { try {
image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.path)); image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.path));
} catch { } catch {
AppLogger.LogError("Commands/View", `Unable to fetch image for card ${card.id}.`);
await interaction.reply(`Unable to fetch image for card ${card.id}.`); await interaction.reply(`Unable to fetch image for card ${card.id}.`);
return; return;
} }
@ -65,7 +70,7 @@ export default class View extends Command {
files: [ attachment ], files: [ attachment ],
}); });
} catch (e) { } catch (e) {
console.error(e); AppLogger.LogError("Commands/View", `Error sending view for card ${card.id}: ${e}`);
if (e instanceof DiscordAPIError) { 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}.`); await interaction.editReply(`Unable to send next drop. Please try again, and report this if it keeps happening. Code: ${e.code}.`);