Created
December 16, 2022 15:32
-
-
Save karlwilcox/1f63bafb9ecdba953003ea6465ba3b2d to your computer and use it in GitHub Desktop.
Discord bot with Github issues integration (credentials in separate .env file, replace <STUFF> with your own data)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const Discord = require('discord.js'); | |
const fetch = require('node-fetch'); | |
require('dotenv').config(); | |
const querystring = require('querystring'); | |
const client = new Discord.Client(); | |
const prefix = '!'; | |
const { exec } = require("child_process"); | |
const helpInfo = { | |
tweet: "*!tweet <message>*\nPost message to the DrawShield Twitter account (super-admin role only).", | |
todo: "*!todo <issue>*\nRaise an issue on the GitHub project page (super-admin role only).", | |
issue: "*!issue\nlist 10 most recent issues, !issue <num> for details, !issue (open|closed) to restrict." | |
}; | |
const trim = (str, max) => (str.length > max ? `${str.slice(0, max - 3)}...` : str); | |
const firstLine = (str) => (str.indexOf("\n") > 10 ? str.slice(0, str.indexOf("\n") ) : trim(str, 80)); | |
client.once('ready', () => { | |
console.log('Ready!'); | |
}); | |
client.on('message', async message => { | |
if (!message.content.startsWith(prefix) || message.author.bot) return; | |
const args = message.content.slice(prefix.length).trim().split(/ +/); | |
const command = args.shift().toLowerCase(); | |
var thisRole = ''; | |
if (command.startsWith('issue')) { | |
const arg = args.join(' '); | |
var limit = 10; | |
var reply = ''; | |
if (!args.length) { // get the 10 latest issues | |
const issueList =await fetch('https://api.github.com/repos/<GITHUB-USER-ID>/<GITHUB-REPO-NAME>/issues').then(response => response.json()); | |
if (issueList.length < limit) limit = issueList.length; | |
for (var i = 0; i < limit; i++) { | |
const issueItem = issueList[i]; | |
reply += `${issueItem.number}: ${issueItem.title} (${issueItem.state})\n`; | |
} | |
} else if (arg.startsWith('op')) { | |
const issueList =await fetch('https://api.github.com/repos/<GITHUB-USER-ID>/<GITHUB-REPO-NAME>/issues?status=open').then(response => response.json()); | |
if (issueList.length < limit) limit = issueList.length; | |
for (var i = 0; i < limit; i++) { | |
const issueItem = issueList[i]; | |
reply += `${issueItem.number}: ${issueItem.title} on ${issueItem.created_at}\n`; | |
} | |
} else if (arg.startsWith('cl')) { | |
const issueList =await fetch('https://api.github.com/repos/<GITHUB-USER-ID>/<GITHUB-REPO-NAME>/issues?status=closed').then(response => response.json()); | |
if (issueList.length < limit) limit = issueList.length; | |
for (var i = 0; i < limit; i++) { | |
const issueItem = issueList[i]; | |
reply += `${issueItem.number}: ${issueItem.title} on ${issueItem.updated_at}\n`; | |
} | |
} else { | |
const issue =await fetch('https://api.github.com/repos/<GITHUB-USER-ID>/<GITHUB-REPO-NAME>/issues/' + arg).then(response => response.json()); | |
if (issue === undefined || issue.hasOwnProperty('message')) { | |
reply = 'Sorry, issue not found'; | |
} else { | |
var body = ''; | |
if (issue.body !== undefined && issue.body.length) body = trim(issue.body, 1024); | |
reply += | |
`Issue no: ${arg} ${issue.title} | |
Raised: ${issue.created_at}, Status: ${issue.state} | |
Details: ${body} | |
URL: ${issue.html_url}`; | |
} | |
} | |
if (!reply.length) reply = "Sorry, something went wrong"; | |
return message.channel.send(reply); | |
} else if (command === 'todo') { | |
if((message.member.roles.cache.find(r => r.name === "<DISCORD-ROLE-NAME>")) { // Change this to match your own roles | |
var body = message.cleanContent; | |
if (message.reference) { | |
let refID = message.reference.messageID; | |
let refMessage = await message.channel.messages.fetch(refID); | |
body += "\n" + refMessage.cleanContent; | |
} | |
let title = firstLine(body); | |
console.log('Raise issue: ' + body); | |
const content = { 'body': body, 'title': title }; | |
const newIssue = await fetch('https://api.github.com/repos/<GITHUB-USER-ID>/<GITHUB-REPO-NAME>/issues', { | |
method: 'POST', | |
body: JSON.stringify(content), | |
headers: { 'Authorization': 'token ' + process.env.GITPAS, | |
"Accept": "application/vnd.github.v3+json" } | |
}).then(res => res.json()); | |
if ( newIssue === undefined || newIssue.hasOwnProperty('message')) { | |
// console.log(newIssue); | |
return message.channel.send( | |
'Sorry, an error occured but the todo has been logged ' | |
+ newIssue.message); | |
} else { | |
// console.log(newIssue); | |
return message.channel.send('Thank you, the issue raised with ID ' | |
+ newIssue.number + ' ' + newIssue.html_url ); | |
} | |
} else { | |
return message.channel.send("Please post your ideas in the suggestion channel for discussion"); | |
} | |
} else if (command === 'help') { | |
helpText = "Admin Commands are role, tweet, todo, issue. Use !help <command> for details."; | |
helpItem = args.join(' '); | |
if (helpItem.startsWith('rol')) { | |
helpText = helpInfo.role; | |
} else if (helpItem.startsWith('iss')) { | |
helpText = helpInfo.issue; | |
} else if (helpItem.startsWith('tod')) { | |
helpText = helpInfo.todo; | |
} else if (helpItem.startsWith('twe')) { | |
helpText = helpInfo.tweet; | |
} else if (helpItem.length) { // don't respond to unknown item (might be other bot) | |
helpText = null; | |
} | |
if (helpText !== null) { | |
return message.channel.send(helpText); | |
} | |
return; | |
} | |
}); | |
client.login(process.env.DISCORDTOKEN); | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment