rbot 0.9.14 → 0.9.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (368) hide show
  1. data/AUTHORS +6 -2
  2. data/REQUIREMENTS +7 -1
  3. data/Rakefile +10 -32
  4. data/bin/rbot +6 -1
  5. data/bin/svnwatch-postcommit-hook +68 -0
  6. data/data/rbot/contrib/plugins/stats.rb +3 -3
  7. data/data/rbot/contrib/plugins/vandale.rb +1 -1
  8. data/data/rbot/filters/rss.rb +72 -0
  9. data/data/rbot/languages/finnish.lang +50 -0
  10. data/data/rbot/plugins/alias.rb +6 -6
  11. data/data/rbot/plugins/autorejoin.rb +41 -2
  12. data/data/rbot/plugins/bans.rb +100 -6
  13. data/data/rbot/plugins/bash.rb +9 -4
  14. data/data/rbot/plugins/cal.rb +1 -1
  15. data/data/rbot/plugins/chucknorris.rb +6 -6
  16. data/data/rbot/plugins/debugger.rb +7 -3
  17. data/data/rbot/plugins/deepthoughts.rb +1 -1
  18. data/data/rbot/plugins/delicious.rb +6 -2
  19. data/data/rbot/plugins/dice.rb +7 -7
  20. data/data/rbot/plugins/dict.rb +4 -3
  21. data/data/rbot/plugins/dictclient.rb +17 -13
  22. data/data/rbot/plugins/digg.rb +3 -3
  23. data/data/rbot/plugins/eightball.rb +1 -1
  24. data/data/rbot/plugins/factoids.rb +13 -4
  25. data/data/rbot/plugins/figlet.rb +4 -4
  26. data/data/rbot/plugins/forecast.rb +3 -3
  27. data/data/rbot/plugins/fortune.rb +14 -8
  28. data/data/rbot/plugins/freshmeat.rb +2 -2
  29. data/data/rbot/plugins/games/azgame.rb +72 -19
  30. data/data/rbot/plugins/games/hangman.rb +499 -0
  31. data/data/rbot/plugins/games/quiz.rb +15 -13
  32. data/data/rbot/plugins/games/roshambo.rb +1 -1
  33. data/data/rbot/plugins/games/roulette.rb +4 -4
  34. data/data/rbot/plugins/games/shiritori.rb +31 -31
  35. data/data/rbot/plugins/games/uno.rb +28 -6
  36. data/data/rbot/plugins/games/wheelfortune.rb +1 -3
  37. data/data/rbot/plugins/geoip.rb +83 -28
  38. data/data/rbot/plugins/googlefight.rb +64 -0
  39. data/data/rbot/plugins/greet.rb +45 -0
  40. data/data/rbot/plugins/grouphug.rb +40 -12
  41. data/data/rbot/plugins/imdb.rb +4 -4
  42. data/data/rbot/plugins/insult.rb +2 -2
  43. data/data/rbot/plugins/karma.rb +6 -5
  44. data/data/rbot/plugins/keywords.rb +26 -22
  45. data/data/rbot/plugins/lart.rb +5 -6
  46. data/data/rbot/plugins/lastfm.rb +488 -125
  47. data/data/rbot/plugins/lib_spotify.rb +84 -0
  48. data/data/rbot/plugins/linkbot.rb +1 -1
  49. data/data/rbot/plugins/markov.rb +567 -78
  50. data/data/rbot/plugins/math.rb +3 -3
  51. data/data/rbot/plugins/modes.rb +1 -1
  52. data/data/rbot/plugins/nickrecover.rb +1 -1
  53. data/data/rbot/plugins/nickserv.rb +7 -7
  54. data/data/rbot/plugins/note.rb +55 -0
  55. data/data/rbot/plugins/nslookup.rb +2 -2
  56. data/data/rbot/plugins/quakeauth.rb +4 -4
  57. data/data/rbot/plugins/quotes.rb +53 -19
  58. data/data/rbot/plugins/reaction.rb +76 -19
  59. data/data/rbot/plugins/remind.rb +3 -96
  60. data/data/rbot/plugins/ri.rb +1 -1
  61. data/data/rbot/plugins/rot13.rb +1 -1
  62. data/data/rbot/plugins/rss.rb +296 -190
  63. data/data/rbot/plugins/salut.rb +8 -8
  64. data/data/rbot/plugins/script.rb +48 -11
  65. data/data/rbot/plugins/search.rb +124 -28
  66. data/data/rbot/plugins/seen.rb +162 -31
  67. data/data/rbot/plugins/shortenurls.rb +1 -1
  68. data/data/rbot/plugins/slashdot.rb +19 -6
  69. data/data/rbot/plugins/spotify.rb +78 -0
  70. data/data/rbot/plugins/theyfightcrime.rb +10 -10
  71. data/data/rbot/plugins/time.rb +2 -2
  72. data/data/rbot/plugins/translator.rb +161 -85
  73. data/data/rbot/plugins/tube.rb +2 -2
  74. data/data/rbot/plugins/tumblr.rb +143 -0
  75. data/data/rbot/plugins/twitter.rb +25 -6
  76. data/data/rbot/plugins/urban.rb +6 -4
  77. data/data/rbot/plugins/url.rb +49 -10
  78. data/data/rbot/plugins/weather.rb +6 -6
  79. data/data/rbot/plugins/wserver.rb +5 -5
  80. data/data/rbot/plugins/youtube.rb +12 -12
  81. data/data/rbot/templates/lart/larts-italian +1 -1
  82. data/launch_here.rb +68 -0
  83. data/lib/rbot/botuser.rb +1 -1
  84. data/lib/rbot/compat19.rb +70 -0
  85. data/lib/rbot/config.rb +8 -6
  86. data/lib/rbot/core/auth.rb +37 -21
  87. data/lib/rbot/core/basics.rb +33 -2
  88. data/lib/rbot/core/config.rb +24 -17
  89. data/lib/rbot/core/filters_ui.rb +2 -2
  90. data/lib/rbot/core/irclog.rb +20 -11
  91. data/lib/rbot/core/remote.rb +9 -9
  92. data/lib/rbot/core/unicode.rb +4 -0
  93. data/lib/rbot/core/userdata.rb +16 -1
  94. data/lib/rbot/core/utils/extends.rb +76 -0
  95. data/lib/rbot/core/utils/filters.rb +47 -0
  96. data/lib/rbot/core/utils/httputil.rb +36 -26
  97. data/lib/rbot/core/utils/parse_time.rb +193 -0
  98. data/lib/rbot/core/utils/utils.rb +81 -56
  99. data/lib/rbot/core/utils/wordlist.rb +66 -0
  100. data/lib/rbot/core/wordlist_ui.rb +27 -0
  101. data/lib/rbot/irc.rb +59 -19
  102. data/lib/rbot/ircbot.rb +190 -58
  103. data/lib/rbot/ircsocket.rb +14 -8
  104. data/lib/rbot/language.rb +4 -3
  105. data/lib/rbot/load-gettext.rb +22 -9
  106. data/lib/rbot/message.rb +89 -18
  107. data/lib/rbot/messagemapper.rb +71 -19
  108. data/lib/rbot/plugins.rb +112 -44
  109. data/lib/rbot/{registry.rb → registry/bdb.rb} +226 -22
  110. data/lib/rbot/registry/tc.rb +531 -0
  111. data/lib/rbot/rfc2812.rb +33 -8
  112. data/lib/rbot/timer.rb +12 -20
  113. data/po/en_US/rbot-autorejoin.po +3 -0
  114. data/po/en_US/rbot-azgame.po +51 -43
  115. data/po/en_US/rbot-bash.po +15 -0
  116. data/po/en_US/rbot-dictclient.po +20 -20
  117. data/po/en_US/rbot-factoids.po +9 -9
  118. data/po/en_US/rbot-geoip.po +0 -0
  119. data/po/en_US/rbot-googlefight.po +24 -0
  120. data/po/en_US/rbot-grouphug.po +4 -4
  121. data/po/en_US/rbot-hangman.po +114 -0
  122. data/po/en_US/rbot-keywords.po +3 -3
  123. data/po/en_US/rbot-lastfm.po +268 -70
  124. data/po/en_US/rbot-markov.po +73 -2
  125. data/po/en_US/rbot-quotes.po +21 -21
  126. data/po/en_US/rbot-rss.po +6 -2
  127. data/po/en_US/rbot-script.po +3 -0
  128. data/po/en_US/rbot-seen.po +72 -0
  129. data/po/en_US/rbot-spell.po +2 -2
  130. data/po/en_US/rbot-translator.po +13 -13
  131. data/po/en_US/rbot-twitter.po +3 -3
  132. data/po/en_US/rbot-uno.po +131 -114
  133. data/po/en_US/rbot-wall.po +12 -13
  134. data/po/en_US/rbot-wheelfortune.po +41 -41
  135. data/po/en_US/rbot.po +254 -194
  136. data/po/fi/rbot-alias.po +82 -0
  137. data/po/fi/rbot-autoop.po +0 -0
  138. data/po/fi/rbot-autorejoin.po +20 -0
  139. data/po/fi/rbot-azgame.po +194 -0
  140. data/po/fi/rbot-bans.po +0 -0
  141. data/po/fi/rbot-bash.po +32 -0
  142. data/po/fi/rbot-botsnack.po +0 -0
  143. data/po/fi/rbot-cal.po +20 -0
  144. data/po/fi/rbot-chanserv.po +0 -0
  145. data/po/fi/rbot-chucknorris.po +0 -0
  146. data/po/fi/rbot-debugger.po +0 -0
  147. data/po/fi/rbot-deepthoughts.po +0 -0
  148. data/po/fi/rbot-delicious.po +0 -0
  149. data/po/fi/rbot-dice.po +0 -0
  150. data/po/fi/rbot-dict.po +0 -0
  151. data/po/fi/rbot-dictclient.po +111 -0
  152. data/po/fi/rbot-digg.po +0 -0
  153. data/po/fi/rbot-eightball.po +0 -0
  154. data/po/fi/rbot-excuse.po +0 -0
  155. data/po/fi/rbot-factoids.po +107 -0
  156. data/po/fi/rbot-figlet.po +36 -0
  157. data/po/fi/rbot-fish.po +0 -0
  158. data/po/fi/rbot-forecast.po +0 -0
  159. data/po/fi/rbot-fortune.po +0 -0
  160. data/po/fi/rbot-freshmeat.po +0 -0
  161. data/po/fi/rbot-geoip.po +0 -0
  162. data/po/fi/rbot-googlefight.po +24 -0
  163. data/po/fi/rbot-grouphug.po +35 -0
  164. data/po/fi/rbot-hangman.po +121 -0
  165. data/po/fi/rbot-hl2.po +0 -0
  166. data/po/fi/rbot-host.po +20 -0
  167. data/po/fi/rbot-imdb.po +0 -0
  168. data/po/fi/rbot-insult.po +0 -0
  169. data/po/fi/rbot-iplookup.po +0 -0
  170. data/po/fi/rbot-karma.po +0 -0
  171. data/po/fi/rbot-keywords.po +24 -0
  172. data/po/fi/rbot-lart.po +0 -0
  173. data/po/fi/rbot-lastfm.po +377 -0
  174. data/po/fi/rbot-linkbot.po +0 -0
  175. data/po/fi/rbot-markov.po +91 -0
  176. data/po/fi/rbot-math.po +0 -0
  177. data/po/fi/rbot-modes.po +0 -0
  178. data/po/fi/rbot-nickrecover.po +36 -0
  179. data/po/fi/rbot-nickserv.po +104 -0
  180. data/po/fi/rbot-nslookup.po +0 -0
  181. data/po/fi/rbot-quakeauth.po +0 -0
  182. data/po/fi/rbot-quiz.po +0 -0
  183. data/po/fi/rbot-quotes.po +108 -0
  184. data/po/fi/rbot-reaction.po +0 -0
  185. data/po/fi/rbot-remind.po +0 -0
  186. data/po/fi/rbot-remotectl.po +0 -0
  187. data/po/fi/rbot-ri.po +0 -0
  188. data/po/fi/rbot-roshambo.po +0 -0
  189. data/po/fi/rbot-rot13.po +0 -0
  190. data/po/fi/rbot-roulette.po +0 -0
  191. data/po/fi/rbot-rss.po +24 -0
  192. data/po/fi/rbot-salut.po +0 -0
  193. data/po/fi/rbot-script.po +20 -0
  194. data/po/fi/rbot-search.po +0 -0
  195. data/po/fi/rbot-seen.po +92 -0
  196. data/po/fi/rbot-shiritori.po +102 -0
  197. data/po/fi/rbot-shortenurls.po +0 -0
  198. data/po/fi/rbot-slashdot.po +0 -0
  199. data/po/fi/rbot-spell.po +54 -0
  200. data/po/fi/rbot-theyfightcrime.po +0 -0
  201. data/po/fi/rbot-threat.po +0 -0
  202. data/po/fi/rbot-time.po +0 -0
  203. data/po/fi/rbot-topic.po +0 -0
  204. data/po/fi/rbot-translator.po +77 -0
  205. data/po/fi/rbot-tube.po +0 -0
  206. data/po/fi/rbot-twitter.po +24 -0
  207. data/po/fi/rbot-uno.po +529 -0
  208. data/po/fi/rbot-urban.po +0 -0
  209. data/po/fi/rbot-url.po +0 -0
  210. data/po/fi/rbot-usermodes.po +0 -0
  211. data/po/fi/rbot-wall.po +32 -0
  212. data/po/fi/rbot-weather.po +0 -0
  213. data/po/fi/rbot-wheelfortune.po +205 -0
  214. data/po/fi/rbot-wow.po +0 -0
  215. data/po/fi/rbot-wserver.po +0 -0
  216. data/po/fi/rbot-youtube.po +58 -0
  217. data/po/fi/rbot.po +1152 -0
  218. data/po/fr/rbot-autorejoin.po +3 -0
  219. data/po/fr/rbot-azgame.po +51 -43
  220. data/po/fr/rbot-bash.po +15 -0
  221. data/po/fr/rbot-dictclient.po +20 -20
  222. data/po/fr/rbot-factoids.po +9 -9
  223. data/po/fr/rbot-geoip.po +0 -0
  224. data/po/fr/rbot-googlefight.po +24 -0
  225. data/po/fr/rbot-grouphug.po +4 -4
  226. data/po/fr/rbot-hangman.po +114 -0
  227. data/po/fr/rbot-keywords.po +3 -3
  228. data/po/fr/rbot-lastfm.po +268 -70
  229. data/po/fr/rbot-markov.po +74 -2
  230. data/po/fr/rbot-quotes.po +21 -21
  231. data/po/fr/rbot-rss.po +6 -2
  232. data/po/fr/rbot-script.po +3 -0
  233. data/po/fr/rbot-seen.po +72 -0
  234. data/po/fr/rbot-spell.po +2 -2
  235. data/po/fr/rbot-translator.po +13 -13
  236. data/po/fr/rbot-twitter.po +3 -3
  237. data/po/fr/rbot-uno.po +132 -114
  238. data/po/fr/rbot-wall.po +8 -9
  239. data/po/fr/rbot-wheelfortune.po +41 -41
  240. data/po/fr/rbot.po +268 -197
  241. data/po/it/rbot-autorejoin.po +3 -0
  242. data/po/it/rbot-azgame.po +50 -42
  243. data/po/it/rbot-bash.po +15 -0
  244. data/po/it/rbot-dictclient.po +20 -20
  245. data/po/it/rbot-factoids.po +9 -9
  246. data/po/it/rbot-geoip.po +0 -0
  247. data/po/it/rbot-googlefight.po +24 -0
  248. data/po/it/rbot-grouphug.po +4 -4
  249. data/po/it/rbot-hangman.po +114 -0
  250. data/po/it/rbot-keywords.po +3 -3
  251. data/po/it/rbot-lastfm.po +268 -70
  252. data/po/it/rbot-markov.po +75 -3
  253. data/po/it/rbot-quotes.po +21 -21
  254. data/po/it/rbot-rss.po +7 -3
  255. data/po/it/rbot-script.po +19 -0
  256. data/po/it/rbot-seen.po +72 -0
  257. data/po/it/rbot-spell.po +2 -2
  258. data/po/it/rbot-translator.po +13 -13
  259. data/po/it/rbot-twitter.po +3 -3
  260. data/po/it/rbot-uno.po +137 -116
  261. data/po/it/rbot-wall.po +8 -9
  262. data/po/it/rbot-wheelfortune.po +41 -41
  263. data/po/it/rbot.po +265 -208
  264. data/po/ja/rbot-autorejoin.po +3 -0
  265. data/po/ja/rbot-azgame.po +51 -43
  266. data/po/ja/rbot-bash.po +15 -0
  267. data/po/ja/rbot-dictclient.po +20 -20
  268. data/po/ja/rbot-factoids.po +9 -9
  269. data/po/ja/rbot-geoip.po +0 -0
  270. data/po/ja/rbot-googlefight.po +24 -0
  271. data/po/ja/rbot-grouphug.po +4 -4
  272. data/po/ja/rbot-hangman.po +114 -0
  273. data/po/ja/rbot-keywords.po +3 -3
  274. data/po/ja/rbot-lastfm.po +268 -70
  275. data/po/ja/rbot-markov.po +73 -2
  276. data/po/ja/rbot-quotes.po +21 -21
  277. data/po/ja/rbot-rss.po +6 -2
  278. data/po/ja/rbot-script.po +3 -0
  279. data/po/ja/rbot-seen.po +72 -0
  280. data/po/ja/rbot-spell.po +2 -2
  281. data/po/ja/rbot-translator.po +13 -13
  282. data/po/ja/rbot-twitter.po +3 -3
  283. data/po/ja/rbot-uno.po +131 -114
  284. data/po/ja/rbot-wall.po +8 -9
  285. data/po/ja/rbot-wheelfortune.po +41 -41
  286. data/po/ja/rbot.po +248 -192
  287. data/po/rbot-alias.pot +2 -2
  288. data/po/rbot-autorejoin.pot +21 -0
  289. data/po/rbot-azgame.pot +51 -43
  290. data/po/rbot-bash.pot +33 -0
  291. data/po/rbot-cal.pot +2 -2
  292. data/po/rbot-dictclient.pot +21 -21
  293. data/po/rbot-factoids.pot +10 -10
  294. data/po/rbot-figlet.pot +2 -2
  295. data/po/rbot-geoip.pot +0 -0
  296. data/po/rbot-googlefight.pot +25 -0
  297. data/po/rbot-grouphug.pot +6 -6
  298. data/po/rbot-hangman.pot +115 -0
  299. data/po/rbot-host.pot +2 -2
  300. data/po/rbot-keywords.pot +4 -4
  301. data/po/rbot-lastfm.pot +270 -72
  302. data/po/rbot-markov.pot +74 -3
  303. data/po/rbot-nickrecover.pot +2 -2
  304. data/po/rbot-nickserv.pot +2 -2
  305. data/po/rbot-quotes.pot +22 -22
  306. data/po/rbot-rss.pot +7 -3
  307. data/po/rbot-script.pot +21 -0
  308. data/po/rbot-seen.pot +90 -0
  309. data/po/rbot-shiritori.pot +2 -2
  310. data/po/rbot-spell.pot +3 -3
  311. data/po/rbot-translator.pot +14 -14
  312. data/po/rbot-twitter.pot +4 -4
  313. data/po/rbot-uno.pot +132 -115
  314. data/po/rbot-wall.pot +2 -2
  315. data/po/rbot-wheelfortune.pot +42 -42
  316. data/po/rbot-youtube.pot +2 -2
  317. data/po/rbot.pot +249 -193
  318. data/po/zh_CN/rbot-autorejoin.po +3 -0
  319. data/po/zh_CN/rbot-azgame.po +50 -42
  320. data/po/zh_CN/rbot-bash.po +15 -0
  321. data/po/zh_CN/rbot-dictclient.po +20 -20
  322. data/po/zh_CN/rbot-factoids.po +9 -9
  323. data/po/zh_CN/rbot-geoip.po +0 -0
  324. data/po/zh_CN/rbot-googlefight.po +24 -0
  325. data/po/zh_CN/rbot-grouphug.po +4 -4
  326. data/po/zh_CN/rbot-hangman.po +114 -0
  327. data/po/zh_CN/rbot-keywords.po +3 -3
  328. data/po/zh_CN/rbot-lastfm.po +268 -70
  329. data/po/zh_CN/rbot-markov.po +73 -2
  330. data/po/zh_CN/rbot-quotes.po +21 -21
  331. data/po/zh_CN/rbot-rss.po +6 -2
  332. data/po/zh_CN/rbot-script.po +3 -0
  333. data/po/zh_CN/rbot-seen.po +72 -0
  334. data/po/zh_CN/rbot-spell.po +2 -2
  335. data/po/zh_CN/rbot-translator.po +13 -13
  336. data/po/zh_CN/rbot-twitter.po +3 -3
  337. data/po/zh_CN/rbot-uno.po +131 -114
  338. data/po/zh_CN/rbot-wall.po +7 -8
  339. data/po/zh_CN/rbot-wheelfortune.po +41 -41
  340. data/po/zh_CN/rbot.po +248 -192
  341. data/po/zh_TW/rbot-autorejoin.po +3 -0
  342. data/po/zh_TW/rbot-azgame.po +50 -42
  343. data/po/zh_TW/rbot-bash.po +15 -0
  344. data/po/zh_TW/rbot-dictclient.po +20 -20
  345. data/po/zh_TW/rbot-factoids.po +9 -9
  346. data/po/zh_TW/rbot-geoip.po +0 -0
  347. data/po/zh_TW/rbot-googlefight.po +24 -0
  348. data/po/zh_TW/rbot-grouphug.po +4 -4
  349. data/po/zh_TW/rbot-hangman.po +114 -0
  350. data/po/zh_TW/rbot-keywords.po +3 -3
  351. data/po/zh_TW/rbot-lastfm.po +268 -70
  352. data/po/zh_TW/rbot-markov.po +73 -2
  353. data/po/zh_TW/rbot-quotes.po +21 -21
  354. data/po/zh_TW/rbot-rss.po +6 -2
  355. data/po/zh_TW/rbot-script.po +3 -0
  356. data/po/zh_TW/rbot-seen.po +72 -0
  357. data/po/zh_TW/rbot-spell.po +2 -2
  358. data/po/zh_TW/rbot-translator.po +13 -13
  359. data/po/zh_TW/rbot-twitter.po +3 -3
  360. data/po/zh_TW/rbot-uno.po +131 -114
  361. data/po/zh_TW/rbot-wall.po +7 -8
  362. data/po/zh_TW/rbot-wheelfortune.po +41 -41
  363. data/po/zh_TW/rbot.po +253 -194
  364. data/setup.rb +4 -4
  365. metadata +127 -18
  366. data/README +0 -43
  367. data/data/rbot/plugins/fish.rb +0 -121
  368. data/lib/rbot/dbhash.rb +0 -199
