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,9 +1,64 @@
1
- module Irc
2
- module Language
1
+ #-- vim:sw=2:et
2
+ #++
3
+ #
4
+ # :title: Language module for rbot
5
+ #
6
+ # This module takes care of language handling for rbot:
7
+ # setting the core.language value, loading the appropriate
8
+ # .lang file etc.
3
9
 
10
+ module Irc
11
+ class Bot
4
12
  class Language
5
- BotConfig.register BotConfigEnumValue.new('core.language',
6
- :default => "english", :wizard => true,
13
+
14
+ # This constant hash holds the mapping
15
+ # from long language names to the usual POSIX
16
+ # locale specifications
17
+ Lang2Locale = {
18
+ :english => 'en',
19
+ :british_english => 'en_GB',
20
+ :american_english => 'en_US',
21
+ :italian => 'it',
22
+ :french => 'fr',
23
+ :german => 'de',
24
+ :dutch => 'nl',
25
+ :japanese => 'ja',
26
+ :russian => 'ru',
27
+ :traditional_chinese => 'zh_TW',
28
+ :simplified_chinese => 'zh_CN'
29
+ }
30
+ # On WIN32 it appears necessary to have ".UTF-8" explicitly for gettext to use UTF-8
31
+ Lang2Locale.each_value {|v| v.replace(v + '.UTF-8')}
32
+
33
+ # Return the shortest language for the current
34
+ # GetText locale
35
+ def Language.from_locale
36
+ return 'english' unless defined?(GetText)
37
+ lang = locale.language
38
+ if locale.country
39
+ str = lang + "_#{locale.country}"
40
+ if Lang2Locale.value?(str)
41
+ # Get the shortest key in Lang2Locale which maps to the given lang_country
42
+ lang_str = Lang2Locale.select { |k, v| v == str }.transpose.first.map { |v| v.to_s }.sort { |a, b| a.length <=> b.length }.first
43
+ if File.exist?(File.join(Config::datadir, "languages/#{lang_str}.lang"))
44
+ return lang_str
45
+ end
46
+ end
47
+ end
48
+ # lang_country didn't work, let's try lan
49
+ if Lang2Locale.value?(lang)
50
+ # Get the shortest key in Lang2Locale which maps to the given lang
51
+ lang_str = Lang2Locale.select { |k, v| v == lang }.transpose.first.map { |v| v.to_s }.sort { |a, b| a.length <=> b.length }.first
52
+ if File.exist?(File.join(Config::datadir, "/languages/#{lang_str}.lang"))
53
+ return lang_str
54
+ end
55
+ end
56
+ # all else fail, return 'english'
57
+ return 'english'
58
+ end
59
+
60
+ Config.register Config::EnumValue.new('core.language',
61
+ :default => Irc::Bot::Language.from_locale, :wizard => true,
7
62
  :values => Proc.new{|bot|
8
63
  Dir.new(Config::datadir + "/languages").collect {|f|
9
64
  f =~ /\.lang$/ ? f.gsub(/\.lang$/, "") : nil
@@ -12,18 +67,41 @@ module Language
12
67
  :on_change => Proc.new {|bot, v| bot.lang.set_language v},
13
68
  :desc => "Which language file the bot should use")
14
69
 
15
- def initialize(language)
70
+ def initialize(bot, language)
71
+ @bot = bot
16
72
  set_language language
17
73
  end
74
+ attr_reader :language
18
75
 
19
76
  def set_language(language)
20
- file = Config::datadir + "/languages/#{language}.lang"
77
+ lang_str = language.to_s.downcase.gsub(/\s+/,'_')
78
+ lang_sym = lang_str.intern
79
+ if defined?(GetText) and Lang2Locale.key?(lang_sym)
80
+ setlocale(Lang2Locale[lang_sym])
81
+ debug "locale set to #{locale}"
82
+ rbot_gettext_debug
83
+ else
84
+ warning "Unable to set locale, unknown language #{language} (#{lang_str})"
85
+ end
86
+
87
+ file = Config::datadir + "/languages/#{lang_str}.lang"
21
88
  unless(FileTest.exist?(file))
22
- raise "no such language: #{language} (no such file #{file})"
89
+ raise "no such language: #{lang_str} (no such file #{file})"
23
90
  end
24
- @language = language
91
+ @language = lang_str
25
92
  @file = file
26
93
  scan
94
+ return if @bot.plugins.nil?
95
+ @bot.plugins.core_modules.each { |p|
96
+ if p.respond_to?('set_language')
97
+ p.set_language(@language)
98
+ end
99
+ }
100
+ @bot.plugins.plugins.each { |p|
101
+ if p.respond_to?('set_language')
102
+ p.set_language(@language)
103
+ end
104
+ }
27
105
  end
28
106
 
29
107
  def scan
@@ -0,0 +1,154 @@
1
+ #-- vim:sw=2:et
2
+ #++
3
+ #
4
+ # :title: GetText interface for rbot
5
+ #
6
+ # Load gettext module and provide fallback in case of failure
7
+
8
+ class GetTextVersionError < Exception
9
+ end
10
+
11
+ # try to load gettext, or provide fake getttext functions
12
+ begin
13
+ require 'gettext/version'
14
+
15
+ gettext_version = GetText::VERSION.split('.').map {|n| n.to_i}
16
+ include Comparable # for Array#>=
17
+ unless gettext_version >= [1, 8, 0]
18
+ raise GetTextVersionError, "Unsupported ruby-gettext version installed: #{gettext_version.join '.'}; supported versions are 1.8.0 and above"
19
+ end
20
+
21
+ require 'gettext'
22
+
23
+ include GetText
24
+
25
+ add_default_locale_path(File.join(Irc::Bot::Config.datadir, "../locale/%{locale}/LC_MESSAGES/%{name}.mo"))
26
+
27
+ if GetText.respond_to? :cached=
28
+ GetText.cached = false
29
+ else
30
+ warning 'This version of ruby-gettext does not support non-cached mode; mo files are not reloaded when setting language'
31
+ end
32
+ bindtextdomain 'rbot'
33
+
34
+ module GetText
35
+ # patch for ruby-gettext 1.8.0 up to 1.10.0 (and more?) to cope with anonymous
36
+ # modules used by rbot
37
+ # FIXME remove the patch when ruby-gettext is fixed, or rbot switches to named modules
38
+ if !instance_methods.include?('orig_bound_targets')
39
+ alias :orig_bound_targets :bound_targets
40
+ end
41
+ def bound_targets(*a) # :nodoc:
42
+ bt = orig_bound_targets(*a) rescue []
43
+ bt.empty? ? orig_bound_targets(Object) : bt
44
+ end
45
+
46
+ require 'stringio'
47
+
48
+ # This method is used to output debug information on the GetText
49
+ # textdomain, and it's called by the language setting routines
50
+ # in rbot
51
+ def rbot_gettext_debug
52
+ begin
53
+ gettext_info = StringIO.new
54
+ current_textdomain_info(:out => gettext_info) # fails sometimes
55
+ rescue Exception
56
+ warning "gettext failed to set call textdomain info. maybe an mo file doesn't exist for your locale."
57
+ ensure
58
+ gettext_info.string.each_line { |l| debug l}
59
+ end
60
+ end
61
+ end
62
+
63
+ log "gettext loaded"
64
+
65
+ rescue LoadError, GetTextVersionError
66
+ warning "failed to load ruby-gettext package: #{$!}; translations are disabled"
67
+
68
+ # undefine GetText, in case it got defined because the error was caused by a
69
+ # wrong version
70
+ if defined?(GetText)
71
+ Object.module_eval { remove_const("GetText") }
72
+ end
73
+
74
+ # dummy functions that return msg_id without translation
75
+ def _(s)
76
+ s
77
+ end
78
+
79
+ def N_(s)
80
+ s
81
+ end
82
+
83
+ def n_(s_single, s_plural, n)
84
+ n > 1 ? s_plural : s_single
85
+ end
86
+
87
+ def Nn_(s_single, s_plural)
88
+ n_(s_single, s_plural)
89
+ end
90
+
91
+ def s_(*args)
92
+ args[0]
93
+ end
94
+
95
+ def bindtextdomain_to(*args)
96
+ end
97
+
98
+ # the following extension to String#% is from ruby-gettext's string.rb file.
99
+ # it needs to be included in the fallback since the source already use this form
100
+
101
+ =begin
102
+ string.rb - Extension for String.
103
+
104
+ Copyright (C) 2005,2006 Masao Mutoh
105
+
106
+ You may redistribute it and/or modify it under the same
107
+ license terms as Ruby.
108
+ =end
109
+
110
+ # Extension for String class.
111
+ #
112
+ # String#% method which accept "named argument". The translator can know
113
+ # the meaning of the msgids using "named argument" instead of %s/%d style.
114
+ class String
115
+ alias :_old_format_m :% # :nodoc:
116
+
117
+ # call-seq:
118
+ # %(arg)
119
+ # %(hash)
120
+ #
121
+ # Format - Uses str as a format specification, and returns the result of applying it to arg.
122
+ # If the format specification contains more than one substitution, then arg must be
123
+ # an Array containing the values to be substituted. See Kernel::sprintf for details of the
124
+ # format string. This is the default behavior of the String class.
125
+ # * arg: an Array or other class except Hash.
126
+ # * Returns: formatted String
127
+ #
128
+ # (e.g.) "%s, %s" % ["Masao", "Mutoh"]
129
+ #
130
+ # Also you can use a Hash as the "named argument". This is recommanded way for Ruby-GetText
131
+ # because the translators can understand the meanings of the msgids easily.
132
+ # * hash: {:key1 => value1, :key2 => value2, ... }
133
+ # * Returns: formatted String
134
+ #
135
+ # (e.g.) "%{firstname}, %{familyname}" % {:firstname => "Masao", :familyname => "Mutoh"}
136
+ def %(args)
137
+ if args.kind_of?(Hash)
138
+ ret = dup
139
+ args.each {|key, value|
140
+ ret.gsub!(/\%\{#{key}\}/, value.to_s)
141
+ }
142
+ ret
143
+ else
144
+ ret = gsub(/%\{/, '%%{')
145
+ begin
146
+ ret._old_format_m(args)
147
+ rescue ArgumentError
148
+ $stderr.puts " The string:#{ret}"
149
+ $stderr.puts " args:#{args.inspect}"
150
+ end
151
+ end
152
+ end
153
+ end
154
+ end
@@ -0,0 +1,162 @@
1
+ module Irc
2
+ class NetmaskDb
3
+ # helper backend class: generic nested radix tree
4
+ class Tree
5
+ attr_reader :pre, :chi
6
+
7
+ def initialize(pre = '', chi = Hash.new)
8
+ @pre = pre
9
+ @chi = chi
10
+ end
11
+
12
+ def add(val, *prefs)
13
+ str = prefs.shift or raise 'empty prefs'
14
+ @pre = str.dup if @chi.empty?
15
+
16
+ n = 0
17
+ @pre.size.times do
18
+ break if @pre[n] != str[n]
19
+ n += 1
20
+ end
21
+
22
+ rest = str.slice(n .. -1)
23
+
24
+ if n != @pre.size
25
+ prest = @pre.slice!(n .. -1)
26
+ pc = prest.slice! 0
27
+ @chi = {pc => Tree.new(prest, @chi)}
28
+ end
29
+
30
+ c = rest.slice!(0)
31
+
32
+ if c
33
+ (@chi[c] ||= Tree.new).add(val, rest, *prefs)
34
+ else
35
+ if prefs.empty?
36
+ (@chi[''] ||= Array.new).push val
37
+ else
38
+ (@chi[''] ||= Tree.new).add(val, *prefs)
39
+ end
40
+ end
41
+ end
42
+
43
+ def empty?
44
+ @chi.empty?
45
+ end
46
+
47
+ def remove(*prefs, &block)
48
+ str = prefs.shift or raise 'empty prefs?'
49
+ return nil unless @pre.empty? or str.index(@pre) == 0
50
+ c = str.slice(@pre.size) || ''
51
+ return nil unless @chi.include? c
52
+ if c == ''
53
+ if prefs.empty?
54
+ @chi[c].reject!(&block)
55
+ else
56
+ @chi[c].remove(*prefs, &block)
57
+ end
58
+ else
59
+ @chi[c].remove(str.slice((@pre.size + 1) .. -1), *prefs, &block)
60
+ end
61
+ @chi.delete(c) if @chi[c].empty?
62
+
63
+ if @chi.size == 1
64
+ k = @chi.keys.shift
65
+ return nil if k == ''
66
+ @pre << k << @chi[k].pre
67
+ @chi = @chi[k].chi
68
+ end
69
+ end
70
+
71
+ def find(*prefs)
72
+ str = prefs.shift or raise 'empty prefs?'
73
+ self.find_helper(str, *prefs) + self.find_helper(str.reverse, *prefs)
74
+ end
75
+
76
+ protected
77
+ def find_helper(*prefs)
78
+ str = prefs.shift or raise 'empty prefs?'
79
+ return [] unless @pre.empty? or str.index(@pre) == 0
80
+ # puts "#{self.inspect}: #{str} == #{@pre} pfx matched"
81
+ if !@chi.include? ''
82
+ matches = []
83
+ elsif Array === @chi['']
84
+ matches = @chi['']
85
+ else
86
+ matches = @chi[''].find(*prefs)
87
+ end
88
+
89
+ c = str.slice(@pre.size)
90
+
91
+ more = []
92
+ if c and @chi.include?(c)
93
+ more = @chi[c].find_helper(str.slice((@pre.size + 1) .. -1), *prefs)
94
+ end
95
+ return more + matches
96
+ end
97
+ end
98
+
99
+ # api wrapper for netmasks
100
+
101
+ def initialize
102
+ @tree = Tree.new
103
+ end
104
+
105
+ def cook_component(str)
106
+ s = (str && !str.empty?) ? str : '*'
107
+ l = s.index(/[\?\*]/)
108
+ if l
109
+ l2 = s.size - s.rindex(/[\?\*]/) - 1
110
+ if l2 > l
111
+ s = s.reverse
112
+ l = l2
113
+ end
114
+
115
+ return (l > 0) ? s.slice(0 .. (l - 1)) : ''
116
+ else
117
+ return s
118
+ end
119
+ end
120
+
121
+ def mask2keys(m)
122
+ md = m.downcased
123
+ [md.host, md.user, md.nick].map { |c| cook_component(c) }
124
+ end
125
+
126
+ def add(user, *masks)
127
+ masks.each do |m|
128
+ debug "adding user #{user} with mask #{m.fullform}"
129
+ @tree.add([user, m], *mask2keys(m))
130
+ end
131
+ end
132
+
133
+ def remove(user, mask)
134
+ debug "trying to remove user #{user} with mask #{mask}"
135
+ @tree.remove(*mask2keys(mask)) do |val|
136
+ val[0] == user and val[1].fullform == mask.fullform
137
+ end
138
+ end
139
+
140
+ def metric(iu, bu, mask)
141
+ ret = nil
142
+ if iu.matches? mask
143
+ ret = iu.fullform.length - mask.fullform.length
144
+ ret += 10 if bu.transient?
145
+ end
146
+ return ret
147
+ end
148
+
149
+ def find(iu)
150
+ debug "find(#{iu.fullform})"
151
+ iud = iu.downcased
152
+ matches = @tree.find(iud.host, iud.user, iud.nick).uniq.map do |val|
153
+ m = metric(iu, *val)
154
+ m ? [val[0], m] : nil
155
+ end.compact.sort { |a, b| a[1] <=> a[1] }
156
+ debug "matches: " + (matches.map do |m|
157
+ "#{m[0].username}: [#{m[1]}]"
158
+ end.join(', '))
159
+ return matches.empty? ? nil : matches[0][0]
160
+ end
161
+ end
162
+ end
@@ -1,13 +1,106 @@
1
+ #-- vim:sw=2:et
2
+ #++
3
+ #
4
+ # :title: IRC message datastructures
5
+
1
6
  module Irc
2
- BotConfig.register BotConfigArrayValue.new('core.address_prefix',
3
- :default => [], :wizard => true,
4
- :desc => "what non nick-matching prefixes should the bot respond to as if addressed (e.g !, so that '!foo' is treated like 'rbot: foo')"
5
- )
6
7
 
7
- Color = "\003"
8
+
9
+ class Bot
10
+ module Config
11
+ Config.register ArrayValue.new('core.address_prefix',
12
+ :default => [], :wizard => true,
13
+ :desc => "what non nick-matching prefixes should the bot respond to as if addressed (e.g !, so that '!foo' is treated like 'rbot: foo')"
14
+ )
15
+
16
+ Config.register BooleanValue.new('core.reply_with_nick',
17
+ :default => false, :wizard => true,
18
+ :desc => "if true, the bot will prepend the nick to what he has to say when replying (e.g. 'markey: you can't do that!')"
19
+ )
20
+
21
+ Config.register StringValue.new('core.nick_postfix',
22
+ :default => ':', :wizard => true,
23
+ :desc => "when replying with nick put this character after the nick of the user the bot is replying to"
24
+ )
25
+ end
26
+ end
27
+
28
+
29
+ # Define standard IRC attriubtes (not so standard actually,
30
+ # but the closest thing we have ...)
8
31
  Bold = "\002"
9
32
  Underline = "\037"
10
33
  Reverse = "\026"
34
+ Italic = "\011"
35
+ NormalText = "\017"
36
+ AttributeRx = /#{Bold}|#{Underline}|#{Reverse}|#{Italic}|#{NormalText}/
37
+
38
+ # Color is prefixed by \003 and followed by optional
39
+ # foreground and background specifications, two-digits-max
40
+ # numbers separated by a comma. One of the two parts
41
+ # must be present.
42
+ Color = "\003"
43
+ ColorRx = /#{Color}\d?\d?(?:,\d\d?)?/
44
+
45
+ FormattingRx = /#{AttributeRx}|#{ColorRx}/
46
+
47
+ # Standard color codes
48
+ ColorCode = {
49
+ :black => 1,
50
+ :blue => 2,
51
+ :navyblue => 2,
52
+ :navy_blue => 2,
53
+ :green => 3,
54
+ :red => 4,
55
+ :brown => 5,
56
+ :purple => 6,
57
+ :olive => 7,
58
+ :yellow => 8,
59
+ :limegreen => 9,
60
+ :lime_green => 9,
61
+ :teal => 10,
62
+ :aqualight => 11,
63
+ :aqua_light => 11,
64
+ :royal_blue => 12,
65
+ :hotpink => 13,
66
+ :hot_pink => 13,
67
+ :darkgray => 14,
68
+ :dark_gray => 14,
69
+ :lightgray => 15,
70
+ :light_gray => 15,
71
+ :white => 16
72
+ }
73
+
74
+ # Convert a String or Symbol into a color number
75
+ def Irc.find_color(data)
76
+ "%02d" % if Integer === data
77
+ data
78
+ else
79
+ f = if String === data
80
+ data.intern
81
+ else
82
+ data
83
+ end
84
+ if ColorCode.key?(f)
85
+ ColorCode[f]
86
+ else
87
+ 0
88
+ end
89
+ end
90
+ end
91
+
92
+ # Insert the full color code for a given
93
+ # foreground/background combination.
94
+ def Irc.color(fg=nil,bg=nil)
95
+ str = Color.dup
96
+ if fg
97
+ str << Irc.find_color(fg)
98
+ end
99
+ if bg
100
+ str << "," << Irc.find_color(bg)
101
+ end
102
+ return str
103
+ end
11
104
 
12
105
  # base user message class, all user messages derive from this
13
106
  # (a user message is defined as having a source hostmask, a target
@@ -17,33 +110,65 @@ module Irc
17
110
  # associated bot
18
111
  attr_reader :bot
19
112
 
113
+ # associated server
114
+ attr_reader :server
115
+
20
116
  # when the message was received
21
117
  attr_reader :time
22
118
 
23
- # hostmask of message source
119
+ # User that originated the message
24
120
  attr_reader :source
25
121
 
26
- # nick of message source
27
- attr_reader :sourcenick
28
-
29
- # url part of message source
30
- attr_reader :sourceaddress
31
-
32
- # nick/channel message was sent to
122
+ # User/Channel message was sent to
33
123
  attr_reader :target
34
124
 
35
- # contents of the message
125
+ # contents of the message (stripped of initial/final format codes)
36
126
  attr_accessor :message
37
127
 
128
+ # contents of the message (for logging purposes)
129
+ attr_accessor :logmessage
130
+
131
+ # contents of the message (stripped of all formatting)
132
+ attr_accessor :plainmessage
133
+
38
134
  # has the message been replied to/handled by a plugin?
39
135
  attr_accessor :replied
136
+ alias :replied? :replied
137
+
138
+ # should the message be ignored?
139
+ attr_accessor :ignored
140
+ alias :ignored? :ignored
141
+
142
+ # set this to true if the method that delegates the message is run in a thread
143
+ attr_accessor :in_thread
144
+ alias :in_thread? :in_thread
145
+
146
+ def inspect(fields=nil)
147
+ ret = self.__to_s__[0..-2]
148
+ ret << ' bot=' << @bot.__to_s__
149
+ ret << ' server=' << server.to_s
150
+ ret << ' time=' << time.to_s
151
+ ret << ' source=' << source.to_s
152
+ ret << ' target=' << target.to_s
153
+ ret << ' message=' << message.inspect
154
+ ret << ' logmessage=' << logmessage.inspect
155
+ ret << ' plainmessage=' << plainmessage.inspect
156
+ ret << fields if fields
157
+ ret << ' (identified)' if identified?
158
+ ret << ' (addressed to me)' if address?
159
+ ret << ' (replied)' if replied?
160
+ ret << ' (ignored)' if ignored?
161
+ ret << ' (in thread)' if in_thread?
162
+ ret << '>'
163
+ end
40
164
 
41
165
  # instantiate a new Message
42
166
  # bot:: associated bot class
43
- # source:: hostmask of the message source
44
- # target:: nick/channel message is destined for
45
- # message:: message part
46
- def initialize(bot, source, target, message)
167
+ # server:: Server where the message took place
168
+ # source:: User that sent the message
169
+ # target:: User/Channel is destined for
170
+ # message:: actual message
171
+ def initialize(bot, server, source, target, message)
47
172
  @msg_wants_id = false unless defined? @msg_wants_id
48
173
 
49
174
  @time = Time.now
@@ -51,31 +176,51 @@ module Irc
51
176
  @source = source
52
177
  @address = false
53
178
  @target = target
54
- @message = BasicUserMessage.stripcolour message
179
+ @message = message || ""
55
180
  @replied = false
181
+ @server = server
182
+ @ignored = false
183
+ @in_thread = false
56
184
 
57
185
  @identified = false
58
- if @msg_wants_id && @bot.capabilities["identify-msg".to_sym]
59
- if @message =~ /([-+])(.*)/
186
+ if @msg_wants_id && @server.capabilities[:"identify-msg"]
187
+ if @message =~ /^([-+])(.*)/
60
188
  @identified = ($1=="+")
61
189
  @message = $2
62
190
  else
63
191
  warning "Message does not have identification"
64
192
  end
65
193
  end
194
+ @logmessage = @message.dup
195
+ @plainmessage = BasicUserMessage.strip_formatting(@message)
196
+ @message = BasicUserMessage.strip_initial_formatting(@message)
66
197
 
67
- # split source into consituent parts
68
- if source =~ /^((\S+)!(\S+))$/
69
- @sourcenick = $2
70
- @sourceaddress = $3
71
- end
72
-
73
- if target && target.downcase == @bot.nick.downcase
198
+ if target && target == @bot.myself
74
199
  @address = true
75
200
  end
76
201
 
77
202
  end
78
203
 
204
+ # Access the nick of the source
205
+ #
206
+ def sourcenick
207
+ @source.nick rescue @source.to_s
208
+ end
209
+
210
+ # Access the user@host of the source
211
+ #
212
+ def sourceaddress
213
+ "#{@source.user}@#{@source.host}" rescue @source.to_s
214
+ end
215
+
216
+ # Access the botuser corresponding to the source, if any
217
+ #
218
+ def botuser
219
+ source.botuser rescue @bot.auth.everyone
220
+ end
221
+
222
+
223
+ # Was the message from an identified user?
79
224
  def identified?
80
225
  return @identified
81
226
  end
@@ -88,19 +233,32 @@ module Irc
88
233
  return @address
89
234
  end
90
235
 
91
- # has this message been replied to by a plugin?
92
- def replied?
93
- return @replied
94
- end
95
-
96
236
  # strip mIRC colour escapes from a string
97
237
  def BasicUserMessage.stripcolour(string)
98
238
  return "" unless string
99
- ret = string.gsub(/\cC\d\d?(?:,\d\d?)?/, "")
239
+ ret = string.gsub(ColorRx, "")
100
240
  #ret.tr!("\x00-\x1f", "")
101
241
  ret
102
242
  end
103
243
 
244
+ def BasicUserMessage.strip_initial_formatting(string)
245
+ return "" unless string
246
+ ret = string.gsub(/^#{FormattingRx}|#{FormattingRx}$/,"")
247
+ end
248
+
249
+ def BasicUserMessage.strip_formatting(string)
250
+ string.gsub(FormattingRx,"")
251
+ end
252
+
253
+ end
254
+
255
+ # class for handling welcome messages from the server
256
+ class WelcomeMessage < BasicUserMessage
257
+ end
258
+
259
+ # class for handling MOTD from the server. Yes, MotdMessage
260
+ # is somewhat redundant, but it fits with the naming scheme
261
+ class MotdMessage < BasicUserMessage
104
262
  end
105
263
 
106
264
  # class for handling IRC user messages. Includes some utilities for handling
@@ -109,6 +267,24 @@ module Irc
109
267
  # (address? will return true in this case)
110
268
  class UserMessage < BasicUserMessage
111
269
 
270
+ def inspect
271
+ fields = ' plugin=' << plugin.inspect
272
+ fields << ' params=' << params.inspect
273
+ fields << ' channel=' << channel.to_s if channel
274
+ fields << ' (reply to ' << replyto.to_s << ')'
275
+ if self.private?
276
+ fields << ' (private)'
277
+ else
278
+ fields << ' (public)'
279
+ end
280
+ if self.action?
281
+ fields << ' (action)'
282
+ elsif ctcp
283
+ fields << ' (CTCP ' << ctcp << ')'
284
+ end
285
+ super(fields)
286
+ end
287
+
112
288
  # for plugin messages, the name of the plugin invoked by the message
113
289
  attr_reader :plugin
114
290
 
@@ -124,6 +300,12 @@ module Irc
124
300
  # channel the message was in, nil for privately addressed messages
125
301
  attr_reader :channel
126
302
 
303
+ # for PRIVMSGs, false unless the message was a CTCP command,
304
+ # in which case it evaluates to the CTCP command itself
305
+ # (TIME, PING, VERSION, etc). The CTCP command parameters
306
+ # are then stored in the message.
307
+ attr_reader :ctcp
308
+
127
309
  # for PRIVMSGs, true if the message was a CTCP ACTION (CTCP stuff
128
310
  # will be stripped from the message)
129
311
  attr_reader :action
@@ -133,18 +315,19 @@ module Irc
133
315
  # source:: hostmask of the message source
134
316
  # target:: nick/channel message is destined for
135
317
  # message:: message part
136
- def initialize(bot, source, target, message)
137
- super(bot, source, target, message)
318
+ def initialize(bot, server, source, target, message)
319
+ super(bot, server, source, target, message)
138
320
  @target = target
139
321
  @private = false
140
322
  @plugin = nil
323
+ @ctcp = false
141
324
  @action = false
142
325
 
143
- if target.downcase == @bot.nick.downcase
326
+ if target == @bot.myself
144
327
  @private = true
145
328
  @address = true
146
329
  @channel = nil
147
- @replyto = @sourcenick
330
+ @replyto = source
148
331
  else
149
332
  @replyto = @target
150
333
  @channel = @target
@@ -166,14 +349,20 @@ module Irc
166
349
  @address = true
167
350
  end
168
351
 
169
- if(@message =~ /^\001ACTION\s(.+)\001/)
170
- @message = $1
171
- @action = true
352
+ if(@message =~ /^\001(\S+)(\s(.+))?\001/)
353
+ @ctcp = $1
354
+ # FIXME need to support quoting of NULL and CR/LF, see
355
+ # http://www.irchelp.org/irchelp/rfc/ctcpspec.html
356
+ @message = $3 || String.new
357
+ @action = @ctcp == 'ACTION'
358
+ debug "Received CTCP command #{@ctcp} with options #{@message} (action? #{@action})"
359
+ @logmessage = @message.dup
172
360
  end
173
361
 
174
362
  # free splitting for plugins
175
363
  @params = @message.dup
176
- if @params.gsub!(/^\s*(\S+)[\s$]*/, "")
364
+ # Created messges (such as by fake_message) can contain multiple lines
365
+ if @params.gsub!(/\A\s*(\S+)[\s$]*/m, "")
177
366
  @plugin = $1.downcase
178
367
  @params = nil unless @params.length > 0
179
368
  end
@@ -198,42 +387,92 @@ module Irc
198
387
  # <tt>@bot.say m.replyto, string</tt>
199
388
  # So if the message is private, it will reply to the user. If it was
200
389
  # in a channel, it will reply in the channel.
201
- def reply(string)
202
- @bot.say @replyto, string
390
+ def plainreply(string, options={})
391
+ @bot.say @replyto, string, options
203
392
  @replied = true
204
393
  end
205
394
 
395
+ # Same as reply, but when replying in public it adds the nick of the user
396
+ # the bot is replying to
397
+ def nickreply(string, options={})
398
+ extra = self.public? ? "#{@source}#{@bot.config['core.nick_postfix']} " : ""
399
+ @bot.say @replyto, extra + string, options
400
+ @replied = true
401
+ end
402
+
403
+ # the default reply style is to nickreply unless the reply already contains
404
+ # the nick or core.reply_with_nick is set to false
405
+ #
406
+ def reply(string, options={})
407
+ if @bot.config['core.reply_with_nick'] and not string =~ /(?:^|\W)#{Regexp.escape(@source.to_s)}(?:$|\W)/
408
+ return nickreply(string, options)
409
+ end
410
+ plainreply(string, options)
411
+ end
412
+
206
413
  # convenience method to reply to a message with an action. It's the
207
414
  # same as doing:
208
415
  # <tt>@bot.action m.replyto, string</tt>
209
416
  # So if the message is private, it will reply to the user. If it was
210
417
  # in a channel, it will reply in the channel.
211
- def act(string)
212
- @bot.action @replyto, string
418
+ def act(string, options={})
419
+ @bot.action @replyto, string, options
213
420
  @replied = true
214
421
  end
215
422
 
423
+ # send a CTCP response, i.e. a private NOTICE to the sender
424
+ # with the same CTCP command and the reply as a parameter
425
+ def ctcp_reply(string, options={})
426
+ @bot.ctcp_notice @source, @ctcp, string, options
427
+ end
428
+
216
429
  # convenience method to reply "okay" in the current language to the
217
430
  # message
431
+ def plainokay
432
+ self.plainreply @bot.lang.get("okay")
433
+ end
434
+
435
+ # Like the above, but append the username
436
+ def nickokay
437
+ str = @bot.lang.get("okay").dup
438
+ if self.public?
439
+ # remove final punctuation
440
+ str.gsub!(/[!,.]$/,"")
441
+ str += ", #{@source}"
442
+ end
443
+ self.plainreply str
444
+ end
445
+
446
+ # the default okay style is the same as the default reply style
447
+ #
218
448
  def okay
219
- @bot.say @replyto, @bot.lang.get("okay")
449
+ if @bot.config['core.reply_with_nick']
450
+ return nickokay
451
+ end
452
+ plainokay
453
+ end
454
+
455
+ # send a NOTICE to the message source
456
+ #
457
+ def notify(msg,opts={})
458
+ @bot.notice(sourcenick, msg, opts)
220
459
  end
221
460
 
222
461
  end
223
462
 
224
463
  # class to manage IRC PRIVMSGs
225
464
  class PrivMessage < UserMessage
226
- def initialize(bot, source, target, message)
227
- @msg_wants_id = true
228
- super
465
+ def initialize(bot, server, source, target, message, opts={})
466
+ @msg_wants_id = opts[:handle_id]
467
+ super(bot, server, source, target, message)
229
468
  end
230
469
  end
231
470
 
232
471
  # class to manage IRC NOTICEs
233
472
  class NoticeMessage < UserMessage
234
- def initialize(bot, source, target, message)
235
- @msg_wants_id = true
236
- super
473
+ def initialize(bot, server, source, target, message, opts={})
474
+ @msg_wants_id = opts[:handle_id]
475
+ super(bot, server, source, target, message)
237
476
  end
238
477
  end
239
478
 
@@ -244,8 +483,31 @@ module Irc
244
483
  # channel user was kicked from
245
484
  attr_reader :channel
246
485
 
247
- def initialize(bot, source, target, channel, message="")
248
- super(bot, source, target, message)
486
+ def inspect
487
+ fields = ' channel=' << channel.to_s
488
+ super(fields)
489
+ end
490
+
491
+ def initialize(bot, server, source, target, channel, message="")
492
+ super(bot, server, source, target, message)
493
+ @channel = channel
494
+ end
495
+ end
496
+
497
+ # class to manage IRC INVITEs
498
+ # +address?+ can be used as a shortcut to see if the bot was invited,
499
+ # which should be true except for server bugs
500
+ class InviteMessage < BasicUserMessage
501
+ # channel user was invited to
502
+ attr_reader :channel
503
+
504
+ def inspect
505
+ fields = ' channel=' << channel.to_s
506
+ super(fields)
507
+ end
508
+
509
+ def initialize(bot, server, source, target, channel, message="")
510
+ super(bot, server, source, target, message)
249
511
  @channel = channel
250
512
  end
251
513
  end
@@ -253,14 +515,61 @@ module Irc
253
515
  # class to pass IRC Nick changes in. @message contains the old nickame,
254
516
  # @sourcenick contains the new one.
255
517
  class NickMessage < BasicUserMessage
256
- def initialize(bot, source, oldnick, newnick)
257
- super(bot, source, oldnick, newnick)
518
+ attr_accessor :is_on
519
+ def initialize(bot, server, source, oldnick, newnick)
520
+ super(bot, server, source, oldnick, newnick)
521
+ @is_on = []
522
+ end
523
+
524
+ def oldnick
525
+ return @target
526
+ end
527
+
528
+ def newnick
529
+ return @message
530
+ end
531
+
532
+ def inspect
533
+ fields = ' old=' << oldnick
534
+ fields << ' new=' << newnick
535
+ super(fields)
536
+ end
537
+ end
538
+
539
+ # class to manage mode changes
540
+ class ModeChangeMessage < BasicUserMessage
541
+ attr_accessor :modes
542
+ def initialize(bot, server, source, target, message="")
543
+ super(bot, server, source, target, message)
544
+ @address = (source == @bot.myself)
545
+ @modes = []
546
+ end
547
+
548
+ def inspect
549
+ fields = ' modes=' << modes.inspect
550
+ super(fields)
551
+ end
552
+ end
553
+
554
+ # class to manage NAME replies
555
+ class NamesMessage < BasicUserMessage
556
+ attr_accessor :users
557
+ def initialize(bot, server, source, target, message="")
558
+ super(bot, server, source, target, message)
559
+ @users = []
560
+ end
561
+
562
+ def inspect
563
+ fields = ' users=' << users.inspect
564
+ super(fields)
258
565
  end
259
566
  end
260
567
 
261
568
  class QuitMessage < BasicUserMessage
262
- def initialize(bot, source, target, message="")
263
- super(bot, source, target, message)
569
+ attr_accessor :was_on
570
+ def initialize(bot, server, source, target, message="")
571
+ super(bot, server, source, target, message)
572
+ @was_on = []
264
573
  end
265
574
  end
266
575
 
@@ -272,11 +581,20 @@ module Irc
272
581
  # topic set on channel
273
582
  attr_reader :channel
274
583
 
275
- def initialize(bot, source, channel, timestamp, topic="")
276
- super(bot, source, channel, topic)
584
+ # :info if topic info, :set if topic set
585
+ attr_accessor :info_or_set
586
+ def initialize(bot, server, source, channel, topic=ChannelTopic.new)
587
+ super(bot, server, source, channel, topic.text)
277
588
  @topic = topic
278
- @timestamp = timestamp
589
+ @timestamp = topic.set_on
279
590
  @channel = channel
591
+ @info_or_set = nil
592
+ end
593
+
594
+ def inspect
595
+ fields = ' topic=' << topic
596
+ fields << ' (set on ' << timestamp << ')'
597
+ super(fields)
280
598
  end
281
599
  end
282
600
 
@@ -284,11 +602,17 @@ module Irc
284
602
  class JoinMessage < BasicUserMessage
285
603
  # channel joined
286
604
  attr_reader :channel
287
- def initialize(bot, source, channel, message="")
288
- super(bot, source, channel, message)
605
+
606
+ def inspect
607
+ fields = ' channel=' << channel.to_s
608
+ super(fields)
609
+ end
610
+
611
+ def initialize(bot, server, source, channel, message="")
612
+ super(bot, server, source, channel, message)
289
613
  @channel = channel
290
614
  # in this case sourcenick is the nick that could be the bot
291
- @address = (sourcenick.downcase == @bot.nick.downcase)
615
+ @address = (source == @bot.myself)
292
616
  end
293
617
  end
294
618
 
@@ -296,4 +620,7 @@ module Irc
296
620
  # same as a join, but can have a message too
297
621
  class PartMessage < JoinMessage
298
622
  end
623
+
624
+ class UnknownMessage < BasicUserMessage
625
+ end
299
626
  end