mirror of
https://git.sr.ht/~emerson/reflectionircd
synced 2025-04-13 09:59:52 +00:00
123 lines
No EOL
3.8 KiB
TypeScript
123 lines
No EOL
3.8 KiB
TypeScript
export class IRCMessage {
|
|
constructor(
|
|
public tags: Map<string, string>,
|
|
public prefix: string,
|
|
public command: string,
|
|
public params: string[],
|
|
) {}
|
|
toString() {
|
|
let messageString = '';
|
|
if (this.tags.size !== 0) {
|
|
let tagArray = [];
|
|
for (const [key, value] of this.tags) {
|
|
if (value === '') {
|
|
tagArray.push(key);
|
|
}
|
|
else {
|
|
tagArray.push(`${key}=${encodeTag(value)}`);
|
|
}
|
|
}
|
|
messageString = `@${tagArray.join(";")} `;
|
|
}
|
|
|
|
if (this.prefix) {
|
|
messageString = `${messageString}:${this.prefix} `;
|
|
}
|
|
|
|
messageString = `${messageString}${this.command}`;
|
|
|
|
const params = this.params.slice();
|
|
|
|
let lastParam = params.pop();
|
|
if (lastParam) {
|
|
if (lastParam.indexOf(' ') !== -1) {
|
|
lastParam = `:${lastParam}`;
|
|
}
|
|
params.push(lastParam);
|
|
}
|
|
messageString = `${messageString} ${params.join(' ')}`;
|
|
return messageString;
|
|
}
|
|
}
|
|
|
|
function decodeTag(value: string): string {
|
|
const tagDecodeMap = new Map([
|
|
['\\:', ';'],
|
|
['\\s', ' '],
|
|
['\\\\', '\\'],
|
|
['\\r', '\r'],
|
|
['\\n', '\n'],
|
|
['\\', ''],
|
|
]);
|
|
return value.replace(/\\:|\\s|\\\\|\\r|\\n|\\/gi, t => tagDecodeMap.get(t) || '')
|
|
}
|
|
|
|
function encodeTag(value: string): string {
|
|
const tagEncodeMap = new Map([
|
|
[';', '\\:'],
|
|
[' ', '\\s'],
|
|
['\\', '\\\\'],
|
|
['\r', '\\r'],
|
|
['\n', '\\n'],
|
|
]);
|
|
return value.replace(/;| |\\|\r|\n/gi, t => tagEncodeMap.get(t) || '');
|
|
}
|
|
|
|
function addToTags(key: string): boolean {
|
|
const tagsToPass = [
|
|
'batch',
|
|
'reflectionircd.chat/delete-message',
|
|
'reflectionircd.chat/edit-message',
|
|
'label',
|
|
]
|
|
return (tagsToPass.includes(key) || key.startsWith('+'));
|
|
}
|
|
|
|
export function parseIRCMessage(rawLine: string) {
|
|
//console.log(`RAW: ${rawLine}`);
|
|
let restOfMessage = rawLine;
|
|
let parsedTags: Map<string, string> = new Map();
|
|
let prefix = '';
|
|
let command = '';
|
|
let params: string[] = [];
|
|
if (rawLine.startsWith('@')) {
|
|
const tags = restOfMessage.substring(1, restOfMessage.indexOf(' '));
|
|
restOfMessage = restOfMessage.substring(restOfMessage.indexOf(' ')+1);
|
|
for (const tag of tags.split(';')) {
|
|
const valueSplit = tag.indexOf('=');
|
|
if (valueSplit === -1 && addToTags(tag)) {
|
|
parsedTags.set(tag, '');
|
|
continue;
|
|
}
|
|
const key = tag.substring(0, valueSplit);
|
|
const value = tag.substring(valueSplit+1);
|
|
if (addToTags(key))
|
|
parsedTags.set(key, decodeTag(value));
|
|
}
|
|
}
|
|
if (restOfMessage.startsWith(':')) {
|
|
prefix = restOfMessage.substring(0, restOfMessage.indexOf(' '));
|
|
restOfMessage = restOfMessage.substring(restOfMessage.indexOf(' ')+1);
|
|
}
|
|
|
|
if (restOfMessage.indexOf(' ') === -1) {
|
|
command = restOfMessage;
|
|
return new IRCMessage(parsedTags, prefix, command, params);
|
|
}
|
|
|
|
command = restOfMessage.substring(0, restOfMessage.indexOf(' '));
|
|
restOfMessage = restOfMessage.substring(restOfMessage.indexOf(' ') + 1);
|
|
|
|
let lastParam = '';
|
|
if (restOfMessage.indexOf(' :') !== -1) {
|
|
lastParam = restOfMessage.substring(restOfMessage.indexOf(' :') + 2);
|
|
restOfMessage = restOfMessage.substring(0, restOfMessage.indexOf(' :'));
|
|
}
|
|
|
|
params = restOfMessage.split(' ');
|
|
if (lastParam !== '') {
|
|
params.push(lastParam);
|
|
}
|
|
//console.log(parsedTags, prefix, command, params);
|
|
return new IRCMessage(parsedTags, prefix, command, params);
|
|
} |