codebrulee-aide 0.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README ADDED
@@ -0,0 +1,82 @@
1
+ = Aide - What can Jabber do for you?
2
+
3
+ http://github.com/duwanis/aide
4
+
5
+ == DESCRIPTION:
6
+
7
+ Aide is a DSL for defining and running Jabber bots.
8
+ In order to have a good grasp on how to use Aide, you'll want to familiarize
9
+ yourself with two classes: Aide::Dsl (used to actually read the Aide DSL), and
10
+ Aide::ActionContext (blocks defined using the DSL get executed in the scope of
11
+ an ActionContext). More thorough documentation will be coming soon...
12
+
13
+ == FEATURES/PROBLEMS:
14
+
15
+ It doesn't do anything yet. This is the main problem, really.
16
+
17
+ == EXAMPLE:
18
+
19
+ Check out example.aide in the source. If you install the gem
20
+ (see INSTALL below), you should be able to do the following to
21
+ see the results of parsing the file (or any other file matching
22
+ the DSL):
23
+ aide example.aide
24
+
25
+
26
+ == REQUIREMENTS:
27
+
28
+ Patience.
29
+
30
+
31
+ == INSTALL:
32
+
33
+ sudo gem install duwanis-aide --source=http://gems.github.com
34
+
35
+ == ROADMAP:
36
+
37
+ Here's the plan:
38
+ - 0.1 - Functionality in place to create a very simple bot. Can take in any
39
+ number of static commands, but nothing fancy.
40
+ - 0.2 - Help/describe functionality built in by default.
41
+ - 0.3 - Dynamic commands.
42
+ - 0.4 - Ability to subscribe to an XMPP Publisher (XEP-0060)
43
+ - 0.5 - Scheduled tasks (e.g. "execute this code every minute")
44
+ - 0.6 - Ability to act as an XMPP Publisher (XEP-0060)
45
+ - 0.7 - Command-line interface for publishing events (e.g. aide-publish [botname] [event])
46
+ - 0.8 - ?????
47
+ - 0.9 - Profit!
48
+ - 1.0 - Fully functional 1.0 release.
49
+
50
+ == HISTORY:
51
+
52
+ - 0.0.4 - Beginnings of xmpp4r integration.
53
+ - 0.0.2 - Bot class started, DSL is done in a sane way (no more creating kernel
54
+ methods, woo)
55
+ - 0.0.1 - Proof of concept. DSL is somewhat spec'd out, and you
56
+ are now capable of parsing files (albeit crudely).
57
+ - 0.0.0 - A new project is born!
58
+
59
+ == LICENSE:
60
+
61
+ (The MIT License)
62
+
63
+ Copyright (c) 2008 Tommy Morgan
64
+
65
+ Permission is hereby granted, free of charge, to any person obtaining
66
+ a copy of this software and associated documentation files (the
67
+ 'Software'), to deal in the Software without restriction, including
68
+ without limitation the rights to use, copy, modify, merge, publish,
69
+ distribute, sublicense, and/or sell copies of the Software, and to
70
+ permit persons to whom the Software is furnished to do so, subject to
71
+ the following conditions:
72
+
73
+ The above copyright notice and this permission notice shall be
74
+ included in all copies or substantial portions of the Software.
75
+
76
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
77
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
78
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
79
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
80
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
81
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
82
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rubygems'
3
+ require 'aide'
4
+
5
+ filepath = Pathname.new(ARGV[0]).cleanpath.to_s
6
+
7
+ bot = Aide::Bot.new
8
+ dsl = Aide::Dsl.new(bot, filepath)
@@ -0,0 +1,11 @@
1
+ # Just to make our requires at the top of the gem a little easier.
2
+ require 'pathname'
3
+ $:.unshift(Pathname(__FILE__).dirname.expand_path)
4
+
5
+ require 'rubygems'
6
+ require 'xmpp4r'
7
+
8
+ require 'aide/errors'
9
+ require 'aide/bot'
10
+ require 'aide/dsl'
11
+ require 'aide/version'
@@ -0,0 +1,49 @@
1
+ module Aide
2
+ ##
3
+ # This class is used to provide an execution context for processing messages.
4
+ # It houses all the attributes and helper methods that are to be exposed to
5
+ # the blocks that are passed in to Aide via the Aide::Dsl.with method.
6
+ # These contexts are created and destroyed on a per-message basis, so all
7
+ # attribute values refer to the message that is currently being processed.
8
+ #
9
+ class ActionContext
10
+ #String - The Jabber address from which the message was sent.
11
+ attr_accessor :from
12
+ #String - The Jabber address to which the message was sent.
13
+ attr_accessor :to
14
+ #String - The text of the message, minus the portion that was
15
+ #matched by the bot.
16
+ attr_accessor :message
17
+ #String - The full text of the message, including the portion that
18
+ #was matched by the bot.
19
+ attr_accessor :text
20
+ #Symbol - The type of the message (e.g. :chat, :group, etc.)
21
+ attr_accessor :type
22
+ #Aide::Bot - The bot instance that received and is acting on this
23
+ #message.
24
+ attr_accessor :bot
25
+
26
+ ##
27
+ # Sends a message back to the jabber id that sent the original message.
28
+ #=== Parameters:
29
+ # - *text*: String. The text of the message to send.
30
+ #
31
+ def respond(text)
32
+ send(text, from)
33
+ end
34
+
35
+ ##
36
+ # Sends a message to the specified jabber id.
37
+ #=== Parameters:
38
+ # - *text*: String. The text of the message to send.
39
+ # - *to*: String. The jabber id to send the message to.
40
+ #
41
+ def send(text, to)
42
+ response = Message.new(to, text)
43
+ response.type = :chat
44
+
45
+ bot.send(response)
46
+ end
47
+
48
+ end
49
+ end
@@ -0,0 +1,176 @@
1
+ module Aide
2
+ ##
3
+ # The Bot class is the workhorse of aide. It is responsible for representing
4
+ # and executing the logic described by the dsl, and interacts with xmpp4r
5
+ # in order to send and receive messages via the jabber protocol.
6
+ #
7
+ class Bot
8
+
9
+ #Hash[String, Block] - the match strings to look for, and the code to execute when found.
10
+ attr_writer :actions
11
+
12
+ #String - the username to sign this bot in with.
13
+ attr_writer :username
14
+ #Password - the password for this bot to use.
15
+ attr_writer :password
16
+ #Array[String] - a list of jabber IDs to allow this bot to interact with. Precludes block_list.
17
+ attr_accessor :allow_list
18
+ #Array[String] - a list of jabber IDs to explicitly block. Ignored if allow_list is set.
19
+ attr_accessor :block_list
20
+
21
+ ##
22
+ #Creates a new Bot instance.
23
+ #
24
+ def initialize
25
+ @actions = {}
26
+ end
27
+
28
+ ##
29
+ #Logs this Bot instance in to the jabber network and starts it listening
30
+ #for messages.
31
+ #=== Preconditions
32
+ #This method assumes that the Bot has already been properly configured;
33
+ #specifically, that at least the username and password properties have
34
+ #been set.
35
+ #=== Postconditions
36
+ #- The Bot will be logged on,
37
+ #- Its presence will be set to 'chat,' and
38
+ #- It will be listening for messages from privileged users in its own thread
39
+ #(see is_user_allowed?)
40
+ #=== Returns
41
+ #+nil+
42
+ #
43
+ def login
44
+ if @password == nil or @username == nil
45
+ raise Aide::Login_Error, "credentials missing"
46
+ end
47
+ @client = Jabber::Client.new(Jabber::JID.new(@username))
48
+ @client.connect
49
+
50
+ #actual authentication with the host
51
+ begin
52
+ @client.auth(@password)
53
+ rescue Jabber::AuthenticationFailure => af
54
+ raise Aide::Login_Error, "Authentication failure: #{af.message}", af.backtrace
55
+ end
56
+
57
+ @client.send(Jabber::Presence.new)
58
+ @thread = Thread.new do
59
+ @client.add_message_callback do |m|
60
+ if m.type == :chat and is_user_allowed? m.from.split('/')[0]
61
+ process_message m
62
+ end
63
+ end
64
+ end
65
+
66
+ end
67
+
68
+ ##
69
+ #Sends the given message.
70
+ #=== Parameters
71
+ #- *message*: Jabber::Message. The message to send.
72
+ #
73
+ def send(message)
74
+ @client.send message
75
+ end
76
+
77
+ ##
78
+ #Examines the given message to see if any actions need to be performed
79
+ #on it. If this message matches any actions defined for this Bot, an
80
+ #Aide::ActionContext is created and used to evaluate the block associated
81
+ #with that action.
82
+ #=== Parameters
83
+ #- *message*: Jabber::Message. The message to process.
84
+ #
85
+ def process_message(message)
86
+ results = match(message.body)
87
+ return nil unless results #no need to do anything if there's no match
88
+
89
+ context = Aide::ActionContext.new
90
+ block = @actions[results[:action_name]]
91
+ context.message = results[:message]
92
+ context.from = message.from
93
+ context.to = message.to
94
+ context.bot = self
95
+ context.text = message.body
96
+ context.type = message.type
97
+ context.instance_eval(block.call)
98
+
99
+ nil #no need to complicate things by returning the results of the block
100
+ end
101
+
102
+ ##
103
+ #Log the bot out of jabber and kill the thread that is listening for
104
+ #messages.
105
+ #
106
+ def logout
107
+ @client.close
108
+ @thread.stop
109
+ end
110
+
111
+ ##
112
+ #Given the text of a message, determines if that text matches any of the
113
+ #actions defined for this Bot.
114
+ #=== Parameters
115
+ #- *text*: String. The text of the message to check for matches.
116
+ #=== Returns
117
+ #Hash[:action_name, :message]
118
+ #Where :action_name corresponds to the name of the action this text
119
+ #matches, and :message corresponds to everything in +text+ after the match.
120
+ #Returns +nil+ if no match was found.
121
+ #
122
+ def match(text)
123
+ nil
124
+ # defaulting to no match until this method is implemented
125
+ end
126
+
127
+ ##
128
+ #Checks a given username to see if it is explicitly allowed or blocked.
129
+ #=== Parameters
130
+ #- *username*: String. The username to check privileges for.
131
+ #=== Returns
132
+ #+boolean+ - the value of this boolean depends on the level of privileges
133
+ #set when the Bot was configured. If an allow_list is defined, then that
134
+ #list has highest precedence - +true+ is returned if the user is in that
135
+ #list, and +false+ is returned otherwise. If allow_list is not defined,
136
+ #but block_list is, then the inverse check is performed (+true+ is
137
+ #returned when the user is absent from the block_list, and vice-versa).
138
+ #If neither list is defined then the user is assumed to be authorized.
139
+ #
140
+ def is_user_allowed?(username)
141
+ return @allow_list.member?(username) if @allow_list
142
+ return !@block_list.member?(username) if @block_list
143
+ return true
144
+ end
145
+
146
+ ##
147
+ # Adds an action to the bot.
148
+ #=== Parameters:
149
+ #- *match*: String. The text to match for this action.
150
+ #- *block*: Proc. The code to execute when this action is fired.
151
+ #
152
+ def add_action(match, block)
153
+ @actions[match] = block
154
+ end
155
+
156
+ ##
157
+ # Allows for appending to the allow_list.
158
+ #=== Parameters:
159
+ #- *list*: Array[String]. The list of users to add to the allow_list.
160
+ #
161
+ def add_allow_list(list)
162
+ @allow_list ||= []
163
+ @allow_list += list
164
+ end
165
+
166
+ ##
167
+ # Allows for appending to the block_list.
168
+ #=== Parameters:
169
+ #- *list*: Array[String]. The list of users to add to the block_list.
170
+ #
171
+ def add_block_list(list)
172
+ @block_list ||= []
173
+ @block_list += list
174
+ end
175
+ end # Bot
176
+ end # Aide
@@ -0,0 +1,74 @@
1
+ module Aide
2
+ ##
3
+ #The Dsl class is used for parsing Aide dsl files. All of the functions made
4
+ #available by this class are available to any dsl file.
5
+ #TODO: This class needs better documentation.
6
+ #
7
+ class Dsl
8
+ ##
9
+ # Creates a new Dsl instance.
10
+ #=== Parameters:
11
+ #- *bot*: Aide::Bot. The bot this dsl will modify/set up.
12
+ #- *filename*: String. The file to parse, if any; defaults to nil.
13
+ #=== Yields:
14
+ #Yields self after the file is parsed.
15
+ #
16
+ def initialize(bot, filename = nil)
17
+ @bot = bot
18
+ load_file filename if filename
19
+ yield self if block_given?
20
+ end
21
+
22
+ ##
23
+ # Sets the username for the Bot that is being loaded.
24
+ #
25
+ def bot_username(text)
26
+ @bot.username=text
27
+ end
28
+
29
+ ##
30
+ # Sets the password for the Bot that is being loaded.
31
+ #
32
+ def bot_password(text)
33
+ @bot.password=text
34
+ end
35
+
36
+ ##
37
+ # Adds *people to the allow_list.
38
+ #
39
+ def allow(*people)
40
+ @bot.add_allow_list people
41
+ end
42
+
43
+ ##
44
+ # Adds *people to the block_list.
45
+ #
46
+ def block(*people)
47
+ @bot.add_block_list people
48
+ end
49
+
50
+ ##
51
+ # Defines an action for the bot.
52
+ #===Parameters:
53
+ #- *text*: String. The text to match on.
54
+ #- *&block*: Block. The code to execute when *text* is found (see Aide::ActionContext)
55
+ #
56
+ def with(text,&block)
57
+ @bot.add_action text, block
58
+ end
59
+
60
+ ##
61
+ # Reads in and parses a Dsl file.
62
+ #
63
+ def load_file(filename)
64
+ instance_eval(File.read(filename), filename)
65
+ end
66
+
67
+ ##
68
+ # Parses a block as though it were a Dsl file.
69
+ #
70
+ def load_block(&block)
71
+ instance_eval(&block)
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,8 @@
1
+ module Aide
2
+ ##
3
+ #Login_Error represents a problem with the credentials
4
+ #given to an instance of Aide::Bot.
5
+ #
6
+ class Login_Error < StandardError
7
+ end
8
+ end
@@ -0,0 +1,9 @@
1
+ module Aide #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 4
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: codebrulee-aide
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.4
5
+ platform: ruby
6
+ authors:
7
+ - Tommy Morgan
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-06-09 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: xmpp4r
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">="
21
+ - !ruby/object:Gem::Version
22
+ version: 0.3.0
23
+ version:
24
+ description: Aide provides a DSL for quickly and easily building Jabber (XMPP) bots.
25
+ email: tommy.morgan@gmail.com
26
+ executables:
27
+ - aide
28
+ extensions: []
29
+
30
+ extra_rdoc_files: []
31
+
32
+ files:
33
+ - README
34
+ - bin/aide
35
+ - lib/aide.rb
36
+ - lib/aide/actioncontext.rb
37
+ - lib/aide/bot.rb
38
+ - lib/aide/dsl.rb
39
+ - lib/aide/errors.rb
40
+ - lib/aide/version.rb
41
+ has_rdoc: true
42
+ homepage: http://github.com/duwanis/aide
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --main
46
+ - README
47
+ require_paths:
48
+ - lib
49
+ required_ruby_version: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ required_rubygems_version: !ruby/object:Gem::Requirement
56
+ requirements:
57
+ - - ">="
58
+ - !ruby/object:Gem::Version
59
+ version: "0"
60
+ version:
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.0.1
65
+ signing_key:
66
+ specification_version: 2
67
+ summary: A DSL for defining and running Jabber bots.
68
+ test_files: []
69
+