Add verification success endpoint and improve trust level system
Adds a POST endpoint `/api/verify-success` to `webServer.js` for handling verification callbacks from aethex.dev, including secret validation and role assignment. Updates `federationProtection.js` and `federation.js` to integrate trust level calculations and benefits. Introduces a new `trustLevels.js` utility file to manage trust level definitions, progression, and related logic. Replit-Commit-Author: Agent Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261 Replit-Commit-Checkpoint-Type: full_checkpoint Replit-Commit-Event-Id: 98ebd9a6-5755-4d7f-ae64-9ed93f1eae4f Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/3tJ1Z1J Replit-Helium-Checkpoint-Created: true
This commit is contained in:
parent
73ff5bcce3
commit
a1912fc48a
4 changed files with 401 additions and 12 deletions
|
|
@ -1,5 +1,6 @@
|
|||
const { SlashCommandBuilder, EmbedBuilder, PermissionFlagsBits, ActionRowBuilder, ButtonBuilder, ButtonStyle } = require('discord.js');
|
||||
const { getServerMode, EMBED_COLORS } = require('../utils/modeHelper');
|
||||
const { getTrustLevelInfo, getProgressToNextLevel, TRUST_LEVELS, calculateReputationChange } = require('../utils/trustLevels');
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
|
|
@ -60,6 +61,7 @@ module.exports = {
|
|||
).setRequired(true))
|
||||
.addStringOption(opt => opt.setName('description').setDescription('Brief description of your server').setRequired(true)))
|
||||
.addSubcommand(sub => sub.setName('status').setDescription('Check your server\'s federation status'))
|
||||
.addSubcommand(sub => sub.setName('stats').setDescription('View detailed trust level stats and progression'))
|
||||
.addSubcommand(sub => sub.setName('treaty').setDescription('View the Federation Treaty'))
|
||||
)
|
||||
.addSubcommandGroup(group =>
|
||||
|
|
@ -270,6 +272,25 @@ async function handleBans(interaction, supabase, client, subcommand) {
|
|||
return interaction.reply({ content: 'Failed to add ban.', ephemeral: true });
|
||||
}
|
||||
|
||||
const reputationGain = calculateReputationChange('ban_report', true);
|
||||
|
||||
const { data: currentServer } = await supabase
|
||||
.from('federation_servers')
|
||||
.select('reports_submitted, reputation_score')
|
||||
.eq('guild_id', interaction.guildId)
|
||||
.maybeSingle();
|
||||
|
||||
if (currentServer) {
|
||||
await supabase
|
||||
.from('federation_servers')
|
||||
.update({
|
||||
reports_submitted: (currentServer.reports_submitted || 0) + 1,
|
||||
reputation_score: (currentServer.reputation_score || 0) + reputationGain,
|
||||
last_activity: new Date().toISOString()
|
||||
})
|
||||
.eq('guild_id', interaction.guildId);
|
||||
}
|
||||
|
||||
const severityColors = { low: 0xffff00, medium: 0xff9900, high: 0xff3300, critical: 0xff0000 };
|
||||
const severityEmojis = { low: '⚠️', medium: '🔶', high: '🔴', critical: '☠️' };
|
||||
|
||||
|
|
@ -280,7 +301,8 @@ async function handleBans(interaction, supabase, client, subcommand) {
|
|||
.addFields(
|
||||
{ name: 'User', value: `${user.tag}\n\`${user.id}\``, inline: true },
|
||||
{ name: 'Severity', value: severity.toUpperCase(), inline: true },
|
||||
{ name: 'Reason', value: reason }
|
||||
{ name: 'Reason', value: reason },
|
||||
{ name: 'Reputation', value: `+${reputationGain} points`, inline: true }
|
||||
)
|
||||
.setFooter({ text: `Added by ${interaction.user.tag}` })
|
||||
.setTimestamp();
|
||||
|
|
@ -553,14 +575,20 @@ async function handleMembership(interaction, supabase, client, subcommand) {
|
|||
.maybeSingle();
|
||||
|
||||
if (server) {
|
||||
const trustLevel = server.trust_level || 'bronze';
|
||||
const trustInfo = getTrustLevelInfo(trustLevel);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(0x00ff00)
|
||||
.setTitle('Federation Member')
|
||||
.setColor(trustInfo.color)
|
||||
.setTitle(`${trustInfo.emoji} Federation Member - ${trustInfo.name}`)
|
||||
.addFields(
|
||||
{ name: 'Status', value: server.status.toUpperCase(), inline: true },
|
||||
{ name: 'Tier', value: server.tier?.toUpperCase() || 'FREE', inline: true },
|
||||
{ name: 'Trust Level', value: `${trustInfo.emoji} ${trustInfo.name}`, inline: true },
|
||||
{ name: 'Reputation', value: `${server.reputation_score || 0} points`, inline: true },
|
||||
{ name: 'Joined', value: new Date(server.joined_at).toLocaleDateString(), inline: true }
|
||||
)
|
||||
.setFooter({ text: 'Use /federation membership stats for detailed progression' })
|
||||
.setTimestamp();
|
||||
return interaction.reply({ embeds: [embed] });
|
||||
}
|
||||
|
|
@ -598,6 +626,78 @@ async function handleMembership(interaction, supabase, client, subcommand) {
|
|||
await interaction.reply({ embeds: [embed] });
|
||||
}
|
||||
|
||||
if (subcommand === 'stats') {
|
||||
const { data: server } = await supabase
|
||||
.from('federation_servers')
|
||||
.select('*')
|
||||
.eq('guild_id', interaction.guildId)
|
||||
.maybeSingle();
|
||||
|
||||
if (!server) {
|
||||
return interaction.reply({
|
||||
content: 'This server is not a federation member. Use `/federation membership apply` to join!',
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
|
||||
const trustLevel = server.trust_level || 'bronze';
|
||||
const trustInfo = getTrustLevelInfo(trustLevel);
|
||||
const progression = getProgressToNextLevel(server);
|
||||
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(trustInfo.color)
|
||||
.setTitle(`${trustInfo.emoji} Trust Level: ${trustInfo.name}`)
|
||||
.setDescription('Your server\'s federation standing and progression.')
|
||||
.addFields(
|
||||
{ name: 'Current Benefits', value: [
|
||||
`**Auto-Action:** ${trustInfo.benefits.autoAction === 'ban' ? 'Auto-ban threats' : trustInfo.benefits.autoAction === 'kick' ? 'Auto-kick threats' : 'Alert only'}`,
|
||||
`**Severity Threshold:** ${trustInfo.benefits.severityThreshold.charAt(0).toUpperCase() + trustInfo.benefits.severityThreshold.slice(1)}+`,
|
||||
`**Featured Eligible:** ${trustInfo.benefits.featuredEligible ? 'Yes' : 'No'}`,
|
||||
`**Partnership Limit:** ${trustInfo.benefits.partnershipLimit} servers`
|
||||
].join('\n') }
|
||||
);
|
||||
|
||||
if (progression.nextLevel) {
|
||||
const progressBars = [];
|
||||
const makeBar = (pct) => {
|
||||
const filled = Math.floor(pct / 10);
|
||||
return '█'.repeat(filled) + '░'.repeat(10 - filled);
|
||||
};
|
||||
|
||||
progressBars.push(`**Members:** ${server.member_count || 0}/${progression.progress.members.required} ${progression.progress.members.met ? '✅' : ''}\n\`${makeBar(progression.progress.members.percentage)}\` ${progression.progress.members.percentage}%`);
|
||||
progressBars.push(`**Days in Federation:** ${progression.progress.days.current}/${progression.progress.days.required} ${progression.progress.days.met ? '✅' : ''}\n\`${makeBar(progression.progress.days.percentage)}\` ${progression.progress.days.percentage}%`);
|
||||
progressBars.push(`**Reputation:** ${server.reputation_score || 0}/${progression.progress.reputation.required} ${progression.progress.reputation.met ? '✅' : ''}\n\`${makeBar(progression.progress.reputation.percentage)}\` ${progression.progress.reputation.percentage}%`);
|
||||
|
||||
embed.addFields({
|
||||
name: `Progress to ${progression.nextLevelInfo.emoji} ${progression.nextLevelInfo.name}`,
|
||||
value: progressBars.join('\n\n')
|
||||
});
|
||||
|
||||
if (progression.allMet) {
|
||||
embed.addFields({
|
||||
name: '🎉 Ready for Upgrade!',
|
||||
value: 'Your server meets all requirements for the next trust level! Upgrades are processed weekly.'
|
||||
});
|
||||
}
|
||||
} else {
|
||||
embed.addFields({
|
||||
name: '👑 Maximum Level',
|
||||
value: 'Your server has reached the highest trust level!'
|
||||
});
|
||||
}
|
||||
|
||||
embed.addFields(
|
||||
{ name: 'Statistics', value: [
|
||||
`**Reports Submitted:** ${server.reports_submitted || 0}`,
|
||||
`**False Positives:** ${server.false_positives || 0}`,
|
||||
`**Last Activity:** ${server.last_activity ? new Date(server.last_activity).toLocaleDateString() : 'N/A'}`
|
||||
].join('\n'), inline: true }
|
||||
);
|
||||
|
||||
embed.setTimestamp();
|
||||
return interaction.reply({ embeds: [embed] });
|
||||
}
|
||||
|
||||
if (subcommand === 'treaty') {
|
||||
const embed = new EmbedBuilder()
|
||||
.setColor(0x7c3aed)
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
const { EmbedBuilder } = require('discord.js');
|
||||
const { getTrustLevelInfo, shouldAutoAction } = require('../utils/trustLevels');
|
||||
|
||||
module.exports = {
|
||||
name: 'guildMemberAdd',
|
||||
|
|
@ -9,7 +10,7 @@ module.exports = {
|
|||
try {
|
||||
const { data: serverConfig } = await supabase
|
||||
.from('federation_servers')
|
||||
.select('tier, status')
|
||||
.select('tier, status, trust_level, reputation_score')
|
||||
.eq('guild_id', member.guild.id)
|
||||
.eq('status', 'approved')
|
||||
.maybeSingle();
|
||||
|
|
@ -25,10 +26,13 @@ module.exports = {
|
|||
|
||||
if (!ban) return;
|
||||
|
||||
const trustLevel = serverConfig.trust_level || 'bronze';
|
||||
const isPremium = serverConfig.tier === 'premium';
|
||||
const isCritical = ban.severity === 'critical';
|
||||
const trustInfo = getTrustLevelInfo(trustLevel);
|
||||
|
||||
if (!isPremium && !isCritical) {
|
||||
const actionDecision = shouldAutoAction(trustLevel, ban.severity, isPremium);
|
||||
|
||||
if (actionDecision.action === 'alert' && ban.severity !== 'critical') {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -42,6 +46,7 @@ module.exports = {
|
|||
.addFields(
|
||||
{ name: 'User', value: `${member.user.tag}\n\`${member.id}\``, inline: true },
|
||||
{ name: 'Severity', value: ban.severity.toUpperCase(), inline: true },
|
||||
{ name: 'Trust Level', value: `${trustInfo.emoji} ${trustInfo.name}`, inline: true },
|
||||
{ name: 'Reason', value: ban.reason || 'No reason provided' }
|
||||
)
|
||||
.setFooter({ text: 'AeThex Federation Protection' })
|
||||
|
|
@ -60,12 +65,12 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
|
||||
if (isCritical) {
|
||||
if (actionDecision.action === 'ban') {
|
||||
try {
|
||||
await member.ban({ reason: `[Federation] Global ban: ${ban.reason}` });
|
||||
await member.ban({ reason: `[Federation] Global ban (${ban.severity}): ${ban.reason}` });
|
||||
|
||||
alertEmbed.setTitle(`${severityEmojis[ban.severity]} Federation Auto-Ban: Critical Threat Removed`);
|
||||
alertEmbed.addFields({ name: 'Action Taken', value: 'User was automatically banned' });
|
||||
alertEmbed.setTitle(`${severityEmojis[ban.severity]} Federation Auto-Ban: Threat Removed`);
|
||||
alertEmbed.addFields({ name: 'Action Taken', value: `User was automatically banned (${trustInfo.name} Protection)` });
|
||||
|
||||
await supabase.from('federation_alerts').update({
|
||||
delivered: true,
|
||||
|
|
@ -77,10 +82,10 @@ module.exports = {
|
|||
console.error('[Federation] Failed to auto-ban:', banError.message);
|
||||
alertEmbed.addFields({ name: 'Action Required', value: 'Auto-ban failed. Please ban manually.' });
|
||||
}
|
||||
} else if (isPremium) {
|
||||
} else if (actionDecision.action === 'kick') {
|
||||
try {
|
||||
await member.kick(`[Federation] Global ban (${ban.severity} severity): ${ban.reason}`);
|
||||
alertEmbed.addFields({ name: 'Action Taken', value: 'User was automatically kicked (Premium Protection)' });
|
||||
alertEmbed.addFields({ name: 'Action Taken', value: `User was automatically kicked (${trustInfo.name} Protection)` });
|
||||
|
||||
await supabase.from('federation_alerts').update({
|
||||
delivered: true,
|
||||
|
|
@ -93,6 +98,11 @@ module.exports = {
|
|||
}
|
||||
}
|
||||
|
||||
await supabase
|
||||
.from('federation_servers')
|
||||
.update({ last_activity: new Date().toISOString() })
|
||||
.eq('guild_id', member.guild.id);
|
||||
|
||||
const owner = await member.guild.fetchOwner().catch(() => null);
|
||||
if (owner && ban.severity === 'critical') {
|
||||
try {
|
||||
|
|
|
|||
|
|
@ -422,6 +422,90 @@ function createWebServer(discordClient, supabase, options = {}) {
|
|||
}
|
||||
});
|
||||
|
||||
// Verification success endpoint - called by aethex.dev when verification completes
|
||||
app.post('/api/verify-success', async (req, res) => {
|
||||
if (!supabase) {
|
||||
return res.status(503).json({ error: 'Database not available' });
|
||||
}
|
||||
|
||||
const webhookSecret = process.env.DISCORD_BOT_WEBHOOK_SECRET;
|
||||
const providedSecret = req.headers['x-webhook-secret'] || req.body.secret;
|
||||
|
||||
if (webhookSecret && providedSecret !== webhookSecret) {
|
||||
console.log('[Verify-Success] Invalid webhook secret provided');
|
||||
return res.status(401).json({ error: 'Invalid webhook secret' });
|
||||
}
|
||||
|
||||
const { discord_id, user_id, username } = req.body;
|
||||
|
||||
if (!discord_id) {
|
||||
return res.status(400).json({ error: 'Missing discord_id' });
|
||||
}
|
||||
|
||||
console.log(`[Verify-Success] Received verification for Discord ID: ${discord_id}`);
|
||||
|
||||
try {
|
||||
// Update or create the discord link
|
||||
if (user_id) {
|
||||
await supabase.from('discord_links').upsert({
|
||||
discord_id,
|
||||
user_id,
|
||||
username: username || null,
|
||||
linked_at: new Date().toISOString()
|
||||
}, { onConflict: 'discord_id' });
|
||||
}
|
||||
|
||||
// Get server configs that have a verified role configured
|
||||
const { data: configs } = await supabase
|
||||
.from('server_config')
|
||||
.select('guild_id, verified_role_id')
|
||||
.not('verified_role_id', 'is', null);
|
||||
|
||||
let rolesAssigned = 0;
|
||||
const assignedIn = [];
|
||||
|
||||
// Assign verified role in all guilds where the user is a member
|
||||
for (const config of configs || []) {
|
||||
if (!config.verified_role_id) continue;
|
||||
|
||||
try {
|
||||
const guild = client.guilds.cache.get(config.guild_id);
|
||||
if (!guild) continue;
|
||||
|
||||
const member = await guild.members.fetch(discord_id).catch(() => null);
|
||||
if (!member) continue;
|
||||
|
||||
const role = guild.roles.cache.get(config.verified_role_id);
|
||||
if (!role) continue;
|
||||
|
||||
if (!member.roles.cache.has(role.id)) {
|
||||
await member.roles.add(role, 'Account verified via aethex.dev');
|
||||
rolesAssigned++;
|
||||
assignedIn.push(guild.name);
|
||||
console.log(`[Verify-Success] Assigned verified role to ${member.user.tag} in ${guild.name}`);
|
||||
}
|
||||
} catch (err) {
|
||||
console.error(`[Verify-Success] Failed to assign role in guild ${config.guild_id}:`, err.message);
|
||||
}
|
||||
}
|
||||
|
||||
// Clean up any pending verification codes
|
||||
await supabase.from('discord_verifications').delete().eq('discord_id', discord_id);
|
||||
|
||||
res.json({
|
||||
success: true,
|
||||
rolesAssigned,
|
||||
assignedIn,
|
||||
message: rolesAssigned > 0
|
||||
? `Verified role assigned in ${rolesAssigned} server(s)`
|
||||
: 'Verification recorded (user not found in any configured servers)'
|
||||
});
|
||||
} catch (error) {
|
||||
console.error('[Verify-Success] Error:', error);
|
||||
res.status(500).json({ error: 'Failed to process verification' });
|
||||
}
|
||||
});
|
||||
|
||||
app.get('/api/stats/:userId/:guildId', async (req, res) => {
|
||||
if (!supabase) {
|
||||
return res.status(503).json({ error: 'Database not available' });
|
||||
|
|
|
|||
195
aethex-bot/utils/trustLevels.js
Normal file
195
aethex-bot/utils/trustLevels.js
Normal file
|
|
@ -0,0 +1,195 @@
|
|||
const TRUST_LEVELS = {
|
||||
bronze: {
|
||||
name: 'Bronze',
|
||||
emoji: '🥉',
|
||||
color: 0xcd7f32,
|
||||
requirements: {
|
||||
minMembers: 0,
|
||||
minDays: 0,
|
||||
minReputationScore: 0
|
||||
},
|
||||
benefits: {
|
||||
autoAction: 'alert',
|
||||
severityThreshold: 'critical',
|
||||
directoryListing: true,
|
||||
featuredEligible: false,
|
||||
partnershipLimit: 3
|
||||
}
|
||||
},
|
||||
silver: {
|
||||
name: 'Silver',
|
||||
emoji: '🥈',
|
||||
color: 0xc0c0c0,
|
||||
requirements: {
|
||||
minMembers: 100,
|
||||
minDays: 30,
|
||||
minReputationScore: 50
|
||||
},
|
||||
benefits: {
|
||||
autoAction: 'kick',
|
||||
severityThreshold: 'medium',
|
||||
directoryListing: true,
|
||||
featuredEligible: false,
|
||||
partnershipLimit: 5
|
||||
}
|
||||
},
|
||||
gold: {
|
||||
name: 'Gold',
|
||||
emoji: '🥇',
|
||||
color: 0xffd700,
|
||||
requirements: {
|
||||
minMembers: 500,
|
||||
minDays: 90,
|
||||
minReputationScore: 200
|
||||
},
|
||||
benefits: {
|
||||
autoAction: 'ban',
|
||||
severityThreshold: 'medium',
|
||||
directoryListing: true,
|
||||
featuredEligible: true,
|
||||
partnershipLimit: 10
|
||||
}
|
||||
},
|
||||
platinum: {
|
||||
name: 'Platinum',
|
||||
emoji: '💎',
|
||||
color: 0xe5e4e2,
|
||||
requirements: {
|
||||
minMembers: 1000,
|
||||
minDays: 180,
|
||||
minReputationScore: 500
|
||||
},
|
||||
benefits: {
|
||||
autoAction: 'ban',
|
||||
severityThreshold: 'low',
|
||||
directoryListing: true,
|
||||
featuredEligible: true,
|
||||
partnershipLimit: 20
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const TRUST_ORDER = ['bronze', 'silver', 'gold', 'platinum'];
|
||||
|
||||
function calculateTrustLevel(serverData) {
|
||||
const memberCount = serverData.member_count || 0;
|
||||
const joinedAt = new Date(serverData.joined_federation_at || serverData.joined_at);
|
||||
const daysInFederation = Math.floor((Date.now() - joinedAt.getTime()) / (1000 * 60 * 60 * 24));
|
||||
const reputationScore = serverData.reputation_score || 0;
|
||||
|
||||
let qualifiedLevel = 'bronze';
|
||||
|
||||
for (const level of TRUST_ORDER) {
|
||||
const reqs = TRUST_LEVELS[level].requirements;
|
||||
if (memberCount >= reqs.minMembers &&
|
||||
daysInFederation >= reqs.minDays &&
|
||||
reputationScore >= reqs.minReputationScore) {
|
||||
qualifiedLevel = level;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return qualifiedLevel;
|
||||
}
|
||||
|
||||
function getTrustLevelInfo(level) {
|
||||
return TRUST_LEVELS[level] || TRUST_LEVELS.bronze;
|
||||
}
|
||||
|
||||
function getNextTrustLevel(currentLevel) {
|
||||
const currentIndex = TRUST_ORDER.indexOf(currentLevel);
|
||||
if (currentIndex === -1 || currentIndex >= TRUST_ORDER.length - 1) {
|
||||
return null;
|
||||
}
|
||||
return TRUST_ORDER[currentIndex + 1];
|
||||
}
|
||||
|
||||
function getProgressToNextLevel(serverData) {
|
||||
const currentLevel = serverData.trust_level || 'bronze';
|
||||
const nextLevel = getNextTrustLevel(currentLevel);
|
||||
|
||||
if (!nextLevel) {
|
||||
return { nextLevel: null, progress: {}, allMet: true };
|
||||
}
|
||||
|
||||
const reqs = TRUST_LEVELS[nextLevel].requirements;
|
||||
const memberCount = serverData.member_count || 0;
|
||||
const joinedAt = new Date(serverData.joined_federation_at || serverData.joined_at);
|
||||
const daysInFederation = Math.floor((Date.now() - joinedAt.getTime()) / (1000 * 60 * 60 * 24));
|
||||
const reputationScore = serverData.reputation_score || 0;
|
||||
|
||||
const progress = {
|
||||
members: {
|
||||
current: memberCount,
|
||||
required: reqs.minMembers,
|
||||
met: memberCount >= reqs.minMembers,
|
||||
percentage: Math.min(100, Math.floor((memberCount / reqs.minMembers) * 100)) || 0
|
||||
},
|
||||
days: {
|
||||
current: daysInFederation,
|
||||
required: reqs.minDays,
|
||||
met: daysInFederation >= reqs.minDays,
|
||||
percentage: Math.min(100, Math.floor((daysInFederation / reqs.minDays) * 100)) || 0
|
||||
},
|
||||
reputation: {
|
||||
current: reputationScore,
|
||||
required: reqs.minReputationScore,
|
||||
met: reputationScore >= reqs.minReputationScore,
|
||||
percentage: Math.min(100, Math.floor((reputationScore / reqs.minReputationScore) * 100)) || 0
|
||||
}
|
||||
};
|
||||
|
||||
const allMet = progress.members.met && progress.days.met && progress.reputation.met;
|
||||
|
||||
return { nextLevel, nextLevelInfo: TRUST_LEVELS[nextLevel], progress, allMet };
|
||||
}
|
||||
|
||||
function shouldAutoAction(trustLevel, banSeverity, isPremium) {
|
||||
const levelInfo = getTrustLevelInfo(trustLevel);
|
||||
const severityOrder = ['low', 'medium', 'high', 'critical'];
|
||||
|
||||
const banSeverityIndex = severityOrder.indexOf(banSeverity);
|
||||
const thresholdIndex = severityOrder.indexOf(levelInfo.benefits.severityThreshold);
|
||||
|
||||
if (banSeverityIndex < thresholdIndex) {
|
||||
if (banSeverity === 'critical') {
|
||||
return { action: 'ban', reason: 'critical_severity' };
|
||||
}
|
||||
return { action: 'alert', reason: 'below_threshold' };
|
||||
}
|
||||
|
||||
if (isPremium) {
|
||||
return { action: levelInfo.benefits.autoAction, reason: 'premium_protection' };
|
||||
}
|
||||
|
||||
if (banSeverity === 'critical') {
|
||||
return { action: 'ban', reason: 'critical_severity' };
|
||||
}
|
||||
|
||||
return { action: 'alert', reason: 'free_tier' };
|
||||
}
|
||||
|
||||
function calculateReputationChange(action, successful = true) {
|
||||
const reputationValues = {
|
||||
ban_report: successful ? 10 : -5,
|
||||
report_verified: 15,
|
||||
false_positive: -20,
|
||||
event_hosted: 25,
|
||||
partnership_formed: 10,
|
||||
monthly_activity: 5
|
||||
};
|
||||
|
||||
return reputationValues[action] || 0;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
TRUST_LEVELS,
|
||||
TRUST_ORDER,
|
||||
calculateTrustLevel,
|
||||
getTrustLevelInfo,
|
||||
getNextTrustLevel,
|
||||
getProgressToNextLevel,
|
||||
shouldAutoAction,
|
||||
calculateReputationChange
|
||||
};
|
||||
Loading…
Reference in a new issue