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 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
@@ -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
- count = args.first || 20
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
@@ -103,7 +103,5 @@ module GoogleReader
103
103
  def unhtml(text)
104
104
  text.gsub("&lt;", "<").gsub("&gt;", ">").gsub("&amp;", "&").gsub("&quot;", '"')
105
105
  end
106
-
107
- GOOGLE_ATOM_NAMESPACE = "http://www.google.com/schemas/reader/atom/".freeze
108
106
  end
109
107
  end
@@ -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
@@ -1,3 +1,3 @@
1
1
  module GoogleReader
2
- VERSION = "1.1.0"
2
+ VERSION = "1.1.1"
3
3
  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("Auth=abc")
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("Auth=my-fancy-token")
16
- GoogleReader::Client.should_receive(:new).with(hash_including("Authorization" => "GoogleLogin auth=my-fancy-token"))
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
@@ -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.0
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