tiktok-open-sdk 0.3.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: 5baf485e6b6be4c1d0541f8d8d3ff76232bba37253fe7e6d89a6a9359328dc04
4
- data.tar.gz: 398eb5072ac7be7fd647679f408ecfa94fce22ff44c4993bf1891637d7cc6150
3
+ metadata.gz: ea350ded46bc468a3b86a72f539c12a36ecc960b1e2476ac7e59c2c52424d8f1
4
+ data.tar.gz: 07fa578800d4d03d9431c39b043008d2185ed62ed2f93c8c20feea8bb331736d
5
5
  SHA512:
6
- metadata.gz: e3ade7fbfaaea010568b79c807b52d65fa4398f486889387ab07a01db54163021a410d77a76552f865599b32db2d40cd89c19df11964ebc83a19022d163887d3
7
- data.tar.gz: b512cb261c7b577a74523b501a25daddce2e1196f90ebc9351cf1472516f33fb1634bd1b501bd04649cdb10c44c9c97513fd0a0474de533bba59f8e1eb15c530
6
+ metadata.gz: 61e3742ea46ddeb02a8a168d3485c7ecc7632698c6c533364e392b67058f6a5d7e325e0e546eebe9eee915070e309981dc8707aca7ff67097dfadd74610977d0
7
+ data.tar.gz: f19aa49f93036f0b02f0d5613d76b7bd86e7a00457a3642569c3f266ac895720a4106e7df27fec6f215581ccfd6fcedb71ac68638c83fdddcfc0dca8b56d5052
data/.rubocop.yml CHANGED
@@ -7,6 +7,9 @@ AllCops:
7
7
  NewCops: enable
8
8
  SuggestExtensions: false
9
9
 
10
+ Naming/VariableNumber:
11
+ EnforcedStyle: snake_case
12
+
10
13
  Metrics/MethodLength:
11
14
  Max: 15
12
15
 
@@ -27,7 +30,7 @@ Style/ModuleFunction:
27
30
  Enabled: false
28
31
 
29
32
  RSpec/NestedGroups:
30
- Max: 4
33
+ Max: 5
31
34
 
32
35
  RSpec/MultipleExpectations:
33
36
  Max: 5
data/CHANGELOG.md CHANGED
@@ -4,7 +4,19 @@ 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`.
10
+
11
+ ## [0.4.0] - 2025-10-06
12
+ ### Added
13
+ - **OmniAuth Strategy** - Ready-to-use OmniAuth strategy for TikTok Open Platform integration in Rails applications
14
+ - Supports multiple TikTok OAuth scopes (user.info.basic, user.info.profile, user.info.stats)
15
+ - Automatic token handling and user info retrieval
16
+ - Rails/Devise integration examples and callbacks
17
+ - **Post API** - New module for interacting with TikTok's Post API endpoints
18
+ - Creator info query functionality for video publishing workflows
19
+ - Support for querying creator settings and capabilities
8
20
 
9
21
  ## [0.3.0] - 2025-09-20
10
22
  ### 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.3.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)
@@ -10,9 +10,11 @@ A comprehensive Ruby SDK for integrating with TikTok Open API. This gem provides
10
10
  ## Features
11
11
 
12
12
  - **OAuth 2.0 Authentication** – Seamless OAuth flow for secure integration
13
+ - **OmniAuth Strategy** – Ready-to-use OmniAuth strategy for Rails applications
13
14
  - **Client Authentication** – Server-to-server authentication with client credentials
14
15
  - **Token Management** – Easy access token exchange and refresh
15
16
  - **User API** – Convenient methods to access user information
17
+ - **Post API** – Methods for querying creator information and video publishing
16
18
  - **HTTP Client** – Built-in client for interacting with TikTok APIs
17
19
 
18
20
  ## Installation
@@ -56,6 +58,11 @@ Tiktok::Open::Sdk.configure do |config|
56
58
  config.user_auth.token_url = 'https://open.tiktokapis.com/v2/oauth/token/'
57
59
  config.user_auth.revoke_token_url = 'https://open.tiktokapis.com/v2/oauth/revoke/'
58
60
  config.user_info_url = 'https://open.tiktokapis.com/v2/user/info/'
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/'
63
+
64
+ # Optional: Enable OmniAuth strategy auto-loading
65
+ config.load_omniauth = true
59
66
  end
60
67
  ```
61
68
 
@@ -158,13 +165,71 @@ end
158
165
 
159
166
  **Note:** Client tokens are used for server-to-server authentication and have different scopes and permissions than user tokens.
160
167
 
168
+ ### Using the Post API
169
+
170
+ The SDK provides convenient methods for interacting with TikTok's Post API:
171
+
172
+ #### Creator Info Query
173
+
174
+ Query creator information for video publishing:
175
+
176
+ ```ruby
177
+ # Get creator information
178
+ response = Tiktok::Open::Sdk.post.creator_info_query(access_token: access_token)
179
+
180
+ if response[:success]
181
+ creator_data = response[:response][:data]
182
+
183
+ puts "Creator Avatar: #{creator_data[:creator_avatar_url]}"
184
+ puts "Creator Nickname: #{creator_data[:creator_nickname]}"
185
+ puts "Max Video Duration: #{creator_data[:max_video_post_duration_sec]} seconds"
186
+ puts "Privacy Options: #{creator_data[:privacy_level_options]}"
187
+ else
188
+ puts "Error: #{response[:response][:error][:message]}"
189
+ end
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
+
161
226
  ### Using the User API
162
227
 
163
228
  The SDK provides a convenient way to access user information:
164
229
 
165
230
  ```ruby
166
231
  # Get user information
