First commit for dscrdbt
This commit is contained in:
		
							
								
								
									
										50
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| # Dependencies | ||||
| node_modules/ | ||||
| package-lock.json | ||||
| yarn.lock | ||||
|  | ||||
| # Environment variables | ||||
| .env | ||||
| .env.local | ||||
| .env.*.local | ||||
|  | ||||
| # Build output | ||||
| dist/ | ||||
| build/ | ||||
| out/ | ||||
|  | ||||
| # Logs | ||||
| logs/ | ||||
| *.log | ||||
| npm-debug.log* | ||||
| yarn-debug.log* | ||||
| yarn-error.log* | ||||
|  | ||||
| # IDE and editor files | ||||
| .idea/ | ||||
| .vscode/ | ||||
| *.swp | ||||
| *.swo | ||||
| *.swn | ||||
| .DS_Store | ||||
|  | ||||
| # Runtime data | ||||
| pids/ | ||||
| *.pid | ||||
| *.seed | ||||
| *.pid.lock | ||||
|  | ||||
| # Optional npm cache directory | ||||
| .npm | ||||
|  | ||||
| # Optional eslint cache | ||||
| .eslintcache | ||||
|  | ||||
| # Optional REPL history | ||||
| .node_repl_history | ||||
|  | ||||
| # Output of 'npm pack' | ||||
| *.tgz | ||||
|  | ||||
| # Yarn Integrity file | ||||
| .yarn-integrity | ||||
							
								
								
									
										59
									
								
								commands/instagram/aipost.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								commands/instagram/aipost.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| const { SlashCommandBuilder, ActionRowBuilder, ModalBuilder, TextInputBuilder, TextInputStyle } = require('discord.js'); | ||||
| const fs = require('fs'); | ||||
| const path = require('path'); | ||||
|  | ||||
| // Configuration | ||||
| const ALLOWED_CHANNEL_ID = '1354951205180150004'; | ||||
|  | ||||
| module.exports = { | ||||
| 	data: new SlashCommandBuilder() | ||||
| 		.setName('aipost') | ||||
| 		.setDescription('Generate an Instagram post from a news article'), | ||||
|  | ||||
| 	async execute(interaction) { | ||||
| 		// Check if the command is used in the allowed channel | ||||
| 		if (interaction.channelId !== ALLOWED_CHANNEL_ID) { | ||||
| 			return await interaction.reply({ | ||||
| 				content: 'This command can only be used in the designated channel.', | ||||
| 				ephemeral: true, | ||||
| 			}); | ||||
| 		} | ||||
|  | ||||
| 		// Modal creation | ||||
| 		const modal = new ModalBuilder() | ||||
| 			.setCustomId('aipostModal') | ||||
| 			.setTitle('News Link'); | ||||
|  | ||||
| 		// Text input component | ||||
| 		const newsLinkInput = new TextInputBuilder() | ||||
| 			.setCustomId('newsLinkInput') | ||||
| 			.setLabel('Please provide the news article URL') | ||||
| 			.setStyle(TextInputStyle.Short) | ||||
| 			.setPlaceholder('https://example.com/news-article') | ||||
| 			.setRequired(true); | ||||
|  | ||||
| 		// Add text input to the modal | ||||
| 		const firstActionRow = new ActionRowBuilder().addComponents(newsLinkInput); | ||||
| 		modal.addComponents(firstActionRow); | ||||
| 		// Make the modal visible to the user | ||||
| 		await interaction.showModal(modal); | ||||
| 	}, | ||||
|  | ||||
| 	// Handle the modal submission | ||||
| 	async modalSubmit(interaction) { | ||||
| 		if (interaction.customId === 'aipostModal') { | ||||
| 			// Acknowledge the interaction | ||||
| 			await interaction.deferReply(); | ||||
|  | ||||
| 			// Placeholder for AI post generation | ||||
| 			await interaction.editReply({ | ||||
| 				content: 'Here is your generated Instagram post:\n\n' + | ||||
| 						'📸 *[Generated Image Placeholder]*\n\n' + | ||||
| 						'📝 **Generated Caption:**\n' + | ||||
| 						'Exciting news in tech! 🚀\n' + | ||||
| 						'Stay updated with the latest trends!\n\n' + | ||||
| 						'#tech #innovation #news #trending #instagram', | ||||
| 			}); | ||||
| 		} | ||||
| 	}, | ||||
| }; | ||||
							
								
								
									
										13
									
								
								commands/utility/ping.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								commands/utility/ping.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| const { SlashCommandBuilder, MessageFlags } = require('discord.js'); | ||||
