From 1dc157276d834b5880a5cb20a7365348bd3c12ae Mon Sep 17 00:00:00 2001 From: pineafan Date: Mon, 14 Mar 2022 21:27:34 +0000 Subject: [PATCH] for coded --- .vscode/launch.json | 3 +- package-lock.json | 479 ++++++++++++++++++++++++++---- package.json | 4 +- src/commands/mod/ban.ts | 2 +- src/commands/mod/kick.ts | 2 +- src/commands/mod/mute.ts | 2 +- src/commands/mod/purge.ts | 2 +- src/commands/mod/softban.ts | 2 +- src/commands/mod/warn.ts | 29 +- src/commands/privacy.ts | 8 +- src/commands/settings/all.ts | 20 -- src/commands/settings/tickets.ts | 8 +- src/commands/ticket/close.ts | 91 +++++- src/commands/ticket/create.ts | 164 +++++++++- src/commands/ticket/delete.ts | 20 -- src/commands/verify.ts | 139 ++++++++- src/config/emojis.json | 23 +- src/index.ts | 6 +- src/utils/generateKeyValueList.ts | 11 +- src/utils/getEmojiByName.ts | 2 +- tsconfig.json | 3 +- 21 files changed, 889 insertions(+), 131 deletions(-) delete mode 100644 src/commands/settings/all.ts delete mode 100644 src/commands/ticket/delete.ts diff --git a/.vscode/launch.json b/.vscode/launch.json index 2024e73..ee5db77 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -4,9 +4,10 @@ // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ + { "command": "npm run dev", - "name": "Run npm start", + "name": "Run npm dev", "request": "launch", "type": "node-terminal" }, diff --git a/package-lock.json b/package-lock.json index d7dd6ea..c7fd036 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,32 +14,9 @@ "humanize": "^0.0.9", "humanize-duration": "^3.27.1", "jshaiku": "file:../haiku", - "typescript": "^4.5.5" - } - }, - "../../WebstormProjects/haiku": { - "version": "1.0.0", - "extraneous": true, - "license": "AGPL-3.0", - "dependencies": { - "@discordjs/builders": "^0.11.0", - "@discordjs/rest": "^0.2.0-canary.0", - "@types/node-cron": "^3.0.1", - "ansi-styles": "^6.1.0", - "chalk": "^5.0.0", - "discord-api-types": "^0.26.1", - "discord.js": "^13.5.1", - "node-cron": "^3.0.0" - }, - "devDependencies": { - "@babel/core": "^7.16.7", - "@babel/preset-env": "^7.16.8", - "@babel/preset-typescript": "^7.16.7", - "@types/jest": "^27.4.0", - "babel-jest": "^27.4.6", - "jest": "^27.4.7", - "ts-node": "^10.4.0", - "typescript": "4.5.4" + "json-diff": "^0.7.1", + "typescript": "^4.5.5", + "unscan": "^1.1.2" } }, "../haiku": { @@ -92,18 +69,18 @@ } }, "node_modules/@sapphire/async-queue": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.2.0.tgz", - "integrity": "sha512-O5ND5Ljpef86X5oy8zXorQ754TMjWALcPSAgPBu4+76HLtDTrNoDyzU2uGE2G4A8Wv51u0MXHzGQ0WZ4GMtpIw==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.3.0.tgz", + "integrity": "sha512-z+CDw5X4UgIEpZL8KM+ThVx1i8V60HBg0l/oFewTNbQQeRDJHdVxHyJykv+SF1H+Rc8EkMS81VTWo95jVYgO/g==", "engines": { "node": ">=v14.0.0", "npm": ">=7.0.0" } }, "node_modules/@sindresorhus/is": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", - "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==", + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", "engines": { "node": ">=10" }, @@ -139,9 +116,9 @@ } }, "node_modules/@types/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-mTClfhq5cuGyW4jthaFuig6Q8OVfB3IRyZfN/9SCyJtiM5H0SubwM89cHoT9UngO6HyUFic88HvT1zSNLNyxWA==", + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.2.tgz", + "integrity": "sha512-VXI82ykONr5tacHEojnErTQk+KQSoYbW1NB6iz6wUwrNd+BqfkfggQNoNdCqhJSzbNumShPERbM+Pc5zpfhlbw==", "dependencies": { "@types/node": "*" } @@ -151,6 +128,21 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "node_modules/cli-color": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.1.tgz", + "integrity": "sha512-eBbxZF6fqPUNnf7CLAFOersUnyYzv83tHFLSlts+OAHsNendaqv2tHCq+/MO+b3Y+9JeoUlIvobyxG/Z8GNeOg==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.15", + "timers-ext": "^0.1.7" + }, + "engines": { + "node": ">=0.10" + } + }, "node_modules/combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -162,6 +154,23 @@ "node": ">= 0.8" } }, + "node_modules/commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==", + "engines": { + "node": ">= 12" + } + }, + "node_modules/d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "dependencies": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "node_modules/delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", @@ -170,11 +179,21 @@ "node": ">=0.4.0" } }, + "node_modules/difflib": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", + "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=", + "dependencies": { + "heap": ">= 0.2.0" + }, + "engines": { + "node": "*" + } + }, "node_modules/discord-api-types": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz", "integrity": "sha512-T5PdMQ+Y1MEECYMV5wmyi9VEYPagEDEi4S0amgsszpWY0VB9JJ/hEvM6BgLhbdnKky4gfmZEXtEEtojN8ZKJQQ==", - "deprecated": "No longer supported. Install the latest release!", "engines": { "node": ">=12" } @@ -215,6 +234,83 @@ "npm": ">=7.0.0" } }, + "node_modules/dreamopt": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.8.0.tgz", + "integrity": "sha1-W8yAvnCX5F/EicNCQFq2gUCowdk=", + "dependencies": { + "wordwrap": ">=0.0.2" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/es5-ext": { + "version": "0.10.57", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.57.tgz", + "integrity": "sha512-L7cCNoPwTkAp7IBHxrKLsh7NKiVFkcdxlP9vbVw9QUvb7gF0Mz9bEBN0WY9xqdTjGF907EMT/iG013vnbqwu1Q==", + "hasInstallScript": true, + "dependencies": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + }, + "engines": { + "node": ">=0.10" + } + }, + "node_modules/es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "dependencies": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "node_modules/es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "dependencies": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "node_modules/event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "dependencies": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "node_modules/ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "dependencies": { + "type": "^2.5.0" + } + }, + "node_modules/ext/node_modules/type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + }, "node_modules/form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -228,6 +324,11 @@ "node": ">= 6" } }, + "node_modules/heap": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==" + }, "node_modules/humanize": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/humanize/-/humanize-0.0.9.tgz", @@ -241,10 +342,54 @@ "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.27.1.tgz", "integrity": "sha512-jCVkMl+EaM80rrMrAPl96SGG4NRac53UyI1o/yAzebDntEY6K6/Fj2HOjdPg8omTqIe5Y0wPBai2q5xXrIbarA==" }, + "node_modules/is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, "node_modules/jshaiku": { "resolved": "../haiku", "link": true }, + "node_modules/json-diff": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.7.3.tgz", + "integrity": "sha512-VBvNBt3cIrCBHa3gYbVsCFUEReqWZPf+Biq1ZtFdIiQ6rytRLDp3qvtrGv7z/iZDd1D4vXWpW7Nx1nP8muLzkg==", + "dependencies": { + "cli-color": "^2.0.0", + "difflib": "~0.2.1", + "dreamopt": "~0.8.0" + }, + "bin": { + "json-diff": "bin/json-diff.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "dependencies": { + "es5-ext": "~0.10.2" + } + }, + "node_modules/memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "dependencies": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, "node_modules/mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", @@ -264,6 +409,11 @@ "node": ">= 0.6" } }, + "node_modules/next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, "node_modules/node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -283,6 +433,15 @@ } } }, + "node_modules/timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "dependencies": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "node_modules/tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -298,10 +457,15 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, + "node_modules/type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, "node_modules/typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==", + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", + "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" @@ -310,6 +474,19 @@ "node": ">=4.2.0" } }, + "node_modules/unscan": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unscan/-/unscan-1.1.2.tgz", + "integrity": "sha512-a5RcGaBFMO9l78QWKffeWUo2cvfqUv05JCXuphE8MFOA92qyqp1Da7isnR+zjJspi45+yS8tTSuhd0vV3asWdA==", + "dependencies": { + "commander": "^8.3.0", + "form-data": "^4.0.0", + "node-fetch": "^2.6.5" + }, + "bin": { + "unscan": "bin/unscan.js" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", @@ -324,6 +501,11 @@ "webidl-conversions": "^3.0.0" } }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, "node_modules/ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", @@ -345,9 +527,9 @@ } }, "node_modules/zod": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.12.0.tgz", - "integrity": "sha512-w+mmntgEL4hDDL5NLFdN6Fq2DSzxfmlSoJqiYE1/CApO8EkOCxvJvRYEVf8Vr/lRs3i6gqoiyFM6KRcWqqdBzQ==", + "version": "3.13.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.13.4.tgz", + "integrity": "sha512-LZRucWt4j/ru5azOkJxCfpR87IyFDn8h2UODdqvXzZLb3K7bb9chUrUIGTy3BPsr8XnbQYfQ5Md5Hu2OYIo1mg==", "funding": { "url": "https://github.com/sponsors/colinhacks" } @@ -372,14 +554,14 @@ "integrity": "sha512-zmjq+l/rV35kE6zRrwe8BHqV78JvIh2ybJeZavBi5NySjWXqN3hmmAKg7kYMMXSeiWtSsMoZ/+MQi0DiQWy2lw==" }, "@sapphire/async-queue": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.2.0.tgz", - "integrity": "sha512-O5ND5Ljpef86X5oy8zXorQ754TMjWALcPSAgPBu4+76HLtDTrNoDyzU2uGE2G4A8Wv51u0MXHzGQ0WZ4GMtpIw==" + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/@sapphire/async-queue/-/async-queue-1.3.0.tgz", + "integrity": "sha512-z+CDw5X4UgIEpZL8KM+ThVx1i8V60HBg0l/oFewTNbQQeRDJHdVxHyJykv+SF1H+Rc8EkMS81VTWo95jVYgO/g==" }, "@sindresorhus/is": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.4.0.tgz", - "integrity": "sha512-QppPM/8l3Mawvh4rn9CNEYIU9bxpXUCRMaX9yUpvBk1nMKusLKpfXGDEKExKaPhLzcn3lzil7pR6rnJ11HgeRQ==" + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==" }, "@types/node": { "version": "17.0.21", @@ -408,9 +590,9 @@ } }, "@types/ws": { - "version": "8.5.0", - "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.0.tgz", - "integrity": "sha512-mTClfhq5cuGyW4jthaFuig6Q8OVfB3IRyZfN/9SCyJtiM5H0SubwM89cHoT9UngO6HyUFic88HvT1zSNLNyxWA==", + "version": "8.5.2", + "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.2.tgz", + "integrity": "sha512-VXI82ykONr5tacHEojnErTQk+KQSoYbW1NB6iz6wUwrNd+BqfkfggQNoNdCqhJSzbNumShPERbM+Pc5zpfhlbw==", "requires": { "@types/node": "*" } @@ -420,6 +602,18 @@ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" }, + "cli-color": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-2.0.1.tgz", + "integrity": "sha512-eBbxZF6fqPUNnf7CLAFOersUnyYzv83tHFLSlts+OAHsNendaqv2tHCq+/MO+b3Y+9JeoUlIvobyxG/Z8GNeOg==", + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.15", + "timers-ext": "^0.1.7" + } + }, "combined-stream": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", @@ -428,11 +622,33 @@ "delayed-stream": "~1.0.0" } }, + "commander": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz", + "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==" + }, + "d": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz", + "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==", + "requires": { + "es5-ext": "^0.10.50", + "type": "^1.0.1" + } + }, "delayed-stream": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" }, + "difflib": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/difflib/-/difflib-0.2.4.tgz", + "integrity": "sha1-teMDYabbAjF21WKJLbhZQKcY9H4=", + "requires": { + "heap": ">= 0.2.0" + } + }, "discord-api-types": { "version": "0.26.1", "resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.26.1.tgz", @@ -468,6 +684,78 @@ } } }, + "dreamopt": { + "version": "0.8.0", + "resolved": "https://registry.npmjs.org/dreamopt/-/dreamopt-0.8.0.tgz", + "integrity": "sha1-W8yAvnCX5F/EicNCQFq2gUCowdk=", + "requires": { + "wordwrap": ">=0.0.2" + } + }, + "es5-ext": { + "version": "0.10.57", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.57.tgz", + "integrity": "sha512-L7cCNoPwTkAp7IBHxrKLsh7NKiVFkcdxlP9vbVw9QUvb7gF0Mz9bEBN0WY9xqdTjGF907EMT/iG013vnbqwu1Q==", + "requires": { + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.3", + "next-tick": "^1.1.0" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz", + "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==", + "requires": { + "d": "^1.0.1", + "ext": "^1.1.2" + } + }, + "es6-weak-map": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz", + "integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==", + "requires": { + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "es6-symbol": "^3.1.1" + } + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "ext": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz", + "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==", + "requires": { + "type": "^2.5.0" + }, + "dependencies": { + "type": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz", + "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ==" + } + } + }, "form-data": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", @@ -478,6 +766,11 @@ "mime-types": "^2.1.12" } }, + "heap": { + "version": "0.2.7", + "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.7.tgz", + "integrity": "sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==" + }, "humanize": { "version": "0.0.9", "resolved": "https://registry.npmjs.org/humanize/-/humanize-0.0.9.tgz", @@ -488,6 +781,11 @@ "resolved": "https://registry.npmjs.org/humanize-duration/-/humanize-duration-3.27.1.tgz", "integrity": "sha512-jCVkMl+EaM80rrMrAPl96SGG4NRac53UyI1o/yAzebDntEY6K6/Fj2HOjdPg8omTqIe5Y0wPBai2q5xXrIbarA==" }, + "is-promise": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.2.2.tgz", + "integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ==" + }, "jshaiku": { "version": "file:../haiku", "requires": { @@ -509,6 +807,39 @@ "typescript": "4.5.4" } }, + "json-diff": { + "version": "0.7.3", + "resolved": "https://registry.npmjs.org/json-diff/-/json-diff-0.7.3.tgz", + "integrity": "sha512-VBvNBt3cIrCBHa3gYbVsCFUEReqWZPf+Biq1ZtFdIiQ6rytRLDp3qvtrGv7z/iZDd1D4vXWpW7Nx1nP8muLzkg==", + "requires": { + "cli-color": "^2.0.0", + "difflib": "~0.2.1", + "dreamopt": "~0.8.0" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "requires": { + "es5-ext": "~0.10.2" + } + }, + "memoizee": { + "version": "0.4.15", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.15.tgz", + "integrity": "sha512-UBWmJpLZd5STPm7PMUlOw/TSy972M+z8gcyQ5veOnSDRREz/0bmpyTfKt3/51DhEBqCZQn1udM/5flcSPYhkdQ==", + "requires": { + "d": "^1.0.1", + "es5-ext": "^0.10.53", + "es6-weak-map": "^2.0.3", + "event-emitter": "^0.3.5", + "is-promise": "^2.2.2", + "lru-queue": "^0.1.0", + "next-tick": "^1.1.0", + "timers-ext": "^0.1.7" + } + }, "mime-db": { "version": "1.51.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz", @@ -522,6 +853,11 @@ "mime-db": "1.51.0" } }, + "next-tick": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz", + "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==" + }, "node-fetch": { "version": "2.6.7", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", @@ -530,6 +866,15 @@ "whatwg-url": "^5.0.0" } }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, "tr46": { "version": "0.0.3", "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", @@ -545,10 +890,25 @@ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.3.1.tgz", "integrity": "sha512-77EbyPPpMz+FRFRuAFlWMtmgUWGe9UOG2Z25NqCwiIjRhOf5iKGuzSe5P2w1laq+FkRy4p+PCuVkJSGkzTEKVw==" }, + "type": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz", + "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg==" + }, "typescript": { - "version": "4.5.5", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.5.5.tgz", - "integrity": "sha512-TCTIul70LyWe6IJWT8QSYeA54WQe8EjQFU4wY52Fasj5UKx88LNYKCgBEHcOMOrFF1rKGbD8v/xcNWVUq9SymA==" + "version": "4.6.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.6.2.tgz", + "integrity": "sha512-HM/hFigTBHZhLXshn9sN37H085+hQGeJHJ/X7LpBWLID/fbc2acUMfU+lGD98X81sKP+pFa9f0DZmCwB9GnbAg==" + }, + "unscan": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/unscan/-/unscan-1.1.2.tgz", + "integrity": "sha512-a5RcGaBFMO9l78QWKffeWUo2cvfqUv05JCXuphE8MFOA92qyqp1Da7isnR+zjJspi45+yS8tTSuhd0vV3asWdA==", + "requires": { + "commander": "^8.3.0", + "form-data": "^4.0.0", + "node-fetch": "^2.6.5" + } }, "webidl-conversions": { "version": "3.0.1", @@ -564,6 +924,11 @@ "webidl-conversions": "^3.0.0" } }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=" + }, "ws": { "version": "8.5.0", "resolved": "https://registry.npmjs.org/ws/-/ws-8.5.0.tgz", @@ -571,9 +936,9 @@ "requires": {} }, "zod": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/zod/-/zod-3.12.0.tgz", - "integrity": "sha512-w+mmntgEL4hDDL5NLFdN6Fq2DSzxfmlSoJqiYE1/CApO8EkOCxvJvRYEVf8Vr/lRs3i6gqoiyFM6KRcWqqdBzQ==" + "version": "3.13.4", + "resolved": "https://registry.npmjs.org/zod/-/zod-3.13.4.tgz", + "integrity": "sha512-LZRucWt4j/ru5azOkJxCfpR87IyFDn8h2UODdqvXzZLb3K7bb9chUrUIGTy3BPsr8XnbQYfQ5Md5Hu2OYIo1mg==" } } } diff --git a/package.json b/package.json index 2cba58a..053b2ee 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,9 @@ "humanize": "^0.0.9", "humanize-duration": "^3.27.1", "jshaiku": "file:../haiku", - "typescript": "^4.5.5" + "json-diff": "^0.7.1", + "typescript": "^4.5.5", + "unscan": "^1.1.2" }, "name": "nucleus", "version": "0.0.1", diff --git a/src/commands/mod/ban.ts b/src/commands/mod/ban.ts index 2d7d036..92ed3a7 100644 --- a/src/commands/mod/ban.ts +++ b/src/commands/mod/ban.ts @@ -41,7 +41,7 @@ const callback = async (interaction: CommandInteraction) => { .setEmoji("PUNISH.BAN.RED") .setTitle("Banned") .setDescription(`You have been banned in ${interaction.guild.name}` + - (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : " with no reason provided.")) + (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : ".")) .setStatus("Danger") ] }) diff --git a/src/commands/mod/kick.ts b/src/commands/mod/kick.ts index 56e00e2..08beaa5 100644 --- a/src/commands/mod/kick.ts +++ b/src/commands/mod/kick.ts @@ -39,7 +39,7 @@ const callback = async (interaction: CommandInteraction) => { .setEmoji("PUNISH.KICK.RED") .setTitle("Kicked") .setDescription(`You have been kicked in ${interaction.guild.name}` + - (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : " with no reason provided.")) + (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : ".")) .setStatus("Danger") ] }) diff --git a/src/commands/mod/mute.ts b/src/commands/mod/mute.ts index 7c8cdd9..02d2531 100644 --- a/src/commands/mod/mute.ts +++ b/src/commands/mod/mute.ts @@ -137,7 +137,7 @@ const callback = async (interaction: CommandInteraction) => { .setEmoji("PUNISH.MUTE.RED") .setTitle("Muted") .setDescription(`You have been muted in ${interaction.guild.name}` + - (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : " with no reason provided.\n\n" + + (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : ".\n\n" + `You will be unmuted at: at ()`)) .setStatus("Danger") ] diff --git a/src/commands/mod/purge.ts b/src/commands/mod/purge.ts index 1dc75eb..aa2f405 100644 --- a/src/commands/mod/purge.ts +++ b/src/commands/mod/purge.ts @@ -15,7 +15,7 @@ const command = (builder: SlashCommandSubcommandBuilder) => .setDescription("The amount of messages to delete") .setRequired(false) .setMinValue(1) - .setMaxValue(50)) + .setMaxValue(100)) .addChannelOption(option => option.setName("channel").setDescription("The channel to purge messages from").setRequired(false)) .addUserOption(option => option.setName("user").setDescription("The user to purge messages from").setRequired(false)) .addStringOption(option => option.setName("reason").setDescription("The reason for the purge").setRequired(false)) diff --git a/src/commands/mod/softban.ts b/src/commands/mod/softban.ts index bcebbd5..233b7f2 100644 --- a/src/commands/mod/softban.ts +++ b/src/commands/mod/softban.ts @@ -40,7 +40,7 @@ const callback = async (interaction: CommandInteraction) => { .setEmoji("PUNISH.BAN.RED") .setTitle("Softbanned") .setDescription(`You have been softbanned from ${interaction.guild.name}` + - (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : " with no reason provided.")) + (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : ".")) .setStatus("Danger") ] }) diff --git a/src/commands/mod/warn.ts b/src/commands/mod/warn.ts index 442f290..3662896 100644 --- a/src/commands/mod/warn.ts +++ b/src/commands/mod/warn.ts @@ -16,6 +16,8 @@ const command = (builder: SlashCommandSubcommandBuilder) => ) const callback = async (interaction: CommandInteraction) => { + // @ts-ignore + const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = interaction.client.logger // TODO:[Modals] Replace this with a modal if (await new confirmationMessage(interaction) .setEmoji("PUNISH.WARN.RED") @@ -24,7 +26,8 @@ const callback = async (interaction: CommandInteraction) => { "user": `<@!${(interaction.options.getMember("user") as GuildMember).id}> (${(interaction.options.getMember("user") as GuildMember).user.username})`, "reason": `\n> ${interaction.options.getString("reason") ? interaction.options.getString("reason") : "*No reason provided*"}` }) - + `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n`) + + `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n` + + `Are you sure you want to warn <@!${(interaction.options.getMember("user") as GuildMember).id}>?`) .setColor("Danger") // pluralize("day", interaction.options.getInteger("delete")) // const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" } @@ -37,7 +40,7 @@ const callback = async (interaction: CommandInteraction) => { .setEmoji("PUNISH.WARN.RED") .setTitle("Warned") .setDescription(`You have been warned in ${interaction.guild.name}` + - (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : " with no reason provided.")) + (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : ".")) .setStatus("Danger") ] }) @@ -51,6 +54,25 @@ const callback = async (interaction: CommandInteraction) => { .setStatus("Danger") ], components: []}) } + let data = { + meta:{ + type: 'memberWarn', + displayName: 'Member warned', + calculateType: 'guildMemberPunish', + color: NucleusColors.yellow, + emoji: 'PUNISH.WARN.YELLOW', + timestamp: new Date().getTime() + }, + list: { + user: renderUser((interaction.options.getMember("user") as GuildMember).user.id, (interaction.options.getMember("user") as GuildMember).user), + warnedBy: renderUser(interaction.member.user.id, interaction.member.user), + reason: (interaction.options.getString("reason") ? `\n> ${interaction.options.getString("reason")}` : "No reason provided") + }, + hidden: { + guild: interaction.guild.id + } + } + log(data, interaction.client); let failed = (dmd == false && interaction.options.getString("notify") != "no") if (!failed) { await interaction.editReply({embeds: [new EmojiEmbed() @@ -97,7 +119,7 @@ const callback = async (interaction: CommandInteraction) => { .setEmoji(`PUNISH.WARN.RED`) .setTitle(`Warn`) .setDescription(`You have been warned` + - (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : " with no reason provided.")) + (interaction.options.getString("reason") ? ` for:\n> ${interaction.options.getString("reason")}` : ".")) .setStatus("Danger") ], content: `<@!${(interaction.options.getMember("user") as GuildMember).id}>`, @@ -129,7 +151,6 @@ const callback = async (interaction: CommandInteraction) => { } const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { - return true let member = (interaction.member as GuildMember) let me = (interaction.guild.me as GuildMember) let apply = (interaction.options.getMember("user") as GuildMember) diff --git a/src/commands/privacy.ts b/src/commands/privacy.ts index dc97370..063f195 100644 --- a/src/commands/privacy.ts +++ b/src/commands/privacy.ts @@ -1,13 +1,15 @@ import { CommandInteraction } from "discord.js"; import { SlashCommandBuilder } from "@discordjs/builders"; import { WrappedCheck } from "jshaiku"; +import { testLink, testMalware, testNSFW } from '../utils/scanners.js'; const command = new SlashCommandBuilder() .setName("privacy") - .setDescription("Shows info about Nucleus' privacy options") + .setDescription("we changed the fucking charger again!") + .addStringOption(option => option.setName("link").setDescription("fuck you").setRequired(false)) -const callback = (interaction: CommandInteraction) => { - interaction.reply("Command incomplete [privacy]"); +const callback = async (interaction: CommandInteraction) => { + console.log(await testLink(interaction.options.getString("link"))) } const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { diff --git a/src/commands/settings/all.ts b/src/commands/settings/all.ts deleted file mode 100644 index 0f17545..0000000 --- a/src/commands/settings/all.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { CommandInteraction } from "discord.js"; -import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; -import { WrappedCheck } from "jshaiku"; - -const command = (builder: SlashCommandSubcommandBuilder) => - builder - .setName("all") - .setDescription("Shows a full UI of all settings") - -const callback = (interaction: CommandInteraction) => { - interaction.reply("Command incomplete [settings/all]"); -} - -const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { - return true; -} - -export { command }; -export { callback }; -export { check }; \ No newline at end of file diff --git a/src/commands/settings/tickets.ts b/src/commands/settings/tickets.ts index 33e1586..2c2b806 100644 --- a/src/commands/settings/tickets.ts +++ b/src/commands/settings/tickets.ts @@ -1,18 +1,24 @@ import { CommandInteraction } from "discord.js"; import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; import { WrappedCheck } from "jshaiku"; +import { ChannelType } from 'discord-api-types'; const command = (builder: SlashCommandSubcommandBuilder) => builder .setName("tickets") .setDescription("Shows settings for tickets") + .addStringOption(option => option.setName("enabled").setDescription("If users should be able to create tickets | Default yes").setRequired(false) + .addChoices([["Yes", "yes"], ["No", "no"]])) + .addChannelOption(option => option.setName("category").setDescription("The category where tickets are created").addChannelType(ChannelType.GuildCategory).setRequired(false)) + .addNumberOption(option => option.setName("maxtickets").setDescription("The maximum amount of tickets a user can create | Default 5").setRequired(false).setMinValue(1)) + .addRoleOption(option => option.setName("supportping").setDescription("The role pinged when a ticket is created").setRequired(false)) const callback = (interaction: CommandInteraction) => { interaction.reply("Command incomplete [settings/tickets]"); } const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { - return true; + return interaction.memberPermissions.has("MANAGE_GUILD"); } export { command }; diff --git a/src/commands/ticket/close.ts b/src/commands/ticket/close.ts index 1e0856d..7b9d1c2 100644 --- a/src/commands/ticket/close.ts +++ b/src/commands/ticket/close.ts @@ -1,14 +1,99 @@ -import { CommandInteraction } from "discord.js"; +import Discord, { CommandInteraction } from "discord.js"; import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; import { WrappedCheck } from "jshaiku"; +import EmojiEmbed from "../../utils/generateEmojiEmbed.js"; +import readConfig from "../../utils/readConfig.js"; +import getEmojiByName from "../../utils/getEmojiByName.js"; const command = (builder: SlashCommandSubcommandBuilder) => builder .setName("close") .setDescription("Closes a ticket") -const callback = (interaction: CommandInteraction) => { - interaction.reply("Command incomplete [ticket/close]"); +const callback = async (interaction: CommandInteraction) => { + // @ts-ignore + const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = interaction.client.logger + + let config = await readConfig(interaction.guild.id); + let channel = (interaction.channel as Discord.TextChannel) + if (config.tickets.category != channel.parent.id) { + return interaction.reply({embeds: [new EmojiEmbed() + .setTitle("Close Ticket") + .setDescription("This ticket is not in your tickets category, so cannot be deleted.") + .setStatus("Danger") + .setEmoji("CONTROL.BLOCKCROSS") + ], ephemeral: true}); + } + let status = channel.topic.split(" ")[1]; + if (status == "Archived") { + interaction.reply({embeds: [new EmojiEmbed() + .setTitle("Close Ticket") + .setDescription("This ticket will be deleted in 3 seconds.") + .setStatus("Danger") + .setEmoji("GUILD.TICKET.CLOSE") + ]}); + setTimeout(async () => { + let data = { + meta:{ + type: 'ticketClosed', + displayName: 'Ticket Closed', + calculateType: true, + color: NucleusColors.red, + emoji: 'GUILD.TICKET.CLOSE', + timestamp: new Date().getTime() + }, + list: { + ticketFor: entry(channel.topic.split(" ")[0], renderUser((await interaction.guild.members.fetch(channel.topic.split(" ")[0])).user)), + closedBy: entry(interaction.member.user.id, renderUser(interaction.member.user)), + closedAt: entry(new Date().getTime(), renderDelta(new Date().getTime())) + }, + hidden: { + guild: interaction.guild.id + } + } + log(data, interaction.client); + interaction.channel.delete(); + }, 3000); + return; + } else if (status == "Active") { + interaction.reply({embeds: [new EmojiEmbed() + .setTitle("Close Ticket") + .setDescription("This ticket will be archived in 3 seconds.") + .setStatus("Warning") + .setEmoji("GUILD.TICKET.ARCHIVED") + ]}); + setTimeout(async () =>{ + channel.permissionsFor(await interaction.guild.members.fetch(channel.topic.split(" ")[0])).remove("VIEW_CHANNEL"); + channel.setTopic(`${channel.topic.split(" ")[0]} Archived`); + let data = { + meta:{ + type: 'ticketArchive', + displayName: 'Ticket Archived', + calculateType: true, + color: NucleusColors.yellow, + emoji: 'GUILD.TICKET.ARCHIVED', + timestamp: new Date().getTime() + }, + list: { + ticketFor: entry(channel.topic.split(" ")[0], renderUser((await interaction.guild.members.fetch(channel.topic.split(" ")[0])).user)), + archivedBy: entry(interaction.member.user.id, renderUser(interaction.member.user)), + archivedAt: entry(new Date().getTime(), renderDelta(new Date().getTime())), + ticketChannel: entry(channel.id, renderChannel(channel)), + }, + hidden: { + guild: interaction.guild.id + } + } + log(data, interaction.client); + await interaction.editReply({embeds: [new EmojiEmbed() + .setTitle("Close Ticket") + .setDescription("This ticket has been archived.\nType `/ticket close` to delete it.") + .setStatus("Warning") + .setEmoji("GUILD.TICKET.ARCHIVED") // TODO:[Premium] Add a transcript option ||\----/|| <- the bridge we will cross when we come to it + ]}); + }, 3000); + return; + } } const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { diff --git a/src/commands/ticket/create.ts b/src/commands/ticket/create.ts index 6f45cc2..4f58aa0 100644 --- a/src/commands/ticket/create.ts +++ b/src/commands/ticket/create.ts @@ -1,14 +1,172 @@ -import { CommandInteraction } from "discord.js"; +import Discord, { CommandInteraction, MessageActionRow, MessageButton } from "discord.js"; import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; import { WrappedCheck } from "jshaiku"; +import { tickets, toHexArray, toHexInteger } from "../../utils/calculate.js"; +import readConfig from "../../utils/readConfig.js"; +import EmojiEmbed from "../../utils/generateEmojiEmbed.js"; +import getEmojiByName from "../../utils/getEmojiByName.js"; + +function capitalize(s: string) { + s = s.replace(/([A-Z])/g, ' $1'); + return s.length < 3 ? s.toUpperCase() : s[0].toUpperCase() + s.slice(1).toLowerCase(); +} const command = (builder: SlashCommandSubcommandBuilder) => builder .setName("create") .setDescription("Creates a new modmail ticket") + .addStringOption(option => option.setName("message").setDescription("The content of the ticket").setRequired(false)) + +const callback = async (interaction: CommandInteraction) => { + // @ts-ignore + const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = interaction.client.logger + + let config = await readConfig(interaction.guild.id); + if (!config.tickets.enabled || !config.tickets.category) { + return await interaction.reply({embeds: [new EmojiEmbed() + .setTitle("Tickets are disabled") + .setDescription("Please enable tickets in the configuration to use this command.") + .setStatus("Danger") + .setEmoji("CONTROL.BLOCKCROSS") + ], ephemeral: true}); + } + let category = interaction.guild.channels.cache.get(config.tickets.category) as Discord.CategoryChannel; + let count = 0; + category.children.forEach(element => { + if (!(element.type == "GUILD_TEXT")) return; + if ((element as Discord.TextChannel).topic.includes(`${interaction.member.user.id}`)) { + if ((element as Discord.TextChannel).topic.endsWith("Active")) { + count++; + } + } + }); + if (count >= config.tickets.maxTickets) { + return await interaction.reply({embeds: [new EmojiEmbed() + .setTitle("Create Ticket") + .setDescription(`You have reached the maximum amount of tickets (${config.tickets.maxTickets}). Please close one of your active tickets before creating a new one.`) + .setStatus("Danger") + .setEmoji("CONTROL.BLOCKCROSS") + ], ephemeral: true}); + } + let ticketTypes + if (config.tickets.customTypes) ticketTypes = config.tickets.customTypes; + else if (config.tickets.types) ticketTypes = toHexArray(config.tickets.types, tickets); + else ticketTypes = []; + let chosenType; + if (ticketTypes.length > 0) { + let splitFormattedTicketTypes = []; + let formattedTicketTypes = []; + formattedTicketTypes = ticketTypes.map(type => { + return new MessageButton() + .setLabel(capitalize(type)) + .setStyle("PRIMARY") + .setCustomId(type) + .setEmoji(getEmojiByName(("TICKETS." + type.toString().toUpperCase()), "id")); + }); + for (let i = 0; i < formattedTicketTypes.length; i += 4) { + splitFormattedTicketTypes.push(new MessageActionRow().addComponents(formattedTicketTypes.slice(i, i + 4))); + } + let m = await interaction.reply({embeds: [new EmojiEmbed() + .setTitle("Create Ticket") + .setDescription("Please select a ticket type") + .setStatus("Success") + .setEmoji("GUILD.TICKET.OPEN") + ], ephemeral: true, fetchReply: true, components: splitFormattedTicketTypes}); + let component; + try { + component = await (m as Discord.Message).awaitMessageComponent({time: 2.5 * 60 * 1000}); + } catch (e) { + return; + } + component.deferUpdate(); + chosenType = component.customId; + } else { + chosenType = null + await interaction.reply({embeds: [new EmojiEmbed() + .setTitle("Create Ticket") + .setEmoji("GUILD.TICKET.OPEN") + ], ephemeral: true}) + } + let overwrites = [{ + id: interaction.member, + allow: ["VIEW_CHANNEL", "SEND_MESSAGES", "ATTACH_FILES", "ADD_REACTIONS", "READ_MESSAGE_HISTORY"], + type: "member" + }] as Discord.OverwriteResolvable[]; + if (config.tickets.supportRole != null) { + overwrites.push({ + id: interaction.guild.roles.cache.get(config.tickets.supportRole), + allow: ["VIEW_CHANNEL", "SEND_MESSAGES", "ATTACH_FILES", "ADD_REACTIONS", "READ_MESSAGE_HISTORY"], + type: "role" + }) + } -const callback = (interaction: CommandInteraction) => { - interaction.reply("Command incomplete [ticket/create]"); + let c; + try { + c = await interaction.guild.channels.create(interaction.member.user.username, { + type: "GUILD_TEXT", + topic: `${interaction.member.user.id} Active`, + parent: config.tickets.category, + nsfw: false, + permissionOverwrites: (overwrites as Discord.OverwriteResolvable[]), + reason: "Creating ticket" + }) + } catch (e) { + return await interaction.editReply({embeds: [new EmojiEmbed() + .setTitle("Create Ticket") + .setDescription("Failed to create ticket") + .setStatus("Danger") + .setEmoji("CONTROL.BLOCKCROSS") + ]}); + } + try { + await c.send( + { + content: (`<@${interaction.member.user.id}>` + (config.tickets.supportRole != null ? ` • <@&${config.tickets.supportRole}>` : "")), + allowedMentions: { + users: [(interaction.member as Discord.GuildMember).id], + roles: (config.tickets.supportRole != null ? [config.tickets.supportRole] : []) + } + } + ) + let content = interaction.options.getString("message") || ""; + if (content) content = `**Message:**\n> ${content}\n`; + await c.send({ embeds: [new EmojiEmbed() + .setTitle("New Ticket") + .setDescription( + `Ticket created by <@${interaction.member.user.id}>\n` + + `**Support type:** ${chosenType != null ? (getEmojiByName("TICKETS." + chosenType.toUpperCase()) + " " + capitalize(chosenType)) : "General"}\n` + + `**Ticket ID:** \`${c.id}\`\n${content}\n` + + `Type \`/ticket close\` to archive this ticket.`, + ) + .setStatus("Success") + .setEmoji("GUILD.TICKET.OPEN") + ]}) + let data = { + meta:{ + type: 'ticketCreate', + displayName: 'Ticket Created', + calculateType: true, + color: NucleusColors.green, + emoji: 'GUILD.TICKET.OPEN', + timestamp: new Date().getTime() + }, + list: { + ticketFor: entry(interaction.member.user.id, renderUser(interaction.member.user)), + createdAt: entry(new Date().getTime(), renderDelta(new Date().getTime())), + ticketChannel: entry(c.id, renderChannel(c)), + }, + hidden: { + guild: interaction.guild.id + } + } + log(data, interaction.client); + } catch (e) { console.log(e)} + await interaction.editReply({embeds: [new EmojiEmbed() + .setTitle("Create Ticket") + .setDescription(`Ticket created. You can view it here: <#${c.id}>`) + .setStatus("Success") + .setEmoji("GUILD.TICKET.OPEN") + ], components: []}); } const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { diff --git a/src/commands/ticket/delete.ts b/src/commands/ticket/delete.ts deleted file mode 100644 index 587ecf4..0000000 --- a/src/commands/ticket/delete.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { CommandInteraction } from "discord.js"; -import { SlashCommandSubcommandBuilder } from "@discordjs/builders"; -import { WrappedCheck } from "jshaiku"; - -const command = (builder: SlashCommandSubcommandBuilder) => - builder - .setName("delete") - .setDescription("Deletes a ticket") - -const callback = (interaction: CommandInteraction) => { - interaction.reply("Command incomplete [ticket/delete]"); -} - -const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { - return true; -} - -export { command }; -export { callback }; -export { check }; \ No newline at end of file diff --git a/src/commands/verify.ts b/src/commands/verify.ts index bb93dde..489a109 100644 --- a/src/commands/verify.ts +++ b/src/commands/verify.ts @@ -1,13 +1,144 @@ -import { CommandInteraction } from "discord.js"; +import Discord, { CommandInteraction, GuildMember } from "discord.js"; import { SlashCommandBuilder } from "@discordjs/builders"; import { WrappedCheck } from "jshaiku"; +import generateEmojiEmbed from "../utils/generateEmojiEmbed.js"; +import readConfig from "../utils/readConfig.js"; +import fetch from "node-fetch"; +import { TestString, NSFWCheck } from "../automations/unscan.js"; const command = new SlashCommandBuilder() .setName("verify") .setDescription("Get verified in the server") -const callback = (interaction: CommandInteraction) => { - interaction.reply("Command incomplete [verify]"); +const callback = async (interaction: CommandInteraction) => { + // @ts-ignore + let verify = interaction.client.verify + await interaction.reply({embeds: [new generateEmojiEmbed() + .setTitle("Loading") + .setStatus("Danger") + .setEmoji("NUCLEUS.LOADING") + ], ephemeral: true, fetchReply: true}); + let config = await readConfig(interaction.guild.id); + if ((interaction.member as GuildMember).roles.cache.has(config.verify.role)) { + return await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`You already have the <@&${config.verify.role}> role`) + .setStatus("Danger") + .setEmoji("CONTROL.BLOCKCROSS") + ]}); + } else if (interaction.channel.id != config.verify.channel) { + return await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`You can only use this command in <#${config.verify.channel}>`) + .setStatus("Danger") + .setEmoji("CONTROL.BLOCKCROSS") + ]}); + } + await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`Checking our servers are up`) + .setStatus("Warning") + .setEmoji("NUCLEUS.LOADING") + ]}); + try { + let status = await fetch(`https://clicksminuteper.net`).then(res => res.status); + if (status != 200) { + return await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`Our servers appear to be down, please try again later`) + .setStatus("Danger") + .setEmoji("CONTROL.BLOCKCROSS") + ]}); + } + } catch { + return await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`Our servers appear to be down, please try again later`) + .setStatus("Danger") + .setEmoji("CONTROL.BLOCKCROSS") + ], components: [new Discord.MessageActionRow().addComponents([ + new Discord.MessageButton() + .setLabel("Open webpage") + .setStyle("LINK") + .setURL("https://clicksminuteper.net/"), + new Discord.MessageButton() + .setLabel("Support") + .setStyle("LINK") + .setURL("https://discord.gg/bPaNnxe") + ])]}); + } + if (config.filters.images.NSFW) { + await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`Checking your avatar is safe for work`) + .setStatus("Warning") + .setEmoji("NUCLEUS.LOADING") + ]}); + if (await NSFWCheck((interaction.member as GuildMember).user.avatarURL({format: "png"}))) { + return await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`Your avatar was detected as NSFW, which we do not allow in this server.\nPlease contact one of our staff members if you believe this is a mistake`) + .setStatus("Danger") + .setEmoji("CONTROL.BLOCKCROSS") + ]}); + } + } + if (config.filters.wordFilter) { + await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`Checking your name is allowed`) + .setStatus("Warning") + .setEmoji("NUCLEUS.LOADING") + ]}); + if (TestString((interaction.member as Discord.GuildMember).displayName, config.filters.wordFilter.words.loose, config.filters.wordFilter.words.strict) != "none") { + return await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`Your name contained a word we do not allow in this server.\nPlease contact one of our staff members if you believe this is a mistake`) + .setStatus("Danger") + .setEmoji("CONTROL.BLOCKCROSS") + ]}); + } + } + await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`One moment...`) + .setStatus("Warning") + .setEmoji("NUCLEUS.LOADING") + ]}); + let code = "" + let length = 5 + let itt = 0 + const chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + while (true) { + itt += 1 + code = "" + for (let i = 0; i < length; i++) { code += chars.charAt(Math.floor(Math.random() * chars.length)); } + if (code in verify) continue; + if (itt > 1000) { + itt = 0 + length += 1 + continue + } + break; + } + verify[code] = { + uID: interaction.member.user.id, + gID: interaction.guild.id, + rName: (await interaction.guild.roles.fetch(config.verify.role)).name, + mCount: interaction.guild.memberCount, + gName: interaction.guild.name, + guildIcon: interaction.guild.iconURL({format: "png"}) + } + await interaction.editReply({embeds: [new generateEmojiEmbed() + .setTitle("Verify") + .setDescription(`Looking good!\nClick the button below to get verified`) + .setStatus("Success") + .setEmoji("MEMBER.JOIN") + ], components: [new Discord.MessageActionRow().addComponents([new Discord.MessageButton() + .setLabel("Verify") + .setStyle("LINK") + .setURL(`https://clicksminuteper.net/nucleus/verify?code=${code}`) + ])]}); } const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { @@ -16,4 +147,4 @@ const check = (interaction: CommandInteraction, defaultCheck: WrappedCheck) => { export { command }; export { callback }; -export { check }; \ No newline at end of file +export { check }; diff --git a/src/config/emojis.json b/src/config/emojis.json index 1764932..b759b8a 100644 --- a/src/config/emojis.json +++ b/src/config/emojis.json @@ -1,5 +1,7 @@ { "NUCLEUS": { + "LOGO": "953040840945721385", + "LOADING": "a946346549271732234", "INFO": { "HELP": "751751467014029322", "ABOUT": "751762088346517504", @@ -30,6 +32,7 @@ "CONTROL": { "TICK": "947441964234702849", "CROSS": "947441948543815720", + "BLOCKCROSS": "952261738349330493", "LEFT": "947441951148486728", "RIGHT": "947441957473488916", "DOWNLOAD": "947959513032585236", @@ -48,10 +51,12 @@ "CHANNEL": { "TEXT": { "CREATE": "729066924943737033", + "EDIT": "951957316117360640", "DELETE": "729064529211686922" }, "VOICE": { "CREATE": "729064530830950530", + "EDIT": "951957316071223336", "DELETE": "729064530981683200" }, "STORE": { @@ -180,15 +185,19 @@ } }, "GUILD": { - "EMOJIS": "729066518549233795", + "EMOJI": { + "CREATE": "953035168115982437", + "EDIT": "729066518549233795", + "DELETE": "953035210121953320" + }, "GRAPHS": "752214059159650396", "SETTINGS": "752570111063228507", "ICONCHANGE": "729763053612302356", "MODERATIONUPDATE": "729763053352124529", - "MODMAIL": { + "TICKET": { "OPEN": "853245836331188264", "CLOSE": "853580122506133505", - "ARCHIVE": "853580122636025856" + "ARCHIVED": "853580122636025856" }, "ROLES": { "CREATE": "729064530763579413", @@ -272,5 +281,13 @@ "CFSERVICE": { "VERIFIED": "881984571242053642", "UNVERIFIED": "881984571258847232" + }, + "TICKETS": { + "SUPPORT": "952295894370369587", + "REPORT": "952295894437482537", + "QUESTION": "952295894403907645", + "ISSUE": "952295894412316672", + "SUGGESTION": "952295894399725588", + "OTHER": "952295894445883502" } } \ No newline at end of file diff --git a/src/index.ts b/src/index.ts index 9a361f6..9e2770c 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,11 +1,15 @@ import { HaikuClient } from 'jshaiku'; import { Intents } from 'discord.js'; import config from './config/main.json' assert {type: 'json'}; - +import { Logger } from './utils/log.js'; const client = new HaikuClient({ intents: new Intents(32767).bitfield, // This is a way of specifying all intents w/o having to type them out }, config); await client.registerCommandsIn("./commands"); +await client.registerEventsIn("./events"); + +client.logger = new Logger() +client.verify = {} await client.login(); \ No newline at end of file diff --git a/src/utils/generateKeyValueList.ts b/src/utils/generateKeyValueList.ts index 7f77bef..b3e276f 100644 --- a/src/utils/generateKeyValueList.ts +++ b/src/utils/generateKeyValueList.ts @@ -1,6 +1,11 @@ -function capitalize(s) -{ - return s[0].toUpperCase() + s.slice(1); +const forceCaps = [ + "ID", + "NSFW" +] + +export function capitalize(s: string) { + s = s.replace(/([A-Z])/g, ' $1'); + return forceCaps.includes(s.toUpperCase()) ? s.toUpperCase() : s[0].toUpperCase() + s.slice(1).toLowerCase(); } function keyValueList(data) { diff --git a/src/utils/getEmojiByName.ts b/src/utils/getEmojiByName.ts index 0ec7cd6..bbc8f24 100644 --- a/src/utils/getEmojiByName.ts +++ b/src/utils/getEmojiByName.ts @@ -13,7 +13,7 @@ function getEmojiByName(name: string, format?: string): string { if (id === undefined) { return `` } else if (id.toString().startsWith("a")) { - return `` + return `` } return `<:a:${id}>`; } diff --git a/tsconfig.json b/tsconfig.json index 257f513..aa4591b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -10,5 +10,6 @@ "resolveJsonModule": true, "moduleResolution": "node", }, - "include": ["src/**/*"] + "include": ["src/**/*"], + "exclude": ["src/events:TODO/*"] } \ No newline at end of file