butler 1.8.1 → 1.8.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (71) hide show
  1. data/CHANGELOG.txt +212 -0
  2. data/{README → README.txt} +0 -0
  3. data/Rakefile +16 -11
  4. data/bin/botcontrol +35 -14
  5. data/data/butler/dialogs/create.rb +29 -40
  6. data/data/butler/dialogs/create_config.rb +1 -1
  7. data/data/butler/dialogs/dir.rb +13 -0
  8. data/data/butler/dialogs/en/create.yaml +24 -10
  9. data/data/butler/dialogs/en/dir.yaml +5 -0
  10. data/data/butler/dialogs/en/help.yaml +28 -11
  11. data/data/butler/dialogs/en/quickcreate.yaml +14 -0
  12. data/data/butler/dialogs/help.rb +16 -4
  13. data/data/butler/dialogs/quickcreate.rb +49 -0
  14. data/data/butler/plugins/core/access.rb +211 -0
  15. data/data/butler/plugins/core/logout.rb +11 -11
  16. data/data/butler/plugins/core/plugins.rb +23 -41
  17. data/data/butler/plugins/dev/bleakhouse.rb +46 -0
  18. data/data/butler/plugins/games/roll.rb +1 -1
  19. data/data/butler/plugins/operator/deop.rb +15 -20
  20. data/data/butler/plugins/operator/devoice.rb +14 -20
  21. data/data/butler/plugins/operator/limit.rb +56 -21
  22. data/data/butler/plugins/operator/op.rb +15 -20
  23. data/data/butler/plugins/operator/voice.rb +15 -20
  24. data/data/butler/plugins/service/define.rb +3 -3
  25. data/data/butler/plugins/service/more.rb +40 -0
  26. data/data/butler/plugins/util/cycle.rb +1 -1
  27. data/data/butler/plugins/util/load.rb +5 -5
  28. data/data/butler/plugins/util/pong.rb +3 -2
  29. data/lib/access/privilege.rb +17 -0
  30. data/lib/access/role.rb +33 -2
  31. data/lib/access/savable.rb +6 -0
  32. data/lib/access/yamlbase.rb +1 -2
  33. data/lib/butler/bot.rb +40 -7
  34. data/lib/butler/debuglog.rb +17 -0
  35. data/lib/butler/dialog.rb +1 -1
  36. data/lib/butler/irc/{channels.rb → channellist.rb} +2 -2
  37. data/lib/butler/irc/client.rb +60 -79
  38. data/lib/butler/irc/client/filter.rb +12 -0
  39. data/lib/butler/irc/client/listener.rb +55 -0
  40. data/lib/butler/irc/client/listenerlist.rb +69 -0
  41. data/lib/butler/irc/hostmask.rb +31 -16
  42. data/lib/butler/irc/message.rb +3 -3
  43. data/lib/butler/irc/parser.rb +2 -2
  44. data/lib/butler/irc/parser/rfc2812.rb +2 -6
  45. data/lib/butler/irc/socket.rb +12 -6
  46. data/lib/butler/irc/string.rb +4 -0
  47. data/lib/butler/irc/user.rb +0 -6
  48. data/lib/butler/irc/{users.rb → userlist.rb} +2 -2
  49. data/lib/butler/irc/whois.rb +6 -0
  50. data/lib/butler/plugin.rb +48 -14
  51. data/lib/butler/plugin/configproxy.rb +20 -0
  52. data/lib/butler/plugin/mapper.rb +308 -24
  53. data/lib/butler/plugin/matcher.rb +3 -1
  54. data/lib/butler/plugin/more.rb +65 -0
  55. data/lib/butler/plugin/onhandlers.rb +4 -4
  56. data/lib/butler/plugin/trigger.rb +4 -2
  57. data/lib/butler/plugins.rb +1 -1
  58. data/lib/butler/session.rb +11 -0
  59. data/lib/butler/version.rb +1 -1
  60. data/lib/cloptions.rb +1 -1
  61. data/lib/diagnostics.rb +20 -0
  62. data/lib/dialogline.rb +1 -1
  63. data/lib/durations.rb +19 -6
  64. data/lib/event.rb +8 -5
  65. data/lib/installer.rb +10 -3
  66. data/lib/ostructfixed.rb +11 -0
  67. data/lib/ruby/kernel/daemonize.rb +1 -2
  68. data/test/butler/plugin/mapper.rb +46 -0
  69. metadata +28 -11
  70. data/CHANGELOG +0 -44
  71. data/data/butler/plugins/core/privilege.rb +0 -103
