mIRC Homepage
Posted By: Solo1 who #channel - 07/03/08 12:13 PM
What is the best way to do a slow who on a really large channel without getting flooded off. Is there anyway of making a clean efficient alias to do this?
Posted By: RoCk Re: who #channel - 07/03/08 01:08 PM

You only have to /who the channel once, I don't think you can get any slower than that. If I'm misunderstanding your question, please elaborate.
Posted By: SladeKraven Re: who #channel - 07/03/08 01:37 PM
Not too sure if this is what they meant as I've not tried it and I'm not going to, but if there's too many users in a channel would you get flooded off by who'ing the channel?

Maybe something like

Code:
alias who. {
  var %x = 1, %y
  while (%x <= $nick($chan,0)) {
    inc %y
    .timer 1 $calc(%x + %y) who $nick($chan,%x)
    inc %x
  }
}
Posted By: RoCk Re: who #channel - 07/03/08 02:11 PM

But there's no need to do a /who on each individual nick when you can just /who #chan once. On a channel with 100 users, that 100 /who requests being sent rather than just 1. If mIRC is freezing, it's scripts and the /who results being displayed that's freezing it, so just halt the results from being displayed.

~ Edit ~
wb btw, ltns.
smile
Posted By: SladeKraven Re: who #channel - 07/03/08 02:24 PM
I know it's 100 /who's being sent but atleast it's somewhat delayed, not too sure if it's script related but I'd imagine trying to send too much may cause you to flood off.

And cheers. smile
Posted By: RoCk Re: who #channel - 07/03/08 02:45 PM

That's true, quickly joining several channels and sending a who request for each channel might do that. The OP could que the who requests...

Code:

on *:START:unset %chanwho.*
alias chanwho {
  ; Usage: /chanwho <chan>
  var %whochans = $eval($+(%,chanwho.,$network),2)
  if (!%whochans) {
    set -e $+(%,chanwho.,$network) $1
    who $1
  }
  elseif (!$istok(%whochans,$1,32)) set -e $+(%,chanwho.,$network) %whochans $1
}
raw 352:*: {
  if ($istok($eval($+(%,chanwho.,$network),2),$2,32)) haltdef
}
raw 315:*: {
  var %whochans = $eval($+(%,chanwho.,$network),2)
  if ($istok(%whochans,$2,32)) {
    haltdef
    set -e $+(%,chanwho.,$network) $remtok(%whochans,$2,1,32)
    if ($gettok($eval($+(%,chanwho.,$network),2),1,32)) .timer 1 5 who $v1
    else unset $+(%,chanwho.,$network)
  }
}



~ Edit ~
Set the timer to the delay you want.

~ Edit ~
Made it multi-network.


Posted By: SladeKraven Re: who #channel - 07/03/08 03:32 PM
That went completely over my head, being a way from mIRC for a while I've kinda lost the nack of it all. frown
Posted By: Solo1 Re: who #channel - 08/03/08 09:10 PM
Hi
Yes i meant if i /who #channel on really large channels (1000+ users) i get disconnected.
Posted By: Riamus2 Re: who #channel - 08/03/08 11:08 PM
If all you're doing is a /who on the entire channel, you won't get disconnected. If you're getting disconnected, then you have a script that's doing more than just a /who on the channel. Maybe it's doing a /who on each nick individually (as pointed out earlier in this thread), or you're sending some other information over the network for each nick. In either case, it's a script problem. If you show your script that does the /who and handles the RAW output of it, we could find where your problem is.
Posted By: MeStinkBAD Re: who #channel - 09/03/08 06:02 AM
You don't use /who you use /userhost! My God why isn't this just built into the client? Here I'll just post the entire file that does this for me.

Code:
; #== smirc -rs base.nickfreshen expands group root, class base.common;

;---------------------
#_DEFAULT.PROPERTIES OFF

[start]

[@info]
longname=      Channel Nicklist Refresher
author=        Dustin
authoremail=   
flags=

[description]
n1=ial refresher.mrc [IAL/NICKLIST STUFF]
n2=Part of an unnamed script package by Dustin Goeller. AKA LagMonster,DustBustR

[end]

#_DEFAULT.PROPERTIES END
;---------------------

alias -l  :MAXNICKSPERLINE     { return  5 }
alias -l  :MAXNICKSPERINTERVAL { return 15 }

