feat: fix apis

This commit is contained in:
Nevo David 2025-06-30 16:42:23 +07:00
parent 6a985f9257
commit fc994982fb
20 changed files with 65 additions and 64 deletions

View File

@ -3,12 +3,14 @@ import {
IsOptional,
IsString,
IsUrl,
MaxLength,
MinLength,
} from 'class-validator';
export class PinterestSettingsDto {
@IsString()
@IsOptional()
@MaxLength(100)
title: string;
@IsString()

View File

@ -241,14 +241,14 @@ export class BlueskyProvider extends SocialAbstract implements SocialProvider {
const cidUrl = [] as { cid: string; url: string; rev: string }[];
for (const post of postDetails) {
// Separate images and videos
const imageMedia = post.media?.filter((p) => p.url.indexOf('mp4') === -1) || [];
const videoMedia = post.media?.filter((p) => p.url.indexOf('mp4') !== -1) || [];
const imageMedia = post.media?.filter((p) => p.path.indexOf('mp4') === -1) || [];
const videoMedia = post.media?.filter((p) => p.path.indexOf('mp4') !== -1) || [];
// Upload images
const images = await Promise.all(
imageMedia.map(async (p) => {
return await agent.uploadBlob(
new Blob([await reduceImageBySize(p.url)])
new Blob([await reduceImageBySize(p.path)])
);
})
);
@ -256,7 +256,7 @@ export class BlueskyProvider extends SocialAbstract implements SocialProvider {
// Upload videos (only one video per post is supported by Bluesky)
let videoEmbed: AppBskyEmbedVideo.Main | null = null;
if (videoMedia.length > 0) {
videoEmbed = await uploadVideo(agent, videoMedia[0].url);
videoEmbed = await uploadVideo(agent, videoMedia[0].path);
}
const rt = new RichText({

View File

@ -161,19 +161,19 @@ export class DiscordProvider extends SocialAbstract implements SocialProvider {
attachments: post.media?.map((p, index) => ({
id: index,
description: `Picture ${index}`,
filename: p.url.split('/').pop(),
filename: p.path.split('/').pop(),
})),
})
);
let index = 0;
for (const media of post.media || []) {
const loadMedia = await fetch(media.url);
const loadMedia = await fetch(media.path);
form.append(
`files[${index}]`,
await loadMedia.blob(),
media.url.split('/').pop()
media.path.split('/').pop()
);
index++;
}

View File

@ -130,13 +130,13 @@ export class DribbbleProvider extends SocialAbstract implements SocialProvider {
postDetails: PostDetails<DribbbleDto>[]
): Promise<PostResponse[]> {
const { data, status } = await axios.get(
postDetails?.[0]?.media?.[0]?.url!,
postDetails?.[0]?.media?.[0]?.path!,
{
responseType: 'stream',
}
);
const slash = postDetails?.[0]?.media?.[0]?.url.split('/').at(-1);
const slash = postDetails?.[0]?.media?.[0]?.path.split('/').at(-1);
const formData = new FormData();
formData.append('image', data, {

View File

@ -176,7 +176,7 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
let finalId = '';
let finalUrl = '';
if ((firstPost?.media?.[0]?.url?.indexOf('mp4') || -2) > -1) {
if ((firstPost?.media?.[0]?.path?.indexOf('mp4') || -2) > -1) {
const {
id: videoId,
permalink_url,
@ -190,7 +190,7 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
'Content-Type': 'application/json',
},
body: JSON.stringify({
file_url: firstPost?.media?.[0]?.url!,
file_url: firstPost?.media?.[0]?.path!,
description: firstPost.message,
published: true,
}),
@ -215,7 +215,7 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
'Content-Type': 'application/json',
},
body: JSON.stringify({
url: media.url,
url: media.path,
published: false,
}),
},
@ -266,7 +266,7 @@ export class FacebookProvider extends SocialAbstract implements SocialProvider {
},
body: JSON.stringify({
...(comment.media?.length
? { attachment_url: comment.media[0].url }
? { attachment_url: comment.media[0].path }
: {}),
message: comment.message,
}),

View File

@ -82,7 +82,7 @@ export class FarcasterProvider
const data = await client.publishCast({
embeds:
post?.media?.map((media) => ({
url: media.url,
url: media.path,
})) || [],
signerUuid: accessToken,
text: post.message,

View File

@ -222,17 +222,17 @@ export class InstagramProvider
const isCarousel =
(firstPost?.media?.length || 0) > 1 ? `&is_carousel_item=true` : ``;
const mediaType =
m.url.indexOf('.mp4') > -1
m.path.indexOf('.mp4') > -1
? firstPost?.media?.length === 1
? isStory
? `video_url=${m.url}&media_type=STORIES`
: `video_url=${m.url}&media_type=REELS`
? `video_url=${m.path}&media_type=STORIES`
: `video_url=${m.path}&media_type=REELS`
: isStory
? `video_url=${m.url}&media_type=STORIES`
: `video_url=${m.url}&media_type=VIDEO`
? `video_url=${m.path}&media_type=STORIES`
: `video_url=${m.path}&media_type=VIDEO`
: isStory
? `image_url=${m.url}&media_type=STORIES`
: `image_url=${m.url}`;
? `image_url=${m.path}&media_type=STORIES`
: `image_url=${m.path}`;
console.log('in progress1');
const collaborators =

View File

@ -16,7 +16,7 @@ export class LemmyProvider extends SocialAbstract implements SocialProvider {
identifier = 'lemmy';
name = 'Lemmy';
isBetweenSteps = false;
scopes = [];
scopes = [] as string[];
async customFields() {
return [
@ -150,7 +150,7 @@ export class LemmyProvider extends SocialAbstract implements SocialProvider {
body: firstPost.message,
...(lemmy.value.url ? { url: lemmy.value.url } : {}),
...(firstPost.media?.length
? { custom_thumbnail: firstPost.media[0].url }
? { custom_thumbnail: firstPost.media[0].path }
: {}),
nsfw: false,
}),

View File

@ -339,9 +339,9 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
(post) =>
post.media?.filter(
(media) =>
media.url.toLowerCase().includes('.jpg') ||
media.url.toLowerCase().includes('.jpeg') ||
media.url.toLowerCase().includes('.png')
media.path.toLowerCase().includes('.jpg') ||
media.path.toLowerCase().includes('.jpeg') ||
media.path.toLowerCase().includes('.png')
) || []
);
@ -352,9 +352,9 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
// Convert images to buffers and get dimensions
const imageData = await Promise.all(
allImages.map(async (media) => {
const buffer = await readOrFetch(media.url);
const buffer = await readOrFetch(media.path);
const image = sharp(buffer, {
animated: lookup(media.url) === 'image/gif',
animated: lookup(media.path) === 'image/gif',
});
const metadata = await image.metadata();
@ -431,11 +431,11 @@ export class LinkedinProvider extends SocialAbstract implements SocialProvider {
) {
mediaBuffer = (media as any).buffer;
} else {
mediaBuffer = await this.prepareMediaBuffer(media.url);
mediaBuffer = await this.prepareMediaBuffer(media.path);
}
const uploadedMediaId = await this.uploadPicture(
media.url,
media.path,
accessToken,
personId,
mediaBuffer,

View File

@ -133,7 +133,7 @@ export class MastodonProvider extends SocialAbstract implements SocialProvider {
for (const getPost of postDetails) {
const uploadFiles = await Promise.all(
getPost?.media?.map((media) =>
this.uploadFile(url, media.url, accessToken)
this.uploadFile(url, media.path, accessToken)
) || []
);

View File

@ -168,7 +168,7 @@ export class NostrProvider extends SocialAbstract implements SocialProvider {
{
kind: 1, // Text note
content:
post.message + '\n\n' + post.media?.map((m) => m.url).join('\n\n'),
post.message + '\n\n' + post.media?.map((m) => m.path).join('\n\n'),
tags: [
...(lastId
? [

View File

@ -151,10 +151,10 @@ export class PinterestProvider
): Promise<PostResponse[]> {
let mediaId = '';
const findMp4 = postDetails?.[0]?.media?.find(
(p) => (p.url?.indexOf('mp4') || -1) > -1
(p) => (p.path?.indexOf('mp4') || -1) > -1
);
const picture = postDetails?.[0]?.media?.find(
(p) => (p.url?.indexOf('mp4') || -1) === -1
(p) => (p.path?.indexOf('mp4') || -1) === -1
);
if (findMp4) {
@ -172,7 +172,7 @@ export class PinterestProvider
).json();
const { data, status } = await axios.get(
postDetails?.[0]?.media?.[0]?.url!,
postDetails?.[0]?.media?.[0]?.path!,
{
responseType: 'stream',
}
@ -207,7 +207,7 @@ export class PinterestProvider
}
const mapImages = postDetails?.[0]?.media?.map((m) => ({
url: m.url,
path: m.path,
}));
try {
@ -234,12 +234,12 @@ export class PinterestProvider
? {
source_type: 'video_id',
media_id: mediaId,
cover_image_url: picture?.url,
cover_image_url: picture?.path,
}
: mapImages?.length === 1
? {
source_type: 'image_url',
url: mapImages?.[0]?.url,
url: mapImages?.[0]?.path,
}
: {
source_type: 'multiple_image_urls',

View File

@ -159,7 +159,7 @@ export class SlackProvider extends SocialAbstract implements SocialProvider {
...(post.media?.length
? post.media.map((m) => ({
type: 'image',
image_url: m.url,
image_url: m.path,
alt_text: '',
}))
: []),

View File

@ -101,7 +101,6 @@ export type PollDetails = {
export type MediaContent = {
type: 'image' | 'video'; // Type of the media content
url: string; // URL of the media file, if it's already hosted somewhere
path: string;
};

View File

@ -22,7 +22,7 @@ export class TelegramProvider extends SocialAbstract implements SocialProvider {
name = 'Telegram';
isBetweenSteps = false;
isWeb3 = true;
scopes = [];
scopes = [] as string[];
async refreshToken(refresh_token: string): Promise<AuthTokenDetails> {
return {
@ -147,7 +147,7 @@ export class TelegramProvider extends SocialAbstract implements SocialProvider {
const text = message.message || '';
// check if media is local to modify url
const processedMedia = mediaFiles.map((media) => {
let mediaUrl = media.url;
let mediaUrl = media.path;
if (mediaStorage === 'local' && mediaUrl.startsWith(frontendURL)) {
mediaUrl = mediaUrl.replace(frontendURL, '');
}
@ -168,7 +168,7 @@ export class TelegramProvider extends SocialAbstract implements SocialProvider {
type: mediaType,
media: mediaUrl,
fileOptions: {
filename: media.url.split('/').pop(),
filename: media.path.split('/').pop(),
contentType: mimeType || 'application/octet-stream',
},
};
@ -216,7 +216,7 @@ export class TelegramProvider extends SocialAbstract implements SocialProvider {
const response = await telegramBot.sendMediaGroup(
accessToken,
mediaGroup
mediaGroup as any[]
);
if (i === 0) {
messageId = response[0].message_id;

View File

@ -164,16 +164,16 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
private async createSingleMediaContent(
userId: string,
accessToken: string,
media: { url: string },
media: { path: string },
message: string,
isCarouselItem = false,
replyToId?: string
): Promise<string> {
const mediaType =
media.url.indexOf('.mp4') > -1 ? 'video_url' : 'image_url';
media.path.indexOf('.mp4') > -1 ? 'video_url' : 'image_url';
const mediaParams = new URLSearchParams({
...(mediaType === 'video_url' ? { video_url: media.url } : {}),
...(mediaType === 'image_url' ? { image_url: media.url } : {}),
...(mediaType === 'video_url' ? { video_url: media.path } : {}),
...(mediaType === 'image_url' ? { image_url: media.path } : {}),
...(isCarouselItem ? { is_carousel_item: 'true' } : {}),
...(replyToId ? { reply_to_id: replyToId } : {}),
media_type: mediaType === 'video_url' ? 'VIDEO' : 'IMAGE',
@ -196,7 +196,7 @@ export class ThreadsProvider extends SocialAbstract implements SocialProvider {
private async createCarouselContent(
userId: string,
accessToken: string,
media: { url: string }[],
media: { path: string }[],
message: string,
replyToId?: string
): Promise<string> {

View File

@ -247,7 +247,7 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
await this.fetch(
`https://open.tiktokapis.com/v2/post/publish${this.postingMethod(
firstPost.settings.content_posting_method,
(firstPost?.media?.[0]?.url?.indexOf('mp4') || -1) === -1
(firstPost?.media?.[0]?.path?.indexOf('mp4') || -1) === -1
)}`,
{
method: 'POST',
@ -268,7 +268,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]?.url?.indexOf('mp4') || -1) ===
...((firstPost?.media?.[0]?.path?.indexOf('mp4') || -1) ===
-1
? {
auto_add_music:
@ -278,18 +278,18 @@ export class TiktokProvider extends SocialAbstract implements SocialProvider {
},
}
: {}),
...((firstPost?.media?.[0]?.url?.indexOf('mp4') || -1) > -1
...((firstPost?.media?.[0]?.path?.indexOf('mp4') || -1) > -1
? {
source_info: {
source: 'PULL_FROM_URL',
video_url: firstPost?.media?.[0]?.url!,
video_url: firstPost?.media?.[0]?.path!,
},
}
: {
source_info: {
source: 'PULL_FROM_URL',
photo_cover_index: 0,
photo_images: firstPost.media?.map((p) => p.url),
photo_images: firstPost.media?.map((p) => p.path),
},
post_mode: 'DIRECT_POST',
media_type: 'PHOTO',

View File

@ -166,17 +166,17 @@ export class VkProvider extends SocialAbstract implements SocialProvider {
(post?.media || []).map(async (media) => {
const all = await (
await this.fetch(
media.url.indexOf('mp4') > -1
media.path.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`
)
).json();
const { data } = await axios.get(media.url!, {
const { data } = await axios.get(media.path!, {
responseType: 'stream',
});
const slash = media.url.split('/').at(-1);
const slash = media.path.split('/').at(-1);
const formData = new FormDataNew();
formData.append('photo', data, {
@ -191,7 +191,7 @@ export class VkProvider extends SocialAbstract implements SocialProvider {
})
).data;
if (media.url.indexOf('mp4') > -1) {
if (media.path.indexOf('mp4') > -1) {
return {
id: all.response.video_id,
type: 'video',

View File

@ -270,10 +270,10 @@ export class XProvider extends SocialAbstract implements SocialProvider {
p?.media?.flatMap(async (m) => {
return {
id: await client.v1.uploadMedia(
m.url.indexOf('mp4') > -1
? Buffer.from(await readOrFetch(m.url))
: await sharp(await readOrFetch(m.url), {
animated: lookup(m.url) === 'image/gif',
m.path.indexOf('mp4') > -1
? Buffer.from(await readOrFetch(m.path))
: await sharp(await readOrFetch(m.path), {
animated: lookup(m.path) === 'image/gif',
})
.resize({
width: 1000,
@ -281,7 +281,7 @@ export class XProvider extends SocialAbstract implements SocialProvider {
.gif()
.toBuffer(),
{
mimeType: lookup(m.url) || '',
mimeType: lookup(m.path) || '',
}
),
postId: p.id,

View File

@ -142,7 +142,7 @@ export class YoutubeProvider extends SocialAbstract implements SocialProvider {
const { settings }: { settings: YoutubeSettingsDto } = firstPost;
const response = await axios({
url: firstPost?.media?.[0]?.url,
url: firstPost?.media?.[0]?.path,
method: 'GET',
responseType: 'stream',
});