@@ -9,40 +9,80 @@
9
9
  #
10
10
  # Resolves the geographic locations of users (network-wide) and IP addresses
11
11
 
12
- module GeoIP
12
+ module ::GeoIP
13
13
  class InvalidHostError < RuntimeError; end
14
+ class BadAPIError < RuntimeError; end
14
15
 
15
- GEO_IP_PRIMARY = "http://lakka.kapsi.fi:40086/lookup.yaml?host="
16
- GEO_IP_SECONDARY = "http://www.geoiptool.com/en/?IP="
17
16
  HOST_NAME_REGEX = /^[a-z0-9\-]+(?:\.[a-z0-9\-]+)*\.[a-z]{2,4}/i
18
17
 
19
- REGEX = {
20
- :country => %r{Country:.*?<a href=".*?" target="_blank"> (.*?)</a>}m,
21
- :region => %r{Region:.*?<a href=".*?" target="_blank">(.*?)</a>}m,
22
- :city => %r{City:.*?<td align="left" class="arial_bold">(.*?)</td>}m
23
- }
24
-
25
18
  def self.valid_host?(hostname)
26
19
  hostname =~ HOST_NAME_REGEX ||
27
20
  hostname =~ Resolv::IPv4::Regex && (hostname.split(".").map { |e| e.to_i }.max <= 255)
