rbot 0.9.10 → 0.9.12

Sign up to get free protection for your applications and to get access to all the features.
Files changed (706) hide show
  1. data/AUTHORS +22 -4
  2. data/COPYING +5 -18
  3. data/ChangeLog +396 -0
  4. data/README +23 -25
  5. data/REQUIREMENTS +58 -12
  6. data/Rakefile +215 -0
  7. data/bin/rbot +47 -25
  8. data/bin/rbot-remote +76 -0
  9. data/data/rbot/languages/french.lang +5 -5
  10. data/data/rbot/languages/german.lang +4 -4
  11. data/data/rbot/languages/italian.lang +53 -0
  12. data/data/rbot/languages/japanese.lang +43 -0
  13. data/data/rbot/languages/russian.lang +60 -60
  14. data/data/rbot/languages/traditional_chinese.lang +75 -0
  15. data/data/rbot/plugins/alias.rb +192 -0
  16. data/data/rbot/plugins/autoop.rb +74 -37
  17. data/data/rbot/plugins/autorejoin.rb +15 -5
  18. data/data/rbot/plugins/bans.rb +454 -150
  19. data/data/rbot/plugins/bash.rb +173 -31
  20. data/data/rbot/plugins/botsnack.rb +37 -0
  21. data/data/rbot/plugins/cal.rb +11 -2
  22. data/data/rbot/plugins/chanserv.rb +132 -0
  23. data/data/rbot/plugins/chucknorris.rb +2 -2
  24. data/data/rbot/plugins/chucknorris.yml.gz +0 -0
  25. data/data/rbot/plugins/debugger.rb +136 -0
  26. data/data/rbot/plugins/deepthoughts.rb +89 -95
  27. data/data/rbot/plugins/delicious.rb +109 -0
  28. data/data/rbot/plugins/dice.rb +77 -25
  29. data/data/rbot/plugins/dict.rb +243 -0
  30. data/data/rbot/plugins/dictclient.rb +211 -0
  31. data/data/rbot/plugins/digg.rb +2 -2
  32. data/data/rbot/plugins/excuse.rb +4 -4
  33. data/data/rbot/plugins/factoids.rb +506 -0
  34. data/data/rbot/plugins/figlet.rb +127 -18
  35. data/data/rbot/plugins/fish.rb +93 -33
  36. data/data/rbot/plugins/forecast.rb +40 -27
  37. data/data/rbot/plugins/fortune.rb +86 -11
  38. data/data/rbot/plugins/freshmeat.rb +46 -12
  39. data/data/rbot/plugins/games/azgame.rb +565 -0
  40. data/data/rbot/plugins/games/quiz.rb +961 -0
  41. data/data/rbot/plugins/games/roshambo.rb +62 -0
  42. data/data/rbot/plugins/{roulette.rb → games/roulette.rb} +58 -8
  43. data/data/rbot/plugins/games/shiritori.rb +485 -0
  44. data/data/rbot/plugins/games/uno.rb +1205 -0
  45. data/data/rbot/plugins/games/wheelfortune.rb +615 -0
  46. data/data/rbot/plugins/grouphug.rb +76 -22
  47. data/data/rbot/plugins/hl2.rb +97 -0
  48. data/data/rbot/plugins/host.rb +10 -1
  49. data/data/rbot/plugins/httpd.rb.disabled +1 -0
  50. data/data/rbot/plugins/imdb.rb +511 -47
  51. data/data/rbot/plugins/insult.rb +32 -37
  52. data/data/rbot/plugins/iplookup.rb +224 -224
  53. data/data/rbot/plugins/karma.rb +45 -21
  54. data/data/rbot/plugins/keywords.rb +258 -160
  55. data/data/rbot/plugins/lart.rb +126 -95
  56. data/data/rbot/plugins/lastfm.rb +421 -12
  57. data/data/rbot/plugins/linkbot.rb +75 -0
  58. data/data/rbot/plugins/markov.rb +103 -46
  59. data/data/rbot/plugins/math.rb +6 -5
  60. data/data/rbot/plugins/modes.rb +114 -0
  61. data/data/rbot/plugins/nickrecover.rb +97 -0
  62. data/data/rbot/plugins/nickserv.rb +111 -48
  63. data/data/rbot/plugins/nslookup.rb +15 -19
  64. data/data/rbot/plugins/plugin.header +11 -0
  65. data/data/rbot/plugins/quakeauth.rb +74 -11
  66. data/data/rbot/plugins/quotes.rb +189 -233
  67. data/data/rbot/plugins/reaction.rb +415 -0
  68. data/data/rbot/plugins/remind.rb +11 -15
  69. data/data/rbot/plugins/remotectl.rb +29 -0
  70. data/data/rbot/plugins/ri.rb +74 -0
  71. data/data/rbot/plugins/rot13.rb +16 -1
  72. data/data/rbot/plugins/rss.rb +1219 -585
  73. data/data/rbot/plugins/salut.rb +226 -0
  74. data/data/rbot/plugins/script.rb +184 -0
  75. data/data/rbot/plugins/search.rb +233 -0
  76. data/data/rbot/plugins/seen.rb +44 -40
  77. data/data/rbot/plugins/shortenurls.rb +93 -0
  78. data/data/rbot/plugins/slashdot.rb +49 -11
  79. data/data/rbot/plugins/spell.rb +37 -27
  80. data/data/rbot/plugins/theyfightcrime.rb +36 -39
  81. data/data/rbot/plugins/threat.rb +25 -22
  82. data/data/rbot/plugins/time.rb +135 -0
  83. data/data/rbot/plugins/topic.rb +107 -50
  84. data/data/rbot/plugins/translator.rb +360 -0
  85. data/data/rbot/plugins/tube.rb +28 -40
  86. data/data/rbot/plugins/twitter.rb +187 -0
  87. data/data/rbot/plugins/urban.rb +62 -53
  88. data/data/rbot/plugins/url.rb +193 -409
  89. data/data/rbot/plugins/usermodes.rb +26 -0
  90. data/data/rbot/plugins/wall.rb +60 -0
  91. data/data/rbot/plugins/weather.rb +254 -598
  92. data/data/rbot/plugins/wow.rb +41 -37
  93. data/data/rbot/plugins/wserver.rb +17 -25
  94. data/data/rbot/plugins/youtube.rb +237 -0
  95. data/data/rbot/templates/lart/{larts → larts-english} +0 -0
  96. data/data/rbot/templates/lart/larts-italian +25 -0
  97. data/data/rbot/templates/lart/larts-japanese +10 -0
  98. data/data/rbot/templates/lart/{praises → praises-english} +0 -0
  99. data/data/rbot/templates/lart/praises-italian +4 -0
  100. data/data/rbot/templates/lart/praises-japanese +3 -0
  101. data/data/rbot/templates/quiz/win_messages +11 -0
  102. data/data/rbot/templates/salut/salut-english +40 -0
  103. data/data/rbot/templates/salut/salut-french +29 -0
  104. data/data/rbot/templates/salut/salut-italian +51 -0
  105. data/data/rbot/templates/salut/salut-japanese +31 -0
  106. data/lib/rbot/botuser.rb +940 -0
  107. data/lib/rbot/config-compat.rb +23 -0
  108. data/lib/rbot/config.rb +211 -276
  109. data/lib/rbot/core/auth.rb +1063 -0
  110. data/lib/rbot/core/basics.rb +214 -0
  111. data/lib/rbot/core/config.rb +330 -0
  112. data/lib/rbot/core/filters_ui.rb +64 -0
  113. data/lib/rbot/core/irclog.rb +292 -0
  114. data/lib/rbot/core/remote.rb +401 -0
  115. data/lib/rbot/core/unicode.rb +91 -0
  116. data/lib/rbot/core/userdata.rb +200 -0
  117. data/lib/rbot/core/utils/extends.rb +444 -0
  118. data/lib/rbot/core/utils/filters.rb +154 -0
  119. data/lib/rbot/core/utils/httputil.rb +689 -0
  120. data/lib/rbot/core/utils/utils.rb +717 -0
  121. data/lib/rbot/dbhash.rb +30 -9
  122. data/lib/rbot/irc.rb +1966 -0
  123. data/lib/rbot/ircbot.rb +816 -675
  124. data/lib/rbot/ircsocket.rb +246 -232
  125. data/lib/rbot/language.rb +86 -8
  126. data/lib/rbot/load-gettext.rb +154 -0
  127. data/lib/rbot/maskdb.rb +162 -0
  128. data/lib/rbot/message.rb +392 -65
  129. data/lib/rbot/messagemapper.rb +438 -94
  130. data/lib/rbot/pkgconfig.rb +6 -0
  131. data/lib/rbot/plugins.rb +713 -172
  132. data/lib/rbot/post-config.rb +1 -0
  133. data/lib/rbot/rbotconfig.rb +31 -12
  134. data/lib/rbot/registry.rb +79 -48
  135. data/lib/rbot/rfc2812.rb +927 -519
  136. data/lib/rbot/timer.rb +232 -167
  137. data/po/en_US/rbot-alias.po +82 -0
  138. data/po/en_US/rbot-autoop.po +0 -0
  139. data/po/en_US/rbot-autorejoin.po +0 -0
  140. data/po/en_US/rbot-azgame.po +200 -0
  141. data/po/en_US/rbot-bans.po +0 -0
  142. data/po/en_US/rbot-bash.po +0 -0
  143. data/po/en_US/rbot-botsnack.po +0 -0
  144. data/po/en_US/rbot-cal.po +3 -0
  145. data/po/en_US/rbot-chanserv.po +0 -0
  146. data/po/en_US/rbot-chucknorris.po +0 -0
  147. data/po/en_US/rbot-debugger.po +0 -0
  148. data/po/en_US/rbot-deepthoughts.po +0 -0
  149. data/po/en_US/rbot-delicious.po +0 -0
  150. data/po/en_US/rbot-dice.po +0 -0
  151. data/po/en_US/rbot-dict.po +0 -0
  152. data/po/en_US/rbot-dictclient.po +124 -0
  153. data/po/en_US/rbot-digg.po +0 -0
  154. data/po/en_US/rbot-eightball.po +0 -0
  155. data/po/en_US/rbot-excuse.po +0 -0
  156. data/po/en_US/rbot-factoids.po +107 -0
  157. data/po/en_US/rbot-figlet.po +36 -0
  158. data/po/en_US/rbot-fish.po +0 -0
  159. data/po/en_US/rbot-forecast.po +0 -0
  160. data/po/en_US/rbot-fortune.po +0 -0
  161. data/po/en_US/rbot-freshmeat.po +0 -0
  162. data/po/en_US/rbot-grouphug.po +18 -0
  163. data/po/en_US/rbot-hl2.po +0 -0
  164. data/po/en_US/rbot-host.po +3 -0
  165. data/po/en_US/rbot-imdb.po +0 -0
  166. data/po/en_US/rbot-insult.po +0 -0
  167. data/po/en_US/rbot-iplookup.po +0 -0
  168. data/po/en_US/rbot-karma.po +0 -0
  169. data/po/en_US/rbot-keywords.po +24 -0
  170. data/po/en_US/rbot-lart.po +0 -0
  171. data/po/en_US/rbot-lastfm.po +172 -0
  172. data/po/en_US/rbot-linkbot.po +0 -0
  173. data/po/en_US/rbot-markov.po +20 -0
  174. data/po/en_US/rbot-math.po +0 -0
  175. data/po/en_US/rbot-modes.po +0 -0
  176. data/po/en_US/rbot-nickrecover.po +40 -0
  177. data/po/en_US/rbot-nickserv.po +104 -0
  178. data/po/en_US/rbot-nslookup.po +0 -0
  179. data/po/en_US/rbot-quakeauth.po +0 -0
  180. data/po/en_US/rbot-quiz.po +0 -0
  181. data/po/en_US/rbot-quotes.po +108 -0
  182. data/po/en_US/rbot-reaction.po +0 -0
  183. data/po/en_US/rbot-remind.po +0 -0
  184. data/po/en_US/rbot-remotectl.po +0 -0
  185. data/po/en_US/rbot-ri.po +0 -0
  186. data/po/en_US/rbot-roshambo.po +0 -0
  187. data/po/en_US/rbot-rot13.po +0 -0
  188. data/po/en_US/rbot-roulette.po +0 -0
  189. data/po/en_US/rbot-rss.po +20 -0
  190. data/po/en_US/rbot-salut.po +0 -0
  191. data/po/en_US/rbot-script.po +0 -0
  192. data/po/en_US/rbot-search.po +0 -0
  193. data/po/en_US/rbot-seen.po +0 -0
  194. data/po/en_US/rbot-shiritori.po +113 -0
  195. data/po/en_US/rbot-shortenurls.po +0 -0
  196. data/po/en_US/rbot-slashdot.po +0 -0
  197. data/po/en_US/rbot-spell.po +54 -0
  198. data/po/en_US/rbot-theyfightcrime.po +0 -0
  199. data/po/en_US/rbot-threat.po +0 -0
  200. data/po/en_US/rbot-time.po +0 -0
  201. data/po/en_US/rbot-topic.po +0 -0
  202. data/po/en_US/rbot-translator.po +77 -0
  203. data/po/en_US/rbot-tube.po +0 -0
  204. data/po/en_US/rbot-twitter.po +24 -0
  205. data/po/en_US/rbot-uno.po +512 -0
  206. data/po/en_US/rbot-urban.po +0 -0
  207. data/po/en_US/rbot-url.po +0 -0
  208. data/po/en_US/rbot-usermodes.po +0 -0
  209. data/po/en_US/rbot-wall.po +33 -0
  210. data/po/en_US/rbot-weather.po +0 -0
  211. data/po/en_US/rbot-wheelfortune.po +205 -0
  212. data/po/en_US/rbot-wow.po +0 -0
  213. data/po/en_US/rbot-wserver.po +0 -0
  214. data/po/en_US/rbot-youtube.po +58 -0
  215. data/po/en_US/rbot.po +1097 -0
  216. data/po/fr/rbot-alias.po +97 -0
  217. data/po/fr/rbot-autoop.po +0 -0
  218. data/po/fr/rbot-autorejoin.po +0 -0
  219. data/po/fr/rbot-azgame.po +204 -0
  220. data/po/fr/rbot-bans.po +0 -0
  221. data/po/fr/rbot-bash.po +0 -0
  222. data/po/fr/rbot-botsnack.po +0 -0
  223. data/po/fr/rbot-cal.po +3 -0
  224. data/po/fr/rbot-chanserv.po +0 -0
  225. data/po/fr/rbot-chucknorris.po +0 -0
  226. data/po/fr/rbot-debugger.po +0 -0
  227. data/po/fr/rbot-deepthoughts.po +0 -0
  228. data/po/fr/rbot-delicious.po +0 -0
  229. data/po/fr/rbot-dice.po +0 -0
  230. data/po/fr/rbot-dict.po +0 -0
  231. data/po/fr/rbot-dictclient.po +134 -0
  232. data/po/fr/rbot-digg.po +0 -0
  233. data/po/fr/rbot-eightball.po +0 -0
  234. data/po/fr/rbot-excuse.po +0 -0
  235. data/po/fr/rbot-factoids.po +111 -0
  236. data/po/fr/rbot-figlet.po +37 -0
  237. data/po/fr/rbot-fish.po +0 -0
  238. data/po/fr/rbot-forecast.po +0 -0
  239. data/po/fr/rbot-fortune.po +0 -0
  240. data/po/fr/rbot-freshmeat.po +0 -0
  241. data/po/fr/rbot-grouphug.po +18 -0
  242. data/po/fr/rbot-hl2.po +0 -0
  243. data/po/fr/rbot-host.po +3 -0
  244. data/po/fr/rbot-imdb.po +0 -0
  245. data/po/fr/rbot-insult.po +0 -0
  246. data/po/fr/rbot-iplookup.po +0 -0
  247. data/po/fr/rbot-karma.po +0 -0
  248. data/po/fr/rbot-keywords.po +24 -0
  249. data/po/fr/rbot-lart.po +0 -0
  250. data/po/fr/rbot-lastfm.po +172 -0
  251. data/po/fr/rbot-linkbot.po +0 -0
  252. data/po/fr/rbot-markov.po +20 -0
  253. data/po/fr/rbot-math.po +0 -0
  254. data/po/fr/rbot-modes.po +0 -0
  255. data/po/fr/rbot-nickrecover.po +36 -0
  256. data/po/fr/rbot-nickserv.po +116 -0
  257. data/po/fr/rbot-nslookup.po +0 -0
  258. data/po/fr/rbot-quakeauth.po +0 -0
  259. data/po/fr/rbot-quiz.po +0 -0
  260. data/po/fr/rbot-quotes.po +138 -0
  261. data/po/fr/rbot-reaction.po +0 -0
  262. data/po/fr/rbot-remind.po +0 -0
  263. data/po/fr/rbot-remotectl.po +0 -0
  264. data/po/fr/rbot-ri.po +0 -0
  265. data/po/fr/rbot-roshambo.po +0 -0
  266. data/po/fr/rbot-rot13.po +0 -0
  267. data/po/fr/rbot-roulette.po +0 -0
  268. data/po/fr/rbot-rss.po +20 -0
  269. data/po/fr/rbot-salut.po +0 -0
  270. data/po/fr/rbot-script.po +0 -0
  271. data/po/fr/rbot-search.po +0 -0
  272. data/po/fr/rbot-seen.po +0 -0
  273. data/po/fr/rbot-shiritori.po +119 -0
  274. data/po/fr/rbot-shortenurls.po +0 -0
  275. data/po/fr/rbot-slashdot.po +0 -0
  276. data/po/fr/rbot-spell.po +56 -0
  277. data/po/fr/rbot-theyfightcrime.po +0 -0
  278. data/po/fr/rbot-threat.po +0 -0
  279. data/po/fr/rbot-time.po +0 -0
  280. data/po/fr/rbot-topic.po +0 -0
  281. data/po/fr/rbot-translator.po +90 -0
  282. data/po/fr/rbot-tube.po +0 -0
  283. data/po/fr/rbot-twitter.po +24 -0
  284. data/po/fr/rbot-uno.po +521 -0
  285. data/po/fr/rbot-urban.po +0 -0
  286. data/po/fr/rbot-url.po +0 -0
  287. data/po/fr/rbot-usermodes.po +0 -0
  288. data/po/fr/rbot-wall.po +33 -0
  289. data/po/fr/rbot-weather.po +0 -0
  290. data/po/fr/rbot-wheelfortune.po +255 -0
  291. data/po/fr/rbot-wow.po +0 -0
  292. data/po/fr/rbot-wserver.po +0 -0
  293. data/po/fr/rbot-youtube.po +64 -0
  294. data/po/fr/rbot.po +1133 -0
  295. data/po/it/rbot-alias.po +82 -0
  296. data/po/it/rbot-autoop.po +0 -0
  297. data/po/it/rbot-autorejoin.po +0 -0
  298. data/po/it/rbot-azgame.po +186 -0
  299. data/po/it/rbot-bans.po +0 -0
  300. data/po/it/rbot-bash.po +0 -0
  301. data/po/it/rbot-botsnack.po +0 -0
  302. data/po/it/rbot-cal.po +3 -0
  303. data/po/it/rbot-chanserv.po +0 -0
  304. data/po/it/rbot-chucknorris.po +0 -0
  305. data/po/it/rbot-debugger.po +0 -0
  306. data/po/it/rbot-deepthoughts.po +0 -0
  307. data/po/it/rbot-delicious.po +0 -0
  308. data/po/it/rbot-dice.po +0 -0
  309. data/po/it/rbot-dict.po +0 -0
  310. data/po/it/rbot-dictclient.po +111 -0
  311. data/po/it/rbot-digg.po +0 -0
  312. data/po/it/rbot-eightball.po +0 -0
  313. data/po/it/rbot-excuse.po +0 -0
  314. data/po/it/rbot-factoids.po +110 -0
  315. data/po/it/rbot-figlet.po +36 -0
  316. data/po/it/rbot-fish.po +0 -0
  317. data/po/it/rbot-forecast.po +0 -0
  318. data/po/it/rbot-fortune.po +0 -0
  319. data/po/it/rbot-freshmeat.po +0 -0
  320. data/po/it/rbot-grouphug.po +18 -0
  321. data/po/it/rbot-hl2.po +0 -0
  322. data/po/it/rbot-host.po +3 -0
  323. data/po/it/rbot-imdb.po +0 -0
  324. data/po/it/rbot-insult.po +0 -0
  325. data/po/it/rbot-iplookup.po +0 -0
  326. data/po/it/rbot-karma.po +0 -0
  327. data/po/it/rbot-keywords.po +24 -0
  328. data/po/it/rbot-lart.po +0 -0
  329. data/po/it/rbot-lastfm.po +172 -0
  330. data/po/it/rbot-linkbot.po +0 -0
  331. data/po/it/rbot-markov.po +20 -0
  332. data/po/it/rbot-math.po +0 -0
  333. data/po/it/rbot-modes.po +0 -0
  334. data/po/it/rbot-nickrecover.po +36 -0
  335. data/po/it/rbot-nickserv.po +104 -0
  336. data/po/it/rbot-nslookup.po +0 -0
  337. data/po/it/rbot-quakeauth.po +0 -0
  338. data/po/it/rbot-quiz.po +0 -0
  339. data/po/it/rbot-quotes.po +108 -0
  340. data/po/it/rbot-reaction.po +0 -0
  341. data/po/it/rbot-remind.po +0 -0
  342. data/po/it/rbot-remotectl.po +0 -0
  343. data/po/it/rbot-ri.po +0 -0
  344. data/po/it/rbot-roshambo.po +0 -0
  345. data/po/it/rbot-rot13.po +0 -0
  346. data/po/it/rbot-roulette.po +0 -0
  347. data/po/it/rbot-rss.po +20 -0
  348. data/po/it/rbot-salut.po +0 -0
  349. data/po/it/rbot-script.po +0 -0
  350. data/po/it/rbot-search.po +0 -0
  351. data/po/it/rbot-seen.po +0 -0
  352. data/po/it/rbot-shiritori.po +102 -0
  353. data/po/it/rbot-shortenurls.po +0 -0
  354. data/po/it/rbot-slashdot.po +0 -0
  355. data/po/it/rbot-spell.po +54 -0
  356. data/po/it/rbot-theyfightcrime.po +0 -0
  357. data/po/it/rbot-threat.po +0 -0
  358. data/po/it/rbot-time.po +0 -0
  359. data/po/it/rbot-topic.po +0 -0
  360. data/po/it/rbot-translator.po +77 -0
  361. data/po/it/rbot-tube.po +0 -0
  362. data/po/it/rbot-twitter.po +24 -0
  363. data/po/it/rbot-uno.po +564 -0
  364. data/po/it/rbot-urban.po +0 -0
  365. data/po/it/rbot-url.po +0 -0
  366. data/po/it/rbot-usermodes.po +0 -0
  367. data/po/it/rbot-wall.po +33 -0
  368. data/po/it/rbot-weather.po +0 -0
  369. data/po/it/rbot-wheelfortune.po +251 -0
  370. data/po/it/rbot-wow.po +0 -0
  371. data/po/it/rbot-wserver.po +0 -0
  372. data/po/it/rbot-youtube.po +64 -0
  373. data/po/it/rbot.po +1127 -0
  374. data/po/ja/rbot-alias.po +82 -0
  375. data/po/ja/rbot-autoop.po +0 -0
  376. data/po/ja/rbot-autorejoin.po +0 -0
  377. data/po/ja/rbot-azgame.po +194 -0
  378. data/po/ja/rbot-bans.po +0 -0
  379. data/po/ja/rbot-bash.po +0 -0
  380. data/po/ja/rbot-botsnack.po +0 -0
  381. data/po/ja/rbot-cal.po +3 -0
  382. data/po/ja/rbot-chanserv.po +0 -0
  383. data/po/ja/rbot-chucknorris.po +0 -0
  384. data/po/ja/rbot-debugger.po +0 -0
  385. data/po/ja/rbot-deepthoughts.po +0 -0
  386. data/po/ja/rbot-delicious.po +0 -0
  387. data/po/ja/rbot-dice.po +0 -0
  388. data/po/ja/rbot-dict.po +0 -0
  389. data/po/ja/rbot-dictclient.po +111 -0
  390. data/po/ja/rbot-digg.po +0 -0
  391. data/po/ja/rbot-eightball.po +0 -0
  392. data/po/ja/rbot-excuse.po +0 -0
  393. data/po/ja/rbot-factoids.po +107 -0
  394. data/po/ja/rbot-figlet.po +36 -0
  395. data/po/ja/rbot-fish.po +0 -0
  396. data/po/ja/rbot-forecast.po +0 -0
  397. data/po/ja/rbot-fortune.po +0 -0
  398. data/po/ja/rbot-freshmeat.po +0 -0
  399. data/po/ja/rbot-grouphug.po +18 -0
  400. data/po/ja/rbot-hl2.po +0 -0
  401. data/po/ja/rbot-host.po +3 -0
  402. data/po/ja/rbot-imdb.po +0 -0
  403. data/po/ja/rbot-insult.po +0 -0
  404. data/po/ja/rbot-iplookup.po +0 -0
  405. data/po/ja/rbot-karma.po +0 -0
  406. data/po/ja/rbot-keywords.po +24 -0
  407. data/po/ja/rbot-lart.po +0 -0
  408. data/po/ja/rbot-lastfm.po +172 -0
  409. data/po/ja/rbot-linkbot.po +0 -0
  410. data/po/ja/rbot-markov.po +20 -0
  411. data/po/ja/rbot-math.po +0 -0
  412. data/po/ja/rbot-modes.po +0 -0
  413. data/po/ja/rbot-nickrecover.po +36 -0
  414. data/po/ja/rbot-nickserv.po +104 -0
  415. data/po/ja/rbot-nslookup.po +0 -0
  416. data/po/ja/rbot-quakeauth.po +0 -0
  417. data/po/ja/rbot-quiz.po +0 -0
  418. data/po/ja/rbot-quotes.po +108 -0
  419. data/po/ja/rbot-reaction.po +0 -0
  420. data/po/ja/rbot-remind.po +0 -0
  421. data/po/ja/rbot-remotectl.po +0 -0
  422. data/po/ja/rbot-ri.po +0 -0
  423. data/po/ja/rbot-roshambo.po +0 -0
  424. data/po/ja/rbot-rot13.po +0 -0
  425. data/po/ja/rbot-roulette.po +0 -0
  426. data/po/ja/rbot-rss.po +20 -0
  427. data/po/ja/rbot-salut.po +0 -0
  428. data/po/ja/rbot-script.po +0 -0
  429. data/po/ja/rbot-search.po +0 -0
  430. data/po/ja/rbot-seen.po +0 -0
  431. data/po/ja/rbot-shiritori.po +115 -0
  432. data/po/ja/rbot-shortenurls.po +0 -0
  433. data/po/ja/rbot-slashdot.po +0 -0
  434. data/po/ja/rbot-spell.po +54 -0
  435. data/po/ja/rbot-theyfightcrime.po +0 -0
  436. data/po/ja/rbot-threat.po +0 -0
  437. data/po/ja/rbot-time.po +0 -0
  438. data/po/ja/rbot-topic.po +0 -0
  439. data/po/ja/rbot-translator.po +77 -0
  440. data/po/ja/rbot-tube.po +0 -0
  441. data/po/ja/rbot-twitter.po +24 -0
  442. data/po/ja/rbot-uno.po +512 -0
  443. data/po/ja/rbot-urban.po +0 -0
  444. data/po/ja/rbot-url.po +0 -0
  445. data/po/ja/rbot-usermodes.po +0 -0
  446. data/po/ja/rbot-wall.po +33 -0
  447. data/po/ja/rbot-weather.po +0 -0
  448. data/po/ja/rbot-wheelfortune.po +205 -0
  449. data/po/ja/rbot-wow.po +0 -0
  450. data/po/ja/rbot-wserver.po +0 -0
  451. data/po/ja/rbot-youtube.po +58 -0
  452. data/po/ja/rbot.po +999 -0
  453. data/po/rbot-alias.pot +83 -0
  454. data/po/rbot-autoop.pot +0 -0
  455. data/po/rbot-autorejoin.pot +0 -0
  456. data/po/rbot-azgame.pot +187 -0
  457. data/po/rbot-bans.pot +0 -0
  458. data/po/rbot-bash.pot +0 -0
  459. data/po/rbot-botsnack.pot +0 -0
  460. data/po/rbot-cal.pot +21 -0
  461. data/po/rbot-chanserv.pot +0 -0
  462. data/po/rbot-chucknorris.pot +0 -0
  463. data/po/rbot-debugger.pot +0 -0
  464. data/po/rbot-deepthoughts.pot +0 -0
  465. data/po/rbot-delicious.pot +0 -0
  466. data/po/rbot-dice.pot +0 -0
  467. data/po/rbot-dict.pot +0 -0
  468. data/po/rbot-dictclient.pot +112 -0
  469. data/po/rbot-digg.pot +0 -0
  470. data/po/rbot-eightball.pot +0 -0
  471. data/po/rbot-excuse.pot +0 -0
  472. data/po/rbot-factoids.pot +108 -0
  473. data/po/rbot-figlet.pot +37 -0
  474. data/po/rbot-fish.pot +0 -0
  475. data/po/rbot-forecast.pot +0 -0
  476. data/po/rbot-fortune.pot +0 -0
  477. data/po/rbot-freshmeat.pot +0 -0
  478. data/po/rbot-grouphug.pot +36 -0
  479. data/po/rbot-hl2.pot +0 -0
  480. data/po/rbot-host.pot +21 -0
  481. data/po/rbot-imdb.pot +0 -0
  482. data/po/rbot-insult.pot +0 -0
  483. data/po/rbot-iplookup.pot +0 -0
  484. data/po/rbot-karma.pot +0 -0
  485. data/po/rbot-keywords.pot +25 -0
  486. data/po/rbot-lart.pot +0 -0
  487. data/po/rbot-lastfm.pot +190 -0
  488. data/po/rbot-linkbot.pot +0 -0
  489. data/po/rbot-markov.pot +21 -0
  490. data/po/rbot-math.pot +0 -0
  491. data/po/rbot-modes.pot +0 -0
  492. data/po/rbot-nickrecover.pot +37 -0
  493. data/po/rbot-nickserv.pot +105 -0
  494. data/po/rbot-nslookup.pot +0 -0
  495. data/po/rbot-quakeauth.pot +0 -0
  496. data/po/rbot-quiz.pot +0 -0
  497. data/po/rbot-quotes.pot +109 -0
  498. data/po/rbot-reaction.pot +0 -0
  499. data/po/rbot-remind.pot +0 -0
  500. data/po/rbot-remotectl.pot +0 -0
  501. data/po/rbot-ri.pot +0 -0
  502. data/po/rbot-roshambo.pot +0 -0
  503. data/po/rbot-rot13.pot +0 -0
  504. data/po/rbot-roulette.pot +0 -0
  505. data/po/rbot-rss.pot +21 -0
  506. data/po/rbot-salut.pot +0 -0
  507. data/po/rbot-script.pot +0 -0
  508. data/po/rbot-search.pot +0 -0
  509. data/po/rbot-seen.pot +0 -0
  510. data/po/rbot-shiritori.pot +103 -0
  511. data/po/rbot-shortenurls.pot +0 -0
  512. data/po/rbot-slashdot.pot +0 -0
  513. data/po/rbot-spell.pot +55 -0
  514. data/po/rbot-theyfightcrime.pot +0 -0
  515. data/po/rbot-threat.pot +0 -0
  516. data/po/rbot-time.pot +0 -0
  517. data/po/rbot-topic.pot +0 -0
  518. data/po/rbot-translator.pot +78 -0
  519. data/po/rbot-tube.pot +0 -0
  520. data/po/rbot-twitter.pot +25 -0
  521. data/po/rbot-uno.pot +513 -0
  522. data/po/rbot-urban.pot +0 -0
  523. data/po/rbot-url.pot +0 -0
  524. data/po/rbot-usermodes.pot +0 -0
  525. data/po/rbot-wall.pot +33 -0
  526. data/po/rbot-weather.pot +0 -0
  527. data/po/rbot-wheelfortune.pot +206 -0
  528. data/po/rbot-wow.pot +0 -0
  529. data/po/rbot-wserver.pot +0 -0
  530. data/po/rbot-youtube.pot +59 -0
  531. data/po/rbot.pot +1004 -0
  532. data/po/zh_CN/rbot-alias.po +82 -0
  533. data/po/zh_CN/rbot-autoop.po +0 -0
  534. data/po/zh_CN/rbot-autorejoin.po +0 -0
  535. data/po/zh_CN/rbot-azgame.po +186 -0
  536. data/po/zh_CN/rbot-bans.po +0 -0
  537. data/po/zh_CN/rbot-bash.po +0 -0
  538. data/po/zh_CN/rbot-botsnack.po +0 -0
  539. data/po/zh_CN/rbot-cal.po +3 -0
  540. data/po/zh_CN/rbot-chanserv.po +0 -0
  541. data/po/zh_CN/rbot-chucknorris.po +0 -0
  542. data/po/zh_CN/rbot-debugger.po +0 -0
  543. data/po/zh_CN/rbot-deepthoughts.po +0 -0
  544. data/po/zh_CN/rbot-delicious.po +0 -0
  545. data/po/zh_CN/rbot-dice.po +0 -0
  546. data/po/zh_CN/rbot-dict.po +0 -0
  547. data/po/zh_CN/rbot-dictclient.po +111 -0
  548. data/po/zh_CN/rbot-digg.po +0 -0
  549. data/po/zh_CN/rbot-eightball.po +0 -0
  550. data/po/zh_CN/rbot-excuse.po +0 -0
  551. data/po/zh_CN/rbot-factoids.po +107 -0
  552. data/po/zh_CN/rbot-figlet.po +36 -0
  553. data/po/zh_CN/rbot-fish.po +0 -0
  554. data/po/zh_CN/rbot-forecast.po +0 -0
  555. data/po/zh_CN/rbot-fortune.po +0 -0
  556. data/po/zh_CN/rbot-freshmeat.po +0 -0
  557. data/po/zh_CN/rbot-grouphug.po +18 -0
  558. data/po/zh_CN/rbot-hl2.po +0 -0
  559. data/po/zh_CN/rbot-host.po +3 -0
  560. data/po/zh_CN/rbot-imdb.po +0 -0
  561. data/po/zh_CN/rbot-insult.po +0 -0
  562. data/po/zh_CN/rbot-iplookup.po +0 -0
  563. data/po/zh_CN/rbot-karma.po +0 -0
  564. data/po/zh_CN/rbot-keywords.po +24 -0
  565. data/po/zh_CN/rbot-lart.po +0 -0
  566. data/po/zh_CN/rbot-lastfm.po +172 -0
  567. data/po/zh_CN/rbot-linkbot.po +0 -0
  568. data/po/zh_CN/rbot-markov.po +20 -0
  569. data/po/zh_CN/rbot-math.po +0 -0
  570. data/po/zh_CN/rbot-modes.po +0 -0
  571. data/po/zh_CN/rbot-nickrecover.po +36 -0
  572. data/po/zh_CN/rbot-nickserv.po +104 -0
  573. data/po/zh_CN/rbot-nslookup.po +0 -0
  574. data/po/zh_CN/rbot-quakeauth.po +0 -0
  575. data/po/zh_CN/rbot-quiz.po +0 -0
  576. data/po/zh_CN/rbot-quotes.po +108 -0
  577. data/po/zh_CN/rbot-reaction.po +0 -0
  578. data/po/zh_CN/rbot-remind.po +0 -0
  579. data/po/zh_CN/rbot-remotectl.po +0 -0
  580. data/po/zh_CN/rbot-ri.po +0 -0
  581. data/po/zh_CN/rbot-roshambo.po +0 -0
  582. data/po/zh_CN/rbot-rot13.po +0 -0
  583. data/po/zh_CN/rbot-roulette.po +0 -0
  584. data/po/zh_CN/rbot-rss.po +20 -0
  585. data/po/zh_CN/rbot-salut.po +0 -0
  586. data/po/zh_CN/rbot-script.po +0 -0
  587. data/po/zh_CN/rbot-search.po +0 -0
  588. data/po/zh_CN/rbot-seen.po +0 -0
  589. data/po/zh_CN/rbot-shiritori.po +102 -0
  590. data/po/zh_CN/rbot-shortenurls.po +0 -0
  591. data/po/zh_CN/rbot-slashdot.po +0 -0
  592. data/po/zh_CN/rbot-spell.po +54 -0
  593. data/po/zh_CN/rbot-theyfightcrime.po +0 -0
  594. data/po/zh_CN/rbot-threat.po +0 -0
  595. data/po/zh_CN/rbot-time.po +0 -0
  596. data/po/zh_CN/rbot-topic.po +0 -0
  597. data/po/zh_CN/rbot-translator.po +77 -0
  598. data/po/zh_CN/rbot-tube.po +0 -0
  599. data/po/zh_CN/rbot-twitter.po +24 -0
  600. data/po/zh_CN/rbot-uno.po +512 -0
  601. data/po/zh_CN/rbot-urban.po +0 -0
  602. data/po/zh_CN/rbot-url.po +0 -0
  603. data/po/zh_CN/rbot-usermodes.po +0 -0
  604. data/po/zh_CN/rbot-wall.po +33 -0
  605. data/po/zh_CN/rbot-weather.po +0 -0
  606. data/po/zh_CN/rbot-wheelfortune.po +205 -0
  607. data/po/zh_CN/rbot-wow.po +0 -0
  608. data/po/zh_CN/rbot-wserver.po +0 -0
  609. data/po/zh_CN/rbot-youtube.po +58 -0
  610. data/po/zh_CN/rbot.po +1006 -0
  611. data/po/zh_TW/rbot-alias.po +82 -0
  612. data/po/zh_TW/rbot-autoop.po +0 -0
  613. data/po/zh_TW/rbot-autorejoin.po +0 -0
  614. data/po/zh_TW/rbot-azgame.po +186 -0
  615. data/po/zh_TW/rbot-bans.po +0 -0
  616. data/po/zh_TW/rbot-bash.po +0 -0
  617. data/po/zh_TW/rbot-botsnack.po +0 -0
  618. data/po/zh_TW/rbot-cal.po +3 -0
  619. data/po/zh_TW/rbot-chanserv.po +0 -0
  620. data/po/zh_TW/rbot-chucknorris.po +0 -0
  621. data/po/zh_TW/rbot-debugger.po +0 -0
  622. data/po/zh_TW/rbot-deepthoughts.po +0 -0
  623. data/po/zh_TW/rbot-delicious.po +0 -0
  624. data/po/zh_TW/rbot-dice.po +0 -0
  625. data/po/zh_TW/rbot-dict.po +0 -0
  626. data/po/zh_TW/rbot-dictclient.po +111 -0
  627. data/po/zh_TW/rbot-digg.po +0 -0
  628. data/po/zh_TW/rbot-eightball.po +0 -0
  629. data/po/zh_TW/rbot-excuse.po +0 -0
  630. data/po/zh_TW/rbot-factoids.po +107 -0
  631. data/po/zh_TW/rbot-figlet.po +36 -0
  632. data/po/zh_TW/rbot-fish.po +0 -0
  633. data/po/zh_TW/rbot-forecast.po +0 -0
  634. data/po/zh_TW/rbot-fortune.po +0 -0
  635. data/po/zh_TW/rbot-freshmeat.po +0 -0
  636. data/po/zh_TW/rbot-grouphug.po +18 -0
  637. data/po/zh_TW/rbot-hl2.po +0 -0
  638. data/po/zh_TW/rbot-host.po +3 -0
  639. data/po/zh_TW/rbot-imdb.po +0 -0
  640. data/po/zh_TW/rbot-insult.po +0 -0
  641. data/po/zh_TW/rbot-iplookup.po +0 -0
  642. data/po/zh_TW/rbot-karma.po +0 -0
  643. data/po/zh_TW/rbot-keywords.po +24 -0
  644. data/po/zh_TW/rbot-lart.po +0 -0
  645. data/po/zh_TW/rbot-lastfm.po +172 -0
  646. data/po/zh_TW/rbot-linkbot.po +0 -0
  647. data/po/zh_TW/rbot-markov.po +20 -0
  648. data/po/zh_TW/rbot-math.po +0 -0
  649. data/po/zh_TW/rbot-modes.po +0 -0
  650. data/po/zh_TW/rbot-nickrecover.po +36 -0
  651. data/po/zh_TW/rbot-nickserv.po +104 -0
  652. data/po/zh_TW/rbot-nslookup.po +0 -0
  653. data/po/zh_TW/rbot-quakeauth.po +0 -0
  654. data/po/zh_TW/rbot-quiz.po +0 -0
  655. data/po/zh_TW/rbot-quotes.po +108 -0
  656. data/po/zh_TW/rbot-reaction.po +0 -0
  657. data/po/zh_TW/rbot-remind.po +0 -0
  658. data/po/zh_TW/rbot-remotectl.po +0 -0
  659. data/po/zh_TW/rbot-ri.po +0 -0
  660. data/po/zh_TW/rbot-roshambo.po +0 -0
  661. data/po/zh_TW/rbot-rot13.po +0 -0
  662. data/po/zh_TW/rbot-roulette.po +0 -0
  663. data/po/zh_TW/rbot-rss.po +20 -0
  664. data/po/zh_TW/rbot-salut.po +0 -0
  665. data/po/zh_TW/rbot-script.po +0 -0
  666. data/po/zh_TW/rbot-search.po +0 -0
  667. data/po/zh_TW/rbot-seen.po +0 -0
  668. data/po/zh_TW/rbot-shiritori.po +102 -0
  669. data/po/zh_TW/rbot-shortenurls.po +0 -0
  670. data/po/zh_TW/rbot-slashdot.po +0 -0
  671. data/po/zh_TW/rbot-spell.po +54 -0
  672. data/po/zh_TW/rbot-theyfightcrime.po +0 -0
  673. data/po/zh_TW/rbot-threat.po +0 -0
  674. data/po/zh_TW/rbot-time.po +0 -0
  675. data/po/zh_TW/rbot-topic.po +0 -0
  676. data/po/zh_TW/rbot-translator.po +77 -0
  677. data/po/zh_TW/rbot-tube.po +0 -0
  678. data/po/zh_TW/rbot-twitter.po +24 -0
  679. data/po/zh_TW/rbot-uno.po +512 -0
  680. data/po/zh_TW/rbot-urban.po +0 -0
  681. data/po/zh_TW/rbot-url.po +0 -0
  682. data/po/zh_TW/rbot-usermodes.po +0 -0
  683. data/po/zh_TW/rbot-wall.po +33 -0
  684. data/po/zh_TW/rbot-weather.po +0 -0
  685. data/po/zh_TW/rbot-wheelfortune.po +205 -0
  686. data/po/zh_TW/rbot-wow.po +0 -0
  687. data/po/zh_TW/rbot-wserver.po +0 -0
  688. data/po/zh_TW/rbot-youtube.po +58 -0
  689. data/po/zh_TW/rbot.po +1034 -0
  690. data/setup.rb +800 -574
  691. metadata +723 -108
  692. data/data/rbot/contrib/plugins/figlet.rb +0 -20
  693. data/data/rbot/contrib/plugins/ri.rb +0 -83
  694. data/data/rbot/plugins/demauro.rb +0 -95
  695. data/data/rbot/plugins/google.rb +0 -53
  696. data/data/rbot/plugins/opme.rb +0 -19
  697. data/data/rbot/plugins/roshambo.rb +0 -54
  698. data/data/rbot/plugins/rubyurl.rb +0 -39
  699. data/data/rbot/plugins/tinyurl.rb +0 -39
  700. data/data/rbot/plugins/xmlrpc.rb.disabled +0 -52
  701. data/data/rbot/templates/levels.rbot +0 -32
  702. data/data/rbot/templates/users.rbot +0 -1
  703. data/lib/rbot/auth.rb +0 -314
  704. data/lib/rbot/channel.rb +0 -54
  705. data/lib/rbot/httputil.rb +0 -309
  706. data/lib/rbot/utils.rb +0 -83
