374 lines
12 KiB
Haxe
374 lines
12 KiB
Haxe
import hxdiscord.DiscordClient;
|
|
import hxdiscord.types.*;
|
|
import hxdiscord.endpoints.Endpoints;
|
|
import haxe.MainLoop;
|
|
import haxe.Json;
|
|
import sys.io.File;
|
|
import sys.FileSystem;
|
|
using StringTools;
|
|
|
|
class Onequestionmark {
|
|
// Initialize vars
|
|
static var Bot:DiscordClient;
|
|
static var settings:Dynamic;
|
|
static var botInfo:Dynamic;
|
|
static var iceRegex:EReg = ~/\bicc?ed?\b/i;
|
|
|
|
static var hugDB:Array<String>;
|
|
static var motdDB:haxe.DynamicAccess<Dynamic> = {};
|
|
static var yesnoDB:Dynamic;
|
|
static var echoboxDB:haxe.DynamicAccess<Dynamic> = {};
|
|
|
|
static var saveTimer = Date.now().getMinutes();
|
|
static var saveQueue:Array<String> = [];
|
|
|
|
|
|
static function main() {
|
|
|
|
Sys.println('[${timestamp()}] Starting onequestionmark-chat');
|
|
|
|
// Load files
|
|
if (FileSystem.exists("settings.json")) {
|
|
Sys.println('[${timestamp()}] Found settings.json, loading');
|
|
settings = Json.parse(File.getContent("settings.json"));
|
|
} else {
|
|
Sys.println('[${timestamp()}] Did not find settings.json, exiting');
|
|
Sys.exit(0);
|
|
}
|
|
|
|
if (FileSystem.exists("hug-db.json")) {
|
|
Sys.println('[${timestamp()}] Found hug-db.json, loading');
|
|
hugDB = Json.parse(File.getContent("hug-db.json"));
|
|
} else {
|
|
Sys.println('[${timestamp()}] Did not find hug-db.json, skipping');
|
|
hugDB = ["https://cdn.discordapp.com/attachments/270113422232911883/445026464623099907/brohugbump.gif"]; // Fallback
|
|
}
|
|
|
|
if (FileSystem.exists("motd-db.json")) {
|
|
Sys.println('[${timestamp()}] Found motd-db.json, loading');
|
|
motdDB = Json.parse(File.getContent("motd-db.json"));
|
|
} else {
|
|
Sys.println('[${timestamp()}] Did not find motd-db.json, skipping');
|
|
motdDB = Json.parse('{"sunday": [],"monday": [],"tuesday": [],"wednesday": [],"thursday": [],"friday": [],"saturday": []}'); // Fallback
|
|
}
|
|
|
|
if (FileSystem.exists("yesno-db.json")) {
|
|
Sys.println('[${timestamp()}] Found yesno-db.json, loading');
|
|
yesnoDB = Json.parse(File.getContent("yesno-db.json"));
|
|
} else {
|
|
Sys.println('[${timestamp()}] Did not find yesno-db.json, skipping');
|
|
yesnoDB = {"yes": [],"no": []}; // Fallback
|
|
}
|
|
|
|
if (FileSystem.exists("echobox-db.json")) {
|
|
Sys.println('[${timestamp()}] Found echobox-db.json, loading');
|
|
echoboxDB = Json.parse(File.getContent("echobox-db.json"));
|
|
} else {
|
|
Sys.println('[${timestamp()}] Did not find echobox-db.json, generating');
|
|
File.saveContent("echobox-db.json", Json.stringify(echoboxDB, "\t"));
|
|
}
|
|
|
|
// Start the bot
|
|
Bot = new DiscordClient(settings.token, [3276799], settings.debug);
|
|
Bot.onReady = onReady;
|
|
Bot.onMessageCreate = onMessageCreate;
|
|
Bot.connect();
|
|
}
|
|
|
|
public static function onReady() {
|
|
Sys.sleep(1);
|
|
Sys.println('[${timestamp()}] Bot is online');
|
|
//Endpoints.sendMessage(settings.devchannel, {content:"onequestionmark-chat alpha test is now running"}, null, false);
|
|
botInfo = Endpoints.getCurrentUser();
|
|
|
|
MainLoop.add(motd);
|
|
MainLoop.add(saveSystem);
|
|
}
|
|
|
|
public static function onMessageCreate(m:Message) {
|
|
// DevMode check
|
|
if ((!settings.devmode) || (m.guild_id == settings.devserver)) {
|
|
var msg = m.content;
|
|
|
|
// Command processor
|
|
if (msg.charAt(0) == "?") {
|
|
var command = "";
|
|
|
|
if (msg.indexOf(" ") != -1) {
|
|
// Separate command from rest of message, if necessary
|
|
command = msg.substring(1, msg.indexOf(" ")).toLowerCase();
|
|
msg = msg.substring(msg.indexOf(" ")+1);
|
|
} else {
|
|
// Otherwise, remove msg
|
|
command = msg.substring(1).toLowerCase();
|
|
msg = "";
|
|
}
|
|
|
|
switch (command) {
|
|
// Commands that require authorization
|
|
case "quit":
|
|
if (m.author.id == settings.botowner) {
|
|
m.react('✅');
|
|
Sys.println('[${timestamp()}] Shutdown command received from botowner, exiting');
|
|
shutdown();
|
|
}
|
|
case "devmode":
|
|
if (m.author.id == settings.botowner) {
|
|
if (!settings.devmode) {
|
|
settings.devmode = true;
|
|
m.reply({content:"DevMode enabled."}, false);
|
|
} else {
|
|
settings.devmode = false;
|
|
m.reply({content:"DevMode disabled."}, false);
|
|
}
|
|
}
|
|
case "motd":
|
|
if (m.author.id == settings.botowner) {
|
|
if (!settings.motd.channels.contains(m.channel_id)) {
|
|
settings.motd.channels.push(m.channel_id);
|
|
m.reply({content:'MOTD has been enabled for <#${m.channel_id}>'}, false);
|
|
} else {
|
|
settings.motd.channels.remove(m.channel_id);
|
|
m.reply({content:'MOTD has been disabled for <#${m.channel_id}>'}, false);
|
|
}
|
|
saveQueue.push("settings");
|
|
}
|
|
// System for WIP commands that only work in testing server
|
|
case "wipcommand":
|
|
if (m.guild_id == settings.devserver) {
|
|
m.reply({content:"Dev Server response."}, true);
|
|
}
|
|
// Basic response commands
|
|
case "help":
|
|
m.reply({content:'
|
|
**onequestionmark bot commands**\n`?chk`: ack\n`?slap <target>`: The classic mIRC troutslap.\n`?hug <target (optional)>`: Posts randomized hug image.\n`?yes` and `?no`: Posts randomized yes/no.\n`?angery`\n`?subway`\n`?motd`: Enables MOTD for current channel (requires auth)\n`?devmode`: Toggles Dev Mode (requires auth)\n`?quit`: Shutdown command (requires auth)\n**Non-command bot functions:**\n*MOTD*: Bot will post a randomized *Meme of the Day* in enabled channels.\n*Icce*: Bot provides users with ice cuboids.\n*Meteor*: Bot reacts to falling rocks in the chat.'}, false);
|
|
case "chk":
|
|
m.reply({content:'<@${m.author.id}>: ack'}, false);
|
|
case "mrkrabs":
|
|
m.reply({content:'<@${m.author.id}>: ack ack ack ack ack'}, false);
|
|
case "slap":
|
|
if (msg.length != 0) {m.reply({content:'*onequestionmark slaps ${msg} around a bit with a large trout*'}, false);}
|
|
// Basic aliases
|
|
case "angery":
|
|
m.reply({content:"https://cdn.discordapp.com/attachments/1071547517847732305/1079518504413311108/angery.jpg"}, false);
|
|
case "subway":
|
|
m.reply({content:"https://www.youtube.com/watch?v=y3VRXVvr6XU"}, false);
|
|
case "illuminati":
|
|
m.reply({content:"https://cdn.discordapp.com/attachments/1071547517847732305/1147204253039984671/illuminati.gif"}, false);
|
|
case "cube":
|
|
m.reply({content:"https://cdn.discordapp.com/attachments/270113422232911883/502690458779123722/the_cube.jpg"}, false);
|
|
case "coolsville":
|
|
m.reply({content:"https://cdn.discordapp.com/attachments/1071547517847732305/1147583765212835921/coolsville.gif"}, false);
|
|
case "tufac":
|
|
m.reply({content:"*Not Teh Face, but better,*\n*Tufac to the letter!*\n*Always two faces, never one,*\n*Tufac has you on the run!*"}, false);
|
|
case "communism":
|
|
m.reply({content:"https://cdn.discordapp.com/attachments/1071547517847732305/1147590229960691742/communism.gif"}, false);
|
|
// Image database commands
|
|
case "hug":
|
|
m.reply({content:'🫂 *hugs ${msg}*\n${hugDB[randInt(0, hugDB.length-1)]}'}, false);
|
|
case "yes":
|
|
var yes = yesnoDB.yes;
|
|
m.reply({content:'${yes[randInt(0, yes.length-1)]}'}, false);
|
|
case "no":
|
|
var no = yesnoDB.no;
|
|
m.reply({content:'${no[randInt(0, no.length-1)]}'}, false);
|
|
// Echobox
|
|
case "echobox":
|
|
// Create Echobox array for the server if missing
|
|
if (!echoboxDB.exists('server${m.guild_id}')) {
|
|
echoboxDB.set('server${m.guild_id}', []);
|
|
}
|
|
|
|
var echobox:Array<String> = echoboxDB.get('server${m.guild_id}');
|
|
var quote:String = "";
|
|
|
|
// Echobox response
|
|
if (!m.mention_everyone) {
|
|
if (echobox.length > 0) {
|
|
var ebchoice = randInt(0, echobox.length-1);
|
|
//m.reply({content:'**Echobox, quote #${ebchoice+1}:** ${echobox[ebchoice]}'}, false);
|
|
quote = '**Echobox, quote #${ebchoice+1}:** ${echobox[ebchoice]}';
|
|
} else {
|
|
//m.reply({content:'**Echobox:** There are no quotes in this server\'s Echobox yet.'}, false);
|
|
quote = '**Echobox:** There are no quotes in this server\'s Echobox yet.';
|
|
}
|
|
|
|
// Add quote to Echobox
|
|
if (msg.length != 0) {
|
|
if (!echobox.contains(msg)) {
|
|
echobox.push(msg);
|
|
echoboxDB.set('server${m.guild_id}', echobox);
|
|
saveQueue.push("echobox");
|
|
m.reply({content:quote}, false);
|
|
} else {
|
|
m.reply({content:'**Echobox:** This quote is already in the database.'}, false);
|
|
}
|
|
} else {
|
|
m.reply({content:quote}, false);
|
|
}
|
|
} else {
|
|
m.reply({content:'**Echobox:** You cannot add `@everyone` to the Echobox.'}, false);
|
|
}
|
|
}
|
|
}
|
|
|
|
// Non-command responses
|
|
if ((msg.charAt(0) == ".") && (msg.length == 1)) {m.reply({content:"omg a meteor"}, true);}
|
|
if ((iceRegex.match(msg)) && (m.author.id != botInfo.id)) {m.reply({content:"Did some carbon-based lifeform just say **I C E**?"});}
|
|
if ((m.mention_everyone == true) && (msg.charAt(0) != "?")) {m.reply({content:"https://cdn.discordapp.com/attachments/1071547517847732305/1147598637241741343/at_everyone.jpg"}, true);}
|
|
}
|
|
}
|
|
|
|
// Time-related functions
|
|
public static function timestamp() {
|
|
return '${StringTools.lpad(Std.string(Date.now().getHours()), "0", 2)}:${StringTools.lpad(Std.string(Date.now().getMinutes()), "0", 2)}';
|
|
}
|
|
|
|
public static function datestamp() {
|
|
return '${StringTools.lpad(Std.string(Date.now().getMonth()+1), "0", 2)}-${StringTools.lpad(Std.string(Date.now().getDate()), "0", 2)}';
|
|
}
|
|
|
|
// Clean print day of week
|
|
public static function checkDay() {
|
|
var day = "";
|
|
switch (Date.now().getDay()+1) {
|
|
case 1:
|
|
day = "sun";
|
|
case 2:
|
|
day = "mon";
|
|
case 3:
|
|
day = "tues";
|
|
case 4:
|
|
day = "wed";
|
|
case 5:
|
|
day = "thurs";
|
|
case 6:
|
|
day = "fri";
|
|
case 7:
|
|
day = "sat";
|
|
}
|
|
return day;
|
|
}
|
|
|
|
// Clean print month
|
|
public static function checkMonth() {
|
|
var month = "";
|
|
switch (Date.now().getMonth()+1) {
|
|
case 1:
|
|
month = "jan";
|
|
case 2:
|
|
month = "feb";
|
|
case 3:
|
|
month = "mar";
|
|
case 4:
|
|
month = "apr";
|
|
case 5:
|
|
month = "may";
|
|
case 6:
|
|
month = "jun";
|
|
case 7:
|
|
month = "jul";
|
|
case 8:
|
|
month = "aug";
|
|
case 9:
|
|
month = "sep";
|
|
case 10:
|
|
month = "oct";
|
|
case 11:
|
|
month = "nov";
|
|
case 12:
|
|
month = "dec";
|
|
}
|
|
return month;
|
|
}
|
|
|
|
//Get current day of month, padded
|
|
public static function checkDate() {
|
|
return StringTools.lpad(Std.string(Date.now().getDate()), "0", 2);
|
|
}
|
|
|
|
public static function monthdate() {
|
|
return '${checkMonth()}${checkDate()}';
|
|
}
|
|
|
|
public static function weekdate() {
|
|
return '${checkDay()}${checkDate()}';
|
|
}
|
|
|
|
public static function motd() {
|
|
if (settings.motd.date != datestamp()) {
|
|
settings.motd.date = datestamp();
|
|
settings.motd.posted = false;
|
|
}
|
|
|
|
if ((settings.motd.posted == false) && (Date.now().getHours() >= settings.motd.time)) {
|
|
settings.motd.posted = true;
|
|
saveQueue.push("settings");
|
|
|
|
var msg = "";
|
|
var day:Array<String> = [];
|
|
|
|
// Check for exact date
|
|
if (motdDB.exists('${monthdate()}-${Date.now().getFullYear()}')) {
|
|
day = motdDB.get('${monthdate()}-${Date.now().getFullYear()}');
|
|
}
|
|
// Else, check for special date
|
|
else if (motdDB.exists(monthdate())) {
|
|
day = motdDB.get(monthdate());
|
|
}
|
|
// Else, check for special day/date combo
|
|
else if (motdDB.exists(weekdate())) {
|
|
day = motdDB.get(weekdate());
|
|
}
|
|
// Otherwise, post daily meme
|
|
else if (motdDB.exists(checkDay())) {
|
|
day = motdDB.get(checkDay());
|
|
}
|
|
|
|
if (day.length > 0) {msg = day[randInt(0, day.length-1)];}
|
|
|
|
var channels:Array<String> = settings.motd.channels; // Because it won't let me do this directly
|
|
|
|
if (channels.length > 0) {for (i in channels) {if (msg.length > 0) {Endpoints.sendMessage(i, {content:msg}, null, false);}}}
|
|
}
|
|
}
|
|
|
|
// Filesystem operations
|
|
public static function saveSystem() {
|
|
if (saveTimer != Date.now().getMinutes()) { // We only want to run this once a minute
|
|
|
|
if (saveQueue.length > 0) { // See if there's anything in the queue
|
|
switch (saveQueue.shift()) {
|
|
case "settings":
|
|
saveSettings();
|
|
Sys.println('[${timestamp()}] Saved settings.json');
|
|
case "echobox":
|
|
saveEchoboxDB();
|
|
Sys.println('[${timestamp()}] Saved echobox-db.json');
|
|
}
|
|
}
|
|
|
|
saveTimer = Date.now().getMinutes(); // Update timer
|
|
}
|
|
}
|
|
|
|
public static function saveSettings() {
|
|
File.saveContent("settings.json", Json.stringify(settings, "\t"));
|
|
}
|
|
|
|
public static function saveEchoboxDB() {
|
|
File.saveContent("echobox-db.json", Json.stringify(echoboxDB, "\t"));
|
|
}
|
|
|
|
// General functions
|
|
public static function randInt(x, y) {
|
|
// Return a random integer between x and y, both inclusive
|
|
return Std.random((y+1)-x)+x;
|
|
}
|
|
|
|
public static function shutdown() {
|
|
saveSettings();
|
|
saveEchoboxDB();
|
|
Sys.exit(0);
|
|
}
|
|
} |