timebot

Convert live time across time-zones on IRC
git clone http://git.hanabi.in/repos/timebot.git
Log | Files | Refs | LICENSE

index.js (4045B)


      1 // node imports
      2 const fs = require("fs");
      3 
      4 // npm imports
      5 const moment = require("moment-timezone");
      6 const irc = require("irc");
      7 
      8 // local imports
      9 const {
     10   channels,
     11   maintainers,
     12   nick,
     13   password,
     14   server,
     15 } = require("./config.js");
     16 
     17 // constants
     18 const FILE = "./alias.json";
     19 let alias = JSON.parse(fs.readFileSync(FILE));
     20 
     21 const ircClient = new irc.Client(server, nick, {
     22   channels,
     23   userName: "timebot",
     24   realName: "timebot",
     25   sasl: true,
     26   password,
     27   floodProtection: true,
     28   floodProtectionDelay: 1000,
     29 });
     30 
     31 // irc event-listeners
     32 ircClient.addListener("error", errorHandler);
     33 
     34 ircClient.addListener("message", normalMsg);
     35 
     36 ircClient.addListener("pm", pmHandler);
     37 
     38 // event listener functions
     39 function errorHandler(msg) {
     40   const err = JSON.stringify(msg);
     41   for (const maintainer of maintainers)
     42     ircClient.say(maintainer, `${nick} error: ${err}`);
     43 }
     44 
     45 function normalMsg(sender, channel, msg) {
     46   if (msg.includes(`${nick} help`)) showHelp(channel, msg);
     47   else if (msg.includes(`${nick} ls `)) showList(sender, msg);
     48   else if (msg.includes(`${nick} add `)) addAlias(sender, channel, msg);
     49   else if (msg.includes(`${nick} rm `)) deleteAlias(sender, channel, msg);
     50   else if (msg.includes(`${nick} link`)) giveLink(sender);
     51   else if (msg.includes(`${nick} `)) sayTime(channel, msg);
     52 }
     53 
     54 function pmHandler(sender, msg) {
     55   handleKill(sender, msg);
     56 }
     57 
     58 // helper functions
     59 function addAlias(sender, channel, msg) {
     60   if (!maintainers.includes(sender)) {
     61     ircClient.say(channel, "Only maintainers allowed to add aliases.");
     62     return;
     63   }
     64   if (!msg.includes(":")) {
     65     ircClient.say(channel, "Wrong syntax, see <https://w.wiki/yes>");
     66     return;
     67   }
     68   const reg = new RegExp(`${nick}:? add (.*)`);
     69   let [key, value] = msg.match(reg)[1].split(":");
     70   key = key.toLowerCase();
     71   const machineReadableValue = value.replace(/ /g, "_");
     72   if (moment.tz.names().includes(machineReadableValue)) {
     73     alias[key] = machineReadableValue;
     74     fs.writeFileSync(
     75       FILE,
     76       JSON.stringify(Object.assign({}, alias), null, 2) + "\n",
     77       (err) => {
     78         if (err) {
     79           ircClient.say(channel, `Error occurred: ${err}`);
     80           delete alias[key];
     81           return;
     82         }
     83       }
     84     );
     85     alias = JSON.parse(fs.readFileSync(FILE));
     86     ircClient.say(channel, `Alias for ${key} has been added.`);
     87   }
     88 }
     89 
     90 function deleteAlias(sender, channel, msg) {
     91   if (!maintainers.includes(sender)) {
     92     ircClient.say(channel, "Only maintainers allowed to delete aliases.");
     93     return;
     94   }
     95   const reg = new RegExp(`${nick}:? rm (.*)`);
     96   const key = msg.match(reg)[1].toLowerCase();
     97   const val = alias[key];
     98   delete alias[key];
     99   fs.writeFileSync(
    100     FILE,
    101     JSON.stringify(Object.assign({}, alias), null, 2) + "\n",
    102     (err) => {
    103       if (err) {
    104         ircClient.say(channel, `Error occurred: ${err}`);
    105         if (val) alias[key] = val;
    106         return;
    107       }
    108     }
    109   );
    110   alias = JSON.parse(fs.readFileSync(FILE));
    111   ircClient.say(channel, `Alias for ${key} now does not exist.`);
    112 }
    113 
    114 function giveLink(sender) {
    115   ircClient.say(sender, "https://time-convertor.toolforge.org");
    116 }
    117 
    118 function handleKill(sender, msg) {
    119   if (msg != "KILL") return;
    120   if (!maintainers.includes(sender)) return;
    121   process.abort();
    122 }
    123 
    124 function sayTime(channel, msg) {
    125   const reg = new RegExp(`${nick}:? (.*)`);
    126   const zone = msg.match(reg)[1].replace(/ /g, "_");
    127   const machineReadableZone = alias[zone.toLowerCase()] || zone;
    128   const TZ = moment.tz.names().includes(machineReadableZone)
    129     ? machineReadableZone
    130     : "UTC";
    131   let time = moment.tz(TZ).format("HH:mm MMM DD z");
    132   ircClient.say(channel, time);
    133 }
    134 
    135 function showHelp(channel) {
    136   ircClient.say(channel, "Docs: <https://w.wiki/yes>");
    137 }
    138 
    139 function showList(sender, msg) {
    140   const reg = new RegExp(`${nick}:? ls (.*)`);
    141   const zone = msg.match(reg)[1].toLowerCase();
    142   const allZones = moment.tz.names().map((el) => el.replace(/_/g, " "));
    143   const res = allZones
    144     .filter((el) => el.toLowerCase().includes(zone))
    145     .join(", ");
    146   ircClient.say(sender, res);
    147 }