28
21
  end
29
22
 
30
- def self.resolve(hostname)
31
- raise InvalidHostError unless valid_host?(hostname)
23
+ def self.geoiptool(ip)
24
+ url = "http://www.geoiptool.com/en/?IP="
25
+ regexes = {
26
+ :country => %r{Country:.*?<a href=".*?" target="_blank"> (.*?)</a>}m,
27
+ :region => %r{Region:.*?<a href=".*?" target="_blank">(.*?)</a>}m,
28
+ :city => %r{City:.*?<td align="left" class="arial_bold">(.*?)</td>}m,
29
+ :lat => %r{Latitude:.*?<td align="left" class="arial_bold">(.*?)</td>}m,
30
+ :lon => %r{Longitude:.*?<td align="left" class="arial_bold">(.*?)</td>}m
31
+ }
32
+ res = {}
33
+ raw = Irc::Utils.bot.httputil.get_response(url+ip)
34
+ raw = raw.decompress_body(raw.raw_body)
35
+
36
+ regexes.each { |key, regex| res[key] = Iconv.conv('utf-8', 'ISO-8859-1', raw.scan(regex).to_s) }
37
+
38
+ return res
39
+ end
32
40
 
33
- yaml = Irc::Utils.bot.httputil.get(GEO_IP_PRIMARY+hostname)
41
+ def self.kapsi(ip)
42
+ url = "http://lakka.kapsi.fi:40086/lookup.yaml?host="
43
+ yaml = Irc::Utils.bot.httputil.get(url+ip)
44
+ return YAML::load(yaml)
45
+ end
34
46
 
