tiktok-open-sdk 0.4.0 → 0.5.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: 804836be4e23b6a46c29c263b7b6d802cd2e6a70c61ed02a8f70328715649236
4
- data.tar.gz: d2dee367fb303f07078a5e07a5a303f163db4895bb3e7468bbdeb2678308e1db
3
+ metadata.gz: ea350ded46bc468a3b86a72f539c12a36ecc960b1e2476ac7e59c2c52424d8f1
4
+ data.tar.gz: 07fa578800d4d03d9431c39b043008d2185ed62ed2f93c8c20feea8bb331736d
5
5
  SHA512:
6
- metadata.gz: 860dfd7da6a964785d661f1e6c9b2fd84bb324f1c8511207c0b3f981239b5d361490b8c410f31d0600bd5b4302c21b3b0cc69e370ad80814c1dc24c05b03ab06
7
- data.tar.gz: 7707f1602f9c088c7d84aff5c20101138fd30e9bfb91569f13062c7e56591361fe4b1ecff06ee6b26b82ee89f362ffb2b5244fb4823c7989b8d9c125df9f9bd2
6
+ metadata.gz: 61e3742ea46ddeb02a8a168d3485c7ecc7632698c6c533364e392b67058f6a5d7e325e0e546eebe9eee915070e309981dc8707aca7ff67097dfadd74610977d0
7
+ data.tar.gz: f19aa49f93036f0b02f0d5613d76b7bd86e7a00457a3642569c3f266ac895720a4106e7df27fec6f215581ccfd6fcedb71ac68638c83fdddcfc0dca8b56d5052
data/.rubocop.yml CHANGED
@@ -30,7 +30,7 @@ Style/ModuleFunction:
30
30
  Enabled: false
31
31
 
32
32
  RSpec/NestedGroups:
33
- Max: 4
33
+ Max: 5
34
34
 
35
35
  RSpec/MultipleExpectations:
36
36
  Max: 5
data/CHANGELOG.md CHANGED
@@ -4,7 +4,9 @@ All notable changes to this project will be documented in this file.
4
4
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
5
5
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
- ## [Unreleased]
7
+ ## [0.5.0] - 2026-02-14
8
+ ### Added
9
+ - **Post API: video_init** - Initialize a video publish to obtain an upload URL (file upload) or to start a pull-from-URL flow. Accepts `access_token` and `params` (post_info, source_info). Optional config: `video_init_url`.
8
10
 
9
11
  ## [0.4.0] - 2025-10-06
10
12
  ### Added
data/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # TikTok Open SDK
2
2
 