|  | ||||
| module.exports = { | ||||
|     data: new SlashCommandBuilder() | ||||
|         .setName('ping') | ||||
|         .setDescription('Replies with Pong!'), | ||||
|     async execute(interaction) { | ||||
|         await interaction.reply({  | ||||
|             content: 'Secret Pong!',  | ||||
|             flags: MessageFlags.Ephemeral | ||||
|         }); | ||||
|     }, | ||||
| }; | ||||
							
								
								
									
										11
									
								
								commands/utility/server.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								commands/utility/server.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| const { SlashCommandBuilder } = require('discord.js'); | ||||
|  | ||||
| module.exports = { | ||||
|     data: new SlashCommandBuilder() | ||||
|         .setName('server') | ||||
|         .setDescription('Provides information about the server.'), | ||||
|     async execute(interaction) { | ||||
|         await interaction.reply(`This server is ${interaction.guild.name} and has  | ||||
|             ${interaction.guild.memberCount} members.`); | ||||
|     }, | ||||
| }; | ||||
							
								
								
									
										11
									
								
								commands/utility/user.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								commands/utility/user.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| const { SlashCommandBuilder } = require('discord.js'); | ||||
|  | ||||
| module.exports = { | ||||
|     data: new SlashCommandBuilder() | ||||
|         .setName('user') | ||||
|         .setDescription('Provides information about the user.'), | ||||
|     async execute(interaction) { | ||||
|         await interaction.reply(`This command was run by ${interaction.user.username},  | ||||
|             who joined on ${interaction.member.joinedAt}.`); | ||||
|     }, | ||||
| }; | ||||
							
								
								
									
										39
									
								
								deploy-commands.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										39
									
								
								deploy-commands.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,39 @@ | ||||
