simple_tweet 3.0.1 → 3.1.0

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: a6ce5d4a7a448770b21c18cc4b68f25adc7f21d8814a02970864efc4c487d071
4
- data.tar.gz: 6dfec2f42eff6f04cd8e0dc59571b31bc558b027fc20efdc87c59dd8402a47a1
3
+ metadata.gz: eda2472eda06f1ddc2348a30e194c498e0cd9998036e7dabdbdee4850e1098dc
4
+ data.tar.gz: 50c944ffd64e0f687f968d254389bd2fab8b521b959c5433fbe2aecfe772507e
5
5
  SHA512:
6
- metadata.gz: bef5b277879212fc6c8a6c542ed70d71fd35e5c8e12ab0ab9119d50c3969e271b99b95f812b990eb4bb5ef93c9bc6b9726cb6e71fcf974112789e20da94e0b6f
7
- data.tar.gz: '09771d8edada2fba52358e1f897410a620703d91fe87a6f1b602ec846c56e9771b4a3289908d4bcded74da60c396a235d074ae3388e61917da067422852346f5'
6
+ metadata.gz: a24c2848c3164782c1e424ac6fa6504fb4c1df5b1d720e92323cea4c8298d9327d1878fc49e1b13091c1a043bd612efd06a409ad2bc218c82cb650b962222f3c
7
+ data.tar.gz: e03a4050dc75280addf7a86cad0faa1cc9541c39abbe2f9d1adca6a6fd4cb4898712ff68d7411b0c382de6d85bb6aab4c29f13ae305bd33fce31afd61662a108
data/.rubocop.yml CHANGED
@@ -9,6 +9,9 @@ Style/StringLiteralsInInterpolation:
9
9
  Enabled: true
10
10
  EnforcedStyle: double_quotes
11
11
 
12
+ Style/FrozenStringLiteralComment:
13
+ Enabled: false
14
+
12
15
  Layout/LineLength:
13
16
  Max: 120
14
17
 
@@ -21,5 +24,6 @@ Metrics/MethodLength:
21
24
  Metrics/AbcSize:
22
25
  Max: 30
23
26
 
24
- Style/FrozenStringLiteralComment:
25
- Enabled: false
27
+ Metrics/BlockLength:
28
+ Exclude:
29
+ - 'spec/**/*'
data/Gemfile CHANGED
@@ -9,3 +9,4 @@ gem "rake", "~> 13.0"
9
9
  gem "rspec", "~> 3.0"
10
10
  gem "rubocop", "~> 1.56"
11
11
  gem "steep"
12
+ gem "webmock"
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- simple_tweet (3.0.1)
4
+ simple_tweet (3.1.0)
5
5
  multipart-post (>= 2.2.3)
6
6
  oauth (~> 1.1.0)
7
7
 
@@ -13,13 +13,18 @@ GEM
13
13
  i18n (>= 1.6, < 2)
14
14
  minitest (>= 5.1)
15
15
  tzinfo (~> 2.0)
16
+ addressable (2.8.5)
17
+ public_suffix (>= 2.0.2, < 6.0)
16
18
  ast (2.4.2)
17
19
  base64 (0.1.1)
18
20
  concurrent-ruby (1.2.2)
21
+ crack (0.4.5)
22
+ rexml
19
23
  csv (3.2.7)
20
24
  diff-lcs (1.5.0)
21
25
  ffi (1.15.5)
22
26
  fileutils (1.7.1)
27
+ hashdiff (1.0.1)
23
28
  hashie (5.0.0)
24
29
  i18n (1.14.1)
25
30
  concurrent-ruby (~> 1.0)
@@ -41,6 +46,7 @@ GEM
41
46
  parser (3.2.2.3)
42
47
  ast (~> 2.4.1)
43
48
  racc
49
+ public_suffix (5.0.3)
44
50
  racc (1.7.1)
45
51
  rainbow (3.1.1)
46
52
  rake (13.0.6)
@@ -104,6 +110,10 @@ GEM
104
110
  concurrent-ruby (~> 1.0)
105
111
  unicode-display_width (2.4.2)
106
112
  version_gem (1.1.3)
113
+ webmock (3.19.1)
114
+ addressable (>= 2.8.0)
115
+ crack (>= 0.3.2)
116
+ hashdiff (>= 0.4.0, < 2.0.0)
107
117
 
