GoogleReaderApi 0.3.5 → 0.3.6

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,44 +1,42 @@
1
1
  # Generated by jeweler
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
- # Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{GoogleReaderApi}
8
- s.version = "0.3.5"
8
+ s.version = "0.3.6"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
- s.authors = ["Toon Willems"]
12
- s.date = %q{2010-06-22}
11
+ s.authors = [%q{Toon Willems}]
12
+ s.date = %q{2011-08-21}
13
13
  s.description = %q{a google reader api (unofficial) written in ruby}
14
14
  s.email = %q{willemstoon@gmail.com}
15
15
  s.extra_rdoc_files = [
16
16
  "README.mdown"
17
17
  ]
18
18
  s.files = [
19
- ".gitignore",
20
- "GoogleReaderApi.gemspec",
21
- "License",
22
- "README.mdown",
23
- "Rakefile",
24
- "VERSION",
25
- "lib/google-reader-api/api.rb",
26
- "lib/google-reader-api/cache.rb",
27
- "lib/google-reader-api/entry.rb",
28
- "lib/google-reader-api/feed.rb",
29
- "lib/google-reader-api/rss_utils.rb",
30
- "lib/google-reader-api/subscription_list.rb",
31
- "lib/google-reader-api/user.rb",
32
- "lib/google_reader_api.rb"
19
+ "GoogleReaderApi.gemspec",
20
+ "License",
21
+ "README.mdown",
22
+ "Rakefile",
23
+ "VERSION",
24
+ "lib/google-reader-api/api.rb",
25
+ "lib/google-reader-api/cache.rb",
26
+ "lib/google-reader-api/entry.rb",
27
+ "lib/google-reader-api/feed.rb",
28
+ "lib/google-reader-api/google_login.rb",
29
+ "lib/google-reader-api/rss_utils.rb",
30
+ "lib/google-reader-api/subscription_list.rb",
31
+ "lib/google-reader-api/user.rb",
32
+ "lib/google_reader_api.rb"
33
33
  ]
