egghelp.org community Forum Index
[ egghelp.org home | forum home ]
egghelp.org community
Discussion of eggdrop bots, shell accounts and tcl scripts.
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

same issue with massvoice and nicks with {}

 
Post new topic   Reply to topic    egghelp.org community Forum Index -> Scripting Help
View previous topic :: View next topic  
Author Message
simo
Owner


Joined: 22 Mar 2015
Posts: 941

PostPosted: Thu Jul 30, 2020 11:31 am    Post subject: same issue with massvoice and nicks with {} Reply with quote

simmilarly as the previous one i checked what it could be and i couldnt find any thing why it wouldnt set voice on nicks with {} in them like {somenick}

Code:

bind pub n .mv voice_all
 
set excnick {
    "chanserv"
    "somenick"
}

 


proc voice_all {nick host handle chan text} {
global excnick

if {![botisop $chan]} {
      puthelp "NOTICE $nick :I'm not oped on $chan."
      return
   }

     # grab the channel members list and exclude the bot from it
   set userList [chanlist $chan]
   set pos [lsearch -nocase $userList $::botnick]
   set userList [lreplace $userList $pos $pos]
 
   # build the op list with only people that aren't op or any other channel access level
   foreach user [split $userList] {
    if {![isvoice $user $chan] && ![isop $user $chan] && ![ishalfop $user $chan] && ![matchattr [nick2hand $user] o|o $chan]  && [lsearch -nocase $excnick $user] == -1} {  lappend voiceList $user }
    }
 
   # define the max amount of modes per line
   set max 15
 
   # op all the members in the above built voice list
   if {[info exists voiceList]} {
      set len [llength $voiceList]
      while {$len > 0} {
         if {$len > $max} {
         set mode [string repeat "v" $max]
         set users [join [lrange $voiceList 0 [expr {$max - 1}]]]
         set voiceList [lrange $voiceList $max end]
         incr len -$max
         } else {
            set mode [string repeat "v" $len]
            set users [join $voiceList]
            set len 0
         }
      putnow "MODE $chan +$mode $users"
      }
      puthelp "NOTICE $nick :Voiced all users on $chan."
   } else {
      puthelp "NOTICE $nick :Nobody needed to be Voiced on $chan."
   }
}


it adds {} to the nicks for example
a nick like {ykbeucwvi} would be seen as {{ykbeucwvi}}
Back to top
View user's profile Send private message
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Thu Jul 30, 2020 11:55 am    Post subject: Reply with quote

Hi Simo,
Going to try and not make a complete teardown of the script this time...

