thunk 0.0.0 → 0.1.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/CHANGELOG.rdoc +6 -0
- data/Manifest.txt +2 -0
- data/README.rdoc +2 -0
- data/Rakefile +3 -1
- data/bin/thunk +8 -8
- data/lib/thunk.rb +28 -71
- data/lib/thunk/server.rb +71 -0
- data/test/test_thunk.rb +12 -66
- data/test/test_thunk_server.rb +73 -0
- metadata +18 -13
data/CHANGELOG.rdoc
CHANGED
data/Manifest.txt
CHANGED
data/README.rdoc
CHANGED
@@ -8,6 +8,8 @@
|
|
8
8
|
An API for talking to thunk.us, a (soon to be) generally awesome
|
9
9
|
notification service. Thunk lets you share and change simple state.
|
10
10
|
|
11
|
+
== Notes in Progress
|
12
|
+
|
11
13
|
We know these docs are rough, but we wanted to get a version of the
|
12
14
|
API out quickly. We'll have it all polished by 1.0, we promise. :)
|
13
15
|
|
data/Rakefile
CHANGED
@@ -4,7 +4,8 @@ Hoe.plugin :doofus, :git
|
|
4
4
|
Hoe.plugins.delete :rubyforge
|
5
5
|
|
6
6
|
Hoe.spec "thunk" do
|
7
|
-
developer "Eleven Eleven", "hello@
|
7
|
+
developer "Eleven Eleven", "hello@thunk.us"
|
8
|
+
developer "John Barnette", "john@thunk.us"
|
8
9
|
|
9
10
|
self.extra_rdoc_files = Dir["*.rdoc"]
|
10
11
|
self.history_file = "CHANGELOG.rdoc"
|
@@ -14,4 +15,5 @@ Hoe.spec "thunk" do
|
|
14
15
|
extra_deps << %w(json_pure 1.2.0)
|
15
16
|
extra_dev_deps << %w(fakeweb 1.2.8)
|
16
17
|
extra_dev_deps << %w(minitest 1.5.0)
|
18
|
+
extra_dev_deps << %w(mocha 0.9.8)
|
17
19
|
end
|
data/bin/thunk
CHANGED
@@ -7,14 +7,15 @@ OptionParser.new do |opts|
|
|
7
7
|
@payload = nil
|
8
8
|
@poke = nil
|
9
9
|
@raw = false
|
10
|
+
@server = Thunk::Server.new
|
10
11
|
|
11
|
-
opts.banner =
|
12
|
-
"Usage: thunk [options] --create [
|
12
|
+
opts.banner =
|
13
|
+
"Usage: thunk [options] --create [name]\n" +
|
13
14
|
" thunk [options] <uuid>\n" +
|
14
15
|
" thunk [options] {--good, --bad, --iffy, --unknown} <uuid>\n\n"
|
15
16
|
|
16
|
-
opts.on "--create [
|
17
|
-
thunk =
|
17
|
+
opts.on "--create [NAME]", "-c", "Create a thunk, optional name." do |n|
|
18
|
+
thunk = @server.create n
|
18
19
|
puts thunk.uuid if thunk.uuid
|
19
20
|
exit thunk.exists? ? 0 : 1
|
20
21
|
end
|
@@ -25,7 +26,7 @@ OptionParser.new do |opts|
|
|
25
26
|
end
|
26
27
|
|
27
28
|
opts.on "--payload PAYLOAD", "-p", "-m",
|
28
|
-
"
|
29
|
+
"Add a payload/message to a poke." do |p|
|
29
30
|
|
30
31
|
@payload = p
|
31
32
|
end
|
@@ -35,7 +36,7 @@ OptionParser.new do |opts|
|
|
35
36
|
end
|
36
37
|
|
37
38
|
opts.on "--url URL", "Use a different base URL." do |url|
|
38
|
-
Thunk.
|
39
|
+
@server = Thunk::Server.new url
|
39
40
|
end
|
40
41
|
|
41
42
|
opts.on "--version", "-V", "Prints #{Thunk::VERSION}." do
|
@@ -61,10 +62,9 @@ OptionParser.new do |opts|
|
|
61
62
|
end
|
62
63
|
|
63
64
|
abort "#$0: Specify a thunk UUID!" unless uuid = ARGV.shift
|
64
|
-
thunk =
|
65
|
+
thunk = @server.get uuid
|
65
66
|
|
66
67
|
if @poke
|
67
|
-
p @payload
|
68
68
|
thunk.send "#{@poke}!", @payload
|
69
69
|
else
|
70
70
|
if @raw
|
data/lib/thunk.rb
CHANGED
@@ -1,76 +1,32 @@
|
|
1
|
-
require "
|
2
|
-
require "json/pure"
|
3
|
-
require "net/http"
|
4
|
-
require "uri"
|
1
|
+
require "thunk/server"
|
5
2
|
|
6
3
|
class Thunk
|
7
|
-
VERSION = "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
|
4
|
+
VERSION = "0.1.0"
|
65
5
|
|
66
6
|
attr_reader :name
|
67
7
|
attr_reader :payload
|
68
8
|
attr_reader :puuid
|
69
9
|
attr_reader :state
|
70
10
|
attr_reader :updated
|
71
|
-
attr_reader :url
|
72
11
|
attr_reader :uuid
|
73
12
|
|
13
|
+
def self.create *args
|
14
|
+
server.create *args
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.get *args
|
18
|
+
server.get *args
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.server
|
22
|
+
@server ||= Thunk::Server.new
|
23
|
+
end
|
24
|
+
|
25
|
+
def initialize server, json
|
26
|
+
@server = server
|
27
|
+
apply json
|
28
|
+
end
|
29
|
+
|
74
30
|
def bad?
|
75
31
|
:bad == state
|
76
32
|
end
|
@@ -80,7 +36,7 @@ class Thunk
|
|
80
36
|
end
|
81
37
|
|
82
38
|
def exists?
|
83
|
-
|
39
|
+
@server.request :get, url
|
84
40
|
end
|
85
41
|
|
86
42
|
def good?
|
@@ -99,7 +55,9 @@ class Thunk
|
|
99
55
|
poke :iffy, payload
|
100
56
|
end
|
101
57
|
|
102
|
-
|
58
|
+
# Used for the --raw option in the command-line client.
|
59
|
+
|
60
|
+
def json # :nodoc:
|
103
61
|
json = {
|
104
62
|
:name => name,
|
105
63
|
:payload => payload,
|
@@ -115,7 +73,7 @@ class Thunk
|
|
115
73
|
end
|
116
74
|
|
117
75
|
def poke state, payload = nil
|
118
|
-
if
|
76
|
+
if @server.request :post, "#{url}/#{state}", :payload => payload
|
119
77
|
@payload = payload
|
120
78
|
@state = state.to_sym
|
121
79
|
@updated = Time.now.utc
|
@@ -140,13 +98,12 @@ class Thunk
|
|
140
98
|
poke :unknown, payload
|
141
99
|
end
|
142
100
|
|
143
|
-
|
144
|
-
|
145
|
-
def initialize url, json
|
146
|
-
@url = url
|
147
|
-
apply json
|
101
|
+
def url
|
102
|
+
"#{@server.url}/#{uuid}"
|
148
103
|
end
|
149
104
|
|
105
|
+
private
|
106
|
+
|
150
107
|
def apply json
|
151
108
|
@name = json["name"]
|
152
109
|
@payload = json["payload"]
|
data/lib/thunk/server.rb
ADDED
@@ -0,0 +1,71 @@
|
|
1
|
+
require "cgi"
|
2
|
+
require "json/pure"
|
3
|
+
require "net/http"
|
4
|
+
require "uri"
|
5
|
+
|
6
|
+
require "thunk"
|
7
|
+
|
8
|
+
class Thunk
|
9
|
+
|
10
|
+
class << self
|
11
|
+
public :new # FIX
|
12
|
+
end
|
13
|
+
|
14
|
+
class Server
|
15
|
+
attr_reader :url
|
16
|
+
|
17
|
+
def initialize url = "http://thunk.us"
|
18
|
+
@url = url
|
19
|
+
end
|
20
|
+
|
21
|
+
def create name = nil
|
22
|
+
json = request :post, url, :name => name
|
23
|
+
url = "#{self.url}/#{json['uuid']}"
|
24
|
+
|
25
|
+
Thunk.new self, json
|
26
|
+
end
|
27
|
+
|
28
|
+
def get uuid
|
29
|
+
url = "#{self.url}/#{uuid}"
|
30
|
+
Thunk.new self, request(:get, url)
|
31
|
+
end
|
32
|
+
|
33
|
+
def request method, url, options = {}
|
34
|
+
url = URI.parse url
|
35
|
+
|
36
|
+
unless options.empty?
|
37
|
+
url.query = options.collect { |k ,v|
|
38
|
+
"#{CGI.escape k.to_s}=#{CGI.escape v.to_s}"
|
39
|
+
}.join "&"
|
40
|
+
end
|
41
|
+
|
42
|
+
# FIX http timeout settings
|
43
|
+
# FIX exception handing, etc
|
44
|
+
|
45
|
+
http = Net::HTTP.new url.host, url.port
|
46
|
+
rclass = { :get => Net::HTTP::Get, :post => Net::HTTP::Post }[method]
|
47
|
+
req = rclass.new url.request_uri
|
48
|
+
res = http.request req
|
49
|
+
success = %w(200 201).include? res.code
|
50
|
+
|
51
|
+
unless success
|
52
|
+
warn "[Thunk] #{res.code}, #{method}, #{url}: #{res.message}"
|
53
|
+
warn res.body if res.body
|
54
|
+
end
|
55
|
+
|
56
|
+
return success if res.body.empty?
|
57
|
+
|
58
|
+
data = JSON.parse(res.body) rescue {}
|
59
|
+
|
60
|
+
unless Hash === data
|
61
|
+
warn "[Thunk] Malformed JSON response: #{data.inspect}"
|
62
|
+
data = {}
|
63
|
+
end
|
64
|
+
|
65
|
+
warn warning if warning = data.delete("warn")
|
66
|
+
abort critical if critical = data.delete("abort")
|
67
|
+
|
68
|
+
data
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
data/test/test_thunk.rb
CHANGED
@@ -1,29 +1,19 @@
|
|
1
1
|
require "fakeweb"
|
2
2
|
require "minitest/autorun"
|
3
|
+
require "mocha"
|
3
4
|
|
4
5
|
require "thunk"
|
5
6
|
|
6
7
|
FakeWeb.allow_net_connect = false
|
7
8
|
|
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
9
|
class TestThunk < MiniTest::Unit::TestCase
|
20
10
|
def setup
|
21
11
|
FakeWeb.clean_registry
|
22
|
-
|
12
|
+
@server = Thunk::Server.new
|
23
13
|
end
|
24
14
|
|
25
15
|
def test_bangs_and_predicates
|
26
|
-
t = Thunk.new "
|
16
|
+
t = Thunk.new @server, { "uuid" => "uuid" }
|
27
17
|
|
28
18
|
[:good, :iffy, :bad, :unknown].each do |state|
|
29
19
|
FakeWeb.register_uri :post, "http://thunk.us/uuid/#{state}?payload=hi",
|
@@ -38,8 +28,8 @@ class TestThunk < MiniTest::Unit::TestCase
|
|
38
28
|
end
|
39
29
|
|
40
30
|
def test_exists?
|
41
|
-
good = Thunk.new "
|
42
|
-
bad = Thunk.new "
|
31
|
+
good = Thunk.new @server, { "uuid" => "exists" }
|
32
|
+
bad = Thunk.new @server, { "uuid" => "nonexistent" }
|
43
33
|
|
44
34
|
FakeWeb.register_uri :get, "http://thunk.us/exists", :status => 200
|
45
35
|
FakeWeb.register_uri :get, "http://thunk.us/nonexistent", :status => 404
|
@@ -55,66 +45,22 @@ class TestThunk < MiniTest::Unit::TestCase
|
|
55
45
|
FakeWeb.register_uri :get, "http://thunk.us/public",
|
56
46
|
:body => JSON.generate({ :uuid => "public" })
|
57
47
|
|
58
|
-
t =
|
48
|
+
t = @server.get "pokeable"
|
59
49
|
assert t.pokeable?, "pokeable"
|
60
50
|
refute t.public?, "public"
|
61
51
|
|
62
|
-
t =
|
52
|
+
t = @server.get "public"
|
63
53
|
refute t.pokeable?, "pokeable"
|
64
54
|
assert t.public?, "public"
|
65
55
|
end
|
66
56
|
|
67
57
|
def test_self_create
|
68
|
-
|
69
|
-
|
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
|
58
|
+
Thunk.server.expects(:create).with "foo"
|
59
|
+
Thunk.create "foo"
|
85
60
|
end
|
86
61
|
|
87
|
-
def
|
88
|
-
|
89
|
-
|
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
|
62
|
+
def test_self_get
|
63
|
+
Thunk.server.expects(:get).with "foo"
|
64
|
+
Thunk.get "foo"
|
119
65
|
end
|
120
66
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
require "fakeweb"
|
2
|
+
require "minitest/autorun"
|
3
|
+
|
4
|
+
require "thunk"
|
5
|
+
|
6
|
+
FakeWeb.allow_net_connect = false
|
7
|
+
|
8
|
+
class Thunk::Server
|
9
|
+
def abort *; end
|
10
|
+
def warn *; end
|
11
|
+
end
|
12
|
+
|
13
|
+
class TestThunkServer < MiniTest::Unit::TestCase
|
14
|
+
def setup
|
15
|
+
FakeWeb.clean_registry
|
16
|
+
@server = Thunk::Server.new
|
17
|
+
end
|
18
|
+
|
19
|
+
def test_create
|
20
|
+
response = {
|
21
|
+
:name => "Hello",
|
22
|
+
:puuid => "public",
|
23
|
+
:state => :new,
|
24
|
+
:uuid => "uuid"
|
25
|
+
}
|
26
|
+
|
27
|
+
FakeWeb.register_uri :post, "http://thunk.us?name=Hello",
|
28
|
+
:body => JSON.generate(response)
|
29
|
+
|
30
|
+
t = @server.create "Hello"
|
31
|
+
|
32
|
+
response.each do |key, value|
|
33
|
+
assert_equal value, t.send(key)
|
34
|
+
end
|
35
|
+
|
36
|
+
assert_equal "http://thunk.us/uuid", t.url
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_create_bad
|
40
|
+
FakeWeb.register_uri :post, "http://thunk.us?name=Hello",
|
41
|
+
:status => 500, :body => "[]"
|
42
|
+
|
43
|
+
t = @server.create "Hello"
|
44
|
+
assert_equal :unknown, t.state
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_get
|
48
|
+
response = {
|
49
|
+
:name => "Hello",
|
50
|
+
:payload => "All is well!",
|
51
|
+
:puuid => "public",
|
52
|
+
:state => :good,
|
53
|
+
:uuid => "uuid"
|
54
|
+
}
|
55
|
+
|
56
|
+
FakeWeb.register_uri :get, "http://thunk.us/uuid",
|
57
|
+
:body => JSON.generate(response)
|
58
|
+
|
59
|
+
t = @server.get "uuid"
|
60
|
+
|
61
|
+
response.each do |key, value|
|
62
|
+
assert_equal value, t.send(key)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def test_initialize
|
67
|
+
s = Thunk::Server.new
|
68
|
+
assert_equal "http://thunk.us", s.url
|
69
|
+
|
70
|
+
s = Thunk::Server.new "http://thunk.local"
|
71
|
+
assert_equal "http://thunk.local", s.url
|
72
|
+
end
|
73
|
+
end
|
metadata
CHANGED
@@ -1,15 +1,16 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: thunk
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eleven Eleven
|
8
|
+
- John Barnette
|
8
9
|
autorequire:
|
9
10
|
bindir: bin
|
10
11
|
cert_chain: []
|
11
12
|
|
12
|
-
date: 2010-01-
|
13
|
+
date: 2010-01-29 00:00:00 -08:00
|
13
14
|
default_executable:
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
@@ -52,6 +53,16 @@ dependencies:
|
|
52
53
|
- !ruby/object:Gem::Version
|
53
54
|
version: 1.5.0
|
54
55
|
version:
|
56
|
+
- !ruby/object:Gem::Dependency
|
57
|
+
name: mocha
|
58
|
+
type: :development
|
59
|
+
version_requirement:
|
60
|
+
version_requirements: !ruby/object:Gem::Requirement
|
61
|
+
requirements:
|
62
|
+
- - "="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
version: 0.9.8
|
65
|
+
version:
|
55
66
|
- !ruby/object:Gem::Dependency
|
56
67
|
name: hoe
|
57
68
|
type: :development
|
@@ -65,18 +76,9 @@ dependencies:
|
|
65
76
|
description: |-
|
66
77
|
An API for talking to thunk.us, a (soon to be) generally awesome
|
67
78
|
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
79
|
email:
|
79
|
-
- hello@
|
80
|
+
- hello@thunk.us
|
81
|
+
- john@thunk.us
|
80
82
|
executables:
|
81
83
|
- thunk
|
82
84
|
extensions: []
|
@@ -93,7 +95,9 @@ files:
|
|
93
95
|
- Rakefile
|
94
96
|
- bin/thunk
|
95
97
|
- lib/thunk.rb
|
98
|
+
- lib/thunk/server.rb
|
96
99
|
- test/test_thunk.rb
|
100
|
+
- test/test_thunk_server.rb
|
97
101
|
has_rdoc: true
|
98
102
|
homepage: http://github.com/eleven/thunk
|
99
103
|
licenses: []
|
@@ -125,3 +129,4 @@ specification_version: 3
|
|
125
129
|
summary: An API for talking to thunk.us, a (soon to be) generally awesome notification service
|
126
130
|
test_files:
|
127
131
|
- test/test_thunk.rb
|
132
|
+
- test/test_thunk_server.rb
|