feat: tiktok fixes
This commit is contained in:
parent
5a7be6e184
commit
16c9c45d1e
|
|
@ -69,7 +69,7 @@ export const EditorWrapper: FC<{ children: ReactNode }> = ({ children }) => {
|
|||
};
|
||||
|
||||
export const withProvider = (
|
||||
SettingsComponent: FC | null,
|
||||
SettingsComponent: FC<{values?: any}> | null,
|
||||
CustomPreviewComponent?: FC<{maximumCharacters?: number}>,
|
||||
dto?: any,
|
||||
checkValidity?: (
|
||||
|
|
@ -403,7 +403,7 @@ export const withProvider = (
|
|||
)}
|
||||
{(showTab === 0 || showTab === 2) && (
|
||||
<div className={clsx('mt-[20px]', showTab !== 2 && 'hidden')}>
|
||||
<Component />
|
||||
<Component values={editInPlace ? InPlaceValue : props.value} />
|
||||
</div>
|
||||
)}
|
||||
{showTab === 0 && (
|
||||
|
|
|
|||
|
|
@ -1,8 +1,16 @@
|
|||
import { FC } from 'react';
|
||||
import {
|
||||
FC,
|
||||
ReactEventHandler,
|
||||
useCallback,
|
||||
useEffect,
|
||||
useMemo,
|
||||
useState,
|
||||
} from 'react';
|
||||
import { withProvider } from '@gitroom/frontend/components/launches/providers/high.order.provider';
|
||||
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';
|
||||
import { useCustomProviderFunction } from '@gitroom/frontend/components/launches/helpers/use.custom.provider.function';
|
||||
|
||||
const privacyLevel = [
|
||||
{
|
||||
|
|
@ -34,10 +42,72 @@ const yesNo = [
|
|||
},
|
||||
];
|
||||
|
||||
const TikTokSettings: FC = () => {
|
||||
const CheckTikTokValidity: FC<{ picture: string }> = (props) => {
|
||||
const { register } = useSettings();
|
||||
const func = useCustomProviderFunction();
|
||||
const [maxVideoLength, setMaxVideoLength] = useState(0);
|
||||
const [isValidVideo, setIsValidVideo] = useState<undefined | boolean>(
|
||||
undefined
|
||||
);
|
||||
|
||||
const registerVideo = register('isValidVideo');
|
||||
const video = useMemo(() => {
|
||||
return props.picture;
|
||||
}, [props.picture]);
|
||||
|
||||
useEffect(() => {
|
||||
loadStats();
|
||||
}, []);
|
||||
|
||||
const loadStats = useCallback(async () => {
|
||||
const { maxDurationSeconds } = await func.get('maxVideoLength');
|
||||
// setMaxVideoLength(5);
|
||||
setMaxVideoLength(maxDurationSeconds);
|
||||
}, []);
|
||||
|
||||
const loadVideo: ReactEventHandler<HTMLVideoElement> = useCallback(
|
||||
(e) => {
|
||||
// @ts-ignore
|
||||
setIsValidVideo(e.target.duration <= maxVideoLength);
|
||||
registerVideo.onChange({
|
||||
target: {
|
||||
name: 'isValidVideo',
|
||||
// @ts-ignore
|
||||
value: String(e.target.duration <= maxVideoLength),
|
||||
},
|
||||
});
|
||||
},
|
||||
[maxVideoLength, registerVideo]
|
||||
);
|
||||
|
||||
if (!maxVideoLength || !video || video.indexOf('mp4') === -1) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
{isValidVideo === false && (
|
||||
<div className="text-red-600 my-[20px]">
|
||||
Video length is invalid, must be up to {maxVideoLength} seconds
|
||||
</div>
|
||||
)}
|
||||
<video
|
||||
controls
|
||||
onLoadedMetadata={loadVideo}
|
||||
className="w-0 h-0 overflow-hidden pointer-events-none"
|
||||
>
|
||||
<source src={video} type="video/mp4" />
|
||||
</video>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const TikTokSettings: FC<{ values?: any }> = (props) => {
|
||||
const { register, control } = useSettings();
|
||||
|
||||
return (
|
||||
<div className="flex flex-col">
|
||||
<CheckTikTokValidity picture={props?.values?.[0]?.image?.[0]?.path} />
|
||||
<Select
|
||||
label="Privacy Level"
|
||||
{...register('privacy_level', {
|
||||
|
|
|
|||
|
|
@ -1,9 +1,18 @@
|
|||
import { IsBoolean, IsIn, IsString } from 'class-validator';
|
||||
import { IsBoolean, IsDefined, IsIn, IsString } from 'class-validator';
|
||||
|
||||
export class TikTokDto {
|
||||
@IsIn(['PUBLIC_TO_EVERYONE', 'MUTUAL_FOLLOW_FRIENDS', 'FOLLOWER_OF_CREATOR', 'SELF_ONLY'])
|
||||
@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';
|
||||
privacy_level:
|
||||
| 'PUBLIC_TO_EVERYONE'
|
||||
| 'MUTUAL_FOLLOW_FRIENDS'
|
||||
| 'FOLLOWER_OF_CREATOR'
|
||||
| 'SELF_ONLY';
|
||||
|
||||
@IsBoolean()
|
||||
disable_duet: boolean;
|
||||
|
|
@ -19,4 +28,8 @@ export class TikTokDto {
|
|||
|
||||
@IsBoolean()
|
||||
brand_organic_toggle: boolean;
|
||||
|
||||
@IsIn(['true'])
|
||||
@IsDefined()
|
||||
isValidVideo: boolean;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -15,7 +15,12 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
|
|||
identifier = 'tiktok';
|
||||
name = 'Tiktok';
|
||||
isBetweenSteps = false;
|
||||
scopes = ['user.info.basic', 'video.publish', 'video.upload'];
|
||||
scopes = [
|
||||
'user.info.basic',
|
||||
'video.publish',
|
||||
'video.upload',
|
||||
'user.info.profile',
|
||||
];
|
||||
|
||||
async refreshToken(refreshToken: string): Promise<AuthTokenDetails> {
|
||||
const value = {
|
||||
|
|
@ -37,11 +42,11 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
|
|||
|
||||
const {
|
||||
data: {
|
||||
user: { avatar_url, display_name, open_id },
|
||||
user: { avatar_url, display_name, open_id, username },
|
||||
},
|
||||
} = await (
|
||||
await fetch(
|
||||
'https://open.tiktokapis.com/v2/user/info/?fields=open_id,avatar_url,display_name',
|
||||
'https://open.tiktokapis.com/v2/user/info/?fields=open_id,avatar_url,display_name,username',
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
|
|
@ -58,7 +63,7 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
|
|||
id: open_id.replace(/-/g, ''),
|
||||
name: display_name,
|
||||
picture: avatar_url,
|
||||
username: display_name.toLowerCase(),
|
||||
username: username,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -119,7 +124,7 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
|
|||
},
|
||||
} = await (
|
||||
await fetch(
|
||||
'https://open.tiktokapis.com/v2/user/info/?fields=open_id,avatar_url,display_name,union_id',
|
||||
'https://open.tiktokapis.com/v2/user/info/?fields=open_id,avatar_url,display_name,union_id,username',
|
||||
{
|
||||
method: 'GET',
|
||||
headers: {
|
||||
|
|
@ -129,8 +134,6 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
|
|||
)
|
||||
).json();
|
||||
|
||||
console.log(username);
|
||||
|
||||
return {
|
||||
id: open_id.replace(/-/g, ''),
|
||||
name: display_name,
|
||||
|
|
@ -138,7 +141,28 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
|
|||
refreshToken: refresh_token,
|
||||
expiresIn: dayjs().add(23, 'hours').unix() - dayjs().unix(),
|
||||
picture: avatar_url,
|
||||
username: display_name,
|
||||
username: username,
|
||||
};
|
||||
}
|
||||
|
||||
async maxVideoLength(accessToken: string) {
|
||||
const {
|
||||
data: { max_video_post_duration_sec },
|
||||
} = await (
|
||||
await this.fetch(
|
||||
'https://open.tiktokapis.com/v2/post/publish/creator_info/query/',
|
||||
{
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'Content-Type': 'application/json; charset=UTF-8',
|
||||
Authorization: `Bearer ${accessToken}`,
|
||||
},
|
||||
}
|
||||
)
|
||||
).json();
|
||||
|
||||
return {
|
||||
maxDurationSeconds: max_video_post_duration_sec,
|
||||
};
|
||||
}
|
||||
|
||||
|
|
@ -190,7 +214,7 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
|
|||
} catch (err) {
|
||||
throw new BadBody('titok-error', JSON.stringify(err), {
|
||||
// @ts-ignore
|
||||
postDetails
|
||||
postDetails,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue