buffer 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.bufferapprc.template +23 -0
- data/.gitignore +6 -0
- data/.rubocop.yml +18 -0
- data/.ruby-version +1 -0
- data/.travis.yml +5 -0
- data/API_COVERAGE.md +19 -0
- data/Gemfile +1 -1
- data/Guardfile +10 -0
- data/{LICENSE → LICENSE.txt} +1 -1
- data/README.md +62 -80
- data/Rakefile +25 -1
- data/TODO.md +3 -0
- data/bin/buffer +35 -0
- data/buffer.gemspec +26 -16
- data/lib/buffer/client.rb +26 -0
- data/lib/buffer/core.rb +64 -0
- data/lib/buffer/datastructure.rb +18 -0
- data/lib/buffer/encode.rb +33 -0
- data/lib/buffer/error.rb +10 -0
- data/lib/buffer/info.rb +10 -0
- data/lib/buffer/link.rb +10 -0
- data/lib/buffer/profile.rb +27 -0
- data/lib/buffer/update.rb +75 -0
- data/lib/buffer/user.rb +9 -0
- data/lib/buffer/version.rb +1 -1
- data/lib/buffer.rb +16 -102
- data/spec/fixtures/destroy.txt +10 -0
- data/spec/fixtures/info.txt +10 -0
- data/spec/fixtures/interactions_by_update_id.txt +10 -0
- data/spec/fixtures/link.txt +12 -0
- data/spec/fixtures/profile_authenticated.txt +11 -0
- data/spec/fixtures/profile_schedules_by_id.txt +10 -0
- data/spec/fixtures/profiles_by_id.txt +10 -0
- data/spec/fixtures/update_by_id.txt +10 -0
- data/spec/fixtures/update_by_id_non_auth.txt +9 -0
- data/spec/fixtures/updates_by_profile_id.txt +10 -0
- data/spec/fixtures/updates_by_profile_id_pending.txt +10 -0
- data/spec/fixtures/user_authenticated.txt +19 -0
- data/spec/lib/buffer/encode_spec.rb +42 -0
- data/spec/lib/buffer/link_spec.rb +22 -0
- data/spec/lib/buffer/profile_spec.rb +87 -0
- data/spec/lib/buffer/schedule_spec.rb +80 -0
- data/spec/lib/buffer/update_spec.rb +227 -0
- data/spec/lib/buffer/user_spec.rb +26 -0
- data/spec/lib/buffer_spec.rb +30 -0
- data/spec/lib/core_spec.rb +60 -0
- data/spec/spec_helper.rb +171 -0
- metadata +215 -67
- data/spec/buffer_spec.rb +0 -354
- data/spec/fixtures/create_body.txt +0 -1
- data/spec/fixtures/success.json +0 -1
- data/spec/fixtures/user.json +0 -1
- data/spec/helper.rb +0 -43
@@ -0,0 +1,75 @@
|
|
1
|
+
module Buffer
|
2
|
+
class Client
|
3
|
+
module Update
|
4
|
+
def update_by_id(id, options = {})
|
5
|
+
check_id(id)
|
6
|
+
response = get("/updates/#{id}.json")
|
7
|
+
Buffer::Update.new(response)
|
8
|
+
end
|
9
|
+
|
10
|
+
def updates_by_profile_id(id, options = {})
|
11
|
+
status = options.fetch(:status) do
|
12
|
+
raise Buffer::Error::MissingStatus, "Include :pending or :sent in args"
|
13
|
+
end
|
14
|
+
options.delete(:status)
|
15
|
+
response = get("/profiles/#{id}/updates/#{status.to_s}.json", options)
|
16
|
+
updates = response['updates'].map { |r| Buffer::Update.new(r) }
|
17
|
+
Buffer::Updates.new (
|
18
|
+
{ total: response['total'],
|
19
|
+
updates: updates }
|
20
|
+
)
|
21
|
+
end
|
22
|
+
|
23
|
+
def interactions_by_update_id(id, options = {})
|
24
|
+
check_id(id)
|
25
|
+
response = get("/updates/#{id}/interactions.json", options)
|
26
|
+
interactions = response['interactions'].map do |r|
|
27
|
+
Buffer::Interaction.new(r)
|
28
|
+
end
|
29
|
+
Buffer::Interactions.new(
|
30
|
+
{ total: response['total'], interactions: interactions }
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
def reorder_updates(profile_id, options = {})
|
35
|
+
options.fetch(:order) { raise ArgumentError }
|
36
|
+
post("/profiles/#{profile_id}/updates/reorder.json", body: options)
|
37
|
+
end
|
38
|
+
|
39
|
+
def shuffle_updates(profile_id, options = {})
|
40
|
+
post("/profiles/#{profile_id}/updates/shuffle.json",
|
41
|
+
body: options)
|
42
|
+
end
|
43
|
+
|
44
|
+
def create_update(options = {})
|
45
|
+
options[:body].fetch(:text) do
|
46
|
+
raise ArgumentError, "Must include text for update"
|
47
|
+
end
|
48
|
+
options[:body].fetch(:profile_ids) do
|
49
|
+
raise ArgumentError, "Must include array of profile_ids"
|
50
|
+
end
|
51
|
+
post("/updates/create.json", options)
|
52
|
+
end
|
53
|
+
|
54
|
+
def modify_update_text(update_id, options = {})
|
55
|
+
options[:body].fetch(:text) do
|
56
|
+
raise ArgumentError, "Must include updated text"
|
57
|
+
end
|
58
|
+
post("/updates/#{update_id}/update.json", options)
|
59
|
+
end
|
60
|
+
|
61
|
+
def share_update(update_id)
|
62
|
+
post("/updates/#{update_id}/share.json")
|
63
|
+
end
|
64
|
+
|
65
|
+
def destroy_update(update_id)
|
66
|
+
post("/updates/#{update_id}/destroy.json")
|
67
|
+
end
|
68
|
+
|
69
|
+
def check_id(id)
|
70
|
+
raise Buffer::Error::InvalidIdLength unless id.length == 24
|
71
|
+
raise Buffer::Error::InvalidIdContent unless id[/^[a-f0-9]+$/i]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
data/lib/buffer/user.rb
ADDED
data/lib/buffer/version.rb
CHANGED
data/lib/buffer.rb
CHANGED
@@ -1,107 +1,21 @@
|
|
1
|
-
require 'buffer/version'
|
2
1
|
require 'faraday'
|
3
|
-
require '
|
2
|
+
require 'faraday_middleware'
|
3
|
+
require 'json'
|
4
|
+
require 'hashie/mash'
|
4
5
|
require 'addressable/uri'
|
5
|
-
require '
|
6
|
-
|
7
|
-
module Buffer
|
8
|
-
class Client
|
9
|
-
|
10
|
-
attr_reader :token
|
11
|
-
|
12
|
-
# Initialize a new Buffer::Client
|
13
|
-
#
|
14
|
-
# Also sets up a Faraday connection object
|
15
|
-
#
|
16
|
-
# token - string access token for use with all API requests
|
17
|
-
def initialize(token)
|
18
|
-
if token.kind_of? String
|
19
|
-
@token = token
|
20
|
-
else
|
21
|
-
raise ArgumentError, "token must be a string"
|
22
|
-
end
|
23
|
-
|
24
|
-
@conn = Faraday.new :url => 'https://api.bufferapp.com/1/'
|
25
|
-
@addr = Addressable::URI.new
|
26
|
-
end
|
27
|
-
|
28
|
-
# get is a shorthand method for api :get
|
29
|
-
#
|
30
|
-
# uri - string endpoint uri
|
31
|
-
def get(uri)
|
32
|
-
api :get, uri
|
33
|
-
end
|
34
|
-
|
35
|
-
# post is a shorthand method for api :post
|
36
|
-
#
|
37
|
-
# uri - string endpoint uri
|
38
|
-
# data - hash or array for POST body
|
39
|
-
def post(uri, data = {})
|
40
|
-
api :post, uri, data
|
41
|
-
end
|
42
|
-
|
43
|
-
# api is the root method of the Client, handling all requests.
|
44
|
-
#
|
45
|
-
# type - HTTP verb, :get or :post
|
46
|
-
# url - enpoint uri, with or without .json
|
47
|
-
# data - hash or array of data to be sent in POST body
|
48
|
-
def api(type, uri, data = {})
|
49
|
-
uri << '.json' unless uri =~ /\.json$/
|
50
|
-
res = if type == :get
|
51
|
-
@conn.get uri, :access_token => @token
|
52
|
-
elsif type == :post
|
53
|
-
@conn.post do |req|
|
54
|
-
req.url uri, :access_token => @token
|
55
|
-
req.body = data.to_query
|
56
|
-
end
|
57
|
-
end
|
58
|
-
# Return nil if the body is less that 2 characters long,
|
59
|
-
# ie. '{}' is the minimum valid JSON, or if the decoder
|
60
|
-
# raises an exception when passed mangled JSON
|
61
|
-
begin
|
62
|
-
MultiJson.load res.body if res.body && res.body.length >= 2
|
63
|
-
rescue
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
67
|
-
end
|
6
|
+
require 'environs'
|
68
7
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
#
|
81
|
-
# Returns a hash of user data.
|
82
|
-
def user
|
83
|
-
@cache[:user] ||= get 'user'
|
84
|
-
end
|
85
|
-
|
86
|
-
public
|
87
|
-
|
88
|
-
# invalidate wipes the cache so that future requests
|
89
|
-
# rebuild it from server data
|
90
|
-
def invalidate
|
91
|
-
@cache = {}
|
92
|
-
end
|
93
|
-
|
94
|
-
# method_missing steps in to enable the helper methods
|
95
|
-
# by trying to get a particular key from self.user
|
96
|
-
#
|
97
|
-
# Returns the user data or the result of super
|
98
|
-
def method_missing(method, *args, &block)
|
99
|
-
user[method.to_s] || super
|
100
|
-
end
|
101
|
-
|
102
|
-
def respond_to?(name)
|
103
|
-
user.key_exist? name
|
104
|
-
end
|
8
|
+
require 'buffer/version'
|
9
|
+
require 'buffer/core'
|
10
|
+
require 'buffer/user'
|
11
|
+
require 'buffer/profile'
|
12
|
+
require 'buffer/update'
|
13
|
+
require 'buffer/link'
|
14
|
+
require 'buffer/error'
|
15
|
+
require 'buffer/encode'
|
16
|
+
require 'buffer/datastructure'
|
17
|
+
require 'buffer/info'
|
18
|
+
require 'buffer/client'
|
105
19
|
|
106
|
-
|
20
|
+
module Buffer
|
107
21
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
HTTP/1.1 200 Awesome
|
2
|
+
Content-Type: application/json;charset=UTF-8
|
3
|
+
Date: Wed, 15 May 2013 01:43:34 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
x-frame-options: SAMEORIGIN
|
7
|
+
Content-Length: 828
|
8
|
+
Connection: keep-alive
|
9
|
+
|
10
|
+
{"success":true,"message":"Update deleted successfully"}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
HTTP/1.1 200 Awesome
|
2
|
+
Content-Type: application/json;charset=UTF-8
|
3
|
+
Date: Thu, 16 May 2013 22:05:18 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
x-frame-options: SAMEORIGIN
|
7
|
+
Content-Length: 2820
|
8
|
+
Connection: keep-alive
|
9
|
+
|
10
|
+
{"services":{"twitter":{"types":{"profile":{"name":"Twitter","character_limit":140,"schedule_limit":288,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/twitter-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/twitter-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/twitter-64x64.png"},"supported_interactions":["favorites","favorite","mentions","mention","retweets","retweet"]}},"urls":{"user":"https:\/\/twitter.com\/","hashtag":"https:\/\/twitter.com\/#!\/search?q=%23","cashtag":"https:\/\/twitter.com\/#!\/search?q=%24"}},"facebook":{"types":{"profile":{"name":"Facebook","character_limit":5000,"schedule_limit":5,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/facebook-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/facebook-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/facebook-64x64.png"},"supported_interactions":["likes","like","comments","comment"]},"page":{"name":"Facebook Page","character_limit":5000,"schedule_limit":5,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/facebook-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/facebook-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/facebook-64x64.png"},"supported_interactions":["likes","like","comments","comment"]}},"urls":{"user":"https:\/\/www.facebook.com\/"}},"linkedin":{"types":{"profile":{"name":"LinkedIn","character_limit":700,"schedule_limit":25,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-64x64.png"},"supported_interactions":["comments","comment","likes","like"]},"group":{"name":"LinkedIn Group","character_limit":200,"schedule_limit":100,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/linkedin-64x64.png"},"supported_interactions":["comments","comment","likes","like"]}},"urls":{"user":"http:\/\/www.linkedin.com\/search\/fpsearch?type=people&keywords="}},"appdotnet":{"types":{"profile":{"name":"App.net","character_limit":256,"schedule_limit":288,"icons":{"16":"http:\/\/static.bufferapp.com\/images\/services\/appdotnet-alpha-16x16.png","32":"http:\/\/static.bufferapp.com\/images\/services\/appdotnet-alpha2-32x32.png","64":"http:\/\/static.bufferapp.com\/images\/services\/appdotnet-alpha-64x64.png"},"supported_interactions":[]}},"urls":{"user":"https:\/\/alpha.app.net\/","hashtag":"https:\/\/alpha.app.net\/hashtags\/"}}},"media":{"picture_size_min":0,"picture_size_max":5242880,"picture_filetypes":["jpeg","jpg","gif","png"]}}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
HTTP/1.1 200 Awesome
|
2
|
+
Content-Type: application/json;charset=UTF-8
|
3
|
+
Date: Fri, 17 May 2013 04:21:13 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
x-frame-options: SAMEORIGIN
|
7
|
+
Content-Length: 29
|
8
|
+
Connection: keep-alive
|
9
|
+
|
10
|
+
{"total":0,"interactions":[]}
|
@@ -0,0 +1,12 @@
|
|
1
|
+
HTTP/1.1 200 Awesome
|
2
|
+
Content-Type: application/json;charset=UTF-8
|
3
|
+
Date: Wed, 15 May 2013 01:43:34 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
x-frame-options: SAMEORIGIN
|
7
|
+
Content-Length: 828
|
8
|
+
Connection: keep-alive
|
9
|
+
|
10
|
+
{
|
11
|
+
"shares":47348
|
12
|
+
}
|
@@ -0,0 +1,11 @@
|
|
1
|
+
HTTP/1.1 200 Awesome
|
2
|
+
Content-Type: application/json;charset=UTF-8
|
3
|
+
Date: Tue, 14 May 2013 05:02:18 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
X-Cache: Awwww Yea
|
7
|
+
x-frame-options: SAMEORIGIN
|
8
|
+
Content-Length: 845
|
9
|
+
Connection: keep-alive
|
10
|
+
|
11
|
+
[{"_id":"5160746d13f04a5e3a00000f","avatar":"http:\/\/a0.twimg.com\/profile_images\/3604112130.jpeg","avatar_https":"https:\/\/twimg0-a.akamaihd.net\/profile_images\/3604112130.jpeg","counts":{"pending":1,"sent":40},"created_at":1365275757,"default":true,"disconnected":null,"formatted_service":"Twitter","formatted_username":"@example","id":"5160746d13d04a5e3a00000f","quick_signin":true,"schedules":[{"days":["mon","tue","wed","thu","fri","sat","sun"],"times":["06:13","09:10","11:58","12:17","13:49","18:07","21:04","22:13"]}],"service":"twitter","service_id":"737649619","service_type":"profile","service_username":"example","statistics":{"followers":179},"timezone":"America\/New_York","user_id":"5160746d13d04a5e3a00000d","utm_tracking":"enabled","verb":"tweet"}]
|
@@ -0,0 +1,10 @@
|
|
1
|
+
HTTP/1.1 200 Awesome
|
2
|
+
Content-Type: application/json;charset=UTF-8
|
3
|
+
Date: Wed, 15 May 2013 01:53:50 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
x-frame-options: SAMEORIGIN
|
7
|
+
Content-Length: 128
|
8
|
+
Connection: keep-alive
|
9
|
+
|
10
|
+
[{"days":["mon","tue","wed","thu","fri","sat","sun"],"times":["06:13","09:10","11:58","12:17","13:49","18:07","21:04","22:13"]}]
|
@@ -0,0 +1,10 @@
|
|
1
|
+
HTTP/1.1 200 Awesome
|
2
|
+
Content-Type: application/json;charset=UTF-8
|
3
|
+
Date: Wed, 15 May 2013 01:43:34 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
x-frame-options: SAMEORIGIN
|
7
|
+
Content-Length: 828
|
8
|
+
Connection: keep-alive
|
9
|
+
|
10
|
+
{"_id":"5160746d13d04a5e3a00000f","avatar":"http:\/\/a0.twimg.com\/profile_images\/3604112130.jpeg","avatar_https":"https:\/\/twimg0-a.akamaihd.net\/profile_images\/3604112130.jpeg","counts":{"pending":1,"sent":46},"created_at":1365275757,"disconnected":null,"formatted_service":"Twitter","formatted_username":"@example","id":"5160746d13d04a5e3a00000f","quick_signin":true,"schedules":[{"days":["mon","tue","wed","thu","fri","sat","sun"],"times":["06:13","09:10","11:58","12:17","13:49","18:07","21:04","22:13"]}],"service":"twitter","service_id":"737649619","service_type":"profile","service_username":"example","statistics":{"followers":179},"timezone":"America\/New_York","user_id":"5160746d13d04a5e3a00000d","utm_tracking":"enabled","verb":"tweet"}
|
@@ -0,0 +1,10 @@
|
|
1
|
+
HTTP/1.1 200 Awesome
|
2
|
+
Content-Type: application/json;charset=UTF-8
|
3
|
+
Date: Wed, 15 May 2013 01:43:34 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
x-frame-options: SAMEORIGIN
|
7
|
+
Content-Length: 828
|
8
|
+
Connection: keep-alive
|
9
|
+
|
10
|
+
{"id":"4eb8565e0acb04bb82000004","created_at":1320703582,"day":"Monday 7th November","due_at":1320742680,"due_time":"10:09 pm","profile_id":"4eb854340acb04e870000010","profile_service":"twitter","sent_at":1320744001,"service_update_id":"133667319959392256","statistics":{"reach":2460,"clicks":56,"retweets":20,"favorites":1,"mentions":1},"status":"sent","text":"This is just the beginning, the very beginning, of the transfor...","text_formatted":"This is just the beginning, the very beginning, of th...","user_id":"4eb9276e0acb04bb81000067","via":"chrome"}
|
@@ -0,0 +1,9 @@
|
|
1
|
+
HTTP/1.1 401 Authorization Required
|
2
|
+
Content-Type: text/html; charset=UTF-8
|
3
|
+
Date: Fri, 17 May 2013 02:46:37 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
WWW-Authenticate: OAuth realm='Service', error='invalid_request', error_description='The request is missing a required parameter, includes an unsupported parameter or parameter value, repeats the same parameter, uses more than one method for including an access token, or is otherwise malformed.'
|
7
|
+
Content-Length: 0
|
8
|
+
Connection: keep-alive
|
9
|
+
|
@@ -0,0 +1,10 @@
|
|
1
|
+
HTTP/1.1 200 Awesome
|
2
|
+
Content-Type: application/json;charset=UTF-8
|
3
|
+
Date: Wed, 15 May 2013 01:43:34 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
x-frame-options: SAMEORIGIN
|
7
|
+
Content-Length: 828
|
8
|
+
Connection: keep-alive
|
9
|
+
|
10
|
+
{"total":8,"updates":[{"id":"4ec93ae4512f7e6307000002","created_at":1320703582,"day":"Monday 7th November","due_at":1320543480,"due_time":"07:01 pm","profile_id":"4eb854340acb04e870000010","profile_service":"twitter","status":"buffer","text":"This is me in an alternate life where i can breakdance j.mp/w...","text_formatted":"This is me in an alternate life where i can breakda...","user_id":"4eb9276e0acb04bb81000067","via":"firefox"},] }
|
@@ -0,0 +1,10 @@
|
|
1
|
+
HTTP/1.1 200 Awesome
|
2
|
+
Content-Type: application/json;charset=UTF-8
|
3
|
+
Date: Thu, 16 May 2013 04:48:14 GMT
|
4
|
+
Server: Apache
|
5
|
+
Vary: Accept-Encoding,User-Agent
|
6
|
+
x-frame-options: SAMEORIGIN
|
7
|
+
Content-Length: 737
|
8
|
+
Connection: keep-alive
|
9
|
+
|
10
|
+
{"total":1,"updates":[{"_id":"519464f2872cad3734000028","created_at":1368679666,"day":"Today","due_at":1368699180,"due_time":"6:13 am","id":"519464f2872cad3734000028","profile_id":"5160746d13d04a5e3a00000f","profile_service":"twitter","shared_now":false,"status":"buffer","text":"Exciting to have even 1 person fork my fork of a repo :) jaysonlane\/buffer-ruby \u00b7 GitHub http:\/\/bit.ly\/15OS4ap","text_formatted":"Exciting to have even 1 person fork my fork of a repo :) jaysonlane\/buffer-ruby \u00b7 GitHub <a class=\"url\" href=\"http:\/\/bit.ly\/15OS4ap\" rel=\"external nofollow\" target=\"_blank\">http:\/\/bit.ly\/15OS4ap<\/a>","type":"link","updated_at":1368679666,"user_id":"5160746d54f04a5e3a00000d","via":"bookmarklet"}]}
|
@@ -0,0 +1,19 @@
|
|
1
|
+
HTTP/1.1 200 OK
|
2
|
+
Server: nginx/0.7.65
|
3
|
+
Date: Thu, 03 Mar 2011 19:25:34 GMT
|
4
|
+
Content-Type: application/json
|
5
|
+
Connection: keep-alive
|
6
|
+
Keep-Alive: timeout=20
|
7
|
+
Content-Length: 380
|
8
|
+
|
9
|
+
{
|
10
|
+
"_id":"4f0c0a06512f7ef214000000",
|
11
|
+
"activity_at":1343654640,
|
12
|
+
"created_at":1326189062,
|
13
|
+
"id":"4f0c0a06512f7ef214000000",
|
14
|
+
"plan":"free",
|
15
|
+
"referral_link":"http:\/\/bufferapp.com\/r\/abcde",
|
16
|
+
"referral_token":"abcde",
|
17
|
+
"secret_email":"supersecret@to.bufferapp.com",
|
18
|
+
"timezone":"Asia\/Tel_Aviv"
|
19
|
+
}
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe Buffer::Encode do
|
4
|
+
|
5
|
+
context "successful code" do
|
6
|
+
|
7
|
+
let(:schedule_first) { { :days => ["mon", "tue", "wed", "thu"], :times => ["12:00", "13:00"]} }
|
8
|
+
let(:schedule_second) { { :days => ["sun", "sat"], :times => ["09:00", "24:00"]} }
|
9
|
+
let(:schedules_hash) { { schedules: [schedule_first, schedule_second] } }
|
10
|
+
let(:short_schedule) { { days: ["mon", "tue", "wed"], times: ["12:00", "17:00", "18:00"]} }
|
11
|
+
let(:short_schedule_encoded) { "[days][]=mon&[days][]=tue&[times][]=12%3A00&[times][]=13%3A00" }
|
12
|
+
let(:schedules_encoded) { "schedules[0][days][]=mon&schedules[0][days][]=tue&schedules[0][days][]=wed&schedules[0][times][]=12:00&schedules[0][times][]=17:00&schedules[0][times][]=18:00" }
|
13
|
+
let(:very_short_schedule) { { :days => ["sun", "sat"], :times => ["09:00", "24:00"]} }
|
14
|
+
|
15
|
+
|
16
|
+
describe "#encode"
|
17
|
+
it "converts to match Buffer API specs encoding" do
|
18
|
+
Buffer::Encode.encode([short_schedule]).
|
19
|
+
should eq(schedules_encoded.gsub(/:/, '%3A'))
|
20
|
+
end
|
21
|
+
|
22
|
+
it "processes an input array of schedules" do
|
23
|
+
Buffer::Encode.encode([very_short_schedule, very_short_schedule]).
|
24
|
+
should eq("schedules[0][days][]=sun&schedules[0][days][]=sat&schedules[0][times][]=09%3A00&schedules[0][times][]=24%3A00&schedules[1][days][]=sun&schedules[1][days][]=sat&schedules[1][times][]=09%3A00&schedules[1][times][]=24%3A00")
|
25
|
+
end
|
26
|
+
|
27
|
+
it "includes index in conversion when multiple schedules present" do
|
28
|
+
Buffer::Encode.encode([very_short_schedule, very_short_schedule, very_short_schedule]).
|
29
|
+
should eq("schedules[0][days][]=sun&schedules[0][days][]=sat&schedules[0][times][]=09%3A00&schedules[0][times][]=24%3A00&schedules[1][days][]=sun&schedules[1][days][]=sat&schedules[1][times][]=09%3A00&schedules[1][times][]=24%3A00&schedules[2][days][]=sun&schedules[2][days][]=sat&schedules[2][times][]=09%3A00&schedules[2][times][]=24%3A00")
|
30
|
+
end
|
31
|
+
|
32
|
+
it "processes an input hash" do
|
33
|
+
Buffer::Encode.encode({ schedules: [very_short_schedule, very_short_schedule, very_short_schedule] }).
|
34
|
+
should eq("schedules[0][days][]=sun&schedules[0][days][]=sat&schedules[0][times][]=09%3A00&schedules[0][times][]=24%3A00&schedules[1][days][]=sun&schedules[1][days][]=sat&schedules[1][times][]=09%3A00&schedules[1][times][]=24%3A00&schedules[2][days][]=sun&schedules[2][days][]=sat&schedules[2][times][]=09%3A00&schedules[2][times][]=24%3A00")
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
describe "#encode_schedule_primary" do
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Buffer::Client do
|
4
|
+
describe "#link" do
|
5
|
+
let(:client) { Buffer::Client.new("some_token") }
|
6
|
+
let(:url) { %q{http://bufferapp.com} }
|
7
|
+
|
8
|
+
before do
|
9
|
+
stub_request(:get, "#{ base_path }/links/shares.json?#{ access_token_param }&url=http://bufferapp.com").
|
10
|
+
to_return(fixture('link.txt'))
|
11
|
+
end
|
12
|
+
|
13
|
+
it "connects to the correct endpoint" do
|
14
|
+
client.link({url: url})
|
15
|
+
end
|
16
|
+
|
17
|
+
it "parses the shares of a link" do
|
18
|
+
client.link({url: url}).shares.should eq(47348)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Buffer::Client::Profile do
|
4
|
+
let(:id) { "5160746d54f04a5e3a00000f" }
|
5
|
+
|
6
|
+
subject do
|
7
|
+
Buffer::Client.new("some_token")
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "#profiles" do
|
11
|
+
let(:rash) { Buffer::Client.new("some_token").profiles }
|
12
|
+
|
13
|
+
before(:each) do
|
14
|
+
url = "#{ base_path }/profiles.json"
|
15
|
+
stub_with_to_return(:get, url, 'profile_authenticated.txt')
|
16
|
+
end
|
17
|
+
|
18
|
+
it "makes the correct url request" do
|
19
|
+
subject.profiles
|
20
|
+
end
|
21
|
+
|
22
|
+
it "returns a Rash collection object" do
|
23
|
+
rash[0].class.should eq(Buffer::Profile)
|
24
|
+
end
|
25
|
+
|
26
|
+
it "provides an accessor for plan" do
|
27
|
+
rash[0].service.should eq("twitter")
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "#profile_by_id" do
|
32
|
+
let(:id) { "5160746d54f04a5e3a00000f" }
|
33
|
+
before(:each) do
|
34
|
+
url = "#{base_path}/profiles/#{id}.json"
|
35
|
+
fixture_name = "profiles_by_id.txt"
|
36
|
+
stub_with_to_return(:get, url, fixture_name)
|
37
|
+
end
|
38
|
+
|
39
|
+
let(:rash) { Buffer::Client.new("some_token").profile_by_id(id) }
|
40
|
+
|
41
|
+
it "returns a rash collection" do
|
42
|
+
rash.class.should eq(Buffer::Profile)
|
43
|
+
end
|
44
|
+
|
45
|
+
it "accesses formatted service" do
|
46
|
+
rash.formatted_service.should eq("Twitter")
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
describe "#schedules_by_profile_id" do
|
51
|
+
before(:each) do
|
52
|
+
url = "#{base_path}/profiles/#{id}/schedules.json"
|
53
|
+
fixture_name = 'profile_schedules_by_id.txt'
|
54
|
+
stub_with_to_return(:get, url, fixture_name)
|
55
|
+
end
|
56
|
+
|
57
|
+
let(:rash) { Buffer::Client.new("some_token").schedules_by_profile_id(id) }
|
58
|
+
|
59
|
+
it "returns a rash collection" do
|
60
|
+
rash[0].class.should eq(Buffer::Schedule)
|
61
|
+
end
|
62
|
+
|
63
|
+
it "accesses days" do
|
64
|
+
expect(rash[0].days).to include("mon")
|
65
|
+
end
|
66
|
+
|
67
|
+
it "accesses times" do
|
68
|
+
expect(rash[0].times).to include("06:13")
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
|
73
|
+
describe "#info" do
|
74
|
+
before do
|
75
|
+
stub_request(:get, "#{base_path}/info/configuration.json?access_token=some_token").
|
76
|
+
to_return(fixture("info.txt"))
|
77
|
+
end
|
78
|
+
|
79
|
+
it "connects to the correct endpoint" do
|
80
|
+
subject.info
|
81
|
+
end
|
82
|
+
|
83
|
+
it "retrieves the correct name" do
|
84
|
+
subject.info.services.twitter.types.profile.name.should eq("Twitter")
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Buffer::Schedules do
|
4
|
+
before do
|
5
|
+
@schedule = JSON.parse <<EOF
|
6
|
+
{
|
7
|
+
"days" : [
|
8
|
+
"mon",
|
9
|
+
"tue",
|
10
|
+
"wed",
|
11
|
+
"thu",
|
12
|
+
"fri"
|
13
|
+
],
|
14
|
+
"times" : [
|
15
|
+
"12:00",
|
16
|
+
"17:00",
|
17
|
+
"18:00"
|
18
|
+
]
|
19
|
+
}
|
20
|
+
EOF
|
21
|
+
|
22
|
+
@sample_schedules = JSON.parse <<EOF
|
23
|
+
{ "schedules" : [{
|
24
|
+
"days" : [
|
25
|
+
"mon",
|
26
|
+
"tue",
|
27
|
+
"wed",
|
28
|
+
"thu",
|
29
|
+
"fri"
|
30
|
+
],
|
31
|
+
"times" : [
|
32
|
+
"12:00",
|
33
|
+
"17:00",
|
34
|
+
"18:00"
|
35
|
+
]
|
36
|
+
},
|
37
|
+
{
|
38
|
+
"days" : [
|
39
|
+
"mon",
|
40
|
+
"tue",
|
41
|
+
"wed",
|
42
|
+
"thu",
|
43
|
+
"fri"
|
44
|
+
],
|
45
|
+
"times" : [
|
46
|
+
"12:00",
|
47
|
+
"17:00",
|
48
|
+
"18:00"
|
49
|
+
]
|
50
|
+
}]
|
51
|
+
}
|
52
|
+
EOF
|
53
|
+
end
|
54
|
+
|
55
|
+
it "accepts an array of days" do
|
56
|
+
lambda {
|
57
|
+
schedules = Buffer::Schedules.new
|
58
|
+
schedules << Buffer::Schedule.new
|
59
|
+
}.should_not raise_error
|
60
|
+
end
|
61
|
+
|
62
|
+
it "dumping a double schedule yields correct json" do
|
63
|
+
schedules = Buffer::Schedules.new
|
64
|
+
schedules << @schedule << @schedule
|
65
|
+
@sample_schedules = @sample_schedules.to_json
|
66
|
+
|
67
|
+
schedules.dump.should eq(@sample_schedules)
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#set_schedules" do
|
71
|
+
let(:id) { "5160746d54f04a5e3a00000f" }
|
72
|
+
it "throw error if schedules is empty" do
|
73
|
+
lambda {
|
74
|
+
Buffer::Client.new("some_token").set_schedules(id) }.
|
75
|
+
should raise_error(ArgumentError)
|
76
|
+
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|