simple_tweet 3.0.0 → 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: cb994313a55f3a80782b1c73c983a7551fa2a394f49aa5149efdf59372d20d40
4
- data.tar.gz: 2dff9773d979e4f907b1ad37072adc59d30d13c64d73ed26a004032a50cc2456
3
+ metadata.gz: eda2472eda06f1ddc2348a30e194c498e0cd9998036e7dabdbdee4850e1098dc
4
+ data.tar.gz: 50c944ffd64e0f687f968d254389bd2fab8b521b959c5433fbe2aecfe772507e
5
5
  SHA512:
6
- metadata.gz: e5425884322fcb27da54bf4747c709ad412c9479daf0fd0b040209dbbec8be6f5d930505b4a72c85dabbef8a55b5817b5f5d83f7be2a8255d4e2aaa9253ec4e3
7
- data.tar.gz: 31fb1439304050a6038b19ce25520795eb3588ebcdfe29b75b1249adbbdfff932f79833c131ef3492ff784599f2e4e3301222f7885784d60de2a634652d6cbef
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
 
@@ -20,3 +23,7 @@ Metrics/MethodLength:
20
23
 
21
24
  Metrics/AbcSize:
22
25
  Max: 30
26
+
27
+ Metrics/BlockLength:
28
+ Exclude:
29
+ - 'spec/**/*'
data/Gemfile CHANGED
@@ -8,3 +8,5 @@ gemspec
8
8
  gem "rake", "~> 13.0"
9
9
  gem "rspec", "~> 3.0"
10
10
  gem "rubocop", "~> 1.56"
11
+ gem "steep"
12
+ gem "webmock"
data/Gemfile.lock CHANGED
@@ -1,19 +1,40 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- simple_tweet (3.0.0)
4
+ simple_tweet (3.1.0)
5
5
  multipart-post (>= 2.2.3)
6
6
  oauth (~> 1.1.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
+ activesupport (7.0.8)
12
+ concurrent-ruby (~> 1.0, >= 1.0.2)
13
+ i18n (>= 1.6, < 2)
14
+ minitest (>= 5.1)
15
+ tzinfo (~> 2.0)
16
+ addressable (2.8.5)
17
+ public_suffix (>= 2.0.2, < 6.0)
11
18
  ast (2.4.2)
12
19
  base64 (0.1.1)
20
+ concurrent-ruby (1.2.2)
21
+ crack (0.4.5)
22
+ rexml
23
+ csv (3.2.7)
13
24
  diff-lcs (1.5.0)
25
+ ffi (1.15.5)
26
+ fileutils (1.7.1)
27
+ hashdiff (1.0.1)
14
28
  hashie (5.0.0)
29
+ i18n (1.14.1)
30
+ concurrent-ruby (~> 1.0)
15
31
  json (2.6.3)
16
32
  language_server-protocol (3.17.0.3)
33
+ listen (3.8.0)
34
+ rb-fsevent (~> 0.10, >= 0.10.3)
35
+ rb-inotify (~> 0.9, >= 0.9.10)
36
+ logger (1.5.3)
37
+ minitest (5.20.0)
17
38
  multipart-post (2.3.0)
18
39
  oauth (1.1.0)
19
40
  oauth-tty (~> 1.0, >= 1.0.1)
@@ -25,9 +46,14 @@ GEM
25
46
  parser (3.2.2.3)
26
47
  ast (~> 2.4.1)
27
48
  racc
49
+ public_suffix (5.0.3)
28
50
  racc (1.7.1)
29
51
  rainbow (3.1.1)
30
52
  rake (13.0.6)
53
+ rb-fsevent (0.11.2)
54
+ rb-inotify (0.10.1)
55
+ ffi (~> 1.0)
56
+ rbs (3.2.1)
31
57
  regexp_parser (2.8.1)
32
58
  rexml (3.2.6)
33
59
  rspec (3.12.0)
@@ -58,20 +84,48 @@ GEM
58
84
  rubocop-ast (1.29.0)
59
85
  parser (>= 3.2.1.0)
60
86
  ruby-progressbar (1.13.0)
87
+ securerandom (0.2.2)
61
88
  snaky_hash (2.0.1)
62
89
  hashie
63
90
  version_gem (~> 1.1, >= 1.1.1)
91
+ steep (1.5.3)
92
+ activesupport (>= 5.1)
93
+ concurrent-ruby (>= 1.1.10)
94
+ csv (>= 3.0.9)
95
+ fileutils (>= 1.1.0)
96
+ json (>= 2.1.0)
97
+ language_server-protocol (>= 3.15, < 4.0)
98
+ listen (~> 3.0)
99
+ logger (>= 1.3.0)
100
+ parser (>= 3.1)
101
+ rainbow (>= 2.2.2, < 4.0)
102
+ rbs (>= 3.1.0)
103
+ securerandom (>= 0.1)
104
+ strscan (>= 1.0.0)
105
+ terminal-table (>= 2, < 4)
106
+ strscan (3.0.6)
107
+ terminal-table (3.0.2)
108
+ unicode-display_width (>= 1.1.1, < 3)
109
+ tzinfo (2.0.6)
110
+ concurrent-ruby (~> 1.0)
64
111
  unicode-display_width (2.4.2)
65
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)
66
117
 
