butler 1.8.1 → 1.8.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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.