feat: trial reels

This commit is contained in:
Nevo David 2026-02-10 10:21:38 +07:00
parent 5869300e64
commit 0ceaa3d04d
3 changed files with 74 additions and 3 deletions

View file

@ -6,6 +6,7 @@ import {
} from '@gitroom/frontend/components/new-launch/providers/high.order.provider';
import { FC } from 'react';
import { Select } from '@gitroom/react/form/select';
import { Checkbox } from '@gitroom/react/form/checkbox';
import { useSettings } from '@gitroom/frontend/components/launches/helpers/use.values';
import { InstagramDto } from '@gitroom/nestjs-libraries/dtos/posts/providers-settings/instagram.dto';
import { InstagramCollaboratorsTags } from '@gitroom/frontend/components/new-launch/providers/instagram/instagram.tags';
@ -21,12 +22,24 @@ const postType = [
label: 'Story',
},
];
const graduationStrategies = [
{
value: 'MANUAL',
label: 'Manual',
},
{
value: 'SS_PERFORMANCE',
label: 'Auto (based on performance)',
},
];
const InstagramCollaborators: FC<{
values?: any;
}> = (props) => {
const t = useT();
const { watch, register, formState, control } = useSettings();
const postCurrentType = watch('post_type');
const isTrialReel = watch('is_trial_reel');
return (
<>
<Select
@ -51,6 +64,32 @@ const InstagramCollaborators: FC<{
})}
/>
)}
{postCurrentType === 'post' && (
<div className="mt-[18px] flex flex-col gap-[18px]">
<Checkbox
{...register('is_trial_reel', {
value: false,
})}
label={t('trial_reel', 'Trial Reel (share only to non-followers first)')}
/>
{isTrialReel && (
<Select
label="Graduation Strategy"
{...register('graduation_strategy', {
value: 'MANUAL',
})}
>
{graduationStrategies.map((item) => (
<option key={item.value} value={item.value}>
{item.label}
</option>
))}
</Select>
)}
</div>
)}
</>
);
};
@ -67,6 +106,17 @@ export default withProvider<InstagramDto>({
if ((firstPost?.length ?? 0) > 1 && settings?.post_type === 'story') {
return 'Stories can only have one media';
}
if (settings?.is_trial_reel) {
if ((firstPost?.length ?? 0) > 1) {
return 'Trial Reels can only have one video';
}
const hasVideo = firstPost?.some(
(f) => (f?.path?.indexOf?.('mp4') ?? -1) > -1
);
if (!hasVideo) {
return 'Trial Reels must be a video';
}
}
const checkVideosLength = await Promise.all(
firstPost
?.filter((f) => (f?.path?.indexOf?.('mp4') ?? -1) > -1)

View file

@ -18,6 +18,13 @@ export class InstagramDto {
@IsDefined()
post_type: 'post' | 'story';
@IsOptional()
is_trial_reel?: boolean;
@IsIn(['MANUAL', 'SS_PERFORMANCE'])
@IsOptional()
graduation_strategy?: 'MANUAL' | 'SS_PERFORMANCE';
@Type(() => Collaborators)
@ValidateNested({ each: true })
@IsArray()

View file

@ -64,6 +64,12 @@ export class InstagramProvider
value: 'An unknown error occurred, please try again later',
};
}
if (body.indexOf('2207081') > -1) {
return {
type: 'bad-body' as const,
value: 'This account doesn\'t support Trial Reels',
};
}
if (body.indexOf('REVOKED_ACCESS_TOKEN') > -1) {
return {
@ -457,6 +463,7 @@ export class InstagramProvider
const [firstPost] = postDetails;
console.log('in progress', id);
const isStory = firstPost.settings.post_type === 'story';
const isTrialReel = !!firstPost.settings.is_trial_reel;
const medias = await Promise.all(
firstPost?.media?.map(async (m) => {
const caption =
@ -481,7 +488,15 @@ export class InstagramProvider
: isStory
? `image_url=${m.path}&media_type=STORIES`
: `image_url=${m.path}`;
console.log('in progress1');
const trialParams = isTrialReel
? `&trial_params=${encodeURIComponent(
JSON.stringify({
graduation_strategy:
firstPost.settings.graduation_strategy || 'MANUAL',
})
)}`
: ``;
const collaborators =
firstPost?.settings?.collaborators?.length && !isStory
@ -490,10 +505,9 @@ export class InstagramProvider
)}`
: ``;
console.log(collaborators);
const { id: photoId } = await (
await this.fetch(
`https://${type}/v20.0/${id}/media?${mediaType}${isCarousel}${collaborators}&access_token=${accessToken}${caption}`,
`https://${type}/v20.0/${id}/media?${mediaType}${isCarousel}${collaborators}${trialParams}&access_token=${accessToken}${caption}`,
{
method: 'POST',
}