But...
Lets start here:
Code:
set userList [chanlist $chan]
set pos [lsearch -nocase $userList $::botnick
set userList [lreplace $userList $pos $pos]

Here, we treat userList as an actual list (which it is); so far so good.

But then, we get here:
Code:
foreach user [split $userList] {

split is really only intended to be used on strings, not lists. Remove it, as userList already is a list.

Next;
Code:
 if {... && [lsearch -nocase $excnick $user] ...

Here, we treat excnick as a list, but to be honest it's merely a list-like string;
Code:
set excnick {
    "chanserv"
    "somenick"
}

You'll get away with it for as long as your exclusion-nicks does not contain list-formatting characters such as {}... Consider creating a proper list using the list command instead.

In the end, you've got some code iterating through a list of nicks, trying to build optimal MODE commands (stack multiple mode changes in one command, not unlike the KICK-stacking in your previous thread). Technically nothing obviously wrong with the code; I just wanted to point out that this functionality is already implemented in eggdrop itself using the pushmode command (which will queue all mode changes until the binding returns, and then stack them properly).
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
simo
Owner


Joined: 22 Mar 2015
Posts: 941

PostPosted: Thu Jul 30, 2020 12:12 pm    Post subject: Reply with quote

excellent tnx for the explanation nml375

about the list i tried searching for it in the docs couldnt find it would you have any example i can use as a template cause we might want to add nicks wich may contain list formatting chars as u mentioned we want to have it optional anyway

tnx once again nml375 much apreciated
Back to top
View user's profile Send private message
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Thu Jul 30, 2020 12:49 pm    Post subject: Reply with quote

Certainly; though the man-page for list do have a few good examples: https://www.tcl.tk/man/tcl8.6/TclCmd/list.htm

Code:
#sampe 1
set excnick [list chanserv somenick]

#sample 2
set excnick [list \
  chanserv \
  somenick \
]

#sample 3, adding the value of the global variable ::botnick to the list.
set excnick [list "chanserv" \
  somenick $::botnick]


Be cautious though, as you still go through variable- and command-substitutions, as well as syntax checks in the tcl-interpreter:
Code:
#this will not work well;
set uxcnick [list badnick{ \
badnick2 \
}badnick3 ]

#this one might surprise you
set excnick [list "chanserv" \
{somenick} \
]
#result is "chanserv somenick"

#What you probably wanted:
set excnick [list "chanserv" \
"{somenick}" \
"{othernick" \
]
#result is "chanserv {{somenick}} \{othernick"
#"lindex $excnick 0" => "chanserv"
#"lindex $excnick 1" => "{somenick}"
#"lindex $excnick 2" => "{othernick"

#Another one:
set excnick [list "chanserv" \
{$botnick} \
]
#result is "chanserv {$botnick}"
#"lindex $excnick 1" => "$botnick"
#note that there is no variable substitution done due to the use of braces

Somewhat simplified, an atomic item on the command line may be a single word (no quotes or braces), a substitutable string (enclosed in quotes), or a plain string (enclosed in braces, or {}). That's why list "chanserv" {somenick} produced a list with the strings "chanserv" and "somenick", and list "chanserv" {$botnick} created a list containing the strings "chanserv" and "$botnick".

Finally, the backspaces are needed to escape the newline character into a whitespace character, as newline otherwize would terminate the commandline early (and there's alot of more trickery that can be done with escaping).

You'll also find a decent readup on the various substitutions done by the tcl interpreter here: https://www.tcl.tk/man/tcl8.6/TclCmd/Tcl.htm
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
simo
Owner


Joined: 22 Mar 2015
Posts: 941

PostPosted: Thu Jul 30, 2020 1:06 pm    Post subject: Reply with quote

excellent thank you nml375 for the explanation and the provided examples much apreciated
Back to top
View user's profile Send private message
nml375
Revered One


Joined: 04 Aug 2006
Posts: 2857

PostPosted: Thu Jul 30, 2020 1:11 pm    Post subject: Reply with quote

You're welcome,
I tried to cover the most common mistakes I've seen over the years, though there certainly are other pitfalls. Understanding when and how substitutions and escaping occurs is really the name of the game here.

The list command does guarantee a valid list (will not break on foreach, lindex, etc), but you still need to make sure the input isn't mangled by the tcl interpreter before list gets it hands on it.
_________________
NML_375, idling at #eggdrop@IrcNET
Back to top
View user's profile Send private message
CrazyCat
Revered One


Joined: 13 Jan 2002
Posts: 1032
Location: France

PostPosted: Thu Jul 30, 2020 6:00 pm    Post subject: Reply with quote

I'll made a short critic about the script...

You set a "max" variable ("define the max amount of modes per line") and after various calculation and manipulation you use:
Code:
putnow "MODE $chan +$mode $users"


I think that if you use the good tcl commands (pushmode & flushmode), you can really simplify your procedure:
Code:
proc voice_all {nick host handle chan text} {
   global excnick
   if {![botisop $chan]} {
      puthelp "NOTICE $nick :I'm not oped on $chan."
      return 0
   }

   # build the op list with only people that aren't op or any other channel access level
   set voiced 0
   foreach user [chanlist $chan] {
      if {($user ne $::botnick) && ![isvoice $user $chan] && ![isop $user $chan] && ![ishalfop $user $chan] && ![matchattr [nick2hand $user] o|o $chan]  && [lsearch -nocase $excnick $user] == -1} {
         incr voiced
         pushmode $chan +v $user
      }
    }
   flushmode $chan
   if { $voiced == 0} {
      puthelp "NOTICE $nick :Nobody needed to be Voiced on $chan."
   } else {
      puthelp "NOTICE $nick :Voiced all users on $chan."
   }
}

_________________
https://www.eggdrop.fr - French IRC network
Offer me a coffee - Do not ask me help in PM, we are a community.
Back to top
View user's profile Send private message Visit poster's website
simo
Owner


Joined: 22 Mar 2015
Posts: 941

PostPosted: Thu Jul 30, 2020 8:44 pm    Post subject: Reply with quote

thats even better thanx CrazyCat
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    egghelp.org community Forum Index -> Scripting Help All times are GMT - 4 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Forum hosting provided by Reverse.net

Powered by phpBB © 2001, 2005 phpBB Group
subGreen style by ktauber