mirror of
https://git.sr.ht/~emersion/gamja
synced 2024-11-14 11:15:13 -05:00
wip: implement case-mapping
This commit is contained in:
parent
22e54dac56
commit
7ce98e0e90
2 changed files with 133 additions and 2 deletions
|
@ -161,7 +161,18 @@ export default class Client extends EventTarget {
|
|||
break;
|
||||
case irc.RPL_ISUPPORT:
|
||||
var tokens = msg.params.slice(1, -1);
|
||||
irc.parseISUPPORT(tokens, this.isupport);
|
||||
var changed = irc.parseISUPPORT(tokens, this.isupport);
|
||||
if (changed.indexOf("CASEMAPPING") >= 0) {
|
||||
this.setCaseMapping(this.isupport.get("CASEMAPPING"));
|
||||
}
|
||||
break;
|
||||
case irc.RPL_ENDOFMOTD:
|
||||
case irc.ERR_NOMOTD:
|
||||
// These messages are used to indicate the end of the ISUPPORT list
|
||||
if (!this.isupport.has("CASEMAPPING")) {
|
||||
// Server didn't send any CASEMAPPING token, assume RFC 1459
|
||||
this.setCaseMapping("rfc1459");
|
||||
}
|
||||
break;
|
||||
case "CAP":
|
||||
this.handleCap(msg);
|
||||
|
@ -358,6 +369,14 @@ export default class Client extends EventTarget {
|
|||
console.log("Sent:", msg);
|
||||
}
|
||||
|
||||
setCaseMapping(name) {
|
||||
this.cm = irc.CaseMapping.byName(name);
|
||||
if (!this.cm) {
|
||||
console.error("Unsupported case-mapping '" + name + "', falling back to RFC 1459");
|
||||
this.cm = irc.CaseMapping.RFC1459;
|
||||
}
|
||||
}
|
||||
|
||||
/* Execute a command that expects a response. `done` is called with message
|
||||
* events until it returns a truthy value. */
|
||||
roundtrip(msg, done) {
|
||||
|
|
114
lib/irc.js
114
lib/irc.js
|
@ -11,6 +11,7 @@ export const RPL_TOPICWHOTIME = "333";
|
|||
export const RPL_WHOREPLY = "352";
|
||||
export const RPL_NAMREPLY = "353";
|
||||
export const RPL_ENDOFNAMES = "366";
|
||||
export const RPL_ENDOFMOTD = "376";
|
||||
export const ERR_NOMOTD = "422";
|
||||
export const ERR_ERRONEUSNICKNAME = "432";
|
||||
export const ERR_NICKNAMEINUSE = "433";
|
||||
|
@ -320,6 +321,7 @@ export function parseCTCP(msg) {
|
|||
}
|
||||
|
||||
export function parseISUPPORT(tokens, params) {
|
||||
var changed = [];
|
||||
tokens.forEach((tok) => {
|
||||
if (tok.startsWith("-")) {
|
||||
var k = tok.slice(1);
|
||||
|
@ -333,6 +335,116 @@ export function parseISUPPORT(tokens, params) {
|
|||
k = tok.slice(0, i);
|
||||
v = tok.slice(i + 1);
|
||||
}
|
||||
params.set(k.toUpperCase(), v);
|
||||
|
||||
k = k.toUpperCase();
|
||||
|
||||
params.set(k, v);
|
||||
changed.push(k);
|
||||
});
|
||||
return changed;
|
||||
}
|
||||
|
||||
export const CaseMapping = {
|
||||
ASCII(str) {
|
||||
var out = "";
|
||||
for (var i = 0; i < out.length; i++) {
|
||||
var ch = str[i];
|
||||
if ("A" <= ch && ch <= "Z") {
|
||||
ch = ch.toLowerCase();
|
||||
}
|
||||
out += ch;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
RFC1459(str) {
|
||||
var out = "";
|
||||
for (var i = 0; i < out.length; i++) {
|
||||
var ch = str[i];
|
||||
if ("A" <= ch && ch <= "Z") {
|
||||
ch = ch.toLowerCase();
|
||||
} else if (ch == "{") {
|
||||
ch = "[";
|
||||
} else if (ch == "}") {
|
||||
ch = "]";
|
||||
} else if (ch == "\\") {
|
||||
ch = "|";
|
||||
} else if (ch == "~") {
|
||||
ch = "^";
|
||||
}
|
||||
out += ch;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
RFC1459Strict(str) {
|
||||
var out = "";
|
||||
for (var i = 0; i < out.length; i++) {
|
||||
var ch = str[i];
|
||||
if ("A" <= ch && ch <= "Z") {
|
||||
ch = ch.toLowerCase();
|
||||
} else if (ch == "{") {
|
||||
ch = "[";
|
||||
} else if (ch == "}") {
|
||||
ch = "]";
|
||||
} else if (ch == "\\") {
|
||||
ch = "|";
|
||||
}
|
||||
out += ch;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
byName(name) {
|
||||
switch (name) {
|
||||
case "ascii":
|
||||
return CaseMapping.ASCII;
|
||||
case "rfc1459":
|
||||
return CaseMapping.RFC1459;
|
||||
case "rfc1459-strict":
|
||||
return CaseMapping.RFC1459Strict;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export class CaseMapMap {
|
||||
caseMap: null,
|
||||
map: new Map(),
|
||||
|
||||
constructor(caseMap, iterable) {
|
||||
this.caseMap = caseMap;
|
||||
|
||||
for (var [key, value] of iterable) {
|
||||
this.set(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
has(key) {
|
||||
return this.map.has(this.caseMap(key));
|
||||
}
|
||||
|
||||
get(key) {
|
||||
var value = this.map.get(this.caseMap(key));
|
||||
if (value) {
|
||||
return value.value;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
set(key, value) {
|
||||
this.map.set(this.caseMap(key), { key, value });
|
||||
}
|
||||
|
||||
[Symbol.iterator]() {
|
||||
var it = this.map.entries();
|
||||
return {
|
||||
next: () => {
|
||||
var { value, done } = it.next();
|
||||
if (done) {
|
||||
return { done: true };
|
||||
}
|
||||
return { value: [value[1].key, value[1].value], done: false };
|
||||
},
|
||||
};
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue