From 24258e4e9aabd89723f392c26293145b7e268570 Mon Sep 17 00:00:00 2001 From: YaraSenousy <102993483+YaraSenousy@users.noreply.github.com> Date: Sat, 2 May 2026 22:55:55 +0300 Subject: [PATCH 1/2] fix: update track factory to update urls --- src/database/factories/track.factory.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/database/factories/track.factory.ts b/src/database/factories/track.factory.ts index 3c1332c8..85b7d82c 100644 --- a/src/database/factories/track.factory.ts +++ b/src/database/factories/track.factory.ts @@ -13,13 +13,13 @@ export default setSeederFactory(Track, async () => { // Media URLs track.audioUrl = - 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/d96f835d-488c-4d9d-99b3-a67e28a652d7/WhatsApp_Audio_2026-05-02_at_51805_PM_standard.mp3'; + 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/e2117315-c592-479f-81f2-f5f91e8cc691/WhatsApp_Audio_2026-05-02_at_51805_PM_standard.mp3'; track.previewAudioUrl = - 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/d96f835d-488c-4d9d-99b3-a67e28a652d7/WhatsApp_Audio_2026-05-02_at_51805_PM_preview.mp3'; + 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/e2117315-c592-479f-81f2-f5f91e8cc691/WhatsApp_Audio_2026-05-02_at_51805_PM_preview.mp3'; track.waveformUrl = - 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/d96f835d-488c-4d9d-99b3-a67e28a652d7/waveform.json'; + 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/e2117315-c592-479f-81f2-f5f91e8cc691/waveform.json'; track.audioUrlHq = - 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/d96f835d-488c-4d9d-99b3-a67e28a652d7/WhatsApp_Audio_2026-05-02_at_51805_PM_hq.mp3'; + 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/e2117315-c592-479f-81f2-f5f91e8cc691/WhatsApp_Audio_2026-05-02_at_51805_PM_preview.mp3'; track.coverImage = faker.image.url({ width: 500, height: 500 }); // Metadata From d638723eee0510813dcf67f9cd1df5c7dd00bea3 Mon Sep 17 00:00:00 2001 From: YaraSenousy <102993483+YaraSenousy@users.noreply.github.com> Date: Sat, 2 May 2026 23:25:05 +0300 Subject: [PATCH 2/2] fix: implement protection for seeded audio URLs in processor and factory --- src/audio/audio.processor.ts | 6 ++++-- src/database/factories/track.factory.ts | 17 ++++++++--------- src/database/seeds/seed-audio-urls.constant.ts | 11 +++++++++++ src/track/track.service.ts | 5 ++++- 4 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 src/database/seeds/seed-audio-urls.constant.ts diff --git a/src/audio/audio.processor.ts b/src/audio/audio.processor.ts index 50a8103e..2567d96f 100644 --- a/src/audio/audio.processor.ts +++ b/src/audio/audio.processor.ts @@ -10,6 +10,7 @@ import { FfmpegService } from './ffmpeg.service'; import { StorageService } from '../common/storage_service'; import { Track } from '../track/entities/track.entity'; import { TrackStatus } from '../track/enums/track-status.enum'; +import { SEED_PROTECTED_AUDIO_URLS } from '../database/seeds/seed-audio-urls.constant'; export interface AudioJobResult { audioUrl: string; @@ -58,7 +59,8 @@ export class AudioProcessor extends WorkerHost { const { trackId, filePath, originalName, previewStartTime } = job.data; this.logger.log(`Processing audio for track ${trackId}`); - // Snapshot old S3 URLs before overwriting them + // Snapshot old S3 URLs before overwriting them. + // Exclude seeded URLs so they are never accidentally deleted. const existing = await this.trackRepository.findOne({ where: { trackId } }); const oldUrls = existing ? [ @@ -66,7 +68,7 @@ export class AudioProcessor extends WorkerHost { existing.audioUrlHq, existing.previewAudioUrl, existing.waveformUrl, - ].filter(Boolean) + ].filter((url) => url && !SEED_PROTECTED_AUDIO_URLS.has(url)) : []; try { diff --git a/src/database/factories/track.factory.ts b/src/database/factories/track.factory.ts index 85b7d82c..bd4a89b0 100644 --- a/src/database/factories/track.factory.ts +++ b/src/database/factories/track.factory.ts @@ -2,6 +2,9 @@ import { setSeederFactory } from 'typeorm-extension'; import { Track } from '../../track/entities/track.entity'; import { TrackStatus } from '../../track/enums/track-status.enum'; import { TrackVisibility } from '../../track/enums/track-visibility.enum'; +import { SEED_PROTECTED_AUDIO_URLS } from '../seeds/seed-audio-urls.constant'; + +const [audioUrl, audioUrlHq, previewAudioUrl, waveformUrl] = [...SEED_PROTECTED_AUDIO_URLS]; export default setSeederFactory(Track, async () => { const { faker } = await import('@faker-js/faker'); @@ -11,15 +14,11 @@ export default setSeederFactory(Track, async () => { track.title = faker.music.songName(); track.description = faker.lorem.paragraph(); - // Media URLs - track.audioUrl = - 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/e2117315-c592-479f-81f2-f5f91e8cc691/WhatsApp_Audio_2026-05-02_at_51805_PM_standard.mp3'; - track.previewAudioUrl = - 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/e2117315-c592-479f-81f2-f5f91e8cc691/WhatsApp_Audio_2026-05-02_at_51805_PM_preview.mp3'; - track.waveformUrl = - 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/e2117315-c592-479f-81f2-f5f91e8cc691/waveform.json'; - track.audioUrlHq = - 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/e2117315-c592-479f-81f2-f5f91e8cc691/WhatsApp_Audio_2026-05-02_at_51805_PM_preview.mp3'; + // Media URLs — sourced from seed-audio-urls.constant.ts (protected from processor deletion) + track.audioUrl = audioUrl; + track.previewAudioUrl = previewAudioUrl; + track.waveformUrl = waveformUrl; + track.audioUrlHq = audioUrlHq; track.coverImage = faker.image.url({ width: 500, height: 500 }); // Metadata diff --git a/src/database/seeds/seed-audio-urls.constant.ts b/src/database/seeds/seed-audio-urls.constant.ts new file mode 100644 index 00000000..dbb50581 --- /dev/null +++ b/src/database/seeds/seed-audio-urls.constant.ts @@ -0,0 +1,11 @@ +/** + * Shared S3 URLs used by the track seeder factory. + * The audio processor checks against this list before deleting old S3 files + * to prevent accidentally wiping seeded assets during re-processing. + */ +export const SEED_PROTECTED_AUDIO_URLS = new Set([ + 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/4bb04f6f-b570-48b9-a97b-2790795e0d72/WhatsApp_Audio_2026-05-02_at_51805_PM_standard.mp3', + 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/4bb04f6f-b570-48b9-a97b-2790795e0d72/WhatsApp_Audio_2026-05-02_at_51805_PM_hq.mp3', + 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/4bb04f6f-b570-48b9-a97b-2790795e0d72/WhatsApp_Audio_2026-05-02_at_51805_PM_preview.mp3', + 'https://harmonica-s3-storage-287109772507-us-east-1-an.s3.amazonaws.com/tracks/4bb04f6f-b570-48b9-a97b-2790795e0d72/waveform.json', +]); diff --git a/src/track/track.service.ts b/src/track/track.service.ts index d338c7e5..1ad82f97 100644 --- a/src/track/track.service.ts +++ b/src/track/track.service.ts @@ -48,6 +48,7 @@ import { RecentlyPlayedItemType } from './entities/recently-played.entity'; import { FansService } from './services/fans.service'; import { ActivityService } from '../activity/activity.service'; import { ActivityType } from '../activity/entities/activity.entity'; +import { SEED_PROTECTED_AUDIO_URLS } from '../database/seeds/seed-audio-urls.constant'; import { REDIS_CLIENT } from '../redis/redis.module'; import { Genre } from '../genre/entities/genre.entity'; import { DEFAULT_GENRE_NAMES } from '../genre/genre.constants'; @@ -934,7 +935,9 @@ export class TrackService { throw new ForbiddenException('You do not own this track'); } const oldUrls = track - ? [track.audioUrl, track.audioUrlHq, track.previewAudioUrl, track.waveformUrl].filter(Boolean) + ? [track.audioUrl, track.audioUrlHq, track.previewAudioUrl, track.waveformUrl].filter( + (url) => url && !SEED_PROTECTED_AUDIO_URLS.has(url) + ) : []; await Promise.allSettled(oldUrls.map((url) => this.storageService.deleteFile(url)));