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.

My Channel Operations Script

Help for those learning Tcl or writing their own scripts.
Post Reply
C
CharlesZink
Voice
Posts: 12
Joined: Sun Feb 28, 2010 7:41 pm
Location: The Interweb
Contact:

My Channel Operations Script

Post by CharlesZink »

Hi guys,

I've posted a couple questions around here and the help has been great! I just started trying to learn TCL. I've mostly learned from reading other peoples scripts, and trial & error.

This is my first attempt at a script and it works.. Sorta. Some commands don't work at all, and other do only once. Not sure what is wrong, can you take a look and help out please?

(I've compiled this from some of my own stuff, and copying out of some other scripts.)

Code: Select all


### BINDS ###

# All I can say is, change with caution.

bind pub o !op op_nick
bind pub o !deop deop_nick
bind pub o !voice voice_nick
bind pub o !devoice devoice_nick
bind pub o !kick kick_nick
bind pub o !topic set_topic
bind pub o !cycle cycle_bot

### CODE ###

# Don't edit my work, please.

#----- OP -----#

proc op_nick {nick host handle channel testes} {
putserv "MODE $channel +o $nick"
return 1
}

#----- DEOP -----#

proc deop_nick {nick host handle channel testes} {
putserv "MODE $channel -o $nick"
return 1
}

#----- VOICE -----#

proc voice_nick {nick host handle channel testes  } {
putserv "MODE $channel +v $nick"
return 1
}

#----- DEVOICE -----#

proc devoice_nick {nick host handle channel testes} {
putserv "MODE $channel -v $nick"
return 1
}

#----- KICK -----#

proc kick_nick {nick uhost hand chan arg} {
global botnick
set who [lindex $arg 0]
set why [lrange $arg 1 end]
putserv "KICK $chan $who :$why 1 5,1•4•5•14,1.:X:. 14,1Gô15,1G14,1eR4,1.:X:. 5,1•4•5•"
return 1
}

#----- TOPIC -----#

proc set_topic {user host handle channel testes} {
set what [lrange $testes 0 end]
putserv "TOPIC $channel :$what"
return 1
}

#----- CYCLE -----#

proc cycle_bot  {nick host handle channel testes} {
  global botnick
 set who [lindex $testes 0]
 if {$who == ""} {
 restart
 return 1
}


}

User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

Good effort.

Some of the things I've noticed :-

Although Tcl lists are in fact strings because Tcl can only have string data types, they are different in structure. You can't safely use string commands on lists or list commands on normal strings. The additional 'text' argument passed to a proc from a PUB bind, as well as other bind types, is a normal string. If you want to use list commands on it, you will need to split it into a list first. You may choose to join it back into a normal string before outputting, though this may not matter.

Your code :-

Code: Select all

proc set_topic {user host handle channel testes} {
set what [lrange $testes 0 end]
putserv "TOPIC $channel :$what"
return 1
}
Correct code :-

Code: Select all

proc set_topic {user host handle channel testes} {
  set what [join [lrange [split $testes] 0 end]]
  putserv "TOPIC $channel :$what"
  return 0
}
In actual fact, in this particular case it is pointless.

[join [lrange [split $testes] 0 end]] == $testes

You may just as well do the following :-

Code: Select all

proc set_topic {user host handle channel testes} {
  putserv "TOPIC $channel :$testes"
  return 0
}
Better still you might want to test if the command user actually included a topic with the command, as follows :-

Code: Select all

proc set_topic {user host handle channel testes} {
  if {[string length [string trim $testes]] != 0} {
    putserv "TOPIC $channel :[string trim $testes]"
  } else {
    putserv "PRIVMSG $channel :correct syntax is !topic <topic>"
  }
  return 0
}
A good document to read on the subject of strings vs lists and how to avoid such issues choking scripts is :-

http://www.peterre.info/characters.html

Note also that I have returned 0 rather than 1. Some bind types (including PUB) behave differently if the proc returns 1. Simply a good habit, unless you deliberately want to return 1.

Take a look at tcl-commands.html in your bots doc/html subdirectory under the heading Binds b. Return values.

Your cycle command should probably be renamed to a restart command. There is no need to restart the bot if all you want to do is cycle an IRC channel.

To cycle the bot :-

Code: Select all

putserv "PART #channelname"
The bot will immediately rejoin the channel because it still retains a record for the channel.

It is possible to control how long the bot stays out by, instead of the above, programmatically setting the channel +inactive then using a timer to reset the channel -inactive (normally the default value).

Generally, I would avoid overuse of the strange characters used to format text output (as in your kick command). Mainly because it makes the script difficult to read. There is an excellent text formatting document in the Scripting FAQ section of this forum.
I must have had nothing to do
C
CharlesZink
Voice
Posts: 12
Joined: Sun Feb 28, 2010 7:41 pm
Location: The Interweb
Contact:

RE

Post by CharlesZink »

Ok, thanks.

I partially understand what your saying, but how should I make this apply to the other commands like !voice and such?

Would this work:

Code: Select all

proc voice_nick {nick host handle channel testes  } {
putserv "MODE $channel :+v $testes"
return 0
}
For some reason I just don't think it's going to. I've done mIRC all my life, and TCL has thrown me for a total loop :-D

Thanks for all your help, and I'll change the 'cycle' to 'restart' because when it leaves and comes back in, I want it to refresh all the scripts and such too, so it will see any changes, so I guess thats a restart not a cycle.
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

Yes that would work fine, providing you used the command !voice <name> where <name> was the nick of the user you wished the bot to voice.

I would tend to trim the argument before using it because some IRC clients insert a space after the nick when using autocomplete.

Code: Select all

proc voice_nick {nick host handle channel testes  } {
putserv "MODE $channel :+v [string trim $testes]"
return 0
}
I must have had nothing to do
C
CharlesZink
Voice
Posts: 12
Joined: Sun Feb 28, 2010 7:41 pm
Location: The Interweb
Contact:

Thanks

Post by CharlesZink »

Thanks for the help! I will re-code it all and see if it works. Much appreciated.

This page, http://www.egginfo.org/?page=tcl, has an amazing amount of info on some of the commands too.
C
CharlesZink
Voice
Posts: 12
Joined: Sun Feb 28, 2010 7:41 pm
Location: The Interweb
Contact:

WHAT THE HELL?

Post by CharlesZink »

Woah! My bot is totally freaking out! I copied the voice code you edited and showed me and this is what I'm getting
<~TheNerdTV> !voice advcomp2019
* Terminator sets mode: +p-s
And it does different stuff depending on each person?
<~TheNerdTV> !voice SamsTechAnswers
* Terminator sets mode: +smcT
Any idea why? Once again, this is what I'm using...

Code: Select all

proc voice_nick {nick host handle channel testes  } {
putserv "MODE $channel :+v [string trim $testes]"
return 0
} 
Crazy!
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

The putserv statement has a superfluous colon. Sorry, I didn't notice that. This is the same used in a public command tcl shell.

[22:21] <@arfer> % putserv "MODE #eggtcl -v Hestia"
[22:21] * Baal sets mode: -v Hestia

Just remove the :
I must have had nothing to do
User avatar
arfer
Master
Posts: 436
Joined: Fri Nov 26, 2004 8:45 pm
Location: Manchester, UK

Post by arfer »

Out of interest, the following code for voicing users is what I would call more complete. It outputs pretty much every type of error that can occur in using the command and it lends much more scope in the possible syntax.

The bind requires that the user has global operator status in the bot's userfile (user flag o).

The other commands such as op, deop, devoice can be written in a similar way.

Code: Select all

# !voice --> voice yourself in the command source channel
# !voice nick --> voice the specified nick in the command source channel
# !voice #channel --> voice yourself in the specified channel
# !voice nick #channel --> voice the specified nick in the specified channel

bind PUB o !voice pCommandsVoice

proc pCommandsVoice {nick uhost hand chan text} {
    set arguments [regsub -all -- {[\s]{2,}} [string trim $text] { }]
    switch -- [llength [split $arguments]] {
        0 {
            set tnick $nick
            set tchan $chan
        }
        1 {
            if {[regexp -- {^#} $arguments]} {
                set tnick $nick
                set tchan $arguments
            } else {
                set tnick $arguments
                set tchan $chan
            }
        }
        2 {
            set tnick [lindex [split $arguments] 0]
            set tchan [lindex [split $arguments] 1]
        }
        default {
            putserv "PRIVMSG $chan :Incorrect syntax, use !voice ?nick? ?#channel?"
            return 0
        }
    }
    if {[string equal -nocase $nick $tnick]} {set nprefix "You are"} else {set nprefix "$tnick is"}
    if {[string equal -nocase $chan $tchan]} {set cprefix "here"} else {set cprefix "on $tchan"}
    if {[regexp -- {^#} $tchan]} {
        if {[validchan $tchan]} {
            if {[botonchan $tchan]} {
                if {[botisop $tchan]} {
                    if {[regexp -- {^[\x41-\x7D][-\d\x41-\x7D]*$} $tnick]} {
                        if {[onchan $tnick $tchan]} {
                            if {![isvoice $tnick $tchan]} {
                                putserv "MODE $tchan +v $tnick"
                            } else {putserv "PRIVMSG $chan :$nprefix already voice'd $cprefix"}
                        } else {putserv "PRIVMSG $chan :$nprefix not $cprefix"}
                    } else {putserv "PRIVMSG $chan :$tnick is not a valid nick"}
                } else {putserv "PRIVMSG $chan :I need to be op'd $cprefix to do that"}
            } else {putserv "PRIVMSG $chan :I am not currently on $tchan"}
        } else {putserv "PRIVMSG $chan :$tchan is not a valid bot channel"}
    } else {putserv "PRIVMSG $chan :$tchan is not a valid channel name"}
    return 0
}
I must have had nothing to do
C
CharlesZink
Voice
Posts: 12
Joined: Sun Feb 28, 2010 7:41 pm
Location: The Interweb
Contact:

Thanks

Post by CharlesZink »

Thank you for taking the time to give me that voice code. Once I start putting the bot on multiple channels, I will use that. Off to remove the colon :-D
Post Reply