grapi 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.textile CHANGED
@@ -1,13 +1,14 @@
1
1
  h2. Grapi : Ruby client to access the unofficial Google Reader API
2
2
 
3
- h3. Client Dependencies
3
+ h3. Install
4
4
 
5
- * "Curb":http://github.com/taf2/curb (gem install curb)
5
+ <pre>
6
+ gem install grapi
7
+ </pre>
6
8
 
7
- h3. ReadingList Parser
9
+ h3. Client Dependencies
8
10
 
9
- * "Nokogiri":http://github.com/tenderlove/nokogiri (gem install nokogiri)
10
- * "Loofah":http://github.com/flavorjones/loofah (gem install loofah)
11
+ * "Curb":http://github.com/taf2/curb (gem install curb)
11
12
 
12
13
  h3. Synopsis
13
14
 
@@ -18,20 +19,27 @@ require "grapi"
18
19
  reader = Grapi::Reader.new
19
20
  reader.login USERNAME, PASSWORD
20
21
 
21
- require "grapi/parser"
22
- list= Grapi::Parser::ReadingList.parse reader.reading_list
22
+ puts reader.reading_list
23
23
 
24
24
  </pre>
25
25
 
26
26
  h3. API methods
27
27
 
28
+ Public API:
29
+
28
30
  * initialize(verbose= false)
29
31
  * login(USERNAME, PASSWORD)
30
- * reading_list(continuation=nil, dump_data= false)
32
+ * reading_list(:continuation => nil, :dump_data => false, :output => "atom/json")
31
33
  * subscribe(feed_url, label=test)
32
34
  * unsubscribe(feed_url)
33
35
  * mark_as_read(entry_google_id)
34
36
 
37
+ Protected API:
38
+
39
+ * get(url)
40
+ * post(url, params={})
41
+ * post_with_token(url, params={})
42
+
35
43
  h3. License: see "MIT-LICENSE":http://github.com/aurelian/grapi/blob/master/MIT-LICENSE
36
44
 
37
45
  h3. For: contact - ideas - patches please use github infrastructure
data/Rakefile CHANGED
@@ -11,9 +11,6 @@ begin
11
11
  gem.homepage = "http://github.com/aurelian/grapi"
12
12
  gem.authors = ["Aurelian Oancea"]
13
13
  gem.add_dependency("curb", ">=0.6.1.0")
14
- gem.add_dependency("nokogiri", ">=1.4.1")
15
- gem.add_dependency("loofah", ">=0.4.1")
16
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
14
  end
18
15
  Jeweler::GemcutterTasks.new
19
16
  rescue LoadError
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.0
1
+ 0.3.0
data/grapi.gemspec CHANGED
@@ -5,7 +5,7 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{grapi}
8
- s.version = "0.2.0"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Aurelian Oancea"]
@@ -21,11 +21,9 @@ Gem::Specification.new do |s|
21
21
  "README.textile",
22
22
  "Rakefile",
23
23
  "VERSION",
24
- "example.rb",
25
24
  "grapi.gemspec",
26
25
  "lib/core_ext/string.rb",
27
26
  "lib/grapi.rb",
28
- "lib/grapi/parser.rb",
29
27
  "lib/grapi/reader.rb",
30
28
  "test/helper.rb",
31
29
  "test/test_grapi.rb"
@@ -46,17 +44,11 @@ Gem::Specification.new do |s|
46
44
 
47
45
  if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
48
46
  s.add_runtime_dependency(%q<curb>, [">= 0.6.1.0"])
49
- s.add_runtime_dependency(%q<nokogiri>, [">= 1.4.1"])
50
- s.add_runtime_dependency(%q<loofah>, [">= 0.4.1"])
51
47
  else
52
48
  s.add_dependency(%q<curb>, [">= 0.6.1.0"])
53
- s.add_dependency(%q<nokogiri>, [">= 1.4.1"])
54
- s.add_dependency(%q<loofah>, [">= 0.4.1"])
55
49
  end
56
50
  else
57
51
  s.add_dependency(%q<curb>, [">= 0.6.1.0"])
58
- s.add_dependency(%q<nokogiri>, [">= 1.4.1"])
59
- s.add_dependency(%q<loofah>, [">= 0.4.1"])
60
52
  end
61
53
  end
62
54
 
data/lib/grapi/reader.rb CHANGED
@@ -4,32 +4,19 @@ module Grapi
4
4
 
5
5
  class Reader
6
6
 
7
+ VERSION = File.read(File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "VERSION"))).strip
8
+
7
9
  def initialize(verbose= false)
8
10
  @client = ::Curl::Easy.new do | easy |
9
11
  easy.headers= {
10
- "User-Agent" => "Grapi::Reader /0.2 +gzip",
12
+ "User-Agent" => "Grapi::Reader /#{Grapi::Reader::VERSION} +gzip",
11
13
  "Accept-Encoding" => "gzip, deflate",
12
14
  "GData-Version" => 2
13
15
  }
14
16
  easy.follow_location= true
15
17
  easy.verbose= true if verbose
16
18
  end
17
- @token = nil
18
- end
19
-
20
- def get(url)
21
- make_request(url){|c| c.http_get }
22
- end
23
-
24
- def post(url, params)
25
- curl_post_params= params.inject([]){|p, e| p << ::Curl::PostField.content(e[0],e[1])}
26
- make_request(url){|c| c.http_post(*curl_post_params)}
27
- end
28
-
29
- def post_with_token(url, params)
30
- request_token if @token.nil?
31
- params["T"]= @token
32
- post url, params
19
+ @token= nil
33
20
  end
34
21
 
35
22
  def login(username, password)
@@ -57,18 +44,42 @@ module Grapi
57
44
  post_with_token "http://www.google.com/reader/api/0/edit-tag", {"i" => entry_id, "a" => "user/-/state/com.google/read"}
58
45
  end
59
46
 
60
- def reading_list(continuation= nil, dump_data= false)
61
- get "http://www.google.com/reader/atom/user/-/state/com.google/reading-list?xt=user/-/state/com.google/read&ck=#{Time.now.to_i*1000}&n=1000&c=#{continuation}"
47
+ # options:
48
+ # :continuation (default: nil) -> continuation string
49
+ # :dump_data (default: false) -> whether to write the response to a file in /tmp or not
50
+ # :output (default: atom) -> desired output (atom|json)
51
+ def reading_list(options={})
52
+ options= {:continuation => nil, :output => "atom", :dump_data => false}.update(options)
53
+ if options[:output] == "atom"
54
+ get "http://www.google.com/reader/atom/user/-/state/com.google/reading-list?xt=user/-/state/com.google/read&ck=#{Time.now.to_i*1000}&n=1000&c=#{options[:continuation]}"
55
+ else
56
+ get "http://www.google.com/reader/api/0/stream/contents/user/-/state/com.google/reading-list?output=#{options[:output]}&xt=user/-/state/com.google/read&ck=#{Time.now.to_i*1000}&n=1000&c=#{options[:continuation]}"
57
+ end
62
58
  response= @client.body_str.uncompress
63
- File.open("/tmp/#{Time.now.to_i}-reading_list.atom", "w"){|f|f<<response} if dump_data
59
+ File.open("/tmp/#{Time.now.to_i}-reading_list.#{options[:output]}", "w"){|f|f<<response} if options[:dump_data]
64
60
  response
65
61
  end
66
62
 
67
- private
63
+ protected
64
+ def get(url)
65
+ make_request(url){|c| c.http_get }
66
+ end
67
+
68
+ def post(url, params)
69
+ curl_post_params= params.inject([]){|p, e| p << ::Curl::PostField.content(e[0],e[1])}
70
+ make_request(url){|c| c.http_post(*curl_post_params)}
71
+ end
68
72
 
73
+ def post_with_token(url, params)
74
+ request_token if @token.nil?
75
+ params["T"]= @token
76
+ post url, params
77
+ end
78
+
79
+ private
69
80
  def edit_subscription(feed_url, action, params={})
70
81
  post_with_token "http://www.google.com/reader/api/0/subscription/edit", { "s" => "feed/#{feed_url}", "ac" => action }.update(params)
71
- response = @client.body_str.uncompress
82
+ response= @client.body_str.uncompress
72
83
  unless response == "OK"
73
84
  $stderr<< "WARN: [#{__FILE__}:#{__LINE__}] ~> response is not OK. probably token has expired!\n#{response}\n\n"
74
85
  end
@@ -76,7 +87,7 @@ module Grapi
76
87
 
77
88
  def request_token
78
89
  get "http://www.google.com/reader/api/0/token"
79
- @token = @client.body_str.uncompress
90
+ @token= @client.body_str.uncompress
80
91
  end
81
92
 
82
93
  def make_request(url)
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: grapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Aurelian Oancea
@@ -22,26 +22,6 @@ dependencies:
22
22
  - !ruby/object:Gem::Version
23
23
  version: 0.6.1.0
24
24
  version:
