Skip to content

Instantly share code, notes, and snippets.

@slashinfty
Created July 26, 2020 03:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save slashinfty/b730190e5f5696680a0e40ea6c566b77 to your computer and use it in GitHub Desktop.
Save slashinfty/b730190e5f5696680a0e40ea6c566b77 to your computer and use it in GitHub Desktop.
Mobile Speedrunning Bot
//dependencies: discord.js, node-fetch, dotenv
const fs = require('fs');
const Discord = require('discord.js');
const fetch = require('node-fetch');
const path = require('path');
require('dotenv').config();
const client = new Discord.Client();
client.login(process.env.TOKEN);
// Verify time of last run checked
let checkTime, servers;
// Convert times to a readable format
const convert = time => {
let hr, min, sec, ms;
let parts = time.toString().split('.');
ms = parts.length > 1 ? parseInt((parts[1] + '00').substr(0,3)) : undefined;
sec = parseInt(parts[0]);
if (sec >= 60) {min = Math.floor(sec / 60); sec = sec < 10 ? '0' + (sec % 60) : sec % 60}
if (min >= 60) {hr = Math.floor(min / 60); min = min < 10 ? '0' + (min % 60) : min % 60}
ms = ms < 10 ? '00' + ms : ms < 100 ? '0' + ms : ms;
if (min === undefined) return ms === undefined ? sec.toString() + 's' : sec.toString() + 's ' + ms.toString() + 'ms';
else if (hr === undefined) return ms === undefined ? min.toString() + 'm ' + sec.toString() + 's' : min.toString() + 'm ' + sec.toString() + 's ' + ms.toString() + 'ms';
else return ms === undefined ? hr.toString() + 'h ' + min.toString() + 'm ' + sec.toString() + 's' : hr.toString() + 'h ' + min.toString() + 'm ' + sec.toString() + 's ' + ms.toString() + 'ms';
}
client.once('ready', async () => {
console.log('ready');
// Discord status
client.user.setActivity("Hello world.");
// Fill servers and games
const serverFile = path.join(__dirname, 'servers.json');
// Create file if it doesn't exist
if (!fs.existsSync(serverFile)) {
const newServerObj = {
"servers": []
};
fs.writeFileSync(serverFile, JSON.stringify(newServerObj));
}
const serverContents = fs.readFileSync(serverFile);
servers = JSON.parse(serverContents).servers;
});
client.setInterval(async () => {
const recentRunsResponse = await fetch(`https://www.speedrun.com/api/v1/runs?status=verified&orderby=verify-date&direction=desc&embed=game,category.variables,platform,players`);
const recentRunsObject = await recentRunsResponse.json();
const recentRuns = recentRunsObject.data;
let newCheckTime;
// Android, iOS, Windows Phone
const platforms = ['lq60nl94', 'gde3xgek', 'p36no5e8'];
for (let i = 0; i < recentRuns.length; i++) {
const thisRun = recentRuns[i];
// When run was verified
const verifyTime = await new Date(thisRun.status['verify-date']);
// Update time to check if it's the first run
if (i === 0) {
if (checkTime === undefined) checkTime = verifyTime;
newCheckTime = verifyTime;
}
// If the run was before last first checked run, quit (but update time!)
if (verifyTime - checkTime <= 0) {
checkTime = newCheckTime;
return;
}
if (!platforms.includes(thisRun.system.platform)) continue;
// Get subcategory information
const subCategoryObject = thisRun.category.data.variables.data.find(v => v['is-subcategory']);
// Get subcategory name
let subCategory = '';
if (subCategoryObject !== undefined) {
const subCatValue = thisRun.values[subCategoryObject.id];
subCategory = ' (' + subCategoryObject.values.values[subCatValue].label + ')';
}
// Get runner name
const runnerName = thisRun.players.data[0].rel === 'user' ? thisRun.players.data[0].names.international : thisRun.players.data[0].name;
// Create Discord embed
const embed = new Discord.MessageEmbed()
.setColor('#80C86F')
.setTitle(convert(thisRun.times.primary_t) + ' by ' + runnerName)
.setThumbnail(thisRun.game.data.assets['cover-medium'].uri)
.setURL(thisRun.weblink)
.setAuthor(thisRun.game.data.names.international + ' - ' + thisRun.category.data.name + subCategory)
.addField('Date Played:', thisRun.date)
.setTimestamp();
// Create array of channels
const serverFile = fs.readFileSync(path.join(__dirname, 'servers.json'));
let servers = JSON.parse(serverFile).servers;
let channels = servers.map(s => s.channel);
// Message each of the channels
for (let j = 0; j < channels.length; j++) {
const thisChannel = await client.channels.fetch(channels[j]);
await thisChannel.send(embed).then(msg => checkTime = newCheckTime);
}
}
// Update time to check
checkTime = newCheckTime;
}, 3e4); // 30 seconds
client.on('message', async message => {
// Require message to be from server owner and mention the bot and only mention one channel
if (message.member.id === message.guild.ownerID && message.mentions.users.has(client.user.id) && message.mentions.channels.size === 1) {
// Get the channel ID of channel mentioned
const channelId = message.mentions.channels.first().id;
// Path of server/channel information
const p = path.join(__dirname, 'servers.json');
// If the files doesn't exist, create it
if (!fs.existsSync(p)) {
const newObject = {"servers": []};
fs.writeFileSync(p, JSON.stringify(newObject));
}
// Read the file and parse it
const contents = fs.readFileSync(p);
let obj = JSON.parse(contents).servers;
// Check if server exists in file
const existingServer = obj.find(e => e.server === message.guild.id);
// If it exists, update the channel
if (existingServer !== undefined) {
existingServer.channel = channelId;
existingServer.channelName = message.mentions.channels.first().name;
}
// If not, add the server and channel
else {
const newServer = {"server": message.guild.id, "serverName": message.guild.name, "channel": channelId, "channelName": message.mentions.channels.first().name};
obj.push(newServer);
}
// Let owner know it worked
message.reply('Now sending in ' + message.mentions.channels.first().name);
// Write the file
fs.writeFileSync(p, JSON.stringify({"servers": obj}));
}
});
client.on('guildDelete', guild => {
// Read the servers file and parse it
const contents = fs.readFileSync(path.join(__dirname, 'servers.json'));
let obj = JSON.parse(contents).servers;
// Find the server being left
obj.splice(obj.findIndex(e => e.server === guild.id), 1);
// Write the file
fs.writeFileSync(path.join(__dirname, 'servers.json'), JSON.stringify({"servers": obj}));
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment