AeThex-Bot-Master/aethex-bot/commands/poll.js
sirpiglr 7ca85f433a Add persistent storage for federation mappings and tickets
Integrates Supabase for persistent storage of federation mappings and active tickets, along with adding new commands for announcements, audit logs, and polls.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: aed2e46d-25bb-4b73-81a1-bb9e8437c261
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 110a0afc-77c3-48ac-afca-8e969438dafc
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/3bdfff67-975a-46ad-9845-fbb6b4a4c4b5/aed2e46d-25bb-4b73-81a1-bb9e8437c261/hHBt1No
Replit-Helium-Checkpoint-Created: true
2025-12-08 03:38:13 +00:00

91 lines
2.9 KiB
JavaScript
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

const { SlashCommandBuilder, EmbedBuilder } = require('discord.js');
const POLL_EMOJIS = ['1⃣', '2⃣', '3⃣', '4⃣', '5⃣', '6⃣', '7⃣', '8⃣', '9⃣', '🔟'];
module.exports = {
data: new SlashCommandBuilder()
.setName('poll')
.setDescription('Create a community poll')
.addStringOption(option =>
option.setName('question')
.setDescription('The poll question')
.setRequired(true)
.setMaxLength(256)
)
.addStringOption(option =>
option.setName('options')
.setDescription('Poll options separated by | (e.g., "Yes | No | Maybe")')
.setRequired(true)
.setMaxLength(1000)
)
.addIntegerOption(option =>
option.setName('duration')
.setDescription('Poll duration in hours (default: 24)')
.setRequired(false)
.setMinValue(1)
.setMaxValue(168)
),
async execute(interaction, supabase, client) {
const question = interaction.options.getString('question');
const optionsRaw = interaction.options.getString('options');
const duration = interaction.options.getInteger('duration') || 24;
const options = optionsRaw.split('|').map(o => o.trim()).filter(o => o.length > 0);
if (options.length < 2) {
return interaction.reply({
content: 'Please provide at least 2 options separated by |',
ephemeral: true
});
}
if (options.length > 10) {
return interaction.reply({
content: 'Maximum 10 options allowed',
ephemeral: true
});
}
const endsAt = new Date(Date.now() + duration * 60 * 60 * 1000);
const optionsText = options.map((opt, i) => `${POLL_EMOJIS[i]} ${opt}`).join('\n');
const embed = new EmbedBuilder()
.setColor(0x7c3aed)
.setTitle(`📊 ${question}`)
.setDescription(optionsText)
.addFields(
{ name: 'Created by', value: interaction.user.tag, inline: true },
{ name: 'Ends', value: `<t:${Math.floor(endsAt.getTime() / 1000)}:R>`, inline: true },
{ name: 'Options', value: `${options.length}`, inline: true }
)
.setFooter({ text: 'React to vote!' })
.setTimestamp();
const message = await interaction.reply({ embeds: [embed], fetchReply: true });
for (let i = 0; i < options.length; i++) {
try {
await message.react(POLL_EMOJIS[i]);
} catch (e) {
console.error('Failed to add reaction:', e.message);
}
}
if (supabase) {
try {
await supabase.from('polls').insert({
message_id: message.id,
channel_id: interaction.channelId,
guild_id: interaction.guildId,
question: question,
options: JSON.stringify(options),
created_by: interaction.user.id,
ends_at: endsAt.toISOString(),
});
} catch (e) {
console.warn('Failed to save poll:', e.message);
}
}
},
};