25
- - !ruby/object:Gem::Dependency
26
- name: nokogiri
27
- type: :runtime
28
- version_requirement:
29
- version_requirements: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
32
- - !ruby/object:Gem::Version
33
- version: 1.4.1
34
- version:
35
- - !ruby/object:Gem::Dependency
36
- name: loofah
37
- type: :runtime
38
- version_requirement:
39
- version_requirements: !ruby/object:Gem::Requirement
40
- requirements:
41
- - - ">="
42
- - !ruby/object:Gem::Version
43
- version: 0.4.1
44
- version:
45
25
  description: Ruby client for unofficial Google Reader API
46
26
  email: oancea@gmail.com
47
27
  executables: []
@@ -56,11 +36,9 @@ files:
56
36
  - README.textile
57
37
  - Rakefile
58
38
  - VERSION
59
- - example.rb
60
39
  - grapi.gemspec
61
40
  - lib/core_ext/string.rb
62
41
  - lib/grapi.rb
63
- - lib/grapi/parser.rb
64
42
  - lib/grapi/reader.rb
65
43
  - test/helper.rb
66
44
  - test/test_grapi.rb
data/example.rb DELETED
@@ -1,34 +0,0 @@
1
- $LOAD_PATH<< "lib"
2
-
3
- require "rubygems"
4
- require "grapi"
5
- require "grapi/parser"
6
- require "yaml"
7
-
8
- def print_list(list)
9
- puts "~> Got: #{list.gid} updated at: #{list.updated_at}\n\t contains: #{list.entries.size} items. continuation: #{list.continuation}"
10
- list.entries.each do | entry |
11
- puts "~> #{entry.title}"
12
- puts "\tpublished at: #{entry.published_at}"
13
- puts "\tcategories: \n\t\t#{entry.categories.map{|k| "label= #{k[:label]} | term= #{k[:term]}"}.join("\n\t\t")}"
14
- puts "\tsource: #{entry.source[:title]}"
15
- puts "\tauthor: #{entry.author}"
16
- puts "\turl: #{entry.link}"
17
- puts "\tsummary: #{entry.summary}"
18
- puts "======================================================================="
19
- end
20
- end
21
-
22
- config= YAML.load_file File.expand_path("~/.gdata.yml")
23
-
24
- reader= Grapi::Reader.new(true)
25
- reader.login config["username"], config["password"]
26
-
27
- continuation= nil
28
- loop do
29
- list= Grapi::Parser::ReadingList.parse(reader.reading_list(continuation))
30
- print_list list
31
- continuation= list.continuation
32
- break if continuation.nil?
33
- end
34
-
data/lib/grapi/parser.rb DELETED
@@ -1,55 +0,0 @@
1
- require "nokogiri"
2
- require "loofah"
3
- require "time"
4
-
5
- module Grapi
6
-
7
- module Parser
8
-
9
- class Entry
10
- attr_accessor :crawled_at, :summary, :gid, :categories, :published_at, :updated_at, :author, :source, :title, :link
11
-
12
- def initialize
13
- @categories= []
14
- yield self
15
- end
16
- end
17
-
18
- class ReadingList
19
- attr_accessor :entries, :gid, :updated_at, :continuation
20
-
21
- def initialize
22
- @entries= []
23
- yield self
24
- end
25
-
26
- def self.parse(xml)
27
- doc= Nokogiri::XML xml
28
- Grapi::Parser::ReadingList.new do | list |
29
- list.gid = doc.search("id").first.inner_text
30
- list.updated_at = Time.parse(doc.search("updated").first.inner_text)
31
- list.continuation = doc.at_xpath("//gr:continuation").inner_text rescue nil
32
- doc.search("entry").each do | entry |
33
- list.entries << Grapi::Parser::Entry.new do | e |
34
- e.gid = entry.search("id").first.inner_text
35
- e.title = entry.search("title").first.inner_text
36
- e.published_at = Time.parse(entry.search("published").first.inner_text)
37
- e.updated_at = Time.parse(entry.search("updated").first.inner_text)
38
- e.link = entry.search("link").attr("href").value
39
- e.crawled_at = Time.at(entry["crawl-timestamp-msec"].to_i/1000.0).utc
40
- e.summary = Loofah.fragment(entry.search("summary").inner_text).scrub!(:strip).text
41
- e.author = entry.search("author/name").inner_text
42
- e.source = {
43
- :id => entry.search("source/id").inner_text,
44
- :title => entry.search("source/title").inner_text,
45
- :link => entry.search("source/link").attr("href").value
46
- }
47
- entry.search("category").each { | category | e.categories << {:term=>category.attr("term"), :label=>category.attr("label")} }
48
- end
49
- end
50
- end
51
- end
52
- end
53
- end
54
- end
55
-