diff --git a/apps/frontend/src/components/launches/providers/high.order.provider.tsx b/apps/frontend/src/components/launches/providers/high.order.provider.tsx
index 6d1d9bee..7a5e6e87 100644
--- a/apps/frontend/src/components/launches/providers/high.order.provider.tsx
+++ b/apps/frontend/src/components/launches/providers/high.order.provider.tsx
@@ -382,8 +382,8 @@ export const withProvider = (
,
document.querySelector('#renderEditor')!
)}
- {showTab === 2 && (
-
+ {(showTab === 0 || showTab === 2) && (
+
)}
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 8aabc469..0da127c7 100644
--- a/apps/frontend/src/components/launches/providers/tiktok/tiktok.provider.tsx
+++ b/apps/frontend/src/components/launches/providers/tiktok/tiktok.provider.tsx
@@ -8,6 +8,133 @@ import {
linkedinCompanyPreventRemove,
} from '@gitroom/helpers/utils/linkedin.company.prevent.remove';
import { VideoOrImage } from '@gitroom/react/helpers/video.or.image';
+import { TikTokDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/tiktok.dto';
+import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values';
+import { Select } from '@gitroom/react/form/select';
+
+const privacyLevel = [
+ {
+ value: 'PUBLIC_TO_EVERYONE',
+ label: 'Public to everyone',
+ },
+ {
+ value: 'MUTUAL_FOLLOW_FRIENDS',
+ label: 'Mutual follow friends',
+ },
+ {
+ value: 'FOLLOWER_OF_CREATOR',
+ label: 'Follower of creator',
+ },
+ {
+ value: 'SELF_ONLY',
+ label: 'Self only',
+ },
+];
+
+const yesNo = [
+ {
+ value: 'true',
+ label: 'Yes',
+ },
+ {
+ value: 'false',
+ label: 'No',
+ },
+];
+
+const TikTokSettings: FC = () => {
+ const { register, control } = useSettings();
+ return (
+
+
+
+
+
+
+
+
+
+
+
+ );
+};
const TikTokPreview: FC = (props) => {
const { value: topValue, integration } = useIntegration();
@@ -110,4 +237,4 @@ const TikTokPreview: FC = (props) => {
);
};
-export default withProvider(null, TikTokPreview);
+export default withProvider(TikTokSettings, TikTokPreview, TikTokDto);
diff --git a/libraries/nestjs-libraries/src/dtos/posts/create.post.dto.ts b/libraries/nestjs-libraries/src/dtos/posts/create.post.dto.ts
index 563b4c65..20d813c4 100644
--- a/libraries/nestjs-libraries/src/dtos/posts/create.post.dto.ts
+++ b/libraries/nestjs-libraries/src/dtos/posts/create.post.dto.ts
@@ -11,6 +11,7 @@ import {RedditSettingsDto} from "@gitroom/nestjs-libraries/dtos/posts/providers-
import { YoutubeSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/youtube.settings.dto';
import { PinterestSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/pinterest.dto';
import { DribbbleDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/dribbble.dto';
+import { TikTokDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/tiktok.dto';
export class EmptySettings {}
export class Integration {
@@ -66,6 +67,7 @@ export class Post {
{ value: YoutubeSettingsDto, name: 'youtube' },
{ value: PinterestSettingsDto, name: 'pinterest' },
{ value: DribbbleDto, name: 'dribbble' },
+ { value: TikTokDto, name: 'tiktok' },
],
},
})
diff --git a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/all.providers.settings.ts b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/all.providers.settings.ts
index 042e3ad7..2f6ad04c 100644
--- a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/all.providers.settings.ts
+++ b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/all.providers.settings.ts
@@ -4,6 +4,7 @@ import { HashnodeSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/provid
import { RedditSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/reddit.dto';
import { PinterestSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/pinterest.dto';
import { YoutubeSettingsDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/youtube.settings.dto';
+import { TikTokDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/tiktok.dto';
export type AllProvidersSettings =
| DevToSettingsDto
@@ -11,4 +12,5 @@ export type AllProvidersSettings =
| HashnodeSettingsDto
| RedditSettingsDto
| YoutubeSettingsDto
- | PinterestSettingsDto;
+ | PinterestSettingsDto
+ | TikTokDto;
diff --git a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/tiktok.dto.ts b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/tiktok.dto.ts
new file mode 100644
index 00000000..8bd53412
--- /dev/null
+++ b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/tiktok.dto.ts
@@ -0,0 +1,22 @@
+import { IsBoolean, IsIn, IsString } from 'class-validator';
+
+export class TikTokDto {
+ @IsIn(['PUBLIC_TO_EVERYONE', 'MUTUAL_FOLLOW_FRIENDS', 'FOLLOWER_OF_CREATOR', 'SELF_ONLY'])
+ @IsString()
+ privacy_level: 'PUBLIC_TO_EVERYONE' | 'MUTUAL_FOLLOW_FRIENDS' | 'FOLLOWER_OF_CREATOR' | 'SELF_ONLY';
+
+ @IsBoolean()
+ disable_duet: boolean;
+
+ @IsBoolean()
+ disable_stitch: boolean;
+
+ @IsBoolean()
+ disable_comment: boolean;
+
+ @IsBoolean()
+ brand_content_toggle: boolean;
+
+ @IsBoolean()
+ brand_organic_toggle: boolean;
+}
diff --git a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts
index de634367..ace3bce3 100644
--- a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts
+++ b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts
@@ -4,7 +4,6 @@ import {
PostResponse,
SocialProvider,
} from '@gitroom/nestjs-libraries/integrations/social/social.integrations.interface';
-import { makeId } from '@gitroom/nestjs-libraries/services/make.is';
import dayjs from 'dayjs';
import { SocialAbstract } from '@gitroom/nestjs-libraries/integrations/social.abstract';
@@ -13,57 +12,71 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
name = 'Tiktok';
isBetweenSteps = false;
- async refreshToken(refresh_token: string): Promise
{
+ async refreshToken(refreshToken: string): Promise {
+ const value = {
+ client_key: process.env.TIKTOK_CLIENT_ID!,
+ client_secret: process.env.TIKTOK_CLIENT_SECRET!,
+ grant_type: 'authorization_code',
+ refresh_token: refreshToken,
+ };
+
+ const { access_token, refresh_token } = await (
+ await this.fetch('https://open.tiktokapis.com/v2/oauth/token/', {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ method: 'POST',
+ body: new URLSearchParams(value).toString(),
+ })
+ ).json();
+
+ const {
+ data: {
+ user: { avatar_url, display_name, open_id },
+ },
+ } = await (
+ await fetch(
+ 'https://open.tiktokapis.com/v2/user/info/?fields=open_id,avatar_url,display_name',
+ {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${access_token}`,
+ },
+ }
+ )
+ ).json();
+
return {
- refreshToken: '',
- expiresIn: 0,
- accessToken: '',
- id: '',
- name: '',
- picture: '',
- username: '',
+ refreshToken: refresh_token,
+ expiresIn: dayjs().add(23, 'hours').unix() - dayjs().unix(),
+ accessToken: access_token,
+ id: open_id.replace(/-/g, ''),
+ name: display_name,
+ picture: avatar_url,
+ username: display_name.toLowerCase(),
};
}
async generateAuthUrl(refresh?: string) {
- const state = makeId(6);
- console.log(
- 'https://www.tiktok.com/v2/auth/authorize' +
- `?client_key=${process.env.TIKTOK_CLIENT_ID}` +
- `&redirect_uri=${encodeURIComponent(
- `${
- process.env.NODE_ENV === 'development' || !process.env.NODE_ENV
- ? 'https://redirectmeto.com/'
- : ''
- }${process.env.FRONTEND_URL}/integrations/social/tiktok${
- refresh ? `?refresh=${refresh}` : ''
- }`
- )}` +
- `&state=${state}` +
- `&response_type=code` +
- `&scope=${encodeURIComponent(
- 'user.info.basic,video.publish,video.upload'
- )}`
- );
+ const state = Math.random().toString(36).substring(2);
+
return {
url:
- 'https://www.tiktok.com/v2/auth/authorize' +
+ 'https://www.tiktok.com/v2/auth/authorize/' +
`?client_key=${process.env.TIKTOK_CLIENT_ID}` +
`&redirect_uri=${encodeURIComponent(
`${
process.env.NODE_ENV === 'development' || !process.env.NODE_ENV
- ? 'https://redirectmeto.com/'
- : ''
- }${process.env.FRONTEND_URL}/integrations/social/tiktok${
- refresh ? `?refresh=${refresh}` : ''
- }`
+ ? `https://integration.git.sn/integrations/social/tiktok`
+ : `${process.env.FRONTEND_URL}/integrations/social/tiktok`
+ }${refresh ? `?refresh=${refresh}` : ''}`
)}` +
`&state=${state}` +
`&response_type=code` +
`&scope=${encodeURIComponent(
'user.info.basic,video.publish,video.upload'
)}`,
- codeVerifier: makeId(10),
+ codeVerifier: state,
state,
};
}
@@ -73,15 +86,52 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
codeVerifier: string;
refresh?: string;
}) {
- console.log(params);
+ const value = {
+ client_key: process.env.TIKTOK_CLIENT_ID!,
+ client_secret: process.env.TIKTOK_CLIENT_SECRET!,
+ code: params.code,
+ grant_type: 'authorization_code',
+ code_verifier: params.codeVerifier,
+ redirect_uri:
+ process.env.NODE_ENV === 'development' || !process.env.NODE_ENV
+ ? `https://integration.git.sn/integrations/social/tiktok`
+ : `${process.env.FRONTEND_URL}/integrations/social/tiktok`,
+ };
+
+ const { access_token, refresh_token } = await (
+ await this.fetch('https://open.tiktokapis.com/v2/oauth/token/', {
+ headers: {
+ 'Content-Type': 'application/x-www-form-urlencoded',
+ },
+ method: 'POST',
+ body: new URLSearchParams(value).toString(),
+ })
+ ).json();
+
+ const {
+ data: {
+ user: { avatar_url, display_name, open_id },
+ },
+ } = await (
+ await fetch(
+ 'https://open.tiktokapis.com/v2/user/info/?fields=open_id,avatar_url,display_name',
+ {
+ method: 'GET',
+ headers: {
+ Authorization: `Bearer ${access_token}`,
+ },
+ }
+ )
+ ).json();
+
return {
- id: '',
- name: '',
- accessToken: '',
- refreshToken: '',
- expiresIn: dayjs().add(59, 'days').unix() - dayjs().unix(),
- picture: '',
- username: '',
+ id: open_id.replace(/-/g, ''),
+ name: display_name,
+ accessToken: access_token,
+ refreshToken: refresh_token,
+ expiresIn: dayjs().add(23, 'hours').unix() - dayjs().unix(),
+ picture: avatar_url,
+ username: display_name.toLowerCase(),
};
}