storify 0.0.7 → 0.0.8

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 8e5b35c38cdddf4afe33c92a7e6881ffaa67204a
4
- data.tar.gz: 8812500f6fd457cbab902acb867eb360594f211e
3
+ metadata.gz: ee651fbc8ced627f9d5711d772ac0d998c4cea5f
4
+ data.tar.gz: de03b76abd522d5992ac684e6446222a299bf2cc
5
5
  SHA512:
6
- metadata.gz: 5242d0dc6441c8f683fd1f29014454094c24b099921e40de4a12f15ca679bf9509ffa5ee1e3f77303acf249a064866142cfbcba4d2e65ef71bc48b048f8a3b09
7
- data.tar.gz: 0ae3995e36650a02fdddc67945dc00a29b4fc801abad24c477b84587fe5b1d95fec541f8eefbe3742b1e37de709f8b4ebf342aaf3880e223f17c7cd2cd0513e0
6
+ metadata.gz: b15afc86cbfda8cda37ca17da233df0b68065e8f0f107f445fc8f495747e77fa3fd49de10ef21629729460b3c372ea24da2074d2fea2e8f420442ec969e38dd0
7
+ data.tar.gz: ca3fff59c7a87850892817b60603dfbb26663a8516a1a0806d7b8b887a81d1eca198656dc5bff6f94f39aafbcc3508f9bb5d35dfdfad8f48509a40c0adb31096
@@ -1,13 +1,15 @@
1
- class Storify::ApiError < StandardError
2
- attr_reader :status, :type, :message
1
+ module Storify
2
+ class ApiError < StandardError
3
+ attr_reader :status, :type, :message
3
4
 
4
- def initialize(status, message, type = nil)
5
- @type = type
6
- @status = status
7
- @message = message
8
- end
5
+ def initialize(status, message, type = nil)
6
+ @type = type
7
+ @status = status
8
+ @message = message
9
+ end
9
10
 
10
- def to_s
11
- "#{self.status} #{self.type} #{self.message}"
11
+ def to_s
12
+ "#{self.status} #{self.type} #{self.message}"
13
+ end
12
14
  end
13
15
  end
@@ -2,101 +2,128 @@ require 'json'
2
2
  require 'rest-client'
3
3
  #RestClient.log = './restclient.log'
4
4
 
5
- class Storify::Client
6
- attr_reader :api_key, :username, :token
5
+ module Storify
6
+ class Client
7
+ # define end of content example
8
+ EOC = {'content' => {'stories' => [], 'elements' => []}}
7
9
 
8
- def initialize(api_key, username)
9
- @api_key = api_key
10
- @username = username
11
- end
10
+ attr_reader :api_key, :username, :token
12
11
 
13
- def auth(password, options: {})
14
- endpoint = Storify::endpoint(version: options[:version], method: :auth)
15
- data = call(endpoint, :POST, {password: password})
16
- @token = data['content']['_token']
12
+ def initialize(api_key, username)
13
+ @api_key = api_key
14
+ @username = username
15
+ end
17
16
 
18
- self
19
- end
17
+ def auth(password, options: {})
18
+ endpoint = Storify::endpoint(version: options[:version], method: :auth)
19
+ data = call(endpoint, :POST, params: {password: password})
20
+ @token = data['content']['_token']
20
21
 
21
- def userstories(username = @username, pager: nil, options: {})
22
- endpoint = Storify::endpoint(version: options[:version],
23
- protocol: options[:protocol],
24
- method: :userstories,
25
- params: {':username' => username})
22
+ self
23
+ end
26
24
 
27
- pager = Storify::Pager.new unless pager.is_a?(Storify::Pager)
28
- stories = []
25
+ def stories(pager: nil, options: {})
26
+ story_list(:stories, pager, options: options, use_auth: false)
27
+ end
29
28
 
