diff --git a/legacy/src/core/services/logger.service.ts b/legacy/src/core/services/logger.service.ts deleted file mode 100644 index 58ab524..0000000 --- a/legacy/src/core/services/logger.service.ts +++ /dev/null @@ -1,34 +0,0 @@ -import path from 'path'; -import winston from 'winston'; - -import LogLevel from '../../../../src/types/LogLevel'; - -import ConfigService from './config.service'; - -export default class LoggerService { - private _logger: winston.Logger; - - constructor(private _configService: ConfigService) { - this._logger = winston.createLogger({ - level: this._configService.get('LOG_LEVEL'), - format: winston.format.json(), - transports: [ - new winston.transports.File({ - filename: path.resolve(__dirname, '../../', 'logs', 'error.log'), - level: 'error', - }), - new winston.transports.Console({ - format: winston.format.simple(), - }), - ], - }); - } - - log(level: LogLevel, message: string, payload?: unknown): void { - if (this._logger[level]) { - this._logger.log(level, message, payload); - } else { - this._logger.info(message, payload); - } - } -} diff --git a/package.json b/package.json index 5a81818..1df1ade 100644 --- a/package.json +++ b/package.json @@ -19,7 +19,8 @@ "discord.js": "^14.15.3", "dotenv": "^16.4.5", "mongodb": "^6.8.0", - "nanoid": "^5.0.7" + "nanoid": "^5.0.7", + "winston": "^3.13.1" }, "nodemonConfig": { "ignore": [ diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5564153..27ea654 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -20,6 +20,9 @@ importers: nanoid: specifier: ^5.0.7 version: 5.0.7 + winston: + specifier: ^3.13.1 + version: 3.13.1 devDependencies: '@eslint/js': specifier: ^9.8.0 @@ -45,6 +48,13 @@ importers: packages: + '@colors/colors@1.6.0': + resolution: {integrity: sha512-Ir+AOibqzrIsL6ajt3Rz3LskB7OiMVHqltZmspbW/TJuTVuyOMirVqAkjfY6JISiLHgyNqicAC8AyHHGzNd/dA==} + engines: {node: '>=0.1.90'} + + '@dabh/diagnostics@2.0.3': + resolution: {integrity: sha512-hrlQOIi7hAfzsMqlGSFyVucrx38O+j6wiGOf//H2ecvIEqYN4ADBSS2iLMh5UFyDunCNniUIPk/q3riFv45xRA==} + '@discordjs/builders@1.8.2': resolution: {integrity: sha512-6wvG3QaCjtMu0xnle4SoOIeFB4y6fKMN6WZfy3BMKJdQQtPLik8KGzDwBVL/+wTtcE/ZlFjgEk74GublyEVZ7g==} engines: {node: '>=16.11.0'} @@ -282,6 +292,9 @@ packages: '@types/tough-cookie@4.0.5': resolution: {integrity: sha512-/Ad8+nIOV7Rl++6f1BdKxFSMgmoqEoYbHRpPcx3JEfv8VRsQe9Z4mCXeJBzxs7mbHY/XOZZuXlRNfhpVPbs6ZA==} + '@types/triple-beam@1.3.5': + resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} + '@types/webidl-conversions@7.0.3': resolution: {integrity: sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==} @@ -392,6 +405,9 @@ packages: resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} engines: {node: '>=8'} + async@3.2.5: + resolution: {integrity: sha512-baNZyqaaLhyLVKm/DlvdW051MSgO6b8eVfIezl9E5PqWxFgzLm/wQntEW4zOytVburDEr0JlALEpdOFwvErLsg==} + asynckit@0.4.0: resolution: {integrity: sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==} @@ -428,13 +444,28 @@ packages: resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} engines: {node: '>= 8.10.0'} + color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + color-convert@2.0.1: resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} engines: {node: '>=7.0.0'} + color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + color-name@1.1.4: resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + color-string@1.9.1: + resolution: {integrity: sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==} + + color@3.2.1: + resolution: {integrity: sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==} + + colorspace@1.1.4: + resolution: {integrity: sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w==} + combined-stream@1.0.8: resolution: {integrity: sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==} engines: {node: '>= 0.8'} @@ -505,6 +536,9 @@ packages: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} + enabled@2.0.0: + resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} + entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} @@ -567,6 +601,9 @@ packages: fastq@1.17.1: resolution: {integrity: sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==} + fecha@4.2.3: + resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} + file-entry-cache@6.0.1: resolution: {integrity: sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==} engines: {node: ^10.12.0 || >=12.0.0} @@ -586,6 +623,9 @@ packages: flatted@3.3.1: resolution: {integrity: sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==} + fn.name@1.1.0: + resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} + form-data@4.0.0: resolution: {integrity: sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==} engines: {node: '>= 6'} @@ -670,6 +710,9 @@ packages: inherits@2.0.4: resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + is-arrayish@0.3.2: + resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-binary-path@2.1.0: resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} engines: {node: '>=8'} @@ -693,6 +736,10 @@ packages: is-potential-custom-element-name@1.0.1: resolution: {integrity: sha512-bCYeRA2rVibKZd+s2625gGnGF/t7DSqDs4dP7CrLA1m7jKWz6pps0LpYLJN8Q64HtmPKJ1hrN3nzPNKFEKOUiQ==} + is-stream@2.0.1: + resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} + engines: {node: '>=8'} + isexe@2.0.0: resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} @@ -721,6 +768,9 @@ packages: keyv@4.5.4: resolution: {integrity: sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==} + kuler@2.0.0: + resolution: {integrity: sha512-Xq9nH7KlWZmXAtodXDDRE7vs6DU1gTU8zYDHDiWLSip45Egwq3plLHzPn27NgvzL2r1LMPC1vdqh98sQxtqj4A==} + levn@0.4.1: resolution: {integrity: sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==} engines: {node: '>= 0.8.0'} @@ -738,6 +788,10 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + logform@2.6.1: + resolution: {integrity: sha512-CdaO738xRapbKIMVn2m4F6KTj4j7ooJ8POVnebSgKo3KBz5axNXRAL7ZdRjIV6NOr2Uf4vjtRkxrFETOioCqSA==} + engines: {node: '>= 12.0.0'} + magic-bytes.js@1.10.0: resolution: {integrity: sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ==} @@ -823,6 +877,9 @@ packages: once@1.4.0: resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + one-time@1.0.0: + resolution: {integrity: sha512-5DXOiRKwuSEcQ/l0kGCF6Q3jcADFv5tSmRaJck/OqkVFcOzutB134KRSfF0xDrL39MNnqxbHBbUUcjZIhTgb2g==} + optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -882,6 +939,10 @@ packages: queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} + readable-stream@3.6.2: + resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} + engines: {node: '>= 6'} + readdirp@3.6.0: resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} engines: {node: '>=8.10.0'} @@ -914,6 +975,13 @@ packages: run-parallel@1.2.0: resolution: {integrity: sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==} + safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + + safe-stable-stringify@2.4.3: + resolution: {integrity: sha512-e2bDA2WJT0wxseVd4lsDP4+3ONX6HpMXQa1ZhFQ7SU+GjvORCmShbCMltrtIDfkYhVHrOcPtj+KhmDBdPdZD1g==} + engines: {node: '>=10'} + safer-buffer@2.1.2: resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} @@ -934,6 +1002,9 @@ packages: resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} engines: {node: '>=8'} + simple-swizzle@0.2.2: + resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} + simple-update-notifier@2.0.0: resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} engines: {node: '>=10'} @@ -945,9 +1016,15 @@ packages: sparse-bitfield@3.0.3: resolution: {integrity: sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==} + stack-trace@0.0.10: + resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} + stream-transform@3.3.2: resolution: {integrity: sha512-v64PUnPy9Qw94NGuaEMo+9RHQe4jTBYf+NkTtqkCgeuiNo8NlL0LtLR7fkKWNVFtp3RhIm5Dlxkgm5uz7TDimQ==} + string_decoder@1.3.0: + resolution: {integrity: sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==} + strip-ansi@6.0.1: resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} engines: {node: '>=8'} @@ -967,6 +1044,9 @@ packages: symbol-tree@3.2.4: resolution: {integrity: sha512-9QNk5KwDF+Bvz+PyObkmSYjI5ksVUYtjW7AU22r2NKcfLJcXp96hkDWU3+XndOsUb+AQ9QhfzfCT2O+CNWT5Tw==} + text-hex@1.0.0: + resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} + text-table@0.2.0: resolution: {integrity: sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==} @@ -990,6 +1070,10 @@ packages: resolution: {integrity: sha512-tk2G5R2KRwBd+ZN0zaEXpmzdKyOYksXwywulIX95MBODjSzMIuQnQ3m8JxgbhnL1LeVo7lqQKsYa1O3Htl7K5g==} engines: {node: '>=18'} + triple-beam@1.4.1: + resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} + engines: {node: '>= 14.0.0'} + ts-api-utils@1.3.0: resolution: {integrity: sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==} engines: {node: '>=16'} @@ -1050,6 +1134,9 @@ packages: url-parse@1.5.10: resolution: {integrity: sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==} + util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + w3c-xmlserializer@5.0.0: resolution: {integrity: sha512-o8qghlI8NZHU1lLPrpi2+Uq7abh4GGPpYANlalzWxyWteJOCsr/P+oPBA49TOLu5FTZO4d3F9MnWJfiMo4BkmA==} engines: {node: '>=18'} @@ -1079,6 +1166,14 @@ packages: engines: {node: '>= 8'} hasBin: true + winston-transport@4.7.1: + resolution: {integrity: sha512-wQCXXVgfv/wUPOfb2x0ruxzwkcZfxcktz6JIMUaPLmcNhO4bZTwA/WtDWK74xV3F2dKu8YadrFv0qhwYjVEwhA==} + engines: {node: '>= 12.0.0'} + + winston@3.13.1: + resolution: {integrity: sha512-SvZit7VFNvXRzbqGHsv5KSmgbEYR5EiQfDAL9gxYkRqa934Hnk++zze0wANKtMHcy/gI4W/3xmSDwlhf865WGw==} + engines: {node: '>= 12.0.0'} + word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -1111,6 +1206,14 @@ packages: snapshots: + '@colors/colors@1.6.0': {} + + '@dabh/diagnostics@2.0.3': + dependencies: + colorspace: 1.1.4 + enabled: 2.0.0 + kuler: 2.0.0 + '@discordjs/builders@1.8.2': dependencies: '@discordjs/formatters': 0.4.0 @@ -1301,6 +1404,8 @@ snapshots: '@types/tough-cookie@4.0.5': {} + '@types/triple-beam@1.3.5': {} + '@types/webidl-conversions@7.0.3': {} '@types/whatwg-url@11.0.5': @@ -1430,6 +1535,8 @@ snapshots: array-union@2.1.0: {} + async@3.2.5: {} + asynckit@0.4.0: {} balanced-match@1.0.2: {} @@ -1470,12 +1577,33 @@ snapshots: optionalDependencies: fsevents: 2.3.3 + color-convert@1.9.3: + dependencies: + color-name: 1.1.3 + color-convert@2.0.1: dependencies: color-name: 1.1.4 + color-name@1.1.3: {} + color-name@1.1.4: {} + color-string@1.9.1: + dependencies: + color-name: 1.1.4 + simple-swizzle: 0.2.2 + + color@3.2.1: + dependencies: + color-convert: 1.9.3 + color-string: 1.9.1 + + colorspace@1.1.4: + dependencies: + color: 3.2.1 + text-hex: 1.0.0 + combined-stream@1.0.8: dependencies: delayed-stream: 1.0.0 @@ -1552,6 +1680,8 @@ snapshots: dotenv@16.4.5: {} + enabled@2.0.0: {} + entities@4.5.0: {} esbuild@0.21.5: @@ -1668,6 +1798,8 @@ snapshots: dependencies: reusify: 1.0.4 + fecha@4.2.3: {} + file-entry-cache@6.0.1: dependencies: flat-cache: 3.2.0 @@ -1689,6 +1821,8 @@ snapshots: flatted@3.3.1: {} + fn.name@1.1.0: {} + form-data@4.0.0: dependencies: asynckit: 0.4.0 @@ -1780,6 +1914,8 @@ snapshots: inherits@2.0.4: {} + is-arrayish@0.3.2: {} + is-binary-path@2.1.0: dependencies: binary-extensions: 2.3.0 @@ -1796,6 +1932,8 @@ snapshots: is-potential-custom-element-name@1.0.1: {} + is-stream@2.0.1: {} + isexe@2.0.0: {} js-yaml@4.1.0: @@ -1840,6 +1978,8 @@ snapshots: dependencies: json-buffer: 3.0.1 + kuler@2.0.0: {} + levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -1855,6 +1995,15 @@ snapshots: lodash@4.17.21: {} + logform@2.6.1: + dependencies: + '@colors/colors': 1.6.0 + '@types/triple-beam': 1.3.5 + fecha: 4.2.3 + ms: 2.1.2 + safe-stable-stringify: 2.4.3 + triple-beam: 1.4.1 + magic-bytes.js@1.10.0: {} memory-pager@1.5.0: {} @@ -1918,6 +2067,10 @@ snapshots: dependencies: wrappy: 1.0.2 + one-time@1.0.0: + dependencies: + fn.name: 1.1.0 + optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -1965,6 +2118,12 @@ snapshots: queue-microtask@1.2.3: {} + readable-stream@3.6.2: + dependencies: + inherits: 2.0.4 + string_decoder: 1.3.0 + util-deprecate: 1.0.2 + readdirp@3.6.0: dependencies: picomatch: 2.3.1 @@ -1989,6 +2148,10 @@ snapshots: dependencies: queue-microtask: 1.2.3 + safe-buffer@5.2.1: {} + + safe-stable-stringify@2.4.3: {} + safer-buffer@2.1.2: {} saxes@6.0.0: @@ -2003,6 +2166,10 @@ snapshots: shebang-regex@3.0.0: {} + simple-swizzle@0.2.2: + dependencies: + is-arrayish: 0.3.2 + simple-update-notifier@2.0.0: dependencies: semver: 7.6.3 @@ -2013,8 +2180,14 @@ snapshots: dependencies: memory-pager: 1.5.0 + stack-trace@0.0.10: {} + stream-transform@3.3.2: {} + string_decoder@1.3.0: + dependencies: + safe-buffer: 5.2.1 + strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -2031,6 +2204,8 @@ snapshots: symbol-tree@3.2.4: {} + text-hex@1.0.0: {} + text-table@0.2.0: {} to-regex-range@5.0.1: @@ -2054,6 +2229,8 @@ snapshots: dependencies: punycode: 2.3.1 + triple-beam@1.4.1: {} + ts-api-utils@1.3.0(typescript@5.5.4): dependencies: typescript: 5.5.4 @@ -2105,6 +2282,8 @@ snapshots: querystringify: 2.2.0 requires-port: 1.0.0 + util-deprecate@1.0.2: {} + w3c-xmlserializer@5.0.0: dependencies: xml-name-validator: 5.0.0 @@ -2131,6 +2310,26 @@ snapshots: dependencies: isexe: 2.0.0 + winston-transport@4.7.1: + dependencies: + logform: 2.6.1 + readable-stream: 3.6.2 + triple-beam: 1.4.1 + + winston@3.13.1: + dependencies: + '@colors/colors': 1.6.0 + '@dabh/diagnostics': 2.0.3 + async: 3.2.5 + is-stream: 2.0.1 + logform: 2.6.1 + one-time: 1.0.0 + readable-stream: 3.6.2 + safe-stable-stringify: 2.4.3 + stack-trace: 0.0.10 + triple-beam: 1.4.1 + winston-transport: 4.7.1 + word-wrap@1.2.5: {} wrappy@1.0.2: {} diff --git a/src/commands/help.command.ts b/src/commands/help.command.ts index b39d299..e3b7aec 100644 --- a/src/commands/help.command.ts +++ b/src/commands/help.command.ts @@ -1,6 +1,7 @@ import Discord from 'discord.js' import { command, commands } from '@/core/commands' import { BOT_PREFIX } from '@/env' +import { logger } from '@/core/logger' export default command({ command: 'help', @@ -62,7 +63,7 @@ export default command({ try { return message.reply(data.join('\n')) } catch (error) { - console.log('error', `Could not send help DM to ${message.author.tag}.\n`, error) + logger.error(`Could not send help DM to ${message.author.tag}.\n`, error) return message.reply("it seems like I can't DM you! Do you have DMs disabled?") } diff --git a/src/core/commands.ts b/src/core/commands.ts index b9e7f1a..8b4d0bd 100644 --- a/src/core/commands.ts +++ b/src/core/commands.ts @@ -2,6 +2,7 @@ import { Message } from 'discord.js' import path from 'node:path' import fs from 'node:fs/promises' import { BOT_TRIGGERS } from '@/env' +import { logger } from './logger' export interface Command { command: string @@ -19,7 +20,7 @@ export async function loadCommands(): Promise { const files = await fs.readdir(dir) for (const file of files) { const command = (await import(path.resolve(dir, file))).default - console.log('Command loaded:', command.command) + logger.debug('Command loaded:', command.command) _commands[command.command] = command } return Object.values(_commands) diff --git a/src/core/logger.ts b/src/core/logger.ts new file mode 100644 index 0000000..f75224b --- /dev/null +++ b/src/core/logger.ts @@ -0,0 +1,67 @@ +import { LOG_LEVEL } from '@/env' +import path from 'path' +import winston from 'winston' +import util from 'node:util' + +const _logger = winston.createLogger({ + level: LOG_LEVEL, + format: winston.format.json(), + transports: [ + new winston.transports.File({ + filename: path.resolve(process.cwd(), 'logs', 'error.log'), + level: 'error', + format: winston.format.uncolorize(), + }), + new winston.transports.Console({ + format: winston.format.printf((i) => { + const colorMap: Record = { + error: 31, // red + warn: 33, // yellow + info: 36, // cyan + verbose: 32, // green + debug: 34, // blue + silly: 35, // magenta + } + const color = `\x1b[${colorMap[i.level as LogLevel]}m[` + const level = i.level.toUpperCase().padEnd(7, ' ') + return `${color}${level}] ${i.message}` + }), + }), + ], +}) + +export type LogLevel = 'error' | 'warn' | 'info' | 'verbose' | 'debug' | 'silly' + +function _log(level: LogLevel, ...message: unknown[]): void { + const parsed = + `[${new Date().toISOString()}] ` + + message + .map((x) => (typeof x === 'object' ? util.inspect(x, { depth: null }) : x?.toString())) + .join(' ') + if (_logger[level]) { + _logger.log(level, parsed) + } else { + _logger.info(parsed) + } +} + +export function log(...message: unknown[]): void { + _log('info', ...message) +} + +export function warn(...message: unknown[]): void { + _log('warn', ...message) +} + +export function error(...message: unknown[]): void { + _log('error', ...message) +} + +export function info(...message: unknown[]): void { + _log('info', ...message) +} +export function debug(...message: unknown[]): void { + _log('debug', ...message) +} + +export const logger = Object.assign(_log, { log, warn, error, info, debug }) diff --git a/src/index.ts b/src/index.ts index 6c4fb98..280a86c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,6 +1,7 @@ import { Client, Events, GatewayIntentBits } from 'discord.js' import { BOT_TRIGGERS, DISCORD_TOKEN } from '@/env' import { loadCommands, parseArguments, parseCommand } from '@/core/commands' +import { logger } from '@/core/logger' const client = new Client({ intents: [ @@ -11,17 +12,17 @@ const client = new Client({ }) loadCommands().then((commands) => - console.log('Commands loaded:', commands.map((c) => c.command).join(', ')), + logger.log('Commands loaded:', commands.map((c) => c.command).join(', ')), ) client.once(Events.ClientReady, (readyClient) => { - console.log('Ready! Logged in as', readyClient.user.tag) + logger.log('Ready! Logged in as', readyClient.user.tag) readyClient.on(Events.MessageCreate, (message) => { - console.log('Message received:', message.content, 'from', message.author) + logger.log('Message received:', message.content, 'from', message.author) for (const prefix of BOT_TRIGGERS) { if (message.content.startsWith(prefix)) { - console.log('Command received:', message.content, 'from', message.author) + logger.log('Command received:', message.content, 'from', message.author) const command = parseCommand(message.content) const [cmdName, ...args] = parseArguments(message.content) if (command) { diff --git a/src/scripts/quotes/collect.ts b/src/scripts/quotes/collect.ts index dfb2dee..3813426 100755 --- a/src/scripts/quotes/collect.ts +++ b/src/scripts/quotes/collect.ts @@ -7,6 +7,7 @@ import path from 'node:path' import { JSDOM } from 'jsdom' import { Quote } from '@/commands/quotes.command' import { nanoid } from 'nanoid' +import { logger } from '@/core/logger' const PAGE_SIZE = 15 const MAX_PAGE = 35 @@ -28,7 +29,7 @@ async function run(): Promise { for (let i = 0; i < PAGE_SIZE * MAX_PAGE; i += PAGE_SIZE) { const urlWithPage = `${url}&st=${i}` - console.log(`fetching: ${urlWithPage}`) + logger.log(`fetching: ${urlWithPage}`) const headers = new Headers() headers.set('Cookie', process.env.CA_SCRAPER_COOKIE!) @@ -46,13 +47,13 @@ async function run(): Promise { const author = (row.querySelector('td:first-child') as HTMLElement).innerText const quote = (row.querySelector('td:nth-child(2)') as HTMLElement).innerText if (!author && !quote) continue - console.log(`Found: ${author}: "${quote}"`) + logger.log(`Found: ${author}: "${quote}"`) quotes.push({ author, quote, uid: nanoid() }) } return quotes }) .catch((error) => { - console.error(error) + logger.error(error) return [] as Quote[] }), ) @@ -61,7 +62,7 @@ async function run(): Promise { await Promise.all(promises) await fs.writeFile(path.join(outputDir, 'quotes.json'), JSON.stringify(quotes)) - console.log('Wrote output.') + logger.log('Wrote output.') const csvOut = [['author', 'quote']] for (const row of quotes) { @@ -77,7 +78,7 @@ async function run(): Promise { stringify(quotes, async (err, out) => { if (err) throw err await fs.writeFile(path.join(outputDir, 'quotes.csv'), out) - console.log('Wrote output.') + logger.log('Wrote output.') }) } diff --git a/src/scripts/quotes/dump-to-db.ts b/src/scripts/quotes/dump-to-db.ts index 4e990f7..620561b 100755 --- a/src/scripts/quotes/dump-to-db.ts +++ b/src/scripts/quotes/dump-to-db.ts @@ -4,6 +4,7 @@ import path from 'node:path' import { Quote } from '@/commands/quotes.command' import { nanoid } from 'nanoid' import { db } from '@/core/db' +import { logger } from '@/core/logger' async function run(): Promise { const outputDir = path.join(__dirname, '..', 'outputs') @@ -11,15 +12,15 @@ async function run(): Promise { const data = await fs.readFile(path.join(outputDir, 'quotes_clean.csv')) parse(data.toString(), { columns: true }, async (csvErr, rows: Quote[]) => { if (csvErr) throw csvErr - console.log('Start dumping...') + logger.log('Start dumping...') try { await db .collection('quotes') .insertMany(rows.map((row) => ({ ...row, uid: nanoid() }))) - console.log('Done dumping.') + logger.log('Done dumping.') } catch (error) { - console.error(error) + logger.error(error) } }) }