@@ -1,62 +1,50 @@
1
1
  #Tube Status Enquiry plugin for rbot
2
2
  #Plugin by Colm Linehan
3
3
 
4
- require 'rexml/document'
5
- require 'uri/common'
6
-
7
4
  class TubePlugin < Plugin
8
- include REXML
9
5
  def help(plugin, topic="")
10
- "tube [district|circle|metropolitan|central|jubilee|bakerloo|waterloo_city|hammersmith_city|victoria|eastlondon|northern|piccadilly] => display tube service status for the specified line(Docklands Light Railway is not currently supported), tube stations => list tube stations (not lines) with problems"
6
+ "tube [district|circle|metropolitan|central|jubilee|bakerloo|waterlooandcity|hammersmithandcity|victoria|eastlondon|northern|piccadilly] => display tube service status for the specified line(Docklands Light Railway is not currently supported)" # , tube stations => list tube stations (not lines) with problems"
11
7
  end
12
8
 
13
9
  def tube(m, params)
14
10
  line = params[:line]
15
- begin
16
- tube_page = @bot.httputil.get(URI.parse("http://www.tfl.gov.uk/tfl/service_rt_tube.shtml"), 1, 1)
17
- rescue URI::InvalidURIError, URI::BadURIError => e
18
- m.reply "Cannot contact Tube Service Status page"
19
- return
20
- end
21
- unless tube_page
22
- m.reply "Cannot contact Tube Service Status page"
23
- return
24
- end
25
- next_line = false
26
- tube_page.each_line {|l|
27
- next if l == "\r\n"
28
- next if l == "\n"
29
- if (next_line)
30
- if (l =~ /^<tr valign=top> <td>\s*(.*)<\/td><\/tr>/i)
31
- m.reply $1.split(/<[^>]+>|&nbsp;/i).join(" ")
32
- return
33
- else
34
- m.reply "There are problems on the #{line} line, but I didn't understand the page format. You should check out http://www.tfl.gov.uk/tfl/service_rt_tube.shtml for more details."
35
- return
36
- end
11
+ tube_page = @bot.httputil.get('http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html')
12
+ unless tube_page
13
+ m.reply "Cannot contact Tube Service Status page"
14
+ return
37
15
  end
38
- next_line = true if (l =~ /class="#{line}"/i)
16
+ next_line = false
17
+ tube_page.each_line {|l|
18
+ next if l == "\r\n"
19
+ next if l == "\n"
20
+ if (next_line)
21
+ if (l =~ /^<p>\s*(.*)<\/p>/i)
22
+ m.reply $1.split(/<[^>]+>|&nbsp;/i).join(" ")
23
+ return
24
+ elsif l =~ /ul|h3|"message"/
25
+ next
26
+ else
27
+ m.reply "There are problems on the #{line} line, but I didn't understand the page format. You should check out http://www.tfl.gov.uk/tfl/livetravelnews/realtime/tube/default.html for more details."
28
+ return
29
+ end
30
+ end
31
+ next_line = true if (l =~ /li class="#{line}"/i)
39
32
  }
40
- m.reply "No Problems on the #{line} line."
33
+ m.reply "No Problems on the #{line} line."
41
34
  end
42
35
 
43
36
  def check_stations(m, params)
44
- begin
45
- tube_page = @bot.httputil.get(URI.parse("http://www.tfl.gov.uk/tfl/service_rt_tube.shtml"))
46
- rescue URI::InvalidURIError, URI::BadURIError => e
47
- m.reply "Cannot contact Tube Service Status page"
48
- return
49
- end
37
+ tube_page = @bot.httputil.get('http://www.tfl.gov.uk/tfl/service_rt_tube.shtml')
50
38
  unless tube_page
51
39
  m.reply "Cannot contact Tube Service Status page"
52
40
  return
53
41
  end
54
42
  stations_array = Array.new
55
43
  tube_page.each_line {|l|
56
- if (l =~ /<tr valign=top> <td valign="middle" class="Station"><b>(.*)<\/b><\/td><\/tr>\s*/i)
57
- stations_array.push $1
58
- end
59
- }
44
+ if (l =~ /<tr valign=top> <td valign="middle" class="Station"><b>(.*)<\/b><\/td><\/tr>\s*/i)
45
+ stations_array.push $1
46
+ end
47
+ }
60
48
  if stations_array.empty?