;------------------------------------------

ON !:*:JOIN:*: {
  updatenick $nick $fulladdress
  hadd -m $markcid($+(NICKDATABASE,.,$chan)) $nick 0
}

;------

ON !:*:PART:*: {
  if ($comchan($nick,0)) {
    isaway - $+ $nick
    isoper - $+ $nick
  }
  hdel $markcid($+(NICKDATABASE,.,$chan)) $nick
}

;------

ON ME:*:PART:*: {
  var %i,%total,%nick
  var %tablename = $markcid(OPER.LIST)

  %total = $hget(%tablename,0)

  while (%i < %total) {
    inc %i

    if $comchan($hfind(%tablename,*,%i)) {
      %nick = $ifmatch
      if ($isnot($comchan(%nick,0)) || ($comchan(%nick,0) == 1) && ($comchan(%nick,1) == $chan)) {
        isoper - $+ %nick
      }
    }
  }

  %tablename = $markcid(AWAY.LIST)
  %total = $hget(%tablename,0)
  %i = 0

  while (%i < %total) {
    inc %i
    if $comchan($hfind(%tablename,*,%i)) {
      %nick = $ifmatch
      if ($isnot($comchan(%nick,0)) || ($comchan(%nick,0) == 1) && ($comchan(%nick,1) == $chan)) {
        isaway - $+ %nick
      }
    }
  }

  hfree $markcid($+(NICKDATABASE,.,$chan))
}

;------

ON !:*:QUIT:  {
  isaway - $+ $nick
  isoper - $+ $nick

  var %i = 0
  while (%i < $comchan($nick,0)) {
    inc %i
    hdel $markcid($+(NICKDATABASE,.,$comchan($nick,%i))) $nick
} }

;------

ON *:NICK:  {
  if ($isaway($nick)) {
    isaway - $+ $nick
    isaway + $+ $newnick
  }
  if ($isoper($nick)) {
    isoper - $+ $nick
    isoper + $+ $newnick
  }

  var %i = 0
  while (%i < $comchan($nick,0)) {
    inc %i
    hadd -z $markcid($+(NICKDATABASE,.,$comchan($nick,%i))) $newnick $hget($markcid($+(NICKDATABASE,.,$comchan($nick,%i))),$nick)
    hdel $markcid($+(NICKDATABASE,.,$comchan($nick,%i))) $nick
    if ($hget($markcid(HIDEUSERHOSTREPLY),$nick)) {
      hadd -zm $markcid(HIDEUSERHOSTREPLY) $newnick $hget($markcid(HIDEUSERHOSTREPLY),$nick)
      hdel $markcid(HIDEUSERHOSTREPLY) $nick
    }
  }
}

;------

ON *:DISCONNECT: {
  var %opertablename = $markcid(OPER.LIST)
  var %awaytablename = $markcid(AWAY.LIST)

  if ($hget(%opertablename) != $null) {
    hfree $iif($debugger,-s) %opertablename
  }
  if ($hget(%awaytablename) != $null) {
    hfree $iif($debugger,-s) %awaytablename
  }
}

;------

;** 353 RPL_NAMREPLY
RAW 353:*: {
  ;-- parses the NAME REPLY string and adds them to the hash table.
  var %i = 0, %nick
  var %table = $markcid($+(NICKDATABASE,.,$3))
  var %limit = $numtok($4-,32)
  tokenize 32 $3-

  if ($hget(%table) == $null) { hmake %table 100 }

  while (%i < %limit) {
    inc %i
    tokenize 32 $2-
    while ($left($1,1) isin $prefix) { tokenize 32 $right($1-,-1) }
    ;-- counts down for 30 seconds
    /hadd -z %table $1 30
  }
  ;*** if ($nick($3,0) < 50) { /.who $3 }
  /hadd -u1m HALTSIGNALS $+(NUMERIC.,$numeric) $false
  ROOTSIGNAL $+(NUMERIC.,$numeric) $1-
}

;------

;** 366 RPL_ENDOFNAMES
RAW 366:*: { PRECOLOR.NICKLIST $2 }
RAW 305:*: { isaway - $+ $1 | updatenick $1 $me! $+ $email $+ @ $+ $host }
RAW 306:*: { isaway $1 | updatenick $1 $me! $+ $email $+ @ $+ $host }