35
- if yaml
36
- return YAML::load(yaml)
47
+ def self.blogama(ip)
48
+ url = "http://ipinfodb.com/ip_query.php?ip="
49
+ debug "Requesting #{url+ip}"
50
+
51
+ xml = Irc::Utils.bot.httputil.get(url+ip)
52
+
53
+ if xml
54
+ obj = REXML::Document.new(xml)
55
+ debug "Found #{obj}"
56
+ newobj = {
57
+ :country => obj.elements["Response"].elements["CountryName"].text,
58
+ :city => obj.elements["Response"].elements["City"].text,
59
+ :region => obj.elements["Response"].elements["RegionName"].text,
60
+ }
61
+ debug "Returning #{newobj}"
62
+ return newobj
37
63
  else
38
- res = {}
39
- raw = Irc::Utils.bot.httputil.get_response(GEO_IP_SECONDARY+hostname)
40
- raw = raw.decompress_body(raw.raw_body)
64
+ raise InvalidHostError
65
+ end
66
+ end
41
67
 
42
- REGEX.each { |key, regex| res[key] = Iconv.conv('utf-8', 'ISO-8859-1', raw.scan(regex).to_s) }
68
+ def self.resolve(hostname, api)
69
+ raise InvalidHostError unless valid_host?(hostname)
43
70
 
