forked from Galactic/galactic-bot
modlog import
This commit is contained in:
parent
2ea7d097f4
commit
4f75472c37
@ -134,6 +134,7 @@ class GuildWrapper {
|
||||
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) {
|
||||
if (!this._settings) await this.settings();
|
||||
try {
|
||||
|
@ -1,3 +1,4 @@
|
||||
const { InfractionMigrator, Util } = require("../../../../utilities");
|
||||
const SettingsMigrator = require("../../../../utilities/SettingsMigrator");
|
||||
const { SlashCommand } = require("../../../interfaces");
|
||||
|
||||
@ -6,6 +7,7 @@ const dbs = {
|
||||
'3': 'newgbot'
|
||||
};
|
||||
|
||||
const { MONGODB_HOST, MONGODB_USERNAME, MONGODB_PASSWORD, MONGODB_V2_HOST } = process.env;
|
||||
class ImportCommand extends SlashCommand {
|
||||
|
||||
constructor(client) {
|
||||
@ -17,7 +19,7 @@ class ImportCommand extends SlashCommand {
|
||||
guildOnly: true,
|
||||
memberPermissions: ['ADMINISTRATOR'],
|
||||
options: [{
|
||||
name: ['settings', 'modlogs'],
|
||||
name: ['settings'],
|
||||
type: 'SUB_COMMAND',
|
||||
options: [{
|
||||
name: 'version',
|
||||
@ -27,24 +29,49 @@ class ImportCommand extends SlashCommand {
|
||||
{ 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 settings = await guild.settings();
|
||||
if (settings._imported);
|
||||
let settings = await guild.settings();
|
||||
if (settings._imported[subcommand.name]) return { emoji: 'failure', index: 'COMMAND_IMPORT_IMPORTED', params: { thing: Util.capitalise(subcommand.name) } };
|
||||
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;
|
||||
const migrator = new SettingsMigrator(this.client, guild, {
|
||||
host: MONGODB_HOST,
|
||||
result._edit = true;
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
async modlogs(guild, version, overwrite = false) {
|
||||
|
||||
const migrator = new InfractionMigrator(this.client, guild, {
|
||||
host: version === '2' ? MONGODB_V2_HOST : MONGODB_HOST,
|
||||
username: MONGODB_USERNAME,
|
||||
password: MONGODB_PASSWORD,
|
||||
database: dbs[version], // Default to v3
|
||||
@ -54,7 +81,48 @@ class ImportCommand extends SlashCommand {
|
||||
await migrator.connect();
|
||||
let imported = null;
|
||||
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) {
|
||||
this.client.logger.error(err.stack);
|
||||
return { index: 'COMMAND_IMPORT_ERROR', params: { message: err.message }, emoji: 'failure' };
|
||||
@ -68,7 +136,7 @@ class ImportCommand extends SlashCommand {
|
||||
if (typeof webhook === 'string') {
|
||||
const hooks = await guild.fetchWebhooks();
|
||||
const hook = hooks.get(webhook);
|
||||
if(hook) await guild.updateWebhook('messages', hook);
|
||||
if (hook) await guild.updateWebhook('messages', hook);
|
||||
} else if (version === '3') {
|
||||
delete webhook.feature;
|
||||
await this.client.storageManager.mongodb.webhooks.updateOne({ feature: 'messages', guild: guild.id }, webhook);
|
||||
|
@ -1,3 +1,5 @@
|
||||
const { ObjectId } = require("mongodb");
|
||||
|
||||
class MongodbTable {
|
||||
|
||||
constructor(client, provider, opts = {}) {
|
||||
@ -11,11 +13,11 @@ class MongodbTable {
|
||||
|
||||
//Data Search
|
||||
|
||||
async find(query, opts = {}, { sort, skip, limit } = {}) { //opts: { projection: ... }
|
||||
find(query, opts = {}, { sort, skip, limit } = {}) { //opts: { projection: ... }
|
||||
query = this._handleData(query);
|
||||
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 (skip) cursor.skip(skip);
|
||||
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) {
|
||||
query = this._handleData(query);
|
||||
@ -164,17 +169,15 @@ class MongodbTable {
|
||||
});
|
||||
}
|
||||
|
||||
//Lazy Function
|
||||
// Shouldn't be necessary anymore -- cleanup later
|
||||
_handleData(data) { //Convert data._id to Mongo ObjectIds (gets converted to plaintext through shard communication)
|
||||
// if (data._id) {
|
||||
// if (typeof data._id === 'string') data._id = ObjectId(data._id);
|
||||
// else if (typeof data._id === 'object') data._id = {
|
||||
// $in: Object.values(data._id)[0].map((id) => {
|
||||
// return ObjectId(id);
|
||||
// })
|
||||
// };
|
||||
// }
|
||||
_handleData(data) { //Convert data._id to Mongo ObjectIds
|
||||
if (data._id) {
|
||||
if (typeof data._id === 'string') data._id = ObjectId(data._id);
|
||||
else if (typeof data._id === 'object') data._id = {
|
||||
$in: Object.values(data._id)[0].map((id) => {
|
||||
return ObjectId(id);
|
||||
})
|
||||
};
|
||||
}
|
||||
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`);
|
||||
}
|
||||
|
||||
async migrate() {
|
||||
async import() {
|
||||
|
||||
this.logger.debug(`Attempting settings migration for ${this.guild}`);
|
||||
|
||||
@ -65,10 +65,10 @@ class SettingsMigrator {
|
||||
const settings = await this.mongo.findOne(collection, filter);
|
||||
if (!settings) return Promise.reject(new Error('No old settings found'));
|
||||
|
||||
const { _version } = settings;
|
||||
if (!_version) return Promise.reject(new Error('Unable to determine configuration version'));
|
||||
// const { _version } = settings;
|
||||
// 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,
|
||||
permissions = null;
|
||||
@ -93,7 +93,7 @@ class SettingsMigrator {
|
||||
permissions.guildId = this.guild;
|
||||
}
|
||||
|
||||
translated._imported = true;
|
||||
// translated._imported = true;
|
||||
translated.guildId = 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)
|
||||
settings.moderation = {
|
||||
channel: result.modlogs || null,
|
||||
@ -344,6 +360,7 @@ class SettingsMigrator {
|
||||
const _points = entries.filter(([key]) => !key.includes('Expire') && !['enabled', 'associations', 'multiplier'].includes(key));
|
||||
|
||||
for (const [key, value] of _points) points[key.toUpperCase()] = value;
|
||||
// eslint-disable-next-line prefer-const
|
||||
for (let [key, value] of _expirations) {
|
||||
key = key.replace('Expire', '').toUpperCase();
|
||||
expirations[key] = value;
|
||||
|
@ -3,5 +3,6 @@ module.exports = {
|
||||
BinaryTree: require('./BinaryTree.js'),
|
||||
FilterUtil: require('./FilterUtil.js'),
|
||||
Logger: require('./Logger.js'),
|
||||
SettingsMigrator: require('./SettingsMigrator')
|
||||
SettingsMigrator: require('./SettingsMigrator'),
|
||||
InfractionMigrator: require('./InfractionMigrator')
|
||||
};
|
Loading…
Reference in New Issue
Block a user