One form of simplification I could suggest is abusing regex for all this and avoid the while loops entirely.

While this doesn't go as deep as your /whois to grab sign-on time and reported server-idle, it's still a good example:
NOTE: looks bigger than what it is... remove the comments it's quite small.
Code
alias idl {
  ;== Set who we're going to check
  var %who = $1

  ;== 1st Regsubex: make a string of spaces one less than the number of common channels, replace the zero-width spots in-between with the common channel name
  ;== 2nd Regsubex: Find all "channels" within said string, replace it with [idle]:[modeprefix][channel]
  var %ret = $regsubex($regsubex($str($chr(32),$calc($comchan($me,0) -1)),//g,$comchan($me,\n)),/([^ ]+)/g,$+($nick(\1,%who).idle,:,$left($nick(\1,%who,a,r).pnick,1),\1))

  ;== prepend query/dcc-chat info to the end [idle]:[type]
  if ($query(%who)) { var %ret = %ret $+($query(%who).idle,:Query) }
  if ($chat(%who)) { var %ret = %ret $+($chat(%who).idle,:Chat) }

  ;== Regsubex: Sort all by number via $sorttok() (lowest idle) find [(digits)]:[(not space or end of string)] and reformat to <word>[<duration>]
  ;NOTE: we started each "token" with a number (idle) so we can hack $sorttok() in our favor. and use regsubex to "reformat" to your preference.
  var %ret = $regsubex($sorttok(%ret,32,n),/(\d+)\x3a([^ ]+|$)/g,$+(\2,[,$dur(\1),]))

  ;== return if called as an $identifier() else echo to active.
  ;NOTE: Here's where you could prepend your "sign-on" and "whois-idle" before %ret

  $iif($isid,return,echo -a) %ret
}

;== Forgot yours was posted in your snippet so I just whipped up this one....
alias dur { return $regsubex(dur,$duration($1),/([a-z]+|\s)/gi,$iif(\1 != $chr(32),$left(\1,1))) }

/idl Talon
+#minecraft[5m39s] Query[23m34s] %#swiftirc[24m44s] #programming[24m44s]