67
118
  PLATFORMS
68
119
  arm64-darwin-21
120
+ x86_64-linux
69
121
 
70
122
  DEPENDENCIES
71
123
  rake (~> 13.0)
72
124
  rspec (~> 3.0)
73
125
  rubocop (~> 1.56)
74
126
  simple_tweet!
127
+ steep
128
+ webmock
75
129
 
76
130
  BUNDLED WITH
77
131
  2.3.24
data/Steepfile ADDED
@@ -0,0 +1,11 @@
1
+ D = Steep::Diagnostic
2
+
3
+ target :lib do
4
+ signature "sig"
5
+ check "lib"
6
+ library "net-http"
7
+
8
+ configure_code_diagnostics(D::Ruby.strict) do |config|
9
+ config[D::Ruby::UnknownConstant] = :information
10
+ end
11
+ end
@@ -27,7 +27,7 @@ module SimpleTweet
27
27
 
28
28
  # https://developer.twitter.com/en/docs/twitter-api/tweets/manage-tweets/migrate
29
29
  def tweet(message:, media_ids: [])
30
- json = { text: message }
30
+ json = { text: message } # : ::Hash[::Symbol, (::String|::Hash[::Symbol, ::Array[::String]])]
31
31
  json[:media] = { media_ids: media_ids } unless media_ids.empty?
32
32
  header = { "User-Agent": UA, "content-type": "application/json" }
33
33
  access_token.post(TW_TWEET_PATH, json.to_json, header)
@@ -55,7 +55,10 @@ module SimpleTweet
55
55
  @client.sign! req
56
56
 
57
57
  url = ::URI.parse(TW_UPLOAD_ORIGIN + TW_MEDIA_UPLOAD_PATH)
58
- https = ::Net::HTTP.new(url.host, url.port)
58
+ https = ::Net::HTTP.new(
59
+ url.host, # : ::String
60
+ url.port
61
+ )
59
62
  https.use_ssl = true
60
63
 
61
64
  https.start do |http|
@@ -63,6 +66,21 @@ module SimpleTweet
63
66
  end
64
67
  end
65
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
+
66
84
  # https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/api-reference/post-media-upload
67
85
  ## maybe todo: multiple image
68
86
  # ここはv1のAPIを叩いている。
@@ -85,55 +103,46 @@ module SimpleTweet
85
103
  total_bytes: video.size,
86
104
  media_type: "video/mp4"
87
105
  )
88
- init_res = request(init_req)
89
- raise UploadMediaError.new("init failed", response: init_res) unless init_res.code == "202"
90
-
106
+ init_res = request_with_retry(req: init_req, expected_status_code: "202", error_kind_message: "init failed")
91
107
  ::JSON.parse(init_res.body)
92
108
  end
93
109
 