108
118
  PLATFORMS
109
119
  arm64-darwin-21
@@ -115,6 +125,7 @@ DEPENDENCIES
115
125
  rubocop (~> 1.56)
116
126
  simple_tweet!
117
127
  steep
128
+ webmock
118
129
 
119
130
  BUNDLED WITH
120
131
  2.3.24
@@ -66,6 +66,21 @@ module SimpleTweet
66
66
  end
67
67
  end
68
68
 
69
+ def request_with_retry(req:, expected_status_code:, error_kind_message:, retry_count: 3)
70
+ res = request(req)
71
+ return res if expected_status_code === res.code # rubocop:disable Style/CaseEquality
72
+ raise UploadMediaError.new(error_kind_message, response: res) unless retry_count.positive?
73
+
74
+ @client = nil # reset client
75
+ sleep 1 << (3 - retry_count)
76
+ request_with_retry(
77
+ req: req,
78
+ expected_status_code: expected_status_code,
79
+ error_kind_message: error_kind_message,
80
+ retry_count: retry_count - 1
81
+ )
82
+ end
83
+
69
84
  # https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/api-reference/post-media-upload
70
85
  ## maybe todo: multiple image
71
86
  # ここはv1のAPIを叩いている。
@@ -88,55 +103,46 @@ module SimpleTweet
88
103
  total_bytes: video.size,
89
104
  media_type: "video/mp4"
90
105
  )
91
- init_res = request(init_req)
92
- raise UploadMediaError.new("init failed", response: init_res) unless init_res.code == "202"
93
-
106
+ init_res = request_with_retry(req: init_req, expected_status_code: "202", error_kind_message: "init failed")
94
107
  ::JSON.parse(init_res.body)
95
108
  end
96
109
 