30
- begin
31
- data = call(endpoint, :GET, pager.to_hash)
32
- content = data['content']
29
+ def latest(pager: nil, options: {})
30
+ story_list(:latest, pager, options: options, use_auth: false)
31
+ end
33
32
 
34
- content['stories'].each do |s|
35
- stories << Storify::Story.new(s)
36
- end
33
+ def featured(pager: nil, options: {})
34
+ story_list(:featured, pager, options: options, use_auth: false)
35
+ end
37
36
 
38
- pager.next
39
- end while pager.has_pages?(content['stories'])
37
+ def popular(pager: nil, options: {})
38
+ story_list(:popular, pager, options: options, use_auth: false)
39
+ end
40
40
 
41
- stories
42
- end
41
+ def userstories(username = @username, pager: nil, options: {})
42
+ params = {':username' => username}
43
+ story_list(:userstories, pager, options: options, params: params)
44
+ end
43
45
 
44
- def story(slug, username = @username, pager: nil, options: {})
45
- params = {':username' => username, ':slug' => slug}
46
- endpoint = Storify::endpoint(version: options[:version],
47
- protocol: options[:protocol],
48
- method: :userstory,
49
- params: params)
46
+ def story(slug, username = @username, pager: nil, options: {})
47
+ params = {':username' => username, ':slug' => slug}
48
+ endpoint = Storify::endpoint(version: options[:version],
49
+ protocol: options[:protocol],
50
+ method: :userstory,
51
+ params: params)
50
52
 
51
- pager = Storify::Pager.new unless pager.is_a?(Storify::Pager)
52
- story = nil
53
- elements = []
53
+ pager = pager ||= Pager.new
54
54
 
55
- begin
56
- data = call(endpoint, :GET, pager.to_hash)
57
- story = Storify::Story.new(data['content']) if story.nil?
55
+ story = nil
56
+ elements = []
58
57
 
59
- # create elements
60
- data['content']['elements'].each do |e|
61
- story.add_element(Storify::Element.new(e))
62
- end
58
+ begin
59
+ data = call(endpoint, :GET, paging: pager.to_hash)
60
+ story = Story.new(data['content']) if story.nil?
63
61
 
64
- pager.next
65
- end while pager.has_pages?(data['content']['elements'])
62
+ # create elements
63
+ data['content']['elements'].each do |e|
64
+ story.add_element(Element.new(e))
65
+ end
66
66
 
67
- story
68
- end
67
+ pager.next
68
+ end while pager.has_pages?(data['content']['elements'])
69
69
 
70
- def authenticated
71
- !@token.nil?
72
- end
70
+ story
71
+ end
73
72
 
73
+ def authenticated
74
+ !@token.nil?
75
+ end
74
76
 
75
- private
76
77
 
77
- def call(endpoint, verb, params = {}, opts = {})
78
- raw = nil
78
+ private
79
79
 
80
- begin
81
- # inject auth params automatically (if available)
82
- params[:username] = @username
83
- params[:api_key] = @api_key
84
- params[:_token] = @token if authenticated
80
+ def story_list(method, pager, params: {}, options: {}, use_auth: true)
81
+ endpoint = Storify::endpoint(version: options[:version],
82
+ protocol: options[:protocol],
83
+ method: method,
84
+ params: params)
85
85
 
86
- case verb
87
- when :POST
88
- raw = RestClient.post endpoint, params, {:accept => :json}
89
- when :GET
90
- raw = RestClient.get endpoint, {:params => params}
91
- end
92
- rescue => e
93
- raw = e.response
86
+ pager = pager ||= Pager.new
87
+ stories = []
88
+
89
+ begin
90
+ data = call(endpoint, :GET, paging: pager.to_hash, use_auth: use_auth)
91
+ content = data['content']
94
92
 
95
- data = JSON.parse(e.response)
96
- error = data['error']
97
- raise Storify::ApiError.new(data['code'], error['message'], error['type'])
93
+ content['stories'].each do |s|
94
+ stories << Story.new(s)
95
+ end
96
+
97
+ pager.next
98
+ end while pager.has_pages?(content['stories'])
99
+
100
+ stories
98
101
  end