44
- return res
71
+ begin
72
+ ip = Resolv.getaddress(hostname)
73
+ rescue Resolv::ResolvError
74
+ raise InvalidHostError
45
75
  end
76
+
77
+ jump_table = {
78
+ "blogama" => Proc.new { |ip| blogama(ip) },
79
+ "kapsi" => Proc.new { |ip| kapsi(ip) },
80
+ "geoiptool" => Proc.new { |ip| geoiptool(ip) },
81
+ }
82
+
83
+ raise BadAPIError unless jump_table.key?(api)
84
+
85
+ return jump_table[api].call(ip)
46
86
  end
47
87
  end
48
88
 
@@ -66,6 +106,10 @@ class Stack
66
106
  end
67
107
 
68
108
  class GeoIpPlugin < Plugin
109
+ Config.register Config::ArrayValue.new('geoip.sources',
110
+ :default => [ "blogama", "kapsi", "geoiptool" ],
111
+ :desc => "Which API to use for lookups. Supported values: blogama, kapsi, geoiptool")
112
+
69
113
  def help(plugin, topic="")
70
114
  "geoip [<user|hostname|ip>] => returns the geographic location of whichever has been given -- note: user can be anyone on the network"
71
115
  end
@@ -128,12 +172,23 @@ class GeoIpPlugin < Plugin
128
172
  def host2output(host, nick=nil)
