166 lines
4.7 KiB
JavaScript
166 lines
4.7 KiB
JavaScript
const fs = require("fs");
|
|
const Discord = require("discord.js");
|
|
const {prefix, token, reference_min_num} = require('./config.json');
|
|
const reference_min_number = reference_min_num || 0
|
|
const request = require("request");
|
|
const {sendGitHubEmbedReply} = require("./common.js");
|
|
|
|
// Error if missing configuration
|
|
if (!token || !prefix) {
|
|
console.log("Error: Missing configurations! See config.json.example.");
|
|
return;
|
|
}
|
|
|
|
const client = new Discord.Client();
|
|
client.commands = new Discord.Collection();
|
|
|
|
client.pages = new Discord.Collection();
|
|
client.pageControls = {
|
|
prev: "⬅",
|
|
next: "➡",
|
|
exit: "🇽"
|
|
};
|
|
|
|
// Find term function
|
|
client.searchText = function(text, term) {
|
|
let results = [];
|
|
const lines = text.split("\n");
|
|
for (let i = 0; i < lines.length; i++) {
|
|
const l = lines[i];
|
|
if (l.toLowerCase().includes(term.toLowerCase())) results.push([i + 1, l]);
|
|
}
|
|
return results;
|
|
}
|
|
|
|
// Load commands
|
|
const commandFiles = fs.readdirSync("./commands").filter(file => file.endsWith(".js"));
|
|
for (const file of commandFiles) {
|
|
let command = require(`./commands/${file}`);
|
|
if (typeof(command) === "function") command = command(client); // Pass client if needed
|
|
client.commands.set(command.name, command);
|
|
|
|
if (command.page) client.pages.set(command.name, command.page);
|
|
}
|
|
|
|
let mentionString = "";
|
|
|
|
client.once("ready", () => {
|
|
console.log(`Logged in as ${client.user.tag}.`);
|
|
mentionString = `<@!${client.user.id}>`
|
|
|
|
client.user.setActivity("no one.", {type: "LISTENING"});
|
|
});
|
|
|
|
client.on("message", async message => {
|
|
// Pingsock >:/
|
|
if (message.content === mentionString) {
|
|
const pingsock = client.guilds.cache.get("531580497789190145").emojis.cache.find(emoji => emoji.name === "pingsock");
|
|
message.channel.send(`${pingsock}`);
|
|
return;
|
|
}
|
|
|
|
if (message.author.bot) return;
|
|
|
|
try {
|
|
let p;
|
|
if (message.content.startsWith(p = prefix) || message.content.startsWith(p = mentionString)) {
|
|
const args = message.content.slice(p.length).trim().split(/ +/g);
|
|
const commandName = args.shift().toLowerCase();
|
|
|
|
const command = client.commands.get(commandName) ||
|
|
client.commands.find(cmd => cmd.aliases && cmd.aliases.includes(commandName));
|
|
if (command) {
|
|
command.execute(message, args, client);
|
|
return;
|
|
}
|
|
}
|
|
// No valid command, look for #d+, referencing pulls or issues
|
|
for (const match of message.content.matchAll(/(^|\s+)#(\d+)/g)) {
|
|
let count = 0;
|
|
for (let i = 0; i < match.index; i++) {
|
|
if (message.content.charAt(i) === "`") {
|
|
count++;
|
|
}
|
|
}
|
|
// even number of code block starters => all code blocks have been closed
|
|
// no code block terminator after #id => code block containing id hasn't been closed
|
|
let not_inside_codeblock = (count % 2 === 0) || (message.content.indexOf("`", match.index + match[0].length) < 0);
|
|
if (not_inside_codeblock) {
|
|
const number = parseInt(match[2]);
|
|
if (number >= reference_min_number) {
|
|
request({
|
|
url: "https://api.github.com/repos/minetest/minetest/issues/" + number,
|
|
json: true,
|
|
headers: {
|
|
"User-Agent": "Minetest Bot"
|
|
}
|
|
}, function(err, res, pkg) {
|
|
if (pkg.url) {
|
|
sendGitHubEmbedReply(message, pkg);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
}
|
|
} catch (error) {
|
|
console.error(error);
|
|
message.channel.send(":warning: Yikes, something broke.");
|
|
}
|
|
});
|
|
|
|
// Page handler
|
|
client.on("messageReactionAdd", (reaction, user) => {
|
|
const message = reaction.message;
|
|
if (message.author != client.user || user == client.user) return; // Message author must be bot; Reactor must not be bot
|
|
reaction.users.remove(user);
|
|
|
|
if (!reaction.me) return;
|
|
if (!message.embeds.length) return;
|
|
const embed = message.embeds[0];
|
|
|
|
let event = ""; // Unused internally; Up to commands to utilize if needed
|
|
for (const [action, name] of Object.entries(client.pageControls)) {
|
|
if (reaction.emoji.name === name) {
|
|
event = action;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (event === "") return;
|
|
if (event === "exit") {
|
|
if (!embed.footer ||
|
|
embed.footer.iconURL().match(/avatars\/(\d+)/)[1] == user.id ||
|
|
message.guild.member(user).hasPermission("MANAGE_MESSAGES"))
|
|
message.delete();
|
|
return;
|
|
} else {
|
|
if (!embed.footer) return;
|
|
if (!(new RegExp(/^Page /).test(embed.footer.text))) return; // Nothing to do if no pages
|
|
|
|
const matches = embed.footer.text.match(/^Page (\d+) ?\/ ?(\d+) \| (.+)/);
|
|
const commandName = matches[3];
|
|
const command = client.pages.get(commandName)
|
|
if (!command) return;
|
|
|
|
let page = parseInt(matches[1]);
|
|
const total = parseInt(matches[2]);
|
|
|
|
switch (event) {
|
|
case "next":
|
|
page++;
|
|
if (page > total) page = 1;
|
|
break;
|
|
case "prev":
|
|
page--;
|
|
if (page < 1) page = total;
|
|
break;
|
|
}
|
|
|
|
// (message, current page, total pages, reaction event)
|
|
command.execute(message, page, total, event);
|
|
}
|
|
});
|
|
|
|
// Launch
|
|
client.login(token);
|