mirror of
https://git.sr.ht/~emersion/gamja
synced 2024-11-28 18:45:51 -05:00
Add support for WHOX
This allows querying the account of the user.
This commit is contained in:
parent
0b32d9295a
commit
329f9063d0
4 changed files with 105 additions and 17 deletions
|
@ -585,8 +585,7 @@ export default class App extends Component {
|
|||
continue;
|
||||
}
|
||||
this.createBuffer(serverID, buf.name);
|
||||
client.who(buf.name);
|
||||
client.monitor(buf.name);
|
||||
this.whoUserBuffer(buf.name, serverID);
|
||||
}
|
||||
|
||||
let lastReceipt = this.latestReceipt(ReceiptType.DELIVERED);
|
||||
|
@ -853,6 +852,15 @@ export default class App extends Component {
|
|||
});
|
||||
}
|
||||
|
||||
whoUserBuffer(target, serverID) {
|
||||
let client = this.clients.get(serverID);
|
||||
|
||||
client.who(target, {
|
||||
fields: ["flags", "hostname", "nick", "realname", "username", "account"],
|
||||
});
|
||||
client.monitor(target);
|
||||
}
|
||||
|
||||
open(target, serverID) {
|
||||
if (!serverID) {
|
||||
serverID = State.getActiveServerID(this.state);
|
||||
|
@ -865,8 +873,7 @@ export default class App extends Component {
|
|||
this.switchToChannel = target;
|
||||
client.send({ command: "JOIN", params: [target] });
|
||||
} else {
|
||||
client.who(target);
|
||||
client.monitor(target);
|
||||
this.whoUserBuffer(target, serverID);
|
||||
this.createBuffer(serverID, target);
|
||||
this.switchBuffer({ server: serverID, name: target });
|
||||
}
|
||||
|
|
|
@ -30,7 +30,21 @@ const NORMAL_CLOSURE = 1000;
|
|||
const GOING_AWAY = 1001;
|
||||
const UNSUPPORTED_DATA = 1003;
|
||||
|
||||
// See https://github.com/quakenet/snircd/blob/master/doc/readme.who
|
||||
// Sorted by order of appearance in RPL_WHOSPCRPL
|
||||
const WHOX_FIELDS = {
|
||||
"channel": "c",
|
||||
"username": "u",
|
||||
"hostname": "h",
|
||||
"server": "s",
|
||||
"nick": "n",
|
||||
"flags": "f",
|
||||
"account": "a",
|
||||
"realname": "r",
|
||||
};
|
||||
|
||||
let lastLabel = 0;
|
||||
let lastWhoxToken = 0;
|
||||
|
||||
export default class Client extends EventTarget {
|
||||
static Status = {
|
||||
|
@ -65,6 +79,7 @@ export default class Client extends EventTarget {
|
|||
cm = irc.CaseMapping.RFC1459;
|
||||
monitored = new irc.CaseMapMap(null, irc.CaseMapping.RFC1459);
|
||||
whoisDB = new irc.CaseMapMap(null, irc.CaseMapping.RFC1459);
|
||||
whoxQueries = new Map();
|
||||
|
||||
constructor(params) {
|
||||
super();
|
||||
|
@ -332,14 +347,43 @@ export default class Client extends EventTarget {
|
|||
}
|
||||
}
|
||||
|
||||
who(mask) {
|
||||
let msg = { command: "WHO", params: [mask] };
|
||||
who(mask, options) {
|
||||
let params = [mask];
|
||||
|
||||
let fields = "", token = "";
|
||||
if (options && this.isupport.has("WHOX")) {
|
||||
let match = ""; // Matches exact channel or nick
|
||||
|
||||
fields = "t"; // Always include token in reply
|
||||
if (options.fields) {
|
||||
options.fields.forEach((k) => {
|
||||
if (!WHOX_FIELDS[k]) {
|
||||
throw new Error(`Unknown WHOX field ${k}`);
|
||||
}
|
||||
fields += WHOX_FIELDS[k];
|
||||
});
|
||||
}
|
||||
|
||||
token = String(lastWhoxToken % 1000);
|
||||
lastWhoxToken++;
|
||||
|
||||
params.push(`${match}%${fields},${token}`);
|
||||
this.whoxQueries.set(token, fields);
|
||||
}
|
||||
|
||||
let msg = { command: "WHO", params };
|
||||
let l = [];
|
||||
return this.roundtrip(msg, (msg) => {
|
||||
switch (msg.command) {
|
||||
case irc.RPL_WHOREPLY:
|
||||
// TODO: match with mask
|
||||
l.push(msg);
|
||||
l.push(this.parseWhoReply(msg));
|
||||
break;
|
||||
case irc.RPL_WHOSPCRPL:
|
||||
if (msg.params.length !== fields.length || msg.params[1] !== token) {
|
||||
break;
|
||||
}
|
||||
l.push(this.parseWhoReply(msg));
|
||||
break;
|
||||
case irc.RPL_ENDOFWHO:
|
||||
if (msg.params[1] === mask) {
|
||||
|
@ -347,9 +391,45 @@ export default class Client extends EventTarget {
|
|||
}
|
||||
break;
|
||||
}
|
||||
}).finally(() => {
|
||||
this.whoxQueries.delete(token);
|
||||
});
|
||||
}
|
||||
|
||||
parseWhoReply(msg) {
|
||||
switch (msg.command) {
|
||||
case irc.RPL_WHOREPLY:
|
||||
let last = msg.params[msg.params.length - 1];
|
||||
return {
|
||||
username: msg.params[2],
|
||||
hostname: msg.params[3],
|
||||
server: msg.params[4],
|
||||
nick: msg.params[5],
|
||||
flags: msg.params[6],
|
||||
realname: last.slice(last.indexOf(" ") + 1),
|
||||
};
|
||||
case irc.RPL_WHOSPCRPL:
|
||||
let token = msg.params[1];
|
||||
let fields = this.whoxQueries.get(token);
|
||||
if (!fields) {
|
||||
throw new Error("Unknown WHOX token: " + token);
|
||||
}
|
||||
let who = {};
|
||||
let i = 0;
|
||||
Object.keys(WHOX_FIELDS).forEach((k) => {
|
||||
if (fields.indexOf(WHOX_FIELDS[k]) < 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
who[k] = msg.params[2 + i];
|
||||
i++;
|
||||
});
|
||||
return who;
|
||||
default:
|
||||
throw new Error("Not a WHO reply: " + msg.command);
|
||||
}
|
||||
}
|
||||
|
||||
whois(target) {
|
||||
let targetCM = this.cm(target);
|
||||
let msg = { command: "WHOIS", params: [target] };
|
||||
|
|
|
@ -23,6 +23,7 @@ export const RPL_EXCEPTLIST = "348";
|
|||
export const RPL_ENDOFEXCEPTLIST = "349";
|
||||
export const RPL_WHOREPLY = "352";
|
||||
export const RPL_NAMREPLY = "353";
|
||||
export const RPL_WHOSPCRPL = "354";
|
||||
export const RPL_ENDOFNAMES = "366";
|
||||
export const RPL_BANLIST = "367";
|
||||
export const RPL_ENDOFBANLIST = "368";
|
||||
|
|
20
state.js
20
state.js
|
@ -363,16 +363,16 @@ export const State = {
|
|||
case irc.RPL_ENDOFNAMES:
|
||||
break;
|
||||
case irc.RPL_WHOREPLY:
|
||||
let last = msg.params[msg.params.length - 1];
|
||||
who = {
|
||||
username: msg.params[2],
|
||||
hostname: msg.params[3],
|
||||
server: msg.params[4],
|
||||
nick: msg.params[5],
|
||||
away: msg.params[6] == 'G', // H for here, G for gone
|
||||
realname: last.slice(last.indexOf(" ") + 1),
|
||||
offline: false,
|
||||
};
|
||||
case irc.RPL_WHOSPCRPL:
|
||||
let who = client.parseWhoReply(msg);
|
||||
|
||||
if (who.flags !== undefined) {
|
||||
who.away = who.flags.indexOf("G") >= 0; // H for here, G for gone
|
||||
delete who.flags;
|
||||
}
|
||||
|
||||
who.offline = false;
|
||||
|
||||
return updateUser(who.nick, who);
|
||||
case irc.RPL_ENDOFWHO:
|
||||
target = msg.params[1];
|
||||
|
|
Loading…
Reference in a new issue