Skip to content

Instantly share code, notes, and snippets.

@karlwilcox
Created December 16, 2022 15:32
Show Gist options
  • Save karlwilcox/1f63bafb9ecdba953003ea6465ba3b2d to your computer and use it in GitHub Desktop.
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)
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