-
Notifications
You must be signed in to change notification settings - Fork 63
Creating a Birdwatcher Module
Creating a new module in Birdwatcher is pretty simple if you know a bit of Ruby. There a lot of helper methods and classes baked into Birdwatcher that you can use to output information to the console, querying the Twitter API, performing HTTP requests, natural language parsing of dates, and much more. A good place to start is to check out the documentation for the Birdwatcher::Module
class here.
All Birdwatcher modules live inside the lib/birdwatcher/modules directory. The main module directory is split up into sub directories that act as namespacing for the modules. If a module is manipulating users, it should live in the users/
directory. If it manipulates statuses, it should live in the statuses/
directory, and so on. The namespace directory and the filename without the .rb
extension will also automatically become the module's path that will be used to reference the module inside the console, so make sure you name the file in a descriptive way.
When you have found the right location for the new module, you can use this template to get a skeleton module up and running:
module Birdwatcher
module Modules
class MyNewModule < Birdwatcher::Module # Remember to rename the class
self.meta = {
:name => "My New Module",
:description => "Does something awesome.",
:author => "YOUR NAME <EMAIL>",
:options => {
"USERS" => { # Just an example option; remove if not needed
:value => nil,
:description => "Space-separated list of users to process (all users if empty)",
:required => false
}
}
}
def self.info
# This is where you put additional information about the module.
# It is optional to define this method, but encouraged to give helpful information.
end
def run
# This method is called when the user runs the module.
info("My New Module was executed!")
end
end
end
end
All modules should live inside the Birdwatcher::Modules
namespace and must be a subclass of the Birdwatcher::Module
class. This is also what makes all the helper methods available for you to use in the #run
method.
It is also required that all modules define a meta
hash which is used by the framework to display human readable information about the module. The meta hash must have the keys :name
, :description
, :author
and :options
. If any of these are missing, Birdwatcher will throw an error next time it is started. The :options
hash is where you define any options your module might need. The keys function as the option name and must be in UPPERCASE and the value hash is where you define any default value as well as a description and indication of wether the option is required to be set or not. The value hash must have the keys :default
, :description
and :required
. To get an idea of how to define these options, you can browse some of the existing modules.
The #run
method is where all the magic should happen. This method is called when a user issues the run
command for your module.
Here are some helper methods that might be useful to you:
To output information to the console, you can use the #info
, #warn
, #error
and #fatal
methods. They all require one argument which is the string you want to have outputted. The message will automatically get the right styling.
Another special method is the #task
method which is useful if you have a longer running job and want to indicate to the user that it's being worked on. The method accepts a message to display while the task is running and a code block to execute. Here is an example:
task("Doing something that takes a while...") do
do_long_running_task
end
When the code block is done executing, the method will append done after the message or failed in case an exception was raised inside the code block.
If your module is about to do something that you want the user to confirm (e.g. a destructive action like overriding a file), you can use the #confirm
method. It requires an argument which is the question to ask the user. The method will handle user input and return true
if the user said Yes or false
if the user said No:
if confirm("Do you want to divide by zero?")
0 / 0
end
If your module has defined any options, you can retrieve the value that the user has set with the #option_setting
method:
screen_names = option_setting("USERS").split(" ")
Please keep in mind that the method will only return the raw value that was given. You will have to handle type casting, splitting, etc.
Birdwatcher uses the excellent Twitter gem to communicate with the Twitter API. if you want to get a Twitter client, you can use the #twitter_client
method. This will automatically instantiate a new Twitter::REST::Client
configured with a random key pair from the configuration.
statuses = twitter_client.user_timeline("twitter")
The current workspace is an instance of Birdwatcher::Models::Workspace
which is a sub class of Sequel::Model
. The current workspace model instance can be accessed with the current_workspace
method:
users_in_workspace = current_workspace.users_dataset.order("screen_name")
For more information about how to work with Sequel models, have a look at the documentation.
If your module does a lot of work, you can speed things up with concurrent threads. The method #thread_pool
can give you a pool of threads to do the work in:
screen_names = option_setting("USERS").split(" ")
threads = thread_pool
screen_names.each do |screen_name|
threads.process do
do_something(screen_name)
end
end
threads.shutdown # Always remember the `#shutdown` call!
I hope this article gave you a bit of help getting started making your own Birdwatcher modules. Remember to check the documentation and go look at the code for existing modules for inspiration.