167
- response = Tiktok::Open::Sdk::OpenApi::User.get_user_info(
232
+ response = Tiktok::Open::Sdk.user.get_user_info(
168
233
  access_token: access_token,
169
234
  fields: %w[open_id union_id avatar_url display_name]
170
235
  )
@@ -187,6 +252,73 @@ Available user fields include:
187
252
  - `username` - User's username
188
253
  - And more (see documentation for full list)
189
254
 
255
+ ### Using OmniAuth Strategy
256
+
257
+ The SDK provides a ready-to-use OmniAuth strategy for Rails applications:
258
+
259
+ #### Rails Setup
260
+
261
+ Add the OmniAuth strategy to your Rails application:
262
+
263
+ ```ruby
264
+ # config/initializers/devise.rb
265
+ Devise.setup do |config|
266
+ config.omniauth(
267
+ :tiktok_open_sdk,
268
+ Rails.application.credentials.dig(:tiktok, :client_key),
269
+ Rails.application.credentials.dig(:tiktok, :client_secret),
270
+ scope: 'user.info.basic,user.info.profile,user.info.stats',
271
+ )
272
+ end
273
+ ```
274
+
275
+ Or use the SDK configuration:
276
+
277
+ ```ruby
278
+ # config/initializers/tiktok_sdk.rb
279
+ Tiktok::Open::Sdk.configure do |config|
280
+ config.client_key = Rails.application.credentials.dig(:tiktok, :client_key)
281
+ config.client_secret = Rails.application.credentials.dig(:tiktok, :client_secret)
282
+ config.user_auth.scopes = %w[user.info.basic video.publish]
283
+ config.user_auth.redirect_uri = "#{Rails.application.config.action_mailer.asset_host.chomp('/')}/users/auth/tiktok_open_sdk/callback"
284
+ config.load_omniauth = true
285
+ end
286
+ ```
287
+
288
+ #### OmniAuth Callback
289
+
290
+ Handle the OmniAuth callback in your controller:
291
+
292
+ ```ruby
293
+ # app/controllers/omniauth_callbacks_controller.rb
294
+ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
295
+ def tiktok_open_sdk
296
+ @auth = request.env['omniauth.auth']
297
+
298
+ # Find or create user based on TikTok auth data
299
+ @user = User.find_for_oauth(@auth)
300
+
301
+ # ...
302
+
303
+ if @user.persisted?
304
+ sign_in_and_redirect @user, event: :authentication
305
+ set_flash_message :notice, :success, kind: 'TikTok'
306
+ else
307
+ session['devise.provider_data'] = @auth.except('extra')
308
+ redirect_to new_user_registration_url
309
+ end
310
+ end
311
+ end
312
+ ```
313
+
314
+ #### Supported Scopes
315
+
316
+ The OmniAuth strategy supports the following TikTok scopes:
317
+
318
+ - `user.info.basic` - Basic user info: open_id, union_id, display_name, avatar URLs
319
+ - `user.info.profile` - Profile info: username, bio_description, profile_deep_link, is_verified
320
+ - `user.info.stats` - Statistics: follower_count, following_count, likes_count, video_count
321
+
190
322
  ### Using the HTTP Client
191
323
 
192
324
  The SDK includes a flexible HTTP client for making API calls:
@@ -331,6 +463,8 @@ Tiktok::Open::Sdk.configure do |config|
331
463
  config.user_auth.scopes = %w[user.info.basic] # Optional
332
464
  config.user_auth.redirect_uri = 'https://...' # Optional
333
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
334
468
  end
335
469
  ```
336
470
 
@@ -410,20 +544,59 @@ Retrieves user information from the TikTok Open API.
410
544
  **Returns:** Hash with `:success`, `:code`, and `:response` keys
411
545
 
412
546
  **Available Fields:**
413
- - `open_id` - The unique identification of the user in the current application.Open id for the client
414
- - `union_id` - The unique identification of the user across different apps for the same developer. For example, if a partner has X number of clients, it will get X number of open_id for the same TikTok user, but one persistent union_id for the particular user
415
- - `avatar_url` - User's profile image
416
- - `avatar_url_100` - User`s profile image in 100x100 size
417
- - `avatar_large_url` - User's profile image with higher resolution
418
- - `display_name` - User's profile name
419
- - `bio_description` - User's bio description if there is a valid one
420
- - `profile_deep_link` - The link to user's TikTok profile page
421
- - `is_verified` - Whether TikTok has provided a verified badge to the account after confirming that it belongs to the user it represents
422
- - `username` - User's username
423
- - `follower_count` - User's followers count
424
- - `following_count` - The number of accounts that the user is following
425
- - `likes_count` - The total number of likes received by the user across all of their videos
426
- - `video_count` - The total number of publicly posted videos by the user
547
+ - `open_id` - Unique identifier for the user within the current application
548
+ - `union_id` - Persistent identifier for the user across different applications from the same developer
549
+ - `avatar_url` - URL to the user's profile image
550
+ - `avatar_url_100` - URL to the user's profile image in 100x100 pixel size
551
+ - `avatar_large_url` - URL to the user's profile image in higher resolution
552
+ - `display_name` - User's display name shown on their TikTok profile
553
+ - `bio_description` - User's biography text (if available)
554
+ - `profile_deep_link` - Direct link to the user's TikTok profile page
555
+ - `is_verified` - Boolean indicating if the account is verified by TikTok
556
+ - `username` - User's unique TikTok username
557
+ - `follower_count` - Number of followers the user has
558
+ - `following_count` - Number of accounts the user is following
559
+ - `likes_count` - Total number of likes received across all user's videos
560
+ - `video_count` - Total number of publicly posted videos by the user
561
+
562
+ ### Post API
563
+
564
+ #### `creator_info_query(access_token:)`
565
+
566
+ Queries creator information from the TikTok Open API for video publishing.
567
+
568
+ **Parameters:**
569
+ - `access_token` (String, required) - OAuth2 access token for authentication
570
+
571
+ **Returns:** Hash with `:success`, `:code`, and `:response` keys
572
+
573
+ **Response Data:**
574
+ - `creator_avatar_url` - Creator's avatar URL
575
+ - `creator_nickname` - Creator's display name
576
+ - `creator_username` - Creator's username
577
+ - `stitch_disabled` - Whether stitch is disabled for the creator
578
+ - `comment_disabled` - Whether comments are disabled for the creator
579
+ - `duet_disabled` - Whether duet is disabled for the creator
580
+ - `max_video_post_duration_sec` - Maximum video duration in seconds
581
+ - `privacy_level_options` - Available privacy level options
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
427
600
 
428
601
  ### HTTP Client
429
602
 
@@ -0,0 +1,177 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Tiktok
4
+ module Open
5
+ module Omniauth
6
+ module Strategies
7
+ # OmniAuth strategy for TikTok Open Platform.
8
+ #
9
+ # Integrates TikTok OAuth2 authentication with OmniAuth.
10
+ #
11
+ # @example
12
+ # use OmniAuth::Builder do
13
+ # provider :tiktok_open, 'CLIENT_KEY', 'CLIENT_SECRET'
14
+ # end
15
+ #
16
+ # Supported scopes and their user info fields:
17
+ # - user.info.basic: open_id, union_id, display_name, avatar_url, avatar_url_100, avatar_large_url
18
+ # - user.info.profile: profile_deep_link, bio_description, is_verified, username
19
+ # - user.info.stats: follower_count, following_count, likes_count, video_count
20
+ class TiktokOpenSdk < ::OmniAuth::Strategies::OAuth2
21
+ # Custom access token class for TikTok.
22
+ class AccessToken < ::OAuth2::AccessToken; end
23
+
24
+ # Maps TikTok OAuth scopes to user info fields.
25
+ SCOPE_FIELDS = {
26
+ 'user.info.basic' => %w[open_id union_id display_name avatar_url avatar_url_100 avatar_large_url],
27
+ 'user.info.profile' => %w[profile_deep_link bio_description is_verified username],
28
+ 'user.info.stats' => %w[follower_count following_count likes_count video_count]
29
+ }.freeze
30
+
31
+ private_constant :SCOPE_FIELDS
32
+
33
+ # The name of this OmniAuth strategy.
34
+ option :name, :tiktok_open_sdk
35
+
36
+ # OAuth2 client options for TikTok endpoints.
37
+ # - :site: TikTok Open API base URL
38
+ # - :authorize_url: TikTok OAuth2 authorization endpoint
39
+ # - :token_url: TikTok OAuth2 token endpoint
40
+ option :client_options, {
41
+ site: ::Tiktok::Open::Sdk::Config::OPEN_API_BASE_URL,
42
+ authorize_url: ::Tiktok::Open::Sdk.config.user_auth.auth_url,
43
+ token_url: ::Tiktok::Open::Sdk.config.user_auth.token_url,
44
+ auth_scheme: :request_body,
45
+ auth_token_class: AccessToken
46
+ }
47
+
48
+ # List of parameters allowed in the authorization request.
49
+ option :authorize_options, %i[scope state redirect_uri]
50
+
51
+ # Default scope and redirect_uri from SDK config.
52
+ option :scope, ::Tiktok::Open::Sdk.config.user_auth.scopes.join(',')
53
+ option :redirect_uri, ::Tiktok::Open::Sdk.config.user_auth.redirect_uri
54
+
55
+ # Returns the unique TikTok user ID (open_id).
56
+ #
57
+ # @return [String] TikTok user's open_id.
58
+ uid { raw_info[:open_id].to_s }
59
+
60
+ # Returns a hash of user information.
61
+ #
62
+ # @return [Hash] User info with :name and :image keys, and profile fields if scope is present.
63
+ info do
64
+ { name: raw_info[:display_name], image: raw_info[:avatar_url_100] }.tap do |info|
65
+ if request_scopes.include?('user.info.profile')
66
+ info.merge!(raw_info.slice(:username, :bio_description, :profile_deep_link))
67
+ end
68
+ end
69
+ end
70
+
71
+ # Returns extra raw user information from TikTok.
72
+ #
73
+ # @return [Hash] Raw user info data from TikTok API.
74
+ extra { raw_info }
75
+
76
+ # Returns the callback URL without query parameters.
77
+ #
78
+ # @return [String] Callback URL.
79
+ def callback_url
80
+ super.split('?').first
81
+ end
82
+
83
+ # Builds the access token from TikTok's token endpoint.
84
+ #
85
+ # @raise [OAuth2::Error] if the token response is unsuccessful.
86
+ # @return [AccessToken] OAuth2 access token object.
87
+ def build_access_token
88
+ response = fetch_access_token
89
+ validate_token_response(response)
90
+ create_access_token(response[:response])
91
+ end
92
+
93
+ # Handles the initial OAuth2 request phase.
94
+ #
95
+ # @raise [ArgumentError] if client_secret is present in params.
96
+ def request_phase
97
+ params = authorize_params.merge('response_type' => 'code')
98
+
99
+ if params.key?(:client_secret) || params.key?('client_secret')
100
+ raise ArgumentError, 'client_secret is not allowed in authorize URL query params'
101
+ end
102
+
103
+ redirect client.authorize_url(params)
104
+ end
105
+
106
+ # Builds the authorization parameters for the OAuth2 request,
107
+ # adding the TikTok client_key.
108
+ #
109
+ # @return [Hash] Authorization parameters.
110
+ def authorize_params
111
+ super.tap do |params|
112
+ params[:client_key] = options.client_id
113
+ end
114
+ end
115
+
116
+ private
117
+
118
+ # Fetches access token from TikTok API
119
+ #
120
+ # @return [Hash] Token response from TikTok
121
+ def fetch_access_token
122
+ Tiktok::Open::Sdk.user_auth.fetch_access_token(
123
+ code: request.params['code'],
124
+ redirect_uri: callback_url
125
+ )
126
+ end
127
+
128
+ # Validates the token response
129
+ #
130
+ # @param response [Hash] Token response
131
+ # @raise [OAuth2::Error] if response is unsuccessful
132
+ def validate_token_response(response)
133
+ raise OAuth2::Error, response[:response] unless response[:success]
134
+ end
135
+
136
+ # Creates AccessToken from response data
137
+ #
138
+ # @param data [Hash] Token data from response
139
+ # @return [AccessToken] OAuth2 access token object
140
+ def create_access_token(data)
141
+ AccessToken.from_hash(
142
+ client,
143
+ access_token: data[:access_token],
144
+ refresh_token: data[:refresh_token],
145
+ expires_at: Time.now.to_i + data[:expires_in].to_i
146
+ )
147
+ end
148
+
149
+ # Returns the list of requested OAuth scopes.
150
+ #
151
+ # @return [Array<String>] List of scope strings.
152
+ def request_scopes
153
+ @request_scopes ||= request.params.fetch('scopes', 'user.info.basic').split(',')
154
+ end
155
+
156
+ # Returns the list of user info fields to request from TikTok,
157
+ # based on the requested scopes.
158
+ #
159
+ # @return [Array<String>] List of user info field names.
160
+ def user_info_fields
161
+ request_scopes.flat_map { |scope| SCOPE_FIELDS[scope] }.compact
162
+ end
163
+
164
+ # Fetches and memoizes the raw user info from the TikTok API.
165
+ #
166
+ # @return [Hash] Raw user info data, or empty hash if unavailable.
167
+ def raw_info
168
+ @raw_info ||= Tiktok::Open::Sdk.user.get_user_info(
169
+ access_token: access_token.token,
170
+ fields: user_info_fields
171
+ ).dig(:response, :data, :user) || {}
172
+ end
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end
@@ -29,14 +29,29 @@ module Tiktok
29
29
  # @return [String] TikTok user info endpoint URL.
30
30
  attr_accessor :user_info_url
31
31
 
32
+ # @!attribute [rw] creator_info_query_url
33
+ # @return [String] TikTok Query Creator Info endpoint URL.
34
+ attr_accessor :creator_info_query_url
35
+
36
+ # @!attribute [rw] video_init_url
37
+ # @return [String] TikTok Video Init endpoint URL.
38
+ attr_accessor :video_init_url
39
+
32
40
  # @!attribute [rw] user_auth
33
41
  # @return [UserAuth] User authentication configuration.
34
42
  attr_accessor :user_auth
35
43
 
44
+ # @!attribute [rw] load_omniauth
45
+ # @return [Boolean] Whether to automatically load OmniAuth strategy.
46
+ attr_accessor :load_omniauth
47
+
36
48
  # Create a new Config with default user authentication settings.
37
49
  def initialize
38
- @user_info_url = "#{OPEN_API_BASE_URL}/v2/user/info/"
39
- @user_auth = UserAuth.new
50
+ @user_info_url = "#{OPEN_API_BASE_URL}/v2/user/info/"
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/"
53
+ @user_auth = UserAuth.new
54
+ @load_omniauth = false
40
55
  end
41
56
 
42
57
  # User authentication configuration for TikTok Open SDK.
@@ -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
@@ -85,7 +85,7 @@ module Tiktok
85
85
  case content_type
86
86
  when 'application/x-www-form-urlencoded'
87
87
  request.set_form_data(body)
88
- when 'application/json'
88
+ when 'application/json', 'application/json; charset=UTF-8'
89
89
  request.body = body.to_json
90
90
  else
91
91
  raise ArgumentError, "Unsupported content type: #{content_type}"
@@ -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
@@ -23,7 +23,7 @@ module Tiktok
23
23
  # @return [URI] The constructed authorization URI.
24
24
  def authorization_uri(params = {})
25
25
  allowed_params = params.slice(:scope, :redirect_uri, :state)
26
- uri = URI(Tiktok::Open::Sdk.config.user_auth.auth_url)
26
+ uri = URI.parse(Tiktok::Open::Sdk.config.user_auth.auth_url)
27
27
  query_params = authorization_uri_default_params.merge(allowed_params)
28
28
  uri.query = URI.encode_www_form(query_params)
29
29
 
@@ -0,0 +1,54 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Provides methods to interact with TikTok Open API post endpoints.
4
+ module Tiktok
5
+ module Open
6
+ module Sdk
7
+ module OpenApi
8
+ module Post
9
+ # Provides methods for handling TikTok Open API post endpoints.
10
+ module Publish
11
+ extend self
12
+
13
+ include ::Tiktok::Open::Sdk::Helpers::ResponseHelper
14
+ include ::Tiktok::Open::Sdk::Helpers::Validators::TokenValidator
15
+ include ::Tiktok::Open::Sdk::Helpers::Validators::PostPublishValidator
16
+
17
+ # Queries creator information from the TikTok Open API.
18
+ #
19
+ # @param access_token [String] OAuth2 access token for authentication.
20
+ # @return [Hash] Parsed API response containing creator information.
21
+ # @raise [::Tiktok::Open::Sdk::RequestValidationError] If the access token is invalid.
22
+ #
23
+ # @example
24
+ # Tiktok::Open::Sdk.post.creator_info_query(access_token: 'your_access_token')
25
+ def creator_info_query(access_token:)
26
+ validate_token!(access_token)
27
+
28
+ render_response Tiktok::Open::Sdk::HttpClient.post(
29
+ Tiktok::Open::Sdk.config.creator_info_query_url,
30
+ headers: {
31
+ Authorization: "Bearer #{access_token}"
32
+ }
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
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
@@ -3,7 +3,7 @@
3
3
  module Tiktok
4
4
  module Open
5
5
  module Sdk
6
- VERSION = '0.3.0'
6
+ VERSION = '0.5.0'
7
7
  end
8
8
  end
9
9
  end
@@ -4,8 +4,10 @@ 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'
10
+ require_relative 'sdk/open_api/post/publish'
9
11
  require_relative 'sdk/open_api/user'
10
12
  require_relative 'sdk/version'
11
13
  require_relative 'sdk/http_client'
@@ -21,7 +23,31 @@ module Tiktok
21
23
  # raise Tiktok::Open::Sdk::Error, "Something went wrong"
22
24
  class Error < StandardError; end
23
25
 
24
- 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
25
51
 
26
52
  class << self
27
53
  # SDK configuration object
@@ -45,12 +71,15 @@ module Tiktok
45
71
  # config.user_auth.token_url = 'https://open.tiktokapis.com/v2/oauth/token/'
46
72
  # config.user_auth.scopes = %w[user.info.basic video.list]
47
73
  # config.user_auth.redirect_uri = 'https://your-redirect-uri.example.com'
74
+ # config.load_omniauth = true
48
75
  # end
49
76
  def configure
50
77
  self.config ||= Config.new
51
78
 
52
79
  yield(config)
53
80
 
81
+ load_omniauth! if config.load_omniauth
82
+
54
83
  config
55
84
  end
56
85
 
@@ -73,6 +102,44 @@ module Tiktok
73
102
  def client_auth
74
103
  OpenApi::Auth::Client
75
104
  end
105
+
106
+ # Convenience accessor for post publish functionality
107
+ #
108
+ # @return [OpenApi::Post::Publish] the Post publish module
109
+ #
110
+ # @example
111
+ # Tiktok::Open::Sdk.post.video_init(access_token: 'token', post_info: post_info, source_info: source_info)
112
+ def post
113
+ OpenApi::Post::Publish
114
+ end
115
+
116
+ # Convenience accessor for user functionality
117
+ #
118
+ # @return [OpenApi::User] the User module
119
+ #
120
+ # @example
121
+ # Tiktok::Open::Sdk.user.info(access_token: 'token')
122
+ def user
123
+ OpenApi::User
124
+ end
125
+
126
+ private
127
+
128
+ # Loads the OmniAuth strategy for TikTok Open Platform.
129
+ #
130
+ # Attempts to require the necessary OmniAuth dependencies for TikTok Open integration.
131
+ # Raises an error if the required gems are not available.
132
+ #
133
+ # @raise [Tiktok::Open::Sdk::Error] if 'omniauth-oauth2' or the TikTok strategy cannot be loaded
134
+ # @example
135
+ # Tiktok::Open::Sdk.load_omniauth!
136
+ def load_omniauth!
137
+ require 'omniauth-oauth2'
138
+ require 'tiktok/open/omniauth/strategies/tiktok_open_sdk'
139
+ rescue LoadError => e
140
+ raise ::Tiktok::Open::Sdk::Error,
141
+ "OmniAuth is not loaded! Error: #{e.message}"
142
+ end
76
143
  end
77
144
  end
78
145
  end
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.3.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Taras Pochkun
@@ -26,15 +26,20 @@ files:
26
26
  - LICENSE.txt
27
27
  - README.md
28
28
  - Rakefile
29
+ - lib/tiktok/open/omniauth/strategies/tiktok_open_sdk.rb
29
30
  - lib/tiktok/open/sdk.rb
30
31
  - lib/tiktok/open/sdk/config.rb
31
32
  - lib/tiktok/open/sdk/helpers/auth_helper.rb
32
33
  - lib/tiktok/open/sdk/helpers/response_helper.rb
33
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
34
38
  - lib/tiktok/open/sdk/helpers/validators/token_validator.rb
35
39
  - lib/tiktok/open/sdk/http_client.rb
36
40
  - lib/tiktok/open/sdk/open_api/auth/client.rb
37
41
  - lib/tiktok/open/sdk/open_api/auth/user.rb
42
+ - lib/tiktok/open/sdk/open_api/post/publish.rb
38
43
  - lib/tiktok/open/sdk/open_api/user.rb
39
44
  - lib/tiktok/open/sdk/version.rb
40
45
  - sig/tiktok/open/sdk.rbs
@@ -44,7 +49,7 @@ licenses:
44
49
  metadata:
45
50
  allowed_push_host: https://rubygems.org
46
51
  homepage_uri: https://github.com/pochkuntaras/tiktok-open-sdk
47
- source_code_uri: https://github.com/pochkuntaras/tiktok-open-sdk
52
+ source_code_uri: https://github.com/pochkuntaras/tiktok-open-sdk.git
48
53
  changelog_uri: https://github.com/pochkuntaras/tiktok-open-sdk/blob/main/CHANGELOG.md
49
54
  rubygems_mfa_required: 'true'
50
55
  documentation_uri: https://rubydoc.info/gems/tiktok-open-sdk