181 lines
7.6 KiB
Java
181 lines
7.6 KiB
Java
package com.hlab.yanalyst.service;
|
|
|
|
import com.hlab.yanalyst.domain.opal.*;
|
|
import com.hlab.yanalyst.domain.script.ScriptGen;
|
|
import com.hlab.yanalyst.domain.script.ScriptGenRepository;
|
|
import com.hlab.yanalyst.domain.video.YtVideo;
|
|
import com.hlab.yanalyst.domain.video.YtVideoRepository;
|
|
import com.hlab.yanalyst.service.external.ExternalApiService;
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
|
import lombok.RequiredArgsConstructor;
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.util.List;
|
|
|
|
@Service
|
|
@RequiredArgsConstructor
|
|
@Transactional
|
|
public class AnalysisWorkflowService {
|
|
|
|
private final YtVideoRepository ytVideoRepository;
|
|
private final ScriptGenRepository scriptGenRepository;
|
|
private final OpalDraftRepository opalDraftRepository;
|
|
private final OpalFinalRepository opalFinalRepository;
|
|
private final OpalFinalAssetRepository opalFinalAssetRepository;
|
|
private final ExternalApiService externalApiService;
|
|
private final ObjectMapper objectMapper;
|
|
|
|
public ScriptGen generateScript(Long videoId) {
|
|
YtVideo video = ytVideoRepository.findById(videoId)
|
|
.orElseThrow(() -> new IllegalArgumentException("Video not found"));
|
|
|
|
String scriptContent = externalApiService.generateScript(video.getVideoUrl());
|
|
|
|
ScriptGen scriptGen = scriptGenRepository.findById(videoId).orElse(new ScriptGen());
|
|
if (scriptGen.getVideoId() == null) {
|
|
scriptGen.setVideo(video);
|
|
}
|
|
scriptGen.setResponseText(scriptContent);
|
|
scriptGen.setStatus("SUCCESS");
|
|
// Update video status
|
|
video.setStatus("SCRIPT_READY");
|
|
|
|
return scriptGenRepository.save(scriptGen);
|
|
}
|
|
|
|
public OpalDraft generateDraft(Long videoId, String feedback, String mode) {
|
|
YtVideo video = ytVideoRepository.findById(videoId)
|
|
.orElseThrow(() -> new IllegalArgumentException("Video not found"));
|
|
|
|
ScriptGen scriptGen = scriptGenRepository.findById(videoId)
|
|
.orElseThrow(() -> new IllegalArgumentException("Script not found"));
|
|
|
|
var draftDto = externalApiService.generateOpalDraft(scriptGen.getResponseText(), feedback, mode);
|
|
|
|
OpalDraft draft = new OpalDraft();
|
|
draft.setVideo(video);
|
|
draft.setOldScriptSummary(draftDto.getOldScriptSummary());
|
|
draft.setNewScriptSummary(draftDto.getNewScriptSummary());
|
|
// For compatibility, we can concatenate or just leave responseText empty/null, or use New Summary as main response
|
|
draft.setResponseText(draftDto.getNewScriptSummary());
|
|
draft.setUserFeedback(feedback);
|
|
|
|
Integer maxVersion = opalDraftRepository.findByVideo_VideoIdOrderByVersionNoDesc(videoId)
|
|
.stream().findFirst().map(OpalDraft::getVersionNo).orElse(0);
|
|
draft.setVersionNo(maxVersion + 1);
|
|
draft.setStatus("SUCCESS");
|
|
|
|
video.setStatus("DRAFTING");
|
|
|
|
return opalDraftRepository.save(draft);
|
|
}
|
|
|
|
public OpalFinal acceptDraft(Long videoId, Long draftId) {
|
|
YtVideo video = ytVideoRepository.findById(videoId).orElseThrow();
|
|
OpalDraft draft = opalDraftRepository.findById(draftId).orElseThrow();
|
|
|
|
if (!draft.getVideo().getVideoId().equals(videoId)) {
|
|
throw new IllegalArgumentException("Draft does not match video");
|
|
}
|
|
|
|
// Deactivate existing active final
|
|
opalFinalRepository.findByVideo_VideoIdAndIsActiveTrue(videoId)
|
|
.ifPresent(existing -> {
|
|
existing.setIsActive(false);
|
|
opalFinalRepository.save(existing);
|
|
});
|
|
|
|
// Mark draft accepted
|
|
draft.setIsAccepted(true);
|
|
draft.setAcceptedAt(LocalDateTime.now());
|
|
opalDraftRepository.save(draft);
|
|
|
|
OpalFinal opalFinal = new OpalFinal();
|
|
opalFinal.setVideo(video);
|
|
opalFinal.setDraft(draft);
|
|
opalFinal.setFinalScriptText(draft.getResponseText());
|
|
opalFinal.setIsActive(true);
|
|
|
|
return opalFinalRepository.save(opalFinal);
|
|
}
|
|
|
|
public OpalFinalAsset generateFinalAsset(Long videoId) {
|
|
YtVideo video = ytVideoRepository.findById(videoId).orElseThrow();
|
|
OpalFinal activeFinal = opalFinalRepository.findByVideo_VideoIdAndIsActiveTrue(videoId)
|
|
.orElse(null);
|
|
|
|
if (activeFinal == null) {
|
|
OpalDraft latestDraft = opalDraftRepository.findByVideo_VideoIdOrderByVersionNoDesc(videoId)
|
|
.stream().findFirst()
|
|
.orElseThrow(() -> new IllegalArgumentException("No active final script and no drafts found. Please generate a draft first."));
|
|
|
|
activeFinal = new OpalFinal();
|
|
activeFinal.setVideo(video);
|
|
activeFinal.setDraft(latestDraft);
|
|
activeFinal.setIsActive(true);
|
|
activeFinal.setFinalScriptText("");
|
|
activeFinal = opalFinalRepository.save(activeFinal);
|
|
}
|
|
|
|
// 1. Fetch updated final script from external source (GDoc)
|
|
String updatedFinalScript = externalApiService.fetchFinalScript();
|
|
|
|
// 2. Update and save active final script
|
|
activeFinal.setFinalScriptText(updatedFinalScript);
|
|
opalFinalRepository.save(activeFinal);
|
|
|
|
// 3. Generate asset metadata
|
|
var assetMap = externalApiService.generateFinalAsset(activeFinal.getFinalScriptText());
|
|
|
|
OpalFinalAsset asset = new OpalFinalAsset();
|
|
asset.setOpalFinal(activeFinal);
|
|
try {
|
|
asset.setAssetJson(objectMapper.writeValueAsString(assetMap));
|
|
asset.setTitle((String) assetMap.get("title"));
|
|
asset.setSummary((String) assetMap.get("summary"));
|
|
asset.setTimeline(objectMapper.writeValueAsString(assetMap.get("timeline")));
|
|
asset.setVideoPrompt((String) assetMap.get("video_prompt"));
|
|
asset.setImageUrls(objectMapper.writeValueAsString(assetMap.get("image_urls")));
|
|
} catch (Exception e) {
|
|
throw new RuntimeException("JSON processing error", e);
|
|
}
|
|
|
|
video.setStatus("FINALIZED");
|
|
return opalFinalAssetRepository.save(asset);
|
|
}
|
|
public boolean toggleComplete(Long videoId) {
|
|
YtVideo video = ytVideoRepository.findById(videoId)
|
|
.orElseThrow(() -> new IllegalArgumentException("Video not found"));
|
|
|
|
boolean newState = video.getIsCompleted() == null ? true : !video.getIsCompleted();
|
|
video.setIsCompleted(newState);
|
|
ytVideoRepository.save(video);
|
|
return newState;
|
|
}
|
|
|
|
public void updateFinalAsset(Long videoId, String newText) {
|
|
OpalFinal opalFinal = opalFinalRepository.findByVideo_VideoIdAndIsActiveTrue(videoId)
|
|
.orElseThrow(() -> new IllegalArgumentException("No active final asset found for videoId: " + videoId));
|
|
opalFinal.setFinalScriptText(newText);
|
|
opalFinalRepository.save(opalFinal);
|
|
}
|
|
|
|
public void generateOpening(Long videoId, String docId) {
|
|
YtVideo video = ytVideoRepository.findById(videoId)
|
|
.orElseThrow(() -> new IllegalArgumentException("Video not found"));
|
|
|
|
String openingScript = externalApiService.fetchOpeningScript(docId);
|
|
video.setOpeningScript(openingScript);
|
|
ytVideoRepository.save(video);
|
|
}
|
|
|
|
public void resetOpening(Long videoId) {
|
|
YtVideo video = ytVideoRepository.findById(videoId)
|
|
.orElseThrow(() -> new IllegalArgumentException("Video not found"));
|
|
video.setOpeningScript(null);
|
|
ytVideoRepository.save(video);
|
|
}
|
|
}
|