RAW 311:*: {
  isaway - $+ $2
  isoper - $+ $2
  set %p.whois.address $2 $+ ! $+ $3 $+ @ $+ $4
}
RAW 301:*: { isaway + $+ $2 }
RAW 313:*: { isoper + $+ $2 }
RAW 318:*: {
  updatenick $2 %p.whois.address
  unset %p.whois.address
}

;------------------------------

;*** /UPDATECHANNELDATABASE <CHANNEL>
ALIAS UPDATECHANNELDATABASE {
  ;-- function that handles checking nicks if they need to be scanned.
  ;-- sends up to 4 (default) userhost strings per iteration.
  ;-- 5 (default) nicks per each line. 20 nicks total per iteration.
  if ($me !ison $1) {
    if ($hget($markcid($+(NICKDATABASE,.,$upper($1)))) != $null) { hfree $ifmatch }
    return
  }

  ;-- keeps iterations 3 seconds apart
  if !$calc(%p.idle.counter % 3) {
    return
  }

  ;*** get limits properties
  var %maxnicksperline = $:MAXNICKSPERLINE
  var %maxnicksperinterval = $:MAXNICKSPERINTERVAL

  var %table = $markcid($+(NICKDATABASE,.,$1))
  var %nick
  var %textout
  var %n
  var %i = 1

  ;*** loop start
  while ($nick($1,%i)) {
    if (!$hget(%table,$v1)) {
      %nick = $nick($1,%i)

      if !$comchan(%nick,0) {
        hdel %table %nick
        inc %i
        continue
      }

      if ($comchan(%nick,0)) {
        ;*** nick is in a channel
        hadd -z %table %nick -300
      }

      hadd -mz $markcid(HIDEUSERHOSTREPLY) %nick 60

      %textout = $addtok(%textout,%nick,32)
      inc %n
      inc %i
    }

    if (($numtok(%textout,32) >= %maxnicksperline) || (%n >= %maxnicksperinterval)) {
      ;*** limit reached; output data
      debugmsg 9 -l50 /userhost %textout
      userhost %textout
      %textout = $null
      if (%n >= %maxnicksperinterval) { break }
    }
    inc %i
  }

  if ($len(%textout)) {
    ;*** queue isn't empty, so perform last lookup
    debugmsg 9 -l50 /userhost %textout
    userhost %textout
  }
}

;------

ALIAS RESETNICKQUERYDB {
  var %i = 0, %table = $markcid($+(NICKDATABASE,.,$1))

  if ($hget(%table) == $null) { hmake %table 100 }
}

;-----------------
;*** NICKLIST ****
;-----------------

;bit     value   override
;---------------------------
;01       1      Op
;02       2      Helper
;03       4      Voice
;04       8      Away
;05       16     Oper
;06       32     Friend
;07       64     Ignore
;08       128    NotInIAL
;09       256    Refresh
;10       512    Self

alias NICKLIST.COLOR.LOOKUP {
  var %itemname =  $1
  var %colortype = $2
  var %colornumber = $colour(Normal Text)

  if ($gettok(%itemname,1,46) == CHANNEL) {

    ;*** foreground or background color
    if (F isin %colortype) { %colortype = 1 }
    elseif (B isin %colortype) { %colortype = 2 }
    else { %colortype = 0 }

    tokenize 32 $hget(NICKLIST.COLORS,%itemname)
    if (%colortype) { %colornumber = [ $ $+ [ %colortype ] ] }
  }

  if ($gettok(%itemname,1,46) == NICK) {
    ;*** MORE TO COME
  }

  return %colornumber
}

;------

