diff --git a/fileRestructure.js b/fileRestructure.js new file mode 100644 index 0000000..bad5a7c --- /dev/null +++ b/fileRestructure.js @@ -0,0 +1,28 @@ +// Load environment variables from .env file +require("dotenv").config(); + +// Require discord.js library +const { Client } = require('discord.js'); +const { setupMessageHandler } = require('./messageHandler'); +const { setupReadyListener } = require('./readyListener'); + +// Create Discord client +const client = new Client({ + intents: ['Guilds', 'GuildMembers', 'GuildMessages', 'MessageContent', 'DirectMessages'] +}); + +// Event listener for when the bot is ready +client.once('ready', () => { + console.log('Logged in as ' + client.user.tag); +}); + +// // Require event handlers +// const readyHandler = require('./handlers/readyHandler.js'); +// const messageHandler = require('./handlers/messageHandler.js'); + +// Set up event listeners +setupReadyListener(client); +setupMessageHandler(client); + +// Log in to Discord with your bot token +client.login(process.env.DISCORD_TOKEN); \ No newline at end of file diff --git a/handlers/generateResponse.js b/handlers/generateResponse.js new file mode 100644 index 0000000..87d84fe --- /dev/null +++ b/handlers/generateResponse.js @@ -0,0 +1,43 @@ +const { OpenAI } = require('openai'); + +const openai = new OpenAI({ + apiKey: process.env.OPENAI_API_KEY +}); + +async function generateResponse(input) { + // Generate response using OpenAI + const response = await openai.chat.completions.create({ + model: 'gpt-4', + messages: [{ + role: 'system', + content: 'ChatGPT is a nice chatbot.' + }, + { + role: 'user', + content: input, + } + ] + }); + + // Extract the response message + let responseMessage = response.choices[0].message.content; + + // Check if the response message exceeds 2000 characters + if (responseMessage.length > 2000) { + const chunkSizeLimit = 2000; + const chunks = []; + + // Split the response message into chunks of 2000 characters + for (let i = 0; i < responseMessage.length; i += chunkSizeLimit) { + chunks.push(responseMessage.substring(i, i + chunkSizeLimit)); + } + + // Return the array of message chunks + return chunks; + } + + // Return the response message if it's within the character limit + return responseMessage; +} + +module.exports = { generateResponse }; diff --git a/handlers/messageCreate.js b/handlers/messageCreate.js new file mode 100644 index 0000000..354e981 --- /dev/null +++ b/handlers/messageCreate.js @@ -0,0 +1,149 @@ +const { PermissionsBitField, ChannelType } = require('discord.js'); +const frq = require('../utils/fetchRandomQuote'); +const { generateResponse } = require('./generateResponse'); + +// Define a map to store users who are temporarily muted +const mutedUsers = new Set(); + +// Event listener for incoming messages +const messageHandler = async (client,message) => { + try { + // Check if message is from a bot or not in a guild + if (message.author.bot || !message.guild) return; + + // Check if the user is temporarily muted + if (mutedUsers.has(message.author.id)) { + // Inform the user that they are muted + return message.reply('You are temporarily muted. Please wait before sending another message.') + .catch(error => { + console.error("Error sending muted message:", error); + }); + } + + // Check for specific keywords or patterns + if (message.content.toLowerCase().includes('inappropriate_keyword')) { + // Delete the message + await message.delete(); + // Log the deleted message + console.log(`Message containing inappropriate keyword deleted: ${message.content}`); + + // Mute the user for 5 minutes + mutedUsers.add(message.author.id); + setTimeout(() => { + mutedUsers.delete(message.author.id); + }, 5 * 60 * 1000); // 5 minutes + + return; // Stop processing further if message is deleted + } + + // Show typing indicator + message.channel.sendTyping(); + + // Check if the message starts with the bot's prefix + const prefix = '!'; + if (message.content.startsWith(prefix)) { + // If it's a command, extract the command and arguments from the message content + const args = message.content.slice(prefix.length).trim().split(/ +/); + const command = args.shift().toLowerCase(); + + // Process commands + switch (command) { + case 'ping': + message.reply('Pong!'); + break; + case 'hello': + message.reply('Hello!'); + break; + case 'help': + message.reply('Available commands: !ping, !hello, !quote, !calculate, !senddm, !createchannel'); + break; + case 'quote': + const quote = await frq.fetchRandomQuote(); + message.reply(quote ? `Here's a random quote for you: ${quote}` : 'Sorry, failed to fetch a quote at the moment.'); + break; + case 'calculate': + const expression = args.join(' '); + try { + const result = eval(expression); + message.reply(`Result: ${result}`); + } catch (error) { + message.reply('Invalid expression.'); + } + break; + case 'senddm': + const user = message.mentions.users.first(); + if (!user) { + message.reply('Please mention a user to send a direct message.'); + return; + } + if (!user.bot && user.id !== client.user.id) { + user.send(`${message.author.displayName}: ${message.content.replace(`!senddm <@${user.id}>`, "")}`) + .then(() => message.reply('Direct message sent successfully!')) + .catch((error) => message.reply('Failed to send direct message. Please make sure the user allows direct messages from server members.')); + } else { + message.reply('You cannot send direct messages to bots or to yourself.'); + } + break; + case 'createchannel': + // Check if the message is from a guild + if (!message.guild) { + message.reply("This command can only be used in a server (guild)."); + return; + } + // Check if the user has permission to manage channels + if (!message.member.permissions.has(PermissionsBitField.Flags.ManageChannels)) { + message.reply("You don't have permission to create channels."); + return; + } + + // Get the guild where you want to create the channel + const guild = message.guild; + + // Define the permissions for the channel + const permissions = [{ + id: guild.roles.everyone, // Set permissions for @everyone role + deny: [PermissionsBitField.Flags.ViewChannel] // Deny view permission + }]; + + // Create the channel with specified permissions + guild.channels.create({ + name: 'private-channel', + type: ChannelType.GuildText, + permissionOverwrites: permissions + }) + .then(channel => { + message.reply(`Private channel created: ${channel}`); + }) + .catch(error => { + console.error('Error creating channel:', error); + message.reply('Failed to create private channel.'); + }); + + break; + default: + // If the command is not recognized, do nothing + break; + } + } else { + // Process non-command messages using OpenAI + const response = await generateResponse(message.content); + + // Check if the response is an array of chunks + if (Array.isArray(response)) { + // Reply with each chunk separately + for (const chunk of response) { + await message.reply(chunk); + } + } else { + // Reply with the single response + await message.reply(response); + } + } + } catch (error) { + console.error("Error:", error.message); + message.reply("Error processing message. Please try again later."); + } +}; + +// exports.messageHandler = messageHandler; +module.exports = messageHandler; \ No newline at end of file diff --git a/index.js b/index.js index 7bb3191..4cf955d 100644 --- a/index.js +++ b/index.js @@ -1,151 +1,23 @@ // Load environment variables from .env file require("dotenv").config(); -// Require discord.js library +/// Require discord.js library const { Client } = require('discord.js'); -const { OpenAI } = require('openai'); -const fetch = require('node-fetch'); +const messageHandler = require("./handlers/messageCreate"); const client = new Client({ intents: ['Guilds', 'GuildMembers', 'GuildMessages', 'MessageContent', 'DirectMessages'] }); -// Prepare connection to the OpenAI API -const openai = new OpenAI({ - apiKey: process.env.OPENAI_API_KEY -}); - // Event listener for when the bot is ready client.once('ready', () => { console.log('Logged in as ' + client.user.tag); }); // Event listener for incoming messages -client.on('messageCreate', async function(message) { - try { - // Check if message is from a bot - if (message.author.bot) return; - - // Show typing indicator - message.channel.sendTyping(); - - // Check if the message starts with the bot's prefix - const prefix = '!'; - if (message.content.startsWith(prefix)) { - // If it's a command, extract the command and arguments from the message content - const args = message.content.slice(prefix.length).trim().split(/ +/); - const command = args.shift().toLowerCase(); - - // Process commands - switch (command) { - case 'ping': - message.reply('Pong!'); - break; - case 'hello': - message.reply('Hello!'); - break; - case 'help': - message.reply('Available commands: !ping, !hello, !quote, !calculate, !senddm'); - break; - case 'quote': - const quote = await fetchRandomQuote(); - message.reply(quote ? `Here's a random quote for you: ${quote}` : 'Sorry, failed to fetch a quote at the moment.'); - break; - case 'calculate': - const expression = args.join(' '); - try { - const result = eval(expression); - message.reply(`Result: ${result}`); - } catch (error) { - message.reply('Invalid expression.'); - } - break; - case 'senddm': - const user = message.mentions.users.first(); - if (!user) { - message.reply('Please mention a user to send a direct message.'); - return; - } - if (!user.bot && user.id !== client.user.id) { - user.send('This is a direct message from the bot!') - .then(() => message.reply('Direct message sent successfully!')) - .catch((error) => message.reply('Failed to send direct message. Please make sure the user allows direct messages from server members.')); - } else { - message.reply('You cannot send direct messages to bots or to yourself.'); - } - break; - default: - // If the command is not recognized, do nothing - break; - } - } else { - // Process non-command messages using OpenAI - const response = await generateResponse(message.content); - - // Check if the response is an array of chunks - if (Array.isArray(response)) { - // Reply with each chunk separately - for (const chunk of response) { - await message.reply(chunk); - } - } else { - // Reply with the single response - await message.reply(response); - } - } - } catch (error) { - console.error("Error:", error.message); - message.reply("Error processing message. Please try again later."); - } +client.on('messageCreate', message => { + messageHandler(client, message); }); -async function fetchRandomQuote() { - try { - const response = await fetch('https://api.quotable.io/random'); - const data = await response.json(); - return data.content; - } catch (error) { - console.error("Error fetching quote:", error.message); - return null; - } -} - -// Function to generate response using OpenAI -async function generateResponse(input) { - // Generate response using OpenAI - const response = await openai.chat.completions.create({ - model: 'gpt-4', - messages: [{ - role: 'system', - content: 'ChatGPT is a nice chatbot.' - }, - { - role: 'user', - content: input, - } - ] - }); - - // Extract the response message - let responseMessage = response.choices[0].message.content; - - // Check if the response message exceeds 2000 characters - if (responseMessage.length > 2000) { - const chunkSizeLimit = 2000; - const chunks = []; - - // Split the response message into chunks of 2000 characters - for (let i = 0; i < responseMessage.length; i += chunkSizeLimit) { - chunks.push(responseMessage.substring(i, i + chunkSizeLimit)); - } - - // Return the array of message chunks - return chunks; - } - - // Return the response message if it's within the character limit - return responseMessage; -} - // Log in to Discord with your bot token client.login(process.env.DISCORD_TOKEN); diff --git a/test.js b/old.js similarity index 100% rename from test.js rename to old.js diff --git a/utils/fetchRandomQuote.js b/utils/fetchRandomQuote.js new file mode 100644 index 0000000..ff616be --- /dev/null +++ b/utils/fetchRandomQuote.js @@ -0,0 +1,16 @@ +// utils/fetchRandomQuote.js + +const fetch = require('node-fetch'); + +async function fetchRandomQuote() { + try { + const response = await fetch('https://api.quotable.io/random'); + const data = await response.json(); + return data.content; + } catch (error) { + console.error("Error fetching quote:", error.message); + return null; + } +} + +exports.fetchRandomQuote = fetchRandomQuote; \ No newline at end of file