irctokens
Version:
RFC1459 and IRCv3 protocol tokeniser
138 lines • 4.08 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.Line = void 0;
exports.tokenise = tokenise;
const const_1 = require("./const");
const formatting_1 = require("./formatting");
const hostmask_1 = require("./hostmask");
class Line {
tags;
source;
command;
params;
constructor({ tags, source, command, params }) {
this.tags = tags;
this.source = source;
this.command = command;
this.params = params;
}
#hostmask;
get hostmask() {
if (this.source) {
if (!this.#hostmask)
this.#hostmask = (0, hostmask_1.hostmask)(this.source);
return this.#hostmask;
}
else {
throw new TypeError('cannot parse hostmask from null source');
}
}
format() {
return (0, formatting_1.format)({
tags: this.tags,
source: this.source,
command: this.command,
params: this.params,
});
}
withSource(source) {
return new Line({
tags: this.tags,
source,
command: this.command,
params: this.params,
});
}
copy() {
return new Line(this);
}
}
exports.Line = Line;
function unescapeTag(value) {
let unescaped = '';
if (!value)
return unescaped;
const escaped = value.split('');
while (escaped.length) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const current = escaped.shift();
if (current === '\\') {
if (escaped.length) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const next = escaped.shift();
const duo = `${current}${next}`;
const index = const_1.TAG_ESCAPED.indexOf(duo);
if (index > -1)
unescaped += const_1.TAG_UNESCAPED[index];
else
unescaped += next;
}
}
else {
unescaped += current;
}
}
return unescaped;
}
function _tokenise(line) {
let value = line;
let tags;
if (value.startsWith('@')) {
let tagsS;
[tagsS, value] = value.substring(1).split(/ (.*)/);
tags = {};
for (const part of tagsS.split(';')) {
const [key, val] = part.split(/=(.*)/);
tags[key] = unescapeTag(val);
}
}
let trailing;
[value, trailing] = value.split(/ :(.*)/);
const params = value.split(' ').filter(part => !!part);
let source;
if (params[0].startsWith(':')) {
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
source = (params.shift()).substring(1);
}
if (!params.length)
throw TypeError('Cannot tokenise command-less line');
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
const command = (params.shift()).toLocaleUpperCase();
if (typeof trailing === 'string')
params.push(trailing);
return new Line({
tags,
source,
command,
params,
});
}
function tokenise(line, encoding = 'utf8', fallback = 'latin1') {
let dline = '';
const decoder = new TextDecoder(encoding, { fatal: true });
const fallbackDecoder = new TextDecoder(fallback, { fatal: true });
if (line instanceof Uint8Array) {
if (line[0] === '@'.charCodeAt(0)) {
const idx = line.indexOf(' '.charCodeAt(0));
const tagsB = line.slice(0, idx + 1);
line = line.slice(idx + 1);
dline += decoder.decode(tagsB);
}
try {
dline += decoder.decode(line);
}
catch {
dline += fallbackDecoder.decode(line);
}
}
else {
dline = line;
}
for (const badchar of ['\x00', '\r', '\n']) {
if (dline.includes(badchar)) {
[dline] = dline.split(badchar);
}
}
return _tokenise(dline);
}
//# sourceMappingURL=line.js.map