gslide 0.1.1 → 0.1.3

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 52da391c6d99b7a6c04b766ec32349d41409af6a568f6b3dad3bc300f9e362b4
4
- data.tar.gz: 0adf949984afb45f782c8a4bef5d516b68550bd499b382dfa2e993b008b7402c
3
+ metadata.gz: 8fe444ca4bdef588c1e0aadf54db33d2024612b4d3450c4da243bd7ea3538055
4
+ data.tar.gz: 5416cb52420d81d5c5f8e4f99a13d2745e405a372c780314debb67c64e4c1b61
5
5
  SHA512:
6
- metadata.gz: 788294f12da41010e96ecb1576983e51cbd57de78970971b7940a60a325563685a2a494395925998c936ea2b862467d8971c6dbcfa62dd21442bafd81d7b83be
7
- data.tar.gz: 5c18a8c54b79bdff0da9c8f896d7aa31a2388cc7a86b9ad6e5a6c4a4425236a6915cde046dfee446e1a80ec5d8966b487e59c9356dbc4b5e54c8052f66f4736e
6
+ metadata.gz: 5477601ab8d237e62853bf974c1e3961fbd60e5197822754cdfe1d903a2bc37983395c412b674b27c8405fa3883d6b48291b384c49a619c7c4334f7bab719256
7
+ data.tar.gz: 518e86e5a3ececa73d696c737f3d0672f21fae300f5e57b2aa53c1de8fde8a9d925e1cadbbfd3c2048d9af90d41a3cd0765cd61f445bd9a78bc39c1183aafccd
data/CHANGELOG.md CHANGED
@@ -1,7 +1,15 @@
1
+ ## [0.1.3] - 2026-08-19
2
+
3
+ - Add `Gslide::Presentation::PRESENTATION_ID_PATTERN` and `Gslide::Presentation.file_id_in`, so callers can validate a presentation id without repeating the pattern
4
+
5
+ ## [0.1.2] - 2025-05-09
6
+
7
+ - Add `Gslide::HTTPError`, `Gslide::UnauthorizedError` and `Gslide::QuotaExceededError` #10
8
+
1
9
  ## [0.1.1] - 2025-04-14
2
10
 
