@@ -328,12 +328,29 @@ const handlers = {
328
328
329
329
RPL_WHOWASUSER : function ( command , handler ) {
330
330
const cache_key = command . params [ 1 ] . toLowerCase ( ) ;
331
- const cache = handler . cache ( 'whois.' + cache_key ) ;
331
+ let whois_cache = handler . cache ( 'whois.' + cache_key ) ;
332
+
333
+ // multiple RPL_WHOWASUSER replies are received prior to the RPL_ENDOFWHOWAS command
334
+ // one for each timestamp the server is aware of, from newest to oldest.
335
+ // They are optionally interleaved with various other numerics such as RPL_WHOISACTUALLY etc.
336
+ // Hence if we already find something we are receiving older data and need to make sure that we
337
+ // store anything already in the cache into its own entry
338
+ const whowas_cache = handler . cache ( 'whowas.' + cache_key ) ;
339
+ if ( ! whowas_cache . whowas ) {
340
+ // this will get populated by the next RPL_WHOWASUSER or RPL_ENDOFWHOWAS
341
+ whowas_cache . whowas = [ ] ;
342
+ } else {
343
+ // push the previous event prior to modifying anything
344
+ whowas_cache . whowas . push ( whois_cache ) ;
345
+ // ensure we are starting with a clean cache for the next data
346
+ whois_cache . destroy ( ) ;
347
+ whois_cache = handler . cache ( 'whois.' + cache_key ) ;
348
+ }
332
349
333
- cache . nick = command . params [ 1 ] ;
334
- cache . ident = command . params [ 2 ] ;
335
- cache . hostname = command . params [ 3 ] ;
336
- cache . real_name = command . params [ command . params . length - 1 ] ;
350
+ whois_cache . nick = command . params [ 1 ] ;
351
+ whois_cache . ident = command . params [ 2 ] ;
352
+ whois_cache . hostname = command . params [ 3 ] ;
353
+ whois_cache . real_name = command . params [ command . params . length - 1 ] ;
337
354
} ,
338
355
339
356
RPL_ENDOFWHOWAS : function ( command , handler ) {
@@ -347,16 +364,22 @@ const handlers = {
347
364
// server_info, actual_username
348
365
// More optional fields MAY exist, depending on the type of ircd.
349
366
const cache_key = command . params [ 1 ] . toLowerCase ( ) ;
350
- const cache = handler . cache ( 'whois.' + cache_key ) ;
351
-
352
- // Should, in theory, never happen.
353
- if ( ! cache . nick ) {
354
- cache . nick = command . params [ 1 ] ;
355
- cache . error = 'no_such_nick' ;
367
+ const whois_cache = handler . cache ( 'whois.' + cache_key ) ;
368
+ const whowas_cache = handler . cache ( 'whowas.' + cache_key ) ;
369
+
370
+ // after all prior RPL_WHOWASUSER pushed newer events onto the history stack
371
+ // push the last one to complete the set (server returns from newest to oldest)
372
+ whowas_cache . whowas = whowas_cache . whowas || [ ] ;
373
+ if ( ! whois_cache . error ) {
374
+ whowas_cache . whowas . push ( whois_cache ) ;
375
+ Object . assign ( whowas_cache , whowas_cache . whowas [ 0 ] ) ;
376
+ } else {
377
+ Object . assign ( whowas_cache , whois_cache ) ;
356
378
}
357
379
358
- handler . emit ( 'whowas' , cache ) ;
359
- cache . destroy ( ) ;
380
+ handler . emit ( 'whowas' , whowas_cache ) ;
381
+ whois_cache . destroy ( ) ;
382
+ whowas_cache . destroy ( ) ;
360
383
} ,
361
384
362
385
ERR_WASNOSUCHNICK : function ( command , handler ) {
0 commit comments