Support uploaded cover images for media posts
فشلت بعض الفحوصات
Deploy To Ghaymah / deploy (push) Has been cancelled
فشلت بعض الفحوصات
Deploy To Ghaymah / deploy (push) Has been cancelled
هذا الالتزام موجود في:
@@ -1898,9 +1898,9 @@
|
|||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "thumbnailUrl",
|
"key": "coverImageFile",
|
||||||
"value": "https://cdn.example.com/video-cover.jpg",
|
"type": "file",
|
||||||
"type": "text"
|
"src": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "style",
|
"key": "style",
|
||||||
@@ -1964,7 +1964,7 @@
|
|||||||
"const json = pm.response.json();",
|
"const json = pm.response.json();",
|
||||||
"pm.expect(json.postType).to.eql('video');",
|
"pm.expect(json.postType).to.eql('video');",
|
||||||
"pm.expect(json.durationSeconds).to.eql(42);",
|
"pm.expect(json.durationSeconds).to.eql(42);",
|
||||||
"pm.expect(json.thumbnailUrl).to.eql('https://cdn.example.com/video-cover.jpg');",
|
"if (json.thumbnailUrl) { pm.expect(json.thumbnailUrl).to.be.a('string'); }",
|
||||||
"pm.expect(json.style).to.eql('Sharqi');",
|
"pm.expect(json.style).to.eql('Sharqi');",
|
||||||
"pm.expect(json.maqam).to.eql('Hijaz');",
|
"pm.expect(json.maqam).to.eql('Hijaz');",
|
||||||
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
||||||
@@ -2005,9 +2005,9 @@
|
|||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "thumbnailUrl",
|
"key": "coverImageFile",
|
||||||
"value": "https://cdn.example.com/reel-cover.jpg",
|
"type": "file",
|
||||||
"type": "text"
|
"src": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "style",
|
"key": "style",
|
||||||
@@ -2051,7 +2051,7 @@
|
|||||||
"const json = pm.response.json();",
|
"const json = pm.response.json();",
|
||||||
"pm.expect(json.postType).to.eql('video');",
|
"pm.expect(json.postType).to.eql('video');",
|
||||||
"pm.expect(json.durationSeconds).to.eql(30);",
|
"pm.expect(json.durationSeconds).to.eql(30);",
|
||||||
"pm.expect(json.thumbnailUrl).to.eql('https://cdn.example.com/reel-cover.jpg');",
|
"if (json.thumbnailUrl) { pm.expect(json.thumbnailUrl).to.be.a('string'); }",
|
||||||
"pm.expect(json.style).to.eql('Sharqi');",
|
"pm.expect(json.style).to.eql('Sharqi');",
|
||||||
"pm.expect(json.maqam).to.eql('Hijaz');",
|
"pm.expect(json.maqam).to.eql('Hijaz');",
|
||||||
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
||||||
@@ -2146,9 +2146,9 @@
|
|||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "thumbnailUrl",
|
"key": "coverImageFile",
|
||||||
"value": "https://cdn.example.com/audio-cover.jpg",
|
"type": "file",
|
||||||
"type": "text"
|
"src": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "style",
|
"key": "style",
|
||||||
@@ -2192,7 +2192,7 @@
|
|||||||
"const json = pm.response.json();",
|
"const json = pm.response.json();",
|
||||||
"pm.expect(json.postType).to.eql('audio');",
|
"pm.expect(json.postType).to.eql('audio');",
|
||||||
"pm.expect(json.durationSeconds).to.eql(54);",
|
"pm.expect(json.durationSeconds).to.eql(54);",
|
||||||
"pm.expect(json.thumbnailUrl).to.eql('https://cdn.example.com/audio-cover.jpg');",
|
"if (json.thumbnailUrl) { pm.expect(json.thumbnailUrl).to.be.a('string'); }",
|
||||||
"pm.expect(json.style).to.eql('Sharqi');",
|
"pm.expect(json.style).to.eql('Sharqi');",
|
||||||
"pm.expect(json.maqam).to.eql('Hijaz');",
|
"pm.expect(json.maqam).to.eql('Hijaz');",
|
||||||
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
||||||
@@ -2404,9 +2404,9 @@
|
|||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "thumbnailUrl",
|
"key": "coverImageFile",
|
||||||
"value": "https://cdn.example.com/video-cover-updated.jpg",
|
"type": "file",
|
||||||
"type": "text"
|
"src": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "style",
|
"key": "style",
|
||||||
@@ -2453,7 +2453,7 @@
|
|||||||
"const json = pm.response.json();",
|
"const json = pm.response.json();",
|
||||||
"pm.expect(json.postType).to.eql('video');",
|
"pm.expect(json.postType).to.eql('video');",
|
||||||
"pm.expect(json.durationSeconds).to.eql(58);",
|
"pm.expect(json.durationSeconds).to.eql(58);",
|
||||||
"pm.expect(json.thumbnailUrl).to.eql('https://cdn.example.com/video-cover-updated.jpg');",
|
"if (json.thumbnailUrl) { pm.expect(json.thumbnailUrl).to.be.a('string'); }",
|
||||||
"pm.expect(json.style).to.eql('Contemporary');",
|
"pm.expect(json.style).to.eql('Contemporary');",
|
||||||
"pm.expect(json.maqam).to.eql('Bayati');",
|
"pm.expect(json.maqam).to.eql('Bayati');",
|
||||||
"pm.expect(json.rhythmSignature).to.eql('4/4');"
|
"pm.expect(json.rhythmSignature).to.eql('4/4');"
|
||||||
@@ -2487,9 +2487,9 @@
|
|||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "thumbnailUrl",
|
"key": "coverImageFile",
|
||||||
"value": "https://cdn.example.com/audio-cover-updated.jpg",
|
"type": "file",
|
||||||
"type": "text"
|
"src": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "style",
|
"key": "style",
|
||||||
@@ -2536,7 +2536,7 @@
|
|||||||
"const json = pm.response.json();",
|
"const json = pm.response.json();",
|
||||||
"pm.expect(json.postType).to.eql('audio');",
|
"pm.expect(json.postType).to.eql('audio');",
|
||||||
"pm.expect(json.durationSeconds).to.eql(61);",
|
"pm.expect(json.durationSeconds).to.eql(61);",
|
||||||
"pm.expect(json.thumbnailUrl).to.eql('https://cdn.example.com/audio-cover-updated.jpg');",
|
"if (json.thumbnailUrl) { pm.expect(json.thumbnailUrl).to.be.a('string'); }",
|
||||||
"pm.expect(json.style).to.eql('Tarab');",
|
"pm.expect(json.style).to.eql('Tarab');",
|
||||||
"pm.expect(json.maqam).to.eql('Nahawand');",
|
"pm.expect(json.maqam).to.eql('Nahawand');",
|
||||||
"pm.expect(json.rhythmSignature).to.eql('6/8');"
|
"pm.expect(json.rhythmSignature).to.eql('6/8');"
|
||||||
|
|||||||
@@ -1359,9 +1359,9 @@
|
|||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "thumbnailUrl",
|
"key": "coverImageFile",
|
||||||
"value": "https://cdn.example.com/video-cover.jpg",
|
"type": "file",
|
||||||
"type": "text"
|
"src": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "style",
|
"key": "style",
|
||||||
@@ -1425,7 +1425,7 @@
|
|||||||
"const json = pm.response.json();",
|
"const json = pm.response.json();",
|
||||||
"pm.expect(json.postType).to.eql('video');",
|
"pm.expect(json.postType).to.eql('video');",
|
||||||
"pm.expect(json.durationSeconds).to.eql(42);",
|
"pm.expect(json.durationSeconds).to.eql(42);",
|
||||||
"pm.expect(json.thumbnailUrl).to.eql('https://cdn.example.com/video-cover.jpg');",
|
"if (json.thumbnailUrl) { pm.expect(json.thumbnailUrl).to.be.a('string'); }",
|
||||||
"pm.expect(json.style).to.eql('Sharqi');",
|
"pm.expect(json.style).to.eql('Sharqi');",
|
||||||
"pm.expect(json.maqam).to.eql('Hijaz');",
|
"pm.expect(json.maqam).to.eql('Hijaz');",
|
||||||
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
||||||
@@ -1466,9 +1466,9 @@
|
|||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "thumbnailUrl",
|
"key": "coverImageFile",
|
||||||
"value": "https://cdn.example.com/reel-cover.jpg",
|
"type": "file",
|
||||||
"type": "text"
|
"src": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "style",
|
"key": "style",
|
||||||
@@ -1512,7 +1512,7 @@
|
|||||||
"const json = pm.response.json();",
|
"const json = pm.response.json();",
|
||||||
"pm.expect(json.postType).to.eql('video');",
|
"pm.expect(json.postType).to.eql('video');",
|
||||||
"pm.expect(json.durationSeconds).to.eql(30);",
|
"pm.expect(json.durationSeconds).to.eql(30);",
|
||||||
"pm.expect(json.thumbnailUrl).to.eql('https://cdn.example.com/reel-cover.jpg');",
|
"if (json.thumbnailUrl) { pm.expect(json.thumbnailUrl).to.be.a('string'); }",
|
||||||
"pm.expect(json.style).to.eql('Sharqi');",
|
"pm.expect(json.style).to.eql('Sharqi');",
|
||||||
"pm.expect(json.maqam).to.eql('Hijaz');",
|
"pm.expect(json.maqam).to.eql('Hijaz');",
|
||||||
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
||||||
@@ -1607,9 +1607,9 @@
|
|||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "thumbnailUrl",
|
"key": "coverImageFile",
|
||||||
"value": "https://cdn.example.com/audio-cover.jpg",
|
"type": "file",
|
||||||
"type": "text"
|
"src": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "style",
|
"key": "style",
|
||||||
@@ -1653,7 +1653,7 @@
|
|||||||
"const json = pm.response.json();",
|
"const json = pm.response.json();",
|
||||||
"pm.expect(json.postType).to.eql('audio');",
|
"pm.expect(json.postType).to.eql('audio');",
|
||||||
"pm.expect(json.durationSeconds).to.eql(54);",
|
"pm.expect(json.durationSeconds).to.eql(54);",
|
||||||
"pm.expect(json.thumbnailUrl).to.eql('https://cdn.example.com/audio-cover.jpg');",
|
"if (json.thumbnailUrl) { pm.expect(json.thumbnailUrl).to.be.a('string'); }",
|
||||||
"pm.expect(json.style).to.eql('Sharqi');",
|
"pm.expect(json.style).to.eql('Sharqi');",
|
||||||
"pm.expect(json.maqam).to.eql('Hijaz');",
|
"pm.expect(json.maqam).to.eql('Hijaz');",
|
||||||
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
"pm.expect(json.rhythmSignature).to.eql('6/8');",
|
||||||
@@ -1865,9 +1865,9 @@
|
|||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "thumbnailUrl",
|
"key": "coverImageFile",
|
||||||
"value": "https://cdn.example.com/video-cover-updated.jpg",
|
"type": "file",
|
||||||
"type": "text"
|
"src": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "style",
|
"key": "style",
|
||||||
@@ -1914,7 +1914,7 @@
|
|||||||
"const json = pm.response.json();",
|
"const json = pm.response.json();",
|
||||||
"pm.expect(json.postType).to.eql('video');",
|
"pm.expect(json.postType).to.eql('video');",
|
||||||
"pm.expect(json.durationSeconds).to.eql(58);",
|
"pm.expect(json.durationSeconds).to.eql(58);",
|
||||||
"pm.expect(json.thumbnailUrl).to.eql('https://cdn.example.com/video-cover-updated.jpg');",
|
"if (json.thumbnailUrl) { pm.expect(json.thumbnailUrl).to.be.a('string'); }",
|
||||||
"pm.expect(json.style).to.eql('Contemporary');",
|
"pm.expect(json.style).to.eql('Contemporary');",
|
||||||
"pm.expect(json.maqam).to.eql('Bayati');",
|
"pm.expect(json.maqam).to.eql('Bayati');",
|
||||||
"pm.expect(json.rhythmSignature).to.eql('4/4');"
|
"pm.expect(json.rhythmSignature).to.eql('4/4');"
|
||||||
@@ -1948,9 +1948,9 @@
|
|||||||
"type": "text"
|
"type": "text"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "thumbnailUrl",
|
"key": "coverImageFile",
|
||||||
"value": "https://cdn.example.com/audio-cover-updated.jpg",
|
"type": "file",
|
||||||
"type": "text"
|
"src": []
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"key": "style",
|
"key": "style",
|
||||||
@@ -1997,7 +1997,7 @@
|
|||||||
"const json = pm.response.json();",
|
"const json = pm.response.json();",
|
||||||
"pm.expect(json.postType).to.eql('audio');",
|
"pm.expect(json.postType).to.eql('audio');",
|
||||||
"pm.expect(json.durationSeconds).to.eql(61);",
|
"pm.expect(json.durationSeconds).to.eql(61);",
|
||||||
"pm.expect(json.thumbnailUrl).to.eql('https://cdn.example.com/audio-cover-updated.jpg');",
|
"if (json.thumbnailUrl) { pm.expect(json.thumbnailUrl).to.be.a('string'); }",
|
||||||
"pm.expect(json.style).to.eql('Tarab');",
|
"pm.expect(json.style).to.eql('Tarab');",
|
||||||
"pm.expect(json.maqam).to.eql('Nahawand');",
|
"pm.expect(json.maqam).to.eql('Nahawand');",
|
||||||
"pm.expect(json.rhythmSignature).to.eql('6/8');"
|
"pm.expect(json.rhythmSignature).to.eql('6/8');"
|
||||||
|
|||||||
@@ -45,6 +45,7 @@ export class PostsController {
|
|||||||
{ name: 'imageFiles', maxCount: 10 },
|
{ name: 'imageFiles', maxCount: 10 },
|
||||||
{ name: 'videoFile', maxCount: 1 },
|
{ name: 'videoFile', maxCount: 1 },
|
||||||
{ name: 'audioFile', maxCount: 1 },
|
{ name: 'audioFile', maxCount: 1 },
|
||||||
|
{ name: 'coverImageFile', maxCount: 1 },
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
@ApiConsumes('multipart/form-data')
|
@ApiConsumes('multipart/form-data')
|
||||||
@@ -76,6 +77,7 @@ export class PostsController {
|
|||||||
imageFiles: { type: 'array', items: { type: 'string', format: 'binary' } },
|
imageFiles: { type: 'array', items: { type: 'string', format: 'binary' } },
|
||||||
videoFile: { type: 'string', format: 'binary' },
|
videoFile: { type: 'string', format: 'binary' },
|
||||||
audioFile: { type: 'string', format: 'binary' },
|
audioFile: { type: 'string', format: 'binary' },
|
||||||
|
coverImageFile: { type: 'string', format: 'binary' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -88,6 +90,7 @@ export class PostsController {
|
|||||||
imageFiles?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
imageFiles?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
||||||
videoFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
videoFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
||||||
audioFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
audioFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
||||||
|
coverImageFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
return this.postsService.create(
|
return this.postsService.create(
|
||||||
@@ -96,6 +99,7 @@ export class PostsController {
|
|||||||
files?.imageFiles ?? [],
|
files?.imageFiles ?? [],
|
||||||
files?.videoFile?.[0],
|
files?.videoFile?.[0],
|
||||||
files?.audioFile?.[0],
|
files?.audioFile?.[0],
|
||||||
|
files?.coverImageFile?.[0],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -119,6 +123,7 @@ export class PostsController {
|
|||||||
@UseInterceptors(
|
@UseInterceptors(
|
||||||
FileFieldsInterceptor([
|
FileFieldsInterceptor([
|
||||||
{ name: 'videoFile', maxCount: 1 },
|
{ name: 'videoFile', maxCount: 1 },
|
||||||
|
{ name: 'coverImageFile', maxCount: 1 },
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
@ApiConsumes('multipart/form-data')
|
@ApiConsumes('multipart/form-data')
|
||||||
@@ -136,6 +141,7 @@ export class PostsController {
|
|||||||
rhythmSignature: { type: 'string', example: '6/8' },
|
rhythmSignature: { type: 'string', example: '6/8' },
|
||||||
mentionUsernames: { type: 'array', items: { type: 'string' } },
|
mentionUsernames: { type: 'array', items: { type: 'string' } },
|
||||||
videoFile: { type: 'string', format: 'binary' },
|
videoFile: { type: 'string', format: 'binary' },
|
||||||
|
coverImageFile: { type: 'string', format: 'binary' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -146,9 +152,10 @@ export class PostsController {
|
|||||||
@UploadedFiles()
|
@UploadedFiles()
|
||||||
files?: {
|
files?: {
|
||||||
videoFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
videoFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
||||||
|
coverImageFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
return this.postsService.createReel(user.sub, dto, files?.videoFile?.[0]);
|
return this.postsService.createReel(user.sub, dto, files?.videoFile?.[0], files?.coverImageFile?.[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ApiBearerAuth()
|
@ApiBearerAuth()
|
||||||
@@ -172,6 +179,7 @@ export class PostsController {
|
|||||||
{ name: 'imageFiles', maxCount: 10 },
|
{ name: 'imageFiles', maxCount: 10 },
|
||||||
{ name: 'videoFile', maxCount: 1 },
|
{ name: 'videoFile', maxCount: 1 },
|
||||||
{ name: 'audioFile', maxCount: 1 },
|
{ name: 'audioFile', maxCount: 1 },
|
||||||
|
{ name: 'coverImageFile', maxCount: 1 },
|
||||||
]),
|
]),
|
||||||
)
|
)
|
||||||
@ApiConsumes('multipart/form-data')
|
@ApiConsumes('multipart/form-data')
|
||||||
@@ -203,6 +211,7 @@ export class PostsController {
|
|||||||
imageFiles: { type: 'array', items: { type: 'string', format: 'binary' } },
|
imageFiles: { type: 'array', items: { type: 'string', format: 'binary' } },
|
||||||
videoFile: { type: 'string', format: 'binary' },
|
videoFile: { type: 'string', format: 'binary' },
|
||||||
audioFile: { type: 'string', format: 'binary' },
|
audioFile: { type: 'string', format: 'binary' },
|
||||||
|
coverImageFile: { type: 'string', format: 'binary' },
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
@@ -216,6 +225,7 @@ export class PostsController {
|
|||||||
imageFiles?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
imageFiles?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
||||||
videoFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
videoFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
||||||
audioFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
audioFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
||||||
|
coverImageFile?: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }>;
|
||||||
},
|
},
|
||||||
) {
|
) {
|
||||||
return this.postsService.update(
|
return this.postsService.update(
|
||||||
@@ -225,6 +235,7 @@ export class PostsController {
|
|||||||
files?.imageFiles ?? [],
|
files?.imageFiles ?? [],
|
||||||
files?.videoFile?.[0],
|
files?.videoFile?.[0],
|
||||||
files?.audioFile?.[0],
|
files?.audioFile?.[0],
|
||||||
|
files?.coverImageFile?.[0],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -87,6 +87,7 @@ export class PostsService {
|
|||||||
imageFiles: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }> = [],
|
imageFiles: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }> = [],
|
||||||
videoFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
videoFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
||||||
audioFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
audioFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
||||||
|
coverImageFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
||||||
): Promise<PostDocument> {
|
): Promise<PostDocument> {
|
||||||
const inputImageUrls = dto.imageUrls ?? [];
|
const inputImageUrls = dto.imageUrls ?? [];
|
||||||
if (inputImageUrls.length > 10 || imageFiles.length > 10) {
|
if (inputImageUrls.length > 10 || imageFiles.length > 10) {
|
||||||
@@ -104,6 +105,12 @@ export class PostsService {
|
|||||||
if (audioFile && dto.audioUrl) {
|
if (audioFile && dto.audioUrl) {
|
||||||
throw new BadRequestException('Provide either audioFile or audioUrl, not both');
|
throw new BadRequestException('Provide either audioFile or audioUrl, not both');
|
||||||
}
|
}
|
||||||
|
if (coverImageFile && dto.thumbnailUrl) {
|
||||||
|
throw new BadRequestException('Provide either coverImageFile or thumbnailUrl, not both');
|
||||||
|
}
|
||||||
|
if (coverImageFile && !(videoFile || audioFile || dto.videoUrl || dto.audioUrl)) {
|
||||||
|
throw new BadRequestException('coverImageFile is allowed only with video or audio posts');
|
||||||
|
}
|
||||||
if ((videoFile || dto.videoUrl) && (imageFiles.length || inputImageUrls.length)) {
|
if ((videoFile || dto.videoUrl) && (imageFiles.length || inputImageUrls.length)) {
|
||||||
throw new BadRequestException('Post can contain either images or video, not both');
|
throw new BadRequestException('Post can contain either images or video, not both');
|
||||||
}
|
}
|
||||||
@@ -115,10 +122,15 @@ export class PostsService {
|
|||||||
const uploadedImageUrls = savedImageUploads.map((item) => item.primaryUrl);
|
const uploadedImageUrls = savedImageUploads.map((item) => item.primaryUrl);
|
||||||
const uploadedImageVariants = savedImageUploads.map((item) => item.variants);
|
const uploadedImageVariants = savedImageUploads.map((item) => item.variants);
|
||||||
const savedVideoUpload = videoFile ? await this.saveVideoUpload(videoFile) : null;
|
const savedVideoUpload = videoFile ? await this.saveVideoUpload(videoFile) : null;
|
||||||
|
const savedCoverImageUpload = coverImageFile
|
||||||
|
? await this.saveResponsiveImageAsset('thumbnails', coverImageFile)
|
||||||
|
: null;
|
||||||
const uploadedVideoUrl = savedVideoUpload?.videoUrl ?? '';
|
const uploadedVideoUrl = savedVideoUpload?.videoUrl ?? '';
|
||||||
const uploadedHlsUrl = savedVideoUpload?.hlsUrl ?? '';
|
const uploadedHlsUrl = savedVideoUpload?.hlsUrl ?? '';
|
||||||
const uploadedThumbnailUrl = savedVideoUpload?.thumbnailUrl ?? '';
|
const generatedThumbnailUrl = savedVideoUpload?.thumbnailUrl ?? '';
|
||||||
const uploadedThumbnailVariants = savedVideoUpload?.thumbnailVariants ?? null;
|
const generatedThumbnailVariants = savedVideoUpload?.thumbnailVariants ?? null;
|
||||||
|
const uploadedThumbnailUrl = savedCoverImageUpload?.primaryUrl ?? generatedThumbnailUrl;
|
||||||
|
const uploadedThumbnailVariants = savedCoverImageUpload?.variants ?? generatedThumbnailVariants;
|
||||||
const uploadedAudioUrl = audioFile ? await this.saveMediaFile('audio', audioFile) : '';
|
const uploadedAudioUrl = audioFile ? await this.saveMediaFile('audio', audioFile) : '';
|
||||||
const finalImageUrls = uploadedImageUrls.length ? uploadedImageUrls : inputImageUrls;
|
const finalImageUrls = uploadedImageUrls.length ? uploadedImageUrls : inputImageUrls;
|
||||||
const finalImageVariants = uploadedImageVariants.length ? uploadedImageVariants : [];
|
const finalImageVariants = uploadedImageVariants.length ? uploadedImageVariants : [];
|
||||||
@@ -174,11 +186,18 @@ export class PostsService {
|
|||||||
uploadedThumbnailUrl
|
uploadedThumbnailUrl
|
||||||
? this.deleteThumbnailAsset(uploadedThumbnailUrl, uploadedThumbnailVariants)
|
? this.deleteThumbnailAsset(uploadedThumbnailUrl, uploadedThumbnailVariants)
|
||||||
: Promise.resolve(),
|
: Promise.resolve(),
|
||||||
|
generatedThumbnailUrl && generatedThumbnailUrl !== uploadedThumbnailUrl
|
||||||
|
? this.deleteThumbnailAsset(generatedThumbnailUrl, generatedThumbnailVariants)
|
||||||
|
: Promise.resolve(),
|
||||||
uploadedAudioUrl ? this.deleteManagedPostMedia(uploadedAudioUrl) : Promise.resolve(),
|
uploadedAudioUrl ? this.deleteManagedPostMedia(uploadedAudioUrl) : Promise.resolve(),
|
||||||
]);
|
]);
|
||||||
throw error;
|
throw error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (generatedThumbnailUrl && generatedThumbnailUrl !== uploadedThumbnailUrl) {
|
||||||
|
await this.deleteThumbnailAsset(generatedThumbnailUrl, generatedThumbnailVariants);
|
||||||
|
}
|
||||||
|
|
||||||
await this.usersRepository.incrementPostsCount(userId, 1);
|
await this.usersRepository.incrementPostsCount(userId, 1);
|
||||||
await this.feedVersionService.bumpGlobalVersion();
|
await this.feedVersionService.bumpGlobalVersion();
|
||||||
await this.notifyMentionedUsers(userId, post.id, mentionResolution.mentionedUsers, finalContent);
|
await this.notifyMentionedUsers(userId, post.id, mentionResolution.mentionedUsers, finalContent);
|
||||||
@@ -192,6 +211,7 @@ export class PostsService {
|
|||||||
imageFiles: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }> = [],
|
imageFiles: Array<{ mimetype?: string; size: number; buffer: Buffer; originalname?: string }> = [],
|
||||||
videoFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
videoFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
||||||
audioFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
audioFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
||||||
|
coverImageFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
||||||
): Promise<PostDocument> {
|
): Promise<PostDocument> {
|
||||||
const post = await this.postsRepository.findById(postId);
|
const post = await this.postsRepository.findById(postId);
|
||||||
if (!post) {
|
if (!post) {
|
||||||
@@ -219,6 +239,15 @@ export class PostsService {
|
|||||||
if (audioFile && dto.audioUrl) {
|
if (audioFile && dto.audioUrl) {
|
||||||
throw new BadRequestException('Provide either audioFile or audioUrl, not both');
|
throw new BadRequestException('Provide either audioFile or audioUrl, not both');
|
||||||
}
|
}
|
||||||
|
if (coverImageFile && dto.thumbnailUrl) {
|
||||||
|
throw new BadRequestException('Provide either coverImageFile or thumbnailUrl, not both');
|
||||||
|
}
|
||||||
|
if (coverImageFile && (imageFiles.length || inputImageUrls.length)) {
|
||||||
|
throw new BadRequestException('coverImageFile is allowed only with video or audio posts');
|
||||||
|
}
|
||||||
|
if (coverImageFile && !(videoFile || audioFile || dto.videoUrl || dto.audioUrl || post.videoUrl || post.audioUrl)) {
|
||||||
|
throw new BadRequestException('coverImageFile is allowed only with video or audio posts');
|
||||||
|
}
|
||||||
if ((videoFile || dto.videoUrl) && (imageFiles.length || inputImageUrls.length)) {
|
if ((videoFile || dto.videoUrl) && (imageFiles.length || inputImageUrls.length)) {
|
||||||
throw new BadRequestException('Post can contain either images or video, not both');
|
throw new BadRequestException('Post can contain either images or video, not both');
|
||||||
}
|
}
|
||||||
@@ -230,10 +259,15 @@ export class PostsService {
|
|||||||
const uploadedImageUrls = savedImageUploads.map((item) => item.primaryUrl);
|
const uploadedImageUrls = savedImageUploads.map((item) => item.primaryUrl);
|
||||||
const uploadedImageVariants = savedImageUploads.map((item) => item.variants);
|
const uploadedImageVariants = savedImageUploads.map((item) => item.variants);
|
||||||
const savedVideoUpload = videoFile ? await this.saveVideoUpload(videoFile) : null;
|
const savedVideoUpload = videoFile ? await this.saveVideoUpload(videoFile) : null;
|
||||||
|
const savedCoverImageUpload = coverImageFile
|
||||||
|
? await this.saveResponsiveImageAsset('thumbnails', coverImageFile)
|
||||||
|
: null;
|
||||||
const uploadedVideoUrl = savedVideoUpload?.videoUrl ?? '';
|
const uploadedVideoUrl = savedVideoUpload?.videoUrl ?? '';
|
||||||
const uploadedHlsUrl = savedVideoUpload?.hlsUrl ?? '';
|
const uploadedHlsUrl = savedVideoUpload?.hlsUrl ?? '';
|
||||||
const uploadedThumbnailUrl = savedVideoUpload?.thumbnailUrl ?? '';
|
const generatedThumbnailUrl = savedVideoUpload?.thumbnailUrl ?? '';
|
||||||
const uploadedThumbnailVariants = savedVideoUpload?.thumbnailVariants ?? null;
|
const generatedThumbnailVariants = savedVideoUpload?.thumbnailVariants ?? null;
|
||||||
|
const uploadedThumbnailUrl = savedCoverImageUpload?.primaryUrl ?? generatedThumbnailUrl;
|
||||||
|
const uploadedThumbnailVariants = savedCoverImageUpload?.variants ?? generatedThumbnailVariants;
|
||||||
const uploadedAudioUrl = audioFile ? await this.saveMediaFile('audio', audioFile) : '';
|
const uploadedAudioUrl = audioFile ? await this.saveMediaFile('audio', audioFile) : '';
|
||||||
const hasImageUpdate = typeof dto.imageUrls !== 'undefined' || imageFiles.length > 0;
|
const hasImageUpdate = typeof dto.imageUrls !== 'undefined' || imageFiles.length > 0;
|
||||||
const existingImageVariants = Array.isArray((post as any).imageVariants)
|
const existingImageVariants = Array.isArray((post as any).imageVariants)
|
||||||
@@ -266,7 +300,7 @@ export class PostsService {
|
|||||||
? uploadedAudioUrl
|
? uploadedAudioUrl
|
||||||
: dto.audioUrl ?? ''
|
: dto.audioUrl ?? ''
|
||||||
: post.audioUrl ?? '';
|
: post.audioUrl ?? '';
|
||||||
const nextThumbnailVariants = videoFile
|
const nextThumbnailVariants = coverImageFile || videoFile
|
||||||
? uploadedThumbnailVariants
|
? uploadedThumbnailVariants
|
||||||
: typeof dto.thumbnailUrl === 'string'
|
: typeof dto.thumbnailUrl === 'string'
|
||||||
? null
|
? null
|
||||||
@@ -392,6 +426,9 @@ export class PostsService {
|
|||||||
uploadedThumbnailUrl
|
uploadedThumbnailUrl
|
||||||
? this.deleteThumbnailAsset(uploadedThumbnailUrl, uploadedThumbnailVariants)
|
? this.deleteThumbnailAsset(uploadedThumbnailUrl, uploadedThumbnailVariants)
|
||||||
: Promise.resolve(),
|
: Promise.resolve(),
|
||||||
|
generatedThumbnailUrl && generatedThumbnailUrl !== uploadedThumbnailUrl
|
||||||
|
? this.deleteThumbnailAsset(generatedThumbnailUrl, generatedThumbnailVariants)
|
||||||
|
: Promise.resolve(),
|
||||||
uploadedAudioUrl ? this.deleteManagedPostMedia(uploadedAudioUrl) : Promise.resolve(),
|
uploadedAudioUrl ? this.deleteManagedPostMedia(uploadedAudioUrl) : Promise.resolve(),
|
||||||
]);
|
]);
|
||||||
throw error;
|
throw error;
|
||||||
@@ -404,6 +441,9 @@ export class PostsService {
|
|||||||
uploadedThumbnailUrl
|
uploadedThumbnailUrl
|
||||||
? this.deleteThumbnailAsset(uploadedThumbnailUrl, uploadedThumbnailVariants)
|
? this.deleteThumbnailAsset(uploadedThumbnailUrl, uploadedThumbnailVariants)
|
||||||
: Promise.resolve(),
|
: Promise.resolve(),
|
||||||
|
generatedThumbnailUrl && generatedThumbnailUrl !== uploadedThumbnailUrl
|
||||||
|
? this.deleteThumbnailAsset(generatedThumbnailUrl, generatedThumbnailVariants)
|
||||||
|
: Promise.resolve(),
|
||||||
uploadedAudioUrl ? this.deleteManagedPostMedia(uploadedAudioUrl) : Promise.resolve(),
|
uploadedAudioUrl ? this.deleteManagedPostMedia(uploadedAudioUrl) : Promise.resolve(),
|
||||||
]);
|
]);
|
||||||
throw new NotFoundException('Post not found');
|
throw new NotFoundException('Post not found');
|
||||||
@@ -418,6 +458,9 @@ export class PostsService {
|
|||||||
if ((post.thumbnailUrl ?? '') !== (updated.thumbnailUrl ?? '')) {
|
if ((post.thumbnailUrl ?? '') !== (updated.thumbnailUrl ?? '')) {
|
||||||
await this.deleteThumbnailAsset(post.thumbnailUrl ?? '', existingThumbnailVariants);
|
await this.deleteThumbnailAsset(post.thumbnailUrl ?? '', existingThumbnailVariants);
|
||||||
}
|
}
|
||||||
|
if (generatedThumbnailUrl && generatedThumbnailUrl !== uploadedThumbnailUrl) {
|
||||||
|
await this.deleteThumbnailAsset(generatedThumbnailUrl, generatedThumbnailVariants);
|
||||||
|
}
|
||||||
if (hasAudioUpdate && (post.audioUrl ?? '') !== (updated.audioUrl ?? '')) {
|
if (hasAudioUpdate && (post.audioUrl ?? '') !== (updated.audioUrl ?? '')) {
|
||||||
await this.deleteManagedPostMedia(post.audioUrl ?? '');
|
await this.deleteManagedPostMedia(post.audioUrl ?? '');
|
||||||
}
|
}
|
||||||
@@ -567,6 +610,7 @@ export class PostsService {
|
|||||||
userId: string,
|
userId: string,
|
||||||
dto: CreateReelDto,
|
dto: CreateReelDto,
|
||||||
videoFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
videoFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
||||||
|
coverImageFile?: { mimetype?: string; size: number; buffer: Buffer; originalname?: string },
|
||||||
): Promise<PostDocument> {
|
): Promise<PostDocument> {
|
||||||
if (!videoFile && !dto.videoUrl) {
|
if (!videoFile && !dto.videoUrl) {
|
||||||
throw new BadRequestException('Reel requires videoFile or videoUrl');
|
throw new BadRequestException('Reel requires videoFile or videoUrl');
|
||||||
@@ -592,6 +636,7 @@ export class PostsService {
|
|||||||
[],
|
[],
|
||||||
videoFile,
|
videoFile,
|
||||||
undefined,
|
undefined,
|
||||||
|
coverImageFile,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
المرجع في مشكلة جديدة
حظر مستخدم