google_reader 1.1.0 → 1.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.textile +6 -0
- data/lib/google_reader/client.rb +19 -8
- data/lib/google_reader/entry.rb +0 -2
- data/lib/google_reader/feed.rb +39 -0
- data/lib/google_reader/version.rb +1 -1
- data/lib/google_reader.rb +3 -0
- data/spec/client_spec.rb +27 -10
- data/spec/feed_spec.rb +23 -0
- data/spec/fixtures/entry.xml +9 -0
- metadata +4 -1
data/README.textile
CHANGED
@@ -37,6 +37,12 @@ p item.author
|
|
37
37
|
p item.source
|
38
38
|
p item.liking_users
|
39
39
|
p item.summary
|
40
|
+
|
41
|
+
# You may also get feed objects back, which then allow you to query "since" a time
|
42
|
+
feed = client.read_feed
|
43
|
+
cutoff_at = feed.updated_at
|
44
|
+
sleep 30
|
45
|
+
client.read_feed(:since => cutoff_at) # Only new items since that cutoff time
|
40
46
|
</code></pre>
|
41
47
|
|
42
48
|
h2. Ruby Library
|
data/lib/google_reader/client.rb
CHANGED
@@ -54,11 +54,27 @@ module GoogleReader
|
|
54
54
|
tracking-item-link-used
|
55
55
|
tracking-body-link-used).each do |suffix|
|
56
56
|
|
57
|
+
method_name = suffix.gsub("-", "_") + "_feed"
|
58
|
+
define_method(method_name) do |*args|
|
59
|
+
options = args.first || Hash.new
|
60
|
+
params = Hash.new
|
61
|
+
params[:n] = options[:count] || 20
|
62
|
+
if options.has_key?(:since) then
|
63
|
+
params[:r] = "o"
|
64
|
+
params[:ot] = options[:since].to_i
|
65
|
+
end
|
66
|
+
|
67
|
+
str_params = params.map do |k, v|
|
68
|
+
CGI.escape(k.to_s) << "=" << CGI.escape(v.to_s)
|
69
|
+
end.join("&")
|
70
|
+
|
71
|
+
content = RestClient.get(STATE_URL + suffix + "?#{str_params}", headers)
|
72
|
+
Feed.new( Nokogiri::XML(content) )
|
73
|
+
end
|
74
|
+
|
57
75
|
method_name = suffix.gsub("-", "_") + "_items"
|
58
76
|
define_method(method_name) do |*args|
|
59
|
-
|
60
|
-
content = RestClient.get(STATE_URL + suffix + "?n=#{CGI.escape(count.to_s)}", headers)
|
61
|
-
parse_atom_feed(content)
|
77
|
+
__send__(method_name.sub("_items", "_feed"), *args).entries
|
62
78
|
end
|
63
79
|
end
|
64
80
|
|
@@ -66,10 +82,5 @@ module GoogleReader
|
|
66
82
|
content = RestClient.get(STATE_URL + suffix + "?n=#{CGI.escape(count.to_s)}&xt=#{CGI.escape("state/com.google/read")}", headers)
|
67
83
|
parse_atom_feed(content)
|
68
84
|
end
|
69
|
-
|
70
|
-
def parse_atom_feed(feed)
|
71
|
-
doc = Nokogiri::XML(feed)
|
72
|
-
doc.search("entry").map {|entry| Entry.new(entry)}
|
73
|
-
end
|
74
85
|
end
|
75
86
|
end
|
data/lib/google_reader/entry.rb
CHANGED
@@ -0,0 +1,39 @@
|
|
1
|
+
require "time"
|
2
|
+
|
3
|
+
module GoogleReader
|
4
|
+
class Feed
|
5
|
+
attr_reader :feed
|
6
|
+
|
7
|
+
def initialize(feed)
|
8
|
+
@feed = feed
|
9
|
+
end
|
10
|
+
|
11
|
+
def entries
|
12
|
+
@entries ||= @feed.search("entry").map {|entry| Entry.new(entry)}
|
13
|
+
end
|
14
|
+
|
15
|
+
def id
|
16
|
+
@feed.search("id").first.text
|
17
|
+
end
|
18
|
+
|
19
|
+
def updated_at
|
20
|
+
Time.parse( @feed.search("updated").first.text )
|
21
|
+
end
|
22
|
+
|
23
|
+
def continuation
|
24
|
+
@feed.search("gr:continuation", "gr" => GoogleReader::GOOGLE_ATOM_NAMESPACE).first.text
|
25
|
+
end
|
26
|
+
|
27
|
+
def title
|
28
|
+
@feed.search("title").first.text
|
29
|
+
end
|
30
|
+
|
31
|
+
def href
|
32
|
+
@feed.search("link[rel=self]").first["href"]
|
33
|
+
end
|
34
|
+
|
35
|
+
def author
|
36
|
+
@feed.search("author name").first.text
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
data/lib/google_reader.rb
CHANGED
@@ -1,5 +1,8 @@
|
|
1
1
|
module GoogleReader
|
2
2
|
autoload :Client, "google_reader/client"
|
3
3
|
autoload :Source, "google_reader/source"
|
4
|
+
autoload :Feed, "google_reader/feed"
|
4
5
|
autoload :Entry, "google_reader/entry"
|
6
|
+
|
7
|
+
GOOGLE_ATOM_NAMESPACE = "http://www.google.com/schemas/reader/atom/".freeze
|
5
8
|
end
|
data/spec/client_spec.rb
CHANGED
@@ -2,7 +2,7 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe GoogleReader::Client, "#authenticate" do
|
4
4
|
it "should immediately authenticate using Google's client login" do
|
5
|
-
RestClient.should_receive(:post).and_return("
|
5
|
+
RestClient.should_receive(:post).and_return("a=b\nAuth=my-fancy-token\nb=c")
|
6
6
|
GoogleReader::Client.authenticate("abc", "123")
|
7
7
|
end
|
8
8
|
|
@@ -12,8 +12,8 @@ describe GoogleReader::Client, "#authenticate" do
|
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should instantiate a new GoogleReader::Client instance with the correct authentication header" do
|
15
|
-
RestClient.stub(:post).and_return("
|
16
|
-
GoogleReader::Client.should_receive(:new).with(
|
15
|
+
RestClient.stub(:post).and_return("a=b\nAuth=my-fancy-token\nb=c")
|
16
|
+
GoogleReader::Client.should_receive(:new).with("my-fancy-token")
|
17
17
|
GoogleReader::Client.authenticate("a", "b")
|
18
18
|
end
|
19
19
|
end
|
@@ -34,7 +34,7 @@ describe GoogleReader::Client do
|
|
34
34
|
|
35
35
|
it "should fetch the requested number of items from #read_items" do
|
36
36
|
RestClient.should_receive(:get).with("http://www.google.com/reader/atom/user/-/state/com.google/read?n=59", anything).and_return(xml_content)
|
37
|
-
subject.read_items(59)
|
37
|
+
subject.read_items(:count => 59)
|
38
38
|
end
|
39
39
|
|
40
40
|
it "should fetch the default 20 items from #broadcast_items" do
|
@@ -44,7 +44,7 @@ describe GoogleReader::Client do
|
|
44
44
|
|
45
45
|
it "should fetch the requested number of items from #broadcast_items" do
|
46
46
|
RestClient.should_receive(:get).with("http://www.google.com/reader/atom/user/-/state/com.google/broadcast?n=59", anything).and_return(xml_content)
|
47
|
-
subject.broadcast_items(59)
|
47
|
+
subject.broadcast_items(:count => 59)
|
48
48
|
end
|
49
49
|
|
50
50
|
it "should fetch the default 20 items from #starred_items" do
|
@@ -54,7 +54,7 @@ describe GoogleReader::Client do
|
|
54
54
|
|
55
55
|
it "should fetch the requested number of items from #starred_items" do
|
56
56
|
RestClient.should_receive(:get).with("http://www.google.com/reader/atom/user/-/state/com.google/starred?n=31", anything).and_return(xml_content)
|
57
|
-
subject.starred_items(31)
|
57
|
+
subject.starred_items(:count => 31)
|
58
58
|
end
|
59
59
|
|
60
60
|
it "should fetch the default 20 items from #subscriptions_items" do
|
@@ -64,7 +64,7 @@ describe GoogleReader::Client do
|
|
64
64
|
|
65
65
|
it "should fetch the requested number of items from #subscriptions_items" do
|
66
66
|
RestClient.should_receive(:get).with("http://www.google.com/reader/atom/user/-/state/com.google/subscriptions?n=19", anything).and_return(xml_content)
|
67
|
-
subject.subscriptions_items(19)
|
67
|
+
subject.subscriptions_items(:count => 19)
|
68
68
|
end
|
69
69
|
|
70
70
|
it "should fetch the default 20 items from #tracking_emailed_items" do
|
@@ -74,7 +74,7 @@ describe GoogleReader::Client do
|
|
74
74
|
|
75
75
|
it "should fetch the requested number of items from #tracking_emailed_items" do
|
76
76
|
RestClient.should_receive(:get).with("http://www.google.com/reader/atom/user/-/state/com.google/tracking-emailed?n=43", anything).and_return(xml_content)
|
77
|
-
subject.tracking_emailed_items(43)
|
77
|
+
subject.tracking_emailed_items(:count => 43)
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should fetch the default 20 items from #tracking_item_link_used_items" do
|
@@ -84,7 +84,7 @@ describe GoogleReader::Client do
|
|
84
84
|
|
85
85
|
it "should fetch the requested number of items from #tracking_item_link_used_items" do
|
86
86
|
RestClient.should_receive(:get).with("http://www.google.com/reader/atom/user/-/state/com.google/tracking-item-link-used?n=43", anything).and_return(xml_content)
|
87
|
-
subject.tracking_item_link_used_items(43)
|
87
|
+
subject.tracking_item_link_used_items(:count => 43)
|
88
88
|
end
|
89
89
|
|
90
90
|
it "should fetch the default 20 items from #tracking_body_link_used_items" do
|
@@ -94,6 +94,23 @@ describe GoogleReader::Client do
|
|
94
94
|
|
95
95
|
it "should fetch the requested number of items from #tracking_body_link_used_items" do
|
96
96
|
RestClient.should_receive(:get).with("http://www.google.com/reader/atom/user/-/state/com.google/tracking-body-link-used?n=43", anything).and_return(xml_content)
|
97
|
-
subject.tracking_body_link_used_items(43)
|
97
|
+
subject.tracking_body_link_used_items(:count => 43)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "should return a Feed instance on-demand" do
|
101
|
+
RestClient.stub(:get).and_return(xml_content)
|
102
|
+
subject.read_feed.should be_kind_of(GoogleReader::Feed)
|
103
|
+
end
|
104
|
+
|
105
|
+
it "should fetch items since a specific timestamp" do
|
106
|
+
cutoff_at = Time.now
|
107
|
+
RestClient.should_receive(:get).with do |*args|
|
108
|
+
url = args.first
|
109
|
+
uri = URI.parse(url)
|
110
|
+
pairs = Hash[ *uri.query.split("&").map {|pair| pair.split("=").map {|val| CGI.unescape(val)}}.flatten ]
|
111
|
+
url.split("?", 2).first == "http://www.google.com/reader/atom/user/-/state/com.google/read" && pairs["n"] == "240" && pairs["r"] == "o" && pairs["ot"] == cutoff_at.to_i.to_s
|
112
|
+
end.and_return(xml_content)
|
113
|
+
|
114
|
+
subject.read_items(:since => cutoff_at, :count => 240)
|
98
115
|
end
|
99
116
|
end
|
data/spec/feed_spec.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe GoogleReader::Feed do
|
4
|
+
let :entry_xml do
|
5
|
+
File.read(File.dirname(__FILE__) + "/fixtures/entry.xml")
|
6
|
+
end
|
7
|
+
|
8
|
+
let :doc do
|
9
|
+
Nokogiri::XML(entry_xml)
|
10
|
+
end
|
11
|
+
|
12
|
+
subject do
|
13
|
+
GoogleReader::Feed.new(doc)
|
14
|
+
end
|
15
|
+
|
16
|
+
it "should have a title" do
|
17
|
+
subject.title.should == %("tracking-item-link-used" via francois.beausoleil in Google Reader)
|
18
|
+
end
|
19
|
+
|
20
|
+
it "should have an #udpated_at" do
|
21
|
+
subject.updated_at.should == Time.utc(2011, 5, 2, 17, 53, 46)
|
22
|
+
end
|
23
|
+
end
|
data/spec/fixtures/entry.xml
CHANGED
@@ -1,5 +1,14 @@
|
|
1
1
|
<?xml version="1.0"?>
|
2
2
|
<feed xmlns:idx="urn:atom-extension:indexing" xmlns:media="http://search.yahoo.com/mrss/" xmlns:gr="http://www.google.com/schemas/reader/atom/" xmlns="http://www.w3.org/2005/Atom" idx:index="no" gr:dir="ltr">
|
3
|
+
<generator uri="http://www.google.com/reader">Google Reader</generator>
|
4
|
+
<id>tag:google.com,2005:reader/user/10212770223479967035/state/com.google/tracking-item-link-used</id>
|
5
|
+
<title>"tracking-item-link-used" via francois.beausoleil in Google Reader</title>
|
6
|
+
<gr:continuation>CPX6rZKan6gC</gr:continuation>
|
7
|
+
<link rel="self" href="http://www.google.com/reader/atom/user/-/state/com.google/tracking-item-link-used"/>
|
8
|
+
<author>
|
9
|
+
<name>francois.beausoleil</name>
|
10
|
+
</author>
|
11
|
+
<updated>2011-05-02T17:53:46Z</updated>
|
3
12
|
<entry gr:crawl-timestamp-msec="1303995951053">
|
4
13
|
<id gr:original-id="http://www.depesz.com/?p=2149">tag:google.com,2005:reader/item/d5dee0c34e012ddb</id>
|
5
14
|
<category term="user/10212770223479967035/state/com.google/read" scheme="http://www.google.com/reader/" label="read"/>
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: google_reader
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 1.1.
|
5
|
+
version: 1.1.1
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- "Fran\xC3\xA7ois Beausoleil"
|
@@ -65,10 +65,12 @@ files:
|
|
65
65
|
- lib/google_reader.rb
|
66
66
|
- lib/google_reader/client.rb
|
67
67
|
- lib/google_reader/entry.rb
|
68
|
+
- lib/google_reader/feed.rb
|
68
69
|
- lib/google_reader/source.rb
|
69
70
|
- lib/google_reader/version.rb
|
70
71
|
- spec/client_spec.rb
|
71
72
|
- spec/entry_spec.rb
|
73
|
+
- spec/feed_spec.rb
|
72
74
|
- spec/fixtures/entry-with-no-likes.xml
|
73
75
|
- spec/fixtures/entry-with-no-original-id.xml
|
74
76
|
- spec/fixtures/entry-with-unknown-author.xml
|
@@ -105,6 +107,7 @@ summary: An unofficial Ruby client for Google Reader
|
|
105
107
|
test_files:
|
106
108
|
- spec/client_spec.rb
|
107
109
|
- spec/entry_spec.rb
|
110
|
+
- spec/feed_spec.rb
|
108
111
|
- spec/fixtures/entry-with-no-likes.xml
|
109
112
|
- spec/fixtures/entry-with-no-original-id.xml
|
110
113
|
- spec/fixtures/entry-with-unknown-author.xml
|