This is the new home of the egghelp.org community forum.
All data has been migrated (including user logins/passwords) to a new phpBB version.


For more information, see this announcement post. Click the X in the top right-corner of this box to dismiss this message.

wont kick nicks with chars like {}

Help for those learning Tcl or writing their own scripts.
User avatar
CrazyCat
Revered One
Posts: 1304
Joined: Sun Jan 13, 2002 8:00 pm
Location: France
Contact:

Post by CrazyCat »

simo wrote:Thanx crazycat except the thing is i already used split in the set im not sure its a good idea to have duplicate split text
I don't understand what you mean...
I said you to do:

Code: Select all

bind pub n .k pub:kicker
proc pub:kicker {nick host hand chan text} {
   global botnick
   if {![botisop $chan]} {
      puthelp "NOTICE $nick :I'm not oped on $chan."
      return
   }
   set users [list]
   set reason [join [lrange [split $text "."] 1 end] "."]
   set text  [lindex [split $text "."] 0]
   if {$reason eq ""} { set reason Requested  }
   foreach user [split $text] {
      set user [join $user]
      if {![onchan $user $chan]} {
         putserv "NOTICE $nick $user is not on channel $chan"
      } else {
         lappend users $user
      }
   }
   stackKicks $chan [join $users] $reason 4
}
Just add a line after the foreach.
s
simo
Revered One
Posts: 1107
Joined: Sun Mar 22, 2015 2:41 pm

Post by simo »

tnx CrazyCat i tried that one and gave me same result it stripped the {} and returns: Aron is not on channel
while the nick is actually {Aron}


also doesnt the :

lappend users $user

already store the nicks ? instead of using another :

set user [join $user]
Last edited by simo on Wed Jul 29, 2020 9:24 am, edited 1 time in total.
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

Figured I'd butt my head in here...
There is indeed issues with mixing list- and string-types in this script:

Starting from the initial script:

Code: Select all

   set users [list]
   set reason [join [lrange [split $text "."] 1 end] "."]
   set text [lindex [split $text "."] 0]
users is an (empty) list
reason is a (sub)string of everything past the first "." on the "commandline"
text is a (sub)string of everything before the first "." on the "commandline"

Moving on...

