149 lines
4.5 KiB
JavaScript
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);
|
|
}; |