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
152
153
154
155
156
157
158
159
160
161
162
|
#-- vim:sw=2:et
#++
#
# :title: bash.org quote retrieval
#
# Author:: Robin Kearney <robin@riviera.org.uk>
# Author:: cs
# Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
#
# Copyright:: (C) 2005 Robin Kearney
# Copyright:: (C) 2007 cs, Giuseppe Bilotta
#
# License:: public domain
#
# TODO improve output of quote
# TODO show more than one quote
# TODO allow selection of only quotes with vote > 0
require 'rexml/document'
class ::BashQuote
attr_accessor :num, :text, :irc_text, :vote
def initialize(num, text, vote)
@num = num.to_i
@text = text
@vote = vote
@irc_text = mk_irc_text
end
def url
"http://www.bash.org/?#{@num}"
end
private
def mk_irc_text
cur_nick = nil
last_nick = nil
text = String.new
@text.each_line { |l|
debug "line: #{l.inspect}"
cur_nick = l.match(/^\s*(<.*?>|\(.*?\)|.*?:)/)[1] rescue nil
debug "nick: #{cur_nick.inspect}; last: #{last_nick.inspect}"
if cur_nick and cur_nick == last_nick
text << l.sub(cur_nick,"")
else
last_nick = cur_nick.dup if cur_nick
text << l
end
}
debug text
# TODO: the gsub of br tags to | should be an ircify_html option
text.gsub(/(?:<br \/>\s*)+/, ' | ').ircify_html
end
end
class BashPlugin < Plugin
BotConfig.register BotConfigEnumValue.new('bash.access',
:values => ['xml', 'html'], :default => 'html',
:desc => "Which method the bot should use to access bash.org quotes: xml files or standard webpages")
include REXML
def help(plugin, topic="")
"bash => print a random quote from bash.org, bash quote_id => print that quote id from bash.org, bash latest => print the latest quote from bash.org (currently broken, need to get josh@bash.org to fix the xml)"
end
def bash(m, params)
id = params[:id]
case @bot.config['bash.access'].intern
when :xml
xml_bash(m, id)
else
html_bash(m, :id => id)
end
end
def search(m, params)
esc = CGI.escape(params[:words].to_s)
html = @bot.httputil.get("http://bash.org/?search=#{esc}")
html_bash(m, :html => html)
end
def html_bash(m, opts={})
quotes = []
html = opts[:html]
if not html
id = opts[:id]
case id
when 'latest'
html = @bot.httputil.get("http://bash.org/?latest")
when nil
html = @bot.httputil.get("http://bash.org/?random", :cache => false)
else
html = @bot.httputil.get("http://bash.org/?" + id)
end
end
html_quotes = html.split(/<p class="quote">/)
html_quotes.each { |htqt|
# debug htqt.inspect
if htqt.match(/<a href="\?(\d+)"[^>]*>.*?\((-?\d+)\).*?<p class="qt">(.*)<\/p>\s+(?:<\/td>.*)?\z/m)
num = $1
vote = $2
text = $3
quotes << BashQuote.new(num, text, vote)
end
}
case quotes.length
when 0
m.reply "no quotes found"
return
when 1
quote = quotes.first
else
# For the time being, we only echo the first quote, but in the future we
# may want to echo more than one for latest/random
quote = quotes.first
end
m.reply "#%d (%d): %s" % [quote.num, quote.vote, quote.irc_text]
end
def xml_bash(m, id=nil)
case id
when 'latest'
xml = @bot.httputil.get("http://bash.org/xml/?latest&num=1")
when nil
xml = @bot.httputil.get("http://bash.org/xml/?random&num=1", :cache => false)
else
xml = @bot.httputil.get("http://bash.org/xml/?" + id + "&num=1")
end
unless xml
m.reply "bash.org rss parse failed"
return
end
doc = Document.new xml
unless doc
m.reply "bash.org rss parse failed"
return
end
doc.elements.each("*/item") {|e|
if(id != 0)
reply = e.elements["title"].text.gsub(/QDB: /,"") + " " + e.elements["link"].text.gsub(/QDB: /,"") + "\n"
reply = reply + e.elements["description"].text.gsub(/\<br \/\>/, "\n")
else
reply = e.elements["title"].text.gsub(/QDB: /,"") + " " + e.elements["link"].text.gsub(/QDB: /,"") + "\n"
reply = reply + e.elements["description"].text.gsub(/\<br \/\>/, "\n")
end
m.reply reply
}
end
end
plugin = BashPlugin.new
plugin.map "bash search *words", :action => :search
plugin.map "bash [:id]"
|