Code: Select all

   foreach user [split $text] {
We want to build a list of users; text is a string presumably with an enumeration of nicks separated with space. Thus, we use split to get a list of strings (nicknames).

Code: Select all

      set user [join $user]
This is just wrong; foreach iterates through each list-member - which in this instance is a string. Don't try to join it here, or you'll try to parse {} as list delimiters (and they'll disappear, or the code breaks due to a malformed list).

Next...

Code: Select all

      if {![onchan $user $chan]} {
         putserv "NOTICE $nick $user is not on channel $chan"
      } else {
         lappend users $user
      }
Unless you are using some arcane IRC-server that I havn't kept up to date with, the text-argument for a NOTICE-command needs to be prefixed with : if it contains spaces

Code: Select all

putserv "NOTICE $nick :$user is not on channel $chan"
lappend appends the (string) user to the list users. That is legit.

Finally...

Code: Select all

   stackKicks $chan [join $users] $reason 4
Here we take our list of nicks to be kicked, and squash it into a string; which is not so good given that stackKicks actually expects a list of nicknames, not a string...
Drop the join.

Now, for stackKicks:

Code: Select all

proc stackKicks {chan kicklist reason {max 4}} {
   set count [llength $kicklist]
   while {$count > 0} {
So we expect kicklist to be a list of nicks, and we iterate over it using a while-loop.

Code: Select all

      if {$count > $max} {
         set users [join [lrange $kicklist 0 [expr {$max - 1}]] ","]
         set kicklist [lrange $kicklist $max end]
         incr count -$max
If there's more than max entities remaining in the list, grab the first max items, and squash then down to a string with "," as separator.
Then trim the first max entities off the kicklist.

Edit: disregard this part, as it's not really valid:
You could probably gain some readability and performance by using lreplace instead of set ... [lrange ...], but it's still fully functional.

Finally decrement count so we don't get stuck in an infinite loop. Good!

Code: Select all

      } else {
         set users [join $kicklist ","]
         set count 0
      }
Otherwise, we just grab the whole (remaining) list, and squash it.

Code: Select all

      putnow "KICK $chan $users $reason"
Finally, we send a KICK-command to the server; once again, if the last argument contains spaces, it should be prefixed with :


Sorry if I got a bit lengthy...
Last edited by nml375 on Wed Jul 29, 2020 10:05 am, edited 1 time in total.
NML_375
s
simo
Revered One
Posts: 1107
Joined: Sun Mar 22, 2015 2:41 pm

Post by simo »

excellent tnx nml375 that fixed it
and about the stackicks proc could you show me how to use the lreplace in it as im kinda confused how to integrate it

i assume you meant the :

set users [join [lrange $kicklist 0 [expr {$max - 1}]] ","]
Last edited by simo on Wed Jul 29, 2020 9:45 am, edited 1 time in total.
User avatar
CrazyCat
Revered One
Posts: 1304
Joined: Sun Jan 13, 2002 8:00 pm
Location: France
Contact:

Post by CrazyCat »

You wrote your post as I was testing.

I was thinking the trouble was in the $user, but it is when appending the list $users. Adding a string which contains special chars adds {} to protect it.

Small test:

Code: Select all

bind pub - .k pub:kicker
proc pub:kicker {nick uhost handle chan text} {
	set text  [lindex [split $text "."] 0]
	set users [list]
	foreach user [split [string trim $text]] {
		#putlog "looking for *$user*"
		if {![onchan $user $chan]} {
			putlog "Can't find *$user*"
		} else {
			putlog "Will kill *$user*"
			lappend users $user
		}
	}
	putlog "List is //$users//"
	foreach user2 $users {
		putlog "And now *$user2*"
	}
}
IRC: .k [Guru] Galaad CrazyCat {test0r} .my reason

Code: Select all

[15:19] Will kill *[Guru]*
[15:19] Will kill *Galaad*
[15:19] Will kill *CrazyCat*
[15:19] Will kill *{test0r}*
[15:19] list is //{[Guru]} Galaad CrazyCat {{test0r}}//
[15:19] And now *[Guru]*
[15:19] And now *Galaad*
[15:19] And now *CrazyCat*
[15:19] And now *{test0r}*
So, the trouble is just in stackKicks where the list is badly managed
s
simo
Revered One
Posts: 1107
Joined: Sun Mar 22, 2015 2:41 pm

Post by simo »

thank you CrazyCat apreciated
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

CrazyCat wrote:...
So, the trouble is just in stackKicks where the list is badly managed
I'm sorry I don't quite follow you there...

stackKicks expects a list of nicks, and properly handles that list as a list as far as I can tell. For me, it would only break if you pass something other than a list to it (such as squashing the list with that join in the end). Would you mind elaborate how it is badly managed?
simo wrote:...
and about the stackicks proc could you show me how to use the lreplace in it as im kinda confused how to integrate it

i assume you meant the :

set users [join [lrange $kicklist 0 [expr {$max - 1}]] ","]
No, that part is perfectly fine. It's the second line, where you remove the first elements:

Code: Select all

set kicklist [lrange $kicklist $max end]
However, iterating over that code yet another time, I realize I messed up on that one; lreplace expects a list as input, not a varName - thus we'd still have to use set to update the variable. Must've had lappend in my mind (which obviously does the complete opposite to what we are trying to achieve here).
However, for reference this is how you'd use lreplace in your scenario:

Code: Select all

set kicklist [lreplace $kicklist 0 [expr {$max -1}]]
Not sure if this actually ended up more readable... (would make more sense if you'd have to change or remove items in the middle of the list).
NML_375
s
simo
Revered One
Posts: 1107
Joined: Sun Mar 22, 2015 2:41 pm

Post by simo »

tnx for the explanation nml375

ive come another issue with the custom kick reason added

when i do:
.k nick {nick}
it kicks fine with the default kick reason but when i do like:
.k nick {nick} .some custom reason
it complains with :
is not on channel
but it kicks both tho so that part works except the custom reason part

i suspect it sees the kick reason as a nick to kick as well
User avatar
CrazyCat
Revered One
Posts: 1304
Joined: Sun Jan 13, 2002 8:00 pm
Location: France
Contact:

Post by CrazyCat »

nml375 wrote:
CrazyCat wrote:...
So, the trouble is just in stackKicks where the list is badly managed
I'm sorry I don't quite follow you there...
Sorry, I badly said the thing...
stackKicks may work, but the way the list was sent seems strange to me:

Code: Select all

stackKicks $chan [join $users] $reason 4
So, $users is a list, and it's joined when sending to stackKicks ? Bad idea imho:

Code: Select all

% set text "\[Guru\] Galaad CrazyCat {test0r}"
[Guru] Galaad CrazyCat {test0r}
% set users [list]
% foreach user [split $text] { lappend users $user }
% puts $users
{[Guru]} Galaad CrazyCat {{test0r}}
% puts [join $users]
[Guru] Galaad CrazyCat {test0r}
It's not anymore a list
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

On my mobile right now, so I'll be brief...
The problem is that the trailing space in the enumeration of nicks becomes an empty element when you split the substring.
I think you'd be able to use something like string trim to remove the space(s) once you've separated the reason from the nicks...

Edit: See code by CrazyCat in a previous post for a good example how to implement this.
Last edited by nml375 on Wed Jul 29, 2020 11:53 am, edited 1 time in total.
NML_375
User avatar
CrazyCat
Revered One
Posts: 1304
Joined: Sun Jan 13, 2002 8:00 pm
Location: France
Contact:

Post by CrazyCat »

nml375 wrote:The problem is that the trailing space in the enumeration of nicks becomes an empty element when you split the substring.
I think you'd be able to use something like string trim to remove the space(s) once you've separated the reason from the nicks...
simo, see my previous code (my test in http://forum.egghelp.org/viewtopic.php?p=108811#108811 ):

Code: Select all

foreach user [split [string trim $text]] {
s
simo
Revered One
Posts: 1107
Joined: Sun Mar 22, 2015 2:41 pm

Post by simo »

excellent CrazyCat that fixed it much apreciated so far all working well thnx CrazyCat and nml375
n
nml375
Revered One
Posts: 2860
Joined: Fri Aug 04, 2006 2:09 pm

Post by nml375 »

CrazyCat wrote:...
Sorry, I badly said the thing...
stackKicks may work, but the way the list was sent seems strange to me:

Code: Select all

stackKicks $chan [join $users] $reason 4
Fair enough, was afraid I had overlooked something in there.

Sorry about not noticing the addition of string trim in your sample-code, or I would had cited it in my previous reply.
NML_375
User avatar
caesar
Mint Rubber
Posts: 3778
Joined: Sun Oct 14, 2001 8:00 pm
Location: Mint Factory

Post by caesar »

@simo btw, since you added the max as 4th argument and got it set with a default value as 4 in this:

Code: Select all

proc stackKicks {chan kicklist reason {max 4}} {
there's no need to call the function like:

Code: Select all

stackKicks $chan $users $reason 4
if it's 4 as well. Or you plan to have a different value?
Once the game is over, the king and the pawn go back in the same box.
s
simo
Revered One
Posts: 1107
Joined: Sun Mar 22, 2015 2:41 pm

Post by simo »

good point caesar thank you
Post Reply