-
Notifications
You must be signed in to change notification settings - Fork 2
Plugin DSL
For plugin developers. See lib/plugin.rb for latest :)
You define plugins by making a file or directory in the plugins
folder. The name of the file or directory is the name of your plugin. The plugin DSL makes heavy use of blocks and closures. Checkout existing plugins for more examples and ideas.
The following methods are available to your plugin:
-
command([name=plugin.name],options={},&block)
Starts a new command block. If you don't give a name, it defaults to the plugin name.
-
resource([name=plugin.name],[options={}],[&block])
shortcut for setting up a command with default actions
-
action([name],[options={}],&callback)
create a new action for the current command (must be called within a command block). See Command DSL for more info.
-
timer(seconds, &callback)
-
_setup a timer. TODO: callback block has what params?
-
send(options={})
Send a message. Optionas are :to,:from,:html|:txt
-
on(event_name, &callback)
subscribe to an event
-
publish(event_name, args...)
publish an event
-
config(name,options,&block)
Specify a configuration option for your plugin. Options are :description and :default. The optional block param takes 3 args, |value,configured_value,default_value| and it is run whenever the config option is accessed. The result of the block is the value of the config option.
The following objects are in scope for you to reference in your plugin:
-
self
the plugin instance
-
plugin
deprecated
-
bot
the bot instance
-
config
access the config object. any properties you reference must have been setup with a config() DSL call from above, or an error will be raised.
Random notes about commands. Probably move this to its own page.
Typical pattern:
- <command> <action> <arg1>
- <command> <action> <arg1> <arg2>
- <command> <action> [<arg1>]
Often with a default action:
- <command> [<action>] # default no arg action
- <command> [<action>] <arg1> # default 1 arg (optional or required)
- <command> [<action>] <arg1> <arg2> # default 2 arg (optional or required)
- <command> [<action>] [<arg>] # default N arg (optional or required)
Each command syntax has a corresponding regex and behavior. We call this an action. For this to work, we must sort each action regex by [name>no-name (aka default action), then by higher required arity]. Something like:
- /^command\s+action\s+(.?)\s$/
- /^command\s+action\s*$/
- /^command\s+(.?)\s+(.?)\s*$/ ; run command.default($1,$2)
- /^command\s+(.?)\s$/ ; run command.default($1)
- /^command\s*$/ ; run command.default() note: lowest arity so must sort last
Only valid within command blocks.
description(str) : set the description for this command
aliases(alias1, alias2, ...) : set one or more aliases for this command
action([name],[options],&callback) : create an action. If no name, its a default action. Options are :required, :optional, :html, :is_public, :description. Callback block is called when the command/action regex matches the result of which are sent
This is a fun name :)
syntax:
- plugin [status]
- plugin [status] # show
- plugin enable
- plugin disable
code:
command do |cmd|
description 'manage plugins'
action :list, :default=>true do |msg|
end
action :show, :required=>:plugin, :default=>true do |msg,plugin|
end
action :enable, :optional=>:plugin do |msg,plugin|
end
action :disable, :required=>:plugin do |msg,plugin|
end
end
produces the following regexes:
- /^plugin\s+show\s+(.*)$/ # plugin.show($1)
- /^plugin\s+show\s+$/ # plugin.show()
- /^plugin\s+enable\s+(.*)$/ # plugin.enable($1)
- /^plugin\s+enable\s+(.*)$/ # plugin.disable($1)
- /^plugin\s+(.*)$/ # default, run plugin.show($1)
- /^plugin\s*$/ # default action, run first noarg plugin action
syntax:
- hot [trends]
- hot [search] <topic>
code:
command :hot do
description 'Whats hot on twitter'
action :trends, :default=>true do
format(popular())
end
action :search, :required=>:topic, :default=>true do |topic|
format(search(topic))
end
end
regexes:
- /^hot\s+trends\s*$/ # run hot.popular()
- /^hot\s+search\s+(.?)\s$/ # run hot.search($1)
- /^hot\s+(.?)\s$/ # run hot.search($1)
- /^hot\s*$/ # run hot.popular()
Commands with default actions that manage REST like resources.
The code:
resource :lunch do
action :custom, :default=>true do
(load_data||[]).sample
end
end
creates the following command syntax:
- lunch add # add new lunch
- lunch del # remove lunch
- lunch list # shows all lunch
- lunch # shows random from list, aka default action
which is equivalent to:
command :lunch do
description "foo"
action :list, :default=>true do
end
action :add, :alias=>[:+], :required=>:name do |msg,name|
end
action :delete, :alias=>[:del,:-] do
end
action :custom, :default=>true do
"Custom response"
end
end
- check action callback arity, and don't pass the msg unless arty is 1 greater than action arty
- better handle conflict on helpers (better scoping somehow?)