From 4ff5c5ec1327a466b62e96901d2eb9c194004438 Mon Sep 17 00:00:00 2001 From: vladp Date: Fri, 20 Mar 2026 15:26:20 +0700 Subject: [PATCH] dev add violation notion --- .../search/SearchProperties.java | 26 ++++ .../controller/SearchSettingsController.java | 58 ++++++++ .../dto/search/config/SearchSettingsDto.java | 11 ++ .../handler/ImageFoundRequestHandler.java | 102 ++++++++------ .../service/file/FileCleanupService.java | 15 --- .../monitoring/MonitoringSearchService.java | 93 +++++++++---- .../search/GlobalSearchAsyncProcessor.java | 125 +++++++++++------- .../service/search/SearchImageService.java | 58 ++++---- src/main/resources/application.yaml | 11 ++ 9 files changed, 348 insertions(+), 151 deletions(-) create mode 100644 src/main/java/ru/soune/nocopy/configuration/search/SearchProperties.java create mode 100644 src/main/java/ru/soune/nocopy/controller/SearchSettingsController.java create mode 100644 src/main/java/ru/soune/nocopy/dto/search/config/SearchSettingsDto.java diff --git a/src/main/java/ru/soune/nocopy/configuration/search/SearchProperties.java b/src/main/java/ru/soune/nocopy/configuration/search/SearchProperties.java new file mode 100644 index 0000000..3ca91ff --- /dev/null +++ b/src/main/java/ru/soune/nocopy/configuration/search/SearchProperties.java @@ -0,0 +1,26 @@ +package ru.soune.nocopy.configuration.search; + +import lombok.Data; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.stereotype.Component; +import java.util.Map; + +@Data +@Component +@ConfigurationProperties(prefix = "search") +public class SearchProperties { + private Map engines; + private ProxyConfig proxy; + + @Data + public static class EngineConfig { + private boolean enabled; + } + + @Data + public static class ProxyConfig { + private boolean enabled; + private String host; + private int port; + } +} diff --git a/src/main/java/ru/soune/nocopy/controller/SearchSettingsController.java b/src/main/java/ru/soune/nocopy/controller/SearchSettingsController.java new file mode 100644 index 0000000..d18596a --- /dev/null +++ b/src/main/java/ru/soune/nocopy/controller/SearchSettingsController.java @@ -0,0 +1,58 @@ +package ru.soune.nocopy.controller; + +import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; +import org.springframework.http.ResponseEntity; +import org.springframework.web.bind.annotation.*; +import ru.soune.nocopy.configuration.search.SearchProperties; +import ru.soune.nocopy.dto.BaseResponse; +import ru.soune.nocopy.dto.search.config.SearchSettingsDto; + +import java.util.Map; + + +@Slf4j +@RestController +@RequestMapping("/api/search/settings") +@RequiredArgsConstructor +public class SearchSettingsController { + + private final SearchProperties searchProperties; + + @GetMapping + public ResponseEntity getSettings() { + SearchSettingsDto dto = new SearchSettingsDto(); + + dto.setEngines(Map.of( + "yandex", searchProperties.getEngines().get("yandex").isEnabled(), + "google", searchProperties.getEngines().get("google").isEnabled())); + + dto.setProxyEnabled(searchProperties.getProxy().isEnabled()); + + return ResponseEntity.ok().body(BaseResponse.builder() + .messageDesc("Success") + .messageBody(dto) + .build()); + } + + @PutMapping + public ResponseEntity updateSettings(@RequestBody SearchSettingsDto settings) { + if (settings.getEngines() != null) { + settings.getEngines().forEach((key, value) -> { + if (searchProperties.getEngines().containsKey(key)) { + searchProperties.getEngines().get(key).setEnabled(value); + } + }); + } + + if (settings.getProxyEnabled() != null) { + searchProperties.getProxy().setEnabled(settings.getProxyEnabled()); + } + + log.info("Settings updated: {}", settings); + + return ResponseEntity.ok().body(BaseResponse.builder() + .messageDesc("Settings updated") + .build()); + } +} diff --git a/src/main/java/ru/soune/nocopy/dto/search/config/SearchSettingsDto.java b/src/main/java/ru/soune/nocopy/dto/search/config/SearchSettingsDto.java new file mode 100644 index 0000000..ffacfa0 --- /dev/null +++ b/src/main/java/ru/soune/nocopy/dto/search/config/SearchSettingsDto.java @@ -0,0 +1,11 @@ +package ru.soune.nocopy.dto.search.config; + + +import lombok.Data; +import java.util.Map; + +@Data +public class SearchSettingsDto { + private Map engines; + private Boolean proxyEnabled; +} diff --git a/src/main/java/ru/soune/nocopy/handler/ImageFoundRequestHandler.java b/src/main/java/ru/soune/nocopy/handler/ImageFoundRequestHandler.java index 2f42428..51bb0fa 100644 --- a/src/main/java/ru/soune/nocopy/handler/ImageFoundRequestHandler.java +++ b/src/main/java/ru/soune/nocopy/handler/ImageFoundRequestHandler.java @@ -4,6 +4,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Component; +import ru.soune.nocopy.configuration.search.SearchProperties; import ru.soune.nocopy.dto.BaseRequest; import ru.soune.nocopy.dto.BaseResponse; import ru.soune.nocopy.dto.MessageCode; @@ -36,6 +37,8 @@ public class ImageFoundRequestHandler implements RequestHandler { private final TariffInfoService tariffInfoService; + private final SearchProperties searchProperties; + @Override public BaseResponse handle(BaseRequest request) throws Exception { ImageSearchRequest imageSearchRequest = objectMapper.convertValue(request.getMessageBody(), @@ -47,47 +50,72 @@ public class ImageFoundRequestHandler implements RequestHandler { .orElseThrow(() -> { throw new NotValidFieldException("File not found", new BaseResponse(20007, MessageCode.FILE_NOT_FOUND.getCode(), MessageCode.FILE_NOT_FOUND.getDescription(), - Map.of("fileId",fileId))); - }); + Map.of("fileId", fileId)));}); - String searchResponseYandex; -// String searchResponseGoogle; - List allYandexImages = new ArrayList<>(); -// List allGoogleImages = new ArrayList<>(); - List allUniqueImages; + List allYandexImages = new ArrayList<>(); + List allGoogleImages = new ArrayList<>(); boolean hasTimeout = false; -// -// try { -// searchResponseGoogle = searchImageService.searchReverseByPublicUrl(fileEntity, "google_lens", -// "exact_matches"); -// log.info("searchResponseGoogle OK,{}", searchResponseGoogle); -// allGoogleImages = searchImageService.getAllImagesWithoutPagination( -// searchResponseGoogle, "exact_matches"); -// -// } catch (TimeoutException e) { -// log.warn("Google search timeout for file {}", fileId); -// hasTimeout = true; -// } catch (IOException e) { -// log.error("Google search failed for file {}", fileId, e); -// } - try { - searchResponseYandex = searchImageService.searchReverseByPublicUrl(fileEntity, "yandex_reverse_image", - "visual_matches"); - log.info("searchResponseYandex OK"); - allYandexImages = searchImageService.getAllImagesWithoutPagination( - searchResponseYandex, "visual_matches"); - } catch (TimeoutException e) { - log.warn("Yandex search timeout for file {}", fileId); - hasTimeout = true; - } catch (IOException e) { - log.error("Yandex search failed for file {}", fileId, e); - } + boolean useGoogle = searchProperties.getEngines().getOrDefault("google", + new SearchProperties.EngineConfig()).isEnabled(); + boolean useYandex = searchProperties.getEngines().getOrDefault("yandex", + new SearchProperties.EngineConfig()).isEnabled(); -// allUniqueImages = searchImageService.removeDuplicateUrls(allYandexImages, allGoogleImages); -// allUniqueImages = allGoogleImages; - allUniqueImages = allYandexImages; - log.info("allUniqueImages OK: {} images", allUniqueImages.size()); + log.info("Search settings: useGoogle={}, useYandex={}", useGoogle, useYandex); + + if (useGoogle) { + try { + String searchResponseGoogle = searchImageService.searchReverseByPublicUrl(fileEntity, "google_lens", + "exact_matches"); + log.info("searchResponseGoogle OK"); + allGoogleImages = searchImageService.getAllImagesWithoutPagination( + searchResponseGoogle, "exact_matches"); + } catch (TimeoutException e) { + log.warn("Google search timeout for file {}", fileId); + hasTimeout = true; + } catch (IOException e) { + log.error("Google search failed for file {}", fileId, e); + } + } else { + log.info("Google search is disabled by settings"); + } + + if (useYandex) { + try { + String searchResponseYandex = searchImageService.searchReverseByPublicUrl(fileEntity, "yandex_reverse_image", + "visual_matches"); + log.info("searchResponseYandex OK"); + allYandexImages = searchImageService.getAllImagesWithoutPagination( + searchResponseYandex, "visual_matches"); + } catch (TimeoutException e) { + log.warn("Yandex search timeout for file {}", fileId); + hasTimeout = true; + } catch (IOException e) { + log.error("Yandex search failed for file {}", fileId, e); + } + } else { + log.info("Yandex search is disabled by settings"); + } + + if (allYandexImages.isEmpty() && allGoogleImages.isEmpty()) { + log.warn("No results from any search engine"); + String errorMessage = useGoogle || useYandex ? "No results found" : "All search engines are disabled"; + + return new BaseResponse(request.getMsgId(), MessageCode.SUCCESS.getCode(), + errorMessage, new YandexSearchResponse()); + } + + List allUniqueImages; + if (useGoogle && useYandex) { + allUniqueImages = searchImageService.removeDuplicateUrls(allYandexImages, allGoogleImages); + log.info("Merged results from both engines: {} unique images", allUniqueImages.size()); + } else if (useGoogle) { + allUniqueImages = allGoogleImages; + log.info("Results only from Google: {} images", allUniqueImages.size()); + } else { + allUniqueImages = allYandexImages; + log.info("Results only from Yandex: {} images", allUniqueImages.size()); + } tariffInfoService.writeOffTokens(fileEntity.getUserId(), TariffConstants.TOKEN_VALUE_FOR_SEARCH); checkCounterService.incrementCheckCount(fileEntity.getUserId(), fileEntity.getMimeType()); diff --git a/src/main/java/ru/soune/nocopy/service/file/FileCleanupService.java b/src/main/java/ru/soune/nocopy/service/file/FileCleanupService.java index 18bf37c..7d90acb 100644 --- a/src/main/java/ru/soune/nocopy/service/file/FileCleanupService.java +++ b/src/main/java/ru/soune/nocopy/service/file/FileCleanupService.java @@ -34,8 +34,6 @@ public class FileCleanupService { public void cleanupExpiredFiles() { log.info("Starting cleanup of expired temporary files"); -// cleanupOldPeriods(); - Path tempDir = Paths.get(basePath, "temp"); if (!Files.exists(tempDir)) { return; @@ -85,17 +83,4 @@ public class FileCleanupService { log.error("Error during cleanup", e); } } - - private void cleanupOldPeriods() { - LocalDate thirtyDaysAgo = LocalDate.now().minusDays(30); - - List checks = protectedFileCheckRepository.findByPeriodStartDateBefore(thirtyDaysAgo); - - for (ProtectedFileCheck check : checks) { - check.cleanupOldData(); - } - - protectedFileCheckRepository.saveAll(checks); - log.info("Cleaned up {} old protection usage records", checks.size()); - } } diff --git a/src/main/java/ru/soune/nocopy/service/monitoring/MonitoringSearchService.java b/src/main/java/ru/soune/nocopy/service/monitoring/MonitoringSearchService.java index 0b11018..93f43f3 100644 --- a/src/main/java/ru/soune/nocopy/service/monitoring/MonitoringSearchService.java +++ b/src/main/java/ru/soune/nocopy/service/monitoring/MonitoringSearchService.java @@ -5,11 +5,11 @@ import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; +import ru.soune.nocopy.configuration.search.SearchProperties; import ru.soune.nocopy.dto.file.YandexSearchResponse; import ru.soune.nocopy.dto.tarriff.TariffDTO; import ru.soune.nocopy.entity.monitoring.FileMonitoringEntity; import ru.soune.nocopy.entity.monitoring.MonitoringType; -import ru.soune.nocopy.entity.search.GlobalSearchResult; import ru.soune.nocopy.entity.tarif.TariffInfo; import ru.soune.nocopy.entity.tarif.TariffType; import ru.soune.nocopy.entity.user.User; @@ -24,6 +24,7 @@ import ru.soune.nocopy.service.violation.ViolationService; import java.io.IOException; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import java.util.concurrent.TimeoutException; @@ -45,6 +46,8 @@ public class MonitoringSearchService { private final ViolationService violationService; + private final SearchProperties searchProperties; + @Transactional public void processFileSearch(FileMonitoringEntity monitoring) throws MessagingException, IOException { monitoring.setLastRun(LocalDateTime.now()); @@ -53,36 +56,78 @@ public class MonitoringSearchService { MonitoringType monitoringType = monitoring.getMonitoringType(); TariffDTO tariffMonitoring = tariffService.getTariffByType(TariffType.valueOf(monitoringType.name())); + try { tariffInfoService.writeOffTokens(monitoring.getUserId(), tariffMonitoring.getTokens()); - String yandexResponse = searchImageService.searchReverseByPublicUrl( - monitoring.getFile(), "yandex_reverse_image", "visual_matches"); + boolean useYandex = searchProperties.getEngines().getOrDefault("yandex", + new SearchProperties.EngineConfig()).isEnabled(); + boolean useGoogle = searchProperties.getEngines().getOrDefault("google", + new SearchProperties.EngineConfig()).isEnabled(); - List yandexImages = - searchImageService.getAllImagesWithoutPagination(yandexResponse, "visual_matches"); + log.info("Monitoring search settings: useYandex={}, useGoogle={}", useYandex, useGoogle); - for (YandexSearchResponse.ImageResult imageResult : yandexImages) { + List allResults = new ArrayList<>(); + + if (useYandex) { + try { + String yandexResponse = searchImageService.searchReverseByPublicUrl( + monitoring.getFile(), "yandex_reverse_image", "visual_matches"); + + List yandexImages = + searchImageService.getAllImagesWithoutPagination(yandexResponse, "visual_matches"); + + allResults.addAll(yandexImages); + log.info("Yandex search found {} results", yandexImages.size()); + + } catch (TimeoutException e) { + log.warn("Yandex search timeout for monitoring file {}", monitoring.getFile().getId()); + } catch (IOException e) { + log.error("Yandex search failed for monitoring file {}", monitoring.getFile().getId(), e); + } + } else { + log.info("Yandex search is disabled by settings"); + } + + if (useGoogle) { + try { + String googleResponse = searchImageService.searchReverseByPublicUrl( + monitoring.getFile(), "google_lens", "exact_matches"); + + List googleImages = + searchImageService.getAllImagesWithoutPagination(googleResponse, "exact_matches"); + + allResults.addAll(googleImages); + log.info("Google search found {} results", googleImages.size()); + + } catch (TimeoutException e) { + log.warn("Google search timeout for monitoring file {}", monitoring.getFile().getId()); + } catch (IOException e) { + log.error("Google search failed for monitoring file {}", monitoring.getFile().getId(), e); + } + } else { + log.info("Google search is disabled by settings"); + } + + List uniqueResults = allResults; + if (useYandex && useGoogle) { + uniqueResults = searchImageService.removeDuplicateUrls( + useYandex ? allResults : new ArrayList<>(), + useGoogle ? allResults : new ArrayList<>() + ); + log.info("After deduplication: {} unique results", uniqueResults.size()); + } + + for (YandexSearchResponse.ImageResult imageResult : uniqueResults) { violationService.processViolation(imageResult, monitoring.getFile(), null); } -// try { -// String googleResponse = searchImageService.searchReverseByPublicUrl( -// monitoring.getFile(), "google_lens", "exact_matches"); -// -// List googleImages = -// searchImageService.getAllImagesWithoutPagination(googleResponse, "exact_matches"); -// -// -// for (YandexSearchResponse.ImageResult imageResult : googleImages) { -// violationService.processViolation(imageResult, monitoring.getFile(), null); -// } -// -// } catch (TimeoutException | IOException e) { -// log.warn("Google search failed"); -// } - monitoring.setLastRunStatus("SUCCESS"); + + if (uniqueResults.isEmpty()) { + log.info("No results found for monitoring file {}", monitoring.getFile().getId()); + } + } catch (TariffNotFoundException e) { User user = userRepository.findById(monitoring.getUserId()).orElseThrow(); TariffInfo activeTariffInfo = user.getActiveTariffInfo(); @@ -91,10 +136,12 @@ public class MonitoringSearchService { emailService.sendTokensNotFoundEmail(user, currentTokens, tariffMonitoring.getTokens()); monitoring.setLastRunStatus("ERROR: " + e.getMessage()); updateNextRun(monitoring); - monitoringRepository.save(monitoring); + } catch (Exception e) { + log.error("Error processing monitoring search", e); monitoring.setLastRunStatus("ERROR: " + e.getMessage()); + } finally { updateNextRun(monitoring); monitoringRepository.save(monitoring); diff --git a/src/main/java/ru/soune/nocopy/service/search/GlobalSearchAsyncProcessor.java b/src/main/java/ru/soune/nocopy/service/search/GlobalSearchAsyncProcessor.java index 9f202c4..19b1644 100644 --- a/src/main/java/ru/soune/nocopy/service/search/GlobalSearchAsyncProcessor.java +++ b/src/main/java/ru/soune/nocopy/service/search/GlobalSearchAsyncProcessor.java @@ -1,21 +1,18 @@ package ru.soune.nocopy.service.search; -import com.fasterxml.jackson.databind.ObjectMapper; -import com.vrt.fileprotection.image.ImageCheckResult; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Component; import org.springframework.transaction.annotation.Transactional; +import ru.soune.nocopy.configuration.search.SearchProperties; import ru.soune.nocopy.dto.file.YandexSearchResponse; 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.entity.violation.Violation; import ru.soune.nocopy.repository.GlobalSearchResultRepository; import ru.soune.nocopy.repository.GlobalSearchTaskRepository; -import ru.soune.nocopy.repository.ViolationRepository; import ru.soune.nocopy.service.tariff.TariffConstants; import ru.soune.nocopy.service.tariff.TariffInfoService; import ru.soune.nocopy.service.violation.ViolationService; @@ -36,16 +33,14 @@ public class GlobalSearchAsyncProcessor { private final SearchImageService searchImageService; - private final ObjectMapper objectMapper; - private final TariffInfoService tariffInfoService; private final GlobalSearchTaskRepository globalSearchTaskRepository; - private final ViolationRepository violationRepository; - private final ViolationService violationService; + private final SearchProperties searchProperties; + @Async @Transactional public void processFilesAsync(String taskId, List filesToProcess, Long userId) { @@ -85,52 +80,85 @@ public class GlobalSearchAsyncProcessor { result = globalSearchResultRepository.save(result); -// List googleImages = new ArrayList<>(); + boolean useGoogle = searchProperties.getEngines().getOrDefault("google", + new SearchProperties.EngineConfig()).isEnabled(); + boolean useYandex = searchProperties.getEngines().getOrDefault("yandex", + new SearchProperties.EngineConfig()).isEnabled(); + + log.info("Global search settings for file {}: useGoogle={}, useYandex={}", + file.getId(), useGoogle, useYandex); + + List googleImages = new ArrayList<>(); List yandexImages = new ArrayList<>(); - List allUniqueImages = new ArrayList<>(); + List allResults = new ArrayList<>(); boolean hasTimeout = false; -// try { -// String searchResponseGoogle = searchImageService.searchReverseByPublicUrl( -// file, "google_lens", "exact_matches"); -// -// googleImages = searchImageService.getAllImagesWithoutPagination(searchResponseGoogle, -// "exact_matches"); -// -// allUniqueImages.addAll(googleImages); -// log.info("Google search OK for file {}", file.getId()); -// -// } catch (TimeoutException e) { -// log.warn("Google search timeout for file {}", file.getId()); -// hasTimeout = true; -// } catch (IOException e) { -// log.error("Google search failed for file {}", file.getId(), e); -// } + if (useGoogle) { + try { + String searchResponseGoogle = searchImageService.searchReverseByPublicUrl( + file, "google_lens", "exact_matches"); - try { - String searchResponseYandex = searchImageService.searchReverseByPublicUrl( - file, "yandex_reverse_image", "visual_matches"); + googleImages = searchImageService.getAllImagesWithoutPagination(searchResponseGoogle, + "exact_matches"); - yandexImages = - searchImageService.getAllImagesWithoutPagination(searchResponseYandex, "visual_matches"); + allResults.addAll(googleImages); + log.info("Google search OK for file {}, found {} results", file.getId(), googleImages.size()); - allUniqueImages.addAll(yandexImages); - log.info("Yandex search OK for file {}", file.getId()); - - } catch (TimeoutException e) { - log.warn("Yandex search timeout for file {}", file.getId()); - hasTimeout = true; - } catch (IOException e) { - log.error("Yandex search failed for file {}", file.getId(), e); + } catch (TimeoutException e) { + log.warn("Google search timeout for file {}", file.getId()); + hasTimeout = true; + } catch (IOException e) { + log.error("Google search failed for file {}", file.getId(), e); + } + } else { + log.info("Google search is disabled by settings for file {}", file.getId()); } -// allUniqueImages = searchImageService.removeDuplicateUrls( -// allUniqueImages.stream() -// .filter(img -> img.getUrl() != null) -// .collect(Collectors.toList()), -// new ArrayList<>()); + if (useYandex) { + try { + String searchResponseYandex = searchImageService.searchReverseByPublicUrl( + file, "yandex_reverse_image", "visual_matches"); - allUniqueImages = yandexImages; + yandexImages = searchImageService.getAllImagesWithoutPagination(searchResponseYandex, "visual_matches"); + + allResults.addAll(yandexImages); + log.info("Yandex search OK for file {}, found {} results", file.getId(), yandexImages.size()); + + } catch (TimeoutException e) { + log.warn("Yandex search timeout for file {}", file.getId()); + hasTimeout = true; + } catch (IOException e) { + log.error("Yandex search failed for file {}", file.getId(), e); + } + } else { + log.info("Yandex search is disabled by settings for file {}", file.getId()); + } + + List allUniqueImages; + if (useGoogle && useYandex) { + allUniqueImages = searchImageService.removeDuplicateUrls( + yandexImages.stream() + .filter(img -> img.getUrl() != null) + .collect(Collectors.toList()), + googleImages.stream() + .filter(img -> img.getUrl() != null) + .collect(Collectors.toList()) + ); + log.info("Merged results from both engines: {} unique images", allUniqueImages.size()); + } else if (useGoogle) { + allUniqueImages = googleImages.stream() + .filter(img -> img.getUrl() != null) + .collect(Collectors.toList()); + log.info("Results only from Google: {} images", allUniqueImages.size()); + } else if (useYandex) { + allUniqueImages = yandexImages.stream() + .filter(img -> img.getUrl() != null) + .collect(Collectors.toList()); + log.info("Results only from Yandex: {} images", allUniqueImages.size()); + } else { + allUniqueImages = new ArrayList<>(); + log.warn("All search engines are disabled for file {}", file.getId()); + } for (YandexSearchResponse.ImageResult imageResult : allUniqueImages) { violationService.processViolation(imageResult, file, result); @@ -138,10 +166,15 @@ public class GlobalSearchAsyncProcessor { if (allUniqueImages.isEmpty() && hasTimeout) { result.setFileStatus(SearchStatus.TIMEOUT.name()); + } else if (allUniqueImages.isEmpty() && (!useGoogle && !useYandex)) { + result.setFileStatus(SearchStatus.FAILED.name()); + log.warn("No results for file {} because all engines are disabled", file.getId()); } else { result.setFileStatus(SearchStatus.SUCCESS.name()); - tariffInfoService.writeOffTokens(userId, TariffConstants.TOKEN_VALUE_FOR_SEARCH); + if (!allUniqueImages.isEmpty()) { + tariffInfoService.writeOffTokens(userId, TariffConstants.TOKEN_VALUE_FOR_SEARCH); + } } return result; diff --git a/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java b/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java index c9ad65f..2aa67dd 100644 --- a/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java +++ b/src/main/java/ru/soune/nocopy/service/search/SearchImageService.java @@ -8,6 +8,7 @@ import lombok.extern.slf4j.Slf4j; import okhttp3.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; +import ru.soune.nocopy.configuration.search.SearchProperties; import ru.soune.nocopy.dto.BaseResponse; import ru.soune.nocopy.dto.MessageCode; import ru.soune.nocopy.dto.file.YandexSearchResponse; @@ -23,40 +24,15 @@ import java.util.concurrent.*; @Slf4j @Service + public class SearchImageService { private final ObjectMapper objectMapper; - private final OkHttpClient yandexHttpClient; - - private final OkHttpClient googleHttpClient; - - public SearchImageService() { - Proxy proxy = new Proxy(Proxy.Type.HTTP, - new InetSocketAddress("193.46.217.94", 3128)); - - this.yandexHttpClient = new OkHttpClient.Builder() - .proxy(proxy) - .connectTimeout(35, TimeUnit.SECONDS) - .writeTimeout(35, TimeUnit.SECONDS) - .readTimeout(35, TimeUnit.SECONDS) - .callTimeout(35, TimeUnit.SECONDS) - .followRedirects(true) - .followSslRedirects(true) - .retryOnConnectionFailure(true) - .build(); - - this.googleHttpClient = new OkHttpClient.Builder() -// .proxy(proxy) - .connectTimeout(35, TimeUnit.SECONDS) - .writeTimeout(35, TimeUnit.SECONDS) - .readTimeout(35, TimeUnit.SECONDS) - .callTimeout(35, TimeUnit.SECONDS) - .followRedirects(true) - .followSslRedirects(true) - .retryOnConnectionFailure(true) - .build(); + private final SearchProperties searchProperties; + public SearchImageService(SearchProperties searchProperties) { + this.searchProperties = searchProperties; this.objectMapper = new ObjectMapper(); } @@ -113,12 +89,34 @@ public class SearchImageService { return mimeType != null && mimeType.startsWith("image"); } + private OkHttpClient createHttpClient(boolean useProxy) { + OkHttpClient.Builder builder = new OkHttpClient.Builder() + .connectTimeout(35, TimeUnit.SECONDS) + .writeTimeout(35, TimeUnit.SECONDS) + .readTimeout(35, TimeUnit.SECONDS) + .callTimeout(35, TimeUnit.SECONDS) + .followRedirects(true) + .followSslRedirects(true) + .retryOnConnectionFailure(true); + + if (useProxy && searchProperties.getProxy().isEnabled()) { + Proxy proxy = new Proxy(Proxy.Type.HTTP, + new InetSocketAddress(searchProperties.getProxy().getHost(), + searchProperties.getProxy().getPort())); + builder.proxy(proxy); + } + + return builder.build(); + } + private String callReverseImageApiByUrl(String imageUrl, String engine, String searchType) throws IOException { if (searchApiKey == null || searchApiKey.isBlank()) { throw new IllegalStateException("SearchAPI key not configured"); } - OkHttpClient client = engine.contains("yandex_reverse_image") ? yandexHttpClient : googleHttpClient; + boolean useProxy = searchProperties.getProxy().isEnabled(); + + OkHttpClient client = createHttpClient(useProxy); HttpUrl url = HttpUrl.parse("https://www.searchapi.io/api/v1/search") .newBuilder() diff --git a/src/main/resources/application.yaml b/src/main/resources/application.yaml index a0d6d5a..43f3b9a 100644 --- a/src/main/resources/application.yaml +++ b/src/main/resources/application.yaml @@ -107,6 +107,17 @@ searchapi: api-key: ${SEARCHAPI_API_KEY:5jyYZC8jSaxhZTwjMUhwtAXi} reverse-image-url: "https://searchapi.io/api/v1/search" +search: + engines: + yandex: + enabled: true + google: + enabled: false + proxy: + enabled: true + host: "193.46.217.94" + port: 3128 + yookassa: secret-key: test_0Yns_0NHV5GJf6ypJ5HC4NSfnLO8SJkw-1PwrVWsDl4 shop-id: 1276731