alias UPDATENICK {
  ;-- updates nick in nicklist.
  var %nick = $1
  var %address = $2
  var %color = $colour(Listbox Text)
  var %chan
  var %lcolor

  if ($cnick(%address)) {
    %color = $cnick(%address,1).color
  }
  elseif ($cnick(%nick)) {
    %color = $cnick(nick,1).color
  }
  else {
    if ((%address isignore) && ($ignore(%address) != *!*@*)) {
      %color = $NICKLIST.COLOR.LOOKUP(CHANNEL.IGNORE,F)
    }
    elseif ($isoper(%nick)) { %color = $NICKLIST.COLOR.LOOKUP(CHANNEL.OPER,F)  }
    elseif ($isaway(%nick)) { %color = $NICKLIST.COLOR.LOOKUP(CHANNEL.AWAY,F) }
    elseif (%nick == $me) { %color = $NICKLIST.COLOR.LOOKUP(CHANNEL.SELF,F) }
    else { %color = -1 }
  }

  var %i = 0

  while ($comchan(%nick,0) > %i) {

    inc %i
    %chan = $comchan(%nick,%i)

    if (%color >= 0) {
      if ($nick(%chan, %nick).color != %color) {
        cline -m %color %chan %nick
      }
      continue
    }
    if ($nick(%chan,%nick).idle > 3600) {
      %lcolor = $NICKLIST.COLOR.LOOKUP(CHANNEL.IDLE,F)
    }
    elseif (%nick isop %chan) {
      %lcolor = $NICKLIST.COLOR.LOOKUP(CHANNEL.OP,F)
    }
    elseif (%nick ishop %chan) {
      %lcolor = $NICKLIST.COLOR.LOOKUP(CHANNEL.HELPER,F)
    }
    elseif (%nick isvo %chan) {
      %lcolor = $NICKLIST.COLOR.LOOKUP(CHANNEL.VOICE,F)
    }
    else {
      %lcolor = $color(Listbox Text)
    }
    if ($nick(%chan,%nick).color != %lcolor) {
      cline -m %lcolor %chan %nick
    }
} }

;------

;------------------------------

alias REFRESHNICKLIST {
  DEBUGMSG 7 -l20 $bold(refreshnicklist) $1-
  var %rf.mask,%rf.chan

  if ($1 == $null) { %rf.mask = * }
  else { %rf.mask = $completeaddress($1) }

  if ($2 == $null) { set %rf.chan = * }
  else { %rf.chan = $2 }

  var %rf.i = 0
  var %rf.limit = $ialchan(%rf.mask,%rf.chan,0)
  if (%rf.limit > 100) { pbar -m rfn %rf.i %rf.limit }

  while (%rf.i >= %rf.limit) {
    inc %rf.i 1
    if ($pbar(rfn)) { pbar rfn %rf.i }
    updatenick $ialchan(%rf.mask,%rf.chan,%rf.i).nick
  }
  if ($pbar(rfn)) { pbar -x rfn }
  return
}

;--------

ALIAS PRECOLOR.NICKLIST {
  var %i = 0
  if $chan($1) {
    while (%i < $nick($1,0)) {
      inc %i
      if (!$len($ial($nick($1,%i),1))) && $isnot($hget($markcid($+(NICKDATABASE,.,$1)),$nick($1,%i))) {
        hadd -z $markcid($+(NICKDATABASE,.,$1)) $nick($1,%i) 30
      }
      else { 
        UPDATENICK $nick($1,%i) $ial($nick($1,%i),1)
      }
    }
  }
}

;-----------

ON *:SIGNAL:IDLE: {

  inc -e %throtle 1
  if ($calc(%throtle % 3) != 1) { return }

  var %i = 0, %counter

  ; *!*!*! Problem is here

  if ($raw) {
    while (%i < $scid(0)) {
      inc %i
      /scid $scon(%i).cid
      if $isnot($server) { continue }

      var %n = $calc(%p.idle.counter % ($chan(0) + 1))
      if (($chan(0) > 0) && (%n > 0)) { UPDATECHANNELDATABASE $chan(%n) }
      /PRECOLOR.NICKLIST $chan(%n) 
    }
    /scon -r
  } 
  ; *!*!*! 
}

ON *:SIGNAL:STARTUP: {
  var %i
  while (%i < $chan(0)) {
    inc %i
    /PRECOLOR.NICKLIST $chan(%i)
  }
}

;------------

