mirror of
https://github.com/ZeppelinBot/Zeppelin.git
synced 2025-03-15 05:41:51 +00:00
Update djs & knub (#395)
* update pkgs
Signed-off-by: GitHub <noreply@github.com>
* new knub typings
Signed-off-by: GitHub <noreply@github.com>
* more pkg updates
Signed-off-by: GitHub <noreply@github.com>
* more fixes
Signed-off-by: GitHub <noreply@github.com>
* channel typings
Signed-off-by: GitHub <noreply@github.com>
* more message utils typings fixes
Signed-off-by: GitHub <noreply@github.com>
* migrate permissions
Signed-off-by: GitHub <noreply@github.com>
* fix: InternalPoster webhookables
Signed-off-by: GitHub <noreply@github.com>
* djs typings: Attachment & Util
Signed-off-by: GitHub <noreply@github.com>
* more typings
Signed-off-by: GitHub <noreply@github.com>
* fix: rename permissionNames
Signed-off-by: GitHub <noreply@github.com>
* more fixes
Signed-off-by: GitHub <noreply@github.com>
* half the number of errors
* knub commands => messageCommands
Signed-off-by: GitHub <noreply@github.com>
* configPreprocessor => configParser
Signed-off-by: GitHub <noreply@github.com>
* fix channel.messages
Signed-off-by: GitHub <noreply@github.com>
* revert automod any typing
Signed-off-by: GitHub <noreply@github.com>
* more configParser typings
Signed-off-by: GitHub <noreply@github.com>
* revert
Signed-off-by: GitHub <noreply@github.com>
* remove knub type params
Signed-off-by: GitHub <noreply@github.com>
* fix more MessageEmbed / MessageOptions
Signed-off-by: GitHub <noreply@github.com>
* dumb commit for @almeidx to see why this is stupid
Signed-off-by: GitHub <noreply@github.com>
* temp disable custom_events
Signed-off-by: GitHub <noreply@github.com>
* more minor typings fixes - 23 err left
Signed-off-by: GitHub <noreply@github.com>
* update djs dep
* +debug build method (revert this)
Signed-off-by: GitHub <noreply@github.com>
* Revert "+debug build method (revert this)"
This reverts commit a80af1e729
.
* Redo +debug build (Revert this)
Signed-off-by: GitHub <noreply@github.com>
* uniform before/after Load shorthands
Signed-off-by: GitHub <noreply@github.com>
* remove unused imports & add prettier plugin
Signed-off-by: GitHub <noreply@github.com>
* env fixes for web platform hosting
Signed-off-by: GitHub <noreply@github.com>
* feat: knub v32-next; related fixes
* fix: allow legacy keys in change_perms action
* fix: request Message Content intent
* fix: use Knub's config validation logic in API
* fix(dashboard): fix error when there are no message and/or slash commands in a plugin
* fix(automod): start_thread action thread options
* fix(CustomEvents): message command types
* chore: remove unneeded type annotation
* feat: add forum channel icon; use thread icon for news threads
* chore: make tslint happy
* chore: fix formatting
---------
Signed-off-by: GitHub <noreply@github.com>
Co-authored-by: almeidx <almeidx@pm.me>
Co-authored-by: Dragory <2606411+Dragory@users.noreply.github.com>
This commit is contained in:
parent
293115af22
commit
06877e90cc
476 changed files with 2965 additions and 3251 deletions
575
backend/package-lock.json
generated
575
backend/package-lock.json
generated
|
@ -13,8 +13,7 @@
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"deep-diff": "^1.0.2",
|
"deep-diff": "^1.0.2",
|
||||||
"discord-api-types": "^0.33.1",
|
"discord.js": "^14.8.0",
|
||||||
"discord.js": "^13.14.0",
|
|
||||||
"dotenv": "^4.0.0",
|
"dotenv": "^4.0.0",
|
||||||
"emoji-regex": "^8.0.0",
|
"emoji-regex": "^8.0.0",
|
||||||
"erlpack": "github:discord/erlpack",
|
"erlpack": "github:discord/erlpack",
|
||||||
|
@ -24,7 +23,7 @@
|
||||||
"humanize-duration": "^3.15.0",
|
"humanize-duration": "^3.15.0",
|
||||||
"io-ts": "^2.0.0",
|
"io-ts": "^2.0.0",
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"knub": "^30.0.0-beta.46",
|
"knub": "^32.0.0-next.4",
|
||||||
"knub-command-manager": "^9.1.0",
|
"knub-command-manager": "^9.1.0",
|
||||||
"last-commit-log": "^2.1.0",
|
"last-commit-log": "^2.1.0",
|
||||||
"lodash.chunk": "^4.2.0",
|
"lodash.chunk": "^4.2.0",
|
||||||
|
@ -53,6 +52,7 @@
|
||||||
"tsconfig-paths": "^3.9.0",
|
"tsconfig-paths": "^3.9.0",
|
||||||
"twemoji": "^12.1.4",
|
"twemoji": "^12.1.4",
|
||||||
"typeorm": "^0.2.31",
|
"typeorm": "^0.2.31",
|
||||||
|
"typescript": "~4.9.5",
|
||||||
"utf-8-validate": "^5.0.5",
|
"utf-8-validate": "^5.0.5",
|
||||||
"uuid": "^3.3.2",
|
"uuid": "^3.3.2",
|
||||||
"yawn-yaml": "github:dragory/yawn-yaml#string-number-fix-build",
|
"yawn-yaml": "github:dragory/yawn-yaml#string-number-fix-build",
|
||||||
|
@ -124,35 +124,73 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@discordjs/builders": {
|
"node_modules/@discordjs/builders": {
|
||||||
"version": "0.16.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.5.0.tgz",
|
||||||
"integrity": "sha512-9/NCiZrLivgRub2/kBc0Vm5pMBE5AUdYbdXsLu/yg9ANgvnaJ0bZKTY8yYnLbsEc/LYUP79lEIdC73qEYhWq7A==",
|
"integrity": "sha512-7XxT78mnNBPigHn2y6KAXkicxIBFtZREGWaRZ249EC1l6gBUEP8IyVY5JTciIjJArxkF+tg675aZvsTNTKBpmA==",
|
||||||
"deprecated": "no longer supported",
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@sapphire/shapeshift": "^3.5.1",
|
"@discordjs/formatters": "^0.2.0",
|
||||||
"discord-api-types": "^0.36.2",
|
"@discordjs/util": "^0.2.0",
|
||||||
|
"@sapphire/shapeshift": "^3.8.1",
|
||||||
|
"discord-api-types": "^0.37.35",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"ts-mixer": "^6.0.1",
|
"ts-mixer": "^6.0.3",
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.5.0"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.9.0"
|
"node": ">=16.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@discordjs/builders/node_modules/discord-api-types": {
|
|
||||||
"version": "0.36.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz",
|
|
||||||
"integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg=="
|
|
||||||
},
|
|
||||||
"node_modules/@discordjs/builders/node_modules/tslib": {
|
"node_modules/@discordjs/builders/node_modules/tslib": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||||
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||||
},
|
},
|
||||||
"node_modules/@discordjs/collection": {
|
"node_modules/@discordjs/collection": {
|
||||||
"version": "0.7.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.4.0.tgz",
|
||||||
"integrity": "sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA==",
|
"integrity": "sha512-hiOJyk2CPFf1+FL3a4VKCuu1f448LlROVuu8nLz1+jCOAPokUcdFAV+l4pd3B3h6uJlJQSASoZzrdyNdjdtfzQ==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/formatters": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-vn4oMSXuMZUm8ITqVOtvE7/fMMISj4cI5oLsR09PEQXHKeKDAMLltG/DWeeIs7Idfy6V8Fk3rn1e69h7NfzuNA==",
|
||||||
|
"dependencies": {
|
||||||
|
"discord-api-types": "^0.37.35"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/rest": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-HGvqNCZ5Z5j0tQHjmT1lFvE5ETO4hvomJ1r0cbnpC1zM23XhCpZ9wgTCiEmaxKz05cyf2CI9p39+9LL+6Yz1bA==",
|
||||||
|
"dependencies": {
|
||||||
|
"@discordjs/collection": "^1.4.0",
|
||||||
|
"@discordjs/util": "^0.2.0",
|
||||||
|
"@sapphire/async-queue": "^1.5.0",
|
||||||
|
"@sapphire/snowflake": "^3.4.0",
|
||||||
|
"discord-api-types": "^0.37.35",
|
||||||
|
"file-type": "^18.2.1",
|
||||||
|
"tslib": "^2.5.0",
|
||||||
|
"undici": "^5.20.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16.9.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/rest/node_modules/tslib": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||||
|
},
|
||||||
|
"node_modules/@discordjs/util": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-/8qNbebFzLWKOOg+UV+RB8itp4SmU5jw0tBUD3ifElW6rYNOj1Ku5JaSW7lLl/WgjjxF01l/1uQPCzkwr110vg==",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.9.0"
|
"node": ">=16.9.0"
|
||||||
}
|
}
|
||||||
|
@ -211,6 +249,15 @@
|
||||||
"npm": ">=7.0.0"
|
"npm": ">=7.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@sapphire/snowflake": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-zZxymtVO6zeXVMPds+6d7gv/OfnCc25M1Z+7ZLB0oPmeMTPeRWVPQSS16oDJy5ZsyCOLj7M6mbZml5gWXcVRNw==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=v14.0.0",
|
||||||
|
"npm": ">=7.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@silvia-odwyer/photon-node": {
|
"node_modules/@silvia-odwyer/photon-node": {
|
||||||
"version": "0.3.1",
|
"version": "0.3.1",
|
||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
|
@ -238,6 +285,11 @@
|
||||||
"node": ">=6"
|
"node": ">=6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@tokenizer/token": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="
|
||||||
|
},
|
||||||
"node_modules/@types/body-parser": {
|
"node_modules/@types/body-parser": {
|
||||||
"version": "1.17.1",
|
"version": "1.17.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -348,9 +400,10 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/node-fetch": {
|
"node_modules/@types/node-fetch": {
|
||||||
"version": "2.6.3",
|
"version": "2.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||||
"integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==",
|
"integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==",
|
||||||
|
"dev": true,
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"form-data": "^3.0.0"
|
"form-data": "^3.0.0"
|
||||||
|
@ -426,8 +479,9 @@
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/@types/ws": {
|
"node_modules/@types/ws": {
|
||||||
"version": "8.5.3",
|
"version": "8.5.4",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz",
|
||||||
|
"integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
|
@ -580,6 +634,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/asynckit": {
|
"node_modules/asynckit": {
|
||||||
"version": "0.4.0",
|
"version": "0.4.0",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
"node_modules/ava": {
|
"node_modules/ava": {
|
||||||
|
@ -1351,6 +1406,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/combined-stream": {
|
"node_modules/combined-stream": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"delayed-stream": "~1.0.0"
|
"delayed-stream": "~1.0.0"
|
||||||
|
@ -1642,6 +1698,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/delayed-stream": {
|
"node_modules/delayed-stream": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=0.4.0"
|
"node": ">=0.4.0"
|
||||||
|
@ -1698,46 +1755,37 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/discord-api-types": {
|
"node_modules/discord-api-types": {
|
||||||
"version": "0.33.4",
|
"version": "0.37.35",
|
||||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.4.tgz",
|
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.35.tgz",
|
||||||
"integrity": "sha512-Y6RMvXsHKiBgQhm/q5MgRieXc4Tzh5p/JuDyqreI48lmy+AQfO+g9Xhz0tuGBaN1FtsrLT7mD+lbFONPo5vdwA=="
|
"integrity": "sha512-iyKZ/82k7FX3lcmHiAvvWu5TmyfVo78RtghBV/YsehK6CID83k5SI03DKKopBcln+TiEIYw5MGgq7SJXSpNzMg=="
|
||||||
},
|
},
|
||||||
"node_modules/discord.js": {
|
"node_modules/discord.js": {
|
||||||
"version": "13.14.0",
|
"version": "14.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.8.0.tgz",
|
||||||
"integrity": "sha512-EXHAZmFHMf6qBHDsIANwSG792SYJpzEFv2nssfakyDqEn0HLxFLLXMaOxBtVohdkUMgtD+dzyeBlbDvAW/A0AA==",
|
"integrity": "sha512-UOxYtc/YnV7jAJ2gISluJyYeBw4e+j8gWn+IoqG8unaHAVuvZ13DdYN0M1f9fbUgUvSarV798inIrYFtDNDjwQ==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@discordjs/builders": "^0.16.0",
|
"@discordjs/builders": "^1.5.0",
|
||||||
"@discordjs/collection": "^0.7.0",
|
"@discordjs/collection": "^1.4.0",
|
||||||
"@sapphire/async-queue": "^1.5.0",
|
"@discordjs/formatters": "^0.2.0",
|
||||||
"@types/node-fetch": "^2.6.2",
|
"@discordjs/rest": "^1.6.0",
|
||||||
"@types/ws": "^8.5.3",
|
"@discordjs/util": "^0.2.0",
|
||||||
"discord-api-types": "^0.33.5",
|
"@sapphire/snowflake": "^3.4.0",
|
||||||
"form-data": "^4.0.0",
|
"@types/ws": "^8.5.4",
|
||||||
"node-fetch": "^2.6.7",
|
"discord-api-types": "^0.37.35",
|
||||||
"ws": "^8.9.0"
|
"fast-deep-equal": "^3.1.3",
|
||||||
|
"lodash.snakecase": "^4.1.1",
|
||||||
|
"tslib": "^2.5.0",
|
||||||
|
"undici": "^5.20.0",
|
||||||
|
"ws": "^8.12.1"
|
||||||
},
|
},
|
||||||
"engines": {
|
"engines": {
|
||||||
"node": ">=16.6.0",
|
"node": ">=16.9.0"
|
||||||
"npm": ">=7.0.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/discord.js/node_modules/discord-api-types": {
|
"node_modules/discord.js/node_modules/tslib": {
|
||||||
"version": "0.33.5",
|
"version": "2.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.5.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||||
"integrity": "sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg=="
|
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||||
},
|
|
||||||
"node_modules/discord.js/node_modules/form-data": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"license": "MIT",
|
|
||||||
"dependencies": {
|
|
||||||
"asynckit": "^0.4.0",
|
|
||||||
"combined-stream": "^1.0.8",
|
|
||||||
"mime-types": "^2.1.12"
|
|
||||||
},
|
|
||||||
"engines": {
|
|
||||||
"node": ">= 6"
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"node_modules/dot-prop": {
|
"node_modules/dot-prop": {
|
||||||
"version": "5.3.0",
|
"version": "5.3.0",
|
||||||
|
@ -2001,6 +2049,22 @@
|
||||||
"url": "https://github.com/sponsors/sindresorhus"
|
"url": "https://github.com/sponsors/sindresorhus"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/file-type": {
|
||||||
|
"version": "18.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz",
|
||||||
|
"integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==",
|
||||||
|
"dependencies": {
|
||||||
|
"readable-web-to-node-stream": "^3.0.2",
|
||||||
|
"strtok3": "^7.0.0",
|
||||||
|
"token-types": "^5.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"url": "https://github.com/sindresorhus/file-type?sponsor=1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/file-uri-to-path": {
|
"node_modules/file-uri-to-path": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
|
@ -2044,6 +2108,7 @@
|
||||||
},
|
},
|
||||||
"node_modules/form-data": {
|
"node_modules/form-data": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
|
"dev": true,
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
|
@ -2639,13 +2704,17 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/knub": {
|
"node_modules/knub": {
|
||||||
"version": "30.0.0-beta.46",
|
"version": "32.0.0-next.4",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/knub/-/knub-32.0.0-next.4.tgz",
|
||||||
|
"integrity": "sha512-ywZbwcGFSr4Erl/nEUDVmziQHXKVIykWtI2Z05DLt01YmxDS+rTO8l/E6LYx7ZL3m+f2DbtLH0HB8zaZb0pUag==",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"discord-api-types": "^0.22.0",
|
"discord.js": "^14.8.0",
|
||||||
"discord.js": "^13.0.1",
|
|
||||||
"knub-command-manager": "^9.1.0",
|
"knub-command-manager": "^9.1.0",
|
||||||
"ts-essentials": "^6.0.7"
|
"ts-essentials": "^9",
|
||||||
|
"zod": "^3.19.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=16"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/knub-command-manager": {
|
"node_modules/knub-command-manager": {
|
||||||
|
@ -2662,13 +2731,6 @@
|
||||||
"node": ">=8"
|
"node": ">=8"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/knub/node_modules/discord-api-types": {
|
|
||||||
"version": "0.22.0",
|
|
||||||
"license": "MIT",
|
|
||||||
"engines": {
|
|
||||||
"node": ">=12"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"node_modules/last-commit-log": {
|
"node_modules/last-commit-log": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
|
@ -2749,6 +2811,11 @@
|
||||||
"version": "4.4.0",
|
"version": "4.4.0",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
},
|
},
|
||||||
|
"node_modules/lodash.snakecase": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
|
||||||
|
},
|
||||||
"node_modules/log-symbols": {
|
"node_modules/log-symbols": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -3577,6 +3644,18 @@
|
||||||
"through": "~2.3"
|
"through": "~2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/peek-readable": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Borewit"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/picomatch": {
|
"node_modules/picomatch": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -3846,6 +3925,34 @@
|
||||||
"util-deprecate": "~1.0.1"
|
"util-deprecate": "~1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/readable-web-to-node-stream": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==",
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": "^3.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=8"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Borewit"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/readable-web-to-node-stream/node_modules/readable-stream": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
|
"dependencies": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">= 6"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/readdirp": {
|
"node_modules/readdirp": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -4344,6 +4451,22 @@
|
||||||
"node": ">=0.10.0"
|
"node": ">=0.10.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/strtok3": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tokenizer/token": "^0.3.0",
|
||||||
|
"peek-readable": "^5.0.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Borewit"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/supertap": {
|
"node_modules/supertap": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -4494,6 +4617,22 @@
|
||||||
"node": ">=0.6"
|
"node": ">=0.6"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/token-types": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==",
|
||||||
|
"dependencies": {
|
||||||
|
"@tokenizer/token": "^0.3.0",
|
||||||
|
"ieee754": "^1.2.1"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=14.16"
|
||||||
|
},
|
||||||
|
"funding": {
|
||||||
|
"type": "github",
|
||||||
|
"url": "https://github.com/sponsors/Borewit"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/tr46": {
|
"node_modules/tr46": {
|
||||||
"version": "0.0.3",
|
"version": "0.0.3",
|
||||||
"license": "MIT"
|
"license": "MIT"
|
||||||
|
@ -4508,10 +4647,11 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ts-essentials": {
|
"node_modules/ts-essentials": {
|
||||||
"version": "6.0.7",
|
"version": "9.3.1",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.3.1.tgz",
|
||||||
|
"integrity": "sha512-9CChSvQMyVRo29Vb1A2jbs+LKo3d/bAf+ndSaX0T8cEiy/HChVaRN/HY5DqUryZ8hZ6uol9bEgCnGmnDbwBR9Q==",
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"typescript": ">=3.7.0"
|
"typescript": ">=4.1.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/ts-mixer": {
|
"node_modules/ts-mixer": {
|
||||||
|
@ -4797,9 +4937,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/typescript": {
|
"node_modules/typescript": {
|
||||||
"version": "4.4.4",
|
"version": "4.9.5",
|
||||||
"license": "Apache-2.0",
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||||
"peer": true,
|
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g==",
|
||||||
"bin": {
|
"bin": {
|
||||||
"tsc": "bin/tsc",
|
"tsc": "bin/tsc",
|
||||||
"tsserver": "bin/tsserver"
|
"tsserver": "bin/tsserver"
|
||||||
|
@ -4811,6 +4951,36 @@
|
||||||
"node_modules/uid2": {
|
"node_modules/uid2": {
|
||||||
"version": "0.0.3"
|
"version": "0.0.3"
|
||||||
},
|
},
|
||||||
|
"node_modules/undici": {
|
||||||
|
"version": "5.20.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz",
|
||||||
|
"integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==",
|
||||||
|
"dependencies": {
|
||||||
|
"busboy": "^1.6.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=12.18"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici/node_modules/busboy": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
|
||||||
|
"dependencies": {
|
||||||
|
"streamsearch": "^1.1.0"
|
||||||
|
},
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.16.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"node_modules/undici/node_modules/streamsearch": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
|
||||||
|
"engines": {
|
||||||
|
"node": ">=10.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/unique-string": {
|
"node_modules/unique-string": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -5276,8 +5446,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/zod": {
|
"node_modules/zod": {
|
||||||
"version": "3.14.4",
|
"version": "3.21.4",
|
||||||
"license": "MIT",
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
|
||||||
|
"integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==",
|
||||||
"funding": {
|
"funding": {
|
||||||
"url": "https://github.com/sponsors/colinhacks"
|
"url": "https://github.com/sponsors/colinhacks"
|
||||||
}
|
}
|
||||||
|
@ -5318,22 +5489,19 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@discordjs/builders": {
|
"@discordjs/builders": {
|
||||||
"version": "0.16.0",
|
"version": "1.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-0.16.0.tgz",
|
"resolved": "https://registry.npmjs.org/@discordjs/builders/-/builders-1.5.0.tgz",
|
||||||
"integrity": "sha512-9/NCiZrLivgRub2/kBc0Vm5pMBE5AUdYbdXsLu/yg9ANgvnaJ0bZKTY8yYnLbsEc/LYUP79lEIdC73qEYhWq7A==",
|
"integrity": "sha512-7XxT78mnNBPigHn2y6KAXkicxIBFtZREGWaRZ249EC1l6gBUEP8IyVY5JTciIjJArxkF+tg675aZvsTNTKBpmA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@sapphire/shapeshift": "^3.5.1",
|
"@discordjs/formatters": "^0.2.0",
|
||||||
"discord-api-types": "^0.36.2",
|
"@discordjs/util": "^0.2.0",
|
||||||
|
"@sapphire/shapeshift": "^3.8.1",
|
||||||
|
"discord-api-types": "^0.37.35",
|
||||||
"fast-deep-equal": "^3.1.3",
|
"fast-deep-equal": "^3.1.3",
|
||||||
"ts-mixer": "^6.0.1",
|
"ts-mixer": "^6.0.3",
|
||||||
"tslib": "^2.4.0"
|
"tslib": "^2.5.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"discord-api-types": {
|
|
||||||
"version": "0.36.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.36.3.tgz",
|
|
||||||
"integrity": "sha512-bz/NDyG0KBo/tY14vSkrwQ/n3HKPf87a0WFW/1M9+tXYK+vp5Z5EksawfCWo2zkAc6o7CClc0eff1Pjrqznlwg=="
|
|
||||||
},
|
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "2.5.0",
|
"version": "2.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||||
|
@ -5342,9 +5510,44 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@discordjs/collection": {
|
"@discordjs/collection": {
|
||||||
"version": "0.7.0",
|
"version": "1.4.0",
|
||||||
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-0.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/@discordjs/collection/-/collection-1.4.0.tgz",
|
||||||
"integrity": "sha512-R5i8Wb8kIcBAFEPLLf7LVBQKBDYUL+ekb23sOgpkpyGT+V4P7V83wTxcsqmX+PbqHt4cEHn053uMWfRqh/Z/nA=="
|
"integrity": "sha512-hiOJyk2CPFf1+FL3a4VKCuu1f448LlROVuu8nLz1+jCOAPokUcdFAV+l4pd3B3h6uJlJQSASoZzrdyNdjdtfzQ=="
|
||||||
|
},
|
||||||
|
"@discordjs/formatters": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/formatters/-/formatters-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-vn4oMSXuMZUm8ITqVOtvE7/fMMISj4cI5oLsR09PEQXHKeKDAMLltG/DWeeIs7Idfy6V8Fk3rn1e69h7NfzuNA==",
|
||||||
|
"requires": {
|
||||||
|
"discord-api-types": "^0.37.35"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@discordjs/rest": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/rest/-/rest-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-HGvqNCZ5Z5j0tQHjmT1lFvE5ETO4hvomJ1r0cbnpC1zM23XhCpZ9wgTCiEmaxKz05cyf2CI9p39+9LL+6Yz1bA==",
|
||||||
|
"requires": {
|
||||||
|
"@discordjs/collection": "^1.4.0",
|
||||||
|
"@discordjs/util": "^0.2.0",
|
||||||
|
"@sapphire/async-queue": "^1.5.0",
|
||||||
|
"@sapphire/snowflake": "^3.4.0",
|
||||||
|
"discord-api-types": "^0.37.35",
|
||||||
|
"file-type": "^18.2.1",
|
||||||
|
"tslib": "^2.5.0",
|
||||||
|
"undici": "^5.20.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"tslib": {
|
||||||
|
"version": "2.5.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||||
|
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"@discordjs/util": {
|
||||||
|
"version": "0.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@discordjs/util/-/util-0.2.0.tgz",
|
||||||
|
"integrity": "sha512-/8qNbebFzLWKOOg+UV+RB8itp4SmU5jw0tBUD3ifElW6rYNOj1Ku5JaSW7lLl/WgjjxF01l/1uQPCzkwr110vg=="
|
||||||
},
|
},
|
||||||
"@nodelib/fs.scandir": {
|
"@nodelib/fs.scandir": {
|
||||||
"version": "2.1.3",
|
"version": "2.1.3",
|
||||||
|
@ -5380,6 +5583,11 @@
|
||||||
"lodash": "^4.17.21"
|
"lodash": "^4.17.21"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@sapphire/snowflake": {
|
||||||
|
"version": "3.4.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@sapphire/snowflake/-/snowflake-3.4.0.tgz",
|
||||||
|
"integrity": "sha512-zZxymtVO6zeXVMPds+6d7gv/OfnCc25M1Z+7ZLB0oPmeMTPeRWVPQSS16oDJy5ZsyCOLj7M6mbZml5gWXcVRNw=="
|
||||||
|
},
|
||||||
"@silvia-odwyer/photon-node": {
|
"@silvia-odwyer/photon-node": {
|
||||||
"version": "0.3.1"
|
"version": "0.3.1"
|
||||||
},
|
},
|
||||||
|
@ -5397,6 +5605,11 @@
|
||||||
"defer-to-connect": "^1.0.1"
|
"defer-to-connect": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@tokenizer/token": {
|
||||||
|
"version": "0.3.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
|
||||||
|
"integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A=="
|
||||||
|
},
|
||||||
"@types/body-parser": {
|
"@types/body-parser": {
|
||||||
"version": "1.17.1",
|
"version": "1.17.1",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -5491,9 +5704,10 @@
|
||||||
"version": "14.0.14"
|
"version": "14.0.14"
|
||||||
},
|
},
|
||||||
"@types/node-fetch": {
|
"@types/node-fetch": {
|
||||||
"version": "2.6.3",
|
"version": "2.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.3.tgz",
|
"resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.1.tgz",
|
||||||
"integrity": "sha512-ETTL1mOEdq/sxUtgtOhKjyB2Irra4cjxksvcMUR5Zr4n+PxVhsCD9WS46oPbHL3et9Zde7CNRr+WUNlcHvsX+w==",
|
"integrity": "sha512-oMqjURCaxoSIsHSr1E47QHzbmzNR5rK8McHuNb11BOM9cHcIK3Avy0s/b2JlXHoQGTYS3NsvWzV1M0iK7l0wbA==",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/node": "*",
|
"@types/node": "*",
|
||||||
"form-data": "^3.0.0"
|
"form-data": "^3.0.0"
|
||||||
|
@ -5559,7 +5773,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@types/ws": {
|
"@types/ws": {
|
||||||
"version": "8.5.3",
|
"version": "8.5.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.4.tgz",
|
||||||
|
"integrity": "sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@types/node": "*"
|
"@types/node": "*"
|
||||||
}
|
}
|
||||||
|
@ -5651,7 +5867,8 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"asynckit": {
|
"asynckit": {
|
||||||
"version": "0.4.0"
|
"version": "0.4.0",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"ava": {
|
"ava": {
|
||||||
"version": "3.15.0",
|
"version": "3.15.0",
|
||||||
|
@ -6146,6 +6363,7 @@
|
||||||
},
|
},
|
||||||
"combined-stream": {
|
"combined-stream": {
|
||||||
"version": "1.0.8",
|
"version": "1.0.8",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"delayed-stream": "~1.0.0"
|
"delayed-stream": "~1.0.0"
|
||||||
}
|
}
|
||||||
|
@ -6337,7 +6555,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"delayed-stream": {
|
"delayed-stream": {
|
||||||
"version": "1.0.0"
|
"version": "1.0.0",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"depd": {
|
"depd": {
|
||||||
"version": "1.1.2"
|
"version": "1.1.2"
|
||||||
|
@ -6377,38 +6596,34 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"discord-api-types": {
|
"discord-api-types": {
|
||||||
"version": "0.33.4",
|
"version": "0.37.35",
|
||||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.4.tgz",
|
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.37.35.tgz",
|
||||||
"integrity": "sha512-Y6RMvXsHKiBgQhm/q5MgRieXc4Tzh5p/JuDyqreI48lmy+AQfO+g9Xhz0tuGBaN1FtsrLT7mD+lbFONPo5vdwA=="
|
"integrity": "sha512-iyKZ/82k7FX3lcmHiAvvWu5TmyfVo78RtghBV/YsehK6CID83k5SI03DKKopBcln+TiEIYw5MGgq7SJXSpNzMg=="
|
||||||
},
|
},
|
||||||
"discord.js": {
|
"discord.js": {
|
||||||
"version": "13.14.0",
|
"version": "14.8.0",
|
||||||
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-13.14.0.tgz",
|
"resolved": "https://registry.npmjs.org/discord.js/-/discord.js-14.8.0.tgz",
|
||||||
"integrity": "sha512-EXHAZmFHMf6qBHDsIANwSG792SYJpzEFv2nssfakyDqEn0HLxFLLXMaOxBtVohdkUMgtD+dzyeBlbDvAW/A0AA==",
|
"integrity": "sha512-UOxYtc/YnV7jAJ2gISluJyYeBw4e+j8gWn+IoqG8unaHAVuvZ13DdYN0M1f9fbUgUvSarV798inIrYFtDNDjwQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"@discordjs/builders": "^0.16.0",
|
"@discordjs/builders": "^1.5.0",
|
||||||
"@discordjs/collection": "^0.7.0",
|
"@discordjs/collection": "^1.4.0",
|
||||||
"@sapphire/async-queue": "^1.5.0",
|
"@discordjs/formatters": "^0.2.0",
|
||||||
"@types/node-fetch": "^2.6.2",
|
"@discordjs/rest": "^1.6.0",
|
||||||
"@types/ws": "^8.5.3",
|
"@discordjs/util": "^0.2.0",
|
||||||
"discord-api-types": "^0.33.5",
|
"@sapphire/snowflake": "^3.4.0",
|
||||||
"form-data": "^4.0.0",
|
"@types/ws": "^8.5.4",
|
||||||
"node-fetch": "^2.6.7",
|
"discord-api-types": "^0.37.35",
|
||||||
"ws": "^8.9.0"
|
"fast-deep-equal": "^3.1.3",
|
||||||
|
"lodash.snakecase": "^4.1.1",
|
||||||
|
"tslib": "^2.5.0",
|
||||||
|
"undici": "^5.20.0",
|
||||||
|
"ws": "^8.12.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"discord-api-types": {
|
"tslib": {
|
||||||
"version": "0.33.5",
|
"version": "2.5.0",
|
||||||
"resolved": "https://registry.npmjs.org/discord-api-types/-/discord-api-types-0.33.5.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
|
||||||
"integrity": "sha512-dvO5M52v7m7Dy96+XUnzXNsQ/0npsYpU6dL205kAtEDueswoz3aU3bh1UMoK4cQmcGtB1YRyLKqp+DXi05lzFg=="
|
"integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg=="
|
||||||
},
|
|
||||||
"form-data": {
|
|
||||||
"version": "4.0.0",
|
|
||||||
"requires": {
|
|
||||||
"asynckit": "^0.4.0",
|
|
||||||
"combined-stream": "^1.0.8",
|
|
||||||
"mime-types": "^2.1.12"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -6588,6 +6803,16 @@
|
||||||
"escape-string-regexp": "^1.0.5"
|
"escape-string-regexp": "^1.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"file-type": {
|
||||||
|
"version": "18.2.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/file-type/-/file-type-18.2.1.tgz",
|
||||||
|
"integrity": "sha512-Yw5MtnMv7vgD2/6Bjmmuegc8bQEVA9GmAyaR18bMYWKqsWDG9wgYZ1j4I6gNMF5Y5JBDcUcjRQqNQx7Y8uotcg==",
|
||||||
|
"requires": {
|
||||||
|
"readable-web-to-node-stream": "^3.0.2",
|
||||||
|
"strtok3": "^7.0.0",
|
||||||
|
"token-types": "^5.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"file-uri-to-path": {
|
"file-uri-to-path": {
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
},
|
},
|
||||||
|
@ -6618,6 +6843,7 @@
|
||||||
},
|
},
|
||||||
"form-data": {
|
"form-data": {
|
||||||
"version": "3.0.1",
|
"version": "3.0.1",
|
||||||
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"asynckit": "^0.4.0",
|
"asynckit": "^0.4.0",
|
||||||
"combined-stream": "^1.0.8",
|
"combined-stream": "^1.0.8",
|
||||||
|
@ -6975,17 +7201,14 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"knub": {
|
"knub": {
|
||||||
"version": "30.0.0-beta.46",
|
"version": "32.0.0-next.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/knub/-/knub-32.0.0-next.4.tgz",
|
||||||
|
"integrity": "sha512-ywZbwcGFSr4Erl/nEUDVmziQHXKVIykWtI2Z05DLt01YmxDS+rTO8l/E6LYx7ZL3m+f2DbtLH0HB8zaZb0pUag==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"discord-api-types": "^0.22.0",
|
"discord.js": "^14.8.0",
|
||||||
"discord.js": "^13.0.1",
|
|
||||||
"knub-command-manager": "^9.1.0",
|
"knub-command-manager": "^9.1.0",
|
||||||
"ts-essentials": "^6.0.7"
|
"ts-essentials": "^9",
|
||||||
},
|
"zod": "^3.19.1"
|
||||||
"dependencies": {
|
|
||||||
"discord-api-types": {
|
|
||||||
"version": "0.22.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"knub-command-manager": {
|
"knub-command-manager": {
|
||||||
|
@ -7055,6 +7278,11 @@
|
||||||
"lodash.pick": {
|
"lodash.pick": {
|
||||||
"version": "4.4.0"
|
"version": "4.4.0"
|
||||||
},
|
},
|
||||||
|
"lodash.snakecase": {
|
||||||
|
"version": "4.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/lodash.snakecase/-/lodash.snakecase-4.1.1.tgz",
|
||||||
|
"integrity": "sha512-QZ1d4xoBHYUeuouhEq3lk3Uq7ldgyFXGBhg04+oRLnIz8o9T65Eh+8YdroUwn846zchkA9yDsDl5CVVaV2nqYw=="
|
||||||
|
},
|
||||||
"log-symbols": {
|
"log-symbols": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -7556,6 +7784,11 @@
|
||||||
"through": "~2.3"
|
"through": "~2.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"peek-readable": {
|
||||||
|
"version": "5.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-5.0.0.tgz",
|
||||||
|
"integrity": "sha512-YtCKvLUOvwtMGmrniQPdO7MwPjgkFBtFIrmfSbYmYuq3tKDV/mcfAhBth1+C3ru7uXIZasc/pHnb+YDYNkkj4A=="
|
||||||
|
},
|
||||||
"picomatch": {
|
"picomatch": {
|
||||||
"version": "2.2.2",
|
"version": "2.2.2",
|
||||||
"dev": true
|
"dev": true
|
||||||
|
@ -7726,6 +7959,26 @@
|
||||||
"util-deprecate": "~1.0.1"
|
"util-deprecate": "~1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"readable-web-to-node-stream": {
|
||||||
|
"version": "3.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.2.tgz",
|
||||||
|
"integrity": "sha512-ePeK6cc1EcKLEhJFt/AebMCLL+GgSKhuygrZ/GLaKZYEecIgIECf4UaUuaByiGtzckwR4ain9VzUh95T1exYGw==",
|
||||||
|
"requires": {
|
||||||
|
"readable-stream": "^3.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"readable-stream": {
|
||||||
|
"version": "3.6.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
|
||||||
|
"integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
|
||||||
|
"requires": {
|
||||||
|
"inherits": "^2.0.3",
|
||||||
|
"string_decoder": "^1.1.1",
|
||||||
|
"util-deprecate": "^1.0.1"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"readdirp": {
|
"readdirp": {
|
||||||
"version": "3.6.0",
|
"version": "3.6.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -8052,6 +8305,15 @@
|
||||||
"version": "2.0.1",
|
"version": "2.0.1",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"strtok3": {
|
||||||
|
"version": "7.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/strtok3/-/strtok3-7.0.0.tgz",
|
||||||
|
"integrity": "sha512-pQ+V+nYQdC5H3Q7qBZAz/MO6lwGhoC2gOAjuouGf/VO0m7vQRh8QNMl2Uf6SwAtzZ9bOw3UIeBukEGNJl5dtXQ==",
|
||||||
|
"requires": {
|
||||||
|
"@tokenizer/token": "^0.3.0",
|
||||||
|
"peek-readable": "^5.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"supertap": {
|
"supertap": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -8145,6 +8407,15 @@
|
||||||
"toidentifier": {
|
"toidentifier": {
|
||||||
"version": "1.0.0"
|
"version": "1.0.0"
|
||||||
},
|
},
|
||||||
|
"token-types": {
|
||||||
|
"version": "5.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/token-types/-/token-types-5.0.1.tgz",
|
||||||
|
"integrity": "sha512-Y2fmSnZjQdDb9W4w4r1tswlMHylzWIeOKpx0aZH9BgGtACHhrk3OkT52AzwcuqTRBZtvvnTjDBh8eynMulu8Vg==",
|
||||||
|
"requires": {
|
||||||
|
"@tokenizer/token": "^0.3.0",
|
||||||
|
"ieee754": "^1.2.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"tr46": {
|
"tr46": {
|
||||||
"version": "0.0.3"
|
"version": "0.0.3"
|
||||||
},
|
},
|
||||||
|
@ -8155,7 +8426,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"ts-essentials": {
|
"ts-essentials": {
|
||||||
"version": "6.0.7",
|
"version": "9.3.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/ts-essentials/-/ts-essentials-9.3.1.tgz",
|
||||||
|
"integrity": "sha512-9CChSvQMyVRo29Vb1A2jbs+LKo3d/bAf+ndSaX0T8cEiy/HChVaRN/HY5DqUryZ8hZ6uol9bEgCnGmnDbwBR9Q==",
|
||||||
"requires": {}
|
"requires": {}
|
||||||
},
|
},
|
||||||
"ts-mixer": {
|
"ts-mixer": {
|
||||||
|
@ -8333,12 +8606,36 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"typescript": {
|
"typescript": {
|
||||||
"version": "4.4.4",
|
"version": "4.9.5",
|
||||||
"peer": true
|
"resolved": "https://registry.npmjs.org/typescript/-/typescript-4.9.5.tgz",
|
||||||
|
"integrity": "sha512-1FXk9E2Hm+QzZQ7z+McJiHL4NW1F2EzMu9Nq9i3zAaGqibafqYwCVU6WyWAuyQRRzOlxou8xZSyXLEN8oKj24g=="
|
||||||
},
|
},
|
||||||
"uid2": {
|
"uid2": {
|
||||||
"version": "0.0.3"
|
"version": "0.0.3"
|
||||||
},
|
},
|
||||||
|
"undici": {
|
||||||
|
"version": "5.20.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/undici/-/undici-5.20.0.tgz",
|
||||||
|
"integrity": "sha512-J3j60dYzuo6Eevbawwp1sdg16k5Tf768bxYK4TUJRH7cBM4kFCbf3mOnM/0E3vQYXvpxITbbWmBafaDbxLDz3g==",
|
||||||
|
"requires": {
|
||||||
|
"busboy": "^1.6.0"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"busboy": {
|
||||||
|
"version": "1.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
|
||||||
|
"integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
|
||||||
|
"requires": {
|
||||||
|
"streamsearch": "^1.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"streamsearch": {
|
||||||
|
"version": "1.1.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
|
||||||
|
"integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"unique-string": {
|
"unique-string": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
|
@ -8631,7 +8928,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"zod": {
|
"zod": {
|
||||||
"version": "3.14.4"
|
"version": "3.21.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/zod/-/zod-3.21.4.tgz",
|
||||||
|
"integrity": "sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw=="
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,8 +28,7 @@
|
||||||
"cors": "^2.8.5",
|
"cors": "^2.8.5",
|
||||||
"cross-env": "^5.2.0",
|
"cross-env": "^5.2.0",
|
||||||
"deep-diff": "^1.0.2",
|
"deep-diff": "^1.0.2",
|
||||||
"discord-api-types": "^0.33.1",
|
"discord.js": "^14.8.0",
|
||||||
"discord.js": "^13.14.0",
|
|
||||||
"dotenv": "^4.0.0",
|
"dotenv": "^4.0.0",
|
||||||
"emoji-regex": "^8.0.0",
|
"emoji-regex": "^8.0.0",
|
||||||
"erlpack": "github:discord/erlpack",
|
"erlpack": "github:discord/erlpack",
|
||||||
|
@ -39,7 +38,7 @@
|
||||||
"humanize-duration": "^3.15.0",
|
"humanize-duration": "^3.15.0",
|
||||||
"io-ts": "^2.0.0",
|
"io-ts": "^2.0.0",
|
||||||
"js-yaml": "^3.13.1",
|
"js-yaml": "^3.13.1",
|
||||||
"knub": "^30.0.0-beta.46",
|
"knub": "^32.0.0-next.4",
|
||||||
"knub-command-manager": "^9.1.0",
|
"knub-command-manager": "^9.1.0",
|
||||||
"last-commit-log": "^2.1.0",
|
"last-commit-log": "^2.1.0",
|
||||||
"lodash.chunk": "^4.2.0",
|
"lodash.chunk": "^4.2.0",
|
||||||
|
@ -68,6 +67,7 @@
|
||||||
"tsconfig-paths": "^3.9.0",
|
"tsconfig-paths": "^3.9.0",
|
||||||
"twemoji": "^12.1.4",
|
"twemoji": "^12.1.4",
|
||||||
"typeorm": "^0.2.31",
|
"typeorm": "^0.2.31",
|
||||||
|
"typescript": "~4.9.5",
|
||||||
"utf-8-validate": "^5.0.5",
|
"utf-8-validate": "^5.0.5",
|
||||||
"uuid": "^3.3.2",
|
"uuid": "^3.3.2",
|
||||||
"yawn-yaml": "github:dragory/yawn-yaml#string-number-fix-build",
|
"yawn-yaml": "github:dragory/yawn-yaml#string-number-fix-build",
|
||||||
|
|
|
@ -8,8 +8,8 @@ import { ApiLogins } from "../data/ApiLogins";
|
||||||
import { ApiPermissionAssignments } from "../data/ApiPermissionAssignments";
|
import { ApiPermissionAssignments } from "../data/ApiPermissionAssignments";
|
||||||
import { ApiUserInfo } from "../data/ApiUserInfo";
|
import { ApiUserInfo } from "../data/ApiUserInfo";
|
||||||
import { ApiUserInfoData } from "../data/entities/ApiUserInfo";
|
import { ApiUserInfoData } from "../data/entities/ApiUserInfo";
|
||||||
import { ok } from "./responses";
|
|
||||||
import { env } from "../env";
|
import { env } from "../env";
|
||||||
|
import { ok } from "./responses";
|
||||||
|
|
||||||
interface IPassportApiUser {
|
interface IPassportApiUser {
|
||||||
apiKey: string;
|
apiKey: string;
|
||||||
|
|
|
@ -56,7 +56,7 @@ export function initDocs(app: express.Express) {
|
||||||
const name = plugin.name;
|
const name = plugin.name;
|
||||||
const info = plugin.info || {};
|
const info = plugin.info || {};
|
||||||
|
|
||||||
const commands = (plugin.commands || []).map((cmd) => ({
|
const commands = (plugin.messageCommands || []).map((cmd) => ({
|
||||||
trigger: cmd.trigger,
|
trigger: cmd.trigger,
|
||||||
permission: cmd.permission,
|
permission: cmd.permission,
|
||||||
signature: cmd.signature,
|
signature: cmd.signature,
|
||||||
|
@ -66,7 +66,7 @@ export function initDocs(app: express.Express) {
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const defaultOptions = plugin.defaultOptions || {};
|
const defaultOptions = plugin.defaultOptions || {};
|
||||||
const configSchema = plugin.configSchema && formatConfigSchema(plugin.configSchema);
|
const configSchema = plugin.info?.configSchema && formatConfigSchema(plugin.info.configSchema);
|
||||||
|
|
||||||
res.json({
|
res.json({
|
||||||
name,
|
name,
|
||||||
|
|
|
@ -1,20 +1,20 @@
|
||||||
import { ApiPermissions } from "@shared/apiPermissions";
|
import { ApiPermissions } from "@shared/apiPermissions";
|
||||||
import express, { Request, Response } from "express";
|
import express, { Request, Response } from "express";
|
||||||
import { YAMLException } from "js-yaml";
|
import { YAMLException } from "js-yaml";
|
||||||
|
import moment from "moment-timezone";
|
||||||
import { validateGuildConfig } from "../configValidator";
|
import { validateGuildConfig } from "../configValidator";
|
||||||
import { AllowedGuilds } from "../data/AllowedGuilds";
|
import { AllowedGuilds } from "../data/AllowedGuilds";
|
||||||
|
import { ApiAuditLog } from "../data/ApiAuditLog";
|
||||||
|
import { AuditLogEventTypes } from "../data/apiAuditLogTypes";
|
||||||
import { ApiPermissionAssignments, ApiPermissionTypes } from "../data/ApiPermissionAssignments";
|
import { ApiPermissionAssignments, ApiPermissionTypes } from "../data/ApiPermissionAssignments";
|
||||||
import { Configs } from "../data/Configs";
|
import { Configs } from "../data/Configs";
|
||||||
|
import { Queue } from "../Queue";
|
||||||
|
import { isSnowflake } from "../utils";
|
||||||
|
import { loadYamlSafely } from "../utils/loadYamlSafely";
|
||||||
|
import { ObjectAliasError } from "../utils/validateNoObjectAliases";
|
||||||
import { apiTokenAuthHandlers } from "./auth";
|
import { apiTokenAuthHandlers } from "./auth";
|
||||||
import { hasGuildPermission, requireGuildPermission } from "./permissions";
|
import { hasGuildPermission, requireGuildPermission } from "./permissions";
|
||||||
import { clientError, ok, serverError, unauthorized } from "./responses";
|
import { clientError, ok, serverError, unauthorized } from "./responses";
|
||||||
import { loadYamlSafely } from "../utils/loadYamlSafely";
|
|
||||||
import { ObjectAliasError } from "../utils/validateNoObjectAliases";
|
|
||||||
import { isSnowflake } from "../utils";
|
|
||||||
import moment from "moment-timezone";
|
|
||||||
import { ApiAuditLog } from "../data/ApiAuditLog";
|
|
||||||
import { AuditLogEventTypes } from "../data/apiAuditLogTypes";
|
|
||||||
import { Queue } from "../Queue";
|
|
||||||
|
|
||||||
const apiPermissionAssignments = new ApiPermissionAssignments();
|
const apiPermissionAssignments = new ApiPermissionAssignments();
|
||||||
const auditLog = new ApiAuditLog();
|
const auditLog = new ApiAuditLog();
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { ApiPermissions } from "@shared/apiPermissions";
|
import { ApiPermissions } from "@shared/apiPermissions";
|
||||||
import express, { Request, Response } from "express";
|
import express, { Request, Response } from "express";
|
||||||
import { requireGuildPermission } from "../permissions";
|
import moment from "moment-timezone";
|
||||||
import { clientError, ok } from "../responses";
|
|
||||||
import { GuildCases } from "../../data/GuildCases";
|
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
import { Case } from "../../data/entities/Case";
|
import { Case } from "../../data/entities/Case";
|
||||||
import { rateLimit } from "../rateLimits";
|
import { GuildCases } from "../../data/GuildCases";
|
||||||
import { MINUTES } from "../../utils";
|
import { MINUTES } from "../../utils";
|
||||||
import moment from "moment-timezone";
|
import { requireGuildPermission } from "../permissions";
|
||||||
|
import { rateLimit } from "../rateLimits";
|
||||||
|
import { clientError, ok } from "../responses";
|
||||||
|
|
||||||
const caseHandlingModeSchema = z.union([
|
const caseHandlingModeSchema = z.union([
|
||||||
z.literal("replace"),
|
z.literal("replace"),
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import express from "express";
|
import express from "express";
|
||||||
import { apiTokenAuthHandlers } from "../auth";
|
import { apiTokenAuthHandlers } from "../auth";
|
||||||
import { initGuildsMiscAPI } from "./misc";
|
|
||||||
import { initGuildsImportExportAPI } from "./importExport";
|
import { initGuildsImportExportAPI } from "./importExport";
|
||||||
|
import { initGuildsMiscAPI } from "./misc";
|
||||||
|
|
||||||
export function initGuildsAPI(app: express.Express) {
|
export function initGuildsAPI(app: express.Express) {
|
||||||
const guildRouter = express.Router();
|
const guildRouter = express.Router();
|
||||||
|
|
|
@ -1,22 +1,19 @@
|
||||||
import { ApiPermissions } from "@shared/apiPermissions";
|
import { ApiPermissions } from "@shared/apiPermissions";
|
||||||
import express, { Request, Response } from "express";
|
import express, { Request, Response } from "express";
|
||||||
import { YAMLException } from "js-yaml";
|
import { YAMLException } from "js-yaml";
|
||||||
|
import moment from "moment-timezone";
|
||||||
import { validateGuildConfig } from "../../configValidator";
|
import { validateGuildConfig } from "../../configValidator";
|
||||||
import { AllowedGuilds } from "../../data/AllowedGuilds";
|
import { AllowedGuilds } from "../../data/AllowedGuilds";
|
||||||
import { ApiPermissionAssignments, ApiPermissionTypes } from "../../data/ApiPermissionAssignments";
|
|
||||||
import { Configs } from "../../data/Configs";
|
|
||||||
import { apiTokenAuthHandlers } from "../auth";
|
|
||||||
import { hasGuildPermission, requireGuildPermission } from "../permissions";
|
|
||||||
import { clientError, ok, serverError, unauthorized } from "../responses";
|
|
||||||
import { loadYamlSafely } from "../../utils/loadYamlSafely";
|
|
||||||
import { ObjectAliasError } from "../../utils/validateNoObjectAliases";
|
|
||||||
import { isSnowflake } from "../../utils";
|
|
||||||
import moment from "moment-timezone";
|
|
||||||
import { ApiAuditLog } from "../../data/ApiAuditLog";
|
import { ApiAuditLog } from "../../data/ApiAuditLog";
|
||||||
import { AuditLogEventTypes } from "../../data/apiAuditLogTypes";
|
import { AuditLogEventTypes } from "../../data/apiAuditLogTypes";
|
||||||
|
import { ApiPermissionAssignments, ApiPermissionTypes } from "../../data/ApiPermissionAssignments";
|
||||||
|
import { Configs } from "../../data/Configs";
|
||||||
import { Queue } from "../../Queue";
|
import { Queue } from "../../Queue";
|
||||||
import { GuildCases } from "../../data/GuildCases";
|
import { isSnowflake } from "../../utils";
|
||||||
import { z } from "zod";
|
import { loadYamlSafely } from "../../utils/loadYamlSafely";
|
||||||
|
import { ObjectAliasError } from "../../utils/validateNoObjectAliases";
|
||||||
|
import { hasGuildPermission, requireGuildPermission } from "../permissions";
|
||||||
|
import { clientError, ok, serverError, unauthorized } from "../responses";
|
||||||
|
|
||||||
const apiPermissionAssignments = new ApiPermissionAssignments();
|
const apiPermissionAssignments = new ApiPermissionAssignments();
|
||||||
const auditLog = new ApiAuditLog();
|
const auditLog = new ApiAuditLog();
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { connect } from "../data/db";
|
import { connect } from "../data/db";
|
||||||
import { setIsAPI } from "../globals";
|
|
||||||
import { env } from "../env";
|
import { env } from "../env";
|
||||||
|
import { setIsAPI } from "../globals";
|
||||||
|
|
||||||
if (!env.KEY) {
|
if (!env.KEY) {
|
||||||
// tslint:disable-next-line:no-console
|
// tslint:disable-next-line:no-console
|
||||||
|
@ -20,5 +20,5 @@ setIsAPI(true);
|
||||||
// Connect to the database before loading the rest of the code (that depend on the database connection)
|
// Connect to the database before loading the rest of the code (that depend on the database connection)
|
||||||
console.log("Connecting to database..."); // tslint:disable-line
|
console.log("Connecting to database..."); // tslint:disable-line
|
||||||
connect().then(() => {
|
connect().then(() => {
|
||||||
import("./start");
|
import("./start.js");
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,14 +1,14 @@
|
||||||
import cors from "cors";
|
import cors from "cors";
|
||||||
import express from "express";
|
import express from "express";
|
||||||
|
import multer from "multer";
|
||||||
import { TokenError } from "passport-oauth2";
|
import { TokenError } from "passport-oauth2";
|
||||||
|
import { env } from "../env";
|
||||||
import { initArchives } from "./archives";
|
import { initArchives } from "./archives";
|
||||||
import { initAuth } from "./auth";
|
import { initAuth } from "./auth";
|
||||||
import { initDocs } from "./docs";
|
import { initDocs } from "./docs";
|
||||||
import { initGuildsAPI } from "./guilds/index";
|
import { initGuildsAPI } from "./guilds/index";
|
||||||
import { clientError, error, notFound } from "./responses";
|
import { clientError, error, notFound } from "./responses";
|
||||||
import { startBackgroundTasks } from "./tasks";
|
import { startBackgroundTasks } from "./tasks";
|
||||||
import multer from "multer";
|
|
||||||
import { env } from "../env";
|
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,18 @@
|
||||||
import { GuildChannel, GuildMember, Snowflake, Util, User, GuildTextBasedChannel } from "discord.js";
|
import {
|
||||||
import { baseCommandParameterTypeHelpers, baseTypeConverters, CommandContext, TypeConversionError } from "knub";
|
escapeCodeBlock,
|
||||||
|
escapeInlineCode,
|
||||||
|
GuildChannel,
|
||||||
|
GuildMember,
|
||||||
|
GuildTextBasedChannel,
|
||||||
|
Snowflake,
|
||||||
|
User,
|
||||||
|
} from "discord.js";
|
||||||
|
import {
|
||||||
|
baseCommandParameterTypeHelpers,
|
||||||
|
CommandContext,
|
||||||
|
messageCommandBaseTypeConverters,
|
||||||
|
TypeConversionError,
|
||||||
|
} from "knub";
|
||||||
import { createTypeHelper } from "knub-command-manager";
|
import { createTypeHelper } from "knub-command-manager";
|
||||||
import {
|
import {
|
||||||
channelMentionRegex,
|
channelMentionRegex,
|
||||||
|
@ -14,11 +27,9 @@ import {
|
||||||
import { isValidTimezone } from "./utils/isValidTimezone";
|
import { isValidTimezone } from "./utils/isValidTimezone";
|
||||||
import { MessageTarget, resolveMessageTarget } from "./utils/resolveMessageTarget";
|
import { MessageTarget, resolveMessageTarget } from "./utils/resolveMessageTarget";
|
||||||
import { inputPatternToRegExp } from "./validatorUtils";
|
import { inputPatternToRegExp } from "./validatorUtils";
|
||||||
import { getChannelId } from "knub/dist/utils";
|
|
||||||
import { disableCodeBlocks } from "knub/dist/helpers";
|
|
||||||
|
|
||||||
export const commandTypes = {
|
export const commandTypes = {
|
||||||
...baseTypeConverters,
|
...messageCommandBaseTypeConverters,
|
||||||
|
|
||||||
delay(value) {
|
delay(value) {
|
||||||
const result = convertDelayStringToMS(value);
|
const result = convertDelayStringToMS(value);
|
||||||
|
@ -32,7 +43,7 @@ export const commandTypes = {
|
||||||
async resolvedUser(value, context: CommandContext<any>) {
|
async resolvedUser(value, context: CommandContext<any>) {
|
||||||
const result = await resolveUser(context.pluginData.client, value);
|
const result = await resolveUser(context.pluginData.client, value);
|
||||||
if (result == null || result instanceof UnknownUser) {
|
if (result == null || result instanceof UnknownUser) {
|
||||||
throw new TypeConversionError(`User \`${Util.escapeCodeBlock(value)}\` was not found`);
|
throw new TypeConversionError(`User \`${escapeCodeBlock(value)}\` was not found`);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
@ -40,7 +51,7 @@ export const commandTypes = {
|
||||||
async resolvedUserLoose(value, context: CommandContext<any>) {
|
async resolvedUserLoose(value, context: CommandContext<any>) {
|
||||||
const result = await resolveUser(context.pluginData.client, value);
|
const result = await resolveUser(context.pluginData.client, value);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
throw new TypeConversionError(`Invalid user: \`${Util.escapeCodeBlock(value)}\``);
|
throw new TypeConversionError(`Invalid user: \`${escapeCodeBlock(value)}\``);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
@ -52,9 +63,7 @@ export const commandTypes = {
|
||||||
|
|
||||||
const result = await resolveMember(context.pluginData.client, context.message.channel.guild, value);
|
const result = await resolveMember(context.pluginData.client, context.message.channel.guild, value);
|
||||||
if (result == null) {
|
if (result == null) {
|
||||||
throw new TypeConversionError(
|
throw new TypeConversionError(`Member \`${escapeCodeBlock(value)}\` was not found or they have left the server`);
|
||||||
`Member \`${Util.escapeCodeBlock(value)}\` was not found or they have left the server`,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
},
|
},
|
||||||
|
@ -64,7 +73,7 @@ export const commandTypes = {
|
||||||
|
|
||||||
const result = await resolveMessageTarget(context.pluginData, value);
|
const result = await resolveMessageTarget(context.pluginData, value);
|
||||||
if (!result) {
|
if (!result) {
|
||||||
throw new TypeConversionError(`Unknown message \`${Util.escapeInlineCode(value)}\``);
|
throw new TypeConversionError(`Unknown message \`${escapeInlineCode(value)}\``);
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
|
@ -84,28 +93,27 @@ export const commandTypes = {
|
||||||
return value as Snowflake;
|
return value as Snowflake;
|
||||||
}
|
}
|
||||||
|
|
||||||
throw new TypeConversionError(`Could not parse ID: \`${Util.escapeInlineCode(value)}\``);
|
throw new TypeConversionError(`Could not parse ID: \`${escapeInlineCode(value)}\``);
|
||||||
},
|
},
|
||||||
|
|
||||||
regex(value: string, context: CommandContext<any>): RegExp {
|
regex(value: string, context: CommandContext<any>): RegExp {
|
||||||
try {
|
try {
|
||||||
return inputPatternToRegExp(value);
|
return inputPatternToRegExp(value);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw new TypeConversionError(`Could not parse RegExp: \`${Util.escapeInlineCode(e.message)}\``);
|
throw new TypeConversionError(`Could not parse RegExp: \`${escapeInlineCode(e.message)}\``);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
timezone(value: string) {
|
timezone(value: string) {
|
||||||
if (!isValidTimezone(value)) {
|
if (!isValidTimezone(value)) {
|
||||||
throw new TypeConversionError(`Invalid timezone: ${Util.escapeInlineCode(value)}`);
|
throw new TypeConversionError(`Invalid timezone: ${escapeInlineCode(value)}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return value;
|
return value;
|
||||||
},
|
},
|
||||||
|
|
||||||
guildTextBasedChannel(value: string, context: CommandContext<any>) {
|
guildTextBasedChannel(value: string, context: CommandContext<any>) {
|
||||||
// FIXME: Remove once Knub's types have been fixed
|
return messageCommandBaseTypeConverters.textChannel(value, context);
|
||||||
return baseTypeConverters.textChannel(value, context) as GuildTextBasedChannel;
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { configUtils, ConfigValidationError, PluginOptions } from "knub";
|
import { ConfigValidationError, PluginConfigManager } from "knub";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { guildPlugins } from "./plugins/availablePlugins";
|
import { guildPlugins } from "./plugins/availablePlugins";
|
||||||
import { ZeppelinPlugin } from "./plugins/ZeppelinPlugin";
|
import { ZeppelinPlugin } from "./plugins/ZeppelinPlugin";
|
||||||
|
@ -34,9 +34,12 @@ export async function validateGuildConfig(config: any): Promise<string | null> {
|
||||||
}
|
}
|
||||||
|
|
||||||
const plugin = pluginNameToPlugin.get(pluginName)!;
|
const plugin = pluginNameToPlugin.get(pluginName)!;
|
||||||
|
const configManager = new PluginConfigManager(plugin.defaultOptions || { config: {} }, pluginOptions, {
|
||||||
|
levels: {},
|
||||||
|
parser: plugin.configParser,
|
||||||
|
});
|
||||||
try {
|
try {
|
||||||
const mergedOptions = configUtils.mergeConfig(plugin.defaultOptions || {}, pluginOptions);
|
await configManager.init();
|
||||||
await plugin.configPreprocessor?.(mergedOptions as unknown as PluginOptions<any>, true);
|
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err instanceof ConfigValidationError || err instanceof StrictValidationError) {
|
if (err instanceof ConfigValidationError || err instanceof StrictValidationError) {
|
||||||
return `${pluginName}: ${err.message}`;
|
return `${pluginName}: ${err.message}`;
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
|
import moment from "moment-timezone";
|
||||||
import { getRepository, Repository } from "typeorm";
|
import { getRepository, Repository } from "typeorm";
|
||||||
|
import { DBDateFormat } from "../utils";
|
||||||
import { ApiPermissionTypes } from "./ApiPermissionAssignments";
|
import { ApiPermissionTypes } from "./ApiPermissionAssignments";
|
||||||
import { BaseRepository } from "./BaseRepository";
|
import { BaseRepository } from "./BaseRepository";
|
||||||
import { AllowedGuild } from "./entities/AllowedGuild";
|
import { AllowedGuild } from "./entities/AllowedGuild";
|
||||||
import moment from "moment-timezone";
|
|
||||||
import { DBDateFormat } from "../utils";
|
|
||||||
import { env } from "../env";
|
|
||||||
|
|
||||||
export class AllowedGuilds extends BaseRepository {
|
export class AllowedGuilds extends BaseRepository {
|
||||||
private allowedGuilds: Repository<AllowedGuild>;
|
private allowedGuilds: Repository<AllowedGuild>;
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import { BaseRepository } from "./BaseRepository";
|
|
||||||
import { getRepository, Repository } from "typeorm/index";
|
import { getRepository, Repository } from "typeorm/index";
|
||||||
import { ApiAuditLogEntry } from "./entities/ApiAuditLogEntry";
|
|
||||||
import { ApiLogin } from "./entities/ApiLogin";
|
|
||||||
import { AuditLogEventData, AuditLogEventType } from "./apiAuditLogTypes";
|
import { AuditLogEventData, AuditLogEventType } from "./apiAuditLogTypes";
|
||||||
|
import { BaseRepository } from "./BaseRepository";
|
||||||
|
import { ApiAuditLogEntry } from "./entities/ApiAuditLogEntry";
|
||||||
|
|
||||||
export class ApiAuditLog extends BaseRepository {
|
export class ApiAuditLog extends BaseRepository {
|
||||||
private auditLog: Repository<ApiAuditLogEntry<any>>;
|
private auditLog: Repository<ApiAuditLogEntry<any>>;
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { ApiPermissions } from "@shared/apiPermissions";
|
import { ApiPermissions } from "@shared/apiPermissions";
|
||||||
import { getRepository, Repository } from "typeorm";
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { BaseRepository } from "./BaseRepository";
|
|
||||||
import { ApiPermissionAssignment } from "./entities/ApiPermissionAssignment";
|
|
||||||
import { Permissions } from "discord.js";
|
|
||||||
import { ApiAuditLog } from "./ApiAuditLog";
|
import { ApiAuditLog } from "./ApiAuditLog";
|
||||||
import { AuditLogEventTypes } from "./apiAuditLogTypes";
|
import { AuditLogEventTypes } from "./apiAuditLogTypes";
|
||||||
|
import { BaseRepository } from "./BaseRepository";
|
||||||
|
import { ApiPermissionAssignment } from "./entities/ApiPermissionAssignment";
|
||||||
|
|
||||||
export enum ApiPermissionTypes {
|
export enum ApiPermissionTypes {
|
||||||
User = "USER",
|
User = "USER",
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { getRepository, Repository } from "typeorm";
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { ArchiveEntry } from "./entities/ArchiveEntry";
|
|
||||||
import { BaseRepository } from "./BaseRepository";
|
import { BaseRepository } from "./BaseRepository";
|
||||||
|
import { ArchiveEntry } from "./entities/ArchiveEntry";
|
||||||
|
|
||||||
export class Archives extends BaseRepository {
|
export class Archives extends BaseRepository {
|
||||||
protected archives: Repository<ArchiveEntry>;
|
protected archives: Repository<ArchiveEntry>;
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
import { Guild, Snowflake, User } from "discord.js";
|
import { Guild, Snowflake } from "discord.js";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { isDefaultSticker } from "src/utils/isDefaultSticker";
|
import { isDefaultSticker } from "src/utils/isDefaultSticker";
|
||||||
import { getRepository, Repository } from "typeorm";
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { renderTemplate, TemplateSafeValueContainer } from "../templateFormatter";
|
import { renderTemplate, TemplateSafeValueContainer } from "../templateFormatter";
|
||||||
import { trimLines } from "../utils";
|
import { trimLines } from "../utils";
|
||||||
|
import { decrypt, encrypt } from "../utils/crypt";
|
||||||
|
import { channelToTemplateSafeChannel, guildToTemplateSafeGuild } from "../utils/templateSafeObjects";
|
||||||
import { BaseGuildRepository } from "./BaseGuildRepository";
|
import { BaseGuildRepository } from "./BaseGuildRepository";
|
||||||
import { ArchiveEntry } from "./entities/ArchiveEntry";
|
import { ArchiveEntry } from "./entities/ArchiveEntry";
|
||||||
import {
|
|
||||||
channelToTemplateSafeChannel,
|
|
||||||
guildToTemplateSafeGuild,
|
|
||||||
userToTemplateSafeUser,
|
|
||||||
} from "../utils/templateSafeObjects";
|
|
||||||
import { SavedMessage } from "./entities/SavedMessage";
|
import { SavedMessage } from "./entities/SavedMessage";
|
||||||
import { decrypt, encrypt } from "../utils/crypt";
|
|
||||||
|
|
||||||
const DEFAULT_EXPIRY_DAYS = 30;
|
const DEFAULT_EXPIRY_DAYS = 30;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,11 @@
|
||||||
import { getRepository, In, InsertResult, Repository } from "typeorm";
|
import { getRepository, In, InsertResult, Repository } from "typeorm";
|
||||||
|
import { Queue } from "../Queue";
|
||||||
|
import { chunkArray } from "../utils";
|
||||||
import { BaseGuildRepository } from "./BaseGuildRepository";
|
import { BaseGuildRepository } from "./BaseGuildRepository";
|
||||||
import { CaseTypes } from "./CaseTypes";
|
import { CaseTypes } from "./CaseTypes";
|
||||||
import { connection } from "./db";
|
import { connection } from "./db";
|
||||||
import { Case } from "./entities/Case";
|
import { Case } from "./entities/Case";
|
||||||
import { CaseNote } from "./entities/CaseNote";
|
import { CaseNote } from "./entities/CaseNote";
|
||||||
import moment from "moment-timezone";
|
|
||||||
import { chunkArray } from "../utils";
|
|
||||||
import { Queue } from "../Queue";
|
|
||||||
|
|
||||||
const CASE_SUMMARY_REASON_MAX_LENGTH = 300;
|
const CASE_SUMMARY_REASON_MAX_LENGTH = 300;
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Mute } from "./entities/Mute";
|
import { Mute } from "./entities/Mute";
|
||||||
import { ScheduledPost } from "./entities/ScheduledPost";
|
|
||||||
import { Reminder } from "./entities/Reminder";
|
import { Reminder } from "./entities/Reminder";
|
||||||
|
import { ScheduledPost } from "./entities/ScheduledPost";
|
||||||
import { Tempban } from "./entities/Tempban";
|
import { Tempban } from "./entities/Tempban";
|
||||||
import { VCAlert } from "./entities/VCAlert";
|
import { VCAlert } from "./entities/VCAlert";
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,5 @@
|
||||||
import { getRepository, Repository } from "typeorm";
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { Reminder } from "./entities/Reminder";
|
|
||||||
import { BaseRepository } from "./BaseRepository";
|
|
||||||
import moment from "moment-timezone";
|
|
||||||
import { DBDateFormat } from "../utils";
|
|
||||||
import { BaseGuildRepository } from "./BaseGuildRepository";
|
import { BaseGuildRepository } from "./BaseGuildRepository";
|
||||||
import { RoleQueueItem } from "./entities/RoleQueueItem";
|
|
||||||
import { connection } from "./db";
|
|
||||||
import { RoleButtonsItem } from "./entities/RoleButtonsItem";
|
import { RoleButtonsItem } from "./entities/RoleButtonsItem";
|
||||||
|
|
||||||
export class GuildRoleButtons extends BaseGuildRepository {
|
export class GuildRoleButtons extends BaseGuildRepository {
|
||||||
|
|
|
@ -1,11 +1,7 @@
|
||||||
import { getRepository, Repository } from "typeorm";
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { Reminder } from "./entities/Reminder";
|
|
||||||
import { BaseRepository } from "./BaseRepository";
|
|
||||||
import moment from "moment-timezone";
|
|
||||||
import { DBDateFormat } from "../utils";
|
|
||||||
import { BaseGuildRepository } from "./BaseGuildRepository";
|
import { BaseGuildRepository } from "./BaseGuildRepository";
|
||||||
import { RoleQueueItem } from "./entities/RoleQueueItem";
|
|
||||||
import { connection } from "./db";
|
import { connection } from "./db";
|
||||||
|
import { RoleQueueItem } from "./entities/RoleQueueItem";
|
||||||
|
|
||||||
export class GuildRoleQueue extends BaseGuildRepository {
|
export class GuildRoleQueue extends BaseGuildRepository {
|
||||||
private roleQueue: Repository<RoleQueueItem>;
|
private roleQueue: Repository<RoleQueueItem>;
|
||||||
|
|
|
@ -1,15 +1,13 @@
|
||||||
import { GuildChannel, Message } from "discord.js";
|
import { GuildChannel, Message } from "discord.js";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { getRepository, Repository } from "typeorm";
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { QueryDeepPartialEntity } from "typeorm/query-builder/QueryPartialEntity";
|
|
||||||
import { QueuedEventEmitter } from "../QueuedEventEmitter";
|
import { QueuedEventEmitter } from "../QueuedEventEmitter";
|
||||||
import { BaseGuildRepository } from "./BaseGuildRepository";
|
|
||||||
import { ISavedMessageData, SavedMessage } from "./entities/SavedMessage";
|
|
||||||
import { buildEntity } from "./buildEntity";
|
|
||||||
import { noop } from "../utils";
|
import { noop } from "../utils";
|
||||||
import { decrypt } from "../utils/crypt";
|
|
||||||
import { decryptJson, encryptJson } from "../utils/cryptHelpers";
|
|
||||||
import { asyncMap } from "../utils/async";
|
import { asyncMap } from "../utils/async";
|
||||||
|
import { decryptJson, encryptJson } from "../utils/cryptHelpers";
|
||||||
|
import { BaseGuildRepository } from "./BaseGuildRepository";
|
||||||
|
import { buildEntity } from "./buildEntity";
|
||||||
|
import { ISavedMessageData, SavedMessage } from "./entities/SavedMessage";
|
||||||
|
|
||||||
export class GuildSavedMessages extends BaseGuildRepository<SavedMessage> {
|
export class GuildSavedMessages extends BaseGuildRepository<SavedMessage> {
|
||||||
private messages: Repository<SavedMessage>;
|
private messages: Repository<SavedMessage>;
|
||||||
|
@ -53,13 +51,13 @@ export class GuildSavedMessages extends BaseGuildRepository<SavedMessage> {
|
||||||
title: embed.title,
|
title: embed.title,
|
||||||
description: embed.description,
|
description: embed.description,
|
||||||
url: embed.url,
|
url: embed.url,
|
||||||
timestamp: embed.timestamp,
|
timestamp: embed.timestamp ? Date.parse(embed.timestamp) : null,
|
||||||
color: embed.color,
|
color: embed.color,
|
||||||
|
|
||||||
fields: embed.fields.map((field) => ({
|
fields: embed.fields.map((field) => ({
|
||||||
name: field.name,
|
name: field.name,
|
||||||
value: field.value,
|
value: field.value,
|
||||||
inline: field.inline,
|
inline: field.inline ?? false,
|
||||||
})),
|
})),
|
||||||
|
|
||||||
author: embed.author
|
author: embed.author
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { Brackets, getRepository, Repository } from "typeorm";
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { Mute } from "./entities/Mute";
|
|
||||||
import { DAYS, DBDateFormat } from "../utils";
|
import { DAYS, DBDateFormat } from "../utils";
|
||||||
import { BaseRepository } from "./BaseRepository";
|
import { BaseRepository } from "./BaseRepository";
|
||||||
|
import { Mute } from "./entities/Mute";
|
||||||
|
|
||||||
const OLD_EXPIRED_MUTE_THRESHOLD = 7 * DAYS;
|
const OLD_EXPIRED_MUTE_THRESHOLD = 7 * DAYS;
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { getRepository, Repository } from "typeorm";
|
|
||||||
import { PhishermanCacheEntry } from "./entities/PhishermanCacheEntry";
|
|
||||||
import { PhishermanDomainInfo, PhishermanUnknownDomain } from "./types/phisherman";
|
|
||||||
import fetch, { Headers } from "node-fetch";
|
|
||||||
import { DAYS, DBDateFormat, HOURS, MINUTES } from "../utils";
|
|
||||||
import moment from "moment-timezone";
|
|
||||||
import { PhishermanKeyCacheEntry } from "./entities/PhishermanKeyCacheEntry";
|
|
||||||
import crypto from "crypto";
|
import crypto from "crypto";
|
||||||
|
import moment from "moment-timezone";
|
||||||
|
import fetch, { Headers } from "node-fetch";
|
||||||
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { env } from "../env";
|
import { env } from "../env";
|
||||||
|
import { DAYS, DBDateFormat, HOURS, MINUTES } from "../utils";
|
||||||
|
import { PhishermanCacheEntry } from "./entities/PhishermanCacheEntry";
|
||||||
|
import { PhishermanKeyCacheEntry } from "./entities/PhishermanKeyCacheEntry";
|
||||||
|
import { PhishermanDomainInfo, PhishermanUnknownDomain } from "./types/phisherman";
|
||||||
|
|
||||||
const API_URL = "https://api.phisherman.gg";
|
const API_URL = "https://api.phisherman.gg";
|
||||||
const MASTER_API_KEY = env.PHISHERMAN_API_KEY;
|
const MASTER_API_KEY = env.PHISHERMAN_API_KEY;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { getRepository, Repository } from "typeorm";
|
|
||||||
import { Reminder } from "./entities/Reminder";
|
|
||||||
import { BaseRepository } from "./BaseRepository";
|
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { DBDateFormat } from "../utils";
|
import { DBDateFormat } from "../utils";
|
||||||
|
import { BaseRepository } from "./BaseRepository";
|
||||||
|
import { Reminder } from "./entities/Reminder";
|
||||||
|
|
||||||
export class Reminders extends BaseRepository {
|
export class Reminders extends BaseRepository {
|
||||||
private reminders: Repository<Reminder>;
|
private reminders: Repository<Reminder>;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { getRepository, Repository } from "typeorm";
|
|
||||||
import { ScheduledPost } from "./entities/ScheduledPost";
|
|
||||||
import { BaseRepository } from "./BaseRepository";
|
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { DBDateFormat } from "../utils";
|
import { DBDateFormat } from "../utils";
|
||||||
|
import { BaseRepository } from "./BaseRepository";
|
||||||
|
import { ScheduledPost } from "./entities/ScheduledPost";
|
||||||
|
|
||||||
export class ScheduledPosts extends BaseRepository {
|
export class ScheduledPosts extends BaseRepository {
|
||||||
private scheduledPosts: Repository<ScheduledPost>;
|
private scheduledPosts: Repository<ScheduledPost>;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { getRepository, Repository } from "typeorm";
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { Tempban } from "./entities/Tempban";
|
|
||||||
import { BaseRepository } from "./BaseRepository";
|
|
||||||
import { DBDateFormat } from "../utils";
|
import { DBDateFormat } from "../utils";
|
||||||
|
import { BaseRepository } from "./BaseRepository";
|
||||||
|
import { Tempban } from "./entities/Tempban";
|
||||||
|
|
||||||
export class Tempbans extends BaseRepository {
|
export class Tempbans extends BaseRepository {
|
||||||
private tempbans: Repository<Tempban>;
|
private tempbans: Repository<Tempban>;
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import { getRepository, Repository } from "typeorm";
|
|
||||||
import { VCAlert } from "./entities/VCAlert";
|
|
||||||
import { BaseRepository } from "./BaseRepository";
|
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { DBDateFormat } from "../utils";
|
import { DBDateFormat } from "../utils";
|
||||||
|
import { BaseRepository } from "./BaseRepository";
|
||||||
|
import { VCAlert } from "./entities/VCAlert";
|
||||||
|
|
||||||
export class VCAlerts extends BaseRepository {
|
export class VCAlerts extends BaseRepository {
|
||||||
private allAlerts: Repository<VCAlert>;
|
private allAlerts: Repository<VCAlert>;
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { getRepository, Repository } from "typeorm";
|
import { getRepository, Repository } from "typeorm";
|
||||||
import { Webhook } from "./entities/Webhook";
|
|
||||||
import { BaseRepository } from "./BaseRepository";
|
|
||||||
import { decrypt, encrypt } from "../utils/crypt";
|
import { decrypt, encrypt } from "../utils/crypt";
|
||||||
|
import { BaseRepository } from "./BaseRepository";
|
||||||
|
import { Webhook } from "./entities/Webhook";
|
||||||
|
|
||||||
export class Webhooks extends BaseRepository {
|
export class Webhooks extends BaseRepository {
|
||||||
repository: Repository<Webhook> = getRepository(Webhook);
|
repository: Repository<Webhook> = getRepository(Webhook);
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
|
import path from "path";
|
||||||
import { Connection, createConnection } from "typeorm";
|
import { Connection, createConnection } from "typeorm";
|
||||||
|
import { backendDir } from "../paths";
|
||||||
import { SimpleError } from "../SimpleError";
|
import { SimpleError } from "../SimpleError";
|
||||||
import { QueryLogger } from "./queryLogger";
|
import { QueryLogger } from "./queryLogger";
|
||||||
import path from "path";
|
|
||||||
import { backendDir } from "../paths";
|
|
||||||
|
|
||||||
const ormconfigPath = path.join(backendDir, "ormconfig.js");
|
const ormconfigPath = path.join(backendDir, "ormconfig.js");
|
||||||
const connectionOptions = require(ormconfigPath);
|
const connectionOptions = require(ormconfigPath);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm";
|
import { Column, Entity, PrimaryColumn } from "typeorm";
|
||||||
import { ApiUserInfo } from "./ApiUserInfo";
|
|
||||||
import { AuditLogEventData, AuditLogEventType } from "../apiAuditLogTypes";
|
import { AuditLogEventData, AuditLogEventType } from "../apiAuditLogTypes";
|
||||||
|
|
||||||
@Entity("api_audit_log")
|
@Entity("api_audit_log")
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm";
|
import { Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from "typeorm";
|
||||||
import { ApiUserInfo } from "./ApiUserInfo";
|
|
||||||
import { ApiPermissionTypes } from "../ApiPermissionAssignments";
|
import { ApiPermissionTypes } from "../ApiPermissionAssignments";
|
||||||
|
import { ApiUserInfo } from "./ApiUserInfo";
|
||||||
|
|
||||||
@Entity("api_permissions")
|
@Entity("api_permissions")
|
||||||
export class ApiPermissionAssignment {
|
export class ApiPermissionAssignment {
|
||||||
|
|
|
@ -2,7 +2,7 @@ import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
|
||||||
export const TRIGGER_COMPARISON_OPS = ["=", "!=", ">", "<", ">=", "<="] as const;
|
export const TRIGGER_COMPARISON_OPS = ["=", "!=", ">", "<", ">=", "<="] as const;
|
||||||
|
|
||||||
export type TriggerComparisonOp = typeof TRIGGER_COMPARISON_OPS[number];
|
export type TriggerComparisonOp = (typeof TRIGGER_COMPARISON_OPS)[number];
|
||||||
|
|
||||||
const REVERSE_OPS: Record<TriggerComparisonOp, TriggerComparisonOp> = {
|
const REVERSE_OPS: Record<TriggerComparisonOp, TriggerComparisonOp> = {
|
||||||
"=": "!=",
|
"=": "!=",
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
|
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
|
||||||
@Entity("reminders")
|
@Entity("reminders")
|
||||||
export class Reminder {
|
export class Reminder {
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Snowflake } from "discord.js";
|
import { Snowflake, StickerFormatType, StickerType } from "discord.js";
|
||||||
import { Column, Entity, PrimaryColumn } from "typeorm";
|
import { Column, Entity, PrimaryColumn } from "typeorm";
|
||||||
|
|
||||||
export interface ISavedMessageAttachmentData {
|
export interface ISavedMessageAttachmentData {
|
||||||
|
@ -55,13 +55,13 @@ export interface ISavedMessageEmbedData {
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISavedMessageStickerData {
|
export interface ISavedMessageStickerData {
|
||||||
format: string;
|
format: StickerFormatType;
|
||||||
guildId: Snowflake | null;
|
guildId: Snowflake | null;
|
||||||
id: Snowflake;
|
id: Snowflake;
|
||||||
name: string;
|
name: string;
|
||||||
description: string | null;
|
description: string | null;
|
||||||
available: boolean | null;
|
available: boolean | null;
|
||||||
type: string | null;
|
type: StickerType | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ISavedMessageData {
|
export interface ISavedMessageData {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { MessageAttachment } from "discord.js";
|
import { Attachment } from "discord.js";
|
||||||
import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
|
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||||
import { StrictMessageContent } from "../../utils";
|
import { StrictMessageContent } from "../../utils";
|
||||||
|
|
||||||
@Entity("scheduled_posts")
|
@Entity("scheduled_posts")
|
||||||
|
@ -17,7 +17,7 @@ export class ScheduledPost {
|
||||||
|
|
||||||
@Column("simple-json") content: StrictMessageContent;
|
@Column("simple-json") content: StrictMessageContent;
|
||||||
|
|
||||||
@Column("simple-json") attachments: MessageAttachment[];
|
@Column("simple-json") attachments: Attachment[];
|
||||||
|
|
||||||
@Column({ type: String, nullable: true }) post_at: string | null;
|
@Column({ type: String, nullable: true }) post_at: string | null;
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Column, Entity, PrimaryColumn, PrimaryGeneratedColumn } from "typeorm";
|
import { Column, Entity, PrimaryGeneratedColumn } from "typeorm";
|
||||||
|
|
||||||
@Entity("vc_alerts")
|
@Entity("vc_alerts")
|
||||||
export class VCAlert {
|
export class VCAlert {
|
||||||
|
|
|
@ -2,7 +2,6 @@
|
||||||
|
|
||||||
import { lazyMemoize, MINUTES } from "../../utils";
|
import { lazyMemoize, MINUTES } from "../../utils";
|
||||||
import { Archives } from "../Archives";
|
import { Archives } from "../Archives";
|
||||||
import moment from "moment-timezone";
|
|
||||||
|
|
||||||
const LOOP_INTERVAL = 15 * MINUTES;
|
const LOOP_INTERVAL = 15 * MINUTES;
|
||||||
const getArchivesRepository = lazyMemoize(() => new Archives());
|
const getArchivesRepository = lazyMemoize(() => new Archives());
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// tslint:disable:no-console
|
// tslint:disable:no-console
|
||||||
|
|
||||||
import { lazyMemoize, memoize, MINUTES } from "../../utils";
|
|
||||||
import { Mutes } from "../Mutes";
|
|
||||||
import Timeout = NodeJS.Timeout;
|
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
|
import { lazyMemoize, MINUTES } from "../../utils";
|
||||||
import { Mute } from "../entities/Mute";
|
import { Mute } from "../entities/Mute";
|
||||||
import { emitGuildEvent, hasGuildEventListener } from "../GuildEvents";
|
import { emitGuildEvent, hasGuildEventListener } from "../GuildEvents";
|
||||||
|
import { Mutes } from "../Mutes";
|
||||||
|
import Timeout = NodeJS.Timeout;
|
||||||
|
|
||||||
const LOOP_INTERVAL = 15 * MINUTES;
|
const LOOP_INTERVAL = 15 * MINUTES;
|
||||||
const MAX_TRIES_PER_SERVER = 3;
|
const MAX_TRIES_PER_SERVER = 3;
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
// tslint:disable:no-console
|
// tslint:disable:no-console
|
||||||
|
|
||||||
import { lazyMemoize, MINUTES } from "../../utils";
|
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
|
import { lazyMemoize, MINUTES } from "../../utils";
|
||||||
|
import { Tempban } from "../entities/Tempban";
|
||||||
import { emitGuildEvent, hasGuildEventListener } from "../GuildEvents";
|
import { emitGuildEvent, hasGuildEventListener } from "../GuildEvents";
|
||||||
import { Tempbans } from "../Tempbans";
|
import { Tempbans } from "../Tempbans";
|
||||||
import { Tempban } from "../entities/Tempban";
|
|
||||||
import Timeout = NodeJS.Timeout;
|
import Timeout = NodeJS.Timeout;
|
||||||
|
|
||||||
const LOOP_INTERVAL = 15 * MINUTES;
|
const LOOP_INTERVAL = 15 * MINUTES;
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
// tslint:disable:no-console
|
// tslint:disable:no-console
|
||||||
|
|
||||||
import { lazyMemoize, MINUTES } from "../../utils";
|
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { emitGuildEvent, hasGuildEventListener } from "../GuildEvents";
|
import { lazyMemoize, MINUTES } from "../../utils";
|
||||||
import Timeout = NodeJS.Timeout;
|
|
||||||
import { VCAlerts } from "../VCAlerts";
|
|
||||||
import { VCAlert } from "../entities/VCAlert";
|
import { VCAlert } from "../entities/VCAlert";
|
||||||
|
import { emitGuildEvent, hasGuildEventListener } from "../GuildEvents";
|
||||||
|
import { VCAlerts } from "../VCAlerts";
|
||||||
|
import Timeout = NodeJS.Timeout;
|
||||||
|
|
||||||
const LOOP_INTERVAL = 15 * MINUTES;
|
const LOOP_INTERVAL = 15 * MINUTES;
|
||||||
const MAX_TRIES_PER_SERVER = 3;
|
const MAX_TRIES_PER_SERVER = 3;
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
// tslint:disable:no-console
|
// tslint:disable:no-console
|
||||||
|
|
||||||
import { HOURS, MINUTES } from "../../utils";
|
import { MINUTES } from "../../utils";
|
||||||
import {
|
import {
|
||||||
deleteStalePhishermanCacheEntries,
|
deleteStalePhishermanCacheEntries,
|
||||||
deleteStalePhishermanKeyCacheEntries,
|
deleteStalePhishermanKeyCacheEntries,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// tslint:disable:no-console
|
// tslint:disable:no-console
|
||||||
|
|
||||||
import { lazyMemoize, MINUTES } from "../../utils";
|
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { emitGuildEvent, hasGuildEventListener } from "../GuildEvents";
|
import { lazyMemoize, MINUTES } from "../../utils";
|
||||||
import { Reminder } from "../entities/Reminder";
|
import { Reminder } from "../entities/Reminder";
|
||||||
|
import { emitGuildEvent, hasGuildEventListener } from "../GuildEvents";
|
||||||
import { Reminders } from "../Reminders";
|
import { Reminders } from "../Reminders";
|
||||||
import Timeout = NodeJS.Timeout;
|
import Timeout = NodeJS.Timeout;
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
// tslint:disable:no-console
|
// tslint:disable:no-console
|
||||||
|
|
||||||
import { lazyMemoize, MINUTES } from "../../utils";
|
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
|
import { lazyMemoize, MINUTES } from "../../utils";
|
||||||
|
import { ScheduledPost } from "../entities/ScheduledPost";
|
||||||
import { emitGuildEvent, hasGuildEventListener } from "../GuildEvents";
|
import { emitGuildEvent, hasGuildEventListener } from "../GuildEvents";
|
||||||
import { ScheduledPosts } from "../ScheduledPosts";
|
import { ScheduledPosts } from "../ScheduledPosts";
|
||||||
import { ScheduledPost } from "../entities/ScheduledPost";
|
|
||||||
import Timeout = NodeJS.Timeout;
|
import Timeout = NodeJS.Timeout;
|
||||||
|
|
||||||
const LOOP_INTERVAL = 15 * MINUTES;
|
const LOOP_INTERVAL = 15 * MINUTES;
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import { AdvancedConsoleLogger } from "typeorm/logger/AdvancedConsoleLogger";
|
|
||||||
import type { QueryRunner } from "typeorm";
|
import type { QueryRunner } from "typeorm";
|
||||||
|
import { AdvancedConsoleLogger } from "typeorm/logger/AdvancedConsoleLogger";
|
||||||
|
|
||||||
let groupedQueryStats: Map<string, number> = new Map();
|
let groupedQueryStats: Map<string, number> = new Map();
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import path from "path";
|
|
||||||
import fs from "fs";
|
|
||||||
import dotenv from "dotenv";
|
import dotenv from "dotenv";
|
||||||
import { rootDir } from "./paths";
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
import { z } from "zod";
|
import { z } from "zod";
|
||||||
|
import { rootDir } from "./paths";
|
||||||
|
|
||||||
const envType = z.object({
|
const envType = z.object({
|
||||||
KEY: z.string().length(32),
|
KEY: z.string().length(32),
|
||||||
|
@ -52,11 +52,11 @@ const envType = z.object({
|
||||||
DB_DATABASE: z.string().optional().default("zeppelin"),
|
DB_DATABASE: z.string().optional().default("zeppelin"),
|
||||||
});
|
});
|
||||||
|
|
||||||
let toValidate = {};
|
let toValidate = { ...process.env };
|
||||||
const envPath = path.join(rootDir, ".env");
|
const envPath = path.join(rootDir, ".env");
|
||||||
if (fs.existsSync(envPath)) {
|
if (fs.existsSync(envPath)) {
|
||||||
const buf = fs.readFileSync(envPath);
|
const buf = fs.readFileSync(envPath);
|
||||||
toValidate = dotenv.parse(buf);
|
toValidate = { ...toValidate, ...dotenv.parse(buf) };
|
||||||
}
|
}
|
||||||
|
|
||||||
export const env = envType.parse(toValidate);
|
export const env = envType.parse(toValidate);
|
||||||
|
|
|
@ -1,42 +1,45 @@
|
||||||
import { Client, Constants, Intents, Options, TextChannel, ThreadChannel } from "discord.js";
|
import {
|
||||||
import { Knub, PluginError } from "knub";
|
Client,
|
||||||
import { PluginLoadError } from "knub/dist/plugins/PluginLoadError";
|
Events,
|
||||||
// Always use UTC internally
|
GatewayIntentBits,
|
||||||
// This is also enforced for the database in data/db.ts
|
Options,
|
||||||
|
Partials,
|
||||||
|
RESTEvents,
|
||||||
|
TextChannel,
|
||||||
|
ThreadChannel,
|
||||||
|
} from "discord.js";
|
||||||
|
import { EventEmitter } from "events";
|
||||||
|
import { Knub, PluginError, PluginLoadError, PluginNotLoadedError } from "knub";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
|
import { performance } from "perf_hooks";
|
||||||
import { AllowedGuilds } from "./data/AllowedGuilds";
|
import { AllowedGuilds } from "./data/AllowedGuilds";
|
||||||
import { Configs } from "./data/Configs";
|
import { Configs } from "./data/Configs";
|
||||||
import { connect } from "./data/db";
|
import { connect } from "./data/db";
|
||||||
import { GuildLogs } from "./data/GuildLogs";
|
import { GuildLogs } from "./data/GuildLogs";
|
||||||
import { LogType } from "./data/LogType";
|
import { LogType } from "./data/LogType";
|
||||||
import { DiscordJSError } from "./DiscordJSError";
|
import { runExpiredArchiveDeletionLoop } from "./data/loops/expiredArchiveDeletionLoop";
|
||||||
import { logger } from "./logger";
|
|
||||||
import { baseGuildPlugins, globalPlugins, guildPlugins } from "./plugins/availablePlugins";
|
|
||||||
import { RecoverablePluginError } from "./RecoverablePluginError";
|
|
||||||
import { SimpleError } from "./SimpleError";
|
|
||||||
import { ZeppelinGlobalConfig, ZeppelinGuildConfig } from "./types";
|
|
||||||
import { startUptimeCounter } from "./uptime";
|
|
||||||
import { errorMessage, isDiscordAPIError, isDiscordHTTPError, MINUTES, SECONDS, sleep, successMessage } from "./utils";
|
|
||||||
import { loadYamlSafely } from "./utils/loadYamlSafely";
|
|
||||||
import { DecayingCounter } from "./utils/DecayingCounter";
|
|
||||||
import { PluginNotLoadedError } from "knub/dist/plugins/PluginNotLoadedError";
|
|
||||||
import { logRestCall } from "./restCallStats";
|
|
||||||
import { logRateLimit } from "./rateLimitStats";
|
|
||||||
import { runExpiringMutesLoop } from "./data/loops/expiringMutesLoop";
|
import { runExpiringMutesLoop } from "./data/loops/expiringMutesLoop";
|
||||||
import { runUpcomingRemindersLoop } from "./data/loops/upcomingRemindersLoop";
|
|
||||||
import { runUpcomingScheduledPostsLoop } from "./data/loops/upcomingScheduledPostsLoop";
|
|
||||||
import { runExpiringTempbansLoop } from "./data/loops/expiringTempbansLoop";
|
import { runExpiringTempbansLoop } from "./data/loops/expiringTempbansLoop";
|
||||||
import { runExpiringVCAlertsLoop } from "./data/loops/expiringVCAlertsLoop";
|
import { runExpiringVCAlertsLoop } from "./data/loops/expiringVCAlertsLoop";
|
||||||
import { runExpiredArchiveDeletionLoop } from "./data/loops/expiredArchiveDeletionLoop";
|
|
||||||
import { runSavedMessageCleanupLoop } from "./data/loops/savedMessageCleanupLoop";
|
|
||||||
import { performance } from "perf_hooks";
|
|
||||||
import { setProfiler } from "./profiler";
|
|
||||||
import { enableProfiling } from "./utils/easyProfiler";
|
|
||||||
import { runPhishermanCacheCleanupLoop, runPhishermanReportingLoop } from "./data/loops/phishermanLoops";
|
import { runPhishermanCacheCleanupLoop, runPhishermanReportingLoop } from "./data/loops/phishermanLoops";
|
||||||
|
import { runSavedMessageCleanupLoop } from "./data/loops/savedMessageCleanupLoop";
|
||||||
|
import { runUpcomingRemindersLoop } from "./data/loops/upcomingRemindersLoop";
|
||||||
|
import { runUpcomingScheduledPostsLoop } from "./data/loops/upcomingScheduledPostsLoop";
|
||||||
import { hasPhishermanMasterAPIKey } from "./data/Phisherman";
|
import { hasPhishermanMasterAPIKey } from "./data/Phisherman";
|
||||||
import { consumeQueryStats } from "./data/queryLogger";
|
import { consumeQueryStats } from "./data/queryLogger";
|
||||||
import { EventEmitter } from "events";
|
import { DiscordJSError } from "./DiscordJSError";
|
||||||
import { env } from "./env";
|
import { env } from "./env";
|
||||||
|
import { logger } from "./logger";
|
||||||
|
import { baseGuildPlugins, globalPlugins, guildPlugins } from "./plugins/availablePlugins";
|
||||||
|
import { setProfiler } from "./profiler";
|
||||||
|
import { logRateLimit } from "./rateLimitStats";
|
||||||
|
import { RecoverablePluginError } from "./RecoverablePluginError";
|
||||||
|
import { SimpleError } from "./SimpleError";
|
||||||
|
import { startUptimeCounter } from "./uptime";
|
||||||
|
import { errorMessage, isDiscordAPIError, isDiscordHTTPError, MINUTES, SECONDS, sleep, successMessage } from "./utils";
|
||||||
|
import { DecayingCounter } from "./utils/DecayingCounter";
|
||||||
|
import { enableProfiling } from "./utils/easyProfiler";
|
||||||
|
import { loadYamlSafely } from "./utils/loadYamlSafely";
|
||||||
|
|
||||||
// Error handling
|
// Error handling
|
||||||
let recentPluginErrors = 0;
|
let recentPluginErrors = 0;
|
||||||
|
@ -162,6 +165,8 @@ for (const [i, part] of actualVersionParts.entries()) {
|
||||||
throw new SimpleError(`Unsupported Node.js version! Must be at least ${REQUIRED_NODE_VERSION}`);
|
throw new SimpleError(`Unsupported Node.js version! Must be at least ${REQUIRED_NODE_VERSION}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Always use UTC internally
|
||||||
|
// This is also enforced for the database in data/db.ts
|
||||||
moment.tz.setDefault("UTC");
|
moment.tz.setDefault("UTC");
|
||||||
|
|
||||||
// Blocking check
|
// Blocking check
|
||||||
|
@ -188,17 +193,19 @@ setInterval(() => {
|
||||||
logger.info("Connecting to database");
|
logger.info("Connecting to database");
|
||||||
connect().then(async () => {
|
connect().then(async () => {
|
||||||
const client = new Client({
|
const client = new Client({
|
||||||
partials: ["USER", "CHANNEL", "GUILD_MEMBER", "MESSAGE", "REACTION"],
|
partials: [Partials.User, Partials.Channel, Partials.GuildMember, Partials.Message, Partials.Reaction],
|
||||||
|
|
||||||
makeCache: Options.cacheWithLimits({
|
makeCache: Options.cacheWithLimits({
|
||||||
...Options.defaultMakeCacheSettings,
|
...Options.DefaultMakeCacheSettings,
|
||||||
MessageManager: 1,
|
MessageManager: 1,
|
||||||
// GuildMemberManager: 15000,
|
// GuildMemberManager: 15000,
|
||||||
GuildInviteManager: 0,
|
GuildInviteManager: 0,
|
||||||
}),
|
}),
|
||||||
|
|
||||||
restGlobalRateLimit: 50,
|
rest: {
|
||||||
// restTimeOffset: 1000,
|
// globalRequestsPerSecond: 50,
|
||||||
|
// offset: 1000,
|
||||||
|
},
|
||||||
|
|
||||||
// Disable mentions by default
|
// Disable mentions by default
|
||||||
allowedMentions: {
|
allowedMentions: {
|
||||||
|
@ -209,25 +216,26 @@ connect().then(async () => {
|
||||||
},
|
},
|
||||||
intents: [
|
intents: [
|
||||||
// Privileged
|
// Privileged
|
||||||
Intents.FLAGS.GUILD_MEMBERS,
|
GatewayIntentBits.GuildMembers,
|
||||||
// Intents.FLAGS.GUILD_PRESENCES,
|
GatewayIntentBits.MessageContent,
|
||||||
Intents.FLAGS.GUILD_MESSAGE_TYPING,
|
// GatewayIntentBits.GuildPresences,
|
||||||
|
|
||||||
// Regular
|
// Regular
|
||||||
Intents.FLAGS.DIRECT_MESSAGES,
|
GatewayIntentBits.GuildMessageTyping,
|
||||||
Intents.FLAGS.GUILD_BANS,
|
GatewayIntentBits.DirectMessages,
|
||||||
Intents.FLAGS.GUILD_EMOJIS_AND_STICKERS,
|
GatewayIntentBits.GuildModeration,
|
||||||
Intents.FLAGS.GUILD_INVITES,
|
GatewayIntentBits.GuildEmojisAndStickers,
|
||||||
Intents.FLAGS.GUILD_MESSAGE_REACTIONS,
|
GatewayIntentBits.GuildInvites,
|
||||||
Intents.FLAGS.GUILD_MESSAGES,
|
GatewayIntentBits.GuildMessageReactions,
|
||||||
Intents.FLAGS.GUILDS,
|
GatewayIntentBits.GuildMessages,
|
||||||
Intents.FLAGS.GUILD_VOICE_STATES,
|
GatewayIntentBits.Guilds,
|
||||||
|
GatewayIntentBits.GuildVoiceStates,
|
||||||
],
|
],
|
||||||
});
|
});
|
||||||
// FIXME: TS doesn't see Client as a child of EventEmitter for some reason
|
// FIXME: TS doesn't see Client as a child of EventEmitter for some reason
|
||||||
(client as unknown as EventEmitter).setMaxListeners(200);
|
(client as unknown as EventEmitter).setMaxListeners(200);
|
||||||
|
|
||||||
client.on(Constants.Events.RATE_LIMIT, (data) => {
|
client.rest.on(RESTEvents.RateLimited, (data) => {
|
||||||
// tslint:disable-next-line:no-console
|
// tslint:disable-next-line:no-console
|
||||||
// console.log(`[DEBUG] [RATE_LIMIT] ${JSON.stringify(data)}`);
|
// console.log(`[DEBUG] [RATE_LIMIT] ${JSON.stringify(data)}`);
|
||||||
});
|
});
|
||||||
|
@ -235,7 +243,7 @@ connect().then(async () => {
|
||||||
const safe429DecayInterval = 5 * SECONDS;
|
const safe429DecayInterval = 5 * SECONDS;
|
||||||
const safe429MaxCount = 5;
|
const safe429MaxCount = 5;
|
||||||
const safe429Counter = new DecayingCounter(safe429DecayInterval);
|
const safe429Counter = new DecayingCounter(safe429DecayInterval);
|
||||||
client.on(Constants.Events.DEBUG, (errorText) => {
|
client.on(Events.Debug, (errorText) => {
|
||||||
if (!errorText.includes("429")) {
|
if (!errorText.includes("429")) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -258,7 +266,7 @@ connect().then(async () => {
|
||||||
const allowedGuilds = new AllowedGuilds();
|
const allowedGuilds = new AllowedGuilds();
|
||||||
const guildConfigs = new Configs();
|
const guildConfigs = new Configs();
|
||||||
|
|
||||||
const bot = new Knub<ZeppelinGuildConfig, ZeppelinGlobalConfig>(client, {
|
const bot = new Knub(client, {
|
||||||
guildPlugins,
|
guildPlugins,
|
||||||
globalPlugins,
|
globalPlugins,
|
||||||
|
|
||||||
|
@ -329,6 +337,7 @@ connect().then(async () => {
|
||||||
sendSuccessMessageFn(channel, body) {
|
sendSuccessMessageFn(channel, body) {
|
||||||
const guildId =
|
const guildId =
|
||||||
channel instanceof TextChannel || channel instanceof ThreadChannel ? channel.guild.id : undefined;
|
channel instanceof TextChannel || channel instanceof ThreadChannel ? channel.guild.id : undefined;
|
||||||
|
// @ts-expect-error
|
||||||
const emoji = guildId ? bot.getLoadedGuild(guildId)!.config.success_emoji : undefined;
|
const emoji = guildId ? bot.getLoadedGuild(guildId)!.config.success_emoji : undefined;
|
||||||
channel.send(successMessage(body, emoji));
|
channel.send(successMessage(body, emoji));
|
||||||
},
|
},
|
||||||
|
@ -336,6 +345,7 @@ connect().then(async () => {
|
||||||
sendErrorMessageFn(channel, body) {
|
sendErrorMessageFn(channel, body) {
|
||||||
const guildId =
|
const guildId =
|
||||||
channel instanceof TextChannel || channel instanceof ThreadChannel ? channel.guild.id : undefined;
|
channel instanceof TextChannel || channel instanceof ThreadChannel ? channel.guild.id : undefined;
|
||||||
|
// @ts-expect-error
|
||||||
const emoji = guildId ? bot.getLoadedGuild(guildId)!.config.error_emoji : undefined;
|
const emoji = guildId ? bot.getLoadedGuild(guildId)!.config.error_emoji : undefined;
|
||||||
channel.send(errorMessage(body, emoji));
|
channel.send(errorMessage(body, emoji));
|
||||||
},
|
},
|
||||||
|
@ -346,7 +356,7 @@ connect().then(async () => {
|
||||||
startUptimeCounter();
|
startUptimeCounter();
|
||||||
});
|
});
|
||||||
|
|
||||||
client.on(Constants.Events.RATE_LIMIT, (data) => {
|
client.rest.on(RESTEvents.RateLimited, (data) => {
|
||||||
logRateLimit(data);
|
logRateLimit(data);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -2,19 +2,23 @@
|
||||||
* @file Utility functions that are plugin-instance-specific (i.e. use PluginData)
|
* @file Utility functions that are plugin-instance-specific (i.e. use PluginData)
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { GuildMember, Message, MessageMentionOptions, MessageOptions, TextChannel } from "discord.js";
|
import { GuildMember, Message, MessageCreateOptions, MessageMentionOptions, TextBasedChannel } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { CommandContext, configUtils, ConfigValidationError, GuildPluginData, helpers, PluginOptions } from "knub";
|
import {
|
||||||
import { PluginOverrideCriteria } from "knub/dist/config/configTypes";
|
AnyPluginData,
|
||||||
import { ExtendedMatchParams } from "knub/dist/config/PluginConfigManager"; // TODO: Export from Knub index
|
CommandContext,
|
||||||
import { AnyPluginData } from "knub/dist/plugins/PluginData";
|
ConfigValidationError,
|
||||||
|
ExtendedMatchParams,
|
||||||
|
GuildPluginData,
|
||||||
|
helpers,
|
||||||
|
PluginOverrideCriteria,
|
||||||
|
} from "knub";
|
||||||
import { logger } from "./logger";
|
import { logger } from "./logger";
|
||||||
import { ZeppelinPlugin } from "./plugins/ZeppelinPlugin";
|
|
||||||
import { TZeppelinKnub } from "./types";
|
|
||||||
import { deepKeyIntersect, errorMessage, successMessage, tDeepPartial, tNullable } from "./utils";
|
|
||||||
import { Tail } from "./utils/typeUtils";
|
|
||||||
import { decodeAndValidateStrict, StrictValidationError, validate } from "./validatorUtils";
|
|
||||||
import { isStaff } from "./staff";
|
import { isStaff } from "./staff";
|
||||||
|
import { TZeppelinKnub } from "./types";
|
||||||
|
import { errorMessage, successMessage, tNullable } from "./utils";
|
||||||
|
import { Tail } from "./utils/typeUtils";
|
||||||
|
import { StrictValidationError, validate } from "./validatorUtils";
|
||||||
|
|
||||||
const { getMemberLevel } = helpers;
|
const { getMemberLevel } = helpers;
|
||||||
|
|
||||||
|
@ -91,117 +95,32 @@ export function strictValidationErrorToConfigValidationError(err: StrictValidati
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getPluginConfigPreprocessor(
|
export function makeIoTsConfigParser<Schema extends t.Type<any>>(schema: Schema): (input: unknown) => t.TypeOf<Schema> {
|
||||||
blueprint: ZeppelinPlugin,
|
return (input: unknown) => {
|
||||||
customPreprocessor?: ZeppelinPlugin["configPreprocessor"],
|
const error = validate(schema, input);
|
||||||
) {
|
if (error) {
|
||||||
return async (options: PluginOptions<any>, strict?: boolean) => {
|
throw error;
|
||||||
// 1. Validate the basic structure of plugin config
|
|
||||||
const basicOptionsValidation = validate(BasicPluginStructureType, options);
|
|
||||||
if (basicOptionsValidation instanceof StrictValidationError) {
|
|
||||||
throw strictValidationErrorToConfigValidationError(basicOptionsValidation);
|
|
||||||
}
|
}
|
||||||
|
return input as t.TypeOf<Schema>;
|
||||||
// 2. Validate config/overrides against *partial* config schema. This ensures valid properties have valid types.
|
|
||||||
const partialConfigSchema = tDeepPartial(blueprint.configSchema);
|
|
||||||
|
|
||||||
if (options.config) {
|
|
||||||
const partialConfigValidation = validate(partialConfigSchema, options.config);
|
|
||||||
if (partialConfigValidation instanceof StrictValidationError) {
|
|
||||||
throw strictValidationErrorToConfigValidationError(partialConfigValidation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.overrides) {
|
|
||||||
for (const override of options.overrides) {
|
|
||||||
// Validate criteria and extra criteria
|
|
||||||
// FIXME: This is ugly
|
|
||||||
for (const key of Object.keys(override)) {
|
|
||||||
if (!validTopLevelOverrideKeys.includes(key)) {
|
|
||||||
if (strict) {
|
|
||||||
throw new ConfigValidationError(`Unknown override criterion '${key}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete override[key];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (override.extra != null) {
|
|
||||||
for (const extraCriterion of Object.keys(override.extra)) {
|
|
||||||
if (!blueprint.customOverrideCriteriaFunctions?.[extraCriterion]) {
|
|
||||||
if (strict) {
|
|
||||||
throw new ConfigValidationError(`Unknown override extra criterion '${extraCriterion}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
delete override.extra[extraCriterion];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Validate override config
|
|
||||||
const partialOverrideConfigValidation = decodeAndValidateStrict(partialConfigSchema, override.config || {});
|
|
||||||
if (partialOverrideConfigValidation instanceof StrictValidationError) {
|
|
||||||
throw strictValidationErrorToConfigValidationError(partialOverrideConfigValidation);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 3. Run custom preprocessor, if any
|
|
||||||
if (customPreprocessor) {
|
|
||||||
options = await customPreprocessor(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
// 4. Merge with default options and validate/decode the entire config
|
|
||||||
let decodedConfig = {};
|
|
||||||
const decodedOverrides: Array<PluginOverrideCriteria<unknown> & { config: any }> = [];
|
|
||||||
|
|
||||||
if (options.config) {
|
|
||||||
decodedConfig = blueprint.configSchema
|
|
||||||
? decodeAndValidateStrict(blueprint.configSchema, options.config)
|
|
||||||
: options.config;
|
|
||||||
if (decodedConfig instanceof StrictValidationError) {
|
|
||||||
throw strictValidationErrorToConfigValidationError(decodedConfig);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (options.overrides) {
|
|
||||||
for (const override of options.overrides) {
|
|
||||||
const overrideConfigMergedWithBaseConfig = configUtils.mergeConfig(options.config || {}, override.config || {});
|
|
||||||
const decodedOverrideConfig = blueprint.configSchema
|
|
||||||
? decodeAndValidateStrict(blueprint.configSchema, overrideConfigMergedWithBaseConfig)
|
|
||||||
: overrideConfigMergedWithBaseConfig;
|
|
||||||
if (decodedOverrideConfig instanceof StrictValidationError) {
|
|
||||||
throw strictValidationErrorToConfigValidationError(decodedOverrideConfig);
|
|
||||||
}
|
|
||||||
decodedOverrides.push({
|
|
||||||
...override,
|
|
||||||
config: deepKeyIntersect(decodedOverrideConfig, override.config || {}),
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {
|
|
||||||
config: decodedConfig,
|
|
||||||
overrides: decodedOverrides,
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export async function sendSuccessMessage(
|
export async function sendSuccessMessage(
|
||||||
pluginData: AnyPluginData<any>,
|
pluginData: AnyPluginData<any>,
|
||||||
channel: TextChannel,
|
channel: TextBasedChannel,
|
||||||
body: string,
|
body: string,
|
||||||
allowedMentions?: MessageMentionOptions,
|
allowedMentions?: MessageMentionOptions,
|
||||||
): Promise<Message | undefined> {
|
): Promise<Message | undefined> {
|
||||||
const emoji = pluginData.fullConfig.success_emoji || undefined;
|
const emoji = pluginData.fullConfig.success_emoji || undefined;
|
||||||
const formattedBody = successMessage(body, emoji);
|
const formattedBody = successMessage(body, emoji);
|
||||||
const content: MessageOptions = allowedMentions
|
const content: MessageCreateOptions = allowedMentions
|
||||||
? { content: formattedBody, allowedMentions }
|
? { content: formattedBody, allowedMentions }
|
||||||
: { content: formattedBody };
|
: { content: formattedBody };
|
||||||
|
|
||||||
return channel
|
return channel
|
||||||
.send({ ...content }) // Force line break
|
.send({ ...content }) // Force line break
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
const channelInfo = channel.guild ? `${channel.id} (${channel.guild.id})` : channel.id;
|
const channelInfo = "guild" in channel ? `${channel.id} (${channel.guild.id})` : channel.id;
|
||||||
logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`);
|
logger.warn(`Failed to send success message to ${channelInfo}): ${err.code} ${err.message}`);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
|
@ -209,20 +128,20 @@ export async function sendSuccessMessage(
|
||||||
|
|
||||||
export async function sendErrorMessage(
|
export async function sendErrorMessage(
|
||||||
pluginData: AnyPluginData<any>,
|
pluginData: AnyPluginData<any>,
|
||||||
channel: TextChannel,
|
channel: TextBasedChannel,
|
||||||
body: string,
|
body: string,
|
||||||
allowedMentions?: MessageMentionOptions,
|
allowedMentions?: MessageMentionOptions,
|
||||||
): Promise<Message | undefined> {
|
): Promise<Message | undefined> {
|
||||||
const emoji = pluginData.fullConfig.error_emoji || undefined;
|
const emoji = pluginData.fullConfig.error_emoji || undefined;
|
||||||
const formattedBody = errorMessage(body, emoji);
|
const formattedBody = errorMessage(body, emoji);
|
||||||
const content: MessageOptions = allowedMentions
|
const content: MessageCreateOptions = allowedMentions
|
||||||
? { content: formattedBody, allowedMentions }
|
? { content: formattedBody, allowedMentions }
|
||||||
: { content: formattedBody };
|
: { content: formattedBody };
|
||||||
|
|
||||||
return channel
|
return channel
|
||||||
.send({ ...content }) // Force line break
|
.send({ ...content }) // Force line break
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
const channelInfo = channel.guild ? `${channel.id} (${channel.guild.id})` : channel.id;
|
const channelInfo = "guild" in channel ? `${channel.id} (${channel.guild.id})` : channel.id;
|
||||||
logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`);
|
logger.warn(`Failed to send error message to ${channelInfo}): ${err.code} ${err.message}`);
|
||||||
return undefined;
|
return undefined;
|
||||||
});
|
});
|
||||||
|
@ -230,11 +149,13 @@ export async function sendErrorMessage(
|
||||||
|
|
||||||
export function getBaseUrl(pluginData: AnyPluginData<any>) {
|
export function getBaseUrl(pluginData: AnyPluginData<any>) {
|
||||||
const knub = pluginData.getKnubInstance() as TZeppelinKnub;
|
const knub = pluginData.getKnubInstance() as TZeppelinKnub;
|
||||||
|
// @ts-expect-error
|
||||||
return knub.getGlobalConfig().url;
|
return knub.getGlobalConfig().url;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function isOwner(pluginData: AnyPluginData<any>, userId: string) {
|
export function isOwner(pluginData: AnyPluginData<any>, userId: string) {
|
||||||
const knub = pluginData.getKnubInstance() as TZeppelinKnub;
|
const knub = pluginData.getKnubInstance() as TZeppelinKnub;
|
||||||
|
// @ts-expect-error
|
||||||
const owners = knub.getGlobalConfig()?.owners;
|
const owners = knub.getGlobalConfig()?.owners;
|
||||||
if (!owners) {
|
if (!owners) {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { PluginOptions } from "knub";
|
import { PluginOptions } from "knub";
|
||||||
import { GuildLogs } from "../../data/GuildLogs";
|
import { GuildLogs } from "../../data/GuildLogs";
|
||||||
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
|
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
|
||||||
|
import { makeIoTsConfigParser } from "../../pluginUtils";
|
||||||
import { LogsPlugin } from "../Logs/LogsPlugin";
|
import { LogsPlugin } from "../Logs/LogsPlugin";
|
||||||
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
import { TimeAndDatePlugin } from "../TimeAndDate/TimeAndDatePlugin";
|
||||||
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
|
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
|
||||||
|
@ -23,10 +24,11 @@ export const AutoDeletePlugin = zeppelinGuildPlugin<AutoDeletePluginType>()({
|
||||||
prettyName: "Auto-delete",
|
prettyName: "Auto-delete",
|
||||||
description: "Allows Zeppelin to auto-delete messages from a channel after a delay",
|
description: "Allows Zeppelin to auto-delete messages from a channel after a delay",
|
||||||
configurationGuide: "Maximum deletion delay is currently 5 minutes",
|
configurationGuide: "Maximum deletion delay is currently 5 minutes",
|
||||||
|
configSchema: ConfigSchema,
|
||||||
},
|
},
|
||||||
|
|
||||||
dependencies: () => [TimeAndDatePlugin, LogsPlugin],
|
dependencies: () => [TimeAndDatePlugin, LogsPlugin],
|
||||||
configSchema: ConfigSchema,
|
configParser: makeIoTsConfigParser(ConfigSchema),
|
||||||
defaultOptions,
|
defaultOptions,
|
||||||
|
|
||||||
beforeLoad(pluginData) {
|
beforeLoad(pluginData) {
|
||||||
|
@ -56,8 +58,10 @@ export const AutoDeletePlugin = zeppelinGuildPlugin<AutoDeletePluginType>()({
|
||||||
},
|
},
|
||||||
|
|
||||||
beforeUnload(pluginData) {
|
beforeUnload(pluginData) {
|
||||||
pluginData.state.guildSavedMessages.events.off("create", pluginData.state.onMessageCreateFn);
|
const { state, guild } = pluginData;
|
||||||
pluginData.state.guildSavedMessages.events.off("delete", pluginData.state.onMessageDeleteFn);
|
|
||||||
pluginData.state.guildSavedMessages.events.off("deleteBulk", pluginData.state.onMessageDeleteBulkFn);
|
state.guildSavedMessages.events.off("create", state.onMessageCreateFn);
|
||||||
|
state.guildSavedMessages.events.off("delete", state.onMessageDeleteFn);
|
||||||
|
state.guildSavedMessages.events.off("deleteBulk", state.onMessageDeleteBulkFn);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
import { Permissions, Snowflake, TextChannel } from "discord.js";
|
import { ChannelType, PermissionsBitField, Snowflake } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { channelToTemplateSafeChannel, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
|
||||||
import { LogType } from "../../../data/LogType";
|
import { LogType } from "../../../data/LogType";
|
||||||
import { logger } from "../../../logger";
|
import { logger } from "../../../logger";
|
||||||
import { resolveUser, verboseChannelMention } from "../../../utils";
|
import { resolveUser, verboseChannelMention } from "../../../utils";
|
||||||
|
@ -17,8 +16,8 @@ export async function deleteNextItem(pluginData: GuildPluginData<AutoDeletePlugi
|
||||||
|
|
||||||
scheduleNextDeletion(pluginData);
|
scheduleNextDeletion(pluginData);
|
||||||
|
|
||||||
const channel = pluginData.guild.channels.cache.get(itemToDelete.message.channel_id as Snowflake) as TextChannel;
|
const channel = pluginData.guild.channels.cache.get(itemToDelete.message.channel_id as Snowflake);
|
||||||
if (!channel) {
|
if (!channel || channel.type === ChannelType.GuildCategory) {
|
||||||
// Channel was deleted, ignore
|
// Channel was deleted, ignore
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +25,9 @@ export async function deleteNextItem(pluginData: GuildPluginData<AutoDeletePlugi
|
||||||
const logs = pluginData.getPlugin(LogsPlugin);
|
const logs = pluginData.getPlugin(LogsPlugin);
|
||||||
const perms = channel.permissionsFor(pluginData.client.user!.id);
|
const perms = channel.permissionsFor(pluginData.client.user!.id);
|
||||||
|
|
||||||
if (!hasDiscordPermissions(perms, Permissions.FLAGS.VIEW_CHANNEL | Permissions.FLAGS.READ_MESSAGE_HISTORY)) {
|
if (
|
||||||
|
!hasDiscordPermissions(perms, PermissionsBitField.Flags.ViewChannel | PermissionsBitField.Flags.ReadMessageHistory)
|
||||||
|
) {
|
||||||
logs.logBotAlert({
|
logs.logBotAlert({
|
||||||
body: `Missing permissions to read messages or message history in auto-delete channel ${verboseChannelMention(
|
body: `Missing permissions to read messages or message history in auto-delete channel ${verboseChannelMention(
|
||||||
channel,
|
channel,
|
||||||
|
@ -35,7 +36,7 @@ export async function deleteNextItem(pluginData: GuildPluginData<AutoDeletePlugi
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!hasDiscordPermissions(perms, Permissions.FLAGS.MANAGE_MESSAGES)) {
|
if (!hasDiscordPermissions(perms, PermissionsBitField.Flags.ManageMessages)) {
|
||||||
logs.logBotAlert({
|
logs.logBotAlert({
|
||||||
body: `Missing permissions to delete messages in auto-delete channel ${verboseChannelMention(channel)}`,
|
body: `Missing permissions to delete messages in auto-delete channel ${verboseChannelMention(channel)}`,
|
||||||
});
|
});
|
||||||
|
@ -45,7 +46,7 @@ export async function deleteNextItem(pluginData: GuildPluginData<AutoDeletePlugi
|
||||||
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
const timeAndDate = pluginData.getPlugin(TimeAndDatePlugin);
|
||||||
|
|
||||||
pluginData.state.guildLogs.ignoreLog(LogType.MESSAGE_DELETE, itemToDelete.message.id);
|
pluginData.state.guildLogs.ignoreLog(LogType.MESSAGE_DELETE, itemToDelete.message.id);
|
||||||
(channel as TextChannel).messages.delete(itemToDelete.message.id as Snowflake).catch((err) => {
|
channel.messages.delete(itemToDelete.message.id as Snowflake).catch((err) => {
|
||||||
if (err.code === 10008) {
|
if (err.code === 10008) {
|
||||||
// "Unknown Message", probably already deleted by automod or another bot, ignore
|
// "Unknown Message", probably already deleted by automod or another bot, ignore
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -1,10 +1,9 @@
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import { SavedMessage } from "../../../data/entities/SavedMessage";
|
import { SavedMessage } from "../../../data/entities/SavedMessage";
|
||||||
import { LogType } from "../../../data/LogType";
|
|
||||||
import { convertDelayStringToMS, resolveMember } from "../../../utils";
|
import { convertDelayStringToMS, resolveMember } from "../../../utils";
|
||||||
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { AutoDeletePluginType, MAX_DELAY } from "../types";
|
import { AutoDeletePluginType, MAX_DELAY } from "../types";
|
||||||
import { addMessageToDeletionQueue } from "./addMessageToDeletionQueue";
|
import { addMessageToDeletionQueue } from "./addMessageToDeletionQueue";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
|
||||||
|
|
||||||
export async function onMessageCreate(pluginData: GuildPluginData<AutoDeletePluginType>, msg: SavedMessage) {
|
export async function onMessageCreate(pluginData: GuildPluginData<AutoDeletePluginType>, msg: SavedMessage) {
|
||||||
const member = await resolveMember(pluginData.client, pluginData.guild, msg.user_id);
|
const member = await resolveMember(pluginData.client, pluginData.guild, msg.user_id);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import { PluginOptions } from "knub";
|
import { PluginOptions } from "knub";
|
||||||
import { GuildAutoReactions } from "../../data/GuildAutoReactions";
|
import { GuildAutoReactions } from "../../data/GuildAutoReactions";
|
||||||
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
|
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
|
||||||
|
import { makeIoTsConfigParser } from "../../pluginUtils";
|
||||||
import { trimPluginDescription } from "../../utils";
|
import { trimPluginDescription } from "../../utils";
|
||||||
import { LogsPlugin } from "../Logs/LogsPlugin";
|
import { LogsPlugin } from "../Logs/LogsPlugin";
|
||||||
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
|
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
|
||||||
|
@ -31,6 +32,7 @@ export const AutoReactionsPlugin = zeppelinGuildPlugin<AutoReactionsPluginType>(
|
||||||
description: trimPluginDescription(`
|
description: trimPluginDescription(`
|
||||||
Allows setting up automatic reactions to all new messages on a channel
|
Allows setting up automatic reactions to all new messages on a channel
|
||||||
`),
|
`),
|
||||||
|
configSchema: ConfigSchema,
|
||||||
},
|
},
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
|
@ -38,11 +40,11 @@ export const AutoReactionsPlugin = zeppelinGuildPlugin<AutoReactionsPluginType>(
|
||||||
LogsPlugin,
|
LogsPlugin,
|
||||||
],
|
],
|
||||||
|
|
||||||
configSchema: ConfigSchema,
|
configParser: makeIoTsConfigParser(ConfigSchema),
|
||||||
defaultOptions,
|
defaultOptions,
|
||||||
|
|
||||||
// prettier-ignore
|
// prettier-ignore
|
||||||
commands: [
|
messageCommands: [
|
||||||
NewAutoReactionsCmd,
|
NewAutoReactionsCmd,
|
||||||
DisableAutoReactionsCmd,
|
DisableAutoReactionsCmd,
|
||||||
],
|
],
|
||||||
|
@ -53,8 +55,10 @@ export const AutoReactionsPlugin = zeppelinGuildPlugin<AutoReactionsPluginType>(
|
||||||
],
|
],
|
||||||
|
|
||||||
beforeLoad(pluginData) {
|
beforeLoad(pluginData) {
|
||||||
pluginData.state.savedMessages = GuildSavedMessages.getGuildInstance(pluginData.guild.id);
|
const { state, guild } = pluginData;
|
||||||
pluginData.state.autoReactions = GuildAutoReactions.getGuildInstance(pluginData.guild.id);
|
|
||||||
pluginData.state.cache = new Map();
|
state.savedMessages = GuildSavedMessages.getGuildInstance(guild.id);
|
||||||
|
state.autoReactions = GuildAutoReactions.getGuildInstance(guild.id);
|
||||||
|
state.cache = new Map();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { GuildChannel, Permissions } from "discord.js";
|
import { PermissionsBitField } from "discord.js";
|
||||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||||
import { canUseEmoji, customEmojiRegex, isEmoji } from "../../../utils";
|
import { canUseEmoji, customEmojiRegex, isEmoji } from "../../../utils";
|
||||||
|
@ -7,7 +7,7 @@ import { missingPermissionError } from "../../../utils/missingPermissionError";
|
||||||
import { readChannelPermissions } from "../../../utils/readChannelPermissions";
|
import { readChannelPermissions } from "../../../utils/readChannelPermissions";
|
||||||
import { autoReactionsCmd } from "../types";
|
import { autoReactionsCmd } from "../types";
|
||||||
|
|
||||||
const requiredPermissions = readChannelPermissions | Permissions.FLAGS.ADD_REACTIONS;
|
const requiredPermissions = readChannelPermissions | PermissionsBitField.Flags.AddReactions;
|
||||||
|
|
||||||
export const NewAutoReactionsCmd = autoReactionsCmd({
|
export const NewAutoReactionsCmd = autoReactionsCmd({
|
||||||
trigger: "auto_reactions",
|
trigger: "auto_reactions",
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
import { GuildChannel, GuildTextBasedChannel, Permissions } from "discord.js";
|
import { GuildTextBasedChannel, PermissionsBitField } from "discord.js";
|
||||||
import { LogType } from "../../../data/LogType";
|
import { AutoReaction } from "../../../data/entities/AutoReaction";
|
||||||
import { isDiscordAPIError } from "../../../utils";
|
import { isDiscordAPIError } from "../../../utils";
|
||||||
import { getMissingChannelPermissions } from "../../../utils/getMissingChannelPermissions";
|
import { getMissingChannelPermissions } from "../../../utils/getMissingChannelPermissions";
|
||||||
import { missingPermissionError } from "../../../utils/missingPermissionError";
|
import { missingPermissionError } from "../../../utils/missingPermissionError";
|
||||||
import { readChannelPermissions } from "../../../utils/readChannelPermissions";
|
import { readChannelPermissions } from "../../../utils/readChannelPermissions";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { autoReactionsEvt } from "../types";
|
import { autoReactionsEvt } from "../types";
|
||||||
import { AutoReaction } from "../../../data/entities/AutoReaction";
|
|
||||||
|
|
||||||
const p = Permissions.FLAGS;
|
const p = PermissionsBitField.Flags;
|
||||||
|
|
||||||
export const AddReactionsEvt = autoReactionsEvt({
|
export const AddReactionsEvt = autoReactionsEvt({
|
||||||
event: "messageCreate",
|
event: "messageCreate",
|
||||||
|
@ -40,7 +39,7 @@ export const AddReactionsEvt = autoReactionsEvt({
|
||||||
|
|
||||||
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
||||||
if (me) {
|
if (me) {
|
||||||
const missingPermissions = getMissingChannelPermissions(me, channel, readChannelPermissions | p.ADD_REACTIONS);
|
const missingPermissions = getMissingChannelPermissions(me, channel, readChannelPermissions | p.AddReactions);
|
||||||
if (missingPermissions) {
|
if (missingPermissions) {
|
||||||
const logs = pluginData.getPlugin(LogsPlugin);
|
const logs = pluginData.getPlugin(LogsPlugin);
|
||||||
logs.logBotAlert({
|
logs.logBotAlert({
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { BasePluginType, typedGuildCommand, typedGuildEventListener } from "knub";
|
import { BasePluginType, guildPluginEventListener, guildPluginMessageCommand } from "knub";
|
||||||
|
import { AutoReaction } from "../../data/entities/AutoReaction";
|
||||||
import { GuildAutoReactions } from "../../data/GuildAutoReactions";
|
import { GuildAutoReactions } from "../../data/GuildAutoReactions";
|
||||||
import { GuildLogs } from "../../data/GuildLogs";
|
import { GuildLogs } from "../../data/GuildLogs";
|
||||||
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
|
import { GuildSavedMessages } from "../../data/GuildSavedMessages";
|
||||||
import { AutoReaction } from "../../data/entities/AutoReaction";
|
|
||||||
|
|
||||||
export const ConfigSchema = t.type({
|
export const ConfigSchema = t.type({
|
||||||
can_manage: t.boolean,
|
can_manage: t.boolean,
|
||||||
|
@ -20,5 +20,5 @@ export interface AutoReactionsPluginType extends BasePluginType {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
export const autoReactionsCmd = typedGuildCommand<AutoReactionsPluginType>();
|
export const autoReactionsCmd = guildPluginMessageCommand<AutoReactionsPluginType>();
|
||||||
export const autoReactionsEvt = typedGuildEventListener<AutoReactionsPluginType>();
|
export const autoReactionsEvt = guildPluginEventListener<AutoReactionsPluginType>();
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
import * as t from "io-ts";
|
||||||
import { configUtils, CooldownManager } from "knub";
|
import { configUtils, CooldownManager } from "knub";
|
||||||
import { ConfigPreprocessorFn } from "knub/dist/config/configTypes";
|
|
||||||
import { GuildAntiraidLevels } from "../../data/GuildAntiraidLevels";
|
import { GuildAntiraidLevels } from "../../data/GuildAntiraidLevels";
|
||||||
import { GuildArchives } from "../../data/GuildArchives";
|
import { GuildArchives } from "../../data/GuildArchives";
|
||||||
import { GuildLogs } from "../../data/GuildLogs";
|
import { GuildLogs } from "../../data/GuildLogs";
|
||||||
|
@ -9,11 +9,13 @@ import { discardRegExpRunner, getRegExpRunner } from "../../regExpRunners";
|
||||||
import { MINUTES, SECONDS } from "../../utils";
|
import { MINUTES, SECONDS } from "../../utils";
|
||||||
import { registerEventListenersFromMap } from "../../utils/registerEventListenersFromMap";
|
import { registerEventListenersFromMap } from "../../utils/registerEventListenersFromMap";
|
||||||
import { unregisterEventListenersFromMap } from "../../utils/unregisterEventListenersFromMap";
|
import { unregisterEventListenersFromMap } from "../../utils/unregisterEventListenersFromMap";
|
||||||
import { StrictValidationError } from "../../validatorUtils";
|
import { StrictValidationError, validate } from "../../validatorUtils";
|
||||||
import { CountersPlugin } from "../Counters/CountersPlugin";
|
import { CountersPlugin } from "../Counters/CountersPlugin";
|
||||||
|
import { InternalPosterPlugin } from "../InternalPoster/InternalPosterPlugin";
|
||||||
import { LogsPlugin } from "../Logs/LogsPlugin";
|
import { LogsPlugin } from "../Logs/LogsPlugin";
|
||||||
import { ModActionsPlugin } from "../ModActions/ModActionsPlugin";
|
import { ModActionsPlugin } from "../ModActions/ModActionsPlugin";
|
||||||
import { MutesPlugin } from "../Mutes/MutesPlugin";
|
import { MutesPlugin } from "../Mutes/MutesPlugin";
|
||||||
|
import { PhishermanPlugin } from "../Phisherman/PhishermanPlugin";
|
||||||
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
|
import { zeppelinGuildPlugin } from "../ZeppelinPluginBlueprint";
|
||||||
import { availableActions } from "./actions/availableActions";
|
import { availableActions } from "./actions/availableActions";
|
||||||
import { AntiraidClearCmd } from "./commands/AntiraidClearCmd";
|
import { AntiraidClearCmd } from "./commands/AntiraidClearCmd";
|
||||||
|
@ -35,8 +37,6 @@ import { clearOldRecentSpam } from "./functions/clearOldRecentSpam";
|
||||||
import { pluginInfo } from "./info";
|
import { pluginInfo } from "./info";
|
||||||
import { availableTriggers } from "./triggers/availableTriggers";
|
import { availableTriggers } from "./triggers/availableTriggers";
|
||||||
import { AutomodPluginType, ConfigSchema } from "./types";
|
import { AutomodPluginType, ConfigSchema } from "./types";
|
||||||
import { PhishermanPlugin } from "../Phisherman/PhishermanPlugin";
|
|
||||||
import { InternalPosterPlugin } from "../InternalPoster/InternalPosterPlugin";
|
|
||||||
|
|
||||||
const defaultOptions = {
|
const defaultOptions = {
|
||||||
config: {
|
config: {
|
||||||
|
@ -63,13 +63,15 @@ const defaultOptions = {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Config preprocessor to set default values for triggers and perform extra validation
|
* Config preprocessor to set default values for triggers and perform extra validation
|
||||||
|
* TODO: Separate input and output types
|
||||||
*/
|
*/
|
||||||
const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = (options) => {
|
const configParser = (input: unknown) => {
|
||||||
if (options.config?.rules) {
|
const rules = (input as any).rules;
|
||||||
|
if (rules) {
|
||||||
// Loop through each rule
|
// Loop through each rule
|
||||||
for (const [name, rule] of Object.entries(options.config.rules)) {
|
for (const [name, rule] of Object.entries(rules)) {
|
||||||
if (rule == null) {
|
if (rule == null) {
|
||||||
delete options.config.rules[name];
|
delete rules[name];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -97,7 +99,7 @@ const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = (options) =>
|
||||||
for (const triggerObj of rule["triggers"]) {
|
for (const triggerObj of rule["triggers"]) {
|
||||||
for (const triggerName in triggerObj) {
|
for (const triggerName in triggerObj) {
|
||||||
if (!availableTriggers[triggerName]) {
|
if (!availableTriggers[triggerName]) {
|
||||||
throw new StrictValidationError([`Unknown trigger '${triggerName}' in rule '${rule.name}'`]);
|
throw new StrictValidationError([`Unknown trigger '${triggerName}' in rule '${rule["name"]}'`]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const triggerBlueprint = availableTriggers[triggerName];
|
const triggerBlueprint = availableTriggers[triggerName];
|
||||||
|
@ -117,11 +119,11 @@ const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = (options) =>
|
||||||
|
|
||||||
if (white && black) {
|
if (white && black) {
|
||||||
throw new StrictValidationError([
|
throw new StrictValidationError([
|
||||||
`Cannot have both blacklist and whitelist enabled at rule <${rule.name}/match_attachment_type>`,
|
`Cannot have both blacklist and whitelist enabled at rule <${rule["name"]}/match_attachment_type>`,
|
||||||
]);
|
]);
|
||||||
} else if (!white && !black) {
|
} else if (!white && !black) {
|
||||||
throw new StrictValidationError([
|
throw new StrictValidationError([
|
||||||
`Must have either blacklist or whitelist enabled at rule <${rule.name}/match_attachment_type>`,
|
`Must have either blacklist or whitelist enabled at rule <${rule["name"]}/match_attachment_type>`,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -132,11 +134,11 @@ const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = (options) =>
|
||||||
|
|
||||||
if (white && black) {
|
if (white && black) {
|
||||||
throw new StrictValidationError([
|
throw new StrictValidationError([
|
||||||
`Cannot have both blacklist and whitelist enabled at rule <${rule.name}/match_mime_type>`,
|
`Cannot have both blacklist and whitelist enabled at rule <${rule["name"]}/match_mime_type>`,
|
||||||
]);
|
]);
|
||||||
} else if (!white && !black) {
|
} else if (!white && !black) {
|
||||||
throw new StrictValidationError([
|
throw new StrictValidationError([
|
||||||
`Must have either blacklist or whitelist enabled at rule <${rule.name}/match_mime_type>`,
|
`Must have either blacklist or whitelist enabled at rule <${rule["name"]}/match_mime_type>`,
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -147,7 +149,7 @@ const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = (options) =>
|
||||||
if (rule["actions"]) {
|
if (rule["actions"]) {
|
||||||
for (const actionName in rule["actions"]) {
|
for (const actionName in rule["actions"]) {
|
||||||
if (!availableActions[actionName]) {
|
if (!availableActions[actionName]) {
|
||||||
throw new StrictValidationError([`Unknown action '${actionName}' in rule '${rule.name}'`]);
|
throw new StrictValidationError([`Unknown action '${actionName}' in rule '${rule["name"]}'`]);
|
||||||
}
|
}
|
||||||
|
|
||||||
const actionBlueprint = availableActions[actionName];
|
const actionBlueprint = availableActions[actionName];
|
||||||
|
@ -163,9 +165,9 @@ const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = (options) =>
|
||||||
|
|
||||||
// Enable logging of automod actions by default
|
// Enable logging of automod actions by default
|
||||||
if (rule["actions"]) {
|
if (rule["actions"]) {
|
||||||
for (const actionName in rule.actions) {
|
for (const actionName in rule["actions"]) {
|
||||||
if (!availableActions[actionName]) {
|
if (!availableActions[actionName]) {
|
||||||
throw new StrictValidationError([`Unknown action '${actionName}' in rule '${rule.name}'`]);
|
throw new StrictValidationError([`Unknown action '${actionName}' in rule '${rule["name"]}'`]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,13 +175,18 @@ const configPreprocessor: ConfigPreprocessorFn<AutomodPluginType> = (options) =>
|
||||||
rule["actions"]["log"] = true;
|
rule["actions"]["log"] = true;
|
||||||
}
|
}
|
||||||
if (rule["actions"]["clean"] && rule["actions"]["start_thread"]) {
|
if (rule["actions"]["clean"] && rule["actions"]["start_thread"]) {
|
||||||
throw new StrictValidationError([`Cannot have both clean and start_thread at rule '${rule.name}'`]);
|
throw new StrictValidationError([`Cannot have both clean and start_thread at rule '${rule["name"]}'`]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return options;
|
const error = validate(ConfigSchema, input);
|
||||||
|
if (error) {
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
|
||||||
|
return input as t.TypeOf<typeof ConfigSchema>;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
|
export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
|
||||||
|
@ -197,9 +204,8 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
|
||||||
InternalPosterPlugin,
|
InternalPosterPlugin,
|
||||||
],
|
],
|
||||||
|
|
||||||
configSchema: ConfigSchema,
|
|
||||||
defaultOptions,
|
defaultOptions,
|
||||||
configPreprocessor,
|
configParser,
|
||||||
|
|
||||||
customOverrideCriteriaFunctions: {
|
customOverrideCriteriaFunctions: {
|
||||||
antiraid_level: (pluginData, matchParams, value) => {
|
antiraid_level: (pluginData, matchParams, value) => {
|
||||||
|
@ -218,136 +224,126 @@ export const AutomodPlugin = zeppelinGuildPlugin<AutomodPluginType>()({
|
||||||
// Messages use message events from SavedMessages, see onLoad below
|
// Messages use message events from SavedMessages, see onLoad below
|
||||||
],
|
],
|
||||||
|
|
||||||
commands: [AntiraidClearCmd, SetAntiraidCmd, ViewAntiraidCmd],
|
messageCommands: [AntiraidClearCmd, SetAntiraidCmd, ViewAntiraidCmd],
|
||||||
|
|
||||||
async beforeLoad(pluginData) {
|
async beforeLoad(pluginData) {
|
||||||
pluginData.state.queue = new Queue();
|
const { state, guild } = pluginData;
|
||||||
|
|
||||||
pluginData.state.regexRunner = getRegExpRunner(`guild-${pluginData.guild.id}`);
|
state.queue = new Queue();
|
||||||
|
|
||||||
pluginData.state.recentActions = [];
|
state.regexRunner = getRegExpRunner(`guild-${guild.id}`);
|
||||||
|
|
||||||
pluginData.state.recentSpam = [];
|
state.recentActions = [];
|
||||||
|
|
||||||
pluginData.state.recentNicknameChanges = new Map();
|
state.recentSpam = [];
|
||||||
|
|
||||||
pluginData.state.ignoredRoleChanges = new Set();
|
state.recentNicknameChanges = new Map();
|
||||||
|
|
||||||
pluginData.state.cooldownManager = new CooldownManager();
|
state.ignoredRoleChanges = new Set();
|
||||||
|
|
||||||
pluginData.state.logs = new GuildLogs(pluginData.guild.id);
|
state.cooldownManager = new CooldownManager();
|
||||||
pluginData.state.savedMessages = GuildSavedMessages.getGuildInstance(pluginData.guild.id);
|
|
||||||
pluginData.state.antiraidLevels = GuildAntiraidLevels.getGuildInstance(pluginData.guild.id);
|
|
||||||
pluginData.state.archives = GuildArchives.getGuildInstance(pluginData.guild.id);
|
|
||||||
|
|
||||||
pluginData.state.cachedAntiraidLevel = await pluginData.state.antiraidLevels.get();
|
state.logs = new GuildLogs(guild.id);
|
||||||
|
state.savedMessages = GuildSavedMessages.getGuildInstance(guild.id);
|
||||||
|
state.antiraidLevels = GuildAntiraidLevels.getGuildInstance(guild.id);
|
||||||
|
state.archives = GuildArchives.getGuildInstance(guild.id);
|
||||||
|
|
||||||
|
state.cachedAntiraidLevel = await state.antiraidLevels.get();
|
||||||
},
|
},
|
||||||
|
|
||||||
async afterLoad(pluginData) {
|
async afterLoad(pluginData) {
|
||||||
pluginData.state.clearRecentActionsInterval = setInterval(() => clearOldRecentActions(pluginData), 1 * MINUTES);
|
const { state, guild } = pluginData;
|
||||||
pluginData.state.clearRecentSpamInterval = setInterval(() => clearOldRecentSpam(pluginData), 1 * SECONDS);
|
|
||||||
pluginData.state.clearRecentNicknameChangesInterval = setInterval(
|
state.clearRecentActionsInterval = setInterval(() => clearOldRecentActions(pluginData), 1 * MINUTES);
|
||||||
|
state.clearRecentSpamInterval = setInterval(() => clearOldRecentSpam(pluginData), 1 * SECONDS);
|
||||||
|
state.clearRecentNicknameChangesInterval = setInterval(
|
||||||
() => clearOldRecentNicknameChanges(pluginData),
|
() => clearOldRecentNicknameChanges(pluginData),
|
||||||
30 * SECONDS,
|
30 * SECONDS,
|
||||||
);
|
);
|
||||||
|
|
||||||
pluginData.state.onMessageCreateFn = (message) => runAutomodOnMessage(pluginData, message, false);
|
state.onMessageCreateFn = (message) => runAutomodOnMessage(pluginData, message, false);
|
||||||
pluginData.state.savedMessages.events.on("create", pluginData.state.onMessageCreateFn);
|
state.savedMessages.events.on("create", state.onMessageCreateFn);
|
||||||
|
|
||||||
pluginData.state.onMessageUpdateFn = (message) => runAutomodOnMessage(pluginData, message, true);
|
|
||||||
pluginData.state.savedMessages.events.on("update", pluginData.state.onMessageUpdateFn);
|
|
||||||
|
|
||||||
|
state.onMessageUpdateFn = (message) => runAutomodOnMessage(pluginData, message, true);
|
||||||
|
state.savedMessages.events.on("update", state.onMessageUpdateFn);
|
||||||
const countersPlugin = pluginData.getPlugin(CountersPlugin);
|
const countersPlugin = pluginData.getPlugin(CountersPlugin);
|
||||||
|
|
||||||
pluginData.state.onCounterTrigger = (name, triggerName, channelId, userId) => {
|
state.onCounterTrigger = (name, triggerName, channelId, userId) => {
|
||||||
runAutomodOnCounterTrigger(pluginData, name, triggerName, channelId, userId, false);
|
runAutomodOnCounterTrigger(pluginData, name, triggerName, channelId, userId, false);
|
||||||
};
|
};
|
||||||
|
|
||||||
pluginData.state.onCounterReverseTrigger = (name, triggerName, channelId, userId) => {
|
state.onCounterReverseTrigger = (name, triggerName, channelId, userId) => {
|
||||||
runAutomodOnCounterTrigger(pluginData, name, triggerName, channelId, userId, true);
|
runAutomodOnCounterTrigger(pluginData, name, triggerName, channelId, userId, true);
|
||||||
};
|
};
|
||||||
|
countersPlugin.onCounterEvent("trigger", state.onCounterTrigger);
|
||||||
countersPlugin.onCounterEvent("trigger", pluginData.state.onCounterTrigger);
|
countersPlugin.onCounterEvent("reverseTrigger", state.onCounterReverseTrigger);
|
||||||
countersPlugin.onCounterEvent("reverseTrigger", pluginData.state.onCounterReverseTrigger);
|
|
||||||
|
|
||||||
const modActionsEvents = pluginData.getPlugin(ModActionsPlugin).getEventEmitter();
|
const modActionsEvents = pluginData.getPlugin(ModActionsPlugin).getEventEmitter();
|
||||||
pluginData.state.modActionsListeners = new Map();
|
state.modActionsListeners = new Map();
|
||||||
pluginData.state.modActionsListeners.set("note", (userId: string) =>
|
state.modActionsListeners.set("note", (userId: string) => runAutomodOnModAction(pluginData, "note", userId));
|
||||||
runAutomodOnModAction(pluginData, "note", userId),
|
state.modActionsListeners.set("warn", (userId: string, reason: string | undefined, isAutomodAction: boolean) =>
|
||||||
|
runAutomodOnModAction(pluginData, "warn", userId, reason, isAutomodAction),
|
||||||
);
|
);
|
||||||
pluginData.state.modActionsListeners.set(
|
state.modActionsListeners.set("kick", (userId: string, reason: string | undefined, isAutomodAction: boolean) =>
|
||||||
"warn",
|
runAutomodOnModAction(pluginData, "kick", userId, reason, isAutomodAction),
|
||||||
(userId: string, reason: string | undefined, isAutomodAction: boolean) =>
|
|
||||||
runAutomodOnModAction(pluginData, "warn", userId, reason, isAutomodAction),
|
|
||||||
);
|
);
|
||||||
pluginData.state.modActionsListeners.set(
|
state.modActionsListeners.set("ban", (userId: string, reason: string | undefined, isAutomodAction: boolean) =>
|
||||||
"kick",
|
runAutomodOnModAction(pluginData, "ban", userId, reason, isAutomodAction),
|
||||||
(userId: string, reason: string | undefined, isAutomodAction: boolean) =>
|
|
||||||
runAutomodOnModAction(pluginData, "kick", userId, reason, isAutomodAction),
|
|
||||||
);
|
);
|
||||||
pluginData.state.modActionsListeners.set(
|
state.modActionsListeners.set("unban", (userId: string) => runAutomodOnModAction(pluginData, "unban", userId));
|
||||||
"ban",
|
registerEventListenersFromMap(modActionsEvents, state.modActionsListeners);
|
||||||
(userId: string, reason: string | undefined, isAutomodAction: boolean) =>
|
|
||||||
runAutomodOnModAction(pluginData, "ban", userId, reason, isAutomodAction),
|
|
||||||
);
|
|
||||||
pluginData.state.modActionsListeners.set("unban", (userId: string) =>
|
|
||||||
runAutomodOnModAction(pluginData, "unban", userId),
|
|
||||||
);
|
|
||||||
registerEventListenersFromMap(modActionsEvents, pluginData.state.modActionsListeners);
|
|
||||||
|
|
||||||
const mutesEvents = pluginData.getPlugin(MutesPlugin).getEventEmitter();
|
const mutesEvents = pluginData.getPlugin(MutesPlugin).getEventEmitter();
|
||||||
pluginData.state.mutesListeners = new Map();
|
state.mutesListeners = new Map();
|
||||||
pluginData.state.mutesListeners.set(
|
state.mutesListeners.set("mute", (userId: string, reason: string | undefined, isAutomodAction: boolean) =>
|
||||||
"mute",
|
runAutomodOnModAction(pluginData, "mute", userId, reason, isAutomodAction),
|
||||||
(userId: string, reason: string | undefined, isAutomodAction: boolean) =>
|
|
||||||
runAutomodOnModAction(pluginData, "mute", userId, reason, isAutomodAction),
|
|
||||||
);
|
);
|
||||||
pluginData.state.mutesListeners.set("unmute", (userId: string) =>
|
state.mutesListeners.set("unmute", (userId: string) => runAutomodOnModAction(pluginData, "unmute", userId));
|
||||||
runAutomodOnModAction(pluginData, "unmute", userId),
|
registerEventListenersFromMap(mutesEvents, state.mutesListeners);
|
||||||
);
|
|
||||||
registerEventListenersFromMap(mutesEvents, pluginData.state.mutesListeners);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
async beforeUnload(pluginData) {
|
async beforeUnload(pluginData) {
|
||||||
|
const { state, guild } = pluginData;
|
||||||
|
|
||||||
const countersPlugin = pluginData.getPlugin(CountersPlugin);
|
const countersPlugin = pluginData.getPlugin(CountersPlugin);
|
||||||
if (pluginData.state.onCounterTrigger) {
|
if (state.onCounterTrigger) {
|
||||||
countersPlugin.offCounterEvent("trigger", pluginData.state.onCounterTrigger);
|
countersPlugin.offCounterEvent("trigger", state.onCounterTrigger);
|
||||||
}
|
}
|
||||||
if (pluginData.state.onCounterReverseTrigger) {
|
if (state.onCounterReverseTrigger) {
|
||||||
countersPlugin.offCounterEvent("reverseTrigger", pluginData.state.onCounterReverseTrigger);
|
countersPlugin.offCounterEvent("reverseTrigger", state.onCounterReverseTrigger);
|
||||||
}
|
}
|
||||||
|
|
||||||
const modActionsEvents = pluginData.getPlugin(ModActionsPlugin).getEventEmitter();
|
const modActionsEvents = pluginData.getPlugin(ModActionsPlugin).getEventEmitter();
|
||||||
if (pluginData.state.modActionsListeners) {
|
if (state.modActionsListeners) {
|
||||||
unregisterEventListenersFromMap(modActionsEvents, pluginData.state.modActionsListeners);
|
unregisterEventListenersFromMap(modActionsEvents, state.modActionsListeners);
|
||||||
}
|
}
|
||||||
|
|
||||||
const mutesEvents = pluginData.getPlugin(MutesPlugin).getEventEmitter();
|
const mutesEvents = pluginData.getPlugin(MutesPlugin).getEventEmitter();
|
||||||
if (pluginData.state.mutesListeners) {
|
if (state.mutesListeners) {
|
||||||
unregisterEventListenersFromMap(mutesEvents, pluginData.state.mutesListeners);
|
unregisterEventListenersFromMap(mutesEvents, state.mutesListeners);
|
||||||
}
|
}
|
||||||
|
|
||||||
pluginData.state.queue.clear();
|
state.queue.clear();
|
||||||
|
|
||||||
discardRegExpRunner(`guild-${pluginData.guild.id}`);
|
discardRegExpRunner(`guild-${guild.id}`);
|
||||||
|
|
||||||
if (pluginData.state.clearRecentActionsInterval) {
|
if (state.clearRecentActionsInterval) {
|
||||||
clearInterval(pluginData.state.clearRecentActionsInterval);
|
clearInterval(state.clearRecentActionsInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginData.state.clearRecentSpamInterval) {
|
if (state.clearRecentSpamInterval) {
|
||||||
clearInterval(pluginData.state.clearRecentSpamInterval);
|
clearInterval(state.clearRecentSpamInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginData.state.clearRecentNicknameChangesInterval) {
|
if (state.clearRecentNicknameChangesInterval) {
|
||||||
clearInterval(pluginData.state.clearRecentNicknameChangesInterval);
|
clearInterval(state.clearRecentNicknameChangesInterval);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pluginData.state.onMessageCreateFn) {
|
if (state.onMessageCreateFn) {
|
||||||
pluginData.state.savedMessages.events.off("create", pluginData.state.onMessageCreateFn);
|
state.savedMessages.events.off("create", state.onMessageCreateFn);
|
||||||
}
|
}
|
||||||
if (pluginData.state.onMessageUpdateFn) {
|
if (state.onMessageUpdateFn) {
|
||||||
pluginData.state.savedMessages.events.off("update", pluginData.state.onMessageUpdateFn);
|
state.savedMessages.events.off("update", state.onMessageUpdateFn);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Permissions, Snowflake } from "discord.js";
|
import { PermissionFlagsBits, Snowflake } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { LogType } from "../../../data/LogType";
|
|
||||||
import { nonNullish, unique } from "../../../utils";
|
import { nonNullish, unique } from "../../../utils";
|
||||||
import { canAssignRole } from "../../../utils/canAssignRole";
|
import { canAssignRole } from "../../../utils/canAssignRole";
|
||||||
import { getMissingPermissions } from "../../../utils/getMissingPermissions";
|
import { getMissingPermissions } from "../../../utils/getMissingPermissions";
|
||||||
|
@ -10,7 +9,7 @@ import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { ignoreRoleChange } from "../functions/ignoredRoleChanges";
|
import { ignoreRoleChange } from "../functions/ignoredRoleChanges";
|
||||||
import { automodAction } from "../helpers";
|
import { automodAction } from "../helpers";
|
||||||
|
|
||||||
const p = Permissions.FLAGS;
|
const p = PermissionFlagsBits;
|
||||||
|
|
||||||
export const AddRolesAction = automodAction({
|
export const AddRolesAction = automodAction({
|
||||||
configType: t.array(t.string),
|
configType: t.array(t.string),
|
||||||
|
@ -20,7 +19,7 @@ export const AddRolesAction = automodAction({
|
||||||
const members = unique(contexts.map((c) => c.member).filter(nonNullish));
|
const members = unique(contexts.map((c) => c.member).filter(nonNullish));
|
||||||
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
||||||
|
|
||||||
const missingPermissions = getMissingPermissions(me.permissions, p.MANAGE_ROLES);
|
const missingPermissions = getMissingPermissions(me.permissions, p.ManageRoles);
|
||||||
if (missingPermissions) {
|
if (missingPermissions) {
|
||||||
const logs = pluginData.getPlugin(LogsPlugin);
|
const logs = pluginData.getPlugin(LogsPlugin);
|
||||||
logs.logBotAlert({
|
logs.logBotAlert({
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { LogType } from "../../../data/LogType";
|
|
||||||
import { CountersPlugin } from "../../Counters/CountersPlugin";
|
import { CountersPlugin } from "../../Counters/CountersPlugin";
|
||||||
import { automodAction } from "../helpers";
|
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
|
import { automodAction } from "../helpers";
|
||||||
|
|
||||||
export const AddToCounterAction = automodAction({
|
export const AddToCounterAction = automodAction({
|
||||||
configType: t.type({
|
configType: t.type({
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Snowflake, TextChannel, ThreadChannel } from "discord.js";
|
import { Snowflake } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { erisAllowedMentionsToDjsMentionOptions } from "src/utils/erisAllowedMentionsToDjsMentionOptions";
|
import { erisAllowedMentionsToDjsMentionOptions } from "src/utils/erisAllowedMentionsToDjsMentionOptions";
|
||||||
import { LogType } from "../../../data/LogType";
|
import { LogType } from "../../../data/LogType";
|
||||||
|
@ -9,21 +9,19 @@ import {
|
||||||
TemplateSafeValueContainer,
|
TemplateSafeValueContainer,
|
||||||
} from "../../../templateFormatter";
|
} from "../../../templateFormatter";
|
||||||
import {
|
import {
|
||||||
createChunkedMessage,
|
chunkMessageLines,
|
||||||
|
isTruthy,
|
||||||
messageLink,
|
messageLink,
|
||||||
stripObjectToScalars,
|
|
||||||
tAllowedMentions,
|
tAllowedMentions,
|
||||||
tNormalizedNullOptional,
|
tNormalizedNullOptional,
|
||||||
isTruthy,
|
|
||||||
verboseChannelMention,
|
|
||||||
validateAndParseMessageContent,
|
validateAndParseMessageContent,
|
||||||
chunkMessageLines,
|
verboseChannelMention,
|
||||||
} from "../../../utils";
|
} from "../../../utils";
|
||||||
|
import { messageIsEmpty } from "../../../utils/messageIsEmpty";
|
||||||
|
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
||||||
|
import { InternalPosterPlugin } from "../../InternalPoster/InternalPosterPlugin";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { automodAction } from "../helpers";
|
import { automodAction } from "../helpers";
|
||||||
import { TemplateSafeUser, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
|
||||||
import { messageIsEmpty } from "../../../utils/messageIsEmpty";
|
|
||||||
import { InternalPosterPlugin } from "../../InternalPoster/InternalPosterPlugin";
|
|
||||||
|
|
||||||
export const AlertAction = automodAction({
|
export const AlertAction = automodAction({
|
||||||
configType: t.type({
|
configType: t.type({
|
||||||
|
@ -38,7 +36,7 @@ export const AlertAction = automodAction({
|
||||||
const channel = pluginData.guild.channels.cache.get(actionConfig.channel as Snowflake);
|
const channel = pluginData.guild.channels.cache.get(actionConfig.channel as Snowflake);
|
||||||
const logs = pluginData.getPlugin(LogsPlugin);
|
const logs = pluginData.getPlugin(LogsPlugin);
|
||||||
|
|
||||||
if (channel?.isText()) {
|
if (channel?.isTextBased()) {
|
||||||
const text = actionConfig.text;
|
const text = actionConfig.text;
|
||||||
const theMessageLink =
|
const theMessageLink =
|
||||||
contexts[0].message && messageLink(pluginData.guild.id, contexts[0].message.channel_id, contexts[0].message.id);
|
contexts[0].message && messageLink(pluginData.guild.id, contexts[0].message.channel_id, contexts[0].message.id);
|
||||||
|
@ -96,7 +94,7 @@ export const AlertAction = automodAction({
|
||||||
const chunks = chunkMessageLines(rendered);
|
const chunks = chunkMessageLines(rendered);
|
||||||
for (const chunk of chunks) {
|
for (const chunk of chunks) {
|
||||||
await poster.sendMessage(channel, {
|
await poster.sendMessage(channel, {
|
||||||
content: rendered,
|
content: chunk,
|
||||||
allowedMentions: erisAllowedMentionsToDjsMentionOptions(actionConfig.allowed_mentions),
|
allowedMentions: erisAllowedMentionsToDjsMentionOptions(actionConfig.allowed_mentions),
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { ThreadChannel } from "discord.js";
|
import { AnyThreadChannel } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { noop } from "../../../utils";
|
import { noop } from "../../../utils";
|
||||||
import { automodAction } from "../helpers";
|
import { automodAction } from "../helpers";
|
||||||
|
@ -11,7 +11,7 @@ export const ArchiveThreadAction = automodAction({
|
||||||
const threads = contexts
|
const threads = contexts
|
||||||
.filter((c) => c.message?.channel_id)
|
.filter((c) => c.message?.channel_id)
|
||||||
.map((c) => pluginData.guild.channels.cache.get(c.message!.channel_id))
|
.map((c) => pluginData.guild.channels.cache.get(c.message!.channel_id))
|
||||||
.filter((c): c is ThreadChannel => c?.isThread() ?? false);
|
.filter((c): c is AnyThreadChannel => c?.isThread() ?? false);
|
||||||
|
|
||||||
for (const thread of threads) {
|
for (const thread of threads) {
|
||||||
await thread.setArchived().catch(noop);
|
await thread.setArchived().catch(noop);
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { LogType } from "../../../data/LogType";
|
|
||||||
import { nonNullish, unique } from "../../../utils";
|
import { nonNullish, unique } from "../../../utils";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { automodAction } from "../helpers";
|
import { automodAction } from "../helpers";
|
||||||
|
|
|
@ -1,20 +1,72 @@
|
||||||
import { Permissions, PermissionString } from "discord.js";
|
import { PermissionsBitField, PermissionsString } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { automodAction } from "../helpers";
|
|
||||||
import { tNullable, isValidSnowflake, tPartialDictionary } from "../../../utils";
|
|
||||||
import { noop } from "knub/dist/utils";
|
|
||||||
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
|
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
|
||||||
|
import { isValidSnowflake, noop, tNullable, tPartialDictionary } from "../../../utils";
|
||||||
import {
|
import {
|
||||||
guildToTemplateSafeGuild,
|
guildToTemplateSafeGuild,
|
||||||
savedMessageToTemplateSafeSavedMessage,
|
savedMessageToTemplateSafeSavedMessage,
|
||||||
userToTemplateSafeUser,
|
userToTemplateSafeUser,
|
||||||
} from "../../../utils/templateSafeObjects";
|
} from "../../../utils/templateSafeObjects";
|
||||||
|
import { automodAction } from "../helpers";
|
||||||
|
|
||||||
|
type LegacyPermMap = Record<string, keyof (typeof PermissionsBitField)["Flags"]>;
|
||||||
|
const legacyPermMap = {
|
||||||
|
CREATE_INSTANT_INVITE: "CreateInstantInvite",
|
||||||
|
KICK_MEMBERS: "KickMembers",
|
||||||
|
BAN_MEMBERS: "BanMembers",
|
||||||
|
ADMINISTRATOR: "Administrator",
|
||||||
|
MANAGE_CHANNELS: "ManageChannels",
|
||||||
|
MANAGE_GUILD: "ManageGuild",
|
||||||
|
ADD_REACTIONS: "AddReactions",
|
||||||
|
VIEW_AUDIT_LOG: "ViewAuditLog",
|
||||||
|
PRIORITY_SPEAKER: "PrioritySpeaker",
|
||||||
|
STREAM: "Stream",
|
||||||
|
VIEW_CHANNEL: "ViewChannel",
|
||||||
|
SEND_MESSAGES: "SendMessages",
|
||||||
|
SEND_TTSMESSAGES: "SendTTSMessages",
|
||||||
|
MANAGE_MESSAGES: "ManageMessages",
|
||||||
|
EMBED_LINKS: "EmbedLinks",
|
||||||
|
ATTACH_FILES: "AttachFiles",
|
||||||
|
READ_MESSAGE_HISTORY: "ReadMessageHistory",
|
||||||
|
MENTION_EVERYONE: "MentionEveryone",
|
||||||
|
USE_EXTERNAL_EMOJIS: "UseExternalEmojis",
|
||||||
|
VIEW_GUILD_INSIGHTS: "ViewGuildInsights",
|
||||||
|
CONNECT: "Connect",
|
||||||
|
SPEAK: "Speak",
|
||||||
|
MUTE_MEMBERS: "MuteMembers",
|
||||||
|
DEAFEN_MEMBERS: "DeafenMembers",
|
||||||
|
MOVE_MEMBERS: "MoveMembers",
|
||||||
|
USE_VAD: "UseVAD",
|
||||||
|
CHANGE_NICKNAME: "ChangeNickname",
|
||||||
|
MANAGE_NICKNAMES: "ManageNicknames",
|
||||||
|
MANAGE_ROLES: "ManageRoles",
|
||||||
|
MANAGE_WEBHOOKS: "ManageWebhooks",
|
||||||
|
MANAGE_EMOJIS_AND_STICKERS: "ManageEmojisAndStickers",
|
||||||
|
USE_APPLICATION_COMMANDS: "UseApplicationCommands",
|
||||||
|
REQUEST_TO_SPEAK: "RequestToSpeak",
|
||||||
|
MANAGE_EVENTS: "ManageEvents",
|
||||||
|
MANAGE_THREADS: "ManageThreads",
|
||||||
|
CREATE_PUBLIC_THREADS: "CreatePublicThreads",
|
||||||
|
CREATE_PRIVATE_THREADS: "CreatePrivateThreads",
|
||||||
|
USE_EXTERNAL_STICKERS: "UseExternalStickers",
|
||||||
|
SEND_MESSAGES_IN_THREADS: "SendMessagesInThreads",
|
||||||
|
USE_EMBEDDED_ACTIVITIES: "UseEmbeddedActivities",
|
||||||
|
MODERATE_MEMBERS: "ModerateMembers",
|
||||||
|
} satisfies LegacyPermMap;
|
||||||
|
|
||||||
|
const realToLegacyMap = Object.entries(legacyPermMap).reduce((map, pair) => {
|
||||||
|
map[pair[1]] = pair[0];
|
||||||
|
return map;
|
||||||
|
}, {}) as Record<keyof typeof PermissionsBitField.Flags, keyof typeof legacyPermMap>;
|
||||||
|
|
||||||
export const ChangePermsAction = automodAction({
|
export const ChangePermsAction = automodAction({
|
||||||
configType: t.type({
|
configType: t.type({
|
||||||
target: t.string,
|
target: t.string,
|
||||||
channel: tNullable(t.string),
|
channel: tNullable(t.string),
|
||||||
perms: tPartialDictionary(t.keyof(Permissions.FLAGS), tNullable(t.boolean)),
|
perms: tPartialDictionary(
|
||||||
|
t.union([t.keyof(PermissionsBitField.Flags), t.keyof(legacyPermMap)]),
|
||||||
|
tNullable(t.boolean),
|
||||||
|
),
|
||||||
}),
|
}),
|
||||||
defaultConfig: {},
|
defaultConfig: {},
|
||||||
|
|
||||||
|
@ -52,13 +104,15 @@ export const ChangePermsAction = automodAction({
|
||||||
const channel = pluginData.guild.channels.resolve(channelId);
|
const channel = pluginData.guild.channels.resolve(channelId);
|
||||||
if (!channel || channel.isThread()) return;
|
if (!channel || channel.isThread()) return;
|
||||||
const overwrite = channel.permissionOverwrites.cache.find((pw) => pw.id === target);
|
const overwrite = channel.permissionOverwrites.cache.find((pw) => pw.id === target);
|
||||||
const allow = new Permissions(overwrite?.allow ?? 0n).serialize();
|
const allow = new PermissionsBitField(overwrite?.allow ?? 0n).serialize();
|
||||||
const deny = new Permissions(overwrite?.deny ?? 0n).serialize();
|
const deny = new PermissionsBitField(overwrite?.deny ?? 0n).serialize();
|
||||||
const newPerms: Partial<Record<PermissionString, boolean | null>> = {};
|
const newPerms: Partial<Record<PermissionsString, boolean | null>> = {};
|
||||||
|
|
||||||
for (const key in allow) {
|
for (const key in allow) {
|
||||||
if (typeof actionConfig.perms[key] !== "undefined") {
|
const legacyKey = realToLegacyMap[key];
|
||||||
newPerms[key] = actionConfig.perms[key];
|
const configEntry = actionConfig.perms[key] ?? actionConfig.perms[legacyKey];
|
||||||
|
if (typeof configEntry !== "undefined") {
|
||||||
|
newPerms[key] = configEntry;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (allow[key]) {
|
if (allow[key]) {
|
||||||
|
@ -86,11 +140,12 @@ export const ChangePermsAction = automodAction({
|
||||||
|
|
||||||
if (!role) return;
|
if (!role) return;
|
||||||
|
|
||||||
const perms = new Permissions(role.permissions).serialize();
|
const perms = new PermissionsBitField(role.permissions).serialize();
|
||||||
for (const key in actionConfig.perms) {
|
for (const key in actionConfig.perms) {
|
||||||
perms[key] = actionConfig.perms[key];
|
const realKey = legacyPermMap[key] ?? key;
|
||||||
|
perms[realKey] = actionConfig.perms[key];
|
||||||
}
|
}
|
||||||
const permsArray = <PermissionString[]>Object.keys(perms).filter((key) => perms[key]);
|
const permsArray = <PermissionsString[]>Object.keys(perms).filter((key) => perms[key]);
|
||||||
await role.setPermissions(new Permissions(permsArray)).catch(noop);
|
await role.setPermissions(new PermissionsBitField(permsArray)).catch(noop);
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Snowflake, TextChannel } from "discord.js";
|
import { GuildTextBasedChannel, Snowflake } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { LogType } from "../../../data/LogType";
|
import { LogType } from "../../../data/LogType";
|
||||||
import { noop } from "../../../utils";
|
import { noop } from "../../../utils";
|
||||||
|
@ -32,7 +32,7 @@ export const CleanAction = automodAction({
|
||||||
pluginData.state.logs.ignoreLog(LogType.MESSAGE_DELETE, id);
|
pluginData.state.logs.ignoreLog(LogType.MESSAGE_DELETE, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as TextChannel;
|
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as GuildTextBasedChannel;
|
||||||
await channel.bulkDelete(messageIds as Snowflake[]).catch(noop);
|
await channel.bulkDelete(messageIds as Snowflake[]).catch(noop);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,9 +1,7 @@
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { LogType } from "../../../data/LogType";
|
import { isTruthy, unique } from "../../../utils";
|
||||||
import { isTruthy, stripObjectToScalars, unique } from "../../../utils";
|
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { automodAction } from "../helpers";
|
import { automodAction } from "../helpers";
|
||||||
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
|
||||||
|
|
||||||
export const LogAction = automodAction({
|
export const LogAction = automodAction({
|
||||||
configType: t.boolean,
|
configType: t.boolean,
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { LogType } from "../../../data/LogType";
|
|
||||||
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
|
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
|
||||||
import { convertDelayStringToMS, nonNullish, tDelayString, tNullable, unique } from "../../../utils";
|
import { convertDelayStringToMS, nonNullish, tDelayString, tNullable, unique } from "../../../utils";
|
||||||
import { CaseArgs } from "../../Cases/types";
|
import { CaseArgs } from "../../Cases/types";
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { Permissions, Snowflake } from "discord.js";
|
import { PermissionFlagsBits, Snowflake } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { LogType } from "../../../data/LogType";
|
|
||||||
import { nonNullish, unique } from "../../../utils";
|
import { nonNullish, unique } from "../../../utils";
|
||||||
import { canAssignRole } from "../../../utils/canAssignRole";
|
import { canAssignRole } from "../../../utils/canAssignRole";
|
||||||
import { getMissingPermissions } from "../../../utils/getMissingPermissions";
|
import { getMissingPermissions } from "../../../utils/getMissingPermissions";
|
||||||
|
@ -10,7 +9,7 @@ import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { ignoreRoleChange } from "../functions/ignoredRoleChanges";
|
import { ignoreRoleChange } from "../functions/ignoredRoleChanges";
|
||||||
import { automodAction } from "../helpers";
|
import { automodAction } from "../helpers";
|
||||||
|
|
||||||
const p = Permissions.FLAGS;
|
const p = PermissionFlagsBits;
|
||||||
|
|
||||||
export const RemoveRolesAction = automodAction({
|
export const RemoveRolesAction = automodAction({
|
||||||
configType: t.array(t.string),
|
configType: t.array(t.string),
|
||||||
|
@ -21,7 +20,7 @@ export const RemoveRolesAction = automodAction({
|
||||||
const members = unique(contexts.map((c) => c.member).filter(nonNullish));
|
const members = unique(contexts.map((c) => c.member).filter(nonNullish));
|
||||||
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
const me = pluginData.guild.members.cache.get(pluginData.client.user!.id)!;
|
||||||
|
|
||||||
const missingPermissions = getMissingPermissions(me.permissions, p.MANAGE_ROLES);
|
const missingPermissions = getMissingPermissions(me.permissions, p.ManageRoles);
|
||||||
if (missingPermissions) {
|
if (missingPermissions) {
|
||||||
const logs = pluginData.getPlugin(LogsPlugin);
|
const logs = pluginData.getPlugin(LogsPlugin);
|
||||||
logs.logBotAlert({
|
logs.logBotAlert({
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
import { MessageOptions, Permissions, Snowflake, TextChannel, ThreadChannel, User } from "discord.js";
|
import { GuildTextBasedChannel, MessageCreateOptions, PermissionsBitField, Snowflake, User } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
|
||||||
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
|
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
|
||||||
import {
|
import {
|
||||||
convertDelayStringToMS,
|
convertDelayStringToMS,
|
||||||
|
@ -14,10 +13,11 @@ import {
|
||||||
verboseChannelMention,
|
verboseChannelMention,
|
||||||
} from "../../../utils";
|
} from "../../../utils";
|
||||||
import { hasDiscordPermissions } from "../../../utils/hasDiscordPermissions";
|
import { hasDiscordPermissions } from "../../../utils/hasDiscordPermissions";
|
||||||
|
import { messageIsEmpty } from "../../../utils/messageIsEmpty";
|
||||||
|
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
||||||
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { automodAction } from "../helpers";
|
import { automodAction } from "../helpers";
|
||||||
import { AutomodContext } from "../types";
|
import { AutomodContext } from "../types";
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
|
||||||
import { messageIsEmpty } from "../../../utils/messageIsEmpty";
|
|
||||||
|
|
||||||
export const ReplyAction = automodAction({
|
export const ReplyAction = automodAction({
|
||||||
configType: t.union([
|
configType: t.union([
|
||||||
|
@ -36,7 +36,7 @@ export const ReplyAction = automodAction({
|
||||||
.filter((c) => c.message?.channel_id)
|
.filter((c) => c.message?.channel_id)
|
||||||
.filter((c) => {
|
.filter((c) => {
|
||||||
const channel = pluginData.guild.channels.cache.get(c.message!.channel_id as Snowflake);
|
const channel = pluginData.guild.channels.cache.get(c.message!.channel_id as Snowflake);
|
||||||
return channel?.isText();
|
return channel?.isTextBased();
|
||||||
});
|
});
|
||||||
|
|
||||||
const contextsByChannelId = contextsWithTextChannels.reduce((map: Map<string, AutomodContext[]>, context) => {
|
const contextsByChannelId = contextsWithTextChannels.reduce((map: Map<string, AutomodContext[]>, context) => {
|
||||||
|
@ -63,16 +63,16 @@ export const ReplyAction = automodAction({
|
||||||
const formatted =
|
const formatted =
|
||||||
typeof actionConfig === "string"
|
typeof actionConfig === "string"
|
||||||
? await renderReplyText(actionConfig)
|
? await renderReplyText(actionConfig)
|
||||||
: ((await renderRecursively(actionConfig.text, renderReplyText)) as MessageOptions);
|
: ((await renderRecursively(actionConfig.text, renderReplyText)) as MessageCreateOptions);
|
||||||
|
|
||||||
if (formatted) {
|
if (formatted) {
|
||||||
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as TextChannel;
|
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake) as GuildTextBasedChannel;
|
||||||
|
|
||||||
// Check for basic Send Messages and View Channel permissions
|
// Check for basic Send Messages and View Channel permissions
|
||||||
if (
|
if (
|
||||||
!hasDiscordPermissions(
|
!hasDiscordPermissions(
|
||||||
channel.permissionsFor(pluginData.client.user!.id),
|
channel.permissionsFor(pluginData.client.user!.id),
|
||||||
Permissions.FLAGS.SEND_MESSAGES | Permissions.FLAGS.VIEW_CHANNEL,
|
PermissionsBitField.Flags.SendMessages | PermissionsBitField.Flags.ViewChannel,
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
pluginData.getPlugin(LogsPlugin).logBotAlert({
|
pluginData.getPlugin(LogsPlugin).logBotAlert({
|
||||||
|
@ -84,7 +84,10 @@ export const ReplyAction = automodAction({
|
||||||
// If the message is an embed, check for embed permissions
|
// If the message is an embed, check for embed permissions
|
||||||
if (
|
if (
|
||||||
typeof formatted !== "string" &&
|
typeof formatted !== "string" &&
|
||||||
!hasDiscordPermissions(channel.permissionsFor(pluginData.client.user!.id), Permissions.FLAGS.EMBED_LINKS)
|
!hasDiscordPermissions(
|
||||||
|
channel.permissionsFor(pluginData.client.user!.id),
|
||||||
|
PermissionsBitField.Flags.EmbedLinks,
|
||||||
|
)
|
||||||
) {
|
) {
|
||||||
pluginData.getPlugin(LogsPlugin).logBotAlert({
|
pluginData.getPlugin(LogsPlugin).logBotAlert({
|
||||||
body: `Missing permissions to reply **with an embed** in ${verboseChannelMention(
|
body: `Missing permissions to reply **with an embed** in ${verboseChannelMention(
|
||||||
|
@ -96,7 +99,7 @@ export const ReplyAction = automodAction({
|
||||||
|
|
||||||
const messageContent = validateAndParseMessageContent(formatted);
|
const messageContent = validateAndParseMessageContent(formatted);
|
||||||
|
|
||||||
const messageOpts: MessageOptions = {
|
const messageOpts: MessageCreateOptions = {
|
||||||
...messageContent,
|
...messageContent,
|
||||||
allowedMentions: {
|
allowedMentions: {
|
||||||
users: [user.id],
|
users: [user.id],
|
||||||
|
@ -118,7 +121,7 @@ export const ReplyAction = automodAction({
|
||||||
|
|
||||||
if (typeof actionConfig === "object" && actionConfig.auto_delete) {
|
if (typeof actionConfig === "object" && actionConfig.auto_delete) {
|
||||||
const delay = convertDelayStringToMS(String(actionConfig.auto_delete))!;
|
const delay = convertDelayStringToMS(String(actionConfig.auto_delete))!;
|
||||||
setTimeout(() => !replyMsg.deleted && replyMsg.delete().catch(noop), delay);
|
setTimeout(() => replyMsg.deletable && replyMsg.delete().catch(noop), delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { LogType } from "../../../data/LogType";
|
|
||||||
import { CountersPlugin } from "../../Counters/CountersPlugin";
|
import { CountersPlugin } from "../../Counters/CountersPlugin";
|
||||||
import { automodAction } from "../helpers";
|
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
|
import { automodAction } from "../helpers";
|
||||||
|
|
||||||
export const SetCounterAction = automodAction({
|
export const SetCounterAction = automodAction({
|
||||||
configType: t.type({
|
configType: t.type({
|
||||||
|
|
|
@ -1,10 +1,8 @@
|
||||||
import { Snowflake, TextChannel } from "discord.js";
|
import { ChannelType, GuildTextBasedChannel, Snowflake } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { ChannelTypeStrings } from "src/types";
|
|
||||||
import { LogType } from "../../../data/LogType";
|
|
||||||
import { convertDelayStringToMS, isDiscordAPIError, tDelayString, tNullable } from "../../../utils";
|
import { convertDelayStringToMS, isDiscordAPIError, tDelayString, tNullable } from "../../../utils";
|
||||||
import { automodAction } from "../helpers";
|
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
|
import { automodAction } from "../helpers";
|
||||||
|
|
||||||
export const SetSlowmodeAction = automodAction({
|
export const SetSlowmodeAction = automodAction({
|
||||||
configType: t.type({
|
configType: t.type({
|
||||||
|
@ -23,29 +21,27 @@ export const SetSlowmodeAction = automodAction({
|
||||||
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake);
|
const channel = pluginData.guild.channels.cache.get(channelId as Snowflake);
|
||||||
|
|
||||||
// Only text channels and text channels within categories support slowmodes
|
// Only text channels and text channels within categories support slowmodes
|
||||||
if (!channel || !(channel.type === ChannelTypeStrings.TEXT || ChannelTypeStrings.CATEGORY)) {
|
if (!channel || (!channel.isTextBased() && channel.type !== ChannelType.GuildCategory)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
const channelsToSlowmode: TextChannel[] = [];
|
const channelsToSlowmode: GuildTextBasedChannel[] = [];
|
||||||
if (channel.type === ChannelTypeStrings.CATEGORY) {
|
if (channel.type === ChannelType.GuildCategory) {
|
||||||
// Find all text channels within the category
|
// Find all text channels within the category
|
||||||
for (const ch of pluginData.guild.channels.cache.values()) {
|
for (const ch of pluginData.guild.channels.cache.values()) {
|
||||||
if (ch.parentId === channel.id && ch.type === ChannelTypeStrings.TEXT) {
|
if (ch.parentId === channel.id && ch.type === ChannelType.GuildText) {
|
||||||
channelsToSlowmode.push(ch as TextChannel);
|
channelsToSlowmode.push(ch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
channelsToSlowmode.push(channel as TextChannel);
|
channelsToSlowmode.push(channel);
|
||||||
}
|
}
|
||||||
|
|
||||||
const slowmodeSeconds = Math.ceil(slowmodeMs / 1000);
|
const slowmodeSeconds = Math.ceil(slowmodeMs / 1000);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (const chan of channelsToSlowmode) {
|
for (const chan of channelsToSlowmode) {
|
||||||
await chan.edit({
|
await chan.setRateLimitPerUser(slowmodeSeconds);
|
||||||
rateLimitPerUser: slowmodeSeconds,
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// Check for invalid form body -> indicates duration was too large
|
// Check for invalid form body -> indicates duration was too large
|
||||||
|
|
|
@ -1,8 +1,12 @@
|
||||||
import { GuildFeature, ThreadAutoArchiveDuration } from "discord-api-types/v9";
|
import {
|
||||||
import { TextChannel } from "discord.js";
|
ChannelType,
|
||||||
|
GuildFeature,
|
||||||
|
GuildTextThreadCreateOptions,
|
||||||
|
ThreadAutoArchiveDuration,
|
||||||
|
ThreadChannel,
|
||||||
|
} from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
|
import { renderTemplate, TemplateSafeValueContainer } from "../../../templateFormatter";
|
||||||
import { ChannelTypeStrings } from "../../../types";
|
|
||||||
import { convertDelayStringToMS, MINUTES, noop, tDelayString, tNullable } from "../../../utils";
|
import { convertDelayStringToMS, MINUTES, noop, tDelayString, tNullable } from "../../../utils";
|
||||||
import { savedMessageToTemplateSafeSavedMessage, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
import { savedMessageToTemplateSafeSavedMessage, userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
||||||
import { automodAction } from "../helpers";
|
import { automodAction } from "../helpers";
|
||||||
|
@ -32,12 +36,11 @@ export const StartThreadAction = automodAction({
|
||||||
const threads = contexts.filter((c) => {
|
const threads = contexts.filter((c) => {
|
||||||
if (!c.message || !c.user) return false;
|
if (!c.message || !c.user) return false;
|
||||||
const channel = pluginData.guild.channels.cache.get(c.message.channel_id);
|
const channel = pluginData.guild.channels.cache.get(c.message.channel_id);
|
||||||
if (channel?.type !== ChannelTypeStrings.TEXT || !channel.isText()) return false; // for some reason the typing here for channel.type defaults to ThreadChannelTypes (?)
|
if (channel?.type !== ChannelType.GuildText || !channel.isTextBased()) return false; // for some reason the typing here for channel.type defaults to ThreadChannelTypes (?)
|
||||||
// check against max threads per channel
|
// check against max threads per channel
|
||||||
if (actionConfig.limit_per_channel && actionConfig.limit_per_channel > 0) {
|
if (actionConfig.limit_per_channel && actionConfig.limit_per_channel > 0) {
|
||||||
const threadCount = channel.threads.cache.filter(
|
const threadCount = channel.threads.cache.filter(
|
||||||
(tr) =>
|
(tr) => tr.ownerId === pluginData.client.user!.id && !tr.archived && tr.parentId === channel.id,
|
||||||
tr.ownerId === pluginData.client.user!.id && !tr.deleted && !tr.archived && tr.parentId === channel.id,
|
|
||||||
).size;
|
).size;
|
||||||
if (threadCount >= actionConfig.limit_per_channel) return false;
|
if (threadCount >= actionConfig.limit_per_channel) return false;
|
||||||
}
|
}
|
||||||
|
@ -53,7 +56,9 @@ export const StartThreadAction = automodAction({
|
||||||
: ThreadAutoArchiveDuration.OneHour;
|
: ThreadAutoArchiveDuration.OneHour;
|
||||||
|
|
||||||
for (const threadContext of threads) {
|
for (const threadContext of threads) {
|
||||||
const channel = pluginData.guild.channels.cache.get(threadContext.message!.channel_id) as TextChannel;
|
const channel = pluginData.guild.channels.cache.get(threadContext.message!.channel_id);
|
||||||
|
if (!channel || !("threads" in channel) || channel.type === ChannelType.GuildForum) continue;
|
||||||
|
|
||||||
const renderThreadName = async (str: string) =>
|
const renderThreadName = async (str: string) =>
|
||||||
renderTemplate(
|
renderTemplate(
|
||||||
str,
|
str,
|
||||||
|
@ -63,20 +68,35 @@ export const StartThreadAction = automodAction({
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
const threadName = await renderThreadName(actionConfig.name ?? "{user.tag}s thread");
|
const threadName = await renderThreadName(actionConfig.name ?? "{user.tag}s thread");
|
||||||
const thread = await channel.threads
|
const threadOptions: GuildTextThreadCreateOptions<unknown> = {
|
||||||
.create({
|
name: threadName,
|
||||||
name: threadName,
|
autoArchiveDuration: autoArchive,
|
||||||
autoArchiveDuration: autoArchive,
|
startMessage:
|
||||||
type:
|
!actionConfig.private && guild.features.includes(GuildFeature.PrivateThreads)
|
||||||
actionConfig.private && guild.features.includes(GuildFeature.PrivateThreads)
|
? threadContext.message!.id
|
||||||
? ChannelTypeStrings.PRIVATE_THREAD
|
: undefined,
|
||||||
: ChannelTypeStrings.PUBLIC_THREAD,
|
};
|
||||||
startMessage:
|
|
||||||
!actionConfig.private && guild.features.includes(GuildFeature.PrivateThreads)
|
let thread: ThreadChannel | undefined;
|
||||||
? threadContext.message!.id
|
if (channel.type === ChannelType.GuildNews) {
|
||||||
: undefined,
|
thread = await channel.threads
|
||||||
})
|
.create({
|
||||||
.catch(noop);
|
...threadOptions,
|
||||||
|
type: ChannelType.AnnouncementThread,
|
||||||
|
})
|
||||||
|
.catch(() => undefined);
|
||||||
|
} else {
|
||||||
|
thread = await channel.threads
|
||||||
|
.create({
|
||||||
|
...threadOptions,
|
||||||
|
type: actionConfig.private ? ChannelType.PrivateThread : ChannelType.PublicThread,
|
||||||
|
startMessage:
|
||||||
|
!actionConfig.private && guild.features.includes(GuildFeature.PrivateThreads)
|
||||||
|
? threadContext.message!.id
|
||||||
|
: undefined,
|
||||||
|
})
|
||||||
|
.catch(() => undefined);
|
||||||
|
}
|
||||||
if (actionConfig.slowmode && thread) {
|
if (actionConfig.slowmode && thread) {
|
||||||
const dur = Math.ceil(Math.max(convertDelayStringToMS(actionConfig.slowmode) ?? 0, 0) / 1000);
|
const dur = Math.ceil(Math.max(convertDelayStringToMS(actionConfig.slowmode) ?? 0, 0) / 1000);
|
||||||
if (dur > 0) {
|
if (dur > 0) {
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { typedGuildCommand } from "knub";
|
import { guildPluginMessageCommand } from "knub";
|
||||||
import { sendSuccessMessage } from "../../../pluginUtils";
|
import { sendSuccessMessage } from "../../../pluginUtils";
|
||||||
import { setAntiraidLevel } from "../functions/setAntiraidLevel";
|
import { setAntiraidLevel } from "../functions/setAntiraidLevel";
|
||||||
import { AutomodPluginType } from "../types";
|
import { AutomodPluginType } from "../types";
|
||||||
|
|
||||||
export const AntiraidClearCmd = typedGuildCommand<AutomodPluginType>()({
|
export const AntiraidClearCmd = guildPluginMessageCommand<AutomodPluginType>()({
|
||||||
trigger: ["antiraid clear", "antiraid reset", "antiraid none", "antiraid off"],
|
trigger: ["antiraid clear", "antiraid reset", "antiraid none", "antiraid off"],
|
||||||
permission: "can_set_antiraid",
|
permission: "can_set_antiraid",
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { typedGuildCommand } from "knub";
|
import { guildPluginMessageCommand } from "knub";
|
||||||
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
import { commandTypeHelpers as ct } from "../../../commandTypes";
|
||||||
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
import { sendErrorMessage, sendSuccessMessage } from "../../../pluginUtils";
|
||||||
import { setAntiraidLevel } from "../functions/setAntiraidLevel";
|
import { setAntiraidLevel } from "../functions/setAntiraidLevel";
|
||||||
import { AutomodPluginType } from "../types";
|
import { AutomodPluginType } from "../types";
|
||||||
|
|
||||||
export const SetAntiraidCmd = typedGuildCommand<AutomodPluginType>()({
|
export const SetAntiraidCmd = guildPluginMessageCommand<AutomodPluginType>()({
|
||||||
trigger: "antiraid",
|
trigger: "antiraid",
|
||||||
permission: "can_set_antiraid",
|
permission: "can_set_antiraid",
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { typedGuildCommand } from "knub";
|
import { guildPluginMessageCommand } from "knub";
|
||||||
import { AutomodPluginType } from "../types";
|
import { AutomodPluginType } from "../types";
|
||||||
|
|
||||||
export const ViewAntiraidCmd = typedGuildCommand<AutomodPluginType>()({
|
export const ViewAntiraidCmd = guildPluginMessageCommand<AutomodPluginType>()({
|
||||||
trigger: "antiraid",
|
trigger: "antiraid",
|
||||||
permission: "can_view_antiraid",
|
permission: "can_view_antiraid",
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { typedGuildEventListener } from "knub";
|
import { guildPluginEventListener } from "knub";
|
||||||
import { RecentActionType } from "../constants";
|
import { RecentActionType } from "../constants";
|
||||||
import { runAutomod } from "../functions/runAutomod";
|
import { runAutomod } from "../functions/runAutomod";
|
||||||
import { AutomodContext, AutomodPluginType } from "../types";
|
import { AutomodContext, AutomodPluginType } from "../types";
|
||||||
|
|
||||||
export const RunAutomodOnJoinEvt = typedGuildEventListener<AutomodPluginType>()({
|
export const RunAutomodOnJoinEvt = guildPluginEventListener<AutomodPluginType>()({
|
||||||
event: "guildMemberAdd",
|
event: "guildMemberAdd",
|
||||||
listener({ pluginData, args: { member } }) {
|
listener({ pluginData, args: { member } }) {
|
||||||
const context: AutomodContext = {
|
const context: AutomodContext = {
|
||||||
|
@ -26,7 +26,7 @@ export const RunAutomodOnJoinEvt = typedGuildEventListener<AutomodPluginType>()(
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const RunAutomodOnLeaveEvt = typedGuildEventListener<AutomodPluginType>()({
|
export const RunAutomodOnLeaveEvt = guildPluginEventListener<AutomodPluginType>()({
|
||||||
event: "guildMemberRemove",
|
event: "guildMemberRemove",
|
||||||
listener({ pluginData, args: { member } }) {
|
listener({ pluginData, args: { member } }) {
|
||||||
const context: AutomodContext = {
|
const context: AutomodContext = {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { typedGuildEventListener } from "knub";
|
import { guildPluginEventListener } from "knub";
|
||||||
import diff from "lodash.difference";
|
import diff from "lodash.difference";
|
||||||
import isEqual from "lodash.isequal";
|
import isEqual from "lodash.isequal";
|
||||||
import { runAutomod } from "../functions/runAutomod";
|
import { runAutomod } from "../functions/runAutomod";
|
||||||
import { AutomodContext, AutomodPluginType } from "../types";
|
import { AutomodContext, AutomodPluginType } from "../types";
|
||||||
|
|
||||||
export const RunAutomodOnMemberUpdate = typedGuildEventListener<AutomodPluginType>()({
|
export const RunAutomodOnMemberUpdate = guildPluginEventListener<AutomodPluginType>()({
|
||||||
event: "guildMemberUpdate",
|
event: "guildMemberUpdate",
|
||||||
listener({ pluginData, args: { oldMember, newMember } }) {
|
listener({ pluginData, args: { oldMember, newMember } }) {
|
||||||
if (!oldMember) return;
|
if (!oldMember) return;
|
||||||
|
|
|
@ -14,7 +14,6 @@ export async function runAutomodOnCounterTrigger(
|
||||||
) {
|
) {
|
||||||
const user = userId ? await resolveUser(pluginData.client, userId) : undefined;
|
const user = userId ? await resolveUser(pluginData.client, userId) : undefined;
|
||||||
const member = (userId && (await resolveMember(pluginData.client, pluginData.guild, userId))) || undefined;
|
const member = (userId && (await resolveMember(pluginData.client, pluginData.guild, userId))) || undefined;
|
||||||
|
|
||||||
const prettyCounterName = pluginData.getPlugin(CountersPlugin).getPrettyNameForCounter(counterName);
|
const prettyCounterName = pluginData.getPlugin(CountersPlugin).getPrettyNameForCounter(counterName);
|
||||||
const prettyTriggerName = pluginData
|
const prettyTriggerName = pluginData
|
||||||
.getPlugin(CountersPlugin)
|
.getPlugin(CountersPlugin)
|
||||||
|
|
|
@ -1,13 +1,12 @@
|
||||||
import { Snowflake } from "discord.js";
|
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
|
import { performance } from "perf_hooks";
|
||||||
import { SavedMessage } from "../../../data/entities/SavedMessage";
|
import { SavedMessage } from "../../../data/entities/SavedMessage";
|
||||||
|
import { profilingEnabled } from "../../../utils/easyProfiler";
|
||||||
import { addRecentActionsFromMessage } from "../functions/addRecentActionsFromMessage";
|
import { addRecentActionsFromMessage } from "../functions/addRecentActionsFromMessage";
|
||||||
import { clearRecentActionsForMessage } from "../functions/clearRecentActionsForMessage";
|
import { clearRecentActionsForMessage } from "../functions/clearRecentActionsForMessage";
|
||||||
import { runAutomod } from "../functions/runAutomod";
|
import { runAutomod } from "../functions/runAutomod";
|
||||||
import { AutomodContext, AutomodPluginType } from "../types";
|
import { AutomodContext, AutomodPluginType } from "../types";
|
||||||
import { performance } from "perf_hooks";
|
|
||||||
import { profilingEnabled } from "../../../utils/easyProfiler";
|
|
||||||
|
|
||||||
export async function runAutomodOnMessage(
|
export async function runAutomodOnMessage(
|
||||||
pluginData: GuildPluginData<AutomodPluginType>,
|
pluginData: GuildPluginData<AutomodPluginType>,
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import { typedGuildEventListener } from "knub";
|
import { guildPluginEventListener } from "knub";
|
||||||
import { RecentActionType } from "../constants";
|
import { RecentActionType } from "../constants";
|
||||||
import { runAutomod } from "../functions/runAutomod";
|
import { runAutomod } from "../functions/runAutomod";
|
||||||
import { AutomodContext, AutomodPluginType } from "../types";
|
import { AutomodContext, AutomodPluginType } from "../types";
|
||||||
|
|
||||||
export const RunAutomodOnThreadCreate = typedGuildEventListener<AutomodPluginType>()({
|
export const RunAutomodOnThreadCreate = guildPluginEventListener<AutomodPluginType>()({
|
||||||
event: "threadCreate",
|
event: "threadCreate",
|
||||||
async listener({ pluginData, args: { thread } }) {
|
async listener({ pluginData, args: { thread } }) {
|
||||||
const user = thread.ownerId
|
const user = thread.ownerId
|
||||||
|
@ -32,7 +32,7 @@ export const RunAutomodOnThreadCreate = typedGuildEventListener<AutomodPluginTyp
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const RunAutomodOnThreadDelete = typedGuildEventListener<AutomodPluginType>()({
|
export const RunAutomodOnThreadDelete = guildPluginEventListener<AutomodPluginType>()({
|
||||||
event: "threadDelete",
|
event: "threadDelete",
|
||||||
async listener({ pluginData, args: { thread } }) {
|
async listener({ pluginData, args: { thread } }) {
|
||||||
const user = thread.ownerId
|
const user = thread.ownerId
|
||||||
|
@ -54,7 +54,7 @@ export const RunAutomodOnThreadDelete = typedGuildEventListener<AutomodPluginTyp
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
export const RunAutomodOnThreadUpdate = typedGuildEventListener<AutomodPluginType>()({
|
export const RunAutomodOnThreadUpdate = guildPluginEventListener<AutomodPluginType>()({
|
||||||
event: "threadUpdate",
|
event: "threadUpdate",
|
||||||
async listener({ pluginData, args: { oldThread, newThread: thread } }) {
|
async listener({ pluginData, args: { oldThread, newThread: thread } }) {
|
||||||
const user = thread.ownerId
|
const user = thread.ownerId
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
|
import { startProfiling } from "../../../utils/easyProfiler";
|
||||||
import { RECENT_ACTION_EXPIRY_TIME } from "../constants";
|
import { RECENT_ACTION_EXPIRY_TIME } from "../constants";
|
||||||
import { AutomodPluginType } from "../types";
|
import { AutomodPluginType } from "../types";
|
||||||
import { startProfiling } from "../../../utils/easyProfiler";
|
|
||||||
|
|
||||||
export function clearOldRecentActions(pluginData: GuildPluginData<AutomodPluginType>) {
|
export function clearOldRecentActions(pluginData: GuildPluginData<AutomodPluginType>) {
|
||||||
const stopProfiling = startProfiling(pluginData.getKnubInstance().profiler, "automod:fns:clearOldRecentActions");
|
const stopProfiling = startProfiling(pluginData.getKnubInstance().profiler, "automod:fns:clearOldRecentActions");
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
|
import { startProfiling } from "../../../utils/easyProfiler";
|
||||||
import { RECENT_SPAM_EXPIRY_TIME } from "../constants";
|
import { RECENT_SPAM_EXPIRY_TIME } from "../constants";
|
||||||
import { AutomodPluginType } from "../types";
|
import { AutomodPluginType } from "../types";
|
||||||
import { startProfiling } from "../../../utils/easyProfiler";
|
|
||||||
|
|
||||||
export function clearOldRecentSpam(pluginData: GuildPluginData<AutomodPluginType>) {
|
export function clearOldRecentSpam(pluginData: GuildPluginData<AutomodPluginType>) {
|
||||||
const stopProfiling = startProfiling(pluginData.getKnubInstance().profiler, "automod:fns:clearOldRecentSpam");
|
const stopProfiling = startProfiling(pluginData.getKnubInstance().profiler, "automod:fns:clearOldRecentSpam");
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import { AutomodContext, AutomodPluginType } from "../types";
|
|
||||||
import { startProfiling } from "../../../utils/easyProfiler";
|
import { startProfiling } from "../../../utils/easyProfiler";
|
||||||
|
import { AutomodContext, AutomodPluginType } from "../types";
|
||||||
|
|
||||||
export function clearRecentActionsForMessage(pluginData: GuildPluginData<AutomodPluginType>, context: AutomodContext) {
|
export function clearRecentActionsForMessage(pluginData: GuildPluginData<AutomodPluginType>, context: AutomodContext) {
|
||||||
const stopProfiling = startProfiling(
|
const stopProfiling = startProfiling(
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
|
import { startProfiling } from "../../../utils/easyProfiler";
|
||||||
import { RecentActionType } from "../constants";
|
import { RecentActionType } from "../constants";
|
||||||
import { AutomodPluginType } from "../types";
|
import { AutomodPluginType } from "../types";
|
||||||
import { startProfiling } from "../../../utils/easyProfiler";
|
|
||||||
|
|
||||||
export function findRecentSpam(
|
export function findRecentSpam(
|
||||||
pluginData: GuildPluginData<AutomodPluginType>,
|
pluginData: GuildPluginData<AutomodPluginType>,
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import moment from "moment-timezone";
|
import moment from "moment-timezone";
|
||||||
import { SavedMessage } from "../../../data/entities/SavedMessage";
|
import { SavedMessage } from "../../../data/entities/SavedMessage";
|
||||||
|
import { startProfiling } from "../../../utils/easyProfiler";
|
||||||
import { RecentActionType } from "../constants";
|
import { RecentActionType } from "../constants";
|
||||||
import { AutomodPluginType } from "../types";
|
import { AutomodPluginType } from "../types";
|
||||||
import { getMatchingRecentActions } from "./getMatchingRecentActions";
|
import { getMatchingRecentActions } from "./getMatchingRecentActions";
|
||||||
import { startProfiling } from "../../../utils/easyProfiler";
|
|
||||||
|
|
||||||
export function getMatchingMessageRecentActions(
|
export function getMatchingMessageRecentActions(
|
||||||
pluginData: GuildPluginData<AutomodPluginType>,
|
pluginData: GuildPluginData<AutomodPluginType>,
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
|
import { startProfiling } from "../../../utils/easyProfiler";
|
||||||
import { RecentActionType } from "../constants";
|
import { RecentActionType } from "../constants";
|
||||||
import { AutomodPluginType } from "../types";
|
import { AutomodPluginType } from "../types";
|
||||||
import { startProfiling } from "../../../utils/easyProfiler";
|
|
||||||
|
|
||||||
export function getMatchingRecentActions(
|
export function getMatchingRecentActions(
|
||||||
pluginData: GuildPluginData<AutomodPluginType>,
|
pluginData: GuildPluginData<AutomodPluginType>,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Snowflake, TextChannel } from "discord.js";
|
import { ActivityType, Snowflake } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import { messageSummary, verboseChannelMention } from "../../../utils";
|
import { messageSummary, verboseChannelMention } from "../../../utils";
|
||||||
import { AutomodContext, AutomodPluginType } from "../types";
|
import { AutomodContext, AutomodPluginType } from "../types";
|
||||||
|
@ -11,13 +11,13 @@ export function getTextMatchPartialSummary(
|
||||||
) {
|
) {
|
||||||
if (type === "message") {
|
if (type === "message") {
|
||||||
const message = context.message!;
|
const message = context.message!;
|
||||||
const channel = pluginData.guild.channels.cache.get(message.channel_id as Snowflake) as TextChannel;
|
const channel = pluginData.guild.channels.cache.get(message.channel_id as Snowflake);
|
||||||
const channelMention = channel ? verboseChannelMention(channel) : `\`#${message.channel_id}\``;
|
const channelMention = channel ? verboseChannelMention(channel) : `\`#${message.channel_id}\``;
|
||||||
|
|
||||||
return `message in ${channelMention}:\n${messageSummary(message)}`;
|
return `message in ${channelMention}:\n${messageSummary(message)}`;
|
||||||
} else if (type === "embed") {
|
} else if (type === "embed") {
|
||||||
const message = context.message!;
|
const message = context.message!;
|
||||||
const channel = pluginData.guild.channels.cache.get(message.channel_id as Snowflake) as TextChannel;
|
const channel = pluginData.guild.channels.cache.get(message.channel_id as Snowflake);
|
||||||
const channelMention = channel ? verboseChannelMention(channel) : `\`#${message.channel_id}\``;
|
const channelMention = channel ? verboseChannelMention(channel) : `\`#${message.channel_id}\``;
|
||||||
|
|
||||||
return `message embed in ${channelMention}:\n${messageSummary(message)}`;
|
return `message embed in ${channelMention}:\n${messageSummary(message)}`;
|
||||||
|
@ -29,6 +29,6 @@ export function getTextMatchPartialSummary(
|
||||||
const visibleName = context.member?.nickname || context.user!.username;
|
const visibleName = context.member?.nickname || context.user!.username;
|
||||||
return `visible name: ${visibleName}`;
|
return `visible name: ${visibleName}`;
|
||||||
} else if (type === "customstatus") {
|
} else if (type === "customstatus") {
|
||||||
return `custom status: ${context.member!.presence?.activities.find((a) => a.type === "CUSTOM")?.name}`;
|
return `custom status: ${context.member!.presence?.activities.find((a) => a.type === ActivityType.Custom)?.name}`;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,8 @@
|
||||||
import { Constants, MessageEmbed } from "discord.js";
|
import { ActivityType, Embed } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import { SavedMessage } from "../../../data/entities/SavedMessage";
|
import { SavedMessage } from "../../../data/entities/SavedMessage";
|
||||||
import { resolveMember } from "../../../utils";
|
import { resolveMember } from "../../../utils";
|
||||||
|
import { DeepMutable } from "../../../utils/typeUtils.js";
|
||||||
import { AutomodPluginType } from "../types";
|
import { AutomodPluginType } from "../types";
|
||||||
|
|
||||||
type TextTriggerWithMultipleMatchTypes = {
|
type TextTriggerWithMultipleMatchTypes = {
|
||||||
|
@ -33,7 +34,7 @@ export async function* matchMultipleTextTypesOnMessage(
|
||||||
}
|
}
|
||||||
|
|
||||||
if (trigger.match_embeds && msg.data.embeds?.length) {
|
if (trigger.match_embeds && msg.data.embeds?.length) {
|
||||||
const copiedEmbed: MessageEmbed = JSON.parse(JSON.stringify(msg.data.embeds[0]));
|
const copiedEmbed: DeepMutable<Embed> = JSON.parse(JSON.stringify(msg.data.embeds[0]));
|
||||||
if (copiedEmbed.video) {
|
if (copiedEmbed.video) {
|
||||||
copiedEmbed.description = ""; // The description is not rendered, hence it doesn't need to be matched
|
copiedEmbed.description = ""; // The description is not rendered, hence it doesn't need to be matched
|
||||||
}
|
}
|
||||||
|
@ -53,7 +54,7 @@ export async function* matchMultipleTextTypesOnMessage(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const activity of member.presence?.activities ?? []) {
|
for (const activity of member.presence?.activities ?? []) {
|
||||||
if (activity.type === Constants.ActivityTypes[4]) {
|
if (activity.type === ActivityType.Custom) {
|
||||||
yield ["customstatus", `${activity.emoji} ${activity.name}`];
|
yield ["customstatus", `${activity.emoji} ${activity.name}`];
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Snowflake, TextChannel, ThreadChannel } from "discord.js";
|
import { Snowflake } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
|
import { ERRORS, RecoverablePluginError } from "../../../RecoverablePluginError";
|
||||||
import { disableUserNotificationStrings, UserNotificationMethod } from "../../../utils";
|
import { disableUserNotificationStrings, UserNotificationMethod } from "../../../utils";
|
||||||
|
@ -19,7 +19,7 @@ export function resolveActionContactMethods(
|
||||||
}
|
}
|
||||||
|
|
||||||
const channel = pluginData.guild.channels.cache.get(actionConfig.notifyChannel as Snowflake);
|
const channel = pluginData.guild.channels.cache.get(actionConfig.notifyChannel as Snowflake);
|
||||||
if (!channel?.isText()) {
|
if (!channel?.isTextBased()) {
|
||||||
throw new RecoverablePluginError(ERRORS.INVALID_USER_NOTIFICATION_CHANNEL);
|
throw new RecoverablePluginError(ERRORS.INVALID_USER_NOTIFICATION_CHANNEL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
import { Snowflake, TextChannel, ThreadChannel } from "discord.js";
|
import { GuildTextBasedChannel, Snowflake } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
|
import { performance } from "perf_hooks";
|
||||||
|
import { calculateBlocking, profilingEnabled } from "../../../utils/easyProfiler";
|
||||||
import { availableActions } from "../actions/availableActions";
|
import { availableActions } from "../actions/availableActions";
|
||||||
import { CleanAction } from "../actions/clean";
|
import { CleanAction } from "../actions/clean";
|
||||||
import { AutomodTriggerMatchResult } from "../helpers";
|
import { AutomodTriggerMatchResult } from "../helpers";
|
||||||
import { availableTriggers } from "../triggers/availableTriggers";
|
import { availableTriggers } from "../triggers/availableTriggers";
|
||||||
import { AutomodContext, AutomodPluginType } from "../types";
|
import { AutomodContext, AutomodPluginType } from "../types";
|
||||||
import { checkAndUpdateCooldown } from "./checkAndUpdateCooldown";
|
import { checkAndUpdateCooldown } from "./checkAndUpdateCooldown";
|
||||||
import { performance } from "perf_hooks";
|
|
||||||
import { calculateBlocking, profilingEnabled } from "../../../utils/easyProfiler";
|
|
||||||
|
|
||||||
export async function runAutomod(pluginData: GuildPluginData<AutomodPluginType>, context: AutomodContext) {
|
export async function runAutomod(pluginData: GuildPluginData<AutomodPluginType>, context: AutomodContext) {
|
||||||
const userId = context.user?.id || context.member?.id || context.message?.user_id;
|
const userId = context.user?.id || context.member?.id || context.message?.user_id;
|
||||||
|
@ -18,7 +18,7 @@ export async function runAutomod(pluginData: GuildPluginData<AutomodPluginType>,
|
||||||
const channelOrThread =
|
const channelOrThread =
|
||||||
context.channel ??
|
context.channel ??
|
||||||
(channelIdOrThreadId
|
(channelIdOrThreadId
|
||||||
? (pluginData.guild.channels.cache.get(channelIdOrThreadId as Snowflake) as TextChannel | ThreadChannel)
|
? (pluginData.guild.channels.cache.get(channelIdOrThreadId as Snowflake) as GuildTextBasedChannel)
|
||||||
: null);
|
: null);
|
||||||
const channelId = channelOrThread?.isThread() ? channelOrThread.parent?.id : channelIdOrThreadId;
|
const channelId = channelOrThread?.isThread() ? channelOrThread.parent?.id : channelIdOrThreadId;
|
||||||
const threadId = channelOrThread?.isThread() ? channelOrThread.id : null;
|
const threadId = channelOrThread?.isThread() ? channelOrThread.id : null;
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
import { User } from "discord.js";
|
import { User } from "discord.js";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import { userToTemplateSafeUser } from "../../../utils/templateSafeObjects";
|
|
||||||
import { LogType } from "../../../data/LogType";
|
|
||||||
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
import { LogsPlugin } from "../../Logs/LogsPlugin";
|
||||||
import { runAutomodOnAntiraidLevel } from "../events/runAutomodOnAntiraidLevel";
|
import { runAutomodOnAntiraidLevel } from "../events/runAutomodOnAntiraidLevel";
|
||||||
import { AutomodPluginType } from "../types";
|
import { AutomodPluginType } from "../types";
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { GuildPluginData } from "knub";
|
import { GuildPluginData } from "knub";
|
||||||
import { Awaitable } from "knub/dist/utils";
|
import { Awaitable } from "../../utils/typeUtils";
|
||||||
import { AutomodContext, AutomodPluginType } from "./types";
|
import { AutomodContext, AutomodPluginType } from "./types";
|
||||||
|
|
||||||
interface BaseAutomodTriggerMatchResult {
|
interface BaseAutomodTriggerMatchResult {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
import { trimPluginDescription } from "../../utils";
|
import { trimPluginDescription } from "../../utils";
|
||||||
import { ZeppelinGuildPluginBlueprint } from "../ZeppelinPluginBlueprint";
|
import { ZeppelinGuildPluginBlueprint } from "../ZeppelinPluginBlueprint";
|
||||||
|
import { ConfigSchema } from "./types";
|
||||||
|
|
||||||
export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = {
|
export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = {
|
||||||
prettyName: "Automod",
|
prettyName: "Automod",
|
||||||
|
@ -99,4 +100,5 @@ export const pluginInfo: ZeppelinGuildPluginBlueprint["info"] = {
|
||||||
{matchSummary}
|
{matchSummary}
|
||||||
~~~
|
~~~
|
||||||
`),
|
`),
|
||||||
|
configSchema: ConfigSchema,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Snowflake, TextChannel } from "discord.js";
|
import { Snowflake } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { verboseChannelMention } from "../../../utils";
|
import { verboseChannelMention } from "../../../utils";
|
||||||
import { automodTrigger } from "../helpers";
|
import { automodTrigger } from "../helpers";
|
||||||
|
@ -22,7 +22,7 @@ export const AnyMessageTrigger = automodTrigger<AnyMessageResultType>()({
|
||||||
},
|
},
|
||||||
|
|
||||||
renderMatchInformation({ pluginData, contexts, matchResult }) {
|
renderMatchInformation({ pluginData, contexts, matchResult }) {
|
||||||
const channel = pluginData.guild.channels.cache.get(contexts[0].message!.channel_id as Snowflake) as TextChannel;
|
const channel = pluginData.guild.channels.cache.get(contexts[0].message!.channel_id as Snowflake);
|
||||||
return `Matched message (\`${contexts[0].message!.id}\`) in ${
|
return `Matched message (\`${contexts[0].message!.id}\`) in ${
|
||||||
channel ? verboseChannelMention(channel) : "Unknown Channel"
|
channel ? verboseChannelMention(channel) : "Unknown Channel"
|
||||||
}`;
|
}`;
|
||||||
|
|
|
@ -11,9 +11,9 @@ import { KickTrigger } from "./kick";
|
||||||
import { LineSpamTrigger } from "./lineSpam";
|
import { LineSpamTrigger } from "./lineSpam";
|
||||||
import { LinkSpamTrigger } from "./linkSpam";
|
import { LinkSpamTrigger } from "./linkSpam";
|
||||||
import { MatchAttachmentTypeTrigger } from "./matchAttachmentType";
|
import { MatchAttachmentTypeTrigger } from "./matchAttachmentType";
|
||||||
import { MatchMimeTypeTrigger } from "./matchMimeType";
|
|
||||||
import { MatchInvitesTrigger } from "./matchInvites";
|
import { MatchInvitesTrigger } from "./matchInvites";
|
||||||
import { MatchLinksTrigger } from "./matchLinks";
|
import { MatchLinksTrigger } from "./matchLinks";
|
||||||
|
import { MatchMimeTypeTrigger } from "./matchMimeType";
|
||||||
import { MatchRegexTrigger } from "./matchRegex";
|
import { MatchRegexTrigger } from "./matchRegex";
|
||||||
import { MatchWordsTrigger } from "./matchWords";
|
import { MatchWordsTrigger } from "./matchWords";
|
||||||
import { MemberJoinTrigger } from "./memberJoin";
|
import { MemberJoinTrigger } from "./memberJoin";
|
||||||
|
@ -26,14 +26,14 @@ import { NoteTrigger } from "./note";
|
||||||
import { RoleAddedTrigger } from "./roleAdded";
|
import { RoleAddedTrigger } from "./roleAdded";
|
||||||
import { RoleRemovedTrigger } from "./roleRemoved";
|
import { RoleRemovedTrigger } from "./roleRemoved";
|
||||||
import { StickerSpamTrigger } from "./stickerSpam";
|
import { StickerSpamTrigger } from "./stickerSpam";
|
||||||
|
import { ThreadArchiveTrigger } from "./threadArchive";
|
||||||
import { ThreadCreateTrigger } from "./threadCreate";
|
import { ThreadCreateTrigger } from "./threadCreate";
|
||||||
import { ThreadCreateSpamTrigger } from "./threadCreateSpam";
|
import { ThreadCreateSpamTrigger } from "./threadCreateSpam";
|
||||||
import { ThreadDeleteTrigger } from "./threadDelete";
|
import { ThreadDeleteTrigger } from "./threadDelete";
|
||||||
|
import { ThreadUnarchiveTrigger } from "./threadUnarchive";
|
||||||
import { UnbanTrigger } from "./unban";
|
import { UnbanTrigger } from "./unban";
|
||||||
import { UnmuteTrigger } from "./unmute";
|
import { UnmuteTrigger } from "./unmute";
|
||||||
import { WarnTrigger } from "./warn";
|
import { WarnTrigger } from "./warn";
|
||||||
import { ThreadArchiveTrigger } from "./threadArchive";
|
|
||||||
import { ThreadUnarchiveTrigger } from "./threadUnarchive";
|
|
||||||
|
|
||||||
export const availableTriggers: Record<string, AutomodTriggerBlueprint<any, any>> = {
|
export const availableTriggers: Record<string, AutomodTriggerBlueprint<any, any>> = {
|
||||||
any_message: AnyMessageTrigger,
|
any_message: AnyMessageTrigger,
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
import { Snowflake, TextChannel, Util } from "discord.js";
|
import { escapeInlineCode, Snowflake } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils";
|
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils";
|
||||||
import { automodTrigger } from "../helpers";
|
import { automodTrigger } from "../helpers";
|
||||||
|
@ -66,12 +66,12 @@ export const MatchAttachmentTypeTrigger = automodTrigger<MatchResultType>()({
|
||||||
},
|
},
|
||||||
|
|
||||||
renderMatchInformation({ pluginData, contexts, matchResult }) {
|
renderMatchInformation({ pluginData, contexts, matchResult }) {
|
||||||
const channel = pluginData.guild.channels.cache.get(contexts[0].message!.channel_id as Snowflake) as TextChannel;
|
const channel = pluginData.guild.channels.cache.get(contexts[0].message!.channel_id as Snowflake)!;
|
||||||
const prettyChannel = verboseChannelMention(channel);
|
const prettyChannel = verboseChannelMention(channel);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
asSingleLine(`
|
asSingleLine(`
|
||||||
Matched attachment type \`${Util.escapeInlineCode(matchResult.extra.matchedType)}\`
|
Matched attachment type \`${escapeInlineCode(matchResult.extra.matchedType)}\`
|
||||||
(${matchResult.extra.mode === "blacklist" ? "blacklisted" : "not in whitelist"})
|
(${matchResult.extra.mode === "blacklist" ? "blacklisted" : "not in whitelist"})
|
||||||
in message (\`${contexts[0].message!.id}\`) in ${prettyChannel}:
|
in message (\`${contexts[0].message!.id}\`) in ${prettyChannel}:
|
||||||
`) + messageSummary(contexts[0].message!)
|
`) + messageSummary(contexts[0].message!)
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
import { Util } from "discord.js";
|
import { escapeInlineCode } from "discord.js";
|
||||||
import escapeStringRegexp from "escape-string-regexp";
|
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
|
import { phishermanDomainIsSafe } from "../../../data/Phisherman";
|
||||||
import { allowTimeout } from "../../../RegExpRunner";
|
import { allowTimeout } from "../../../RegExpRunner";
|
||||||
import { getUrlsInString, tNullable } from "../../../utils";
|
import { getUrlsInString, tNullable } from "../../../utils";
|
||||||
|
import { mergeRegexes } from "../../../utils/mergeRegexes";
|
||||||
|
import { mergeWordsIntoRegex } from "../../../utils/mergeWordsIntoRegex";
|
||||||
import { TRegex } from "../../../validatorUtils";
|
import { TRegex } from "../../../validatorUtils";
|
||||||
|
import { PhishermanPlugin } from "../../Phisherman/PhishermanPlugin";
|
||||||
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary";
|
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary";
|
||||||
import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage";
|
import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage";
|
||||||
import { automodTrigger } from "../helpers";
|
import { automodTrigger } from "../helpers";
|
||||||
import { mergeRegexes } from "../../../utils/mergeRegexes";
|
|
||||||
import { mergeWordsIntoRegex } from "../../../utils/mergeWordsIntoRegex";
|
|
||||||
import { PhishermanPlugin } from "../../Phisherman/PhishermanPlugin";
|
|
||||||
import { phishermanDomainIsSafe } from "../../../data/Phisherman";
|
|
||||||
|
|
||||||
interface MatchResultType {
|
interface MatchResultType {
|
||||||
type: MatchableTextType;
|
type: MatchableTextType;
|
||||||
|
@ -186,7 +185,7 @@ export const MatchLinksTrigger = automodTrigger<MatchResultType>()({
|
||||||
|
|
||||||
renderMatchInformation({ pluginData, contexts, matchResult }) {
|
renderMatchInformation({ pluginData, contexts, matchResult }) {
|
||||||
const partialSummary = getTextMatchPartialSummary(pluginData, matchResult.extra.type, contexts[0]);
|
const partialSummary = getTextMatchPartialSummary(pluginData, matchResult.extra.type, contexts[0]);
|
||||||
let information = `Matched link \`${Util.escapeInlineCode(matchResult.extra.link)}\``;
|
let information = `Matched link \`${escapeInlineCode(matchResult.extra.link)}\``;
|
||||||
if (matchResult.extra.details) {
|
if (matchResult.extra.details) {
|
||||||
information += ` ${matchResult.extra.details}`;
|
information += ` ${matchResult.extra.details}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { automodTrigger } from "../helpers";
|
import { escapeInlineCode } from "discord.js";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils";
|
import { asSingleLine, messageSummary, verboseChannelMention } from "../../../utils";
|
||||||
import { GuildChannel, Util } from "discord.js";
|
import { automodTrigger } from "../helpers";
|
||||||
|
|
||||||
interface MatchResultType {
|
interface MatchResultType {
|
||||||
matchedType: string;
|
matchedType: string;
|
||||||
|
@ -65,13 +65,13 @@ export const MatchMimeTypeTrigger = automodTrigger<MatchResultType>()({
|
||||||
|
|
||||||
renderMatchInformation({ pluginData, contexts, matchResult }) {
|
renderMatchInformation({ pluginData, contexts, matchResult }) {
|
||||||
const { message } = contexts[0];
|
const { message } = contexts[0];
|
||||||
const channel = pluginData.guild.channels.resolve(message!.channel_id);
|
const channel = pluginData.guild.channels.resolve(message!.channel_id)!;
|
||||||
const prettyChannel = verboseChannelMention(channel as GuildChannel);
|
const prettyChannel = verboseChannelMention(channel);
|
||||||
const { matchedType, mode } = matchResult.extra;
|
const { matchedType, mode } = matchResult.extra;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
asSingleLine(`
|
asSingleLine(`
|
||||||
Matched MIME type \`${Util.escapeInlineCode(matchedType)}\`
|
Matched MIME type \`${escapeInlineCode(matchedType)}\`
|
||||||
(${mode === "blacklist" ? "blacklisted" : "not in whitelist"})
|
(${mode === "blacklist" ? "blacklisted" : "not in whitelist"})
|
||||||
in message (\`${message!.id}\`) in ${prettyChannel}
|
in message (\`${message!.id}\`) in ${prettyChannel}
|
||||||
`) + messageSummary(message!)
|
`) + messageSummary(message!)
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { allowTimeout } from "../../../RegExpRunner";
|
import { allowTimeout } from "../../../RegExpRunner";
|
||||||
|
import { mergeRegexes } from "../../../utils/mergeRegexes";
|
||||||
import { normalizeText } from "../../../utils/normalizeText";
|
import { normalizeText } from "../../../utils/normalizeText";
|
||||||
import { stripMarkdown } from "../../../utils/stripMarkdown";
|
import { stripMarkdown } from "../../../utils/stripMarkdown";
|
||||||
import { TRegex } from "../../../validatorUtils";
|
import { TRegex } from "../../../validatorUtils";
|
||||||
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary";
|
import { getTextMatchPartialSummary } from "../functions/getTextMatchPartialSummary";
|
||||||
import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage";
|
import { MatchableTextType, matchMultipleTextTypesOnMessage } from "../functions/matchMultipleTextTypesOnMessage";
|
||||||
import { automodTrigger } from "../helpers";
|
import { automodTrigger } from "../helpers";
|
||||||
import { mergeRegexes } from "../../../utils/mergeRegexes";
|
|
||||||
|
|
||||||
interface MatchResultType {
|
interface MatchResultType {
|
||||||
pattern: string;
|
pattern: string;
|
||||||
|
|
|
@ -1,4 +1,3 @@
|
||||||
import { Util } from "discord.js";
|
|
||||||
import escapeStringRegexp from "escape-string-regexp";
|
import escapeStringRegexp from "escape-string-regexp";
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { normalizeText } from "../../../utils/normalizeText";
|
import { normalizeText } from "../../../utils/normalizeText";
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Snowflake } from "discord-api-types/v9";
|
import { escapeBold, User, type Snowflake } from "discord.js";
|
||||||
import { User, Util } from "discord.js";
|
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { tNullable } from "../../../utils";
|
import { tNullable } from "../../../utils";
|
||||||
import { automodTrigger } from "../helpers";
|
import { automodTrigger } from "../helpers";
|
||||||
|
@ -49,7 +48,7 @@ export const ThreadArchiveTrigger = automodTrigger<ThreadArchiveResult>()({
|
||||||
const parentName = matchResult.extra.matchedThreadParentName;
|
const parentName = matchResult.extra.matchedThreadParentName;
|
||||||
const base = `Thread **#${threadName}** (\`${threadId}\`) has been archived in the **#${parentName}** (\`${parentId}\`) channel`;
|
const base = `Thread **#${threadName}** (\`${threadId}\`) has been archived in the **#${parentName}** (\`${parentId}\`) channel`;
|
||||||
if (threadOwner) {
|
if (threadOwner) {
|
||||||
return `${base} by **${Util.escapeBold(threadOwner.tag)}** (\`${threadOwner.id}\`)`;
|
return `${base} by **${escapeBold(threadOwner.tag)}** (\`${threadOwner.id}\`)`;
|
||||||
}
|
}
|
||||||
return base;
|
return base;
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,5 +1,4 @@
|
||||||
import { Snowflake } from "discord-api-types/v9";
|
import { escapeBold, User, type Snowflake } from "discord.js";
|
||||||
import { User, Util } from "discord.js";
|
|
||||||
import * as t from "io-ts";
|
import * as t from "io-ts";
|
||||||
import { automodTrigger } from "../helpers";
|
import { automodTrigger } from "../helpers";
|
||||||
|
|
||||||
|
@ -41,7 +40,7 @@ export const ThreadCreateTrigger = automodTrigger<ThreadCreateResult>()({
|
||||||
const parentName = matchResult.extra.matchedThreadParentName;
|
const parentName = matchResult.extra.matchedThreadParentName;
|
||||||
const base = `Thread **#${threadName}** (\`${threadId}\`) has been created in the **#${parentName}** (\`${parentId}\`) channel`;
|
const base = `Thread **#${threadName}** (\`${threadId}\`) has been created in the **#${parentName}** (\`${parentId}\`) channel`;
|
||||||
if (threadOwner) {
|
if (threadOwner) {
|
||||||
return `${base} by **${Util.escapeBold(threadOwner.tag)}** (\`${threadOwner.id}\`)`;
|
return `${base} by **${escapeBold(threadOwner.tag)}** (\`${threadOwner.id}\`)`;
|
||||||
}
|
}
|
||||||
return base;
|
return base;
|
||||||
},
|
},
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue