-
Notifications
You must be signed in to change notification settings - Fork 19
/
Copy pathbash.tcl
151 lines (127 loc) · 3.99 KB
/
bash.tcl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
# bash.org quote fetcher
# Must .chanset #channel +bash
#
# Usage: !bash [optional search terms]
# If search terms are not provided, fetch random quotes.
#
# Keeps fetched quotes in memory until displayed, including all results per
# search term
package require http
package require htmlparse
namespace eval ::bash {
variable trigger !bash
variable line_length 399
variable max_lines 10
variable useragent "Mozilla/5.0 (compatible; Y!J; for robot study; keyoshid)"
variable output_cmd putserv
setudef flag bash
bind pub -|- $::bash::trigger ::bash::handler
variable url http://bash.org/?
variable list_regexp {<p class="quote">.*?<p class="qt">.*?</p>}
variable quote_regexp {<p class="quote">.*?<b>#(.*?)</b>.*?class="qa".*?</a>\((.*)\)<a.*?<p class="qt">(.*?)</p>}
variable random_quotes []
variable search_quotes []
}
proc ::bash::quote_output {chan quote} {
if {$quote == ""} {
$::bash::output_cmd "PRIVMSG $chan :No result!"
return
}
set number [dict get $quote number]
set rating [dict get $quote rating]
set quote [::htmlparse::mapEscapes [dict get $quote quote]]
set quote [regsub -all -- {<br />} $quote ""]
$::bash::output_cmd "PRIVMSG $chan :#\002${number}\002 (Rating: ${rating})"
foreach line [split $quote \n] {
if {[incr count] > $::bash::max_lines} {
$::bash::output_cmd "PRIVMSG $chan :Output truncated. ${::bash::url}${number}"
break
}
foreach subline [::bash::split_line $::bash::line_length $line] {
$::bash::output_cmd "PRIVMSG $chan : $subline"
}
}
}
proc ::bash::handler {nick uhost hand chan argv} {
if {![channel get $chan bash]} { return }
if {$argv == ""} {
if {[catch {::bash::random $chan} result]} {
$::bash::output_cmd "PRIVMSG $chan :Error: $result"
return
}
::bash::quote_output $chan $result
} else {
if {[catch {::bash::search $argv $chan} result]} {
$::bash::output_cmd "PRIVMSG $chan :Error: $result"
return
}
::bash::quote_output $chan $result
}
}
proc ::bash::random {chan} {
if {![llength $::bash::random_quotes]} {
$::bash::output_cmd "PRIVMSG $chan :Fetching new random quotes..."
set ::bash::random_quotes [::bash::fetch ${::bash::url}random1]
}
set quote [lindex $::bash::random_quotes 0]
set ::bash::random_quotes [lreplace $::bash::random_quotes 0 0]
return $quote
}
proc ::bash::search {query chan} {
if {![dict exists $::bash::search_quotes $query]} {
$::bash::output_cmd "PRIVMSG $chan :Fetching results..."
set url ${::bash::url}[::http::formatQuery search $query sort 0 show 25]
dict set ::bash::search_quotes $query [::bash::fetch $url]
}
set quotes [dict get $::bash::search_quotes $query]
set quote [lindex $quotes 0]
set quotes [lreplace $quotes 0 0]
# Remove key if no more quotes after removal of one, else set quotes to remaining
if {![llength $quotes]} {
dict unset ::bash::search_quotes $query
} else {
dict set ::bash::search_quotes $query $quotes
}
return $quote
}
proc ::bash::fetch {url} {
::http::config -useragent $::bash::useragent
set token [::http::geturl $url -timeout 10000]
set data [::http::data $token]
set ncode [::http::ncode $token]
::http::cleanup $token
if {$ncode != 200} {
error "HTTP fetch error $ncode: $data"
}
return [::bash::parse $data]
}
proc ::bash::parse {html} {
set quotes []
foreach raw_quote [regexp -all -inline -- $::bash::list_regexp $html] {
if {![regexp $::bash::quote_regexp $raw_quote -> number rating quote]} {
error "Parse error"
}
# Strip <font color=green|red> from rating
regsub -all {<font.*?>} $rating {} rating
regsub -all {</font>} $rating {} rating
lappend quotes [list number $number rating $rating quote $quote]
}
return $quotes
}
# by fedex
proc ::bash::split_line {max str} {
set last [expr {[string length $str] -1}]
set start 0
set end [expr {$max -1}]
set lines []
while {$start <= $last} {
if {$last >= $end} {
set end [string last { } $str $end]
}
lappend lines [string trim [string range $str $start $end]]
set start $end
set end [expr {$start + $max}]
}
return $lines
}
putlog "bash.tcl loaded"