| const { REST, Routes } = require('discord.js'); | ||||
| require('dotenv').config(); | ||||
| const fs = require('fs'); | ||||
| const path = require('path'); | ||||
|  | ||||
| const commands = []; | ||||
| const foldersPath = path.join(__dirname, 'commands'); | ||||
| const commandFolders = fs.readdirSync(foldersPath); | ||||
|  | ||||
| for (const folder of commandFolders) { | ||||
|     const commandsPath = path.join(foldersPath, folder); | ||||
|     const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); | ||||
|     for (const file of commandFiles) { | ||||
|         const filePath = path.join(commandsPath, file); | ||||
|         const command = require(filePath); | ||||
|         if ('data' in command && 'execute' in command) { | ||||
|             commands.push(command.data.toJSON()) | ||||
|        } else { | ||||
|             console.log(`[WARNING] The command at ${filePath} is missing a required | ||||
|                 "data" or "execute" property.`); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| const rest = new REST().setToken(process.env.DISCORD_TOKEN); | ||||
|  | ||||
| (async () => { | ||||
|     try { | ||||
|         console.log(`Started refreshing ${commands.length} application (/) commands`); | ||||
|         const data = await rest.put( | ||||
|             Routes.applicationGuildCommands(process.env.clientId, process.env.guildId), | ||||
|             { body: commands },  | ||||
|         ); | ||||
|  | ||||
|         console.log(`Successfully reloaded ${data.length} application (/) commands.`); | ||||
|     } catch (error) { | ||||
|         console.error(error); | ||||
|     } | ||||
| })(); | ||||
							
								
								
									
										50
									
								
								eslint.config.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										50
									
								
								eslint.config.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,50 @@ | ||||
| const js = require('@eslint/js'); | ||||
|  | ||||
| module.exports = [ | ||||
| 	js.configs.recommended, | ||||
| 	{ | ||||
| 		languageOptions: { | ||||
| 			ecmaVersion: 'latest', | ||||
| 		}, | ||||
| 		rules: { | ||||
| 			'arrow-spacing': ['warn', { before: true, after: true }], | ||||
| 			'brace-style': ['error', 'stroustrup', { allowSingleLine: true }], | ||||
| 			'comma-dangle': ['error', 'always-multiline'], | ||||
| 			'comma-spacing': 'error', | ||||
| 			'comma-style': 'error', | ||||
| 			curly: ['error', 'multi-line', 'consistent'], | ||||
| 			'dot-location': ['error', 'property'], | ||||
| 			'handle-callback-err': 'off', | ||||
| 			indent: ['error', 'tab'], | ||||
| 			'keyword-spacing': 'error', | ||||
| 			'max-nested-callbacks': ['error', { max: 4 }], | ||||
| 			'max-statements-per-line': ['error', { max: 2 }], | ||||
| 			'no-console': 'off', | ||||
| 			'no-empty-function': 'error', | ||||
| 			'no-floating-decimal': 'error', | ||||
| 			'no-inline-comments': 'error', | ||||
| 			'no-lonely-if': 'error', | ||||
| 			'no-multi-spaces': 'error', | ||||
| 			'no-multiple-empty-lines': ['error', { max: 2, maxEOF: 1, maxBOF: 0 }], | ||||
| 			'no-shadow': ['error', { allow: ['err', 'resolve', 'reject'] }], | ||||
| 			'no-trailing-spaces': ['error'], | ||||
| 			'no-var': 'error', | ||||
| 			'no-undef': 'off', | ||||
| 			'object-curly-spacing': ['error', 'always'], | ||||
| 			'prefer-const': 'error', | ||||
| 			quotes: ['error', 'single'], | ||||
| 			semi: ['error', 'always'], | ||||
| 			'space-before-blocks': 'error', | ||||
| 			'space-before-function-paren': ['error', { | ||||
| 				anonymous: 'never', | ||||
| 				named: 'never', | ||||
| 				asyncArrow: 'always', | ||||
| 			}], | ||||
| 			'space-in-parens': 'error', | ||||
| 			'space-infix-ops': 'error', | ||||
| 			'space-unary-ops': 'error', | ||||
| 			'spaced-comment': 'error', | ||||
| 			yoda: 'error', | ||||
| 		}, | ||||
| 	}, | ||||
| ]; | ||||
							
								
								
									
										59
									
								
								events/interacionAiPost.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										59
									
								
								events/interacionAiPost.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,59 @@ | ||||
| const { Events } = require('discord.js'); | ||||
| const { generateCaption, generateImage, generatePostImage } = require('../utils/newsProcessor'); | ||||
|  | ||||
| module.exports = { | ||||
| 	name: Events.InteractionCreate, | ||||
| 	async execute(interaction) { | ||||
| 		if (!interaction.isModalSubmit()) return; | ||||
| 		if (interaction.customId !== 'aipostModal') return; | ||||
|  | ||||
| 		try { | ||||
| 			const newsLink = interaction.fields.getTextInputValue('newsLinkInput'); | ||||
| 			await interaction.deferReply(); | ||||
|  | ||||
| 			// Process the article with status updates | ||||
| 			// await interaction.editReply('📰 Reading article...'); | ||||
| 			// const articleData = await scrapeArticle(newsLink); | ||||
|  | ||||
| 			await interaction.editReply('✍️ Generating image copy...'); | ||||
| 			const imageText = await generateImage(newsLink); | ||||
|  | ||||
| 			await interaction.editReply('🎨 Creating AI image...'); | ||||
| 			const imageUrl = await generatePostImage(imageText); | ||||
|  | ||||
| 			await interaction.editReply('📝 Generating Instagram post...'); | ||||
| 			const postText = await generateCaption(newsLink); | ||||
|  | ||||
| 			// First message with the AI-generated image and its copy | ||||
| 			await interaction.editReply({ | ||||
| 				content: `📸 **Generated Image Copy:**\n${imageText}`, | ||||
| 				files: [imageUrl], | ||||
| 			}); | ||||
|  | ||||
| 			// Second message with the Instagram post copy | ||||
| 			await interaction.followUp({ | ||||
| 				content: `📱 **Generated Instagram Post:**\n${postText}`, | ||||
| 			}); | ||||
|  | ||||
| 		} | ||||
| 		catch (error) { | ||||
| 			console.error('Error in modal submission:', error); | ||||
| 			const errorMessage = error.message.includes('Failed to') | ||||
| 				? error.message | ||||
| 				: 'An unexpected error occurred while generating the post.'; | ||||
|  | ||||
| 			if (interaction.deferred) { | ||||
| 				await interaction.editReply({ | ||||
| 					content: `❌ ${errorMessage}\nPlease try again or use a different article.`, | ||||
| 					ephemeral: true, | ||||
| 				}); | ||||
| 			} | ||||
| 			else { | ||||
| 				await interaction.reply({ | ||||
| 					content: `❌ ${errorMessage}\nPlease try again or use a different article.`, | ||||
| 					ephemeral: true, | ||||
| 				}); | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| }; | ||||
							
								
								
									
										33
									
								
								events/interactionCreate.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								events/interactionCreate.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| const { Events } = require('discord.js'); | ||||
|  | ||||
| module.exports = { | ||||
| 	name: Events.InteractionCreate, | ||||
| 	async execute(interaction) { | ||||
| 		if (!interaction.isChatInputCommand()) return; | ||||
|  | ||||
| 		const command = interaction.client.commands.get(interaction.commandName); | ||||
| 		if (!command) { | ||||
| 			console.error(`No command matching ${interaction.commandName} was found.`); | ||||
| 			return; | ||||
| 		} | ||||
|  | ||||
| 		try { | ||||
| 			await command.execute(interaction); | ||||
| 		} | ||||
| 		catch (error) { | ||||
| 			console.error(error); | ||||
| 			if (interaction.replied || interaction.deferred) { | ||||
| 				await interaction.followUp({ | ||||
| 					content: 'There was an error while executing this command', | ||||
| 					ephemeral: true, | ||||
| 				}); | ||||
| 			} | ||||
| 			else { | ||||
| 				await interaction.reply({ | ||||
| 					content: 'There was an error while executing this command!', | ||||
| 					ephemeral: true, | ||||
| 				}); | ||||
| 			} | ||||
| 		} | ||||
| 	}, | ||||
| }; | ||||
							
								
								
									
										9
									
								
								events/ready.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								events/ready.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| const { Events } = require('discord.js'); | ||||
|  | ||||
| module.exports = { | ||||
|     name: Events.ClientReady, | ||||
|     once: true, | ||||
|     execute(client) { | ||||
|         console.log(`Ready! Logged in as ${client.user.tag}`); | ||||
|     }, | ||||
| }; | ||||
							
								
								
									
										47
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								index.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,47 @@ | ||||
| const { Client, GatewayIntentBits, Collection } = require('discord.js'); | ||||
| const fs = require('fs'); | ||||
| const path = require('path'); | ||||
| require('dotenv').config(); | ||||
|  | ||||
| const client = new Client({ | ||||
|   intents: [ | ||||
|     GatewayIntentBits.Guilds, | ||||
|     GatewayIntentBits.GuildMembers, | ||||
|     GatewayIntentBits.GuildMessages, | ||||
|     GatewayIntentBits.MessageContent, | ||||
|   ], | ||||
| }); | ||||
|  | ||||
| client.commands = new Collection(); | ||||
| const foldersPath = path.join(__dirname, 'commands'); | ||||
| const commandFolders = fs.readdirSync(foldersPath); | ||||
|  | ||||
| for (const folder of commandFolders) { | ||||
|   const commandsPath = path.join(foldersPath, folder); | ||||
|   const commandFiles = fs.readdirSync(commandsPath).filter(file => file.endsWith('.js')); | ||||
|   for (const file of commandFiles) { | ||||
|     const filePath = path.join(commandsPath, file); | ||||
|     const command = require(filePath); | ||||
|     if ('data' in command && 'execute' in command) { | ||||
|       client.commands.set(command.data.name, command); | ||||
|     } else { | ||||
|         console.log(`[WARNING] The command at ${filePath} is missing a required "data" or | ||||
|           "execute" property.`); | ||||
|     } | ||||
|   } | ||||
| } | ||||
|  | ||||
| const eventsPath = path.join(__dirname, 'events'); | ||||
| const eventFiles = fs.readdirSync(eventsPath).filter(file => file.endsWith('.js')); | ||||
|  | ||||
| for (const file of eventFiles) { | ||||
|   const filePath = path.join(eventsPath, file); | ||||
|   const event = require(filePath); | ||||
|   if (event.once) { | ||||
|     client.once(event.name, (...args) => event.execute(...args)); | ||||
|   } else { | ||||
|     client.on(event.name, (...args) => event.execute(...args)); | ||||
|   } | ||||
| } | ||||
|  | ||||
| client.login(process.env.DISCORD_TOKEN); | ||||
							
								
								
									
										21
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								package.json
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| { | ||||
|   "name": "dscrdbt", | ||||
|   "version": "1.0.0", | ||||
|   "main": "index.js", | ||||
|   "scripts": { | ||||
|     "start": "node src/index.js" | ||||
|   }, | ||||
|   "keywords": [], | ||||
|   "author": "", | ||||
|   "license": "ISC", | ||||
|   "description": "", | ||||
|   "dependencies": { | ||||
|     "discord.js": "^14.18.0", | ||||
|     "dotenv": "^16.4.7", | ||||
|     "openai": "^4.90.0" | ||||
|   }, | ||||
|   "devDependencies": { | ||||
|     "@eslint/js": "^9.23.0", | ||||
|     "eslint": "^9.23.0" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										80
									
								
								utils/newsProcessor.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								utils/newsProcessor.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| const OpenAI = require('openai'); | ||||
|  | ||||
| // Initialize OpenAI client | ||||
| const openai = new OpenAI({ | ||||
| 	apiKey: process.env.OPENAI_API_KEY, | ||||
| }); | ||||
|  | ||||
| // Function to generate Instagram caption | ||||
| async function generateCaption(articleData) { | ||||
| 	try { | ||||
| 		const prompt = `Act as a community manager for a technology and software community. Your job is to create content for the community's social media. | ||||
| 		Give me the copy for the Instagram post. | ||||
| 		Here is the information: | ||||
| 		URL: ${articleData} | ||||
| 		The copy for the Instagram post should be informative and educational, written in a friendly and approachable tone that invites conversation and interaction. | ||||
| 		Try to relate the information to technology and software. | ||||
| 		Make sure to include hashtags following Instagram and marketing best practices.`; | ||||
|  | ||||
| 		const completion = await openai.chat.completions.create({ | ||||
| 			model: 'gpt-3.5-turbo', | ||||
| 			messages: [{ role: 'user', content: prompt }], | ||||
| 			max_tokens: 500, | ||||
| 			temperature: 0.7, | ||||
| 		}); | ||||
|  | ||||
| 		return completion.choices[0].message.content.trim(); | ||||
| 	} | ||||
| 	catch (error) { | ||||
| 		throw new Error(`Failed to generate caption: ${error.message}`); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Function to generate image copy | ||||
| async function generateImage(articleData) { | ||||
| 	try { | ||||
| 		const prompt = `Act as a community manager for a technology and software community. Your job is to create content for the community's social media. | ||||
| 		Give me the copy for the image. | ||||
| 		Here is the information: | ||||
| 		URL: ${articleData} | ||||
| 		The copy for the image should be engaging and attention-grabbing to encourage people to click and read the post.`; | ||||
|  | ||||
| 		const completion = await openai.chat.completions.create({ | ||||
| 			model: 'gpt-3.5-turbo', | ||||
| 			messages: [{ role: 'user', content: prompt }], | ||||
| 			max_tokens: 100, | ||||
| 			temperature: 0.7, | ||||
| 		}); | ||||
|  | ||||
| 		return completion.choices[0].message.content.trim(); | ||||
| 	} | ||||
| 	catch (error) { | ||||
| 		throw new Error(`Failed to generate image copy: ${error.message}`); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| // Function to generate image using DALL-E | ||||
| async function generatePostImage(imageText) { | ||||
| 	try { | ||||
| 		const prompt = `Create a modern, professional social media image that represents: ${imageText}. The image should be suitable for a technology and software community, with a clean and engaging design.`; | ||||
|  | ||||
| 		const response = await openai.images.generate({ | ||||
| 			model: 'dall-e-3', | ||||
| 			prompt: prompt, | ||||
| 			n: 1, | ||||
| 			quality: 'standard', | ||||
| 			size: '1024x1024', | ||||
| 		}); | ||||
|  | ||||
| 		return response.data[0].url; | ||||
| 	} | ||||
| 	catch (error) { | ||||
| 		throw new Error(`Failed to generate image with DALL-E: ${error.message}`); | ||||
| 	} | ||||
| } | ||||
|  | ||||
| module.exports = { | ||||
| 	generateCaption, | ||||
| 	generateImage, | ||||
| 	generatePostImage, | ||||
| }; | ||||
		Reference in New Issue
	
	Block a user