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,151 +1,177 @@
1
- # Author: Michael Brailsford <brailsmt@yahoo.com>
2
- # aka brailsmt
3
- # Purpose: Provide for humorous larts and praises
4
- # Copyright: 2002 Michael Brailsford. All rights reserved.
5
- # License: This plugin is licensed under the BSD license. The terms of
6
- # which follow.
1
+ #-- vim:sw=2:et
2
+ #++
7
3
  #
8
- # Redistribution and use in source and binary forms, with or without
9
- # modification, are permitted provided that the following conditions
10
- # are met:
4
+ # :title: lart/praise plugin for rbot
11
5
  #
12
- # 1. Redistributions of source code must retain the above copyright notice,
13
- # this list of conditions and the following disclaimer.
6
+ # Author:: Michael Brailsford <brailsmt@yahoo.com> aka brailsmt
7
+ # Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
14
8
  #
15
- # 2. Redistributions in binary form must reproduce the above copyright
16
- # notice, this list of conditions and the following disclaimer in the
17
- # documentation and/or other materials provided with the distribution.
9
+ # Copyright:: (C) 2002 Michael Brailsford. All rights reserved.
10
+ # Copyright:: (C) 2006 Giuseppe Bilotta. All rights reserved.
11
+ #
12
+ # License:: This plugin is licensed under the BSD license. The terms of
13
+ # which follow.
14
+ #
15
+ # Redistribution and use in source and binary forms, with or without
16
+ # modification, are permitted provided that the following conditions
17
+ # are met:
18
+ #
19
+ # 1. Redistributions of source code must retain the above copyright notice,
20
+ # this list of conditions and the following disclaimer.
21
+ #
22
+ # 2. Redistributions in binary form must reproduce the above copyright
23
+ # notice, this list of conditions and the following disclaimer in the
24
+ # documentation and/or other materials provided with the distribution.
25
+ #
26
+ # Purpose:: Provide for humorous larts and praises
18
27
 
19
28
  class LartPlugin < Plugin
20
29
 
21
- # Keep a 1:1 relation between commands and handlers
22
- @@handlers = {
23
- "lart" => "handle_lart",
24
- "praise" => "handle_praise",
25
- "addlart" => "handle_addlart",
26
- "rmlart" => "handle_rmlart",
27
- "addpraise" => "handle_addpraise",
28
- "rmpraise" => "handle_rmpraise"
29
- }
30
-
31
- def name
32
- "lart"
33
- end
34
-
35
30
  def initialize
36
- super
37
31
  @larts = Array.new
38
32
  @praises = Array.new
