diff --git a/apps/frontend/src/components/launches/providers/tiktok/tiktok.provider.tsx b/apps/frontend/src/components/launches/providers/tiktok/tiktok.provider.tsx index 0da127c7..b2fddd50 100644 --- a/apps/frontend/src/components/launches/providers/tiktok/tiktok.provider.tsx +++ b/apps/frontend/src/components/launches/providers/tiktok/tiktok.provider.tsx @@ -237,4 +237,25 @@ const TikTokPreview: FC = (props) => { ); }; -export default withProvider(TikTokSettings, TikTokPreview, TikTokDto); +export default withProvider( + TikTokSettings, + TikTokPreview, + TikTokDto, + async (items) => { + const [firstItems] = items; + + if (items.length !== 1) { + return 'Tiktok items should be one'; + } + + if (items[0].length !== 1) { + return 'You need one media'; + } + + if (firstItems[0].path.indexOf('mp4') === -1) { + return 'Item must be a video'; + } + + return true; + } +); diff --git a/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx b/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx index 06315820..a80a109e 100644 --- a/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx +++ b/apps/frontend/src/components/launches/providers/youtube/youtube.provider.tsx @@ -158,7 +158,7 @@ export default withProvider( } if (items[0].length !== 1) { - return 'You need one item'; + return 'You need one media'; } if (firstItems[0].path.indexOf('mp4') === -1) { diff --git a/libraries/nestjs-libraries/src/integrations/social.abstract.ts b/libraries/nestjs-libraries/src/integrations/social.abstract.ts index 52439fdb..2bc9bc29 100644 --- a/libraries/nestjs-libraries/src/integrations/social.abstract.ts +++ b/libraries/nestjs-libraries/src/integrations/social.abstract.ts @@ -4,6 +4,7 @@ export class RefreshToken { export abstract class SocialAbstract { async fetch(url: string, options: RequestInit = {}) { const request = await fetch(url, options); + console.log(request.status); if (request.status === 401) { throw new RefreshToken(); } diff --git a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts index ace3bce3..26ea3d6d 100644 --- a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts @@ -6,6 +6,7 @@ import { } from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface'; import dayjs from 'dayjs'; import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract'; +import { TikTokDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/tiktok.dto'; export class TiktokProvider extends SocialAbstract implements SocialProvider { identifier = 'tiktok'; @@ -16,12 +17,12 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider { const value = { client_key: process.env.TIKTOK_CLIENT_ID!, client_secret: process.env.TIKTOK_CLIENT_SECRET!, - grant_type: 'authorization_code', + grant_type: 'refresh_token', refresh_token: refreshToken, }; - const { access_token, refresh_token } = await ( - await this.fetch('https://open.tiktokapis.com/v2/oauth/token/', { + const { access_token, refresh_token, ...all } = await ( + await fetch('https://open.tiktokapis.com/v2/oauth/token/', { headers: { 'Content-Type': 'application/x-www-form-urlencoded', }, @@ -138,117 +139,50 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider { async post( id: string, accessToken: string, - postDetails: PostDetails[] + postDetails: PostDetails[] ): Promise { - const [firstPost, ...comments] = postDetails; - - let finalId = ''; - let finalUrl = ''; - if ((firstPost?.media?.[0]?.path?.indexOf('mp4') || -2) > -1) { - const { id: videoId, permalink_url } = await ( - await this.fetch( - `https://graph.facebook.com/v20.0/${id}/videos?access_token=${accessToken}&fields=id,permalink_url`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - file_url: firstPost?.media?.[0]?.path!, - description: firstPost.message, - published: true, - }), - } - ) - ).json(); - - finalUrl = permalink_url; - finalId = videoId; - } else { - const uploadPhotos = !firstPost?.media?.length - ? [] - : await Promise.all( - firstPost.media.map(async (media) => { - const { id: photoId } = await ( - await this.fetch( - `https://graph.facebook.com/v20.0/${id}/photos?access_token=${accessToken}`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - url: media.url, - published: false, - }), - } - ) - ).json(); - - return { media_fbid: photoId }; - }) - ); - + try { + const [firstPost, ...comments] = postDetails; const { - id: postId, - permalink_url, - ...all + data: { publish_id }, } = await ( await this.fetch( - `https://graph.facebook.com/v20.0/${id}/feed?access_token=${accessToken}&fields=id,permalink_url`, + 'https://open.tiktokapis.com/v2/post/publish/video/init/', { method: 'POST', headers: { - 'Content-Type': 'application/json', + 'Content-Type': 'application/json; charset=UTF-8', + Authorization: `Bearer ${accessToken}`, }, body: JSON.stringify({ - ...(uploadPhotos?.length ? { attached_media: uploadPhotos } : {}), - message: firstPost.message, - published: true, + post_info: { + title: firstPost.message, + privacy_level: firstPost.settings.privacy_level, + disable_duet: firstPost.settings.disable_duet, + disable_comment: firstPost.settings.disable_comment, + disable_stitch: firstPost.settings.disable_stitch, + brand_content_toggle: firstPost.settings.brand_content_toggle, + brand_organic_toggle: firstPost.settings.brand_organic_toggle, + }, + source_info: { + source: 'PULL_FROM_URL', + video_url: firstPost?.media?.[0]?.url!, + }, }), } ) ).json(); - finalUrl = permalink_url; - finalId = postId; + return [ + { + id: firstPost.id, + releaseURL: `https://www.tiktok.com`, + postId: publish_id, + status: 'success', + }, + ]; + } catch (err) { + return []; } - - const postsArray = []; - for (const comment of comments) { - const data = await ( - await this.fetch( - `https://graph.facebook.com/v20.0/${finalId}/comments?access_token=${accessToken}&fields=id,permalink_url`, - { - method: 'POST', - headers: { - 'Content-Type': 'application/json', - }, - body: JSON.stringify({ - ...(comment.media?.length - ? { attachment_url: comment.media[0].url } - : {}), - message: comment.message, - }), - } - ) - ).json(); - - postsArray.push({ - id: comment.id, - postId: data.id, - releaseURL: data.permalink_url, - status: 'success', - }); - } - return [ - { - id: firstPost.id, - postId: finalId, - releaseURL: finalUrl, - status: 'success', - }, - ...postsArray, - ]; } }