Improve backend media readiness for mobile clients
فشلت بعض الفحوصات
Deploy To Ghaymah / deploy (push) Has been cancelled
فشلت بعض الفحوصات
Deploy To Ghaymah / deploy (push) Has been cancelled
هذا الالتزام موجود في:
@@ -1,4 +1,4 @@
|
||||
import { Body, Controller, Post, UseGuards } from '@nestjs/common';
|
||||
import { Body, Controller, Get, Post, UseGuards } from '@nestjs/common';
|
||||
import { ApiBearerAuth, ApiTags } from '@nestjs/swagger';
|
||||
import { Throttle } from '../../common/decorators/throttle.decorator';
|
||||
import { CurrentUser } from '../../common/decorators/current-user.decorator';
|
||||
@@ -12,6 +12,13 @@ import { MediaService } from './media.service';
|
||||
export class MediaController {
|
||||
constructor(private readonly mediaService: MediaService) {}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Get('health')
|
||||
async mediaHealth() {
|
||||
return this.mediaService.getMediaHealth();
|
||||
}
|
||||
|
||||
@ApiBearerAuth()
|
||||
@UseGuards(JwtAuthGuard)
|
||||
@Post('ai/text-to-music')
|
||||
|
||||
@@ -16,6 +16,30 @@ export class MediaService {
|
||||
private readonly storageService: ManagedStorageService,
|
||||
) {}
|
||||
|
||||
async getMediaHealth() {
|
||||
return {
|
||||
storage: await this.storageService.getHealth(),
|
||||
processing: {
|
||||
imageProcessingEnabled:
|
||||
this.configService.get<boolean>('imageProcessing.enabled', { infer: true }) ?? false,
|
||||
videoProcessingEnabled:
|
||||
this.configService.get<boolean>('videoProcessing.enabled', { infer: true }) ?? false,
|
||||
videoHlsGenerationEnabled:
|
||||
this.configService.get<boolean>('videoProcessing.generateHls', { infer: true }) ?? true,
|
||||
videoThumbnailGenerationEnabled:
|
||||
this.configService.get<boolean>('videoProcessing.generateThumbnails', { infer: true }) ??
|
||||
true,
|
||||
ffmpegPath:
|
||||
this.configService.get<string>('videoProcessing.ffmpegPath', { infer: true }) ?? 'ffmpeg',
|
||||
},
|
||||
serving: {
|
||||
rangeRequests: true,
|
||||
immutableCacheSeconds: 31536000,
|
||||
hlsManifestCacheSeconds: 300,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
async generateMusicFromText(userId: string, dto: TextToMusicDto) {
|
||||
const enabled = this.configService.get<boolean>('aiMusic.enabled', { infer: true });
|
||||
if (!enabled) {
|
||||
|
||||
@@ -4,6 +4,7 @@ import { Types } from 'mongoose';
|
||||
import { ModerationStatus } from '../../common/enums/moderation-status.enum';
|
||||
import { PostType } from '../../common/enums/post-type.enum';
|
||||
import { PostVisibility } from '../../common/enums/post-visibility.enum';
|
||||
import { ProcessingStatus } from '../../common/enums/processing-status.enum';
|
||||
import { buildPaginatedResponse } from '../../common/utils/pagination.util';
|
||||
import { resolveMongoSortDirection } from '../../common/utils/sort.util';
|
||||
import {
|
||||
@@ -172,6 +173,7 @@ export class PostsService {
|
||||
latitude,
|
||||
longitude,
|
||||
postType,
|
||||
processingStatus: ProcessingStatus.READY,
|
||||
visibility: dto.visibility ?? PostVisibility.PUBLIC,
|
||||
commentsDisabled: dto.commentsDisabled ?? false,
|
||||
commentsFollowersOnly: dto.commentsFollowersOnly ?? false,
|
||||
@@ -372,6 +374,7 @@ export class PostsService {
|
||||
latitude: nextLatitude,
|
||||
longitude: nextLongitude,
|
||||
postType: nextPostType,
|
||||
processingStatus: ProcessingStatus.READY,
|
||||
...mediaMetadata,
|
||||
};
|
||||
|
||||
@@ -1247,6 +1250,7 @@ export class PostsService {
|
||||
const post = await this.postsRepository.create(userId, {
|
||||
content,
|
||||
postType: PostType.TEXT,
|
||||
processingStatus: ProcessingStatus.READY,
|
||||
visibility: dto.visibility ?? PostVisibility.PUBLIC,
|
||||
repostOfPostId: content ? null : new Types.ObjectId(sourcePostId),
|
||||
quoteOfPostId: content ? new Types.ObjectId(sourcePostId) : null,
|
||||
|
||||
@@ -3,6 +3,8 @@ import { HydratedDocument, Types } from 'mongoose';
|
||||
import { ModerationStatus } from '../../../common/enums/moderation-status.enum';
|
||||
import { PostType } from '../../../common/enums/post-type.enum';
|
||||
import { PostVisibility } from '../../../common/enums/post-visibility.enum';
|
||||
import { ProcessingStatus } from '../../../common/enums/processing-status.enum';
|
||||
import { buildPostMediaResponse } from '../../../common/utils/post-media-response.util';
|
||||
import {
|
||||
resolveManagedFileUrl,
|
||||
resolveManagedFileUrlRecord,
|
||||
@@ -115,6 +117,14 @@ export class Post {
|
||||
@Prop({ enum: PostType, default: PostType.TEXT, index: true })
|
||||
postType!: PostType;
|
||||
|
||||
@Prop({
|
||||
type: String,
|
||||
enum: Object.values(ProcessingStatus),
|
||||
default: ProcessingStatus.READY,
|
||||
index: true,
|
||||
})
|
||||
processingStatus!: ProcessingStatus;
|
||||
|
||||
@Prop({ enum: PostVisibility, default: PostVisibility.PUBLIC, index: true })
|
||||
visibility!: PostVisibility;
|
||||
|
||||
@@ -182,6 +192,7 @@ PostSchema.index({ repostOfPostId: 1, createdAt: -1 });
|
||||
PostSchema.index({ quoteOfPostId: 1, createdAt: -1 });
|
||||
PostSchema.index({ visibility: 1, createdAt: -1 });
|
||||
PostSchema.index({ postType: 1, createdAt: -1 });
|
||||
PostSchema.index({ processingStatus: 1, createdAt: -1 });
|
||||
PostSchema.index({ hashtags: 1, createdAt: -1 });
|
||||
PostSchema.index({ taggedUserIds: 1, createdAt: -1 });
|
||||
PostSchema.index({ collaboratorIds: 1, createdAt: -1 });
|
||||
@@ -216,6 +227,8 @@ const transformManagedPostFiles = (_doc: unknown, ret: any) => {
|
||||
ret.audioUrl = resolveManagedFileUrl(ret.audioUrl);
|
||||
ret.thumbnailUrl = resolveManagedFileUrl(ret.thumbnailUrl);
|
||||
ret.thumbnailVariants = resolveManagedFileUrlRecord(ret.thumbnailVariants);
|
||||
ret.processingStatus = ret.processingStatus ?? ProcessingStatus.READY;
|
||||
ret.media = buildPostMediaResponse(ret);
|
||||
return ret;
|
||||
};
|
||||
|
||||
|
||||
المرجع في مشكلة جديدة
حظر مستخدم