129
173
  return "127.0.0.1 could not be res.. wait, what?" if host == "127.0.0.1"
130
174
 
175
+ geo = {:country => ""}
131
176
  begin
132
- geo = GeoIP::resolve(host)
133
-
134
- raise if geo[:country].empty?
177
+ apis = @bot.config['geoip.sources']
178
+ apis.compact.each { |api|
179
+ geo = GeoIP::resolve(host, api)
180
+ if geo[:country] != ""
181
+ break
182
+ end
183
+ }
135
184
  rescue GeoIP::InvalidHostError, RuntimeError
136
- return _("#{nick ? "#{nick}'s location" : host} could not be resolved")
185
+ if nick
186
+ return _("#{nick}'s location could not be resolved")
187
+ else
188
+ return _("#{host} could not be resolved")
189
+ end
190
+ rescue GeoIP::BadAPIError
191
+ return _("The owner configured me to use an API that doesn't exist, bug them!")
137
192
  end
138
193
 
139
194
  res = _("%{thing} is #{nick ? "from" : "located in"}") % {
@@ -141,18 +196,18 @@ class GeoIpPlugin < Plugin
141
196
  :country => geo[:country]
142
197
  }
143
198
 
144
- res << " %{city}," % {
199
+ res << " %{city}" % {
145
200
  :city => geo[:city]
146
201
  } unless geo[:city].to_s.empty?
147
202
 
203
+ res << " %{region}," % {
204
+ :region => geo[:region]
205
+ } unless geo[:region].to_s.empty? || geo[:region] == geo[:city]
206
+
148
207
  res << " %{country}" % {
149
208
  :country => geo[:country]
150
209
  }
151
210
 
152
- res << " (%{region})" % {
153
- :region => geo[:region]
154
- } unless geo[:region].to_s.empty? || geo[:region] == geo[:city]
155
-
156
211
  return res
157
212
  end
158
213
  end
@@ -0,0 +1,64 @@
1
+ #-- vim:sw=2:et
2
+ #++
3
+ #
4
+ # :title: Googlefight plugin for rbot
5
+ #
6
+ # Author:: Raine Virta <rane@kapsi.fi
7
+ # Copyright:: (C) 2009 Raine Virta
8
+ # License:: GPL v2
9
+
10
+ class GoogleFightPlugin < Plugin
11
+ def help(plugin, topic)
12
+ "googlefight <keyword 1> <keyword 2> [... <keyword n+1>] => battles given keywords based on amount of google search results and announces the winner!"
13
+ end
14
+
15
+ def fight(m, params)
16
+ keywords = parse_keywords(params)
17
+ return if keywords.nil?
18
+
19
+ keywords.map! do |k|
20
+ [k, google_count(k)]
21
+ end
22
+
23
+ m.reply output(keywords)
24
+ end
25
+
26
+ def output(result)
27
+ result = result.sort_by { |e| e[1] }.reverse
28
+ str = result.map do |kw|
29
+ "%{keyword} (%{count})" % {
30
+ :keyword => Bold+kw[0]+Bold,
31
+ :count => kw[1].to_s.gsub(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
32
+ }
33
+ end.join(" vs. ")
34
+
35
+ unless result[0][1].zero?
36
+ str << _(" -- %{keyword} wins!") % {
37
+ :keyword => Bold+result[0][0]+Bold
38
+ }
39
+ else
40
+ str << _(" -- no winner here!")
41
+ end
42
+ end
43
+
44
+ def parse_keywords(params)
45
+ str = params[:keywords].join(" ")
46
+
47
+ # foo "foo bar" bar
48
+ # no separators so assume they're all separate keywords
49
+ if str.match(/(?:"[\w\s]+"|\w+)(?: (?:"[\w\s]+"|\w+))+/)
50
+ str.scan(/"[^"]+"|\S+/).flatten
51
+ end
52
+ end
53
+
54
+ def google_count(query)
55
+ url = 'http://www.google.com/search?hl=en&safe=off&btnG=Search&q=' << CGI.escape(query)
56
+ html = Net::HTTP.get(URI.parse((url)))
57
+ res = html.scan(%r{Results <b>1</b> - <b>\d+</b> of(?: about)? <b>([\d,]+)</b>})
58
+ res.to_s.tr(",", "").to_i
59
+ end
60
+ end
61
+
62
+ plugin = GoogleFightPlugin.new
63
+ plugin.map "googlefight *keywords", :action => "fight",
64
+ :requirements => { :keywords => /^[\w\s"]+? (?:(?:(?:\||vs\.) )?[\w\s"]+?)+/ }
@@ -0,0 +1,45 @@
1
+ #-- vim:sw=2:et
2
+ #++
3
+ #
4
+ # :title: Greet Plugin
5
+ #
6
+ # Author:: Raine Virta <rane@kapsi.fi>
7
+ # Copyright:: (C) 2009 Raine Virta
8
+ # License:: GPL v2
9
+ #
10
+ # Description:: Greet people when they join a channel
11
+
12
+ class GreetPlugin < Plugin
13
+ Config.register Config::ArrayValue.new('greet.channels',
14
+ :desc => _("Greet people on these channels."),
15
+ :default => [])
16
+
17
+ Config.register Config::ArrayValue.new('greet.messages',
18
+ :desc => _("By default, greetings are fetched from lang files. You can use this to specify custom messages, use %s to represent a nick."),
19
+ :default => [])
20
+
21
+ Config.register Config::BooleanValue.new('greet.delay',
22
+ :desc => _("Greet with delay so that the greeting seems human-like."),
23
+ :default => false)
24
+
25
+
26
+ def join(m)
27
+ return unless @bot.config['greet.channels'].include?(m.channel.to_s)
28
+
29
+ greeting = if @bot.config['greet.messages'].empty?
30
+ @bot.lang.get("hello_X")
31
+ else
32
+ @bot.config['greet.messages'].pick_one
33
+ end
34
+
35
+ msg = Proc.new { @bot.say m.channel, greeting % m.sourcenick }
36
+
37
+ if @bot.config['greet.delay']
38
+ @bot.timer.add_once(2+rand(3)) { msg.call }
39
+ else
40
+ msg.call
41
+ end
42
+ end
43
+ end
44
+
45
+ plugin = GreetPlugin.new
@@ -10,11 +10,13 @@
10
10
  # License:: GPL v2
11
11
 
12
12
  class GrouphugPlugin < Plugin
13
+ START = '<div id="main"'
13
14
  REG = Regexp.new('<div class="content">\s*<p>(.*?)</p>\s+</div>', Regexp::MULTILINE)
14
15
  REGPOST = Regexp.new('title>(.*?) \| Group Hug')
15
16
  def initialize
16
17
  super
17
18
  @confessions = Array.new
19
+ @bot.register_filter(:grouphug, :htmlinfo) { |s| grouphug_filter(s) }
18
20
  end
19
21
 
20
22
  def help( plugin, topic="" )
@@ -45,6 +47,15 @@ class GrouphugPlugin < Plugin
45
47
  end
46
48
  end
47
49
 
50
+ def get_confessions(html)
51
+ return [] unless html
52
+ start = html.index(START)
53
+ res = html[start, html.length - start].scan(REG)
54
+ return [] unless res
55
+ return res.map { |quote|
56
+ quote[0].ircify_html
57
+ }
58
+ end
48
59
 
49
60
  def confess(m, params)
50
61
  opts = { :cache => false }
@@ -55,26 +66,43 @@ class GrouphugPlugin < Plugin
55
66
  path = "confessions/#{params[:num]}"
56
67
  opts.delete(:cache)
57
68
  data = @bot.httputil.get("http://grouphug.us/#{path}", opts)
58
-
59
- res = data.scan(REG)
60
- confession = res[0][0].ircify_html
61
- confession = "no confession ##{params[:num]} found" if confession.empty? and params[:num]
62
- m.reply confession
69
+ confessions = get_confessions(data)
70
+ if confessions.length > 1
71
+ warn "more than one confession found!"
72
+ warn confessions
73
+ end
74
+ confessions << "no confession ##{params[:num]} found" if confessions.empty?
75
+ m.reply confessions.first
63
76
  else # Cache random confessions
64
77
  if @confessions.empty?
65
78
  data = @bot.httputil.get("http://grouphug.us/#{path}", opts)
66
- res = data.scan(REG)
67
- res.each do |quote|
68
- @confessions << quote[0].ircify_html
69
- end
79
+ @confessions.replace get_confessions(data)
70
80
  end
71
- confession = @confessions.pop
72
- m.reply confession
81
+ @confessions << "no confessions found!" if @confessions.empty?
82
+ m.reply @confessions.pop
73
83
  end
74
- rescue
84
+ rescue Exception => e
85
+ error e
75
86
  m.reply "failed to connect to grouphug.us"
76
87
  end
77
88
  end
89
+
90
+ def grouphug_filter(s)
91
+ # check if we like the location of the page
92
+ loc = Utils.check_location(s, %r{http://(?:.*\.)?grouphug\.us})
93
+ return unless loc
94
+ # check if there are any conefssions
95
+ confessions = get_confessions(s[:text])
96
+ return if confessions.empty?
97
+ title = s[:text].ircify_html_title
98
+ # return the first confession
99
+ return {
100
+ :title => title,
101
+ :content => confessions.first,
102
+ :grouphug_confessions => confessions
103
+ }
104
+ end
105
+
78
106
  end
79
107
 
80
108
 
@@ -12,7 +12,7 @@
12
12
  # License:: MIT license
13
13
 
14
14
  class Imdb
15
- IMDB = "http://us.imdb.com"
15
+ IMDB = "http://www.imdb.com"
16
16
  TITLE_OR_NAME_MATCH = /<a href="(\/(?:title|name)\/(?:tt|nm)[0-9]+\/?)[^"]*"(?:[^>]*)>([^<]*)<\/a>/
17
17
  TITLE_MATCH = /<a href="(\/title\/tt[0-9]+\/?)[^"]*"(?:[^>]*)>([^<]*)<\/a>/
18
18
  NAME_MATCH = /<a href="(\/name\/nm[0-9]+\/?)[^"]*"(?:[^>]*)>([^<]*)<\/a>/
@@ -99,7 +99,7 @@ class Imdb
99
99
  end
100
100
 
101
101
  def grab_info(info, body)
102
- /<div class="info">\s+<h5>#{info}:<\/h5>\s+(.*?)<\/div>/mi.match(body)[1] rescue nil
102
+ /<div (?:id="\S+-info" )?class="info">\s+<h5>#{info}:<\/h5>\s+(.*?)<\/div>/mi.match(body)[1] rescue nil
103
103
  end
104
104
 
105
105
  def fix_article(org_tit)
@@ -165,7 +165,7 @@ class Imdb
165
165
  end
166
166
 
167
167
  ratings = "no votes"
168
- m = /<b>([0-9.]+)\/10<\/b>\n?\r?\s+<small>\(<a href="ratings">([0-9,]+) votes?<\/a>\)<\/small>/.match(resp.body)
168
+ m = /<b>([0-9.]+)\/10<\/b>\n?\r?\s+[^<]+<a href="ratings"[^>]+>([0-9,]+) votes?<\/a>/.match(resp.body)
169
169
  if m
170
170
  ratings = "#{m[1]}/10 (#{m[2]} voters)"
171
171
  end
@@ -469,7 +469,7 @@ class ImdbPlugin < Plugin
469
469
  end
470
470
 
471
471
  # Find the movies with a participation of :who in the year :year
472
- # TODO: allow year to be either a year or a decade ('[in the] 1960s')
472
+ # TODO: allow year to be either a year or a decade ('[in the] 1960s')
473
473
  #
474
474
  def movies(m, params)
475
475
  who = params[:who].to_s
@@ -134,7 +134,7 @@ class InsultPlugin < Plugin
134
134
  ]
