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,1063 @@
1
+ #-- vim:sw=2:et
2
+ #++
3
+ #
4
+ # :title: rbot auth management from IRC
5
+ #
6
+ # Author:: Giuseppe "Oblomov" Bilotta <giuseppe.bilotta@gmail.com>
7
+
8
+ class AuthModule < CoreBotModule
9
+
10
+ def initialize
11
+ super
12
+
13
+ # The namespace migration causes each Irc::Auth::PermissionSet to be
14
+ # unrecoverable, and we have to rename their class name to
15
+ # Irc::Bot::Auth::PermissionSet
16
+ @registry.recovery = Proc.new { |val|
17
+ patched = val.sub("o:\035Irc::Auth::PermissionSet", "o:\042Irc::Bot::Auth::PermissionSet")
18
+ Marshal.restore(patched)
19
+ }
20
+
21
+ load_array(:default, true)
22
+ debug "initialized auth. Botusers: #{@bot.auth.save_array.pretty_inspect}"
23
+ end
24
+
25
+ def save
26
+ save_array
27
+ end
28
+
29
+ def save_array(key=:default)
30
+ if @bot.auth.changed?
31
+ @registry[key] = @bot.auth.save_array
32
+ @bot.auth.reset_changed
33
+ debug "saved botusers (#{key}): #{@registry[key].pretty_inspect}"
34
+ end
35
+ end
36
+
37
+ def load_array(key=:default, forced=false)
38
+ debug "loading botusers (#{key}): #{@registry[key].pretty_inspect}"
39
+ @bot.auth.load_array(@registry[key], forced) if @registry.has_key?(key)
40
+ if @bot.auth.botowner.password != @bot.config['auth.password']
41
+ error "Master password is out of sync!"
42
+ debug " db password: #{@bot.auth.botowner.password}"
43
+ debug "conf password: #{@bot.config['auth.password']}"
44
+ error "Using conf password"
45
+ @bot.auth.botowner.password = @bot.config['auth.password']
46
+ end
47
+ end
48
+
49
+ # The permission parameters accept arguments with the following syntax:
50
+ # cmd_path... [on #chan .... | in here | in private]
51
+ # This auxiliary method scans the array _ar_ to see if it matches
52
+ # the given syntax: it expects + or - signs in front of _cmd_path_
53
+ # elements when _setting_ = true
54
+ #
55
+ # It returns an array whose first element is the array of cmd_path,
56
+ # the second element is an array of locations and third an array of
57
+ # warnings occurred while parsing the strings
58
+ #
59
+ def parse_args(ar, setting)
60
+ cmds = []
61
+ locs = []
62
+ warns = []
63
+ doing_cmds = true
64
+ next_must_be_chan = false
65
+ want_more = false
66
+ last_idx = 0
67
+ ar.each_with_index { |x, i|
68
+ if doing_cmds # parse cmd_path
69
+ # check if the list is done
70
+ if x == "on" or x == "in"
71
+ doing_cmds = false
72
+ next_must_be_chan = true if x == "on"
73
+ next
74
+ end
75
+ if "+-".include?(x[0])
76
+ warns << ArgumentError.new(_("please do not use + or - in front of command %{command} when resetting") % {:command => x}) unless setting
77
+ else
78
+ warns << ArgumentError.new(_("+ or - expected in front of %{string}") % {:string => x}) if setting
79
+ end
80
+ cmds << x
81
+ else # parse locations
82
+ if x[-1].chr == ','
83
+ want_more = true
84
+ else
85
+ want_more = false
86
+ end
87
+ case next_must_be_chan
88
+ when false
89
+ locs << x.gsub(/^here$/,'_').gsub(/^private$/,'?')
90
+ else
91
+ warns << ArgumentError.new(_("'%{string}' doesn't look like a channel name") % {:string => x}) unless @bot.server.supports[:chantypes].include?(x[0])
92
+ locs << x
93
+ end
94
+ unless want_more
95
+ last_idx = i
96
+ break
97
+ end
98
+ end
99
+ }
100
+ warns << _("trailing comma") if want_more
101
+ warns << _("you probably forgot a comma") unless last_idx == ar.length - 1
102
+ return cmds, locs, warns
103
+ end
104
+
105
+ def auth_edit_perm(m, params)
106
+
107
+ setting = m.message.split[1] == "set"
108
+ splits = params[:args]
109
+
110
+ has_for = splits[-2] == "for"
111
+ return usage(m) unless has_for
112
+
113
+ begin
114
+ user = @bot.auth.get_botuser(splits[-1].sub(/^all$/,"everyone"))
115
+ rescue
116
+ return m.reply(_("couldn't find botuser %{name}") % {:name => splits[-1]})
117
+ end
118
+ return m.reply(_("you can't change permissions for %{username}") % {:username => user.username}) if user.owner?
119
+ splits.slice!(-2,2) if has_for
120
+
121
+ cmds, locs, warns = parse_args(splits, setting)
122
+ errs = warns.select { |w| w.kind_of?(Exception) }
123
+
124
+ unless errs.empty?
125
+ m.reply _("couldn't satisfy your request: %{errors}") % {:errors => errs.join(',')}
126
+ return
127
+ end
128
+
129
+ if locs.empty?
130
+ locs << "*"
131
+ end
132
+ begin
133
+ locs.each { |loc|
134
+ ch = loc
135
+ if m.private?
136
+ ch = "?" if loc == "_"
137
+ else
138
+ ch = m.target.to_s if loc == "_"
139
+ end
140
+ cmds.each { |setval|
141
+ if setting
142
+ val = setval[0].chr == '+'
143
+ cmd = setval[1..-1]
144
+ user.set_permission(cmd, val, ch)
145
+ else
146
+ cmd = setval
147
+ user.reset_permission(cmd, ch)
148
+ end
149
+ }
150
+ }
151
+ rescue => e
152
+ m.reply "something went wrong while trying to set the permissions"
153
+ raise
154
+ end
155
+ @bot.auth.set_changed
156
+ debug "user #{user} permissions changed"
157
+ m.okay
158
+ end
159
+
160
+ def auth_view_perm(m, params)
161
+ begin
162
+ if params[:user].nil?
163
+ user = get_botusername_for(m.source)
164
+ return m.reply(_("you are owner, you can do anything")) if user.owner?
165
+ else
166
+ user = @bot.auth.get_botuser(params[:user].sub(/^all$/,"everyone"))
167
+ return m.reply(_("owner can do anything")) if user.owner?
168
+ end
169
+ rescue
170
+ return m.reply(_("couldn't find botuser %{name}") % {:name => params[:user]})
171
+ end
172
+ perm = user.perm
173
+ str = []
174
+ perm.each { |k, val|
175
+ next if val.perm.empty?
176
+ case k
177
+ when :*
178
+ str << _("on any channel: ")
179
+ when :"?"
180
+ str << _("in private: ")
181
+ else
182
+ str << _("on #{k}: ")
183
+ end
184
+ sub = []
185
+ val.perm.each { |cmd, bool|
186
+ sub << (bool ? "+" : "-")
187
+ sub.last << cmd.to_s
188
+ }
189
+ str.last << sub.join(', ')
190
+ }
191
+ if str.empty?
192
+ m.reply _("no permissions set for %{user}") % {:user => user.username}
193
+ else
194
+ m.reply _("permissions for %{user}:: %{permissions}") %
195
+ { :user => user.username, :permissions => str.join('; ')}
196
+ end
197
+ end
198
+
199
+ def auth_search_perm(m, p)
200
+ pattern = Regexp.new(p[:pattern].to_s)
201
+ results = @bot.plugins.maps.select { |k, v| k.match(pattern) }
202
+ count = results.length
203
+ max = @bot.config['send.max_lines']
204
+ extra = (count > max ? _(". only %{max} will be shown") : "") % { :max => max }
205
+ m.reply _("%{count} commands found matching %{pattern}%{extra}") % {
206
+ :count => count, :pattern => pattern, :extra => extra
207
+ }
208
+ return if count == 0
209
+ results[0,max].each { |cmd, hash|
210
+ m.reply _("%{cmd}: %{perms}") % {
211
+ :cmd => cmd,
212
+ :perms => hash[:auth].join(", ")
213
+ }
214
+ }
215
+ end
216
+
217
+ def find_auth(pseudo)
218
+ k = pseudo.plugin.intern
219
+ cmds = @bot.plugins.commands
220
+ auth = nil
221
+ if cmds.has_key?(k)
222
+ cmds[k][:botmodule].handler.each do |tmpl|
223
+ options, failure = tmpl.recognize(pseudo)
224
+ next if options.nil?
225
+ auth = tmpl.options[:full_auth_path]
226
+ break
227
+ end
228
+ end
229
+ return auth
230
+ end
231
+
232
+ def auth_allow_deny(m, p)
233
+ begin
234
+ botuser = @bot.auth.get_botuser(p[:user].sub(/^all$/,"everyone"))
235
+ rescue
236
+ return m.reply(_("couldn't find botuser %{name}") % {:name => p[:user]})
237
+ end
238
+
239
+ if p[:where].to_s.empty?
240
+ where = :*
241
+ else
242
+ where = m.parse_channel_list(p[:where].to_s).first # should only be one anyway
243
+ end
244
+
245
+ # pseudo-message to find the template. The source is ignored, and the
246
+ # target is set according to where the template should be checked
247
+ # (public or private)
248
+ # This might still fail in the case of 'everywhere' for commands there are
249
+ # really only private
250
+ case where
251
+ when :"?"
252
+ pseudo_target = @bot.myself
253
+ when :*
254
+ pseudo_target = m.channel
255
+ else
256
+ pseudo_target = m.server.channel(where)
257
+ end
258
+
259
+ pseudo = PrivMessage.new(bot, m.server, m.source, pseudo_target, p[:stuff].to_s)
260
+
261
+ auth_path = find_auth(pseudo)
262
+ debug auth_path
263
+
264
+ if auth_path
265
+ allow = p[:allow]
266
+ if @bot.auth.permit?(botuser, auth_path, where)
267
+ return m.reply(_("%{user} can already do that") % {:user => botuser}) if allow
268
+ else
269
+ return m.reply(_("%{user} can't do that already") % {:user => botuser}) if !allow
270
+ end
271
+ cmd = PrivMessage.new(bot, m.server, m.source, m.target, "permissions set %{sign}%{path} %{where} for %{user}" % {
272
+ :path => auth_path,
273
+ :user => p[:user],
274
+ :sign => (allow ? '+' : '-'),
275
+ :where => p[:where].to_s
276
+ })
277
+ handle(cmd)
278
+ else
279
+ m.reply(_("sorry, %{cmd} doesn't look like a valid command. maybe you misspelled it, or you need to specify it should be in private?") % {
280
+ :cmd => p[:stuff].to_s
281
+ })
282
+ end
283
+ end
284
+
285
+ def auth_allow(m, p)
286
+ auth_allow_deny(m, p.merge(:allow => true))
287
+ end
288
+
289
+ def auth_deny(m, p)
290
+ auth_allow_deny(m, p.merge(:allow => false))
291
+ end
292
+
293
+ def get_botuser_for(user)
294
+ @bot.auth.irc_to_botuser(user)
295
+ end
296
+
297
+ def get_botusername_for(user)
298
+ get_botuser_for(user).username
299
+ end
300
+
301
+ def say_welcome(m)
302
+ m.reply _("welcome, %{user}") % {:user => get_botusername_for(m.source)}
303
+ end
304
+
305
+ def auth_auth(m, params)
306
+ params[:botuser] = 'owner'
307
+ auth_login(m,params)
308
+ end
309
+
310
+ def auth_login(m, params)
311
+ begin
312
+ case @bot.auth.login(m.source, params[:botuser], params[:password])
313
+ when true
314
+ say_welcome(m)
315
+ @bot.auth.set_changed
316
+ else
317
+ m.reply _("sorry, can't do")
318
+ end
319
+ rescue => e
320
+ m.reply _("couldn't login: %{exception}") % {:exception => e}
321
+ raise
322
+ end
323
+ end
324
+
325
+ def auth_autologin(m, params)
326
+ u = do_autologin(m.source)
327
+ if u.default?
328
+ m.reply _("I couldn't find anything to let you login automatically")
329
+ else
330
+ say_welcome(m)
331
+ end
332
+ end
333
+
334
+ def do_autologin(user)
335
+ @bot.auth.autologin(user)
336
+ end
337
+
338
+ def auth_whoami(m, params)
339
+ m.reply _("you are %{who}") % {
340
+ :who => get_botusername_for(m.source).gsub(
341
+ /^everyone$/, _("no one that I know")).gsub(
342
+ /^owner$/, _("my boss"))
343
+ }
344
+ end
345
+
346
+ def auth_whois(m, params)
347
+ return auth_whoami(m, params) if !m.public?
348
+ u = m.channel.users[params[:user]]
349
+
350
+ return m.reply("I don't see anyone named '#{params[:user]}' here") unless u
351
+
352
+ m.reply _("#{params[:user]} is %{who}") % {
353
+ :who => get_botusername_for(u).gsub(
354
+ /^everyone$/, _("no one that I know")).gsub(
355
+ /^owner$/, _("my boss"))
356
+ }
357
+ end
358
+
359
+ def help(cmd, topic="")
360
+ case cmd
361
+ when "login"
362
+ return _("login [<botuser>] [<pass>]: logs in to the bot as botuser <botuser> with password <pass>. When using the full form, you must contact the bot in private. <pass> can be omitted if <botuser> allows login-by-mask and your netmask is among the known ones. if <botuser> is omitted too autologin will be attempted")
363
+ when "whoami"
364
+ return _("whoami: names the botuser you're linked to")
365
+ when "who"
366
+ return _("who is <user>: names the botuser <user> is linked to")
367
+ when /^permission/
368
+ case topic
369
+ when "syntax"
370
+ return _("a permission is specified as module::path::to::cmd; when you want to enable it, prefix it with +; when you want to disable it, prefix it with -; when using the +reset+ command, do not use any prefix")
371
+ when "set", "reset", "[re]set", "(re)set"
372
+ return _("permissions [re]set <permission> [in <channel>] for <user>: sets or resets the permissions for botuser <user> in channel <channel> (use ? to change the permissions for private addressing)")
373
+ when "view"
374
+ return _("permissions view [for <user>]: display the permissions for user <user>")
375
+ when "search"
376
+ return _("permissions search <pattern>: display the permissions associated with the commands matching <pattern>")
377
+ else
378
+ return _("permission topics: syntax, (re)set, view, search")
379
+ end
380
+ when "user"
381
+ case topic
382
+ when "show"
383
+ return _("user show <what> : shows info about the user; <what> can be any of autologin, login-by-mask, netmasks")
384
+ when /^(en|dis)able/
385
+ return _("user enable|disable <what> : turns on or off <what> (autologin, login-by-mask)")
386
+ when "set"
387
+ return _("user set password <blah> : sets the user password to <blah>; passwords can only contain upper and lowercase letters and numbers, and must be at least 4 characters long")
388
+ when "add", "rm"
389
+ return _("user add|rm netmask <mask> : adds/removes netmask <mask> from the list of netmasks known to the botuser you're linked to")
390
+ when "reset"
391
+ return _("user reset <what> : resets <what> to the default values. <what> can be +netmasks+ (the list will be emptied), +autologin+ or +login-by-mask+ (will be reset to the default value) or +password+ (a new one will be generated and you'll be told in private)")
392
+ when "tell"
393
+ return _("user tell <who> the password for <botuser> : contacts <who> in private to tell him/her the password for <botuser>")
394
+ when "create"
395
+ return _("user create <name> <password> : create botuser named <name> with password <password>. The password can be omitted, in which case a random one will be generated. The <name> should only contain alphanumeric characters and the underscore (_)")
396
+ when "list"
397
+ return _("user list : lists all the botusers")
398
+ when "destroy"
399
+ return _("user destroy <botuser> : destroys <botuser>. This function %{highlight}must%{highlight} be called in two steps. On the first call <botuser> is queued for destruction. On the second call, which must be in the form 'user confirm destroy <botuser>', the botuser will be destroyed. If you want to cancel the destruction, issue the command 'user cancel destroy <botuser>'") % {:highlight => Bold}
400
+ else
401
+ return _("user topics: show, enable|disable, add|rm netmask, set, reset, tell, create, list, destroy")
402
+ end
403
+ when "auth"
404
+ return _("auth <masterpassword>: log in as the bot owner; other commands: login, whoami, permissions syntax, permissions [re]set, permissions view, user, meet, hello, allow, prevent")
405
+ when "meet"
406
+ return _("meet <nick> [as <user>]: creates a bot user for nick, calling it user (defaults to the nick itself)")
407
+ when "hello"
408
+ return _("hello: creates a bot user for the person issuing the command")
409
+ when "allow"
410
+ return _("allow <user> to do <sample command> [<where>]: gives botuser <user> the permissions to execute a command such as the provided sample command (in private or in channel, according to the optional <where>)")
411
+ when "deny"
412
+ return _("deny <user> from doing <sample command> [<where>]: removes from botuser <user> the permissions to execute a command such as the provided sample command (in private or in channel, according to the optional <where>)")
413
+ else
414
+ return _("auth commands: auth, login, whoami, who, permission[s], user, meet, hello, allow, deny")
415
+ end
416
+ end
417
+
418
+ def need_args(cmd)
419
+ _("sorry, I need more arguments to %{command}") % {:command => cmd}
420
+ end
421
+
422
+ def not_args(cmd, *stuff)
423
+ _("I can only %{command} these: %{arguments}") %
424
+ {:command => cmd, :arguments => stuff.join(', ')}
425
+ end
426
+
427
+ def set_prop(botuser, prop, val)
428
+ k = prop.to_s.gsub("-","_")
429
+ botuser.send( (k + "=").to_sym, val)
430
+ if prop == :password and botuser == @bot.auth.botowner
431
+ @bot.config.items[:'auth.password'].set_string(@bot.auth.botowner.password)
432
+ end
433
+ end
434
+
435
+ def reset_prop(botuser, prop)
436
+ k = prop.to_s.gsub("-","_")
437
+ botuser.send( ("reset_"+k).to_sym)
438
+ end
439
+
440
+ def ask_bool_prop(botuser, prop)
441
+ k = prop.to_s.gsub("-","_")
442
+ botuser.send( (k + "?").to_sym)
443
+ end
444
+
445
+ def auth_manage_user(m, params)
446
+ splits = params[:data]
447
+
448
+ cmd = splits.first
449
+ return auth_whoami(m, params) if cmd.nil?
450
+
451
+ botuser = get_botuser_for(m.source)
452
+ # By default, we do stuff on the botuser the irc user is bound to
453
+ butarget = botuser
454
+
455
+ has_for = splits[-2] == "for"
456
+ if has_for
457
+ butarget = @bot.auth.get_botuser(splits[-1]) rescue nil
458
+ return m.reply(_("no such bot user %{user}") % {:user => splits[-1]}) unless butarget
459
+ splits.slice!(-2,2)
460
+ end
461
+ return m.reply(_("you can't mess with %{user}") % {:user => butarget.username}) if butarget.owner? && botuser != butarget
462
+
463
+ bools = [:autologin, :"login-by-mask"]
464
+ can_set = [:password]
465
+ can_addrm = [:netmasks]
466
+ can_reset = bools + can_set + can_addrm
467
+ can_show = can_reset + ["perms"]
468
+
469
+ begin
470
+ case cmd.to_sym
471
+
472
+ when :show
473
+ return m.reply(_("you can't see the properties of %{user}") %
474
+ {:user => butarget.username}) if botuser != butarget &&
475
+ !botuser.permit?("auth::show::other")
476
+
477
+ case splits[1]
478
+ when nil, "all"
479
+ props = can_reset
480
+ when "password"
481
+ if botuser != butarget
482
+ return m.reply(_("no way I'm telling you the master password!")) if butarget == @bot.auth.botowner
483
+ return m.reply(_("you can't ask for someone else's password"))
484
+ end
485
+ return m.reply(_("c'mon, you can't be asking me seriously to tell you the password in public!")) if m.public?
486
+ return m.reply(_("the password for %{user} is %{password}") %
487
+ { :user => butarget.username, :password => butarget.password })
488
+ else
489
+ props = splits[1..-1]
490
+ end
491
+
492
+ str = []
493
+
494
+ props.each { |arg|
495
+ k = arg.to_sym
496
+ next if k == :password
497
+ case k
498
+ when *bools
499
+ if ask_bool_prop(butarget, k)
500
+ str << _("can %{action}") % {:action => k}
501
+ else
502
+ str << _("can not %{action}") % {:action => k}
503
+ end
504
+ when :netmasks
505
+ if butarget.netmasks.empty?
506
+ str << _("knows no netmasks")
507
+ else
508
+ str << _("knows %{netmasks}") % {:netmasks => butarget.netmasks.join(", ")}
509
+ end
510
+ end
511
+ }
512
+ return m.reply("#{butarget.username} #{str.join('; ')}")
513
+
514
+ when :enable, :disable
515
+ return m.reply(_("you can't change the default user")) if butarget.default? && !botuser.permit?("auth::edit::other::default")
516
+ return m.reply(_("you can't edit %{user}") % {:user => butarget.username}) if butarget != botuser && !botuser.permit?("auth::edit::other")
517
+
518
+ return m.reply(need_args(cmd)) unless splits[1]
519
+ things = []
520
+ skipped = []
521
+ splits[1..-1].each { |a|
522
+ arg = a.to_sym
523
+ if bools.include?(arg)
524
+ set_prop(butarget, arg, cmd.to_sym == :enable)
525
+ things << a
526
+ else
527
+ skipped << a
528
+ end
529
+ }
530
+
531
+ m.reply(_("I ignored %{things} because %{reason}") % {
532
+ :things => skipped.join(', '),
533
+ :reason => not_args(cmd, *bools)}) unless skipped.empty?
534
+ if things.empty?
535
+ m.reply _("I haven't changed anything")
536
+ else
537
+ @bot.auth.set_changed
538
+ return auth_manage_user(m, {:data => ["show"] + things + ["for", butarget.username] })
539
+ end
540
+
541
+ when :set
542
+ return m.reply(_("you can't change the default user")) if
543
+ butarget.default? && !botuser.permit?("auth::edit::default")
544
+ return m.reply(_("you can't edit %{user}") % {:user=>butarget.username}) if
545
+ butarget != botuser && !botuser.permit?("auth::edit::other")
546
+
547
+ return m.reply(need_args(cmd)) unless splits[1]
548
+ arg = splits[1].to_sym
549
+ return m.reply(not_args(cmd, *can_set)) unless can_set.include?(arg)
550
+ argarg = splits[2]
551
+ return m.reply(need_args([cmd, splits[1]].join(" "))) unless argarg
552
+ if arg == :password && m.public?
553
+ return m.reply(_("is that a joke? setting the password in public?"))
554
+ end
555
+ set_prop(butarget, arg, argarg)
556
+ @bot.auth.set_changed
557
+ auth_manage_user(m, {:data => ["show", arg.to_s, "for", butarget.username] })
558
+
559
+ when :reset
560
+ return m.reply(_("you can't change the default user")) if
561
+ butarget.default? && !botuser.permit?("auth::edit::default")
562
+ return m.reply(_("you can't edit %{user}") % {:user=>butarget.username}) if
563
+ butarget != botuser && !botuser.permit?("auth::edit::other")
564
+
565
+ return m.reply(need_args(cmd)) unless splits[1]
566
+ things = []
567
+ skipped = []
568
+ splits[1..-1].each { |a|
569
+ arg = a.to_sym
570
+ if can_reset.include?(arg)
571
+ reset_prop(butarget, arg)
572
+ things << a
573
+ else
574
+ skipped << a
575
+ end
576
+ }
577
+
578
+ m.reply(_("I ignored %{things} because %{reason}") %
579
+ { :things => skipped.join(', '),
580
+ :reason => not_args(cmd, *can_reset)}) unless skipped.empty?
581
+ if things.empty?
582
+ m.reply _("I haven't changed anything")
583
+ else
584
+ @bot.auth.set_changed
585
+ @bot.say(m.source, _("the password for %{user} is now %{password}") %
586
+ {:user => butarget.username, :password => butarget.password}) if
587
+ things.include?("password")
588
+ return auth_manage_user(m, {:data => (["show"] + things - ["password"]) + ["for", butarget.username]})
589
+ end
590
+
591
+ when :add, :rm, :remove, :del, :delete
592
+ return m.reply(_("you can't change the default user")) if
593
+ butarget.default? && !botuser.permit?("auth::edit::default")
594
+ return m.reply(_("you can't edit %{user}") % {:user => butarget.username}) if
595
+ butarget != botuser && !botuser.permit?("auth::edit::other")
596
+
597
+ arg = splits[1]
598
+ if arg.nil? or arg !~ /netmasks?/ or splits[2].nil?
599
+ return m.reply(_("I can only add/remove netmasks. See +help user add+ for more instructions"))
600
+ end
601
+
602
+ method = cmd.to_sym == :add ? :add_netmask : :delete_netmask
603
+
604
+ failed = []
605
+
606
+ splits[2..-1].each { |mask|
607
+ begin
608
+ butarget.send(method, mask.to_irc_netmask(:server => @bot.server))
609
+ rescue => e
610
+ debug "failed with #{e.message}"
611
+ debug e.backtrace.join("\n")
612
+ failed << mask
613
+ end
614
+ }
615
+ m.reply "I failed to #{cmd} #{failed.join(', ')}" unless failed.empty?
616
+ @bot.auth.set_changed
617
+ return auth_manage_user(m, {:data => ["show", "netmasks", "for", butarget.username] })
618
+
619
+ else
620
+ m.reply _("sorry, I don't know how to %{request}") % {:request => m.message}
621
+ end
622
+ rescue => e
623
+ m.reply _("couldn't %{cmd}: %{exception}") % {:cmd => cmd, :exception => e}
624
+ end
625
+ end
626
+
627
+ def auth_meet(m, params)
628
+ nick = params[:nick]
629
+ if !nick
630
+ # we are actually responding to a 'hello' command
631
+ unless m.botuser.transient?
632
+ m.reply @bot.lang.get('hello_X') % m.botuser
633
+ return
634
+ end
635
+ nick = m.sourcenick
636
+ irc_user = m.source
637
+ else
638
+ # m.channel is always an Irc::Channel because the command is either
639
+ # public-only 'meet' or private/public 'hello' which was handled by
640
+ # the !nick case, so this shouldn't fail
641
+ irc_user = m.channel.users[nick]
642
+ return m.reply("I don't see anyone named '#{nick}' here") unless irc_user
643
+ end
644
+ # BotUser name
645
+ buname = params[:user] || nick
646
+ begin
647
+ call_event(:botuser,:pre_perm, {:irc_user => irc_user, :bot_user => buname})
648
+ met = @bot.auth.make_permanent(irc_user, buname)
649
+ @bot.auth.set_changed
650
+ call_event(:botuser,:post_perm, {:irc_user => irc_user, :bot_user => buname})
651
+ m.reply @bot.lang.get('hello_X') % met
652
+ @bot.say nick, _("you are now registered as %{buname}. I created a random password for you : %{pass} and you can change it at any time by telling me 'user set password <password>' in private" % {
653
+ :buname => buname,
654
+ :pass => met.password
655
+ })
656
+ rescue RuntimeError
657
+ # or can this happen for other cases too?
658
+ # TODO autologin if forced
659
+ m.reply _("but I already know %{buname}" % {:buname => buname})
660
+ rescue => e
661
+ m.reply _("I had problems meeting %{nick}: %{e}" % { :nick => nick, :e => e })
662
+ end
663
+ end
664
+
665
+ def auth_tell_password(m, params)
666
+ user = params[:user]
667
+ begin
668
+ botuser = @bot.auth.get_botuser(params[:botuser])
669
+ rescue
670
+ return m.reply(_("couldn't find botuser %{user}") % {:user => params[:botuser]})
671
+ end
672
+ return m.reply(_("I'm not telling the master password to anyone, pal")) if botuser == @bot.auth.botowner
673
+ msg = _("the password for botuser %{user} is %{password}") %
674
+ {:user => botuser.username, :password => botuser.password}
675
+ @bot.say user, msg
676
+ @bot.say m.source, _("I told %{user} that %{message}") % {:user => user, :message => msg}
677
+ end
678
+
679
+ def auth_create_user(m, params)
680
+ name = params[:name]
681
+ password = params[:password]
682
+ return m.reply(_("are you nuts, creating a botuser with a publicly known password?")) if m.public? and not password.nil?
683
+ begin
684
+ bu = @bot.auth.create_botuser(name, password)
685
+ @bot.auth.set_changed
686
+ rescue => e
687
+ m.reply(_("failed to create %{user}: %{exception}") % {:user => name, :exception => e})
688
+ debug e.inspect + "\n" + e.backtrace.join("\n")
689
+ return
690
+ end
691
+ m.reply(_("created botuser %{user}") % {:user => bu.username})
692
+ end
693
+
694
+ def auth_list_users(m, params)
695
+ # TODO name regexp to filter results
696
+ list = @bot.auth.save_array.inject([]) { |list, x| ['everyone', 'owner'].include?(x[:username]) ? list : list << x[:username] }
697
+ if defined?(@destroy_q)
698
+ list.map! { |x|
699
+ @destroy_q.include?(x) ? x + _(" (queued for destruction)") : x
700
+ }
701
+ end
702
+ return m.reply(_("I have no botusers other than the default ones")) if list.empty?
703
+ return m.reply(n_("botuser: %{list}", "botusers: %{list}", list.length) %
704
+ {:list => list.join(', ')})
705
+ end
706
+
707
+ def auth_destroy_user(m, params)
708
+ @destroy_q = [] unless defined?(@destroy_q)
709
+ buname = params[:name]
710
+ return m.reply(_("You can't destroy %{user}") % {:user => buname}) if
711
+ ["everyone", "owner"].include?(buname)
712
+ mod = params[:modifier].to_sym rescue nil
713
+
714
+ buser_array = @bot.auth.save_array
715
+ buser_hash = buser_array.inject({}) { |h, u|
716
+ h[u[:username]] = u
717
+ h
718
+ }
719
+
720
+ return m.reply(_("no such botuser %{user}") % {:user=>buname}) unless
721
+ buser_hash.keys.include?(buname)
722
+
723
+ case mod
724
+ when :cancel
725
+ if @destroy_q.include?(buname)
726
+ @destroy_q.delete(buname)
727
+ m.reply(_("%{user} removed from the destruction queue") % {:user=>buname})
728
+ else
729
+ m.reply(_("%{user} was not queued for destruction") % {:user=>buname})
730
+ end
731
+ return
732
+ when nil
733
+ if @destroy_q.include?(buname)
734
+ return m.reply(_("%{user} already queued for destruction, use %{highlight}user confirm destroy %{user}%{highlight} to destroy it") % {:user=>buname, :highlight=>Bold})
735
+ else
736
+ @destroy_q << buname
737
+ return m.reply(_("%{user} queued for destruction, use %{highlight}user confirm destroy %{user}%{highlight} to destroy it") % {:user=>buname, :highlight=>Bold})
738
+ end
739
+ when :confirm
740
+ begin
741
+ return m.reply(_("%{user} is not queued for destruction yet") %
742
+ {:user=>buname}) unless @destroy_q.include?(buname)
743
+ buser_array.delete_if { |u|
744
+ u[:username] == buname
745
+ }
746
+ @destroy_q.delete(buname)
747
+ @bot.auth.load_array(buser_array, true)
748
+ @bot.auth.set_changed
749
+ rescue => e
750
+ return m.reply(_("failed: %{exception}") % {:exception => e})
751
+ end
752
+ return m.reply(_("botuser %{user} destroyed") % {:user => buname})
753
+ end
754
+ end
755
+
756
+ def auth_copy_ren_user(m, params)
757
+ source = Auth::BotUser.sanitize_username(params[:source])
758
+ dest = Auth::BotUser.sanitize_username(params[:dest])
759
+ return m.reply(_("please don't touch the default users")) unless
760
+ (["everyone", "owner"] & [source, dest]).empty?
761
+
762
+ buser_array = @bot.auth.save_array
763
+ buser_hash = buser_array.inject({}) { |h, u|
764
+ h[u[:username]] = u
765
+ h
766
+ }
767
+
768
+ return m.reply(_("no such botuser %{source}") % {:source=>source}) unless
769
+ buser_hash.keys.include?(source)
770
+ return m.reply(_("botuser %{dest} exists already") % {:dest=>dest}) if
771
+ buser_hash.keys.include?(dest)
772
+
773
+ copying = m.message.split[1] == "copy"
774
+ begin
775
+ if copying
776
+ h = {}
777
+ buser_hash[source].each { |k, val|
778
+ h[k] = val.dup
779
+ }
780
+ else
781
+ h = buser_hash[source]
782
+ end
783
+ h[:username] = dest
784
+ buser_array << h if copying
785
+
786
+ @bot.auth.load_array(buser_array, true)
787
+ @bot.auth.set_changed
788
+ call_event(:botuser, copying ? :copy : :rename, :source => source, :dest => dest)
789
+ rescue => e
790
+ return m.reply(_("failed: %{exception}") % {:exception=>e})
791
+ end
792
+ if copying
793
+ m.reply(_("botuser %{source} copied to %{dest}") %
794
+ {:source=>source, :dest=>dest})
795
+ else
796
+ m.reply(_("botuser %{source} renamed to %{dest}") %
797
+ {:source=>source, :dest=>dest})
798
+ end
799
+
800
+ end
801
+
802
+ def auth_export(m, params)
803
+
804
+ exportfile = "#{@bot.botclass}/new-auth.users"
805
+
806
+ what = params[:things]
807
+
808
+ has_to = what[-2] == "to"
809
+ if has_to
810
+ exportfile = "#{@bot.botclass}/#{what[-1]}"
811
+ what.slice!(-2,2)
812
+ end
813
+
814
+ what.delete("all")
815
+
816
+ m.reply _("selecting data to export ...")
817
+
818
+ buser_array = @bot.auth.save_array
819
+ buser_hash = buser_array.inject({}) { |h, u|
820
+ h[u[:username]] = u
821
+ h
822
+ }
823
+
824
+ if what.empty?
825
+ we_want = buser_hash
826
+ else
827
+ we_want = buser_hash.delete_if { |key, val|
828
+ not what.include?(key)
829
+ }
830
+ end
831
+
832
+ m.reply _("preparing data for export ...")
833
+ begin
834
+ yaml_hash = {}
835
+ we_want.each { |k, val|
836
+ yaml_hash[k] = {}
837
+ val.each { |kk, v|
838
+ case kk
839
+ when :username
840
+ next
841
+ when :netmasks
842
+ yaml_hash[k][kk] = []
843
+ v.each { |nm|
844
+ yaml_hash[k][kk] << {
845
+ :fullform => nm.fullform,
846
+ :casemap => nm.casemap.to_s
847
+ }
848
+ }
849
+ else
850
+ yaml_hash[k][kk] = v
851
+ end
852
+ }
853
+ }
854
+ rescue => e
855
+ m.reply _("failed to prepare data: %{exception}") % {:exception=>e}
856
+ debug e.backtrace.dup.unshift(e.inspect).join("\n")
857
+ return
858
+ end
859
+
860
+ m.reply _("exporting to %{file} ...") % {:file=>exportfile}
861
+ begin
862
+ # m.reply yaml_hash.inspect
863
+ File.open(exportfile, "w") do |file|
864
+ file.puts YAML::dump(yaml_hash)
865
+ end
866
+ rescue => e
867
+ m.reply _("failed to export users: %{exception}") % {:exception=>e}
868
+ debug e.backtrace.dup.unshift(e.inspect).join("\n")
869
+ return
870
+ end
871
+ m.reply _("done")
872
+ end
873
+
874
+ def auth_import(m, params)
875
+
876
+ importfile = "#{@bot.botclass}/new-auth.users"
877
+
878
+ what = params[:things]
879
+
880
+ has_from = what[-2] == "from"
881
+ if has_from
882
+ importfile = "#{@bot.botclass}/#{what[-1]}"
883
+ what.slice!(-2,2)
884
+ end
885
+
886
+ what.delete("all")
887
+
888
+ m.reply _("reading %{file} ...") % {:file=>importfile}
889
+ begin
890
+ yaml_hash = YAML::load_file(importfile)
891
+ rescue => e
892
+ m.reply _("failed to import from: %{exception}") % {:exception=>e}
893
+ debug e.backtrace.dup.unshift(e.inspect).join("\n")
894
+ return
895
+ end
896
+
897
+ # m.reply yaml_hash.inspect
898
+
899
+ m.reply _("selecting data to import ...")
900
+
901
+ if what.empty?
902
+ we_want = yaml_hash
903
+ else
904
+ we_want = yaml_hash.delete_if { |key, val|
905
+ not what.include?(key)
906
+ }
907
+ end
908
+
909
+ m.reply _("parsing data from import ...")
910
+
911
+ buser_hash = {}
912
+
913
+ begin
914
+ yaml_hash.each { |k, val|
915
+ buser_hash[k] = { :username => k }
916
+ val.each { |kk, v|
917
+ case kk
918
+ when :netmasks
919
+ buser_hash[k][kk] = []
920
+ v.each { |nm|
921
+ buser_hash[k][kk] << nm[:fullform].to_irc_netmask(:casemap => nm[:casemap].to_irc_casemap).to_irc_netmask(:server => @bot.server)
922
+ }
923
+ else
924
+ buser_hash[k][kk] = v
925
+ end
926
+ }
927
+ }
928
+ rescue => e
929
+ m.reply _("failed to parse data: %{exception}") % {:exception=>e}
930
+ debug e.backtrace.dup.unshift(e.inspect).join("\n")
931
+ return
932
+ end
933
+
934
+ # m.reply buser_hash.inspect
935
+
936
+ org_buser_array = @bot.auth.save_array
937
+ org_buser_hash = org_buser_array.inject({}) { |h, u|
938
+ h[u[:username]] = u
939
+ h
940
+ }
941
+
942
+ # TODO we may want to do a(n optional) key-by-key merge
943
+ #
944
+ org_buser_hash.merge!(buser_hash)
945
+ new_buser_array = org_buser_hash.values
946
+ @bot.auth.load_array(new_buser_array, true)
947
+ @bot.auth.set_changed
948
+
949
+ m.reply _("done")
950
+ end
951
+
952
+ end
953
+
954
+ auth = AuthModule.new
955
+
956
+ auth.map "user export *things",
957
+ :action => 'auth_export',
958
+ :defaults => { :things => ['all'] },
959
+ :auth_path => ':manage:fedex:'
960
+
961
+ auth.map "user import *things",
962
+ :action => 'auth_import',
963
+ :auth_path => ':manage:fedex:'
964
+
965
+ auth.map "user create :name :password",
966
+ :action => 'auth_create_user',
967
+ :defaults => {:password => nil},
968
+ :auth_path => ':manage:'
969
+
970
+ auth.map "user [:modifier] destroy :name",
971
+ :action => 'auth_destroy_user',
972
+ :requirements => { :modifier => /^(cancel|confirm)?$/ },
973
+ :defaults => { :modifier => '' },
974
+ :auth_path => ':manage::destroy!'
975
+
976
+ auth.map "user copy :source [to] :dest",
977
+ :action => 'auth_copy_ren_user',
978
+ :auth_path => ':manage:'
979
+
980
+ auth.map "user rename :source [to] :dest",
981
+ :action => 'auth_copy_ren_user',
982
+ :auth_path => ':manage:'
983
+
984
+ auth.map "meet :nick [as :user]",
985
+ :action => 'auth_meet',
986
+ :auth_path => 'user::manage', :private => false
987
+
988
+ auth.map "hello",
989
+ :action => 'auth_meet',
990
+ :auth_path => 'user::manage::meet'
991
+
992
+ auth.default_auth("user::manage", false)
993
+ auth.default_auth("user::manage::meet::hello", true)
994
+
995
+ auth.map "user tell :user the password for :botuser",
996
+ :action => 'auth_tell_password',
997
+ :auth_path => ':manage:'
998
+
999
+ auth.map "user list",
1000
+ :action => 'auth_list_users',
1001
+ :auth_path => '::'
1002
+
1003
+ auth.map "user *data",
1004
+ :action => 'auth_manage_user'
1005
+
1006
+ auth.map "allow :user to do *stuff [*where]",
1007
+ :action => 'auth_allow',
1008
+ :requirements => {:where => /^(?:anywhere|everywhere|[io]n \S+)$/},
1009
+ :auth_path => ':edit::other:'
1010
+
1011
+ auth.map "deny :user from doing *stuff [*where]",
1012
+ :action => 'auth_deny',
1013
+ :requirements => {:where => /^(?:anywhere|everywhere|[io]n \S+)$/},
1014
+ :auth_path => ':edit::other:'
1015
+
1016
+ auth.default_auth("user", true)
1017
+ auth.default_auth("edit::other", false)
1018
+
1019
+ auth.map "whoami",
1020
+ :action => 'auth_whoami',
1021
+ :auth_path => '!*!'
1022
+
1023
+ auth.map "who is :user",
1024
+ :action => 'auth_whois',
1025
+ :auth_path => '!*!'
1026
+
1027
+ auth.map "auth :password",
1028
+ :action => 'auth_auth',
1029
+ :public => false,
1030
+ :auth_path => '!login!'
1031
+
1032
+ auth.map "login :botuser :password",
1033
+ :action => 'auth_login',
1034
+ :public => false,
1035
+ :defaults => { :password => nil },
1036
+ :auth_path => '!login!'
1037
+
1038
+ auth.map "login :botuser",
1039
+ :action => 'auth_login',
1040
+ :auth_path => '!login!'
1041
+
1042
+ auth.map "login",
1043
+ :action => 'auth_autologin',
1044
+ :auth_path => '!login!'
1045
+
1046
+ auth.map "permissions set *args",
1047
+ :action => 'auth_edit_perm',
1048
+ :auth_path => ':edit::set:'
1049
+
1050
+ auth.map "permissions reset *args",
1051
+ :action => 'auth_edit_perm',
1052
+ :auth_path => ':edit::set:'
1053
+
1054
+ auth.map "permissions view [for :user]",
1055
+ :action => 'auth_view_perm',
1056
+ :auth_path => '::'
1057
+
1058
+ auth.map "permissions search *pattern",
1059
+ :action => 'auth_search_perm',
1060
+ :auth_path => '::'
1061
+
1062
+ auth.default_auth('*', false)
1063
+