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
@@ -0,0 +1,40 @@
1
+ ---
2
+ :"generic-in":
3
+ - hello
4
+ - howdy
5
+ - hola
6
+ - salut
7
+ - sup
8
+ - re
9
+ - hey
10
+ - hi
11
+ - yo
12
+ :"morning-in":
13
+ - good morning
14
+ - goodmorning
15
+ - morning
16
+ - "'morning"
17
+ :"afternoon-in":
18
+ - good afternoon
19
+ - goodafternoon
20
+ - afternoon
21
+ - "'afternoon"
22
+ :"generic-out":
23
+ - bye
24
+ - cya
25
+ - see you
26
+ - see ya
27
+ - g'bye
28
+ - goodbye
29
+ - later
30
+ :"evening-in":
31
+ - good evening
32
+ - goodevening
33
+ - evening
34
+ - "'evening"
35
+ :"generic-dest":
36
+ - all
37
+ - people
38
+ - everybody
39
+ - y'all
40
+ - bots
@@ -0,0 +1,29 @@
1
+ ---
2
+ :"generic-in":
3
+ - "'lo"
4
+ - "'lu"
5
+ - plop
6
+ - "'jour"
7
+ - bonjour
8
+ :"morning-in":
9
+ - "'jour"
10
+ :"afternoon-in":
11
+ - bonne journée
12
+ - bonne journee
13
+ - "'journée"
14
+ - "'journee"
15
+ :"generic-out":
16
+ - bye
17
+ - cya
18
+ - see you
19
+ - a plus tard
20
+ - a plus
21
+ - "'nuit"
22
+ - nenuit
23
+ :"evening-in":
24
+ - "'soir"
25
+ - bonsoir
26
+ - "'nuit"
27
+ :"generic-dest":
28
+ - tous
29
+ - all
@@ -0,0 +1,51 @@
1
+ ---
2
+ :"generic-in":
3
+ - salve
4
+ - ehila'
5
+ - ehilà
6
+ - ola'
7
+ - olà
8
+ - yo
9
+ - ue'
10
+ - uè
11
+ :"morning-in":
12
+ - "'giorno"
13
+ - giorno
14
+ - buon giorno
15
+ - buon di'
16
+ - buon dì
17
+ - buondì
18
+ - buongiorno
19
+ :"afternoon-in":
20
+ - "'sera"
21
+ - buona sera
22
+ - buonasera
23
+ :"evening-in":
24
+ - "'sera"
25
+ - buona sera
26
+ - buonasera
27
+ :"generic-out":
28
+ - a dopo
29
+ - ci vediamo
30
+ - adios
31
+ - se vedemio
32
+ - arrivederci
33
+ - saluti
34
+ :"morning-out":
35
+ - buona giornata
36
+ :"evening-out":
37
+ - buona serata
38
+ - buona notte
39
+ - buonanotte
40
+ :"generic":
41
+ - ciao
42
+ :"generic-dest":
43
+ - gente
44
+ - tutti
45
+ - raga
46
+ - raga'
47
+ - ragà
48
+ - ragazzi
49
+ - ragazze
50
+ - bot
51
+ - bots
@@ -0,0 +1,31 @@
1
+ ---
2
+ :"generic-in":
3
+ - ハロー
4
+ - こんにちは
5
+ - こんにちわ
6
+ - やあ
7
+ :"morning-in":
8
+ - おはよう
9
+ - おはようございます
10
+ - こんにちは
11
+ :"afternoon-in":
12
+ - こんにちは
13
+ - こんにちわ
14
+ :"generic-out":
15
+ - じゃあな
16
+ - またね
17
+ - さようなら
18
+ - バイバイ
19
+ - 失礼します
20
+ - しつれい
21
+ :"evening-in":
22
+ - こんばんは
23
+ - こんばんわ
24
+ - 今晩は
25
+ :"generic-dest":
26
+ - みんな
27
+ - 諸君
28
+ - みなさん
29
+ - 皆さん
30
+ - 皆
31
+ - 皆様
@@ -0,0 +1,940 @@
1
+ #-- vim:sw=2:et
2
+ #++
3
+ # :title: User management
4
+ #
5
+ # rbot user management
6
+ # Author:: Giuseppe Bilotta (giuseppe.bilotta@gmail.com)
7
+
8
+ require 'singleton'
9
+ require 'set'
10
+ require 'rbot/maskdb'
11
+
12
+ # This would be a good idea if it was failproof, but the truth
13
+ # is that other methods can indirectly modify the hash. *sigh*
14
+ #
15
+ # class AuthNotifyingHash < Hash
16
+ # %w(clear default= delete delete_if replace invert
17
+ # merge! update rehash reject! replace shift []= store).each { |m|
18
+ # class_eval {
19
+ # define_method(m) { |*a|
20
+ # r = super(*a)
21
+ # Irc::Bot::Auth.manager.set_changed
22
+ # r
23
+ # }
24
+ # }
25
+ # }
26
+ # end
27
+ #
28
+
29
+ module Irc
30
+ class Bot
31
+
32
+
33
+ # This module contains the actual Authentication stuff
34
+ #
35
+ module Auth
36
+
37
+ Config.register Config::StringValue.new( 'auth.password',
38
+ :default => 'rbotauth', :wizard => true,
39
+ :on_change => Proc.new {|bot, v| bot.auth.botowner.password = v},
40
+ :desc => _('Password for the bot owner'))
41
+ Config.register Config::BooleanValue.new( 'auth.login_by_mask',
42
+ :default => 'true',
43
+ :desc => _('Set false to prevent new botusers from logging in without a password when the user netmask is known'))
44
+ Config.register Config::BooleanValue.new( 'auth.autologin',
45
+ :default => 'true',
46
+ :desc => _('Set false to prevent new botusers from recognizing IRC users without a need to manually login'))
47
+ Config.register Config::BooleanValue.new( 'auth.autouser',
48
+ :default => 'false',
49
+ :desc => _('Set true to allow new botusers to be created automatically'))
50
+ # Config.register Config::IntegerValue.new( 'auth.default_level',
51
+ # :default => 10, :wizard => true,
52
+ # :desc => 'The default level for new/unknown users' )
53
+
54
+ # Generate a random password of length _l_
55
+ #
56
+ def Auth.random_password(l=8)
57
+ pwd = ""
58
+ l.times do
59
+ pwd << (rand(26) + (rand(2) == 0 ? 65 : 97) ).chr
60
+ end
61
+ return pwd
62
+ end
63
+
64
+
65
+ # An Irc::Bot::Auth::Command defines a command by its "path":
66
+ #
67
+ # base::command::subcommand::subsubcommand::subsubsubcommand
68
+ #
69
+ class Command
70
+
71
+ attr_reader :command, :path
72
+
73
+ # A method that checks if a given _cmd_ is in a form that can be
74
+ # reduced into a canonical command path, and if so, returns it
75
+ #
76
+ def sanitize_command_path(cmd)
77
+ pre = cmd.to_s.downcase.gsub(/^\*?(?:::)?/,"").gsub(/::$/,"")
78
+ return pre if pre.empty?
79
+ return pre if pre =~ /^\S+(::\S+)*$/
80
+ raise TypeError, "#{cmd.inspect} is not a valid command"
81
+ end
82
+
83
+ # Creates a new Command from a given string; you can then access
84
+ # the command as a symbol with the :command method and the whole
85
+ # path as :path
86
+ #
87
+ # Command.new("core::auth::save").path => [:"*", :"core", :"core::auth", :"core::auth::save"]
88
+ #
89
+ # Command.new("core::auth::save").command => :"core::auth::save"
90
+ #
91
+ def initialize(cmd)
92
+ cmdpath = sanitize_command_path(cmd).split('::')
93
+ seq = cmdpath.inject(["*"]) { |list, cmd|
94
+ list << (list.length > 1 ? list.last + "::" : "") + cmd
95
+ }
96
+ @path = seq.map { |k|
97
+ k.to_sym
98
+ }
99
+ @command = path.last
100
+ debug "Created command #{@command.inspect} with path #{@path.pretty_inspect}"
101
+ end
102
+
103
+ # Returs self
104
+ def to_irc_auth_command
105
+ self
106
+ end
107
+
108
+ end
109
+
110
+ end
111
+
112
+ end
113
+ end
114
+
115
+
116
+ class String
117
+
118
+ # Returns an Irc::Bot::Auth::Comand from the receiver
119
+ def to_irc_auth_command
120
+ Irc::Bot::Auth::Command.new(self)
121
+ end
122
+
123
+ end
124
+
125
+
126
+ class Symbol
127
+
128
+ # Returns an Irc::Bot::Auth::Comand from the receiver
129
+ def to_irc_auth_command
130
+ Irc::Bot::Auth::Command.new(self)
131
+ end
132
+
133
+ end
134
+
135
+
136
+ module Irc
137
+ class Bot
138
+
139
+
140
+ module Auth
141
+
142
+
143
+ # This class describes a permission set
144
+ class PermissionSet
145
+
146
+ attr_reader :perm
147
+ # Create a new (empty) PermissionSet
148
+ #
149
+ def initialize
150
+ @perm = {}
151
+ end
152
+
153
+ # Inspection simply inspects the internal hash
154
+ def inspect
155
+ @perm.inspect
156
+ end
157
+
158
+ # Sets the permission for command _cmd_ to _val_,
159
+ #
160
+ def set_permission(str, val)
161
+ cmd = str.to_irc_auth_command
162
+ case val
163
+ when true, false
164
+ @perm[cmd.command] = val
165
+ when nil
166
+ @perm.delete(cmd.command)
167
+ else
168
+ raise TypeError, "#{val.inspect} must be true or false" unless [true,false].include?(val)
169
+ end
170
+ end
171
+
172
+ # Resets the permission for command _cmd_
173
+ #
174
+ def reset_permission(cmd)
175
+ set_permission(cmd, nil)
176
+ end
177
+
178
+ # Tells if command _cmd_ is permitted. We do this by returning
179
+ # the value of the deepest Command#path that matches.
180
+ #
181
+ def permit?(str)
182
+ cmd = str.to_irc_auth_command
183
+ # TODO user-configurable list of always-allowed commands,
184
+ # for admins that want to set permissions -* for everybody
185
+ return true if cmd.command == :login
186
+ allow = nil
187
+ cmd.path.reverse.each { |k|
188
+ if @perm.has_key?(k)
189
+ allow = @perm[k]
190
+ break
191
+ end
192
+ }
193
+ return allow
194
+ end
195
+
196
+ end
197
+
198
+
199
+ # This is the error that gets raised when an invalid password is met
200
+ #
201
+ class InvalidPassword < RuntimeError
202
+ end
203
+
204
+
205
+ # This is the basic class for bot users: they have a username, a
206
+ # password, a list of netmasks to match against, and a list of
207
+ # permissions. A BotUser can be marked as 'transient', usually meaning
208
+ # it's not intended for permanent storage. Transient BotUsers have lower
209
+ # priority than nontransient ones for autologin purposes.
210
+ #
211
+ # To initialize a BotUser, you pass a _username_ and an optional
212
+ # hash of options. Currently, only two options are recognized:
213
+ #
214
+ # transient:: true or false, determines if the BotUser is transient or
215
+ # permanent (default is false, permanent BotUser).
216
+ #
217
+ # Transient BotUsers are initialized by prepending an
218
+ # asterisk (*) to the username, and appending a sanitized
219
+ # version of the object_id. The username can be empty.
220
+ # A random password is generated.
221
+ #
222
+ # Permanent Botusers need the username as is, and no
223
+ # password is generated.
224
+ #
225
+ # masks:: an array of Netmasks to initialize the NetmaskList. This
226
+ # list is used as-is for permanent BotUsers.
227
+ #
228
+ # Transient BotUsers will alter the list elements which are
229
+ # Irc::User by globbing the nick and any initial nonletter
230
+ # part of the ident.
231
+ #
232
+ # The masks option is optional for permanent BotUsers, but
233
+ # obligatory (non-empty) for transients.
234
+ #
235
+ class BotUser
236
+
237
+ attr_reader :username
238
+ attr_reader :password
239
+ attr_reader :netmasks
240
+ attr_reader :perm
241
+ attr_reader :perm_temp
242
+ attr_writer :login_by_mask
243
+ attr_writer :transient
244
+
245
+ def autologin=(vnew)
246
+ vold = @autologin
247
+ @autologin = vnew
248
+ if vold && !vnew
249
+ @netmasks.each { |n| Auth.manager.maskdb.remove(self, n) }
250
+ elsif vnew && !vold
251
+ @netmasks.each { |n| Auth.manager.maskdb.add(self, n) }
252
+ end
253
+ end
254
+
255
+ # Checks if the BotUser is transient
256
+ def transient?
257
+ @transient
258
+ end
259
+
260
+ # Checks if the BotUser is permanent (not transient)
261
+ def permanent?
262
+ !@transient
263
+ end
264
+
265
+ # Sets if the BotUser is permanent or not
266
+ def permanent=(bool)
267
+ @transient=!bool
268
+ end
269
+
270
+ # Make the BotUser permanent
271
+ def make_permanent(name)
272
+ raise TypeError, "permanent already" if permanent?
273
+ @username = BotUser.sanitize_username(name)
274
+ @transient = false
275
+ reset_autologin
276
+ reset_password # or not?
277
+ @netmasks.dup.each do |m|
278
+ delete_netmask(m)
279
+ add_netmask(m.generalize)
280
+ end
281
+ end
282
+
283
+ # Create a new BotUser with given username
284
+ def initialize(username, options={})
285
+ opts = {:transient => false}.merge(options)
286
+ @transient = opts[:transient]
287
+
288
+ if @transient
289
+ @username = "*"
290
+ @username << BotUser.sanitize_username(username) if username and not username.to_s.empty?
291
+ @username << BotUser.sanitize_username(object_id)
292
+ reset_password
293
+ @login_by_mask=true
294
+ @autologin=true
295
+ else
296
+ @username = BotUser.sanitize_username(username)
297
+ @password = nil
298
+ reset_login_by_mask
299
+ reset_autologin
300
+ end
301
+
302
+ @netmasks = NetmaskList.new
303
+ if opts.key?(:masks) and opts[:masks]
304
+ masks = opts[:masks]
305
+ masks = [masks] unless masks.respond_to?(:each)
306
+ masks.each { |m|
307
+ mask = m.to_irc_netmask
308
+ if @transient and User === m
309
+ mask.nick = "*"
310
+ mask.host = m.host.dup
311
+ mask.user = "*" + m.user.sub(/^\w?[^\w]+/,'')
312
+ end
313
+ add_netmask(mask) unless mask.to_s == "*"
314
+ }
315
+ end
316
+ raise "must provide a usable mask for transient BotUser #{@username}" if @transient and @netmasks.empty?
317
+
318
+ @perm = {}
319
+ @perm_temp = {}
320
+ end
321
+
322
+ # Inspection
323
+ def inspect
324
+ str = self.__to_s__[0..-2]
325
+ str << " (transient)" if @transient
326
+ str << ":"
327
+ str << " @username=#{@username.inspect}"
328
+ str << " @netmasks=#{@netmasks.inspect}"
329
+ str << " @perm=#{@perm.inspect}"
330
+ str << " @perm_temp=#{@perm_temp.inspect}" unless @perm_temp.empty?
331
+ str << " @login_by_mask=#{@login_by_mask}"
332
+ str << " @autologin=#{@autologin}"
333
+ str << ">"
334
+ end
335
+
336
+ # In strings
337
+ def to_s
338
+ @username
339
+ end
340
+
341
+ # Convert into a hash
342
+ def to_hash
343
+ {
344
+ :username => @username,
345
+ :password => @password,
346
+ :netmasks => @netmasks,
347
+ :perm => @perm,
348
+ :login_by_mask => @login_by_mask,
349
+ :autologin => @autologin,
350
+ }
351
+ end
352
+
353
+ # Do we allow logging in without providing the password?
354
+ #
355
+ def login_by_mask?
356
+ @login_by_mask
357
+ end
358
+
359
+ # Reset the login-by-mask option
360
+ #
361
+ def reset_login_by_mask
362
+ @login_by_mask = Auth.manager.bot.config['auth.login_by_mask'] unless defined?(@login_by_mask)
363
+ end
364
+
365
+ # Reset the autologin option
366
+ #
367
+ def reset_autologin
368
+ @autologin = Auth.manager.bot.config['auth.autologin'] unless defined?(@autologin)
369
+ end
370
+
371
+ # Do we allow automatic logging in?
372
+ #
373
+ def autologin?
374
+ @autologin
375
+ end
376
+
377
+ # Restore from hash
378
+ def from_hash(h)
379
+ @username = h[:username] if h.has_key?(:username)
380
+ @password = h[:password] if h.has_key?(:password)
381
+ @login_by_mask = h[:login_by_mask] if h.has_key?(:login_by_mask)
382
+ @autologin = h[:autologin] if h.has_key?(:autologin)
383
+ if h.has_key?(:netmasks)
384
+ @netmasks = h[:netmasks]
385
+ debug @netmasks
386
+ @netmasks.each { |n| Auth.manager.maskdb.add(self, n) } if @autologin
387
+ debug @netmasks
388
+ end
389
+ @perm = h[:perm] if h.has_key?(:perm)
390
+ end
391
+
392
+ # This method sets the password if the proposed new password
393
+ # is valid
394
+ def password=(pwd=nil)
395
+ pass = pwd.to_s
396
+ if pass.empty?
397
+ reset_password
398
+ else
399
+ begin
400
+ raise InvalidPassword, "#{pass} contains invalid characters" if pass !~ /^[\x21-\x7e]+$/
401
+ raise InvalidPassword, "#{pass} too short" if pass.length < 4
402
+ @password = pass
403
+ rescue InvalidPassword => e
404
+ raise e
405
+ rescue => e
406
+ raise InvalidPassword, "Exception #{e.inspect} while checking #{pass.inspect} (#{pwd.inspect})"
407
+ end
408
+ end
409
+ end
410
+
411
+ # Resets the password by creating a new onw
412
+ def reset_password
413
+ @password = Auth.random_password
414
+ end
415
+
416
+ # Sets the permission for command _cmd_ to _val_ on channel _chan_
417
+ #
418
+ def set_permission(cmd, val, chan="*")
419
+ k = chan.to_s.to_sym
420
+ @perm[k] = PermissionSet.new unless @perm.has_key?(k)
421
+ @perm[k].set_permission(cmd, val)
422
+ end
423
+
424
+ # Resets the permission for command _cmd_ on channel _chan_
425
+ #
426
+ def reset_permission(cmd, chan ="*")
427
+ set_permission(cmd, nil, chan)
428
+ end
429
+
430
+ # Sets the temporary permission for command _cmd_ to _val_ on channel _chan_
431
+ #
432
+ def set_temp_permission(cmd, val, chan="*")
433
+ k = chan.to_s.to_sym
434
+ @perm_temp[k] = PermissionSet.new unless @perm_temp.has_key?(k)
435
+ @perm_temp[k].set_permission(cmd, val)
436
+ end
437
+
438
+ # Resets the temporary permission for command _cmd_ on channel _chan_
439
+ #
440
+ def reset_temp_permission(cmd, chan ="*")
441
+ set_temp_permission(cmd, nil, chan)
442
+ end
443
+
444
+ # Checks if BotUser is allowed to do something on channel _chan_,
445
+ # or on all channels if _chan_ is nil
446
+ #
447
+ def permit?(cmd, chan=nil)
448
+ if chan
449
+ k = chan.to_s.to_sym
450
+ else
451
+ k = :*
452
+ end
453
+ allow = nil
454
+ pt = @perm.merge @perm_temp
455
+ if pt.has_key?(k)
456
+ allow = pt[k].permit?(cmd)
457
+ end
458
+ return allow
459
+ end
460
+
461
+ # Adds a Netmask
462
+ #
463
+ def add_netmask(mask)
464
+ m = mask.to_irc_netmask
465
+ @netmasks << m
466
+ if self.autologin?
467
+ Auth.manager.maskdb.add(self, m)
468
+ Auth.manager.logout_transients(m) if self.permanent?
469
+ end
470
+ end
471
+
472
+ # Removes a Netmask
473
+ #
474
+ def delete_netmask(mask)
475
+ m = mask.to_irc_netmask
476
+ @netmasks.delete(m)
477
+ Auth.manager.maskdb.remove(self, m) if self.autologin?
478
+ end
479
+
480
+ # Reset Netmasks, clearing @netmasks
481
+ #
482
+ def reset_netmasks
483
+ @netmasks.each { |m|
484
+ Auth.manager.maskdb.remove(self, m) if self.autologin?
485
+ }
486
+ @netmasks.clear
487
+ end
488
+
489
+ # This method checks if BotUser has a Netmask that matches _user_
490
+ #
491
+ def knows?(usr)
492
+ user = usr.to_irc_user
493
+ !!@netmasks.find { |n| user.matches? n }
494
+ end
495
+
496
+ # This method gets called when User _user_ wants to log in.
497
+ # It returns true or false depending on whether the password
498
+ # is right. If it is, the Netmask of the user is added to the
499
+ # list of acceptable Netmask unless it's already matched.
500
+ def login(user, password=nil)
501
+ if password == @password or (password.nil? and (@login_by_mask || @autologin) and knows?(user))
502
+ add_netmask(user) unless knows?(user)
503
+ debug "#{user} logged in as #{self.inspect}"
504
+ return true
505
+ else
506
+ return false
507
+ end
508
+ end
509
+
510
+ # # This method gets called when User _user_ has logged out as this BotUser
511
+ # def logout(user)
512
+ # delete_netmask(user) if knows?(user)
513
+ # end
514
+
515
+ # This method sanitizes a username by chomping, downcasing
516
+ # and replacing any nonalphanumeric character with _
517
+ #
518
+ def BotUser.sanitize_username(name)
519
+ candidate = name.to_s.chomp.downcase.gsub(/[^a-z0-9]/,"_")
520
+ raise "sanitized botusername #{candidate} too short" if candidate.length < 3
521
+ return candidate
522
+ end
523
+
524
+ end
525
+
526
+ # This is the default BotUser: it's used for all users which haven't
527
+ # identified with the bot
528
+ #
529
+ class DefaultBotUserClass < BotUser
530
+
531
+ private :add_netmask, :delete_netmask
532
+
533
+ include Singleton
534
+
535
+ # The default BotUser is named 'everyone'
536
+ #
537
+ def initialize
538
+ reset_login_by_mask
539
+ reset_autologin
540
+ super("everyone")
541
+ @default_perm = PermissionSet.new
542
+ end
543
+
544
+ # This method returns without changing anything
545
+ #
546
+ def login_by_mask=(val)
547
+ debug "Tried to change the login-by-mask for default bot user, ignoring"
548
+ return @login_by_mask
549
+ end
550
+
551
+ # The default botuser allows logins by mask
552
+ #
553
+ def reset_login_by_mask
554
+ @login_by_mask = true
555
+ end
556
+
557
+ # This method returns without changing anything
558
+ #
559
+ def autologin=(val)
560
+ debug "Tried to change the autologin for default bot user, ignoring"
561
+ return
562
+ end
563
+
564
+ # The default botuser doesn't allow autologin (meaningless)
565
+ #
566
+ def reset_autologin
567
+ @autologin = false
568
+ end
569
+
570
+ # Sets the default permission for the default user (i.e. the ones
571
+ # set by the BotModule writers) on all channels
572
+ #
573
+ def set_default_permission(cmd, val)
574
+ @default_perm.set_permission(Command.new(cmd), val)
575
+ debug "Default permissions now: #{@default_perm.pretty_inspect}"
576
+ end
577
+
578
+ # default knows everybody
579
+ #
580
+ def knows?(user)
581
+ return true if user.to_irc_user
582
+ end
583
+
584
+ # We always allow logging in as the default user
585
+ def login(user, password)
586
+ return true
587
+ end
588
+
589
+ # DefaultBotUser will check the default_perm after checking
590
+ # the global ones
591
+ # or on all channels if _chan_ is nil
592
+ #
593
+ def permit?(cmd, chan=nil)
594
+ allow = super(cmd, chan)
595
+ if allow.nil? && chan.nil?
596
+ allow = @default_perm.permit?(cmd)
597
+ end
598
+ return allow
599
+ end
600
+
601
+ end
602
+
603
+ # Returns the only instance of DefaultBotUserClass
604
+ #
605
+ def Auth.defaultbotuser
606
+ return DefaultBotUserClass.instance
607
+ end
608
+
609
+ # This is the BotOwner: he can do everything
610
+ #
611
+ class BotOwnerClass < BotUser
612
+
613
+ include Singleton
614
+
615
+ def initialize
616
+ @login_by_mask = false
617
+ @autologin = true
618
+ super("owner")
619
+ end
620
+
621
+ def permit?(cmd, chan=nil)
622
+ return true
623
+ end
624
+
625
+ end
626
+
627
+ # Returns the only instance of BotOwnerClass
628
+ #
629
+ def Auth.botowner
630
+ return BotOwnerClass.instance
631
+ end
632
+
633
+
634
+ class BotUser
635
+ # Check if the current BotUser is the default one
636
+ def default?
637
+ return DefaultBotUserClass === self
638
+ end
639
+
640
+ # Check if the current BotUser is the owner
641
+ def owner?
642
+ return BotOwnerClass === self
643
+ end
644
+ end
645
+
646
+
647
+ # This is the ManagerClass singleton, used to manage
648
+ # Irc::User/Irc::Bot::Auth::BotUser connections and everything
649
+ #
650
+ class ManagerClass
651
+
652
+ include Singleton
653
+
654
+ attr_reader :maskdb
655
+ attr_reader :everyone
656
+ attr_reader :botowner
657
+ attr_reader :bot
658
+
659
+ # The instance manages two <code>Hash</code>es: one that maps
660
+ # <code>Irc::User</code>s onto <code>BotUser</code>s, and the other that maps
661
+ # usernames onto <code>BotUser</code>
662
+ def initialize
663
+ @everyone = Auth::defaultbotuser
664
+ @botowner = Auth::botowner
665
+ bot_associate(nil)
666
+ end
667
+
668
+ def bot_associate(bot)
669
+ raise "Cannot associate with a new bot! Save first" if defined?(@has_changes) && @has_changes
670
+
671
+ reset_hashes
672
+
673
+ # Associated bot
674
+ @bot = bot
675
+
676
+ # This variable is set to true when there have been changes
677
+ # to the botusers list, so that we know when to save
678
+ @has_changes = false
679
+ end
680
+
681
+ def set_changed
682
+ @has_changes = true
683
+ end
684
+
685
+ def reset_changed
686
+ @has_changes = false
687
+ end
688
+
689
+ def changed?
690
+ @has_changes
691
+ end
692
+
693
+ # resets the hashes
694
+ def reset_hashes
695
+ @botusers = Hash.new
696
+ @maskdb = NetmaskDb.new
697
+ @allbotusers = Hash.new
698
+ [everyone, botowner].each do |x|
699
+ @allbotusers[x.username.to_sym] = x
700
+ end
701
+ end
702
+
703
+ def load_array(ary, forced)
704
+ unless ary
705
+ warning "Tried to load an empty array"
706
+ return
707
+ end
708
+ raise "Won't load with unsaved changes" if @has_changes and not forced
709
+ reset_hashes
710
+ ary.each { |x|
711
+ raise TypeError, "#{x} should be a Hash" unless x.kind_of?(Hash)
712
+ u = x[:username]
713
+ unless include?(u)
714
+ create_botuser(u)
715
+ end
716
+ get_botuser(u).from_hash(x)
717
+ get_botuser(u).transient = false
718
+ }
719
+ @has_changes=false
720
+ end
721
+
722
+ def save_array
723
+ @allbotusers.values.map { |x|
724
+ x.transient? ? nil : x.to_hash
725
+ }.compact
726
+ end
727
+
728
+ # checks if we know about a certain BotUser username
729
+ def include?(botusername)
730
+ @allbotusers.has_key?(botusername.to_sym)
731
+ end
732
+
733
+ # Maps <code>Irc::User</code> to BotUser
734
+ def irc_to_botuser(ircuser)
735
+ logged = @botusers[ircuser.to_irc_user]
736
+ return logged if logged
737
+ return autologin(ircuser)
738
+ end
739
+
740
+ # creates a new BotUser
741
+ def create_botuser(name, password=nil)
742
+ n = BotUser.sanitize_username(name)
743
+ k = n.to_sym
744
+ raise "botuser #{n} exists" if include?(k)
745
+ bu = BotUser.new(n)
746
+ bu.password = password
747
+ @allbotusers[k] = bu
748
+ return bu
749
+ end
750
+
751
+ # returns the botuser with name _name_
752
+ def get_botuser(name)
753
+ @allbotusers.fetch(BotUser.sanitize_username(name).to_sym)
754
+ end
755
+
756
+ # Logs Irc::User _user_ in to BotUser _botusername_ with password _pwd_
757
+ #
758
+ # raises an error if _botusername_ is not a known BotUser username
759
+ #
760
+ # It is possible to autologin by Netmask, on request
761
+ #
762
+ def login(user, botusername, pwd=nil)
763
+ ircuser = user.to_irc_user
764
+ n = BotUser.sanitize_username(botusername)
765
+ k = n.to_sym
766
+ raise "No such BotUser #{n}" unless include?(k)
767
+ if @botusers.has_key?(ircuser)
768
+ return true if @botusers[ircuser].username == n
769
+ # TODO
770
+ # @botusers[ircuser].logout(ircuser)
771
+ end
772
+ bu = @allbotusers[k]
773
+ if bu.login(ircuser, pwd)
774
+ @botusers[ircuser] = bu
775
+ return true
776
+ end
777
+ return false
778
+ end
779
+
780
+ # Tries to auto-login Irc::User _user_ by looking at the known botusers that allow autologin
781
+ # and trying to login without a password
782
+ #
783
+ def autologin(user)
784
+ ircuser = user.to_irc_user
785
+ debug "Trying to autologin #{ircuser}"
786
+ return @botusers[ircuser] if @botusers.has_key?(ircuser)
787
+ bu = maskdb.find(ircuser)
788
+ if bu
789
+ debug "trying #{bu}"
790
+ bu.login(ircuser) or raise '...what?!'
791
+ @botusers[ircuser] = bu
792
+ return bu
793
+ end
794
+ # Finally, create a transient if we're set to allow it
795
+ if @bot.config['auth.autouser']
796
+ bu = create_transient_botuser(ircuser)
797
+ @botusers[ircuser] = bu
798
+ return bu
799
+ end
800
+ return everyone
801
+ end
802
+
803
+ # Creates a new transient BotUser associated with Irc::User _user_,
804
+ # automatically logging him in. Note that transient botuser creation can
805
+ # fail, typically if we don't have the complete user netmask (e.g. for
806
+ # messages coming in from a linkbot)
807
+ #
808
+ def create_transient_botuser(user)
809
+ ircuser = user.to_irc_user
810
+ bu = everyone
811
+ begin
812
+ bu = BotUser.new(ircuser, :transient => true, :masks => ircuser)
813
+ bu.login(ircuser)
814
+ rescue
815
+ warning "failed to create transient for #{user}"
816
+ error $!
817
+ end
818
+ return bu
819
+ end
820
+
821
+ # Logs out any Irc::User matching Irc::Netmask _m_ and logged in
822
+ # to a transient BotUser
823
+ #
824
+ def logout_transients(m)
825
+ debug "to check: #{@botusers.keys.join ' '}"
826
+ @botusers.keys.each do |iu|
827
+ debug "checking #{iu.fullform} against #{m.fullform}"
828
+ bu = @botusers[iu]
829
+ bu.transient? or next
830
+ iu.matches?(m) or next
831
+ @botusers.delete(iu).autologin = false
832
+ end
833
+ end
834
+
835
+ # Makes transient BotUser _user_ into a permanent BotUser
836
+ # named _name_; if _user_ is an Irc::User, act on the transient
837
+ # BotUser (if any) it's logged in as
838
+ #
839
+ def make_permanent(user, name)
840
+ buname = BotUser.sanitize_username(name)
841
+ # TODO merge BotUser instead?
842
+ raise "there's already a BotUser called #{name}" if include?(buname)
843
+
844
+ tuser = nil
845
+ case user
846
+ when String, Irc::User
847
+ tuser = irc_to_botuser(user)
848
+ when BotUser
849
+ tuser = user
850
+ else
851
+ raise TypeError, "sorry, don't know how to make #{user.class} into a permanent BotUser"
852
+ end
853
+ return nil unless tuser
854
+ raise TypeError, "#{tuser} is not transient" unless tuser.transient?
855
+
856
+ tuser.make_permanent(buname)
857
+ @allbotusers[tuser.username.to_sym] = tuser
858
+
859
+ return tuser
860
+ end
861
+
862
+ # Checks if User _user_ can do _cmd_ on _chan_.
863
+ #
864
+ # Permission are checked in this order, until a true or false
865
+ # is returned:
866
+ # * associated BotUser on _chan_
867
+ # * associated BotUser on all channels
868
+ # * everyone on _chan_
869
+ # * everyone on all channels
870
+ #
871
+ def permit?(user, cmdtxt, channel=nil)
872
+ if user.class <= BotUser
873
+ botuser = user
874
+ else
875
+ botuser = irc_to_botuser(user)
876
+ end
877
+ cmd = cmdtxt.to_irc_auth_command
878
+
879
+ chan = channel
880
+ case chan
881
+ when User
882
+ chan = "?"
883
+ when Channel
884
+ chan = chan.name
885
+ end
886
+
887
+ allow = nil
888
+
889
+ allow = botuser.permit?(cmd, chan) if chan
890
+ return allow unless allow.nil?
891
+ allow = botuser.permit?(cmd)
892
+ return allow unless allow.nil?
893
+
894
+ unless botuser == everyone
895
+ allow = everyone.permit?(cmd, chan) if chan
896
+ return allow unless allow.nil?
897
+ allow = everyone.permit?(cmd)
898
+ return allow unless allow.nil?
899
+ end
900
+
901
+ raise "Could not check permission for user #{user.inspect} to run #{cmdtxt.inspect} on #{chan.inspect}"
902
+ end
903
+
904
+ # Checks if command _cmd_ is allowed to User _user_ on _chan_, optionally
905
+ # telling if the user is authorized
906
+ #
907
+ def allow?(cmdtxt, user, chan=nil)
908
+ if permit?(user, cmdtxt, chan)
909
+ return true
910
+ else
911
+ # cmds = cmdtxt.split('::')
912
+ # @bot.say chan, "you don't have #{cmds.last} (#{cmds.first}) permissions here" if chan
913
+ @bot.say chan, _("%{user}, you don't have '%{command}' permissions here") %
914
+ {:user=>user, :command=>cmdtxt} if chan
915
+ return false
916
+ end
917
+ end
918
+
919
+ end
920
+
921
+ # Returns the only instance of ManagerClass
922
+ #
923
+ def Auth.manager
924
+ return ManagerClass.instance
925
+ end
926
+
927
+ end
928
+ end
929
+
930
+ class User
931
+
932
+ # A convenience method to automatically found the botuser
933
+ # associated with the receiver
934
+ #
935
+ def botuser
936
+ Irc::Bot::Auth.manager.irc_to_botuser(self)
937
+ end
938
+ end
939
+
940
+ end