From 9e8792804556dca4765f1ef727044635cabd42a0 Mon Sep 17 00:00:00 2001 From: Nevo David Date: Thu, 7 Aug 2025 21:13:38 +0700 Subject: [PATCH] feat: fix youtube title --- .../components/new-launch/manage.modal.tsx | 1 + .../youtube.settings.dto.ts | 9 +- .../src/integrations/social.abstract.ts | 1 + .../integrations/social/youtube.provider.ts | 137 +++++++++--------- 4 files changed, 70 insertions(+), 78 deletions(-) diff --git a/apps/frontend/src/components/new-launch/manage.modal.tsx b/apps/frontend/src/components/new-launch/manage.modal.tsx index f1657155..41dd7e4e 100644 --- a/apps/frontend/src/components/new-launch/manage.modal.tsx +++ b/apps/frontend/src/components/new-launch/manage.modal.tsx @@ -142,6 +142,7 @@ export const ManageModal: FC = (props) => { (type: 'draft' | 'now' | 'schedule') => async () => { setLoading(true); const checkAllValid = await ref.current.checkAllValid(); + console.log(checkAllValid); if (type !== 'draft') { const notEnoughChars = checkAllValid.filter((p: any) => { return p.values.some((a: any) => { diff --git a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/youtube.settings.dto.ts b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/youtube.settings.dto.ts index 0cf68af4..f2a7045f 100644 --- a/libraries/nestjs-libraries/src/dtos/posts/providers-settings/youtube.settings.dto.ts +++ b/libraries/nestjs-libraries/src/dtos/posts/providers-settings/youtube.settings.dto.ts @@ -1,11 +1,5 @@ import { - IsArray, - IsDefined, - IsIn, - IsOptional, - IsString, - MinLength, - ValidateNested, + IsArray, IsDefined, IsIn, IsOptional, IsString, MaxLength, MinLength, ValidateNested } from 'class-validator'; import { MediaDto } from '@gitroom/nestjs-libraries/dtos/media/media.dto'; import { Type } from 'class-transformer'; @@ -21,6 +15,7 @@ export class YoutubeTagsSettings { export class YoutubeSettingsDto { @IsString() @MinLength(2) + @MaxLength(100) @IsDefined() title: string; diff --git a/libraries/nestjs-libraries/src/integrations/social.abstract.ts b/libraries/nestjs-libraries/src/integrations/social.abstract.ts index 0d46f04b..93cadf14 100644 --- a/libraries/nestjs-libraries/src/integrations/social.abstract.ts +++ b/libraries/nestjs-libraries/src/integrations/social.abstract.ts @@ -50,6 +50,7 @@ export abstract class SocialAbstract { try { return await func(); } catch (err) { + console.log(err); const handle = this.handleErrors(JSON.stringify(err)); return { err: true, ...(handle || {}) }; } diff --git a/libraries/nestjs-libraries/src/integrations/social/youtube.provider.ts b/libraries/nestjs-libraries/src/integrations/social/youtube.provider.ts index d8327ba3..a9f0c369 100644 --- a/libraries/nestjs-libraries/src/integrations/social/youtube.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/youtube.provider.ts @@ -65,6 +65,55 @@ export class YoutubeProvider extends SocialAbstract implements SocialProvider { editor = 'normal' as const; + override handleErrors(body: string): + | { + type: 'refresh-token' | 'bad-body'; + value: string; + } + | undefined { + if (body.includes('invalidTitle')) { + return { + type: 'bad-body', + value: + 'We have uploaded your video but we could not set the title. Title is too long.', + }; + } + + if (body.includes('failedPrecondition')) { + return { + type: 'bad-body', + value: + 'We have uploaded your video but we could not set the thumbnail. Thumbnail size is too large.', + }; + } + + if (body.includes('uploadLimitExceeded')) { + return { + type: 'bad-body', + value: + 'You have reached your daily upload limit, please try again tomorrow.', + }; + } + + if (body.includes('youtubeSignupRequired')) { + return { + type: 'bad-body', + value: + 'You have to link your youtube account to your google account first.', + }; + } + + if (body.includes('youtube.thumbnail')) { + return { + type: 'bad-body', + value: + 'Your account is not verified, we have uploaded your video but we could not set the thumbnail. Please verify your account and try again.', + }; + } + + return undefined; + } + async refreshToken(refresh_token: string): Promise { const { client, oauth2 } = clientAndYoutube(); client.setCredentials({ refresh_token }); @@ -153,9 +202,8 @@ export class YoutubeProvider extends SocialAbstract implements SocialProvider { responseType: 'stream', }); - let all: GaxiosResponse; - try { - all = await this.runInConcurrent(async () => + const all: GaxiosResponse = await this.runInConcurrent( + async () => youtubeClient.videos.insert({ part: ['id', 'snippet', 'status'], notifySubscribers: true, @@ -175,76 +223,23 @@ export class YoutubeProvider extends SocialAbstract implements SocialProvider { body: response.data, }, }) - ); - } catch (err: any) { - if ( - err.response?.data?.error?.errors?.[0]?.reason === 'failedPrecondition' - ) { - throw new BadBody( - 'youtube', - JSON.stringify(err.response.data), - JSON.stringify(err.response.data), - 'We have uploaded your video but we could not set the thumbnail. Thumbnail size is too large.' - ); - } - if ( - err.response?.data?.error?.errors?.[0]?.reason === 'uploadLimitExceeded' - ) { - throw new BadBody( - 'youtube', - JSON.stringify(err.response.data), - JSON.stringify(err.response.data), - 'You have reached your daily upload limit, please try again tomorrow.' - ); - } - if ( - err.response?.data?.error?.errors?.[0]?.reason === - 'youtubeSignupRequired' - ) { - throw new BadBody( - 'youtube', - JSON.stringify(err.response.data), - JSON.stringify(err.response.data), - 'You have to link your youtube account to your google account first.' - ); - } - - throw new BadBody( - 'youtube', - JSON.stringify(err.response.data), - JSON.stringify(err.response.data), - 'An error occurred while uploading your video, please try again later.' - ); - } + ); if (settings?.thumbnail?.path) { - try { - await this.runInConcurrent(async () => - youtubeClient.thumbnails.set({ - videoId: all?.data?.id!, - media: { - body: ( - await axios({ - url: settings?.thumbnail?.path, - method: 'GET', - responseType: 'stream', - }) - ).data, - }, - }) - ); - } catch (err: any) { - if ( - err.response?.data?.error?.errors?.[0]?.domain === 'youtube.thumbnail' - ) { - throw new BadBody( - '', - JSON.stringify(err.response.data), - JSON.stringify(err.response.data), - 'Your account is not verified, we have uploaded your video but we could not set the thumbnail. Please verify your account and try again.' - ); - } - } + await this.runInConcurrent(async () => + youtubeClient.thumbnails.set({ + videoId: all?.data?.id!, + media: { + body: ( + await axios({ + url: settings?.thumbnail?.path, + method: 'GET', + responseType: 'stream', + }) + ).data, + }, + }) + ); } return [