From 0677f8feb846c427de11960ecfa9f89c94f5c046 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Wed, 28 Feb 2024 17:58:41 +0000 Subject: [PATCH 1/6] Install winston --- package-lock.json | 222 +++++++++++++++++++++++++++++++++++++++- package.json | 3 +- src/client/appLogger.ts | 63 ++++++++++++ src/client/client.ts | 5 + 4 files changed, 291 insertions(+), 2 deletions(-) create mode 100644 src/client/appLogger.ts diff --git a/package-lock.json b/package-lock.json index ee09231..9df3a5e 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", @@ -3604,6 +3633,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", @@ -3618,6 +3656,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", @@ -3628,6 +3675,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, @@ -4233,6 +4302,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", @@ -4823,6 +4897,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, @@ -4915,6 +4994,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", @@ -7111,6 +7195,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, @@ -7611,6 +7700,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, @@ -8726,6 +8836,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", @@ -9943,6 +10061,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" @@ -10090,6 +10216,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" @@ -10279,6 +10418,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", @@ -10627,6 +10774,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", @@ -10712,6 +10864,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", @@ -11303,6 +11463,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 732ab99..b503360 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" }, "resolutions": {}, "devDependencies": { diff --git a/src/client/appLogger.ts b/src/client/appLogger.ts new file mode 100644 index 0000000..4127e93 --- /dev/null +++ b/src/client/appLogger.ts @@ -0,0 +1,63 @@ +import { LogLevel } from "typeorm"; +import { Logger, createLogger, format, transports } from "winston"; +import { CoreClient } from "./client"; + +export default class AppLogger { + public static InitialiseLogger(logLevel: LogLevel, outputToConsole: boolean): Logger { + 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, + )})); + } + + return logger; + } + + public static LogError(label: string, message: string) { + CoreClient.Logger.error({ label, message }); + } + + public static LogWarn(label: string, message: string) { + CoreClient.Logger.warn({ label, message }); + } + + public static LogInfo(label: string, message: string) { + CoreClient.Logger.info({ label, message }); + } + + public static LogVerbose(label: string, message: string) { + CoreClient.Logger.verbose({ label, message }); + } + + public static LogDebug(label: string, message: string) { + CoreClient.Logger.debug({ label, message }); + } + + public static LogSilly(label: string, message: string) { + CoreClient.Logger.silly({ label, message }); + } +} \ No newline at end of file diff --git a/src/client/client.ts b/src/client/client.ts index ca2fba3..16056bd 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -13,6 +13,8 @@ import { Environment } from "../constants/Environment"; import Webhooks from "../webhooks"; import CardMetadataFunction from "../Functions/CardMetadataFunction"; import { SeriesMetadata } from "../contracts/SeriesMetadata"; +import { Logger } from "winston"; +import AppLogger from "./appLogger"; export class CoreClient extends Client { private static _commandItems: ICommandItem[]; @@ -27,6 +29,7 @@ export class CoreClient extends Client { public static Environment: Environment; public static AllowDrops: boolean; public static Cards: SeriesMetadata[]; + public static Logger: Logger; public static get commandItems(): ICommandItem[] { return this._commandItems; @@ -44,6 +47,8 @@ export class CoreClient extends Client { super({ intents: intents }); dotenv.config(); + CoreClient.Logger = AppLogger.InitialiseLogger("info", true); + CoreClient._commandItems = []; CoreClient._buttonEvents = []; -- 2.43.4 From 408874859efa4d9308dcb94d842e8193d14a2f37 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Wed, 28 Feb 2024 18:10:27 +0000 Subject: [PATCH 2/6] Allow log levels to be configurable --- .dev.env | 1 + .prod.env | 1 + .stage.env | 1 + src/client/appLogger.ts | 3 +-- src/client/client.ts | 5 +++-- 5 files changed, 7 insertions(+), 4 deletions(-) diff --git a/.dev.env b/.dev.env index b61d698..c02e9db 100644 --- a/.dev.env +++ b/.dev.env @@ -12,6 +12,7 @@ BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=682942374040961060 BOT_ENV=4 +BOT_VERBOSE=false BOT_ADMINS=147392775707426816,887272961504071690 ABOUT_FUNDING= diff --git a/.prod.env b/.prod.env index a3d5a1e..b2e9e61 100644 --- a/.prod.env +++ b/.prod.env @@ -12,6 +12,7 @@ BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=1093810443589529631 BOT_ENV=1 +BOT_VERBOSE=false BOT_ADMINS=147392775707426816,887272961504071690 ABOUT_FUNDING= diff --git a/.stage.env b/.stage.env index c2f65e6..d10e8bf 100644 --- a/.stage.env +++ b/.stage.env @@ -12,6 +12,7 @@ BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=1147976642942214235 BOT_ENV=2 +BOT_VERBOSE=false BOT_ADMINS=147392775707426816,887272961504071690 ABOUT_FUNDING= diff --git a/src/client/appLogger.ts b/src/client/appLogger.ts index 4127e93..b06627b 100644 --- a/src/client/appLogger.ts +++ b/src/client/appLogger.ts @@ -1,9 +1,8 @@ -import { LogLevel } from "typeorm"; import { Logger, createLogger, format, transports } from "winston"; import { CoreClient } from "./client"; export default class AppLogger { - public static InitialiseLogger(logLevel: LogLevel, outputToConsole: boolean): Logger { + public static InitialiseLogger(logLevel: string, outputToConsole: boolean): Logger { const customFormat = format.printf(({ level, message, timestamp, label }) => { return `${timestamp} [${label}] ${level}: ${message}`; }); diff --git a/src/client/client.ts b/src/client/client.ts index 16056bd..b31cd3d 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -47,7 +47,9 @@ export class CoreClient extends Client { super({ intents: intents }); dotenv.config(); - CoreClient.Logger = AppLogger.InitialiseLogger("info", true); + CoreClient.Environment = Number(process.env.BOT_ENV); + + CoreClient.Logger = AppLogger.InitialiseLogger(process.env.BOT_VERBOSE == "true" ? "verbose" : "info", CoreClient.Environment == Environment.Local); CoreClient._commandItems = []; CoreClient._buttonEvents = []; @@ -56,7 +58,6 @@ 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}`); CoreClient.AllowDrops = true; -- 2.43.4 From 4a0050eb7054feda43cc62c106f7f0a15d1a0e6f Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Tue, 12 Mar 2024 17:42:02 +0000 Subject: [PATCH 3/6] WIP: Start of logging --- src/buttonEvents/Claim.ts | 3 ++ src/buttonEvents/Inventory.ts | 8 +++- src/buttonEvents/Reroll.ts | 8 +++- src/buttonEvents/Trade.ts | 7 +++ src/client/appLogger.ts | 19 ++++---- src/client/client.ts | 46 ++++++++++++++++--- src/client/events.ts | 5 +- src/client/interactionCreate/Button.ts | 8 +++- .../interactionCreate/ChatInputCommand.ts | 8 +++- src/client/util.ts | 5 ++ src/commands/drop.ts | 5 +- src/commands/gdrivesync.ts | 10 ++++ src/commands/give.ts | 3 ++ src/commands/inventory.ts | 3 ++ src/commands/resync.ts | 5 ++ src/commands/trade.ts | 5 ++ src/commands/view.ts | 7 ++- 17 files changed, 131 insertions(+), 24 deletions(-) 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 index b06627b..e865e48 100644 --- a/src/client/appLogger.ts +++ b/src/client/appLogger.ts @@ -1,8 +1,9 @@ import { Logger, createLogger, format, transports } from "winston"; -import { CoreClient } from "./client"; 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 }) => { 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) { - CoreClient.Logger.error({ label, message }); + AppLogger.Logger.error({ label, message }); } public static LogWarn(label: string, message: string) { - CoreClient.Logger.warn({ label, message }); + AppLogger.Logger.warn({ label, message }); } public static LogInfo(label: string, message: string) { - CoreClient.Logger.info({ label, message }); + AppLogger.Logger.info({ label, message }); } public static LogVerbose(label: string, message: string) { - CoreClient.Logger.verbose({ label, message }); + AppLogger.Logger.verbose({ label, message }); } public static LogDebug(label: string, message: string) { - CoreClient.Logger.debug({ label, message }); + AppLogger.Logger.debug({ label, message }); } public static LogSilly(label: string, message: string) { - CoreClient.Logger.silly({ label, message }); + AppLogger.Logger.silly({ label, message }); } } \ No newline at end of file diff --git a/src/client/client.ts b/src/client/client.ts index b31cd3d..92fbc5e 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -13,7 +13,6 @@ import { Environment } from "../constants/Environment"; import Webhooks from "../webhooks"; import CardMetadataFunction from "../Functions/CardMetadataFunction"; import { SeriesMetadata } from "../contracts/SeriesMetadata"; -import { Logger } from "winston"; import AppLogger from "./appLogger"; export class CoreClient extends Client { @@ -29,7 +28,6 @@ export class CoreClient extends Client { public static Environment: Environment; public static AllowDrops: boolean; public static Cards: SeriesMetadata[]; - public static Logger: Logger; public static get commandItems(): ICommandItem[] { return this._commandItems; @@ -49,7 +47,9 @@ export class CoreClient extends Client { 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._buttonEvents = []; @@ -58,20 +58,24 @@ export class CoreClient extends Client { this._util = new Util(); this._webhooks = new Webhooks(); - 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); @@ -96,6 +100,8 @@ export class CoreClient extends Client { if ((environment & CoreClient.Environment) == CoreClient.Environment) { CoreClient._commandItems.push(item); + + AppLogger.LogVerbose("Client", `Registered Command: ${name}`); } } @@ -118,6 +124,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", `Registered Channel Create Event`); } public static RegisterChannelDeleteEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) { @@ -139,6 +147,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", `Registered Channel Delete Event`); } public static RegisterChannelUpdateEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) { @@ -160,6 +170,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", `Registered Channel Update Event`); } public static RegisterGuildBanAddEvent(fn: (ban: GuildBan) => void) { @@ -181,6 +193,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", `Registered Guild Ban Add Event`); } public static RegisterGuildBanRemoveEvent(fn: (channel: GuildBan) => void) { @@ -202,6 +216,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", `Registered Guild Ban Remove Event`); } public static RegisterGuildCreateEvent(fn: (guild: Guild) => void) { @@ -223,6 +239,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", `Registered Guild Create Event`); } public static RegisterGuildMemberAddEvent(fn: (member: GuildMember) => void) { @@ -244,6 +262,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", `Registered Guild Member Add Event`); } public static RegisterGuildMemberRemoveEvent(fn: (member: GuildMember | PartialGuildMember) => void) { @@ -265,6 +285,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) { @@ -286,6 +308,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", `Registered Guild Member Update Event`); } public static RegisterMessageCreateEvent(fn: (message: Message) => void) { @@ -307,6 +331,8 @@ export class CoreClient extends Client { MessageUpdate: [], }; } + + AppLogger.LogVerbose("Client", `Registered Message Create Event`); } public static RegisterMessageDeleteEvent(fn: (message: Message | PartialMessage) => void) { @@ -328,6 +354,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) { @@ -349,6 +377,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) { @@ -360,6 +390,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..65b2b3e 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; } @@ -61,7 +64,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..6c5ee51 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; diff --git a/src/commands/resync.ts b/src/commands/resync.ts index 7040d52..887208f 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,6 +24,8 @@ export default class Resync extends Command { return; } + AppLogger.LogInfo("Commands/Resync", "Resyncing database"); + const result = await CardMetadataFunction.Execute(true); if (result) { @@ -34,6 +37,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}.`); -- 2.43.4 From efc0186db23600daa39a117a7ed1006139ecdb8f Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Tue, 12 Mar 2024 17:56:43 +0000 Subject: [PATCH 4/6] Add logger to code logic --- src/Functions/CardMetadataFunction.ts | 22 +++++++++++++++------- src/commands/drop.ts | 2 ++ src/commands/inventory.ts | 4 +++- src/commands/resync.ts | 2 ++ src/helpers/CardDropHelperMetadata.ts | 17 +++++++++++++++++ src/helpers/InventoryHelper.ts | 5 ++++- src/hooks/ReloadDB.ts | 3 ++- src/webhooks.ts | 3 ++- 8 files changed, 47 insertions(+), 11 deletions(-) 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/commands/drop.ts b/src/commands/drop.ts index 65b2b3e..7a91042 100644 --- a/src/commands/drop.ts +++ b/src/commands/drop.ts @@ -34,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; } diff --git a/src/commands/inventory.ts b/src/commands/inventory.ts index 6c5ee51..7d77764 100644 --- a/src/commands/inventory.ts +++ b/src/commands/inventory.ts @@ -39,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 887208f..f90c96c 100644 --- a/src/commands/resync.ts +++ b/src/commands/resync.ts @@ -30,6 +30,8 @@ export default class Resync extends Command { 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."); 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 -- 2.43.4 From 7a17c1685eaeb3168efa25849e7ab840c1c24d91 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Wed, 13 Mar 2024 18:03:48 +0000 Subject: [PATCH 5/6] Create configurable log level --- .dev.env | 2 +- .prod.env | 2 +- .stage.env | 2 +- src/client/appLogger.ts | 2 ++ src/client/client.ts | 4 +++- 5 files changed, 8 insertions(+), 4 deletions(-) diff --git a/.dev.env b/.dev.env index c02e9db..2af0ac7 100644 --- a/.dev.env +++ b/.dev.env @@ -12,7 +12,7 @@ BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=682942374040961060 BOT_ENV=4 -BOT_VERBOSE=false +BOT_LOGLEVEL=info BOT_ADMINS=147392775707426816,887272961504071690 ABOUT_FUNDING= diff --git a/.prod.env b/.prod.env index b2e9e61..c623491 100644 --- a/.prod.env +++ b/.prod.env @@ -12,7 +12,7 @@ BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=1093810443589529631 BOT_ENV=1 -BOT_VERBOSE=false +BOT_LOGLEVEL=info BOT_ADMINS=147392775707426816,887272961504071690 ABOUT_FUNDING= diff --git a/.stage.env b/.stage.env index d10e8bf..6473f09 100644 --- a/.stage.env +++ b/.stage.env @@ -12,7 +12,7 @@ BOT_AUTHOR=Vylpes BOT_OWNERID=147392775707426816 BOT_CLIENTID=1147976642942214235 BOT_ENV=2 -BOT_VERBOSE=false +BOT_LOGLEVEL=info BOT_ADMINS=147392775707426816,887272961504071690 ABOUT_FUNDING= diff --git a/src/client/appLogger.ts b/src/client/appLogger.ts index e865e48..f65faa8 100644 --- a/src/client/appLogger.ts +++ b/src/client/appLogger.ts @@ -35,6 +35,8 @@ export default class AppLogger { } AppLogger.Logger = logger; + + AppLogger.LogInfo('AppLogger', `Log Level: ${logLevel}`); } public static LogError(label: string, message: string) { diff --git a/src/client/client.ts b/src/client/client.ts index 92fbc5e..55b934a 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -47,7 +47,9 @@ export class CoreClient extends Client { CoreClient.Environment = Number(process.env.BOT_ENV); - AppLogger.InitialiseLogger(process.env.BOT_VERBOSE == "true" ? "verbose" : "info", CoreClient.Environment == Environment.Local); + const loglevel = process.env.BOT_LOGLEVEL ?? "info"; + + AppLogger.InitialiseLogger(loglevel, CoreClient.Environment == Environment.Local); AppLogger.LogInfo("Client", "Initialising Client"); -- 2.43.4 From f812185937696f874c9b30fa7f0ee6344ad412c4 Mon Sep 17 00:00:00 2001 From: Ethan Lane Date: Wed, 13 Mar 2024 18:04:18 +0000 Subject: [PATCH 6/6] Fix linting issues --- src/client/appLogger.ts | 12 ++++++------ src/client/client.ts | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/client/appLogger.ts b/src/client/appLogger.ts index f65faa8..c5d022b 100644 --- a/src/client/appLogger.ts +++ b/src/client/appLogger.ts @@ -12,16 +12,16 @@ export default class AppLogger { level: logLevel, format: format.combine( format.timestamp({ - format: 'YYYY-MM-DD HH:mm:ss' + format: "YYYY-MM-DD HH:mm:ss" }), format.errors({ stack: true }), format.splat(), customFormat, ), - defaultMeta: { service: 'bot' }, + defaultMeta: { service: "bot" }, transports: [ - new transports.File({ filename: 'error.log', level: 'error' }), - new transports.File({ filename: 'combined.log' }), + new transports.File({ filename: "error.log", level: "error" }), + new transports.File({ filename: "combined.log" }), ], }); @@ -31,12 +31,12 @@ export default class AppLogger { format.colorize(), format.timestamp(), customFormat, - )})); + )})); } AppLogger.Logger = logger; - AppLogger.LogInfo('AppLogger', `Log Level: ${logLevel}`); + AppLogger.LogInfo("AppLogger", `Log Level: ${logLevel}`); } public static LogError(label: string, message: string) { diff --git a/src/client/client.ts b/src/client/client.ts index 55b934a..c694950 100644 --- a/src/client/client.ts +++ b/src/client/client.ts @@ -127,7 +127,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Channel Create Event`); + AppLogger.LogVerbose("Client", "Registered Channel Create Event"); } public static RegisterChannelDeleteEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) { @@ -150,7 +150,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Channel Delete Event`); + AppLogger.LogVerbose("Client", "Registered Channel Delete Event"); } public static RegisterChannelUpdateEvent(fn: (channel: DMChannel | NonThreadGuildBasedChannel) => void) { @@ -173,7 +173,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Channel Update Event`); + AppLogger.LogVerbose("Client", "Registered Channel Update Event"); } public static RegisterGuildBanAddEvent(fn: (ban: GuildBan) => void) { @@ -196,7 +196,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Guild Ban Add Event`); + AppLogger.LogVerbose("Client", "Registered Guild Ban Add Event"); } public static RegisterGuildBanRemoveEvent(fn: (channel: GuildBan) => void) { @@ -219,7 +219,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Guild Ban Remove Event`); + AppLogger.LogVerbose("Client", "Registered Guild Ban Remove Event"); } public static RegisterGuildCreateEvent(fn: (guild: Guild) => void) { @@ -242,7 +242,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Guild Create Event`); + AppLogger.LogVerbose("Client", "Registered Guild Create Event"); } public static RegisterGuildMemberAddEvent(fn: (member: GuildMember) => void) { @@ -265,7 +265,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Guild Member Add Event`); + AppLogger.LogVerbose("Client", "Registered Guild Member Add Event"); } public static RegisterGuildMemberRemoveEvent(fn: (member: GuildMember | PartialGuildMember) => void) { @@ -288,7 +288,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Guild Member Remove Event`); + AppLogger.LogVerbose("Client", "Registered Guild Member Remove Event"); } public static GuildMemebrUpdate(fn: (oldMember: GuildMember | PartialGuildMember, newMember: GuildMember) => void) { @@ -311,7 +311,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Guild Member Update Event`); + AppLogger.LogVerbose("Client", "Registered Guild Member Update Event"); } public static RegisterMessageCreateEvent(fn: (message: Message) => void) { @@ -334,7 +334,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Message Create Event`); + AppLogger.LogVerbose("Client", "Registered Message Create Event"); } public static RegisterMessageDeleteEvent(fn: (message: Message | PartialMessage) => void) { @@ -357,7 +357,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Message Delete Event`); + AppLogger.LogVerbose("Client", "Registered Message Delete Event"); } public static RegisterMessageUpdateEvent(fn: (oldMessage: Message | PartialMessage, newMessage: Message | PartialMessage) => void) { @@ -380,7 +380,7 @@ export class CoreClient extends Client { }; } - AppLogger.LogVerbose("Client", `Registered Message Update Event`); + AppLogger.LogVerbose("Client", "Registered Message Update Event"); } public static RegisterButtonEvent(buttonId: string, event: ButtonEvent, environment: Environment = Environment.All) { -- 2.43.4