mIRC Home    About    Download    Register    News    Help

Print Thread
following user mode changes using sockets #203534 19/08/08 09:28 AM
Joined: Mar 2007
Posts: 139
S
Solo1 Offline OP
Vogon poet
OP Offline
Vogon poet
S
Joined: Mar 2007
Posts: 139
Hi people

I have a socket bot. I want to follow user modes correctly and am having difficulty with it. I am getting user modes on joining a channel from the names list but when mode changes happen in a channel i have trouble following them.

I want to add these mode changes to a hash table so if solo has +v and then gets +o the hash table should show +vo. Additionally i want to cater if someone sets /mode #test +oo-v solo solo123 otheruser so it should show that solo1 and solo123 having +o and otheruser -v etc.
I have pasted the raw message my server sends and the deficient code idea i am using now.

;server raw example
:Solo!solo@hhx-C0087967.dsl.in-add.orange.co.uk MODE #test +o Solo

;my code example

Code:
if ($2 == mode) && (+ isin $4) {
hadd -m temp $+($3,_,$5) users mode
}


as you can see it wont keep track of complex mode changes etc. What is the best way of doing this?

Many Thanks

Re: following user mode changes using sockets [Re: Solo1] #203535 19/08/08 09:51 AM
Joined: Aug 2004
Posts: 7,252
R
RusselB Offline
Hoopy frood
Offline
Hoopy frood
R
Joined: Aug 2004
Posts: 7,252
While you could script a lot of events for this, ON JOIN, ON PART, ON QUIT, ON KICK, ON BAN, etc,. etc. etc.
You could also use the ON RAWMODE event

With this event, the line
Code:
/mode #test +oo-v solo solo123 otheruser
would return
Quote:
+oo-v solo solo123 otheruser
as $1-

As I'm not familiar with socket bots, this may not be applicable to your usage, but from a mIRC scripting aspect, this should be ideal.



Re: following user mode changes using sockets [Re: RusselB] #203537 19/08/08 10:01 AM
Joined: Mar 2007
Posts: 139
S
Solo1 Offline OP
Vogon poet
OP Offline
Vogon poet
S
Joined: Mar 2007
Posts: 139
Hi
I am aware of that event but it won't help me as i am using sockets as i mentioned.

Re: following user mode changes using sockets [Re: Solo1] #203540 19/08/08 02:26 PM
Joined: Oct 2005
Posts: 1,741
G
genius_at_work Offline
Hoopy frood
Offline
Hoopy frood
G
Joined: Oct 2005
Posts: 1,741
I'm not entirely familiar with raw MODE changes, but I believe you have to check any and all modes in the MODE raw against the list of user/channel modes given by the server when you first connect (I don't know the RAW of that list, probably 001-005). That will tell you whether each mode (character) needs to use one of the arguments provided after the mode characters. ie

:nick!ident@host MODE #channel +os-v targetnick1 targetnick2

= mode characters
= arguments

In the example, mode +o (ops) requires an argument and consumes the first nickname provided. Mode +s (secret channel) doesn't require an argument, so it doesn't use up one from the list. Mode -v (devoice) requires an argument, so it consumes the remaining argument given.

The server I am presently on, doesn't use this method (precisely). Instead, it arranges the mode characters so that if n arguments are provided, the mode characters associated with those arguments are last in the string of mode characters. Example:

/mode #channel -hC+Rv targetnick1 targetnick2
:nick!ident@host MODE #channel +R-Ch+v genius_at_work genius_at_work

You can see that the server rearranged the modes so that the two requiring arguments (-h and +v) were last in the mode character string. Because of the modes I chose to set and unset, the server had to do + modes twice.

Your script should take these two possibilities into account if you plan on using it on more than one server.

-genius_at_work

Re: following user mode changes using sockets [Re: genius_at_work] #203543 19/08/08 02:44 PM
Joined: Mar 2007
Posts: 139
S
Solo1 Offline OP
Vogon poet
OP Offline
Vogon poet
S
Joined: Mar 2007
Posts: 139
Hi Genius at work
Thanks for your reply

