:
258 | #
259 | # For example if the bot's nick is:
260 | # bot: Hi there
261 | #
262 | # This is checked case insensitively.
263 | proc ::dictionary::is_addressing_bot {text botnick} {
264 | set text [string trim $text]
265 | set text [string tolower $text]
266 |
267 | set prefix [string tolower $botnick]
268 | append prefix :
269 |
270 | set idx [string first $prefix $text]
271 |
272 | return [expr $idx == 0]
273 | }
274 |
275 | # Return 1 if the string contains the term. This is tested case insensitively.
276 | #
277 | # The term is present only if it is by itself surrounded whitespace or
278 | # punctuation.
279 | #
280 | # e.g. if the term is 'test' then these strings contain it:
281 | #
282 | # hi test hi
283 | # hi test, hi
284 | # test
285 | #
286 | # But these do not:
287 | #
288 | # hi testing hi
289 | # hitest
290 | proc ::dictionary::string_contains_term {s term} {
291 | set term_lc [string tolower $term]
292 | set term_quoted [::dictionary::quotemeta $term_lc]
293 |
294 | set re {\m}
295 | append re $term_quoted
296 | append re {\M}
297 | return [regexp -nocase -- $re $s]
298 | }
299 |
300 | # Escape/quote metacharacters so that the string becomes suitable for placing in
301 | # a regular expression. This makes it so any regex metacharacter is quoted.
302 | #
303 | # See http://stackoverflow.com/questions/4346750/regular-expression-literal-text-span/4352893#4352893
304 | proc ::dictionary::quotemeta {s} {
305 | return [regsub -all {\W} $s {\\&}]
306 | }
307 |
308 | proc ::dictionary::get_affirmative_response {nick} {
309 | return "OK, $nick"
310 | }
311 |
312 | proc ::dictionary::get_negative_response {nick} {
313 | return "Shut up."
314 | }
315 |
316 | proc ::dictionary::get_chatty_response {nick} {
317 | set n [llength $::dictionary::chatty_responses]
318 | if {$n == 0} {
319 | return "Hi."
320 | }
321 |
322 | set idx [expr int($n*rand())]
323 | set response [lindex $::dictionary::chatty_responses $idx]
324 |
325 | return [regsub -all -- "%%nick%%" $response $nick]
326 | }
327 |
328 | # Load the term database from our data file.
329 | proc ::dictionary::load_terms {} {
330 | variable term_file
331 | variable terms
332 | set terms [dict create]
333 |
334 | if {[catch {open $term_file "r"} fp]} {
335 | return
336 | }
337 | set terms [read -nonewline $fp]
338 | close $fp
339 | set count [llength [dict keys $terms]]
340 | return $count
341 | }
342 |
343 | # Load contents of a file into a list.
344 | #
345 | # Each line of the file is made into one element in the list.
346 | #
347 | # Blank lines are skipped.
348 | #
349 | # Path: Path to the file to open
350 | #
351 | # Returns: If we do not find the file or we can't open it then we return an
352 | # empty list.
353 | proc ::dictionary::file_contents_to_list {path} {
354 | if {![file exists $path]} {
355 | return [list]
356 | }
357 | if {[catch {open $path r} fp]} {
358 | return [list]
359 | }
360 | set content [read -nonewline $fp]
361 | close $fp
362 |
363 | set l [list]
364 | foreach line [split $content "\n"] {
365 | set line [string trim $line]
366 | if {[string length $line] == 0} {
367 | continue
368 | }
369 | lappend l $line
370 | }
371 | return $l
372 | }
373 |
374 | proc ::dictionary::list_to_file {l path} {
375 | set fh [open $path w]
376 | foreach e $l {
377 | puts $fh $e
378 | }
379 | close $fh
380 | }
381 |
382 | # Load a list of nicks to skip from a data file.
383 | proc ::dictionary::load_skip_nicks {} {
384 | set ::dictionary::skip_nicks [::dictionary::file_contents_to_list \
385 | $::dictionary::skip_nick_file]
386 | }
387 |
388 | # Load chatty responses from data file.
389 | proc ::dictionary::load_chatty_responses {} {
390 | set ::dictionary::chatty_responses [::dictionary::file_contents_to_list \
391 | $::dictionary::chatty_responses_file]
392 | }
393 |
394 | # Load data from our data files into memory.
395 | proc ::dictionary::load {args} {
396 | set term_count [::dictionary::load_terms]
397 |
398 | ::dictionary::load_skip_nicks
399 |
400 | ::dictionary::load_chatty_responses
401 |
402 | return $term_count
403 | }
404 |
405 | # Save the terms and definitions to the data file.
406 | proc ::dictionary::save {} {
407 | variable term_file
408 | variable terms
409 |
410 | if {![file isdirectory [file dirname $term_file]]} {
411 | file mkdir [file dirname $term_file]
412 | }
413 | set fp [open $term_file w]
414 | puts -nonewline $fp $terms
415 | close $fp
416 | }
417 |
418 | set ::dictionary::count [::dictionary::load]
419 | if {$::dictionary::count == 1} {
420 | putlog "dictionary.tcl loaded. $::dictionary::count term."
421 | } else {
422 | putlog "dictionary.tcl loaded. $::dictionary::count terms."
423 | }
424 |
--------------------------------------------------------------------------------
/dictionary_test.tcl:
--------------------------------------------------------------------------------
1 | #
2 | # Unit tests for dictionary.tcl
3 | #
4 |
5 | # Dummy some eggdrop functions.
6 | proc ::bind {a b c d} {}
7 | proc ::setudef {a b} {}
8 | proc ::putlog {s} {}
9 |
10 | source dictionary.tcl
11 |
12 | proc ::tests {} {
13 | puts "Running tests..."
14 |
15 | set success 1
16 |
17 | if {![::test_quotemeta]} {
18 | set success 0
19 | }
20 |
21 | if {![::test_string_contains_term]} {
22 | set success 0
23 | }
24 |
25 | if {![::test_is_addressing_bot]} {
26 | set success 0
27 | }
28 |
29 | if {$success} {
30 | puts "Success!"
31 | } else {
32 | puts "Failure."
33 | exit 1
34 | }
35 | }
36 |
37 | proc ::test_quotemeta {} {
38 | set tests [list \
39 | [dict create input hi! output hi\\!] \
40 | [dict create input hi output hi] \
41 | [dict create input hi*+ output hi\\*\\+] \
42 | [dict create input hi\{\}\\ output hi\\\{\\\}\\\\] \
43 | ]
44 |
45 | set failed 0
46 |
47 | foreach test $tests {
48 | set output [::dictionary::quotemeta [dict get $test input]]
49 | if {$output != [dict get $test output]} {
50 | puts [format "FAILURE: quotemeta(%s) = %s, wanted %s" \
51 | [dict get $test input] $output [dict get $test output]]
52 |
53 | incr failed
54 | }
55 | }
56 |
57 | if {$failed != 0} {
58 | puts [format "quotemeta: %d/%d tests failed" $failed [llength $tests]]
59 | }
60 |
61 | return [expr $failed == 0]
62 | }
63 |
64 | proc ::test_string_contains_term {} {
65 | set tests [list \
66 | [dict create s "hi test hi" term "test" want 1] \
67 | [dict create s "hi testing hi" term "test" want 0] \
68 | [dict create s "hi test, hi" term "test" want 1] \
69 | [dict create s "hi test. hi" term "test" want 1] \
70 | [dict create s "test" term "test" want 1] \
71 | [dict create s "hi test" term "test" want 1] \
72 | [dict create s "test hi" term "test" want 1] \
73 | [dict create s "test hi" term "TEST" want 1] \
74 | [dict create s "TEST hi" term "test" want 1] \
75 | ]
76 |
77 | set failed 0
78 |
79 | foreach test $tests {
80 | set s [dict get $test s]
81 | set term [dict get $test term]
82 | set want [dict get $test want]
83 |
84 | set output [::dictionary::string_contains_term $s $term]
85 | if {$output != $want} {
86 | puts [format "FAILURE: string_contains_term(\"%s\", \"%s\") = %d, wanted %d" \
87 | $s $term $output $want]
88 |
89 | incr failed
90 | }
91 | }
92 |
93 | if {$failed != 0} {
94 | puts [format "string_contains_term: %d/%d tests failed" $failed \
95 | [llength $tests]]
96 | }
97 |
98 | return [expr $failed == 0]
99 | }
100 |
101 | proc ::test_is_addressing_bot {} {
102 | set tests [list \
103 | [dict create line "bot: hi" botnick "bot" want 1] \
104 | [dict create line "BOT: hi" botnick "bot" want 1] \
105 | [dict create line "bot: hi" botnick "BOT" want 1] \
106 | [dict create line "bot:hi" botnick "BOT" want 1] \
107 | [dict create line "bot hi" botnick "bot" want 0] \
108 | [dict create line "bot2: hi" botnick "bot" want 0] \
109 | [dict create line ": hi" botnick "bot" want 0] \
110 | [dict create line "hi bot: hi" botnick "bot" want 0] \
111 | [dict create line "bbot: hi" botnick "bot" want 0] \
112 | [dict create line "botbot: hi" botnick "bot" want 0] \
113 | ]
114 |
115 | set failed 0
116 |
117 | foreach test $tests {
118 | set line [dict get $test line]
119 | set botnick [dict get $test botnick]
120 | set want [dict get $test want]
121 |
122 | set output [::dictionary::is_addressing_bot $line $botnick]
123 | if {$output != $want} {
124 | puts [format "FAILURE: is_addressing_bot(\"%s\", \"%s\") = %d, wanted %d" \
125 | $s $line $botnick $want]
126 |
127 | incr failed
128 | }
129 | }
130 |
131 | if {$failed != 0} {
132 | puts [format "string_contains_term: %d/%d tests failed" $failed \
133 | [llength $tests]]
134 | }
135 |
136 | return [expr $failed == 0]
137 | }
138 |
139 | ::tests
140 |
--------------------------------------------------------------------------------
/horgh_autoop.tcl:
--------------------------------------------------------------------------------
1 | # Auto op script. Ops everyone in channels set +horgh_autoop
2 | #
3 | #
4 | # Last change Sat Nov 15 17:18:29 PST 2008
5 | #
6 | # Created Thu Oct 23 18:32:36 PDT 2008
7 | # By horgh
8 |
9 | namespace eval horgh_autoop {
10 | variable output_cmd putserv
11 |
12 | setudef flag horgh_autoop
13 | bind join -|- * horgh_autoop::horgh_autoop
14 | }
15 |
16 | proc horgh_autoop::horgh_autoop {nick host hand chan} {
17 | if {![channel get $chan horgh_autoop]} { return }
18 | $horgh_autoop::output_cmd "MODE $chan +o $nick"
19 | }
20 |
21 | putlog "horgh_autoop.tcl loaded"
22 |
--------------------------------------------------------------------------------
/irb.tcl:
--------------------------------------------------------------------------------
1 | #
2 | # 0.2 - ???
3 | # - fix error when rehash/restart if socket isnt open
4 | #
5 | # 0.1 - May 15 2010
6 | # - initial release
7 | #
8 | # by horgh (www.summercat.com)
9 | #
10 | # A _VERY UNSAFE_ wrapper for irb <-> irc via eggdrop
11 | #
12 | # Setup:
13 | # - make sure you set/check the 3 variables (channel, command char, irb path)
14 | #
15 | # Usage:
16 | # - {command_char}reset to get a fresh irb session
17 | #
18 | # - any commands prefixed with command_char are sent to irb and the result is
19 | # posted to the channel
20 | # - e.g.
21 | # <@horgh> 'test
22 | # <@Yorick> Starting new irb session...
23 | # <@Yorick> => ArgumentError: wrong number of arguments
24 | # <@Yorick> => from (irb):1:in `test'
25 | # <@Yorick> => from (irb):1
26 | #
27 | # BUGS:
28 | # - since "=>" isn't shown from the open call for some reason (perhaps it goes
29 | # to stderr or something, i'm not sure), some results that print on same line
30 | # do not display nicely, such as:
31 | # '5.times { print "*" }
32 | # results in "=> *****5" whereas it should be "*****=> 5" from the prompt
33 | #
34 |
35 | namespace eval irb {
36 | # Settings
37 |
38 | # channel to respond to irb commands / send output
39 | set channel #YOUR_CHANNEL
40 | # system path to irb binary
41 | set irb {/usr/local/bin/irb}
42 | # prefix character for sending data to irb
43 | set command_char "'"
44 |
45 | #set output_cmd cd::putnow
46 | set output_cmd putserv
47 |
48 | # You shouldn't need to edit anything below here
49 |
50 | set irb_chan []
51 | # store commands entered here so we don't output them
52 | # they are deleted as they come up from reading irb output
53 | set cmd_cache []
54 |
55 | bind pubm -|- "*" irb::put
56 | bind pub -|- "${command_char}reset" irb::reset
57 | bind evnt -|- "prerestart" irb::end
58 | bind evnt -|- "prerehash" irb::end
59 | }
60 |
61 | proc irb::put {nick uhost hand chan argv} {
62 | if {$chan != $irb::channel} { return }
63 | if {[string index $argv 0] != $irb::command_char} { return}
64 |
65 | set cmd [string range $argv 1 end]
66 | if {$cmd == "reset" } { return }
67 | if {$cmd == ""} { return }
68 |
69 | if {$irb::irb_chan == []} {
70 | setup_irb
71 | }
72 |
73 | lappend irb::cmd_cache $cmd
74 | puts $irb::irb_chan $cmd
75 | }
76 |
77 | proc irb::reset {nick uhost hand chan argv} {
78 | $irb::output_cmd "PRIVMSG $irb::channel :Closing irb session."
79 | irb::end
80 | }
81 |
82 | proc irb::setup_irb {} {
83 | $irb::output_cmd "PRIVMSG $irb::channel :Starting new irb session..."
84 | set irb::irb_chan [open "|${irb::irb}" r+]
85 | fconfigure $irb::irb_chan -blocking 1 -buffering line
86 | # call irb::output when data to be read
87 | fileevent $irb::irb_chan readable irb::output
88 | }
89 |
90 | proc irb::output {} {
91 | set output [gets $irb::irb_chan]
92 | set output [string map {\t " "} $output]
93 |
94 | # check if it is a command sent to irb rather than a result (to not print)
95 | set index [lsearch -exact $irb::cmd_cache $output]
96 | if {$index >= 0} {
97 | set irb::cmd_cache [lreplace $irb::cmd_cache $index $index]
98 | } else {
99 | $irb::output_cmd "PRIVMSG $irb::channel :=> $output"
100 | }
101 | }
102 |
103 | # We close channel before restart/rehash
104 | proc irb::end {args} {
105 | if {$irb::irb_chan == ""} { return }
106 | close $irb::irb_chan
107 | set irb::irb_chan []
108 | }
109 |
110 | putlog "irb.tcl loaded"
111 |
--------------------------------------------------------------------------------
/latoc.tcl:
--------------------------------------------------------------------------------
1 | # Provides binds to read Yahoo.com futures
2 | #
3 | # If you update this, update the one in
4 | # https://github.com/horgh/irssi-tcl-scripts.
5 | package require http
6 | package require tls
7 | ::http::register https 443 [list ::tls::socket -ssl2 0 -ssl3 0 -tls1 1]
8 |
9 | namespace eval ::latoc {
10 | variable output_cmd putserv
11 |
12 | variable user_agent "Lynx/2.8.5rel.1 libwww-FM/2.14 SSL-MM/1.4.1 OpenSSL/0.9.7e"
13 |
14 | variable list_regexp {
}
15 | variable stock_regexp {(.*) | (.*) | (.*) | (.*) | symbol name price last change percent volume interest]} {
56 | error "error parsing HTML"
57 | }
58 |
59 | set direction none
60 | if {$change < 0} {
61 | set direction Down
62 | }
63 | if {$change > 0} {
64 | set direction Up
65 | }
66 | lappend lines [::latoc::format $name $price $last $direction $change $percent]
67 | }
68 |
69 | return $lines
70 | }
71 |
72 | proc ::latoc::output {chan lines symbol_pattern} {
73 | foreach line $lines {
74 | if {![regexp -- $symbol_pattern $line]} {
75 | continue
76 | }
77 | $::latoc::output_cmd "PRIVMSG $chan :$line"
78 | }
79 | }
80 |
81 | proc ::latoc::oil_handler {nick uhost hand chan argv} {
82 | if {![channel get $chan latoc]} { return }
83 |
84 | set data [::latoc::fetch $chan]
85 | set lines [::latoc::parse $data]
86 | ::latoc::output $chan $lines {Crude Oil}
87 | }
88 |
89 | proc ::latoc::gold_handler {nick uhost hand chan argv} {
90 | if {![channel get $chan latoc]} { return }
91 |
92 | set data [::latoc::fetch $chan]
93 | set lines [::latoc::parse $data]
94 | ::latoc::output $chan $lines {Gold}
95 | }
96 |
97 | proc ::latoc::silver_handler {nick uhost hand chan argv} {
98 | if {![channel get $chan latoc]} { return }
99 |
100 | set data [::latoc::fetch $chan]
101 | set lines [::latoc::parse $data]
102 | ::latoc::output $chan $lines {Silver}
103 | }
104 |
105 | proc ::latoc::format {name price last direction change percent} {
106 | return "$name: \00310$price [::latoc::colour $direction $change] [::latoc::colour $direction $percent]\003 $last"
107 | }
108 |
109 | proc ::latoc::colour {direction value} {
110 | if {[string match "Down" $direction]} {
111 | return \00304$value\017
112 | }
113 | if {[string match "Up" $direction]} {
114 | return \00309$value\017
115 | }
116 | return $value
117 | }
118 |
119 | putlog "latoc.tcl loaded"
120 |
--------------------------------------------------------------------------------
/mysqlquote.tcl:
--------------------------------------------------------------------------------
1 | #
2 | # 16/08/2010
3 | # by horgh
4 | #
5 | # MySQL quote script
6 | #
7 | # Setup:
8 | # The table must be called "quote" and have the following schema:
9 | # CREATE TABLE quote (
10 | # qid SMALLINT UNSIGNED NOT NULL AUTO_INCREMENT,
11 | # uid SMALLINT UNSIGNED NOT NULL,
12 | # quote TEXT NOT NULL,
13 | # PRIMARY KEY (qid)
14 | # );
15 | # Other keys are possible but not required
16 | #
17 | # aq (addquote) usage:
18 | # - \n starts a new line for the quote
19 | # - e.g.: aq hi there!\n hey
20 | # becomes the quote:
21 | # hi there
22 | # hey
23 | #
24 |
25 | package require mysqltcl
26 |
27 | namespace eval sqlquote {
28 | variable output_cmd putserv
29 |
30 | # MySQL settings
31 | variable host localhost
32 | variable user quote
33 | variable pass quote
34 | variable db quote
35 |
36 | # mysql connection handler
37 | variable conn []
38 |
39 | # search results stored in this dict
40 | variable results []
41 |
42 | bind pub -|- latest sqlquote::latest
43 | bind pub -|- quotestats sqlquote::stats
44 | bind pub -|- quote sqlquote::quote
45 | bind pub -|- aq sqlquote::addquote
46 | bind pub m|- delquote sqlquote::delquote
47 |
48 | setudef flag quote
49 | }
50 |
51 | proc sqlquote::connect {} {
52 | # If connection not initialised or has disconnected
53 | if {![mysql::state $sqlquote::conn -numeric] || ![mysql::ping $sqlquote::conn]} {
54 | set sqlquote::conn [mysql::connect -host $sqlquote::host -user $sqlquote::user -password $sqlquote::pass -db $sqlquote::db]
55 | putlog "Connecting to db..."
56 | }
57 | }
58 |
59 | # fetch a single quote row with given statement
60 | proc sqlquote::fetch_single {stmt} {
61 | mysql::sel $sqlquote::conn $stmt
62 | mysql::map $sqlquote::conn {qid quote} {
63 | set q [list qid $qid quote $quote]
64 | }
65 | return $q
66 | }
67 |
68 | proc sqlquote::fetch_search {terms} {
69 | putlog "Retrieving new quotes for $terms..."
70 | set terms [mysql::escape $sqlquote::conn $terms]
71 | set stmt "SELECT qid, quote FROM quote WHERE quote LIKE \"%${terms}%\" LIMIT 20"
72 | set count [mysql::sel $sqlquote::conn $stmt]
73 | if {$count <= 0} {
74 | return []
75 | }
76 | mysql::map $sqlquote::conn {qid quote} {
77 | lappend quotes [list qid $qid quote $quote]
78 | }
79 | return $quotes
80 | }
81 |
82 | proc sqlquote::stats {nick host hand chan argv} {
83 | if {![channel get $chan quote]} { return }
84 | sqlquote::connect
85 | set stmt "SELECT COUNT(qid) FROM quote"
86 | mysql::sel $sqlquote::conn $stmt
87 | mysql::map $sqlquote::conn {c} {
88 | set count $c
89 | }
90 | $sqlquote::output_cmd "PRIVMSG $chan :There are $count quotes in the database."
91 | }
92 |
93 | proc sqlquote::latest {nick host hand chan argv} {
94 | if {![channel get $chan quote]} { return }
95 | sqlquote::connect
96 | set stmt "SELECT qid, quote FROM quote ORDER BY qid DESC LIMIT 1"
97 | sqlquote::output $chan [sqlquote::fetch_single $stmt]
98 | }
99 |
100 | proc sqlquote::random {} {
101 | set stmt "SELECT qid, quote FROM quote ORDER BY RAND() LIMIT 1"
102 | return [sqlquote::fetch_single $stmt]
103 | }
104 |
105 | proc sqlquote::quote_by_id {id} {
106 | set stmt "SELECT qid, quote FROM quote WHERE qid = ${id}"
107 | return [sqlquote::fetch_single $stmt]
108 | }
109 |
110 | proc sqlquote::quote {nick host hand chan argv} {
111 | if {![channel get $chan quote]} { return }
112 | sqlquote::connect
113 | if {$argv == ""} {
114 | sqlquote::output $chan [sqlquote::random]
115 | } elseif {[string is integer $argv]} {
116 | sqlquote::output $chan [sqlquote::quote_by_id $argv]
117 | } else {
118 | sqlquote::output $chan {*}[sqlquote::search $argv]
119 | }
120 | }
121 |
122 | proc sqlquote::search {terms} {
123 | set terms [regsub -all -- {\*} $terms "%"]
124 | if {![dict exists $sqlquote::results $terms]} {
125 | dict set sqlquote::results $terms [sqlquote::fetch_search $terms]
126 | }
127 |
128 | # Extract one quote from results
129 | set quotes [dict get $sqlquote::results $terms]
130 | set quote [lindex $quotes 0]
131 | set quotes [lreplace $quotes 0 0]
132 |
133 | # Remove key if no quotes after removal of one, else update quotes
134 | if {![llength $quotes]} {
135 | dict unset sqlquote::results $terms
136 | } else {
137 | dict set sqlquote::results $terms $quotes
138 | }
139 | return [list $quote [llength $quotes]]
140 | }
141 |
142 | proc sqlquote::addquote {nick host hand chan argv} {
143 | if {![channel get $chan quote]} { return }
144 | if {$argv == ""} {
145 | $sqlquote::output_cmd "PRIVMSG $chan :Usage: aq "
146 | return
147 | }
148 | sqlquote::connect
149 |
150 | set argv [regsub -all -- {\\n} $argv \n]
151 | set quote [mysql::escape $sqlquote::conn $argv]
152 | set stmt "INSERT INTO quote (uid, quote) VALUES(1, \"${quote}\")"
153 | set count [mysql::exec $sqlquote::conn $stmt]
154 | $sqlquote::output_cmd "PRIVMSG $chan :${count} quote added."
155 | }
156 |
157 | proc sqlquote::delquote {nick host hand chan argv} {
158 | if {$argv == "" || ![string is integer $argv]} {
159 | $sqlquote::output_cmd "PRIVMSG $chan :Usage: delquote <#>"
160 | return
161 | }
162 | sqlquote::connect
163 | set stmt "DELETE FROM quote WHERE qid = ${argv}"
164 | set count [mysql::exec $sqlquote::conn $stmt]
165 | $sqlquote::output_cmd "PRIVMSG $chan :#${argv} deleted. ($count quotes affected.)"
166 | }
167 |
168 | # quote is dict of form {qid ID quote TEXT}
169 | proc sqlquote::output {chan quote {left {}}} {
170 | if {$quote == ""} {
171 | $sqlquote::output_cmd "PRIVMSG $chan :No quotes found."
172 | return
173 | }
174 | set qid [dict get $quote qid]
175 | set text [dict get $quote quote]
176 | set head "Quote #\002$qid\002"
177 | if {$left ne ""} {
178 | set head "${head} ($left left)"
179 | }
180 | $sqlquote::output_cmd "PRIVMSG $chan :$head"
181 | foreach l [split $text \n] {
182 | $sqlquote::output_cmd "PRIVMSG $chan : $l"
183 | }
184 | }
185 |
186 | sqlquote::connect
187 | putlog "sqlquote.tcl loaded"
188 |
--------------------------------------------------------------------------------
/patternban.tcl:
--------------------------------------------------------------------------------
1 | #
2 | # 10/07/2011
3 | #
4 |
5 | namespace eval patternban {
6 | variable filename "scripts/patternbans.txt"
7 | variable ban_reason "bye"
8 |
9 | # List of pattern bans. Each item in list has the syntax:
10 | # {channel} {host pattern} {words pattern}
11 | variable patternbans [list]
12 |
13 | bind msg o|- "!addpatternban" ::patternban::add
14 | bind msg o|- "!listpatternbans" ::patternban::ls
15 | bind msg o|- "!delpatternban" ::patternban::rm
16 |
17 | bind pubm -|- "*" ::patternban::match
18 | }
19 |
20 | # Return a list consisting of the 3 parts of a uhost: nick!ident@host
21 | # Not used. Only part of match_mask.
22 | proc ::patternban::split_uhost {uhost} {
23 | set nick_uhost [split $uhost !]
24 | set nick [lindex $nick_uhost 0]
25 |
26 | set ident_host [split [lindex $nick_uhost 1] @]
27 |
28 | set ident [lindex $ident_host 0]
29 | set host [lindex $ident_host 1]
30 |
31 | return [list $nick $ident $host]
32 | }
33 |
34 | # Return whether uhost matches the given uhost_mask
35 | # Not used. Same as matchaddr?
36 | proc ::patternban::match_mask {uhost_mask uhost} {
37 | set mask_split [::patternban::split_uhost $uhost_mask]
38 | set uhost_split [::patternban::split_uhost $uhost]
39 | # Nick portion
40 | if {[string match [lindex $mask_split 0] [lindex $uhost_split 0]]} {
41 | # Ident portion
42 | if {[string match [lindex $mask_split 1] [lindex $uhost_split 1]]} {
43 | if {[string match [lindex $mask_split 2] [lindex $uhost_split 2]]} {
44 | return 1
45 | }
46 | }
47 | }
48 | return 0
49 | }
50 |
51 | proc ::patternban::ban {chan nick uhost} {
52 | putlog "Trying to ban ${nick}!${uhost} on $chan."
53 | putserv "mode $chan +b [maskhost $uhost 3]"
54 | putserv "kick $chan $nick :$::patternban::ban_reason"
55 | }
56 |
57 | proc ::patternban::match {nick uhost hand chan text} {
58 | foreach pattern $::patternban::patternbans {
59 | set pattern_channel [lindex $pattern 0]
60 | set pattern_uhost [lindex $pattern 1]
61 | set pattern_pattern [lindex $pattern 2]
62 | if {$chan == $pattern_channel} {
63 | if {[string match *${pattern_pattern}* $text] && [matchaddr $pattern_uhost ${nick}!${uhost}]} {
64 | ::patternban::ban $chan $nick $uhost
65 | return
66 | }
67 | }
68 | }
69 | }
70 |
71 | proc ::patternban::add {nick uhost hand text} {
72 | set text [split $text]
73 | if {[llength $text] != 3} {
74 | putserv "PRIVMSG $nick :Usage: !addpatternban <#channel> "
75 | return
76 | }
77 | set channel [lindex $text 0]
78 | set uhost_pattern [lindex $text 1]
79 | set pattern [lindex $text 2]
80 | lappend ::patternban::patternbans [list $channel $uhost_pattern $pattern]
81 | ::patternban::save_patternbans
82 | putserv "PRIVMSG $nick :Added pattern ban on $channel for $uhost_pattern containing $pattern."
83 | }
84 |
85 | proc ::patternban::ls {nick uhost hand text} {
86 | set count 0
87 | putserv "PRIVMSG $nick :[llength $::patternban::patternbans] patternbans."
88 | foreach pattern $::patternban::patternbans {
89 | putserv "PRIVMSG $nick :#${count}: $pattern"
90 | incr count
91 | }
92 | }
93 |
94 | proc ::patternban::rm {nick uhost hand text} {
95 | set text [split $text]
96 | if {[llength $text] != 1 || ![string is digit $text]} {
97 | putserv "PRIVMSG $nick :Usage: !delpatternban <#>"
98 | return
99 | }
100 | if {$text >= [llength $::patternban::patternbans]} {
101 | putserv "PRIVMSG $nick :Error: No such pattern ban."
102 | return
103 | }
104 | set ::patternban::patternbans [lreplace $::patternban::patternbans $text $text]
105 | putserv "PRIVMSG $nick :Pattern ban deleted."
106 | ::patternban::save_patternbans
107 | }
108 |
109 | proc ::patternban::save_patternbans {} {
110 | if {[catch {open $::patternban::filename w} fid]} {
111 | return
112 | }
113 | puts -nonewline $fid $::patternban::patternbans
114 | close $fid
115 | }
116 |
117 | proc ::patternban::load_patternbans {} {
118 | if {[catch {open $::patternban::filename r} fid]} {
119 | return
120 | }
121 | set ::patternban::patternbans [read -nonewline $fid]
122 | close $fid
123 | }
124 |
125 | ::patternban::load_patternbans
126 | putlog "patternban.tcl loaded"
127 |
--------------------------------------------------------------------------------
/slang.tcl:
--------------------------------------------------------------------------------
1 | #
2 | # slang.tcl - June 24 2010
3 | # by horgh
4 | #
5 | # Requires Tcl 8.5+ and tcllib
6 | #
7 | # Made with heavy inspiration from perpleXa's urbandict script!
8 | #
9 | # Must .chanset #channel +ud
10 | #
11 | # Uses is.gd to shorten long definition URL if isgd.tcl package present
12 | #
13 |
14 | package require htmlparse
15 | package require http
16 | package require tls
17 |
18 | ::http::register https 443 [list ::tls::socket -ssl2 0 -ssl3 0 -tls1 1]
19 |
20 | namespace eval ::ud {
21 | # set this to !ud or whatever you want
22 | variable trigger "slang"
23 |
24 | # maximum lines to output
25 | variable max_lines 1
26 |
27 | # approximate characters per line
28 | variable line_length 400
29 |
30 | # show truncated message / url if more than one line
31 | variable show_truncate 1
32 |
33 | # toggle whether we store raw response data.
34 | # this will store the response from an http request to urbandictionary.com
35 | # in files for debugging.
36 | # NOTE: enabling this will cause a file to be created for every request
37 | # the script makes, so these can pile up quickly!
38 | variable store_responses 0
39 | # the directory to store responses if store_responses is on.
40 | # this is under your eggdrop directory.
41 | # files under this directory will be named with unix timestamps
42 | # (microseconds).
43 | variable store_responses_dir slang_responses
44 |
45 | variable output_cmd "putserv"
46 |
47 | variable client "Mozilla/5.0 (compatible; Y!J; for robot study; keyoshid)"
48 | variable url https://www.urbandictionary.com/define.php
49 | variable url_random https://www.urbandictionary.com/random.php
50 |
51 | # regex to find the word
52 | variable word_regex {(.*?)}
53 | variable list_regex { .*? |