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 'dotenv/config'; | ||||||
| import express from 'express'; | import express from 'express'; | ||||||
|  | import { verifyDiscordRequest } from './utils.js'; | ||||||
|  | import { | ||||||
|  |     TEST_COMMAND, | ||||||
|  |     hasGuildCommands, | ||||||
|  | } from './commands.js'; | ||||||
| 
 | 
 | ||||||
| // Create an express app
 | // Create an express app
 | ||||||
| const app = express(); | const app = express(); | ||||||
|  | @ -8,8 +13,15 @@ const app = express(); | ||||||
| const PORT = process.env.PORT || 3000; | const PORT = process.env.PORT || 3000; | ||||||
| 
 | 
 | ||||||
| // Parse request body and verifies incoming requests using discord-interactions package
 | // 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, () => { | app.listen(PORT, () => { | ||||||
|     console.log('Listening on port', 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