thunk 0.0.0
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/.autotest +5 -0
- data/CHANGELOG.rdoc +4 -0
- data/Manifest.txt +8 -0
- data/README.rdoc +72 -0
- data/Rakefile +17 -0
- data/bin/thunk +83 -0
- data/lib/thunk.rb +160 -0
- data/test/test_thunk.rb +120 -0
- metadata +127 -0
data/.autotest
ADDED
data/CHANGELOG.rdoc
ADDED
data/Manifest.txt
ADDED
data/README.rdoc
ADDED
@@ -0,0 +1,72 @@
|
|
1
|
+
= Thunk!
|
2
|
+
|
3
|
+
* http://github.com/eleven/thunk
|
4
|
+
* http://thunk.us
|
5
|
+
|
6
|
+
== Description
|
7
|
+
|
8
|
+
An API for talking to thunk.us, a (soon to be) generally awesome
|
9
|
+
notification service. Thunk lets you share and change simple state.
|
10
|
+
|
11
|
+
We know these docs are rough, but we wanted to get a version of the
|
12
|
+
API out quickly. We'll have it all polished by 1.0, we promise. :)
|
13
|
+
|
14
|
+
Since Thunk gets used in basic infrastructure tools, it works extra
|
15
|
+
hard to never throw exceptions or cause hangs/timeouts. If it does,
|
16
|
+
please file a bug! Even a nonexistent or read-only thunk will
|
17
|
+
successfully respond to pokes, returning stub information. If you need
|
18
|
+
to make extra sure you're hooked up to a valid thunk, check out
|
19
|
+
<tt>Thunk#exists?</tt> and <tt>Thunk#pokeable?</tt>.
|
20
|
+
|
21
|
+
== Examples
|
22
|
+
|
23
|
+
(Eventually) check out the RDoc for more detailed information.
|
24
|
+
|
25
|
+
=== Poking & Reading a Thunk
|
26
|
+
|
27
|
+
thunk = Thunk.for "0681851956dccf88"
|
28
|
+
thunk.good! "Everything went better than expected!"
|
29
|
+
|
30
|
+
thunk.good? # => true
|
31
|
+
thunk.payload # => "Everything went..."
|
32
|
+
|
33
|
+
=== Creating a Thunk
|
34
|
+
|
35
|
+
thunk = Thunk.create "My New Thunk"
|
36
|
+
|
37
|
+
thunk.name # => "My New Thunk"
|
38
|
+
thunk.state # => :new
|
39
|
+
thunk.uuid # => "..."
|
40
|
+
|
41
|
+
thunk.good! "I just made this thunk! Aaugh!"
|
42
|
+
|
43
|
+
=== At the Command Line
|
44
|
+
|
45
|
+
$ thunk -h
|
46
|
+
|
47
|
+
== Installation
|
48
|
+
|
49
|
+
$ gem install thunk
|
50
|
+
|
51
|
+
== License
|
52
|
+
|
53
|
+
Copyright 2010 Eleven Eleven (hello@thunk.us)
|
54
|
+
|
55
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
56
|
+
a copy of this software and associated documentation files (the
|
57
|
+
'Software'), to deal in the Software without restriction, including
|
58
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
59
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
60
|
+
permit persons to whom the Software is furnished to do so, subject to
|
61
|
+
the following conditions:
|
62
|
+
|
63
|
+
The above copyright notice and this permission notice shall be
|
64
|
+
included in all copies or substantial portions of the Software.
|
65
|
+
|
66
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
67
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
68
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
69
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
70
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
71
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
72
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "hoe"
|
2
|
+
|
3
|
+
Hoe.plugin :doofus, :git
|
4
|
+
Hoe.plugins.delete :rubyforge
|
5
|
+
|
6
|
+
Hoe.spec "thunk" do
|
7
|
+
developer "Eleven Eleven", "hello@3lev3n.com"
|
8
|
+
|
9
|
+
self.extra_rdoc_files = Dir["*.rdoc"]
|
10
|
+
self.history_file = "CHANGELOG.rdoc"
|
11
|
+
self.readme_file = "README.rdoc"
|
12
|
+
self.testlib = :minitest
|
13
|
+
|
14
|
+
extra_deps << %w(json_pure 1.2.0)
|
15
|
+
extra_dev_deps << %w(fakeweb 1.2.8)
|
16
|
+
extra_dev_deps << %w(minitest 1.5.0)
|
17
|
+
end
|
data/bin/thunk
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "optparse"
|
4
|
+
require "thunk"
|
5
|
+
|
6
|
+
OptionParser.new do |opts|
|
7
|
+
@payload = nil
|
8
|
+
@poke = nil
|
9
|
+
@raw = false
|
10
|
+
|
11
|
+
opts.banner =
|
12
|
+
"Usage: thunk [options] --create [message]\n" +
|
13
|
+
" thunk [options] <uuid>\n" +
|
14
|
+
" thunk [options] {--good, --bad, --iffy, --unknown} <uuid>\n\n"
|
15
|
+
|
16
|
+
opts.on "--create [PAYLOAD]", "-c", "Create a thunk, optional payload." do |p|
|
17
|
+
thunk = Thunk.create p
|
18
|
+
puts thunk.uuid if thunk.uuid
|
19
|
+
exit thunk.exists? ? 0 : 1
|
20
|
+
end
|
21
|
+
|
22
|
+
opts.on "--help", "-h", "-?", "Show this help." do
|
23
|
+
puts opts
|
24
|
+
exit 0
|
25
|
+
end
|
26
|
+
|
27
|
+
opts.on "--payload PAYLOAD", "-p", "-m",
|
28
|
+
"An optional poke payload/message." do |p|
|
29
|
+
|
30
|
+
@payload = p
|
31
|
+
end
|
32
|
+
|
33
|
+
opts.on "--raw", "Show the thunk data as raw JSON." do
|
34
|
+
@raw = true
|
35
|
+
end
|
36
|
+
|
37
|
+
opts.on "--url URL", "Use a different base URL." do |url|
|
38
|
+
Thunk.url = url
|
39
|
+
end
|
40
|
+
|
41
|
+
opts.on "--version", "-V", "Prints #{Thunk::VERSION}." do
|
42
|
+
puts Thunk::VERSION
|
43
|
+
exit 0
|
44
|
+
end
|
45
|
+
|
46
|
+
%w(good iffy bad unknown).each do |state|
|
47
|
+
opts.on "--#{state}", "-#{state[0,1]}", "Send a '#{state}' poke." do
|
48
|
+
@poke = state
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
if ARGV.empty?
|
53
|
+
puts opts
|
54
|
+
exit 1
|
55
|
+
end
|
56
|
+
|
57
|
+
begin
|
58
|
+
opts.parse! ARGV
|
59
|
+
rescue OptionParser::ParseError => e
|
60
|
+
abort "#$0: #{e.message}"
|
61
|
+
end
|
62
|
+
|
63
|
+
abort "#$0: Specify a thunk UUID!" unless uuid = ARGV.shift
|
64
|
+
thunk = Thunk.for uuid
|
65
|
+
|
66
|
+
if @poke
|
67
|
+
p @payload
|
68
|
+
thunk.send "#{@poke}!", @payload
|
69
|
+
else
|
70
|
+
if @raw
|
71
|
+
puts thunk.json
|
72
|
+
else
|
73
|
+
str = [thunk.name, thunk.state].compact.join ", "
|
74
|
+
str << ", updated at #{thunk.updated}" if thunk.updated
|
75
|
+
str << ": #{thunk.payload}" if thunk.payload
|
76
|
+
|
77
|
+
puts str
|
78
|
+
end
|
79
|
+
|
80
|
+
exit({ :new => 0, :good => 0, :iffy => 2,
|
81
|
+
:bad => 4, :iffy => 8, :unknown => 16 }[thunk.state])
|
82
|
+
end
|
83
|
+
end
|
data/lib/thunk.rb
ADDED
@@ -0,0 +1,160 @@
|
|
1
|
+
require "cgi"
|
2
|
+
require "json/pure"
|
3
|
+
require "net/http"
|
4
|
+
require "uri"
|
5
|
+
|
6
|
+
class Thunk
|
7
|
+
VERSION = "0.0.0"
|
8
|
+
URL = "http://thunk.us".freeze
|
9
|
+
|
10
|
+
class << self
|
11
|
+
attr_accessor :url
|
12
|
+
private :new
|
13
|
+
|
14
|
+
def create name = nil
|
15
|
+
json = request :post, url, :name => name
|
16
|
+
new "#{url}/#{json["uuid"]}", json
|
17
|
+
end
|
18
|
+
|
19
|
+
def for url
|
20
|
+
url = "#{self.url}/#{url}" unless /^http/ =~ url
|
21
|
+
json = request :get, url
|
22
|
+
new url, json
|
23
|
+
end
|
24
|
+
|
25
|
+
def request method, url, options = {}
|
26
|
+
url = URI.parse url
|
27
|
+
|
28
|
+
unless options.empty?
|
29
|
+
url.query = options.collect { |k ,v|
|
30
|
+
"#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
31
|
+
}.join "&"
|
32
|
+
end
|
33
|
+
|
34
|
+
# FIX http timeout settings
|
35
|
+
# FIX exception handing, etc
|
36
|
+
|
37
|
+
http = Net::HTTP.new url.host, url.port
|
38
|
+
rclass = { :get => Net::HTTP::Get, :post => Net::HTTP::Post }[method]
|
39
|
+
req = rclass.new url.request_uri
|
40
|
+
res = http.request req
|
41
|
+
success = %w(200 201).include? res.code
|
42
|
+
|
43
|
+
unless success
|
44
|
+
warn "[Thunk] #{res.code}, #{method}, #{url}: #{res.message}"
|
45
|
+
warn res.body if res.body
|
46
|
+
end
|
47
|
+
|
48
|
+
return success if res.body.empty?
|
49
|
+
|
50
|
+
data = JSON.parse(res.body) rescue {}
|
51
|
+
|
52
|
+
unless Hash === data
|
53
|
+
warn "[Thunk] Malformed JSON response: #{data.inspect}"
|
54
|
+
data = {}
|
55
|
+
end
|
56
|
+
|
57
|
+
warn warning if warning = data.delete("warn")
|
58
|
+
abort critical if critical = data.delete("abort")
|
59
|
+
|
60
|
+
data
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
self.url = URL
|
65
|
+
|
66
|
+
attr_reader :name
|
67
|
+
attr_reader :payload
|
68
|
+
attr_reader :puuid
|
69
|
+
attr_reader :state
|
70
|
+
attr_reader :updated
|
71
|
+
attr_reader :url
|
72
|
+
attr_reader :uuid
|
73
|
+
|
74
|
+
def bad?
|
75
|
+
:bad == state
|
76
|
+
end
|
77
|
+
|
78
|
+
def bad! payload = nil
|
79
|
+
poke :bad, payload
|
80
|
+
end
|
81
|
+
|
82
|
+
def exists?
|
83
|
+
self.class.request :get, url
|
84
|
+
end
|
85
|
+
|
86
|
+
def good?
|
87
|
+
:good == state
|
88
|
+
end
|
89
|
+
|
90
|
+
def good! payload = nil
|
91
|
+
poke :good, payload
|
92
|
+
end
|
93
|
+
|
94
|
+
def iffy?
|
95
|
+
:iffy == state
|
96
|
+
end
|
97
|
+
|
98
|
+
def iffy! payload = nil
|
99
|
+
poke :iffy, payload
|
100
|
+
end
|
101
|
+
|
102
|
+
def json
|
103
|
+
json = {
|
104
|
+
:name => name,
|
105
|
+
:payload => payload,
|
106
|
+
:puuid => puuid,
|
107
|
+
:state => state,
|
108
|
+
:updated => updated,
|
109
|
+
:url => url,
|
110
|
+
:uuid => uuid
|
111
|
+
}
|
112
|
+
|
113
|
+
json.reject! { |k, v| v.nil? }
|
114
|
+
JSON.generate json
|
115
|
+
end
|
116
|
+
|
117
|
+
def poke state, payload = nil
|
118
|
+
if self.class.request :post, "#{url}/#{state}", :payload => payload
|
119
|
+
@payload = payload
|
120
|
+
@state = state.to_sym
|
121
|
+
@updated = Time.now.utc
|
122
|
+
end
|
123
|
+
|
124
|
+
@state
|
125
|
+
end
|
126
|
+
|
127
|
+
def pokeable?
|
128
|
+
puuid
|
129
|
+
end
|
130
|
+
|
131
|
+
def public?
|
132
|
+
!puuid
|
133
|
+
end
|
134
|
+
|
135
|
+
def unknown?
|
136
|
+
:unknown == state
|
137
|
+
end
|
138
|
+
|
139
|
+
def unknown! payload = nil
|
140
|
+
poke :unknown, payload
|
141
|
+
end
|
142
|
+
|
143
|
+
private
|
144
|
+
|
145
|
+
def initialize url, json
|
146
|
+
@url = url
|
147
|
+
apply json
|
148
|
+
end
|
149
|
+
|
150
|
+
def apply json
|
151
|
+
@name = json["name"]
|
152
|
+
@payload = json["payload"]
|
153
|
+
@state = (json["state"] || "unknown").to_sym
|
154
|
+
@updated = json["updated"]
|
155
|
+
@uuid = json["uuid"]
|
156
|
+
@puuid = json["puuid"]
|
157
|
+
|
158
|
+
self
|
159
|
+
end
|
160
|
+
end
|
data/test/test_thunk.rb
ADDED
@@ -0,0 +1,120 @@
|
|
1
|
+
require "fakeweb"
|
2
|
+
require "minitest/autorun"
|
3
|
+
|
4
|
+
require "thunk"
|
5
|
+
|
6
|
+
FakeWeb.allow_net_connect = false
|
7
|
+
|
8
|
+
class Thunk
|
9
|
+
class << self
|
10
|
+
def abort *; end
|
11
|
+
def warn *; end
|
12
|
+
|
13
|
+
public :new
|
14
|
+
end
|
15
|
+
|
16
|
+
public :initialize
|
17
|
+
end
|
18
|
+
|
19
|
+
class TestThunk < MiniTest::Unit::TestCase
|
20
|
+
def setup
|
21
|
+
FakeWeb.clean_registry
|
22
|
+
Thunk.url = Thunk::URL
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_bangs_and_predicates
|
26
|
+
t = Thunk.new "http://thunk.us/uuid", {}
|
27
|
+
|
28
|
+
[:good, :iffy, :bad, :unknown].each do |state|
|
29
|
+
FakeWeb.register_uri :post, "http://thunk.us/uuid/#{state}?payload=hi",
|
30
|
+
:status => 201
|
31
|
+
|
32
|
+
t.send "#{state}!", "hi"
|
33
|
+
assert t.send("#{state}?"), "thunk is #{state}"
|
34
|
+
|
35
|
+
refute_nil t.updated
|
36
|
+
assert_equal "hi", t.payload
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def test_exists?
|
41
|
+
good = Thunk.new "http://thunk.us/exists", {}
|
42
|
+
bad = Thunk.new "http://thunk.us/nonexistent", {}
|
43
|
+
|
44
|
+
FakeWeb.register_uri :get, "http://thunk.us/exists", :status => 200
|
45
|
+
FakeWeb.register_uri :get, "http://thunk.us/nonexistent", :status => 404
|
46
|
+
|
47
|
+
assert good.exists?, "good exists"
|
48
|
+
refute bad.exists?, "nonexistent"
|
49
|
+
end
|
50
|
+
|
51
|
+
def test_pokeable_and_public
|
52
|
+
FakeWeb.register_uri :get, "http://thunk.us/pokeable",
|
53
|
+
:body => JSON.generate({ :uuid => "pokeable", :puuid => "public" })
|
54
|
+
|
55
|
+
FakeWeb.register_uri :get, "http://thunk.us/public",
|
56
|
+
:body => JSON.generate({ :uuid => "public" })
|
57
|
+
|
58
|
+
t = Thunk.for "pokeable"
|
59
|
+
assert t.pokeable?, "pokeable"
|
60
|
+
refute t.public?, "public"
|
61
|
+
|
62
|
+
t = Thunk.for "public"
|
63
|
+
refute t.pokeable?, "pokeable"
|
64
|
+
assert t.public?, "public"
|
65
|
+
end
|
66
|
+
|
67
|
+
def test_self_create
|
68
|
+
response = {
|
69
|
+
:name => "Hello",
|
70
|
+
:puuid => "public",
|
71
|
+
:state => :new,
|
72
|
+
:uuid => "uuid"
|
73
|
+
}
|
74
|
+
|
75
|
+
FakeWeb.register_uri :post, "http://thunk.us?name=Hello",
|
76
|
+
:body => JSON.generate(response)
|
77
|
+
|
78
|
+
t = Thunk.create "Hello"
|
79
|
+
|
80
|
+
response.each do |key, value|
|
81
|
+
assert_equal value, t.send(key)
|
82
|
+
end
|
83
|
+
|
84
|
+
assert_equal "http://thunk.us/uuid", t.url
|
85
|
+
end
|
86
|
+
|
87
|
+
def test_self_create_bad
|
88
|
+
FakeWeb.register_uri :post, "http://thunk.us?name=Hello",
|
89
|
+
:status => 500, :body => "[]"
|
90
|
+
|
91
|
+
t = Thunk.create "Hello"
|
92
|
+
assert_equal :unknown, t.state
|
93
|
+
end
|
94
|
+
|
95
|
+
def test_self_for
|
96
|
+
response = {
|
97
|
+
:name => "Hello",
|
98
|
+
:payload => "All is well!",
|
99
|
+
:puuid => "public",
|
100
|
+
:state => :good,
|
101
|
+
:uuid => "uuid"
|
102
|
+
}
|
103
|
+
|
104
|
+
FakeWeb.register_uri :get, "http://thunk.us/uuid",
|
105
|
+
:body => JSON.generate(response)
|
106
|
+
|
107
|
+
t = Thunk.for "uuid"
|
108
|
+
|
109
|
+
response.each do |key, value|
|
110
|
+
assert_equal value, t.send(key)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def test_self_url
|
115
|
+
assert_equal "http://thunk.us", Thunk.url
|
116
|
+
|
117
|
+
Thunk.url = "bleh"
|
118
|
+
assert_equal "bleh", Thunk.url
|
119
|
+
end
|
120
|
+
end
|
metadata
ADDED
@@ -0,0 +1,127 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: thunk
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Eleven Eleven
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
|
12
|
+
date: 2010-01-25 00:00:00 -08:00
|
13
|
+
default_executable:
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: json_pure
|
17
|
+
type: :runtime
|
18
|
+
version_requirement:
|
19
|
+
version_requirements: !ruby/object:Gem::Requirement
|
20
|
+
requirements:
|
21
|
+
- - "="
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 1.2.0
|
24
|
+
version:
|
25
|
+
- !ruby/object:Gem::Dependency
|
26
|
+
name: gemcutter
|
27
|
+
type: :development
|
28
|
+
version_requirement:
|
29
|
+
version_requirements: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.2.1
|
34
|
+
version:
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
name: fakeweb
|
37
|
+
type: :development
|
38
|
+
version_requirement:
|
39
|
+
version_requirements: !ruby/object:Gem::Requirement
|
40
|
+
requirements:
|
41
|
+
- - "="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
version: 1.2.8
|
44
|
+
version:
|
45
|
+
- !ruby/object:Gem::Dependency
|
46
|
+
name: minitest
|
47
|
+
type: :development
|
48
|
+
version_requirement:
|
49
|
+
version_requirements: !ruby/object:Gem::Requirement
|
50
|
+
requirements:
|
51
|
+
- - "="
|
52
|
+
- !ruby/object:Gem::Version
|
53
|
+
version: 1.5.0
|
54
|
+
version:
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: hoe
|
57
|
+
type: :development
|
58
|
+
version_requirement:
|
59
|
+
version_requirements: !ruby/object:Gem::Requirement
|
60
|
+
requirements:
|
61
|
+
- - ">="
|
62
|
+
- !ruby/object:Gem::Version
|
63
|
+
version: 2.5.0
|
64
|
+
version:
|
65
|
+
description: |-
|
66
|
+
An API for talking to thunk.us, a (soon to be) generally awesome
|
67
|
+
notification service. Thunk lets you share and change simple state.
|
68
|
+
|
69
|
+
We know these docs are rough, but we wanted to get a version of the
|
70
|
+
API out quickly. We'll have it all polished by 1.0, we promise. :)
|
71
|
+
|
72
|
+
Since Thunk gets used in basic infrastructure tools, it works extra
|
73
|
+
hard to never throw exceptions or cause hangs/timeouts. If it does,
|
74
|
+
please file a bug! Even a nonexistent or read-only thunk will
|
75
|
+
successfully respond to pokes, returning stub information. If you need
|
76
|
+
to make extra sure you're hooked up to a valid thunk, check out
|
77
|
+
<tt>Thunk#exists?</tt> and <tt>Thunk#pokeable?</tt>.
|
78
|
+
email:
|
79
|
+
- hello@3lev3n.com
|
80
|
+
executables:
|
81
|
+
- thunk
|
82
|
+
extensions: []
|
83
|
+
|
84
|
+
extra_rdoc_files:
|
85
|
+
- Manifest.txt
|
86
|
+
- CHANGELOG.rdoc
|
87
|
+
- README.rdoc
|
88
|
+
files:
|
89
|
+
- .autotest
|
90
|
+
- CHANGELOG.rdoc
|
91
|
+
- Manifest.txt
|
92
|
+
- README.rdoc
|
93
|
+
- Rakefile
|
94
|
+
- bin/thunk
|
95
|
+
- lib/thunk.rb
|
96
|
+
- test/test_thunk.rb
|
97
|
+
has_rdoc: true
|
98
|
+
homepage: http://github.com/eleven/thunk
|
99
|
+
licenses: []
|
100
|
+
|
101
|
+
post_install_message:
|
102
|
+
rdoc_options:
|
103
|
+
- --main
|
104
|
+
- README.rdoc
|
105
|
+
require_paths:
|
106
|
+
- lib
|
107
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
version: "0"
|
112
|
+
version:
|
113
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: "0"
|
118
|
+
version:
|
119
|
+
requirements: []
|
120
|
+
|
121
|
+
rubyforge_project: thunk
|
122
|
+
rubygems_version: 1.3.5
|
123
|
+
signing_key:
|
124
|
+
specification_version: 3
|
125
|
+
summary: An API for talking to thunk.us, a (soon to be) generally awesome notification service
|
126
|
+
test_files:
|
127
|
+
- test/test_thunk.rb
|