141 lines
5.5 KiB
Java
141 lines
5.5 KiB
Java
package ru.soune.nocopy.controller;
|
|||
|
|
|
||
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||
|
|
import lombok.RequiredArgsConstructor;
|
||
|
|
import lombok.extern.slf4j.Slf4j;
|
||
|
|
import org.springframework.http.ResponseEntity;
|
||
|
|
import org.springframework.web.bind.annotation.*;
|
||
|
|
import ru.soune.nocopy.dto.file.YandexSearchResponse;
|
||
|
|
import ru.soune.nocopy.dto.search.GlobalSearchFileResult;
|
||
|
|
import ru.soune.nocopy.dto.search.GlobalSearchStartRequest;
|
||
|
|
import ru.soune.nocopy.dto.search.GlobalSearchStartResponse;
|
||
|
|
import ru.soune.nocopy.dto.search.GlobalSearchStatusResponse;
|
||
|
|
import ru.soune.nocopy.entity.file.FileEntity;
|
||
|
|
import ru.soune.nocopy.entity.search.GlobalSearchResult;
|
||
|
|
import ru.soune.nocopy.entity.search.GlobalSearchTask;
|
||
|
|
import ru.soune.nocopy.entity.search.SearchStatus;
|
||
|
|
import ru.soune.nocopy.repository.GlobalSearchResultRepository;
|
||
|
|
import ru.soune.nocopy.repository.GlobalSearchTaskRepository;
|
||
|
|
import ru.soune.nocopy.service.register.AuthService;
|
||
|
|
import ru.soune.nocopy.service.search.GlobalSearchService;
|
||
|
|
|
||
|
|
import java.util.*;
|
||
|
|
import java.util.stream.Collectors;
|
||
|
|
|
||
|
|
@Slf4j
|
||
|
|
@RestController
|
||
|
|
@RequestMapping("/api/v1/global-search")
|
||
|
|
@RequiredArgsConstructor
|
||
|
|
public class GlobalSearchController {
|
||
|
|
|
||
|
|
private final AuthService authService;
|
||
|
|
|
||
|
|
private final GlobalSearchService globalSearchService;
|
||
|
|
|
||
|
|
private final GlobalSearchTaskRepository globalSearchTaskRepository;
|
||
|
|
|
||
|
|
private final GlobalSearchTaskRepository searchTaskRepository;
|
||
|
|
|
||
|
|
private final GlobalSearchResultRepository globalSearchResultRepository;
|
||
|
|
|
||
|
|
private final ObjectMapper objectMapper;
|
||
|
|
|
||
|
|
@PostMapping("/start")
|
||
|
|
public ResponseEntity<?> startSearch(
|
||
|
|
@RequestBody GlobalSearchStartRequest request,
|
||
|
|
@RequestHeader(value = "Authorization", required = false) String tokenHeader) {
|
||
|
|
|
||
|
|
if (tokenHeader == null || tokenHeader.isBlank()) {
|
||
|
|
Map<String, Object> errorData = new HashMap<>();
|
||
|
|
errorData.put("token", tokenHeader);
|
||
|
|
|
||
|
|
return ResponseEntity.ok().body(Map.of("error", errorData));
|
||
|
|
}
|
||
|
|
|
||
|
|
Long userId = authService.useUserAuthToken(tokenHeader);
|
||
|
|
|
||
|
|
List<FileEntity> filesToProcess = globalSearchService.getFilesToProcess(request, userId);
|
||
|
|
|
||
|
|
if (filesToProcess.isEmpty()) return ResponseEntity.ok().body("Files for search not found");
|
||
|
|
|
||
|
|
String taskId = globalSearchService.startSearch(request, userId, filesToProcess);
|
||
|
|
|
||
|
|
Optional<GlobalSearchTask> taskOptional = globalSearchTaskRepository.findById(taskId);
|
||
|
|
|
||
|
|
if (taskOptional.isEmpty()) return ResponseEntity.ok().body("Task not found");
|
||
|
|
|
||
|
|
GlobalSearchTask task = taskOptional.orElseThrow();
|
||
|
|
GlobalSearchStartResponse response = new GlobalSearchStartResponse();
|
||
|
|
response.setTaskId(taskId);
|
||
|
|
response.setStatus(SearchStatus.ACCEPTED.name());
|
||
|
|
response.setTotalFiles(task.getTotalFiles());
|
||
|
|
|
||
|
|
return ResponseEntity.ok(response);
|
||
|
|
}
|
||
|
|
|
||
|
|
@GetMapping("/status/{taskId}")
|
||
|
|
public ResponseEntity<?> getStatus(
|
||
|
|
@PathVariable String taskId,
|
||
|
|
@RequestHeader(value = "Authorization", required = false) String tokenHeader) {
|
||
|
|
|
||
|
|
if (tokenHeader == null || tokenHeader.isBlank()) {
|
||
|
|
Map<String, Object> errorData = new HashMap<>();
|
||
|
|
errorData.put("token", tokenHeader);
|
||
|
|
|
||
|
|
return ResponseEntity.ok().body(Map.of("error", errorData));
|
||
|
|
}
|
||
|
|
|
||
|
|
Long userId = authService.useUserAuthToken(tokenHeader);
|
||
|
|
|
||
|
|
Optional<GlobalSearchTask> taskOptional = searchTaskRepository.findByTaskIdAndUserId(taskId, userId);
|
||
|
|
|
||
|
|
if (taskOptional.isEmpty()) return ResponseEntity.ok().body("Task not found");
|
||
|
|
|
||
|
|
GlobalSearchTask task = taskOptional.orElseThrow();
|
||
|
|
|
||
|
|
List<GlobalSearchResult> results = globalSearchResultRepository.findByTaskIdOrderByIdAsc(taskId);
|
||
|
|
|
||
|
|
List<GlobalSearchFileResult> fileResults = results.stream()
|
||
|
|
.map(result -> {
|
||
|
|
GlobalSearchFileResult dto = new GlobalSearchFileResult();
|
||
|
|
dto.setFileId(result.getFileId());
|
||
|
|
dto.setFileName(result.getFileName());
|
||
|
|
dto.setThumbnail(result.getThumbnail());
|
||
|
|
dto.setFileStatus(result.getFileStatus());
|
||
|
|
|
||
|
|
try {
|
||
|
|
YandexSearchResponse searchResponse = objectMapper.readValue(
|
||
|
|
result.getSearchResults(),
|
||
|
|
YandexSearchResponse.class
|
||
|
|
);
|
||
|
|
|
||
|
|
dto.setImages(searchResponse.getImages());
|
||
|
|
dto.setPage(searchResponse.getPage());
|
||
|
|
dto.setPageSize(searchResponse.getPageSize());
|
||
|
|
dto.setTotalResults(searchResponse.getTotalResults());
|
||
|
|
dto.setTotalPages(searchResponse.getTotalPages());
|
||
|
|
|
||
|
|
} catch (Exception e) {
|
||
|
|
log.error("Failed to parse search results for file: {}", result.getFileId(), e);
|
||
|
|
dto.setImages(new ArrayList<>());
|
||
|
|
dto.setTotalResults(0);
|
||
|
|
}
|
||
|
|
|
||
|
|
return dto;
|
||
|
|
})
|
||
|
|
.collect(Collectors.toList());
|
||
|
|
|
||
|
|
int progress = task.getTotalFiles() > 0
|
||
|
|
? task.getProcessedFiles() * 100 / task.getTotalFiles()
|
||
|
|
: 0;
|
||
|
|
|
||
|
|
GlobalSearchStatusResponse response = new GlobalSearchStatusResponse();
|
||
|
|
response.setTaskId(taskId);
|
||
|
|
response.setStatus(task.getStatus());
|
||
|
|
response.setProgress(progress);
|
||
|
|
response.setResults(fileResults);
|
||
|
|
|
||
|
|
return ResponseEntity.ok(response);
|
||
|
|
}
|
||
|
|
}
|