fix
This commit is contained in:
@@ -1,20 +1,19 @@
|
||||
package kz.konturai.parser.controller;
|
||||
|
||||
import jakarta.validation.Valid;
|
||||
import kz.konturai.parser.dto.ApiResponse;
|
||||
import kz.konturai.parser.dto.ErrorResponse;
|
||||
import kz.konturai.parser.dto.MarketingAnalysisV3Request;
|
||||
import kz.konturai.parser.dto.MarketingStrategyRequest;
|
||||
import kz.konturai.parser.dto.StrategyHistoryResponse;
|
||||
import kz.konturai.parser.dto.*;
|
||||
import kz.konturai.parser.enums.StrategyModel;
|
||||
import kz.konturai.parser.model.MarketingAnalysisV3Document;
|
||||
import kz.konturai.parser.model.MarketingStrategy;
|
||||
import kz.konturai.parser.model.PostingTask;
|
||||
import kz.konturai.parser.service.JwtService;
|
||||
import kz.konturai.parser.service.MarketingAnalysisV3Service;
|
||||
import kz.konturai.parser.service.MarketingStrategyV3Service;
|
||||
import kz.konturai.parser.service.MinIOService;
|
||||
import kz.konturai.parser.service.PostingTaskService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
@@ -22,6 +21,7 @@ import org.springframework.web.bind.MethodArgumentNotValidException;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@@ -37,6 +37,7 @@ public class MarketingAnalysisV3Controller {
|
||||
|
||||
private final MarketingAnalysisV3Service analysisService;
|
||||
private final MarketingStrategyV3Service strategyService;
|
||||
private final PostingTaskService postingTaskService;
|
||||
private final MinIOService minIOService;
|
||||
private final JwtService jwtService;
|
||||
|
||||
@@ -47,7 +48,6 @@ public class MarketingAnalysisV3Controller {
|
||||
try {
|
||||
return jwtService.extractUserIdFromHeader(authHeader);
|
||||
} catch (Exception e) {
|
||||
log.error("Error extracting userId from JWT: {}", e.getMessage());
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -68,7 +68,6 @@ public class MarketingAnalysisV3Controller {
|
||||
);
|
||||
return ResponseEntity.accepted().body(ApiResponse.success("Анализ запущен", responseData));
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to start analysis V3", e);
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
@@ -90,7 +89,6 @@ public class MarketingAnalysisV3Controller {
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.success(analysis));
|
||||
} catch (Exception e) {
|
||||
log.error("Error fetching analysis V3: {}", id, e);
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
@@ -106,11 +104,102 @@ public class MarketingAnalysisV3Controller {
|
||||
List<MarketingAnalysisV3Document> analyses = analysisService.getAllByUser(userId);
|
||||
return ResponseEntity.ok(ApiResponse.success(analyses));
|
||||
} catch (Exception e) {
|
||||
log.error("Error fetching user analyses V3", e);
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{analysisId}/history")
|
||||
public ResponseEntity<?> getAnalysisHistory(
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String analysisId
|
||||
) {
|
||||
String userId = extractUserIdFromHeader(authHeader);
|
||||
if (userId == null) return unauthorizedResponse();
|
||||
|
||||
try {
|
||||
Optional<MarketingAnalysisV3Document> analysisOpt = analysisService.getAnalysisById(analysisId);
|
||||
if (analysisOpt.isEmpty()) return notFoundResponse("Анализ не найден");
|
||||
|
||||
MarketingAnalysisV3Document analysis = analysisOpt.get();
|
||||
if (!analysis.getUserId().equals(userId)) return forbiddenResponse();
|
||||
|
||||
AnalysisHistoryResponse response = new AnalysisHistoryResponse();
|
||||
response.setAnalysisId(analysis.getId());
|
||||
if (analysis.getRequestData() != null) {
|
||||
response.setBusinessNiche(analysis.getRequestData().getBusinessNiche());
|
||||
response.setProduct(analysis.getRequestData().getProductName());
|
||||
response.setGoal(analysis.getRequestData().getGoal());
|
||||
response.setDetailLevel(analysis.getRequestData().getDetailLevel());
|
||||
|
||||
if (analysis.getRequestData().getAnalysisType() != null) {
|
||||
response.setAnalysisType(String.join(", ", analysis.getRequestData().getAnalysisType()));
|
||||
}
|
||||
if (analysis.getRequestData().getClientTarget() != null) {
|
||||
response.setTargetAudience(analysis.getRequestData().getClientTarget().name());
|
||||
}
|
||||
if (analysis.getRequestData().getPromotionCities() != null) {
|
||||
response.setRegion(String.join(", ", analysis.getRequestData().getPromotionCities()));
|
||||
}
|
||||
}
|
||||
response.setStatus(analysis.getStatus());
|
||||
response.setUserId(analysis.getUserId());
|
||||
response.setCreatedAt(analysis.getCreatedAt());
|
||||
response.setCompletedAt(analysis.getUpdatedAt());
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.success(response));
|
||||
} catch (Exception e) {
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{analysisId}/download")
|
||||
public ResponseEntity<?> downloadPdf(
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String analysisId
|
||||
) {
|
||||
String userId = extractUserIdFromHeader(authHeader);
|
||||
if (userId == null) return unauthorizedResponse();
|
||||
|
||||
try {
|
||||
Optional<MarketingAnalysisV3Document> analysisOpt = analysisService.getAnalysisById(analysisId);
|
||||
if (analysisOpt.isEmpty()) return ResponseEntity.notFound().build();
|
||||
|
||||
MarketingAnalysisV3Document analysis = analysisOpt.get();
|
||||
if (!analysis.getUserId().equals(userId)) {
|
||||
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
|
||||
}
|
||||
|
||||
return ResponseEntity.notFound().build();
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.internalServerError().build();
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/images/{imageFilename}")
|
||||
public ResponseEntity<byte[]> getPostImage(
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String imageFilename
|
||||
) {
|
||||
String userId = extractUserIdFromHeader(authHeader);
|
||||
if (userId == null) return ResponseEntity.status(HttpStatus.UNAUTHORIZED).build();
|
||||
|
||||
try {
|
||||
if (!minIOService.fileExists(imageFilename)) {
|
||||
return ResponseEntity.notFound().build();
|
||||
}
|
||||
InputStream inputStream = minIOService.downloadFile(imageFilename);
|
||||
byte[] bytes = inputStream.readAllBytes();
|
||||
inputStream.close();
|
||||
|
||||
return ResponseEntity.ok()
|
||||
.header(HttpHeaders.CONTENT_TYPE, MediaType.IMAGE_PNG_VALUE)
|
||||
.header(HttpHeaders.CACHE_CONTROL, "public, max-age=3600")
|
||||
.body(bytes);
|
||||
} catch (Exception e) {
|
||||
return ResponseEntity.internalServerError().build();
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{analysisId}/strategy-preview")
|
||||
public ResponseEntity<?> previewStrategy(
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@@ -134,7 +223,6 @@ public class MarketingAnalysisV3Controller {
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.success("Рекомендация сформирована", responseData));
|
||||
} catch (Exception e) {
|
||||
log.error("Error previewing strategy for analysis: {}", analysisId, e);
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
@@ -160,7 +248,6 @@ public class MarketingAnalysisV3Controller {
|
||||
logoFile.getOriginalFilename().substring(logoFile.getOriginalFilename().lastIndexOf(".")) : ".png";
|
||||
logoFilename = "logo_" + UUID.randomUUID() + originalExt;
|
||||
minIOService.uploadFile(logoFilename, logoFile.getBytes(), logoFile.getContentType());
|
||||
log.info("Логотип клиента успешно загружен в MinIO: {}", logoFilename);
|
||||
}
|
||||
|
||||
if (request == null) {
|
||||
@@ -177,7 +264,6 @@ public class MarketingAnalysisV3Controller {
|
||||
return ResponseEntity.accepted().body(ApiResponse.success("Автономная генерация запущена", responseData));
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to generate strategy for analysis: {}", analysisId, e);
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
@@ -199,7 +285,28 @@ public class MarketingAnalysisV3Controller {
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.success(strategy));
|
||||
} catch (Exception e) {
|
||||
log.error("Error fetching strategy: {}", strategyId, e);
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/{analysisId}/strategy")
|
||||
public ResponseEntity<?> getStrategyByAnalysis(
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String analysisId
|
||||
) {
|
||||
String userId = extractUserIdFromHeader(authHeader);
|
||||
if (userId == null) return unauthorizedResponse();
|
||||
|
||||
try {
|
||||
Optional<MarketingAnalysisV3Document> optAnalysis = analysisService.getAnalysisById(analysisId);
|
||||
if (optAnalysis.isEmpty()) return notFoundResponse("Анализ не найден");
|
||||
if (!optAnalysis.get().getUserId().equals(userId)) return forbiddenResponse();
|
||||
|
||||
Optional<MarketingStrategy> strategyOpt = strategyService.getStrategyByAnalysisId(analysisId);
|
||||
if (strategyOpt.isEmpty()) return notFoundResponse("Стратегия не найдена");
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.success(strategyOpt.get()));
|
||||
} catch (Exception e) {
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
@@ -219,7 +326,138 @@ public class MarketingAnalysisV3Controller {
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.success(responseList));
|
||||
} catch (Exception e) {
|
||||
log.error("Error fetching user strategies", e);
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
|
||||
@GetMapping("/strategy/{strategyId}/history")
|
||||
public ResponseEntity<?> getStrategyHistory(
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String strategyId
|
||||
) {
|
||||
String userId = extractUserIdFromHeader(authHeader);
|
||||
if (userId == null) return unauthorizedResponse();
|
||||
|
||||
try {
|
||||
Optional<MarketingStrategy> optStrategy = strategyService.getStrategyById(strategyId);
|
||||
if (optStrategy.isEmpty()) return notFoundResponse("Стратегия не найдена");
|
||||
|
||||
MarketingStrategy strategy = optStrategy.get();
|
||||
if (!strategy.getUserId().equals(userId)) return forbiddenResponse();
|
||||
|
||||
StrategyHistoryResponse response = convertToStrategyHistoryResponse(strategy);
|
||||
return ResponseEntity.ok(ApiResponse.success(response));
|
||||
} catch (Exception e) {
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/strategy/{strategyId}/start")
|
||||
public ResponseEntity<?> startStrategy(
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String strategyId
|
||||
) {
|
||||
String userId = extractUserIdFromHeader(authHeader);
|
||||
if (userId == null) return unauthorizedResponse();
|
||||
|
||||
try {
|
||||
Optional<MarketingStrategy> optStrategy = strategyService.getStrategyById(strategyId);
|
||||
if (optStrategy.isEmpty()) return notFoundResponse("Стратегия не найдена");
|
||||
|
||||
MarketingStrategy strategy = optStrategy.get();
|
||||
if (!strategy.getUserId().equals(userId)) return forbiddenResponse();
|
||||
|
||||
if (!"completed".equals(strategy.getStatus())) {
|
||||
ErrorResponse error = new ErrorResponse("INVALID_STATUS", "Стратегия еще не завершена. Статус: " + strategy.getStatus());
|
||||
return ResponseEntity.status(400).body(ApiResponse.error("Стратегия не готова к запуску", error));
|
||||
}
|
||||
|
||||
List<PostingTask> tasks = postingTaskService.createTasksFromStrategy(strategyId);
|
||||
List<String> platforms = tasks.stream().map(PostingTask::getPlatform).distinct().collect(Collectors.toList());
|
||||
|
||||
StartStrategyResponse response = new StartStrategyResponse(
|
||||
strategyId,
|
||||
tasks.size(),
|
||||
platforms,
|
||||
"Стратегия успешно запущена. Создано задач: " + tasks.size()
|
||||
);
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.success("Стратегия успешно запущена", response));
|
||||
} catch (IllegalStateException e) {
|
||||
return ResponseEntity.status(400).body(ApiResponse.error("Не удалось запустить стратегию", new ErrorResponse("ERROR", e.getMessage())));
|
||||
} catch (Exception e) {
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/tasks/{taskId}/execute")
|
||||
public ResponseEntity<?> executeTaskManually(
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String taskId
|
||||
) {
|
||||
String userId = extractUserIdFromHeader(authHeader);
|
||||
if (userId == null) return unauthorizedResponse();
|
||||
|
||||
try {
|
||||
Optional<PostingTask> optTask = postingTaskService.getTaskById(taskId);
|
||||
if (optTask.isEmpty()) return notFoundResponse("Задача не найдена");
|
||||
|
||||
PostingTask task = optTask.get();
|
||||
if (!userId.equals(task.getUserId())) return forbiddenResponse();
|
||||
|
||||
postingTaskService.executeTaskManually(taskId);
|
||||
|
||||
Optional<PostingTask> updatedTask = postingTaskService.getTaskById(taskId);
|
||||
if (updatedTask.isPresent()) {
|
||||
PostingTask taskData = updatedTask.get();
|
||||
Map<String, Object> responseData = Map.of(
|
||||
"taskId", taskData.getId(),
|
||||
"status", taskData.getStatus(),
|
||||
"platform", taskData.getPlatform(),
|
||||
"publishDate", taskData.getPublishDate()
|
||||
);
|
||||
return ResponseEntity.ok(ApiResponse.success("Задача успешно запущена", responseData));
|
||||
}
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.success("Задача отправлена в обработку", Map.of("taskId", taskId)));
|
||||
} catch (IllegalStateException e) {
|
||||
return ResponseEntity.status(400).body(ApiResponse.error("Задача не может быть запущена", new ErrorResponse("INVALID_STATUS", e.getMessage())));
|
||||
} catch (Exception e) {
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
|
||||
@PostMapping("/strategy/{strategyId}/post/{postIndex}/regenerate-image")
|
||||
public ResponseEntity<?> regeneratePostImage(
|
||||
@RequestHeader(value = "Authorization", required = false) String authHeader,
|
||||
@PathVariable String strategyId,
|
||||
@PathVariable int postIndex
|
||||
) {
|
||||
String userId = extractUserIdFromHeader(authHeader);
|
||||
if (userId == null) return unauthorizedResponse();
|
||||
|
||||
try {
|
||||
Optional<MarketingStrategy> optStrategy = strategyService.getStrategyById(strategyId);
|
||||
if (optStrategy.isEmpty()) return notFoundResponse("Стратегия не найдена");
|
||||
|
||||
MarketingStrategy strategy = optStrategy.get();
|
||||
if (!strategy.getUserId().equals(userId)) return forbiddenResponse();
|
||||
|
||||
MarketingStrategy.PostCalendarItem updatedItem = strategyService.regeneratePostImage(strategyId, postIndex);
|
||||
if (updatedItem == null) return notFoundResponse("Пост не найден");
|
||||
|
||||
Map<String, Object> responseData = Map.of(
|
||||
"strategyId", strategyId,
|
||||
"postIndex", postIndex,
|
||||
"imageUrl", updatedItem.getImageUrl() != null ? updatedItem.getImageUrl() : "",
|
||||
"imageFilename", updatedItem.getImageFilename() != null ? updatedItem.getImageFilename() : "",
|
||||
"theme", updatedItem.getTheme() != null ? updatedItem.getTheme() : "",
|
||||
"platform", updatedItem.getPlatform() != null ? updatedItem.getPlatform() : "",
|
||||
"publishDate", updatedItem.getPublishDate()
|
||||
);
|
||||
|
||||
return ResponseEntity.ok(ApiResponse.success("Изображение для поста успешно регенерировано", responseData));
|
||||
} catch (Exception e) {
|
||||
return internalErrorResponse(e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,48 +1,17 @@
|
||||
package kz.konturai.parser.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
|
||||
@Data
|
||||
@AllArgsConstructor
|
||||
@NoArgsConstructor
|
||||
public class StatusHistoryEntry {
|
||||
private String status;
|
||||
private LocalDateTime timestamp;
|
||||
private String message;
|
||||
|
||||
public StatusHistoryEntry() {
|
||||
}
|
||||
|
||||
public StatusHistoryEntry(String status, LocalDateTime timestamp) {
|
||||
this.status = status;
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public StatusHistoryEntry(String status, LocalDateTime timestamp, String message) {
|
||||
this.status = status;
|
||||
this.timestamp = timestamp;
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
public LocalDateTime getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
public void setTimestamp(LocalDateTime timestamp) {
|
||||
this.timestamp = timestamp;
|
||||
}
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -51,13 +51,17 @@ public class MarketingStrategyV3Service {
|
||||
return repository.findById(id);
|
||||
}
|
||||
|
||||
public Optional<MarketingStrategy> getStrategyByAnalysisId(String analysisId) {
|
||||
return repository.findByAnalysisId(analysisId);
|
||||
}
|
||||
|
||||
public List<MarketingStrategy> getUserStrategies(String userId) {
|
||||
return repository.findByUserIdOrderByCreatedAtDesc(userId);
|
||||
}
|
||||
|
||||
public MarketingStrategy generateStrategy(String analysisId, MarketingStrategyRequest request, String userId, String uploadedLogoFilename) {
|
||||
MarketingAnalysisV3Document analysisDoc = analysisRepository.findById(analysisId)
|
||||
.orElseThrow(() -> new IllegalArgumentException("Анализ V3 не найден"));
|
||||
.orElseThrow(() -> new IllegalArgumentException("Analysis V3 not found"));
|
||||
|
||||
MarketingStrategy strategy = new MarketingStrategy(analysisId);
|
||||
strategy.setUserId(userId);
|
||||
@@ -87,7 +91,6 @@ public class MarketingStrategyV3Service {
|
||||
repository.save(strategy);
|
||||
|
||||
StrategyModel bestModel = calculateBestScoringModel(analysis.getRequestData());
|
||||
log.info("[Strategy ID: {}] Выбрана модель: {}", strategyId, bestModel.name());
|
||||
|
||||
String systemPrompt = buildSystemPrompt(bestModel);
|
||||
String userPrompt = buildUserPrompt(analysis, bestModel);
|
||||
@@ -96,7 +99,7 @@ public class MarketingStrategyV3Service {
|
||||
String jsonResponse = extractCleanJson(rawResponse);
|
||||
|
||||
if (jsonResponse == null) {
|
||||
throw new IllegalStateException("AI не вернул валидный JSON");
|
||||
throw new IllegalStateException("AI failed to return valid JSON");
|
||||
}
|
||||
|
||||
Map<String, Object> strategyData = objectMapper.readValue(jsonResponse, new TypeReference<>() {});
|
||||
@@ -119,11 +122,52 @@ public class MarketingStrategyV3Service {
|
||||
repository.save(strategy);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Ошибка при генерации стратегии {}: {}", strategyId, e.getMessage(), e);
|
||||
log.error("Strategy generation error {}: {}", strategyId, e.getMessage(), e);
|
||||
markAsFailed(strategyId, "Ошибка при генерации стратегии: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
public MarketingStrategy.PostCalendarItem regeneratePostImage(String strategyId, int postIndex) {
|
||||
Optional<MarketingStrategy> optStrategy = repository.findById(strategyId);
|
||||
if (optStrategy.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MarketingStrategy strategy = optStrategy.get();
|
||||
List<MarketingStrategy.PostCalendarItem> postCalendar = strategy.getPostCalendar();
|
||||
|
||||
if (postCalendar == null || postIndex < 0 || postIndex >= postCalendar.size()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MarketingStrategy.PostCalendarItem item = postCalendar.get(postIndex);
|
||||
|
||||
Optional<MarketingAnalysisV3Document> analysisOpt = analysisRepository.findById(strategy.getAnalysisId());
|
||||
if (analysisOpt.isEmpty()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
MarketingAnalysisV3Document analysis = analysisOpt.get();
|
||||
String businessContext = getBusinessContext(analysis);
|
||||
String brandName = analysis.getRequestData().getProductName();
|
||||
|
||||
byte[] clientLogoBytes = null;
|
||||
if (strategy.getStrategyData() != null && strategy.getStrategyData().containsKey("clientLogoFilename")) {
|
||||
String logoFilename = (String) strategy.getStrategyData().get("clientLogoFilename");
|
||||
try {
|
||||
InputStream logoStream = minIOService.downloadFile(logoFilename);
|
||||
clientLogoBytes = logoStream.readAllBytes();
|
||||
logoStream.close();
|
||||
} catch (Exception e) {
|
||||
log.error("Failed to download logo for regeneration: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
doGenerateImage(item, businessContext, brandName, clientLogoBytes);
|
||||
repository.save(strategy);
|
||||
return item;
|
||||
}
|
||||
|
||||
public StrategyModel calculateBestScoringModel(kz.konturai.parser.dto.MarketingAnalysisV3Request req) {
|
||||
int entry = 0, authority = 0, trust = 0, conversion = 0;
|
||||
|
||||
@@ -238,9 +282,8 @@ public class MarketingStrategyV3Service {
|
||||
InputStream logoStream = minIOService.downloadFile(logoFilename);
|
||||
clientLogoBytes = logoStream.readAllBytes();
|
||||
logoStream.close();
|
||||
log.info("Загружен логотип для генерации: {}", logoFilename);
|
||||
} catch (Exception e) {
|
||||
log.error("Не удалось скачать логотип {}: {}", logoFilename, e.getMessage());
|
||||
log.error("Failed to download logo: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -250,13 +293,12 @@ public class MarketingStrategyV3Service {
|
||||
try {
|
||||
if (contentType.contains("видео") || contentType.contains("reels") || contentType.contains("tiktok")) {
|
||||
String videoPrompt = "High quality cinematic commercial video. Business niche: " + businessContext + ". Scene: " + item.getTheme() + ". Photorealistic, dynamic motion, 4k.";
|
||||
log.info("Попытка генерации ВИДЕО: {}", videoPrompt);
|
||||
|
||||
byte[] videoBytes = null;
|
||||
try {
|
||||
videoBytes = geminiVideoService.generateVideo(videoPrompt);
|
||||
} catch (Exception e) {
|
||||
log.warn("Сервис видео упал с ошибкой: {}", e.getMessage());
|
||||
log.warn("Video service failed: {}", e.getMessage());
|
||||
}
|
||||
|
||||
if (videoBytes != null && videoBytes.length > 0) {
|
||||
@@ -264,9 +306,7 @@ public class MarketingStrategyV3Service {
|
||||
minIOService.uploadFile(filename, videoBytes, "video/mp4");
|
||||
item.setVideoUrl(filename);
|
||||
item.setVideoFilename(filename);
|
||||
log.info("Видео успешно сгенерировано: {}", filename);
|
||||
} else {
|
||||
log.warn("Видео не сгенерировалось (вернулся null). Включаю FALLBACK -> генерирую ФОТО для темы: {}", item.getTheme());
|
||||
item.setContentType("фото");
|
||||
doGenerateImage(item, businessContext, brandName, clientLogoBytes);
|
||||
}
|
||||
@@ -277,14 +317,13 @@ public class MarketingStrategyV3Service {
|
||||
if (delayBetweenRequestsMs > 0) Thread.sleep(delayBetweenRequestsMs);
|
||||
|
||||
} catch (Exception e) {
|
||||
log.error("Критическая ошибка создания медиа для поста '{}': {}", item.getTheme(), e.getMessage());
|
||||
log.error("Error creating media for post '{}': {}", item.getTheme(), e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void doGenerateImage(MarketingStrategy.PostCalendarItem item, String businessContext, String brandName, byte[] clientLogoBytes) {
|
||||
String imagePrompt = buildImagePrompt(item, businessContext, brandName);
|
||||
log.info("Генерация ФОТО: {}", imagePrompt);
|
||||
try {
|
||||
byte[] imageBytes = imageGenerationService.generateImageWithReference(imagePrompt, clientLogoBytes);
|
||||
if (imageBytes != null && imageBytes.length > 0) {
|
||||
@@ -292,11 +331,9 @@ public class MarketingStrategyV3Service {
|
||||
minIOService.uploadFile(filename, imageBytes, MediaType.IMAGE_PNG_VALUE);
|
||||
item.setImageUrl(filename);
|
||||
item.setImageFilename(filename);
|
||||
} else {
|
||||
log.warn("NanoBanana вернул пустой массив байтов для темы: {}", item.getTheme());
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("Генерация фото упала с ошибкой: {}", e.getMessage());
|
||||
log.error("Image generation failed: {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user