Port a commands and utils modules from getting-started
This commit is contained in:
		
							parent
							
								
									50febb14bd
								
							
						
					
					
						commit
						494576d19c
					
				
					 3 changed files with 105 additions and 1 deletions
				
			
		
							
								
								
									
										14
									
								
								app.js
									
										
									
									
									
								
							
							
						
						
									
										14
									
								
								app.js
									
										
									
									
									
								
							|  | @ -1,5 +1,10 @@ | |||
| import 'dotenv/config'; | ||||
| import express from 'express'; | ||||
| import { verifyDiscordRequest } from './utils.js'; | ||||
| import { | ||||
|     TEST_COMMAND, | ||||
|     hasGuildCommands, | ||||
| } from './commands.js'; | ||||
| 
 | ||||
| // Create an express app
 | ||||
| const app = express(); | ||||
|  | @ -8,8 +13,15 @@ const app = express(); | |||
| const PORT = process.env.PORT || 3000; | ||||
| 
 | ||||
| // Parse request body and verifies incoming requests using discord-interactions package
 | ||||
| app.use(express.json({ verify: VerifyDiscordRequest(process.env.PUBLIC_KEY) })); | ||||
| app.use(express.json({ | ||||
|     verify: verifyDiscordRequest(process.env.PUBLIC_KEY) | ||||
| })); | ||||
| 
 | ||||
| app.listen(PORT, () => { | ||||
|     console.log('Listening on port', PORT); | ||||
| 
 | ||||
|     // Check if guild commands from commands.js are installed (if not, install them)
 | ||||
|     hasGuildCommands(process.env.APP_ID, process.env.GUILD_ID, [ | ||||
|         TEST_COMMAND, | ||||
|     ]); | ||||
| }); | ||||
|  |  | |||
							
								
								
									
										47
									
								
								commands.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										47
									
								
								commands.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,47 @@ | |||
| import { discordRequest } from './utils.js'; | ||||
| 
 | ||||
| export const TEST_COMMAND = { | ||||
|   name: 'test', | ||||
|   description: 'Basic guild command', | ||||
|   type: 1, | ||||
| }; | ||||
| 
 | ||||
| export async function hasGuildCommands(appId, guildId, commands) { | ||||
|     if (guildId === '' || appId === '') { | ||||
|         return; | ||||
|     } | ||||
| 
 | ||||
|     commands.forEach((c) => hasGuildCommand(appId, guildId, c)); | ||||
| } | ||||
| 
 | ||||
| async function hasGuildCommand(appId, guildId, command) { | ||||
|     const endpoint = `applications/${appId}/guilds/${guildId}/commands`; | ||||
| 
 | ||||
|     try { | ||||
|         const res = await discordRequest(endpoint, { method: 'GET' }); | ||||
|         const data = await res.json(); | ||||
| 
 | ||||
|         if (data) { | ||||
|             const installedNames = data.map((c) => c['name']); | ||||
|             // This is just matching on the name, so it's not good for updates
 | ||||
|             if (!installedNames.includes(command['name'])) { | ||||
|                 console.log(`Installing "${command['name']}"`); | ||||
|                 installGuildCommand(appId, guildId, command); | ||||
|             } else { | ||||
|                 console.log(`"${command['name']}" command already installed`); | ||||
|             } | ||||
|         } | ||||
|     } catch (err) { | ||||
|         console.error(err); | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export async function installGuildCommand(appId, guildId, command) { | ||||
|     const endpoint = `applications/${appId}/guilds/${guildId}/commands`; | ||||
| 
 | ||||
|     try { | ||||
|         await discordRequest(endpoint, { method: 'POST', body: command }); | ||||
|     } catch (err) { | ||||
|         console.error(err); | ||||
|     } | ||||
| } | ||||
							
								
								
									
										45
									
								
								utils.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								utils.js
									
										
									
									
									
										Normal file
									
								
							|  | @ -0,0 +1,45 @@ | |||
| import 'dotenv/config'; | ||||
| import fetch from 'node-fetch'; | ||||
| import { verifyKey } from 'discord-interactions'; | ||||
| 
 | ||||
| const baseURL = 'https://discord.com/api/v10/'; | ||||
| 
 | ||||
| export function verifyDiscordRequest(clientKey) { | ||||
|     return function (req, res, buf, encoding) { | ||||
|         const signature = req.get('X-Signature-Ed25519'); | ||||
|         const timestamp = req.get('X-Signature-Timestamp'); | ||||
| 
 | ||||
|         const isValidRequest = verifyKey(buf, signature, timestamp, clientKey); | ||||
|         if (!isValidRequest) { | ||||
|             res.status(401).send('Bad request signature'); | ||||
|             throw new Error('Bad request signature'); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
| 
 | ||||
| export async function discordRequest(endpoint, options) { | ||||
|     const url = baseURL + endpoint; | ||||
| 
 | ||||
|     if (options.body) { | ||||
|         options.body = JSON.stringify(options.body); | ||||
|     } | ||||
| 
 | ||||
|     // Use node-fetch to make requests
 | ||||
|     const res = await fetch(url, { | ||||
|         headers: { | ||||
|             'Authorization': `Bot ${process.env.DISCORD_TOKEN}`, | ||||
|             'Content-Type': 'application/json; charset=UTF-8', | ||||
|             'User-Agent': 'DiscordBot (https://github.com/erynofwales/thirteenth-friend, 1.0.0)', | ||||
|         }, | ||||
|         ...options | ||||
|     }); | ||||
| 
 | ||||
|     if (!res.ok) { | ||||
|         const data = await res.json(); | ||||
|         console.error('Request failed with status:', res.status); | ||||
|         throw new Error(JSON.stringify(data)); | ||||
|     } | ||||
| 
 | ||||
|     return res; | ||||
| } | ||||
| 
 | ||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue