diff --git a/package.json b/package.json index 2a8bffb..1265662 100644 --- a/package.json +++ b/package.json @@ -23,8 +23,8 @@ "vitest": "3.0.5" }, "dependencies": { + "@nhcarrigan/logger": "1.0.0", "discord.js": "14.18.0", - "fastify": "5.2.1", - "winston": "3.17.0" + "fastify": "5.2.1" } } diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 3376bd4..2e18264 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,15 +8,15 @@ importers: .: dependencies: + '@nhcarrigan/logger': + specifier: 1.0.0 + version: 1.0.0 discord.js: specifier: 14.18.0 version: 14.18.0 fastify: specifier: 5.2.1 version: 5.2.1 - winston: - specifier: 3.17.0 - version: 3.17.0 devDependencies: '@nhcarrigan/eslint-config': specifier: 5.1.0 @@ -109,13 +109,6 @@ packages: resolution: {integrity: sha512-eUuWapzEGWFEpHFxgEaBG8e3n6S8L3MSu0oda755rOfabWPnh0Our1AozNFVUxGFIhbKgd1ksprsoDGMinTOTA==} engines: {node: '>=6.9.0'} - '@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.10.1': resolution: {integrity: sha512-OWo1fY4ztL1/M/DUyRPShB4d/EzVfuUvPTRRHRIt/YxBrUYSz0a+JicD5F5zHFoNs2oTuWavxCOVFV1UljHTng==} engines: {node: '>=16.11.0'} @@ -429,6 +422,9 @@ packages: typescript: '>=5' vitest: '>=2' + '@nhcarrigan/logger@1.0.0': + resolution: {integrity: sha512-2e19Bie+ZKb6yKPKjhawqsENkhHatYkvBAmFZx9eToOXdOca+CYi51tldRMtejg6e0+4hOOf2bo5zdBQKmH0dw==} + '@nhcarrigan/typescript-config@4.0.0': resolution: {integrity: sha512-969HVha7A/Sg77fuMwOm6p14a+7C5iE6g55OD71srqwKIgksQl+Ex/hAI/pyzTQFDQ/FBJbpnHlR4Ov25QV/rw==} engines: {node: '20', pnpm: '9'} @@ -589,9 +585,6 @@ packages: '@types/normalize-package-data@2.4.4': resolution: {integrity: sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==} - '@types/triple-beam@1.3.5': - resolution: {integrity: sha512-6WaYesThRMCl19iryMYP7/x2OVgCtbIVflDGFpWnb9irXI3UjYE4AzmYuiUKY1AJstGijoY+MgUszMgRxIYTYw==} - '@types/ws@8.5.14': resolution: {integrity: sha512-bd/YFLW+URhBzMXurx7lWByOu+xzU9+kb3RboOteXYDfW+tr+JZa99OyNmPINEGB/ahzKrEuc8rcv4gnpJmxTw==} @@ -844,9 +837,6 @@ packages: resolution: {integrity: sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==} engines: {node: '>= 0.4'} - async@3.2.6: - resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} - atomic-sleep@1.0.0: resolution: {integrity: sha512-kNOjDqAh7px0XWNI+4QbzoiR/nTkHAWNud2uvnJquD1/x5a7EQZMJT0AczqK0Qn67oY/TTQ1LbUKajZpp3I9tQ==} engines: {node: '>=8.0.0'} @@ -923,28 +913,13 @@ packages: resolution: {integrity: sha512-GfisEZEJvzKrmGWkvfhgzcz/BllN1USeqD2V6tg14OAOgaCD2Z/PUEuxnAZ/nPvmaHRG7a8y77p1T/IRQ4D1Hw==} engines: {node: '>=4'} - 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==} - comment-parser@1.4.1: resolution: {integrity: sha512-buhp5kePrmda3vhc5B9t7pUQXAb2Tnd0qgpkIhPhkHXxJpiPJ11H0ZEU0oBpJ2QztSbzG/ZxMj/CHsYJqRHmyg==} engines: {node: '>= 12.0.0'} @@ -1045,9 +1020,6 @@ packages: emoji-regex@9.2.2: resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} - enabled@2.0.0: - resolution: {integrity: sha512-AKrN98kuwOzMIdAizXGI86UFBoo26CL21UM763y1h/GMSJ4/OHU9k2YlsmBpyScFo/wbLzWQJBMCW4+IO3/+OQ==} - error-ex@1.3.2: resolution: {integrity: sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==} @@ -1262,9 +1234,6 @@ packages: fastq@1.19.0: resolution: {integrity: sha512-7SFSRCNjBQIZH/xZR3iy5iQYR8aGBE0h3VG6/cwlbrpdciNYBMotQav8c1XI3HjHH+NikUpP53nPdlZSdWmFzA==} - fecha@4.2.3: - resolution: {integrity: sha512-OP2IUU6HeYKJi3i0z4A19kHMQoLVs4Hc+DPqqxI2h/DPZHTm/vjsfC6P0b4jCMy14XizLBqvndQ+UilD7707Jw==} - file-entry-cache@8.0.0: resolution: {integrity: sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==} engines: {node: '>=16.0.0'} @@ -1292,9 +1261,6 @@ packages: flatted@3.3.2: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} - fn.name@1.1.0: - resolution: {integrity: sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw==} - for-each@0.3.4: resolution: {integrity: sha512-kKaIINnFpzW6ffJNDjjyjrk21BkDx38c0xa/klsT8VzLCaMEefv4ZTacrcVR4DmgTeBra++jMDAfS/tS799YDw==} engines: {node: '>= 0.4'} @@ -1431,9 +1397,6 @@ packages: resolution: {integrity: sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==} engines: {node: '>=8'} - inherits@2.0.4: - resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} - internal-slot@1.1.0: resolution: {integrity: sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==} engines: {node: '>= 0.4'} @@ -1449,9 +1412,6 @@ packages: is-arrayish@0.2.1: resolution: {integrity: sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==} - is-arrayish@0.3.2: - resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} - is-async-function@2.1.1: resolution: {integrity: sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==} engines: {node: '>= 0.4'} @@ -1528,10 +1488,6 @@ packages: resolution: {integrity: sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==} engines: {node: '>= 0.4'} - is-stream@2.0.1: - resolution: {integrity: sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==} - engines: {node: '>=8'} - is-string@1.1.1: resolution: {integrity: sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==} engines: {node: '>= 0.4'} @@ -1643,9 +1599,6 @@ 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'} @@ -1673,10 +1626,6 @@ packages: lodash@4.17.21: resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} - logform@2.7.0: - resolution: {integrity: sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ==} - engines: {node: '>= 12.0.0'} - loose-envify@1.4.0: resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} hasBin: true @@ -1786,9 +1735,6 @@ packages: resolution: {integrity: sha512-0eJJY6hXLGf1udHwfNftBqH+g73EU4B504nZeKpz1sYRKafAghwxEJunB2O7rDZkL4PGfsMVnTXZ2EjibbqcsA==} engines: {node: '>=14.0.0'} - 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'} @@ -1936,10 +1882,6 @@ packages: resolution: {integrity: sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==} engines: {node: '>=8'} - readable-stream@3.6.2: - resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} - engines: {node: '>= 6'} - real-require@0.2.0: resolution: {integrity: sha512-57frrGM/OCTLqLOAh0mhVA9VBMHd+9U7Zb2THMGdBUoZVOtGbJzjxsYGDJ3A9AYYCP4hn6y1TVbaOfzWtm5GFg==} engines: {node: '>= 12.13.0'} @@ -2004,9 +1946,6 @@ packages: resolution: {integrity: sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==} engines: {node: '>=0.4'} - safe-buffer@5.2.1: - resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} - safe-push-apply@1.0.0: resolution: {integrity: sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==} engines: {node: '>= 0.4'} @@ -2084,9 +2023,6 @@ packages: resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} engines: {node: '>=14'} - simple-swizzle@0.2.2: - resolution: {integrity: sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==} - slash@3.0.0: resolution: {integrity: sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==} engines: {node: '>=8'} @@ -2120,9 +2056,6 @@ packages: resolution: {integrity: sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==} engines: {node: '>= 10.x'} - stack-trace@0.0.10: - resolution: {integrity: sha512-KGzahc7puUKkzyMt+IqAep+TVNbKP+k2Lmwhub39m1AsTSkaDutx56aDCo+HLDzf/D26BIHTJWNiTG1KAJiQCg==} - stackback@0.0.2: resolution: {integrity: sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw==} @@ -2156,9 +2089,6 @@ packages: resolution: {integrity: sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==} engines: {node: '>= 0.4'} - 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'} @@ -2195,9 +2125,6 @@ packages: resolution: {integrity: sha512-pFYqmTw68LXVjeWJMST4+borgQP2AyMNbg1BpZh9LbyhUeNkeaPF9gzfPGUAnSMV3qPYdWUwDIjjCLiSDOl7vg==} engines: {node: '>=18'} - text-hex@1.0.0: - resolution: {integrity: sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==} - thread-stream@3.1.0: resolution: {integrity: sha512-OqyPZ9u96VohAyMfJykzmivOrY2wfMSf3C5TtFJVgN+Hm6aj+voFhlK+kZEIv2FBh1X6Xp3DlnCOfEQ3B2J86A==} @@ -2227,10 +2154,6 @@ packages: resolution: {integrity: sha512-/m8M+2BJUpoJdgAHoG+baCwBT+tf2VraSfkBgl0Y00qIWt41DJ8R5B8nsEw0I58YwF5IZH6z24/2TobDKnqSWw==} engines: {node: '>=12'} - triple-beam@1.4.1: - resolution: {integrity: sha512-aZbgViZrg1QNcG+LULa7nhZpJTZSLm/mXnHXnbAbjmN5aSa0y7V+wvv6+4WaBtpISJzThKy+PIPxc1Nq1EJ9mg==} - engines: {node: '>= 14.0.0'} - ts-api-utils@1.4.3: resolution: {integrity: sha512-i3eMG77UTMD0hZhgRS562pv83RC6ukSAC2GMNWc+9dieh/+jDM5u5YG+NHX6VNDRHQcHwmsTHctP9LhbC3WxVw==} engines: {node: '>=16'} @@ -2309,9 +2232,6 @@ packages: uri-js@4.4.1: resolution: {integrity: sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==} - util-deprecate@1.0.2: - resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} - validate-npm-package-license@3.0.4: resolution: {integrity: sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==} @@ -2414,14 +2334,6 @@ packages: engines: {node: '>=8'} hasBin: true - winston-transport@4.9.0: - resolution: {integrity: sha512-8drMJ4rkgaPo1Me4zD/3WLfI/zPdA9o2IipKODunnGDcuqbHwjsbB79ylv04LCGGzU0xQ6vTznOMpQGaLhhm6A==} - engines: {node: '>= 12.0.0'} - - winston@3.17.0: - resolution: {integrity: sha512-DLiFIXYC5fMPxaRg832S6F5mJYvePtmO5G9v9IgUFPhXm9/GkXarH/TUrBAVzhTCzAj9anE/+GjrgXp/54nOgw==} - engines: {node: '>= 12.0.0'} - word-wrap@1.2.5: resolution: {integrity: sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==} engines: {node: '>=0.10.0'} @@ -2559,14 +2471,6 @@ snapshots: '@babel/helper-string-parser': 7.25.9 '@babel/helper-validator-identifier': 7.25.9 - '@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.10.1': dependencies: '@discordjs/formatters': 0.6.0 @@ -2846,6 +2750,8 @@ snapshots: - eslint-import-resolver-webpack - supports-color + '@nhcarrigan/logger@1.0.0': {} + '@nhcarrigan/typescript-config@4.0.0(typescript@5.7.3)': dependencies: typescript: 5.7.3 @@ -2961,8 +2867,6 @@ snapshots: '@types/normalize-package-data@2.4.4': {} - '@types/triple-beam@1.3.5': {} - '@types/ws@8.5.14': dependencies: '@types/node': 22.13.1 @@ -3301,8 +3205,6 @@ snapshots: async-function@1.0.0: {} - async@3.2.6: {} - atomic-sleep@1.0.0: {} available-typed-arrays@1.0.7: @@ -3382,33 +3284,12 @@ snapshots: dependencies: escape-string-regexp: 1.0.5 - 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 - comment-parser@1.4.1: {} concat-map@0.0.1: {} @@ -3513,8 +3394,6 @@ snapshots: emoji-regex@9.2.2: {} - enabled@2.0.0: {} - error-ex@1.3.2: dependencies: is-arrayish: 0.2.1 @@ -3916,8 +3795,6 @@ snapshots: dependencies: reusify: 1.0.4 - fecha@4.2.3: {} - file-entry-cache@8.0.0: dependencies: flat-cache: 4.0.1 @@ -3949,8 +3826,6 @@ snapshots: flatted@3.3.2: {} - fn.name@1.1.0: {} - for-each@0.3.4: dependencies: is-callable: 1.2.7 @@ -4087,8 +3962,6 @@ snapshots: indent-string@4.0.0: {} - inherits@2.0.4: {} - internal-slot@1.1.0: dependencies: es-errors: 1.3.0 @@ -4105,8 +3978,6 @@ snapshots: is-arrayish@0.2.1: {} - is-arrayish@0.3.2: {} - is-async-function@2.1.1: dependencies: async-function: 1.0.0 @@ -4186,8 +4057,6 @@ snapshots: dependencies: call-bound: 1.0.3 - is-stream@2.0.1: {} - is-string@1.1.1: dependencies: call-bound: 1.0.3 @@ -4307,8 +4176,6 @@ snapshots: dependencies: json-buffer: 3.0.1 - kuler@2.0.0: {} - levn@0.4.1: dependencies: prelude-ls: 1.2.1 @@ -4336,15 +4203,6 @@ snapshots: lodash@4.17.21: {} - logform@2.7.0: - dependencies: - '@colors/colors': 1.6.0 - '@types/triple-beam': 1.3.5 - fecha: 4.2.3 - ms: 2.1.3 - safe-stable-stringify: 2.5.0 - triple-beam: 1.4.1 - loose-envify@1.4.0: dependencies: js-tokens: 4.0.0 @@ -4454,10 +4312,6 @@ snapshots: on-exit-leak-free@2.1.2: {} - one-time@1.0.0: - dependencies: - fn.name: 1.1.0 - optionator@0.9.4: dependencies: deep-is: 0.1.4 @@ -4603,12 +4457,6 @@ snapshots: parse-json: 5.2.0 type-fest: 0.6.0 - readable-stream@3.6.2: - dependencies: - inherits: 2.0.4 - string_decoder: 1.3.0 - util-deprecate: 1.0.2 - real-require@0.2.0: {} reflect.getprototypeof@1.0.10: @@ -4698,8 +4546,6 @@ snapshots: has-symbols: 1.1.0 isarray: 2.0.5 - safe-buffer@5.2.1: {} - safe-push-apply@1.0.0: dependencies: es-errors: 1.3.0 @@ -4787,10 +4633,6 @@ snapshots: signal-exit@4.1.0: {} - simple-swizzle@0.2.2: - dependencies: - is-arrayish: 0.3.2 - slash@3.0.0: {} slashes@3.0.12: {} @@ -4822,8 +4664,6 @@ snapshots: split2@4.2.0: {} - stack-trace@0.0.10: {} - stackback@0.0.2: {} std-env@3.8.0: {} @@ -4884,10 +4724,6 @@ snapshots: define-properties: 1.2.1 es-object-atoms: 1.1.1 - string_decoder@1.3.0: - dependencies: - safe-buffer: 5.2.1 - strip-ansi@6.0.1: dependencies: ansi-regex: 5.0.1 @@ -4921,8 +4757,6 @@ snapshots: glob: 10.4.5 minimatch: 9.0.5 - text-hex@1.0.0: {} - thread-stream@3.1.0: dependencies: real-require: 0.2.0 @@ -4943,8 +4777,6 @@ snapshots: toad-cache@3.7.0: {} - triple-beam@1.4.1: {} - ts-api-utils@1.4.3(typescript@5.7.3): dependencies: typescript: 5.7.3 @@ -5030,8 +4862,6 @@ snapshots: dependencies: punycode: 2.3.1 - util-deprecate@1.0.2: {} - validate-npm-package-license@3.0.4: dependencies: spdx-correct: 3.2.0 @@ -5154,26 +4984,6 @@ snapshots: siginfo: 2.0.0 stackback: 0.0.2 - winston-transport@4.9.0: - dependencies: - logform: 2.7.0 - readable-stream: 3.6.2 - triple-beam: 1.4.1 - - winston@3.17.0: - dependencies: - '@colors/colors': 1.6.0 - '@dabh/diagnostics': 2.0.3 - async: 3.2.6 - is-stream: 2.0.1 - logform: 2.7.0 - one-time: 1.0.0 - readable-stream: 3.6.2 - safe-stable-stringify: 2.5.0 - stack-trace: 0.0.10 - triple-beam: 1.4.1 - winston-transport: 4.9.0 - word-wrap@1.2.5: {} wrap-ansi@7.0.0: diff --git a/prod.env b/prod.env index e8550bb..429aed4 100644 --- a/prod.env +++ b/prod.env @@ -1,2 +1,3 @@ DISCORD_TOKEN="op://Environment Variables - Naomi/Aria Iuvo/discord_token" TRANSLATE_TOKEN="op://Environment Variables - Naomi/Aria Iuvo/api_token" +LOG_TOKEN="op://Environment Variables - Naomi/Alert Server/api_auth" \ No newline at end of file diff --git a/src/i18n/responses.ts b/src/i18n/responses.ts index 28592d2..238beef 100644 --- a/src/i18n/responses.ts +++ b/src/i18n/responses.ts @@ -9,13 +9,14 @@ /* eslint-disable max-lines -- massive chonky boi*/ import { Locale } from "discord.js"; -export const responses: Record = { +export const responses: Record = { en: { "button": { code: "Source code", support: "Need help?", }, - "embed": { + "command-error": "An error occurred while running this command.", + "embed": { commit: "Current Commit", description: "Aria Iuvo is a Discord bot that uses LibreTranslate to provide translations for messages. She is developed by NHCarrigan. To use the bot, right click on a message, select `Apps`, then select `Translate message`!", title: "About Aria Iuvo", @@ -33,7 +34,8 @@ export const responses: Record { + if (error instanceof Error) { + void logger.error("Unhandled Rejection", error); + return; + } + void logger.error("unhandled rejection", new Error(String(error))); +}); + +process.on("uncaughtException", (error) => { + if (error instanceof Error) { + void logger.error("Uncaught Exception", error); + return; + } + void logger.error("uncaught exception", new Error(String(error))); +}); const client = new Client({ intents: [], @@ -22,8 +38,16 @@ client.on(Events.InteractionCreate, (interaction) => { } }); +client.on(Events.EntitlementCreate, (entitlement) => { + void logger.log("info", `User ${entitlement.userId} has subscribed!`); +}); + +client.on(Events.EntitlementDelete, (entitlement) => { + void logger.log("info", `User ${entitlement.userId} has unsubscribed... :c`); +}); + client.on(Events.ClientReady, () => { - logHandler.info("Bot is ready."); + void logger.log("debug", "Bot is ready."); }); instantiateServer(); diff --git a/src/modules/about.ts b/src/modules/about.ts index 0caa1b6..493c966 100644 --- a/src/modules/about.ts +++ b/src/modules/about.ts @@ -14,6 +14,8 @@ import { type ChatInputCommandInteraction, } from "discord.js"; import { i18n } from "../utils/i18n.js"; +import { logger } from "../utils/logger.js"; +import { replyToError } from "../utils/replyToError.js"; import { getLocale } from "./getLocale.js"; /** @@ -22,46 +24,54 @@ import { getLocale } from "./getLocale.js"; */ export const about = async(interaction: ChatInputCommandInteraction): Promise => { - await interaction.deferReply({ flags: [ MessageFlags.Ephemeral ] }); - const targetLocale = getLocale(interaction); + try { + await interaction.deferReply({ flags: [ MessageFlags.Ephemeral ] }); + const targetLocale = getLocale(interaction); - const version = process.env.npm_package_version ?? "Unknown"; - const commit = execSync("git rev-parse --short HEAD").toString(). - trim(); + const version = process.env.npm_package_version ?? "Unknown"; + const commit = execSync("git rev-parse --short HEAD").toString(). + trim(); - const embed = new EmbedBuilder(); - embed.setTitle(i18n("embed.title", targetLocale)); - embed.setDescription(i18n("embed.description", targetLocale)); - embed.addFields( - { - name: i18n("embed.version", targetLocale), - value: version, - }, - { - name: i18n("embed.commit", targetLocale), - value: commit, - }, - ); + const embed = new EmbedBuilder(); + embed.setTitle(i18n("embed.title", targetLocale)); + embed.setDescription(i18n("embed.description", targetLocale)); + embed.addFields( + { + name: i18n("embed.version", targetLocale), + value: version, + }, + { + name: i18n("embed.commit", targetLocale), + value: commit, + }, + ); - const supportButton = new ButtonBuilder(). - setLabel(i18n("button.support", targetLocale)). - setStyle(ButtonStyle.Link). - setURL("https://chat.nhcarrigan.com"); - const sourceButton = new ButtonBuilder(). - setLabel(i18n("button.code", targetLocale)). - setStyle(ButtonStyle.Link). - setURL("https://git.nhcarrigan.com/nhcarrigan/aria-iuvo"); - const subscribeButton = new ButtonBuilder(). - setStyle(ButtonStyle.Premium). - setSKUId("1338596712121499669"); - const row = new ActionRowBuilder().addComponents( - supportButton, - sourceButton, - subscribeButton, - ); + const supportButton = new ButtonBuilder(). + setLabel(i18n("button.support", targetLocale)). + setStyle(ButtonStyle.Link). + setURL("https://chat.nhcarrigan.com"); + const sourceButton = new ButtonBuilder(). + setLabel(i18n("button.code", targetLocale)). + setStyle(ButtonStyle.Link). + setURL("https://git.nhcarrigan.com/nhcarrigan/aria-iuvo"); + const subscribeButton = new ButtonBuilder(). + setStyle(ButtonStyle.Premium). + setSKUId("1338596712121499669"); + const row = new ActionRowBuilder().addComponents( + supportButton, + sourceButton, + subscribeButton, + ); - await interaction.editReply({ - components: [ row ], - embeds: [ embed ], - }); + await interaction.editReply({ + components: [ row ], + embeds: [ embed ], + }); + } catch (error) { + const targetLocale = getLocale(interaction); + await replyToError(interaction, targetLocale); + if (error instanceof Error) { + await logger.error("about command", error); + } + } }; diff --git a/src/modules/translate.ts b/src/modules/translate.ts index b2a5870..7b137d2 100644 --- a/src/modules/translate.ts +++ b/src/modules/translate.ts @@ -13,6 +13,8 @@ import { } from "discord.js"; import { supportedLocales } from "../config/locales.js"; import { i18n } from "../utils/i18n.js"; +import { logger } from "../utils/logger.js"; +import { replyToError } from "../utils/replyToError.js"; import { getLocale } from "./getLocale.js"; /** @@ -23,82 +25,97 @@ import { getLocale } from "./getLocale.js"; export const translate = async( interaction: MessageContextMenuCommandInteraction, ): Promise => { - await interaction.deferReply({ flags: [ MessageFlags.Ephemeral ] }); - const targetLocale = getLocale(interaction); + try { + await interaction.deferReply({ flags: [ MessageFlags.Ephemeral ] }); + const targetLocale = getLocale(interaction); - const isEntitled = interaction.entitlements.find((entitlement) => { - return entitlement.userId === interaction.user.id && entitlement.isActive(); - }); + const isEntitled = interaction.entitlements.find((entitlement) => { + return ( + entitlement.userId === interaction.user.id && entitlement.isActive() + ); + }); - if (!isEntitled && interaction.user.id !== "465650873650118659") { - const subscribeButton = new ButtonBuilder(). - setStyle(ButtonStyle.Premium). - setSKUId("1338596712121499669"); - const row = new ActionRowBuilder().addComponents( - subscribeButton, + if (!isEntitled && interaction.user.id !== "465650873650118659") { + const subscribeButton = new ButtonBuilder(). + setStyle(ButtonStyle.Premium). + setSKUId("1338596712121499669"); + const row = new ActionRowBuilder().addComponents( + subscribeButton, + ); + await interaction.editReply({ + components: [ row ], + content: i18n("subscription-required", targetLocale), + }); + return; + } + + if (!supportedLocales.includes(targetLocale)) { + await interaction.editReply( + i18n("unsupported-locale", targetLocale, { + target: targetLocale, + }), + ); + return; + } + + const message = interaction.options.getMessage("message", true); + if (message.content === "") { + await interaction.editReply({ + content: i18n("no-message-content", targetLocale), + }); + return; + } + const sourceLocaleRequestParameters = new URLSearchParams(); + sourceLocaleRequestParameters.append("q", message.content); + sourceLocaleRequestParameters.append( + "api_key", + process.env.TRANSLATE_TOKEN ?? "", ); + const sourceLocaleRequest = await fetch( + "https://trans.nhcarrigan.com/detect", + { + body: sourceLocaleRequestParameters, + method: "POST", + }, + ); + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- .json() doesn't accept a generic. + const [ sourceLocale ] = (await sourceLocaleRequest.json()) as Array<{ + confidence: number; + language: string; + }>; + const translationRequestParameters = new URLSearchParams(); + translationRequestParameters.append("q", message.content); + translationRequestParameters.append( + "source", + sourceLocale?.language ?? "en", + ); + translationRequestParameters.append("target", targetLocale); + translationRequestParameters.append( + "api_key", + process.env.TRANSLATE_TOKEN ?? "", + ); + const translationRequest = await fetch( + "https://trans.nhcarrigan.com/translate", + { body: translationRequestParameters, method: "POST" }, + ); + // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- .json() doesn't accept a generic. + const translation = (await translationRequest.json()) as { + translatedText: string; + }; + await interaction.editReply({ - components: [ row ], - content: i18n("subscription-required", targetLocale), + content: i18n("translation", targetLocale, { + confidence: sourceLocale?.confidence, + language: sourceLocale?.language, + lng: targetLocale, + translation: translation.translatedText, + }), }); - return; + } catch (error) { + const targetLocale = getLocale(interaction); + await replyToError(interaction, targetLocale); + if (error instanceof Error) { + await logger.error("translate command", error); + } } - - if (!supportedLocales.includes(targetLocale)) { - await interaction.editReply(i18n("unsupported-locale", targetLocale, { - target: targetLocale, - })); - return; - } - - const message = interaction.options.getMessage("message", true); - if (message.content === "") { - await interaction.editReply({ - content: i18n("no-message-content", targetLocale), - }); - return; - } - const sourceLocaleRequestParameters = new URLSearchParams(); - sourceLocaleRequestParameters.append("q", message.content); - sourceLocaleRequestParameters.append( - "api_key", - process.env.TRANSLATE_TOKEN ?? "", - ); - const sourceLocaleRequest = await fetch( - "https://trans.nhcarrigan.com/detect", - { - body: sourceLocaleRequestParameters, - method: "POST", - }, - ); - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- .json() doesn't accept a generic. - const [ sourceLocale ] = (await sourceLocaleRequest.json()) as Array<{ - confidence: number; - language: string; - }>; - const translationRequestParameters = new URLSearchParams(); - translationRequestParameters.append("q", message.content); - translationRequestParameters.append("source", sourceLocale?.language ?? "en"); - translationRequestParameters.append("target", targetLocale); - translationRequestParameters.append( - "api_key", - process.env.TRANSLATE_TOKEN ?? "", - ); - const translationRequest = await fetch( - "https://trans.nhcarrigan.com/translate", - { body: translationRequestParameters, method: "POST" }, - ); - // eslint-disable-next-line @typescript-eslint/consistent-type-assertions -- .json() doesn't accept a generic. - const translation = (await translationRequest.json()) as { - translatedText: string; - }; - - await interaction.editReply({ - content: i18n("translation", targetLocale, { - confidence: sourceLocale?.confidence, - language: sourceLocale?.language, - lng: targetLocale, - translation: translation.translatedText, - }), - }); }; diff --git a/src/server/serve.ts b/src/server/serve.ts index 178999b..0e7ffeb 100644 --- a/src/server/serve.ts +++ b/src/server/serve.ts @@ -5,7 +5,7 @@ */ import fastify from "fastify"; -import { logHandler } from "../utils/logHandler.js"; +import { logger } from "../utils/logger.js"; const html = ` @@ -60,12 +60,16 @@ export const instantiateServer = (): void => { server.listen({ port: 5001 }, (error) => { if (error) { - logHandler.error(error); + void logger.error("instantiate server", error); return; } - logHandler.info("Server listening on port 5001."); + void logger.log("debug", "Server listening on port 5001."); }); } catch (error) { - logHandler.error(error); + if (error instanceof Error) { + void logger.error("instantiate server", error); + return; + } + void logger.error("instantiate server", new Error(String(error))); } }; diff --git a/src/utils/logHandler.ts b/src/utils/logHandler.ts deleted file mode 100644 index 88d9274..0000000 --- a/src/utils/logHandler.ts +++ /dev/null @@ -1,31 +0,0 @@ -/** - * @copyright nhcarrigan - * @license Naomi's Public License - * @author Naomi Carrigan - */ -import { createLogger, format, transports, config } from "winston"; - -const { combine, timestamp, colorize, printf } = format; - -/** - * Standard log handler, using winston to wrap and format - * messages. Call with `logHandler.log(level, message)`. - * @param {string} level - The log level to use. - * @param {string} message - The message to log. - */ -export const logHandler = createLogger({ - exitOnError: false, - format: combine( - timestamp({ - format: "YYYY-MM-DD HH:mm:ss", - }), - colorize(), - printf((info) => { - // eslint-disable-next-line @typescript-eslint/restrict-template-expressions -- Winston properties... - return `${info.level}: ${info.timestamp}: ${info.message}`; - }), - ), - level: "silly", - levels: config.npm.levels, - transports: [ new transports.Console() ], -}); diff --git a/src/utils/logger.ts b/src/utils/logger.ts new file mode 100644 index 0000000..cdbaa07 --- /dev/null +++ b/src/utils/logger.ts @@ -0,0 +1,12 @@ +/** + * @copyright nhcarrigan + * @license Naomi's Public License + * @author Naomi Carrigan + */ + +import { Logger } from "@nhcarrigan/logger"; + +export const logger = new Logger( + "Aria Iuvo", + process.env.LOG_TOKEN ?? "", +); diff --git a/src/utils/replyToError.ts b/src/utils/replyToError.ts new file mode 100644 index 0000000..acb2f66 --- /dev/null +++ b/src/utils/replyToError.ts @@ -0,0 +1,28 @@ +/** + * @copyright nhcarrigan + * @license Naomi's Public License + * @author Naomi Carrigan + */ +import { i18n } from "./i18n.js"; +import type { + ChatInputCommandInteraction, + MessageContextMenuCommandInteraction, +} from "discord.js"; + +/** + * Responds to an interaction with a generic error message. + * @param interaction -- The interaction payload from Discord. + * @param locale -- The locale to respond in. + */ +export const replyToError = async( + interaction: + | ChatInputCommandInteraction + | MessageContextMenuCommandInteraction, + locale: string, +): Promise => { + if (interaction.deferred || interaction.replied) { + await interaction.editReply(i18n("command-error", locale)); + return; + } + await interaction.reply(i18n("command-error", locale)); +};