#---------------------------------------------------------------------# # incith:morse $Rev:: 105 $ # # $Id:: incith-morse.tcl 105 2009-01-23 03:54:09Z incith $ # # # # meant to provide a base for http-based scripts # # tested on Eggdrop 1.6.19 & Windrop v1.6.17 # # # # Usage: # # .chanset #channel +morse # # !morse # # returns the of # # # # ChangeLog (m/d/y): # # 1/22/09: script created for KB1OHY, replacement for Morse.tcl. # # # # TODO: # # - Suggestions/Thanks/Bugs/Ideas, e-mail at bottom of header. # # # # LICENSE (GPLv3): # # This program is free software: you can redistribute it and/or # # modify it under the terms of the GNU General Public License as # # published by the Free Software Foundation, either version 3 of # # the License, or (at your option) any later version. # # # # This program is distributed in the hope that it will be useful, # # but WITHOUT ANY WARRANTY; without even the implied warranty of # # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. # # # # See the GNU General Public License for more details. # # (http://www.gnu.org/licenses/gpl-3.0.txt) # # # # Copyright (C) 2009, Jordan # # http://incith.com ~ incith@gmail.com ~ irc.freenode.net/#incith # #---------------------------------------------------------------------# package require http 2.3 setudef flag morse # 0 (zero) will disable an optional variable, 1 or above enables # namespace eval incith::morse { # the bind prefix/command char(s) ({!} or {! .} etc, separate with space) variable command_chars {! .} # binds {one two three} variable binds {morse} # allow binds to be used in /msg's to the bot? variable private_messages 1 # send public/channel output to the user instead? variable public_to_private 0 # send replies as notices instead of private messages? variable notices 0 # levels required to use the binds, global|channel. variable public_flags {-|-} variable private_flag {-|-} # only the global flag matters. # only send script 'errors' as notices? (not enough input etc) variable notice_errors_only 0 # bold the 'Morse:' and 'Text:' words? variable bold 1 # maximum length of a reply before breaking it up variable split_length 440 # if your bots participate in a botnet, you can enable this variable # and load the script on all of the bots, but only one bot will respond # to morse requests. if that bot quits, the next bot in line will start. # there is no reason to disable this variable that I can think of. variable botnet 1 } # script begings namespace eval incith::morse { global botnet-nick nick if {${botnet-nick} == ""} { set botnet-nick ${nick} } variable version "incith:morse-SVN" variable debug 0 array set static {} if {${incith::morse::botnet} >= 1} { set static(botnet,${botnet-nick},time) [clock seconds] } else { set static(botnet,${botnet-nick},time) "noswarm" } if {![info exists static(botnet,bots)]} { set static(botnet,bots) ${botnet-nick} } } # bind the binds foreach command_char [split ${incith::morse::command_chars} " "] { foreach bind [split ${incith::morse::binds} " "] { # public message binds bind pub ${incith::morse::public_flags} "${command_char}${bind}" incith::morse::message_handler # private message binds if {${incith::morse::private_messages} >= 1} { bind msg ${incith::morse::private_flag} "${command_char}${bind}" incith::morse::message_handler } } } # bind the botnet binds if {${incith::morse::botnet} >= 1} { bind bot - incith:morse incith::morse::bot_msg bind link - * incith::morse::bot_link # it really depends what works better for you, checking if # the bot is onchan or just making sure they are linked. # bind disc - * incith::morse::bot_disc } namespace eval incith::morse { proc bot_msg {from cmd text} { global botnet-nick upvar #0 incith::morse::static static if {${incith::morse::debug} >= 1} { putlog "${incith::morse::version} (botmsg): <${from}> ${cmd} ${text}" } # receiving a bots load time if {[string match "time ?*" $text]} { regexp -- {time (.*)} $text - time set static(botnet,${from},time) $time # make sure this bot is in our bot list if {![string match "*${from}*" $static(botnet,bots)]} { putlog "${incith::morse::version} (botnet): ${from} has joined the incith:morse swarm." append static(botnet,bots) ";${from}" regsub -all -- {;;} $static(botnet,bots) {;} static(botnet,bots) set static(botnet,bots) [string trimright $static(botnet,bots) {;}] } } } proc bot_link {bot hub} { global botnet-nick upvar #0 incith::morse::static static # send our time to the bots putallbots "incith:morse time $static(botnet,${botnet-nick},time)" } proc bot_disc {bot} { global botnet-nick upvar #0 incith::morse::static static if {[string match "*${bot}*" $static(botnet,bots)]} { if {$static(botnet,${bot},time) != "noswarm"} { putlog "${incith::morse::version} (botnet): ${bot} has left the incith:morse swarm." } } # remove this bot from our bot list regsub -all -- $bot $static(botnet,bots) {} static(botnet,bots) regsub -all -- {;;} $static(botnet,bots) {;} static(botnet,bots) set static(botnet,bots) [string trimright $static(botnet,bots) {;}] # remove their time? If they just lost link, they might still be [onchan] # unset static(botnet,${bot},time) } } namespace eval incith::morse { # [message_handler] : handles public & private messages # proc message_handler {nick uhand hand args} { global botnet-nick lastbind upvar #0 incith::morse::static static set input(who) $nick if {[llength $args] >= 2} { # public message set input(where) [lindex $args 0] if {${incith::morse::public_to_private} >= 1} { set input(chan) $input(who) } else { set input(chan) $input(where) } set input(query) [lindex $args 1] if {[channel get $input(where) morse] != 1} { return } } else { # private message set input(where) "private" set input(chan) $input(who) set input(query) [lindex $args 0] if {${incith::morse::private_messages} <= 0} { return } } # botnet if {${incith::morse::botnet} >= 1 && $input(where) != "private"} { foreach bot [split $static(botnet,bots) ";"] { # skip ourselves, bots not on the input channel, and bots not participating if {${bot} == ${botnet-nick} || ![onchan ${bot} $input(where)] || $static(botnet,${bot},time) == "noswarm"} { continue # bots that load last will serve first. change > into < to reverse. } elseif {$static(botnet,${bot},time) > $static(botnet,${botnet-nick},time)} { if {${incith::morse::debug} >= 1} { putlog "${incith::morse::version} (botnet): $bot loaded before me." } return # should 2 bots have the same time, set a new random time (this did happen in testing) } elseif {$static(botnet,${bot},time) == $static(botnet,${botnet-nick},time)} { if {${incith::morse::debug} >= 1} { putlog "${incith::morse::version} (botnet): $bot had the same load time as me, fixing." } set static(botnet,${botnet-nick},time) [expr [clock seconds] + int(rand()*60)+1] putallbots "incith:morse time $static(botnet,${botnet-nick},time)" return } } # looks like we're serving, make sure we keep the botnet up to date putallbots "incith:morse time $static(botnet,${botnet-nick},time)" } # log it if {[regexp -- {^\s*$} $input(query)]} { ipl "<${input(who)}/${input(where)}>" send_output $input(chan) "Syntax: ${lastbind} " return } else { ipl ${input(who)} ${input(where)} "${lastbind} ${input(query)}" } # do some things: if {![string match -nocase {*[a-zA-Z0-9,\?'!/\(\)\&\:\;\=+_\"\$\@]*} $input(query)]} { send_output $input(chan) "[ibold "Text:"] [string toupper [morse2text "$input(query) "]]" } else { send_output $input(chan) "[ibold "Morse:"] [text2morse $input(query)]" } } # [text2morse] : turns text into morse code # proc text2morse {text} { return [string map -nocase "{a} {.- } {b} {-... } {c} {-.-. } {d} {-.. } {e} {. } {f} {..-. } {g} {--. } {h} {.... } {i} {.. } {j} {.--- } {k} {-.- } {l} {.-.. } {m} {-- } {n} {-. } {o} {--- } {p} {.--. } {q} {--.- } {r} {.-. } {s} {... } {t} {- } {u} {..- } {v} {...- } {w} {.-- } {x} {-..- } {y} {-.-- } {z} {--.. } {0} {----- } {1} {.---- } {2} {..--- } {3} {...-- } {4} {....- } {5} {..... } {6} {-.... } {7} {--... } {8} {---.. } {9} {----. } {.} {.-.-.- } {,} {--..-- } {\?} {..--.. } {'} {.----. } {!} {-.-.-- } {/} {-..-. } {(} {-.--. } {)} {-.--.- } {&} {.-... } {:} {---... } {;} {-.-.-. } {=} {-...- } {+} {.-.-. } {-} {-....- } {_} {..--.- } {\"} {.-..-. } {$} {...-..- } {@} {.--.-. }" $text] } # [morse2text] : turns morse into text # proc morse2text {morse} { return [string map -nocase "{.- } {a} {-... } {b} {-.-. } {c} {-.. } {d} {. } {e} {..-. } {f} {--. } {g} {.... } {h} {.. } {i} {.--- } {j} {-.- } {k} {.-.. } {l} {-- } {m} {-. } {n} {--- } {o} {.--. } {p} {--.- } {q} {.-. } {r} {... } {s} {- } {t} {..- } {u} {...- } {v} {.-- } {w} {-..- } {x} {-.-- } {y} {--.. } {z} {----- } {0} {.---- } {1} {..--- } {2} {...-- } {3} {....- } {4} {..... } {5} {-.... } {6} {--... } {7} {---.. } {8} {----. } {9} {.-.-.- } {.} {--..-- } {,} {..--.. } {\?} {.----. } {'} {-.-.-- } {!} {-..-. } {/} {-.--. } {(} {-.--.- } {)} {.-... } {&} {---... } {:} {-.-.-. } {;} {-...- } {=} {.-.-. } {+} {-....- } {-} {..--.- } {_} {.-..-. } {\"} {...-..- } {$} {.--.-. } {@}" $morse] } # [ipl] : a neat/handy putlog procedure # proc ipl {who {where {}} {what {}}} { if {$where == "" && $what == ""} { # first argument only = data only putlog "${incith::morse::version}: ${who}" } elseif {$where != "" && $what == ""} { # two arguments = who and data putlog "${incith::morse::version}: <${who}> ${where}" } else { # all three... putlog "${incith::morse::version}: <${who}/${where}> ${what}" } } # [send_output] : sends $data appropriately out to $where # proc send_output {where data {isErrorNick {}}} { if {${incith::morse::notices} >= 1} { foreach line [incith::morse::line_wrap $data] { putquick "NOTICE $where :${line}" } } elseif {${incith::morse::notice_errors_only} >= 1 && $isErrorNick != ""} { foreach line [incith::morse::line_wrap $data] { putquick "NOTICE $isErrorNick :${line}" } } else { foreach line [incith::morse::line_wrap $data] { putquick "PRIVMSG $where :${line}" } } } # [line_wrap] : takes a long line in, and chops it before the specified length # http://forum.egghelp.org/viewtopic.php?t=6690 # proc line_wrap {str {splitChr { }}} { set out [set cur {}] set i 0 set len $incith::morse::split_length foreach word [split [set str][set str ""] $splitChr] { if {[incr i [string len $word]] > $len} { lappend out [join $cur $splitChr] set cur [list $word] set i [string len $word] } else { lappend cur $word } incr i } lappend out [join $cur $splitChr] } # [ibold] : bolds some text, if bolding is enabled # proc ibold {input} { if {${incith::morse::bold} >= 1} { return "\002${input}\002" } return $input } } # the script has loaded. namespace eval incith::morse { putallbots "incith:morse time $static(botnet,${botnet-nick},time)" } incith::morse::ipl "loaded." # EOF