@@ -1,6 +1,6 @@
1
1
  begin
2
2
  user = variables.user || variables.botcontrol.user
3
- variables.botcontrol.configure_user unless variables.botcontrol.configured?(user)
3
+ variables.botcontrol.configure_user(user) unless variables.botcontrol.configured?(user)
4
4
  Butler.path = variables.botcontrol.butler_path
5
5
  rescue Errno::EACCES
6
6
  say :cant_configure, :user => user, :app => $0
@@ -0,0 +1,13 @@
1
+ if !variables.botcontrol.configured? then
2
+ say(:not_configured)
3
+ elsif !Butler.exists?(nil, variables.botname)
4
+ say(:no_such_bot, :botname => variables.botname)
5
+ else
6
+ bot = Butler.new(nil, variables.botname)
7
+ path = variables.dirname.to_sym
8
+ if path = bot.path[path]
9
+ say(:path, :dirname => variables.dirname, :path => path)
10
+ else
11
+ say(:no_such_dir, :dirname => variables.dirname)
12
+ end
13
+ end
@@ -1,11 +1,25 @@
1
1
  ---
2
- :name: "Please choose a name for the bot (alphanumeric characters only)"
3
- :delete_existing: "A bot named <%= name %> already exists, do you wish to delete it"
4
- :quicksetup: "Do you wish to do a quick configuration (you can use '<%= $0 %> config <%= name %>' any time)"
5
- :server: "Servername to connect to"
6
- :language: "The main language"
7
- :channels: "Comma separated list of channels to join on login"
8
- :user: "Please choose a username for the bot-admin"
9
- :pass: "The password for the bot-admin"
10
- :nickpass: "The password for the nick (empty if not registered)"
11
- :how_to_start: "You can now start your bot using '<%= $0 %> start <%= name %>'"
2
+ :sudo_user: "You are running 'create' with sudo, botcontrol will create the bot for <%= ENV['SUDO_USER'] %>, continue"
3
+ :name: "Please choose a name for the bot (alphanumeric characters only)"
4
+ :delete_existing: "A bot named <%= name %> already exists, do you wish to delete it"
5
+ :quicksetup: "Do you wish to do a quick configuration (you can use '<%= $0 %> config <%= name %>' any time)"
6
+ :server: "Servername to connect to"
7
+ :port: "Port to connect on"
8
+ :connect_delay: "Delay before trying to reconnect"
9
+ :connect_tries: "Number of tries to reconnect"
10
+ :server_encoding: "Main charset-encoding of the server"
11
+ :language: "The main language"
12
+ :nick: "Nickname of the bot"
13
+ :user: "Username of the bot"
14
+ :real: "Realname of the bot"
15
+ :nickpass: "The password for the nick (empty if not registered)"
16
+ :channels: "Comma separated list of channels to join on login"
17
+ :config_channel: "Configuration for channel <%= name %>"
18
+ :channel_password: "Password to join the channel"
19
+ :channel_language: "Language in the channel"
20
+ :channel_encoding: "Charset encoding used in the channel"
21
+ :admin_user: "Please choose a username for the bot-admin"
22
+ :admin_pass: "The password for the bot-admin"
23
+ :how_to_start: |
24
+ You can now start your bot using '<%= $0 %> start <%= name %>'.
25
+ You can then authenticate as administrator of the bot in irc using '/msg <%= botname %> login <%= user %> <%= pass %>'.
@@ -0,0 +1,5 @@
1
+ ---
2
+ :not_configured: "Your user is not configured yet."
3
+ :no_such_bot: "No bot named <%= name %> found."
4
+ :no_such_dir: "No path info for path <%= dirname %>."
5
+ :path: "Path to <%= dirname %>: <%= path %>"
@@ -2,16 +2,33 @@
2
2
  :help: |-
3
3
  This is the tool to administrate your irc-bots.
4
4
  The the following commands are available:
5
- -create: create a new bot
6
- -start: start an existing bot
7
- -stop: stop a running bot
8
- -rename: rename an existing bot
9
- -config: configure an existing bot
10
- -delete: delete an existing bot
11
- -list: list all existing bots
12
- -backup: make a backup of an existing bot
13
- -help: you're looking at it"
5
+ backup: make a backup of an existing bot
6
+ config: configure an existing bot
7
+ create: create a new bot
8
+ delete: delete an existing bot
9
+ dir: shows directories to specific parts of a specific bot
10
+ help: get help about a command or a topic
11
+ info: displays information about user, bots and paths
12
+ interactive: run botcontrol interactively
13
+ log: browse the logs of a bot
14
+ list: list all existing bots
15
+ rename: rename an existing bot
16
+ setup: setup botcontrol for usage
17
+ start: start one of your bots
18
+ stop: stop a running bot
19
+ sync_plugins: sync the plugins of a bot with your local repository
20
+ uninstall: uninstall butler
14
21
  :tutorial: The tutorial is on http://butler.rubyforge.org/tutorial
15
22
  :plugins: You can download plugins from http://rubyforge.org/frs/?group_id=1349
16
- :manual: The manual is on http://butler.rubyforge.org/manual
17
- :home: Butlers home is on http://butler.rubyforge.org/
23
+ :manual: The manual is on http://butler.rubyforge.org/manual.html
24
+ :home: Butlers home is on http://butler.rubyforge.org/
25
+ :topics: |-
26
+ Available help topics are:
27
+ backup info setup
28
+ config interactive start
29
+ create log stop
30
+ delete list sync_plugins
31
+ dir manual tutorial
32
+ help plugins uninstall
33
+ home rename
34
+ :unknown: The command <%= name %> is not known, use 'help topics' to get a list of help topics.
@@ -0,0 +1,14 @@
1
+ ---
2
+ :sudo_user: "You are running 'create' with sudo, botcontrol will create the bot for <%= ENV['SUDO_USER'] %>, continue"
3
+ :name: "Please choose a name for the bot (alphanumeric characters only)"
4
+ :delete_existing: "A bot named <%= name %> already exists, do you wish to delete it"
5
+ :quicksetup: "Do you wish to do a quick configuration (you can use '<%= $0 %> config <%= name %>' any time)"
6
+ :server: "Servername to connect to"
7
+ :language: "The main language"
8
+ :channels: "Comma separated list of channels to join on login"
9
+ :user: "Please choose a username for the bot-admin"
10
+ :pass: "The password for the bot-admin"
11
+ :nickpass: "The password for the nick (empty if not registered)"
12
+ :how_to_start: |
13
+ You can now start your bot using '<%= $0 %> start <%= name %>'.
14
+ You can then authenticate as administrator of the bot in irc using '/msg <%= botname %> login <%= user %> <%= pass %>'.
@@ -1,10 +1,22 @@
1
1
  if variables.command then
2
2
  case variables.command
3
- when "tutorial": say(:tutorial)
4
- when "documentation": say(:documentation)
5
- when "plugins": say(:plugins)
3
+ when "manual": say(:manual)
4
+ when "plugins": say(:plugins)
5
+ when "topics": say(:topics)
6
+ when "tutorial": say(:tutorial)
6
7
  else
7
- variables.options[variables.command].help
8
+ if found = variables.options[variables.command] then
9
+ options = found.help.sub(/.*?\n.*?\n/,'').gsub(/^/, ' ')
10
+ puts found.usage
11
+ if options.strip.empty? then
12
+ puts "Command doesn't have options"
13
+ else
14
+ puts "Options:\n"
15
+ puts options
16
+ end
17
+ else
18
+ say(:unknown, :name => variables.command)
19
+ end
8
20
  end
9
21
  else
10
22
  say(:help)