34
34
  s.homepage = %q{http://github.com/nudded/GoogleReaderAPI}
35
- s.rdoc_options = ["--charset=UTF-8"]
36
- s.require_paths = ["lib"]
37
- s.rubygems_version = %q{1.3.7}
35
+ s.require_paths = [%q{lib}]
36
+ s.rubygems_version = %q{1.8.8}
38
37
  s.summary = %q{a google reader api (unofficial) written in ruby}
39
38
 
40
39
  if s.respond_to? :specification_version then
41
- current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
42
40
  s.specification_version = 3
43
41
 
44
42
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.5
1
+ 0.3.6
@@ -1,41 +1,52 @@
1
1
  module GoogleReaderApi
2
-
2
+
3
3
  class Api
4
-
4
+
5
5
  require "cgi"
6
6
  require "net/https"
7
7
  require "uri"
8
-
8
+
9
9
  BASE_URL = "http://www.google.com/reader/"
10
-
11
- def initialize(email,password)
12
- request_sid(email,password)
10
+
11
+ # specify either the :email and :password or the :auth token you got in the past
12
+ #
13
+ # [:email] the user's email address for login purposes
14
+ #
15
+ # [:password] the user's password for login purposes
16
+ #
17
+ # [:auth] the auth token you got from a previous authentication request
18
+ # if you provide this you do not need to provide the email and password
19
+ def initialize(options)
20
+ if options[:auth]
21
+ @auth = options[:auth]
22
+ else
23
+ request_auth(options[:email],options[:password])
24
+ end
13
25
  @cache = GoogleReaderApi::Cache.new(2)
14
26
  end
15
-
27
+
16
28
  # do a get request to the link
17
29
  # args is a hash of values that should be used in the request
18
30
  def get_link(link,args={})
19
31
  link = BASE_URL + link
20
32
  get_request(link,args)
21
33
  end
22
-
34
+
23
35
  def post_link(link,args={})
24
36
  link = BASE_URL + link
25
37
  post_request(link,args)
26
38
  end
27
-
39
+
28
40
  def cached_unread_count
29
41
  @cache['unread-count'] ||= get_link 'api/0/unread-count', :output => :json
30
42
  end
31
-
43
+
32
44
  private
33
45
 
34
46
  # url as a string
35
47
  # the post data as a hash
36
48
  def post_request(url,args)
37
49
  uri = URI.parse(url)
38
- args[:T] = token
39
50
  req = Net::HTTP::Post.new(uri.path)
40
51
  req.set_form_data(args)
41
52
  request(uri,req)
@@ -45,24 +56,24 @@ module GoogleReaderApi
45
56
  # e.g. :allcomments => true etc...
46
57
  def get_request(url,args)
47
58
  uri = URI.parse url
48
-
59
+
49
60
  # ck is the current unix timestamp
50
61
  args[:ck] = Time.now.to_i unless args[:ck]
51
-
62
+
52
63
  req = Net::HTTP::Get.new("#{uri.path}?#{argument_string(args)}")
53
64
  request(uri,req)
54
65
  end
55
66
 
56
67
  def request(uri,request)
57
68
  # add the cookie to the http header
58
- request.add_field('Cookie',user_cookie)
69
+ request.add_field('Authorization',"GoogleLogin auth=#{auth}")
59
70
  res = Net::HTTP.start(uri.host,uri.port) do |http|
60
71
  http.request(request)
61
72
  end
62
73
  # TODO: use better exception
63
74
  if res.code != '200'
64
75
  p res.body
65
- raise "something went wrong"
76
+ raise "something went wrong"
66
77
  end
67
78
  res.body
68
79
  end
@@ -71,37 +82,17 @@ module GoogleReaderApi
71
82
  def argument_string(args)
72
83
  args.to_a.map { |v| v.join '=' }.join('&')
73
84
  end
74
-
75
- def token
76
- url = URI.parse "http://www.google.com/reader/api/0/token"
77
- res = Net::HTTP.start(url.host,url.port) do |http|
78
- http.get(url.path,"Cookie" => user_cookie)
79
- end
80
- res.body
81
- end
82
85
 
83
- def user_cookie
84
- CGI::Cookie::new('name' => 'SID' , 'value' => sid ,
85
- 'path' => '/' , 'domain' => '.google.com').to_s
86
+ def auth
87
+ @auth
86
88
  end
87
89
 
88
- def sid
89
- @sid
90
- end
91
-
92
- def request_sid(email,password)
93
- password = CGI.escape(password)
94
- email = CGI.escape(email)
95
- url = URI.parse "https://www.google.com/accounts/ClientLogin?service=reader&Email=#{email}&Passwd=#{password}"
96
- http = Net::HTTP.new(url.host,url.port)
97
- http.use_ssl = true
98
- res,data = http.get("#{url.path}?#{url.query}")
99
-
100
- raise "could not authenticate" if res.code != "200"
101
-
102
- @sid = data.match(/SID=(.+?)\n/)[1]
90
+ def request_auth(email,password)
91
+ login = GoogleLogin::ClientLogin.new :service => 'reader', :source => 'nudded-greader-0.1'
92
+ login.authenticate email, password
93
+ @auth = login.auth
103
94
  end
104
-
95
+
105
96
  end
106
-
107
- end
97
+
98
+ end
@@ -0,0 +1,139 @@
1
+ require "net/https"
2
+ require "uri"
3
+
4
+ module GoogleLogin
5
+
6
+ # == ClientLogin
7
+ #
8
+ # Use this Class to get an auth-token
9
+ class ClientLogin
10
+
11
+ # Base Exception class
12
+ LoginError = Class.new Exception
13
+
14
+ # All the possible exceptions
15
+ [
16
+ "BadAuthentication",
17
+ "NotVerified",
18
+ "TermsNotAgreed",
19
+ "CaptchaRequired",
20
+ "Unknown",
21
+ "AccountDeleted",
22
+ "AccountDisabled",
23
+ "ServiceDisabled",
24
+ "ServiceUnavailable",
25
+ ].each do |const|
26
+ const_set const, Class.new(LoginError)
27
+ end
28
+
29
+ DEFAULTS = {
30
+ :accountType => 'HOSTED_OR_GOOGLE' ,
31
+ :source => 'companyName-applicationName-versionID',
32
+ :service => 'service-identifier'
33
+ }
34
+
35
+ attr_reader :auth, :sid, :lsid, :captcha_url
36
+
37
+ # specify the :service, :source and optionally :accountType
38
+ #
39
+ # [:service] the service identifier, check the google api documentation.
40
+ #
41
+ # [:source] the name of your application. String should be in the form
42
+ # "companyName-applicationName-versionID".
43
+ #
44
+ # [:accountType] one of the following values:
45
+ # "GOOGLE", "HOSTED", "HOSTED_OR_GOOGLE" (default if none
46
+ # given)
47
+ def initialize(arghash = {})
48
+ @options = DEFAULTS.merge arghash
49
+ end
50
+
51
+ # authenticate a user, which sets the auth, sid and lsid instance_variables
52
+ # if you provide a block, it will be called with a captcha url if google
53
+ # forces you to answer the captcha. Make sure you return the anwer in the block.
54
+ #
55
+ # if no block is given, this will raise a CaptchaRequired error.
56
+ # you can rescue them and show the url via the captcha_url method.
57
+ #
58
+ # you can then call authenticate and as 3rd parameter you provide the
59
+ # captcha answer.
60
+ #
61
+ # all Exceptions this raises are subclasses of ClientLogin::LoginError.
62
+ # so make sure you handle them.
63
+ #
64
+ # This is a list of all the possible errors and their meaning
65
+ # Error code:: Description
66
+ # BadAuthentication:: The login request used a username or password that is not recognized.
67
+ # NotVerified:: The account email address has not been verified. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.
68
+ # TermsNotAgreed:: The user has not agreed to terms. The user will need to access their Google account directly to resolve the issue before logging in using a non-Google application.
69
+ # CaptchaRequired:: A CAPTCHA is required. (A response with this error code will also contain an image URL and a CAPTCHA token.)
70
+ # Unknown:: The error is unknown or unspecified; the request contained invalid input or was malformed.
71
+ # AccountDeleted:: The user account has been deleted.
72
+ # AccountDisabled:: The user account has been disabled.
73
+ # ServiceDisabled:: The user's access to the specified service has been disabled. (The user account may still be valid.)
74
+ # ServiceUnavailable:: The service is not available; try again later.
75
+ def authenticate(username, password, captcha_response = nil)
76
+ @options[:Email], @options[:Passwd] = username, password
77
+ # set logincaptcha, captchatoken will already be set
78
+ @options[:logincaptcha] = captcha_response if captcha_response
79
+
80
+ parse_response perform_request
81
+
82
+ rescue CaptchaRequired
83
+ if block_given?
84
+ @options[:logincaptcha] = yield captcha_url
85
+ retry
86
+ else
87
+ raise CaptchaRequired
88
+ end
89
+ end
90
+
91
+ private
92
+
93
+ def perform_request
94
+ request = Net::HTTP::Post.new '/accounts/ClientLogin'
95
+ request.form_data = @options
96
+
97
+ https = Net::HTTP.new 'www.google.com', 443
98
+ https.use_ssl = true
99
+
100
+ https.request request
101
+ end
102
+
103
+ def parse_body(response_body)
104
+ response_body.scan(/(\w+)=(.+)\n/).each do |key, value|
105
+ instance_variable_set "@#{key.downcase}" , value
106
+ end
107
+ end
108
+
109
+ def parse_response(response)
110
+ if response.code_type == Net::HTTPOK
111
+ parse_body response.body
112
+ else
113
+ handle_error response.body
114
+ end
115
+ end
116
+
117
+
118
+ def handle_error(response_body)
119
+ error_message = response_body.match(/Error=(\w+)\n/)[1].strip
120
+
121
+ if error_message == "CaptchaRequired"
122
+ @options[:logintoken] = response_body.match(/CaptchaToken=(.+)\n/)[1]
123
+ self.captcha_url = response_body.match(/CaptchaUrl=(.+)\n/)[1]
124
+ end
125
+
126
+ raise_error_class error_message
127
+ end
128
+
129
+ def raise_error_class(error_message)
130
+ raise self.class.const_get error_message
131
+ end
132
+
133
+ def captcha_url=(url)
134
+ @captcha_url = "http://www.google.com/accounts/" << url
135
+ end
136
+
137
+ end
138
+
139
+ end
@@ -5,9 +5,17 @@ module GoogleReaderApi
5
5
  require "json"
6
6
  # maybe someone would like to access the api for a user
7
7
  attr_reader :api
8
-
9
- def initialize(email,password)
10
- @api = GoogleReaderApi::Api::new email,password
8
+
9
+ # specify either the :email and :password or the :auth token you got in the past
10
+ #
11
+ # [:email] the user's email address for login purposes
12
+ #
13
+ # [:password] the user's password for login purposes
14
+ #
15
+ # [:auth] the auth token you got from a previous authentication request
16
+ # if you provide this you do not need to provide the email and password
17
+ def initialize(options)
18
+ @api = GoogleReaderApi::Api::new options
11
19
  end
12
20
 
13
21
  def info
@@ -4,4 +4,5 @@ require "google-reader-api/cache"
4
4
  require "google-reader-api/entry"
5
5
  require "google-reader-api/feed"
6
6
  require "google-reader-api/subscription_list"
7
- require "google-reader-api/user"
7
+ require "google-reader-api/user"
8
+ require "google-reader-api/google_login"
metadata CHANGED
@@ -1,34 +1,23 @@
1
- --- !ruby/object:Gem::Specification
1
+ --- !ruby/object:Gem::Specification
2
2
  name: GoogleReaderApi
3
- version: !ruby/object:Gem::Version
4
- hash: 25
5
- prerelease: false
6
- segments:
7
- - 0
8
- - 3
9
- - 5
10
- version: 0.3.5
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.3.6
5
+ prerelease:
11
6
  platform: ruby
12
- authors:
7
+ authors:
13
8
  - Toon Willems
14
9
  autorequire:
15
10
  bindir: bin
16
11
  cert_chain: []
17
-
18
- date: 2010-06-22 00:00:00 +02:00
19
- default_executable:
12
+ date: 2011-08-21 00:00:00.000000000Z
20
13
  dependencies: []
21
-
22
14
  description: a google reader api (unofficial) written in ruby
23
15
  email: willemstoon@gmail.com
24
16
  executables: []
25
-
26
17
  extensions: []
27
-
28
- extra_rdoc_files:
18
+ extra_rdoc_files:
29
19
  - README.mdown
30
- files:
31
- - .gitignore
20
+ files:
32
21
  - GoogleReaderApi.gemspec
33
22
  - License
34
23
  - README.mdown
@@ -38,43 +27,33 @@ files:
38
27
  - lib/google-reader-api/cache.rb
39
28
  - lib/google-reader-api/entry.rb
40
29
  - lib/google-reader-api/feed.rb
30
+ - lib/google-reader-api/google_login.rb
41
31
  - lib/google-reader-api/rss_utils.rb
42
32
  - lib/google-reader-api/subscription_list.rb
43
33
  - lib/google-reader-api/user.rb
44
34
  - lib/google_reader_api.rb
45
- has_rdoc: true
46
35
  homepage: http://github.com/nudded/GoogleReaderAPI
47
36
  licenses: []
48
-
49
37
  post_install_message:
50
- rdoc_options:
51
- - --charset=UTF-8
52
- require_paths:
38
+ rdoc_options: []
39
+ require_paths:
53
40
  - lib
54
- required_ruby_version: !ruby/object:Gem::Requirement
41
+ required_ruby_version: !ruby/object:Gem::Requirement
55
42
  none: false
56
- requirements:
57
- - - ">="
58
- - !ruby/object:Gem::Version
59
- hash: 3
60
- segments:
61
- - 0
62
- version: "0"
63
- required_rubygems_version: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: '0'
47
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
48
  none: false
65
- requirements:
66
- - - ">="
67
- - !ruby/object:Gem::Version
68
- hash: 3
69
- segments:
70
- - 0
71
- version: "0"
49
+ requirements:
50
+ - - ! '>='
51
+ - !ruby/object:Gem::Version
52
+ version: '0'
72
53
  requirements: []
73
-
74
54
  rubyforge_project:
75
- rubygems_version: 1.3.7
55
+ rubygems_version: 1.8.8
76
56
  signing_key:
77
57
  specification_version: 3
78
58
  summary: a google reader api (unofficial) written in ruby
79
59
  test_files: []
80
-
data/.gitignore DELETED
@@ -1 +0,0 @@
1
- pkg