61
49
  m.reply "There are no station-specific announcements"
62
50
  return
@@ -67,5 +55,5 @@ class TubePlugin < Plugin
67
55
  end
68
56
  end
69
57
  plugin = TubePlugin.new
70
- plugin.map 'tube stations', :action => 'check_stations'
58
+ # plugin.map 'tube stations', :action => 'check_stations'
71
59
  plugin.map 'tube :line'
@@ -0,0 +1,187 @@
1
+ #-- vim:sw=2:et
2
+ #++
3
+ #
4
+ # :title: Twitter Status Update for rbot
5
+ #
6
+ # Author:: Carter Parks (carterparks) <carter@carterparks.com>
7
+ # Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
8
+ #
9
+ # Copyright:: (C) 2007 Carter Parks
10
+ # Copyright:: (C) 2007 Giuseppe Bilotta
11
+ #
12
+ # Users can setup their twitter username and password and then begin updating
13
+ # twitter whenever
14
+
15
+ require 'rexml/rexml'
16
+ require 'cgi'
17
+
18
+ class TwitterPlugin < Plugin
19
+ Config.register Config::IntegerValue.new('twitter.status_count',
20
+ :default => 1, :validate => Proc.new { |v| v > 0 && v <= 10},
21
+ :desc => "Maximum number of status updates shown by 'twitter status'")
22
+ Config.register Config::IntegerValue.new('twitter.friends_status_count',
23
+ :default => 3, :validate => Proc.new { |v| v > 0 && v <= 10},
24
+ :desc => "Maximum number of status updates shown by 'twitter friends status'")
25
+
26
+ def initialize
27
+ super
28
+
29
+ class << @registry
30
+ def store(val)
31
+ val
32
+ end
33
+ def restore(val)
34
+ val
35
+ end
36
+ end
37
+
38
+ @header = {
39
+ 'X-Twitter-Client' => 'rbot twitter plugin'
40
+ }
41
+ end
42
+
43
+ # return a help string when the bot is asked for help on this plugin
44
+ def help(plugin, topic="")
45
+ return "twitter status [nick] => show nick's (or your) status, use 'twitter friends status [nick]' to also show the friends' timeline | twitter update [status] => updates your status on twitter | twitter identify [username] [password] => ties your nick to your twitter username and password | twitter actions [on|off] => enable/disable twitting of actions (/me does ...)"
46
+ end
47
+
48
+ # update the status on twitter
49
+ def get_status(m, params)
50
+
51
+ nick = params[:nick] || @registry[m.sourcenick + "_username"]
52
+
53
+ if not nick
54
+ m.reply "you should specify the username of the twitter touse, or identify using 'twitter identify [username] [password]'"
55
+ return false
56
+ end
57
+
58
+ user = URI.escape(nick)
59
+
60
+ count = @bot.config['twitter.status_count']
61
+ unless params[:friends]
62
+ uri = "http://twitter.com/statuses/user_timeline/#{user}.xml?count=#{count}"
63
+ else
64
+ count = @bot.config['twitter.friends_status_count']
65
+ uri = "http://twitter.com/statuses/friends_timeline/#{user}.xml"
66
+ end
67
+
68
+ response = @bot.httputil.get(uri, :headers => @header, :cache => false)
69
+ debug response
70
+
71
+ texts = []
72
+
73
+ if response
74
+ begin
75
+ rex = REXML::Document.new(response)
76
+ rex.root.elements.each("status") { |st|
77
+ # month, day, hour, min, sec, year = st.elements['created_at'].text.match(/\w+ (\w+) (\d+) (\d+):(\d+):(\d+) \S+ (\d+)/)[1..6]
78
+ # debug [year, month, day, hour, min, sec].inspect
79
+ # time = Time.local(year.to_i, month, day.to_i, hour.to_i, min.to_i, sec.to_i)
80
+ time = Time.parse(st.elements['created_at'].text)
81
+ now = Time.now
82
+ # Sometimes, time can be in the future; invert the relation in this case
83
+ delta = ((time > now) ? time - now : now - time)
84
+ msg = st.elements['text'].to_s + " (#{Utils.secs_to_string(delta.to_i)} ago via #{st.elements['source'].to_s})"
85
+ author = ""
86
+ if params[:friends]
87
+ author = Utils.decode_html_entities(st.elements['user'].elements['name'].text) + ": " rescue ""
88
+ end
89
+ texts << author+Utils.decode_html_entities(msg).ircify_html
90
+ }
91
+ if params[:friends]
92
+ # friends always return the latest 20 updates, so we clip the count
93
+ texts[count..-1]=nil
94
+ end
95
+ rescue
96
+ error $!
97
+ m.reply "could not parse status for #{nick}"
98
+ return false
99
+ end
100
+ m.reply texts.reverse.join("\n")
101
+ return true
102
+ else
103
+ m.reply "could not get status for #{nick}"
104
+ return false
105
+ end
106
+ end
107
+
108
+ # update the status on twitter
109
+ def update_status(m, params)
110
+
111
+
112
+ unless @registry.has_key?(m.sourcenick + "_password") && @registry.has_key?(m.sourcenick + "_username")
113
+ m.reply "you must identify using 'twitter identify [username] [password]'"
114
+ return false
115
+ end
116
+
117
+ user = URI.escape(@registry[m.sourcenick + "_username"])
118
+ pass = URI.escape(@registry[m.sourcenick + "_password"])
119
+ uri = "http://#{user}:#{pass}@twitter.com/statuses/update.xml"
120
+
121
+ msg = params[:status].to_s
122
+
123
+ if msg.length > 160
124
+ m.reply "your status message update is too long, please keep it under 140 characters if possible, 160 characters maximum"
125
+ return
126
+ end
127
+
128
+ if msg.length > 140
129
+ m.reply "your status message is longer than 140 characters, which is not optimal, but I'm going to update anyway"
130
+ end
131
+
132
+ source = "source=rbot"
133
+ msg = "status=#{CGI.escape(msg)}"
134
+ body = [source,msg].join("&")
135
+
136
+ response = @bot.httputil.post(uri, body, :headers => @header)
137
+ debug response
138
+
139
+ reply_method = params[:notify] ? :notify : :reply
140
+ if response.class == Net::HTTPOK
141
+ m.__send__(reply_method, "status updated")
142
+ else
143
+ m.__send__(reply_method, "could not update status")
144
+ end
145
+ end
146
+
147
+ # ties a nickname to a twitter username and password
148
+ def identify(m, params)
149
+ @registry[m.sourcenick + "_username"] = params[:username].to_s
150
+ @registry[m.sourcenick + "_password"] = params[:password].to_s
151
+ m.reply "you're all setup!"
152
+ end
153
+
154
+ # update on ACTION if the user has enabled the option
155
+ def ctcp_listen(m)
156
+ return unless m.action?
157
+ return unless @registry[m.sourcenick + "_actions"]
158
+ update_status(m, :status => m.message, :notify => true)
159
+ end
160
+
161
+ # show or toggle action twitting
162
+ def actions(m, params)
163
+ case params[:toggle]
164
+ when 'on'
165
+ @registry[m.sourcenick + "_actions"] = true
166
+ m.okay
167
+ when 'off'
168
+ @registry.delete(m.sourcenick + "_actions")
169
+ m.okay
170
+ else
171
+ if @registry[m.sourcenick + "_actions"]
172
+ m.reply _("actions will be twitted")
173
+ else
174
+ m.reply _("actions will not be twitted")
175
+ end
176
+ end
177
+ end
178
+ end
179
+
180
+ # create an instance of our plugin class and register for the "length" command
181
+ plugin = TwitterPlugin.new
182
+ plugin.map 'twitter identify :username :password', :action => "identify", :public => false
183
+ plugin.map 'twitter update *status', :action => "update_status", :threaded => true
184
+ plugin.map 'twitter status [:nick]', :action => "get_status", :threaded => true
185
+ plugin.map 'twitter actions [:toggle]', :action => "actions", :requirements => { :toggle => /^on|off$/ }
186
+ plugin.map 'twitter :friends [status] [:nick]', :action => "get_status", :requirements => { :friends => /^friends?$/ }, :threaded => true
187
+
@@ -1,71 +1,80 @@
1
- require 'cgi'
2
- begin
3
- require 'rubyful_soup'
4
- rescue
5
- warning "could not load rubyful_soup, urban dictionary disabled"
6
- warning "please get it from http://www.crummy.com/software/RubyfulSoup/"
7
- warning "or install it via gem"
8
- return
9
- end
10
- require 'uri/common'
11
-
12
1
  class UrbanPlugin < Plugin
