simple_tweet 3.0.0 → 3.1.0

Sign up to get free protection for your applications and to get access to all the features.
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