94
- def append(video:, media_id:, index:, retry_count: 0)
95
- append_req = ::Net::HTTP::Post::Multipart.new(
110
+ def append(video:, media_id:, index:)
111
+ req = ::Net::HTTP::Post::Multipart.new(
96
112
  TW_MEDIA_UPLOAD_PATH,
97
113
  command: "APPEND",
98
114
  media_id: media_id,
99
115
  media: video.read(APPEND_PER),
100
116
  segment_index: index
101
117
  )
102
- res = request(append_req)
103
- return if res.code == "204"
104
- raise UploadMediaError.new("append failed", response: res) unless retry_count <= @max_append_retry_
105
-
106
- 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")
107
119
  end
108
120
 
109
121
  def finalize(media_id:)
110
- finalize_req = ::Net::HTTP::Post::Multipart.new(
122
+ req = ::Net::HTTP::Post::Multipart.new(
111
123
  TW_MEDIA_UPLOAD_PATH,
112
124
  command: "FINALIZE",
113
125
  media_id: media_id
114
126
  )
115
- finalize_res = request(finalize_req)
116
- raise UploadMediaError.new("finalize failed", response: finalize_res) unless finalize_res.code == "201"
117
-
118
- ::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)
119
130
  end
120
131
 
121
132
  def status(media_id:)
122
- status_req = ::Net::HTTP::Post::Multipart.new(
123
- TW_MEDIA_UPLOAD_PATH,
124
- command: "STATUS",
125
- media_id: media_id
126
- )
127
- status_res = request(status_req)
128
- raise UploadMediaError.new("status failed", response: status_res) unless status_res.code == "200"
129
-
130
- ::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)
131
140
  end
132
141
 
133
142
  # https://developer.twitter.com/en/docs/twitter-api/v1/media/upload-media/api-reference/post-media-upload-init
134
143
  def upload_video(video:)
135
144
  init_res = init(video: video)
136
- media_id = init_res["media_id_string"]
145
+ media_id = init_res["media_id_string"] # : String
137
146
 
138
147
  chunks_needed = (video.size - 1) / APPEND_PER + 1
139
148
  chunks_needed.times do |i|
@@ -165,13 +174,10 @@ module SimpleTweet
165
174
  end
166
175
 
167
176
  def create_media_metadata(media_id:, alt_text:)
168
- header = { "content-type": "application/json; charset=UTF-8" }
177
+ header = { "content-type" => "application/json; charset=UTF-8" } # : ::Hash[::String, ::String]
169
178
  req = ::Net::HTTP::Post.new(TW_METADATA_CREATE_PATH, header)
170
179
  req.body = { media_id: media_id, alt_text: { text: alt_text } }.to_json
171
- res = request(req)
172
- raise UploadMediaError.new("create_media_metadata failed", response: res) if res.code != "200"
173
-
174
- res
180
+ request_with_retry(req: req, expected_status_code: "200", error_kind_message: "create_media_metadata failed")
175
181
  end
176
182
  end
177
183
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module SimpleTweet
4
- VERSION = "3.0.0"
4
+ VERSION = "3.1.0"
5
5
  end
data/lib/simple_tweet.rb CHANGED
@@ -11,7 +11,7 @@ module SimpleTweet
11
11
  attr_reader :response
12
12
 
13
13
  def initialize(message = nil, response: nil)
14
- super(message)
14
+ super(message) unless message.nil?
15
15
  @response = response
16
16
  end
17
17
  end
