changes to how deleting tickets works, and UI when creating mod tickets

pull/5/head
pineafan 4 years ago
parent 5be5eca351
commit 6fb3e07eab
No known key found for this signature in database
GPG Key ID: 0BC8D3DCC20E96FE

5
.gitignore vendored

@ -8,4 +8,7 @@ yarn.lock
src/utils/temp/*.png src/utils/temp/*.png
src/utils/temp/*.webp src/utils/temp/*.webp
src/utils/temp/*.jpeg src/utils/temp/*.jpeg
src/utils/temp/*.jpg src/utils/temp/*.jpg
ClicksMigratingProblems/oldData/
ClicksMigratingProblems/oldData copy/

@ -0,0 +1,147 @@
import fs from 'fs';
import { MongoClient } from 'mongodb';
const mongoClient = new MongoClient('mongodb://127.0.0.1:27017/local');
await mongoClient.connect()
const database = mongoClient.db("Nucleus");
const collection = database.collection("migrationTesting");
// Loop through all files in the oldData folder
const files = fs.readdirSync('./oldData');
let x = 0
for (const file of files) {
console.log(`┌ Processing file ${x} of ${files.length - 1} | ${file}`);
// Read the file as a json
let data
try {
data = JSON.parse(fs.readFileSync(`./oldData/${file}`));
} catch {
console.log(`└ Error reading file ${file}`);
x++
continue;
}
// Check if data version is 3
if (data.version !== 3) {
console.log(`├ Version was too old on ${file}`);
console.log(`└ Skipping file`);
x++;
continue
}
// Convert to the new format
const newData = {
"id": data.guild_info.id.toString(),
"version": 1,
"singleEventNotifications": {
"statsChannelDeleted": false
},
"filters": {
"images": {
"NSFW": !data.images.nsfw,
"size": data.images.toosmall
},
"wordFilter": {
"enabled": true,
"words": {
"strict": data.wordfilter.strict,
"loose": data.wordfilter.soft
},
"allowed": {
"users": data.wordfilter.ignore.members.map(user => user.toString()),
"roles": data.wordfilter.ignore.roles.map(role => role.toString()),
"channels": data.wordfilter.ignore.channels.map(channel => channel.toString())
}
},
"invite": {
"enabled": data.invite ? data.invite.enabled : false,
"allowed": {
"users": data.invite ? data.invite.whitelist.members.map(user => user.toString()) : [],
"channels": data.invite ? data.invite.whitelist.channels.map(channel => channel.toString()) : [],
"roles": data.invite ? data.invite.whitelist.roles.map(role => role.toString()) : []
}
},
"pings": {
"mass": 5,
"everyone": true,
"roles": true,
"allowed": {
"roles": [],
"rolesToMention": null,
"users": null,
"channels": null
}
}
},
"welcome": {
"enabled": data.welcome ? (data.welcome.message.text !== null) : false,
"verificationRequired": {
"message": null,
"role": null,
},
"welcomeRole": data.welcome ? (data.welcome.role !== null ? data.welcome.role.toString() : null) : null,
"channel": data.welcome ? (data.welcome.message.text !== null ? data.welcome.message.channel.toString() : null) : null,
"message": data.welcome ? (data.welcome.message.text) : null
},
"stats": [],
"logging": {
"logs": {
"enabled": true,
"channel": data.log_info.log_channel ? data.log_info.log_channel.toString() : null,
"toLog": "3fffff"
},
"staff": {
"channel": data.log_info.staff ? data.log_info.staff.toString() : null,
}
},
"verify": {
"enabled": data.verify_role !== null,
"role": data.verify_role ? data.verify_role.toString() : null,
},
"tickets": {
"enabled": data.modmail ? (data.modmail.cat !== null) : null,
"category": data.modmail ? (data.modmail.cat !== null ? data.modmail.cat.toString() : null) : null,
"types": "3f",
"customTypes": null,
"supportRole": data.modmail ? (data.modmail.mention !== null ? data.modmail.mention.toString() : null) : null,
"maxTickets": data.modmail ? (data.modmail.max) : 5
},
"moderation": {
"mute": {
"timeout": true,
"role": null,
"text": null,
"link": null
},
"kick": {
"text": null,
"link": null
},
"ban": {
"text": null,
"link": null
},
"softban": {
"text": null,
"link": null
},
"warn": {
"text": null,
"link": null
},
"role": {
"role": null
}
},
"tracks": [],
"roleMenu": [],
"tags": data.tags
}
// Insert the new data into the database
await collection.updateOne({ id: data.guild_info.id.toString() }, { $set: newData }, { upsert: true });
// Delete the old file
fs.unlinkSync(`./oldData/${file}`);
console.log(`└ Successfully migrated file ${file}`);
x++;
}
// console.log((await collection.findOne({ id: "your mother" })));

@ -0,0 +1,389 @@
{
"name": "hi",
"version": "1.0.0",
"lockfileVersion": 2,
"requires": true,
"packages": {
"": {
"name": "hi",
"version": "1.0.0",
"license": "ISC",
"dependencies": {
"fs": "^0.0.1-security",
"mongodb": "^4.7.0"
}
},
"node_modules/@types/node": {
"version": "17.0.41",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz",
"integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw=="
},
"node_modules/@types/webidl-conversions": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz",
"integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q=="
},
"node_modules/@types/whatwg-url": {
"version": "8.2.1",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz",
"integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==",
"dependencies": {
"@types/node": "*",
"@types/webidl-conversions": "*"
}
},
"node_modules/base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/bson": {
"version": "4.6.4",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.6.4.tgz",
"integrity": "sha512-TdQ3FzguAu5HKPPlr0kYQCyrYUYh8tFM+CMTpxjNzVzxeiJY00Rtuj3LXLHSgiGvmaWlZ8PE+4KyM2thqE38pQ==",
"dependencies": {
"buffer": "^5.6.0"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
],
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"node_modules/denque": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz",
"integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ==",
"engines": {
"node": ">=0.10"
}
},
"node_modules/fs": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
"integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="
},
"node_modules/ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/feross"
},
{
"type": "patreon",
"url": "https://www.patreon.com/feross"
},
{
"type": "consulting",
"url": "https://feross.org/support"
}
]
},
"node_modules/ip": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
"integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg=="
},
"node_modules/memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"optional": true
},
"node_modules/mongodb": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.7.0.tgz",
"integrity": "sha512-HhVar6hsUeMAVlIbwQwWtV36iyjKd9qdhY+s4wcU8K6TOj4Q331iiMy+FoPuxEntDIijTYWivwFJkLv8q/ZgvA==",
"dependencies": {
"bson": "^4.6.3",
"denque": "^2.0.1",
"mongodb-connection-string-url": "^2.5.2",
"socks": "^2.6.2"
},
"engines": {
"node": ">=12.9.0"
},
"optionalDependencies": {
"saslprep": "^1.0.3"
}
},
"node_modules/mongodb-connection-string-url": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz",
"integrity": "sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA==",
"dependencies": {
"@types/whatwg-url": "^8.2.1",
"whatwg-url": "^11.0.0"
}
},
"node_modules/punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
"engines": {
"node": ">=6"
}
},
"node_modules/saslprep": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"optional": true,
"dependencies": {
"sparse-bitfield": "^3.0.3"
},
"engines": {
"node": ">=6"
}
},
"node_modules/smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
}
},
"node_modules/socks": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz",
"integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==",
"dependencies": {
"ip": "^1.1.5",
"smart-buffer": "^4.2.0"
},
"engines": {
"node": ">= 10.13.0",
"npm": ">= 3.0.0"
}
},
"node_modules/sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
"optional": true,
"dependencies": {
"memory-pager": "^1.0.2"
}
},
"node_modules/tr46": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
"integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
"dependencies": {
"punycode": "^2.1.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==",
"engines": {
"node": ">=12"
}
},
"node_modules/whatwg-url": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
"integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
"dependencies": {
"tr46": "^3.0.0",
"webidl-conversions": "^7.0.0"
},
"engines": {
"node": ">=12"
}
}
},
"dependencies": {
"@types/node": {
"version": "17.0.41",
"resolved": "https://registry.npmjs.org/@types/node/-/node-17.0.41.tgz",
"integrity": "sha512-xA6drNNeqb5YyV5fO3OAEsnXLfO7uF0whiOfPTz5AeDo8KeZFmODKnvwPymMNO8qE/an8pVY/O50tig2SQCrGw=="
},
"@types/webidl-conversions": {
"version": "6.1.1",
"resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-6.1.1.tgz",
"integrity": "sha512-XAahCdThVuCFDQLT7R7Pk/vqeObFNL3YqRyFZg+AqAP/W1/w3xHaIxuW7WszQqTbIBOPRcItYJIou3i/mppu3Q=="
},
"@types/whatwg-url": {
"version": "8.2.1",
"resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.1.tgz",
"integrity": "sha512-2YubE1sjj5ifxievI5Ge1sckb9k/Er66HyR2c+3+I6VDUUg1TLPdYYTEbQ+DjRkS4nTxMJhgWfSfMRD2sl2EYQ==",
"requires": {
"@types/node": "*",
"@types/webidl-conversions": "*"
}
},
"base64-js": {
"version": "1.5.1",
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
},
"bson": {
"version": "4.6.4",
"resolved": "https://registry.npmjs.org/bson/-/bson-4.6.4.tgz",
"integrity": "sha512-TdQ3FzguAu5HKPPlr0kYQCyrYUYh8tFM+CMTpxjNzVzxeiJY00Rtuj3LXLHSgiGvmaWlZ8PE+4KyM2thqE38pQ==",
"requires": {
"buffer": "^5.6.0"
}
},
"buffer": {
"version": "5.7.1",
"resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
"integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"requires": {
"base64-js": "^1.3.1",
"ieee754": "^1.1.13"
}
},
"denque": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz",
"integrity": "sha512-tfiWc6BQLXNLpNiR5iGd0Ocu3P3VpxfzFiqubLgMfhfOw9WyvgJBd46CClNn9k3qfbjvT//0cf7AlYRX/OslMQ=="
},
"fs": {
"version": "0.0.1-security",
"resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz",
"integrity": "sha512-3XY9e1pP0CVEUCdj5BmfIZxRBTSDycnbqhIOGec9QYtmVH2fbLpj86CFWkrNOkt/Fvty4KZG5lTglL9j/gJ87w=="
},
"ieee754": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA=="
},
"ip": {
"version": "1.1.8",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.8.tgz",
"integrity": "sha512-PuExPYUiu6qMBQb4l06ecm6T6ujzhmh+MeJcW9wa89PoAz5pvd4zPgN5WJV104mb6S2T1AwNIAaB70JNrLQWhg=="
},
"memory-pager": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz",
"integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==",
"optional": true
},
"mongodb": {
"version": "4.7.0",
"resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.7.0.tgz",
"integrity": "sha512-HhVar6hsUeMAVlIbwQwWtV36iyjKd9qdhY+s4wcU8K6TOj4Q331iiMy+FoPuxEntDIijTYWivwFJkLv8q/ZgvA==",
"requires": {
"bson": "^4.6.3",
"denque": "^2.0.1",
"mongodb-connection-string-url": "^2.5.2",
"saslprep": "^1.0.3",
"socks": "^2.6.2"
}
},
"mongodb-connection-string-url": {
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.5.2.tgz",
"integrity": "sha512-tWDyIG8cQlI5k3skB6ywaEA5F9f5OntrKKsT/Lteub2zgwSUlhqEN2inGgBTm8bpYJf8QYBdA/5naz65XDpczA==",
"requires": {
"@types/whatwg-url": "^8.2.1",
"whatwg-url": "^11.0.0"
}
},
"punycode": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
"integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A=="
},
"saslprep": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz",
"integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==",
"optional": true,
"requires": {
"sparse-bitfield": "^3.0.3"
}
},
"smart-buffer": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
"integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg=="
},
"socks": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/socks/-/socks-2.6.2.tgz",
"integrity": "sha512-zDZhHhZRY9PxRruRMR7kMhnf3I8hDs4S3f9RecfnGxvcBHQcKcIH/oUcEWffsfl1XxdYlA7nnlGbbTvPz9D8gA==",
"requires": {
"ip": "^1.1.5",
"smart-buffer": "^4.2.0"
}
},
"sparse-bitfield": {
"version": "3.0.3",
"resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz",
"integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==",
"optional": true,
"requires": {
"memory-pager": "^1.0.2"
}
},
"tr46": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz",
"integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==",
"requires": {
"punycode": "^2.1.1"
}
},
"webidl-conversions": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz",
"integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g=="
},
"whatwg-url": {
"version": "11.0.0",
"resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz",
"integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==",
"requires": {
"tr46": "^3.0.0",
"webidl-conversions": "^7.0.0"
}
}
}
}

@ -0,0 +1,16 @@
{
"name": "hi",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "",
"license": "ISC",
"dependencies": {
"fs": "^0.0.1-security",
"mongodb": "^4.7.0"
},
"type": "module"
}

@ -8,6 +8,7 @@
"humanize-duration": "^3.27.1", "humanize-duration": "^3.27.1",
"jshaiku": "file:../haiku", "jshaiku": "file:../haiku",
"json-diff": "^0.7.1", "json-diff": "^0.7.1",
"mongodb": "^4.7.0",
"node-tesseract": "^0.2.7", "node-tesseract": "^0.2.7",
"structured-clone": "^0.2.2", "structured-clone": "^0.2.2",
"tesseract.js": "^2.1.5", "tesseract.js": "^2.1.5",

@ -3,7 +3,7 @@ import readConfig from '../utils/readConfig.js'
import generateEmojiEmbed from '../utils/generateEmojiEmbed.js'; import generateEmojiEmbed from '../utils/generateEmojiEmbed.js';
import getEmojiByName from "../utils/getEmojiByName.js"; import getEmojiByName from "../utils/getEmojiByName.js";
export async function create(guild: Discord.Guild, member: Discord.User, client) { export async function create(guild: Discord.Guild, member: Discord.User, createdBy: Discord.User, client) {
let config = await readConfig(guild.id); let config = await readConfig(guild.id);
// @ts-ignore // @ts-ignore
const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = client.logger const { log, NucleusColors, entry, renderUser, renderChannel, renderDelta } = client.logger
@ -70,6 +70,7 @@ export async function create(guild: Discord.Guild, member: Discord.User, client)
}, },
list: { list: {
ticketFor: entry(member.id, renderUser(member)), ticketFor: entry(member.id, renderUser(member)),
createdBy: entry(createdBy.id, renderUser(createdBy)),
created: entry(new Date().getTime(), renderDelta(new Date().getTime())), created: entry(new Date().getTime(), renderDelta(new Date().getTime())),
ticketChannel: entry(c.id, renderChannel(c)), ticketChannel: entry(c.id, renderChannel(c)),
}, },

@ -11,7 +11,7 @@ export default async function (interaction) {
let channel = (interaction.channel as Discord.TextChannel) let channel = (interaction.channel as Discord.TextChannel)
if (!channel.parent || config.tickets.category != channel.parent.id) { if (!channel.parent || config.tickets.category != channel.parent.id) {
return interaction.reply({embeds: [new generateEmojiEmbed() return interaction.reply({embeds: [new generateEmojiEmbed()
.setTitle("Close Ticket") .setTitle("Deleting Ticket...")
.setDescription("This ticket is not in your tickets category, so cannot be deleted. You cannot run close in a thread.") // TODO bridge to cross later! .setDescription("This ticket is not in your tickets category, so cannot be deleted. You cannot run close in a thread.") // TODO bridge to cross later!
.setStatus("Danger") .setStatus("Danger")
.setEmoji("CONTROL.BLOCKCROSS") .setEmoji("CONTROL.BLOCKCROSS")
@ -19,96 +19,92 @@ export default async function (interaction) {
} }
let status = channel.topic.split(" ")[1]; let status = channel.topic.split(" ")[1];
if (status == "Archived") { if (status == "Archived") {
interaction.reply({embeds: [new generateEmojiEmbed() await interaction.reply({embeds: [new generateEmojiEmbed()
.setTitle("Close Ticket") .setTitle("Delete Ticket")
.setDescription("This ticket will be deleted in 3 seconds.") .setDescription("Your ticket is being deleted...")
.setStatus("Danger") .setStatus("Danger")
.setEmoji("GUILD.TICKET.CLOSE") .setEmoji("GUILD.TICKET.CLOSE")
]}); ]});
setTimeout(async () => { let data = {
let data = { meta:{
meta:{ type: 'ticketDeleted',
type: 'ticketClosed', displayName: 'Ticket Deleted',
displayName: 'Ticket Closed', calculateType: true,
calculateType: true, color: NucleusColors.red,
color: NucleusColors.red, emoji: 'GUILD.TICKET.CLOSE',
emoji: 'GUILD.TICKET.CLOSE', timestamp: new Date().getTime()
timestamp: new Date().getTime() },
}, list: {
list: { ticketFor: entry(channel.topic.split(" ")[0], renderUser((await interaction.guild.members.fetch(channel.topic.split(" ")[0])).user)),
ticketFor: entry(channel.topic.split(" ")[0], renderUser((await interaction.guild.members.fetch(channel.topic.split(" ")[0])).user)), deletedBy: entry(interaction.member.user.id, renderUser(interaction.member.user)),
closedBy: entry(interaction.member.user.id, renderUser(interaction.member.user)), closed: entry(new Date().getTime(), renderDelta(new Date().getTime()))
closed: entry(new Date().getTime(), renderDelta(new Date().getTime())) },
}, hidden: {
hidden: { guild: interaction.guild.id
guild: interaction.guild.id
}
} }
log(data, interaction.client); }
interaction.channel.delete(); log(data, interaction.client);
}, 3000); interaction.channel.delete();
return; return;
} else if (status == "Active") { } else if (status == "Active") {
interaction.reply({embeds: [new generateEmojiEmbed() await interaction.reply({embeds: [new generateEmojiEmbed()
.setTitle("Close Ticket") .setTitle("Close Ticket")
.setDescription("This ticket will be archived in 3 seconds.") .setDescription("Your ticket is being closed...")
.setStatus("Warning") .setStatus("Warning")
.setEmoji("GUILD.TICKET.ARCHIVED") .setEmoji("GUILD.TICKET.ARCHIVED")
]}); ]});
setTimeout(async () =>{ let overwrites = [
let overwrites = [ {
{ id: channel.topic.split(" ")[0],
id: channel.topic.split(" ")[0], deny: ["VIEW_CHANNEL"],
deny: ["VIEW_CHANNEL"], type: "member"
type: "member" },
}, {
{ id: interaction.guild.id,
id: interaction.guild.id, deny: ["VIEW_CHANNEL"],
deny: ["VIEW_CHANNEL"], type: "role"
type: "role"
}
] as Discord.OverwriteResolvable[];
if (config.tickets.supportRole != null) {
overwrites.push({
id: interaction.guild.roles.cache.get(config.tickets.supportRole),
allow: ["VIEW_CHANNEL", "SEND_MESSAGES", "ATTACH_FILES", "ADD_REACTIONS", "READ_MESSAGE_HISTORY"],
type: "role"
})
} }
channel.edit({permissionOverwrites: overwrites}) ] as Discord.OverwriteResolvable[];
channel.setTopic(`${channel.topic.split(" ")[0]} Archived`); if (config.tickets.supportRole != null) {
let data = { overwrites.push({
meta:{ id: interaction.guild.roles.cache.get(config.tickets.supportRole),
type: 'ticketArchive', allow: ["VIEW_CHANNEL", "SEND_MESSAGES", "ATTACH_FILES", "ADD_REACTIONS", "READ_MESSAGE_HISTORY"],
displayName: 'Ticket Archived', type: "role"
calculateType: true, })
color: NucleusColors.yellow, }
emoji: 'GUILD.TICKET.ARCHIVED', channel.edit({permissionOverwrites: overwrites})
timestamp: new Date().getTime() channel.setTopic(`${channel.topic.split(" ")[0]} Archived`);
}, let data = {
list: { meta:{
ticketFor: entry(channel.topic.split(" ")[0], renderUser((await interaction.guild.members.fetch(channel.topic.split(" ")[0])).user)), type: 'ticketClosed',
archivedBy: entry(interaction.member.user.id, renderUser(interaction.member.user)), displayName: 'Ticket Closed',
archived: entry(new Date().getTime(), renderDelta(new Date().getTime())), calculateType: true,
ticketChannel: entry(channel.id, renderChannel(channel)), color: NucleusColors.yellow,
}, emoji: 'GUILD.TICKET.ARCHIVED',
hidden: { timestamp: new Date().getTime()
guild: interaction.guild.id },
} list: {
ticketFor: entry(channel.topic.split(" ")[0], renderUser((await interaction.guild.members.fetch(channel.topic.split(" ")[0])).user)),
closedBy: entry(interaction.member.user.id, renderUser(interaction.member.user)),
closed: entry(new Date().getTime(), renderDelta(new Date().getTime())),
ticketChannel: entry(channel.id, renderChannel(channel)),
},
hidden: {
guild: interaction.guild.id
} }
log(data, interaction.client); }
await interaction.editReply({embeds: [new generateEmojiEmbed() log(data, interaction.client);
.setTitle("Close Ticket") await interaction.editReply({embeds: [new generateEmojiEmbed()
.setDescription("This ticket has been archived.\nType `/ticket close` to delete it.") .setTitle("Close Ticket")
.setStatus("Warning") .setDescription("This ticket has been closed.\nType `/ticket close` again to delete it.")
.setEmoji("GUILD.TICKET.ARCHIVED") // TODO:[Premium] Add a transcript option ||\----/|| <- the bridge we will cross when we come to it .setStatus("Warning")
], components: [new MessageActionRow().addComponents([new MessageButton() .setEmoji("GUILD.TICKET.ARCHIVED") // TODO:[Premium] Add a transcript option ||\----/|| <- the bridge we will cross when we come to it
.setLabel("Close") ], components: [new MessageActionRow().addComponents([new MessageButton()
.setStyle("DANGER") .setLabel("Delete")
.setCustomId("closeticket") .setStyle("DANGER")
.setEmoji(getEmojiByName("CONTROL.CROSS", "id")) .setCustomId("closeticket")
])]}); .setEmoji(getEmojiByName("CONTROL.CROSS", "id"))
}, 3000); ])]});
return; return;
} }
} }

@ -6,7 +6,6 @@ import getEmojiByName from "../../utils/getEmojiByName.js";
import confirmationMessage from "../../utils/confirmationMessage.js"; import confirmationMessage from "../../utils/confirmationMessage.js";
import keyValueList from "../../utils/generateKeyValueList.js"; import keyValueList from "../../utils/generateKeyValueList.js";
import humanizeDuration from "humanize-duration"; import humanizeDuration from "humanize-duration";
import { create, areTicketsEnabled } from "../../automations/createModActionTicket.js";
import readConfig from "../../utils/readConfig.js"; import readConfig from "../../utils/readConfig.js";
const command = (builder: SlashCommandSubcommandBuilder) => const command = (builder: SlashCommandSubcommandBuilder) =>

@ -29,10 +29,10 @@ const callback = async (interaction: CommandInteraction) => {
+ `The user **will${interaction.options.getString("notify") == "yes" ? '' : ' not'}** be notified\n\n` + `The user **will${interaction.options.getString("notify") == "yes" ? '' : ' not'}** be notified\n\n`
+ `Are you sure you want to ${interaction.options.getString("name") ? "change" : "clear"} <@!${(interaction.options.getMember("user") as GuildMember).id}>'s nickname?`) + `Are you sure you want to ${interaction.options.getString("name") ? "change" : "clear"} <@!${(interaction.options.getMember("user") as GuildMember).id}>'s nickname?`)
.setColor("Danger") .setColor("Danger")
.addCustomCallback( .addCustomBoolean(
"Create appeal ticket", !(await areTicketsEnabled(interaction.guild.id)), "Create appeal ticket", !(await areTicketsEnabled(interaction.guild.id)),
() => { create(interaction.guild, interaction.options.getUser("user"), interaction.client)}, async () => await create(interaction.guild, interaction.options.getUser("user"), interaction.user, interaction.client),
"An appeal ticket was created") "An appeal ticket will be created when Confirm is clicked")
// pluralize("day", interaction.options.getInteger("delete")) // pluralize("day", interaction.options.getInteger("delete"))
// const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" } // const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" }
.send() .send()
@ -96,7 +96,7 @@ const callback = async (interaction: CommandInteraction) => {
await interaction.editReply({embeds: [new generateEmojiEmbed() await interaction.editReply({embeds: [new generateEmojiEmbed()
.setEmoji(`PUNISH.NICKNAME.${failed ? "YELLOW" : "GREEN"}`) .setEmoji(`PUNISH.NICKNAME.${failed ? "YELLOW" : "GREEN"}`)
.setTitle(`Nickname`) .setTitle(`Nickname`)
.setDescription("The members nickname was changed" + (failed ? ", but was not notified" : "")) .setDescription("The members nickname was changed" + (failed ? ", but was not notified" : "") + (confirmation.response ? ` and an appeal ticket was opened in <#${confirmation.response}>` : ``))
.setStatus(failed ? "Warning" : "Success") .setStatus(failed ? "Warning" : "Success")
], components: []}) ], components: []})
} else { } else {

@ -5,7 +5,6 @@ import confirmationMessage from "../../utils/confirmationMessage.js";
import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js"; import generateEmojiEmbed from "../../utils/generateEmojiEmbed.js";
import keyValueList from "../../utils/generateKeyValueList.js"; import keyValueList from "../../utils/generateKeyValueList.js";
import getEmojiByName from "../../utils/getEmojiByName.js"; import getEmojiByName from "../../utils/getEmojiByName.js";
import { create, areTicketsEnabled } from "../../automations/createModActionTicket.js";
const command = (builder: SlashCommandSubcommandBuilder) => const command = (builder: SlashCommandSubcommandBuilder) =>
builder builder

@ -129,10 +129,10 @@ const callback = async (interaction: CommandInteraction) => {
+ `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n` + `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n`
+ `Are you sure you want to mute <@!${(interaction.options.getMember("user") as GuildMember).id}>?`) // TODO + `Are you sure you want to mute <@!${(interaction.options.getMember("user") as GuildMember).id}>?`) // TODO
.setColor("Danger") .setColor("Danger")
.addCustomCallback( .addCustomBoolean(
"Create appeal ticket", !(await areTicketsEnabled(interaction.guild.id)), "Create appeal ticket", !(await areTicketsEnabled(interaction.guild.id)),
() => { create(interaction.guild, interaction.options.getUser("user"), interaction.client)}, async () => await create(interaction.guild, interaction.options.getUser("user"), interaction.user, interaction.client),
"An appeal ticket was created") "An appeal ticket will be created when Confirm is clicked")
// pluralize("day", interaction.options.getInteger("delete")) // pluralize("day", interaction.options.getInteger("delete"))
// const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" } // const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" }
.send() .send()

@ -30,10 +30,10 @@ const callback = async (interaction: CommandInteraction) => {
+ `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n` + `The user **will${interaction.options.getString("notify") === "no" ? ' not' : ''}** be notified\n\n`
+ `Are you sure you want to warn <@!${(interaction.options.getMember("user") as GuildMember).id}>?`) + `Are you sure you want to warn <@!${(interaction.options.getMember("user") as GuildMember).id}>?`)
.setColor("Danger") .setColor("Danger")
.addCustomCallback( .addCustomBoolean(
"Create appeal ticket", !(await areTicketsEnabled(interaction.guild.id)), "Create appeal ticket", !(await areTicketsEnabled(interaction.guild.id)),
() => { create(interaction.guild, interaction.options.getUser("user"), interaction.client)}, async () => await create(interaction.guild, interaction.options.getUser("user"), interaction.user, interaction.client),
"An appeal ticket was created") "An appeal ticket will be created when Confirm is clicked")
// pluralize("day", interaction.options.getInteger("delete")) // pluralize("day", interaction.options.getInteger("delete"))
// const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" } // const pluralize = (word: string, count: number) => { return count === 1 ? word : word + "s" }
.send() .send()
@ -85,7 +85,7 @@ const callback = async (interaction: CommandInteraction) => {
await interaction.editReply({embeds: [new generateEmojiEmbed() await interaction.editReply({embeds: [new generateEmojiEmbed()
.setEmoji(`PUNISH.WARN.GREEN`) .setEmoji(`PUNISH.WARN.GREEN`)
.setTitle(`Warn`) .setTitle(`Warn`)
.setDescription("The user was warned") .setDescription("The user was warned" + (confirmation.response ? ` and an appeal ticket was opened in <#${confirmation.response}>` : ``))
.setStatus("Success") .setStatus("Success")
], components: []}) ], components: []})
} else { } else {
@ -135,7 +135,7 @@ const callback = async (interaction: CommandInteraction) => {
return await interaction.editReply({embeds: [new generateEmojiEmbed() return await interaction.editReply({embeds: [new generateEmojiEmbed()
.setEmoji(`PUNISH.WARN.GREEN`) .setEmoji(`PUNISH.WARN.GREEN`)
.setTitle(`Warn`) .setTitle(`Warn`)
.setDescription("The user was warned") .setDescription("The user was warned" + (confirmation.response ? ` and an appeal ticket was opened in <#${confirmation.response}>` : ``))
.setStatus("Success") .setStatus("Success")
], components: []}) ], components: []})
} else { } else {

@ -0,0 +1,108 @@
{
"id": "default",
"version": 1,
"singleEventNotifications": {
"statsChannelDeleted": false
},
"filters": {
"images": {
"NSFW": false,
"size": false
},
"malware": false,
"wordFilter": {
"enabled": false,
"words": {
"strict": [],
"loose": []
},
"allowed": {
"users": [],
"roles": [],
"channels": []
}
},
"invite": {
"enabled": false,
"allowed": {
"users": [],
"channels": [],
"roles": []
}
},
"pings": {
"mass": 5,
"everyone": true,
"roles": true,
"allowed": {
"roles": [],
"rolesToMention": [],
"users": [],
"channels": []
}
}
},
"welcome": {
"enabled": false,
"verificationRequired": {
"message": null,
"role": null
},
"welcomeRole": null,
"channel": null,
"message": null
},
"stats": [],
"logging": {
"logs": {
"enabled": true,
"channel": null,
"toLog": "3fffff"
},
"staff": {
"channel": null
}
},
"verify": {
"enabled": false,
"role": null
},
"tickets": {
"enabled": false,
"category": null,
"types": "3f",
"customTypes": null,
"supportRole": null,
"maxTickets": 5
},
"moderation": {
"mute": {
"timeout": true,
"role": null,
"text": null,
"link": null
},
"kick": {
"text": null,
"link": null
},
"ban": {
"text": null,
"link": null
},
"softban": {
"text": null,
"link": null
},
"warn": {
"text": null,
"link": null
},
"role": {
"role": null
}
},
"tracks": [],
"roleMenu": [],
"tags": {}
}

@ -1,13 +1,10 @@
import { HaikuClient } from 'jshaiku';
import { Intents } from 'discord.js';
import config from './config/main.json' assert {type: 'json'}; import config from './config/main.json' assert {type: 'json'};
import { Logger } from './utils/log.js'; import { Logger } from './utils/log.js';
import runServer from './api/index.js'; import runServer from './api/index.js';
import Memory from './utils/memory.js'; import Memory from './utils/memory.js';
import Database from './utils/database.js';
const client = new HaikuClient({ import client from './utils/client.js';
intents: new Intents(32767).bitfield, // This is a way of specifying all intents w/o having to type them out
}, config);
await client.registerCommandsIn("./commands"); await client.registerCommandsIn("./commands");
await client.registerEventsIn("./events"); await client.registerEventsIn("./events");
@ -19,5 +16,7 @@ client.logger = new Logger()
client.verify = {} client.verify = {}
client.roleMenu = {} client.roleMenu = {}
client.memory = new Memory() client.memory = new Memory()
client.database = await new Database(config.mongoUrl).connect()
await client.login(); await client.login();

@ -0,0 +1,9 @@
import { HaikuClient } from 'jshaiku';
import { Intents } from 'discord.js';
import config from '../config/main.json' assert {type: 'json'};
const client = new HaikuClient({
intents: new Intents(32767).bitfield, // This is a way of specifying all intents w/o having to type them out
}, config);
export default client;

@ -14,6 +14,8 @@ class confirmationMessage {
customCallbackString: string = ""; customCallbackString: string = "";
customCallbackClicked: boolean = false; customCallbackClicked: boolean = false;
customCallbackResponse: any = null; customCallbackResponse: any = null;
customBoolean: () => any;
customBooleanClicked: boolean = null;
inverted: boolean; inverted: boolean;
constructor(interaction: CommandInteraction) { constructor(interaction: CommandInteraction) {
@ -23,8 +25,9 @@ class confirmationMessage {
this.emoji = ""; this.emoji = "";
this.description = ""; this.description = "";
this.color = ""; this.color = "";
this.inverted = false this.inverted = false;
this.customCallback = () => {} this.customCallback = () => {};
this.customBoolean = () => {};
} }
setTitle(title: string) { this.title = title; return this } setTitle(title: string) { this.title = title; return this }
@ -33,12 +36,23 @@ class confirmationMessage {
setColor(color: string) { this.color = color; return this } setColor(color: string) { this.color = color; return this }
setInverted(inverted: boolean) { this.inverted = inverted; return this } setInverted(inverted: boolean) { this.inverted = inverted; return this }
addCustomCallback(title: string, disabled: boolean, callback: () => any, callbackClicked: string) { addCustomCallback(title: string, disabled: boolean, callback: () => any, callbackClicked: string) {
if (this.customButtonTitle) return this
this.customButtonTitle = title; this.customButtonTitle = title;
this.customButtonDisabled = disabled; this.customButtonDisabled = disabled;
this.customCallback = callback; this.customCallback = callback;
this.customCallbackString = callbackClicked; this.customCallbackString = callbackClicked;
return this; return this;
} }
addCustomBoolean(title: string, disabled: boolean, callback: () => any, callbackClicked: string) {
if (this.customButtonTitle) return this
this.customButtonTitle = title;
this.customButtonDisabled = disabled;
this.customBoolean = callback;
this.customCallbackString = callbackClicked;
this.customBooleanClicked = false;
return this;
}
async send(editOnly?: boolean) { async send(editOnly?: boolean) {
while (true) { while (true) {
@ -49,7 +63,7 @@ class confirmationMessage {
.setTitle(this.title) .setTitle(this.title)
.setDescription(this.description) .setDescription(this.description)
.setStatus(this.color) .setStatus(this.color)
.setFooter({text: this.customCallbackClicked ? this.customCallbackString : ""}) .setFooter({text: (this.customBooleanClicked ?? this.customCallbackClicked) ? this.customCallbackString : ""})
], ],
components: [ components: [
new MessageActionRow().addComponents([ new MessageActionRow().addComponents([
@ -66,7 +80,10 @@ class confirmationMessage {
].concat(this.customButtonTitle ? [new Discord.MessageButton() ].concat(this.customButtonTitle ? [new Discord.MessageButton()
.setCustomId("custom") .setCustomId("custom")
.setLabel(this.customButtonTitle) .setLabel(this.customButtonTitle)
.setStyle("PRIMARY") .setStyle(this.customBooleanClicked !== null ?
( this.customBooleanClicked ? "SUCCESS" : "PRIMARY" ) :
"PRIMARY"
)
.setDisabled(this.customButtonDisabled) .setDisabled(this.customButtonDisabled)
.setEmoji(getEmojiByName("CONTROL.TICKET", "id")) .setEmoji(getEmojiByName("CONTROL.TICKET", "id"))
] : [])) ] : []))
@ -84,19 +101,36 @@ class confirmationMessage {
try { try {
component = await (m as Message).awaitMessageComponent({filter: (m) => m.user.id === this.interaction.user.id, time: 2.5 * 60 * 1000}); component = await (m as Message).awaitMessageComponent({filter: (m) => m.user.id === this.interaction.user.id, time: 2.5 * 60 * 1000});
} catch (e) { } catch (e) {
return { success: false, buttonClicked: this.customCallbackClicked, response: this.customCallbackResponse }; return {
success: false,
buttonClicked: this.customBooleanClicked ?? this.customCallbackClicked,
response: this.customCallbackResponse
};
} }
if (component.customId === "yes") { if (component.customId === "yes") {
component.deferUpdate(); component.deferUpdate();
return { success: true, buttonClicked: this.customCallbackClicked, response: this.customCallbackResponse }; if (this.customBooleanClicked === true) this.customCallbackResponse = await this.customBoolean();
return {
success: true,
buttonClicked: this.customBooleanClicked ?? this.customCallbackClicked,
response: this.customCallbackResponse
};
} else if (component.customId === "no") { } else if (component.customId === "no") {
component.deferUpdate(); component.deferUpdate();
return { success: false, buttonClicked: this.customCallbackClicked, response: this.customCallbackResponse }; return {
success: false,
buttonClicked: this.customBooleanClicked ?? this.customCallbackClicked,
response: this.customCallbackResponse
};
} else if (component.customId === "custom") { } else if (component.customId === "custom") {
component.deferUpdate(); component.deferUpdate();
this.customCallbackResponse = this.customCallback(); if (this.customBooleanClicked !== null) {
this.customCallbackClicked = true; this.customBooleanClicked = !this.customBooleanClicked;
this.customButtonDisabled = true; } else {
this.customCallbackResponse = await this.customCallback();
this.customCallbackClicked = true;
this.customButtonDisabled = true;
}
editOnly = true; editOnly = true;
} }
} }

@ -0,0 +1,180 @@
import { Collection, Db, MongoClient } from 'mongodb';
export const Entry = data => {
data = data ?? {};
return {
get(target, prop, receiver) {
let dataToReturn = data[prop]
if (dataToReturn === null ) return Reflect.get(target, prop, receiver);
if (typeof dataToReturn === "object" && !Array.isArray(dataToReturn)) dataToReturn = new Proxy(
Reflect.get(target, prop, receiver),
Entry(dataToReturn),
)
return dataToReturn ?? Reflect.get(target, prop, receiver);
}
}
}
export default class Database {
mongoClient: MongoClient;
database: Db;
guilds: Collection<GuildConfig>;
defaultData: GuildConfig;
constructor(url) {
this.mongoClient = new MongoClient(url);
}
async connect() {
await this.mongoClient.connect()
this.database = this.mongoClient.db("Nucleus");
this.guilds = this.database.collection<GuildConfig>("guilds");
await this.guilds.createIndex({ id: "text" }, { unique: true });
this.defaultData = (await import("../config/default.json", { assert: { type: "json" }})).default as unknown as GuildConfig;
return this;
}
async read(guild: string) {
let entry = await this.guilds.findOne({ id: guild });
return new Proxy(this.defaultData, Entry(entry)) as unknown as GuildConfig
}
async write(guild: string, config: GuildConfig) {
await this.guilds.updateOne({ id: guild }, { $set: config }, { upsert: true });
}
}
export interface GuildConfig {
id: string,
version: number,
singleEventNotifications: {
statsChannelDeleted: boolean
}
filters: {
images: {
NSFW: boolean,
size: boolean
},
malware: boolean,
wordFilter: {
enabled: boolean,
words: {
strict: string[],
loose: string[]
},
allowed: {
users: string[],
roles: string[],
channels: string[]
}
},
invite: {
enabled: boolean,
allowed: {
users: string[],
channels: string[],
roles: string[]
}
},
pings: {
mass: number,
everyone: boolean,
roles: boolean,
allowed: {
roles: string[],
rolesToMention: string[],
users: string[],
channels: string[]
}
}
}
welcome: {
enabled: boolean,
verificationRequired: {
message: boolean,
role: string
},
welcomeRole: string,
channel: string,
message: string
}
stats: {
enabled: boolean,
channel: string,
text: string
}[]
logging: {
logs: {
enabled: boolean,
channel: string,
toLog: string
},
staff: {
channel: string
}
}
verify: {
enabled: boolean,
role: string
}
tickets: {
enabled: boolean,
category: string,
types: string,
customTypes: string[],
supportRole: string,
maxTickets: number
}
moderation: {
mute: {
timeout: boolean,
role: string,
text: string,
link: string
},
kick: {
text: string,
link: string
},
ban: {
text: string,
link: string
},
softban: {
text: string,
link: string
},
warn: {
text: string,
link: string
},
role: {
role: string
}
}
tracks: {
name: string,
retainPrevious: boolean,
nullable: boolean,
track: string[],
manageableBy: string[]
}[]
roleMenu: {
enabled: boolean,
allowWebUI: boolean,
options: {
name: string,
description: string,
min: number,
max: number,
options: {
name: string,
description: string,
role: string
}[]
}[]
}
tags: {}
};

@ -14,7 +14,7 @@ class Memory {
logging: guildData.logging, logging: guildData.logging,
tickets: guildData.tickets, tickets: guildData.tickets,
}; // TODO: REMOVE GUILD FROM MEMORY WHEN THESE UPDATE }; // TODO: REMOVE GUILD FROM MEMORY WHEN THESE UPDATE
} } // TODO: Add a "lastAccessed" prop, delete after 15 minutes
return this.memory[guild]; return this.memory[guild];
} }
} }

@ -1,165 +1,5 @@
import client from './client.js';
export default async function readConfig(guild: string): Promise<any> { export default async function readConfig(guild: string): Promise<any> {
return await client.database.read(guild);
let config = {
singleEventNotifications: {
statsChannelDeleted: false
},
filters: {
images: {
NSFW: true,
size: true
},
malware: true,
wordFilter: {
enabled: true,
words: {
strict: [],
loose: []
},
allowed: {
users: [],
roles: [],
channels: []
}
},
invite: {
enabled: false,
allowed: {
users: [],
channels: [],
roles: []
}
},
pings: {
mass: 5,
everyone: true,
roles: true,
allowed: {
roles: [],
rolesToMention: [],
users: [],
channels: []
}
}
},
welcome: {
enabled: true,
verificationRequired: {
message: false,
role: false
},
welcomeRole: null,
channel: '895209752315961344', // null, channel ID or 'dm'
message: "Welcome to the server, {@}!"
},
stats: [
{
enabled: true,
channel: '951910554291818526',
text: "{count} members | {count:bots} bots | {count:humans} humans"
}
],
logging: {
logs: {
enabled: true,
channel: '952247098437427260',
toLog: "3fffff" // "3ffffe" = - channelUpdate, "3fffff" = all
},
staff: {
channel: "895212366252367933"
}
},
verify: {
enabled: true,
role: '934941369137524816',
},
tickets: {
enabled: true,
category: "952302254302584932",
types: "3f",
customTypes: null,
supportRole: null,
maxTickets: 5
},
moderation: {
mute: {
timeout: true,
role: "934941369137524816", // TODO: Remove this role after the time
text: null,
link: null
},
kick: {
text: "Appeal here",
link: "https://clicks.codes"
},
ban: {
text: null,
link: null
},
softban: {
text: null,
link: null
},
warn: {
text: null,
link: null
},
role: {
role: "934941369137524816"
},
},
tracks: [
{
name: "Moderation",
retainPrevious: false,
nullable: true,
track: [
"934941369137524816",
"934941399806246984",
"934941408849186856",
"934941466734764092"
],
manageableBy: []
},
{
name: "Verification",
retainPrevious: false,
nullable: true,
track: [
"963166531318067250"
],
manageableBy: []
}
],
roleMenu: {
enabled: true,
allowWebUI: true,
options: [
{
name: "Gender",
description: "What's your gender?",
min: 1,
max: 1,
options: [
{ name: "Male", role: "959901318019948574" },
{ name: "Female", role: "959901346000154674" },
{ name: "Non Binary", description: "Better than the others", role: "959901378363420704"}
]
},
{
name: "Pick",
min: 0,
max: 4,
options: [
{ name: "Test Role 1", role: "934941369137524816" },
{ name: "Test Role 2", role: "934941399806246984" },
{ name: "Test Role 3", role: "934941408849186856" },
{ name: "Test Role 4", role: "934941466734764092" }
]
}
]
}
};
return config;
} }

Loading…
Cancel
Save