diff --git a/apps/frontend/src/app/(app)/api/uploads/[[...path]]/route.ts b/apps/frontend/src/app/(app)/api/uploads/[[...path]]/route.ts index 6cc55e1b6..e82ab8c2b 100644 --- a/apps/frontend/src/app/(app)/api/uploads/[[...path]]/route.ts +++ b/apps/frontend/src/app/(app)/api/uploads/[[...path]]/route.ts @@ -19,30 +19,39 @@ function iteratorToStream(iterator: any) { }, }); } -export const GET = ( +export const GET = async ( request: NextRequest, context: { - params: { + params: Promise<{ path: string[]; - }; + }>; } ) => { - const filePath = - process.env.UPLOAD_DIRECTORY + '/' + context.params.path.join('/'); - const response = createReadStream(filePath); - const fileStats = statSync(filePath); - const contentType = mime.getType(filePath) || 'application/octet-stream'; - const iterator = nodeStreamToIterator(response); - const webStream = iteratorToStream(iterator); - return new Response(webStream, { - headers: { - 'Content-Type': contentType, - // Set the appropriate content-type header - 'Content-Length': fileStats.size.toString(), - // Set the content-length header - 'Last-Modified': fileStats.mtime.toUTCString(), - // Set the last-modified header - 'Cache-Control': 'public, max-age=31536000, immutable', // Example cache-control header - }, - }); + try { + const params = await context.params; + const filePath = + process.env.UPLOAD_DIRECTORY + '/' + params.path.join('/'); + const response = createReadStream(filePath); + const fileStats = statSync(filePath); + const contentType = mime.getType(filePath) || 'application/octet-stream'; + const iterator = nodeStreamToIterator(response); + const webStream = iteratorToStream(iterator); + return new Response(webStream, { + headers: { + 'Content-Type': contentType, + // Set the appropriate content-type header + 'Content-Length': fileStats.size.toString(), + // Set the content-length header + 'Last-Modified': fileStats.mtime.toUTCString(), + // Set the last-modified header + 'Cache-Control': 'public, max-age=31536000, immutable', // Example cache-control header + }, + }); + } catch (error: any) { + console.error('Error serving upload:', error); + return new NextResponse( + JSON.stringify({ error: 'File not found', message: error.message }), + { status: 404, headers: { 'Content-Type': 'application/json' } } + ); + } }; diff --git a/apps/frontend/src/components/agents/agent.chat.tsx b/apps/frontend/src/components/agents/agent.chat.tsx index 2f8aa0a6b..f1716eee4 100644 --- a/apps/frontend/src/components/agents/agent.chat.tsx +++ b/apps/frontend/src/components/agents/agent.chat.tsx @@ -159,7 +159,7 @@ const NewInput: FC = (props) => { ? '\n[--Media--]' + media .map((m) => - m.path.indexOf('mp4') > -1 + m.path.toLowerCase().indexOf('mp4') > -1 ? `Video: ${m.path}` : `Image: ${m.path}` ) diff --git a/apps/frontend/src/components/launches/helpers/media.settings.component.tsx b/apps/frontend/src/components/launches/helpers/media.settings.component.tsx index 3ce19f2c3..9924b9971 100644 --- a/apps/frontend/src/components/launches/helpers/media.settings.component.tsx +++ b/apps/frontend/src/components/launches/helpers/media.settings.component.tsx @@ -375,7 +375,7 @@ export const MediaComponentInner: FC<{ className="w-full px-3 py-2 bg-fifth border border-tableBorder rounded-lg text-textColor placeholder-gray-400 focus:outline-none focus:ring-2 focus:ring-forth focus:border-transparent" /> - {media?.path.indexOf('mp4') > -1 && ( + {media?.path.toLowerCase().indexOf('mp4') > -1 && ( <> {/* Alt Text Input */}
diff --git a/apps/frontend/src/components/launches/repeat.component.tsx b/apps/frontend/src/components/launches/repeat.component.tsx index 883255bd9..bd6579a3e 100644 --- a/apps/frontend/src/components/launches/repeat.component.tsx +++ b/apps/frontend/src/components/launches/repeat.component.tsx @@ -51,10 +51,17 @@ export const RepeatComponent: FC<{ label="" hideErrors={true} name="repeat" - value={repeat ? repeat : undefined} - onChange={(e) => props.onChange(Number(e.target.value))} + value={repeat ?? 0} + onChange={(e) => { + const value = e.target.value; + if (value === '0') { + props.onChange(0); + return; + } + props.onChange(Number(value)); + }} > - + {list.map((item) => (
- {media.path.indexOf('mp4') > -1 ? ( + {media.path.toLowerCase().indexOf('mp4') > -1 ? ( ) : ( - {media?.path?.indexOf('mp4') > -1 ? ( + {media?.path?.toLowerCase().indexOf('mp4') > -1 ? ( ) : ( { if ( posts.some( - (p) => p.some((a) => a.path.indexOf('mp4') > -1) && p.length > 1 + (p) => p.some((a) => a.path.toLowerCase().indexOf('mp4') > -1) && p.length > 1 ) ) { return 'You can only upload one video per post.'; diff --git a/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.provider.tsx b/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.provider.tsx index ddc040c39..b7340eab4 100644 --- a/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/dribbble/dribbble.provider.tsx @@ -25,7 +25,7 @@ export default withProvider({ CustomPreviewComponent: undefined, dto: DribbbleDto, checkValidity: async ([firstItem, ...otherItems]) => { - const isMp4 = firstItem?.find((item) => item.path.indexOf('mp4') > -1); + const isMp4 = firstItem?.find((item) => item.path.toLowerCase().indexOf('mp4') > -1); if (firstItem.length !== 1) { return 'Requires one item'; } diff --git a/apps/frontend/src/components/new-launch/providers/instagram/instagram.collaborators.tsx b/apps/frontend/src/components/new-launch/providers/instagram/instagram.collaborators.tsx index c269fc64a..63ad97b30 100644 --- a/apps/frontend/src/components/new-launch/providers/instagram/instagram.collaborators.tsx +++ b/apps/frontend/src/components/new-launch/providers/instagram/instagram.collaborators.tsx @@ -68,7 +68,7 @@ export default withProvider({ } const checkVideosLength = await Promise.all( firstPost - .filter((f) => f.path.indexOf('mp4') > -1) + .filter((f) => f.path.toLowerCase().indexOf('mp4') > -1) .flatMap((p) => p.path) .map((p) => { return new Promise((res) => { diff --git a/apps/frontend/src/components/new-launch/providers/linkedin/linkedin.provider.tsx b/apps/frontend/src/components/new-launch/providers/linkedin/linkedin.provider.tsx index b4b0e07dd..a4d006b61 100644 --- a/apps/frontend/src/components/new-launch/providers/linkedin/linkedin.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/linkedin/linkedin.provider.tsx @@ -37,14 +37,14 @@ export default withProvider({ if ( vals.post_as_images_carousel && (firstPost.length < 2 || - firstPost.some((p) => p.path.indexOf('mp4') > -1)) + firstPost.some((p) => p.path.toLowerCase().indexOf('mp4') > -1)) ) { return 'Carousel can only be created with 2 or more images and no videos.'; } if ( firstPost.length > 1 && - firstPost.some((p) => p.path.indexOf('mp4') > -1) + firstPost.some((p) => p.path.toLowerCase().indexOf('mp4') > -1) ) { return 'Can have maximum 1 media when selecting a video.'; } diff --git a/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.provider.tsx b/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.provider.tsx index e628eb83c..9dea3f51c 100644 --- a/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/pinterest/pinterest.provider.tsx @@ -33,9 +33,9 @@ export default withProvider({ CustomPreviewComponent: undefined, dto: PinterestSettingsDto, checkValidity: async ([firstItem, ...otherItems]) => { - const isMp4 = firstItem?.find((item) => item.path.indexOf('mp4') > -1); + const isMp4 = firstItem?.find((item) => item.path.toLowerCase().indexOf('mp4') > -1); const isPicture = firstItem?.find( - (item) => item.path.indexOf('mp4') === -1 + (item) => item.path.toLowerCase().indexOf('mp4') === -1 ); if (firstItem.length === 0) { return 'Requires at least one media'; @@ -51,7 +51,7 @@ export default withProvider({ } if ( firstItem.length > 1 && - firstItem.every((p) => p.path.indexOf('mp4') == -1) + firstItem.every((p) => p.path.toLowerCase().indexOf('mp4') == -1) ) { const loadAll: Array<{ width: number; diff --git a/apps/frontend/src/components/new-launch/providers/reddit/reddit.provider.tsx b/apps/frontend/src/components/new-launch/providers/reddit/reddit.provider.tsx index 18ce5cae1..d2a2eeae2 100644 --- a/apps/frontend/src/components/new-launch/providers/reddit/reddit.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/reddit/reddit.provider.tsx @@ -226,7 +226,7 @@ export default withProvider({ if ( posts.some((p) => - p.some((a) => !a.thumbnail && a.path.indexOf('mp4') > -1) + p.some((a) => !a.thumbnail && a.path.toLowerCase().indexOf('mp4') > -1) ) ) { return 'You must attach a thumbnail to your video post.'; diff --git a/apps/frontend/src/components/new-launch/providers/threads/threads.provider.tsx b/apps/frontend/src/components/new-launch/providers/threads/threads.provider.tsx index 01ebc7184..3b910f846 100644 --- a/apps/frontend/src/components/new-launch/providers/threads/threads.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/threads/threads.provider.tsx @@ -18,7 +18,7 @@ export default withProvider({ checkValidity: async ([firstPost, ...otherPosts], settings) => { const checkVideosLength = await Promise.all( firstPost - .filter((f) => f.path.indexOf('mp4') > -1) + .filter((f) => f.path.toLowerCase().indexOf('mp4') > -1) .flatMap((p) => p.path) .map((p) => { return new Promise((res) => { diff --git a/apps/frontend/src/components/new-launch/providers/tiktok/tiktok.provider.tsx b/apps/frontend/src/components/new-launch/providers/tiktok/tiktok.provider.tsx index 29c83f10f..782a625d3 100644 --- a/apps/frontend/src/components/new-launch/providers/tiktok/tiktok.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/tiktok/tiktok.provider.tsx @@ -59,7 +59,7 @@ const CheckTikTokValidity: FC<{ }, [maxVideoLength, registerVideo] ); - if (!maxVideoLength || !video || video.indexOf('mp4') === -1) { + if (!maxVideoLength || !video || video.toLowerCase().indexOf('mp4') === -1) { return null; } return ( @@ -92,7 +92,7 @@ const TikTokSettings: FC<{ const t = useT(); const isTitle = useMemo(() => { - return value?.[0].image.some((p) => p.path.indexOf('mp4') === -1); + return value?.[0].image.some((p) => p.path.toLowerCase().indexOf('mp4') === -1); }, [value]); const disclose = watch('disclose'); @@ -376,12 +376,12 @@ export default withProvider({ } if ( firstItems.length > 1 && - firstItems?.some((p) => p?.path?.indexOf('mp4') > -1) + firstItems?.some((p) => p?.path?.toLowerCase().indexOf('mp4') > -1) ) { return 'Only pictures are supported when selecting multiple items'; } else if ( firstItems?.length !== 1 && - firstItems?.[0]?.path?.indexOf('mp4') > -1 + firstItems?.[0]?.path?.toLowerCase().indexOf('mp4') > -1 ) { return 'You need one media'; } diff --git a/apps/frontend/src/components/new-launch/providers/warpcast/warpcast.provider.tsx b/apps/frontend/src/components/new-launch/providers/warpcast/warpcast.provider.tsx index 1d3e25efc..47e45421e 100644 --- a/apps/frontend/src/components/new-launch/providers/warpcast/warpcast.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/warpcast/warpcast.provider.tsx @@ -65,7 +65,7 @@ export default withProvider({ dto: undefined, checkValidity: async (list) => { if ( - list.some((item) => item.some((field) => field.path.indexOf('mp4') > -1)) + list.some((item) => item.some((field) => field.path.toLowerCase().indexOf('mp4') > -1)) ) { return 'Can only accept images'; } diff --git a/apps/frontend/src/components/new-launch/providers/x/x.provider.tsx b/apps/frontend/src/components/new-launch/providers/x/x.provider.tsx index 2ddc7e71b..9188e655e 100644 --- a/apps/frontend/src/components/new-launch/providers/x/x.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/x/x.provider.tsx @@ -85,13 +85,13 @@ export default withProvider({ } if ( posts.some( - (p) => p.some((m) => m.path.indexOf('mp4') > -1) && p.length > 1 + (p) => p.some((m) => m.path.toLowerCase().indexOf('mp4') > -1) && p.length > 1 ) ) { return 'There can be maximum 1 video in a post.'; } for (const load of posts.flatMap((p) => p.flatMap((a) => a.path))) { - if (load.indexOf('mp4') > -1) { + if (load.toLowerCase().indexOf('mp4') > -1) { const isValid = await checkVideoDuration(load, premium); if (!isValid) { return 'Video duration must be less than or equal to 140 seconds.'; diff --git a/apps/frontend/src/components/new-launch/providers/youtube/youtube.provider.tsx b/apps/frontend/src/components/new-launch/providers/youtube/youtube.provider.tsx index d9772d3a3..09bda247b 100644 --- a/apps/frontend/src/components/new-launch/providers/youtube/youtube.provider.tsx +++ b/apps/frontend/src/components/new-launch/providers/youtube/youtube.provider.tsx @@ -70,7 +70,7 @@ export default withProvider({ if (items[0].length !== 1) { return 'You need one media'; } - if (firstItems[0].path.indexOf('mp4') === -1) { + if (firstItems[0].path.toLowerCase().indexOf('mp4') === -1) { return 'Item must be a video'; } return true; diff --git a/apps/frontend/src/components/videos/providers/veo3.provider.tsx b/apps/frontend/src/components/videos/providers/veo3.provider.tsx index d561cb3bc..788bc48dc 100644 --- a/apps/frontend/src/components/videos/providers/veo3.provider.tsx +++ b/apps/frontend/src/components/videos/providers/veo3.provider.tsx @@ -46,7 +46,7 @@ const VEO3Settings: FC = () => { setValue( 'images', val.target.value - .filter((f) => f.path.indexOf('mp4') === -1) + .filter((f) => f.path.toLowerCase().indexOf('mp4') === -1) .slice(0, 3) ) } diff --git a/libraries/helpers/src/utils/valid.url.path.ts b/libraries/helpers/src/utils/valid.url.path.ts index 469f82293..71c28ed0e 100644 --- a/libraries/helpers/src/utils/valid.url.path.ts +++ b/libraries/helpers/src/utils/valid.url.path.ts @@ -7,19 +7,21 @@ import { @ValidatorConstraint({ name: 'checkValidExtension', async: false }) export class ValidUrlExtension implements ValidatorConstraintInterface { validate(text: string, args: ValidationArguments) { + if (!text) return false; + const lowerText = text.toLowerCase(); return ( - text?.endsWith('.png') || - text?.endsWith('.jpg') || - text?.endsWith('.jpeg') || - text?.endsWith('.gif') || - text?.endsWith('.mp4') + lowerText.endsWith('.png') || + lowerText.endsWith('.jpg') || + lowerText.endsWith('.jpeg') || + lowerText.endsWith('.gif') || + lowerText.endsWith('.mp4') ); } defaultMessage(args: ValidationArguments) { // here you can provide default error message if validation failed return ( - 'File must have a valid extension: .png, .jpg, .jpeg, .gif, or .mp4' + 'File must have a valid extension: .png, .jpg, .jpeg, .gif, or .mp4 (case-insensitive)' ); } } diff --git a/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts b/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts index a54758e6e..dd06503a5 100644 --- a/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts +++ b/libraries/nestjs-libraries/src/database/prisma/integrations/integration.service.ts @@ -104,7 +104,7 @@ export class IntegrationService { customInstanceDetails?: string ) { const uploadedPicture = picture - ? picture?.indexOf('imagedelivery.net') > -1 + ? picture?.indexOf('imagedelivery.net') > -1 || picture?.indexOf('/uploads') > -1 ? picture : await this.storage.uploadSimple(picture) : undefined; diff --git a/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts b/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts index 3e1aa59bd..de21b2254 100644 --- a/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/bluesky.provider.ts @@ -269,9 +269,9 @@ export class BlueskyProvider extends SocialAbstract implements SocialProvider { for (const post of postDetails) { // Separate images and videos const imageMedia = - post.media?.filter((p) => p.path.indexOf('mp4') === -1) || []; + post.media?.filter((p) => p.path.toLowerCase().indexOf('mp4') === -1) || []; const videoMedia = - post.media?.filter((p) => p.path.indexOf('mp4') !== -1) || []; + post.media?.filter((p) => p.path.toLowerCase().indexOf('mp4') !== -1) || []; // Upload images const images = await Promise.all( diff --git a/libraries/nestjs-libraries/src/integrations/social/facebook.provider.ts b/libraries/nestjs-libraries/src/integrations/social/facebook.provider.ts index bebd91a20..10fb1bf5e 100644 --- a/libraries/nestjs-libraries/src/integrations/social/facebook.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/facebook.provider.ts @@ -299,7 +299,7 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider { let finalId = ''; let finalUrl = ''; - if ((firstPost?.media?.[0]?.path?.indexOf('mp4') || -2) > -1) { + if ((firstPost?.media?.[0]?.path?.toLowerCase().indexOf('mp4') || -2) > -1) { const { id: videoId, permalink_url, diff --git a/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts b/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts index 2cc499e2a..86f79d86b 100644 --- a/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/instagram.provider.ts @@ -468,22 +468,38 @@ export class InstagramProvider : ``; const isCarousel = (firstPost?.media?.length || 0) > 1 ? `&is_carousel_item=true` : ``; + + // Construct proper media URL using FRONTEND_URL + let mediaUrl = m.path; + + // If it's not already a full HTTPS URL, construct it using FRONTEND_URL + if (!mediaUrl.startsWith('https://')) { + // Remove localhost URL prefix if present + const cleanPath = mediaUrl.replace(/^https?:\/\/[^\/]+/, ''); + // Ensure path starts with / + const pathWithSlash = cleanPath.startsWith('/') ? cleanPath : `/${cleanPath}`; + // Use FRONTEND_URL to construct the full URL + mediaUrl = `${process.env.FRONTEND_URL}${pathWithSlash}`; + } + + console.log('Media URL being sent to Instagram:', mediaUrl); + const mediaType = - m.path.indexOf('.mp4') > -1 + m.path.toLowerCase().indexOf('.mp4') > -1 ? firstPost?.media?.length === 1 ? isStory - ? `video_url=${m.path}&media_type=STORIES` - : `video_url=${m.path}&media_type=REELS&thumb_offset=${ + ? `video_url=${mediaUrl}&media_type=STORIES` + : `video_url=${mediaUrl}&media_type=REELS&thumb_offset=${ m?.thumbnailTimestamp || 0 }` : isStory - ? `video_url=${m.path}&media_type=STORIES` - : `video_url=${m.path}&media_type=VIDEO&thumb_offset=${ + ? `video_url=${mediaUrl}&media_type=STORIES` + : `video_url=${mediaUrl}&media_type=VIDEO&thumb_offset=${ m?.thumbnailTimestamp || 0 }` : isStory - ? `image_url=${m.path}&media_type=STORIES` - : `image_url=${m.path}`; + ? `image_url=${mediaUrl}&media_type=STORIES` + : `image_url=${mediaUrl}`; console.log('in progress1'); const collaborators = @@ -529,7 +545,8 @@ export class InstagramProvider let containerIdGlobal = ''; let linkGlobal = ''; if (medias.length === 1) { - const { id: mediaId } = await ( + console.log('Publishing media to Instagram, container ID:', medias[0]); + const publishResponse = await ( await this.fetch( `https://${type}/v20.0/${id}/media_publish?creation_id=${medias[0]}&access_token=${accessToken}&field=id`, { @@ -538,6 +555,9 @@ export class InstagramProvider ) ).json(); + console.log('Instagram publish response:', JSON.stringify(publishResponse)); + const { id: mediaId } = publishResponse; + containerIdGlobal = mediaId; const { permalink } = await ( @@ -546,6 +566,8 @@ export class InstagramProvider ) ).json(); + console.log('Instagram post published successfully! Permalink:', permalink); + arr.push({ id: firstPost.id, postId: mediaId, diff --git a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts index 4aa1c9d5b..1ca53a59c 100644 --- a/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/linkedin.provider.ts @@ -211,7 +211,7 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider { type = 'personal' as 'company' | 'personal' ) { // Determine the appropriate endpoint based on file type - const isVideo = fileName.indexOf('mp4') > -1; + const isVideo = fileName.toLowerCase().indexOf('mp4') > -1; const isPdf = fileName.toLowerCase().indexOf('pdf') > -1; let endpoint: string; @@ -474,7 +474,7 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider { } private async prepareMediaBuffer(mediaUrl: string): Promise { - const isVideo = mediaUrl.indexOf('mp4') > -1; + const isVideo = mediaUrl.toLowerCase().indexOf('mp4') > -1; if (isVideo) { return Buffer.from(await readOrFetch(mediaUrl)); diff --git a/libraries/nestjs-libraries/src/integrations/social/pinterest.provider.ts b/libraries/nestjs-libraries/src/integrations/social/pinterest.provider.ts index f97790109..d37418624 100644 --- a/libraries/nestjs-libraries/src/integrations/social/pinterest.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/pinterest.provider.ts @@ -182,10 +182,10 @@ export class PinterestProvider ): Promise { let mediaId = ''; const findMp4 = postDetails?.[0]?.media?.find( - (p) => (p.path?.indexOf('mp4') || -1) > -1 + (p) => (p.path?.toLowerCase().indexOf('mp4') || -1) > -1 ); const picture = postDetails?.[0]?.media?.find( - (p) => (p.path?.indexOf('mp4') || -1) === -1 + (p) => (p.path?.toLowerCase().indexOf('mp4') || -1) === -1 ); if (findMp4) { diff --git a/libraries/nestjs-libraries/src/integrations/social/reddit.provider.ts b/libraries/nestjs-libraries/src/integrations/social/reddit.provider.ts index 8a3eb0e05..00c431387 100644 --- a/libraries/nestjs-libraries/src/integrations/social/reddit.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/reddit.provider.ts @@ -192,7 +192,7 @@ export class RedditProvider extends SocialAbstract implements SocialProvider { title: firstPostSettings.value.title || '', kind: firstPostSettings.value.type === 'media' - ? post.media[0].path.indexOf('mp4') > -1 + ? post.media[0].path.toLowerCase().indexOf('mp4') > -1 ? 'video' : 'image' : firstPostSettings.value.type, @@ -210,7 +210,7 @@ export class RedditProvider extends SocialAbstract implements SocialProvider { accessToken, post.media[0].path ), - ...(post.media[0].path.indexOf('mp4') > -1 + ...(post.media[0].path.toLowerCase().indexOf('mp4') > -1 ? { video_poster_url: await this.uploadFileToReddit( accessToken, diff --git a/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts b/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts index 3a39b13e1..e7739d08b 100644 --- a/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/threads.provider.ts @@ -168,7 +168,7 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider { replyToId?: string ): Promise { const mediaType = - media.path.indexOf('.mp4') > -1 ? 'video_url' : 'image_url'; + media.path.toLowerCase().indexOf('.mp4') > -1 ? 'video_url' : 'image_url'; const mediaParams = new URLSearchParams({ ...(mediaType === 'video_url' ? { video_url: media.path } : {}), ...(mediaType === 'image_url' ? { image_url: media.path } : {}), diff --git a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts index 41b4eebce..ac6a82725 100644 --- a/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/tiktok.provider.ts @@ -438,14 +438,14 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider { ): Promise { const [firstPost] = postDetails; - const isPhoto = (firstPost?.media?.[0]?.path?.indexOf('mp4') || -1) === -1; + const isPhoto = (firstPost?.media?.[0]?.path?.toLowerCase().indexOf('mp4') || -1) === -1; const { data: { publish_id }, } = await ( await this.fetch( `https://open.tiktokapis.com/v2/post/publish${this.postingMethod( firstPost.settings.content_posting_method, - (firstPost?.media?.[0]?.path?.indexOf('mp4') || -1) === -1 + (firstPost?.media?.[0]?.path?.toLowerCase().indexOf('mp4') || -1) === -1 )}`, { method: 'POST', @@ -477,7 +477,7 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider { firstPost.settings.brand_content_toggle || false, brand_organic_toggle: firstPost.settings.brand_organic_toggle || false, - ...((firstPost?.media?.[0]?.path?.indexOf('mp4') || -1) === + ...((firstPost?.media?.[0]?.path?.toLowerCase().indexOf('mp4') || -1) === -1 ? { auto_add_music: @@ -487,7 +487,7 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider { }, } : {}), - ...((firstPost?.media?.[0]?.path?.indexOf('mp4') || -1) > -1 + ...((firstPost?.media?.[0]?.path?.toLowerCase().indexOf('mp4') || -1) > -1 ? { source_info: { source: 'PULL_FROM_URL', diff --git a/libraries/nestjs-libraries/src/integrations/social/vk.provider.ts b/libraries/nestjs-libraries/src/integrations/social/vk.provider.ts index adbc8600f..b86b2bbec 100644 --- a/libraries/nestjs-libraries/src/integrations/social/vk.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/vk.provider.ts @@ -172,7 +172,7 @@ export class VkProvider extends SocialAbstract implements SocialProvider { (post?.media || []).map(async (media) => { const all = await ( await this.fetch( - media.path.indexOf('mp4') > -1 + media.path.toLowerCase().indexOf('mp4') > -1 ? `https://api.vk.com/method/video.save?access_token=${accessToken}&v=5.251` : `https://api.vk.com/method/photos.getWallUploadServer?owner_id=${userId}&access_token=${accessToken}&v=5.251` ) @@ -197,7 +197,7 @@ export class VkProvider extends SocialAbstract implements SocialProvider { }) ).data; - if (media.path.indexOf('mp4') > -1) { + if (media.path.toLowerCase().indexOf('mp4') > -1) { return { id: all.response.video_id, type: 'video', diff --git a/libraries/nestjs-libraries/src/integrations/social/x.provider.ts b/libraries/nestjs-libraries/src/integrations/social/x.provider.ts index e1ad9eee4..1cb654a84 100644 --- a/libraries/nestjs-libraries/src/integrations/social/x.provider.ts +++ b/libraries/nestjs-libraries/src/integrations/social/x.provider.ts @@ -330,7 +330,7 @@ export class XProvider extends SocialAbstract implements SocialProvider { id: await this.runInConcurrent( async () => client.v1.uploadMedia( - m.path.indexOf('mp4') > -1 + m.path.toLowerCase().indexOf('mp4') > -1 ? Buffer.from(await readOrFetch(m.path)) : await sharp(await readOrFetch(m.path), { animated: lookup(m.path) === 'image/gif', diff --git a/libraries/react-shared-libraries/src/helpers/video.or.image.tsx b/libraries/react-shared-libraries/src/helpers/video.or.image.tsx index acade7866..cba704f75 100644 --- a/libraries/react-shared-libraries/src/helpers/video.or.image.tsx +++ b/libraries/react-shared-libraries/src/helpers/video.or.image.tsx @@ -6,7 +6,7 @@ export const VideoOrImage: FC<{ isContain?: boolean; }> = (props) => { const { src, autoplay, isContain } = props; - if (src?.indexOf('mp4') > -1) { + if (src?.toLowerCase().indexOf('mp4') > -1) { return (