RISCfuture / autumn

Easy, fresh, feature-rich IRC bots in Ruby

This URL has Read+Write access

Tim Morgan (author)
Fri May 29 17:52:21 -0700 2009
commit  26f6cd28d67c5b545cabe5cbc50770b3c99d51c0
tree    2d09abeb7b3592299a6afa1276d253a530afdfd2
parent  23191f4c84046283a1b8a53e204ad2bc601f408e
autumn / README.textile
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 1 h1. Autumn: A Ruby IRC Bot Framework
d1777acd » Tim Morgan 2008-07-04 Rakefile updates; better le... 2
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 3 *Version 3.0 (Jul 4, 2008)*
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 4
879b3971 » Tim Morgan 2008-07-22 mailto: is redundant in tex... 5 | Author | Tim Morgan (riscfuture@gmail.com) |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 6 | Copyright | Copyright (c)2007-2008 Tim Morgan |
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 7 | License | Distributed under the same terms as Ruby. Portions of this code are copyright (c)2004 David Heinemeier Hansson; please see <tt>libs/inheritable_attributes.rb</tt> for more information. |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 8
9 Autumn is a full-featured framework on top of which IRC bots (called "leaves")
10 can be quickly and easily built. It features a very Ruby-like approach to
11 bot-writing, a complete framework for loading and daemonizing your bots,
12 multiple environment contexts, a database-backed model, and painless logging
13 support.
14
15 h2. Requirements
16
17 Autumn requires "RubyGems":http://www.rubygems.org and the Daemons and Facets*
770dc2cb » Tim Morgan 2008-10-06 Facets 2.4.5 18 gems, as well as some of the gems spun off from Facets. Install RubyGems then
49fe9a47 » Tim Morgan 2008-12-11 Facets 2.5, DataMapper 0.9.8 19 run @sudo gem install daemons facets anise english@ in a command line in order
20 to run Autumn.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 21
22 If you wish to use a database backend for your bot, you will need the DataMapper
23 gem. To install, see the "DataMapper website":http://www.datamapper.org.
24
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 25 The included example bot Scorekeeper requires the DataMapper gem. It can
26 optionally use the Chronic gem to enhance its textual date parsing. The other
27 example bot, Insulter, is much simpler and can run under any Autumn
28 configuration.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 29
30 h2. Directory Structure
31
32 An Autumn installation is like a Ruby on Rails installation: There is a
33 certain directory structure where your files go. A lot of files and folders will
34 seem confusing to people who have never used Autumn before, but bear with me. In
35 a bit I will explain in detail what all of this stuff is. For now, here is an
36 overview you can consult for future reference:
37
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 38 * *config/* - Configuration files and season definitions
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 39 ** global.yml - Universal settings that apply to every season
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 40 *** *seasons/* - Contains directories for each season (see *Seasons*)
41 **** *testing/* - Example season
42 ***** database.yml - Example database configuration file
43 ***** leaves.yml - Example bot configuration file
44 ***** season.yml - Season configuration
45 ***** stems.yml - Example IRC configuration file
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 46 * *doc/* - HTML documentation generated by RDoc
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 47 ** *api/* - Autumn API documentation
48 ** *leaves/* - Autumn leaves documentation
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 49 * *leaves/* - Autumn leaves. Each subdirectory contains all the code and
50 data for a leaf.
51 ** *insulter/* - Very simple example leaf
52 *** _See the *scorekeeper* directory_
53 ** *scorekeeper/* - Database-backed, full-featured example leaf
54 *** config.yml - Optional leaf-global configuration options
55 *** controller.rb - The leaf's controller object
56 *** *data/* - Optional directory for data storage (not used by Autumn)
57 *** *helpers/* - Modules that extend the controller and views
26f6cd28 » Tim Morgan 2009-05-29 Official lib directory per ... 58 *** *lib/* - Library files loaded before the leaf
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 59 *** *models/* - Active record-type database objects
60 *** *tasks/* - Additional rake tasks for this leaf (see *Custom leaf tasks*)
61 *** *views/* - ERb views for each of the leaf's commands
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 62 * *libs/* - Autumn core code
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 63 ** channel_leaf.rb - A leaf subclass that can ignore messages from certain
64 channels its in
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 65 ** coder.rb - Used by script/generate to write out Ruby code
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 66 ** ctcp.rb - CTCP support library
67 ** daemon.rb - Provides support for different kinds of IRC servers
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 68 ** datamapper_hacks.rb - Some hacks to help DataMapper work with Autumn
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 69 ** foliater.rb - Instantiates and manages stems and leaves
70 ** formatting.rb - Provides support for different kinds of IRC client text
71 formatting and colorization
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 72 ** generator.rb - Library used by script/generate
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 73 ** genesis.rb - Boots the Autumn environment
74 ** inheritable_attributes.rb - Adds support for class-level inheritable
75 attributes
76 ** leaf.rb - The core bot superclass
77 ** log_facade.rb - Simplifies logging for stems and leaves
78 ** misc.rb - RubyCore class additions and other knick-knacks
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 79 ** script.rb - Library used by script/generate and script/destroy
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 80 ** speciator.rb - Manages global, season, stem, and leaf configurations
81 ** stem.rb - IRC client library
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 82 ** stem_facade.rb - Additional methods to simplify the Stem class
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 83 * *log/* - Directory where (most) Autumn logs are written (see the *Logs*
84 section)
85 * Rakefile - Contains the rake tasks used to control Autumn (see the *Tasks*
86 section)
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 87 * README - RDoc-formatted readme
88 * README.textile - This file
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 89 * *resources/* - Data files used by Autumn
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 90 ** *daemons/* - Data files describing different IRC server types
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 91 * *script/* - Helper scripts for controlling Autumn
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 92 ** daemon - Runs Autumn as a daemon
93 ** destroy - Destroys Autumn objects
94 ** generate - Creates Autumn objects
95 ** server - Starts Autumn
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 96 * *shared/* - Shared code libraries available to all leaves
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 97 * *tmp/* - Temporary files, such as PID files
98
99 h2. Configuring Autumn for Your First Launch
100
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 101 Before you can run Autumn and try out the example leaves, you'll need to set up
102 a few things. Here are the steps:
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 103
104 h3. Configure Your Testing Season
105
106 In Autumn, your leaves run in an environment, called a "season." Each season has
107 different leaves and different settings for those leaves. By default, Autumn
108 comes with a season called "testing" already set up for you. You can edit that
1bf60b40 » Tim Morgan 2008-07-05 Documentation updates 109 season or create a new one with @script/generate season [season name]@. The
110 files for your season are stored in the <tt>config/seasons</tt> directory.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 111
112 First, edit the <tt>stems.yml</tt> file. This file stores information about your
113 IRC connection. Edit it to connect to an IRC server of your choosing. For more
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 114 information, see *Stems* below.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 115
116 Next, edit the <tt>database.yml</tt> file. As mentioned previously, Scorekeeper
117 requires the DataMapper gem because it uses a persistent store. By default it's
118 set up to use a MySQL database, but you can use PostgreSQL or SQLite 3 if you'd
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 119 like. If you'd prefer not to install any of these database solutions, delete the
120 <tt>database.yml</tt> file and remove the Scorekeeper leaf from the
121 <tt>leaves.yml</tt> and <tt>stems.yml</tt> files.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 122
0bde0a20 » Tim Morgan 2008-07-15 Fixed intro to include info... 123 If you do choose to set up a database, you will have to run @rake db:migrate@
124 after your <tt>database.yml</tt> file is configured and your database is
125 created.
126
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 127 Lastly, view the <tt>leaves.yml</tt> file. You shouldn't have to make any
128 changes to this file, but it's a good idea to look at it to see how leaves are
129 configured. You can do the same with the <tt>season.yml</tt> file. See *Seasons*
130 and *Leaves* below for more.
131
132 h3. Starting the Server
133
134 Run the shell command @script/server@ to start the server. After a short
135 while, your leaf should appear in the channel you specified. You can type
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 136 "!points Coolguy +5" and then "!points" to get started using Scorekeeper, or
137 "!insult" to play with Insulter. Have some fun, and when you're satisfied, stop
138 the server by typing "!quit".
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 139
140 If you'd like to daemonize your server, you can use the shell commands
141 @rake app:start@ and @rake app:stop@. For more information, see *Tasks* below.
142
143 h2. Making Your Own Leaf
144
145 Making your own leaf using Autumn is easy. In this tutorial, I'll show you how
146 to make a simple Fortune bot that responds to a few basic commands.
147
148 h3. Step 1: Subclass Leaf
149
150 Create a new leaf by typing @script/generate leaf fortune@. This will create a
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 151 <tt>fortune</tt> directory in the <tt>leaves</tt> directory, along with the bare
152 bones of files needed within that directory. Edit the <tt>controller.rb</tt>
153 file. First we'll create an array to hold our fortunes:
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 154
155 <pre><code>
156 FORTUNES = [
157 "You will make someone happy today.",
158 "Someone you don't expect will be important to you today.",
159 "Today will bring unexpected hardships."
160 ]
161 </code></pre>
162
163 As you can see, our 3 meager fortunes are stored in the @FORTUNES@ class
164 constant. Now, we'll want it to respond to the "!fortune" command, and all you
165 have to do is create a method called @fortune_command@ to make it work:
166
167 <pre><code>
168 def fortune_command(stem, sender, reply_to, msg)
6a294b88 » Tim Morgan 2009-01-14 Facets and gems updates 169 FORTUNES.pick
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 170 end
171 </code></pre>
172
6a294b88 » Tim Morgan 2009-01-14 Facets and gems updates 173 The @pick@ method is provided by Facets, so you may need to add a <code>require
174 'facets/random'</code> line at the top of your file. Our method returns a
175 fortune at random, which is automatically transmitted to the channel or nick
176 where the command was received.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 177
178 Of course, any self-respecting fortune bot announces its presence when it starts
1bf60b40 » Tim Morgan 2008-07-05 Documentation updates 179 up, so, in your @Controller@ class, override the @Autumn::Leaf#did_start_up@
180 method to display a cheerful greeting:
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 181
182 <pre><code>
183 def did_start_up
184 stems.message 'FortuneBot at your service! Type "!fortune" to get your fortune!'
185 end
186 </code></pre>
187
188 ...and that's it! You now have a fully functional fortune bot featuring -- not
189 two -- but _three_ unique and exciting fortunes!
190
191 (For more on that @stems.message@ bit, see *Stems*.)
192
193 h3. Step 2: Add the Leaf to Your Season
194
195 If you want, you can add the fortune bot to your <tt>leaves.yml</tt> and
196 <tt>stems.yml</tt> files to try it out. Adding a leaf is easy; simply duplicate
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 197 the structure used for another leaf's entry and change the values as
198 appropriate. A typical two-leaf configuration will look like:
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 199
200 <pre><code>
201 Scorekeeper:
202 class: Scorekeeper
203 respond_to_private_messages: false
204 Fortune:
205 class: Fortune
206 respond_to_private_messages: true
207 </code></pre>
208
1bf60b40 » Tim Morgan 2008-07-05 Documentation updates 209 As you notice, each leaf instance is given a name. In this example the name
210 happens to be the same as the leaf's type name, but you could run two copies of
211 a leaf like so:
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 212
213 <pre><code>
214 Fortune1:
215 class: Fortune
216 Fortune2:
217 class: Fortune
218 </code></pre>
219
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 220 This doesn't make a whole lot of sense for our fortune bot, but for more
221 complicated bots it can be useful.
222
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 223 We've created the leaf, but we have to add it to the stem for it to work.
224 (Remember, a stem is an IRC connection and a leaf is a bot.) So, in your
225 <tt>stems.yml</tt> file, add an entry for this leaf. Your new config will appear
226 something like:
227
228 <pre><code>
229 Example:
230 nick: Scorekeeper
231 leaves:
232 - Scorekeeper
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 233 - Insulter
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 234 - Fortune
235 rejoin: true
236 channel: somechannel
237 server: irc.someserver.com
238 </code></pre>
239
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 240 When you restart the server, the bot will come back online and will now also
241 respond to the "!fortune" command. This is a helpful tutorial on how stems and
242 leaves are separate. One leaf can have many stems, and one stem can have many
243 leaves. You can combine these two entities however you need.
244
245 h3. Step 3: Upgrade to ERb Views
246
247 You've already learned that for your @[word]_command@-type methods, the bot
248 responds with whatever string your method returns. For more complicated
249 commands, however, you may want to upgrade to full view abstraction, a la Ruby
250 on Rails. This is what the <tt>views</tt> directory is for.
251
252 If you place a <tt>.txt.erb</tt> file in the <tt>views</tt> directory named
253 after your command, it will be parsed by ERb and rendered as the result. You can
254 pass variables to the ERb parser by using the @Autumn::Leaf#var@ method. Let's
255 upgrade our @fortune_command@ method for that:
256
257 <pre><code>
258 def fortune_command(stem, sender, reply_to, msg)
6a294b88 » Tim Morgan 2009-01-14 Facets and gems updates 259 var :fortune => FORTUNES.pick
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 260 end
261 </code></pre>
262
263 We can then write a view, <tt>fortune.txt.erb</tt>, which will render the
264 fortune:
265
266 <code><%= var :fortune %></code>
267
268 OK, so admittedly, this doesn't really get us anywhere, but for more complicated
269 bots, this well help separate view and controller concerns.
270
271 For more information on view rendering, see the @Autumn::Leaf#render@ method.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 272
273 h2. Seasons
274
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 275 Each time you start Autumn, the process launches in a certain season (a.k.a.
276 environment context). This season is defined in the <tt>config/global.yml</tt>
277 file. You can temporarily override it by setting the @SEASON@ environment
278 variable (e.g., @SEASON=production script/server@).
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 279
280 It's important to realize that an season is just a name, nothing more. You can
281 have as many seasons as you like, and name them anything that you like. Autumn
282 will load the config files for the season you've indicated as active. Autumn
283 doesn't really care if it's named "production" or "live" or
284 "testing-on-jeffs-machine"; it's all the same to Autumn.
285
286 Your season's configuration is stored in the <tt>season.yml</tt> file within
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 287 your season directory. Currently it supports one directive, @logging@. This sets
288 the minimum log level (such as @debug@ or @warn@). If the log level is set to
289 @debug@, it also enables console output parroting. (See the *Logging* section.)
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 290
291 The power of seasons comes in custom configuration options. For instance,
292 consider that you have a testing and production season. In your testing season,
293 your <tt>season.yml</tt> file contains:
294
295 <code>dont_http: true</code>
296
297 and in production, it contains:
298
299 <code>dont_http: false</code>
300
301 Now, in your code, you might have a method like:
302
303 <pre><code>
304 def scores_command(stem, sender, reply_to, msg)
305 if options[:dont_http] then
306 return "Some fake sports scores."
307 else
308 # go on the web and find real sports scores
309 end
310 end
311 </code></pre>
312
313 h3. Standard Configuration Options
314
315 h4. Global
316
317 System-wide configuration is done in the <tt>config/global.yml</tt> file. It
318 supports by default the following directives:
319
320 | @season@ | The season to launch in. |
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 321 | @log_history@ | The number of historical logfiles to keep (default 10). |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 322
323 In addition, the following options are available (but cannot be set in the yml
324 file):
325
326 | @root@ | The root directory of the Autumn installation. |
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 327 | @system_logger@ | The @Autumn::LogFacade@ instance that records system messages. |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 328
329 h4. Season
330
331 Season-specific configuration is done in the
332 <tt>config/seasons/[season]/season.yml</tt> file. Currently it only supports one
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 333 directive, @logging@, which takes log levels like @debug@ or @warn@.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 334
335 h4. Stem
336
337 Stem-specific configuration is done in the
338 <tt>config/seasons/[season]/stems.yml</tt> file. It's important to note that
339 stem and leaf configurations are completely independent of each other. (In other
340 words, stem options do not override leaf options, nor vice versa.) Therefore,
341 you generally won't add custom directives to the <tt>stems.yml</tt> file,
342 because you generally won't be working with stems directly. The standard options
343 are:
344
345 | @server@ | The address of the IRC server. |
346 | @port@ | The IRC server port (default 6667). |
30d84bdc » Tim Morgan 2008-07-04 Documentation updates 347 | @local_ip@ | The IP address to connect on (for virtual hosting). |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 348 | @nick@ | The nick to request. |
349 | @password@ | The nick's password, if it is registered. |
350 | @channel@ | A channel to join. |
351 | @channels@ | A list of channels to join. |
352 | @leaf@ | The name of a leaf to run. |
353 | @leaves@ | A list of leaves to run. (These are the names of leaf configurations in <tt>leaves.yml</tt>, not leaf subclasses.) |
354 | @rejoin@ | If true, the stem will rejoin any channels it is kicked from. |
355 | @server_password@ | The password for the IRC server, if necessary. |
356 | @ssl@ | If true, the connection to the IRC server will be made over SSL. |
357 | @server_type@ | The IRC server type. See <tt>resources/daemons</tt> for a list of valid server types. If you do not manually set this value, it will be guessed automatically. |
358 | @case_sensitive_channel_names@ | If true, channel names will be compared with case sensitivity. |
359 | @dont_ghost@ | If true, the stem will not try to GHOST a registered nick if it's taken. |
360 | @ghost_without_password@ | If true, the stem will use the GHOST command without a password. Set this for servers that use some other form of nick authentication, such as hostname-based. |
361 | @user@ | The username to send (optional). |
362 | @name@ | The user's real name (optional). |
331c618e » Tim Morgan 2008-09-08 Added throttling support (p... 363 | @throttle@ | If enabled, the stem will throttle large amounts of simultaneous messages. |
364 | @throttle_rate@ | Sets the number of seconds that pass between consecutive PRIVMSG's when the leaf's output is throttled. |
365 | @throttle_threshold@ | Sets the number of simultaneous messages that must be queued before the leaf begins throttling output. |
9d588fcb » Tim Morgan 2009-03-28 Custom nick regexes 366 | @nick_regex@ | The regular expression used to match nicknames in server messages. By default, it conforms to the RFC-1459 definition. |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 367
368 The @channel@ and @channels@ directives can also be used to specify a password
369 for a password protected channel, like so:
370
371 <pre><code>
372 channel:
373 channelname: channelpassword
374 </code></pre>
375
376 or
377
378 <pre><code>
379 channels:
380 - channel1: password1
381 - channel2: password2
382 </code></pre>
383
384 The @port@, @server_type@, and @channel@/@channels@ options are set in the
385 config file but not available in the @options@ hash. They are accessed directly
386 from attributes in the @Autumn::Stem@ instance, such as the @channels@
387 attribute.
388
389 h4. Leaf
390
391 Leaf-specific configuration is done in the
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 392 <tt>config/seasons/[season]/leaves.yml</tt> file and the
393 <tt>leaves/[leaf]/config.yml</tt> file, with the former taking precedence over
394 the latter. As mentioned above, leaf and stem configurations are completely
395 separate, so one does not override the other. The standard options are:
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 396
bc495401 » Tim Morgan 2008-07-06 More doc updates, filename ... 397 | @class@ | The type of the leaf. It must be a subdirectory in the <tt>leaves</tt> directory. |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 398 | @command_prefix@ | The text that must precede each command. Defaults to "!". |
399 | @respond_to_private_messages@ | If true, the leaf will parse commands in whispers, and respond over whispers to those commands. |
400 | @database@ | A database connection to use (as defined in <tt>database.yml</tt>). By default Autumn will choose a connection named after your leaf. |
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 401 | @formatter@ | The name of a module in @Autumn::Formatting@ that will handle output formatting and colorization. This defaults to mIRC-style formatting. |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 402
1555539b » Tim Morgan 2008-07-04 Added leaf-level :root opti... 403 In addition, the following options are available (but cannot be set in the yml
404 file):
405
406 | @root@ | The root directory of the leaf installation. |
407
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 408 The <tt>leaves.yml</tt> file is optional. When not included, each leaf in the
409 <tt>leaves</tt> directory will be automatically instantiated once.
410
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 411 h3. Custom Configuration Options
412
413 All configuration files support user-generated directives. You can set options
414 at any level. Options at a more narrow level override those at a broader level.
415
416 Options are maintained and cataloged by the @Autumn::Speciator@ singleton. You
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 417 could access the singleton directly, but most objects have an @options@
418 attribute providing simpler access to the Speciator.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 419
420 For example, to access options in a leaf, all you do is call, for example,
421 @options[:my_custom_option]@. @my_custom_option@ can be set at the
422 global, season, or leaf level.
423
424 h2. Leaves
425
426 The @Autumn::Leaf@ class has many tools to help you write your leaves. These
427 include things like filters, helpers, loggers, and an easy to use IRC library.
428 The @Autumn::Leaf@ and @Autumn::Stem@ class docs are the most thorough way of
429 learning about each of these features, but I'll walk you through the basics
430 here.
431
432 h3. The Many Methods of Leaf
433
434 By subclassing @Autumn::Leaf@, you gain access to a number of neat utilities.
435 These generally come in three classes: IRC commands that have already been
436 written for you, utility methods you can call, and invoked methods you can
bc495401 » Tim Morgan 2008-07-06 More doc updates, filename ... 437 override. Utility methods do things like add filters. Invoked methods are called
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 438 when certain events happen, like when your leaf starts up or when a private
439 message is received. You override them in your leaf to customize how it responds
440 to these events.
441
442 | *Invoked methods* | @will_start_up@, @did_start_up@, @did_receive_channel_message@, etc. |
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 443 | *Utility methods* | @before_filter@, @database@, etc. |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 444 | *IRC commands* | @quit_command@, @reload_command@, @autumn_command@, etc. |
445
446 See the class docs for more information on these methods.
447
448 In addition, your leaf is designated as a listener for its @Autumn::Stem@
449 instances. In short, this means if you want even finer control over the IRC
450 connection, you can implement listener methods. See the
451 @Autumn::Stem#add_listener@ method for examples of such methods.
452
453 Finally, your leaf can implement methods that are broadcast by listener plugins.
454 An example of such a plugin is the @Autumn::CTCP@ class, which is included in
455 all stems by default. Visit its class docs to learn more about how to send and
456 receive CTCP requests.
457
458 h3. Filters
459
460 Filters are methods that are run either before or after a command is executed.
461 In the former case, they can also prevent the command from being run. This is
462 useful for authentication, for instance: A filter could determine if someone is
463 authorized to run a command, and prevent the command from being run if not.
464
465 Use filters to save yourself the effort of rewriting code that will run before
466 or after a command is executed. Filter methods are named @[word]_filter@ and
467 they are added to the filter chain using the @before_filter@ and @after_filter@
468 methods (like in Ruby on Rails). As an example, imagine you wanted your bot to
469 say something after each command:
470
471 <pre><code>
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 472 class Controller > Autumn::Leaf
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 473 after_filter :outro
474
475 private
476
477 def outro_filter(stem, channel, sender, command, msg, opts)
478 stem.message "This has been a production of OutroBot!", channel
479 end
480 end
481 </code></pre>
482
483 The result of this is that after each command, the leaf will make a dramatic
484 exit. (Why did I use @after_filter@ and not @before_filter@? Because as I said
485 earlier, a @before_filter@ can stop the command from being executed; the only
486 way we know for sure that the command was executed -- and therefore should be
487 outroed -- is to use an @after_filter@.)
488
489 I made the @outro_filter@ method private because I felt it shouldn't be exposed
490 to other classes; this is not a requirement of the filter framework, though.
491
492 Now let's say you wanted to prevent the command from being run in some cases.
74c31b40 » Tim Morgan 2008-07-15 Doc updates for new auth mo... 493 The most obvious application of this feature is authentication. Autumn already
494 includes a robust authentication module, but for the sake of example, let's
495 pretend you wanted to do your own authentication in your leaf. So, you write a
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 496 @before_filter@ to determine if the user is authenticated. @before_filter@
497 methods have return values; if they return false, the filter chain is halted and
498 the command is suppressed. If you want to have your leaf display some sort of
499 message (like "Nice try!"), you need to include that in your filter.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 500
501 As an example, here's a simple form of authentication that just checks a
502 person's nick:
503
504 <pre><code>
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 505 class Controller < Autumn::Leaf
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 506 before_filter :authenticate, :only => :quit, :admin => 'Yournick'
507
508 def authenticate_filter(stem, channel, sender, command, msg, opts)
509 sender == opts[:admin]
510 end
511 end
512 </code></pre>
513
514 I'm introducing you to three new features with this sample:
515
516 * You can use the @:only@ option to limit your filter to certain commands. Note
517 that you specify the _command_ name as a symbol, _not_ the method name (which
518 would be @quit_command@ in this case).
519 * You can pass your own options to @before_filter@ and @after_filter@; they are
520 passed through to your method via the last parameter, @opts@.
521 * The return value of a @before_filter@ is used to determine if the command
522 should be run. So be careful that your method does not return @nil@ or @false@
523 unless you really mean for the command to be suppressed.
524
525 Both of these examples use the parameters sent to your filter method. They are,
526 in order:
527
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 528 # the @Autumn::Stem@ instance that received the command,
529 # the name of the channel to which the command was sent (or @nil@ if it was a
530 private message),
531 # the sender hash,
532 # the name of the command that was typed, as a symbol,
533 # any additional parameters after the command (same as the @msg@ parameter in
534 the <tt>[word]_command</tt> methods),
535 # the custom options that were given to @before_filter@ or @after_filter@.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 536
537 There are two built-in options that you can specify for @before_filter@ and
538 @after_filter@, and those are @only@ and @except@. They work just like in Rails:
539 The @only@ option limits the filter to running only on the given command or list
540 of commands, and the @except@ option prevents the filter from being run on the
541 given command or list. All other options are passed to the filter for you to
542 use.
543
544 Filters are run in the order they are added to the filter chain. Therefore, a
545 superclass's filters will run before a subclass's filters, and filters added
546 later in a class definition will be run after those added earlier.
547
548 If you subclass one of your leaves, it inherits your superclass's filters. The
549 @Autumn::Leaf@ superclass does not have any filters by default, though by
550 default new leaves come with a simple authentication filter that checks the
551 user's privilege level.
552
74c31b40 » Tim Morgan 2008-07-15 Doc updates for new auth mo... 553 h3. Authentication
554
555 You don't need to write a @before_filter@ as shown above, because Autumn already
556 includes a robust authentication module. The @Autumn::Authentication@ module
557 includes the @Base@ class and four different subclasses of it. Each of these
558 subclasses handles a different type of authentication. You can choose the
559 authentication strategy you want on a leaf-by-leaf basis or for a whole season.
560
561 To specify the kind of authentication you want, you must add an @authentication@
562 directive to your config. If you want to set it for an individual leaf, add it
563 to the <tt>leaves.yml</tt> file. If you want all leaves to have the same
564 authentication strategy, add it to the <tt>season.yml</tt> or
565 <tt>global.yml</tt> file.
566
567 The @authentication@ directive should be a hash that, at a minimum, includes a
568 key called @type@. This is the snake_cased name of subclass in
569 @Autumn::Authentication@ that you wish to use. As an example, here is an entry
570 for an Administrator bot in a <tt>leaves.yml</tt> file, with ops-based
571 authentication.
572
573 <pre><code>
574 Administrator:
575 class: Administrator
576 authentication:
577 type: op
578 </code></pre>
579
580 This will instantiate the @Autumn::Authentication::Op@ class for use with the
581 Administrator bot.
582
583 Other authentication strategies may require additional information. For
584 instance, if you want to used nick-based authentication, your
585 <tt>leaves.yml</tt> file might look like:
586
587 <pre><code>
588 Administrator:
589 class: Administrator
590 authentication:
591 type: nick
592 nick: MyNick
593 </code></pre>
594
595 See the class docs for each subclass in @Autumn::Authentication@ for more info
596 on how you should set up your configs.
597
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 598 h3. Persistent Stores
599
600 If you would like to use a persistent store for your leaf, you should install
601 the DataMapper gem and a DataObjects gem for your database of choice (MySQL,
602 PostgreSQL, or SQLite). DataMapper works almost identically to ActiveRecord, so
603 if you have any Rails programming experience, you should be able to dive right
604 in.
605
606 Once you've got DataMapper installed, you should create one or more database
607 connections in your <tt>config/seasons/[season]/database.yml</tt> file. A sample
608 database connection looks like:
609
610 <pre><code>
611 connection_name:
612 adapter: mysql
613 host: localhost
614 username: root
615 password: pass
616 database: database_name
617 </code></pre>
618
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 619 or, in a smaller syntax:
620
621 <code>connection_name: mysql://root@pass:localhost/database_name</code>
622
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 623 If you are using the "sqlite3" adapter, the @database@ option is the path to the
bc495401 » Tim Morgan 2008-07-06 More doc updates, filename ... 624 file where the data should be written (example:
625 @leaves/fortune/data/my_database.db@). You can name your connection however you
626 want, but you _should_ name it after either your leaf or your leaf subclass.
627 (More on this below.)
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 628
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 629 You should also create DataMapper model classes for each of your model objects.
630 You can place them within your leaf's <tt>models</tt> directory. This works
631 almost exactly the same as the <tt>app/models</tt> directory in Rails.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 632
633 Once your database, data models, and leaves have been configured, you can use
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 634 the @rake db:migrate@ task to automatically populate your database.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 635
636 Now, unlike Rails, Autumn supports multiple database connections. Two leaves can
637 use two different database connections, or share the same database connection.
638 Because of this, it's important to understand how to manage your connections.
639 Autumn tries to do this for you by guessing which connection belongs to which
640 leaf, based on their names.
641
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 642 For example, imagine you have a leaf named "Fortune" and an instance of that
643 leaf in <tt>leaves.yml</tt> named "MyFortune". If you name your database
644 connection either "Fortune" or "MyFortune" (or "fortune" or "my_fortune"), it
645 will automatically be associated with that leaf. What this means is that for the
646 leaf's command methods (such as @about_command@) and invoked methods (such as
647 @did_receive_private_message@), the database connection will already be set for
648 you, and you can start using your DataMapper objects just like ActiveRecord
649 objects.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 650
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 651 If, on the other hand, you either *named your database connection differently
652 from your leaf or subclass name* or you are *writing a method outside of the
653 normal flow of leaf methods* (for instance, one that is directly called by a
654 @Stem@, or a different listener), you will need to call the @database@ method
655 and pass it a block containing your code.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 656
657 This is terribly confusing, so let me give you an example. Let's assume you've
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 658 got a fortune bot running a leaf named "FortuneLeaf", so your
659 <tt>leaves.yml</tt> configuration is:
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 660
661 <pre><code>
662 FortuneBot:
663 class: FortuneLeaf
664 </code></pre>
665
666 And you have a database connection for that leaf, named after the leaf's class:
667
668 <pre><code>
669 fortune_leaf:
670 adapter: sqlite3
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 671 database: leaves/fortune_leaf/data/development.db
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 672 </code></pre>
673
674 Let's further assume you have a simple DataMapper object:
675
676 <pre><code>
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 677 class Fortune
678 include DataMapper::Resource
679 property :id, Integer, :serial => true
680 property :text, String
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 681 end
682 </code></pre>
683
684 Now, if we wanted to write a "!fortune" command, it would appear something like
685 this:
686
687 <pre><code>
688 def fortune_command(stem, sender, reply_to, msg)
689 fortunes = Fortune.all
690 fortunes[rand(fortunes.size)].text
691 end
692 </code></pre>
693
694 Autumn automatically knows to execute this DataMapper code in the correct
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 695 database context. It knows this because your leaf's name is @FortuneLeaf@, and
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 696 your database context is named the same.
697
698 But what if you wanted to use that connection for other leaves too, so you named
699 it something like "local_database"? Now, Autumn won't be able to guess that you
700 want to use that DB context, so you have to specify it manually:
701
702 <pre><code>
703 def fortune_command(stem, sender, reply_to, msg)
704 database(:local_database) do
705 fortunes = Fortune.all
706 return fortunes[rand(fortunes.size)].text
707 end
708 end
709 </code></pre>
710
711 If that is too tedious, you can specify the database connection manually in the
712 <tt>leaves.yml</tt> file:
713
714 <pre><code>
715 FortuneBot:
716 class: FortuneLeaf
717 database: local_database
718 </code></pre>
719
720 OK, now onto the second special case. Imagine you want your fortune bot to also
721 send a fortune in response to a CTCP VERSION request. So, you'd implement a
722 method like so:
723
724 <pre><code>
725 def ctcp_version_request(handler, stem, sender, arguments)
726 fortune = random_fortune # Loads a random fortune
727 send_ctcp_reply stem, sender[:nick], 'VERSION', fortune.text
728 end
729 </code></pre>
730
731 This will break -- why? Because the @ctcp_version_request@ method is in the
732 realm of the @Autumn::CTCP@ class, _not_ the @Autumn::Leaf@ class. (You can see
733 this by investigating the CTCP class docs; it shows you what methods you can
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 734 implement for CTCP support.) Basically, the @CTCP@ class calls your method
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 735 directly, giving the @Autumn::Leaf@ class no chance to set up the database
736 first. So to fix it, make a call to @database@ first:
737
738 <pre><code>
739 def ctcp_version_request(handler, stem, sender, arguments)
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 740 fortune = database { random_fortune }
741 send_ctcp_reply stem, sender[:nick], 'VERSION', fortune.text
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 742 end
743 </code></pre>
744
745 This will execute those methods in the scope of the database connection guessed
746 by @Autumn::Leaf@. Of course, you can manually pass in a connection name if
747 necessary.
748
f215f4f1 » Tim Morgan 2008-07-08 Just discovered an importan... 749 *Another important note:* You will need to make a call to @database@ in any
750 child threads your leaf creates. The database context is not automatically
751 carried over to such threads.
752
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 753 h3. Your Leaf's Module; or, "What Do I Do About Namespace Conflicts?"
754
755 So, if you have two database-backed leaves, it's entirely likely that both of
756 them will use some sort of DataMapper resource named @Channel@, or something
757 similar. You can't define the class @Channel@ twice in two different ways, so
758 how do you deal with this?
759
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 760 The answer is: It's already dealt with for you. Go ahead and define the class
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 761 twice. Or three times.
762
763 The longer explanation is: Secretly, behind the scenes, *all your leaf code is
764 being cleverly loaded into a module named after your leaf*. So, when, in your
765 <tt>controller.rb</tt> code, it says @class Controller < Autumn::Leaf@, you
766 should read it as @class MyLeafName::Controller < Autumn::Leaf@. When you define
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 767 your model with @class Channel@, it's really read as <code>class
768 MyLeafName::Channel</code>.
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 769
770 Don't worry about table names or associations or anything, either. Just go ahead
771 and use it as if it weren't in a module. The <tt>libs/datamapper_hacks.rb</tt>
772 file has all the necessary code changes to make this bit of trickery work.
773
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 774 h3. Using Support Modules
775
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 776 Helper modules placed in your leaf's <tt>helpers</tt> directory will
777 automatically be loaded and included in your leaf controller and views. To
778 create a helper module, place Ruby files to be loaded into the <tt>helpers</tt>
779 directory. Make sure your helper modules' names end with the word "Helper".
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 780
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 781 For instance, if your leaf's name is "Fortune", and you needed two helpers, a
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 782 database helper and a network helper, you could create two modules named
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 783 @DatabaseHelper@ and @NetworkHelper@. Any modules named in this fashion and
784 placed in the <tt>helpers</tt> subdirectory will be loaded and appended to the
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 785 controller and its views automatically.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 786
26f6cd28 » Tim Morgan 2009-05-29 Official lib directory per ... 787 h3. Loading libraries
788
789 Files placed in your leaf's <tt>lib</tt> directory will be loaded and run before
790 your leaf's controller, helpers, and views are parsed. You can place any gem
791 dependencies in this file, or preload any class definitions.
792
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 793 h3. Debugging Your Leaf
794
795 If you make a simple code change to your leaf, you can reload it without having
796 to restart the whole process. See the @Autumn::Leaf#reload_command@
797 documentation for more information on when and how you can reload your leaf's
798 code.
799
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 800 If an error occurs on a live production instance, it will be logged to the log
801 file for your season. You can inspect the log file to determine what went wrong.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 802
803 If the error happens before the logger is available, oftentimes it will appear
bc495401 » Tim Morgan 2008-07-06 More doc updates, filename ... 804 in the <tt>autumn.output</tt> or <tt>autumn.log</tt> files. These files are
805 generated by the daemon library and note any uncaught exceptions or standard
806 outs. They are in the <tt>tmp</tt> directory.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 807
808 The most tricky of errors can happen before the process is daemonized. If your
809 process is quitting prematurely, and you don't see anything in either log file,
810 consider running @script/server@, allowing you to see any exceptions for
811 yourself.
812
813 Unfortunately, it's still possible that the bug might not appear when you do
814 this, but only appear when the process is daemonized. In this situation, I'd
815 recommend installing rdebug (@sudo gem install rdebug@) and stepping through the
816 code to figure out what's going wrong. In particular, make sure you step into
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 817 the @Foliater@'s @start_stems@ method, when it creates the new threads. It's
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 818 possible your exception will rear its head once you step into that line of code.
819
820 h2. Stems
821
822 @Autumn::Stem@ is a full-featured IRC client library, written from the ground up
823 for Autumn. It makes extensive use of implicit protocols, meaning that most
824 features are accessed by implementing the methods you feel are necessary.
825
826 Most of the time, you will only work with stems indirectly via leaves. For
827 instance, if you want an "!opped" command that returns true if the sender is an
828 operator, it would look like this:
829
830 <pre><code>
831 def opped_command(stem, sender, reply_to, msg)
832 stem.channel_members[reply_to][sender[:nick]] == :operator ? "You are opped." : "You are not opped."
833 end
834 </code></pre>
835
836 Let's break this down. In order to figure out if someone is opped or not, we
837 need three pieces of information: their nick, the channel they are in, and the
838 IRC server they are connected to.
839
840 The @stem@ parameter contains the @Autumn::Stem@ instance that received this
841 message. It is our link to that server. Through it we can perform IRC actions
842 and make requests.
843
844 @Autumn::Stem@ includes an attribute @channel_members@, a hash of channels
845 mapped to their members. The channel that received the message is passed via the
bc495401 » Tim Morgan 2008-07-06 More doc updates, filename ... 846 @reply_to@ parameter. So we call @channel_members[reply_to]@ and we receive a
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 847 hash of member names to their privilege levels. The @sender@ parameter contains
848 information about the person who sent the command, including their nick. So we
849 use their nick to resolve their privilege level.
850
851 Complicated? Sure it is. That's the price we pay for separating stems from
852 leaves. But what if you, like probably 90% of the people out there who use
853 Autumn, only have one stem? Why should you have to call the same damn stem each
854 and every time?
855
856 Fortunately, your pleas are not in vain. For leaves that run off only one stem,
857 the stem's methods are rolled right into the leaf. So, that "!opped" command
858 method becomes:
859
860 <pre><code>
861 def opped_command(stem, sender, reply_to, msg)
862 channel_members[reply_to][sender[:nick]] == :operator ? "You are opped." : "You are not opped."
863 end
864 </code></pre>
865
866 OK, so it's not like a world-class improvement, but it helps.
867
868 The primary thing your leaf will probably do with a @Stem@ instance is use it to
869 send messages, like so:
870
871 <pre><code>
872 def about_command(stem, sender, reply_to, msg)
873 stem.message "I am a pretty awesome bot!", reply_to
874 end
875 </code></pre>
876
877 Fortunately, if you just return a string, @Autumn::Leaf@ will automatically send
878 it for you, simplifying our method:
879
880 <pre><code>
881 def about_command(stem, sender, reply_to, msg)
882 "I am a pretty awesome bot!"
883 end
884 </code></pre>
885
886 You would still interact with the stem directly if you wanted to do something
887 like announce your leaf's presence to everyone. To do this, you'd have to send
888 a message to every channel of every stem the leaf is a listener for:
889
890 <code>stems.each { |stem| stem.channels.each { |channel| stem.message "Hello!", channel } }</code>
891
892 But! @Autumn::Stem#message@ will automatically send a message to every channel
893 if you don't specify any channels, simplifying our code to:
894
895 <code>stems.each { |stem| stem.message "Hello!" }</code>
896
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 897 It gets even better. *You can call methods on the @stems@ array as if it were a
898 stem itself!* This simplifies the line significantly:
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 899
900 <code>stems.message "Hello!"</code>
901
902 Pretty nifty, huh? This also works for functions as well as methods; for
903 instance, the @Autumn::Stem#ready?@ function, which returns true if a stem is
904 ready:
905
906 <code>stems.ready? #=> [ true, true, false, true ]</code> (for example)
907
908 h3. The nitty-gritty of stems
909
910 The section above dealt with stems as they relate to leaves. But when would you
911 need to deal with a stem directly? Generally, never. However, if you find that
912 @Autumn::Leaf@ doesn't have what you need, you may have to turn to
913 @Autumn::Stem@ to get the functionality you are looking for. So let's take a
914 look at how Stem works.
915
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 916 A stem interacts with interested parties via the listener protocol. Your leaf
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 917 signals its interest to a stem by calling @Autumn::Stem#add_listener@. When a
918 leaf or any other object becomes a stem's listener, that stem then invokes
919 methods on the listener whenever an IRC event occurs.
920
921 Let's take a simple example. Assume you wanted to build a basic textual IRC
922 client using Stem. You'd first want to indicate that your client is a listener:
923
924 <pre><code>
925 class MyClient
926 def initialize(stem)
927 @stem = stem
928 @stem.add_listener self
929 end
930 end
931 </code></pre>
932
933 Now the stem will send method calls to your @MyClient@ instance every time an
934 IRC event occurs. None of these methods are required -- you can implement as few
935 or as many as you want. The different methods that @Stem@ will send are
936 documented in the @Autumn::Stem#add_listener@ method docs. One very important
937 method is the @irc_privmsg_event@ method. Let's implement it:
938
939 <pre><code>
940 def irc_privmsg_event(stem, sender, arguments)
941 puts "#{arguments[:channel]} <#{sender[:nick]}> #{arguments[:message]}"
942 end
943 </code></pre>
944
945 Now we've got the most important part of our IRC client done -- receiving
946 messages.
947
948 You can also send IRC events using stem. It's simple: Every IRC command (such as
949 JOIN and PRIVMSG and MODE) has a corresponding method in @Stem@ (such as @join@
950 and @privmsg@ and @mode@). These methods aren't in the API docs because they're
951 implemented using @method_missing@. Their arguments are exactly the same as the
952 arguments the IRC command expects, and in the same order.
953
954 So how do we send a message? Well according to RFC-1459, the basic IRC spec, the
955 PRIVMSG command takes two arguments: a list of receivers, and the text to be
956 sent. So, we know our method call should look something like this:
957
958 @stem.privmsg recipient, message
959
960 Astute readers will note that the spec shows a _list_ of recipients, and indeed,
961 you can call the method like so:
962
963 @stem.privmsg [ recipient1, recipient2 ], message
964
965 That's the basics of how @Autumn::Stem@ works, but there's one other thing worth
966 mentioning, and that's listener plugins. The details are in the
967 @Autumn::Stem#add_listener@ method docs, but the short of it is that these are
968 special listeners that bestow their powers onto other listeners.
969
970 The best example of this is the @Autumn::CTCP@ class. This class is indeed a
971 @Stem@ listener: It listens to PRIVMSG events from the stem, and checks them to
972 see if they are CTCP requests. However, it _also_ gives you, the author of
973 another listener (such as your leaf) the ability to implement methods according
974 to _its_ protocol.
975
976 For example, say you wanted to respond to CTCP VERSION requests with your own
977 version information. You do it like so:
978
979 <pre><code>
980 def ctcp_version_request(handler, stem, sender, arguments)
981 send_ctcp_reply stem, sender[:nick], 'VERSION', "AwesomeBot 2.0 by Sancho Sample"
982 end
983 </code></pre>
984
985 What's going on here? Because the @Autumn::CTCP@ class is a listener plugin, it
986 is sending its own method calls as well as implementing @Stem@'s method calls.
987 One such call is the @ctcp_version_request@ method, which you can see in the
988 @CTCP@ class docs. Somewhere deep in the annals of @Autumn::Foliater@, there is
989 some code similar to the following:
990
991 <pre><code>
992 ctcp = Autumn::CTCP.new
993 stem.add_listener ctcp
994 </code></pre>
995
996 Thus, every stem comes pre-fab with a CTCP listener plugin. That plugin is
997 intercepting PRIVMSG events and checking if they're CTCP requests. If they are,
998 it is invoking methods, such as @ctcp_version_request@, in all of the stem's
999 other listeners, among which is your leaf. Hopefully you understand how this all
1000 fits together.
1001
1002 The lesson to take home here is two-fold: Firstly, if you'd like CTCP support in
1003 your leaf, know that it's the @Autumn::CTCP@ class that is providing the method
1004 calls to your leaf, not the @Autumn::Stem@ class. Secondly, this should
1005 hopefully give you some ideas should you want to write your own listener plugin
1006 to enhance @Stem@'s functionality.
1007
1008 h2. Autumn's Logging
1009
1010 Autumn uses Ruby's @Logger@ class to log; however, it uses @Autumn::LogFacade@
1011 to prepend additional information to each log entry. The @LogFacade@ class has
1012 the exact same external API as @Logger@, so you can use it like a typical Ruby
1013 or Ruby on Rails logger. Many objects (such as @Leaf@ and @Stem@) include a
1014 @logger@ attribute:
1015
1016 <pre><code>
1017 logger.debug "Debug statement"
1018 logger.fatal $!
1019 </code></pre>
1020
1021 See the @LogFacade@ class docs for details.
1022
1023 h2. Tasks
1024
1025 The included Rakefile contains a number of useful tasks to help you develop and
1026 deploy your leaves. You can always get a list of tasks by typing @rake --tasks@.
1027 The various commands you can run are:
1028
1029 Application tasks:
1030
1031 | @rake app:start@ | Starts the Autumn daemon in the background. |
1032 | @rake app:stop@ | Stops the Autumn daemon. |
1033 | @rake app:restart@ | Reloads the Autumn daemons. |
1034 | @rake app:run@ | Starts the Autumn daemon in the foreground. |
1035 | @rake app:zap@ | Forces the daemon to a stopped state. Use this command if your daemon is not running but <tt>script/daemon</tt> thinks it still is. |
1036
1037 Database tasks:
1038
0d2d62f1 » Tim Morgan 2008-07-05 More documentation updates ... 1039 | @LEAF=[leaf name] rake db:migrate@ | Creates all the tables for a leaf, as specified by the leaf's model objects |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 1040
1041 Documentation tasks:
1042
1043 | @rake doc:api@ | Generates HTML documentation for Autumn, found in the <tt>doc/api</tt> directory. |
1044 | @rake doc:leaves@ | Generates HTML documentation for your leaves, found in the <tt>doc/leaves</tt> directory. |
1045 | @rake doc:clear@ | Removes all HTML documentation. |
1046
1047 Logging tasks:
1048
1049 | @rake log:clear@ | Clears the log files for all seasons. |
1050 | @rake log:errors@ | Prints a list of error-level log messages for the current season, and uncaught exceptions in all seasons. |
1051
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 1052 h3. Custom leaf tasks
1053
1054 You can define your own leaf-specific tasks in the <tt>tasks</tt> subdirectory
1055 within your leaf's directory. Any <tt>.rake</tt> files there will be loaded by
1056 rake. The tasks will be added within a task-group named after your leaf. Use
1057 Scorekeeper as an example: If you type @rake --tasks@, you'll see one other
1058 task, @rake scorekeeper:scores@. The "scores" task is defined in the
1059 <tt>leaves/scorekeeper/tasks/stats.rake</tt> file, and placed in the
1060 "scorekeeper" task group by Autumn.
1061
1062 Also, if you open that file up, you'll notice that you have to refer to your
1063 leaf's classes by their _full_ names, including the leaf module. (See *Your
1064 Leaf's Module* if you're confused.)
1065
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 1066 h2. Scripts
1067
0d204307 » Tim Morgan 2008-12-11 script/console documentation 1068 Autumn includes some scripts to help you control it.
1069
1070 h3. <tt>script/console</tt>
1071
1072 Bootstraps an IRb console with the Autumn environment configured. Stems and
1073 leaves are accessile from the Foliater instance. DataMapper models can be used.
1074 Does not start any stems (in other words, no actual server login occurs).
1075
1076 Usage: @script/console [options]@
1077
1078 where [options] may contain:
1079
1080 | @--irb@ | Invoke a different Ruby terminal. |
1081
1082 You can alter the season by setting the @SEASON@ environment variable.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 1083
1084 h3. <tt>script/daemon</tt>
1085
1086 Controller for the Autumn daemon. Starts, stops, and manages the daemon. Must be
1087 run from the Autumn root directory.
1088
1089 Usage: @script/daemon [command] [options] -- [application options]@
1090
1091 where [command] is one of:
1092
1093 | @start@ | start an instance of the application |
1094 | @stop@ | stop all instances of the application |
1095 | @restart@ | stop all instances and restart them afterwards |
1096 | @run@ | start the application and stay on top |
1097 | @zap@ | set the application to a stopped state |
1098
1099 and where [options] may contain several of the following:
1100
1101 | @-t, --ontop@ | Stay on top (does not daemonize) |
1102 | @-f, --force@ | Force operation |
1103
1104 Common options:
1105
1106 | @-h, --help@ | Show this message |
1107 | @--version@ | Show version |
1108
1109 h3. <tt>script/destroy</tt>
1110
1111 Destroys the files for leaves, seasons, and other objects of the Autumn
1112 framework.
1113
1114 Usage: @script/destroy [options] [object] [name]@
1115
1116 | [object] | The object type to destroy. Valid types are "leaf" and "season". |
1117 | [name] | The name of the object to destroy. For example, you can call @script/destroy leaf Scorekeeper@ to remove a leaf named Scorekeeper. |
1118
1119 | @--help, -h@ | Displays this usage information. |
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 1120 | @--vcs, -c@ | Remove any created files or directories from the project's version control system. (Autodetects CVS, Git, and Subversion.) |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 1121
1122 h3. <tt>script/generate</tt>
1123
1124 Generates template files for leaves, seasons, and other Autumn objects.
1125
1126 Usage: @script/generate [options] [template] [name]@
1127
1128 | [template] | The template to create. Valid templates are "leaf" and "season". |
1129 | [name] | The name to give the created template. For example, you can call @script/generate leaf Scorekeeper@ to create a leaf named Scorekeeper. |
1130
1131 | @--help, -h@ | Displays this usage information. |
f185a31b » Tim Morgan 2008-07-04 Doc updates for Autumn 3.0 1132 | @--vcs, -c@ | Add any created files or directories to the project's version control system. (Autodetects CVS, Git, and Subversion.) |
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 1133
1134 h3. <tt>script/server</tt>
1135
1136 Runs Autumn from the command line. This script will not exit until all leaves
1137 have exited. You can set the @SEASON@ environment variable to override the
1138 season.
1139
1140 h2. Thread Safety
1141
1142 Autumn is a multi-threaded IRC client. When a message is received, a new thread
1143 is spawned to process the message. In this thread, the message will be parsed,
1144 and all listener hooks will be invoked, including your leaf's methods. The
1145 thread will terminate once the message has been fully processed and all methods
1146 invoked.
1147
1148 I have made every effort to ensure that @Autumn::Stem@ and @Autumn::Leaf@ are
1149 thread-safe, as well as other relevant support classes such as @Autumn::CTCP@.
1150 It is now in your hands to ensure your leaves are thread-safe! This basically
1151 means recognizing that, while your leaf is churning away at whatever command it
1152 received, things can and will change in the background. If your command requires
1153 your leaf to have operator privileges, write your code under the assumption that
1154 operator could be taken from your leaf in the middle of executing the command.
1155 Write data in critical blocks, use transactions in your database calls ... you
1156 know the deal. Don't assume things will be the same between one line of code and
1157 the next.
1158
1159 h2. Getting Ready for Deployment
1160
1161 There's only a few things you need to do once your leaf is ready to greet
1162 the Real World:
1163
d5069e22 » Tim Morgan 2008-07-03 Textile fixes 1164 # Create a new production season. Configure your stems, leaves, and database
1165 as necessary for your production environment.
1166 # In <tt>config/global.yml</tt>, set the season to your production season.
1167 # If desired, in <tt>script/daemon</tt>, set the @:monitor@ option to true.
1168 This will spawn a monitor process that will relaunch Autumn if it crashes.
c6d61e59 » Tim Morgan 2008-07-03 Doc updates for Github and ... 1169
1170 h2. Other Information
1171
1172 Please consult the "list of known bugs":http://github.com/RISCfuture/autumn/wikis/known-bugs
1173 and "version history":http://github.com/RISCfuture/autumn/wikis/version-history
1174 for more information.
1175
1176 *_Why do you require Facets?_, I hear you ask. Facets doesn't add any super
1177 awesome new features to Ruby like Daemons or DataMapper does. It does, however,
1178 improve code reuse, and I'm a big fan of that. Why should a million different
1179 Ruby projects all write the same @Symbol#to_proc@ method or the same
1180 @Hash#symbolize_keys@ method? I use Facets because that job has already been
1181 done, and staying DRY means staying DRY _between_ codebases, not just within
1182 them.