Scripting » History » Revision 161
Revision 160 (Per Amundsen, 08/14/2012 12:10 PM) → Revision 161/246 (Per Amundsen, 08/14/2012 12:11 PM)
h1. Notice: this is info for 1.8.10 and higher. h1. Scripting *[[Scripting BETA]] Click here to see scripting in the latest beta versions.* You can write full scripts in Commands -> Edit Scripts or you can create one liners in Commands -> Edit Commands h1. Custom Commands: Custom Commands are created in Commands -> Edit Commands Custom commands consists of differents ways to execute a script either by making your own command, or use a hotkey, you can also enter a full script as a one liner (for legacy reasons) *Alias* <pre> /hello /msg $channel hello everybody </pre> This creates a alias named "/hello", everytime you type "/hello" the script "/msg $channel hello everybody" will be executed, you can use any script features here. *Hot keys* <pre> Ctrl&r /msg $channel hello everybody i pressed 'ctrl' and 'r' </pre> Every time you press ctrl + r, the script "/msg $channel hello everybody i pressed 'ctrl' and 'r'" will be executed, you can use any script features her. You can comment out a command by putting a # in front of it. It is also possible to use a full script, but it has to be on one line, and the script editor is preferred. h1. Scripts: *Events:* There are different ways to listen to the irc client/server events for legacy reasons. On/OnEvent will be executed after the event OnBefore/OnBeforeEvent will be executed before the event <pre> OnEvent if ($event == PRIVMSG) { /EXECUTE } OnBeforeEvent if ($event == PRIVMSG) { /EXECUTE } On PRIVMSG { /EXECUTE } OnBefore PRIVMSG { /EXECUTE } OnBefore OnCommand { /EXECUTE } OnCommand /mode { /EXECUTE } </pre> *Available events:* <pre> SockOpen / Called when a script opens a socket SockRead / Called when a socket have data to read SockOpen / Called when a script socket is closed OnLoad / Called when the script is loaded OnUnload / Called when the script is unloaded OnReload / Called when the script is reloaded OnConnecting / Called when a server is connecting OnLookingUp / Called when a server is looking up the hostname OnConnected / Called when a server is connected OnDisconnect / Called when a server gets disconnected OnCommand / Called whenever a user types a /slash command in the client ($0- will hold the full command, $0 will be the first word, $1 the second and so on) OnCTCPRequest / Called when a user recives a CTCP request OnCTCPReply / Called when a user recives a CTCP reply OnDCCRequest / Called when a user recived a DCC request OnNickChanged / Called when a user's nick changes, will only trigger on the user unlike NICK who triggers for everyone OnSongChanged / Called when a song is changed in the selected media player OnDeVoice / Called when a user gets devoiced OnVoice / Called when a user gets voiced OnDeHop / Called when a user gets dehalfoppeed OnHop / Called when a user gets halfopped OnOp / Called when a user gets opped OnDeOp / Called when a user gets deopped OnDeOwner/ Called when a user gets owner deopped OnOwner/ Called when a user gets owner opped OnDeSop / Called when a user gets special deopped OnSop / Called when a user gets special opped MODE / Called whenever a channel or user mode is changed JOIN / Called whenever a user joins a channel PART / Called when a user parts a channel NICK / Called when a user changes their nick TOPIC / Called when a topic is set/changed KICK / Called when any user gets kicked NOTICE / Called when any notice is recived QUIT / Called when a user quits irc PRIVMSG / Called when any message is recived WHOIS / Called when any whois reply is recived LIST / Called when a user gets a /list KILL / Called when a user gets killed ACTION / Called when a user recives a ACTION (/me) message <irc numeric> / Called when a raw irc line with <irc numeric> is recived <irc textual> / Called when a raw irc line with <irc textual> is recived </pre> *if/else if/else blocks:* You can use any combination of if, else if, else and while <pre> OnEvent if ($event == PRIVMSG) { if (%test == null) { /echo Hello world if (%test == null) { /echo Hello world } else /echo Hello World } else if (%test == null) { /echo Hello world } else (%test == null) { /echo Hello world } if (%test == null) { /echo Hello world while (%test == null) { /echo Hello world } } if(%test == null)/echo Hello World else if(%test == null)/echo Hello World else/echo Hello world if(%test == null){/echo Hello World }else if(%test == null){/echo Hello World }else{/echo Hello World } if(%test == null){/echo Hello World}else if(%test == null){/echo Hello World}else{/echo Hello World} } </pre> *while blocks:* <pre> On JOIN { var %t = 0 /echo There are ($user($chan, 0)) users in ($chan) while (%t < $user($chan, 0)) { %t++ var %nick = $user($chan, %t) /echo User (%t) is (%nick) and is $iif(%nick isop $chan, opped, not opped) } } </pre> *goto/label:* <pre> OnCommand /goto { var %loop = 0 if ($1 == 1) { goto 1 } else if ($1 == 2) { goto 2 } else if ($1 == loop) { :3 /echo you typed loop %loop++ if (%loop < 5) { goto 3 } return } else { goto 4 } :1 /echo You typed 1 return :2 /echo You typed 2 return :4 /echo The end return } </pre> *client variables:* All client variables starts with $ <pre> $event / current event, e.g PRIVMSG 001 MODE and so forth $channel / the channel the event occurred on, if any $msg / the message to the channel/user or the message in a raw irc line e.g whois [kr0n] is a registered nick $nick / the nick the event was sent from, can be a irc.server.com, a nick or null $me / my current nick $network / the network the event occured on e.g Quakenet $ident / the from user ident if any $host / the from user hostname if any $myident / my ident $myhost / my host $server / host from the server e.g irc.server.com $now / returns unixtime/ctime from current time. $active / returns the current window Status/#channel/Nick. $activeserver / returns an id for current server $status / returns current server status $crlf / returns newline \r\n $0-$9 / will return parts of the $msg, $<number>- will combine parts of the $msg from 0 to <number>. $0- will return everything $! / returns how many $0 $1 etc variables are filled (not sure if final name of it) $raw0-$raw9 / will return parts of the raw message, $raw<number>- will combine parts of the raw message from 0 to <number>. $raw0- will return everything $r! / returns how many $raw0 $raw1 etc variables are filled (not sure if final name of it) $+ / use to combine variables output e.g "$now $+ $server" </pre> *user set variables:* All user set variables starts with % var %variable = 4242, %variable2 = 4343; will create local variables that gets deleted when the script is done. using += instead of = will append to the variable, if both variable and new value is numbers it will combine them to a new number %variable += 4242. If a variable is created without var, the variable will be available to all scripts, saved to a file and restored when AdiIRC is started. Commands for manipulating variables: <pre> /set {-u seconds/-d] [%var] [value] / create or update a variable with value -u seconds, will delete the variable after X seconds, -d will decrease its value by 1 every second, then remove it /unset [var] / deletes a variable /inc {-u seconds/-d] [%var] [value] / increases a variable with value (only if value and var is ints) -u seconds, will delete the variable after X seconds, -d will decrease its value by 1 every second, then remove it /dec {-u seconds/-d] [%var] [value] / decreases a variable with value (only if value and var is ints) -u seconds, will delete the variable after X seconds, -d will decrease its value by 1 every second, then remove it /vars shows a list of all variables and their values </pre> *functions:* Several functions are exsists, they are all recursive and you can use any %variable or $variable as parameters: They are also usable inside if () else if () while () statements. All variable numbers are floats and all functions supports floats for precise calculations. <pre> $replace(text, text2, text3) / replace all occurrences of text2 in text with text3 $upper(text) / return text uppercase $lower(text) return text lowercase $mid(text, startpos, endpos) / return part of text from startpos to endpos $substr(text, startpos, endpos) / return part of text from startpos to endpos $left(text, pos) / return pos characters starting from left of the text $right(text, pos) / return pos characters starting from right of the text $remove(text, text2) / replace all occurrences of text2 from text $len(text) / return length of text $count(text, text2) / counts all occurrences of text2 in text $pos(text, text2) / returns first occurrences position of text2 in text $lastpos(text, text2) / returns last occurrences position of text2 in text $strip(text) / removes all color and font tags $repeat(text, times) / repeats text X times $insert(text, text2, pos) / inserts text2 into pos of text $chr(num) / returns ascii character from the number num $char(num) / returns ascii character from the number num $calc(formula) / calculate any variation of +-*/ $formatdate(date, text) / formats a unix timestamp into date using date variables %d %m %y etc $fdate(date, text) / formats a unix timestamp into date using date variables %d %m %y etc $ctime(datestamp) / converts most variations of a date stamp to unix/ctime $datediff(ctime1, ctime2) / diffs two unix/ctime and fills the $datematch array with values $datematch(num) / returns part of a $datediff, 0 = milliseconds, 1 = seconds, 2 = minutes, 3 = hours, 4 = days $host(nick) / returns the hostmask of nick $ident(nick) / returns the ident of nick $(number) / dynamically gets a $0 $1 $2 variable e.g $(1) is same as $1 (not sure if final function name) $cond(cond, execute1, execute2) / checks if cond is true then executes execute1, else executes execute2, will return string if not at the begining of the line $iif(cond, execute1, execute2) / checks if cond is true then executes execute1, else executes execute2, will return string if not at the begining of the line $round(num, decimals) / rounds down a float to X decimals $regex(text, pattern) / does a regular expression test if text matches pattern, then returns the matched part $regmatch(num) / returns the captured group at pos num from a $regex. 0 returns group count $regreplace(text, pattern, text2) / replace any occurence in text of patterh with text2 where pattern is a regular expression $file(path) / reads file to end and returns the entire output without newlines $fileloop(path) / reads through a file one line at the time, line increases +1 every time the same file is called $floop(path) / reads through a file one line at the time, line increases +1 every time the same file is called $filerandom(path) / returns a random line from a file $frand(path) / returns a random line from a file $fread(name) / reads a line from current pos in file named name $fileread(name) / reads a line from current pos in file named name $freadc(name) / reads a char/byte from current pos in file named name $freadchar(name) / reads a char/byte from current pos in file named name $fsize(file) / returns size off file in bytes $filesize(file) / returns size off file in bytes $fpos(name) / returns current position/byte in file named name $filepos(name) / returns current position/byte in file named name $flines(file) / returns amount of lines in file $filelines(file) / returns amount of lines in file $fileexists(file) / returns if file exists or not $isfile(file) / returns if file exists or not $chan(num) / if num is 0 returns how many channels you are joined on this server else returns channel name in position num $user(#chan, num) / if num is 0 returns how many users are on this #chan else returns nick in position num $nick(#chan, num) / if num is 0 returns how many users are on this #chan else returns nick in position num $server(num) / if num is 0 returns how many servers you are connected to else returns server id in position num $sread(name) / reads available bytes from socket named name (on sockread) $sockread(name) / reads available bytes from socket named name (on sockread) $sbytes(name) / returns amount of available bytes to be read from socket named name $sockbytes(name) / returns amount of available bytes to be read from socket named name </pre> *operators:* All operators can use ! to reverse the logic e.g !ison. If no operators are added it will test if remaining text is not null if (%test), if ($channel) or if (!$channel) etc. <pre> > / Will try and cast left and right variable to int and try "int1 greater than int2" < / Will try and cast left and right variable to int and try "int1 lower than int2" >= / Will try and cast left and right variable to int and try "int1 greater than or equal to int2" <= / Will try and cast left and right variable to int and try "int1 lower than or equal to int2" isbetween / Will try and cast left variable to int and right variable have to be int-int, e.g "40 isbetween 30-50" ison / check if ($nick ison $channel) nick is the channel isop / check if ($nick isop $channel) is operator on the channel ishop / check if ($nick ishop $channel) is half operator on the channel issop / check if ($nick issop $channel) is special operator on the channel isowner / check if ($nick isowner $channel) is channel owner hasvoice / check if ($nick hasvoice $channel) have voice on the channel inchan / check if i am in chan (#channel inchan) (#channel !inchan) isnum / check something is a number (5 isnum) (5 !isnum) ismatch / will check if left contains right value or right contains left value isin / same as ismatch except only checking if left value is in right value, ismatch checks both </pre> *tips:* / is not needed to execute a command in scripts e.g /echo and echo is the same. use null to check for nothing "if ($nick == null)" Comment out a line with # or several lines with /* code */ All paths needs to be escaped e.g c:\\users\\kr0n\\file.txt if only a filename is entered, the script directory will be used. All characters that needs to be escaped before used as strings are \ { } ; In some cases you might have to escape ( ) | , # $ % ; as a newline "/echo 1; /echo 2" is the same as /echo 1 /echo 2 "halt" will halt the script immediately, telling the client to eat the event and ignoring the rest of the script. "return" will halt immediately, ignoring rest of the script, but not eat anything. h1. Example scripts Simple kickcounter script: <pre> OnBefore OnCommand { if ($0 != /kick) return if (%kickcount == null) %kickcount = 0 %kickcount++ if ($2 == null) { /kick $channel $1 Kick number %kickcount halt } } </pre> Kickban example <pre> OnCommand /kb { if (!$1) { /echo /kb - Nick missing return } var %msg = $iif($channel, $2-, $3-) var %chan = $iif($channel, $channel, $2) # Set this for default ban reason, or remove for no default reason # Can be shortened to %msg = $iif(%msg, %msg, GTFO) if (%msg == null) %msg = GTFO if ($me isop %chan) { /raw MODE %chan +b *!$ident($1)@$host($1) /raw KICK %chan $1 %msg } else /echo You are not oper on %chan } </pre> Simple calculator script: <pre> OnCommand /calc { if (!$1) { /echo /calc - Parameters missing return } # typing /calc -p <expression> sends output to channel if ($1 == -p) { /msg $channel Calculating : $2- /msg $channel Result is : $calc($2-) } else { /echo Calculating : $1- /echo Result is : $calc($1-) } } </pre> Colored version <pre> OnCommand /calc { if (!$1) { /echo /calc - Parameters missing return } # typing /calc -p <expression> sends output to channel if ($1 == -p) { /msg $channel $chr(3)4Calculating : $2- /msg $channel $chr(3)4Result is : $calc($2-) } else { /echo $chr(3)4Calculating : 4$1- /echo $chr(3)4Result is : $calc($1-) } }*/ </pre> CTCP flood detection example <pre> On OnCTCPRequest { if (%count == null) /set -u 10 %count 1 else /inc -u 10 %count 1 if (%count > 4) /ignore -u 30 -t $nick!$ident@$host } </pre> Mass mode example <pre> OnCommand /mass { if (!$2) { /echo /mass - Parameters missing [+/-<mode> <nick> <nick> <nick>] return } %len = 2 # equal to while (%len <= $count(%0-, $chr(32))) while (%len <= $!) { if ($(%len) ison $channel) /mode $channel $1 $(%len) /inc %len } } </pre> Shows info about servers, channels and users <pre> On JOIN { var %s = $server(0), %c = 0, %u = 0, %t = 0, %c2 = 0; while (%t < %s) { %t++ /setserver $server(%t); %c += $chan(0) %c2 = 0 while (%c2 < $chan(0)) { %c2++ %u += $user($chan(%c2), 0) } } /echo You are on (%s) servers, (%c) channels with (%u) users } </pre> It is possible to use scripts as functions. These functions are fully nested like the client functions. Lets say you make a /mycalc like this. <pre> OnCommand /mycalc { return $calc($0+$1); } </pre> Then you can call this function with eiter /mycalc <number> <number> the normal way or $mycalc(<number, <number>) Typing /testcalc will show the result. <pre> OnCommand /testcalc { /echo $0 + $1 is $mycalc($0, $1); /echo 5 + 4 is $mycalc(5, 4); } </pre> Simple convert temperature C to F or F to C /temp C 20 will print 68 F <pre> OnCommand /temp { if ($1 == C) /echo $calc(($2 * 9/5) + 32) F else if ($1 == F) /echo $round($calc(($2 - 32) * 5/9), 1) C else /echo Temp missing } </pre> Test if input contains a link <pre> OnCommand /testlink { if (!$1) { /echo Link missing return } /echo $iif($regex($1, (?i)\\b((?:[a-z][\\w-]+:(?:/\{1\,3\}|[a-z0-9%])|www\\d\{0\,3\}[.]|[a-z0-9.\\-]+[.][a-z]\{2\,4\}/)(?:[^\\s()<>]+|\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\))+(?:\\(([^\\s()<>]+|(\\([^\\s()<>]+\\)))*\\)|[^\\s`!()\\[\\]\\\{\\\}\\\;:'".\,<>?«»“â€â€˜â€™]))), yes, no) } </pre> Retrives plot summary from captured imbd links <pre> On PRIVMSG { var %reg = $regex($0-, http://www\\.imdb\\.com(/title/[a-z0-9]+/)) if (!%reg) { return } /sockclose imdb %text = null %imdb = $regmatch(1)plotsummary %imdbchan = $channel /sockopen imdb www.imdb.com 80 } On SockOpen { if ($1 != imdb) { return } /sockwrite -n imdb GET %imdb HTTP/1.1 /sockwrite -n imdb Host: www.imdb.com /sockwrite -n imdb User-Agent: Mozilla/5.0 (Windows NT 6.1\; WOW64) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.24 Safari/536.5 /sockwrite -n imdb Referer: http://www.imdb.com /sockwrite -n imdb Accept: text/xml,application/xml,application/xhtml+xml,text/html\;q=0.9,text/plain\;q=0.8,video/x-mng,image/png,image/jpeg,image/gif\;q=0.2,text/css,*\/*\;q=0.1 /sockwrite -n imdb Accept-Language: en-us, en\;q=0.50 /sockwrite -n imdb Connection: Close$crlf } On SockRead { if ($1 != imdb) { return } %text += $sockread(imdb) } On SockClose { if ($1 != imdb) { return } if ($regex(%text, <p class="plotpar">([\\s\\S]*?)<i>)) { /msg %imdbchan $regmatch(1) } %text = null } </pre> An example showing the difference between dates <pre> OnCommand /test { $datediff($ctime(1/1 2042), $now) var %text = Difference is %text += $chr(32)$datematch(4) $iif($datematch(4) == 1, day, days) %text += $chr(32)$datematch(3) $iif($datematch(3) == 1, hour, hours) %text += $chr(32)$datematch(2) $iif($datematch(3) == 1, minut, minutes) /echo %text } </pre> Announce song changes in a channel or to a user <pre> On OnSongChanged { /nmsg <network> <channel/Nick> $0- } </pre> Announce to several channels with: <pre> On OnSongChanged { /nmsg <network> <channel1/Nick>,<channel2/Nick> $0- /nmsg <network2> <channel3/Nick> $0- } </pre>