3
- - Use a regular expression for finding a presentation id from url #8
4
- - Add retry logic for slide batch_update #7
11
+ - Use a regular expression for finding a presentation id from url [#8](https://github.com/lininglink/gslide/pull/8)
12
+ - Add retry logic for slide batch_update [#7](https://github.com/lininglink/gslide/pull/7)
5
13
 
6
14
  ## [0.1.0] - 2025-03-31
7
15
 
@@ -1,15 +1,29 @@
1
1
  require "net/http"
2
2
 
3
3
  module Gslide
4
+
5
+ # @private
4
6
  module Concerns
5
7
  module Requests
6
8
  def get_request(uri, auth_token: "")
7
9
  req = Net::HTTP::Get.new(uri.to_s)
8
10
  req['Authorization'] = "Bearer #{auth_token}"
9
11
 
10
- Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
12
+ res = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
11
13
  http.request(req)
12
14
  end
15
+ response_body = JSON(res.body)
16
+
17
+ case res
18
+ when Net::HTTPSuccess
19
+ response_body
20
+ when Net::HTTPUnauthorized
21
+ msg = response_body["error"] ? response_body["error"]["message"] : "Unauthorized"
22
+ raise Gslide::UnauthorizedError, msg
23
+ else
24
+ msg = response_body["error"] ? response_body["error"]["message"] : "HTTPError"
25
+ raise Gslide::HTTPError, msg
26
+ end
13
27
  end
14
28
 
15
29
  def post_request(uri, auth_token: "", body: {})
@@ -19,9 +33,29 @@ module Gslide
19
33
 
20
34
  req.body = body
21
35
 
22
- Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
36
+ res = Net::HTTP.start(uri.host, uri.port, :use_ssl => uri.scheme == 'https') do |http|
23
37
  http.request(req)
24
38
  end
39
+
40
+ response_body = JSON(res.body)
41
+
42
+ case res
43
+ when Net::HTTPSuccess
44
+ response_body
45
+ when Net::HTTPUnauthorized
46
+ msg = response_body["error"] ? response_body["error"]["message"] : "Unauthorized"
47
+ raise Gslide::UnauthorizedError, msg
48
+ when Net::HTTPTooManyRequests
49
+ # "Quota exceeded for quota metric 'Write requests' and limit 'Write requests per minute per user' of service 'slides.googleapis.com' for consumer 'project_number:012345678901'."
50
+ if response_body["error"] && response_body["error"]["message"] =~ /Quota exceeded/
51
+ raise Gslide::QuotaExceededError, msg
52
+ else
53
+ raise Gslide::HTTPError, msg || "TooManyRequests"
54
+ end
55
+ else
56
+ msg = response_body["error"] ? response_body["error"]["message"] : "HTTPError"
57
+ raise Gslide::HTTPError, msg
58
+ end
25
59
  end
26
60
  end
27
61
  end
@@ -23,12 +23,7 @@ module Gslide
23
23
  uri = URI(GOOGLE_SLIDES + "")
24
24
 
25
25
  # "title" is the only allowed field in the request body
26
- res = post_request(uri, auth_token: @token, body: options.to_json)
27
- response_body = JSON(res.body)
28
-
29
- if response_body["error"]
30
- raise Gslide::Error.new(response_body["error"]["message"])
31
- end
26
+ response_body = post_request(uri, auth_token: @token, body: options.to_json)
32
27
  Presentation.new response_body["presentationId"], auth: self
33
28
  end
34
29
  end
@@ -7,10 +7,17 @@ module Gslide
7
7
 
8
8
  attr_reader :id
9
9
 
10
- PRESENTATION_PATTERN = %r[/presentation/d/([a-zA-Z0-9\-_]+)?]
10
+ PRESENTATION_ID_PATTERN = /[a-zA-Z0-9\-_]+/
11
+ PRESENTATION_PATTERN = %r[/presentation/d/(#{PRESENTATION_ID_PATTERN})?]
12
+
13
+ # @param [String] id_or_url a presentation id, or a sharing url holding one.
14
+ # @return [String] the presentation id, or the argument when it is not a url.
15
+ def self.file_id_in(id_or_url)
16
+ (url_id = id_or_url.match(PRESENTATION_PATTERN)) ? url_id[1] : id_or_url
17
+ end
11
18
 
12
19
  def initialize(id_or_url, auth: nil)
13
- @id = (url_id = id_or_url.match(PRESENTATION_PATTERN)) ? url_id[1] : id_or_url
20
+ @id = self.class.file_id_in(id_or_url)
14
21
  @auth = auth
15
22
  end
16
23
 
@@ -19,8 +26,8 @@ module Gslide
19
26
  def get
20
27
  uri = URI(GOOGLE_SLIDES + "/#{@id}")
21
28
 
22
- res = get_request(uri, auth_token: @auth.token)
23
- JSON(res.body).convert_keys {|k| k.snake_case.to_sym }
29
+ response_body = get_request(uri, auth_token: @auth.token)
30
+ response_body.convert_keys {|k| k.snake_case.to_sym }
24
31
  end
25
32
 
26
33
  def link_url
@@ -36,23 +43,16 @@ module Gslide
36
43
  uri = URI(GOOGLE_SLIDES + "/#{@id}:batchUpdate")
37
44
  request_body = options.convert_keys { |k| k.to_s.lower_camel_case }.to_json
38
45
 
39
- res = post_request(uri, auth_token: @auth.token, body: request_body)
40
- response_body = JSON(res.body)
41
-
42
- if response_body["error"]
43
- raise Gslide::Error.new(response_body["error"]["message"])
44
- end
46
+ response_body = post_request(uri, auth_token: @auth.token, body: request_body)
45
47
  response_body["presentationId"] == @id
46
-
47
- rescue Gslide::Error => e
48
- if e.message =~ /Quota exceeded/ && (retries += 1) < 3
49
- # "Quota exceeded for quota metric 'Write requests' and limit 'Write requests per minute per user' of service 'slides.googleapis.com' for consumer 'project_number:012345678901'."
48
+ rescue Gslide::QuotaExceededError
49
+ if (retries += 1) < 3
50
50
  sleep 10 + retries * retries * 10
51
51
 
52
52
  retry
53
53
  end
54
- # all retries failed, re-raise exception
55
- raise e
54
+ # all retries failed, raise exception
55
+ raise
56
56
  end
57
57
 
58
58
  def get_slide_ids
@@ -17,8 +17,8 @@ module Gslide
17
17
  def get
18
18
  uri = URI(GOOGLE_SHEETS + "/#{@id}")
19
19
 
20
- res = get_request(uri, auth_token: @auth.token)
21
- JSON(res.body).convert_keys {|k| k.snake_case.to_sym }
20
+ response_body = get_request(uri, auth_token: @auth.token)
21
+ response_body.convert_keys {|k| k.snake_case.to_sym }
22
22
  end
23
23
 
24
24
  def link_url
@@ -32,12 +32,7 @@ module Gslide
32
32
  uri = URI(GOOGLE_SHEETS + "/#{@id}:batchUpdate")
33
33
  request_body = options.convert_keys { |k| k.to_s.lower_camel_case }.to_json
34
34
 
35
- res = post_request(uri, auth_token: @auth.token, body: request_body)
36
- response_body = JSON(res.body)
37
-
38
- if response_body["error"]
39
- raise Gslide::Error.new(response_body["error"]["message"])
40
- end
35
+ response_body = post_request(uri, auth_token: @auth.token, body: request_body)
41
36
  response_body["spreadsheetId"] == @id
42
37
  end
43
38
 
@@ -45,6 +40,23 @@ module Gslide
45
40
  parsed_body = get
46
41
  parsed_body[:sheets].collect { |h| Sheet.new(h) }
47
42
  end
43
+
44
+ # @param [Hash] options the request body.
45
+ # @see https://developers.google.com/workspace/sheets/api/reference/rest/v4/spreadsheets.values/append
46
+ def values_append(notation, options = {})
47
+ uri = url_escape_uri(GOOGLE_SHEETS + "/#{@id}/values/'#{notation}':append?valueInputOption=USER_ENTERED")
48
+ request_body = options.convert_keys { |k| k.to_s.lower_camel_case }.to_json
49
+
50
+ response_body = post_request(uri, auth_token: @auth.token, body: request_body)
51
+ response_body
52
+ end
53
+
54
+ private
55
+
56
+ def url_escape_uri(uri_string)
57
+ parser = URI::Parser.new
58
+ URI parser.escape(uri_string)
59
+ end
48
60
  end
49
61
 
50
62
  class SpreadsheetDraft
@@ -58,21 +70,19 @@ module Gslide
58
70
  request_body = options.convert_keys { |k| k.to_s.lower_camel_case }.to_json
59
71
 
60
72
  uri = URI(GOOGLE_SHEETS)
61
- res = post_request(uri, auth_token: @auth.token, body: request_body)
62
- response_body = JSON(res.body)
63
- if response_body["error"]
64
- raise Gslide::Error.new(response_body["error"]["message"])
65
- end
73
+ response_body = post_request(uri, auth_token: @auth.token, body: request_body)
74
+
66
75
  spreadsheet_id = response_body["spreadsheetId"]
67
76
  Spreadsheet.new(spreadsheet_id, auth: @auth)
68
77
  end
69
78
  end
70
79
 
71
80
  class Sheet
72
- attr_reader :id, :charts
81
+ attr_reader :id, :title, :charts
73
82
 
74
83
  def initialize(options = {})
75
84
  @id = options[:properties][:sheet_id]
85
+ @title = options[:properties][:title]
76
86
  @charts = options[:charts].collect { |h| Chart.new(h) } if options[:charts]
77
87
  end
78
88
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Gslide
4
- VERSION = "0.1.1"
4
+ VERSION = "0.1.3"
5
5
  end
data/lib/gslide.rb CHANGED
@@ -7,5 +7,7 @@ require "gslide/models/models"
7
7
 
8
8
  module Gslide
9
9
  class Error < StandardError; end
10
-
10
+ class HTTPError < Error; end
11
+ class UnauthorizedError < HTTPError; end
12
+ class QuotaExceededError < HTTPError; end
11
13
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: gslide
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.1.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kang-Kyu Lee
@@ -52,7 +52,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
52
52
  - !ruby/object:Gem::Version
53
53
  version: '0'
54
54
  requirements: []
55
- rubygems_version: 3.6.7
55
+ rubygems_version: 4.0.6
56
56
  specification_version: 4
57
57
  summary: Google Slides API client.
58
58
  test_files: []