2
+ URBAN = 'http://www.urbandictionary.com/define.php?term='
13
3
 
14
4
  def help( plugin, topic="")
15
- "urban [word] [n]. Give the [n]th definition of [word] from urbandictionary.com."
5
+ "urban [word] [n]: give the [n]th definition of [word] from urbandictionary.com. urbanday: give the word-of-the-day at urban"
16
6
  end
17
7
 
18
- def privmsg( m )
8
+ def format_definition(total, num, word, desc, ex)
9
+ "#{Bold}#{word} (#{num}/#{total})#{Bold}: " +
10
+ desc.ircify_html(:limit => 300) + " " +
11
+ "<i>#{ex}</i>".ircify_html(:limit => 100)
12
+ end
19
13
 
20
- unless(m.params && m.params.length > 0)
21
- m.reply "incorrect usage: " + help(m.plugin)
22
- return
14
+ def get_def(m, word, n = nil)
15
+ n = n ? n.to_i : 1
16
+ p = (n-1)/7 + 1
17
+ u = URBAN + URI.escape(word)
18
+ u += '&page=' + p.to_s if p > 1
19
+ s = @bot.httputil.get(u)
20
+ return m.reply "Couldn't get the urban dictionary definition for #{word}" if s.nil?
21
+
22
+ notfound = s.match %r{<div style="color: #669FCE"><i>.*?</i> isn't defined}
23
+
24
+ numpages = s[%r{<div id='paginator'>.*?</div>}m].scan(/\d+/).collect {|x| x.to_i}.max || 1
25
+
26
+ rv = Array.new
27
+ s.scan(%r{<td class='index'[^>]*>.*?(\d+)\..*?</td>.*?<td class='word'>(?:<a.*?>)?([^>]+)(?:</a>)?</td>.*?<div class='definition'>(.+?)</div>.*?<div class='example'>(.+?)</div>}m) do |num, wrd, desc, ex|
28
+ rv << [num.to_i, wrd.strip, desc.strip, ex.strip]
23
29
  end
24
30
 
25
- paramArray = m.params.split(' ')
26
- definitionN = 0
27
- if m.params == 'random' then
28
- uri = URI.parse( "http://www.urbandictionary.com/random.php" )
29
- else
30
- if( paramArray.last.to_i != 0 ) then
31
- definitionN = paramArray.last.to_i - 1
32
- query = m.params.chomp( paramArray.last )
33
- query.rstrip!
34
- else
35
- query = m.params
36
- end
37
- uri = URI.parse( "http://www.urbandictionary.com/define.php?term=#{ URI.escape query}" )
31
+ maxnum = rv.collect {|x| x[0]}.max || 0
32
+ return m.reply("#{Bold}#{word}#{Bold} not found") if rv.empty?
33
+
34
+ if notfound
35
+ suggestions = rv.map { |s| Underline + s[1] + Underline }.uniq.join ', '
36
+ m.reply "#{Bold}#{word}#{Bold} not found. maybe you mean #{suggestions}?"
37
+ return
38
38
  end
39
39
 
40
- soup = BeautifulSoup.new( @bot.httputil.get_cached( uri ) )
41
- if titleNavi = soup.find_all( 'td', :attrs => { 'class' => 'def_word' } )[0] then
42
- title = titleNavi.contents
43
- results = soup.find_all( 'div', :attrs => { 'class' => 'def_p' } )
44
- # debug PP.pp(results,'')
45
- output = Array.new
46
- if results[definitionN] then
47
- results[definitionN].p.contents.each { |s| output.push( strip_tags( s.to_s ) ) }
48
- m.reply "\002#{title}\002 - #{output}"
49
- else
50
- m.reply "#{query} does not have #{definitionN + 1} definitions."
40
+ answer = rv.find { |a| a[0] == n }
41
+ answer ||= (n > maxnum ? rv.last : rv.first)
42
+ m.reply format_definition((p == numpages ? maxnum : "#{(numpages-1)*7 + 1}+"), *answer)
43
+ end
44
+
45
+ def urban(m, params)
46
+ words = params[:words].to_s
47
+ if words.empty?
48
+ resp = @bot.httputil.head('http://www.urbandictionary.com/random.php',
49
+ :max_redir => -1,
50
+ :cache => false)
51
+ return m.reply "Couldn't get a random urban dictionary word" if resp.nil?
52
+ if resp.code == "302" && (loc = resp['location'])
53
+ words = URI.unescape(loc.match(/define.php\?term=(.*)$/)[1]) rescue nil
51
54
  end
52
- else
53
- m.reply "#{m.params} not found."
54
55
  end
55
-
56
+ get_def(m, words, params[:n])
56
57
  end
57
58
 
58
- def strip_tags(html)
59
- html.gsub(/<.+?>/,'').
60
- gsub(/&amp;/,'&').
61
- gsub(/&quot;/,'"').
62
- gsub(/&lt;/,'<').
63
- gsub(/&gt;/,'>').
64
- gsub(/&ellip;/,'...').
65
- gsub(/&apos;/, "'").
66
- gsub("\n",'')
59
+ def uotd(m, params)
60
+ home = @bot.httputil.get("http://www.urbandictionary.com/daily.php")
61
+ if home.nil?
62
+ m.reply "Couldn't get the urban dictionary word of the day"
63
+ return
64
+ end
65
+ home.match(%r{href="/define.php\?term=.*?">(.*?)<})
66
+ wotd = $1
67
+ debug "Urban word of the day: #{wotd}"
68
+ if !wotd
69
+ m.reply "Couldn't get the urban dictionary word of the day"
70
+ return
71
+ end
72
+ get_def(m, wotd, 1)
67
73
  end
68
74
  end
69
75
 
70
76
  plugin = UrbanPlugin.new
71
- plugin.register( "urban" )
77
+ plugin.map "urban *words :n", :requirements => { :n => /^-?\d+$/ }, :action => 'urban'
78
+ plugin.map "urban [*words]", :action => 'urban'
79
+ plugin.map "urbanday", :action => 'uotd'
80
+
@@ -1,434 +1,218 @@
1
- require 'net/http'
2
- require 'uri'
3
- require 'cgi'
4
-
5
- Url = Struct.new("Url", :channel, :nick, :time, :url)
6
- TITLE_RE = /<\s*?title\s*?>(.+?)<\s*?\/title\s*?>/im
7
-
8
- UNESCAPE_TABLE = {
9
- 'raquo' => '>>',
10
- 'quot' => '"',
11
- 'micro' => 'u',
12
- 'copy' => '(c)',
13
- 'trade' => '(tm)',
14
- 'reg' => '(R)',
15
- '#174' => '(R)',
16
- '#8220' => '"',
17
- '#8221' => '"',
18
- '#8212' => '--',
19
- '#39' => '\'',
20
- =begin
21
- # extras codes, for future use...
22
- 'zwnj' => '&#8204;',
23
- 'aring' => '\xe5',
24
- 'gt' => '>',
25
- 'yen' => '\xa5',
26
- 'ograve' => '\xf2',
27
- 'Chi' => '&#935;',
28
- 'bull' => '&#8226;',
29
- 'Egrave' => '\xc8',
30
- 'Ntilde' => '\xd1',
31
- 'upsih' => '&#978;',
32
- 'Yacute' => '\xdd',
33
- 'asymp' => '&#8776;',
34
- 'radic' => '&#8730;',
35
- 'otimes' => '&#8855;',
36
- 'nabla' => '&#8711;',
37
- 'aelig' => '\xe6',
38
- 'oelig' => '&#339;',
39
- 'equiv' => '&#8801;',
40
- 'Psi' => '&#936;',
41
- 'auml' => '\xe4',
42
- 'circ' => '&#710;',
43
- 'Acirc' => '\xc2',
44
- 'Epsilon' => '&#917;',
45
- 'Yuml' => '&#376;',
46
- 'Eta' => '&#919;',
47
- 'lt' => '<',
48
- 'Icirc' => '\xce',
49
- 'Upsilon' => '&#933;',
50
- 'ndash' => '&#8211;',
51
- 'there4' => '&#8756;',
52
- 'Prime' => '&#8243;',
53
- 'prime' => '&#8242;',
54
- 'psi' => '&#968;',
55
- 'Kappa' => '&#922;',
56
- 'rsaquo' => '&#8250;',
57
- 'Tau' => '&#932;',
58
- 'darr' => '&#8595;',
59
- 'ocirc' => '\xf4',
60
- 'lrm' => '&#8206;',
61
- 'zwj' => '&#8205;',
62
- 'cedil' => '\xb8',
63
- 'Ecirc' => '\xca',
64
- 'not' => '\xac',
65
- 'amp' => '&',
66
- 'AElig' => '\xc6',
67
- 'oslash' => '\xf8',
68
- 'acute' => '\xb4',
69
- 'lceil' => '&#8968;',
70
- 'laquo' => '\xab',
71
- 'shy' => '\xad',
72
- 'rdquo' => '&#8221;',
73
- 'ge' => '&#8805;',
74
- 'Igrave' => '\xcc',
75
- 'Ograve' => '\xd2',
76
- 'euro' => '&#8364;',
77
- 'dArr' => '&#8659;',
78
- 'sdot' => '&#8901;',
79
- 'nbsp' => '\xa0',
80
- 'lfloor' => '&#8970;',
81
- 'lArr' => '&#8656;',
82
- 'Auml' => '\xc4',
83
- 'larr' => '&#8592;',
84
- 'Atilde' => '\xc3',
85
- 'Otilde' => '\xd5',
86
- 'szlig' => '\xdf',
87
- 'clubs' => '&#9827;',
88
- 'diams' => '&#9830;',
89
- 'agrave' => '\xe0',
90
- 'Ocirc' => '\xd4',
91
- 'Iota' => '&#921;',
92
- 'Theta' => '&#920;',
93
- 'Pi' => '&#928;',
94
- 'OElig' => '&#338;',
95
- 'Scaron' => '&#352;',
96
- 'frac14' => '\xbc',
97
- 'egrave' => '\xe8',
98
- 'sub' => '&#8834;',
99
- 'iexcl' => '\xa1',
100
- 'frac12' => '\xbd',
101
- 'sbquo' => '&#8218;',
102
- 'ordf' => '\xaa',
103
- 'sum' => '&#8721;',
104
- 'prop' => '&#8733;',
105
- 'Uuml' => '\xdc',
106
- 'ntilde' => '\xf1',
107
- 'sup' => '&#8835;',
108
- 'theta' => '&#952;',
109
- 'prod' => '&#8719;',
110
- 'nsub' => '&#8836;',
111
- 'hArr' => '&#8660;',
112
- 'rlm' => '&#8207;',
113
- 'THORN' => '\xde',
114
- 'infin' => '&#8734;',
115
- 'yuml' => '\xff',
116
- 'Mu' => '&#924;',
117
- 'le' => '&#8804;',
118
- 'Eacute' => '\xc9',
119
- 'thinsp' => '&#8201;',
120
- 'ecirc' => '\xea',
121
- 'bdquo' => '&#8222;',
122
- 'Sigma' => '&#931;',
123
- 'fnof' => '&#402;',
124
- 'Aring' => '\xc5',
125
- 'tilde' => '&#732;',
126
- 'frac34' => '\xbe',
127
- 'emsp' => '&#8195;',
128
- 'mdash' => '&#8212;',
129
- 'uarr' => '&#8593;',
130
- 'permil' => '&#8240;',
131
- 'Ugrave' => '\xd9',
132
- 'rarr' => '&#8594;',
133
- 'Agrave' => '\xc0',
134
- 'chi' => '&#967;',
135
- 'forall' => '&#8704;',
136
- 'eth' => '\xf0',
137
- 'rceil' => '&#8969;',
138
- 'iuml' => '\xef',
139
- 'gamma' => '&#947;',
140
- 'lambda' => '&#955;',
141
- 'harr' => '&#8596;',
142
- 'rang' => '&#9002;',
143
- 'xi' => '&#958;',
144
- 'dagger' => '&#8224;',
145
- 'divide' => '\xf7',
146
- 'Ouml' => '\xd6',
147
- 'image' => '&#8465;',
148
- 'alefsym' => '&#8501;',
149
- 'igrave' => '\xec',
150
- 'otilde' => '\xf5',
151
- 'Oacute' => '\xd3',
152
- 'sube' => '&#8838;',
153
- 'alpha' => '&#945;',
154
- 'frasl' => '&#8260;',
155
- 'ETH' => '\xd0',
156
- 'lowast' => '&#8727;',
157
- 'Nu' => '&#925;',
158
- 'plusmn' => '\xb1',
159
- 'Euml' => '\xcb',
160
- 'real' => '&#8476;',
161
- 'sup1' => '\xb9',
162
- 'sup2' => '\xb2',
163
- 'sup3' => '\xb3',
164
- 'Oslash' => '\xd8',
165
- 'Aacute' => '\xc1',
166
- 'cent' => '\xa2',
167
- 'oline' => '&#8254;',
168
- 'Beta' => '&#914;',
169
- 'perp' => '&#8869;',
170
- 'Delta' => '&#916;',
171
- 'loz' => '&#9674;',
172
- 'pi' => '&#960;',
173
- 'iota' => '&#953;',
174
- 'empty' => '&#8709;',
175
- 'euml' => '\xeb',
176
- 'brvbar' => '\xa6',
177
- 'iacute' => '\xed',
178
- 'para' => '\xb6',
179
- 'micro' => '\xb5',
180
- 'cup' => '&#8746;',
181
- 'weierp' => '&#8472;',
182
- 'uuml' => '\xfc',
183
- 'part' => '&#8706;',
184
- 'icirc' => '\xee',
185
- 'delta' => '&#948;',
186
- 'omicron' => '&#959;',
187
- 'upsilon' => '&#965;',
188
- 'Iuml' => '\xcf',
189
- 'Lambda' => '&#923;',
190
- 'Xi' => '&#926;',
191
- 'kappa' => '&#954;',
192
- 'ccedil' => '\xe7',
193
- 'Ucirc' => '\xdb',
194
- 'cap' => '&#8745;',
195
- 'mu' => '&#956;',
196
- 'scaron' => '&#353;',
197
- 'lsquo' => '&#8216;',
198
- 'isin' => '&#8712;',
199
- 'Zeta' => '&#918;',
200
- 'supe' => '&#8839;',
201
- 'deg' => '\xb0',
202
- 'and' => '&#8743;',
203
- 'tau' => '&#964;',
204
- 'pound' => '\xa3',
205
- 'hellip' => '&#8230;',
206
- 'curren' => '\xa4',
207
- 'int' => '&#8747;',
208
- 'ucirc' => '\xfb',
209
- 'rfloor' => '&#8971;',
210
- 'ensp' => '&#8194;',
211
- 'crarr' => '&#8629;',
212
- 'ugrave' => '\xf9',
213
- 'notin' => '&#8713;',
214
- 'exist' => '&#8707;',
215
- 'uArr' => '&#8657;',
216
- 'cong' => '&#8773;',
217
- 'Dagger' => '&#8225;',
218
- 'oplus' => '&#8853;',
219
- 'times' => '\xd7',
220
- 'atilde' => '\xe3',
221
- 'piv' => '&#982;',
222
- 'ni' => '&#8715;',
223
- 'Phi' => '&#934;',
224
- 'lsaquo' => '&#8249;',
225
- 'Uacute' => '\xda',
226
- 'Omicron' => '&#927;',
227
- 'ang' => '&#8736;',
228
- 'ne' => '&#8800;',
229
- 'iquest' => '\xbf',
230
- 'eta' => '&#951;',
231
- 'yacute' => '\xfd',
232
- 'Rho' => '&#929;',
233
- 'uacute' => '\xfa',
234
- 'Alpha' => '&#913;',
235
- 'zeta' => '&#950;',
236
- 'Omega' => '&#937;',
237
- 'nu' => '&#957;',
238
- 'sim' => '&#8764;',
239
- 'sect' => '\xa7',
240
- 'phi' => '&#966;',
241
- 'sigmaf' => '&#962;',
242
- 'macr' => '\xaf',
243
- 'minus' => '&#8722;',
244
- 'Ccedil' => '\xc7',
245
- 'ordm' => '\xba',
246
- 'epsilon' => '&#949;',
247
- 'beta' => '&#946;',
248
- 'rArr' => '&#8658;',
249
- 'rho' => '&#961;',
250
- 'aacute' => '\xe1',
251
- 'eacute' => '\xe9',
252
- 'omega' => '&#969;',
253
- 'middot' => '\xb7',
254
- 'Gamma' => '&#915;',
255
- 'Iacute' => '\xcd',
256
- 'lang' => '&#9001;',
257
- 'spades' => '&#9824;',
258
- 'rsquo' => '&#8217;',
259
- 'uml' => '\xa8',
260
- 'thorn' => '\xfe',
261
- 'ouml' => '\xf6',
262
- 'thetasym' => '&#977;',
263
- 'or' => '&#8744;',
264
- 'raquo' => '\xbb',
265
- 'acirc' => '\xe2',
266
- 'ldquo' => '&#8220;',
267
- 'hearts' => '&#9829;',
268
- 'sigma' => '&#963;',
269
- 'oacute' => '\xf3',
270
- =end
271
- }
1
+ #-- vim:sw=2:et
2
+ #++
3
+ #
4
+ # :title: Url plugin
5
+
6
+ define_structure :Url, :channel, :nick, :time, :url, :info
272
7
 
273
8
  class UrlPlugin < Plugin
274
- BotConfig.register BotConfigIntegerValue.new('url.max_urls',
9
+ LINK_INFO = "[Link Info]"
10
+ OUR_UNSAFE = Regexp.new("[^#{URI::PATTERN::UNRESERVED}#{URI::PATTERN::RESERVED}%# ]", false, 'N')
11
+
12
+ Config.register Config::IntegerValue.new('url.max_urls',
275
13
  :default => 100, :validate => Proc.new{|v| v > 0},
276
14
  :desc => "Maximum number of urls to store. New urls replace oldest ones.")
277
- BotConfig.register BotConfigBooleanValue.new('url.display_link_info',
278
- :default => false,
279
- :desc => "Get the title of any links pasted to the channel and display it (also tells if the link is broken or the site is down)")
280
-
15
+ Config.register Config::IntegerValue.new('url.display_link_info',
16
+ :default => 0,
17
+ :desc => "Get the title of links pasted to the channel and display it (also tells if the link is broken or the site is down). Do it for at most this many links per line (set to 0 to disable)")
18
+ Config.register Config::BooleanValue.new('url.titles_only',
19
+ :default => false,
20
+ :desc => "Only show info for links that have <title> tags (in other words, don't display info for jpegs, mpegs, etc.)")
21
+ Config.register Config::BooleanValue.new('url.first_par',
22
+ :default => false,
23
+ :desc => "Also try to get the first paragraph of a web page")
24
+ Config.register Config::BooleanValue.new('url.info_on_list',
25
+ :default => false,
26
+ :desc => "Show link info when listing/searching for urls")
27
+ Config.register Config::ArrayValue.new('url.no_info_hosts',
28
+ :default => ['localhost', '^192\.168\.', '^10\.', '^127\.', '^172\.(1[6-9]|2\d|31)\.'],
29
+ :on_change => Proc.new { |bot, v| bot.plugins['url'].reset_no_info_hosts },
30
+ :desc => "A list of regular expressions matching hosts for which no info should be provided")
31
+
32
+
281
33
  def initialize
282
34
  super
283
35
  @registry.set_default(Array.new)
36
+ unless @bot.config['url.display_link_info'].kind_of?(Integer)
37
+ @bot.config.items[:'url.display_link_info'].set_string(@bot.config['url.display_link_info'].to_s)
38
+ end
39
+ reset_no_info_hosts
284
40
  end
285
41
 
286
- def help(plugin, topic="")
287
- "urls [<max>=4] => list <max> last urls mentioned in current channel, urls search [<max>=4] <regexp> => search for matching urls. In a private message, you must specify the channel to query, eg. urls <channel> [max], urls search <channel> [max] <regexp>"
42
+ def reset_no_info_hosts
43
+ @no_info_hosts = Regexp.new(@bot.config['url.no_info_hosts'].join('|'), true)
44
+ debug "no info hosts regexp set to #{@no_info_hosts}"
288
45
  end
289
46
 
290
- def unescape_title(htmldata)
291
- # first pass -- let CGI try to attack it...
292
- htmldata = CGI::unescapeHTML htmldata
293
-
294
- # second pass -- destroy the remaining bits...
295
- htmldata.gsub(/(&(.+?);)/) {
296
- symbol = $2
297
-
298
- # remove the 0-paddng from unicode integers
299
- if symbol =~ /#(.+)/
300
- symbol = "##{$1.to_i.to_s}"
301
- end
302
-
303
- # output the symbol's irc-translated character, or a * if it's unknown
304
- UNESCAPE_TABLE[symbol] || '*'
305
- }
47
+ def help(plugin, topic="")
48
+ "url info <url> => display link info for <url> (set url.display_link_info > 0 if you want the bot to do it automatically when someone writes an url), urls [<max>=4] => list <max> last urls mentioned in current channel, urls search [<max>=4] <regexp> => search for matching urls. In a private message, you must specify the channel to query, eg. urls <channel> [max], urls search <channel> [max] <regexp>"
306
49
  end
307
50
 
308
51
  def get_title_from_html(pagedata)
309
- return unless TITLE_RE.match(pagedata)
310
- title = $1.strip.gsub(/\s*\n+\s*/, " ")
311
- title = unescape_title title
312
- title = title[0..255] if title.length > 255
313
- "[Link Info] title: #{title}"
52
+ return pagedata.ircify_html_title
314
53
  end
315
54
 
316
- def read_data_from_response(response, amount)
317
-
318
- amount_read = 0
319
- chunks = []
320
-
321
- response.read_body do |chunk| # read body now
322
-
323
- amount_read += chunk.length
324
-
325
- if amount_read > amount
326
- amount_of_overflow = amount_read - amount
327
- chunk = chunk[0...-amount_of_overflow]
55
+ def get_title_for_url(uri_str, opts = {})
56
+
57
+ url = uri_str.kind_of?(URI) ? uri_str : URI.parse(uri_str)
58
+ return if url.scheme !~ /https?/
59
+
60
+ # also check the ip, the canonical name and the aliases
61
+ begin
62
+ checks = TCPSocket.gethostbyname(url.host)
63
+ checks.delete_at(-2)
64
+ rescue => e
65
+ return "Unable to retrieve info for #{url.host}: #{e.message}"
66
+ end
67
+
68
+ checks << url.host
69
+ checks.flatten!
70
+
71
+ unless checks.grep(@no_info_hosts).empty?
72
+ return "Sorry, info retrieval for #{url.host} (#{checks.first}) is disabled"
73
+ end
74
+
75
+ logopts = opts.dup
76
+
77
+ title = nil
78
+ extra = []
79
+
80
+ begin
81
+ debug "+ getting info for #{url.request_uri}"
82
+ info = @bot.filter(:htmlinfo, url)
83
+ debug info
84
+ resp = info[:headers]
85
+
86
+ logopts[:title] = title = info[:title]
87
+
88
+ if info[:content]
89
+ logopts[:extra] = info[:content]
90
+ extra << "#{Bold}text#{Bold}: #{info[:content]}" if @bot.config['url.first_par']
91
+ else
92
+ logopts[:extra] = String.new
93
+ logopts[:extra] << "Content Type: #{resp['content-type']}"
94
+ extra << "#{Bold}type#{Bold}: #{resp['content-type']}" unless title
95
+ if enc = resp['content-encoding']
96
+ logopts[:extra] << ", encoding: #{enc}"
97
+ extra << "#{Bold}encoding#{Bold}: #{enc}" if @bot.config['url.first_par'] or not title
98
+ end
99
+
100
+ size = resp['content-length'].first.gsub(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2') rescue nil
101
+ if size
102
+ logopts[:extra] << ", size: #{size} bytes"
103
+ extra << "#{Bold}size#{Bold}: #{size} bytes" if @bot.config['url.first_par'] or not title
104
+ end
328
105
  end
329
-
330
- chunks << chunk
106
+ rescue Exception => e
107
+ case e
108
+ when UrlLinkError
109
+ raise e
110
+ else
111
+ error e
112
+ raise "connecting to site/processing information (#{e.message})"
113
+ end
114
+ end
331
115
 
332
- break if amount_read >= amount
333
-
116
+ call_event(:url_added, url.to_s, logopts)
117
+ if title
118
+ extra.unshift("#{Bold}title#{Bold}: #{title}")
334
119
  end
335
-
336
- chunks.join('')
337
-
120
+ return extra.join(", ") if title or not @bot.config['url.titles_only']
338
121
  end
339
122
 
123
+ def handle_urls(m, urls, display_info=@bot.config['url.display_link_info'])
124
+ return if urls.empty?
125
+ debug "found urls #{urls.inspect}"
126
+ list = m.public? ? @registry[m.target] : nil
127
+ debug "display link info: #{display_info}"
128
+ urls_displayed = 0
129
+ urls.each do |urlstr|
130
+ debug "working on #{urlstr}"
131
+ next unless urlstr =~ /^https?:/
132
+ title = nil
133
+ debug "Getting title for #{urlstr}..."
134
+ reply = nil
135
+ begin
136
+ title = get_title_for_url(urlstr,
137
+ :nick => m.source.nick,
138
+ :channel => m.channel,
139
+ :ircline => m.message)
140
+ debug "Title #{title ? '' : 'not '} found"
141
+ reply = "#{LINK_INFO} #{title}" if title
142
+ rescue => e
143
+ debug e
144
+ # we might get a 404 because of trailing punctuation, so we try again
145
+ # with the last character stripped. this might generate invalid URIs
146
+ # (e.g. because "some.url" gets chopped to some.url%2, so catch that too
147
+ if e.message =~ /\(404 - Not Found\)/i or e.kind_of?(URI::InvalidURIError)
148
+ # chop off last character, and retry if we still have enough string to
149
+ # look like a minimal URL
150
+ retry if urlstr.chop! and urlstr =~ /^https?:\/\/./
151
+ end
152
+ reply = "Error #{e.message}"
153
+ end
154
+
155
+ if display_info > urls_displayed
156
+ if reply
157
+ m.plainreply(reply, :overlong => :truncate)
158
+ urls_displayed += 1
159
+ end
160
+ end
161
+
162
+ next unless list
340
163
 
341
- def get_title_for_url(uri_str, depth=10)
342
- # This god-awful mess is what the ruby http library has reduced me to.
343
- # Python's HTTP lib is so much nicer. :~(
344
-
345
- if depth == 0
346
- raise "Error: Maximum redirects hit."
164
+ # check to see if this url is already listed
165
+ next if list.find {|u| u.url == urlstr }
166
+
167
+ url = Url.new(m.target, m.sourcenick, Time.new, urlstr, title)
168
+ debug "#{list.length} urls so far"
169
+ list.pop if list.length > @bot.config['url.max_urls']
170
+ debug "storing url #{url.url}"
171
+ list.unshift url
172
+ debug "#{list.length} urls now"
347
173
  end
348
-
349
- debug "+ Getting #{uri_str}"
350
- url = URI.parse(uri_str)
351
- return if url.scheme !~ /https?/
174
+ @registry[m.target] = list
175
+ end
352
176
 
353
- title = nil
354
-
355
- debug "+ connecting to #{url.host}:#{url.port}"
356
- http = @bot.httputil.get_proxy(url)
357
- http.start { |http|
358
- url.path = '/' if url.path == ''
359
-
360
- http.request_get(url.path, "User-Agent" => "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)") { |response|
361
-
362
- case response
363
- when Net::HTTPRedirection, Net::HTTPMovedPermanently then
364
- # call self recursively if this is a redirect
365
- redirect_to = response['location'] || './'
366
- debug "+ redirect location: #{redirect_to.inspect}"
367
- url = URI.join url.to_s, redirect_to
368
- debug "+ whee, redirecting to #{url.to_s}!"
369
- return get_title_for_url(url.to_s, depth-1)
370
- when Net::HTTPSuccess then
371
- if response['content-type'] =~ /^text\//
372
- # since the content is 'text/*' and is small enough to
373
- # be a webpage, retrieve the title from the page
374
- debug "+ getting #{url.request_uri}"
375
- data = read_data_from_response(response, 50000)
376
- return get_title_from_html(data)
377
- else
378
- # content doesn't have title, just display info.
379
- size = response['content-length'].gsub(/(\d)(?=\d{3}+(?:\.|$))(\d{3}\..*)?/,'\1,\2')
380
- return "[Link Info] type: #{response['content-type']}#{size ? ", size: #{size} bytes" : ""}"
381
- end
382
- when Net::HTTPClientError then
383
- return "[Link Info] Error getting link (#{response.code} - #{response.message})"
384
- when Net::HTTPServerError then
385
- return "[Link Info] Error getting link (#{response.code} - #{response.message})"
386
- else
387
- return nil
388
- end # end of "case response"
389
-
390
- } # end of request block
391
- } # end of http start block
392
-
393
- return title
394
-
395
- rescue SocketError => e
396
- return "[Link Info] Error connecting to site (#{e.message})"
177
+ def info(m, params)
178
+ escaped = URI.escape(params[:urls].to_s, OUR_UNSAFE)
179
+ urls = URI.extract(escaped)
180
+ Thread.new { handle_urls(m, urls, params[:urls].length) }
397
181
  end
398
182
 
399
- def listen(m)
400
- return unless m.kind_of?(PrivMessage)
183
+ def message(m)
401
184
  return if m.address?
402
- # TODO support multiple urls in one line
403
- if m.message =~ /(f|ht)tps?:\/\//
404
- if m.message =~ /((f|ht)tps?:\/\/.*?)(?:\s+|$)/
405
- urlstr = $1
406
- list = @registry[m.target]
407
-
408
- if @bot.config['url.display_link_info']
409
- debug "Getting title for #{urlstr}..."
410
- title = get_title_for_url urlstr
411
- if title
412
- m.reply title
413
- debug "Title found!"
414
- else
415
- debug "Title not found!"
416
- end
417
- end
418
-
419
- # check to see if this url is already listed
420
- return if list.find {|u| u.url == urlstr }
421
-
422
- url = Url.new(m.target, m.sourcenick, Time.new, urlstr)
423
- debug "#{list.length} urls so far"
424
- if list.length > @bot.config['url.max_urls']
425
- list.pop
185
+
186
+ escaped = URI.escape(m.message, OUR_UNSAFE)
187
+ urls = URI.extract(escaped, ['http', 'https'])
188
+ return if urls.empty?
189
+ Thread.new { handle_urls(m, urls) }
190
+ end
191
+
192
+ def reply_urls(opts={})
193
+ list = opts[:list]
194
+ max = opts[:max]
195
+ channel = opts[:channel]
196
+ m = opts[:msg]
197
+ return unless list and max and m
198
+ list[0..(max-1)].each do |url|
199
+ disp = "[#{url.time.strftime('%Y/%m/%d %H:%M:%S')}] <#{url.nick}> #{url.url}"
200
+ if @bot.config['url.info_on_list']
201
+ title = url.info ||
202
+ get_title_for_url(url.url,
203
+ :nick => url.nick, :channel => channel) rescue nil
204
+ # If the url info was missing and we now have some, try to upgrade it
205
+ if channel and title and not url.info
206
+ ll = @registry[channel]
207
+ debug ll
208
+ if el = ll.find { |u| u.url == url.url }
209
+ el.info = title
210
+ @registry[channel] = ll
211
+ end
426
212
  end
427
- debug "storing url #{url.url}"
428
- list.unshift url
429
- debug "#{list.length} urls now"
430
- @registry[m.target] = list
213
+ disp << " --> #{title}" if title
431
214
  end
215
+ m.reply disp, :overlong => :truncate
432
216
  end
433
217
  end
434
218
 
@@ -441,9 +225,7 @@ class UrlPlugin < Plugin
441
225
  if list.empty?
442
226
  m.reply "no urls seen yet for channel #{channel}"
443
227
  else
444
- list[0..(max-1)].each do |url|
445
- m.reply "[#{url.time.strftime('%Y/%m/%d %H:%M:%S')}] <#{url.nick}> #{url.url}"
446
- end
228
+ reply_urls :msg => m, :channel => channel, :list => list, :max => max
447
229
  end
448
230
  end
449
231
 
@@ -455,18 +237,20 @@ class UrlPlugin < Plugin
455
237
  max = 1 if max < 1
456
238
  regex = Regexp.new(string, Regexp::IGNORECASE)
457
239
  list = @registry[channel].find_all {|url|
458
- regex.match(url.url) || regex.match(url.nick)
240
+ regex.match(url.url) || regex.match(url.nick) ||
241
+ (@bot.config['url.info_on_list'] && regex.match(url.info))
459
242
  }
460
243
  if list.empty?
461
244
  m.reply "no matches for channel #{channel}"
462
245
  else
463
- list[0..(max-1)].each do |url|
464
- m.reply "[#{url.time.strftime('%Y/%m/%d %H:%M:%S')}] <#{url.nick}> #{url.url}"
465
- end
246
+ reply_urls :msg => m, :channel => channel, :list => list, :max => max
466
247
  end
467
248
  end
468
249
  end
250
+
469
251
  plugin = UrlPlugin.new
252
+ plugin.map 'urls info *urls', :action => 'info'
253
+ plugin.map 'url info *urls', :action => 'info'
470
254
  plugin.map 'urls search :channel :limit :string', :action => 'search',
471
255
  :defaults => {:limit => 4},
472
256
  :requirements => {:limit => /^\d+$/},