Rubot/Documentation
From Botdom Wiki
< Rubot
| → |
It is suggested that this page should be moved to Botdom Documentation. Please do not move the page by hand. It will be moved by an administrator with the full edit history. In the meantime, you may continue to edit the page as normal. You can discuss this decision on the talk page. |
Contents |
General documentation
README.txt
====== ===== ===== ===== About Rubot ===== ===== ===== ====== I hope you enjoy rubot, its taken near a year, countless late nights, lots of caffeine and tons of supporting friends to pull this off. Starting with a php pseudo-threaded design, which I named zBot. Soon after realizing that I couldn't overcome certain IPC issues without lots of overhead I moved it to a modular, object oriented design. Finishing zBot for release with OO interface, dAmnBot compatability API and a very efficent modular plugin and extension system I was happy, though zBot's permissions model was never completed. Shortly there after I became interested in ruby, and decided to learn it. I ported the entire zBot code base to ruby. After massive refactoring, a more modular architecture and a formal standard for the dAmnSock interface I ended up with rubot. So here it is, enjoy. :) If you find a bug please note Zeros-Elipticus, this IS a beta-release version though so don't expect it to be perfect. If there is a feature that you'd like to see added send me a note too, Rubot is a constant work in progress. Note: Some features may require a *nix system - Elliott ====== ===== ===== ====== Warranty ====== ===== ===== ====== This software comes with ABSOLUTELY NO WARRANTY. It is distributed as is. The license this software is licensed under can be found in LICENSE.txt. ===== ===== ===== ====== Thank Yous ====== ===== ===== ==== Some components of this software are based on dAmnlib by Kevin Wallace (doofsmack). The original interface was written in php, and then ported to ruby. Major thanks go to him for the excellent design of dAmnLib and for support. Components: dAmnClient class dAmnChannel class dAmnUser class dAmnPacket classes ===== ===== ===== ===== ===== ===== ===== ===== ===== ====== Special thanks to: Kevin Wallace [`doofsmack] - dAmnlib, dAmn packet reference, and lots of other help Stanford Chau [=stfc] - inspiration, regular expression help, and lot of brainstorming Teddy Wexler [=twexler] - general help with dAmn protocol, testing and Linux support Kroc Camen [=Kroc] - general inspiration and motivation to write well documented code Natalie Julke [=thegnat] - For putting up with me always coding, long into the night like a mad man <3 ===== ===== ===== ===== ===== ===== ===== ===== ===== ======
license.txt
/* ################################################## < License > This work is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 2.5 License http://creativecommons.org/licenses/by-nc-sa/2.5/ You CAN: * Create derivitive works, provided you: * attribute the original author with a link to their website * the derivitive is not used for commerical purposes * distribute the derivitive works under the same license * Distribute the code, provided you: * attribute the original author with a link to their website * the code is not used for commerical purposes * distribute the code under the same license You CAN NOT: * Use this code, or derivitives for commerical purposes. * Remove this notice Title: Rubot (OO bot for deviantART Message Network) Date: 2006 Creator: Elliott Sprehn (http://enfinitystudios.thaposse.net elliott@thaposse.net) Original Source: Send an email. < Information > This set of classes, extensions and plugins provides an easily to maintained and extended bot for the deviantART Message Network also known as dAmn. Author: Elliott Sprehn Version: 1.0 Beta-0198 Beta Tester Release Date: June 28 2006 < Requirements > Ruby 1.8.2+ < Changelog > [28-06-2006] Beta Tester Release version. < Quote > "Code well, code to standards, and above all.. code for fun." ################################################## */
Guide.txt
###########
#
# Table Of Contents
#
##
1. Install Ruby
2. Install Rubot
3. Setup Rubot
4. Starting Rubot
5. Changing Permissions
####
# 1. Install Ruby
##
1a. OS X
If you're on OS X you already have ruby! Doesn't hurt to install Ruby 1.8.4
though, so check out the below link and follow the secition on building ruby:
http://hivelogic.com/articles/2005/12/01/ruby_rails_lighttpd_mysql_tiger
1b. Windows
If you're on Windows go have a look at the following links:
http://rubyinstaller.rubyforge.org/wiki/wiki.pl
http://rubyforge.org/projects/rubyinstaller/
Download the latest installer to your desktop and install ruby. It should
associate .rb files with ruby so launching the bot should be easy.
1c. *nix
If you're on a *nix platform the installation steps may vary, its best to check
if there is a ruby package for your platform first before you try and compile it.
Rubot has been tested to work well with Ruby 1.8.1 on OpenBSD (in fact thats what
~rubot is running on).
####
# 2. Install Rubot
##
Unpack the rubot.zip to a directory. It doesn't matter where really. You'll probably have a
rubot folder and a __MACOSX folder. The __MACOSX folder is resource forks from my mac, if
you're on Windows or *nix go ahead and delete it.
Now you'll have a directory structure similar to:
config/
core/
docs/
modules/
plugins/
startup.rb
I'll talk about what each folder is for in a later section.
startup.rb is the script that launches the bot, you'll use this later. For now lets get on
to the configuration.
####
# 3. Setup Rubot
##
Setting up rubot is extremely simple. In the root of the rubot application directory there
is a folder called config. In that there is a file called main.conf.rb; This file holds the
configuration options.
It explains what each of them do in the file, but I'll go over it here too:
RUBOT_USERNAME:
This is the username that will be used to connect to dAmn. It must be a valid
deviantART user account. It should be a string, so put single or double quotes around
it. For example:
RUBOT_USERNAME = 'Zeros-Elipticus'
RUBOT_AUTHTOKEN:
This is the authtoken used to login to dAmn. If you want to get your authtoken login
to deviantART with the account specified in RUBOT_USERNAME. Then open the page
http://chat.deviantart.com/ and join a channel. Now look at the source, you'll see a
line like (all on one line):
initdAmnChat("chat.deviantart.com",
"chat:damnishies",
"Zeros-Elipticus",
"3717c78b9d9e6a47278a8e69edb636e9");
The last portion is your authtoken. Its a 32bit hash that deviantART generates when
you login and its a great deal more secure to use that to have your bot connect.
In the event the bot's source is stolen and someone gets the authtoken you can
login as the bot in a browser and force the dA to generate a new authtoken making
the stolen one useless.
If you absolutely must you can supply a password here instead of an authtoken and
rubot will get the authtoken for you when it attempts to login to dAmn. This is not
recommended though.
Example:
RUBOT_AUTHTOKEN = 'd88bcd894fea88263daab2df523e415e'
RUBOT_AUTHTOKEN = 'my$7r0ngPa$$0w0rd'
RUBOT_DEFAULT_CHANNELS:
This is an array of default channels to join when the bot connects to dAmn, they should
be specified in an array format. The format of the channel names doesn't matter,
'chat:damnishies', '#damnishies' and 'damnishies' are all valid.
Example:
RUBOT_DEFAULT_CHANNELS = ['#botdom','chat:damnishies','trivia']
RUBOT_TRIGGER:
This is the trigger that the bot will look for when checking for commands. For example
if the trigger is '!' when someone types 'about' nothing will happen, but is someone
types '!about' rubot will look for the about plugin and try and execute it if the
user has permissions to do so. (more about permissions later)
There are no reserved characers beyond what ruby strings allow, and the trigger can
be of any length.
Example:
RUBOT_TRIGGER = '--'
RUBOT_OWNER:
The owner is a user with complete access to all plugins. Set this carefully, as it
gives the user total control.
Example:
RUBOT_OWNER = 'Zeros-Elipticus'
RUBOT_CONSOLE_ANSICOLOR:
This determines if messages output to the terminal should be in color or if
only plain text messages should be output. Personally I like color messges as it
makes it easy to tell what type of message is what. Should be either a boolean
true or a boolean false.
Example:
RUBOT_CONSOLE_ANSICOLOR = true
RUBOT_REJOIN_ON_KICK:
This controls if the bot will rejoin when it is kicked from a channel. Set to true
if you want it to rejoin when its kicked, false if you don't.
Example:
RUBOT_REJOIN_ON_KICK = true
####
# 4. Starting Rubot
##
Starting up the bot is quick and simple!
4a. OS X
On OS X open /Applications/Utilities/Terminal.app; then using the cd command go the
directory where you unpacked rubot. Type ./startup.rb and hit enter. The bot should
start right up.
4b. Windows
Open a cmd.exe window and cd into the directory where you unpacked rubot. Type the path to
the ruby executable (for example: C:\ruby\ruby.exe) and then a space and then startup.rb;
the bot should start right up. Optionally, depending on how you installed ruby you may
be able to just double click the startup.rb icon to start the bot.
4c. *nix
Open a terminal and then use the Mac OS X instructions above for what to type.
####
# 5. Changing permissions
##
!privman listusers
!privman listchannels
!privman showuser [username]
!privman adduser [username] [groups...]
!privman remuser [username]
!privman showchannel [channel]
!privman addchannel [channel]
!privman remchannel [channel]
!privman showprivclass [channel] [privclass]
!privman addprivclass [channel] [privclass] [groups...]
!privman remprivclass [channel] [privclass]
When [groups...] are specified it means that a comma seperated list of privelege groups needs
to be provided to the command, there should be no spaced between the comma and the list items.
Example:
add a user with some access groups:
!privman adduser thegnat factfun,admin,basic
show a user:
!privman showuser thegnat
remove a user:
!privman remuser thegnat
add a channel, channels must be added before they can have privclasses added to them:
!privman addchannel botdom
add a privclass with some access groups:
!privman addprivclass botdom the-bot-team admin,basic
show the privclass:
!privman showprivclass botdom the-bot-team
remove the privclass:
!privman remprivclass botdom
show the channel:
!privman showchannel botdom
remove the channel:
!privman remchannel botdom
Adding privelege groups is a bit more complicated. Right now the only way to do this is to
edit the config/permissions.xml file and add the group manually. I'll be adding an easy
interface for this shortly.
To add a group in the XML you need to follow the following steps:
* Open the permissions.xml
* Locate the <groups> element, you will add a new group inside it.
* Create a new <group> element with an attribute 'id' where the value is the group name.
ex. <group id="factfun">
* Inside the <group> element create a <plugin> element for each plugin you want that
group to have access to. The 'name' attribute of the <plugin> element identifies the
plugin name, it should match the folder the plugin cmd.rb is in.
* Inside the <plugin> element create an <access> element.
If you want to give complete access to that plugin use the keyword ALL_ACCESS. Place that
inside the <access> element. If you only want the person to be able to use the default
command for the plugin, which is called when no subcommand is specified, then use
DEFAULT_ACCESS in the same way.
If you want more granular control you can add subcommands to the <access> element, each in
their own <allow> element.
* Make sure all elements are closed, this MUST be valid XML.
Example:
<!-- Create the group basic -->
<group id="basic">
<!-- eightball plugin with complete access -->
<plugin name="eightball">
<access>ALL_ACCESS</access>
</plugin>
<!-- randfact plugin with default access, no sub commands allowed -->
<plugin name="randfact">
<access>DEFAULT_ACCESS</access>
</plugin>
<!-- info plugin, only allow the perm and list sub commands -->
<plugin name="info">
<access>
<allow>perm</allow>
<allow>list</allow>
</access>
</plugin>
</group>
--
Really sorry this is so complicated, I'm working a nice interface to simplify this!!!!
- Elliott
plugins.txt
about - version information about the bot eightball - simple port of the noodlebot eightball, example that porting is easy info - gives info about what channels the bot is in, gets topic and title join - joins channel me - does a \me in a channel part - parts a channel plugin - manage plugins, list and unload them privman - manage privelege groups, plugin access et al. randfact - gets a random fact about a person from the Random Fact Generator say - Says something in a channel sys - System utilities, restart, shutdown, process info. Not fully windows compatible, working on improving this. thread - information about running threads, thread management validate - validate a website's html and css
Development documentation
API Reference.txt
rubot is based on the Object Oriented programming model.
Below is an API quick reference:
packet.channel.msg("hello!")
packet.channel.npmsg("hello!") # non parsed message
packet.channel.action("hello!")
packet.channel.users['rubot'].kick("reason") # privclass is optional
packet.channel.users['rubot'].promote("privclass") # privclass is optional
packet.channel.users['rubot'].demote("privclass") # privclass is optional
packet.channel.part()
packet.channel.setTopic("foo bar")
packet.channel.setTitle("foo bar")
packet.from # username when its a msg/action packet
packet.ns # channel namespace ex. "chat:devart"
packet.msg # the actual message
packet.target # username when its a join or part packet
packet.args # array of packet arguments
packet.channel.properties[:title].value
packet.channel.properties[:title].by
packet.channel.properties[:title].ts
packet.channel.properties[:topic].value
packet.channel.properties[:topic].by
packet.channel.properties[:topic].ts
packet.channel.properties[:privclasses][99][:name] # gets the name of privclass at order 99
packet.channel.properties[:privclasses][99][:members] # same as /admin show privclass 99
dAmn.channels['chat:devart'].users['rubot'].promote("privclass") #privclass is optional
etc...
dAmn.users['rubot'].channels['chat:devart'].msg("hello")
etc...
dAmn.join("chat:devart")
dAmn.msg("chat:devart","hello!")
dAmn.npmsg("chat:devart","hello!") # non parsed message
dAmn.action("chat:devart","hello!")
dAmn.kick("chat:devart","reason")
dAmn.part("chat:devart")
dAmn.promote("chat:devart","rubot","privclass") # privclass is optional
dAmn.demote("chat:devart","rubot","privclass") # privclass is optional
dAmn.promote("chat:devart","rubot","privclass") # privclass is optional
dAmn.disconnect() # it'll automatically reconnnect! use exit() to shutdown
ZAPI::message('info',"some info here") # see /core/class/ZAPI.class.rb for the message() documentation
# very similar to dAmnbot message()
ZAPI::tokenize("foo bar bam",1) # returns "bar"
ZAPI::tokenize("foo bar bam",1,' ',false) # returns "bar"
ZAPI::tokenize("foo bar bam",1,' ',true) # returns "bar bam"
ZAPI::tokenize("foo_bar+bam",0,'+') # returns "foo_bar"
ZAPI::unformatns("#devart") # returns "chat:devart"
ZAPI::unformatns("chat:devart") # returns "#devart"
ZAPI::makens("devart") # returns "chat:devart"
ZAPI::backtrace("\n") # returns a string with a backtrace in it
comment standard.txt
COMMENTING METHODS: # Method description. # # param1:: (datatype) # Parameter 1 description and purpose. # # param2:: (datatype) # Parameter 2 description and purpose. # # # Throws: (Exception) # The condition that causes the method to throw the above execption. # # Returns: (datatype [or datatype...]) # Description of what conditions (pre and post) cause each type # of value to be returned. # # Example: # # [...] # # baz = myMethod(:foo,1234) # # [...] # def myMethod( param1, param2 ) end
Creating plugins.txt
#### # Developing Plugins ## Plugins obviously go in the plugins folder, each plugin should be in its own folder with the folder name being the name of the plugin, in all lower case. There must be at least one file in the plugin directory and it must be named cmd.rb, That file must define a class with the name of the folder, following ruby naming conventions so of course the first letter must be a capital. Here's a simple template for plugins: module Plugin class Myplugin def pc_handleEvent( cmd ) end end end All plugins must be in the plugin module, and must define the method pc_handleEvent. The pc_handleEvent method is called when no other suitable method can be found, its the default. All plugin entry points (pc_* methods) must accept one parameter, this will be the PluginCommand object generated from the packet. Adding a subcommand is easy, just define a new method with the method name prefix pc_, for example pc_dosomething( cmd ). Plugins may specify an initialize method that accepts one parameter which will be a reference to the PluginHandler object. You may define this method with no parameters as well. Any more than 1 parameter and the plugin will NOT load!!! Plugins that are threaded MUST be thread safe, else you'll have issues with shared resource access. Plugins can also define a few special properties: switch_prefix: (String) This should be a string, it allows all subcommands to be prefixed with a special character so that they do no conflict with plugins that use the default method to do something. For example !define might use the '-' switch_prefix so that you have !define -add, !define -remove, !define -update. This would allow the user to do something like '!define remove' and not call the remove method by accident. use_thread: (Boolean) This allows you to override the default setting that controls if plugin command should be threaded or not. True makes the plugin threaded, while false makes it run in the root thread. Careful with this! If the plugin is running in the root thread then it will block on recieves. So make sure not to disable threaded on a plugin that will take a long while. I've set the default inside the bot to always thread plugins, and I've not had any significant issues. One reason you might not want to thread a plugin is if it accesses a shared resource, as threaded plugins must be thread safe. More on this later... I promise!
rubot callbacks.txt
Title: DAmnLib::DAmnClient Callbacks Help File Date: June 26, 2006 Author: Elliott H. Sprehn The file contains documentation on the DAmnLib::DAmnClient class's event system. Each event has a callback hook that allows the developer to attach listeners that perform tasks when these specific states occur. For instance you can write a module that runs a specific task every time the client recieves a kick packet. DESCRIPTION ---------- Callbacks are in the format "name:( param1, param2 )". It should be noted that callbacks propogate up the stack of events, not down it. For example if a pkt_recv_admin_users event is raised the event order would look like the following: 1. pkt_recv_admin_users 2. pkt_recv_admin 3. pkt_recv 4. pkt 5. tick Such that the most specific callback is raised first and the least specific callback is raised last. The tick event is special and is raised on each iteration of the handler loop, so all DAmnClient event stacks end in a tick event. All packet events end with a pkt event. PARAMETERS ---------- dAmn (DAmnLib::DAmnClient) A reference to the DAmnClient object where the connection to dAmn and all incoming and outgoing data is handled before being passed to the DAmnSock. packet (DAmnLib::DAmnPacket) A reference to the DAmnPacket object that was created when the packet was read out of the socket. The type of DAmnPacket depends on the type of packet that dAmn sent. CALLBACKS ---------- tick:( dAmn ) pkt:( dAmn, packet ) pkt_dAmnServer:( dAmn, packet ) pkt_login:( dAmn, packet ) pkt_login_good:( dAmn, packet ) pkt_login_failure:( dAmn, packet ) pkt_kicked:( dAmn, packet ) pkt_kicked_user:( dAmn, packet ) pkt_kicked_badmsg:( dAmn, packet) pkt_property:( dAmn, packet ) pkt_property_privclasses:( dAmn, packet ) pkt_property_members:( dAmn, packet ) pkt_property_topic:( dAmn, packet ) pkt_property_title:( dAmn, packet ) pkt_property_info:( dAmn, packet ) pkt_recv:( dAmn, packet ) pkt_recv_msg:( dAmn, packet ) pkt_recv_action:( dAmn, packet ) pkt_recv_join:( dAmn, packet ) pkt_recv_part:( dAmn, packet ) pkt_recv_kicked:( dAmn, packet ) pkt_recv_privchg:( dAmn, packet ) pkt_recv_admin:( dAmn, packet ) pkt_recv_admin_privclass:( dAmn, packet ) pkt_recv_admin_users:( dAmn, packet ) pkt_join:( dAmn, packet ) pkt_part:( dAmn, packet ) pkt_ping:( dAmn, packet ) pkt_shutdown:( dAmn, packet ) pkt_disconnect:( dAmn, packet ) pkt_send:( dAmn, packet )

