timebot

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

commit d17ec91993c75afeea99b3ac0f0b000cd8639f89
parent 5f3493905503986ba9c2361b3a4e71a748dc260c
Author: Agastya Chandrakant <me@hanabi.in>
Date:   Wed, 10 Feb 2021 15:36:24 +0530

flood protect; fix KILL, reorder functions

Diffstat:
MLICENSE | 2+-
Aalias.json | 2++
Mconfig.js | 6+++---
Dconfig.json | 10----------
Mindex.js | 146++++++++++++++++++++++++++++++++++++-------------------------------------------
5 files changed, 72 insertions(+), 94 deletions(-)

diff --git a/LICENSE b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2020, Agastya Chandrakant +Copyright (c) 2020-2021, Agastya Chandrakant All rights reserved. Redistribution and use in source and binary forms, with or without diff --git a/alias.json b/alias.json @@ -0,0 +1,2 @@ +{ +} diff --git a/config.js b/config.js @@ -1,6 +1,6 @@ module.exports = { + channels: ["##nie"], server: "irc.freenode.net", - nick: "timebot", - channels: ["#nie", "##lipsum"], - maintainers: ["acagastya"] + maintainers: ["acagastya"], + nick: "timebot" }; diff --git a/config.json b/config.json @@ -1,10 +0,0 @@ -{ - "channels": [ - "#foo", - "##bar" - ], - "alias": { - "john": "America/New_York", - "doe": "Australia/Sydney", - } -} diff --git a/index.js b/index.js @@ -1,125 +1,73 @@ +// node imports const fs = require("fs"); + +// npm imports const moment = require("moment-timezone"); const irc = require("irc"); -const { server, nick, maintainers } = require("./config"); -const FILE = "./config.json"; -let { alias, channels } = JSON.parse(fs.readFileSync(FILE)); +// local imports +const { channels, server, nick, maintainers } = require("./config.js"); + +// constants +const FILE = "./alias.json"; +let alias = JSON.parse(fs.readFileSync(FILE)); const ircClient = new irc.Client(server, nick, { channels }); +// irc event-listeners ircClient.addListener("error", errorHandler); ircClient.addListener("message", normalMsg); ircClient.addListener("pm", pmHandler); -function handleKill(sender, msg) { - if (msg != "KILL") return; - if (!maintainer.includes(sender)) return; - process.abort(); -} - -function pmHandler(sender, msg) { - handleKill(sender, msg); - if (!msg.startsWith("#")) return; - channels.push(msg); - fs.writeFileSync( - FILE, - JSON.stringify(Object.assign({}, { channels, alias }), null, 2) + "\n", - err => { - if (err) { - ircClient.say(sender, `Error occurred: ${err}.`); - return; - } - } - ); - ircClient.join(msg); - ircClient.say(sender, "Attempted to join."); - channels = JSON.parse(fs.readFileSync(FILE)); +// event listener functions +function errorHandler(msg) { + for (const maintainer of maintainers) + ircClient.say(maintainer, `${nick} error: ${msg}`); } function normalMsg(sender, channel, msg) { if (msg.includes(`${nick} help`)) showHelp(channel, msg); - else if (msg.includes(`${nick} ls `)) showList(channel, msg); + else if (msg.includes(`${nick} ls `)) showList(sender, msg); else if (msg.includes(`${nick} add `)) addAlias(sender, channel, msg); else if (msg.includes(`${nick} rm `)) deleteAlias(sender, channel, msg); + else if (msg.includes(`${nick} link`)) giveLink(sender); else if (msg.includes(`${nick} `)) sayTime(channel, msg); - else if (msg.includes(nick)) showHelp(channel, msg); -} - -function errorHandler(msg) { - for (const maintainer of maintainers) - ircClient.say(maintainer, `${nick} error: ${msg}`); -} - -function showHelp(channel, msg) { - ircClient.say(channel, `Use "${nick} help" to show help.`); - ircClient.say( - channel, - `Use "${nick} ls <timezone>" to show a list of valid timezones.` - ); - ircClient.say( - channel, - `Use "${nick} <timezone>" to display current time of <timezone>.` - ); - ircClient.say( - channel, - `Use "${nick} add <alias>:<timezone>" for adding an <alias> for a <timezone>.` - ); - ircClient.say( - channel, - `Use "${nick} rm <alias>" from removing an <alias> for a <timezone>.` - ); } -function showList(channel, msg) { - const reg = new RegExp(`${nick}:? ls (.*)`); - const zone = msg.match(reg)[1]; - const allZones = moment.tz.names().map(el => el.replace(/_/g, " ")); - const res = allZones - .filter(el => el.toLowerCase().includes(zone.toLowerCase())) - .join(", "); - ircClient.say(channel, res); -} - -function sayTime(channel, msg) { - const reg = new RegExp(`${nick}:? (.*)`); - const zone = msg.match(reg)[1].replace(/ /g, "_"); - const machineReadableZone = alias[zone] || zone; - const TZ = moment.tz.names().includes(machineReadableZone) - ? machineReadableZone - : "UTC"; - let time = moment.tz(TZ).format("HH:mm MMM DD z"); - ircClient.say(channel, time); +function pmHandler(sender, msg) { + handleKill(sender, msg); } +// helper functions function addAlias(sender, channel, msg) { if (!maintainers.includes(sender)) { ircClient.say(channel, "Only maintainers allowed to add aliases."); return; } if (!msg.includes(":")) { - ircClient.say(channel, "Wrong syntax."); - showHelp(channel); + ircClient.say(channel, "Wrong syntax, see <https://w.wiki/yes>"); return; } const reg = new RegExp(`${nick}:? add (.*)`); - const [key, value] = msg.match(reg)[1].split(":"); + let [key, value] = msg.match(reg)[1].split(":"); + key = key.toLowerCase(); const machineReadableValue = value.replace(/ /g, "_"); if (moment.tz.names().includes(machineReadableValue)) { alias[key] = machineReadableValue; fs.writeFileSync( FILE, - JSON.stringify(Object.assign({}, { channels, alias }), null, 2) + "\n", + JSON.stringify(Object.assign({}, alias), null, 2) + "\n", err => { if (err) { ircClient.say(channel, `Error occurred: ${err}`); + delete alias[key]; return; } } ); - alias = JSON.parse(fs.readFileSync(FILE)).alias; + alias = JSON.parse(fs.readFileSync(FILE)); ircClient.say(channel, `Alias for ${key} has been added.`); } } @@ -130,18 +78,55 @@ function deleteAlias(sender, channel, msg) { return; } const reg = new RegExp(`${nick}:? rm (.*)`); - const key = msg.match(reg)[1]; + const key = msg.match(reg)[1].toLowerCase(); + const val = alias[key]; delete alias[key]; fs.writeFileSync( FILE, - JSON.stringify(Object.assign({}, { channels, alias }), null, 2) + "\n", + JSON.stringify(Object.assign({}, alias), null, 2) + "\n", err => { if (err) { ircClient.say(channel, `Error occurred: ${err}`); + if (val) alias[key] = val; return; } } ); - alias = JSON.parse(fs.readFileSync(FILE)).alias; + alias = JSON.parse(fs.readFileSync(FILE)); ircClient.say(channel, `Alias for ${key} now does not exist.`); } + +function giveLink(sender) { + ircClient.say(sender, "https://time-convertor.toolforge.org"); +} + +function handleKill(sender, msg) { + if (msg != "KILL") return; + if (!maintainers.includes(sender)) return; + process.abort(); +} + +function sayTime(channel, msg) { + const reg = new RegExp(`${nick}:? (.*)`); + const zone = msg.match(reg)[1].replace(/ /g, "_"); + const machineReadableZone = alias[zone.toLowerCase()] || zone; + const TZ = moment.tz.names().includes(machineReadableZone) + ? machineReadableZone + : "UTC"; + let time = moment.tz(TZ).format("HH:mm MMM DD z"); + ircClient.say(channel, time); +} + +function showHelp(channel) { + ircClient.say(channel, "Docs: <https://w.wiki/yes>"); +} + +function showList(sender, msg) { + const reg = new RegExp(`${nick}:? ls (.*)`); + const zone = msg.match(reg)[1].toLowerCase(); + const allZones = moment.tz.names().map(el => el.replace(/_/g, " ")); + const res = allZones + .filter(el => el.toLowerCase().includes(zone)) + .join(", "); + ircClient.say(sender, res); +} +\ No newline at end of file