135
135
 
136
136
  ##
137
- # Amounts
137
+ # Amounts
138
138
  ##
139
139
  @@amt = [
140
140
  "accumulation",
@@ -206,7 +206,7 @@ class InsultPlugin < Plugin
206
206
  "cold sores",
207
207
  "anal warts",
208
208
  ]
209
-
209
+
210
210
  def help(plugin, topic="")
211
211
  return "[msg]insult me|<person> => insult you or <person>. msginsult insults in private"
212
212
  end
@@ -14,16 +14,17 @@ class KarmaPlugin < Plugin
14
14
  @registry.set_default(0)
15
15
 
16
16
  # import if old file format found
17
- if(File.exist?("#{@bot.botclass}/karma.rbot"))
17
+ oldkarma = @bot.path 'karma.rbot'
18
+ if File.exist? oldkarma
18
19
  log "importing old karma data"
19
- IO.foreach("#{@bot.botclass}/karma.rbot") do |line|
20
+ IO.foreach(oldkarma) do |line|
20
21
  if(line =~ /^(\S+)<=>([\d-]+)$/)
21
22
  item = $1
22
23
  karma = $2.to_i
23
24
  @registry[item] = karma
24
25
  end
25
26
  end
26
- File.delete("#{@bot.botclass}/karma.rbot")
27
+ File.delete oldkarma
27
28
  end
28
29
  end
29
30
 
@@ -54,7 +55,7 @@ class KarmaPlugin < Plugin
54
55
  @registry[thing] = params[:val].to_i
55
56
  karma(m, params)
56
57
  end
57
-
58
+
58
59
  def help(plugin, topic="")
59
60
  "karma module: Listens to everyone's chat. <thing>++/<thing>-- => increase/decrease karma for <thing>, karma for <thing>? => show karma for <thing>, karmastats => show stats. Karma is a community rating system - only in-channel messages can affect karma and you cannot adjust your own."
60
61
  end
@@ -86,7 +87,7 @@ class KarmaPlugin < Plugin
86
87
 
87
88
  if op && arg
88
89
  ac[arg] ||= 0
89
- ac[arg] += (op == '--' ? -1 : 1)
90
+ ac[arg] += (op == '--' ? -1 : 1) unless arg.downcase == m.sourcenick.downcase
90
91
  op = arg = nil
91
92
  end
92
93
  end