mod_spox 0.1.0.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (105) hide show
  1. data/CHANGELOG +36 -0
  2. data/INSTALL +2 -2
  3. data/README +0 -1
  4. data/bin/mod_spox +51 -12
  5. data/data/mod_spox/extras/AOLSpeak.rb +5 -18
  6. data/data/mod_spox/extras/AutoKick.rb +44 -23
  7. data/data/mod_spox/extras/AutoMode.rb +2 -5
  8. data/data/mod_spox/extras/AutoRejoin.rb +21 -0
  9. data/data/mod_spox/extras/Bouncer.rb +10 -10
  10. data/data/mod_spox/extras/Bytes.rb +12 -0
  11. data/data/mod_spox/extras/Confess.rb +131 -52
  12. data/data/mod_spox/extras/DCC.rb +189 -0
  13. data/data/mod_spox/extras/DevWatch.rb +32 -33
  14. data/data/mod_spox/extras/FloodKicker.rb +129 -0
  15. data/data/mod_spox/extras/GoogleIt.rb +13 -0
  16. data/data/mod_spox/extras/Headers.rb +31 -4
  17. data/data/mod_spox/extras/Karma.rb +103 -49
  18. data/data/mod_spox/extras/Logger.rb +45 -30
  19. data/data/mod_spox/extras/LolSpeak.rb +1 -1
  20. data/data/mod_spox/extras/NickServ.rb +83 -0
  21. data/data/mod_spox/extras/PhpCli.rb +12 -15
  22. data/data/mod_spox/extras/PhpFuncLookup.rb +57 -25
  23. data/data/mod_spox/extras/Quotes.rb +5 -4
  24. data/data/mod_spox/extras/RegexTracker.rb +160 -0
  25. data/data/mod_spox/extras/Roulette.rb +22 -23
  26. data/data/mod_spox/extras/Search.rb +3 -2
  27. data/data/mod_spox/extras/Slashdot.rb +35 -0
  28. data/data/mod_spox/extras/Topten.rb +5 -5
  29. data/data/mod_spox/extras/TracTicket.rb +68 -0
  30. data/data/mod_spox/extras/Translate.rb +69 -30
  31. data/data/mod_spox/extras/Twitter.rb +372 -0
  32. data/data/mod_spox/extras/UrbanDictionary.rb +21 -12
  33. data/data/mod_spox/extras/Weather.rb +1 -1
  34. data/data/mod_spox/plugins/Authenticator.rb +63 -30
  35. data/data/mod_spox/plugins/Banner.rb +164 -151
  36. data/data/mod_spox/plugins/Helper.rb +18 -7
  37. data/data/mod_spox/plugins/PluginLoader.rb +46 -22
  38. data/data/mod_spox/plugins/PoolConfig.rb +52 -0
  39. data/data/mod_spox/plugins/Quitter.rb +1 -1
  40. data/data/mod_spox/plugins/Status.rb +28 -0
  41. data/lib/mod_spox/Action.rb +20 -3
  42. data/lib/mod_spox/BaseConfig.rb +1 -0
  43. data/lib/mod_spox/Bot.rb +98 -75
  44. data/lib/mod_spox/BotConfig.rb +14 -6
  45. data/lib/mod_spox/ConfigurationWizard.rb +94 -105
  46. data/lib/mod_spox/Database.rb +33 -13
  47. data/lib/mod_spox/Helpers.rb +67 -38
  48. data/lib/mod_spox/Loader.rb +25 -5
  49. data/lib/mod_spox/Logger.rb +20 -62
  50. data/lib/mod_spox/MessageFactory.rb +34 -25
  51. data/lib/mod_spox/Monitors.rb +5 -0
  52. data/lib/mod_spox/Pipeline.rb +40 -51
  53. data/lib/mod_spox/Plugin.rb +40 -9
  54. data/lib/mod_spox/PluginManager.rb +46 -38
  55. data/lib/mod_spox/Pool.rb +129 -143
  56. data/lib/mod_spox/Socket.rb +41 -50
  57. data/lib/mod_spox/Sockets.rb +211 -0
  58. data/lib/mod_spox/Timer.rb +86 -69
  59. data/lib/mod_spox/handlers/BadNick.rb +1 -1
  60. data/lib/mod_spox/handlers/Created.rb +1 -1
  61. data/lib/mod_spox/handlers/Handler.rb +9 -0
  62. data/lib/mod_spox/handlers/Invite.rb +1 -1
  63. data/lib/mod_spox/handlers/Join.rb +2 -2
  64. data/lib/mod_spox/handlers/Kick.rb +1 -1
  65. data/lib/mod_spox/handlers/LuserChannels.rb +1 -1
  66. data/lib/mod_spox/handlers/LuserOp.rb +1 -1
  67. data/lib/mod_spox/handlers/LuserUnknown.rb +1 -1
  68. data/lib/mod_spox/handlers/Mode.rb +2 -2
  69. data/lib/mod_spox/handlers/MyInfo.rb +1 -1
  70. data/lib/mod_spox/handlers/Names.rb +1 -1
  71. data/lib/mod_spox/handlers/Nick.rb +20 -3
  72. data/lib/mod_spox/handlers/NickInUse.rb +3 -3
  73. data/lib/mod_spox/handlers/Notice.rb +5 -15
  74. data/lib/mod_spox/handlers/Part.rb +1 -1
  75. data/lib/mod_spox/handlers/Ping.rb +1 -1
  76. data/lib/mod_spox/handlers/Pong.rb +1 -1
  77. data/lib/mod_spox/handlers/Privmsg.rb +2 -2
  78. data/lib/mod_spox/handlers/Quit.rb +1 -1
  79. data/lib/mod_spox/handlers/Topic.rb +2 -1
  80. data/lib/mod_spox/handlers/Welcome.rb +3 -3
  81. data/lib/mod_spox/handlers/Who.rb +9 -7
  82. data/lib/mod_spox/handlers/Whois.rb +29 -16
  83. data/lib/mod_spox/handlers/YourHost.rb +1 -1
  84. data/lib/mod_spox/messages/incoming/Privmsg.rb +38 -19
  85. data/lib/mod_spox/messages/internal/DCCListener.rb +12 -0
  86. data/lib/mod_spox/messages/internal/DCCRequest.rb +12 -0
  87. data/lib/mod_spox/messages/internal/DCCSocket.rb +19 -0
  88. data/lib/mod_spox/messages/internal/StatusRequest.rb +2 -1
  89. data/lib/mod_spox/messages/outgoing/Privmsg.rb +21 -5
  90. data/lib/mod_spox/migrations/001_initialize_models.rb +115 -0
  91. data/lib/mod_spox/models/Auth.rb +24 -16
  92. data/lib/mod_spox/models/AuthGroup.rb +4 -3
  93. data/lib/mod_spox/models/Channel.rb +20 -12
  94. data/lib/mod_spox/models/ChannelMode.rb +2 -2
  95. data/lib/mod_spox/models/Config.rb +11 -3
  96. data/lib/mod_spox/models/Group.rb +6 -1
  97. data/lib/mod_spox/models/Nick.rb +93 -33
  98. data/lib/mod_spox/models/NickChannel.rb +8 -6
  99. data/lib/mod_spox/models/NickGroup.rb +16 -0
  100. data/lib/mod_spox/models/NickMode.rb +3 -3
  101. data/lib/mod_spox/models/Server.rb +6 -2
  102. data/lib/mod_spox/models/Setting.rb +12 -6
  103. data/lib/mod_spox/models/Signature.rb +7 -13
  104. data/lib/mod_spox/models/Trigger.rb +1 -1
  105. metadata +125 -100