97
- def append(video:, media_id:, index:, retry_count: 0)
98
- append_req = ::Net::HTTP::Post::Multipart.new(
110
+ def append(video:, media_id:, index:)
111
+ req = ::Net::HTTP::Post::Multipart.new(
99
112
  TW_MEDIA_UPLOAD_PATH,
100
113
  command: "APPEND",
101
114
  media_id: media_id,
102
115
  media: video.read(APPEND_PER),
103
116
  segment_index: index
104
117
  )
105
- res = request(append_req)
106
- return if res.code == "204"
107
- raise UploadMediaError.new("append failed", response: res) unless retry_count <= @max_append_retry_
108
-
109
- append(video: video, media_id: media_id, index: index, retry_count: retry_count + 1)
118
+ request_with_retry(req: req, expected_status_code: "204", error_kind_message: "append failed")
110
119
  end
111
120
 
112
121
  def finalize(media_id:)
113
- finalize_req = ::Net::HTTP::Post::Multipart.new(
122
+ req = ::Net::HTTP::Post::Multipart.new(
114
123
  TW_MEDIA_UPLOAD_PATH,
115
124
  command: "FINALIZE",
116
125
  media_id: media_id
117
126
  )
118
- finalize_res = request(finalize_req)
119
- raise UploadMediaError.new("finalize failed", response: finalize_res) unless finalize_res.code == "201"
120
-
121
- ::JSON.parse(finalize_res.body)
127
+ # finalizeは201が帰ってきてても、processing_infoにretry_afterが入っている場合がある(upload_video中で処理)
128
+ res = request_with_retry(req: req, expected_status_code: /^20\d$/, error_kind_message: "finalize failed")
129
+ ::JSON.parse(res.body)
122
130
  end
123
131
 
124
132
  def status(media_id:)
125
- status_req = ::Net::HTTP::Post::Multipart.new(
126
- TW_MEDIA_UPLOAD_PATH,
127
- command: "STATUS",
128
- media_id: media_id
129
- )
130
- status_res = request(status_req)
131
- raise UploadMediaError.new("status failed", response: status_res) unless status_res.code == "200"
132
-
133
- ::JSON.parse(status_res.body)
133
+ # https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/api-reference/get-media-upload-status
134
+ # これはGET
135
+ uri = ::URI.parse(TW_UPLOAD_ORIGIN + TW_MEDIA_UPLOAD_PATH)
136
+ uri.query = ::URI.encode_www_form(command: "STATUS", media_id: media_id)
137
+ req = ::Net::HTTP::Get.new(uri)
138
+ res = request_with_retry(req: req, expected_status_code: "200", error_kind_message: "status failed")
139
+ ::JSON.parse(res.body)
134
140
  end
135
141
 
136
142
  # https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/api-reference/post-media-upload-init
137
143
  def upload_video(video:)
138
144
  init_res = init(video: video)
139
- media_id = init_res["media_id_string"]
145
+ media_id = init_res["media_id_string"] # : String
140
146
 
141
147
  chunks_needed = (video.size - 1) / APPEND_PER + 1
142
148
  chunks_needed.times do |i|
@@ -171,10 +177,7 @@ module SimpleTweet
171
177
  header = { "content-type" => "application/json; charset=UTF-8" } # : ::Hash[::String, ::String]
172
178
  req = ::Net::HTTP::Post.new(TW_METADATA_CREATE_PATH, header)
173
179
  req.body = { media_id: media_id, alt_text: { text: alt_text } }.to_json
174
- res = request(req)
175
- raise UploadMediaError.new("create_media_metadata failed", response: res) if res.code != "200"
176
-
177
- res
180
+ request_with_retry(req: req, expected_status_code: "200", error_kind_message: "create_media_metadata failed")
178
181
  end
179
182
  end
180
183
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleTweet
4
- VERSION = "3.0.1"
4
+ VERSION = "3.1.0"
5
5
  end
data/sig/simple_tweet.rbs CHANGED
@@ -12,8 +12,8 @@ module SimpleTweet
12
12
  APPEND_PER: Integer
13
13
 
14
14
  def initialize: (consumer_key: String, consumer_secret: String, access_token: String, access_token_secret: String, ?max_append_retry: Integer) -> void
15
- def tweet: (message: String, ?media_ids: Array[String]) -> untyped
16
- def tweet_with_media: (message: String, media_type: String, media: untyped, ?alt_text: String?) -> untyped
15
+ def tweet: (message: String, ?media_ids: Array[String]) -> Net::HTTPResponse
16
+ def tweet_with_media: (message: String, media_type: String, media: untyped, ?alt_text: String?) -> Net::HTTPResponse
17
17
 
18
18
  @consumer_key_: String
19
19
  @consumer_secret_: String
@@ -24,14 +24,15 @@ module SimpleTweet
24
24
 
25
25
  private
26
26
  def access_token: (?site: String) -> untyped
27
- def request: (untyped req) -> untyped
28
- def upload_media: (media_type: untyped, media: untyped) -> [untyped]
29
- def init: (video: untyped) -> untyped
30
- def append: (video: untyped, media_id: untyped, index: untyped, ?retry_count: Integer) -> nil
31
- def finalize: (media_id: untyped) -> untyped
32
- def status: (media_id: untyped) -> untyped
33
- def upload_video: (video: untyped) -> [untyped]
34
- def create_media_metadata: (media_id: String, alt_text: String?) -> untyped
27
+ def request: (Net::HTTPRequest req) -> Net::HTTPResponse
28
+ def request_with_retry: (req: Net::HTTPRequest, expected_status_code: String | Regexp, error_kind_message: String, ?retry_count: Integer) -> Net::HTTPResponse
29
+ def upload_media: (media_type: String, media: untyped) -> [String]
30
+ def init: (video: untyped) -> Hash[String, untyped]
31
+ def append: (video: untyped, media_id: String, index: untyped) -> Net::HTTPResponse
32
+ def finalize: (media_id: String) -> Hash[String, untyped]
33
+ def status: (media_id: String) -> Hash[String, untyped]
34
+ def upload_video: (video: untyped) -> [String]
35
+ def create_media_metadata: (media_id: String, alt_text: String?) -> Net::HTTPResponse
35
36
  end
36
37
  end
37
38
 
@@ -39,7 +40,7 @@ module SimpleTweet
39
40
  end
40
41
 
41
42
  class UploadMediaError < Error
42
- attr_reader response: nil
43
- def initialize: (?String? message, ?response: nil) -> void
43
+ attr_reader response: Net::HTTPResponse?
44
+ def initialize: (?String? message, ?response: Net::HTTPResponse?) -> void
44
45
  end
45
46
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_tweet
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.1
4
+ version: 3.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Kugayama Nana
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2023-09-13 00:00:00.000000000 Z
11
+ date: 2023-12-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: multipart-post