Uwev2/src/inc/clients/irc.js
2017-11-22 23:12:45 +01:00

149 lines
4.5 KiB
JavaScript

import { logger } from "../log.js";
const net = require("net")
, tls = require("tls")
, EventEmitter = require("events").EventEmitter
, util = require("util")
, fs = require("fs");
class irc {
constructor(options) {
EventEmitter.call(this);
this.options = options || {};
this.options.channels = this.options.channels || [];
this.options.host = this.options.host || "127.0.0.1";
this.options.port = this.options.port || 6667;
this.options.ssl = this.options.ssl || false;
this.options.selfSigned = this.options.selfSigned || false;
this.options.sasl = this.options.sasl || false;
this.network = this.options.network || "test";
this.nickname = this.options.nickname || "test";
this.username = this.options.username || "test";
this.realname = this.options.realname || "test";
this.channels = this.options.channels || [];
this._recachetime = 60 * 5; // 5 minutes
this._cmd = new Map();
const files = fs.readdirSync(`${__dirname}/irc/`);
for(let file in files) {
if(files[file].substr(-3, 3) === ".js") {
logger.debug(`(${this.network}) loading cmd: ${files[file]}`);
require(`${__dirname}/irc/${files[file]}`)(this);
}
}
this.server = {
motd: "",
me: {},
channel: [],
user: new Map()
};
this.socket = (this.options.ssl ? tls : net).connect({
host: this.options.host,
port: this.options.port,
rejectUnauthorized: !this.options.selfSigned
}, () => {
this.send(`NICK ${this.nickname}`);
this.send(`USER ${this.username} 0 * : ${this.realname}`);
if(this.options.sasl)
this.send("CAP LS");
});
this.socket.setEncoding("utf-8");
this.socket.on("data", msg => {
msg = msg.split(/\r?\n|\r/);
for(let tmp in msg) {
if(msg[tmp].length > 0) {
const cmd = this.parse(msg[tmp]);
if(this._cmd.has(cmd.command))
this._cmd.get(cmd.command)(cmd);
}
}
});
}
send(data) {
this.socket.write(`${data}\n`);
logger.debug(`(${this.network}) out: ${data}`);
}
parse(data, [a, ...b] = data.split(/ +:/)) {
let tmp = a.split(" ").concat(b);
logger.debug(`(${this.network}) in: ${[...tmp]}`);
return data.charAt(0) === ":" ? {
prefix: tmp.shift(),
command: tmp.shift(),
params: tmp
} : {
prefix: null,
command: tmp.shift(),
params: tmp
};
}
reply(tmp) {
return {
type: "irc",
network: this.network,
channel: tmp.params[0],
user: this.parsePrefix(tmp.prefix),
message: tmp.params[1],
time: ~~(Date.now() / 1000),
raw: tmp,
reply: msg => this.send(`PRIVMSG ${tmp.params[0]} :${this.format(""+msg)}`),
replyAction: msg => this.send(`PRIVMSG ${tmp.params[0]} :\u0001ACTION ${this.format(""+msg)}\u0001`),
replyNotice: msg => this.send(`NOTICE ${tmp.params[0]} :${this.format(""+msg)}`),
_chan: this.server.channel[tmp.params[0]],
_user: this.server.user,
_cmd: this._cmd,
join: chan => this.join(chan),
part: (chan, msg) => this.part(chan, msg),
whois: user => this.whois(user),
write: msg => this.send(msg)
};
}
join(channel) {
this.send(`JOIN ${(typeof channel === "object") ? channel.join(",") : channel}`);
}
part(channel, msg=false) {
this.send(`PART ${(typeof channel === "object") ? channel.join(",") : channel}${msg ? " " + msg : " part"}`);
}
whois(user, force = false) {
user = user.toLowerCase();
if(this.server.user.hasi(user) && !force)
if(this.server.user.geti(user).cached >= ~~(Date.now() / 1000) - this._recachetime)
return;
this.send(`WHOIS ${user}`);
}
parsePrefix(prefix) {
prefix = /:?(.*)\!(.*)@(.*)/.exec(prefix);
return {
nick: prefix[1],
username: prefix[2],
hostname: prefix[3]
};
}
format(msg) {
return msg;
/*return msg
.replace(/\[b\](.*?)\[\/b\]/g, "\x02$1\x0F") // bold
.replace(/\[i\](.*?)\[\/i\]/g, "\x1D$1\x0F") // italic
;*/
}
}
module.exports = irc;
util.inherits(irc, EventEmitter);
Map.prototype.hasi = function(val) {
for (let [key] of this)
if(key.toLowerCase() === val.toLowerCase())
return true;
return false;
};
Map.prototype.geti = function(val) {
for (let [key, value] of this)
if(key.toLowerCase() === val.toLowerCase())
return value;
return false;
};
Map.prototype.deli = function(val) {
for (let [key] of this)
if(key.toLowerCase() === val.toLowerCase())
this.delete(key);
};