awesome_bot_factory 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.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/Rakefile +23 -0
- data/awesome_bot_factory.gemspec +25 -0
- data/bin/awesomebotfactory +111 -0
- data/lib/awesome_bot_factory.rb +9 -0
- data/lib/awesome_bot_factory/example_payload.rb +32 -0
- data/lib/awesome_bot_factory/skill.rb +41 -0
- data/lib/awesome_bot_factory/version.rb +3 -0
- data/lib/templates/Gemfile.erb +13 -0
- data/lib/templates/Procfile.erb +2 -0
- data/lib/templates/config.ru.erb +8 -0
- data/lib/templates/readme.md.erb +4 -0
- data/lib/templates/skill.rb.erb +18 -0
- data/lib/templates/skill_spec.rb.erb +22 -0
- data/lib/templates/spec_helper.rb.erb +14 -0
- data/spec/awesome_bot_factory/skill_spec.rb +63 -0
- data/spec/spec_helper.rb +8 -0
- metadata +117 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'bundler'
|
2
|
+
Bundler.setup
|
3
|
+
require "rspec"
|
4
|
+
require "rspec/core/rake_task"
|
5
|
+
|
6
|
+
task :gem => :build
|
7
|
+
task :build do
|
8
|
+
system "gem build awesome_bot_factory.gemspec"
|
9
|
+
end
|
10
|
+
|
11
|
+
task :install => :build do
|
12
|
+
system "gem install awesome_bot_factory-#{AwesomeBotFactory::VERSION}.gem"
|
13
|
+
end
|
14
|
+
|
15
|
+
task :release => :build do
|
16
|
+
system "git tag -a #{AwesomeBotFactory::VERSION} -m 'Tagging #{AwesomeBotFactory::VERSION}'"
|
17
|
+
system "git push --tags"
|
18
|
+
system "gem push awesome_bot_factory-#{AwesomeBotFactory::VERSION}.gem"
|
19
|
+
end
|
20
|
+
|
21
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
22
|
+
spec.pattern = "spec/**/*_spec.rb"
|
23
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
$: << File.expand_path('../lib', __FILE__)
|
3
|
+
require "awesome_bot_factory/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "awesome_bot_factory"
|
7
|
+
s.version = AwesomeBotFactory::VERSION
|
8
|
+
s.authors = ["Michael Bumann"]
|
9
|
+
s.email = ["michael@railslove.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{The AwesomeBotFactory gem}
|
12
|
+
s.description = %q{The AwesomeBotFactory lets you generate lovely bots for your campfire rooms. This gem brings a simple skeleton to build your bots}
|
13
|
+
|
14
|
+
s.rubyforge_project = "[none]"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_path = "lib"
|
20
|
+
|
21
|
+
s.add_dependency 'activesupport', '~> 3.0.0'
|
22
|
+
s.add_dependency 'thor', '~> 0.14.6'
|
23
|
+
s.add_development_dependency "rake"
|
24
|
+
s.add_development_dependency "rspec"
|
25
|
+
end
|
@@ -0,0 +1,111 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "rubygems"
|
4
|
+
require "thor"
|
5
|
+
require 'active_support/inflector'
|
6
|
+
require 'awesome_bot_factory'
|
7
|
+
class AwsomeBotFactoryRunner < Thor
|
8
|
+
include Thor::Actions
|
9
|
+
source_root File.expand_path("../lib/templates", File.dirname(__FILE__))
|
10
|
+
|
11
|
+
desc "deploy", "deploys the application to heroku"
|
12
|
+
def deploy(name=nil)
|
13
|
+
@skill_app_name = name || "abf-#{Dir.getwd.split("/").last}"
|
14
|
+
if !bot_directory?
|
15
|
+
say "no bot found. please make sure to run this command in your application directory", :red
|
16
|
+
return
|
17
|
+
end
|
18
|
+
|
19
|
+
run "bundle install", :capture => true
|
20
|
+
|
21
|
+
git_dirty = !(run("git status", :capture => true) =~ /nothing to commit/)
|
22
|
+
if git_dirty
|
23
|
+
run "git add .", :capture => true
|
24
|
+
run "git commit -a -m 'deployment'", :capture => true
|
25
|
+
end
|
26
|
+
|
27
|
+
remotes = run "git remote", :capture => true
|
28
|
+
heroku_initialized = remotes =~ /heroku/
|
29
|
+
if !heroku_initialized
|
30
|
+
say "creating a new heroku application", :green
|
31
|
+
run "heroku apps:create #{skill_app_name} --stack cedar"
|
32
|
+
end
|
33
|
+
run "git push heroku master"
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "create name", "Creates a new application skeleton for a new awesome bot factory skill"
|
37
|
+
def create(name)
|
38
|
+
directory = bot_directory? ? "." : name.underscore
|
39
|
+
say "Welcome to the AWESOME BOT FACTORY!", :green
|
40
|
+
say "setting up your laboratory for #{name}", :green
|
41
|
+
@skill_class_name = name.underscore.camelize
|
42
|
+
@skill_file_name = name.underscore
|
43
|
+
template('skill.rb.erb', "#{directory}/#{skill_file_name}.rb")
|
44
|
+
if bot_directory?
|
45
|
+
insert_into_file("#{directory}/config.ru", "\nrequire File.join(File.dirname(__FILE__), '#{skill_file_name}.rb')", :after => "Bundler.require")
|
46
|
+
append_file("#{directory}/config.ru", %Q{
|
47
|
+
map '/#{skill_file_name}' do
|
48
|
+
run #{skill_class_name}
|
49
|
+
end
|
50
|
+
});
|
51
|
+
inside(directory) do
|
52
|
+
run "git commit -a -m 'hello #{name}'"
|
53
|
+
end
|
54
|
+
else
|
55
|
+
template('config.ru.erb', "#{directory}/config.ru")
|
56
|
+
template('Procfile.erb', "#{directory}/Procfile")
|
57
|
+
template('Gemfile.erb', "#{directory}/Gemfile")
|
58
|
+
template('readme.md.erb', "#{directory}/README.md")
|
59
|
+
template('skill_spec.rb.erb', "#{directory}/spec/#{skill_file_name}_spec.rb")
|
60
|
+
template('spec_helper.rb.erb', "#{directory}/spec/spec_helper.rb")
|
61
|
+
inside(directory) do
|
62
|
+
run 'bundle install', :capture => true
|
63
|
+
run 'git init'
|
64
|
+
run 'git add .'
|
65
|
+
run "git commit -a -m 'hello #{name}'"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
say "#{skill_author}, #{name} was created, happy hacking!", :green
|
69
|
+
end
|
70
|
+
|
71
|
+
desc "request", "send a test payload to your local application and see what it returns"
|
72
|
+
def request(name, matches="")
|
73
|
+
require "net/http"
|
74
|
+
require "awesome_bot_factory"
|
75
|
+
require "json"
|
76
|
+
|
77
|
+
attributes = JSON.parse(matches) rescue {"match" => matches.split(",")}
|
78
|
+
name = name.underscore
|
79
|
+
|
80
|
+
url = URI.parse("http://localhost:9292/#{name}")
|
81
|
+
request = Net::HTTP::Post.new(url.path)
|
82
|
+
request.body = AwesomeBotFactory::ExamplePayload.new(attributes).as_json
|
83
|
+
response = Net::HTTP.new(url.host, url.port).start {|http| http.request(request) }
|
84
|
+
|
85
|
+
say response.body
|
86
|
+
end
|
87
|
+
|
88
|
+
private
|
89
|
+
|
90
|
+
def skill_file_name
|
91
|
+
@skill_file_name
|
92
|
+
end
|
93
|
+
|
94
|
+
def skill_class_name
|
95
|
+
@skill_class_name
|
96
|
+
end
|
97
|
+
|
98
|
+
def skill_author
|
99
|
+
@skill_author ||= ENV["USER"]
|
100
|
+
end
|
101
|
+
|
102
|
+
def skill_app_name
|
103
|
+
(@skill_app_name || @skill_file_name).to_s.gsub("_","-").downcase
|
104
|
+
end
|
105
|
+
|
106
|
+
def bot_directory?
|
107
|
+
!Dir["*.rb"].find{|f| File.read(f) =~ /AwesomeBotFactory::Skill/ }.nil?
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
AwsomeBotFactoryRunner.start
|
@@ -0,0 +1,9 @@
|
|
1
|
+
require "json"
|
2
|
+
require "awesome_bot_factory/version"
|
3
|
+
require 'active_support/configurable'
|
4
|
+
require 'active_support/core_ext/hash/keys'
|
5
|
+
|
6
|
+
module AwesomeBotFactory
|
7
|
+
autoload :Skill, 'awesome_bot_factory/skill'
|
8
|
+
autoload :ExamplePayload, 'awesome_bot_factory/example_payload'
|
9
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module AwesomeBotFactory
|
2
|
+
class ExamplePayload < Hash
|
3
|
+
DEFAULTS = {
|
4
|
+
"body" => "campfire message",
|
5
|
+
"room_id" => "123456",
|
6
|
+
"user_id" => "7890",
|
7
|
+
"user" => {
|
8
|
+
"name" => "Choco Bit",
|
9
|
+
"avatar_url" => "http://asset0.37img.com/global/.../avatar.png",
|
10
|
+
"type" => "Member",
|
11
|
+
"admin" => false
|
12
|
+
},
|
13
|
+
"user_name" => "choco",
|
14
|
+
"match" => ["key:command value", "command", "value"],
|
15
|
+
"slug" => "hexhash"
|
16
|
+
}
|
17
|
+
|
18
|
+
def initialize(attributes={})
|
19
|
+
self.merge!(DEFAULTS)
|
20
|
+
self.merge!(attributes)
|
21
|
+
end
|
22
|
+
|
23
|
+
def as_hash
|
24
|
+
self
|
25
|
+
end
|
26
|
+
|
27
|
+
def as_json
|
28
|
+
as_hash.to_json
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module AwesomeBotFactory
|
2
|
+
class Skill
|
3
|
+
include ActiveSupport::Configurable
|
4
|
+
|
5
|
+
attr_accessor :message
|
6
|
+
|
7
|
+
def self.matches(*matches)
|
8
|
+
@@matches = matches
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.call(env)
|
12
|
+
message = JSON.parse(env["rack.input"].read)
|
13
|
+
[200, {"Content-Type" => "application/json"}, [ self.new(message).reply.to_json] ]
|
14
|
+
end
|
15
|
+
|
16
|
+
def initialize(campfire_message={})
|
17
|
+
self.message = campfire_message
|
18
|
+
self.message["match"] ||= [] # let's just make sure we have an hash there and don't break if it is in any case empty
|
19
|
+
end
|
20
|
+
|
21
|
+
def read_attribute(attr)
|
22
|
+
index = @@matches.index(attr.to_sym)
|
23
|
+
if index
|
24
|
+
self.message["match"][index+1]
|
25
|
+
else
|
26
|
+
self.message[attr.to_s] || self.message[attr.to_sym]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def attribute_defined?(attr)
|
31
|
+
!@@matches.index(attr).nil?
|
32
|
+
end
|
33
|
+
|
34
|
+
def method_missing(name, *args)
|
35
|
+
return self.message[name.to_s] if self.message.key?(name.to_s)
|
36
|
+
return self.message[name.to_sym] if self.message.key?(name.to_sym)
|
37
|
+
return self.read_attribute(name) if self.attribute_defined?(name)
|
38
|
+
super(name,*args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "thin"
|
4
|
+
gem "rack"
|
5
|
+
gem "awesome_bot_factory", '~><%= AwesomeBotFactory::VERSION %>'
|
6
|
+
|
7
|
+
group :development do
|
8
|
+
gem "heroku"
|
9
|
+
end
|
10
|
+
group :test do
|
11
|
+
gem "rspec", '~>2.6.0'
|
12
|
+
gem "rack-test", '~>0.6.1', :require => "rack/test"
|
13
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
class <%= skill_class_name %> < AwesomeBotFactory::Skill
|
2
|
+
|
3
|
+
configure do |c|
|
4
|
+
c.name = "<%= skill_class_name %>"
|
5
|
+
c.description = ""
|
6
|
+
c.author = "<%= skill_author %>"
|
7
|
+
c.url = "http://abf-<%= skill_app_name %>.herokuapp.com/<%= skill_file_name %>"
|
8
|
+
c.regex = "<%= skill_file_name %>:(.+)"
|
9
|
+
c.help = ""
|
10
|
+
end
|
11
|
+
|
12
|
+
matches :matches, :of, :your, :regex
|
13
|
+
|
14
|
+
def reply
|
15
|
+
{ :type => "TextMessage", :body => "hello world" }
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe <%= skill_class_name %> do
|
4
|
+
|
5
|
+
subject { <%= skill_class_name %>.new(AwesomeBotFactory::ExamplePayload.new("match" => ["bot:dance around the world", "dance", "around", "the", "world"])) }
|
6
|
+
|
7
|
+
it { should have_matches_for(:matches, :of, :your, :regex) }
|
8
|
+
its(:matches) { should eql("dance") }
|
9
|
+
its(:reply) { should eql({ :type => "TextMessage", :body => "hello world" })}
|
10
|
+
|
11
|
+
describe "as a rack application" do
|
12
|
+
let(:app) { <%= skill_class_name %> }
|
13
|
+
before do
|
14
|
+
post "/<%= skill_file_name %>", {}, :input => AwesomeBotFactory::ExamplePayload.new("match" => ["bot:dance around the world", "dance", "around", "the", "world"]).as_json
|
15
|
+
end
|
16
|
+
let(:json_body) { JSON.parse(last_response.body) }
|
17
|
+
|
18
|
+
it { last_response.should be_ok }
|
19
|
+
it { json_body["type"].should eql("TextMessage") }
|
20
|
+
it { json_body["body"].should eql("hello world") }
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require "bundler/setup"
|
2
|
+
Bundler.require(:default, :test)
|
3
|
+
|
4
|
+
require File.expand_path("../<%= skill_file_name %>.rb", File.dirname(__FILE__))
|
5
|
+
|
6
|
+
RSpec.configure do |config|
|
7
|
+
config.include Rack::Test::Methods
|
8
|
+
end
|
9
|
+
|
10
|
+
RSpec::Matchers.define :have_matches_for do |*expected|
|
11
|
+
match do |actual|
|
12
|
+
expected.all? { |e| actual.class.class_variable_get("@@matches").include?(e) }
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
describe AwesomeBotFactory::Skill do
|
3
|
+
|
4
|
+
it "should initialize an empty match array if nothing given" do
|
5
|
+
TestSkill.new.match.should eql([])
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "Rack endpoint" do
|
9
|
+
|
10
|
+
before do
|
11
|
+
JSON.should_receive(:parse).with("body").and_return({:all=>:fake})
|
12
|
+
TestSkill.should_receive(:new).with({:all => :fake}).and_return(mock(:reply => {:body => "response"}))
|
13
|
+
end
|
14
|
+
subject {
|
15
|
+
TestSkill.call({"rack.input" => StringIO.new("body")})
|
16
|
+
}
|
17
|
+
|
18
|
+
its([0]) { should eql(200) }
|
19
|
+
its([1]) { should eql({"Content-Type" => "application/json"}) }
|
20
|
+
its([2]) { should eql(['{"body":"response"}']) }
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
describe "Attributes" do
|
25
|
+
before do
|
26
|
+
TestSkill.matches :one, :two
|
27
|
+
end
|
28
|
+
|
29
|
+
subject { TestSkill.new({"user" => "Mole", :room_id => "12345", :nill => nil, "match" => [1,2,3]}) }
|
30
|
+
|
31
|
+
describe "accessors" do
|
32
|
+
|
33
|
+
its(:one) { should eql(2)}
|
34
|
+
its(:two) { should eql(3)}
|
35
|
+
its(:user) { should eql("Mole") }
|
36
|
+
its(:room_id) { should eql("12345") }
|
37
|
+
its(:nill) { should be_nil }
|
38
|
+
its(:message) { should eql({"user" => "Mole", :room_id => "12345", :nill => nil, "match" => [1,2,3]})}
|
39
|
+
specify { expect { subject.undefined_methdo }.to raise_error(NoMethodError) }
|
40
|
+
end
|
41
|
+
|
42
|
+
describe "read attributes" do
|
43
|
+
it { subject.read_attribute(:user).should eql("Mole") }
|
44
|
+
it { subject.read_attribute(:room_id).should eql("12345") }
|
45
|
+
it { subject.read_attribute(:nill).should be_nil }
|
46
|
+
it { subject.read_attribute(:not_found).should be_nil }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "Configuration" do
|
51
|
+
before(:all) do
|
52
|
+
TestSkill.configure do |c|
|
53
|
+
c.name = "Bender"
|
54
|
+
c.description = "THE Bot"
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
subject { TestSkill.config }
|
59
|
+
its(:name) { should eql("Bender") }
|
60
|
+
its(:description) { should eql("THE Bot") }
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,117 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: awesome_bot_factory
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Michael Bumann
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2011-09-07 00:00:00.000000000Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: activesupport
|
16
|
+
requirement: &2159771200 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.0.0
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *2159771200
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: thor
|
27
|
+
requirement: &2159770700 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ~>
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: 0.14.6
|
33
|
+
type: :runtime
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *2159770700
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: rake
|
38
|
+
requirement: &2159770320 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ! '>='
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: '0'
|
44
|
+
type: :development
|
45
|
+
prerelease: false
|
46
|
+
version_requirements: *2159770320
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: &2159769860 !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: *2159769860
|
58
|
+
description: The AwesomeBotFactory lets you generate lovely bots for your campfire
|
59
|
+
rooms. This gem brings a simple skeleton to build your bots
|
60
|
+
email:
|
61
|
+
- michael@railslove.com
|
62
|
+
executables:
|
63
|
+
- awesomebotfactory
|
64
|
+
extensions: []
|
65
|
+
extra_rdoc_files: []
|
66
|
+
files:
|
67
|
+
- .gitignore
|
68
|
+
- Gemfile
|
69
|
+
- Rakefile
|
70
|
+
- awesome_bot_factory.gemspec
|
71
|
+
- bin/awesomebotfactory
|
72
|
+
- lib/awesome_bot_factory.rb
|
73
|
+
- lib/awesome_bot_factory/example_payload.rb
|
74
|
+
- lib/awesome_bot_factory/skill.rb
|
75
|
+
- lib/awesome_bot_factory/version.rb
|
76
|
+
- lib/templates/Gemfile.erb
|
77
|
+
- lib/templates/Procfile.erb
|
78
|
+
- lib/templates/config.ru.erb
|
79
|
+
- lib/templates/readme.md.erb
|
80
|
+
- lib/templates/skill.rb.erb
|
81
|
+
- lib/templates/skill_spec.rb.erb
|
82
|
+
- lib/templates/spec_helper.rb.erb
|
83
|
+
- spec/awesome_bot_factory/skill_spec.rb
|
84
|
+
- spec/spec_helper.rb
|
85
|
+
homepage: ''
|
86
|
+
licenses: []
|
87
|
+
post_install_message:
|
88
|
+
rdoc_options: []
|
89
|
+
require_paths:
|
90
|
+
- lib
|
91
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
92
|
+
none: false
|
93
|
+
requirements:
|
94
|
+
- - ! '>='
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
segments:
|
98
|
+
- 0
|
99
|
+
hash: 3025311330780698384
|
100
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
101
|
+
none: false
|
102
|
+
requirements:
|
103
|
+
- - ! '>='
|
104
|
+
- !ruby/object:Gem::Version
|
105
|
+
version: '0'
|
106
|
+
segments:
|
107
|
+
- 0
|
108
|
+
hash: 3025311330780698384
|
109
|
+
requirements: []
|
110
|
+
rubyforge_project: ! '[none]'
|
111
|
+
rubygems_version: 1.8.5
|
112
|
+
signing_key:
|
113
|
+
specification_version: 3
|
114
|
+
summary: The AwesomeBotFactory gem
|
115
|
+
test_files:
|
116
|
+
- spec/awesome_bot_factory/skill_spec.rb
|
117
|
+
- spec/spec_helper.rb
|