Skip to content

Commit

Permalink
Add /who handling
Browse files Browse the repository at this point in the history
irc-framework sends the WHOX cuhsnfdaor flags and doesn't support receiving others, so we manually remove parameters the user doesn't request.

I also added an uncaught exception handler on the server to stop a subset of crashes. The problem is people won't look at their server logs often, but bookworm and I agreed that's better than crashing. When we add an admin role we can report it to them.

https://ircv3.net/specs/extensions/whox

ref kiwiirc/irc-framework#331
  • Loading branch information
MaxLeiter committed Sep 8, 2022
1 parent 0fa2035 commit 96d96d1
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 8 deletions.
18 changes: 10 additions & 8 deletions client/components/MessageTypes/whois.vue
@@ -1,6 +1,6 @@
<template>
<span class="content">
<p>
<p v-if="message.whois.nick">
<Username :user="{nick: message.whois.nick}" />
<span v-if="message.whois.whowas"> is offline, last information:</span>
</p>
Expand All @@ -11,13 +11,15 @@
<dd>{{ message.whois.account }}</dd>
</template>

<dt>Host mask:</dt>
<dd class="hostmask">
<ParsedMessage
:network="network"
:text="message.whois.ident + '@' + message.whois.hostname"
/>
</dd>
<template v-if="message.whois.ident && message.whois.hostname">
<dt>Host mask:</dt>
<dd class="hostmask">
<ParsedMessage
:network="network"
:text="message.whois.ident + '@' + message.whois.hostname"
/>
</dd>
</template>

<template v-if="message.whois.actual_hostname">
<dt>Actual host:</dt>
Expand Down
1 change: 1 addition & 0 deletions server/plugins/inputs/index.ts
Expand Up @@ -55,6 +55,7 @@ const builtInInputs = [
"raw",
"rejoin",
"topic",
"who",
"whois",
"mute",
];
Expand Down
89 changes: 89 additions & 0 deletions server/plugins/inputs/who.ts
@@ -0,0 +1,89 @@
import {ClientUser} from "../../../client/js/types";
import Msg, {MessageType} from "../../models/msg";
import {PluginInputHandler} from "./index";

const commands = ["who"];

const parseWhoxResponse = (user: ClientUser, args: string) => {
const parseFieldNameForLounge = (field: string) => {
switch (field) {
case "channel":
return "channel"; // no-op for now
case "nickname":
return "nick";
case "username":
return "account";
case "realname":
return "real_name";
case "op":
return "operator";
default:
return field;
}
};

const whoxFields = {
c: "channel",
u: "username",
h: "hostname",
s: "server",
n: "nickname",
f: "flags",
a: "account",
r: "realname",
};

if (!args) {
return user;
}

const filteredResponse = {};

for (const [token, fieldName] of Object.entries(whoxFields)) {
// TODO: throw on unknown field?
if (args.includes(token)) {
const expectedField = parseFieldNameForLounge(fieldName);
filteredResponse[expectedField] = user[expectedField];
}
}

return filteredResponse;
};

const input: PluginInputHandler = function ({irc}, chan, cmd, args) {
if (args.length === 0) {
return;
}

// We use the callback instead of listening for `wholist` because
// irc-framework doesn't support filtering WHOX.
// This has the added benefit of easily showing it in the same buffer
// as the WHO command.
irc.who(args[0], (event) => {
if (!event.users.length) {
chan.pushMessage(
this,
new Msg({
type: MessageType.ERROR,
text: `The server returned no matching users for ${args[0]}`,
})
);
}

for (const user of event.users) {
const filteredResponse = parseWhoxResponse(user, args[1]);
chan.pushMessage(
this,
new Msg({
type: MessageType.WHOIS,
whois: filteredResponse,
})
);
}
});
};

export default {
commands,
input,
};

0 comments on commit 96d96d1

Please sign in to comment.