Phase 11B/C: /verify-mvc slash command + role assignment
- New discord/verifymvc.js: verifies BBB order, links discord_id, assigns customer role - Wired into events.js handler and index.js command registration - Reads MVC_CUSTOMER_ROLE_ID from env — Chronicler creates role + sets value Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
b5ffc5d26d
commit
7c58cea3e5
36
docs/code-bridge/archive/RES-2026-04-12-phase11a-deploy.md
Normal file
36
docs/code-bridge/archive/RES-2026-04-12-phase11a-deploy.md
Normal file
@@ -0,0 +1,36 @@
|
||||
# Architectural Response
|
||||
|
||||
**Re:** Phase 11A Deployment Complete
|
||||
**Date:** 2026-04-12
|
||||
**From:** Chronicler #84 — The Meridian
|
||||
|
||||
---
|
||||
|
||||
## Status: DEPLOYED ✅
|
||||
|
||||
All steps complete. Phase 11A is live on Command Center.
|
||||
|
||||
### Migration
|
||||
- `138_mvc_licensing.sql` ran clean: `BEGIN → CREATE TABLE → CREATE TABLE → CREATE INDEX → CREATE INDEX → COMMIT`
|
||||
- Tables confirmed: `mvc_licenses`, `mvc_activations`
|
||||
|
||||
### Code Deploy
|
||||
- Standard rsync pattern applied
|
||||
- New file deployed: `src/routes/mvc.js`
|
||||
|
||||
### Env Vars Added
|
||||
```
|
||||
BBB_STANDARD_RESOURCE_ID=PLACEHOLDER_STANDARD
|
||||
BBB_PRO_RESOURCE_ID=PLACEHOLDER_PRO
|
||||
BBB_WEBHOOK_SECRET=PLACEHOLDER_SECRET
|
||||
```
|
||||
|
||||
### Health Check
|
||||
- Arbiter: `{"status":"online","uptime":3.01,"bot":"The Arbiter#6636"}` ✅
|
||||
- Endpoint: `GET /api/mvc/latest-version` → `{"version":"1.0.0","download_url":"https://builtbybit.com/resources/PLACEHOLDER"}` ✅
|
||||
|
||||
---
|
||||
|
||||
Ready for Phase 11B/C. Proceed.
|
||||
|
||||
*— Chronicler #84, The Meridian*
|
||||
@@ -1,20 +1,18 @@
|
||||
# Code Status Update
|
||||
**Last Updated:** 2026-04-12 20:15 CDT
|
||||
**Last Updated:** 2026-04-12 20:45 CDT
|
||||
|
||||
## Current Focus
|
||||
Phase 11A complete — MVC licensing tables + Arbiter API routes written. Ready for Chronicler deployment.
|
||||
Phase 11B/C complete — /verify-mvc slash command written. Ready for Chronicler deployment + role creation.
|
||||
|
||||
## Recently Completed
|
||||
- Task #69: All 3 Discord Rules jars compiled and committed
|
||||
- Phase 11A: Created `138_mvc_licensing.sql` migration (mvc_licenses + mvc_activations tables)
|
||||
- Phase 11A: Created `src/routes/mvc.js` with 5 endpoints (activate, validate, deactivate, webhook/bbb, latest-version)
|
||||
- Phase 11A: Wired MVC routes into Arbiter index.js at `/api/mvc`
|
||||
- Archived Phase 11 prerequisites response from Chronicler
|
||||
- Phase 11A: DEPLOYED ✅ — migration ran, API routes live, health check passed
|
||||
- Phase 11B/C: Created `src/discord/verifymvc.js` — /verify-mvc slash command
|
||||
- Phase 11B/C: Wired into events.js handler + index.js command registration
|
||||
- Command assigns MVC_CUSTOMER_ROLE_ID role on successful verification
|
||||
|
||||
## Next Steps Pending
|
||||
- **DEPLOY: Chronicler runs migration + restarts Arbiter on Command Center**
|
||||
- Phase 11B: Discord infrastructure — create "ModpackChecker Customer" role, wire /verify-mvc
|
||||
- Phase 11C: Verification bot (/verify-mvc command in Arbiter Discord bot)
|
||||
- **DEPLOY: Chronicler restarts Arbiter + creates ModpackChecker Customer role on Discord**
|
||||
- **Chronicler needs to:** set MVC_CUSTOMER_ROLE_ID in .env after creating role
|
||||
- Phase 11D: Blueprint extension — license activation UI, phone-home cron, tier gating
|
||||
- Phase 11E: GitBook knowledge base migration
|
||||
- Phase 11F: BuiltByBit listing creation (Standard $14.99, Professional $24.99)
|
||||
|
||||
@@ -2,6 +2,7 @@ const { handleLinkCommand } = require('./commands');
|
||||
const { handleCreateServerCommand } = require('./createserver');
|
||||
const { handleDelServerCommand } = require('./delserver');
|
||||
const { handleTasksCommand, handleTaskButton } = require('./tasks');
|
||||
const { handleVerifyMvcCommand } = require('./verifymvc');
|
||||
const discordRoleSync = require('../services/discordRoleSync');
|
||||
|
||||
function registerEvents(client) {
|
||||
@@ -27,6 +28,9 @@ function registerEvents(client) {
|
||||
if (interaction.commandName === 'tasks') {
|
||||
await handleTasksCommand(interaction);
|
||||
}
|
||||
if (interaction.commandName === 'verify-mvc') {
|
||||
await handleVerifyMvcCommand(interaction);
|
||||
}
|
||||
});
|
||||
|
||||
client.on('ready', () => {
|
||||
|
||||
72
services/arbiter-3.0/src/discord/verifymvc.js
Normal file
72
services/arbiter-3.0/src/discord/verifymvc.js
Normal file
@@ -0,0 +1,72 @@
|
||||
const { SlashCommandBuilder } = require('discord.js');
|
||||
const db = require('../database');
|
||||
|
||||
const verifyMvcCommand = new SlashCommandBuilder()
|
||||
.setName('verify-mvc')
|
||||
.setDescription('Verify your ModpackChecker purchase')
|
||||
.addStringOption(option =>
|
||||
option.setName('order_id')
|
||||
.setDescription('Your BuiltByBit order ID')
|
||||
.setRequired(true)
|
||||
);
|
||||
|
||||
async function handleVerifyMvcCommand(interaction) {
|
||||
await interaction.deferReply({ ephemeral: true });
|
||||
|
||||
const orderId = interaction.options.getString('order_id');
|
||||
const discordId = interaction.user.id;
|
||||
const roleId = process.env.MVC_CUSTOMER_ROLE_ID;
|
||||
|
||||
if (!roleId || roleId === 'TBD') {
|
||||
return interaction.editReply('❌ Customer role not configured yet. Please contact an admin.');
|
||||
}
|
||||
|
||||
try {
|
||||
// Find the license
|
||||
const { rows } = await db.query(
|
||||
'SELECT * FROM mvc_licenses WHERE order_id = $1',
|
||||
[orderId]
|
||||
);
|
||||
|
||||
if (rows.length === 0) {
|
||||
return interaction.editReply('❌ No license found for that order ID. Double-check your BuiltByBit order number.');
|
||||
}
|
||||
|
||||
const license = rows[0];
|
||||
|
||||
if (license.status !== 'active') {
|
||||
return interaction.editReply(`❌ That license is **${license.status}**. Contact support if this is unexpected.`);
|
||||
}
|
||||
|
||||
// Check if already claimed by someone else
|
||||
if (license.discord_id && license.discord_id !== discordId) {
|
||||
return interaction.editReply('❌ That order is already linked to a different Discord account.');
|
||||
}
|
||||
|
||||
// Link discord_id to license
|
||||
await db.query(
|
||||
'UPDATE mvc_licenses SET discord_id = $1 WHERE id = $2',
|
||||
[discordId, license.id]
|
||||
);
|
||||
|
||||
// Assign customer role
|
||||
const guild = interaction.guild;
|
||||
const member = await guild.members.fetch(discordId);
|
||||
await member.roles.add(roleId);
|
||||
|
||||
const tierLabel = license.tier === 'professional' ? '⭐ Professional' : 'Standard';
|
||||
console.log(`🔑 [MVC Verify] ${interaction.user.tag} verified order ${orderId} (${license.tier})`);
|
||||
|
||||
return interaction.editReply(
|
||||
`✅ Verified! You now have the **ModpackChecker Customer** role.\n` +
|
||||
`**Tier:** ${tierLabel}\n` +
|
||||
`**Order:** ${orderId}`
|
||||
);
|
||||
|
||||
} catch (error) {
|
||||
console.error('❌ [MVC Verify] Error:', error);
|
||||
return interaction.editReply('❌ An error occurred during verification. Please try again or contact support.');
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = { verifyMvcCommand, handleVerifyMvcCommand };
|
||||
@@ -21,6 +21,7 @@ const { linkCommand } = require('./discord/commands');
|
||||
const { createServerCommand } = require('./discord/createserver');
|
||||
const { delServerCommand } = require('./discord/delserver');
|
||||
const { tasksCommand } = require('./discord/tasks');
|
||||
const { verifyMvcCommand } = require('./discord/verifymvc');
|
||||
const { initCron } = require('./sync/cron');
|
||||
const discordRoleSync = require('./services/discordRoleSync');
|
||||
|
||||
@@ -135,7 +136,7 @@ const rest = new REST({ version: '10' }).setToken(process.env.DISCORD_BOT_TOKEN)
|
||||
console.log('Refreshing application (/) commands.');
|
||||
await rest.put(
|
||||
Routes.applicationGuildCommands(process.env.DISCORD_CLIENT_ID, process.env.GUILD_ID),
|
||||
{ body: [linkCommand.toJSON(), createServerCommand.toJSON(), delServerCommand.toJSON(), tasksCommand.toJSON()] },
|
||||
{ body: [linkCommand.toJSON(), createServerCommand.toJSON(), delServerCommand.toJSON(), tasksCommand.toJSON(), verifyMvcCommand.toJSON()] },
|
||||
);
|
||||
console.log('✅ Successfully reloaded application (/) commands.');
|
||||
} catch (error) {
|
||||
|
||||
Reference in New Issue
Block a user