alias ISOPER {
  var %i, %tablename = $markcid(OPER.LIST)

  if ($isid) {
    if ($1 ischan) {
      if $isnot($hget(%tablename)) { return 0 }
      else { return $hfind(%tablename,$+(*,$1,*),0,w).data }
    }
    elseif $isnot($hget(%tablename)) { return $false }
    else return $iif($hfind(%tablename,$1,0),$true,$false)

  }
  if ($left($1,1) == -) {
    if ($hget(%tablename)) && ($hfind(%tablename,$right($1,-1))) {
      hdel %tablename $right($1,-1)
    }
  }
  else {

    if ($left($1,1) == +) {
      tokenize 32 $right($1,-1),1,32)
    }
    else {
      tokenize 32 $1
    }
    if $isnot($hfind(%tablename,$1,0)) && $comchan($1,0) {
      while ($hget(%tablename) == $null) {
        hmake %tablename 20
        inc %i
        if (%i > 100) break
      }
    }

    if ($hget(%tablename) != $null) {
      var %i = 0,%chanlist
      while ($comchan($1,%i)) {
        %chanlist = $addtok(%chanlist,$ifmatch,32)
        inc %i
      }
      if ($len(%chanlist)) {
        hadd %tablename $1 %chanlist
      }
      else {
        hdel %tablename $1
      } 
    }
  }
}

;------

alias ISAWAY {
  var %i,%tablename = $markcid(AWAY.LIST)

  if ($isid) {
    if ($1 ischan) {
      if $isnot($hget(%tablename)) { return 0 }
      else { return $hfind(%tablename,$+(*,$1,*),0,w).data }
    }
    elseif $isnot($hget(%tablename)) { return $false }
    else { return $iif($hfind(%tablename,$1,0),$true,$false) }
  }

  if ($left($1,1) == -) {
    if ($hget(%tablename)) && ($hfind(%tablename,$right($1,-1))) {
      hdel %tablename $right($1,-1)
    }
  }

  else {
    if ($left($1,1) == +) {
      tokenize 32 $right($1,-1),1,32)
    }
    else {
      tokenize 32 $1
    }
    if $isnot($hfind(%tablename,$1,0)) && $comchan($1,0) {
      while ($hget(%tablename) == $null) {
        hmake %tablename 20
        inc %i
        if (%i > 100) break
      }
    }
    if ($hget(%tablename) != $null) {
      var %i = 0,%chanlist
      while ($comchan($1,%i)) {
        %chanlist = $addtok(%chanlist,$ifmatch,32)
        inc %i
      }
      if ($len(%chanlist)) {
        hadd %tablename $1 %chanlist
      }
      else {
        hdel %tablename $1
      }
    } 
  }
}

;------

ALIAS REMOVEGARBAGE {
  var %i = 0

  /while (%i < $hget($markcid(AWAY.LIST),0).item) {
    inc %i
    if $isnot($comchan($hget($markcid(AWAY.LIST),%i).item,0)) {
      hdel $markcid(AWAY.LIST) $hget($markcid(AWAY.LIST),%i).item
  } }

  %i = 1

  while (%i < $hget($markcid(OPER.LIST),0).item) {
    inc %i
    if $isnot($comchan($hget($markcid(OPER.LIST),%i).item,0)) {
      hdel $markcid(OPER.LIST) $hget($markcid(OPER.LIST),%i).item
    } 
  }
}

;------------------------------

;* #302 - 315 RPL_ENDOFWHO
RAW 315:*:  {
  if ($istok($2,%p.whochan.scan,32)) {
    set %p.whochan.scan $remtok(%p.whochan.scan,$2,1,32)
    if (%p.whochan.scan == $null) { unset %p.whochan.scan }
    halt
  } 
}

;------------------------------

;* #352 RPL_WHOREPLY
RAW 352:*: {
  if ($comchan($6,0) == 0) { return }

  if ($left($7,1) == G) { isaway + $+ $6 }
  else { isaway - $+ $6 }

  if (right($7,1) == *) { isoper + $+ $6 }
  else { isoper - $+ $6  }

  updatenick $6 $6 $+ ! $+ $3 $+ @ $+ 4
  if ($istok($2,%p.whochan.scan,32)) { halt }
}

;------------------------------

;* #302 - RPL_USERHOST
RAW 302:*: {
  ;-- parses userhost reply. hides userhost reply if automatically scanned.
  ;-- once information has been gathered, resets nick timer to five minutes.
  var %limit = $calc($numtok($2-,32) + 0)
  var %i = 0
  var %halt = $false

  while (%i < %limit) {
    inc %i

    var %userhost = $gettok($2-,%i,32)
    var %nick = $gettok(%userhost,1,61)

    if ($right(%nick,1) == *) {
      var %nick = $left(%nick,-1)
      if ($network != GameArcadia) { isoper + $+ %nick }
    }
    else {
      isoper - $+ %nick
    }

    if ($left($gettok(%userhost,2,61),1) == -) {
      isaway + $+ %nick
    }
    else { isaway - $+ %nick }

    updatenick %nick %nick $+ ! $+ $right($gettok(%userhost,2,61),-1)

    var %n = 0
    while (%n < $comchan(%nick,0)) {
      inc %n
      if ($hget($markcid(HIDEUSERHOSTREPLY),%nick) > 0) {
        hdel $markcid(HIDEUSERHOSTREPLY) %nick
        hadd -z $markcid($+(NICKDATABASE,.,$comchan(%nick,%n))) %nick 300
        %halt = $true
        break
      }
    }
  }
  $iif(%halt,halt)
}

;--------------------------------------------------------------

ON *:OP:*: { updatenick $opnick $$address($opnick,5) }
ON *:DEOP:*: { updatenick $opnick $$address($opnick,5) }
ON *:VOICE:*: { updatenick $opnick $$address($opnick,5) }
ON *:DEVOICE:*: { updatenick $opnick $$address($opnick,5) }
ON *:HELP:*: { updatenick $opnick $$address($opnick,5) }
ON *:DEHELP:*: { updatenick $opnick $$address($opnick,5) }
ON *:SERVEROP:*: { updatenick $opnick $$address($opnick,5) }
Posted By: Solo1 Re: who #channel - 09/03/08 12:14 PM
Hi Riamus2
No its not a script. i just do /who #channel and i get disconnected. this is on a channel that has about 1200 users. i always get disconnected when i do it and my client is sending nothing but a who request to the channel.
Posted By: 5618 Re: who #channel - 09/03/08 01:15 PM
Surprised no one gets this. :P
If the channel is large enough you'll trigger 'SendQ' on the local IRC server and be disconnected with the message: Max SendQ exceeded
You cannot prevent this, but alternatively you could do a delayed/queued /who on every person in the channel nick list or, as mentioned, a /userhost (although that does not return a realname/gecos).
Posted By: Solo1 Re: who #channel - 09/03/08 08:34 PM
which was my original request. an efficient way to /who #channel without being disconnected.
Posted By: Bekar Re: who #channel - 09/03/08 11:03 PM
*low whistle* What network are you on? On the most picky network I'm on, a 1600-user channel does a single /who #chan happily.

That being said, I had to stagger IAL updates for when first joining channels on the network as it used to sendQ. It wasn't the single /who that killed it, it was 12 at the same time (even though none of those individual channels were larger than 300 members).

If you just /who each individual member of the channel, you're more than likely going to trigger a ReceiveQ flood.

Can you give us the network/server name, and an example channel name with large members so we can test?
Posted By: Solo1 Re: who #channel - 10/03/08 09:48 AM
Hi Bekar
i paste the server and channel below. Please note that only certain times of the day does it exceed 1200 users. So sometimes a /who will go through.

//server $iif($status == connected,-m) irc.dalnet.com -j #jakarta

Thank you
Posted By: Bekar Re: who #channel - 10/03/08 11:57 AM
Wow, dalnet appears to be mean!

Will need to poke some more.. wink
Posted By: RoCk Re: who #channel - 10/03/08 01:09 PM

UnderNet is the same way, but it seems to change from server to server.
Posted By: Bob57 Re: who #channel - 10/03/08 03:24 PM
Instead of doing a /who for each nick you can /who every nick that starts with a particular character. This works on an unreal server, I don’t know about others.

Code:
alias WhoAll.Init {
  set %WhoAll.Ascii 91
  WhoAll.ByChr
}

alias WhoAll.ByChr {
  who +n $chr(%WhoAll.Ascii) $+ *
  if (%WhoAll.Ascii < 125) {
    inc %WhoAll.Ascii
    .timer 1 1 WhoAll.ByChr
  }
  else unset %WhoAll.Ascii
}


That covers every character that a nick can start with on my server. Adjust the timer interval as needed to keep from flooding.

This lets you specify a channel and a nick pattern:
/who +cn #channel $chr(%WhoAll.Ascii) $+ *
© mIRC Discussion Forums