Basically it does not matter how the server changes the modes, i want to correctly parse whatever the socket sees.
For example i just did the following

/mode #test +oo-v Adam comperr decay Solo
the socket saw this
:Solo!solo@hhx-C0087967.dsl.in-addr.orange.co.uk MODE #test +oo-v Adam comperr decay

Basically i want to track save all user modes and add it to a temp hash table in this format $+(#channel_username) usersmodes hence the
hadd -m temp $+($3,_,$5) users mode example i pasted before. Trouble is it only caters in an event one users mode changes it will correctly track but if say a few users modes are changed in one command it will not correctly track all the changes.

p.s
The socket sees basically what one would see in a debug window /debug @debug

Last edited by Solo1; 19/08/08 03:14 PM.
Re: following user mode changes using sockets [Re: Solo1] #203551 19/08/08 06:25 PM
Joined: Oct 2007
Posts: 214
B
Buggs2008 Offline
Fjord artisan
Offline
Fjord artisan
B
Joined: Oct 2007
Posts: 214
This is what I use, I tend to stay away from raw data from sockets as it can be really messy, but for ease of use im sharing this with you. You can format it to your own needs.

Code:
on ^*:RAWMODE:*: {
  var %p = $left($nick($chan,$nick).pnick,1) | if (%p == $left($nick,1)) { unset %p }
  if ($regex($1,/^[\+-]?[ifmstplk]$/)) { echo $color(mode) -ti2 $chan 3 %p $+ $replace($nick,>,Guest_) sets mode: 14 $+ $chr(91) $+ 14 $+(3,$1,3) $2- 14 $+ $chr(93) 143 $+(14,,3) $chan $+(14,3) | haltdef }
  else {
    echo $color(mode) -ti2 $chan 3 %p $+ $replace($nick,>,Guest_) sets mode: 14 $+ $chr(91) $+ 14 $+(3,$regsubex($1,/([oqQvh])\1+/g,\t),3) 14 $+ $chr(93) 143 $replace($2-,$chr(32),$+($chr(44),$chr(32)))
    haltdef
  }
}
 

Re: following user mode changes using sockets [Re: Buggs2008] #203552 19/08/08 07:24 PM
Joined: Mar 2007
Posts: 139
S
Solo1 Offline OP
Vogon poet
OP Offline
Vogon poet
S
Joined: Mar 2007
Posts: 139
Hi
Am not sure this would work for me as am using sockets i would not be able to use $nick or $nick(#,1).pnick properties.

Re: following user mode changes using sockets [Re: Solo1] #203554 19/08/08 07:51 PM
Joined: Jan 2003
Posts: 2,523
Q
qwerty Offline
Hoopy frood
Offline
Hoopy frood
Q
Joined: Jan 2003
Posts: 2,523
Here's something that should get you going:
Code:
alias parseusermodes {
  /* 
  * Fill the two variables below accordingly.
  * When connected normally, mirc provides
  * this information via $nickmode and $chanmodes
  * but you can't use those in sockets. Ideally you
  * should be getting them from the 005 raw, if supplied
  */
  var %nickmode = $nickmode
  var %chanmodes = $chanmodes
  hfree -w usermodes
  hmake usermodes 10
  var %i = 1, %sign
  while $mid($1,%i,1) != $null {
    if ($v1 isin +-) %sign = $v1
    else {
      var %mode = $v1
      if $2 != $null && %mode isincs %nickmode {
        var %oppsign = $mid(-+,%sign $+ 1,1)
        hadd usermodes %sign $+ %mode $addtok($hget(usermodes,%sign $+ %mode),$2,32)
        hadd usermodes %oppsign $+ %mode $remtok($hget(usermodes,%oppsign $+ %mode),$2,32)
        tokenize 32 $1 $3-
      }
      elseif ($matchtokcs(%chanmodes,%mode,1,44) != $null && $&
        ($findtokcs(%chanmodes,$v1,44) isnum 1-2 || ($v1 %sign == 3 +))) $&
        tokenize 32 $1 $3-
    }
    inc %i
  }
  ; done parsing, now just display the user modes
  %i = 1
  while $hget(usermodes,%i).item {
    %mode = $v1
    if ($hget(usermodes,$v1) != $null) {
      var %nicks = $v1
      echo -a %mode : %nicks
    }
    inc %i
  }
  hfree usermodes
}
You can test it like this:

/parseusermodes +ooim-lv Adam comperr decay


/.timerQ 1 0 echo /.timerQ 1 0 $timer(Q).com
Re: following user mode changes using sockets [Re: Solo1] #203563 20/08/08 02:02 AM
Joined: Oct 2005
Posts: 1,741
G
genius_at_work Offline
Hoopy frood
Offline
Hoopy frood
G
Joined: Oct 2005
Posts: 1,741
What I'm trying to say is that it DOES matter how the server parses the data. Not every mode that is set in a channel is related to specific users. IE. you cannot set /mode #channel +s nickname because +s sets a channel to secret, and thus doesn't have anything to do with a specific user.


Here is another sample code that may help you:

Code:

alias parsemodes {
  ;$1=channel, $2=modestring, $3-=arguments

  var %numargs = $numtok($3-,32)
  var %nummodes = $len($remove($2,+,-))
  var %sign, %char, %arg
  var %mcount = 0, %acount = 0

  var %i = 0, %ii = $len($2)
  while (%i < %ii) {
    inc %i
    %char = $mid($2,%i,1)
    if (%char isin +-) { %sign = %char | continue }
    inc %mcount
    if (%mcount <= $calc(%nummodes - %numargs)) { continue }
    inc %acount
    %arg = $gettok($3-,%acount,32)
    if ($ison(%arg,$1)) {
      ;echo -a $+(%sign,%char) %arg
      %cmodes = $hget(usermodes,$+($1,_,%arg))
      if ((%sign == +) && (%char !isin %cmodes)) { hadd -m usermodes $+($1,_,%arg) $sortmodes($+(%cmodes,%char)) }
      elseif ((%sign == -) && (%char isin %cmodes)) { hadd -m usermodes $+($1,_,%arg) $sortmodes($removecs(%cmodes,%char)) }
    }
  }


  ;;; Display usermodes hash
  var %x = 0, %xx = $hfind(usermodes,*,0,w)
  while (%x < %xx) {
    inc %x
    echo -a $hfind(usermodes,*,%x,w) $hget(usermodes,$hfind(usermodes,*,%x,w))
  }

}

;Don't change this alias
alias sortmodes { return $remove($sorttok($regsubex($1,/([a-z])/gi,\1.),46),.) }

;This alias should return $true if $1 ison channel $2
alias ison { return $true }



Syntax:

/parsemodes #channel +Cov nickname1 nickname2
/parsemodes #channel +Co-v nickname1 nickname2
/parsemodes #channel +C-ov nickname1 nickname2
/parsemodes #channel +R-Ch+v nickname1 nickname2


The alias $ison needs to be altered to return $true if the nickname ($1) is on the channel ($2). You probably already keep track of this somehow in your script.

Don't change the $sortmodes alias.

I added a portion of code to display what is in the usermodes hash table for debug purposes.

-genius_at_work

Re: following user mode changes using sockets [Re: genius_at_work] #203571 20/08/08 08:09 AM
Joined: Mar 2007
Posts: 139
S
Solo1 Offline OP
Vogon poet
OP Offline
Vogon poet
S
Joined: Mar 2007
Posts: 139
Hi Geniusatwork
This looks really good. I will play with it a little to try and mod it for my script. Thanks

edit:

After some work i have modded it to my script and it does exactly what i need. But i have tried to make it work with 353 names event on joining a channel and since i dont properly understand the format of this code i have not been successful. I wonder if you could help me with that?

Code:
if ($2 == 353) {  
get usermodes of names in the #channel and add it to the hash table
}


Thanks



:Second Edit

Ok i have managed to do something that gets the modes on a join event. Please let me know if there is a more efficient way of doing this.

Code:
  if ($2 == 353) { 
    var %i = 1,%line = $remove($6-,:)
    while $gettok(%line,%i,32) { 
      var %mode = $left($v1,1)
      if ($regex(%mode,/(@|&|~|%|v)/g)) { hadd -m usermodes $+($5,_,$remove($gettok(%line,%i,32),@,&,~,%)) $replace(%mode,&,a,@,o,%,h,~,q) }
      inc %i
    } 
  }

Last edited by Solo1; 20/08/08 11:43 AM.
Re: following user mode changes using sockets [Re: Solo1] #203589 21/08/08 12:43 AM
Joined: Oct 2005
Posts: 1,741
G
genius_at_work Offline
Hoopy frood
Offline
Hoopy frood
G
Joined: Oct 2005
Posts: 1,741
One correction for my above code:

Code:

      if ((%sign == +) && (%char !isin %cmodes)) { hadd -m usermodes $+($1,_,%arg) $sortmodes($+(%cmodes,%char)) }
      elseif ((%sign == -) && (%char isin %cmodes)) { hadd -m usermodes $+($1,_,%arg) $sortmodes($removecs(%cmodes,%char)) }



should be:

Code:

      if ((%sign == +) && (%char !isincs %cmodes)) { hadd -m usermodes $+($1,_,%arg) $sortmodes($+(%cmodes,%char)) }
      elseif ((%sign == -) && (%char isincs %cmodes)) { hadd -m usermodes $+($1,_,%arg) $sortmodes($removecs(%cmodes,%char)) }



When you connect to the IRC server, you are sent a RAW that contains the PREFIX settings for that server. Example:
PREFIX=(ohv)@%+ . The characters inside the brackets correspond to the characters outside the brackets in the same order. o -> @, h -> %, v -> +. You need to store that information when your bot connects, and then use it later.

And here is a code to read the PREFIX from RAW 005 and user modes from RAW 353:

Code:

alias 005 {

  var %pre = $gettok($matchtok($2-,PREFIX=,1,32),2,61)
  var %prec = $remove($gettok(%pre,1,41),$chr(40))
  var %pres = $gettok(%pre,2,41)

  hadd -m server pre_symb %pres
  hadd -m server pre_char %prec

}

alias 353 {
  var %pres = $hget(server,pre_symb)
  var %prec = $hget(server,pre_char)
  var %temp, %nick, %symb, %char

  var %i = 0, %ii = $numtok($5-,32)
  while (%i < %ii) {
    inc %i

    %temp = $gettok($5-,%i,32)
    %symb = $left(%temp,1)
    %char = $null
    %nick = %temp
    if (%symb isin %pres) {
      %char = $mid(%prec,$pos(%pres,%symb,1),1)
      %nick = $mid(%temp,2)
    }

    ;You can store the nicknames to a list here. $3=chan, %nick=nick
    hadd -m userlist $+($3,_,%nick) $ctime

    var %cmodes = $hget(usermodes,$+($3,_,%nick))
    if (%char !isincs %cmodes) { hadd -m usermodes $+($3,_,%nick) $sortmodes($+(%cmodes,%char)) }
    ;echo -a > %symb : %char : %nick : %temp
  }
}



These aliases respond to the standard format for their respective RAWs.

Samples from my server:

RAW 005:
YourNick MAP KNOCK SAFELIST HCN WATCH=128 SILENCE=5 MODES=13 MAXCHANNELS=25 MAXBANS=120 NICKLEN=30 TOPICLEN=307 KICKLEN=307 CHANTYPES=# PREFIX=(ohv)@%+ are supported by this server

RAW 353:
YourNick @ #channel UserNick1 @UserNick2 %UserNick3 +UserNick4

The code adds the modes to the same hash as my previous code.

-genius_at_work