99
102
 
100
- JSON.parse(raw)
103
+ def call(endpoint, verb, params: {}, paging: {}, opts: {}, use_auth: true)
104
+ raw = nil
105
+
106
+ begin
107
+ # add paging and auth query params
108
+ params.merge!(paging)
109
+ params[:username] = @username
110
+ params[:api_key] = @api_key
111
+ params[:_token] = @token if (authenticated && use_auth)
112
+
113
+ case verb
114
+ when :POST
115
+ raw = RestClient.post endpoint, params, {:accept => :json}
116
+ when :GET
117
+ raw = RestClient.get endpoint, {:params => params}
118
+ end
119
+ rescue => e
120
+ data = JSON.parse(e.response)
121
+ error = data['error']
122
+
123
+ return Storify::error(data['code'], error['message'], error['type'], end_of_content: EOC)
124
+ end
125
+
126
+ JSON.parse(raw)
127
+ end
101
128
  end
102
129
  end
@@ -2,51 +2,53 @@ require 'date'
2
2
  require 'nokogiri'
3
3
 
4
4
  # todo: split logic into separate source types
5
- class Storify::Element
6
- attr_reader :type, :source, :link, :published, :author
7
- attr_accessor :desc
8
-
9
- def initialize(content)
10
- @type = content['type']
11
- @source = content['source']['name']
12
- @link = content['permalink']
13
- @published = DateTime.parse(content['posted_at'])
14
-
15
- case @type
16
- when 'image'
17
- @desc = content['data'][@type]['caption']
18
-
19
- if content['data'].has_key?('oembed')
20
- @author = content['data']['oembed']['author_name']
5
+ module Storify
6
+ class Storify::Element
7
+ attr_reader :type, :source, :link, :published, :author
8
+ attr_accessor :desc
9
+
10
+ def initialize(content)
11
+ @type = content['type']
12
+ @source = content['source']['name']
13
+ @link = content['permalink']
14
+ @published = DateTime.parse(content['posted_at'])
15
+
16
+ case @type
17
+ when 'image'
18
+ @desc = content['data'][@type]['caption']
19
+
20
+ if content['data'].has_key?('oembed')
21
+ @author = content['data']['oembed']['author_name']
22
+ else
23
+ @author = content['attribution']['name']
24
+ end
25
+ when 'text'
26
+ @desc = content['data']['text']
27
+
28
+ doc = Nokogiri::HTML(@desc)
29
+ @desc = doc.xpath("//text()").to_s
21
30
  else
22
- @author = content['attribution']['name']
31
+ @desc = content['data'][@type]['description']
32
+ @author = content['source']['username']
33
+ @author = "@" + @author if @source.downcase == 'twitter'
23
34
  end
24
- when 'text'
25
- @desc = content['data']['text']
26
-
27
- doc = Nokogiri::HTML(@desc)
28
- @desc = doc.xpath("//text()").to_s
29
- else
30
- @desc = content['data'][@type]['description']
31
- @author = content['source']['username']
32
- @author = "@" + @author if @source.downcase == 'twitter'
33
35
  end
34
- end
35
36
 
36
- def to_s
37
- out = ''
37
+ def to_s
38
+ out = ''
39
+ published = @published.to_date
38
40
 
39
- case @source.downcase
40
- when 'storify'
41
- out << "\n#{@desc}\n"
42
- out << ('-' * @desc.length) + "\n\n" if @desc.length < 50
43
- when 'twitter'
44
- out << "[#{@published.to_date.to_s}] #{@author}: #{@link}\n"
45
- else
41
+ case @source.downcase
42
+ when 'storify'
43
+ out << "\n#{@desc}\n"
44
+ out << ('-' * @desc.length) + "\n\n" if @desc.length < 50
45
+ when 'twitter'
46
+ out << "[#{@published.to_s}] #{@author}: #{@link}\n"
47
+ else
48
+ out << "#{@author} [#{@published.to_s}]: #{@link}\n"
49
+ end
46
50
 
