Skip to content

Instantly share code, notes, and snippets.

@Ale32bit
Created January 12, 2023 17:40
Show Gist options
  • Select an option

  • Save Ale32bit/2c441d06a71f4fe90713794683c7d9bb to your computer and use it in GitHub Desktop.

Select an option

Save Ale32bit/2c441d06a71f4fe90713794683c7d9bb to your computer and use it in GitHub Desktop.
/*
Respects Bot by AlexDevs
The only good respects bot
Copyright (c) 2023 AlexDevs
Press F to pay respects
*/
const path = require("path");
const fs = require("fs");
const SwitchChat = require("switchchat");
const config = require("./config.json");
// Only validates is a message only contains f or F
const payRegex = /^f$/i;
let lastDeath = null;
let players = {};
let discordLinks = {};
let respecters = [];
let linkCodes = {};
const client = new SwitchChat.Client(config.license);
client.defaultFormattingMode = "format";
function pad(n, width, z) {
z = z || '0';
n = n + '';
return n.length >= width ? n : new Array(width - n.length + 1).join(z) + n;
}
function randomId() {
return pad(Math.floor(Math.random() * 1000000), 6);
}
function save() {
fs.writeFile(path.resolve(__dirname, "respects.json"), JSON.stringify(players, null, 4), err => {
if (err) console.error(err)
});
fs.writeFile(path.resolve(__dirname, "discordLinks.json"), JSON.stringify(discordLinks, null, 4), err => {
if (err) console.error(err)
});
}
// Create a new player object if non-existent
function newPlayer(user) {
if (!players[user.uuid]) {
players[user.uuid] = {
name: user.name, // Username saved as cache
respects: 0,
deaths: 0,
given: 0,
custom: undefined, // Custom message to display in top 10 leaderboard
quiet: true,
discordId: null,
}
}
save();
}
// Search a player by name
function getPlayer(name) {
for (let uuid in players) {
if (players[uuid].name === name) return players[uuid];
}
}
function tell(user, message) {
return client.tell(user, message, "&6Respects", "format");
}
// Chatbox sub commands
const commands = {
top(command) { // Display top 10 respected players
let message = "&6--- &aTop 10 Leaderboard &6---";
let sortable = [];
for (let k in players) {
sortable.push([
k,
players[k].respects,
])
}
sortable.sort((a, b) => b[1] - a[1]);
for (let i = 0; i < 10; i++) {
if (sortable[i]) {
let player = players[sortable[i][0]];
message += `\n&b${i + 1}. &6${player.name}&7: &a${player.custom ? player.custom.replace(/{}/g, player.respects) : player.respects}`;
}
}
tell(command.user.name, message);
},
deaths(command) { // Display top 10 players who died the most times
let message = "&6--- &aTop 10 Deaths Leaderboard &6---";
let sortable = [];
for (let k in players) {
sortable.push([
k,
players[k].deaths,
])
}
sortable.sort((a, b) => b[1] - a[1]);
for (let i = 0; i < 10; i++) {
if (sortable[i]) {
let player = players[sortable[i][0]];
message += `\n&b${i + 1}. &6${player.name}&7: &a${player.deaths}`;
}
}
tell(command.user.name, message);
},
view(command) { // View more information about a player
// If an argument is passed, use it to look for a player.
let player = command.args.shift();
if (player) {
player = getPlayer(player);
} else { // View yourself if no argument instead
player = players[command.user.uuid];
}
if (!player) {
tell(command.user.name, "&cPlayer not found!");
return;
}
let message =
`&6--- &a${player.name} &6---\n` +
`&6Respects received&7: &a${player.respects}\n` +
`&6Respects paid&7: &a${player.given}\n` +
`&6Deaths&7: &a${player.deaths}\n` +
//`&6Active Time&7: &a${activetime[player.name] ? activetime[player.name].formatted : "&cUnexpected error"}\n` +
`&6Custom counter message&7: &a${player.custom ? player.custom : "*None*"}` +
`${player.custom ? `\n&6Preview&7: &a${player.custom.replace(/{}/g, player.respects)}` : ""}` // Preview
tell(command.user.name, message);
},
set(command) { // Set custom counter message
let custom = command.args.join(" ");
if (custom.trim() === "") { // If no arguments passed, reset the custom message
players[command.user.uuid].custom = undefined;
save();
tell(command.user.name, `&6Custom counter message reset.`)
} else {
custom = custom.replace(/\n/gi, "").substr(0, 64);
players[command.user.uuid].custom = custom;
save();
tell(command.user.name, `&6Custom counter message set to &a${custom}\n&6Preview: &a${custom.replace(/{}/g, players[command.user.uuid].respects)}`)
}
},
quiet(command) {
players[command.user.uuid].quiet = !players[command.user.uuid].quiet;
save();
tell(command.user.name, `&6Quiet mode ${players[command.user.uuid].quiet ? "&aenabled" : "&cdisabled"}&6!`)
},
link(command) {
let id = randomId();
linkCodes[command.user.uuid] = id;
tell(command.user.name, `&6Your link code is &7${id}&6!\nSay your link code in the Discord &9#server-chat&6 channel to link your account!`);
},
help(command) {
let message =
"&6--- &aCommands list &6---\n" +
"&6top&7: &aShow leaderboard of top 10 respected players\n" +
"&6deaths&7: &aShow leaderboard of top 10 death counts\n" +
"&6view&7 [name]: &aView information about a player\n" +
"&6set&7 [custom counter message]: &aSet custom counter message (&7{}&a is counter placeholder)\n" +
"&6quiet&7: &aToggle quiet mode\n" +
"&6link&7: &aLink your Discord account\n" +
"&6help&7: &aShow the commands list\n" +
`\n&aLast death from &6${players[lastDeath] ? players[lastDeath].name : "&oNone"}`;
tell(command.user.name, message, "&6Respects")
},
update(command) { // OP command to overwrite data
if (!command.ownerOnly) {
tell(command.user.name, "&cRun this command as owner only")
return;
}
let cmd = command.args.shift();
if (!cmd) {
tell(command.user.name, "Usage: update <field> <name> <...>")
return;
}
let user = getPlayer(command.args.shift());
if (!user) {
tell(command.user.name, "User not found");
return;
}
switch (cmd) {
case "deaths":
let deaths = parseInt(command.args.shift());
user.deaths = deaths;
save();
break;
case "given":
let given = parseInt(command.args.shift());
user.given = given;
save();
break;
case "respects":
let respects = parseInt(command.args.shift());
user.respects = respects;
save();
break;
case "custom":
let custom = command.args.join(" ");
user.custom = custom.trim() === "" ? undefined : custom;
save();
break;
default:
tell(command.user.name, "Options: deaths, given, respects, custom")
return;
}
}
};
function payRespect(message, isDiscord) {
newPlayer(message.user);
let payerId = message.user.uuid;
if (isDiscord) {
payerId = discordLinks[message.user.id];
}
if (!lastDeath) {
if (isDiscord) return;
tell(message.user.name, "&7&oNo one died since my last restart.")
return;
}
if (lastDeath === payerId) { // Avoid paying respects to yourself
if (isDiscord) return;
tell(message.user.name, "&cYou cannot respect yourself >:(")
return;
}
if (respecters.includes(payerId)) { // Avoid paying respects again
if (isDiscord) return;
tell(message.user.name, `&cYou already paid respects to &6${players[lastDeath].name || "Steve"}`)
return;
}
players[lastDeath].respects++;
players[payerId].given++;
respecters.push(payerId);
save();
if (!players[lastDeath].quiet) {
tell(players[lastDeath].name, `&6${message.user.name} &apaid you respects!`)
.catch(() => {
});
}
if (!players[payerId].quiet && !isDiscord) {
tell(message.user.name, `&aYou paid respects to &6${players[lastDeath].name}`);
}
}
client.on("command", command => { // run sub command
let prefix = command.command.toLowerCase();
if (prefix !== "respects" && prefix !== "f") return;
newPlayer(command.user);
let cmd = command.args.shift();
if (command.args.length === 0 && !commands[cmd]) {
commands.help(command);
return;
}
try {
commands[cmd](command);
} catch (e) {
console.error(e);
tell(command.user.name, "&cAn unexpected error occurred!");
}
})
client.on("chat_ingame", message => {
if (payRegex.test(message.text)) { // a player said "f"
payRespect(message)
}
})
client.on("chat_discord", message => {
if (message.text.length === 6) {
for (let k in linkCodes) {
let v = linkCodes[k];
if (v === message.text) {
let uuid = message.discordUser.id;
players[k].discordId = uuid;
discordLinks[uuid] = k;
save();
tell(players[k].name, `&6Account linked to &9${message.discordUser.name}&6!`)
.catch(console.error);
}
}
} else if (payRegex.test(message.text)) { // a player said "f"
let uuid = discordLinks[message.discordUser.id];
if (uuid) {
let player = players[uuid];
if (player.discordId === message.discordUser.id) {
payRespect(message, true)
}
}
}
})
client.on("death", death => { // increase death counter
newPlayer(death.user); // failsafe in case the bot wasn't running when a new player joined
players[death.user.uuid].deaths++;
save();
respecters = [];
lastDeath = death.user.uuid;
})
client.on("join", join => { // update cached name
let user = join.user;
newPlayer(user);
if (players[user.uuid].name !== user.name) {
players[user.uuid].name = user.name;
save();
}
})
client.on("ready", () => {
console.log("Logged in as " + client.owner);
})
if (!fs.existsSync(path.resolve(__dirname, "respects.json"))) {
fs.writeFileSync(path.resolve(__dirname, "respects.json"), "{}");
}
players = JSON.parse(fs.readFileSync(path.resolve(__dirname, "respects.json")).toString());
if (!fs.existsSync(path.resolve(__dirname, "discordLinks.json"))) {
fs.writeFileSync(path.resolve(__dirname, "discordLinks.json"), "{}");
}
discordLinks = JSON.parse(fs.readFileSync(path.resolve(__dirname, "discordLinks.json")).toString());
/*process.on("uncaughtException", e => {
console.error("Error", e);
})*/
client.connect();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment