Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions changelog.d/110.misc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Include any certfp lines in a whois response.
4 changes: 4 additions & 0 deletions src/codes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,10 @@ export const replyCodes = {
name: 'rpl_globalusers',
type: 'reply'
},
276: {
name: 'rpl_whoiscertfp',
type: 'reply',
},
300: {
name: 'rpl_none',
type: 'reply'
Expand Down
23 changes: 15 additions & 8 deletions src/irc.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1052,6 +1052,8 @@ export class Client extends (EventEmitter as unknown as new () => TypedEmitter<C
return this._addWhoisData(message.args[1], 'serverinfo', message.args[3]);
case 'rpl_whoisactually':
return this._addWhoisData(message.args[1], 'realHost', message.args[2]);
case 'rpl_whoiscertfp':
return this._addWhoisData(message.args[1], 'certfp', message.args[2]);
case 'rpl_whoisoperator':
return this._addWhoisData(message.args[1], 'operator', message.args[2]);
case 'rpl_whoisaccount':
Expand Down Expand Up @@ -1452,6 +1454,7 @@ export class Client extends (EventEmitter as unknown as new () => TypedEmitter<C
* unmaps the client instance from the socket. The state will also need to be cleared up seperately.
*/
public destroy() {
util.log('Destroying connection');
(
['data', 'end', 'close', 'timeout', 'error'] as (keyof IrcConnectionEventsMap)[]
).forEach(evtType => {
Expand Down Expand Up @@ -1690,14 +1693,18 @@ export class Client extends (EventEmitter as unknown as new () => TypedEmitter<C
return this.send('LIST', ...args);
}

private _addWhoisData(nick: string, key: keyof(WhoisResponse), value: string|string[], onlyIfExists = false) {
if (onlyIfExists && !this.state.whoisData.has(nick)) {return;}
const data: WhoisResponse = {
...this.state.whoisData.get(nick),
nick,
[key]: value,
};
this.state.whoisData.set(nick, data);
private _addWhoisData<
K extends keyof(WhoisResponse),
V extends WhoisResponse[K]>(nick: string, key: K, value: V, onlyIfExists = false) {
let data: WhoisResponse|undefined = this.state.whoisData.get(nick);
if (onlyIfExists && !data) {
return;
}
else if (!data) {
data = { nick };
this.state.whoisData.set(nick, data);
}
data[key] = value;
}

private _clearWhoisData(nick: string) {
Expand Down
1 change: 1 addition & 0 deletions src/state.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface WhoisResponse {
account?: string;
accountinfo?: string;
realHost?: string;
certfp?: string;
}

export interface IrcSupported {
Expand Down
8 changes: 6 additions & 2 deletions src/testing/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { randomUUID } from 'crypto';
import { Client, ClientEvents, Message } from '..';
import { Client, ClientEvents, IrcClientOpts, Message } from '..';

const DEFAULT_PORT = parseInt(process.env.IRC_TEST_PORT ?? '6667', 10);
const DEFAULT_ADDRESS = process.env.IRC_TEST_ADDRESS ?? "127.0.0.1";
Expand Down Expand Up @@ -75,7 +75,10 @@ export class TestIrcServer {
}

public readonly clients: Record<string, TestClient> = {};
constructor(public readonly address = DEFAULT_ADDRESS, public readonly port = DEFAULT_PORT) { }
constructor(
public readonly address = DEFAULT_ADDRESS, public readonly port = DEFAULT_PORT,
public readonly customConfig: Partial<IrcClientOpts> = {}
) { }

async setUp(clients = ['speaker', 'listener']) {
const connections: Promise<void>[] = [];
Expand All @@ -86,6 +89,7 @@ export class TestIrcServer {
autoConnect: false,
connectionTimeout: 4000,
debug: true,
...this.customConfig,
});
this.clients[clientName] = client;
// Make sure we load isupport before reporting readyness.
Expand Down