@@ -0,0 +1,372 @@
1
+ require 'open-uri'
2
+ require 'uri'
3
+
4
+ class Twitter < ModSpox::Plugin
5
+
6
+ def initialize(pipeline)
7
+ super
8
+ begin
9
+ require 'htmlentities'
10
+ rescue Object => boom
11
+ Logger.warn('Error: This plugin requires the HTMLEntities gem. Please install and reload plugin.')
12
+ raise Exceptions::BotException.new("Missing required HTMLEntities library")
13
+ end
14
+ begin
15
+ require 'twitter'
16
+ require 'json'
17
+ c = %q{
18
+ class ModClient < Object::Twitter::Client
19
+ def login
20
+ return @login
21
+ end
22
+ def login=(l)
23
+ @login = l
24
+ end
25
+ def password
26
+ return @password
27
+ end
28
+ def password=(p)
29
+ @password = p
30
+ end
31
+ end
32
+ }
33
+ Twitter.class_eval(c)
34
+ ModClient.configure do |conf|
35
+ conf.user_agent = 'mod_spox twitter for twits'
36
+ conf.application_name = 'mod_spox IRC bot'
37
+ conf.application_version = "#{$BOTVERSION} (#{$BOTCODENAME})"
38
+ conf.application_url = 'http://rubyforge.org/projects/mod_spox'
39
+ conf.source = 'modspoxircbot'
40
+ end
41
+ rescue Object => boom
42
+ Logger.warn("Failed to load Twitter4R. Install gem to use Twitter plugin. (#{boom})")
43
+ raise Exceptions::BotException.new('Failed to locate required gem: Twitter4R')
44
+ end
45
+ twitter = Models::Group.find_or_create(:name => 'twitter')
46
+ admin = Models::Group.find_or_create(:name => 'admin')
47
+ add_sig(:sig => 'tweet (.+)', :method => :tweet, :group => twitter, :desc => 'Send a tweet', :params => [:message])
48
+ add_sig(:sig => 'twitter auth( (\S+) (\S+))?', :method => :auth, :group => admin, :desc => 'Set/view authentication information',
49
+ :params => [:info, :username, :password], :req => 'private')
50
+ add_sig(:sig => 'twitter search (.+)', :method => :search, :desc => 'Basic twitter search', :params => [:term])
51
+ add_sig(:sig => 'twitter asearch (.+)', :method => :advanced_search, :desc => 'Advanced search (http://apiwiki.twitter.com/Search-API-Documentation#Search)',
52
+ :params => [:term])
53
+ add_sig(:sig => 'twitter followers( \S+)?', :method => :followers, :desc => 'Show followers', :params => [:twit])
54
+ add_sig(:sig => 'twitter friends( \S+)?', :method => :friends, :desc => 'Show friends', :params => [:twit])
55
+ add_sig(:sig => 'twitter friend (\S+)', :method => :add_friend, :desc => 'Add a friend', :params => [:twit], :group => admin)
56
+ add_sig(:sig => 'twitter unfriend (\S+)', :method => :remove_friend, :desc => 'Remove a friend', :params => [:twit], :group => admin)
57
+ add_sig(:sig => 'twitter info', :method => :info, :desc => 'Show twitter info')
58
+ add_sig(:sig => 'twit (\S+) (.+)', :method => :twat, :group => twitter, :desc => 'Send a direct tweet to twit', :params => [:twit, :message])
59
+ add_sig(:sig => 'twit inbox', :method => :inbox, :group => twitter, :desc => 'Show inbox contents')
60
+ add_sig(:sig => 'twitter del (\d+)', :method => :inbox_del, :group => twitter, :desc => 'Delete direct message from twitter', :params => [:m_id])
61
+ add_sig(:sig => 'tweets del (\d+)', :method => :tweets_del, :group => twitter, :desc => 'Delete a status message from twitter', :params => [:m_id])
62
+ add_sig(:sig => 'tweets (\d+)', :method => :tweets, :desc => 'Get a given message or the current message', :params => [:m_id])
63
+ add_sig(:sig => 'autotweets ?(on|off)?', :method => :auto_tweets, :desc => 'Turn on/off auto tweet for a channel', :params => [:action],
64
+ :group => admin, :req => 'public')
65
+ add_sig(:sig => 'autotweets interval( \d+)?', :method => :auto_tweets_interval, :desc => 'Set/show interval for auto tweet checks',
66
+ :group => admin, :params => [:interval])
67
+ @pipeline.hook(self, :get_timer, :Internal_TimerResponse)
68
+ @auth_info = Models::Setting.find_or_create(:name => 'twitter').value
69
+ @twitter = ModClient.new
70
+ @coder = HTMLEntities.new
71
+ @search_url = 'http://search.twitter.com/search.json'
72
+ unless(@auth_info.is_a?(Hash))
73
+ @auth_info = {:username => nil, :password => nil, :interval => 0, :channels => []}
74
+ else
75
+ connect if @twitter.authenticate?(@auth_info[:username], @auth_info[:password])
76
+ end
77
+ @last_check = Time.now
78
+ @lock = Mutex.new
79
+ @running = false
80
+ @timer = {:action => nil, :id => nil}
81
+ start_auto
82
+ end
83
+
84
+ def search(m, params)
85
+ url = URI.escape("#{@search_url}?rpp=1&q=#{params[:term]}")
86
+ reply m.replyto, do_search(url, params[:term])
87
+ end
88
+
89
+ def advanced_search(m, params)
90
+ opt = {:lang => nil, :rpp => 1, :page => 1, :since_id => nil}
91
+ term = params[:term]
92
+ opt.keys.each do |sym|
93
+ if(term =~ /\b#{sym.to_s}:(\S+)\b/)
94
+ opt[sym] = $1
95
+ term.sub!(/#{sym.to_s}:\S+/, '')
96
+ end
97
+ end
98
+ opt[:rpp] = 5 if opt[:rpp].to_i > 5
99
+ opt[:rpp] = 1 if opt[:rpp].to_i < 1
100
+ term.gsub!(/\s{2,}/, ' ')
101
+ url = URI.escape("#{@search_url}?q=#{term}&#{opt.to_a.map{|a| "#{a[0]}=#{a[1]}"}.join('&')}")
102
+ reply m.replyto, do_search(url, term)
103
+ end
104
+
105
+ def do_search(url, term)
106
+ begin
107
+ buf = open(url, 'UserAgent' => 'mod_spox IRC bot').read
108
+ result = JSON.parse(buf)
109
+ output = ["Twitter match for: \2#{term}:\2"]
110
+ result['results'].each do |item|
111
+ t = Time.parse(item['created_at'])
112
+ output << "[#{t.strftime("%Y/%m/%d-%H:%M:%S")}] <#{item['from_user']}> #{item['text']}"
113
+ end
114
+ return output
115
+ rescue Object => boom
116
+ return "\2Error:\2 Failed to receive search results (over quota?)"
117
+ end
118
+ end
119
+
120
+ def inbox(m, params)
121
+ msgs = @twitter.messages(:received)
122
+ reply m.replyto, "\2Twitter INBOX\2 Messages in inbox: #{msgs.size} (only last 5 displayed)"
123
+ msgs.slice(0..5).each do | msg |
124
+ reply m.replyto, "\2#{msg.sender.screen_name}:\2 [#{msg.id}] #{@coder.decode(msg.text)}"
125
+ end
126
+ end
127
+
128
+ def inbox_del(m, params)
129
+ begin
130
+ @twitter.message(:delete, params[:m_id])
131
+ information m.replyto, "message with ID: #{params[:m_id]} has been deleted"
132
+ rescue Object => boom
133
+ warning m.replyto, "failed to delete message with ID: #{params[:m_id]}"
134
+ end
135
+ end
136
+
137
+ def tweets_del(m, params)
138
+ begin
139
+ @twitter.status(:delete, params[:m_id])
140
+ information m.replyto, "message with ID: #{params[:m_id]} has been deleted"
141
+ rescue Object => boom
142
+ warning m.replyto, "failed to delete status message with ID: #{params[:m_id]}"
143
+ end
144
+ end
145
+
146
+ def info(m, params)
147
+ unless(@auth_info[:username].nil?)
148
+ information m.replyto, "http://twitter.com/#{@auth_info[:username]}"
149
+ else
150
+ warning m.replyto, 'currently not configured'
151
+ end
152
+ end
153
+
154
+ def auto_tweets_interval(m, params)
155
+ if(params[:interval])
156
+ int = params[:interval].strip.to_i
157
+ @auth_info[:interval] = int
158
+ save_info
159
+ update_auto
160
+ information m.replyto, "auto tweet interval updated to: #{int > 0 ? int : 'stopped'}"
161
+ else
162
+ information m.replyto, "auto tweet interval is: #{@auth_info[:interval] > 0 ? "#{@auth_info[:interval]} seconds" : 'stopped'}"
163
+ end
164
+ end
165
+
166
+ def auto_tweets(m, params)
167
+ if(params[:action])
168
+ on = @auth_info[:channels].include?(m.target.id)
169
+ if(params[:action] == 'on')
170
+ if(on)
171
+ warning m.replyto, 'this channel is already enabled for auto tweets'
172
+ else
173
+ @auth_info[:channels] << m.target.id
174
+ save_info
175
+ update_auto
176
+ information m.replyto, 'auto tweets are now enabled for this channel'
177
+ end
178
+ else
179
+ if(on)
180
+ @auth_info[:channels].delete(m.target.id)
181
+ save_info
182
+ update_auto
183
+ information m.replyto, 'auto tweets are now disabled for this channel'
184
+ else
185
+ warning m.replyto, 'this channel is not currently enabled for auto tweets'
186
+ end
187
+ end
188
+ else
189
+ information m.replyto, "auto tweets currently enabled in: #{@auth_info[:channels].size > 0 ? @auth_info[:channels].map{|i| Models::Channel[i].name}.join(', ') : 'not enabled'}"
190
+ end
191
+ end
192
+
193
+ def auth(m, params)
194
+ if(params[:info])
195
+ begin
196
+ @auth_info[:username] = params[:username]
197
+ @auth_info[:password] = params[:password]
198
+ @twitter.authenticate?(params[:username], params[:password])
199
+ save_info
200
+ information m.replyto, 'Authentication information has been updated'
201
+ rescue Object => boom
202
+ error m.replyto, "Failed to save authentication information: #{boom}"
203
+ end
204
+ else
205
+ information m.replyto, "username -> #{@auth_info[:username].nil? ? 'unset' : @auth_info[:username]} password -> #{@auth_info[:password].nil? ? 'unset' : @auth_info[:password]}"
206
+ end
207
+ end
208
+
209
+ def tweet(m, params)
210
+ begin
211
+ @twitter.status(:post, params[:message])
212
+ information m.replyto, 'tweet has been sent'
213
+ rescue Object => boom
214
+ error m.replyto, "failed to send tweet. (#{boom})"
215
+ end
216
+ end
217
+
218
+ def twat(m, params)
219
+ begin
220
+ user = @twitter.user(params[:twit])
221
+ @twitter.message(:post, params[:message], user)
222
+ information m.replyto, 'tweet has been sent'
223
+ rescue Object => boom
224
+ error m.replyto, "failed to send tweet. (#{boom})"
225
+ end
226
+ end
227
+
228
+ def followers(m, params)
229
+ begin
230
+ fs = @twitter.my(:followers)
231
+ if(fs.size > 0)
232
+ reply m.replyto, "\2Followers:\2 #{fs.map{|u| u.screen_name}.join(', ')}"
233
+ else
234
+ warning m.replyto, 'no followers found'
235
+ end
236
+ rescue Object => boom
237
+ error m.replyto, "failed to locate followers list. (#{boom})"
238
+ end
239
+ end
240
+
241
+ def friends(m, params)
242
+ begin
243
+ fs = @twitter.my(:friends)
244
+ if(fs.size > 0)
245
+ reply m.replyto, "\2Friends:\2 #{fs.map{|u| u.screen_name}.join(', ')}"
246
+ else
247
+ warning m.replyto, 'no friends found'
248
+ end
249
+ rescue Object => boom
250
+ error m.replyto, "failed to locate friends list. (#{boom})"
251
+ end
252
+ end
253
+
254
+ def add_friend(m, params)
255
+ begin
256
+ user = @twitter.user(params[:twit])
257
+ unless(@twitter.my(:friends).include?(user))
258
+ @twitter.friend(:add, user)
259
+ information m.replyto, "added new friend: #{params[:twit]}"
260
+ else
261
+ warning m.replyto, "#{params[:twit]} is already in friend list"
262
+ end
263
+ rescue Object => boom
264
+ error m.replyto, "failed to add friend #{params[:twit]}. (#{boom})"
265
+ end
266
+ end
267
+
268
+ def remove_friend(m, params)
269
+ begin
270
+ user = @twitter.user(params[:twit])
271
+ if(@twitter.my(:friends).map{|u|u.screen_name}.include?(user.screen_name))
272
+ @twitter.friend(:remove, user)
273
+ information m.replyto, "removed user from friend list: #{params[:twit]}"
274
+ else
275
+ warning m.replyto, "#{params[:twit]} is not in friend list"
276
+ end
277
+ rescue Object => boom
278
+ error m.replyto, "failed to remove friend #{params[:twit]}. (#{boom})"
279
+ end
280
+ end
281
+
282
+ def tweets(m, params)
283
+ begin
284
+ msg = @twitter.status(:get, params[:m_id])
285
+ if(msg)
286
+ reply m.replyto, "\2Tweet:\2 [#{msg.created_at.strftime("%Y/%m/%d-%H:%M:%S")}}] <#{msg.user.screen_name}> #{@coder.decode(msg.text)}"
287
+ else
288
+ warning m.replyto, "failed to find message with ID: #{params[:m_id].strip}"
289
+ end
290
+ rescue Object => boom
291
+ error m.replyto, "error encountered while attempting to fetch message. (#{boom})"
292
+ end
293
+ end
294
+
295
+ private
296
+
297
+ def check_timeline
298
+ if(@auth_info[:channels].size < 1 || @auth_info[:interval].to_i < 1)
299
+ Logger.warn('Twitter has no channels to send information to')
300
+ else
301
+ begin
302
+ things = []
303
+ @twitter.my(:friends).each do |f|
304
+ @twitter.timeline_for(:friend, :id => f.screen_name, :since => @last_check) do |status|
305
+ if(@coder.decode(status.text) =~ /^@(\S+)/)
306
+ next unless @twitter.my(:friends).map{|f|f.screen_name}.include?($1) || $1 == @twitter.login
307
+ end
308
+ things << "[#{status.created_at.strftime("%H:%M:%S")}] <#{status.user.screen_name}> #{@coder.decode(status.text)}"
309
+ end
310
+ end
311
+ @twitter.timeline_for(:me, :since => @last_check) do |status|
312
+ things << "[#{status.created_at.strftime("%H:%M:%S")}] <#{status.user.screen_name}> #{@coder.decode(status.text)}"
313
+ end
314
+ things.uniq!
315
+ things.sort!
316
+ things.each do |status|
317
+ @auth_info[:channels].each{|i| reply Models::Channel[i], "\2AutoTweet:\2 #{status}"}
318
+ end
319
+ @last_check = Time.now
320
+ rescue Object => boom
321
+ Logger.warn("Twitter encountered an error during autotweets check: #{boom}")
322
+ end
323
+ end
324
+ end
325
+
326
+ def information(to, message)
327
+ reply to, "\2Twitter (info):\2 #{message}"
328
+ end
329
+
330
+ def warning(to, message)
331
+ reply to, "\2Twitter (warn):\2 #{message}"
332
+ end
333
+
334
+ def error(to, message)
335
+ reply to, "\2Twitter (error):\2 #{message}"
336
+ end
337
+
338
+ def save_info
339
+ i = Models::Setting.find_or_create(:name => 'twitter')
340
+ i.value = @auth_info
341
+ i.save
342
+ end
343
+
344
+ def connect
345
+ @twitter.login = @auth_info[:username]
346
+ @twitter.password = @auth_info[:password]
347
+ end
348
+
349
+ def get_timer(m)
350
+ if(m.id == @timer[:id])
351
+ @timer[:action] = m.action_added? ? m.action : nil
352
+ end
353
+ end
354
+
355
+ def update_auto
356
+ if(@auth_info[:interval] > 0 && !@auth_info[:channels].empty?)
357
+ @pipeline << Messages::Internal::TimerRemove.new(@timer[:action]) if @timer[:action].nil?
358
+ start_auto
359
+ else
360
+ @pipeline << Messages::Internal::TimerRemove.new(@timer[:action]) unless @timer[:action].nil?
361
+ end
362
+ end
363
+
364
+ def start_auto
365
+ if(@auth_info[:interval] > 0 && @timer[:action].nil?)
366
+ m = Messages::Internal::TimerAdd.new(self, @auth_info[:interval].to_i){ check_timeline }
367
+ @timer[:id] = m.id
368
+ @pipeline << m
369
+ end
370
+ end
371
+
372
+ end
@@ -1,36 +1,45 @@
1
- require 'soap/rpc/driver'
1
+ require 'soap/wsdlDriver'
2
2
 
3
3
  class UrbanDictionary < ModSpox::Plugin
4
4
 
5
5
  include Messages::Outgoing
6
6
  include Models
7
-
7
+
8
8
  def initialize(pipeline)
9
9
  super(pipeline)
10
- Signature.find_or_create(:signature => 'udefine (?!key)(\d+)? ?(.+)', :plugin => name, :method => 'define',
10
+ begin
11
+ require 'htmlentities'
12
+ rescue Object => boom
13
+ Logger.warn('Error: This plugin requires the HTMLEntities gem. Please install and reload plugin.')
14
+ raise Exceptions::BotException.new("Missing required HTMLEntities library")
15
+ end
16
+ Signature.find_or_create(:signature => 'udefine (?!key)(\d+)? ?(.+)', :plugin => name, :method => 'define',
11
17
  :description => 'Find the definition of a word or phrase').params = [:number, :term]
12
18
  Signature.find_or_create(:signature => 'udefine key (.+)', :plugin => name, :method => 'key',
13
19
  :group_id => Models::Group.filter(:name => 'admin').first.pk, :description => 'Set API key').params = [:key]
20
+ @coder = HTMLEntities.new
14
21
  end
15
-
22
+
16
23
  def define(message, params)
17
24
  key = Config[:urban_key]
18
25
  if(key)
19
- site = 'http://api.urbandictionary.com/soap'
26
+ site = 'http://api.urbandictionary.com/soap?wsdl'
20
27
  result = params[:number] ? params[:number].to_i - 1 : 0
21
28
  begin
22
- udict = SOAP::RPC::Driver.new(site, 'urn:UrbanSearch')
23
- udict.add_method('lookup', 'key', 'term')
24
- defs = udict.lookup(key, params[:term])
29
+ proxy = SOAP::WSDLDriverFactory.new(site).create_rpc_driver
30
+ #udict = SOAP::RPC::Driver.new(site, 'urn:UrbanSearch')
31
+ #udict.add_method('lookup', 'key', 'term')
32
+ defs = proxy.lookup(key, params[:term])
33
+ #defs = udict.lookup(key, params[:term])
25
34
  output = []
26
35
  if defs.size < result + 1
27
36
  @pipeline << Privmsg.new(message.replyto, "Error: Definition number #{result+1} for term: #{params[:term]} not found.")
28
37
  else
29
38
  defin = defs[result].definition.length > 500 ? defs[result].definition.slice(0..500) + " *[CUT]*" : defs[result].definition
30
39
  exp = defs[result].example.length > 500 ? defs[result].example.slice(0..500) + " *[CUT]*" : defs[result].example
31
- output << ["Definition for \2#{defs[result].word}:\2"]
32
- output << defin
33
- output << "\2Example usage:\2 #{exp}" if exp.length > 0
40
+ output << "Definition for \2#{defs[result].word}:\2"
41
+ output << @coder.decode(defin.gsub(/[\r\n\s]+/, ' '))
42
+ output << "\2Example usage:\2 #{@coder.decode(exp.gsub(/[\r\n\s]+/, ' '))}" if exp.length > 0
34
43
  reply message.replyto, output
35
44
  end
36
45
  rescue Timeout::Error
@@ -42,7 +51,7 @@ class UrbanDictionary < ModSpox::Plugin
42
51
  @pipeline << Privmsg.new(message.replyto, "\2Error:\2 No valid key available for dictionary")
43
52
  end
44
53
  end
45
-
54
+
46
55
  def key(message, params)
47
56
  if(message.is_public?)
48
57
  @pipeline << Privmsg.new(message.replyto, 'I don\'t set keys in public')
@@ -42,7 +42,7 @@ class Weather < ModSpox::Plugin
42
42
  end
43
43
  output = ["Weather for: \2#{location}\2"]
44
44
  output << "Current Temp: #{curtemp} - Feels like: #{feeltemp}"
45
- output << "[UV Index: #{uv.gsub(/&.+?;/, '')}][Wind: #{wind.gsub(/&.+?;/, '')}][Humiditiy: #{humid.gsub(/&.+?;/, '')}][Pressure: #{pressure.gsub(/&.+?;/, '')}][Dew Point: #{dewpoint.gsub(/&.+?;/, '')}][Visibility: #{visibility.gsub(/&.+?;/, '')}]"
45
+ output << "[UV Index: #{uv.gsub(/&.+?;/, '')}][Wind: #{wind.gsub(/&.+?;/, '')}][Humidity: #{humid.gsub(/&.+?;/, '')}][Pressure: #{pressure.gsub(/&.+?;/, '')}][Dew Point: #{dewpoint.gsub(/&.+?;/, '')}][Visibility: #{visibility.gsub(/&.+?;/, '')}]"
46
46
  output << future.values_at(0..2).join(' ')
47
47
  reply message.replyto, output
48
48
  else