47
- out << "#{@author} [#{@published.to_date.to_s}]: #{@link}\n"
51
+ out
48
52
  end
49
-
50
- out
51
53
  end
52
54
  end
data/lib/storify/pager.rb CHANGED
@@ -1,46 +1,48 @@
1
- class Storify::Pager
2
- MIN_PAGE = 1
3
- MAX_PER_PAGE = 50
1
+ module Storify
2
+ class Pager
3
+ MIN_PAGE = 1
4
+ MAX_PER_PAGE = 50
4
5
 
5
- attr_reader :page, :per_page, :max
6
+ attr_reader :page, :per_page, :max
6
7
 
7
- def initialize(page: 1, per_page: 20, max: 0)
8
- @max = max.to_i.abs
9
- self.page=(page)
10
- self.per_page=(per_page)
11
- end
8
+ def initialize(page: 1, per_page: 20, max: 0)
9
+ @max = max.to_i.abs
10
+ self.page=(page)
11
+ self.per_page=(per_page)
12
+ end
12
13
 
13
- def per_page=(value)
14
- @per_page = (value > MAX_PER_PAGE) ? MAX_PER_PAGE : value.to_i.abs
15
- end
14
+ def per_page=(value)
15
+ @per_page = (value > MAX_PER_PAGE) ? MAX_PER_PAGE : value.to_i.abs
16
+ end
16
17
 
17
- def next
18
- self.page=(@page + 1)
19
- self
20
- end
18
+ def next
19
+ self.page=(@page + 1)
20
+ self
21
+ end
21
22
 
22
- def prev
23
- self.page=(@page - 1)
24
- self
25
- end
23
+ def prev
24
+ self.page=(@page - 1)
25
+ self
26
+ end
26
27
 
27
- def to_hash
28
- {:page => @page, :per_page => @per_page}
29
- end
28
+ def to_hash
29
+ {:page => @page, :per_page => @per_page}
30
+ end
30
31
 
31
- def has_pages?(array = [])
32
- return false unless array.is_a?(Array)
33
- return false if (@page > @max && @max != 0)
32
+ def has_pages?(array = [])
33
+ return false unless array.is_a?(Array)
34
+ return false if (@page > @max && @max != 0)
34
35
 
35
- array.length != 0
36
- end
36
+ array.length != 0
37
+ end
37
38
 
38
- private
39
+ private
39
40
 
40
- def page=(value)
41
- return @page = MIN_PAGE if (value < MIN_PAGE)
42
- return @page = (@max + 1) if ((value > @max) && @max != 0)
41
+ def page=(value)
42
+ return @page = MIN_PAGE if (value < MIN_PAGE)
43
+ return @page = (@max + 1) if ((value > @max) && @max != 0)
43
44
 
44
- @page = value.to_i
45
+ @page = value.to_i
46
+ end
45
47
  end
46
48
  end
data/lib/storify/story.rb CHANGED
@@ -1,39 +1,41 @@
1
1
  require 'date'
2
2
 
3
- class Storify::Story
4
- attr_reader :slug, :title, :desc, :link, :published, :author, :elements
5
-
6
- def initialize(content)
7
- @slug = content['slug']
8
- @title = content['title']
9
- @desc = content['description']
10
- @link = content['permalink']
11
- @author = content['author']['username']
12
-
13
- unless content['date']['published'].nil?
14
- @published = DateTime.parse(content['date']['published'])
3
+ module Storify
4
+ class Story
5
+ attr_reader :slug, :title, :desc, :link, :published, :author, :elements
6
+
7
+ def initialize(content)
8
+ @slug = content['slug']
9
+ @title = content['title']
10
+ @desc = content['description']
11
+ @link = content['permalink']
12
+ @author = content['author']['username']
13
+
14
+ unless content['date']['published'].nil?
15
+ @published = DateTime.parse(content['date']['published'])
16
+ end
17
+
18
+ @elements = []
15
19
  end