@@ -0,0 +1,49 @@
1
+ exit if ENV["SUDO_USER"] && !prompt(:sudo_user, false)
2
+ name = variables.name
3
+ while Butler.exists?(nil, name)
4
+ if prompt(:delete_existing, false)
5
+ Butler.delete(nil, name)
6
+ else
7
+ name = ask(:name, "butler", String, :matching => /\A[A-Za-z0-9_]+\z/)
8
+ end
9
+ end
10
+ Butler.create(nil, name)
11
+ bot = Butler.new(nil, name)
12
+
13
+ nick = name
14
+ bot.config["connections/main/server"] = server=ask(:server, "irc.freenode.org", String, :min => 3)
15
+ bot.config["connections/main/port"] = 6667
16
+ bot.config["connections/main/host"] = nil
17
+ bot.config["connections/main/reconnect_delay"] = 60
18
+ bot.config["connections/main/reconnect_tries"] = -1
19
+ bot.config["connections/main/charset"] = 'utf-8'
20
+ bot.config["connections/main/language"] = lang=ask(:language, "en", String, :matching => /\A#[A-Za-z0-9_-]{2,40}\z/)
21
+ bot.config["connections/main/nick"] = name
22
+ bot.config["connections/main/alternative"] = name[0,7]+"_"
23
+ bot.config["connections/main/user"] = name
24
+ bot.config["connections/main/real"] = name+" (Butler IRC bot)"
25
+ bot.config["connections/main/password"] = ask(:nickpass, nil, String)
26
+ bot.config["connections/main/identify"] = :auto
27
+ bot.config["connections/main/channels"] = channels=ask(:channels, (server == "irc.freenode.org" ? ["#butler"] : nil), Array, String, :matching => /\A#[^\0\s,]+\z/)
28
+ channels.each { |channel|
29
+ prefix = "channels/#{server.config_key}/#{channel.config_key}"
30
+ bot.config["#{prefix}/password"] = nil
31
+ bot.config["#{prefix}/language"] = lang
32
+ bot.config["#{prefix}/charset"] = 'utf-8'
33
+ }
34
+ user = ask(:user, nil, String, :min => 3)
35
+ pass = ask(:pass, nil, String, :min => 3)
36
+ admin = bot.access.user.create(user, pass, nil, true, :active => true)
37
+ role = bot.access.role.create("default_role", "This role is applied to every user")
38
+ role.privileges.add(%w[
39
+ plugin/public
40
+ plugin/core/login
41
+ plugin/core/logout
42
+ plugin/core/help
43
+ plugin/core/usage
44
+ ])
45
+ user = bot.access.user.create("default_user", nil, nil, false, :active => true)
46
+ user.roles.add(%w[default_role])
47
+
48
+ puts
49
+ say(:how_to_start, :botname => nick, :user => user, :pass => pass)
@@ -0,0 +1,211 @@
1
+ #--
2
+ # Copyright 2007 by Stefan Rusterholz.
3
+ # All rights reserved.
4
+ # See LICENSE.txt for permissions.
5
+ #++
6
+
7
+
8
+
9
+ # add/remove privileges to/from roles
10
+
11
+ def user
12
+ @butler.access.user
13
+ end
14
+
15
+ def role
16
+ @butler.access.role
17
+ end
18
+
19
+ def on_users(params)
20
+ users = params.grep ? user.keys : user.keys.grep(/#{params.grep}/)
21
+ answer(:userlist, :list => users)
22
+ end
23
+
24
+ # "create user :username"
25
+ def on_create_user(params)
26
+ name, pass, active = @message.arguments[2,3]
27
+ params.username.downcase!
28
+ if user.exists?(params.username) then
29
+ answer(:user_already_exists, :username => params.username)
30
+ else
31
+ user.create(
32
+ params.username,
33
+ params.password,
34
+ nil,
35
+ false,
36
+ :active => !!params.active
37
+ )
38
+ user[params.username].roles.add("default_role")
39
+ answer(:user_created, :username => params.username)
40
+ end
41
+ end
42
+
43
+ # "delete user :username"
44
+ def on_delete_user(params)
45
+ params.username.downcase!
46
+ if user.exists?(params.username) then
47
+ user.delete(params.username)
48
+ answer(:user_deleted, :username => params.username)
49
+ else
50
+ answer(:user_doesnt_exist, :username => params.username)
51
+ end
52
+ end
53
+
54
+ def on_create_role(params)
55
+ params.rolename.downcase!
56
+ return answer(:role_already_exists, :rolename => params.rolename) if role.exists?(params.rolename)
57
+ role.create(params.rolename, params.description)
58
+ answer(:role_created, :rolename => params.rolename)
59
+ end
60
+
61
+ def on_delete_role(params)
62
+ params.rolename.downcase!
63
+ return answer(:role_doesnt_exist, :rolename => params.rolename) unless role.exists?(params.rolename)
64
+ role.delete(params.rolename)
65
+ answer(:role_deleted, :rolename => params.rolename)
66
+ end
67
+
68
+ # "grant privilege :privilege to user :username"
69
+ def on_grant_privilege_to_user(params)
70
+ params.username.downcase!
71
+ return answer(:user_doesnt_exist, :username => params.username) unless user.exists?(params.username)
72
+ user[params.username].privileges.add(params.privilege)
73
+ answer(:privilege_granted_to_user, :username => params.username, :privilege => params.privilege)
74
+ end
75
+
76
+ # "revoke privilege :privilege from user :username"
77
+ def on_revoke_privilege_from_user(params)
78
+ params.username.downcase!
79
+ return answer(:user_doesnt_exist, :username => params.username) unless user.exists?(params.username)
80
+ user[params.username].privileges.remove(params.privilege)
81
+ answer(:privilege_revoked_from_user, :username => params.username, :privilege => params.privilege)
82
+ end
83
+
84
+ # "grant privilege :privilege to role :username"
85
+ def on_grant_privilege_to_role(params)
86
+ params.rolename.downcase!
87
+ return answer(:role_doesnt_exist, :rolename => params.rolename) unless role.exists?(params.rolename)
88
+ role[params.rolename].privileges.add(role[params.privilege])
89
+ answer(:privilege_granted_to_role, :rolename => params.rolename, :privilege => params.privilege)
90
+ end
91
+
92
+ # "revoke privilege :privilege from role :username"
93
+ def on_revoke_privilege_from_role(params)
94
+ params.rolename.downcase!
95
+ return answer(:role_doesnt_exist, :rolename => params.rolename) unless role.exists?(params.rolename)
96
+ role[params.rolename].privileges.remove(role[params.privilege])
97
+ answer(:privilege_revoked_from_role, :rolename => params.rolename, :privilege => params.privilege)
98
+ end
99
+
100
+ # "add role :role to user :username"
101
+ def on_add_role_to_user(params)
102
+ params.username.downcase!
103
+ params.rolename.downcase!
104
+ return answer(:user_doesnt_exist, :username => params.username) unless user.exists?(params.username)
105
+ return answer(:role_doesnt_exist, :username => params.rolename) unless role.exists?(params.rolename)
106
+ user[params.username].roles.add(role[params.rolename])
107
+ answer(:role_added_to_user, :username => params.username, :rolename => params.rolename)
108
+ end
109
+
110
+ # "remove role :role from user :username"
111
+ def on_remove_role_from_user(params)
112
+ params.username.downcase!
113
+ params.rolename.downcase!
114
+ return answer(:user_doesnt_exist, :username => params.username) unless user.exists?(params.username)
115
+ return answer(:role_doesnt_exist, :username => params.rolename) unless role.exists?(params.rolename)
116
+ user[params.username].roles.remove(role[params.rolename])
117
+ answer(:role_removed_from_user, :username => params.username, :rolename => params.rolename)
118
+ end
119
+
120
+ def on_set_my_password(params)
121
+
122
+ end
123
+
124
+ __END__
125
+ ---
126
+ :about:
127
+ :mail: "apeiros@gmx.net"
128
+ :version: "1.0.0"
129
+ :author: "Stefan Rusterholz"
130
+ :help:
131
+ en:
132
+ "": |
133
+ Manage your users, roles and privileges.
134
+ :map:
135
+ :on_users:
136
+ en: "show all users [matching :grep]"
137
+ :on_set_my_password:
138
+ en: "set my password to :newpassword"
139
+ :on_create_user:
140
+ en: "create user :username [with password :password] [:active{active}]"
141
+ :on_delete_user:
142
+ en: "delete user :rolename"
143
+ :on_create_role:
144
+ en: "create role :rolename [with description +description]"
145
+ :on_delete_role:
146
+ en: "delete role :rolename"
147
+ :on_activate_user:
148
+ en: "activate user :username"
149
+ :on_deactivate_user:
150
+ en: "deactivate user :username"
151
+ :on_grant_privilege_to_user:
152
+ en: "grant privilege :privilege to user :username"
153
+ :on_revoke_privilege_from_user:
154
+ en: "revoke privilege :privilege from user :username"
155
+ :on_grant_privilege_to_role:
156
+ en: "grant privilege :privilege to role :rolename"
157
+ :on_revoke_privilege_from_role:
158
+ en: "revoke privilege :privilege from role :rolename"
159
+ :on_add_role_to_user:
160
+ en: "add role :rolename to user :username"
161
+ :on_remove_role_from_user:
162
+ en: "remove role :rolename from user :username"
163
+ :on_add_role_to_role:
164
+ en: "add role :rolename to role :rolename2"
165
+ :on_remove_role_from_role:
166
+ en: "remove role :rolename from role :rolename2"
167
+ :revision:
168
+ :plugin: 1
169
+ :strings:
170
+ :userlist:
171
+ en: "<%= list.columnize(5) %>"
172
+ :activated:
173
+ en: "Activated user <%= username %>."
174
+ :deactivated:
175
+ en: "Deactivated user <%= username %>."
176
+ :user_already_exists:
177
+ en: "User <%= username %> exists already."
178
+ :user_doesnt_exist:
179
+ en: "User <%= username %> does not exist."
180
+ :user_created:
181
+ en: "Created user <%= username %>."
182
+ :user_deleted:
183
+ en: "Deleted user <%= username %>."
184
+ :role_already_exists:
185
+ en: "Role <%= rolename %> exists already."
186
+ :role_doesnt_exist:
187
+ en: "Role <%= rolename %> does not exist."
188
+ :role_created:
189
+ en: "Created role <%= rolename %>."
190
+ :role_deleted:
191
+ en: "Deleted role <%= rolename %>."
192
+ :privilege_granted_to_user:
193
+ en: "Granted privilege <%= privilege %> to user <%= username %>."
194
+ :privilege_revoked_from_user:
195
+ en: "Revoked privilege <%= privilege %> from user <%= username %>."
196
+ :privilege_granted_to_role:
197
+ en: "Granted privilege <%= privilege %> to role <%= rolename %>."
198
+ :privilege_revoked_from_role:
199
+ en: "Revoked privilege <%= privilege %> from role <%= rolename %>."
200
+ :role_added_to_user:
201
+ en: "Added role <%= rolename %> to user <%= username %>."
202
+ :role_removed_from_user:
203
+ en: "Removed role <%= rolename %> from user <%= username %>."
204
+ :role_added_to_role:
205
+ en: "Added role <%= rolename %> to role <%= rolename2 %>."
206
+ :role_removed_from_role:
207
+ en: "Removed role <%= rolename %> from role <%= rolename2 %>."
208
+ :summary:
209
+ en: "Manage your users."
210
+ :usage:
211
+ en: "see help access commands for all commands access provides."
@@ -6,8 +6,6 @@
6
6
 
7
7
 
8
8
 
9
- trigger "logout"
10
-
11
9
  def on_trigger
12
10
  if @butler.access.default_user == @message.from.access then
13
11
  answer(:not_logged_in)
@@ -19,23 +17,25 @@ end
19
17
 
20
18
  __END__
21
19
  ---
22
- :revision:
23
- :plugin: 1
24
- :summary:
25
- en: "Log out from the bot"
26
20
  :about:
27
21
  :mail: "apeiros@gmx.net"
28
22
  :version: "1.0.0"
29
23
  :author: "Stefan Rusterholz"
24
+ :help:
25
+ en:
26
+ "": |
27
+ Using 'logout' you can log out from the bot.
28
+ Use it in order to prevent other people from abusing your account while you are not on your computer.
29
+ :revision:
30
+ :plugin: 2
31
+ :summary:
32
+ en: "Log out from the bot"
30
33
  :strings:
31
34
  :success:
32
35
  en: "You are now logged out."
33
36
  :not_logged_in:
34
37
  en: "You are not logged in, can't log you out."
38
+ :trigger:
39
+ en: logout
35
40
  :usage:
36
41
  en: "![b]logout![o]"
37
- :help:
38
- en:
39
- "": |
40
- Using 'logout' you can log out from the bot.
41
- Use it in order to prevent other people from abusing your account while you are not on your computer.