mirror of
https://github.com/artiemis/artemis.js.git
synced 2026-02-14 10:21:54 +00:00
ocr, translate + fixes
This commit is contained in:
parent
82bfb87ae6
commit
4f5b2e54a7
74
bun.lock
74
bun.lock
@ -7,7 +7,9 @@
|
|||||||
"@discordjs/core": "^2.0.1",
|
"@discordjs/core": "^2.0.1",
|
||||||
"@sapphire/discord.js-utilities": "^7.3.2",
|
"@sapphire/discord.js-utilities": "^7.3.2",
|
||||||
"cheerio": "^1.0.0",
|
"cheerio": "^1.0.0",
|
||||||
|
"deepl-node": "^1.16.0",
|
||||||
"discord.js": "^14.17.3",
|
"discord.js": "^14.17.3",
|
||||||
|
"execa": "^9.5.2",
|
||||||
"file-type": "^20.1.0",
|
"file-type": "^20.1.0",
|
||||||
"ky": "^1.7.4",
|
"ky": "^1.7.4",
|
||||||
"lru-cache": "^11.0.2",
|
"lru-cache": "^11.0.2",
|
||||||
@ -133,6 +135,8 @@
|
|||||||
|
|
||||||
"@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="],
|
"@sec-ant/readable-stream": ["@sec-ant/readable-stream@0.4.1", "", {}, "sha512-831qok9r2t8AlxLko40y2ebgSDhenenCatLVeW/uBtnHPyhHOvG0C7TvfgecV+wHzIm5KUICgzmVpWS+IMEAeg=="],
|
||||||
|
|
||||||
|
"@sindresorhus/merge-streams": ["@sindresorhus/merge-streams@4.0.0", "", {}, "sha512-tlqY9xq5ukxTUZBmoOp+m61cqwQD5pHJtFY3Mn8CA8ps6yghLH/Hw8UPdqg4OLmFW3IFlcXnQNmo/dh8HzXYIQ=="],
|
||||||
|
|
||||||
"@toil/translate": ["@toil/translate@1.0.2", "", { "peerDependencies": { "typescript": "^5.6.2" } }, "sha512-awxtAuyhNpogagl20Ic/BV1XY68voGWU0w/5kzxlBN5sxUPrMtSqluDSPm4XvHRfji4v45r1p1NAxLISCQfhpA=="],
|
"@toil/translate": ["@toil/translate@1.0.2", "", { "peerDependencies": { "typescript": "^5.6.2" } }, "sha512-awxtAuyhNpogagl20Ic/BV1XY68voGWU0w/5kzxlBN5sxUPrMtSqluDSPm4XvHRfji4v45r1p1NAxLISCQfhpA=="],
|
||||||
|
|
||||||
"@tokenizer/inflate": ["@tokenizer/inflate@0.2.6", "", { "dependencies": { "debug": "^4.3.7", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-SdR/i05U7Xhnsq36iyIq/ZiGGw4PKzw4ww3bOq80Pjj4wyXpqyTcgrgdDdGlcatnlvzNJx8CQw3hp6QZvkUwhA=="],
|
"@tokenizer/inflate": ["@tokenizer/inflate@0.2.6", "", { "dependencies": { "debug": "^4.3.7", "fflate": "^0.8.2", "token-types": "^6.0.0" } }, "sha512-SdR/i05U7Xhnsq36iyIq/ZiGGw4PKzw4ww3bOq80Pjj4wyXpqyTcgrgdDdGlcatnlvzNJx8CQw3hp6QZvkUwhA=="],
|
||||||
@ -181,6 +185,10 @@
|
|||||||
|
|
||||||
"async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="],
|
"async": ["async@3.2.6", "", {}, "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA=="],
|
||||||
|
|
||||||
|
"asynckit": ["asynckit@0.4.0", "", {}, "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="],
|
||||||
|
|
||||||
|
"axios": ["axios@1.7.9", "", { "dependencies": { "follow-redirects": "^1.15.6", "form-data": "^4.0.0", "proxy-from-env": "^1.1.0" } }, "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw=="],
|
||||||
|
|
||||||
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
"balanced-match": ["balanced-match@1.0.2", "", {}, "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="],
|
||||||
|
|
||||||
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
|
"boolbase": ["boolbase@1.0.0", "", {}, "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="],
|
||||||
@ -211,6 +219,8 @@
|
|||||||
|
|
||||||
"colorspace": ["colorspace@1.1.4", "", { "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" } }, "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w=="],
|
"colorspace": ["colorspace@1.1.4", "", { "dependencies": { "color": "^3.1.3", "text-hex": "1.0.x" } }, "sha512-BgvKJiuVu1igBUF2kEjRCZXol6wiiGbY5ipL/oVPwm0BL9sIpMIzM8IK7vwuxIIzOXMV3Ey5w+vxhm0rR/TN8w=="],
|
||||||
|
|
||||||
|
"combined-stream": ["combined-stream@1.0.8", "", { "dependencies": { "delayed-stream": "~1.0.0" } }, "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg=="],
|
||||||
|
|
||||||
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
"concat-map": ["concat-map@0.0.1", "", {}, "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="],
|
||||||
|
|
||||||
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
"cross-spawn": ["cross-spawn@7.0.6", "", { "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" } }, "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA=="],
|
||||||
@ -223,6 +233,10 @@
|
|||||||
|
|
||||||
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
"deep-is": ["deep-is@0.1.4", "", {}, "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ=="],
|
||||||
|
|
||||||
|
"deepl-node": ["deepl-node@1.16.0", "", { "dependencies": { "@types/node": ">=12.0", "axios": "^1.7.4", "form-data": "^3.0.0", "loglevel": ">=1.6.2" } }, "sha512-sYrh8UngVHKBrgffLPl+ng065mlC+Ep3LBdSN3xqDBd4KdBZzgvdxHiHd9Pm9xQCI5pwyuCHyq0cDUW1T3vQUg=="],
|
||||||
|
|
||||||
|
"delayed-stream": ["delayed-stream@1.0.0", "", {}, "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ=="],
|
||||||
|
|
||||||
"detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="],
|
"detect-libc": ["detect-libc@2.0.3", "", {}, "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw=="],
|
||||||
|
|
||||||
"discord-api-types": ["discord-api-types@0.37.119", "", {}, "sha512-WasbGFXEB+VQWXlo6IpW3oUv73Yuau1Ig4AZF/m13tXcTKnMpc/mHjpztIlz4+BM9FG9BHQkEXiPto3bKduQUg=="],
|
"discord-api-types": ["discord-api-types@0.37.119", "", {}, "sha512-WasbGFXEB+VQWXlo6IpW3oUv73Yuau1Ig4AZF/m13tXcTKnMpc/mHjpztIlz4+BM9FG9BHQkEXiPto3bKduQUg=="],
|
||||||
@ -261,7 +275,7 @@
|
|||||||
|
|
||||||
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
"esutils": ["esutils@2.0.3", "", {}, "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g=="],
|
||||||
|
|
||||||
"execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
"execa": ["execa@9.5.2", "", { "dependencies": { "@sindresorhus/merge-streams": "^4.0.0", "cross-spawn": "^7.0.3", "figures": "^6.1.0", "get-stream": "^9.0.0", "human-signals": "^8.0.0", "is-plain-obj": "^4.1.0", "is-stream": "^4.0.1", "npm-run-path": "^6.0.0", "pretty-ms": "^9.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^4.0.0", "yoctocolors": "^2.0.0" } }, "sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q=="],
|
||||||
|
|
||||||
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
"fast-deep-equal": ["fast-deep-equal@3.1.3", "", {}, "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="],
|
||||||
|
|
||||||
@ -277,6 +291,8 @@
|
|||||||
|
|
||||||
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
|
"fflate": ["fflate@0.8.2", "", {}, "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="],
|
||||||
|
|
||||||
|
"figures": ["figures@6.1.0", "", { "dependencies": { "is-unicode-supported": "^2.0.0" } }, "sha512-d+l3qxjSesT4V7v2fh+QnmFnUWv9lSpjarhShNTgBOfA0ttejbQUAlHLitbjkoRiDulW0OPoQPYIGhIC8ohejg=="],
|
||||||
|
|
||||||
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
"file-entry-cache": ["file-entry-cache@8.0.0", "", { "dependencies": { "flat-cache": "^4.0.0" } }, "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ=="],
|
||||||
|
|
||||||
"file-type": ["file-type@20.1.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.6", "strtok3": "^10.2.0", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-XoxU+lETfCf+bYK3SXkxFusAvmtYQl1u/ZC4zw1DBLEsHUvh339uwYucgQnnSMz1mRCWYJrCzsbJJ95hsQbZ8A=="],
|
"file-type": ["file-type@20.1.0", "", { "dependencies": { "@tokenizer/inflate": "^0.2.6", "strtok3": "^10.2.0", "token-types": "^6.0.0", "uint8array-extras": "^1.4.0" } }, "sha512-XoxU+lETfCf+bYK3SXkxFusAvmtYQl1u/ZC4zw1DBLEsHUvh339uwYucgQnnSMz1mRCWYJrCzsbJJ95hsQbZ8A=="],
|
||||||
@ -291,6 +307,10 @@
|
|||||||
|
|
||||||
"fn.name": ["fn.name@1.1.0", "", {}, "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="],
|
"fn.name": ["fn.name@1.1.0", "", {}, "sha512-GRnmB5gPyJpAhTQdSZTSp9uaPSvl09KoYcMQtsB9rQoOmzs9dH6ffeccH+Z+cv6P68Hu5bC6JjRh4Ah/mHSNRw=="],
|
||||||
|
|
||||||
|
"follow-redirects": ["follow-redirects@1.15.9", "", {}, "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ=="],
|
||||||
|
|
||||||
|
"form-data": ["form-data@3.0.2", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, "sha512-sJe+TQb2vIaIyO783qN6BlMYWMw3WBOHA1Ay2qxsnjuafEOQFJ2JakedOQirT6D5XPRxDvS7AHYyem9fTpb4LQ=="],
|
||||||
|
|
||||||
"get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
|
"get-stream": ["get-stream@9.0.1", "", { "dependencies": { "@sec-ant/readable-stream": "^0.4.1", "is-stream": "^4.0.1" } }, "sha512-kVCxPF3vQM/N0B1PmoqVUqgHP+EeVjmZSQn+1oCRPxd2P21P2F19lIgbR3HBosbB1PUhOAoctJnfEn2GbN2eZA=="],
|
||||||
|
|
||||||
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
"glob-parent": ["glob-parent@6.0.2", "", { "dependencies": { "is-glob": "^4.0.3" } }, "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A=="],
|
||||||
@ -303,7 +323,7 @@
|
|||||||
|
|
||||||
"htmlparser2": ["htmlparser2@9.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.1.0", "entities": "^4.5.0" } }, "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ=="],
|
"htmlparser2": ["htmlparser2@9.1.0", "", { "dependencies": { "domelementtype": "^2.3.0", "domhandler": "^5.0.3", "domutils": "^3.1.0", "entities": "^4.5.0" } }, "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ=="],
|
||||||
|
|
||||||
"human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
"human-signals": ["human-signals@8.0.0", "", {}, "sha512-/1/GPCpDUCCYwlERiYjxoczfP0zfvZMU/OWgQPMya9AbAE24vseigFdhAMObpc8Q4lc/kjutPfUddDYyAmejnA=="],
|
||||||
|
|
||||||
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
"iconv-lite": ["iconv-lite@0.6.3", "", { "dependencies": { "safer-buffer": ">= 2.1.2 < 3.0.0" } }, "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw=="],
|
||||||
|
|
||||||
@ -329,7 +349,11 @@
|
|||||||
|
|
||||||
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
"is-number": ["is-number@7.0.0", "", {}, "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng=="],
|
||||||
|
|
||||||
"is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
|
"is-plain-obj": ["is-plain-obj@4.1.0", "", {}, "sha512-+Pgi+vMuUNkJyExiMBt5IlFoMyKnr5zhJ4Uspz58WOhBF5QoIZkFyNHIbBAtHwzVAgk5RtndVNsDRN61/mmDqg=="],
|
||||||
|
|
||||||
|
"is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
|
||||||
|
|
||||||
|
"is-unicode-supported": ["is-unicode-supported@2.1.0", "", {}, "sha512-mE00Gnza5EEB3Ds0HfMyllZzbBrmLOX3vfWoj9A9PEnTfratQ/BcaJOuMhnkhjXvb2+FkY3VuHqtAGpTPmglFQ=="],
|
||||||
|
|
||||||
"is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
|
"is-wsl": ["is-wsl@3.1.0", "", { "dependencies": { "is-inside-container": "^1.0.0" } }, "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw=="],
|
||||||
|
|
||||||
@ -363,6 +387,8 @@
|
|||||||
|
|
||||||
"logform": ["logform@2.7.0", "", { "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" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="],
|
"logform": ["logform@2.7.0", "", { "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" } }, "sha512-TFYA4jnP7PVbmlBIfhlSe+WKxs9dklXMTEGcBCIvLhE/Tn3H6Gk1norupVW7m5Cnd4bLcr08AytbyV/xj7f/kQ=="],
|
||||||
|
|
||||||
|
"loglevel": ["loglevel@1.9.2", "", {}, "sha512-HgMmCqIJSAKqo68l0rS2AanEWfkxaZ5wNiEFb5ggm08lDs9Xl2KxBlX3PTcaD2chBM1gXAYf491/M2Rv8Jwayg=="],
|
||||||
|
|
||||||
"lru-cache": ["lru-cache@11.0.2", "", {}, "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA=="],
|
"lru-cache": ["lru-cache@11.0.2", "", {}, "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA=="],
|
||||||
|
|
||||||
"magic-bytes.js": ["magic-bytes.js@1.10.0", "", {}, "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ=="],
|
"magic-bytes.js": ["magic-bytes.js@1.10.0", "", {}, "sha512-/k20Lg2q8LE5xiaaSkMXk4sfvI+9EGEykFS4b0CHHGWqDYU0bGUFSwchNOMA56D7TCs9GwVTkqe9als1/ns8UQ=="],
|
||||||
@ -373,6 +399,10 @@
|
|||||||
|
|
||||||
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
"micromatch": ["micromatch@4.0.8", "", { "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" } }, "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA=="],
|
||||||
|
|
||||||
|
"mime-db": ["mime-db@1.52.0", "", {}, "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="],
|
||||||
|
|
||||||
|
"mime-types": ["mime-types@2.1.35", "", { "dependencies": { "mime-db": "1.52.0" } }, "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw=="],
|
||||||
|
|
||||||
"mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
|
"mimic-fn": ["mimic-fn@4.0.0", "", {}, "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw=="],
|
||||||
|
|
||||||
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
"minimatch": ["minimatch@3.1.2", "", { "dependencies": { "brace-expansion": "^1.1.7" } }, "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw=="],
|
||||||
@ -383,7 +413,7 @@
|
|||||||
|
|
||||||
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
"natural-compare": ["natural-compare@1.4.0", "", {}, "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw=="],
|
||||||
|
|
||||||
"npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="],
|
"npm-run-path": ["npm-run-path@6.0.0", "", { "dependencies": { "path-key": "^4.0.0", "unicorn-magic": "^0.3.0" } }, "sha512-9qny7Z9DsQU8Ou39ERsPU4OZQlSTP47ShQzuKZ6PRXpYLtIFgl/DEBYEXKlvcEa+9tHVcK8CF81Y2V72qaZhWA=="],
|
||||||
|
|
||||||
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
|
"nth-check": ["nth-check@2.1.1", "", { "dependencies": { "boolbase": "^1.0.0" } }, "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w=="],
|
||||||
|
|
||||||
@ -399,6 +429,8 @@
|
|||||||
|
|
||||||
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
"parent-module": ["parent-module@1.0.1", "", { "dependencies": { "callsites": "^3.0.0" } }, "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g=="],
|
||||||
|
|
||||||
|
"parse-ms": ["parse-ms@4.0.0", "", {}, "sha512-TXfryirbmq34y8QBwgqCVLi+8oA3oWx2eAnSn62ITyEhEYaWRlVZ2DvMM9eZbMs/RfxPu/PK/aBLyGj4IrqMHw=="],
|
||||||
|
|
||||||
"parse5": ["parse5@7.2.1", "", { "dependencies": { "entities": "^4.5.0" } }, "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ=="],
|
"parse5": ["parse5@7.2.1", "", { "dependencies": { "entities": "^4.5.0" } }, "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ=="],
|
||||||
|
|
||||||
"parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@7.1.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" } }, "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g=="],
|
"parse5-htmlparser2-tree-adapter": ["parse5-htmlparser2-tree-adapter@7.1.0", "", { "dependencies": { "domhandler": "^5.0.3", "parse5": "^7.0.0" } }, "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g=="],
|
||||||
@ -415,6 +447,10 @@
|
|||||||
|
|
||||||
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
"prelude-ls": ["prelude-ls@1.2.1", "", {}, "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g=="],
|
||||||
|
|
||||||
|
"pretty-ms": ["pretty-ms@9.2.0", "", { "dependencies": { "parse-ms": "^4.0.0" } }, "sha512-4yf0QO/sllf/1zbZWYnvWw3NxCQwLXKzIj0G849LSufP15BXKM0rbD2Z3wVnkMfjdn/CB0Dpp444gYAACdsplg=="],
|
||||||
|
|
||||||
|
"proxy-from-env": ["proxy-from-env@1.1.0", "", {}, "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="],
|
||||||
|
|
||||||
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
"punycode": ["punycode@2.3.1", "", {}, "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg=="],
|
||||||
|
|
||||||
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
"queue-microtask": ["queue-microtask@1.2.3", "", {}, "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A=="],
|
||||||
@ -449,7 +485,7 @@
|
|||||||
|
|
||||||
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
"string_decoder": ["string_decoder@1.3.0", "", { "dependencies": { "safe-buffer": "~5.2.0" } }, "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA=="],
|
||||||
|
|
||||||
"strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
"strip-final-newline": ["strip-final-newline@4.0.0", "", {}, "sha512-aulFJcD6YK8V1G7iRB5tigAP4TsHBZZrOV8pjV++zdUwmeV8uzbY7yn6h9MswN62adStNZFuCIx4haBnRuMDaw=="],
|
||||||
|
|
||||||
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
"strip-json-comments": ["strip-json-comments@3.1.1", "", {}, "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig=="],
|
||||||
|
|
||||||
@ -485,6 +521,8 @@
|
|||||||
|
|
||||||
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
|
"undici-types": ["undici-types@6.20.0", "", {}, "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="],
|
||||||
|
|
||||||
|
"unicorn-magic": ["unicorn-magic@0.3.0", "", {}, "sha512-+QBBXBCvifc56fsbuxZQ6Sic3wqqc3WWaqxs58gvJrcOuN83HGTCwz3oS5phzU9LthRNE9VrJCFCLUgHeeFnfA=="],
|
||||||
|
|
||||||
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
"uri-js": ["uri-js@4.4.1", "", { "dependencies": { "punycode": "^2.1.0" } }, "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg=="],
|
||||||
|
|
||||||
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
"util-deprecate": ["util-deprecate@1.0.2", "", {}, "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="],
|
||||||
@ -507,6 +545,8 @@
|
|||||||
|
|
||||||
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
"yocto-queue": ["yocto-queue@0.1.0", "", {}, "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q=="],
|
||||||
|
|
||||||
|
"yoctocolors": ["yoctocolors@2.1.1", "", {}, "sha512-GQHQqAopRhwU8Kt1DDM8NjibDXHC8eoh1erhGAJPEyveY9qqVeXvVikNKrDz69sHowPMorbPUrH/mx8c50eiBQ=="],
|
||||||
|
|
||||||
"zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
|
"zod": ["zod@3.24.1", "", {}, "sha512-muH7gBL9sI1nciMZV67X5fTKKBLtwpZ5VBp1vsOQzj1MhrBZ4wlVCm3gedKZWLp0Oyel8sIGfeiz54Su+OVT+A=="],
|
||||||
|
|
||||||
"@discordjs/rest/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="],
|
"@discordjs/rest/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="],
|
||||||
@ -521,32 +561,44 @@
|
|||||||
|
|
||||||
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
"@typescript-eslint/typescript-estree/minimatch": ["minimatch@9.0.5", "", { "dependencies": { "brace-expansion": "^2.0.1" } }, "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow=="],
|
||||||
|
|
||||||
|
"axios/form-data": ["form-data@4.0.1", "", { "dependencies": { "asynckit": "^0.4.0", "combined-stream": "^1.0.8", "mime-types": "^2.1.12" } }, "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw=="],
|
||||||
|
|
||||||
|
"clipboardy/execa": ["execa@8.0.1", "", { "dependencies": { "cross-spawn": "^7.0.3", "get-stream": "^8.0.1", "human-signals": "^5.0.0", "is-stream": "^3.0.0", "merge-stream": "^2.0.0", "npm-run-path": "^5.1.0", "onetime": "^6.0.0", "signal-exit": "^4.1.0", "strip-final-newline": "^3.0.0" } }, "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg=="],
|
||||||
|
|
||||||
"color-string/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
"color-string/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||||
|
|
||||||
"colorspace/color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="],
|
"colorspace/color": ["color@3.2.1", "", { "dependencies": { "color-convert": "^1.9.3", "color-string": "^1.6.0" } }, "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA=="],
|
||||||
|
|
||||||
"discord.js/@discordjs/ws": ["@discordjs/ws@1.2.0", "", { "dependencies": { "@discordjs/collection": "^2.1.0", "@discordjs/rest": "^2.4.1", "@discordjs/util": "^1.1.0", "@sapphire/async-queue": "^1.5.2", "@types/ws": "^8.5.10", "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "^0.37.114", "tslib": "^2.6.2", "ws": "^8.17.0" } }, "sha512-QH5CAFe3wHDiedbO+EI3OOiyipwWd+Q6BdoFZUw/Wf2fw5Cv2fgU/9UEtJRmJa9RecI+TAhdGPadMaEIur5yJg=="],
|
"discord.js/@discordjs/ws": ["@discordjs/ws@1.2.0", "", { "dependencies": { "@discordjs/collection": "^2.1.0", "@discordjs/rest": "^2.4.1", "@discordjs/util": "^1.1.0", "@sapphire/async-queue": "^1.5.2", "@types/ws": "^8.5.10", "@vladfrangu/async_event_emitter": "^2.2.4", "discord-api-types": "^0.37.114", "tslib": "^2.6.2", "ws": "^8.17.0" } }, "sha512-QH5CAFe3wHDiedbO+EI3OOiyipwWd+Q6BdoFZUw/Wf2fw5Cv2fgU/9UEtJRmJa9RecI+TAhdGPadMaEIur5yJg=="],
|
||||||
|
|
||||||
"execa/get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="],
|
|
||||||
|
|
||||||
"execa/is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="],
|
|
||||||
|
|
||||||
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
"fast-glob/glob-parent": ["glob-parent@5.1.2", "", { "dependencies": { "is-glob": "^4.0.1" } }, "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow=="],
|
||||||
|
|
||||||
"get-stream/is-stream": ["is-stream@4.0.1", "", {}, "sha512-Dnz92NInDqYckGEUJv689RbRiTSEHCQ7wOVeALbkOz999YpqT46yMRIGtSNl2iCL1waAZSx40+h59NV/EwzV/A=="],
|
|
||||||
|
|
||||||
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
"npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
||||||
|
|
||||||
|
"winston/is-stream": ["is-stream@2.0.1", "", {}, "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg=="],
|
||||||
|
|
||||||
"ya-ocr/file-type": ["file-type@19.6.0", "", { "dependencies": { "get-stream": "^9.0.1", "strtok3": "^9.0.1", "token-types": "^6.0.0", "uint8array-extras": "^1.3.0" } }, "sha512-VZR5I7k5wkD0HgFnMsq5hOsSc710MJMu5Nc5QYsbe38NN5iPV/XTObYLc/cpttRTf6lX538+5uO1ZQRhYibiZQ=="],
|
"ya-ocr/file-type": ["file-type@19.6.0", "", { "dependencies": { "get-stream": "^9.0.1", "strtok3": "^9.0.1", "token-types": "^6.0.0", "uint8array-extras": "^1.3.0" } }, "sha512-VZR5I7k5wkD0HgFnMsq5hOsSc710MJMu5Nc5QYsbe38NN5iPV/XTObYLc/cpttRTf6lX538+5uO1ZQRhYibiZQ=="],
|
||||||
|
|
||||||
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
"@typescript-eslint/typescript-estree/minimatch/brace-expansion": ["brace-expansion@2.0.1", "", { "dependencies": { "balanced-match": "^1.0.0" } }, "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA=="],
|
||||||
|
|
||||||
|
"clipboardy/execa/get-stream": ["get-stream@8.0.1", "", {}, "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA=="],
|
||||||
|
|
||||||
|
"clipboardy/execa/human-signals": ["human-signals@5.0.0", "", {}, "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ=="],
|
||||||
|
|
||||||
|
"clipboardy/execa/is-stream": ["is-stream@3.0.0", "", {}, "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA=="],
|
||||||
|
|
||||||
|
"clipboardy/execa/npm-run-path": ["npm-run-path@5.3.0", "", { "dependencies": { "path-key": "^4.0.0" } }, "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ=="],
|
||||||
|
|
||||||
|
"clipboardy/execa/strip-final-newline": ["strip-final-newline@3.0.0", "", {}, "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw=="],
|
||||||
|
|
||||||
"colorspace/color/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
"colorspace/color/color-convert": ["color-convert@1.9.3", "", { "dependencies": { "color-name": "1.1.3" } }, "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg=="],
|
||||||
|
|
||||||
"discord.js/@discordjs/ws/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="],
|
"discord.js/@discordjs/ws/@discordjs/collection": ["@discordjs/collection@2.1.1", "", {}, "sha512-LiSusze9Tc7qF03sLCujF5iZp7K+vRNEDBZ86FT9aQAv3vxMLihUvKvpsCWiQ2DJq1tVckopKm1rxomgNUc9hg=="],
|
||||||
|
|
||||||
"ya-ocr/file-type/strtok3": ["strtok3@9.1.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^5.3.1" } }, "sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw=="],
|
"ya-ocr/file-type/strtok3": ["strtok3@9.1.1", "", { "dependencies": { "@tokenizer/token": "^0.3.0", "peek-readable": "^5.3.1" } }, "sha512-FhwotcEqjr241ZbjFzjlIYg6c5/L/s4yBGWSMvJ9UoExiSqL+FnFA/CaeZx17WGaZMS/4SOZp8wH18jSS4R4lw=="],
|
||||||
|
|
||||||
|
"clipboardy/execa/npm-run-path/path-key": ["path-key@4.0.0", "", {}, "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ=="],
|
||||||
|
|
||||||
"colorspace/color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
"colorspace/color/color-convert/color-name": ["color-name@1.1.3", "", {}, "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw=="],
|
||||||
|
|
||||||
"ya-ocr/file-type/strtok3/peek-readable": ["peek-readable@5.4.2", "", {}, "sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg=="],
|
"ya-ocr/file-type/strtok3/peek-readable": ["peek-readable@5.4.2", "", {}, "sha512-peBp3qZyuS6cNIJ2akRNG1uo1WJ1d0wTxg/fxMdZ0BqCVhx242bSFHM9eNqflfJVS9SsgkzgT/1UgnsurBOTMg=="],
|
||||||
|
|||||||
@ -13,7 +13,9 @@
|
|||||||
"@discordjs/core": "^2.0.1",
|
"@discordjs/core": "^2.0.1",
|
||||||
"@sapphire/discord.js-utilities": "^7.3.2",
|
"@sapphire/discord.js-utilities": "^7.3.2",
|
||||||
"cheerio": "^1.0.0",
|
"cheerio": "^1.0.0",
|
||||||
|
"deepl-node": "^1.16.0",
|
||||||
"discord.js": "^14.17.3",
|
"discord.js": "^14.17.3",
|
||||||
|
"execa": "^9.5.2",
|
||||||
"file-type": "^20.1.0",
|
"file-type": "^20.1.0",
|
||||||
"ky": "^1.7.4",
|
"ky": "^1.7.4",
|
||||||
"lru-cache": "^11.0.2",
|
"lru-cache": "^11.0.2",
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
import type { Command } from "../types/command";
|
import type { Command, CommandBuilder } from "../types/command";
|
||||||
|
|
||||||
export function defineCommand(command: Command) {
|
export function defineCommand<B extends CommandBuilder>(command: Command<B>) {
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|||||||
130
src/commands/language/translate.ts
Normal file
130
src/commands/language/translate.ts
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
import {
|
||||||
|
Attachment,
|
||||||
|
AutocompleteInteraction,
|
||||||
|
SlashCommandBuilder,
|
||||||
|
type InteractionEditReplyOptions,
|
||||||
|
} from "discord.js";
|
||||||
|
import { defineCommand } from "..";
|
||||||
|
import {
|
||||||
|
getSourceLanguages,
|
||||||
|
getTargetLanguages,
|
||||||
|
isSourceLanguageSupported,
|
||||||
|
isTargetLanguageSupported,
|
||||||
|
languageCodeToName,
|
||||||
|
translate,
|
||||||
|
} from "../../utils/deepl";
|
||||||
|
import { abort } from "../../utils/error";
|
||||||
|
|
||||||
|
export async function translateAutocompleteImpl(
|
||||||
|
interaction: AutocompleteInteraction
|
||||||
|
) {
|
||||||
|
const option = interaction.options.getFocused(true);
|
||||||
|
const languages =
|
||||||
|
option.name === "source"
|
||||||
|
? await getSourceLanguages()
|
||||||
|
: await getTargetLanguages();
|
||||||
|
const choices = languages
|
||||||
|
.filter((language) =>
|
||||||
|
language.name.toLowerCase().includes(option.value.toLowerCase())
|
||||||
|
)
|
||||||
|
.map((language) => ({
|
||||||
|
name: language.name,
|
||||||
|
value: language.code,
|
||||||
|
}))
|
||||||
|
.slice(0, 25);
|
||||||
|
await interaction.respond(choices);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function translateImpl(
|
||||||
|
text: string,
|
||||||
|
source: string | null,
|
||||||
|
target: string,
|
||||||
|
attachment?: Attachment
|
||||||
|
): Promise<InteractionEditReplyOptions> {
|
||||||
|
const {
|
||||||
|
text: translatedText,
|
||||||
|
detectedSourceLang,
|
||||||
|
billedCharacters,
|
||||||
|
} = await translate({
|
||||||
|
text,
|
||||||
|
source,
|
||||||
|
target,
|
||||||
|
});
|
||||||
|
|
||||||
|
const displaySource = await languageCodeToName(detectedSourceLang);
|
||||||
|
const displayTarget = await languageCodeToName(target);
|
||||||
|
|
||||||
|
if (translatedText.length > 4096) {
|
||||||
|
return {
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
name: `${displaySource}-${displayTarget}.txt`,
|
||||||
|
attachment: `--- From ${displaySource} to ${displayTarget} ---\n${translatedText}`,
|
||||||
|
},
|
||||||
|
...(attachment ? [attachment] : []),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
title: `From ${displaySource} to ${displayTarget}`,
|
||||||
|
description: translatedText,
|
||||||
|
color: 0x0f2b46,
|
||||||
|
author: {
|
||||||
|
name: "DeepL",
|
||||||
|
icon_url: "https://www.google.com/s2/favicons?domain=deepl.com&sz=64",
|
||||||
|
},
|
||||||
|
footer: {
|
||||||
|
text: `Billed characters: ${billedCharacters}`,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
files: attachment ? [attachment] : [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineCommand({
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName("translate")
|
||||||
|
.setDescription("Translates text using DeepL")
|
||||||
|
.addStringOption((option) =>
|
||||||
|
option
|
||||||
|
.setName("text")
|
||||||
|
.setDescription("The text to translate")
|
||||||
|
.setRequired(true)
|
||||||
|
)
|
||||||
|
.addStringOption((option) =>
|
||||||
|
option
|
||||||
|
.setName("source")
|
||||||
|
.setDescription("Source language of the text")
|
||||||
|
.setAutocomplete(true)
|
||||||
|
)
|
||||||
|
.addStringOption((option) =>
|
||||||
|
option
|
||||||
|
.setName("target")
|
||||||
|
.setDescription("Target language of the text")
|
||||||
|
.setAutocomplete(true)
|
||||||
|
),
|
||||||
|
|
||||||
|
autocomplete: translateAutocompleteImpl,
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
const text = interaction.options.getString("text", true);
|
||||||
|
const source = interaction.options.getString("source") ?? null;
|
||||||
|
const target = interaction.options.getString("target") ?? "en-US";
|
||||||
|
|
||||||
|
await interaction.deferReply();
|
||||||
|
|
||||||
|
if (source && !(await isSourceLanguageSupported(source))) {
|
||||||
|
abort("Source language not supported");
|
||||||
|
}
|
||||||
|
if (target && !(await isTargetLanguageSupported(target))) {
|
||||||
|
abort("Target language not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
const payload = await translateImpl(text, source, target);
|
||||||
|
await interaction.editReply(payload);
|
||||||
|
},
|
||||||
|
});
|
||||||
19
src/commands/language/translateMenu.ts
Normal file
19
src/commands/language/translateMenu.ts
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
import { ApplicationCommandType, ContextMenuCommandBuilder } from "discord.js";
|
||||||
|
import { defineCommand } from "..";
|
||||||
|
import { translateImpl } from "./translate";
|
||||||
|
|
||||||
|
export default defineCommand({
|
||||||
|
data: new ContextMenuCommandBuilder()
|
||||||
|
.setName("Translate to English")
|
||||||
|
.setType(ApplicationCommandType.Message),
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
if (!interaction.isMessageContextMenuCommand()) return;
|
||||||
|
|
||||||
|
const text = interaction.targetMessage.content;
|
||||||
|
await interaction.deferReply();
|
||||||
|
|
||||||
|
const payload = await translateImpl(text, null, "en-US");
|
||||||
|
await interaction.editReply(payload);
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -50,6 +50,8 @@ export default defineCommand({
|
|||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
let term = interaction.options.getString("term", true);
|
let term = interaction.options.getString("term", true);
|
||||||
|
|
||||||
|
await interaction.deferReply();
|
||||||
|
|
||||||
// autocomplete value vs user value
|
// autocomplete value vs user value
|
||||||
if (term.startsWith(":")) {
|
if (term.startsWith(":")) {
|
||||||
term = term.slice(1);
|
term = term.slice(1);
|
||||||
|
|||||||
87
src/commands/ocr/ocr.ts
Normal file
87
src/commands/ocr/ocr.ts
Normal file
@ -0,0 +1,87 @@
|
|||||||
|
import {
|
||||||
|
Attachment,
|
||||||
|
codeBlock,
|
||||||
|
inlineCode,
|
||||||
|
SlashCommandBuilder,
|
||||||
|
type InteractionEditReplyOptions,
|
||||||
|
} from "discord.js";
|
||||||
|
import { defineCommand } from "..";
|
||||||
|
import { downloadFile } from "../../utils/http";
|
||||||
|
import { abort } from "../../utils/error";
|
||||||
|
import { yandexOcr } from "../../utils/ocr";
|
||||||
|
import sharp from "sharp";
|
||||||
|
|
||||||
|
export function buildOcrPayload(
|
||||||
|
text: string,
|
||||||
|
detected_lang: string,
|
||||||
|
attachment?: Attachment
|
||||||
|
): InteractionEditReplyOptions {
|
||||||
|
const languageName =
|
||||||
|
new Intl.DisplayNames(["en"], { type: "language" }).of(detected_lang) ??
|
||||||
|
"unknown";
|
||||||
|
|
||||||
|
const content = `Detected language: ${inlineCode(languageName)}\n${codeBlock(
|
||||||
|
text
|
||||||
|
)}`;
|
||||||
|
|
||||||
|
if (content.length > 2000) {
|
||||||
|
return {
|
||||||
|
content: `Detected language: ${inlineCode(languageName)}`,
|
||||||
|
files: [
|
||||||
|
{
|
||||||
|
name: "ocr.txt",
|
||||||
|
attachment: text,
|
||||||
|
},
|
||||||
|
...(attachment ? [attachment] : []),
|
||||||
|
],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
return {
|
||||||
|
content,
|
||||||
|
files: attachment ? [attachment] : [],
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function ocrImpl(attachment: Attachment) {
|
||||||
|
const { data, type } = await downloadFile(attachment.url);
|
||||||
|
if (!type?.mime.startsWith("image/")) {
|
||||||
|
abort("The file must be an image!");
|
||||||
|
}
|
||||||
|
|
||||||
|
const compressed = await sharp(data)
|
||||||
|
.resize(1000)
|
||||||
|
.jpeg({ quality: 90 })
|
||||||
|
.toBuffer();
|
||||||
|
|
||||||
|
return yandexOcr(compressed, type.mime);
|
||||||
|
}
|
||||||
|
|
||||||
|
export default defineCommand({
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName("ocr")
|
||||||
|
.setDescription("OCR an image using Yandex")
|
||||||
|
.addAttachmentOption((option) =>
|
||||||
|
option
|
||||||
|
.setName("image")
|
||||||
|
.setDescription("The image to OCR")
|
||||||
|
.setRequired(true)
|
||||||
|
),
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
const attachment = interaction.options.getAttachment("image", true);
|
||||||
|
if (!attachment.contentType?.startsWith("image/")) {
|
||||||
|
abort("The file must be an image!");
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.deferReply();
|
||||||
|
|
||||||
|
const result = await ocrImpl(attachment);
|
||||||
|
const payload = buildOcrPayload(
|
||||||
|
result.text,
|
||||||
|
result.detected_lang,
|
||||||
|
attachment
|
||||||
|
);
|
||||||
|
await interaction.editReply(payload);
|
||||||
|
},
|
||||||
|
});
|
||||||
28
src/commands/ocr/ocrMenu.ts
Normal file
28
src/commands/ocr/ocrMenu.ts
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
import { ApplicationCommandType, ContextMenuCommandBuilder } from "discord.js";
|
||||||
|
import { defineCommand } from "..";
|
||||||
|
import { abort } from "../../utils/error";
|
||||||
|
import { buildOcrPayload, ocrImpl } from "./ocr";
|
||||||
|
|
||||||
|
export default defineCommand({
|
||||||
|
data: new ContextMenuCommandBuilder()
|
||||||
|
.setName("OCR")
|
||||||
|
.setType(ApplicationCommandType.Message),
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
if (!interaction.isMessageContextMenuCommand()) return;
|
||||||
|
|
||||||
|
const attachment = interaction.targetMessage.attachments.first();
|
||||||
|
if (!attachment) {
|
||||||
|
abort("No attachment found");
|
||||||
|
}
|
||||||
|
if (!attachment.contentType?.startsWith("image/")) {
|
||||||
|
abort("The file must be an image!");
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.deferReply();
|
||||||
|
|
||||||
|
const result = await ocrImpl(attachment);
|
||||||
|
const payload = buildOcrPayload(result.text, result.detected_lang);
|
||||||
|
await interaction.editReply(payload);
|
||||||
|
},
|
||||||
|
});
|
||||||
63
src/commands/ocr/ocrTranslate.ts
Normal file
63
src/commands/ocr/ocrTranslate.ts
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
import { SlashCommandBuilder } from "discord.js";
|
||||||
|
import { defineCommand } from "..";
|
||||||
|
import { abort } from "../../utils/error";
|
||||||
|
import {
|
||||||
|
isSourceLanguageSupported,
|
||||||
|
isTargetLanguageSupported,
|
||||||
|
} from "../../utils/deepl";
|
||||||
|
import {
|
||||||
|
translateAutocompleteImpl,
|
||||||
|
translateImpl,
|
||||||
|
} from "../language/translate";
|
||||||
|
import { ocrImpl } from "./ocr";
|
||||||
|
|
||||||
|
export default defineCommand({
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName("ocrtranslate")
|
||||||
|
.setDescription(
|
||||||
|
"OCR an image using Yandex and translate the result using DeepL"
|
||||||
|
)
|
||||||
|
.addAttachmentOption((option) =>
|
||||||
|
option
|
||||||
|
.setName("image")
|
||||||
|
.setDescription("The image to OCR")
|
||||||
|
.setRequired(true)
|
||||||
|
)
|
||||||
|
.addStringOption((option) =>
|
||||||
|
option
|
||||||
|
.setName("source")
|
||||||
|
.setDescription("Source language of the text")
|
||||||
|
.setAutocomplete(true)
|
||||||
|
)
|
||||||
|
.addStringOption((option) =>
|
||||||
|
option
|
||||||
|
.setName("target")
|
||||||
|
.setDescription("Target language of the text")
|
||||||
|
.setAutocomplete(true)
|
||||||
|
),
|
||||||
|
|
||||||
|
autocomplete: translateAutocompleteImpl,
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
const attachment = interaction.options.getAttachment("image", true);
|
||||||
|
const source = interaction.options.getString("source") ?? null;
|
||||||
|
const target = interaction.options.getString("target") ?? "en-US";
|
||||||
|
|
||||||
|
if (!attachment.contentType?.startsWith("image/")) {
|
||||||
|
abort("The file must be an image!");
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.deferReply();
|
||||||
|
|
||||||
|
if (source && !(await isSourceLanguageSupported(source))) {
|
||||||
|
abort("Source language not supported");
|
||||||
|
}
|
||||||
|
if (target && !(await isTargetLanguageSupported(target))) {
|
||||||
|
abort("Target language not supported");
|
||||||
|
}
|
||||||
|
|
||||||
|
const { text } = await ocrImpl(attachment);
|
||||||
|
const payload = await translateImpl(text, source, target, attachment);
|
||||||
|
await interaction.editReply(payload);
|
||||||
|
},
|
||||||
|
});
|
||||||
29
src/commands/ocr/ocrTranslateMenu.ts
Normal file
29
src/commands/ocr/ocrTranslateMenu.ts
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
import { ApplicationCommandType, ContextMenuCommandBuilder } from "discord.js";
|
||||||
|
import { defineCommand } from "..";
|
||||||
|
import { abort } from "../../utils/error";
|
||||||
|
import { translateImpl } from "../language/translate";
|
||||||
|
import { ocrImpl } from "./ocr";
|
||||||
|
|
||||||
|
export default defineCommand({
|
||||||
|
data: new ContextMenuCommandBuilder()
|
||||||
|
.setName("OCR and translate to English")
|
||||||
|
.setType(ApplicationCommandType.Message),
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
if (!interaction.isMessageContextMenuCommand()) return;
|
||||||
|
|
||||||
|
const attachment = interaction.targetMessage.attachments.first();
|
||||||
|
if (!attachment) {
|
||||||
|
abort("No attachment found");
|
||||||
|
}
|
||||||
|
if (!attachment.contentType?.startsWith("image/")) {
|
||||||
|
abort("The file must be an image!");
|
||||||
|
}
|
||||||
|
|
||||||
|
await interaction.deferReply();
|
||||||
|
|
||||||
|
const { text } = await ocrImpl(attachment);
|
||||||
|
const payload = await translateImpl(text, null, "en-US");
|
||||||
|
await interaction.editReply(payload);
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -14,6 +14,6 @@ export default defineCommand({
|
|||||||
flags: MessageFlags.Ephemeral,
|
flags: MessageFlags.Ephemeral,
|
||||||
});
|
});
|
||||||
|
|
||||||
await restart(interaction.token);
|
await restart({ token: interaction.token });
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
65
src/commands/owner/update.ts
Normal file
65
src/commands/owner/update.ts
Normal file
@ -0,0 +1,65 @@
|
|||||||
|
import {
|
||||||
|
ActionRowBuilder,
|
||||||
|
ButtonBuilder,
|
||||||
|
ButtonStyle,
|
||||||
|
codeBlock,
|
||||||
|
ComponentType,
|
||||||
|
SlashCommandBuilder,
|
||||||
|
} from "discord.js";
|
||||||
|
import { defineCommand } from "..";
|
||||||
|
import { restart } from "../../utils/restart";
|
||||||
|
import { shell } from "../../utils/functions";
|
||||||
|
|
||||||
|
export default defineCommand({
|
||||||
|
data: new SlashCommandBuilder()
|
||||||
|
.setName("update")
|
||||||
|
.setDescription("Updates the bot"),
|
||||||
|
isOwnerOnly: true,
|
||||||
|
|
||||||
|
async execute(interaction) {
|
||||||
|
const response = await interaction.deferReply({ withResponse: true });
|
||||||
|
const result = await shell`git pull`;
|
||||||
|
const output = result.stdout + result.stderr;
|
||||||
|
|
||||||
|
const row = new ActionRowBuilder<ButtonBuilder>().addComponents(
|
||||||
|
new ButtonBuilder()
|
||||||
|
.setCustomId("restart")
|
||||||
|
.setLabel("Restart")
|
||||||
|
.setStyle(ButtonStyle.Success)
|
||||||
|
);
|
||||||
|
|
||||||
|
const isUpToDate = output.trim() === "Already up to date.";
|
||||||
|
|
||||||
|
await interaction.editReply({
|
||||||
|
components: isUpToDate || result.failed ? [] : [row],
|
||||||
|
embeds: [
|
||||||
|
{
|
||||||
|
description: codeBlock(output),
|
||||||
|
color: isUpToDate ? 0x00ff00 : 0xff0000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!isUpToDate && !result.failed) {
|
||||||
|
response.resource?.message
|
||||||
|
?.awaitMessageComponent({
|
||||||
|
componentType: ComponentType.Button,
|
||||||
|
time: 30000,
|
||||||
|
filter: (i) => i.user.id === interaction.user.id,
|
||||||
|
dispose: true,
|
||||||
|
})
|
||||||
|
.then(async (interaction) => {
|
||||||
|
await interaction.update({
|
||||||
|
components: [],
|
||||||
|
});
|
||||||
|
await interaction.message.react("🔄");
|
||||||
|
await restart({
|
||||||
|
message: {
|
||||||
|
id: interaction.message.id,
|
||||||
|
channelId: interaction.message.channelId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
@ -1,66 +0,0 @@
|
|||||||
import { codeBlock, inlineCode, SlashCommandBuilder } from "discord.js";
|
|
||||||
import { defineCommand } from "..";
|
|
||||||
import { downloadFile } from "../../utils/http";
|
|
||||||
import { abort } from "../../utils/error";
|
|
||||||
import { yandexOcr } from "../../utils/ocr";
|
|
||||||
import sharp from "sharp";
|
|
||||||
|
|
||||||
export default defineCommand({
|
|
||||||
data: new SlashCommandBuilder()
|
|
||||||
.setName("ocr")
|
|
||||||
.setDescription("OCR an image using Yandex")
|
|
||||||
.addAttachmentOption((option) =>
|
|
||||||
option
|
|
||||||
.setName("image")
|
|
||||||
.setDescription("The image to OCR")
|
|
||||||
.setRequired(true)
|
|
||||||
),
|
|
||||||
|
|
||||||
async execute(interaction) {
|
|
||||||
const attachment = interaction.options.getAttachment("image", true);
|
|
||||||
if (!attachment.contentType?.startsWith("image/")) {
|
|
||||||
abort("The file must be an image!");
|
|
||||||
}
|
|
||||||
|
|
||||||
await interaction.deferReply();
|
|
||||||
|
|
||||||
const { data, type } = await downloadFile(attachment.url);
|
|
||||||
if (!type?.mime.startsWith("image/")) {
|
|
||||||
abort("The file must be an image!");
|
|
||||||
}
|
|
||||||
|
|
||||||
const compressed = await sharp(data)
|
|
||||||
.resize(1000)
|
|
||||||
.jpeg({ quality: 90 })
|
|
||||||
.toBuffer();
|
|
||||||
|
|
||||||
const { text, detected_lang } = await yandexOcr(compressed, type.mime);
|
|
||||||
|
|
||||||
const languageName =
|
|
||||||
new Intl.DisplayNames(["en"], { type: "language" }).of(detected_lang) ??
|
|
||||||
"unknown";
|
|
||||||
|
|
||||||
const content = `Detected language: ${inlineCode(
|
|
||||||
languageName
|
|
||||||
)}\n${codeBlock(text)}`;
|
|
||||||
|
|
||||||
if (content.length > 2000) {
|
|
||||||
await interaction.editReply({
|
|
||||||
content: `Detected language: ${inlineCode(languageName)}`,
|
|
||||||
files: [
|
|
||||||
{
|
|
||||||
name: "ocr.txt",
|
|
||||||
attachment: text,
|
|
||||||
},
|
|
||||||
attachment,
|
|
||||||
],
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
await interaction.editReply({
|
|
||||||
content,
|
|
||||||
files: [attachment],
|
|
||||||
});
|
|
||||||
},
|
|
||||||
});
|
|
||||||
@ -10,6 +10,7 @@ const envSchema = z.object({
|
|||||||
.default("development"),
|
.default("development"),
|
||||||
DEV_GUILD_ID: z.string(),
|
DEV_GUILD_ID: z.string(),
|
||||||
DEV_CHANNEL_ID: z.string(),
|
DEV_CHANNEL_ID: z.string(),
|
||||||
|
DEEPL_API_KEY: z.string(),
|
||||||
});
|
});
|
||||||
|
|
||||||
export const env = envSchema.parse(process.env);
|
export const env = envSchema.parse(process.env);
|
||||||
|
|||||||
@ -1,15 +1,24 @@
|
|||||||
import {
|
import {
|
||||||
AutocompleteInteraction,
|
AutocompleteInteraction,
|
||||||
ChatInputCommandInteraction,
|
ChatInputCommandInteraction,
|
||||||
|
ContextMenuCommandBuilder,
|
||||||
Events,
|
Events,
|
||||||
inlineCode,
|
inlineCode,
|
||||||
|
MessageContextMenuCommandInteraction,
|
||||||
MessageFlags,
|
MessageFlags,
|
||||||
|
SlashCommandBuilder,
|
||||||
|
UserContextMenuCommandInteraction,
|
||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
import { client } from "../client";
|
import { client } from "../client";
|
||||||
import { log } from "../utils/logger";
|
import { log } from "../utils/logger";
|
||||||
import { defineEvent } from ".";
|
import { defineEvent } from ".";
|
||||||
import { isExplicitCommandError, notifyError } from "../utils/error";
|
import {
|
||||||
|
isCombinedError,
|
||||||
|
isExplicitCommandError,
|
||||||
|
notifyError,
|
||||||
|
} from "../utils/error";
|
||||||
import { nanoid } from "../utils/functions";
|
import { nanoid } from "../utils/functions";
|
||||||
|
import type { Command } from "../types/command";
|
||||||
|
|
||||||
const running = new Map<string, number>();
|
const running = new Map<string, number>();
|
||||||
const getRunning = (command: string) => running.get(command) ?? 0;
|
const getRunning = (command: string) => running.get(command) ?? 0;
|
||||||
@ -18,7 +27,10 @@ export default defineEvent({
|
|||||||
name: Events.InteractionCreate,
|
name: Events.InteractionCreate,
|
||||||
|
|
||||||
async execute(interaction) {
|
async execute(interaction) {
|
||||||
if (interaction.isChatInputCommand()) {
|
if (
|
||||||
|
interaction.isChatInputCommand() ||
|
||||||
|
interaction.isContextMenuCommand()
|
||||||
|
) {
|
||||||
await handleChatInputCommand(interaction);
|
await handleChatInputCommand(interaction);
|
||||||
} else if (interaction.isAutocomplete()) {
|
} else if (interaction.isAutocomplete()) {
|
||||||
await handleAutocomplete(interaction);
|
await handleAutocomplete(interaction);
|
||||||
@ -27,9 +39,14 @@ export default defineEvent({
|
|||||||
});
|
});
|
||||||
|
|
||||||
async function handleChatInputCommand(
|
async function handleChatInputCommand(
|
||||||
interaction: ChatInputCommandInteraction
|
interaction:
|
||||||
|
| ChatInputCommandInteraction
|
||||||
|
| MessageContextMenuCommandInteraction
|
||||||
|
| UserContextMenuCommandInteraction
|
||||||
) {
|
) {
|
||||||
const command = client.commands.get(interaction.commandName);
|
const command = client.commands.get(interaction.commandName) as Command<
|
||||||
|
SlashCommandBuilder | ContextMenuCommandBuilder
|
||||||
|
>;
|
||||||
if (!command) return;
|
if (!command) return;
|
||||||
|
|
||||||
if (command.isOwnerOnly && interaction.user.id !== client.ownerId) {
|
if (command.isOwnerOnly && interaction.user.id !== client.ownerId) {
|
||||||
@ -61,7 +78,13 @@ async function handleChatInputCommand(
|
|||||||
if (!isExplicitCommandError(err)) {
|
if (!isExplicitCommandError(err)) {
|
||||||
const trace = nanoid();
|
const trace = nanoid();
|
||||||
content += `\ntrace: ${inlineCode(trace)}`;
|
content += `\ntrace: ${inlineCode(trace)}`;
|
||||||
|
if (isCombinedError(err)) {
|
||||||
|
err.errors.forEach((error) => {
|
||||||
|
log.error("Unhandled Command Error", { trace, err: error });
|
||||||
|
});
|
||||||
|
} else {
|
||||||
log.error("Unhandled Command Error", { trace, err });
|
log.error("Unhandled Command Error", { trace, err });
|
||||||
|
}
|
||||||
notifyError(trace, err);
|
notifyError(trace, err);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
import { getDefinitions } from "../utils/wiktionary";
|
import { ArtemisClient } from "../client";
|
||||||
|
import { env } from "../env";
|
||||||
|
|
||||||
const definitions = await getDefinitions("appl");
|
const client = new ArtemisClient();
|
||||||
|
await client.api.applicationCommands.bulkOverwriteGlobalCommands(
|
||||||
if (!definitions) process.exit(1);
|
env.APPLICATION_ID,
|
||||||
|
[]
|
||||||
console.dir(definitions, { depth: null });
|
);
|
||||||
|
|||||||
@ -1,13 +1,29 @@
|
|||||||
import type {
|
import type {
|
||||||
AutocompleteInteraction,
|
AutocompleteInteraction,
|
||||||
ChatInputCommandInteraction,
|
ChatInputCommandInteraction,
|
||||||
|
ContextMenuCommandBuilder,
|
||||||
|
MessageContextMenuCommandInteraction,
|
||||||
SlashCommandBuilder,
|
SlashCommandBuilder,
|
||||||
SlashCommandOptionsOnlyBuilder,
|
SlashCommandOptionsOnlyBuilder,
|
||||||
|
UserContextMenuCommandInteraction,
|
||||||
} from "discord.js";
|
} from "discord.js";
|
||||||
|
|
||||||
export interface Command {
|
export type CommandBuilder =
|
||||||
data: SlashCommandBuilder | SlashCommandOptionsOnlyBuilder;
|
| SlashCommandBuilder
|
||||||
execute(interaction: ChatInputCommandInteraction): Promise<void>;
|
| SlashCommandOptionsOnlyBuilder
|
||||||
|
| ContextMenuCommandBuilder;
|
||||||
|
|
||||||
|
type InferInteraction<B> = B extends
|
||||||
|
| SlashCommandBuilder
|
||||||
|
| SlashCommandOptionsOnlyBuilder
|
||||||
|
? ChatInputCommandInteraction
|
||||||
|
: B extends ContextMenuCommandBuilder
|
||||||
|
? MessageContextMenuCommandInteraction | UserContextMenuCommandInteraction
|
||||||
|
: never;
|
||||||
|
|
||||||
|
export interface Command<B extends CommandBuilder = SlashCommandBuilder> {
|
||||||
|
data: B;
|
||||||
|
execute(interaction: InferInteraction<B>): Promise<void>;
|
||||||
autocomplete?(interaction: AutocompleteInteraction): Promise<void>;
|
autocomplete?(interaction: AutocompleteInteraction): Promise<void>;
|
||||||
category?: string;
|
category?: string;
|
||||||
maxConcurrency?: number;
|
maxConcurrency?: number;
|
||||||
|
|||||||
@ -43,6 +43,6 @@ export async function confirmPrompt(
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
msg.delete();
|
interaction.deleteReply();
|
||||||
return confirmation?.customId === "confirm";
|
return confirmation?.customId === "confirm";
|
||||||
}
|
}
|
||||||
|
|||||||
57
src/utils/deepl.ts
Normal file
57
src/utils/deepl.ts
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
import {
|
||||||
|
Translator,
|
||||||
|
type SourceLanguageCode,
|
||||||
|
type TargetLanguageCode,
|
||||||
|
} from "deepl-node";
|
||||||
|
import { env } from "../env";
|
||||||
|
import { lazy } from "./functions";
|
||||||
|
|
||||||
|
const translator = new Translator(env.DEEPL_API_KEY);
|
||||||
|
export const getSourceLanguages = lazy(() => translator.getSourceLanguages());
|
||||||
|
export const getTargetLanguages = lazy(() => translator.getTargetLanguages());
|
||||||
|
|
||||||
|
type TranslateOptions = {
|
||||||
|
text: string;
|
||||||
|
source?: string | null;
|
||||||
|
target?: string;
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function translate({
|
||||||
|
text,
|
||||||
|
source = null,
|
||||||
|
target = "en-US",
|
||||||
|
}: TranslateOptions) {
|
||||||
|
return translator.translateText(
|
||||||
|
text,
|
||||||
|
source as SourceLanguageCode,
|
||||||
|
target as TargetLanguageCode
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getUsage() {
|
||||||
|
return translator.getUsage();
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function getLanguages() {
|
||||||
|
return (await getSourceLanguages()).concat(await getTargetLanguages());
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function languageCodeToName(code: string) {
|
||||||
|
return (await getLanguages()).find((l) => l.code === code)?.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function isSourceLanguageSupported(code: string) {
|
||||||
|
return (
|
||||||
|
(await getSourceLanguages()).find(
|
||||||
|
(l) => l.code.toLowerCase() === code.toLowerCase()
|
||||||
|
) !== undefined
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
export async function isTargetLanguageSupported(code: string) {
|
||||||
|
return (
|
||||||
|
(await getTargetLanguages()).find(
|
||||||
|
(l) => l.code.toLowerCase() === code.toLowerCase()
|
||||||
|
) !== undefined
|
||||||
|
);
|
||||||
|
}
|
||||||
@ -14,6 +14,10 @@ export function isExplicitCommandError(
|
|||||||
return error instanceof ExplicitCommandError;
|
return error instanceof ExplicitCommandError;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function isCombinedError(error: any): error is { errors: any[] } {
|
||||||
|
return typeof error === "object" && "errors" in error;
|
||||||
|
}
|
||||||
|
|
||||||
export async function notifyError(trace: string, error: any) {
|
export async function notifyError(trace: string, error: any) {
|
||||||
return (client.channels.cache.get(env.DEV_CHANNEL_ID) as TextChannel).send({
|
return (client.channels.cache.get(env.DEV_CHANNEL_ID) as TextChannel).send({
|
||||||
content: trace,
|
content: trace,
|
||||||
|
|||||||
@ -1,7 +1,9 @@
|
|||||||
import * as cheerio from "cheerio";
|
import * as cheerio from "cheerio";
|
||||||
|
import { execa } from "execa";
|
||||||
import { customAlphabet } from "nanoid";
|
import { customAlphabet } from "nanoid";
|
||||||
|
|
||||||
export const nanoid = customAlphabet("1234567890abcdef");
|
export const nanoid = customAlphabet("1234567890abcdef");
|
||||||
|
export const shell = execa({ reject: false });
|
||||||
|
|
||||||
export function noop() {}
|
export function noop() {}
|
||||||
|
|
||||||
@ -51,3 +53,9 @@ export function dedent(parts: TemplateStringsArray, ...values: unknown[]) {
|
|||||||
.join("")
|
.join("")
|
||||||
.replace(/(\n)\s+/g, "$1");
|
.replace(/(\n)\s+/g, "$1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function lazy<T>(cb: () => T) {
|
||||||
|
let defaultValue: T;
|
||||||
|
|
||||||
|
return () => (defaultValue ??= cb());
|
||||||
|
}
|
||||||
|
|||||||
@ -1,34 +1,60 @@
|
|||||||
import { Client, InteractionWebhook, MessageFlags } from "discord.js";
|
import {
|
||||||
|
Client,
|
||||||
|
InteractionWebhook,
|
||||||
|
MessageFlags,
|
||||||
|
TextChannel,
|
||||||
|
} from "discord.js";
|
||||||
import { silently } from "./functions";
|
import { silently } from "./functions";
|
||||||
import { client } from "../client";
|
import { client } from "../client";
|
||||||
import { env } from "../env";
|
import { env } from "../env";
|
||||||
import { readFile, rm, writeFile } from "node:fs/promises";
|
import { readFile, rm, writeFile } from "node:fs/promises";
|
||||||
import { log } from "./logger";
|
import { log } from "./logger";
|
||||||
|
|
||||||
export async function restart(state: string) {
|
type RestartState = {
|
||||||
|
token?: string;
|
||||||
|
message?: {
|
||||||
|
id: string;
|
||||||
|
channelId: string;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export async function restart(state: RestartState) {
|
||||||
log.info("Shutting down...");
|
log.info("Shutting down...");
|
||||||
|
|
||||||
await writeFile("./data/temp/restart", state);
|
await writeFile("./data/temp/restart", JSON.stringify(state));
|
||||||
|
|
||||||
await client.destroy();
|
await client.destroy();
|
||||||
process.exit(0);
|
process.exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function maybeSendRestarted() {
|
export async function maybeSendRestarted() {
|
||||||
const restartToken = await silently(readFile("./data/temp/restart", "utf-8"));
|
const content = await silently(readFile("./data/temp/restart", "utf-8"));
|
||||||
|
if (!content) return;
|
||||||
|
const state = JSON.parse(content) as RestartState;
|
||||||
|
|
||||||
if (restartToken) {
|
if (state.token) {
|
||||||
const webhook = new InteractionWebhook(
|
const webhook = new InteractionWebhook(
|
||||||
client as Client<true>,
|
client as Client<true>,
|
||||||
env.APPLICATION_ID,
|
env.APPLICATION_ID,
|
||||||
restartToken
|
state.token
|
||||||
);
|
);
|
||||||
|
|
||||||
await webhook.send({
|
await silently(
|
||||||
|
webhook.send({
|
||||||
content: "Successfully restarted!",
|
content: "Successfully restarted!",
|
||||||
flags: MessageFlags.Ephemeral,
|
flags: MessageFlags.Ephemeral,
|
||||||
});
|
})
|
||||||
|
);
|
||||||
|
} else if (state.message) {
|
||||||
|
const channel = client.channels.cache.get(
|
||||||
|
state.message.channelId
|
||||||
|
) as TextChannel;
|
||||||
|
if (!channel) return;
|
||||||
|
|
||||||
|
await silently(
|
||||||
|
channel.messages.fetch(state.message.id).then((msg) => msg.react("☑️"))
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
await silently(rm("./data/temp/restart"));
|
await silently(rm("./data/temp/restart"));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user