16
20
 
17
- @elements = []
18
- end
19
-
20
- def add_element(element)
21
- @elements << element
22
- end
21
+ def add_element(element)
22
+ @elements << element
23
+ end
23
24
 
24
- def to_s
25
- published = @published.nil? ? 'unpublished' : @published.to_date.to_s
25
+ def to_s
26
+ published = @published.nil? ? 'unpublished' : @published.to_date
26
27
 
27
- out = "\n#{@title}\n"
28
- out << ('-' * @title.length.to_i) + "\n"
29
- out << "Date: #{published}\n"
30
- out << "Author: #{@author}\n"
31
- out << "Link: #{@link}\n"
32
- out << "\n#{@desc} \n"
28
+ out = "\n#{@title}\n"
29
+ out << ('-' * @title.length.to_i) + "\n"
30
+ out << "Date: #{published.to_s}\n"
31
+ out << "Author: #{@author}\n"
32
+ out << "Link: #{@link}\n"
33
+ out << "\n#{@desc} \n"
33
34
 
34
- # serialize elements
35
- elements.each {|e| out << e.to_s }
35
+ # serialize elements
36
+ elements.each {|e| out << e.to_s }
36
37
 
37
- out
38
+ out
39
+ end
38
40
  end
39
41
  end
data/lib/storify.rb CHANGED
@@ -8,8 +8,12 @@ module Storify
8
8
  :v1 => {
9
9
  :base => 'api.storify.com/v1',
10
10
  :auth => '/auth',
11
+ :stories => '/stories',
11
12
  :userstories => '/stories/:username',
12
- :userstory => '/stories/:username/:slug'
13
+ :userstory => '/stories/:username/:slug',
14
+ :latest => '/stories/browse/latest',
15
+ :featured => '/stories/browse/featured',
16
+ :popular => '/stories/browse/popular'
13
17
  }
14
18
  }
15
19
 
@@ -26,6 +30,14 @@ module Storify
26
30
 
27
31
  uri
28
32
  end
33
+
34
+ def self.error(code, message, type, end_of_content: {})
35
+ unless message.downcase.include?('max')
36
+ raise Storify::ApiError.new(code, message, type)
37
+ end
38
+
39
+ end_of_content
40
+ end
29
41
  end
30
42
 
31
43
  require 'storify/story'
@@ -0,0 +1,71 @@
1
+ require 'spec_helper'
2
+
3
+ # These methods did not work with authentication,
4
+ # so they have been forced to not use the auth token
5
+
6
+ describe "Storify::Client -- Unauthenticated" do
7
+ before(:each) do
8
+ @client = Storify::Client.new(@api_key, @username)
9
+ @options = {:version => :v1, :protocol => :insecure}
10
+ end
11
+
12
+ context "GET /stories" do
13
+ it "should get all stories until the maximum" do
14
+ @client.stories.length.should > 400
15
+ end
16
+
17
+ it "should accept endpoint options (version, protocol)" do
18
+ @client.stories(options: @options).length.should > 400
19
+ end
20
+
21
+ it "should accept paging options (Pager)" do
22
+ pager = Storify::Pager.new(page: 1, max: 2, per_page: 20)
23
+ @client.stories(pager: pager).length.should == 40
24
+ end
25
+ end
26
+
27
+ context "GET /stories/browse/latest" do
28
+ it "should get all the latest stories until the maximum" do
29
+ @client.latest.length.should > 400
30
+ end
31
+
32
+ it "should accept endpoint options (version, protocol)" do
33
+ @client.latest(options: @options).length > 400
34
+ end
35
+
36
+ it "should get the top 20 stories" do
37
+ pager = Storify::Pager.new(page: 1, max: 1, per_page: 20)
38
+ @client.latest(pager: pager).length.should == 20
39
+ end
40
+ end
41
+
42
+ context "GET /stories/browse/featured" do
43
+ it "should get all the featured stories until the maximum" do
44
+ @client.featured.length.should > 400
45
+ end
46
+
47
+ it "should accept endpoint options (version, protocol)" do
48
+ @client.featured(options: @options).length > 400
49
+ end
50
+
51
+ it "should get the top 20 featured stories" do
52
+ pager = Storify::Pager.new(page: 1, max: 1, per_page: 20)
53
+ @client.featured(pager: pager).length.should == 20
54
+ end
55
+ end
56
+
57
+ context "GET /stories/browse/popular" do
58
+ it "should get all the popular stories until the maximum" do
59
+ @client.popular.length.should > 400
60
+ end
61
+
62
+ it "should accept endpoint options (version, protocol)" do
63
+ @client.popular(options: @options).length > 400
64
+ end
65
+
66
+ it "should get the top 15 popular stories" do
67
+ p = Storify::Pager.new(page: 1, max: 1, per_page: 15)
68
+ @client.popular(pager: p).length.should == 15
69
+ end
70
+ end
71
+ end
data/spec/storify_spec.rb CHANGED
@@ -38,6 +38,22 @@ describe Storify do
38
38
  Storify::ENDPOINTS[:v1][:auth].should == "/auth"
