modlog import
This commit is contained in:
parent
2ea7d097f4
commit
4f75472c37
@ -134,6 +134,7 @@ class GuildWrapper {
|
|||||||
return this._settings;
|
return this._settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO Move settings to a settings object insteadd of being in a mess with everything else in the data object
|
||||||
async updateSettings(settings) {
|
async updateSettings(settings) {
|
||||||
if (!this._settings) await this.settings();
|
if (!this._settings) await this.settings();
|
||||||
try {
|
try {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
const { InfractionMigrator, Util } = require("../../../../utilities");
|
||||||
const SettingsMigrator = require("../../../../utilities/SettingsMigrator");
|
const SettingsMigrator = require("../../../../utilities/SettingsMigrator");
|
||||||
const { SlashCommand } = require("../../../interfaces");
|
const { SlashCommand } = require("../../../interfaces");
|
||||||
|
|
||||||
@ -6,6 +7,7 @@ const dbs = {
|
|||||||
'3': 'newgbot'
|
'3': 'newgbot'
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const { MONGODB_HOST, MONGODB_USERNAME, MONGODB_PASSWORD, MONGODB_V2_HOST } = process.env;
|
||||||
class ImportCommand extends SlashCommand {
|
class ImportCommand extends SlashCommand {
|
||||||
|
|
||||||
constructor(client) {
|
constructor(client) {
|
||||||
@ -17,7 +19,7 @@ class ImportCommand extends SlashCommand {
|
|||||||
guildOnly: true,
|
guildOnly: true,
|
||||||
memberPermissions: ['ADMINISTRATOR'],
|
memberPermissions: ['ADMINISTRATOR'],
|
||||||
options: [{
|
options: [{
|
||||||
name: ['settings', 'modlogs'],
|
name: ['settings'],
|
||||||
type: 'SUB_COMMAND',
|
type: 'SUB_COMMAND',
|
||||||
options: [{
|
options: [{
|
||||||
name: 'version',
|
name: 'version',
|
||||||
@ -27,24 +29,49 @@ class ImportCommand extends SlashCommand {
|
|||||||
{ name: 'v3', value: '3' }
|
{ name: 'v3', value: '3' }
|
||||||
]
|
]
|
||||||
}]
|
}]
|
||||||
|
}, {
|
||||||
|
name: 'modlogs',
|
||||||
|
type: 'SUB_COMMAND',
|
||||||
|
options: [{
|
||||||
|
name: 'version',
|
||||||
|
description: 'Which version do you want to import from',
|
||||||
|
choices: [
|
||||||
|
{ name: 'v2', value: '2' },
|
||||||
|
{ name: 'v3', value: '3' }
|
||||||
|
]
|
||||||
|
}, {
|
||||||
|
name: 'overwrite',
|
||||||
|
description: 'Whether any existing logs should be overwritten by the imports. By default new ones are bumped',
|
||||||
|
type: 'BOOLEAN'
|
||||||
|
}]
|
||||||
}]
|
}]
|
||||||
});
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async execute(invoker, { version }) {
|
async execute(invoker, { version, overwrite }) {
|
||||||
const { subcommand, guild } = invoker;
|
const { subcommand, guild } = invoker;
|
||||||
const settings = await guild.settings();
|
let settings = await guild.settings();
|
||||||
if (settings._imported);
|
if (settings._imported[subcommand.name]) return { emoji: 'failure', index: 'COMMAND_IMPORT_IMPORTED', params: { thing: Util.capitalise(subcommand.name) } };
|
||||||
version = version?.value || '3';
|
version = version?.value || '3';
|
||||||
|
|
||||||
if(subcommand.name === 'modlogs') return { content: 'Not supported yet' };
|
await invoker.reply({ index: 'COMMAND_IMPORT_WORKING', emoji: 'loading' });
|
||||||
|
const result = await this[subcommand.name](guild, version, overwrite.value);
|
||||||
|
|
||||||
// TODO split into settings and modlogs
|
// This looks ridiculous but it's to keep track of what's been imported
|
||||||
|
settings = guild._settings;
|
||||||
|
if (!settings.imported) settings.imported = {};
|
||||||
|
settings.imported[subcommand.name] = true;
|
||||||
|
|
||||||
const { MONGODB_HOST, MONGODB_USERNAME, MONGODB_PASSWORD } = process.env;
|
result._edit = true;
|
||||||
const migrator = new SettingsMigrator(this.client, guild, {
|
return result;
|
||||||
host: MONGODB_HOST,
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async modlogs(guild, version, overwrite = false) {
|
||||||
|
|
||||||
|
const migrator = new InfractionMigrator(this.client, guild, {
|
||||||
|
host: version === '2' ? MONGODB_V2_HOST : MONGODB_HOST,
|
||||||
username: MONGODB_USERNAME,
|
username: MONGODB_USERNAME,
|
||||||
password: MONGODB_PASSWORD,
|
password: MONGODB_PASSWORD,
|
||||||
database: dbs[version], // Default to v3
|
database: dbs[version], // Default to v3
|
||||||
@ -54,7 +81,48 @@ class ImportCommand extends SlashCommand {
|
|||||||
await migrator.connect();
|
await migrator.connect();
|
||||||
let imported = null;
|
let imported = null;
|
||||||
try {
|
try {
|
||||||
imported = await migrator.migrate();
|
imported = await migrator.import();
|
||||||
|
imported.sort((a, b) => a.case - b.case);
|
||||||
|
} catch (err) {
|
||||||
|
this.client.logger.error(err.stack);
|
||||||
|
return { index: 'COMMAND_IMPORT_ERROR', params: { message: err.message }, emoji: 'failure' };
|
||||||
|
}
|
||||||
|
await migrator.end();
|
||||||
|
console.log(imported);
|
||||||
|
|
||||||
|
if (overwrite) { // Overwrite any existing logs with the imported ones
|
||||||
|
await this.client.mongodb.infractions.deleteMany({ guild: guild.id });
|
||||||
|
await this.client.mongodb.infractions.insertMany(imported);
|
||||||
|
} else { // Bump existing logs by the highest case id from imported logs
|
||||||
|
const highestOldId = imported[imported.length - 1];
|
||||||
|
const existingLogs = await this.client.mongodb.infractions.find({ guild: guild.id });
|
||||||
|
for (const log of existingLogs) {
|
||||||
|
log.case += highestOldId;
|
||||||
|
await this.client.mongodb.infractions.updateOne({ _id: log._id }, { case: log.case });
|
||||||
|
}
|
||||||
|
guild._settings.caseId += highestOldId;
|
||||||
|
await guild.updateSettings({ caseId: guild._settings.caseId });
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return { content: 'blah' };
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async settings(guild, version) {
|
||||||
|
// const { MONGODB_HOST, MONGODB_USERNAME, MONGODB_PASSWORD } = process.env;
|
||||||
|
const migrator = new SettingsMigrator(this.client, guild, {
|
||||||
|
host: version === '2' ? MONGODB_V2_HOST : MONGODB_HOST,
|
||||||
|
username: MONGODB_USERNAME,
|
||||||
|
password: MONGODB_PASSWORD,
|
||||||
|
database: dbs[version], // Default to v3
|
||||||
|
version
|
||||||
|
});
|
||||||
|
|
||||||
|
await migrator.connect();
|
||||||
|
let imported = null;
|
||||||
|
try {
|
||||||
|
imported = await migrator.import();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
this.client.logger.error(err.stack);
|
this.client.logger.error(err.stack);
|
||||||
return { index: 'COMMAND_IMPORT_ERROR', params: { message: err.message }, emoji: 'failure' };
|
return { index: 'COMMAND_IMPORT_ERROR', params: { message: err.message }, emoji: 'failure' };
|
||||||
@ -68,7 +136,7 @@ class ImportCommand extends SlashCommand {
|
|||||||
if (typeof webhook === 'string') {
|
if (typeof webhook === 'string') {
|
||||||
const hooks = await guild.fetchWebhooks();
|
const hooks = await guild.fetchWebhooks();
|
||||||
const hook = hooks.get(webhook);
|
const hook = hooks.get(webhook);
|
||||||
if(hook) await guild.updateWebhook('messages', hook);
|
if (hook) await guild.updateWebhook('messages', hook);
|
||||||
} else if (version === '3') {
|
} else if (version === '3') {
|
||||||
delete webhook.feature;
|
delete webhook.feature;
|
||||||
await this.client.storageManager.mongodb.webhooks.updateOne({ feature: 'messages', guild: guild.id }, webhook);
|
await this.client.storageManager.mongodb.webhooks.updateOne({ feature: 'messages', guild: guild.id }, webhook);
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
const { ObjectId } = require("mongodb");
|
||||||
|
|
||||||
class MongodbTable {
|
class MongodbTable {
|
||||||
|
|
||||||
constructor(client, provider, opts = {}) {
|
constructor(client, provider, opts = {}) {
|
||||||
@ -11,11 +13,11 @@ class MongodbTable {
|
|||||||
|
|
||||||
//Data Search
|
//Data Search
|
||||||
|
|
||||||
async find(query, opts = {}, { sort, skip, limit } = {}) { //opts: { projection: ... }
|
find(query, opts = {}, { sort, skip, limit } = {}) { //opts: { projection: ... }
|
||||||
query = this._handleData(query);
|
query = this._handleData(query);
|
||||||
if (!this.provider._initialized) return Promise.reject(new Error('MongoDB is not connected.'));
|
if (!this.provider._initialized) return Promise.reject(new Error('MongoDB is not connected.'));
|
||||||
|
|
||||||
const cursor = await this.collection.find(query, opts);
|
const cursor = this.collection.find(query, opts);
|
||||||
if (sort) cursor.sort(sort);
|
if (sort) cursor.sort(sort);
|
||||||
if (skip) cursor.skip(skip);
|
if (skip) cursor.skip(skip);
|
||||||
if (limit) cursor.limit(limit);
|
if (limit) cursor.limit(limit);
|
||||||
@ -70,7 +72,10 @@ class MongodbTable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//NOTE: insertMany?
|
insertMany(documents, options = {}) {
|
||||||
|
if (!this.provider._initialized) return Promise.reject(new Error('MongoDB is not connected.'));
|
||||||
|
return this.collection.insertMany(documents, options);
|
||||||
|
}
|
||||||
|
|
||||||
deleteOne(query) {
|
deleteOne(query) {
|
||||||
query = this._handleData(query);
|
query = this._handleData(query);
|
||||||
@ -164,17 +169,15 @@ class MongodbTable {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
//Lazy Function
|
_handleData(data) { //Convert data._id to Mongo ObjectIds
|
||||||
// Shouldn't be necessary anymore -- cleanup later
|
if (data._id) {
|
||||||
_handleData(data) { //Convert data._id to Mongo ObjectIds (gets converted to plaintext through shard communication)
|
if (typeof data._id === 'string') data._id = ObjectId(data._id);
|
||||||
// if (data._id) {
|
else if (typeof data._id === 'object') data._id = {
|
||||||
// if (typeof data._id === 'string') data._id = ObjectId(data._id);
|
$in: Object.values(data._id)[0].map((id) => {
|
||||||
// else if (typeof data._id === 'object') data._id = {
|
return ObjectId(id);
|
||||||
// $in: Object.values(data._id)[0].map((id) => {
|
})
|
||||||
// return ObjectId(id);
|
};
|
||||||
// })
|
}
|
||||||
// };
|
|
||||||
// }
|
|
||||||
return data;
|
return data;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
137
src/utilities/InfractionMigrator.js
Normal file
137
src/utilities/InfractionMigrator.js
Normal file
@ -0,0 +1,137 @@
|
|||||||
|
const MongoWrapper = require('./SimpleMongoWrapper');
|
||||||
|
const Logger = require('./Logger');
|
||||||
|
|
||||||
|
const modtypes = {
|
||||||
|
'hardban': 'BAN',
|
||||||
|
'ban': 'BAN',
|
||||||
|
'tempban': 'BAN',
|
||||||
|
'softban': 'SOFTBAN',
|
||||||
|
'kick': 'KICK',
|
||||||
|
'note': 'NOTE',
|
||||||
|
'mute': 'MUTE',
|
||||||
|
'unmute': 'UNMUTE',
|
||||||
|
'warn': 'WARN',
|
||||||
|
};
|
||||||
|
|
||||||
|
class InfractionMigrator {
|
||||||
|
|
||||||
|
constructor(client, guild, dbConfig) {
|
||||||
|
|
||||||
|
this._config = dbConfig;
|
||||||
|
this.client = client;
|
||||||
|
this.mongo = new MongoWrapper(dbConfig);
|
||||||
|
this.guild = guild.id || guild;
|
||||||
|
this.logger = new Logger(this);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async connect() {
|
||||||
|
this.logger.info(`Connecting to mongo: ${this._config.database}`);
|
||||||
|
await this.mongo.init();
|
||||||
|
this.logger.info(`Mongo connected`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async end() {
|
||||||
|
this.logger.info(`Disconnecting ${this._config.database}`);
|
||||||
|
await this.mongo.close();
|
||||||
|
this.logger.info(`Disconnected`);
|
||||||
|
}
|
||||||
|
|
||||||
|
async import() {
|
||||||
|
|
||||||
|
this.logger.debug(`Attempting modlogs migration for ${this.guild}`);
|
||||||
|
|
||||||
|
const { version } = this._config;
|
||||||
|
let idIdentifier = null,
|
||||||
|
collection = null;
|
||||||
|
if (version === '2') {
|
||||||
|
collection = 'discord_infractions';
|
||||||
|
idIdentifier = 'guild';
|
||||||
|
} else {
|
||||||
|
collection = 'infractions';
|
||||||
|
idIdentifier = 'guild';
|
||||||
|
}
|
||||||
|
|
||||||
|
const filter = { [idIdentifier]: this.guild };
|
||||||
|
const infractions = await this.mongo.find(collection, filter);
|
||||||
|
if (!infractions.length) return Promise.reject(new Error('No infractions found'));
|
||||||
|
|
||||||
|
const translated = this[version](infractions);
|
||||||
|
return translated;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
'2'(infractions) {
|
||||||
|
|
||||||
|
const result = [];
|
||||||
|
for (const infraction of infractions) {
|
||||||
|
const base = this.infractionBase;
|
||||||
|
base.id = `${infraction.guild}:${infraction.id}`;
|
||||||
|
base.case = infraction.id;
|
||||||
|
base.reason = infraction.reason;
|
||||||
|
base.type = modtypes[infraction.type];
|
||||||
|
|
||||||
|
base.duration = infraction.modlength * 1000;
|
||||||
|
base.timestamp = infraction.timestamp * 1000;
|
||||||
|
|
||||||
|
base.guild = infraction.guild;
|
||||||
|
base.executor = infraction.staff;
|
||||||
|
base.target = infraction.user;
|
||||||
|
|
||||||
|
base.resolved = infraction.resolved;
|
||||||
|
base.points = infraction.modpoints;
|
||||||
|
base.expiration = infraction.expires * 1000;
|
||||||
|
|
||||||
|
base.dmLogMessage = infraction.dm_message_id;
|
||||||
|
base.modLogMessage = infraction.message_id;
|
||||||
|
|
||||||
|
result.push(base);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
'3'(infractions) {
|
||||||
|
const result = [];
|
||||||
|
for (const infraction of infractions) {
|
||||||
|
// Ensure the infractions have all properties, shouldn't be any inconsistencies between 3 and 3.slash but just in case
|
||||||
|
result.push({ ...this.infractionBase, ...infraction });
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
get infractionBase() {
|
||||||
|
return {
|
||||||
|
id: null,
|
||||||
|
guild: null,
|
||||||
|
channel: null,
|
||||||
|
channelName: null,
|
||||||
|
message: null,
|
||||||
|
executor: null,
|
||||||
|
executorTag: null,
|
||||||
|
target: null,
|
||||||
|
targetTag: null,
|
||||||
|
targetType: null,
|
||||||
|
type: null,
|
||||||
|
case: null,
|
||||||
|
timestamp: null,
|
||||||
|
duration: null,
|
||||||
|
callback: null,
|
||||||
|
reason: null,
|
||||||
|
data: null,
|
||||||
|
flags: null,
|
||||||
|
points: null,
|
||||||
|
expiration: null,
|
||||||
|
modLogMessage: null,
|
||||||
|
dmLogMessage: null,
|
||||||
|
modLogChannel: null,
|
||||||
|
resolved: null,
|
||||||
|
changes: null,
|
||||||
|
_callbacked: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = InfractionMigrator;
|
@ -46,7 +46,7 @@ class SettingsMigrator {
|
|||||||
this.logger.info(`Disconnected`);
|
this.logger.info(`Disconnected`);
|
||||||
}
|
}
|
||||||
|
|
||||||
async migrate() {
|
async import() {
|
||||||
|
|
||||||
this.logger.debug(`Attempting settings migration for ${this.guild}`);
|
this.logger.debug(`Attempting settings migration for ${this.guild}`);
|
||||||
|
|
||||||
@ -65,10 +65,10 @@ class SettingsMigrator {
|
|||||||
const settings = await this.mongo.findOne(collection, filter);
|
const settings = await this.mongo.findOne(collection, filter);
|
||||||
if (!settings) return Promise.reject(new Error('No old settings found'));
|
if (!settings) return Promise.reject(new Error('No old settings found'));
|
||||||
|
|
||||||
const { _version } = settings;
|
// const { _version } = settings;
|
||||||
if (!_version) return Promise.reject(new Error('Unable to determine configuration version'));
|
// if (!_version) return Promise.reject(new Error('Unable to determine configuration version'));
|
||||||
|
|
||||||
const translated = this[_version](settings);
|
const translated = this[version](settings);
|
||||||
|
|
||||||
let webhook = null,
|
let webhook = null,
|
||||||
permissions = null;
|
permissions = null;
|
||||||
@ -93,7 +93,7 @@ class SettingsMigrator {
|
|||||||
permissions.guildId = this.guild;
|
permissions.guildId = this.guild;
|
||||||
}
|
}
|
||||||
|
|
||||||
translated._imported = true;
|
// translated._imported = true;
|
||||||
translated.guildId = this.guild;
|
translated.guildId = this.guild;
|
||||||
|
|
||||||
this.logger.info(`Settings migration for ${this.guild}`);
|
this.logger.info(`Settings migration for ${this.guild}`);
|
||||||
@ -220,6 +220,22 @@ class SettingsMigrator {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (selfrole) {
|
||||||
|
settings.selfrole = {
|
||||||
|
roles: selfrole.roles, message: null, channel: null, text: null
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (activity) settings.activity = activity;
|
||||||
|
if (killitwithfire) {
|
||||||
|
settings.dehoist = {
|
||||||
|
enabled: killitwithfire.enabled,
|
||||||
|
begin: killitwithfire.startsWith,
|
||||||
|
characters: [],
|
||||||
|
strict: killitwithfire.strict
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (moderation || modlogs)
|
if (moderation || modlogs)
|
||||||
settings.moderation = {
|
settings.moderation = {
|
||||||
channel: result.modlogs || null,
|
channel: result.modlogs || null,
|
||||||
@ -344,6 +360,7 @@ class SettingsMigrator {
|
|||||||
const _points = entries.filter(([key]) => !key.includes('Expire') && !['enabled', 'associations', 'multiplier'].includes(key));
|
const _points = entries.filter(([key]) => !key.includes('Expire') && !['enabled', 'associations', 'multiplier'].includes(key));
|
||||||
|
|
||||||
for (const [key, value] of _points) points[key.toUpperCase()] = value;
|
for (const [key, value] of _points) points[key.toUpperCase()] = value;
|
||||||
|
// eslint-disable-next-line prefer-const
|
||||||
for (let [key, value] of _expirations) {
|
for (let [key, value] of _expirations) {
|
||||||
key = key.replace('Expire', '').toUpperCase();
|
key = key.replace('Expire', '').toUpperCase();
|
||||||
expirations[key] = value;
|
expirations[key] = value;
|
||||||
|
@ -3,5 +3,6 @@ module.exports = {
|
|||||||
BinaryTree: require('./BinaryTree.js'),
|
BinaryTree: require('./BinaryTree.js'),
|
||||||
FilterUtil: require('./FilterUtil.js'),
|
FilterUtil: require('./FilterUtil.js'),
|
||||||
Logger: require('./Logger.js'),
|
Logger: require('./Logger.js'),
|
||||||
SettingsMigrator: require('./SettingsMigrator')
|
SettingsMigrator: require('./SettingsMigrator'),
|
||||||
|
InfractionMigrator: require('./InfractionMigrator')
|
||||||
};
|
};
|
Loading…
Reference in New Issue
Block a user