Files
vod-system/src/main/java/com/ddf/vodsystem/services/ClipService.java
Dylan De Faoite 65ec8cb29a MOVE clip creation method from ClipService to JobService
The original clip creation method in ClipService handled many different services, like metadata handling, callback methods and more. Moving it to a more suitable location in the JobService allows it to easily access the Job object and update it upon failure.
2025-12-15 21:23:01 +00:00

178 lines
6.5 KiB
Java

package com.ddf.vodsystem.services;
import com.ddf.vodsystem.dto.ClipOptions;
import com.ddf.vodsystem.entities.*;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
import com.ddf.vodsystem.exceptions.FFMPEGException;
import com.ddf.vodsystem.exceptions.NotAuthenticated;
import com.ddf.vodsystem.repositories.ClipRepository;
import com.ddf.vodsystem.services.media.MetadataService;
import com.ddf.vodsystem.services.media.ThumbnailService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
@Service
public class ClipService {
private static final Logger logger = LoggerFactory.getLogger(ClipService.class);
private final ClipRepository clipRepository;
private final DirectoryService directoryService;
private final MetadataService metadataService;
private final ThumbnailService thumbnailService;
private final UserService userService;
public ClipService(ClipRepository clipRepository,
DirectoryService directoryService,
MetadataService metadataService,
ThumbnailService thumbnailService,
UserService userService) {
this.clipRepository = clipRepository;
this.directoryService = directoryService;
this.metadataService = metadataService;
this.thumbnailService = thumbnailService;
this.userService = userService;
}
/**
* Retrieves all clips associated with the currently logged-in user.
*
* @return a list of clips belonging to the authenticated user.
* @throws NotAuthenticated if the user is not authenticated.
*/
public List<Clip> getClipsByUser() {
Optional<User> user = userService.getLoggedInUser();
if (user.isEmpty()) {
throw new NotAuthenticated("User is not authenticated");
}
return clipRepository.findByUser(user.get());
}
/**
* Retrieves a clip by its ID, ensuring the user is authenticated to access it.
*
* @param id the ID of the clip to retrieve.
* @return an Optional containing the Clip if found and accessible, or empty if not found.
* @throws NotAuthenticated if the user is not authorized to access the clip.
*/
public Optional<Clip> getClipById(Long id) {
Optional<Clip> clip = clipRepository.findById(id);
if (clip.isEmpty()) {
logger.warn("Clip with ID {} not found", id);
return clip;
}
if (!isAuthenticatedForClip(clip.get())) {
logger.warn("User is not authorized to access clip with ID {}", id);
throw new NotAuthenticated("You are not authorized to access this clip");
}
return clip;
}
/**
* Deletes a clip by its ID, ensuring the user is authenticated to perform the deletion.
*
* @param id the ID of the clip to delete.
* @return true if the clip was successfully deleted, false if it was not found.
* @throws NotAuthenticated if the user is not authorized to delete the clip.
*/
public boolean deleteClip(Long id) {
Optional<Clip> possibleClip = getClipById(id);
if (possibleClip.isEmpty()) {
logger.warn("Clip with ID {} not found for deletion", id);
return false;
}
Clip clip = possibleClip.get();
if (!isAuthenticatedForClip(clip)) {
throw new NotAuthenticated("You are not authorized to delete this clip");
}
deleteClipFiles(clip);
clipRepository.delete(clip);
logger.info("Clip with ID {} deleted successfully", id);
return true;
}
/**
* Checks if the currently logged-in user is authenticated to access the specified clip.
*
* @param clip the clip to check access for.
* @return true if the user is authenticated for the clip, false otherwise.
*/
public boolean isAuthenticatedForClip(Clip clip) {
Optional<User> user = userService.getLoggedInUser();
if (user.isEmpty() || clip == null) {
return false;
}
return user.get().getId().equals(clip.getUser().getId());
}
public void persistClip(ClipOptions clipOptions,
User user,
File tempFile,
String fileName) {
// Move clip from temp to output directory
File clipFile = directoryService.getUserClipsFile(user.getId(), fileName);
File thumbnailFile = directoryService.getUserThumbnailsFile(user.getId(), fileName + ".png");
directoryService.cutFile(tempFile, clipFile);
ClipOptions clipMetadata;
try {
clipMetadata = metadataService.getVideoMetadata(clipFile).get();
} catch (InterruptedException | ExecutionException e) {
Thread.currentThread().interrupt();
throw new FFMPEGException("Error retrieving video metadata for clip: " + e.getMessage());
}
try {
thumbnailService.createThumbnail(clipFile, thumbnailFile, 0.0f);
} catch (IOException | InterruptedException e) {
logger.error("Error generating thumbnail for clip: {}", e.getMessage());
Thread.currentThread().interrupt();
}
// Save clip to database
Clip clip = new Clip();
clip.setUser(user);
clip.setTitle(clipOptions.getTitle() != null ? clipOptions.getTitle() : "Untitled Clip");
clip.setDescription(clipOptions.getDescription() != null ? clipOptions.getDescription() : "");
clip.setCreatedAt(LocalDateTime.now());
clip.setWidth(clipMetadata.getWidth());
clip.setHeight(clipMetadata.getHeight());
clip.setFps(clipMetadata.getFps());
clip.setDuration(clipMetadata.getDuration() - clipMetadata.getStartPoint());
clip.setFileSize(clipMetadata.getFileSize());
clip.setVideoPath(clipFile.getPath());
clip.setThumbnailPath(thumbnailFile.getPath());
clipRepository.save(clip);
logger.info("Clip created successfully with ID: {}", clip.getId());
}
private void deleteClipFiles(Clip clip) {
File clipFile = new File(clip.getVideoPath());
File thumbnailFile = new File(clip.getThumbnailPath());
try {
Files.deleteIfExists(clipFile.toPath());
Files.deleteIfExists(thumbnailFile.toPath());
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}