import dotenv from 'dotenv'; import * as util from './feature/utility.js'; import { REST, Routes } from 'discord.js'; import { Client, GatewayIntentBits } from 'discord.js'; import { EmbedBuilder } from 'discord.js'; import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js'; import { CronJob } from 'cron'; dotenv.config(); const TOKEN = process.env.TOKEN; const CLIENT_ID = process.env.CLI_ID; const commands = [ { name: 'ping', description: 'Pong! 으로 대답합니다.', }, { name: 'color', description: '아이디 색상을 변경합니다.', }, ]; // const rest = new REST({ version: '10' }).setToken(TOKEN); // try { // console.log('Started refreshing application (/) commands.'); // await rest.put(Routes.applicationCommands(CLIENT_ID), { body: commands }); // console.log('Successfully reloaded application (/) commands.'); // } catch (error) { // console.error(error); // } const roles = { '❤️': '1221079597962104872', '🧡': '1221091257665720360', '💛': '1221091363475423374', '💚': '1221080091371765812', '🩵': '1221091149796610088', '💙': '1221080047469858826', '💜': '1221095844288270387', '🔁': 'reset', }; let botMessageId = ''; const client = new Client({ intents: [ GatewayIntentBits.Guilds, GatewayIntentBits.GuildMessages, GatewayIntentBits.MessageContent, GatewayIntentBits.GuildMessageReactions, GatewayIntentBits.GuildMembers, // 역할을 부여하기 위해 필요 ] }); client.on('ready', () => { console.log(`Logged in as ${client.user.tag}!`); // 서머타임 여부에 따라 시간 설정 console.log(util.isDaylightSavingTime() ? '서머타임 적용 중' : '서머타임 미적용 중'); const openTime = util.isDaylightSavingTime() ? '30 22 * * *' : '30 23 * * *'; // 거래 시작 시간 const closeTime = util.isDaylightSavingTime() ? '0 5 * * *' : '0 6 * * *'; // 거래 종료 시간 // 거래 시작 const job1 = new CronJob(openTime, async () => { const channel = client.channels.cache.get(process.env.CH_FINANCE); if (channel) { await channel.send('미국 주식 시장이 열렸습니다.'); } }, null, true, 'Asia/Seoul'); // 거래 종료 const job2 = new CronJob(closeTime, async () => { const channel = client.channels.cache.get(process.env.CH_FINANCE); if (channel) { await channel.send('미국 주식 시장이 닫혔습니다.'); } }, null, true, 'Asia/Seoul'); job1.start(); job2.start(); }); client.on('interactionCreate', async interaction => { if (!interaction.isChatInputCommand()) return; if (interaction.commandName === 'ping') { await interaction.reply('Pong!'); } }); client.on('messageCreate', async message => { const urlPattern = /https?:\/\/(www\.)?(m\.)?gall\.dcinside\.com\/[^\s]*/g; const urls = message.content.match(urlPattern); if (urls && urls.length > 0) { const metaData = await util.getMetaData(urls[0]); // 첫 번째 URL의 메타데이터를 추출합니다. const embed = new EmbedBuilder() .setColor(0x0099FF) .setTitle(metaData.title) .setURL(urls[0]) // .setAuthor({ name: 'Some name', iconURL: 'https://i.imgur.com/AfFp7pu.png', url: 'https://discord.js.org' }) .setDescription(metaData.description) .setImage(metaData.image) .setThumbnail(metaData.image) // .setThumbnail('https://i.imgur.com/AfFp7pu.png') // .addFields( // { name: 'Regular field title', value: 'Some value here' }, // { name: '\u200B', value: '\u200B' }, // { name: 'Inline field title', value: 'Some value here', inline: true }, // { name: 'Inline field title', value: 'Some value here', inline: true }, // ) // .addFields({ name: '인라인 필드 제목', value: '값', inline: true }) // .setImage('https://i.imgur.com/AfFp7pu.png') // .setTimestamp() // .setFooter({ text: 'footer', iconURL: 'https://i.imgur.com/AfFp7pu.png' }); // if (metaData.image) { // console.log(metaData.image); // embed.setImage(metaData.image); // } message.channel.send({ embeds: [embed] }); } }); client.on('messageCreate', async message => { const badLang = ['권태웅', '태웅', '웅태']; if (badLang.some(word => message.content.includes(word))) { const str = `어허 나쁜말 쓰지 마세요`; message.channel.send(str); } }); client.on('interactionCreate', async interaction => { if (!interaction.isChatInputCommand()) return; if (interaction.commandName === 'color') { const sentMessage = await interaction.reply({ content: '아이디로 보여질 색상을 선택하세요.', fetchReply: true, // 메시지 ID 저장을 위해 reply 객체 반환 }); botMessageId = sentMessage.id; // 메시지 ID 저장 // 이모지 추가 (🔄 포함) await Promise.all( Object.keys(roles).map(async emoji => { await sentMessage.react(emoji); }) ); } }); // 리액션 추가 이벤트 처리 client.on('messageReactionAdd', async (reaction, user) => { if (reaction.message.partial) await reaction.message.fetch(); if (reaction.partial) await reaction.fetch(); if (user.bot) return; // 봇의 리액션 무시 if (reaction.message.author.bot) { await reaction.users.remove(user.id); // 리액션 바로 원복 const { emoji } = reaction; const member = reaction.message.guild.members.cache.get(user.id); const roleId = roles[emoji.name]; if (roleId === 'reset') { // 모든 색상 역할 제거를 병렬로 처리 const removeRolesPromises = Object.values(roles).filter(id => id !== 'reset' && member.roles.cache.has(id)).map(id => member.roles.remove(id)); await Promise.all(removeRolesPromises); } else if (roleId) { // 먼저 모든 색상 역할 제거 후 선택한 역할 추가 const allRoleIds = Object.values(roles).filter(id => id !== 'reset'); const removeRolesPromises = allRoleIds.filter(id => member.roles.cache.has(id)).map(id => member.roles.remove(id)); await Promise.all(removeRolesPromises); const role = reaction.message.guild.roles.cache.get(roleId); if (role) { await member.roles.add(role); console.log(`${user.username}에게 ${role.name} 역할이 부여되었습니다.`); } } } }); client.on('messageCreate', async message => { // '!역할확인' 명령어를 통해 역할과 ID 출력 if (message.content === '!역할확인') { const roles = message.guild.roles.cache.map(role => `${role.name}: ${role.id}`); console.log(roles.join('\n')); message.channel.send(`서버 역할 목록:\n${roles.join('\n')}`); } }); client.login(TOKEN);