@@ -0,0 +1,50 @@
1
+ ---
2
+ sources:
3
+ - type: git
4
+ name: ruby/gem_rbs_collection
5
+ revision: 248499a924c3cb331d40ca667d40528814043788
6
+ remote: https://github.com/ruby/gem_rbs_collection.git
7
+ repo_dir: gems
8
+ path: ".gem_rbs_collection"
9
+ gems:
10
+ - name: ast
11
+ version: '2.4'
12
+ source:
13
+ type: git
14
+ name: ruby/gem_rbs_collection
15
+ revision: 248499a924c3cb331d40ca667d40528814043788
16
+ remote: https://github.com/ruby/gem_rbs_collection.git
17
+ repo_dir: gems
18
+ - name: base64
19
+ version: '0'
20
+ source:
21
+ type: stdlib
22
+ - name: hashie
23
+ version: '5.0'
24
+ source:
25
+ type: git
26
+ name: ruby/gem_rbs_collection
27
+ revision: 248499a924c3cb331d40ca667d40528814043788
28
+ remote: https://github.com/ruby/gem_rbs_collection.git
29
+ repo_dir: gems
30
+ - name: json
31
+ version: '0'
32
+ source:
33
+ type: stdlib
34
+ - name: parallel
35
+ version: '1.20'
36
+ source:
37
+ type: git
38
+ name: ruby/gem_rbs_collection
39
+ revision: 248499a924c3cb331d40ca667d40528814043788
40
+ remote: https://github.com/ruby/gem_rbs_collection.git
41
+ repo_dir: gems
42
+ - name: rainbow
43
+ version: '3.0'
44
+ source:
45
+ type: git
46
+ name: ruby/gem_rbs_collection
47
+ revision: 248499a924c3cb331d40ca667d40528814043788
48
+ remote: https://github.com/ruby/gem_rbs_collection.git
49
+ repo_dir: gems
50
+ gemfile_lock_path: Gemfile.lock
@@ -0,0 +1,17 @@
1
+ sources:
2
+ - type: git
3
+ name: ruby/gem_rbs_collection
4
+ remote: https://github.com/ruby/gem_rbs_collection.git
5
+ revision: main
6
+ repo_dir: gems
7
+
8
+ # A directory to install the downloaded RBSs
9
+ path: .gem_rbs_collection
10
+
11
+ gems:
12
+ # Skip loading rbs gem's RBS.
13
+ # It's unnecessary if you don't use rbs as a library.
14
+ - name: rbs
15
+ ignore: true
16
+ - name: steep
17
+ ignore: true
data/sig/simple_tweet.rbs CHANGED
@@ -1,4 +1,46 @@
1
1
  module SimpleTweet
2
2
  VERSION: String
3
- # See the writing guide of rbs: https://github.com/ruby/rbs#guides
3
+
4
+ module V2
5
+ class Client
6
+ TW_API_ORIGIN: String
7
+ TW_UPLOAD_ORIGIN: String
8
+ TW_MEDIA_UPLOAD_PATH: String
9
+ TW_METADATA_CREATE_PATH: String
10
+ TW_TWEET_PATH: String
11
+ UA: String
12
+ APPEND_PER: Integer
13
+
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]) -> Net::HTTPResponse
16
+ def tweet_with_media: (message: String, media_type: String, media: untyped, ?alt_text: String?) -> Net::HTTPResponse
17
+
18
+ @consumer_key_: String
19
+ @consumer_secret_: String
20
+ @access_token_: String
21
+ @access_token_secret_: String
22
+ @max_append_retry_: Integer
23
+ @client: untyped # ::OAuth::AccessToken
24
+
25
+ private
26
+ def access_token: (?site: 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
36
+ end
37
+ end
38
+
39
+ class Error < StandardError
40
+ end
41
+
42
+ class UploadMediaError < Error
43
+ attr_reader response: Net::HTTPResponse?
44
+ def initialize: (?String? message, ?response: Net::HTTPResponse?) -> void
45
+ end
4
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.0
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
@@ -53,9 +53,12 @@ files:
53
53
  - LICENSE.txt
54
54
  - README.md
55
55
  - Rakefile
56
+ - Steepfile
56
57
  - lib/simple_tweet.rb
57
58
  - lib/simple_tweet/v2_client.rb
58
59
  - lib/simple_tweet/version.rb
60
+ - rbs_collection.lock.yaml
61
+ - rbs_collection.yaml
59
62
  - sig/simple_tweet.rbs
60
63
  - simple_tweet.gemspec
61
64
  homepage: https://github.com/nota/simple_tweet