ClientX/_opt/ansi.js
2025-05-08 01:52:12 +00:00

121 lines
5.2 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import { MessageFlags } from 'discord-api-types/v10';
import { SlashCommandBuilder, PermissionFlagsBits } from 'discord.js';
import { CODES } from '../_src/ansiColors.js';
/**
* Combined ANSI utilities module
* - /ansi: preview nested [tag]…[/] ANSI coloring
* - /ansitheme: display full BG×FG theme chart
* Both commands are Admin-only.
*/
export const commands = [
// Preview arbitrary ANSI tags
{
data: new SlashCommandBuilder()
.setName('ansi')
.setDescription('Preview an ANSI-colored code block')
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
.setDMPermission(false)
.addStringOption(opt =>
opt
.setName('text')
.setDescription('Use [red]…[/], [bold,blue]…[/], escape \\[/]')
.setRequired(true)
)
.addBooleanOption(opt =>
opt
.setName('ephemeral')
.setDescription('Reply ephemerally?')
.setRequired(false)
),
async execute(interaction, client) {
const raw = interaction.options.getString('text', true);
const ephemeral = interaction.options.getBoolean('ephemeral') ?? true;
const colored = client.ansi`${raw}`;
const block = client.wrapAnsi(colored);
const opts = { content: block };
if (ephemeral) opts.flags = MessageFlags.Ephemeral;
await interaction.reply(opts);
}
},
// Show complete ANSI theme chart
{
data: new SlashCommandBuilder()
.setName('ansitheme')
.setDescription('Show ANSI color theme chart')
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator)
.setDMPermission(false)
.addBooleanOption(opt =>
opt
.setName('ephemeral')
.setDescription('Reply ephemerally?')
.setRequired(false)
),
async execute(interaction, client) {
const fgs = ['gray', 'red', 'green', 'yellow', 'blue', 'pink', 'cyan', 'white'];
const bgs = ['bgGray', 'bgOrange', 'bgBlue', 'bgTurquoise', 'bgFirefly', 'bgIndigo', 'bgLightGray', 'bgWhite'];
const pad = 8;
// Column header with padded labels (no colors) - shifted right by 1
const header = ' ' + fgs.map(f => f.padEnd(pad, ' ')).join('');
// Sample row with no background (padded cells)
let defaultRow = '';
for (const fg of fgs) {
const fgCode = CODES[fg];
const openNormal = `\u001b[${fgCode}m`;
const openBold = `\u001b[${fgCode};${CODES.bold}m`;
const openUnder = `\u001b[${fgCode};${CODES.underline}m`;
const cell = `${openNormal}sa\u001b[0m${openBold}mp\u001b[0m${openUnder}le\u001b[0m`;
defaultRow += ' ' + cell + ' ';
}
// Append default row label after one pad
defaultRow += 'default';
// Colored rows per background
const rows = [];
for (const bg of bgs) {
let row = '';
const bgCode = CODES[bg];
for (const fg of fgs) {
const fgCode = CODES[fg];
const openNormal = `\u001b[${bgCode};${fgCode}m`;
const openBold = `\u001b[${bgCode};${fgCode};${CODES.bold}m`;
const openUnder = `\u001b[${bgCode};${fgCode};${CODES.underline}m`;
const cell = `${openNormal}sa\u001b[0m${openBold}mp\u001b[0m${openUnder}le\u001b[0m`;
row += ' ' + cell + ' ';
}
// Append uncolored row label immediately after cell padding
row += bg;
rows.push(row);
}
// Determine ephemeral setting
const ephemeral = interaction.options.getBoolean('ephemeral') ?? true;
// Initial sample table (header + default row)
const sampleContent = [header, defaultRow].join('\n');
const optsSample = { content: client.wrapAnsi(sampleContent) };
if (ephemeral) optsSample.flags = MessageFlags.Ephemeral;
await interaction.reply(optsSample);
// Split colored rows into two tables
const half = Math.ceil(rows.length / 2);
const firstRows = rows.slice(0, half);
const secondRows = rows.slice(half);
// First colored table
const table1 = [header, ...firstRows].join('\n');
const opts1 = { content: client.wrapAnsi(table1) };
if (ephemeral) opts1.flags = MessageFlags.Ephemeral;
await interaction.followUp(opts1);
// Second colored table
if (secondRows.length > 0) {
const table2 = [header, ...secondRows].join('\n');
const opts2 = { content: client.wrapAnsi(table2) };
if (ephemeral) opts2.flags = MessageFlags.Ephemeral;
await interaction.followUp(opts2);
}
}
}
];
export async function init(client) {
client.logger.info('[module:ansi] Loaded ANSI utilities');
}