39
- #read in the lart and praise files
40
- if File.exists? "#{@bot.botclass}/lart/larts"
41
- IO.foreach("#{@bot.botclass}/lart/larts") { |line|
33
+ @lartfile = ""
34
+ @praisefile = ""
35
+ @changed = false
36
+ super
37
+ end
38
+
39
+ def set_language(lang)
40
+ save
41
+
42
+ # We may be on an old installation, so on the first run read non-language-specific larts
43
+ unless defined?(@oldlart)
44
+ @oldlart = "#{@bot.botclass}/lart/larts"
45
+ @oldpraise = "#{@bot.botclass}/lart/praise"
46
+ end
47
+
48
+ @lartfile.replace "#{@bot.botclass}/lart/larts-#{lang}"
49
+ @praisefile.replace "#{@bot.botclass}/lart/praises-#{lang}"
50
+ @larts.clear
51
+ @praises.clear
52
+ if File.exists? @lartfile
53
+ IO.foreach(@lartfile) { |line|
54
+ @larts << line.chomp
55
+ }
56
+ elsif File.exists? @oldlart
57
+ IO.foreach(@oldlart) { |line|
42
58
  @larts << line.chomp
43
59
  }
44
60
  end
45
- if File.exists? "#{@bot.botclass}/lart/praises"
46
- IO.foreach("#{@bot.botclass}/lart/praises") { |line|
61
+ if File.exists? @praisefile
62
+ IO.foreach(@praisefile) { |line|
63
+ @praises << line.chomp
64
+ }
65
+ elsif File.exists? @oldpraise
66
+ IO.foreach(@oldpraise) { |line|
47
67
  @praises << line.chomp
48
68
  }
49
69
  end
50
- end
51
-
52
- def cleanup
70
+ @changed = false
53
71
  end
54
72
 
55
73
  def save
74
+ return unless @changed
56
75
  Dir.mkdir("#{@bot.botclass}/lart") if not FileTest.directory? "#{@bot.botclass}/lart"
57
76
  # TODO implement safe saving here too
58
- File.open("#{@bot.botclass}/lart/larts", "w") { |file|
77
+ Utils.safe_save(@lartfile) { |file|
59
78
  file.puts @larts
60
79
  }
61
- File.open("#{@bot.botclass}/lart/praises", "w") { |file|
80
+ Utils.safe_save(@praisefile) { |file|
62
81
  file.puts @praises
63
82
  }
64
- end
65
-
66
- def privmsg(m)
67
- if not m.params
68
- m.reply "What a crazy fool! Did you mean |help stats?"
69
- return
70
- end
71
-
72
- meth = self.method(@@handlers[m.plugin])
73
- meth.call(m) if(@bot.auth.allow?(m.plugin, m.source, m.replyto))
83
+ @changed = false
74
84
  end
75
85
 
76
86
  def help(plugin, topic="")
77
87
  "Lart: The lart plugin allows you to lart/praise someone in the channel. You can also add new larts and new praises as well as delete them. For the curious, LART is an acronym for Luser Attitude Readjustment Tool. Usage: lart <who> [<reason>] -- larts <who> for <reason>. praise <who> [<reason>] -- praises <who> for <reason>. [add|rm][lart|praise] -- Add or remove a lart or praise."
78
88
  end
79
89
 
80
- # The following are command handler
81
-
82
- def handle_lart(m)
83
- for_idx = m.params =~ /\s+\bfor\b/
84
- if for_idx
85
- nick = m.params[0, for_idx]
86
- else
87
- nick = m.params
88
- end
90
+ def handle_lart(m, params)
89
91
  lart = @larts[get_msg_idx(@larts.length)]
90
- if lart == nil
92
+ if not lart
91
93
  m.reply "I dunno any larts"
92
94
  return
93
95
  end
94
- if nick == @bot.nick
95
- lart = replace_who lart, m.sourcenick
96
- lart << " for trying to make me lart myself"
97
- else
98
- lart = replace_who lart, nick
99
- lart << m.params[for_idx, m.params.length] if for_idx
96
+ who = params[:who].to_s
97
+ reason = params[:why]
98
+ if who == "me"
99
+ who = m.sourcenick
100
100
  end
101
+ if who == @bot.nick
102
+ who = m.sourcenick
103
+ reason = "for trying to make me lart myself"
104
+ end
105
+ lart = replace_who lart, who
106
+ lart << " #{reason}" unless reason.empty?
101
107
 
102
- @bot.action m.replyto, lart
108
+ m.act lart
103
109
  end
104
110
 
105
- def handle_praise(m)
106
- for_idx = m.params =~ /\s+\bfor\b/
107
- if for_idx
108
- nick = m.params[0, for_idx]
109
- else
110
- nick = m.params
111
- end
111
+ def handle_praise(m, params)
112
112
  praise = @praises[get_msg_idx(@praises.length)]
113
113
  if not praise
114
114
  m.reply "I dunno any praises"
115
115
  return
116
116
  end
117
-
118
- if nick == m.sourcenick
119
- praise = @larts[get_msg_idx(@larts.length)]
120
- praise = replace_who praise, nick
121
- else
122
- praise = replace_who praise, nick
123
- praise << m.params.gsub("#{nick}", "")
117
+ who = params[:who].to_s
118
+ reason = params[:why]
119
+ if who == m.sourcenick || who == "me"
120
+ params[:who] = m.sourcenick
121
+ params[:why] = "for praising himself"
122
+ handle_lart(m, params)
123
+ return
124
124
  end
125
+ praise = replace_who praise, who
126
+ praise << " #{reason}" unless reason.empty?
125
127
 
126
- @bot.action m.replyto, praise
128
+ m.act praise
127
129
  end
128
130
 
129
- def handle_addlart(m)
130
- @larts << m.params
131
+ def handle_addlart(m, params)
132
+ @larts << params[:lart].to_s
133
+ @changed = true
131
134
  m.okay
132
135
  end
133
136
 
134
- def handle_rmlart(m)
135
- @larts.delete m.params
137
+ def handle_rmlart(m, params)
138
+ @larts.delete params[:lart].to_s
139
+ @changed = true
136
140
  m.okay
137
141
  end
138
142
 
139
- def handle_addpraise(m)
140
- @praises << m.params
143
+ def handle_listlart(m, params)
144
+ rx = Regexp.new(params[:lart].to_s, true)
145
+ list = @larts.grep(rx)
146
+ unless list.empty?
147
+ m.reply list.join(" | "), :split_at => /\s+\|\s+/
148
+ else
149
+ m.reply "no lart found matching #{params[:lart]}"
150
+ end
151
+ end
152
+
153
+ def handle_addpraise(m, params)
154
+ @praises << params[:praise].to_s
155
+ @changed = true
141
156
  m.okay
142
157
  end
143
158
 
144
- def handle_rmpraise(m)
145
- @praises.delete m.params
159
+ def handle_rmpraise(m, params)
160
+ @praises.delete params[:praise].to_s
161
+ @changed = true
146
162
  m.okay
147
163
  end
148
164
 
165
+ def handle_listpraise(m, params)
166
+ rx = Regexp.new(params[:praise].to_s, true)
167
+ list = @praises.grep(rx)
168
+ unless list.empty?
169
+ m.reply list.join(" | "), :split_at => /\s+\|\s+/
170
+ else
171
+ m.reply "no praise found matching #{params[:praise]}"
172
+ end
173
+ end
174
+
149
175
  # The following are utils for larts/praises
150
176
  def replace_who(msg, nick)
151
177
  msg.gsub(/<who>/i, "#{nick}")
@@ -156,12 +182,17 @@ class LartPlugin < Plugin
156
182
  end
157
183
 
158
184
  end
185
+
159
186
  plugin = LartPlugin.new
160
- plugin.register("lart")
161
- plugin.register("praise")
162
187
 
163
- plugin.register("addlart")
164
- plugin.register("addpraise")
188
+ plugin.map "lart *who [*why]", :requirements => { :why => /(?:for|because)\s+.*/ }, :action => :handle_lart
189
+ plugin.map "praise *who [*why]", :requirements => { :why => /(?:for|because)\s+.*/ }, :action => :handle_praise
190
+
191
+ plugin.map "addlart *lart", :action => :handle_addlart
192
+ plugin.map "addpraise *praise", :action => :handle_addpraise
193
+
194
+ plugin.map "rmlart *lart", :action => :handle_rmlart
195
+ plugin.map "rmpraise *praise", :action => :handle_rmpraise
165
196
 
166
- plugin.register("rmlart")
167
- plugin.register("rmpraise")
197
+ plugin.map "listlart *lart", :action => :handle_listlart
198
+ plugin.map "listpraise *praise", :action => :handle_listpraise
@@ -1,25 +1,434 @@
1
- require 'open-uri'
1
+ #-- vim:sw=2:et
2
+ #++
3
+ #
4
+ # :title: lastfm plugin for rbot
5
+ #
6
+ # Author:: Jeremy Voorhis
7
+ # Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
8
+ # Author:: Casey Link <unnamedrambler@gmail.com>
9
+ #
10
+ # Copyright:: (C) 2005 Jeremy Voorhis
11
+ # Copyright:: (C) 2007 Giuseppe Bilotta
12
+ # Copyright:: (C) 2008 Casey Link
13
+ #
14
+ # License:: GPL v2
2
15
 
3
- # plugin submitted by Jeremy Voorhis (jvoorhis)
16
+ require 'rexml/document'
17
+ require 'cgi'
18
+
19
+ class ::LastFmEvent
20
+ def initialize(hash)
21
+ @url = hash[:url]
22
+ @date = hash[:date]
23
+ @location = hash[:location]
24
+ @description = hash[:description]
25
+ @attendance = hash[:attendance]
26
+
27
+ @artists = hash[:artists]
28
+
29
+ if @artists.length > 10 #more than 10 artists and it floods
30
+ diff = @artists.length - 10
31
+ @artist_string = Bold + @artists[0..10].join(', ') + Bold
32
+ @artist_string << _(" and %{n} more...") % {:n => diff}
33
+ else
34
+ @artist_string = Bold + @artists.join(', ') + Bold
35
+ end
36
+ end
37
+
38
+ def compact_display
39
+ if @attendance
40
+ return "%s %s @ %s (%s attending) %s" % [@date.strftime("%a %b, %d %Y"), @artist_string, @location, @attendance, @url]
41
+ end
42
+ return "%s %s @ %s %s" % [@date.strftime("%a %b, %d %Y"), @artist_string, @location, @url]
43
+ end
44
+ alias :to_s :compact_display
45
+
46
+ end
4
47
 
5
48
  class LastFmPlugin < Plugin
49
+ include REXML
50
+ Config.register Config::IntegerValue.new('lastfm.max_events',
51
+ :default => 25, :validate => Proc.new{|v| v > 1},
52
+ :desc => "Maximum number of events to display.")
53
+ Config.register Config::IntegerValue.new('lastfm.default_events',
54
+ :default => 3, :validate => Proc.new{|v| v > 1},
55
+ :desc => "Default number of events to display.")
56
+
57
+ APIKEY = "b25b959554ed76058ac220b7b2e0a026"
58
+ APIURL = "http://ws.audioscrobbler.com/2.0/?api_key=#{APIKEY}&"
59
+
60
+ def initialize
61
+ super
62
+ class << @registry
63
+ def store(val)
64
+ val
65
+ end
66
+ def restore(val)
67
+ val
68
+ end
69
+ end
70
+ end
71
+
6
72
  def help(plugin, topic="")
7
- "lastfm <function> <user> => lastfm data for <user> on last.fm where <function> in [recenttracks, topartists, topalbums, toptracks, tags, friends, neighbors]"
73
+ case (topic.intern rescue nil)
74
+ when :event, :events
75
+ _("lastfm [<num>] events in <location> => show information on events in or near <location>. lastfm [<num>] events by <artist/group> => show information on events by <artist/group>. The number of events <num> that can be displayed is optional, defaults to %{d} and cannot be higher than %{m}") % {:d => @bot.config['lastfm.default_events'], :m => @bot.config['lastfm.max_events']}
76
+ when :artist
77
+ _("lastfm artist <name> => show information on artist <name> from last.fm")
78
+ when :album
79
+ _("lastfm album <name> => show information on album <name> from last.fm [not implemented yet]")
80
+ when :track
81
+ _("lastfm track <name> => search tracks matching <name> on last.fm")
82
+ when :now, :np
83
+ _("lastfm now [<user>] => show the now playing track from last.fm. np [<user>] does the same.")
84
+ when :set
85
+ _("lastfm set nick <user> => associate your current irc nick with a last.fm user. lastfm set verb <present> <past> => set your preferred now playing verb. default \"listening\" and \"listened\".")
86
+ when :who
87
+ _("lastfm who [<nick>] => show who <nick> is at last.fm. if <nick> is empty, show who you are at lastfm.")
88
+ when :compare
89
+ _("lastfm compare <nick1> <nick2> => show musical taste compatibility between nick1 and nick2.")
90
+ else
91
+ _("lastfm [<user>] => show your or <user>'s now playing track at lastfm. np [<user>] => same as 'lastfm'. other topics: events, artist, album, track, now, set, who, compare")
92
+ end
8
93
  end
9
94
 
10
- def do_lastfm (m, params)
11
- begin
12
- if params[:action] == "neighbors" || params[:action] == "neighbours" then
13
- params[:action]="neighbours"
95
+ def find_events(m, params)
96
+ num = params[:num] || @bot.config['lastfm.default_events']
97
+ num = num.to_i.clip(1, @bot.config['lastfm.max_events'])
98
+
99
+ location = artist = nil
100
+ location = params[:location].to_s if params[:location]
101
+ artist = params[:who].to_s if params[:who]
102
+
103
+ uri = nil
104
+ if artist == nil
105
+ uri = "#{APIURL}method=geo.getevents&location=#{CGI.escape location}"
106
+ else
107
+ uri = "#{APIURL}method=artist.getevents&artist=#{CGI.escape artist}"
108
+ end
109
+ xml = @bot.httputil.get_response(uri)
110
+
111
+ doc = Document.new xml.body
112
+ if xml.class == Net::HTTPInternalServerError
113
+ if doc.root and doc.root.attributes["status"] == "failed"
114
+ m.reply doc.root.elements["error"].text
115
+ else
116
+ m.reply _("Could not retrieve events")
117
+ end
118
+ end
119
+ disp_events = Array.new
120
+ events = Array.new
121
+ doc.root.elements.each("events/event"){ |e|
122
+ h = {}
123
+ h[:title] = e.elements["title"].text
124
+ venue = e.elements["venue"].elements["name"].text
125
+ city = e.elements["venue"].elements["location"].elements["city"].text
126
+ country = e.elements["venue"].elements["location"].elements["country"].text
127
+ h[:location] = Underline + venue + Underline + " #{Bold + city + Bold}, #{country}"
128
+ date = e.elements["startDate"].text.split
129
+ h[:date] = Time.utc(date[3].to_i, date[2], date[1].to_i)
130
+ h[:desc] = e.elements["description"].text
131
+ h[:url] = e.elements["url"].text
132
+ e.detect {|node|
133
+ if node.kind_of? Element and node.attributes["name"] == "attendance" then
134
+ h[:attendance] = node.text
135
+ end
136
+ }
137
+ artists = Array.new
138
+ e.elements.each("artists/artist"){ |a|
139
+ artists << a.text
140
+ }
141
+ h[:artists] = artists
142
+ events << LastFmEvent.new(h)
143
+ }
144
+ events[0...num].each { |event|
145
+ disp_events << event.to_s
146
+ }
147
+ m.reply disp_events.join(' | '), :split_at => /\s+\|\s+/
148
+
149
+ end
150
+
151
+ def tasteometer(m, params)
152
+ opts = { :cache => false }
153
+ user1 = params[:user1].to_s
154
+ user2 = params[:user2].to_s
155
+ xml = @bot.httputil.get_response("#{APIURL}method=tasteometer.compare&type1=user&type2=user&value1=#{CGI.escape user1}&value2=#{CGI.escape user2}", opts)
156
+ doc = Document.new xml.body
157
+ unless doc
158
+ m.reply _("last.fm parsing failed")
159
+ return
160
+ end
161
+ if xml.class == Net::HTTPInternalServerError
162
+ if doc.root.elements["error"].attributes["code"] == "7" then
163
+ error = doc.root.elements["error"].text
164
+ error.match(/Invalid username: \[(.*)\]/);
165
+ if @registry.has_key? $1 and not params[:recurs]
166
+ if user1 == $1
167
+ params[:user1] = @registry[ $1 ]
168
+ elsif user2 == $1
169
+ params[:user2] = @registry[ $1 ]
170
+ end
171
+ params[:recurs] = true
172
+ tasteometer(m, params)
173
+ else
174
+ m.reply _("%{u} doesn't exist at last.fm. Perhaps you need to: lastfm set <username>") % {:u => baduser}
175
+ return
176
+ end
177
+ else
178
+ m.reply _("Bad: %{e}") % {:e => doc.root.element["error"].text}
179
+ return
180
+ end
181
+ end
182
+ now = artist = track = albumtxt = date = nil
183
+ score = doc.root.elements["comparison/result/score"].text.to_f
184
+ rating = nil
185
+ case
186
+ when score >= 0.9
187
+ rating = _("Super")
188
+ when score >= 0.7
189
+ rating = _("Very High")
190
+ when score >= 0.5
191
+ rating = _("High")
192
+ when score >= 0.3
193
+ rating = _("Medium")
194
+ when score >= 0.1
195
+ rating = _("Low")
196
+ else
197
+ rating = _("Very Low")
198
+ end
199
+ m.reply _("%{a}'s and %{b}'s musical compatibility rating is: %{r}") % {:a => user1, :b => user2, :r => rating}
200
+ end
201
+
202
+ def now_playing(m, params)
203
+ opts = { :cache => false }
204
+ user = nil
205
+ if params[:who]
206
+ user = params[:who].to_s
207
+ elsif @registry.has_key? m.sourcenick
208
+ user = @registry[ m.sourcenick ]
209
+ else
210
+ user = m.sourcenick
211
+ end
212
+ xml = @bot.httputil.get_response("#{APIURL}method=user.getrecenttracks&user=#{CGI.escape user}", opts)
213
+ doc = Document.new xml.body
214
+ unless doc
215
+ m.reply _("last.fm parsing failed")
216
+ return
217
+ end
218
+ if xml.class == Net::HTTPBadRequest
219
+ if doc.root.elements["error"].text == "Invalid user name supplied" then
220
+ if @registry.has_key? user and not params[:recurs]
221
+ params[:who] = @registry[ user ]
222
+ params[:recurs] = true
223
+ now_playing(m, params)
224
+ else
225
+ m.reply "#{user} doesn't exist at last.fm. Perhaps you need to: lastfm set <username>"
226
+ return
227
+ end
228
+ else
229
+ m.reply _("Error %{e}") % {:e => doc.root.element["error"].text}
230
+ return
14
231
  end
15
- data = open("http://ws.audioscrobbler.com/1.0/user/#{params[:user]}/#{params[:action]}.txt")
16
- m.reply "#{params[:action]} for #{params[:user]}:"
17
- m.reply data.to_a[0..3].map{|l| l.split(',')[-1].chomp}.join(", ")
232
+ end
233
+ now = artist = track = albumtxt = date = nil
234
+ unless doc.root.elements[1].has_elements?
235
+ m.reply _("%{u} hasn't played anything recently") % {:u => user}
236
+ return
237
+ end
238
+ first = doc.root.elements[1].elements[1]
239
+ now = first.attributes["nowplaying"]
240
+ artist = first.elements["artist"].text
241
+ track = first.elements["name"].text
242
+ albumtxt = first.elements["album"].text
243
+ album = ""
244
+ if albumtxt
245
+ year = get_album(artist, albumtxt)[2]
246
+ album = "[#{albumtxt}, #{year}] " if year
247
+ end
248
+ date = first.elements["date"].attributes["uts"]
249
+ past = Time.at(date.to_i)
250
+ if now == "true"
251
+ verb = _("listening")
252
+ if @registry.has_key? "#{m.sourcenick}_verb_present"
253
+ verb = @registry["#{m.sourcenick}_verb_present"]
254
+ end
255
+ m.reply _("%{u} is %{v} to \"%{t}\" by %{a} %{b}") % {:u => user, :v => verb, :t => track, :a => artist, :b => album}
256
+ else
257
+ verb = _("listened")
258
+ if @registry.has_key? "#{m.sourcenick}_verb_past"
259
+ verb = @registry["#{m.sourcenick}_verb_past"]
260
+ end
261
+ ago = Utils.timeago(past)
262
+ m.reply _("%{u} %{v} to \"%{t}\" by %{a} %{b}%{p}") % {:u => user, :v => verb, :t => track, :a => artist, :b => album, :p => ago}
263
+ end
264
+ end
265
+
266
+ def find_artist(m, params)
267
+ xml = @bot.httputil.get("#{APIURL}method=artist.getinfo&artist=#{CGI.escape params[:artist].to_s}")
268
+ unless xml
269
+ m.reply _("I had problems getting info for %{a}.") % {:a => params[:artist]}
270
+ return
271
+ end
272
+ doc = Document.new xml
273
+ unless doc
274
+ m.reply _("last.fm parsing failed")
275
+ return
276
+ end
277
+ first = doc.root.elements["artist"]
278
+ artist = first.elements["name"].text
279
+ playcount = first.elements["stats"].elements["plays"].text
280
+ listeners = first.elements["stats"].elements["listeners"].text
281
+ summary = first.elements["bio"].elements["summary"].text
282
+ m.reply _("%{b}%{a}%{b} has been played %{c} times and is being listened to by %{l} people.") % {:b => Bold, :a => artist, :c => playcount, :l => listeners}
283
+ m.reply summary.ircify_html
284
+ end
285
+
286
+ def find_track(m, params)
287
+ track = params[:track].to_s
288
+ xml = @bot.httputil.get("#{APIURL}method=track.search&track=#{CGI.escape track}")
289
+ unless xml
290
+ m.reply _("I had problems getting info for %{a}.") % {:a => track}
291
+ return
292
+ end
293
+ debug xml
294
+ doc = Document.new xml
295
+ unless doc
296
+ m.reply _("last.fm parsing failed")
297
+ return
298
+ end
299
+ debug doc.root
300
+ results = doc.root.elements["results/opensearch:totalResults"].text.to_i rescue 0
301
+ if results > 0
302
+ begin
303
+ hits = []
304
+ doc.root.each_element("results/trackmatches/track") do |track|
305
+ hits << _("%{bold}%{t}%{bold} by %{bold}%{a}%{bold} (%{n} listeners)") % {
306
+ :t => track.elements["name"].text,
307
+ :a => track.elements["artist"].text,
308
+ :n => track.elements["listeners"].text,
309
+ :bold => Bold
310
+ }
311
+ end
312
+ m.reply hits.join(' -- '), :split_at => ' -- '
313
+ rescue
314
+ error $!
315
+ m.reply _("last.fm parsing failed")
316
+ end
317
+ else
318
+ m.reply _("track %{a} not found") % {:a => track}
319
+ end
320
+ end
321
+
322
+ def get_album(artist, album)
323
+ xml = @bot.httputil.get("#{APIURL}method=album.getinfo&artist=#{CGI.escape artist}&album=#{CGI.escape album}")
324
+ unless xml
325
+ return [_("I had problems getting album info")]
326
+ end
327
+ doc = Document.new xml
328
+ unless doc
329
+ return [_("last.fm parsing failed")]
330
+ end
331
+ album = date = playcount = artist = date = year = nil
332
+ first = doc.root.elements["album"]
333
+ artist = first.elements["artist"].text
334
+ playcount = first.elements["playcount"].text
335
+ album = first.elements["name"].text
336
+ date = first.elements["releasedate"].text
337
+ unless date.strip.length < 2
338
+ year = date.strip.split[2].chop
339
+ end
340
+ result = [artist, album, year, playcount]
341
+ return result
342
+ end
343
+
344
+ def find_album(m, params)
345
+ album = get_album(params[:artist].to_s, params[:album].to_s)
346
+ if album.length == 1
347
+ m.reply _("I couldn't locate: \"%{a}\" by %{r}") % {:a => params[:album], :r => params[:artist]}
348
+ return
349
+ end
350
+ year = "(#{album[2]}) " unless album[2] == nil
351
+ m.reply _("The album \"%{a}\" by %{r} %{y}has been played %{c} times.") % {:a => album[1], :r => album[0], :y => year, :c => album[3]}
352
+ end
353
+
354
+ def set_user(m, params)
355
+ user = params[:who].to_s
356
+ nick = m.sourcenick
357
+ @registry[ nick ] = user
358
+ m.reply _("Ok, I'll remember that %{n} is %{u} at last.fm") % {:n => nick, :u => user}
359
+ end
360
+
361
+ def set_verb(m, params)
362
+ past = params[:past].to_s
363
+ present = params[:present].to_s
364
+ key = "#{m.sourcenick}_verb_"
365
+ @registry[ "#{key}past" ] = past
366
+ @registry[ "#{key}present" ] = present
367
+ m.reply _("Ok, I'll remember that %{n} prefers %{r} and %{p}.") % {:n => m.sourcenick, :p => past, :r => present}
368
+ end
369
+
370
+ def get_user(m, params)
371
+ nick = ""
372
+ if params[:who]
373
+ nick = params[:who].to_s
374
+ else
375
+ nick = m.sourcenick
376
+ end
377
+ if @registry.has_key? nick
378
+ user = @registry[ nick ]
379
+ m.reply "#{nick} is #{user} at last.fm"
380
+ else
381
+ m.reply _("Sorry, I don't know who %{n} is at last.fm perhaps you need to: lastfm set <username>") % {:n => nick}
382
+ end
383
+ end
384
+
385
+ # TODO this user data retrieval should be upgraded to API 2.0 but it would need separate parsing
386
+ # for each dataset, or almost
387
+ def lastfm(m, params)
388
+ action = params[:action].intern
389
+ action = :neighbours if action == :neighbors
390
+ action = :recenttracks if action == :recentracks
391
+ action = :topalbums if action == :topalbum
392
+ action = :topartists if action == :topartist
393
+ action = :toptags if action == :toptag
394
+ user = nil
395
+ if params[:user] then
396
+ user = params[:user].to_s
397
+ elsif @registry.has_key? m.sourcenick
398
+ user = @registry[ m.sourcenick ]
399
+ else
400
+ # m.reply "I don't know who you are on last.fm. Use 'lastfm set username' to identify yourself."
401
+ # return
402
+ user = m.sourcenick
403
+ end
404
+ begin
405
+ data = @bot.httputil.get("http://ws.audioscrobbler.com/1.0/user/#{user}/#{action}.txt")
406
+ m.reply "#{action} for #{user}:"
407
+ m.reply data.to_a[0..3].map{|l| l.split(',',2)[-1].chomp}.join(", ")
18
408
  rescue
19
- m.reply "could not find #{params[:action]} for #{params[:user]} (is #{params[:user]} a user?)"
409
+ m.reply "could not find #{action} for #{user} (is #{user} a user?). perhaps you need to: lastfm set <username>"
20
410
  end
21
411
  end
22
412
  end
23
413
 
24
414
  plugin = LastFmPlugin.new
25
- plugin.map 'lastfm :action :user', :action => 'do_lastfm'
415
+ plugin.map 'lastfm [:num] event[s] in *location', :action => :find_events, :requirements => { :num => /\d+/ }, :thread => true
416
+ plugin.map 'lastfm [:num] event[s] by *who', :action => :find_events, :requirements => { :num => /\d+/ }, :thread => true
417
+ plugin.map 'lastfm [:num] event[s] [for] *who', :action => :find_events, :requirements => { :num => /\d+/ }, :thread => true
418
+ plugin.map 'lastfm now :who', :action => :now_playing, :thread => true
419
+ plugin.map 'lastfm now', :action => :now_playing, :thread => true
420
+ plugin.map 'np :who', :action => :now_playing, :thread => true
421
+ plugin.map 'lastfm artist *artist', :action => :find_artist, :thread => true
422
+ plugin.map 'lastfm album *album [by *artist]', :action => :find_album
423
+ plugin.map 'lastfm track *track', :action => :find_track, :thread => true
424
+ plugin.map 'lastfm set nick :who', :action => :set_user, :thread => true
425
+ plugin.map 'lastfm set verb :present :past', :action => :set_verb, :thread => true
426
+ plugin.map 'lastfm who :who', :action => :get_user, :thread => true
427
+ plugin.map 'lastfm who', :action => :get_user, :thread => true
428
+ plugin.map 'lastfm compare :user1 :user2', :action => :tasteometer, :thread => true
429
+ plugin.map 'np', :action => :now_playing, :thread => true
430
+ plugin.map "lastfm [user] :action [:user]", :thread => true,
431
+ :requirements => { :action =>
432
+ /^(?:events|friends|neighbou?rs|playlists|recent?tracks|top(?:album|artist|tag)s?|weekly(?:album|artist|track)chart|weeklychartlist)$/
433
+ }
434
+ plugin.map "lastfm [:who]", :action => :now_playing, :thread => true