From 5dd50a3f3b1ff25176e6bbd69d971ffc5cc59fa1 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Fri, 15 Mar 2024 17:33:12 +0000 Subject: [PATCH] Add logger to project (#183) # 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. - Add the winston package to handle logging - Add logging to the project's logic #146 ## Type of change Please delete options that are not relevant. - [x] New feature (non-breaking change which adds functionality) # 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/183 Reviewed-by: VylpesTester Co-authored-by: Ethan Lane Co-committed-by: Ethan Lane --- .dev.env | 1 + .prod.env | 1 + .stage.env | 1 + package-lock.json | 222 +++++++++++++++++- package.json | 3 +- src/Functions/CardMetadataFunction.ts | 22 +- src/buttonEvents/Claim.ts | 3 + src/buttonEvents/Inventory.ts | 8 +- src/buttonEvents/Reroll.ts | 8 +- src/buttonEvents/Trade.ts | 7 + src/client/appLogger.ts | 65 +++++ src/client/client.ts | 50 +++- src/client/events.ts | 5 +- src/client/interactionCreate/Button.ts | 8 +- .../interactionCreate/ChatInputCommand.ts | 8 +- src/client/util.ts | 5 + src/commands/drop.ts | 7 +- src/commands/gdrivesync.ts | 10 + src/commands/give.ts | 3 + src/commands/inventory.ts | 7 +- src/commands/resync.ts | 7 + src/commands/trade.ts | 5 + src/commands/view.ts | 7 +- src/helpers/CardDropHelperMetadata.ts | 17 ++ src/helpers/InventoryHelper.ts | 5 +- src/hooks/ReloadDB.ts | 3 +- src/webhooks.ts | 3 +- 27 files changed, 465 insertions(+), 26 deletions(-) create mode 100644 src/client/appLogger.ts diff --git a/.dev.env b/.dev.env index 9965665..aa54d10 100644 --- a/.dev.env +++ b/.dev.env @@ -12,6 +12,7 @@ BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=682942374040961060 BOT_ENV=4 +BOT_LOGLEVEL=info BOT_ADMINS=147392775707426816,887272961504071690 ABOUT_FUNDING= diff --git a/.prod.env b/.prod.env index da1fc9c..80de62d 100644 --- a/.prod.env +++ b/.prod.env @@ -12,6 +12,7 @@ BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=1093810443589529631 BOT_ENV=1 +BOT_LOGLEVEL=info BOT_ADMINS=147392775707426816,887272961504071690 ABOUT_FUNDING= diff --git a/.stage.env b/.stage.env index 0c9264a..09120c1 100644 --- a/.stage.env +++ b/.stage.env @@ -12,6 +12,7 @@ BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=1147976642942214235 BOT_ENV=2 +BOT_LOGLEVEL=info BOT_ADMINS=147392775707426816,887272961504071690 ABOUT_FUNDING= diff --git a/package-lock.json b/package-lock.json index e2d71ad..d222db8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -25,7 +25,8 @@ "minimatch": "9.0.3", "mysql": "^2.18.1", "ts-jest": "^29.0.0", - "typeorm": "0.3.20" + "typeorm": "0.3.20", + "winston": "^3.11.0" }, "devDependencies": { "@types/node": "^20.0.0", @@ -711,6 +712,24 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/@colors/colors": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.6.0.tgz", + "integrity": "sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==", + "engines": { + "node": ">=0.1.90" + } + }, + "node_modules/@dabh/diagnostics": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@dabh/diagnostics/-/diagnostics-2.0.3.tgz", + "integrity": "sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==", + "dependencies": { + "colorspace": "1.1.x", + "enabled": "2.0.x", + "kuler": "^2.0.0" + } + }, "node_modules/@discordjs/builders": { "version": "1.7.0", "license": "Apache-2.0", @@ -1940,6 +1959,11 @@ "version": "2.0.3", "license": "MIT" }, + "node_modules/@types/triple-beam": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/triple-beam/-/triple-beam-1.3.5.tgz", + "integrity": "sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==" + }, "node_modules/@types/uuid": { "version": "9.0.8", "resolved": "https://registry.npmjs.org/@types/uuid/-/uuid-9.0.8.tgz", @@ -2576,6 +2600,11 @@ "node": ">=8" } }, + "node_modules/async": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.5.tgz", + "integrity": "sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==" + }, "node_modules/babel-jest": { "version": "29.7.0", "license": "MIT", @@ -3582,6 +3611,15 @@ "version": "1.0.2", "license": "MIT" }, + "node_modules/color": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz", + "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==", + "dependencies": { + "color-convert": "^1.9.3", + "color-string": "^1.6.0" + } + }, "node_modules/color-convert": { "version": "2.0.1", "license": "MIT", @@ -3596,6 +3634,15 @@ "version": "1.1.4", "license": "MIT" }, + "node_modules/color-string": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz", + "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==", + "dependencies": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, "node_modules/color-support": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", @@ -3606,6 +3653,28 @@ "color-support": "bin.js" } }, + "node_modules/color/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/color/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/colorspace": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.4.tgz", + "integrity": "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==", + "dependencies": { + "color": "^3.1.3", + "text-hex": "1.0.x" + } + }, "node_modules/commander": { "version": "6.2.1", "dev": true, @@ -4211,6 +4280,11 @@ "version": "8.0.0", "license": "MIT" }, + "node_modules/enabled": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-2.0.0.tgz", + "integrity": "sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==" + }, "node_modules/encodeurl": { "version": "1.0.2", "license": "MIT", @@ -4767,6 +4841,11 @@ "bser": "2.1.1" } }, + "node_modules/fecha": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-4.2.3.tgz", + "integrity": "sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==" + }, "node_modules/figures": { "version": "2.0.0", "dev": true, @@ -4859,6 +4938,11 @@ "integrity": "sha512-36yxDn5H7OFZQla0/jFJmbIKTdZAQHngCedGxiMmpNfEZM0sdEeT+WczLQrjK6D7o2aiyLYDnkw0R3JK0Qv1RQ==", "dev": true }, + "node_modules/fn.name": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fn.name/-/fn.name-1.1.0.tgz", + "integrity": "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==" + }, "node_modules/foreground-child": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", @@ -7055,6 +7139,11 @@ "node": ">=6" } }, + "node_modules/kuler": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-2.0.0.tgz", + "integrity": "sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==" + }, "node_modules/latest-version": { "version": "7.0.0", "dev": true, @@ -7555,6 +7644,27 @@ "node": ">=4" } }, + "node_modules/logform": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-2.6.0.tgz", + "integrity": "sha512-1ulHeNPp6k/LD8H91o7VYFBng5i1BDE7HoKxVbZiGFidS1Rj65qcywLxX+pVfAPoQJEjRdvKcusKwOupHCVOVQ==", + "dependencies": { + "@colors/colors": "1.6.0", + "@types/triple-beam": "^1.3.2", + "fecha": "^4.2.0", + "ms": "^2.1.1", + "safe-stable-stringify": "^2.3.1", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/logform/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/lowercase-keys": { "version": "2.0.0", "dev": true, @@ -8670,6 +8780,14 @@ "wrappy": "1" } }, + "node_modules/one-time": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-1.0.0.tgz", + "integrity": "sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==", + "dependencies": { + "fn.name": "1.x.x" + } + }, "node_modules/onetime": { "version": "5.1.2", "license": "MIT", @@ -9887,6 +10005,14 @@ ], "license": "MIT" }, + "node_modules/safe-stable-stringify": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.4.3.tgz", + "integrity": "sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==", + "engines": { + "node": ">=10" + } + }, "node_modules/safer-buffer": { "version": "2.1.2", "license": "MIT" @@ -10034,6 +10160,19 @@ "version": "3.0.7", "license": "ISC" }, + "node_modules/simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==", + "dependencies": { + "is-arrayish": "^0.3.1" + } + }, + "node_modules/simple-swizzle/node_modules/is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + }, "node_modules/sisteransi": { "version": "1.0.5", "license": "MIT" @@ -10223,6 +10362,14 @@ "node": ">=8" } }, + "node_modules/stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==", + "engines": { + "node": "*" + } + }, "node_modules/stack-utils": { "version": "2.0.6", "license": "MIT", @@ -10571,6 +10718,11 @@ "node": "*" } }, + "node_modules/text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -10656,6 +10808,14 @@ "optional": true, "peer": true }, + "node_modules/triple-beam": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.4.1.tgz", + "integrity": "sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==", + "engines": { + "node": ">= 14.0.0" + } + }, "node_modules/ts-api-utils": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.0.3.tgz", @@ -11244,6 +11404,66 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/winston": { + "version": "3.11.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.11.0.tgz", + "integrity": "sha512-L3yR6/MzZAOl0DsysUXHVjOwv8mKZ71TrA/41EIduGpOOV5LQVodqN+QdQ6BS6PJ/RdIshZhq84P/fStEZkk7g==", + "dependencies": { + "@colors/colors": "^1.6.0", + "@dabh/diagnostics": "^2.0.2", + "async": "^3.2.3", + "is-stream": "^2.0.0", + "logform": "^2.4.0", + "one-time": "^1.0.0", + "readable-stream": "^3.4.0", + "safe-stable-stringify": "^2.3.1", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.5.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.7.0.tgz", + "integrity": "sha512-ajBj65K5I7denzer2IYW6+2bNIVqLGDHqDw3Ow8Ohh+vdW+rv4MZ6eiDvHoKhfJFZ2auyN8byXieDDJ96ViONg==", + "dependencies": { + "logform": "^2.3.2", + "readable-stream": "^3.6.0", + "triple-beam": "^1.3.0" + }, + "engines": { + "node": ">= 12.0.0" + } + }, + "node_modules/winston-transport/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/winston/node_modules/readable-stream": { + "version": "3.6.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", + "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", + "dependencies": { + "inherits": "^2.0.3", + "string_decoder": "^1.1.1", + "util-deprecate": "^1.0.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/wrap-ansi": { "version": "8.1.0", "license": "MIT", diff --git a/package.json b/package.json index d481825..3f77778 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,8 @@ "minimatch": "9.0.3", "mysql": "^2.18.1", "ts-jest": "^29.0.0", - "typeorm": "0.3.20" + "typeorm": "0.3.20", + "winston": "^3.11.0" }, "overrides": { "undici": "^5.28.3" diff --git a/src/Functions/CardMetadataFunction.ts b/src/Functions/CardMetadataFunction.ts index 3a8b97a..733c50c 100644 --- a/src/Functions/CardMetadataFunction.ts +++ b/src/Functions/CardMetadataFunction.ts @@ -4,6 +4,7 @@ import Config from "../database/entities/app/Config"; import { glob } from "glob"; import { SeriesMetadata } from "../contracts/SeriesMetadata"; import { CoreClient } from "../client/client"; +import AppLogger from "../client/appLogger"; export interface CardMetadataResult { IsSuccess: boolean; @@ -21,16 +22,22 @@ export interface FindMetadataResult { export default class CardMetadataFunction { public static async Execute(overrideSafeMode: boolean = false): Promise { - if (!overrideSafeMode && await Config.GetValue("safemode") == "true") return { - IsSuccess: false, - ErrorMessage: "Safe mode is on and not overridden", - }; + AppLogger.LogInfo("Functions/CardMetadataFunction", "Executing"); + + if (!overrideSafeMode && await Config.GetValue("safemode") == "true") { + AppLogger.LogWarn("Functions/CardMetadataFunction", "Safe Mode is active, refusing to resync"); + + return { + IsSuccess: false, + ErrorMessage: "Safe mode is on and not overridden", + }; + } const cardResult = await this.FindMetadataJSONs(); if (cardResult.IsSuccess) { CoreClient.Cards = cardResult.Result!; - console.log(`Loaded ${CoreClient.Cards.flatMap(x => x.cards).length} cards to database`); + AppLogger.LogInfo("Functions/CardMetadataFunction", `Loaded ${CoreClient.Cards.flatMap(x => x.cards).length} cards to database`); return { IsSuccess: true, @@ -38,6 +45,7 @@ export default class CardMetadataFunction { } await Config.SetValue("safemode", "true"); + AppLogger.LogError("Functions/CardMetadataFunction", `Safe Mode activated due to error: ${cardResult.Error!.Message}`); return { IsSuccess: false, @@ -52,13 +60,13 @@ export default class CardMetadataFunction { for (const jsonPath of seriesJSONs) { try { - console.log(`Reading file ${jsonPath}`); + AppLogger.LogVerbose("Functions/CardMetadataFunction", `Reading file ${jsonPath}`); const jsonFile = readFileSync(jsonPath); const parsedJson: SeriesMetadata[] = JSON.parse(jsonFile.toString()); res.push(...parsedJson); } catch (e) { - console.error(e); + AppLogger.LogError("Functions/CardMetadataFunction", `Error reading file ${jsonPath}: ${e}`); return { IsSuccess: false, diff --git a/src/buttonEvents/Claim.ts b/src/buttonEvents/Claim.ts index a9f8c86..53538f4 100644 --- a/src/buttonEvents/Claim.ts +++ b/src/buttonEvents/Claim.ts @@ -3,6 +3,7 @@ import { ButtonEvent } from "../type/buttonEvent"; import Inventory from "../database/entities/app/Inventory"; import { CoreClient } from "../client/client"; import { default as eClaim } from "../database/entities/app/Claim"; +import AppLogger from "../client/appLogger"; export default class Claim extends ButtonEvent { public override async execute(interaction: ButtonInteraction) { @@ -13,6 +14,8 @@ export default class Claim extends ButtonEvent { const droppedBy = interaction.customId.split(" ")[3]; const userId = interaction.user.id; + AppLogger.LogSilly("Button/Claim", `Parameters: cardNumber=${cardNumber}, claimId=${claimId}, droppedBy=${droppedBy}, userId=${userId}`); + await interaction.deferReply(); const claimed = await eClaim.FetchOneByClaimId(claimId); diff --git a/src/buttonEvents/Inventory.ts b/src/buttonEvents/Inventory.ts index 4bfffc1..7dfb305 100644 --- a/src/buttonEvents/Inventory.ts +++ b/src/buttonEvents/Inventory.ts @@ -1,6 +1,7 @@ import { ButtonInteraction } from "discord.js"; import { ButtonEvent } from "../type/buttonEvent"; import InventoryHelper from "../helpers/InventoryHelper"; +import AppLogger from "../client/appLogger"; export default class Inventory extends ButtonEvent { public override async execute(interaction: ButtonInteraction) { @@ -9,6 +10,8 @@ export default class Inventory extends ButtonEvent { const userid = interaction.customId.split(" ")[1]; 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); if (!member) { @@ -17,6 +20,8 @@ export default class Inventory extends ButtonEvent { } 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)); await interaction.update({ @@ -24,7 +29,8 @@ export default class Inventory extends ButtonEvent { components: [ embed.row ], }); } 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."); } } diff --git a/src/buttonEvents/Reroll.ts b/src/buttonEvents/Reroll.ts index a265bcb..c271a3a 100644 --- a/src/buttonEvents/Reroll.ts +++ b/src/buttonEvents/Reroll.ts @@ -7,6 +7,7 @@ import Inventory from "../database/entities/app/Inventory"; import Config from "../database/entities/app/Config"; import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import path from "path"; +import AppLogger from "../client/appLogger"; export default class Reroll extends ButtonEvent { public override async execute(interaction: ButtonInteraction) { @@ -16,6 +17,8 @@ export default class Reroll extends ButtonEvent { } 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."); return; } @@ -30,6 +33,8 @@ export default class Reroll extends ButtonEvent { await interaction.deferReply(); 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 imageFileName = randomCard.card.path.split("/").pop()!; @@ -51,9 +56,8 @@ export default class Reroll extends ButtonEvent { }); CoreClient.ClaimId = claimId; - } 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})`); } diff --git a/src/buttonEvents/Trade.ts b/src/buttonEvents/Trade.ts index d272d9f..9ce4e56 100644 --- a/src/buttonEvents/Trade.ts +++ b/src/buttonEvents/Trade.ts @@ -3,11 +3,14 @@ import { ButtonEvent } from "../type/buttonEvent"; import { CoreClient } from "../client/client"; import Inventory from "../database/entities/app/Inventory"; import EmbedColours from "../constants/EmbedColours"; +import AppLogger from "../client/appLogger"; export default class Trade extends ButtonEvent { public override async execute(interaction: ButtonInteraction) { const action = interaction.customId.split(" ")[1]; + AppLogger.LogSilly("Button/Trade", `Parameters: action=${action}`); + switch (action) { case "accept": await this.AcceptTrade(interaction); @@ -26,6 +29,8 @@ export default class Trade extends ButtonEvent { const expiry = interaction.customId.split(" ")[6]; 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); if (expiryDate < new Date()) { @@ -140,6 +145,8 @@ export default class Trade extends ButtonEvent { // No need to get expiry date const timeoutId = interaction.customId.split(" ")[7]; + 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"); return; diff --git a/src/client/appLogger.ts b/src/client/appLogger.ts new file mode 100644 index 0000000..c5d022b --- /dev/null +++ b/src/client/appLogger.ts @@ -0,0 +1,65 @@ +import { Logger, createLogger, format, transports } from "winston"; + +export default class AppLogger { + public static Logger: Logger; + + public static InitialiseLogger(logLevel: string, outputToConsole: boolean) { + const customFormat = format.printf(({ level, message, timestamp, label }) => { + return `${timestamp} [${label}] ${level}: ${message}`; + }); + + const logger = createLogger({ + level: logLevel, + format: format.combine( + format.timestamp({ + format: "YYYY-MM-DD HH:mm:ss" + }), + format.errors({ stack: true }), + format.splat(), + customFormat, + ), + defaultMeta: { service: "bot" }, + transports: [ + new transports.File({ filename: "error.log", level: "error" }), + new transports.File({ filename: "combined.log" }), + ], + }); + + if (outputToConsole) { + logger.add(new transports.Console({ + format: format.combine( + format.colorize(), + format.timestamp(), + customFormat, + )})); + } + + AppLogger.Logger = logger; + + AppLogger.LogInfo("AppLogger", `Log Level: ${logLevel}`); + } + + public static LogError(label: string, message: string) { + AppLogger.Logger.error({ label, message }); + } + + public static LogWarn(label: string, message: string) { + AppLogger.Logger.warn({ label, message }); + } + + public static LogInfo(label: string, message: string) { + AppLogger.Logger.info({ label, message }); + } + + public static LogVerbose(label: string, message: string) { + AppLogger.Logger.verbose({ label, message }); + } + + public static LogDebug(label: string, message: string) { + AppLogger.Logger.debug({ label, message }); + } + + public static LogSilly(label: string, message: string) { + AppLogger.Logger.silly({ label, message }); + } +} \ No newline at end of file diff --git a/src/client/client.ts b/src/client/client.ts index ca2fba3..c694950 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -13,6 +13,7 @@ import { Environment } from "../constants/Environment"; import Webhooks from "../webhooks"; import CardMetadataFunction from "../Functions/CardMetadataFunction"; import { SeriesMetadata } from "../contracts/SeriesMetadata"; +import AppLogger from "./appLogger"; export class CoreClient extends Client { private static _commandItems: ICommandItem[]; @@ -44,6 +45,14 @@ export class CoreClient extends Client { super({ intents: intents }); dotenv.config(); + CoreClient.Environment = Number(process.env.BOT_ENV); + + const loglevel = process.env.BOT_LOGLEVEL ?? "info"; + + AppLogger.InitialiseLogger(loglevel, CoreClient.Environment == Environment.Local); + + AppLogger.LogInfo("Client", "Initialising Client"); + CoreClient._commandItems = []; CoreClient._buttonEvents = []; @@ -51,21 +60,24 @@ export class CoreClient extends Client { this._util = new Util(); this._webhooks = new Webhooks(); - CoreClient.Environment = Number(process.env.BOT_ENV); - console.log(`Bot Environment: ${CoreClient.Environment}`); + AppLogger.LogInfo("Client", `Environment: ${CoreClient.Environment}`); CoreClient.AllowDrops = true; } public async start() { 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; } await AppDataSource.initialize() - .then(() => console.log("App Data Source Initialised")) - .catch(err => console.error("Error initialising App Data Source", err)); + .then(() => AppLogger.LogInfo("Client", "App Data Source Initialised")) + .catch(err => { + AppLogger.LogError("Client", "App Data Source Initialisation Failed"); + AppLogger.LogError("Client", err); + throw err; + }); super.on("interactionCreate", this._events.onInteractionCreate); super.on("ready", this._events.onReady); @@ -90,6 +102,8 @@ export class CoreClient extends Client { if ((environment & CoreClient.Environment) == CoreClient.Environment) { CoreClient._commandItems.push(item); + + AppLogger.LogVerbose("Client", `Registered Command: ${name}`); } } @@ -112,6 +126,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Channel Create Event"); } public static RegisterChannelDeleteEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) { @@ -133,6 +149,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Channel Delete Event"); } public static RegisterChannelUpdateEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) { @@ -154,6 +172,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Channel Update Event"); } public static RegisterGuildBanAddEvent(fn: (ban: GuildBan) => void) { @@ -175,6 +195,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Guild Ban Add Event"); } public static RegisterGuildBanRemoveEvent(fn: (channel: GuildBan) => void) { @@ -196,6 +218,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Guild Ban Remove Event"); } public static RegisterGuildCreateEvent(fn: (guild: Guild) => void) { @@ -217,6 +241,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Guild Create Event"); } public static RegisterGuildMemberAddEvent(fn: (member: GuildMember) => void) { @@ -238,6 +264,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Guild Member Add Event"); } public static RegisterGuildMemberRemoveEvent(fn: (member: GuildMember | PartialGuildMember) => void) { @@ -259,6 +287,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Guild Member Remove Event"); } public static GuildMemebrUpdate(fn: (oldMember: GuildMember | PartialGuildMember, newMember: GuildMember) => void) { @@ -280,6 +310,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Guild Member Update Event"); } public static RegisterMessageCreateEvent(fn: (message: Message) => void) { @@ -301,6 +333,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Message Create Event"); } public static RegisterMessageDeleteEvent(fn: (message: Message | PartialMessage) => void) { @@ -322,6 +356,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", "Registered Message Delete Event"); } public static RegisterMessageUpdateEvent(fn: (oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage) => void) { @@ -343,6 +379,8 @@ export class CoreClient extends Client { MessageUpdate: [ fn ], }; } + + AppLogger.LogVerbose("Client", "Registered Message Update Event"); } public static RegisterButtonEvent(buttonId: string, event: ButtonEvent, environment: Environment = Environment.All) { @@ -354,6 +392,8 @@ export class CoreClient extends Client { if ((environment & CoreClient.Environment) == CoreClient.Environment) { CoreClient._buttonEvents.push(item); + + AppLogger.LogVerbose("Client", `Registered Button Event: ${buttonId}`); } } } diff --git a/src/client/events.ts b/src/client/events.ts index db6cfc4..0b82cee 100644 --- a/src/client/events.ts +++ b/src/client/events.ts @@ -1,22 +1,25 @@ import { Interaction } from "discord.js"; import ChatInputCommand from "./interactionCreate/ChatInputCommand"; import Button from "./interactionCreate/Button"; +import AppLogger from "./appLogger"; export class Events { public async onInteractionCreate(interaction: Interaction) { if (!interaction.guildId) return; if (interaction.isChatInputCommand()) { + AppLogger.LogVerbose("Client", `ChatInputCommand: ${interaction.commandName}`); ChatInputCommand.onChatInput(interaction); } if (interaction.isButton()) { + AppLogger.LogVerbose("Client", `Button: ${interaction.customId}`); Button.onButtonClicked(interaction); } } // Emit when bot is logged in and ready to use public onReady() { - console.log("Ready"); + AppLogger.LogInfo("Client", "Ready"); } } diff --git a/src/client/interactionCreate/Button.ts b/src/client/interactionCreate/Button.ts index 6d6a926..b8abbfc 100644 --- a/src/client/interactionCreate/Button.ts +++ b/src/client/interactionCreate/Button.ts @@ -1,5 +1,6 @@ import { ButtonInteraction } from "discord.js"; import { CoreClient } from "../client"; +import AppLogger from "../appLogger"; export default class Button { 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]); if (!item) { + AppLogger.LogVerbose("Button", `Event not found: ${interaction.customId}`); + await interaction.reply("Event not found"); return; } try { + AppLogger.LogDebug("Button", `Executing ${interaction.customId}`); + item.Event.execute(interaction); } 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"); } diff --git a/src/client/interactionCreate/ChatInputCommand.ts b/src/client/interactionCreate/ChatInputCommand.ts index 784ce6e..47f7b37 100644 --- a/src/client/interactionCreate/ChatInputCommand.ts +++ b/src/client/interactionCreate/ChatInputCommand.ts @@ -1,6 +1,7 @@ import { Interaction } from "discord.js"; import { CoreClient } from "../client"; import ICommandItem from "../../contracts/ICommandItem"; +import AppLogger from "../appLogger"; export default class ChatInputCommand { public static async onChatInput(interaction: Interaction) { @@ -13,6 +14,8 @@ export default class ChatInputCommand { if (!itemForServer) { if (!item) { + AppLogger.LogVerbose("ChatInputCommand", `Command not found: ${interaction.commandName}`); + await interaction.reply("Command not found"); return; } @@ -23,9 +26,12 @@ export default class ChatInputCommand { } try { + AppLogger.LogDebug("Command", `Executing ${interaction.commandName}`); + itemToUse.Command.execute(interaction); } 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"); } diff --git a/src/client/util.ts b/src/client/util.ts index ddd84fc..47daa3d 100644 --- a/src/client/util.ts +++ b/src/client/util.ts @@ -1,6 +1,7 @@ import { Client, REST, Routes, SlashCommandBuilder } from "discord.js"; import EventExecutors from "../contracts/EventExecutors"; import { CoreClient } from "./client"; +import AppLogger from "./appLogger"; export class Util { public loadSlashCommands(client: Client) { @@ -29,6 +30,8 @@ export class Util { const rest = new REST({ version: "10" }).setToken(process.env.BOT_TOKEN!); + AppLogger.LogVerbose("Util", `REST PUT: ${globalCommandData.flatMap(x => x.name).join(", ")}`); + rest.put( Routes.applicationCommands(process.env.BOT_CLIENTID!), { @@ -49,6 +52,8 @@ export class Util { if (!client.guilds.cache.has(guild)) continue; + AppLogger.LogVerbose("Util", `REST PUT: ${guild} - ${guildCommandData.flatMap(x => x.name).join(", ")}`); + rest.put( Routes.applicationGuildCommands(process.env.BOT_CLIENTID!, guild), { diff --git a/src/commands/drop.ts b/src/commands/drop.ts index e671e76..7a91042 100644 --- a/src/commands/drop.ts +++ b/src/commands/drop.ts @@ -7,6 +7,7 @@ import Inventory from "../database/entities/app/Inventory"; import Config from "../database/entities/app/Config"; import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import path from "path"; +import AppLogger from "../client/appLogger"; export default class Drop extends Command { constructor() { @@ -24,6 +25,8 @@ export default class Drop extends Command { } 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."); return; } @@ -31,6 +34,8 @@ export default class Drop extends Command { const randomCard = CardDropHelperMetadata.GetRandomCard(); if (!randomCard) { + AppLogger.LogWarn("Commands/Drop", "Unable to fetch card, please try again. (randomCard is null)"); + await interaction.reply("Unable to fetch card, please try again."); return; } @@ -61,7 +66,7 @@ export default class Drop extends Command { CoreClient.ClaimId = claimId; } 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})`); } diff --git a/src/commands/gdrivesync.ts b/src/commands/gdrivesync.ts index c8a393c..b02c873 100644 --- a/src/commands/gdrivesync.ts +++ b/src/commands/gdrivesync.ts @@ -4,6 +4,7 @@ import { ExecException, exec } from "child_process"; import { CoreClient } from "../client/client"; import Config from "../database/entities/app/Config"; import CardMetadataFunction from "../Functions/CardMetadataFunction"; +import AppLogger from "../client/appLogger"; export default class Gdrivesync extends Command { constructor() { @@ -32,19 +33,28 @@ export default class Gdrivesync extends Command { 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) => { 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 Config.SetValue("safemode", "true"); } else { const result = await CardMetadataFunction.Execute(true); if (result.IsSuccess) { + AppLogger.LogInfo("Commands/GDriveSync", "Synced successfully"); + await interaction.editReply("Synced successfully."); CoreClient.AllowDrops = true; await Config.SetValue("safemode", "false"); } else { + AppLogger.LogError("Commands/GDriveSync", `Error while running sync command: ${result.ErrorMessage}`); + await interaction.editReply(`Sync failed \`\`\`${result.ErrorMessage}\`\`\``); } } diff --git a/src/commands/give.ts b/src/commands/give.ts index 7bc24be..5121dda 100644 --- a/src/commands/give.ts +++ b/src/commands/give.ts @@ -4,6 +4,7 @@ import { CoreClient } from "../client/client"; import Config from "../database/entities/app/Config"; import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; import Inventory from "../database/entities/app/Inventory"; +import AppLogger from "../client/appLogger"; export default class Give extends Command { constructor() { @@ -46,6 +47,8 @@ export default class Give extends Command { const cardNumber = interaction.options.get("cardnumber", 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()); if (!card) { diff --git a/src/commands/inventory.ts b/src/commands/inventory.ts index 868b14d..7d77764 100644 --- a/src/commands/inventory.ts +++ b/src/commands/inventory.ts @@ -1,6 +1,7 @@ import { CommandInteraction, SlashCommandBuilder } from "discord.js"; import { Command } from "../type/command"; import InventoryHelper from "../helpers/InventoryHelper"; +import AppLogger from "../client/appLogger"; export default class Inventory extends Command { constructor() { @@ -23,6 +24,8 @@ export default class Inventory extends Command { const page = interaction.options.get("page"); const user = interaction.options.getUser("user") || interaction.user; + AppLogger.LogSilly("Commands/Inventory", `Parameters: page=${page?.value}, user=${user.id}`); + try { let pageNumber = 0; @@ -36,7 +39,9 @@ export default class Inventory extends Command { embeds: [ embed.embed ], components: [ embed.row ], }); - } catch { + } catch (e) { + AppLogger.LogError("Commands/Inventory", e as string); + await interaction.reply("No page for user found."); } } diff --git a/src/commands/resync.ts b/src/commands/resync.ts index 7040d52..f90c96c 100644 --- a/src/commands/resync.ts +++ b/src/commands/resync.ts @@ -2,6 +2,7 @@ import { CacheType, CommandInteraction, PermissionsBitField, SlashCommandBuilder import { Command } from "../type/command"; import Config from "../database/entities/app/Config"; import CardMetadataFunction from "../Functions/CardMetadataFunction"; +import AppLogger from "../client/appLogger"; export default class Resync extends Command { constructor() { @@ -23,10 +24,14 @@ export default class Resync extends Command { return; } + AppLogger.LogInfo("Commands/Resync", "Resyncing database"); + const result = await CardMetadataFunction.Execute(true); if (result) { if (await Config.GetValue("safemode") == "true") { + AppLogger.LogInfo("Commands/Resync", "Resync successful, safe mode disabled"); + await Config.SetValue("safemode", "false"); await interaction.reply("Resynced database and disabled safe mode."); @@ -34,6 +39,8 @@ export default class Resync extends Command { } await interaction.reply("Resynced database."); } else { + AppLogger.LogWarn("Commands/Resync", "Resync failed, safe mode activated"); + await interaction.reply("Resync failed, safe mode has been activated until successful resync."); } } diff --git a/src/commands/trade.ts b/src/commands/trade.ts index 8414ae9..60f9033 100644 --- a/src/commands/trade.ts +++ b/src/commands/trade.ts @@ -3,6 +3,7 @@ import { Command } from "../type/command"; import Inventory from "../database/entities/app/Inventory"; import { CoreClient } from "../client/client"; import EmbedColours from "../constants/EmbedColours"; +import AppLogger from "../client/appLogger"; export default class Trade extends Command { constructor() { @@ -33,6 +34,8 @@ export default class Trade extends Command { const give = interaction.options.get("give")!; 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 receiveItemEntity = await Inventory.FetchOneByCardNumberAndUserId(user.id, receive.value!.toString()); @@ -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) { + AppLogger.LogSilly("Commands/Trade/AutoDecline", `Auto declining trade between ${giveUsername} and ${receiveUsername}`); + const tradeEmbed = new EmbedBuilder() .setTitle("Trade Expired") .setDescription(`Trade initiated between ${receiveUsername} and ${giveUsername}`) diff --git a/src/commands/view.ts b/src/commands/view.ts index 8f89eb4..ce6f9cb 100644 --- a/src/commands/view.ts +++ b/src/commands/view.ts @@ -5,6 +5,7 @@ import { readFileSync } from "fs"; import path from "path"; import Inventory from "../database/entities/app/Inventory"; import CardDropHelperMetadata from "../helpers/CardDropHelperMetadata"; +import AppLogger from "../client/appLogger"; export default class View extends Command { constructor() { @@ -23,6 +24,8 @@ export default class View extends Command { public override async execute(interaction: CommandInteraction) { const cardNumber = interaction.options.get("cardnumber"); + AppLogger.LogSilly("Commands/View", `Parameters: cardNumber=${cardNumber?.value}`); + if (!cardNumber || !cardNumber.value) { await interaction.reply("Card number is required."); return; @@ -46,6 +49,8 @@ export default class View extends Command { try { image = readFileSync(path.join(process.env.DATA_DIR!, "cards", card.path)); } catch { + AppLogger.LogError("Commands/View", `Unable to fetch image for card ${card.id}.`); + await interaction.reply(`Unable to fetch image for card ${card.id}.`); return; } @@ -65,7 +70,7 @@ export default class View extends Command { files: [ attachment ], }); } catch (e) { - console.error(e); + AppLogger.LogError("Commands/View", `Error sending view for card ${card.id}: ${e}`); 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}.`); diff --git a/src/helpers/CardDropHelperMetadata.ts b/src/helpers/CardDropHelperMetadata.ts index 762648d..27a0d04 100644 --- a/src/helpers/CardDropHelperMetadata.ts +++ b/src/helpers/CardDropHelperMetadata.ts @@ -3,6 +3,7 @@ import { CardRarity, CardRarityToColour, CardRarityToString } from "../constants import CardRarityChances from "../constants/CardRarityChances"; import { CardMetadata, DropResult } from "../contracts/SeriesMetadata"; import { CoreClient } from "../client/client"; +import AppLogger from "../client/appLogger"; export default class CardDropHelperMetadata { public static GetRandomCard(): DropResult | undefined { @@ -23,10 +24,14 @@ export default class CardDropHelperMetadata { const randomCard = this.GetRandomCardByRarity(cardRarity); + AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCard", `Random card: ${randomCard?.card.id} ${randomCard?.card.name}`); + return randomCard; } public static GetRandomCardByRarity(rarity: CardRarity): DropResult | undefined { + AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCardByRarity", `Parameters: rarity=${rarity}`); + const allCards = CoreClient.Cards .flatMap(x => x.cards) .filter(x => x.type == rarity); @@ -38,9 +43,13 @@ export default class CardDropHelperMetadata { .find(x => x.cards.includes(card)); if (!series) { + AppLogger.LogWarn("CardDropHelperMetadata/GetRandomCardByRarity", `Series not found for card ${card.id}`); + return undefined; } + AppLogger.LogSilly("CardDropHelperMetadata/GetRandomCardByRarity", `Random card: ${card.id} ${card.name}`); + return { series: series, card: card, @@ -48,14 +57,20 @@ export default class CardDropHelperMetadata { } public static GetCardByCardNumber(cardNumber: string): CardMetadata | undefined { + AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Parameters: cardNumber=${cardNumber}`); + const card = CoreClient.Cards .flatMap(x => x.cards) .find(x => x.id == cardNumber); + AppLogger.LogSilly("CardDropHelperMetadata/GetCardByCardNumber", `Card: ${card?.id} ${card?.name}`); + return card; } public static GenerateDropEmbed(drop: DropResult, quantityClaimed: number, imageFileName: string): EmbedBuilder { + AppLogger.LogSilly("CardDropHelperMetadata/GenerateDropEmbed", `Parameters: drop=${drop.card.id}, quantityClaimed=${quantityClaimed}, imageFileName=${imageFileName}`); + let description = ""; description += `Series: ${drop.series.name}\n`; description += `Claimed: ${quantityClaimed}\n`; @@ -69,6 +84,8 @@ export default class CardDropHelperMetadata { } public static GenerateDropButtons(drop: DropResult, claimId: string, userId: string): ActionRowBuilder { + AppLogger.LogSilly("CardDropHelperMetadata/GenerateDropButtons", `Parameters: drop=${drop.card.id}, claimId=${claimId}, userId=${userId}`); + return new ActionRowBuilder() .addComponents( new ButtonBuilder() diff --git a/src/helpers/InventoryHelper.ts b/src/helpers/InventoryHelper.ts index 1103694..3b0c40a 100644 --- a/src/helpers/InventoryHelper.ts +++ b/src/helpers/InventoryHelper.ts @@ -4,6 +4,7 @@ import { CoreClient } from "../client/client"; import EmbedColours from "../constants/EmbedColours"; import { CardRarity, CardRarityToString } from "../constants/CardRarity"; import cloneDeep from "clone-deep"; +import AppLogger from "../client/appLogger"; interface InventoryPage { id: number, @@ -21,6 +22,8 @@ interface InventoryPageCards { export default class InventoryHelper { public static async GenerateInventoryPage(username: string, userid: string, page: number): Promise<{ embed: EmbedBuilder, row: ActionRowBuilder }> { + AppLogger.LogSilly("Helpers/InventoryHelper", `Parameters: username=${username}, userid=${userid}, page=${page}`); + const cardsPerPage = 15; const inventory = await Inventory.FetchAllByUserId(userid); @@ -73,7 +76,7 @@ export default class InventoryHelper { const currentPage = pages[page]; if (!currentPage) { - console.error("Unable to find page"); + AppLogger.LogError("Helpers/InventoryHelper", "Unable to find page"); return Promise.reject("Unable to find page"); } diff --git a/src/hooks/ReloadDB.ts b/src/hooks/ReloadDB.ts index 0f1c026..9d99df7 100644 --- a/src/hooks/ReloadDB.ts +++ b/src/hooks/ReloadDB.ts @@ -1,8 +1,9 @@ import { Request, Response } from "express"; import CardMetadataFunction from "../Functions/CardMetadataFunction"; +import AppLogger from "../client/appLogger"; export default async function ReloadDB(req: Request, res: Response) { - console.log("Reloading Card DB..."); + AppLogger.LogInfo("Hooks/ReloadDB", "Reloading Card DB..."); await CardMetadataFunction.Execute(); diff --git a/src/webhooks.ts b/src/webhooks.ts index cccb598..0b99816 100644 --- a/src/webhooks.ts +++ b/src/webhooks.ts @@ -1,6 +1,7 @@ import bodyParser from "body-parser"; import express, { Application } from "express"; import ReloadDB from "./hooks/ReloadDB"; +import AppLogger from "./client/appLogger"; export default class Webhooks { private app: Application; @@ -24,7 +25,7 @@ export default class Webhooks { private setupListen() { this.app.listen(this.port, () => { - console.log(`API listening on port ${this.port}`); + AppLogger.LogInfo("Webhooks", `API listening on port ${this.port}`); }); } } \ No newline at end of file