read_it_later 0.2.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/.gitignore ADDED
@@ -0,0 +1 @@
1
+ config/test.yml
data/README.textile ADDED
@@ -0,0 +1,7 @@
1
+ h1. ReadItLater API Library for Ruby
2
+
3
+ p. Please see sample_usage.rb for examples of use.
4
+
5
+ p. For details on the ReadItLater API see http://readitlaterlist.com/api/docs/
6
+
7
+ p. For details on what is ReadItLater see http://readitlaterlist.com/
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "read_it_later"
5
+ gemspec.summary = "ReadItLaterList.com API Library for Ruby"
6
+ gemspec.description = "A very simple one-to-one api library for Read It Later API"
7
+ gemspec.email = "rha7.com@gmail.com"
8
+ gemspec.homepage = "http://github.com/rha7dotcom/read_it_later"
9
+ gemspec.authors = ["Gabriel Medina"]
10
+ end
11
+ rescue LoadError
12
+ puts "Jeweler not available. Install it with: gem install jeweler"
13
+ end
14
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.2.0
@@ -0,0 +1 @@
1
+ default: --format pretty --color features
@@ -0,0 +1,3 @@
1
+ :api_key: <Your Read It Later API Key Here>
2
+ :username: <Your user name>
3
+ :password: <Your password>
@@ -0,0 +1,69 @@
1
+ Feature: Read It Later Management
2
+ In order to manage a list of bookmarks from read it later lists,
3
+ I should be able to add, get and mark as read bookmarks.
4
+
5
+ Scenario: Add a new bookmark
6
+ Given I have a valid API Key and User
7
+ When I create a ReadItLater API Object
8
+ And I add a new bookmark
9
+ Then I should get back a success response from RIL server
10
+ And I should receive usual user and key limits
11
+
12
+ Scenario: Send several updates at once
13
+ Given I have a valid API Key and User
14
+ When I create a ReadItLater API Object
15
+ And I send several updates
16
+ Then I should get back a success response from RIL server
17
+ And I should receive usual user and key limits
18
+
19
+ Scenario: Request statistics of Read It Later bookmarks
20
+ Given I have a valid API Key and User
21
+ When I create a ReadItLater API Object
22
+ And I send a statistics request
23
+ Then I should get back a success response from RIL server
24
+ And I should receive usual user and key limits
25
+ And I should receive statistics of usage
26
+
27
+ Scenario Outline: Get a list of bookmarks from Read It Later
28
+ Given I have a valid API Key and User
29
+ When I create a ReadItLater API Object
30
+ And I send a request for a list of "<count>" "<state>" Read It Later bookmarks for page "<page>", which are "<mine_only>", since "<since>", with tags "<tags>"
31
+ Then I should get back a success response from RIL server
32
+ And I should receive data about the list of bookmarks
33
+ And I should receive a list of bookmarks, although it can be empty
34
+
35
+ Examples:
36
+ | state | mine_only | since | count | page | tags |
37
+ | read | | | | | |
38
+ | unread | | | | | |
39
+ | | true | | | | |
40
+ | | false | | | | |
41
+ | | | 2000-01-01 | | | |
42
+ | | | | 10 | | |
43
+ | | | | 10 | 2 | |
44
+ | | | | | | true |
45
+ | | | | | | false |
46
+
47
+ Scenario: Authenticate an existing user
48
+ Given I have a valid API Key and User
49
+ When I create a ReadItLater API Object
50
+ And I authenticate an existing user
51
+ Then I should get back a success response from RIL server
52
+ And I should receive usual user and key limits
53
+
54
+ Scenario:Sign up a new user
55
+ Given I have a valid API Key and User
56
+ When I create a ReadItLater API Object
57
+ And I sign up a new user
58
+ Then I should get back a success response from RIL server
59
+ And I should receive usual user and key limits
60
+
61
+ Scenario: Get bookmark list statistics
62
+ Given I have a valid API Key and User
63
+ When I create a ReadItLater API Object
64
+ And I send an API bookmarks list statistics request
65
+ Then I should get back a success response from RIL server
66
+ And I should receive usual user and key limits
67
+
68
+
69
+
@@ -0,0 +1,24 @@
1
+ Feature: ReadItLater User Management
2
+ In order to make requests to ReadItLaterList.com API
3
+ Library user should be able to create User objects.
4
+
5
+ Scenario: User object created with both a user name and a password
6
+ When I create a User object with a user name "sample" and password "mypassword"
7
+ Then I should get a User object with no errors
8
+ And The User object should have a "user name" of "sample"
9
+ And The User object should have a "password" of "mypassword"
10
+
11
+ Scenario: User object created with a user name only
12
+ When I create a User object with a user name "sample" and password "unspecified"
13
+ Then I should get a User object with no errors
14
+ And The User object should have a "user name" of "sample"
15
+ And The User object should have a "password" of "unspecified"
16
+
17
+ Scenario: User object created without a user name or password
18
+ When I create a User object with a user name "unspecified" and password "unspecified"
19
+ Then I should get a User object with no errors
20
+ And The User object should have a "user name" of "unspecified"
21
+ And The User object should have a "password" of "unspecified"
22
+
23
+
24
+
@@ -0,0 +1,101 @@
1
+ require 'yaml'
2
+ require 'erb'
3
+ require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'read_it_later')
4
+
5
+ CONFIG=YAML.load(ERB.new(File.open(File.join(File.dirname(__FILE__), '..', '..', 'config', 'test.yml')).read).result)
6
+
7
+ Given /^I have a valid API Key and User$/ do
8
+ @api_key = CONFIG[:api_key]
9
+ @username = CONFIG[:username]
10
+ @password = CONFIG[:password]
11
+ end
12
+
13
+ When /^I create a ReadItLater API Object$/ do
14
+ @ril = ReadItLater.new(@api_key)
15
+ @usr = ReadItLater::User.new(@username, @password)
16
+ end
17
+
18
+ When /^I add a new bookmark$/ do
19
+ @response = @ril.add(@usr, "http://www.google.com/search?q=#{rand(999999)}")
20
+ end
21
+
22
+ When /^I send several updates$/ do
23
+ @response = @ril.send(@usr,
24
+ :new => [
25
+ { :url => "http://www.url1.com/", :title => "URL New 1" },
26
+ { :url => "http://www.url2.com/", :title => "URL New 2" },
27
+ { :url => "http://www.url3.com/", :title => "URL New 3" }
28
+ ],
29
+ :read => [
30
+ { :url => "http://www.url1.com/" },
31
+ { :url => "http://www.url2.com/" },
32
+ { :url => "http://www.url3.com/" }
33
+ ],
34
+ :update_title => [
35
+ { :url => "http://www.url1.com/", :title => "Updated URL New 1" },
36
+ { :url => "http://www.url2.com/", :title => "Updated URL New 2" },
37
+ { :url => "http://www.url3.com/", :title => "Updated URL New 3" }
38
+ ],
39
+ :update_tags => [
40
+ { :url => "http://www.url1.com/", :tags => "url1tag1, url1tag2, url1tag3" },
41
+ { :url => "http://www.url2.com/", :tags => "url2tag1, url2tag2, url2tag3" },
42
+ { :url => "http://www.url3.com/", :tags => "url3tag1, url3tag2, url3tag3" }
43
+ ]
44
+ )
45
+ end
46
+
47
+ When /^I send a statistics request$/ do
48
+ @response = @ril.stats(@usr)
49
+ end
50
+
51
+ When /^I send a request for a list of "([^\"]*)" "([^\"]*)" Read It Later bookmarks for page "([^\"]*)", which are "([^\"]*)", since "([^\"]*)", with tags "([^\"]*)"$/ do |count, state, page, mine_only, since, tags|
52
+ params = {}
53
+ params[:state] = state.to_sym unless state.empty? if state
54
+ params[:count] = count.to_i unless count.empty? if count
55
+ params[:page] = page.to_i unless page.empty? if page
56
+ params[:mine_only] = eval(mine_only) unless mine_only.empty? if mine_only
57
+ params[:tags] = eval(tags) unless tags.empty? if tags
58
+ params[:since] = Time.parse(since) unless since.empty? if since
59
+ @response = @ril.get(@usr, params)
60
+ end
61
+
62
+ When /^I authenticate an existing user$/ do
63
+ @response = @ril.auth(@usr)
64
+ end
65
+
66
+ When /^I send an API bookmarks list statistics request$/ do
67
+ @response = @ril.api
68
+ end
69
+
70
+ When /^I sign up a new user$/ do
71
+ @response = @ril.api
72
+ end
73
+
74
+ Then /^I should get back a success response from RIL server$/ do
75
+ @response[:status].should == ReadItLater::STATUS_SUCCESS
76
+ end
77
+
78
+ Then /^I should receive usual user and key limits$/ do
79
+ @response.has_key?(:key).should be_true
80
+ @response.has_key?(:user).should be_true
81
+ @response.has_key?(:text).should be_true
82
+ @response.has_key?(:status).should be_true
83
+ end
84
+
85
+ Then /^I should receive statistics of usage$/ do
86
+ @response.has_key?(:data).should be_true
87
+ @response[:data].has_key?(:user_since).should be_true
88
+ @response[:data].has_key?(:count_unread).should be_true
89
+ @response[:data].has_key?(:count_read).should be_true
90
+ @response[:data].has_key?(:count_list).should be_true
91
+ end
92
+
93
+ Then /^I should receive data about the list of bookmarks$/ do
94
+ @response.should have_key(:data)
95
+ end
96
+
97
+ Then /^I should receive a list of bookmarks, although it can be empty$/ do
98
+ @response[:data].should have_key(:list)
99
+ end
100
+
101
+
@@ -0,0 +1,35 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'lib', 'read_it_later')
2
+
3
+ When /^I create a User object with a user name "([^\"]*)" and password "([^\"]*)"$/ do |username, password|
4
+ @username = (username == "unspecified" ? nil : username)
5
+ @password = (password == "unspecified" ? nil : password)
6
+ end
7
+
8
+ Then /^I should get a User object with no errors$/ do
9
+ lambda {
10
+ if @username and @password
11
+ @user = ReadItLater::User.new(@username, @password)
12
+ elsif @username
13
+ @user = ReadItLater::User.new(@username)
14
+ else
15
+ @user = ReadItLater::User.new
16
+ end
17
+ }.should_not raise_error
18
+ end
19
+
20
+ Then /^The User object should have a "([^\"]*)" of "([^\"]*)"$/ do |field_name, value|
21
+ if field_name == "user name"
22
+ if value == "unspecified"
23
+ @user.username.should be_nil
24
+ else
25
+ @user.username.should == value
26
+ end
27
+ else
28
+ if value == "unspecified"
29
+ @user.password.should be_nil
30
+ else
31
+ @user.password.should == value
32
+ end
33
+ end
34
+ end
35
+
@@ -0,0 +1,2 @@
1
+ require 'spec/expectations'
2
+
@@ -0,0 +1,132 @@
1
+ require 'open-uri'
2
+ require 'json'
3
+
4
+ class ReadItLater
5
+
6
+ STATUS_SUCCESS = 200
7
+ STATUS_INVALID = 400
8
+ STATUS_DENIED = 401
9
+ STATUS_EXCEEDED = 403
10
+ STATUS_MAINTENANCE = 503
11
+
12
+ URL_BASE = 'https://readitlaterlist.com/v2'
13
+ URLS = {
14
+ :add => ReadItLater::URL_BASE+'/add' ,
15
+ :send => ReadItLater::URL_BASE+'/send' ,
16
+ :stats => ReadItLater::URL_BASE+'/stats' ,
17
+ :get => ReadItLater::URL_BASE+'/get' ,
18
+ :auth => ReadItLater::URL_BASE+'/auth' ,
19
+ :signup => ReadItLater::URL_BASE+'/signup',
20
+ :api => ReadItLater::URL_BASE+'/api'
21
+ }
22
+
23
+ attr_reader :last_response
24
+
25
+ class User
26
+ attr_accessor :username, :password
27
+ def initialize(username=nil, password=nil)
28
+ @username, @password, @last_response = username, password, ""
29
+ end
30
+ end
31
+
32
+ attr_accessor :api_key
33
+
34
+ def initialize(api_key)
35
+ @api_key = api_key
36
+ end
37
+
38
+ def add(user, url)
39
+ @last_response = query(:add, user, :url => url)
40
+ end
41
+
42
+ def send(user, params)
43
+ %w(new read update_title update_tags).map(&:to_sym).each do |param|
44
+ params[param] = URI.escape((0..params[param].size-1).to_a.map{|n|{n.to_s=>params[param][n]}}.inject(){|a,b|a.merge(b)}.to_json) if params[param]
45
+ end
46
+ @last_response = query(:send, user, params)
47
+ end
48
+
49
+ def stats(user)
50
+ response = query(:stats, user, :format => "json")
51
+ response[:data] = stringify_keys(JSON.parse(response[:text]))
52
+ response[:data][:user_since] = Time.at(response[:data][:user_since].to_i)
53
+ @last_response = response
54
+ end
55
+
56
+ def get(user, call_params)
57
+ params = { :format => "json" }
58
+ params[:state] = call_params[:state].to_s.strip if call_params[:state]
59
+ params[:myAppOnly] = (call_params[:mine_only] ? "1" : "0") if call_params[:mine_only]
60
+ params[:since] = call_params[:since].to_i if call_params[:since]
61
+ params[:count] = call_params[:count] if call_params[:count]
62
+ params[:page] = call_params[:page] if call_params[:page]
63
+ params[:tags] = (call_params[:tags] ? "1" : "0") if call_params[:tags]
64
+ response = query(:get, user, params)
65
+ response[:data] = stringify_keys(JSON.parse(response[:text]))
66
+ response[:data][:since] = Time.at(response[:data][:since])
67
+ response[:data][:status] = response[:data][:status] == 1 ? :normal : :no_changes
68
+ response[:data][:list] = response[:data][:list].map{|k,v|v.merge(:time_added => Time.at(v[:time_added].to_i), :time_updated => Time.at(v[:time_updated].to_i), :item_id => v[:item_id].to_i, :read => (v[:state].strip == "0")).delete_if{|k,v|k==:state}}
69
+ @last_response = response
70
+ end
71
+
72
+ def auth(user)
73
+ @last_reponse = query(:auth, user)
74
+ end
75
+
76
+ def signup(user)
77
+ @last_reponse = query(:signup, user)
78
+ end
79
+
80
+ def api
81
+ @last_response = query(:api, User.new('',''))
82
+ end
83
+
84
+ private
85
+
86
+ def ril_api_url(method, user, params={})
87
+ params = { :apikey => @api_key, :username => user.username, :password => user.password }.merge(params)
88
+ query_str = URLS[method] + "?" + params.map{|k,v| "#{k.to_s}=#{URI.escape(v.to_s)}" }.join("&")
89
+ return query_str
90
+ end
91
+
92
+ def unique_id
93
+ return (1..24).to_a.map{|i|(('a'..'z').to_a+('0'..'9').to_a)[rand(36)]}.join
94
+ end
95
+
96
+ def query(method, user, params={})
97
+ response = nil
98
+ begin
99
+ open(ril_api_url(method, user, params)) do |f|
100
+ response = build_response(f)
101
+ end
102
+ rescue OpenURI::HTTPError => e
103
+ response = build_response(e.io)
104
+ end
105
+ return response
106
+ end
107
+
108
+ def build_response(io_object)
109
+ return {
110
+ :text => io_object.read.strip,
111
+ :status => io_object.meta["status"].split[0].strip.to_i,
112
+ :user => {
113
+ :limit => (io_object.meta["x-limit-user-limit" ] || "-1").to_i,
114
+ :remaining => (io_object.meta["x-limit-user-remaining"] || "-1").to_i,
115
+ :reset => (io_object.meta["x-limit-user-reset" ] || "-1").to_i
116
+ },
117
+ :key => {
118
+ :limit => (io_object.meta["x-limit-key-limit" ] || "-1").to_i,
119
+ :remaining => (io_object.meta["x-limit-key-remaining" ] || "-1").to_i,
120
+ :reset => (io_object.meta["x-limit-key-reset" ] || "-1").to_i
121
+ },
122
+ :error => io_object.meta["x-error"]
123
+ }
124
+ end
125
+
126
+ def stringify_keys(hsh)
127
+ hsh.map{|k,v|{k.to_sym => (v.class == Hash ? stringify_keys(v) : v)}}.inject(){|a,b|a.merge(b)}
128
+ end
129
+
130
+ end
131
+
132
+
@@ -0,0 +1,50 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{read_it_later}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Gabriel Medina"]
12
+ s.date = %q{2010-02-15}
13
+ s.description = %q{A very simple one-to-one api library for Read It Later API}
14
+ s.email = %q{rha7.com@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "README.textile"
17
+ ]
18
+ s.files = [
19
+ ".gitignore",
20
+ "README.textile",
21
+ "Rakefile",
22
+ "VERSION",
23
+ "config/cucumber.yml",
24
+ "config/test.yml.dist",
25
+ "features/read_it_later.feature",
26
+ "features/read_it_later_users.feature",
27
+ "features/step_definitions/read_it_later_steps.rb",
28
+ "features/step_definitions/read_it_later_user_steps.rb",
29
+ "features/support/env.rb",
30
+ "lib/read_it_later.rb",
31
+ "read_it_later.gemspec",
32
+ "sample_usage.rb"
33
+ ]
34
+ s.homepage = %q{http://github.com/rha7dotcom/read_it_later}
35
+ s.rdoc_options = ["--charset=UTF-8"]
36
+ s.require_paths = ["lib"]
37
+ s.rubygems_version = %q{1.3.5}
38
+ s.summary = %q{ReadItLaterList.com API Library for Ruby}
39
+
40
+ if s.respond_to? :specification_version then
41
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
42
+ s.specification_version = 3
43
+
44
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
45
+ else
46
+ end
47
+ else
48
+ end
49
+ end
50
+
data/sample_usage.rb ADDED
@@ -0,0 +1,64 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ require "lib/read_it_later"
4
+
5
+ ril = ReadItLater.new("<Your ReadItLater API Key Here>")
6
+ usr = ReadItLater::User.new('SomeUserName', 'SomeUserPass')
7
+
8
+ # Add method
9
+ # ===================================================================================
10
+ # pp ril.add(usr, "http://www.google.com/search?q=add+to+ril")
11
+
12
+ # Send method
13
+ # ===================================================================================
14
+ # pp ril.send(usr,
15
+ # :new => [
16
+ # { :url => "http://www.url1.com/", :title => "URL New 1" },
17
+ # { :url => "http://www.url2.com/", :title => "URL New 2" },
18
+ # { :url => "http://www.url3.com/", :title => "URL New 3" }
19
+ # ],
20
+ # :read => [
21
+ # { :url => "http://www.url1.com/" },
22
+ # { :url => "http://www.url2.com/" },
23
+ # { :url => "http://www.url3.com/" }
24
+ # ],
25
+ # :update_title => [
26
+ # { :url => "http://www.url1.com/", :title => "Updated URL New 1" },
27
+ # { :url => "http://www.url2.com/", :title => "Updated URL New 2" },
28
+ # { :url => "http://www.url3.com/", :title => "Updated URL New 3" }
29
+ # ],
30
+ # :update_tags => [
31
+ # { :url => "http://www.url1.com/", :tags => "url1tag1, url1tag2, url1tag3" },
32
+ # { :url => "http://www.url2.com/", :tags => "url2tag1, url2tag2, url2tag3" },
33
+ # { :url => "http://www.url3.com/", :tags => "url3tag1, url3tag2, url3tag3" }
34
+ # ]
35
+ # )
36
+
37
+ # Stats method
38
+ # ===================================================================================
39
+ # pp ril.stats(usr)
40
+
41
+ # Get method
42
+ # ===================================================================================
43
+ # pp ril.get(usr,
44
+ # :state => :unread,
45
+ # :mine_only => false,
46
+ # :since => (Time.now-30*24*60*60),
47
+ # :count => 10,
48
+ # :page => 2,
49
+ # :tags => false)
50
+
51
+ # Auth method
52
+ # ===================================================================================
53
+ # pp ril.auth(usr)
54
+
55
+ # Sign Up method
56
+ # ===================================================================================
57
+ # pp ril.auth(usr)
58
+
59
+ # API method
60
+ # ===================================================================================
61
+ # pp ril.api
62
+
63
+
64
+
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: read_it_later
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Gabriel Medina
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2010-02-15 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies: []
15
+
16
+ description: A very simple one-to-one api library for Read It Later API
17
+ email: rha7.com@gmail.com
18
+ executables: []
19
+
20
+ extensions: []
21
+
22
+ extra_rdoc_files:
23
+ - README.textile
24
+ files:
25
+ - .gitignore
26
+ - README.textile
27
+ - Rakefile
28
+ - VERSION
29
+ - config/cucumber.yml
30
+ - config/test.yml.dist
31
+ - features/read_it_later.feature
32
+ - features/read_it_later_users.feature
33
+ - features/step_definitions/read_it_later_steps.rb
34
+ - features/step_definitions/read_it_later_user_steps.rb
35
+ - features/support/env.rb
36
+ - lib/read_it_later.rb
37
+ - read_it_later.gemspec
38
+ - sample_usage.rb
39
+ has_rdoc: true
40
+ homepage: http://github.com/rha7dotcom/read_it_later
41
+ licenses: []
42
+
43
+ post_install_message:
44
+ rdoc_options:
45
+ - --charset=UTF-8
46
+ require_paths:
47
+ - lib
48
+ required_ruby_version: !ruby/object:Gem::Requirement
49
+ requirements:
50
+ - - ">="
51
+ - !ruby/object:Gem::Version
52
+ version: "0"
53
+ version:
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ version: "0"
59
+ version:
60
+ requirements: []
61
+
62
+ rubyforge_project:
63
+ rubygems_version: 1.3.5
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: ReadItLaterList.com API Library for Ruby
67
+ test_files: []
68
+