inoreader-api 0.9.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.
@@ -0,0 +1,77 @@
1
+ # coding: utf-8
2
+ require 'httparty'
3
+ require 'multi_json'
4
+ require 'hashie'
5
+
6
+ module InoreaderApi
7
+ class Helper
8
+ include HTTParty
9
+
10
+ attr_accessor :ret
11
+
12
+ debug = false
13
+ if debug
14
+ debug_output $stdout
15
+ end
16
+ self.disable_rails_query_string_format
17
+
18
+ base_uri 'https://www.inoreader.com'
19
+
20
+ class << self
21
+
22
+ # option: use httparty respqnse if set true
23
+ @@return_httparty_response = false
24
+
25
+ def return_httparty_response=(bool)
26
+ @@return_httparty_response = bool
27
+ end
28
+
29
+
30
+ # send request
31
+ # @param [String] path request path
32
+ # @param [Hash] query URL params ex. {:query => {:T => 'token', :ref => 'bar'}}
33
+ # @param [Symbol] method :get or :post
34
+ # @return response body
35
+ def request(path, query=nil, method=:get)
36
+
37
+ begin
38
+ response = self.send(method, path, query)
39
+ rescue => e
40
+ #request fail (ex. timeout)
41
+ raise InoreaderApiError.new e.message
42
+ end
43
+
44
+ if response.response.code == '200'
45
+ if @@return_httparty_response
46
+ response
47
+ else
48
+ begin
49
+ #return to hashie
50
+ Hashie::Mash.new MultiJson.decode(response.body)
51
+ rescue
52
+ # its not JSON, return body directly.
53
+ response.body
54
+ end
55
+ end
56
+ else
57
+ # request fail (ex. 500, 401...)
58
+ raise InoreaderApiError.new response.response.message
59
+ end
60
+ end
61
+
62
+ # auth request to Inoreader
63
+ # @param [String] un username
64
+ # @param [String] pw password
65
+ # @return response body
66
+ def auth_request(un, pw)
67
+ response = self.post('/accounts/ClientLogin', {:body => {:Email => un, :Passwd => pw}})
68
+ if response.response.code == '200'
69
+ # request fail (ex. 500, 401...)
70
+ response.body
71
+ else
72
+ raise InoreaderApiError.new response.response.message
73
+ end
74
+ end
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,5 @@
1
+ module Inoreader
2
+ module Api
3
+ VERSION = "0.9.0"
4
+ end
5
+ end
@@ -0,0 +1,57 @@
1
+ require 'rspec'
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ describe 'InoreaderApi::Api auth' do
5
+
6
+ it 'should correct auth' do
7
+ set_auth_stub('dummy_name', 'dummy_pass', 200, "SID=null\nLSID=null\nAuth=thisisdummyauthkey!321")
8
+ ino = InoreaderApi::Api.new(
9
+ :username => 'dummy_name',
10
+ :password => 'dummy_pass'
11
+ )
12
+ ino.auth_token.should == 'thisisdummyauthkey!321'
13
+ end
14
+
15
+ it 'should auth failed (unAuthorizing)' do
16
+ set_auth_stub('fail', 'pass', [400, 'Authorization Required'], 'Error=BadAuthentication')
17
+ proc {
18
+ InoreaderApi::Api.new(
19
+ :username => 'fail',
20
+ :password => 'pass'
21
+ )
22
+ }.should raise_error(InoreaderApi::InoreaderApiError, 'Authorization Required')
23
+ end
24
+
25
+ it 'should auth failed 500' do
26
+ set_auth_stub('error', 'pass', [500, 'Internal Server Error'], '')
27
+ proc {
28
+ InoreaderApi::Api.new(
29
+ :username => 'error',
30
+ :password => 'pass'
31
+ )
32
+ }.should raise_error(InoreaderApi::InoreaderApiError, 'Internal Server Error')
33
+ end
34
+
35
+ it 'should to timeout' do
36
+ stub_request(:post, 'https://www.inoreader.com/accounts/ClientLogin').
37
+ with(:body => 'Email=timeout_name&Passwd=fail_pass').to_timeout
38
+
39
+ proc {
40
+ InoreaderApi::Api.new(
41
+ :username => 'timeout_name',
42
+ :password => 'fail_pass'
43
+ )
44
+ }.should raise_error(InoreaderApi::InoreaderApiError, 'execution expired')
45
+ end
46
+
47
+ it 'should get token' do
48
+ stub_request(:get, 'https://www.inoreader.com/reader/api/0/token?T=dummy_token').
49
+ to_return(
50
+ :status => 200,
51
+ :body => 'dummy_token',
52
+ :headers => {}
53
+ )
54
+ ino = InoreaderApi::Api.new(:auth_token => 'dummy_token')
55
+ ino.instance_variable_get(:@auth_token).should == 'dummy_token'
56
+ end
57
+ end
@@ -0,0 +1,60 @@
1
+ require 'rspec'
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ describe 'InoreaderApi::Api#unread_counters' do
5
+ it 'should get unread count' do
6
+ body = '{"max":"1000","unreadcounts":[{"id":"user\/9999999999\/state\/com.google\/reading-list","count":1000,"newestItemTimestampUsec":"1390821452642780"}]}'
7
+ stub_request(:get, make_url(REQUEST_PATH[:unread_count], {
8
+ :T => 'dummy_token',
9
+ :output => 'json'
10
+ })).to_return(
11
+ :status => 200,
12
+ :body => body,
13
+ :headers => {}
14
+ )
15
+ res = InoreaderApi::Api.new(
16
+ :auth_token => 'dummy_token'
17
+ ).unread_counters
18
+ res[:max].should == '1000'
19
+ res.unreadcounts[0].id == 'user/9999999999/state/com.google/reading-list'
20
+ res.unreadcounts[0].count == 1000
21
+ res.unreadcounts[0].newestItemTimestampUsec == '1390821452642780'
22
+ end
23
+ end
24
+
25
+ describe 'InoreaderApi::Api#user_subscription' do
26
+ it 'should get user subscription' do
27
+ body = '{"subscriptions":[{ "id":"feed\/http:\/\/feeds.feedburner.com\/AjaxRain"}]}'
28
+ stub_request(:get, make_url(REQUEST_PATH[:subscription], {
29
+ :T => 'dummy_token'
30
+ })).to_return(
31
+ :status => 200,
32
+ :body => body,
33
+ :headers => {}
34
+ )
35
+
36
+ res = InoreaderApi::Api.new(
37
+ :auth_token => 'dummy_token'
38
+ ).user_subscription
39
+ res.subscriptions[0].id.should == 'feed/http://feeds.feedburner.com/AjaxRain'
40
+ end
41
+ end
42
+
43
+ describe 'InoreaderApi::Api#user_tags_folders' do
44
+ it 'should get user tags' do
45
+ body = '{"tags": [{ "id": "user\/9999999999\/state\/com.google\/starred", "sortid": "FFFFFFFF" }]}'
46
+ stub_request(:get, make_url(REQUEST_PATH[:tag], {
47
+ :T => 'dummy_token'
48
+ })).to_return(
49
+ :status => 200,
50
+ :body => body,
51
+ :headers => {}
52
+ )
53
+
54
+ res = InoreaderApi::Api.new(
55
+ :auth_token => 'dummy_token'
56
+ ).user_tags_folders
57
+ res.tags[0].id.should == 'user/9999999999/state/com.google/starred'
58
+ res.tags[0].sortid.should == 'FFFFFFFF'
59
+ end
60
+ end
@@ -0,0 +1,23 @@
1
+ require 'rspec'
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ describe 'InoreaderApi::Api mark all as read manipulation' do
5
+
6
+ it 'should mark all as read ' do
7
+ feed = 'feed/http://feeds.feedburner.com/AjaxRain'
8
+ stub_request(:post, make_url(REQUEST_PATH[:mark_all_as_read], {
9
+ :T => 'dummy_token',
10
+ :ts => 1373407120123456,
11
+ :s => feed
12
+ })).to_return(
13
+ :status => 200,
14
+ :body => 'OK',
15
+ :headers => {}
16
+ )
17
+
18
+ InoreaderApi::Api.new(
19
+ :auth_token => 'dummy_token'
20
+ ).mark_all_as_read(1373407120123456, feed).should == 'OK'
21
+
22
+ end
23
+ end
@@ -0,0 +1,62 @@
1
+ require 'rspec'
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ describe 'InoreaderApi::Api preferences manipulation' do
5
+
6
+ it 'should get preferences list' do
7
+ body = '{ "prefs": [{"id": "lhn-prefs", "value": "{\"subscriptions\":{\"ssa\":\"false\"}}"}]}'
8
+ stub_request(:get, make_url(REQUEST_PATH[:preference_list], {
9
+ :T => 'dummy_token',
10
+ })).to_return(
11
+ :status => 200,
12
+ :body => body,
13
+ :headers => {}
14
+ )
15
+
16
+ InoreaderApi::Api.new(
17
+ :auth_token => 'dummy_token'
18
+ ).preferences_list['prefs'].should == [
19
+ {
20
+ "id" => "lhn-prefs",
21
+ "value" => "{\"subscriptions\":{\"ssa\":\"false\"}}"
22
+ }]
23
+ end
24
+
25
+
26
+ it 'should get stream preferences list' do
27
+ body = '{"streamprefs": { "root": [{"id":"subscription-ordering", "value": "00BED5"}]}}'
28
+
29
+ stub_request(:get, make_url(REQUEST_PATH[:stream_preferences_list], {
30
+ :T => 'dummy_token',
31
+ })).to_return(
32
+ :status => 200,
33
+ :body => body,
34
+ :headers => {}
35
+ )
36
+
37
+ hashie_response = InoreaderApi::Api.new(
38
+ :auth_token => 'dummy_token'
39
+ ).stream_preferences_list
40
+ hashie_response.streamprefs.root[0].id.should == 'subscription-ordering'
41
+ hashie_response.streamprefs.root[0].value.should == '00BED5'
42
+
43
+ end
44
+
45
+ it 'should set preferences list' do
46
+
47
+ stub_request(:post, make_url(REQUEST_PATH[:set_stream_preferences], {
48
+ :T => 'dummy_token',
49
+ :k => 'subscription-ordering',
50
+ :s => 'user/-/state/com.google/root',
51
+ :v => '00A3AAB000B9C8F9',
52
+ })).to_return(
53
+ :status => 200,
54
+ :body => 'OK',
55
+ :headers => {}
56
+ )
57
+
58
+ InoreaderApi::Api.new(
59
+ :auth_token => 'dummy_token'
60
+ ).set_subscription_ordering('user/-/state/com.google/root', '00A3AAB000B9C8F9').should == 'OK'
61
+ end
62
+ end
@@ -0,0 +1,154 @@
1
+ require 'rspec'
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ describe 'Inoreader::Api#stream' do
5
+
6
+ it 'should get all item ids' do
7
+ body = '{"items":[],"itemRefs":[{"id":"9878"}]}'
8
+ stub_request(:get, make_url(REQUEST_PATH[:item_ids], {
9
+ :T => 'dummy_token',
10
+ :output => 'json'
11
+ })).to_return(
12
+ :status => 200,
13
+ :body => body,
14
+ :headers => {}
15
+ )
16
+
17
+ hashie_response = InoreaderApi::Api.new(
18
+ :auth_token => 'dummy_token'
19
+ ).item_ids
20
+ hashie_response.itemRefs[0].id.should == '9878'
21
+ hashie_response.items == []
22
+
23
+ httparty_response = InoreaderApi::Api.new(
24
+ :auth_token => 'dummy_token',
25
+ :return_httparty_response => true
26
+ ).item_ids
27
+ httparty_response.body.should == body
28
+
29
+ end
30
+
31
+ it 'should get feeds item ids' do
32
+ body = '{"items":[],"itemRefs":[{"id":"9878"}]}'
33
+ feed = 'feed/http://feeds.feedburner.com/AjaxRain'
34
+ stub_request(:get, make_url(REQUEST_PATH[:item_ids], {
35
+ :T => 'dummy_token',
36
+ :n => 10,
37
+ :r => 'o',
38
+ :ot => '1389756192',
39
+ :xt => 'user/-/state/com.google/read',
40
+ :it => 'user/-/state/com.google/read',
41
+ :c => 'asdfgqer',
42
+ :output => 'json'
43
+ }, feed)).to_return(
44
+ :status => 200,
45
+ :body => body,
46
+ :headers => {}
47
+ )
48
+
49
+ hashie_response = InoreaderApi::Api.new(
50
+ :auth_token => 'dummy_token'
51
+ ).item_ids(feed, {
52
+ :n => 10,
53
+ :r => 'o',
54
+ :ot => '1389756192',
55
+ :xt => 'user/-/state/com.google/read',
56
+ :it => 'user/-/state/com.google/read',
57
+ :c => 'asdfgqer'
58
+ })
59
+ hashie_response.itemRefs[0].id.should == '9878'
60
+ hashie_response.items.should == []
61
+
62
+
63
+ httparty_response = InoreaderApi::Api.new(
64
+ :auth_token => 'dummy_token',
65
+ :return_httparty_response => true
66
+ ).item_ids(feed, {
67
+ :n => 10,
68
+ :r => 'o',
69
+ :ot => '1389756192',
70
+ :xt => 'user/-/state/com.google/read',
71
+ :it => 'user/-/state/com.google/read',
72
+ :c => 'asdfgqer'
73
+ })
74
+
75
+ httparty_response.body.should == body
76
+ end
77
+
78
+ # check items api
79
+ it 'should get all feed items' do
80
+ body = '{"direction": "ltr","title": "Reading List","items":[{"id": "tag:00001"}]}'
81
+ stub_request(:get, make_url(REQUEST_PATH[:items], {
82
+ :T => 'dummy_token',
83
+ :output => 'json'
84
+ })).
85
+ to_return(
86
+ :status => 200,
87
+ :body => body,
88
+ :headers => {}
89
+ )
90
+
91
+ hashie_response = InoreaderApi::Api.new(
92
+ :auth_token => 'dummy_token'
93
+ ).items
94
+ hashie_response.direction.should == 'ltr'
95
+ hashie_response.title.should == 'Reading List'
96
+ hashie_response.items.count.should == 1
97
+ hashie_response.items[0].id.should == 'tag:00001'
98
+
99
+ httparty_response = InoreaderApi::Api.new(
100
+ :auth_token => 'dummy_token',
101
+ :return_httparty_response => true
102
+ ).items
103
+ httparty_response.body.should == body
104
+ end
105
+
106
+ it 'should get feeds items' do
107
+ body = '{"direction": "ltr","title": "feed1","items":[{"id": "tag:00001"}]}'
108
+ feed = 'feed/http://feeds.feedburner.com/AjaxRain'
109
+ stub_request(:get, make_url(REQUEST_PATH[:items], {
110
+ :T => 'dummy_token',
111
+ :n => 10,
112
+ :r => 'o',
113
+ :ot => '1389756192',
114
+ :xt => 'user/-/state/com.google/read',
115
+ :it => 'user/-/state/com.google/read',
116
+ :c => 'Beg3ah6v3',
117
+ :output => 'json'
118
+ },feed)).to_return(
119
+ :status => 200,
120
+ :body => body,
121
+ :headers => {}
122
+ )
123
+
124
+ hashie_response = InoreaderApi::Api.new(
125
+ :auth_token => 'dummy_token'
126
+ ).items(feed, {
127
+ :n => 10,
128
+ :r => 'o',
129
+ :ot => '1389756192',
130
+ :xt => 'user/-/state/com.google/read',
131
+ :it => 'user/-/state/com.google/read',
132
+ :c => 'Beg3ah6v3'
133
+ })
134
+ hashie_response.direction.should == 'ltr'
135
+ hashie_response.title.should == 'feed1'
136
+ hashie_response.items.count.should == 1
137
+ hashie_response.items[0].id.should == 'tag:00001'
138
+
139
+ httparty_response = InoreaderApi::Api.new(
140
+ :auth_token => 'dummy_token',
141
+ :return_httparty_response => true
142
+ ).items(feed, {
143
+ :n => 10,
144
+ :r => 'o',
145
+ :ot => '1389756192',
146
+ :xt => 'user/-/state/com.google/read',
147
+ :it => 'user/-/state/com.google/read',
148
+ :c => 'Beg3ah6v3'
149
+ })
150
+
151
+ httparty_response.body.should == body
152
+ end
153
+
154
+ end
@@ -0,0 +1,112 @@
1
+ require 'rspec'
2
+ require File.join(File.dirname(__FILE__), %w[spec_helper])
3
+
4
+ describe 'InoreaderApi::Api Subscription manipulation' do
5
+
6
+ it 'should add Subscription' do
7
+ url = 'http://feeds.feedburner.com/AjaxRain'
8
+ stub_request(:post, make_url(REQUEST_PATH[:add_subscription], {
9
+ :T => 'dummy_token',
10
+ :quickadd => url
11
+ })).to_return(
12
+ :status => 200,
13
+ :body => 'OK',
14
+ :headers => {}
15
+ )
16
+
17
+ InoreaderApi::Api.new(
18
+ :auth_token => 'dummy_token'
19
+ ).add_subscription(url).should == 'OK'
20
+ end
21
+
22
+ it 'should rename Subscription' do
23
+ feed = 'feed/http://feeds.feedburner.com/AjaxRain'
24
+ stub_request(:post, make_url(REQUEST_PATH[:edit_subscription], {
25
+ :T => 'dummy_token',
26
+ :ac => :edit,
27
+ :s => feed,
28
+ :t => 'new title'
29
+ })).to_return(
30
+ :status => 200,
31
+ :body => 'OK',
32
+ :headers => {}
33
+ )
34
+
35
+ InoreaderApi::Api.new(
36
+ :auth_token => 'dummy_token'
37
+ ).rename_subscription(feed, 'new title').should == 'OK'
38
+
39
+ end
40
+
41
+ it 'should add to folder a Subscription' do
42
+ feed = 'feed/http://feeds.feedburner.com/AjaxRain'
43
+ stub_request(:post, make_url(REQUEST_PATH[:edit_subscription], {
44
+ :T => 'dummy_token',
45
+ :ac => :edit,
46
+ :s => feed,
47
+ :a => 'new folder'
48
+ })).to_return(
49
+ :status => 200,
50
+ :body => 'OK',
51
+ :headers => {}
52
+ )
53
+
54
+ InoreaderApi::Api.new(
55
+ :auth_token => 'dummy_token'
56
+ ).add_folder_subscription(feed, 'new folder').should == 'OK'
57
+ end
58
+
59
+ it 'should remove from Subscription to folder' do
60
+ feed = 'feed/http://feeds.feedburner.com/AjaxRain'
61
+ stub_request(:post, make_url(REQUEST_PATH[:edit_subscription], {
62
+ :T => 'dummy_token',
63
+ :ac => :edit,
64
+ :s => feed,
65
+ :r => 'new folder'
66
+ })).to_return(
67
+ :status => 200,
68
+ :body => 'OK',
69
+ :headers => {}
70
+ )
71
+
72
+ InoreaderApi::Api.new(
73
+ :auth_token => 'dummy_token'
74
+ ).remove_folder_subscription(feed, 'new folder').should == 'OK'
75
+ end
76
+
77
+ it 'should unsubscribe' do
78
+ feed = 'feed/http://feeds.feedburner.com/AjaxRain'
79
+ stub_request(:post, make_url(REQUEST_PATH[:edit_subscription], {
80
+ :T => 'dummy_token',
81
+ :ac => :unsubscribe,
82
+ :s => feed,
83
+ })).to_return(
84
+ :status => 200,
85
+ :body => 'OK',
86
+ :headers => {}
87
+ )
88
+
89
+ InoreaderApi::Api.new(
90
+ :auth_token => 'dummy_token'
91
+ ).unsubscribe(feed).should == 'OK'
92
+ end
93
+
94
+ it 'should subscribe' do
95
+ feed = 'feed/http://feeds.feedburner.com/AjaxRain'
96
+ stub_request(:post, make_url(REQUEST_PATH[:edit_subscription], {
97
+ :T => 'dummy_token',
98
+ :ac => :subscribe,
99
+ :s => feed,
100
+ :a => 'new folder',
101
+ })).to_return(
102
+ :status => 200,
103
+ :body => 'OK',
104
+ :headers => {}
105
+ )
106
+
107
+ InoreaderApi::Api.new(
108
+ :auth_token => 'dummy_token'
109
+ ).subscribe(feed, 'new folder').should == 'OK'
110
+ end
111
+
112
+ end