3
- [![Gem Version](https://img.shields.io/badge/gem-v0.4.0-blue.svg)](https://rubygems.org/gems/tiktok-open-sdk)
3
+ [![Gem Version](https://img.shields.io/badge/gem-v0.5.0-blue.svg)](https://rubygems.org/gems/tiktok-open-sdk)
4
4
  [![Ruby Version](https://img.shields.io/badge/ruby-%3E%3D%203.0.0-red.svg)](https://www.ruby-lang.org/en/downloads/)
5
5
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE.txt)
6
6
  [![CI](https://github.com/pochkuntaras/tiktok-open-sdk/actions/workflows/main.yml/badge.svg)](https://github.com/pochkuntaras/tiktok-open-sdk/actions/workflows/main.yml)
@@ -59,6 +59,7 @@ Tiktok::Open::Sdk.configure do |config|
59
59
  config.user_auth.revoke_token_url = 'https://open.tiktokapis.com/v2/oauth/revoke/'
60
60
  config.user_info_url = 'https://open.tiktokapis.com/v2/user/info/'
61
61
  config.creator_info_query_url = 'https://open.tiktokapis.com/v2/post/publish/creator_info/query/'
62
+ config.video_init_url = 'https://open.tiktokapis.com/v2/post/publish/video/init/'
62
63
 
63
64
  # Optional: Enable OmniAuth strategy auto-loading
64
65
  config.load_omniauth = true
@@ -188,6 +189,40 @@ else
188
189
  end
189
190
  ```
190
191
 
192
+ #### Video Init
193
+
194
+ Initialize a video publish to obtain an upload URL (for file upload) or to start a pull-from-URL flow:
195
+
196
+ ```ruby
197
+ params = {
198
+ post_info: {
199
+ title: 'My video #tiktok',
200
+ privacy_level: 'SELF_ONLY',
201
+ disable_duet: false,
202
+ disable_comment: false,
203
+ disable_stitch: false,
204
+ video_cover_timestamp_ms: 1000
205
+ },
206
+ source_info: {
207
+ source: 'FILE_UPLOAD',
208
+ video_type: 'video/mp4',
209
+ video_size: 7_340_032,
210
+ chunk_size: 7_340_032,
211
+ total_chunk_count: 1
212
+ }
213
+ }
214
+
215
+ response = Tiktok::Open::Sdk.post.video_init(access_token: access_token, params: params)
216
+
217
+ if response[:success]
218
+ publish_id = response[:response][:data][:publish_id]
219
+ upload_url = response[:response][:data][:upload_url]
220
+ # Use upload_url to upload video chunks (FILE_UPLOAD) or proceed with PULL_FROM_URL flow
221
+ else
222
+ puts "Error: #{response[:response][:error][:message]}"
223
+ end
224
+ ```
225
+
191
226
  ### Using the User API
192
227
 
193
228
  The SDK provides a convenient way to access user information:
@@ -428,6 +463,8 @@ Tiktok::Open::Sdk.configure do |config|
428
463
  config.user_auth.scopes = %w[user.info.basic] # Optional
429
464
  config.user_auth.redirect_uri = 'https://...' # Optional
430
465
  config.user_info_url = 'https://open.tiktokapis.com/v2/user/info/' # Optional
466
+ config.creator_info_query_url = 'https://open.tiktokapis.com/v2/post/publish/creator_info/query/' # Optional
467
+ config.video_init_url = 'https://open.tiktokapis.com/v2/post/publish/video/init/' # Optional
431
468
  end
432
469
  ```
433
470
 
@@ -543,6 +580,24 @@ Queries creator information from the TikTok Open API for video publishing.
543
580
  - `max_video_post_duration_sec` - Maximum video duration in seconds
544
581
  - `privacy_level_options` - Available privacy level options
545
582
 
583
+ #### `video_init(access_token:, params: {})`
584
+
585
+ Initializes a video publish and returns a publish ID and upload URL (for file upload) or starts a pull-from-URL flow.
586
+
587
+ **Parameters:**
588
+ - `access_token` (String, required) - OAuth2 access token for authentication
589
+ - `params` (Hash, required) - Request body with `post_info` and `source_info`
590
+ - `post_info` - Post metadata (title, privacy_level, disable_duet, disable_comment, disable_stitch, video_cover_timestamp_ms, etc.)
591
+ - `source_info` - Video source (e.g. `source: 'FILE_UPLOAD'` with video_size, chunk_size, total_chunk_count, video_type; or `source: 'PULL_FROM_URL'` with video_url)
592
+
593
+ **Returns:** Hash with `:success`, `:code`, and `:response` keys
594
+
595
+ **Response Data (on success):**
596
+ - `data.publish_id` - Publish session ID
597
+ - `data.upload_url` - URL for uploading video chunks (when using FILE_UPLOAD)
598
+
599
+ **Raises:** `Tiktok::Open::Sdk::RequestValidationError` if access token is invalid or params fail validation
600
+
546
601
  ### HTTP Client
547
602
 
548
603
  #### `request(method, url, params: {}, headers: {}, body: nil)`
@@ -33,6 +33,10 @@ module Tiktok
33
33
  # @return [String] TikTok Query Creator Info endpoint URL.
34
34
  attr_accessor :creator_info_query_url
35
35
 
36
+ # @!attribute [rw] video_init_url
37
+ # @return [String] TikTok Video Init endpoint URL.
38
+ attr_accessor :video_init_url
39
+
36
40
  # @!attribute [rw] user_auth
37
41
  # @return [UserAuth] User authentication configuration.
38
42
  attr_accessor :user_auth
@@ -45,6 +49,7 @@ module Tiktok
45
49
  def initialize
46
50
  @user_info_url = "#{OPEN_API_BASE_URL}/v2/user/info/"
47
51
  @creator_info_query_url = "#{OPEN_API_BASE_URL}/v2/post/publish/creator_info/query/"
52
+ @video_init_url = "#{OPEN_API_BASE_URL}/v2/post/publish/video/init/"
48
53
  @user_auth = UserAuth.new
49
54
  @load_omniauth = false
50
55
  end
@@ -0,0 +1,178 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tiktok
4
+ module Open
5
+ module Sdk
6
+ module Helpers
7
+ module Validators
8
+ # Validates post information for TikTok video publishing.
9
+ #
10
+ # This module provides validation methods for post-related parameters including
11
+ # privacy level, title, boolean flags, and video cover timestamp.
12
+ #
13
+ # @example Including the validator in a class
14
+ # class VideoPublisher
15
+ # include Tiktok::Open::Sdk::Helpers::Validators::PostInfoValidator
16
+ #
17
+ # def publish(post_info)
18
+ # validate_post_info!(post_info)
19
+ # # proceed with publishing
20
+ # end
21
+ # end
22
+ #
23
+ # @example Validating post information
24
+ # post_info = {
25
+ # privacy_level: 'PUBLIC_TO_EVERYONE',
26
+ # title: 'My awesome video',
27
+ # disable_duet: false,
28
+ # brand_content_toggle: true
29
+ # }
30
+ # validate_post_info!(post_info)
31
+ module PostInfoValidator
32
+ # Valid privacy level options for TikTok videos
33
+ PRIVACY_LEVEL_OPTIONS = %w[
34
+ PUBLIC_TO_EVERYONE
35
+ MUTUAL_FOLLOW_FRIENDS
36
+ FOLLOWER_OF_CREATOR
37
+ SELF_ONLY
38
+ ].freeze
39
+
40
+ # Maximum allowed length for video title
41
+ MAX_TITLE_LENGTH = 2200
42
+
43
+ # Validates post information and raises an error if invalid.
44
+ #
45
+ # @param post_info [Hash, nil] The post information to validate
46
+ # @option post_info [String] :privacy_level Required. Must be one of PRIVACY_LEVEL_OPTIONS
47
+ # @option post_info [String] :title Optional. Maximum 2200 characters
48
+ # @option post_info [Boolean] :disable_duet Optional. Boolean flag
49
+ # @option post_info [Boolean] :disable_stitch Optional. Boolean flag
50
+ # @option post_info [Boolean] :disable_comment Optional. Boolean flag
51
+ # @option post_info [Boolean] :brand_content_toggle Optional. Boolean flag
52
+ # @option post_info [Boolean] :brand_organic_toggle Optional. Boolean flag
53
+ # @option post_info [Boolean] :is_aigc Optional. Boolean flag
54
+ # @option post_info [Integer] :video_cover_timestamp_ms Optional. Non-negative integer
55
+ #
56
+ # @return [void]
57
+ # @raise [Tiktok::Open::Sdk::RequestValidationError] If validation fails
58
+ #
59
+ # @example Valid post information
60
+ # validate_post_info!(privacy_level: 'PUBLIC_TO_EVERYONE')
61
+ #
62
+ # @example Invalid privacy level
63
+ # validate_post_info!(privacy_level: 'INVALID')
64
+ # # => raises RequestValidationError with privacy_level error
65
+ def validate_post_info!(post_info)
66
+ errors = {}
67
+
68
+ validate_post_info(post_info, errors)
69
+
70
+ raise_validation_errors!(errors)
71
+ end
72
+
73
+ private
74
+
75
+ # Raises validation errors if any exist.
76
+ #
77
+ # @param errors [Hash] The accumulated validation errors
78
+ # @return [void]
79
+ # @raise [Tiktok::Open::Sdk::RequestValidationError] If errors is not empty
80
+ def raise_validation_errors!(errors)
81
+ raise ::Tiktok::Open::Sdk::RequestValidationError, errors unless errors.empty?
82
+ end
83
+
84
+ # Validates post information and accumulates errors.
85
+ #
86
+ # @param post_info [Hash, nil] The post information to validate
87
+ # @param errors [Hash] The hash to accumulate errors into
88
+ # @return [void]
89
+ def validate_post_info(post_info, errors)
90
+ return if post_info.nil?
91
+ return add_error errors, :post_info, 'must be a Hash' unless post_info.is_a?(Hash)
92
+
93
+ privacy_level = post_info[:privacy_level]
94
+ title = post_info[:title]
95
+ timestamp = post_info[:video_cover_timestamp_ms]
96
+
97
+ validate_privacy_level! privacy_level, errors
98
+ validate_title! title, errors
99
+ validate_boolean_fields! post_info, errors
100
+ validate_video_cover_timestamp! timestamp, errors
101
+ end
102
+
103
+ # Validates that privacy level is one of the allowed options.
104
+ #
105
+ # @param privacy_level [String, nil] The privacy level to validate
106
+ # @param errors [Hash] The hash to accumulate errors into
107
+ # @return [void]
108
+ def validate_privacy_level!(privacy_level, errors)
109
+ return if PRIVACY_LEVEL_OPTIONS.include?(privacy_level)
110
+
111
+ add_error errors, :privacy_level, "must be one of: #{PRIVACY_LEVEL_OPTIONS.join(", ")}"
112
+ end
113
+
114
+ # Validates video title length and type.
115
+ #
116
+ # @param title [String, nil] The title to validate
117
+ # @param errors [Hash] The hash to accumulate errors into
118
+ # @return [void]
119
+ def validate_title!(title, errors)
120
+ return if title.nil?
121
+ return add_error errors, :title, 'must be a String' unless title.is_a?(String)
122
+ return unless title.length > MAX_TITLE_LENGTH
123
+
124
+ add_error errors, :title, "must be less than #{MAX_TITLE_LENGTH} characters"
125
+ end
126
+
127
+ # Validates that boolean fields contain boolean values.
128
+ #
129
+ # @param post_info [Hash] The post information containing boolean fields
130
+ # @param errors [Hash] The hash to accumulate errors into
131
+ # @return [void]
132
+ def validate_boolean_fields!(post_info, errors)
133
+ boolean_fields = %i[
134
+ disable_duet
135
+ disable_stitch
136
+ disable_comment
137
+ brand_content_toggle
138
+ brand_organic_toggle
139
+ is_aigc
140
+ ]
141
+
142
+ boolean_fields.each do |field|
143
+ next unless post_info.key?(field)
144
+
145
+ value = post_info[field]
146
+ next if value.is_a?(TrueClass) || value.is_a?(FalseClass)
147
+
148
+ add_error errors, field, 'must be a boolean (true or false)'
149
+ end
150
+ end
151
+
152
+ # Validates video cover timestamp is a non-negative integer.
153
+ #
154
+ # @param timestamp [Integer, nil] The timestamp to validate
155
+ # @param errors [Hash] The hash to accumulate errors into
156
+ # @return [void]
157
+ def validate_video_cover_timestamp!(timestamp, errors)
158
+ return if timestamp.nil? || (timestamp.is_a?(Integer) && timestamp >= 0)
159
+
160
+ add_error errors, :video_cover_timestamp_ms, 'must be a non-negative integer'
161
+ end
162
+
163
+ # Adds an error message to the errors hash.
164
+ #
165
+ # @param errors [Hash] The hash to accumulate errors into
166
+ # @param field_name [Symbol] The field name that has an error
167
+ # @param message [String] The error message
168
+ # @return [Hash] The errors hash
169
+ def add_error(errors, field_name, message)
170
+ errors[field_name] ||= [] << message
171
+ errors
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
178
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'post_info_validator'
4
+ require_relative 'source_info_validator'
5
+
6
+ module Tiktok
7
+ module Open
8
+ module Sdk
9
+ module Helpers
10
+ module Validators
11
+ # Provides validation for video publishing initialization parameters.
12
+ #
13
+ # This module combines and applies the `PostInfoValidator` and `SourceInfoValidator` logic
14
+ # for validating `post_info` and `source_info` input hashes typically required for
15
+ # TikTok Open SDK video publishing workflows.
16
+ #
17
+ # @example Including and using PostPublishValidator
18
+ # class Publisher
19
+ # include Tiktok::Open::Sdk::Helpers::Validators::PostPublishValidator
20
+ #
21
+ # def publish_video(params)
22
+ # validate_video_init_info!(params)
23
+ # # ...proceed if valid
24
+ # end
25
+ # end
26
+ #
27
+ # @see PostInfoValidator#validate_post_info
28
+ # @see SourceInfoValidator#validate_source_info
29
+ module PostPublishValidator
30
+ include PostInfoValidator
31
+ include SourceInfoValidator
32
+
33
+ # Validates combined video initialization parameters.
34
+ #
35
+ # Both `post_info` and `source_info` sub-hashes are validated using the appropriate
36
+ # validators. If any errors occur, a RequestValidationError (or similar) is raised.
37
+ #
38
+ # @param params [Hash] The full parameter hash.
39
+ # @option params [Hash] :post_info Info for video post, validated by PostInfoValidator
40
+ # @option params [Hash] :source_info Info on video source, validated by SourceInfoValidator
41
+ #
42
+ # @raise [RequestValidationError] Raised if any validation errors found in either section.
43
+ # @return [void]
44
+ def validate_video_init_info!(params)
45
+ errors = { post_info: {}, source_info: {} }
46
+
47
+ validate_post_info params[:post_info], errors[:post_info]
48
+ validate_source_info params[:source_info], errors[:source_info]
49
+
50
+ raise_validation_errors!(errors) unless errors.values.all?(&:empty?)
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,186 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tiktok
4
+ module Open
5
+ module Sdk
6
+ module Helpers
7
+ module Validators
8
+ # Validates source information for TikTok video publishing.
9
+ #
10
+ # This module provides validation methods for video source parameters including
11
+ # source type (PULL_FROM_URL or FILE_UPLOAD) and their respective required fields.
12
+ #
13
+ # @example Including the validator in a class
14
+ # class VideoPublisher
15
+ # include Tiktok::Open::Sdk::Helpers::Validators::SourceInfoValidator
16
+ #
17
+ # def publish(source_info)
18
+ # validate_source_info!(source_info)
19
+ # # proceed with publishing
20
+ # end
21
+ # end
22
+ #
23
+ # @example Validating PULL_FROM_URL source
24
+ # source_info = {
25
+ # source: 'PULL_FROM_URL',
26
+ # video_url: 'https://example.com/video.mp4'
27
+ # }
28
+ # validate_source_info!(source_info)
29
+ #
30
+ # @example Validating FILE_UPLOAD source
31
+ # source_info = {
32
+ # source: 'FILE_UPLOAD',
33
+ # video_size: 10_485_760,
34
+ # chunk_size: 1_048_576,
35
+ # total_chunk_count: 10
36
+ # }
37
+ # validate_source_info!(source_info)
38
+ module SourceInfoValidator
39
+ # Valid source options for video uploads
40
+ SOURCE_OPTIONS = %w[
41
+ PULL_FROM_URL
42
+ FILE_UPLOAD
43
+ ].freeze
44
+
45
+ # Validates source information and raises an error if invalid.
46
+ #
47
+ # @param source_info [Hash, nil] The source information to validate
48
+ # @option source_info [String] :source Required. Must be 'PULL_FROM_URL' or 'FILE_UPLOAD'
49
+ # @option source_info [String] :video_url Required for PULL_FROM_URL. Non-empty video URL
50
+ # @option source_info [Integer] :video_size Required for FILE_UPLOAD. Positive integer
51
+ # @option source_info [Integer] :chunk_size Optional for FILE_UPLOAD. Positive integer
52
+ # @option source_info [Integer] :total_chunk_count Optional for FILE_UPLOAD. Positive integer
53
+ #
54
+ # @return [void]
55
+ # @raise [Tiktok::Open::Sdk::RequestValidationError] If validation fails
56
+ #
57
+ # @example Valid PULL_FROM_URL source
58
+ # validate_source_info!(source: 'PULL_FROM_URL', video_url: 'https://example.com/video.mp4')
59
+ #
60
+ # @example Valid FILE_UPLOAD source
61
+ # validate_source_info!(source: 'FILE_UPLOAD', video_size: 10_485_760)
62
+ #
63
+ # @example Invalid source type
64
+ # validate_source_info!(source: 'INVALID')
65
+ # # => raises RequestValidationError with source error
66
+ def validate_source_info!(source_info)
67
+ errors = {}
68
+
69
+ validate_source_info(source_info, errors)
70
+
71
+ raise_validation_errors!(errors)
72
+ end
73
+
74
+ private
75
+
76
+ # Raises validation errors if any exist.
77
+ #
78
+ # @param errors [Hash] The accumulated validation errors
79
+ # @return [void]
80
+ # @raise [Tiktok::Open::Sdk::RequestValidationError] If errors is not empty
81
+ def raise_validation_errors!(errors)
82
+ raise ::Tiktok::Open::Sdk::RequestValidationError, errors unless errors.empty?
83
+ end
84
+
85
+ # Validates source information and accumulates errors.
86
+ #
87
+ # @param source_info [Hash, nil] The source information to validate
88
+ # @param errors [Hash] The hash to accumulate errors into
89
+ # @return [void]
90
+ def validate_source_info(source_info, errors)
91
+ if source_info.is_a?(Hash)
92
+ validate_source_specific_fields!(source_info, errors)
93
+ else
94
+ add_error errors, :source_info, 'must be a Hash'
95
+ end
96
+ end
97
+
98
+ # Validates source-specific required fields based on source type.
99
+ #
100
+ # @param source_info [Hash] The source information containing type-specific fields
101
+ # @param errors [Hash] The hash to accumulate errors into
102
+ # @return [void]
103
+ def validate_source_specific_fields!(source_info, errors)
104
+ case source_info[:source]
105
+ when 'PULL_FROM_URL'
106
+ validate_pull_from_url_fields!(source_info, errors)
107
+ when 'FILE_UPLOAD'
108
+ validate_file_upload_fields!(source_info, errors)
109
+ else
110
+ add_error errors, :source, "must be one of: #{SOURCE_OPTIONS.join(", ")}"
111
+ end
112
+ end
113
+
114
+ # Validates required fields for PULL_FROM_URL source type.
115
+ #
116
+ # @param source_info [Hash] The source information
117
+ # @param errors [Hash] The hash to accumulate errors into
118
+ # @return [void]
119
+ def validate_pull_from_url_fields!(source_info, errors)
120
+ video_url = source_info[:video_url]
121
+
122
+ return if video_url.is_a?(String) && !video_url.empty?
123
+
124
+ add_error errors, :video_url, 'is required and must be a non-empty string for PULL_FROM_URL'
125
+ end
126
+
127
+ # Validates required fields for FILE_UPLOAD source type.
128
+ #
129
+ # @param source_info [Hash] The source information
130
+ # @param errors [Hash] The hash to accumulate errors into
131
+ # @return [void]
132
+ def validate_file_upload_fields!(source_info, errors)
133
+ validate_video_size! source_info[:video_size], errors
134
+ validate_chunk_size! source_info[:chunk_size], errors
135
+ validate_total_chunk_count! source_info[:total_chunk_count], errors
136
+ end
137
+
138
+ # Validates video size for FILE_UPLOAD source.
139
+ #
140
+ # @param video_size [Integer, nil] The video size in bytes
141
+ # @param errors [Hash] The hash to accumulate errors into
142
+ # @return [void]
143
+ def validate_video_size!(video_size, errors)
144
+ return if video_size.is_a?(Integer) && video_size.positive?
145
+
146
+ add_error errors, :video_size, 'is required and must be a positive integer for FILE_UPLOAD'
147
+ end
148
+
149
+ # Validates chunk size for FILE_UPLOAD source.
150
+ #
151
+ # @param value [Integer, nil] The chunk size in bytes
152
+ # @param errors [Hash] The hash to accumulate errors into
153
+ # @return [void]
154
+ def validate_chunk_size!(value, errors)
155
+ return if value.nil? || (value.is_a?(Integer) && value.positive?)
156
+
157
+ add_error errors, :chunk_size, 'must be a positive integer if provided'
158
+ end
159
+
160
+ # Validates total chunk count for FILE_UPLOAD source.
161
+ #
162
+ # @param value [Integer, nil] The total number of chunks
163
+ # @param errors [Hash] The hash to accumulate errors into
164
+ # @return [void]
165
+ def validate_total_chunk_count!(value, errors)
166
+ return if value.nil? || (value.is_a?(Integer) && value.positive?)
167
+
168
+ add_error errors, :total_chunk_count, 'must be a positive integer if provided'
169
+ end
170
+
171
+ # Adds an error message to the errors hash.
172
+ #
173
+ # @param errors [Hash] The hash to accumulate errors into
174
+ # @param field_name [Symbol] The field name that has an error
175
+ # @param message [String] The error message
176
+ # @return [Hash] The errors hash
177
+ def add_error(errors, field_name, message)
178
+ errors[field_name] ||= [] << message
179
+ errors
180
+ end
181
+ end
182
+ end
183
+ end
184
+ end
185
+ end
186
+ end
@@ -102,10 +102,11 @@ module Tiktok
102
102
  # @param body [Hash, nil] The request body.
103
103
  # @return [Net::HTTPRequest] The HTTP request object.
104
104
  def build_http_request(method, uri, headers, body)
105
- klass = Net::HTTP.const_get(method.capitalize)
106
- request = klass.new(uri, headers)
105
+ klass = Net::HTTP.const_get(method.capitalize)
106
+ request = klass.new(uri, headers)
107
+ content_type = headers[:'Content-Type'] || headers['Content-Type']
107
108
 
108
- body ? assign_body!(request, body, headers[:'Content-Type']) : request
109
+ body ? assign_body!(request, body, content_type) : request
109
110
  end
110
111
  end
111
112
  end
@@ -12,6 +12,7 @@ module Tiktok
12
12
 
13
13
  include ::Tiktok::Open::Sdk::Helpers::ResponseHelper
14
14
  include ::Tiktok::Open::Sdk::Helpers::Validators::TokenValidator
15
+ include ::Tiktok::Open::Sdk::Helpers::Validators::PostPublishValidator
15
16
 
16
17
  # Queries creator information from the TikTok Open API.
17
18
  #
@@ -31,6 +32,20 @@ module Tiktok
31
32
  }
32
33
  )
33
34
  end
35
+
36
+ def video_init(access_token:, params: {})
37
+ validate_token!(access_token)
38
+ validate_video_init_info!(params)
39
+
40
+ render_response Tiktok::Open::Sdk::HttpClient.post(
41
+ Tiktok::Open::Sdk.config.video_init_url,
42
+ headers: {
43
+ Authorization: "Bearer #{access_token}",
44
+ 'Content-Type': 'application/json; charset=UTF-8'
45
+ },
46
+ body: params
47
+ )
48
+ end
34
49
  end
35
50
  end
36
51
  end
@@ -3,7 +3,7 @@
3
3
  module Tiktok
4
4
  module Open
5
5
  module Sdk
6
- VERSION = '0.4.0'
6
+ VERSION = '0.5.0'
7
7
  end
8
8
  end
9
9
  end
@@ -4,6 +4,7 @@ require_relative 'sdk/helpers/string_utils_helper'
4
4
  require_relative 'sdk/helpers/response_helper'
5
5
  require_relative 'sdk/helpers/auth_helper'
6
6
  require_relative 'sdk/helpers/validators/token_validator'
7
+ require_relative 'sdk/helpers/validators/post_publish_validator'
7
8
  require_relative 'sdk/open_api/auth/user'
8
9
  require_relative 'sdk/open_api/auth/client'
9
10
  require_relative 'sdk/open_api/post/publish'
@@ -22,7 +23,31 @@ module Tiktok
22
23
  # raise Tiktok::Open::Sdk::Error, "Something went wrong"
23
24
  class Error < StandardError; end
24
25
 
25
- class RequestValidationError < Error; end
26
+ # Error class for request validation failures
27
+ #
28
+ # This error is raised when request validation fails, providing access to
29
+ # detailed validation error information.
30
+ #
31
+ # @attr_reader messages [Hash, nil] validation errors hash or nil if no specific errors
32
+ #
33
+ # @example
34
+ # raise RequestValidationError.new({ field: ['error message'] })
35
+ # raise RequestValidationError.new('General validation error')
36
+ class RequestValidationError < Error
37
+ attr_reader :messages
38
+
39
+ def initialize(messages = nil)
40
+ if messages.is_a?(Hash)
41
+ @messages = messages
42
+
43
+ super('Validation failed')
44
+ else
45
+ @messages = nil
46
+
47
+ super
48
+ end
49
+ end
50
+ end
26
51
 
27
52
  class << self
28
53
  # SDK configuration object
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tiktok-open-sdk
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Taras Pochkun
@@ -32,6 +32,9 @@ files:
32
32
  - lib/tiktok/open/sdk/helpers/auth_helper.rb
33
33
  - lib/tiktok/open/sdk/helpers/response_helper.rb
34
34
  - lib/tiktok/open/sdk/helpers/string_utils_helper.rb
35
+ - lib/tiktok/open/sdk/helpers/validators/post_info_validator.rb
36
+ - lib/tiktok/open/sdk/helpers/validators/post_publish_validator.rb
37
+ - lib/tiktok/open/sdk/helpers/validators/source_info_validator.rb
35
38
  - lib/tiktok/open/sdk/helpers/validators/token_validator.rb
36
39
  - lib/tiktok/open/sdk/http_client.rb
37
40
  - lib/tiktok/open/sdk/open_api/auth/client.rb