drivel 0.0.1

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.
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in drivel.gemspec
4
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2013 Joshua M. Keyes
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,79 @@
1
+ # Drivel
2
+
3
+ An alternative DSL utilizing the excellent XMPP library, Blather, for creating interactive XMPP bots.
4
+
5
+ ## Installation
6
+
7
+ Add this line to your application's Gemfile:
8
+
9
+ gem 'drivel'
10
+
11
+ And then execute:
12
+
13
+ $ bundle
14
+
15
+ Or install it yourself as:
16
+
17
+ $ gem install drivel
18
+
19
+ ## Usage
20
+
21
+ TBD.
22
+
23
+ ## Example
24
+
25
+ #!/usr/bin/env ruby
26
+
27
+ require 'drivel'
28
+
29
+ configure do
30
+ # Do basic setup/configuration.
31
+ set nickname: 'DrivelBot', jid: 'username@chat.example.com/resource', password: 'secretpassword'
32
+
33
+ # (Optional) conferences to discover and join.
34
+ set :conferences, 'main', 'offtopic'
35
+ end
36
+
37
+ helpers do
38
+ def authorized?(context)
39
+ context.chat? and message.from == 'owner@example.com'
40
+ end
41
+ end
42
+
43
+ connected do
44
+ status :available, 'At your service.'
45
+ end
46
+
47
+ disconnected do
48
+ status :offline, 'Going away now.' and shutdown
49
+ end
50
+
51
+ subscription do |message|
52
+ # Handle subscription messages like Blather would.
53
+ end
54
+
55
+ command 'ping' do |message|
56
+ respond message, 'pong'
57
+ end
58
+
59
+ command 'join :conference' do |message, params|
60
+ respond message, "I'm afraid I can't do that." and halt unless authorized?(message)
61
+ join params[:conference]
62
+ end
63
+
64
+ command 'leave :conference' do |message, params|
65
+ respond message, "I'm afraid I can't do that." and halt unless authorized?(message)
66
+ leave params[:conference]
67
+ end
68
+
69
+ recognize 'What is love?' do |message|
70
+ respond message, "Baby don't hurt me no more."
71
+ end
72
+
73
+ ## Contributing
74
+
75
+ 1. Fork it
76
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
77
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
78
+ 4. Push to the branch (`git push origin my-new-feature`)
79
+ 5. Create new Pull Request
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'drivel/version'
5
+
6
+ Gem::Specification.new do |gem|
7
+ gem.name = "drivel"
8
+ gem.version = Drivel::VERSION
9
+
10
+ gem.authors = ["Joshua M. Keyes"]
11
+ gem.email = ["joshua.michael.keyes@gmail.com"]
12
+
13
+ gem.description = %q{An alternative DSL utilizing the excellent XMPP library, Blather, for creating interactive XMPP bots.}
14
+ gem.summary = %q{A DSL for building XMPP bots.}
15
+ gem.homepage = "https://github.com/jmkeyes/drivel"
16
+
17
+ gem.files = `git ls-files`.split($/)
18
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
19
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
20
+ gem.require_paths = ["lib"]
21
+
22
+ gem.add_dependency 'blather', '= 0.8.1'
23
+ end
File without changes
@@ -0,0 +1,3 @@
1
+ require 'drivel/version'
2
+ require 'drivel/base'
3
+ require 'drivel/main'
@@ -0,0 +1,193 @@
1
+ require 'blather/client/client'
2
+
3
+ module Drivel
4
+ module DSL
5
+ def set(key, *values)
6
+ if key.is_a?(Hash) and values.empty?
7
+ key.each { |k, v| set(k, v) }
8
+ else
9
+ create_method("#{key}=") { |value| settings[key] = value }
10
+ create_method("#{key}?") { !!settings[key] }
11
+ create_method("#{key}") { settings[key] }
12
+
13
+ settings[key] = values.first
14
+ end
15
+ end
16
+
17
+ def configure
18
+ yield
19
+ end
20
+
21
+ def helpers(*helpers, &block)
22
+ self.instance_eval(&block) if block_given?
23
+ include(*helpers) unless helpers.empty?
24
+ end
25
+
26
+ def before(handler = nil, *guards, &block)
27
+ filter(:before, handler, *guards, &block)
28
+ end
29
+
30
+ def after(handler = nil, *guards, &block)
31
+ filter(:after, handler, *guards, &block)
32
+ end
33
+
34
+ def connected(&block)
35
+ handle(:ready, &block)
36
+ end
37
+
38
+ def disconnected(&block)
39
+ handle(:disconnected, &block)
40
+ end
41
+
42
+ def subscription(&block)
43
+ handle(:subscription, &block)
44
+ end
45
+
46
+ def command(pattern, *arguments, &block)
47
+ raise InvalidArgumentError unless pattern.is_a?(String) or pattern.is_a?(Regexp)
48
+
49
+ safe_nickname = Regexp.escape(settings[:nickname])
50
+ optional_prefix = /(?:#{safe_nickname}[:,]? |[!$%@])/i
51
+
52
+ pattern.gsub!(/((:\w+)|\*)/) do |key|
53
+ (key == '*' ? "(?<splat>.*?)" : "(?<#{key[1..-1]}>[^\s]+)")
54
+ end if pattern.is_a?(String)
55
+
56
+ recognize(/\A#{optional_prefix}#{pattern}\Z/, &block)
57
+ end
58
+
59
+ def recognize(pattern, *arguments, &block)
60
+ raise InvalidArgumentError unless pattern.is_a?(String) or pattern.is_a?(Regexp)
61
+
62
+ matcher = Regexp.compile(pattern, true)
63
+
64
+ handle(:message, :body => matcher) do |message|
65
+ matches = message.body.match(matcher)
66
+ captures = matches.names.map(&:to_sym).zip(matches.captures)
67
+ yield message, Hash[captures]
68
+ end
69
+ end
70
+
71
+ def ready?
72
+ jid? and password? and nickname?
73
+ end
74
+
75
+ def run!
76
+ client.setup(settings[:jid], settings[:password])
77
+
78
+ # Reopen standard input and direct it at /dev/null.
79
+ $stdin.reopen('/dev/null')
80
+
81
+ # Capture interrupt and terminate and force them to shutdown the connection.
82
+ [:INT, :TERM].each do |signal|
83
+ trap(signal) { shutdown }
84
+ end
85
+
86
+ # Start.
87
+ EM.run { client.run }
88
+ end
89
+
90
+ def status(mode, message)
91
+ mode = nil if mode == :offline
92
+ client.status = mode, message
93
+ end
94
+
95
+ def shutdown
96
+ client.close
97
+ end
98
+
99
+ def respond(message = nil, content = nil)
100
+ response = ::Blather::Stanza::Message.new.tap do |stanza|
101
+ if message and content
102
+ stanza.type, stanza.from = message.type, message.to
103
+
104
+ case message.type
105
+ when :groupchat
106
+ stanza.to = message.from.stripped
107
+ stanza.body = message.from.resource + ': ' + content
108
+ when :chat
109
+ stanza.to = message.from
110
+ stanza.body = content
111
+ else
112
+ raise ArgumentError, 'Cannot respond to messages of type ' + message.type.to_s
113
+ end
114
+ end
115
+
116
+ # Evaluate any given block, passing in this message before delivery.
117
+ yield stanza if block_given?
118
+ end
119
+
120
+ EM.next_tick { client.write(response) }
121
+ end
122
+
123
+ def join(conference, &block)
124
+ room = ::Blather::JID.new(conference)
125
+ request = ::Blather::Stanza::Presence::MUC.new.tap do |stanza|
126
+ target = ::Blather::JID.new(room.node, room.domain, settings[:nickname])
127
+ stanza.to, stanza.type = target, nil
128
+ end
129
+ client.write_with_handler(request)
130
+ end
131
+
132
+ def leave(conference, &block)
133
+ room = ::Blather::JID.new(conference)
134
+ request = ::Blather::Stanza::Presence::MUC.new.tap do |stanza|
135
+ target = ::Blather::JID.new(room.node, room.domain, settings[:nickname])
136
+ stanza.to, stanza.type = target, :unavailable
137
+ end
138
+ client.write_with_handler(request, &block)
139
+ end
140
+
141
+ def pass
142
+ throw :pass
143
+ end
144
+
145
+ def halt
146
+ throw :halt
147
+ end
148
+
149
+ def discover(type, target, node = nil, &block)
150
+ stanza = {
151
+ info: ::Blather::Stanza::DiscoInfo,
152
+ items: ::Blather::Stanza::DiscoItems
153
+ }[type].new
154
+
155
+ stanza.node = node
156
+ stanza.from = client.jid
157
+ stanza.to = target
158
+
159
+ client.write_with_handler(stanza, &block)
160
+ end
161
+
162
+ def schedule(interval, repeat = true, &block)
163
+ EM.next_tick do
164
+ if repeat
165
+ EM.add_periodic_timer(interval, &block)
166
+ else
167
+ EM.add_timer(interval, &block)
168
+ end
169
+ end
170
+ end
171
+
172
+ private
173
+ def settings
174
+ @settings ||= {}
175
+ end
176
+
177
+ def client
178
+ @client ||= ::Blather::Client.new
179
+ end
180
+
181
+ def handle(type, *guards, &block)
182
+ client.register_handler(type, *guards, &block)
183
+ end
184
+
185
+ def filter(type, handler = nil, *guards, &block)
186
+ client.register_filter(type, handler, *guards, &block)
187
+ end
188
+
189
+ def create_method(name, *arguments, &block)
190
+ self.class.send(:define_method, name, *arguments, &block)
191
+ end
192
+ end
193
+ end
@@ -0,0 +1,4 @@
1
+ require 'drivel/base'
2
+
3
+ Object.send(:include, ::Drivel::DSL)
4
+ at_exit { run! if ready? }
@@ -0,0 +1,3 @@
1
+ module Drivel
2
+ VERSION = "0.0.1"
3
+ end
File without changes
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: drivel
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Joshua M. Keyes
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-03-05 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: blather
16
+ requirement: &7989760 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - =
20
+ - !ruby/object:Gem::Version
21
+ version: 0.8.1
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *7989760
25
+ description: An alternative DSL utilizing the excellent XMPP library, Blather, for
26
+ creating interactive XMPP bots.
27
+ email:
28
+ - joshua.michael.keyes@gmail.com
29
+ executables: []
30
+ extensions: []
31
+ extra_rdoc_files: []
32
+ files:
33
+ - .gitignore
34
+ - Gemfile
35
+ - LICENSE.txt
36
+ - README.md
37
+ - Rakefile
38
+ - drivel.gemspec
39
+ - examples/.gitkeep
40
+ - lib/drivel.rb
41
+ - lib/drivel/base.rb
42
+ - lib/drivel/main.rb
43
+ - lib/drivel/version.rb
44
+ - spec/spec_helper.rb
45
+ homepage: https://github.com/jmkeyes/drivel
46
+ licenses: []
47
+ post_install_message:
48
+ rdoc_options: []
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ! '>='
55
+ - !ruby/object:Gem::Version
56
+ version: '0'
57
+ required_rubygems_version: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ requirements: []
64
+ rubyforge_project:
65
+ rubygems_version: 1.8.15
66
+ signing_key:
67
+ specification_version: 3
68
+ summary: A DSL for building XMPP bots.
69
+ test_files:
70
+ - spec/spec_helper.rb
71
+ has_rdoc: