').text(`${row.configid} - ${( guild.roles.find( role => {
return role.id === row.role.split('|')[0];
} )?.name || guild.channels.find( channel => {
return channel.id === row.channel.split('|')[1];
} )?.name || row.usergroup.split('|')[( row.usergroup.startsWith('AND|') ? 1 : 0 )] )}`)
).attr('href', `/guild/${guild.id}/verification/${row.configid}${suffix}`);
} ),
( process.env.READONLY || rows.length >= verificationLimit[( guild.patreon ? 'patreon' : 'default' )] ? '' :
$('
').append(
$('
').attr('src', '/src/channel.svg'),
$('').text(dashboardLang.get('verification.new'))
).attr('href', `/guild/${guild.id}/verification/new${suffix}`) )
);
if ( args[4] === 'new' && !( process.env.READONLY || rows.length >= verificationLimit[( guild.patreon ? 'patreon' : 'default' )] ) ) {
$('.channel#channel-new').addClass('selected');
createForm($, dashboardLang.get('verification.form.new'), dashboardLang, {
channel: '', role: '', usergroup: 'user',
editcount: 0, postcount: 0, accountage: 0,
rename: false, defaultrole
}, guild.channels, guild.roles).attr('action', `/guild/${guild.id}/verification/new`).appendTo('#text');
}
else if ( rows.some( row => row.configid.toString() === args[4] ) ) {
let row = rows.find( row => row.configid.toString() === args[4] );
$(`.channel#channel-${row.configid}`).addClass('selected');
createForm($, dashboardLang.get('verification.form.entry', false, row.configid), dashboardLang, row, guild.channels, guild.roles).attr('action', `/guild/${guild.id}/verification/${row.configid}`).appendTo('#text');
}
else {
$('.channel#verification').addClass('selected');
$('#text .description').html(dashboardLang.get('verification.explanation'));
$('#text code.prefix').prepend(escapeText(prefix));
}
let body = $.html();
res.writeHead(200, {'Content-Length': Buffer.byteLength(body)});
res.write( body );
return res.end();
}, dberror => {
console.log( '- Dashboard: Error while getting the verifications: ' + dberror );
createNotice($, 'error', dashboardLang);
$('#text .description').html(dashboardLang.get('verification.explanation'));
$('#text code.prefix').prepend(escapeText(process.env.prefix));
$('.channel#verification').addClass('selected');
let body = $.html();
res.writeHead(200, {'Content-Length': Buffer.byteLength(body)});
res.write( body );
return res.end();
} );
}
/**
* Change verifications
* @param {Function} res - The server response
* @param {import('./util.js').Settings} userSettings - The settings of the user
* @param {String} guild - The id of the guild
* @param {String|Number} type - The setting to change
* @param {Object} settings - The new settings
* @param {String[]} settings.channel
* @param {String[]} settings.role
* @param {String[]} [settings.usergroup]
* @param {String} [settings.usergroup_and]
* @param {Number} settings.editcount
* @param {Number} [settings.postcount]
* @param {String} settings.posteditcount
* @param {Number} settings.accountage
* @param {String} [settings.rename]
* @param {String} [settings.save_settings]
* @param {String} [settings.delete_settings]
*/
function update_verification(res, userSettings, guild, type, settings) {
if ( type === 'default' ) {
return res(`/guild/${guild}/verification`, 'savefail');
}
if ( !settings.save_settings === !settings.delete_settings ) {
return res(`/guild/${guild}/verification/${type}`, 'savefail');
}
if ( settings.save_settings ) {
if ( !/^[\d|]+ [\d|]+$/.test(`${settings.channel} ${settings.role}`) ) {
return res(`/guild/${guild}/verification/${type}`, 'savefail');
}
if ( !/^\d+ \d+$/.test(`${settings.editcount} ${settings.accountage}`) ) {
return res(`/guild/${guild}/verification/${type}`, 'savefail');
}
if ( !( ['and','or','both'].includes( settings.posteditcount ) && ( /^\d+$/.test(settings.postcount) || settings.posteditcount === 'both' ) ) ) {
return res(`/guild/${guild}/verification/${type}`, 'savefail');
}
settings.channel = settings.channel.split('|').filter( (channel, i, self) => {
return ( channel.length && self.indexOf(channel) === i );
} );
if ( !settings.channel.length || settings.channel.length > 10 ) {
return res(`/guild/${guild}/verification/${type}`, 'savefail');
}
settings.role = settings.role.split('|').filter( (role, i, self) => {
return ( role.length && self.indexOf(role) === i );
} );
if ( !settings.role.length || settings.role.length > 10 ) {
return res(`/guild/${guild}/verification/${type}`, 'savefail');
}
if ( !settings.usergroup ) settings.usergroup = 'user';
settings.usergroup = settings.usergroup.replace( /_/g, ' ' ).trim().toLowerCase();
settings.usergroup = settings.usergroup.split(/\s*[,|]\s*/).map( usergroup => {
if ( usergroup === '*' ) return 'user';
return usergroup.replace( / /g, '_' );
} ).filter( (usergroup, i, self) => {
return ( usergroup.length && self.indexOf(usergroup) === i );
} );
if ( !settings.usergroup.length ) settings.usergroup.push('user');
if ( settings.usergroup.length > 10 || settings.usergroup.some( usergroup => {
return ( usergroup.length > 100 );
} ) ) return res(`/guild/${guild}/verification/${type}`, 'invalidusergroup');
settings.editcount = parseInt(settings.editcount, 10);
settings.accountage = parseInt(settings.accountage, 10);
if ( settings.editcount > 1000000 || settings.accountage > 1000000 ) {
return res(`/guild/${guild}/verification/${type}`, 'savefail');
}
if ( settings.posteditcount === 'both' ) settings.postcount = null;
else settings.postcount = parseInt(settings.postcount, 10);
if ( settings.posteditcount === 'or' ) settings.postcount = settings.postcount * -1;
if ( settings.postcount > 1000000 || settings.postcount < -1000000 ) {
return res(`/guild/${guild}/verification/${type}`, 'savefail');
}
if ( type === 'new' ) {
let curGuild = userSettings.guilds.isMember.get(guild);
if ( settings.channel.some( channel => {
return !curGuild.channels.some( guildChannel => {
return ( guildChannel.id === channel && !guildChannel.isCategory );
} );
} ) || settings.role.some( role => {
return !curGuild.roles.some( guildRole => {
return ( guildRole.id === role && guildRole.lower );
} );
} ) ) return res(`/guild/${guild}/verification/new`, 'savefail');
}
}
if ( settings.delete_settings && type === 'new' ) {
return res(`/guild/${guild}/verification/new`, 'savefail');
}
if ( type !== 'new' ) type = parseInt(type, 10);
sendMsg( {
type: 'getMember',
member: userSettings.user.id,
guild: guild
} ).then( response => {
if ( !response ) {
userSettings.guilds.notMember.set(guild, userSettings.guilds.isMember.get(guild));
userSettings.guilds.isMember.delete(guild);
return res(`/guild/${guild}`, 'savefail');
}
if ( response === 'noMember' || !hasPerm(response.userPermissions, 'MANAGE_GUILD') ) {
userSettings.guilds.isMember.delete(guild);
return res('/', 'savefail');
}
if ( settings.delete_settings ) return db.query( 'DELETE FROM verification WHERE guild = $1 AND configid = $2 RETURNING channel, role, editcount, postcount, usergroup, accountage, rename', [guild, type] ).then( ({rows:[row]}) => {
console.log( `- Dashboard: Verification successfully removed: ${guild}#${type}` );
res(`/guild/${guild}/verification`, 'save');
if ( row ) db.query( 'SELECT lang FROM discord WHERE guild = $1 AND channel IS NULL', [guild] ).then( ({rows:[channel]}) => {
var lang = new Lang(channel.lang);
var text = lang.get('verification.dashboard.removed', `<@${userSettings.user.id}>`, type);
if ( row ) {
text += '\n' + lang.get('verification.channel') + ' <#' + row.channel.split('|').filter( channel => channel.length ).join('>, <#') + '>';
text += '\n' + lang.get('verification.role') + ' <@&' + row.role.split('|').join('>, <@&') + '>';
if ( row.postcount === null ) {
text += '\n' + lang.get('verification.posteditcount') + ' `' + row.editcount + '`';
}
else {
text += '\n' + lang.get('verification.editcount') + ' `' + row.editcount + '`';
text += '\n' + lang.get('verification.postcount') + ' `' + Math.abs(row.postcount) + '`';
if ( row.postcount < 0 ) text += ' ' + lang.get('verification.postcount_or');
}
text += '\n' + lang.get('verification.usergroup') + ' `' + ( row.usergroup.startsWith( 'AND|' ) ? row.usergroup.split('|').slice(1).join('` ' + lang.get('verification.and') + ' `') : row.usergroup.split('|').join('` ' + lang.get('verification.or') + ' `') ) + '`';
text += '\n' + lang.get('verification.accountage') + ' `' + row.accountage + '` ' + lang.get('verification.indays');
text += '\n' + lang.get('verification.rename') + ' *`' + lang.get('verification.' + ( row.rename ? 'enabled' : 'disabled')) + '`*';
}
text += `\n<${new URL(`/guild/${guild}/verification`, process.env.dashboard).href}>`;
sendMsg( {
type: 'notifyGuild', guild, text
} ).catch( error => {
console.log( '- Dashboard: Error while notifying the guild: ' + error );
} );
}, dberror => {
console.log( '- Dashboard: Error while notifying the guild: ' + dberror );
} );
}, dberror => {
console.log( '- Dashboard: Error while removing the verification: ' + dberror );
return res(`/guild/${guild}/verification/${type}`, 'savefail');
} );
if ( !hasPerm(response.botPermissions, 'MANAGE_ROLES') ) {
return res(`/guild/${guild}/verification`, 'savefail');
}
if ( type === 'new' ) return db.query( 'SELECT wiki, lang, ARRAY_REMOVE(ARRAY_AGG(configid ORDER BY configid), NULL) count FROM discord LEFT JOIN verification ON discord.guild = verification.guild WHERE discord.guild = $1 AND discord.channel IS NULL GROUP BY wiki, lang', [guild] ).then( ({rows:[row]}) => {
if ( !row ) return res(`/guild/${guild}/verification`, 'savefail');
if ( row.count.length >= verificationLimit[( response.patreon ? 'patreon' : 'default' )] ) {
return res(`/guild/${guild}/verification`, 'savefail');
}
return got.get( row.wiki + 'api.php?action=query&meta=allmessages&refix=group-&amincludelocal=true&amenableparser=true&format=json' ).then( gresponse => {
var body = gresponse.body;
if ( gresponse.statusCode !== 200 || body?.batchcomplete === undefined || !body?.query?.allmessages ) {
console.log( '- Dashboard: ' + gresponse.statusCode + ': Error while getting the usergroups: ' + body?.error?.info );
return;
}
var groups = body.query.allmessages.filter( group => {
if ( group.name === 'group-all' ) return false;
if ( group.name === 'group-membership-link-with-expiry' ) return false;
if ( group.name.endsWith( '.css' ) || group.name.endsWith( '.js' ) ) return false;
return true;
} ).map( group => {
return {
name: group.name.replace( /^group-/, '' ).replace( /-member$/, '' ),
content: group['*'].replace( / /g, '_' ).toLowerCase()
};
} );
settings.usergroup = settings.usergroup.map( usergroup => {
if ( groups.some( group => group.name === usergroup ) ) return usergroup;
if ( groups.some( group => group.content === usergroup ) ) {
return groups.find( group => group.content === usergroup ).name;
}
if ( /^admins?$/.test(usergroup) ) return 'sysop';
if ( usergroup === '*' ) return 'user';
return usergroup;
} );
}, error => {
console.log( '- Dashboard: Error while getting the usergroups: ' + error );
} ).finally( () => {
if ( settings.usergroup_and ) settings.usergroup.unshift('AND');
var configid = 1;
for ( let i of row.count ) {
if ( configid === i ) configid++;
else break;
}
db.query( 'INSERT INTO verification(guild, configid, channel, role, editcount, postcount, usergroup, accountage, rename) VALUES($1, $2, $3, $4, $5, $6, $7, $8, $9)', [guild, configid, '|' + settings.channel.join('|') + '|', settings.role.join('|'), settings.editcount, settings.postcount, settings.usergroup.join('|'), settings.accountage, ( settings.rename ? 1 : 0 )] ).then( () => {
console.log( `- Dashboard: Verification successfully added: ${guild}#${configid}` );
res(`/guild/${guild}/verification/${configid}`, 'save');
var lang = new Lang(row.lang);
var text = lang.get('verification.dashboard.added', `<@${userSettings.user.id}>`, configid);
text += '\n' + lang.get('verification.channel') + ' <#' + settings.channel.join('>, <#') + '>';
text += '\n' + lang.get('verification.role') + ' <@&' + settings.role.join('>, <@&') + '>';
if ( settings.postcount === null ) {
text += '\n' + lang.get('verification.posteditcount') + ' `' + settings.editcount + '`';
}
else {
text += '\n' + lang.get('verification.editcount') + ' `' + settings.editcount + '`';
text += '\n' + lang.get('verification.postcount') + ' `' + Math.abs(settings.postcount) + '`';
if ( settings.postcount < 0 ) text += ' ' + lang.get('verification.postcount_or');
}
text += '\n' + lang.get('verification.usergroup') + ' `' + ( settings.usergroup_and ? settings.usergroup.slice(1).join('` ' + lang.get('verification.and') + ' `') : settings.usergroup.join('` ' + lang.get('verification.or') + ' `') ) + '`';
text += '\n' + lang.get('verification.accountage') + ' `' + settings.accountage + '` ' + lang.get('verification.indays');
text += '\n' + lang.get('verification.rename') + ' *`' + lang.get('verification.' + ( settings.rename ? 'enabled' : 'disabled')) + '`*';
text += `\n<${new URL(`/guild/${guild}/verification/${configid}`, process.env.dashboard).href}>`;
if ( settings.rename && !hasPerm(response.botPermissions, 'MANAGE_NICKNAMES') ) {
text += '\n\n' + lang.get('verification.rename_no_permission', `<@${process.env.bot}>`);
}
if ( settings.role.some( role => {
return !userSettings.guilds.isMember.get(guild).roles.some( guildRole => {
return ( guildRole.id === role && guildRole.lower );
} );
} ) ) {
text += '\n';
settings.role.forEach( role => {
if ( !userSettings.guilds.isMember.get(guild).roles.some( guildRole => {
return ( guildRole.id === role );
} ) ) {
text += '\n' + lang.get('verification.role_deleted', `<@&${role}>`);
}
else if ( userSettings.guilds.isMember.get(guild).roles.some( guildRole => {
return ( guildRole.id === role && !guildRole.lower );
} ) ) {
text += '\n' + lang.get('verification.role_too_high', `<@&${role}>`, `<@${process.env.bot}>`);
}
} );
}
sendMsg( {
type: 'notifyGuild', guild, text
} ).catch( error => {
console.log( '- Dashboard: Error while notifying the guild: ' + error );
} );
}, dberror => {
console.log( '- Dashboard: Error while adding the verification: ' + dberror );
return res(`/guild/${guild}/verification/new`, 'savefail');
} );
} );
}, dberror => {
console.log( '- Dashboard: Error while checking for verifications: ' + dberror );
return res(`/guild/${guild}/verification/new`, 'savefail');
} );
return db.query( 'SELECT wiki, lang, verification.channel, verification.role, editcount, postcount, usergroup, accountage, rename FROM discord LEFT JOIN verification ON discord.guild = verification.guild AND verification.configid = $1 WHERE discord.guild = $2 AND discord.channel IS NULL', [type, guild] ).then( ({rows:[row]}) => {
if ( !row?.channel ) return res(`/guild/${guild}/verification`, 'savefail');
row.channel = row.channel.split('|').filter( channel => channel.length );
var newChannel = settings.channel.filter( channel => !row.channel.includes( channel ) );
row.role = row.role.split('|');
var newRole = settings.role.filter( role => !row.role.includes( role ) );
row.usergroup = row.usergroup.split('|');
var newUsergroup = settings.usergroup.filter( group => !row.usergroup.includes( group ) );
if ( newChannel.length || newRole.length ) {
let curGuild = userSettings.guilds.isMember.get(guild);
if ( newChannel.some( channel => {
return !curGuild.channels.some( guildChannel => {
return ( guildChannel.id === channel && !guildChannel.isCategory );
} );
} ) || newRole.some( role => {
return !curGuild.roles.some( guildRole => {
return ( guildRole.id === role && guildRole.lower );
} );
} ) ) return res(`/guild/${guild}/verification/${type}`, 'savefail');
}
( newUsergroup.length ? got.get( row.wiki + 'api.php?action=query&meta=allmessages&refix=group-&amincludelocal=true&amenableparser=true&format=json' ).then( gresponse => {
var body = gresponse.body;
if ( gresponse.statusCode !== 200 || body?.batchcomplete === undefined || !body?.query?.allmessages ) {
console.log( '- Dashboard: ' + gresponse.statusCode + ': Error while getting the usergroups: ' + body?.error?.info );
return;
}
var groups = body.query.allmessages.filter( group => {
if ( group.name === 'group-all' ) return false;
if ( group.name === 'group-membership-link-with-expiry' ) return false;
if ( group.name.endsWith( '.css' ) || group.name.endsWith( '.js' ) ) return false;
return true;
} ).map( group => {
return {
name: group.name.replace( /^group-/, '' ).replace( /-member$/, '' ),
content: group['*'].replace( / /g, '_' ).toLowerCase()
};
} );
settings.usergroup = settings.usergroup.map( usergroup => {
if ( groups.some( group => group.name === usergroup ) ) return usergroup;
if ( groups.some( group => group.content === usergroup ) ) {
return groups.find( group => group.content === usergroup ).name;
}
if ( /^admins?$/.test(usergroup) ) return 'sysop';
if ( usergroup === '*' ) return 'user';
return usergroup;
} );
}, error => {
console.log( '- Dashboard: Error while getting the usergroups: ' + error );
} ) : Promise.resolve() ).finally( () => {
if ( settings.usergroup_and ) settings.usergroup.unshift('AND');
var lang = new Lang(row.lang);
var diff = [];
if ( newChannel.length || row.channel.some( channel => {
return !settings.channel.includes( channel );
} ) ) {
diff.push(lang.get('verification.channel') + ` ~~<#${row.channel.join('>, <#')}>~~ → <#${settings.channel.join('>, <#')}>`);
}
if ( newRole.length || row.role.some( role => {
return !settings.role.includes( role );
} ) ) {
diff.push(lang.get('verification.role') + ` ~~<@&${row.role.join('>, <@&')}>~~ → <@&${settings.role.join('>, <@&')}>`);
}
if ( row.postcount !== settings.postcount && ( row.postcount === null || settings.postcount === null ) ) {
if ( row.postcount === null ) {
diff.push('~~' + lang.get('verification.posteditcount') + ` \`${row.editcount}\`~~`);
diff.push('→ ' + lang.get('verification.editcount') + ` \`${settings.editcount}\``);
diff.push('→ ' + lang.get('verification.postcount') + ` \`${Math.abs(settings.postcount)}\`` + ( settings.postcount < 0 ? ' ' + lang.get('verification.postcount_or') : '' ));
}
if ( settings.postcount === null ) {
diff.push('~~' + lang.get('verification.editcount') + ` \`${row.editcount}\`~~`);
diff.push('~~' + lang.get('verification.postcount') + ` \`${Math.abs(row.postcount)}\`` + ( row.postcount < 0 ? ' ' + lang.get('verification.postcount_or') : '' ) + '~~');
diff.push('→ ' + lang.get('verification.posteditcount') + ` \`${settings.editcount}\``);
}
}
else {
if ( row.editcount !== settings.editcount ) {
diff.push(lang.get('verification.editcount') + ` ~~\`${row.editcount}\`~~ → \`${settings.editcount}\``);
}
if ( row.postcount !== settings.postcount ) {
if ( ( row.postcount >= 0 && settings.postcount < 0 ) || ( row.postcount < 0 && settings.postcount >= 0 ) ) {
diff.push('~~' + lang.get('verification.postcount') + ` \`${Math.abs(row.postcount)}\`` + ( row.postcount < 0 ? ' ' + lang.get('verification.postcount_or') : '' ) + '~~');
diff.push('→ ' + lang.get('verification.postcount') + ` \`${Math.abs(settings.postcount)}\`` + ( settings.postcount < 0 ? ' ' + lang.get('verification.postcount_or') : '' ));
}
else diff.push(lang.get('verification.postcount') + ` ~~\`${Math.abs(row.postcount)}\`~~ → \`${Math.abs(settings.postcount)}\`` + ( settings.postcount < 0 ? ' ' + lang.get('verification.postcount_or') : '' ));
}
}
if ( newUsergroup.length || row.usergroup.some( usergroup => {
return !settings.usergroup.includes( usergroup );
} ) ) {
diff.push(lang.get('verification.usergroup') + ' ~~`' + ( row.usergroup[0] === 'AND' ? row.usergroup.slice(1).join('` ' + lang.get('verification.and') + ' `') : row.usergroup.join('` ' + lang.get('verification.or') + ' `') ) + '`~~ → `' + ( settings.usergroup_and ? settings.usergroup.slice(1).join('` ' + lang.get('verification.and') + ' `') : settings.usergroup.join('` ' + lang.get('verification.or') + ' `') ) + '`');
}
if ( row.accountage !== settings.accountage ) {
diff.push(lang.get('verification.accountage') + ` ~~\`${row.accountage}\`~~ → \`${settings.accountage}\``);
}
if ( row.rename !== ( settings.rename ? 1 : 0 ) ) {
diff.push(lang.get('verification.rename') + ` ~~*\`${lang.get('verification.' + ( row.rename ? 'enabled' : 'disabled'))}\`*~~ → *\`${lang.get('verification.' + ( settings.rename ? 'enabled' : 'disabled'))}\`*`);
}
if ( !diff.length ) return res(`/guild/${guild}/verification/${type}`, 'save');
db.query( 'UPDATE verification SET channel = $1, role = $2, editcount = $3, postcount = $4, usergroup = $5, accountage = $6, rename = $7 WHERE guild = $8 AND configid = $9', ['|' + settings.channel.join('|') + '|', settings.role.join('|'), settings.editcount, settings.postcount, settings.usergroup.join('|'), settings.accountage, ( settings.rename ? 1 : 0 ), guild, type] ).then( () => {
console.log( `- Dashboard: Verification successfully updated: ${guild}#${type}` );
res(`/guild/${guild}/verification/${type}`, 'save');
var text = lang.get('verification.dashboard.updated', `<@${userSettings.user.id}>`, type);
text += '\n' + diff.join('\n');
text += `\n<${new URL(`/guild/${guild}/verification/${type}`, process.env.dashboard).href}>`;
if ( settings.rename && !hasPerm(response.botPermissions, 'MANAGE_NICKNAMES') ) {
text += '\n\n' + lang.get('verification.rename_no_permission', `<@${process.env.bot}>`);
}
if ( settings.role.some( role => {
return !userSettings.guilds.isMember.get(guild).roles.some( guildRole => {
return ( guildRole.id === role && guildRole.lower );
} );
} ) ) {
text += '\n';
settings.role.forEach( role => {
if ( !userSettings.guilds.isMember.get(guild).roles.some( guildRole => {
return ( guildRole.id === role );
} ) ) {
text += '\n' + lang.get('verification.role_deleted', `<@&${role}>`);
}
else if ( userSettings.guilds.isMember.get(guild).roles.some( guildRole => {
return ( guildRole.id === role && !guildRole.lower );
} ) ) {
text += '\n' + lang.get('verification.role_too_high', `<@&${role}>`, `<@${process.env.bot}>`);
}
} );
}
sendMsg( {
type: 'notifyGuild', guild, text
} ).catch( error => {
console.log( '- Dashboard: Error while notifying the guild: ' + error );
} );
}, dberror => {
console.log( '- Dashboard: Error while updating the verification: ' + dberror );
return res(`/guild/${guild}/verification/${type}`, 'savefail');
} );
} );
}, dberror => {
console.log( '- Dashboard: Error while checking for verifications: ' + dberror );
return res(`/guild/${guild}/verification/${type}`, 'savefail');
} );
}, error => {
console.log( '- Dashboard: Error while getting the member: ' + error );
return res(`/guild/${guild}/verification/${type}`, 'savefail');
} );
}
module.exports = {
get: dashboard_verification,
post: update_verification
};