Created
July 26, 2020 03:21
-
-
Save slashinfty/b730190e5f5696680a0e40ea6c566b77 to your computer and use it in GitHub Desktop.
Mobile Speedrunning Bot
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
//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