39
39
  end
40
40
 
41
+ it "should support the Stories endpoint" do
42
+ Storify::ENDPOINTS[:v1][:stories].should == "/stories"
43
+ end
44
+
45
+ it "should support the Latest Stories endpoint" do
46
+ Storify::ENDPOINTS[:v1][:latest].should == "/stories/browse/latest"
47
+ end
48
+
49
+ it "should support the Featured Stories endpoint" do
50
+ Storify::ENDPOINTS[:v1][:featured].should == "/stories/browse/featured"
51
+ end
52
+
53
+ it "should support the Popular Stories endpoint" do
54
+ Storify::ENDPOINTS[:v1][:popular].should == "/stories/browse/popular"
55
+ end
56
+
41
57
  it "should support the User Stories endpoint" do
42
58
  Storify::ENDPOINTS[:v1][:userstories].should == "/stories/:username"
43
59
  end
@@ -76,4 +92,17 @@ describe Storify do
76
92
  uri.should == 'http://api.storify.com/v1/stories/rtejpar'
77
93
  end
78
94
  end
95
+
96
+ context "API v1 Error Handling" do
97
+ it "should return an empty content block (if api max reached)" do
98
+ eoc = Storify::Client::EOC
99
+ content = Storify::error(400, '...Max...', 'bad request', end_of_content: eoc)
100
+ content.should == eoc
101
+ end
102
+
103
+ it "should return an API error for a non-max case" do
104
+ eoc = Storify::Client::EOC
105
+ expect{Storify::error(400, '...', 'bad request', end_of_content: eoc)}.to raise_error(Storify::ApiError)
106
+ end
107
+ end
79
108
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: storify
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.7
4
+ version: 0.0.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Rizwan Tejpar
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-12-11 00:00:00.000000000 Z
11
+ date: 2013-12-12 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: json
@@ -93,6 +93,7 @@ files:
93
93
  - lib/storify/story.rb
94
94
  - lib/storify.rb
95
95
  - spec/client_auth_spec.rb
96
+ - spec/client_noauth_spec.rb
96
97
  - spec/client_spec.rb
97
98
  - spec/pager_spec.rb
98
99
  - spec/spec_helper.rb
@@ -123,6 +124,7 @@ specification_version: 4
123
124
  summary: Storify API
124
125
  test_files:
125
126
  - spec/client_auth_spec.rb
127
+ - spec/client_noauth_spec.rb
126
128
  - spec/client_spec.rb
127
129
  - spec/pager_spec.rb
128
130
  - spec/spec_helper.rb