From a5cc52d08b49e6bfcb3ea27c8b709e3ea331860c Mon Sep 17 00:00:00 2001 From: EotT123 Date: Fri, 2 Jan 2026 23:20:03 +0100 Subject: [PATCH] fixes --- .../subtools/multisubdownloader/CLI.java | 4 +- .../UpdateAvailableGithub.java | 7 +- .../UserInteractionHandlerCLI.java | 2 +- .../actions/CleanAction.java | 2 +- .../actions/DownloadAction.java | 6 +- .../actions/MoveAndRenameAction.java | 16 +-- .../actions/UserInteractionHandlerAction.java | 6 +- .../cli/progress/CLISearchProgress.java | 2 +- .../gui/dialog/RenameDialog.java | 2 +- .../gui/dialog/SelectDialog.java | 2 +- .../progress/search/SearchProgressDialog.java | 2 +- .../gui/panels/SearchFileInputPanel.java | 5 +- .../gui/workers/RenameWorker.java | 3 +- .../subtitles/filters/SubtitleFilter.java | 2 +- .../lib/library/FilenameLibraryBuilder.java | 6 +- .../lib/library/PathLibraryBuilder.java | 4 +- .../subtitleproviders/SubtitleAdapter.java | 2 +- .../SubtitleProviderStore.java | 5 +- .../util/PropertiesReader.java | 3 +- .../subtitles/SubtitleFilteringTest.java | 2 +- .../sublibrary/cache/ProviderCacheDisk.java | 130 +++++++++--------- .../sublibrary/data/imdb/ImdbAdapter.java | 15 +- .../sublibrary/data/imdb/ImdbSearchIdApi.java | 28 ++-- .../subtools/sublibrary/model/Release.java | 4 +- SubLibrary/src/main/java/util/Utils.java | 7 +- .../sublibrary/assertions/ReleaseAssert.java | 4 +- 26 files changed, 146 insertions(+), 125 deletions(-) diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/CLI.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/CLI.java index da449785..f27ff8b2 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/CLI.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/CLI.java @@ -118,13 +118,13 @@ private void download(ReleaseWithPath release) { if (downloadAll) { selection = release.matchingSubs; if (!selection.isEmpty()) { - System.out.println("Downloading ALL found subtitles for release: ${release.fileNameOrName}"); + System.out.println("Downloading ALL found subtitles for release: ${release.folderNameOrName}"); } } else { selection = userInteractionHandlerAction.subtitleSelection(release, subtitleSelection, dryRun); } if (selection.isEmpty()) { - System.out.println("No subtitles found for: ${release.fileNameOrName}"); + System.out.println("No subtitles found for: ${release.folderNameOrName}"); } else { AtomicInteger counter = new AtomicInteger(1); IntStream.range(0, selection.size()).forEach(j -> { diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/UpdateAvailableGithub.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/UpdateAvailableGithub.java index 92ed3e0d..69e98029 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/UpdateAvailableGithub.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/UpdateAvailableGithub.java @@ -2,6 +2,7 @@ import static java.time.temporal.ChronoUnit.*; import static org.lodder.subtools.multisubdownloader.Messages.*; +import static util.Utils.*; import java.time.Instant; import java.time.LocalDate; @@ -89,7 +90,7 @@ private Optional getUrlLatestNewStableGithubRelease() { url:"$REPO_URL/releases", cacheType:CacheType.NONE, userAgent:null)) - .selectFirstByCss("#repo-content-turbo-frame .box a[href='$REPO_URI/releases/latest']"); + .selectFirstByCss("#repo-content-turbo-frame .box a[href='$REPO_URI/releases/latest']"); Pattern versionPattern = Pattern.compile("\\d*\\.\\d\\.\\d"); String versionText = element.parentElement().selectFirst("a").text(); Matcher matcher = versionPattern.matcher(versionText); @@ -152,8 +153,8 @@ private Optional getUrlLatestNewNightlyGithubRelease() { } private LocalDateTime getBuildTista() { - String timestamp = PropertiesReader.getProperty(PomProperty.BUILD_TIMESTAMP); - return zonedDateTimeStringToLocalDateTime(timestamp); + return ifNotNullOrElseGet(PropertiesReader.getProperty(PomProperty.BUILD_TIMESTAMP), + this::zonedDateTimeStringToLocalDateTime, LocalDateTime::now); } private String getVersion() { diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/UserInteractionHandlerCLI.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/UserInteractionHandlerCLI.java index 7fb8bc27..edc02364 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/UserInteractionHandlerCLI.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/UserInteractionHandlerCLI.java @@ -26,7 +26,7 @@ public UserInteractionHandlerCLI(UserInteractionSettingsIntf settings) { @Override public List selectSubtitles(Release release) { System.out.printf("\n%s : %s%n", getText("SelectDialog.SelectCorrectSubtitleThisRelease"), - release.fileNameOrName); + release.folderNameOrName); return PrompterExt.promptValuesFromList(prompter, getText("SelectDialog.EnterListSelectedSubtitles"), release.matchingSubs, diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/CleanAction.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/CleanAction.java index 4e39ae63..be9d878e 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/CleanAction.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/CleanAction.java @@ -31,7 +31,7 @@ public void cleanUpFiles(ReleaseWithPath release, Path destination, String video throw new IllegalArgumentException("Destination [%s] is not a folder".formatted(destination)); } - release.path.list() + release.path.parent.list() .filter(p -> (p.isDirectory() && p.fileNameContainsIgnoreCase(SAMPLE_DIR_NAME)) || (p.isRegularFile() && FILE_FILTERS.contains(p.getExtension()))) .forEachEx(p -> { diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/DownloadAction.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/DownloadAction.java index 938d9ab4..5959b2df 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/DownloadAction.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/DownloadAction.java @@ -89,7 +89,7 @@ private void download(ReleaseWithPath release, Subtitle subtitle, LibrarySetting } if (!librarySettings.hasLibraryAction(LibraryActionType.NOTHING)) { - Path oldLocationFile = release.path.resolve(ifNullThen(release.fileName, release.name)); + Path oldLocationFile = release.path.parent.resolve(ifNullThen(release.fileName, release.name)); if (oldLocationFile.exists()) { LOGGER.info("Moving/Renaming [{}] to folder [{}] this might take a while... ", videoFileName, path); oldLocationFile.moveToDir(path); @@ -97,8 +97,8 @@ private void download(ReleaseWithPath release, Subtitle subtitle, LibrarySetting CleanAction cleanAction = new CleanAction(librarySettings); cleanAction.cleanUpFiles(release, path, videoFileName); } - if (librarySettings.removeEmptyFolders && release.path.isEmptyDir()) { - release.path.deletePath(); + if (librarySettings.removeEmptyFolders && release.path.parent.isEmptyDir()) { + release.path.parent.deletePath(); } } } diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/MoveAndRenameAction.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/MoveAndRenameAction.java index dd6eaaff..ce9d42cd 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/MoveAndRenameAction.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/MoveAndRenameAction.java @@ -46,7 +46,7 @@ public void moveAndRename(Path f, ReleaseWithPath release) { Path newDir = switch (librarySettings.action) { case MOVE, MOVE_AND_RENAME -> PathLibraryBuilder.fromSettings(librarySettings, manager, userInteractionHandler).buildPath(release); - case RENAME, NOTHING -> release.path; + case RENAME, NOTHING -> release.path.parent; }; if (!newDir.exists()) { LOGGER.debug("Creating dir [{}]", newDir.toAbsolutePath()); @@ -59,7 +59,7 @@ public void moveAndRename(Path f, ReleaseWithPath release) { } LOGGER.trace("rename: newDir [{}]", newDir); - Path file = release.path.resolve(release.fileName); + Path file = release.path.parent.resolve(release.fileName); try { if (librarySettings.hasLibraryAction(LibraryActionType.MOVE) || @@ -68,15 +68,15 @@ public void moveAndRename(Path f, ReleaseWithPath release) { file.moveToDirAndRename(newDir, filename); } else { LOGGER.info("Moving [{}] to the library folder [{}] , this might take a while... ", filename, - release.path); - file.moveToDirAndRename(release.path, filename); + release.path.parent); + file.moveToDirAndRename(release.path.parent, filename); } if (!librarySettings.hasLibraryOtherFileAction(LibraryOtherFileActionType.NOTHING)) { new CleanAction(librarySettings).cleanUpFiles(release, newDir, filename); } - if (librarySettings.removeEmptyFolders && release.path.isEmptyDir()) { - Files.delete(release.path); + if (librarySettings.removeEmptyFolders && release.path.parent.isEmptyDir()) { + Files.delete(release.path.parent); } } catch (IOException e) { LOGGER.error("Unsuccessful in moving the file to the library", e); @@ -87,7 +87,7 @@ private String getNewFilename(Path f, Release release) { FilenameLibraryBuilder filenameLibraryBuilder = FilenameLibraryBuilder.fromSettings(librarySettings, manager, userInteractionHandler); String filename = filenameLibraryBuilder.buildPathStructure(release); - if (release.fileNameOrName.endsWith(".srt")) { + if (release.folderNameOrName.endsWith(".srt")) { Language language = null; if (librarySettings.includeLanguageCode) { language = DetectLanguage.execute(f); @@ -95,7 +95,7 @@ private String getNewFilename(Path f, Release release) { LOGGER.error("Unable to detect language, leaving language code blank"); } } - return filenameLibraryBuilder.buildSubtitle(release.fileNameOrName, filename, language, 0); + return filenameLibraryBuilder.buildSubtitle(release.folderNameOrName, filename, language, 0); } return filename; } diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/UserInteractionHandlerAction.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/UserInteractionHandlerAction.java index d4444958..e0674291 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/UserInteractionHandlerAction.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/actions/UserInteractionHandlerAction.java @@ -52,7 +52,7 @@ public List subtitleSelection(Release release, final boolean subtitleS } else { if (!subs.isEmpty()) { LOGGER.debug("determineWhatSubtitleDownload for videoFile: [{}] # found subs: [{}]", - release.fileNameOrName, subs.size()); + release.folderNameOrName, subs.size()); if (settings.optionsAlwaysConfirm) { return userInteractionHandler.selectSubtitles(release); } else if (subs.size() == 1 && subs.first.subtitleMatchType == SubtitleMatchType.EXACT) { @@ -78,14 +78,14 @@ public List subtitleSelection(Release release, final boolean subtitleS return userInteractionHandler.selectSubtitles(release); } else { LOGGER.info("Multiple subs detected for: [{}] Unhandleable for CMD! switch to GUI or use " + - "'--selection' as switch in de CMD", release.fileNameOrName); + "'--selection' as switch in de CMD", release.folderNameOrName); } } else { LOGGER.debug("determineWhatSubtitleDownload: only one sub taking it!!!!"); return List.of(subs.first); } } - LOGGER.debug("determineWhatSubtitleDownload: No subs found for [{}]", release.fileNameOrName); + LOGGER.debug("determineWhatSubtitleDownload: No subs found for [{}]", release.folderNameOrName); } return List.of(); } diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/cli/progress/CLISearchProgress.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/cli/progress/CLISearchProgress.java index 6cab3b7b..c8cb4750 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/cli/progress/CLISearchProgress.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/cli/progress/CLISearchProgress.java @@ -21,7 +21,7 @@ public CLISearchProgress() { @Override public void progress(SubtitleProvider provider, int jobsLeft, Release release) { - this.tableModel.update(provider.provider, jobsLeft, release.fileNameOrName); + this.tableModel.update(provider.provider, jobsLeft, release.folderNameOrName); this.printProgress(); } diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/RenameDialog.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/RenameDialog.java index 1fa65d22..cd645ca4 100755 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/RenameDialog.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/RenameDialog.java @@ -157,7 +157,7 @@ private void rename(Path dir) throws IOException { if (file.isRegularFile()) { if (!file.fileNameContainsIgnoreCase("sample") && extensions.contains(file.getExtension())) { releaseFactory.createRelease(file, userInteractionHandler).ifPresent(release -> { - publish(release.fileNameOrName); + publish(release.folderNameOrName); if (release.isOfType(videoType)) { moveAndRenameAction.moveAndRename(file, release); } diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/SelectDialog.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/SelectDialog.java index 75d8db54..f7cd6ddc 100755 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/SelectDialog.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/SelectDialog.java @@ -41,7 +41,7 @@ public SelectDialog(@Nullable JFrame frame=null, List subtitles, Relea contentPane .layout(new MigLayout("", "[1000px:n,grow,fill]", "[][::100px,fill][grow]")) .addComponent("cell 0 0", - new JLabel(getText("SelectDialog.SelectCorrectSubtitleThisRelease") + release.fileNameOrName)) + new JLabel(getText("SelectDialog.SelectCorrectSubtitleThisRelease") + release.folderNameOrName)) .addComponent("cell 0 1,grow", new JScrollPane().viewportView(customTable = createCustomTable())) .addComponent("cell 0 2,grow", new JPanel() .layout(new FlowLayout(FlowLayout.RIGHT)) diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/progress/search/SearchProgressDialog.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/progress/search/SearchProgressDialog.java index 00970b14..b98f105f 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/progress/search/SearchProgressDialog.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/dialog/progress/search/SearchProgressDialog.java @@ -63,7 +63,7 @@ public void windowClosing(WindowEvent e) { @Override public void progress(SubtitleProvider provider, int jobsLeft, Release release) { this.setVisible(); - this.tableModel.update(provider.subtitleProviderFrontEnd.name, jobsLeft, release.fileNameOrName); + this.tableModel.update(provider.subtitleProviderFrontEnd.name, jobsLeft, release.folderNameOrName); } @Override diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/panels/SearchFileInputPanel.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/panels/SearchFileInputPanel.java index e86bb223..c297d315 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/panels/SearchFileInputPanel.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/panels/SearchFileInputPanel.java @@ -52,9 +52,7 @@ public void setRecursiveSelected(boolean selected) { } public void addSelectFolderAction(ActionListener selectFolderAction) { - if (selectFolderAction != null) { - btnBrowse.addActionListener(selectFolderAction); - } + btnBrowse.addActionListener(selectFolderAction); } public void setIncomingPath(String path) { @@ -72,5 +70,4 @@ public boolean isRecursiveSelected() { public boolean isForceOverwrite() { return chkForceSubtitleOverwrite.isSelected(); } - } diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/workers/RenameWorker.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/workers/RenameWorker.java index 526b0af1..51a8fe61 100755 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/workers/RenameWorker.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/gui/workers/RenameWorker.java @@ -58,7 +58,8 @@ protected Void doInBackground() { case MovieReleaseWithPath _ -> new MoveAndRenameAction(settings.movieLibrarySettings, manager, userInteractionHandler); }; - moveAndRenameAction.moveAndRename(selectedShow.path.resolve(selectedShow.fileName), selectedShow); + moveAndRenameAction.moveAndRename(selectedShow.path.parent.resolve(selectedShow.fileName), + selectedShow); model.removeShow(selectedShow); } }); diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/control/subtitles/filters/SubtitleFilter.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/control/subtitles/filters/SubtitleFilter.java index 7385cbc7..972ba0a9 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/control/subtitles/filters/SubtitleFilter.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/control/subtitles/filters/SubtitleFilter.java @@ -16,7 +16,7 @@ public boolean excludeSubtitle(Release release, Subtitle subtitle) { } protected String getReleaseName(Release release) { - return StringUtils.substringBeforeLast(release.fileNameOrName, "."); + return StringUtils.substringBeforeLast(release.folderNameOrName, "."); } protected boolean checkKeywordSubtitleMatch(Subtitle subtitle, String keywordsFile) { diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/library/FilenameLibraryBuilder.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/library/FilenameLibraryBuilder.java index c9710d87..ffd6db78 100755 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/library/FilenameLibraryBuilder.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/library/FilenameLibraryBuilder.java @@ -80,7 +80,7 @@ public String buildPathStructure(Release release) { case MovieRelease movieRelease -> buildMovieFolderStructure(movieRelease); }; } - return release.fileNameOrName; + return release.folderNameOrName; } private String buildEpisodeFolderStructure(TvRelease tvRelease) { @@ -101,7 +101,7 @@ private String buildEpisodeFolderStructure(TvRelease tvRelease) { filename = replace(filename, SerieStructureTag.QUALITY, tvRelease.quality); filename = replace(filename, SerieStructureTag.RELEASE_GROUP, tvRelease.releaseGroup); - filename += "." + StringUtils.substringAfterLast(tvRelease.fileNameOrName, "."); + filename += "." + StringUtils.substringAfterLast(tvRelease.folderNameOrName, "."); filename = filename.removeIllegalWindowsChars(); if (replaceSpace) { filename = filename.replace(' ', replacingSpaceChar); @@ -117,7 +117,7 @@ private String buildMovieFolderStructure(MovieRelease movieRelease) { filename = replace(filename, MovieStructureTag.QUALITY, movieRelease.quality); filename = replace(filename, MovieStructureTag.RELEASE_GROUP, movieRelease.releaseGroup); - filename += "." + StringUtils.substringAfterLast(movieRelease.fileNameOrName, "."); + filename += "." + StringUtils.substringAfterLast(movieRelease.folderNameOrName, "."); filename = filename.removeIllegalWindowsChars(); if (replaceSpace) { diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/library/PathLibraryBuilder.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/library/PathLibraryBuilder.java index 47bf5ac4..7183055f 100755 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/library/PathLibraryBuilder.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/lib/library/PathLibraryBuilder.java @@ -63,7 +63,7 @@ public Path buildPath(ReleaseWithPath release) { }; return libraryFolder.resolve(pathStructure.split(FolderStructureTag.SEPARATOR.label)); } else { - return release.path; + return release.path.parent; } } @@ -75,7 +75,7 @@ public String buildPathStructure(Release release) { case MovieRelease movieRelease -> buildMovieFolderStructure(movieRelease); }; } else { - return release.fileNameOrName; + return release.folderNameOrName; } } diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/subtitleproviders/SubtitleAdapter.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/subtitleproviders/SubtitleAdapter.java index f5b3dd1c..5ee2550f 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/subtitleproviders/SubtitleAdapter.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/subtitleproviders/SubtitleAdapter.java @@ -94,7 +94,7 @@ public Set searchSubtitles(MovieRelease movieRelease, Language language) { } if (subtitles.isEmpty()) { if (movieRelease instanceof MovieReleaseWithPath release) { - Path file = release.path.resolve(release.fileName); + Path file = release.path.parent.resolve(release.fileName); if (file.exists()) { try { subtitles.addAll(searchMovieSubtitlesWithHash(FileHasher.computeHash(file), language)); diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/subtitleproviders/SubtitleProviderStore.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/subtitleproviders/SubtitleProviderStore.java index 2b83cb1b..17c9411f 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/subtitleproviders/SubtitleProviderStore.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/subtitleproviders/SubtitleProviderStore.java @@ -3,7 +3,6 @@ import java.util.HashSet; import java.util.Set; -import manifold.ext.props.rt.api.val; import org.jspecify.annotations.NullMarked; import org.lodder.subtools.sublibrary.model.Subtitle; @@ -11,7 +10,9 @@ public class SubtitleProviderStore { protected final Set> subtitleProviders = new HashSet<>(); - @val Set> allProviders = Set.copyOf(this.subtitleProviders); + public Set> getAllProviders() { + return Set.copyOf(this.subtitleProviders); + } public void addProvider(SubtitleProvider provider) { this.subtitleProviders.add(provider); diff --git a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/util/PropertiesReader.java b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/util/PropertiesReader.java index 3bc8d924..03851823 100644 --- a/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/util/PropertiesReader.java +++ b/MultiSubDownloader/src/main/java/org/lodder/subtools/multisubdownloader/util/PropertiesReader.java @@ -6,6 +6,7 @@ import manifold.ext.props.rt.api.val; import org.jspecify.annotations.NullMarked; +import org.jspecify.annotations.Nullable; @NullMarked public class PropertiesReader { @@ -31,7 +32,7 @@ private static PropertiesReader getPropertiesReader() { return propertiesReaderInstance; } - public static String getProperty(PomProperty property) { + public static @Nullable String getProperty(PomProperty property) { return PropertiesReader.getPropertiesReader().properties.getProperty(property.value); } diff --git a/MultiSubDownloader/src/test/java/org/lodder/subtools/multisubdownloader/lib/control/subtitles/SubtitleFilteringTest.java b/MultiSubDownloader/src/test/java/org/lodder/subtools/multisubdownloader/lib/control/subtitles/SubtitleFilteringTest.java index 1c000cb9..5ad06def 100644 --- a/MultiSubDownloader/src/test/java/org/lodder/subtools/multisubdownloader/lib/control/subtitles/SubtitleFilteringTest.java +++ b/MultiSubDownloader/src/test/java/org/lodder/subtools/multisubdownloader/lib/control/subtitles/SubtitleFilteringTest.java @@ -119,7 +119,7 @@ private Settings createSettings(boolean keyword, boolean exact, boolean excludeh private ReleaseWithoutPath createRelease(String filename, String releasegroup) { ReleaseWithoutPath release = mock(TvReleaseWithoutPath.class); - when(release.fileNameOrName).thenReturn(filename); + when(release.folderNameOrName).thenReturn(filename); when(release.releaseGroup).thenReturn(releasegroup); return release; diff --git a/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/cache/ProviderCacheDisk.java b/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/cache/ProviderCacheDisk.java index 1634f86b..6a81143e 100644 --- a/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/cache/ProviderCacheDisk.java +++ b/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/cache/ProviderCacheDisk.java @@ -44,79 +44,79 @@ public final class ProviderCacheDisk extends Provide private final Map> removedToAdd = new HashMap<>(); @val(Private) String tableName; private final LazySupplier connection = new LazySupplier<>(() -> { - try { - synchronized (this.cacheMap) { - Path path = Path.of(System.getProperty("user.home")).resolve(".MultiSubDownloader"); - if (!Files.exists(path)) { - try { - Files.createDirectory(path); - } catch (IOException e) { - throw new RuntimeException("Could not create folder $path", e); - } - } - Class.forName("org.hsqldb.jdbcDriver"); - Connection connection = DriverManager.getConnection( - "jdbc:hsqldb:file:$path/diskcache.hsqldb;hsqldb.write_delay=false;shutdown=true", - "user", "pass"); - - try (Statement stmt = connection.createStatement()) { - stmt.execute( - "create table IF NOT EXISTS ${getTableName()} (key VARCHAR(32768), cacheobject OBJECT);"); + try { + synchronized (this.cacheMap) { + Path path = Path.of(System.getProperty("user.home")).resolve(".MultiSubDownloader"); + if (!Files.exists(path)) { + try { + Files.createDirectory(path); + } catch (IOException e) { + throw new RuntimeException("Could not create folder $path", e); } + } + Class.forName("org.hsqldb.jdbcDriver"); + Connection connection = DriverManager.getConnection( + "jdbc:hsqldb:file:$path/diskcache.hsqldb;hsqldb.write_delay=false;shutdown=true", + "user", "pass"); + + try (Statement stmt = connection.createStatement()) { + stmt.execute( + "create table IF NOT EXISTS ${getTableName()} (key VARCHAR(32768), cacheobject OBJECT);"); + } - boolean errorWhileReadingCacheFile = false; - try (Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery("SELECT key, cacheobject FROM ${getTableName()};")) { - Multimap> tempCache = MultimapBuilder.hashKeys() - .treeSetValues(Comparator.comparing((CacheObject value) -> value.age).reversed()) - .build(); - Gson gson = new GsonFireBuilder().enableHooks(SerieMapping.class).createGson(); - synchronized (this.cacheMap) { - while (rs.next()) { - try { - tempCache.put(gson.fromJson((String) rs.getObject("key"), ProviderCacheKey.class), - (CacheObject) rs.getObject("cacheobject")); - } catch (SQLException e2) { - LOGGER.error("Unable to insert object in disk cache. (${e2.getMessage()})", e2); - errorWhileReadingCacheFile = true; - } + boolean errorWhileReadingCacheFile = false; + try (Statement stmt = connection.createStatement(); + ResultSet rs = stmt.executeQuery("SELECT key, cacheobject FROM ${getTableName()};")) { + Multimap> tempCache = MultimapBuilder.hashKeys() + .treeSetValues(Comparator.comparing((CacheObject value) -> value.age).reversed()) + .build(); + Gson gson = new GsonFireBuilder().enableHooks(SerieMapping.class).createGson(); + synchronized (this.cacheMap) { + while (rs.next()) { + try { + tempCache.put(gson.fromJson((String) rs.getObject("key"), ProviderCacheKey.class), + (CacheObject) rs.getObject("cacheobject")); + } catch (SQLException e2) { + LOGGER.error("Unable to insert object in disk cache. (${e2.getMessage()})", e2); + errorWhileReadingCacheFile = true; } - Map>> map = tempCache.asMap(); - map.entrySet().stream() - .filter(entry -> entry.getValue().size() > 1) - .forEach(entry -> { - doublesToRemove.add(entry.getKey()); - removedToAdd.put(entry.getKey(), entry.getValue().last()); - }); - map.entrySet() - .stream() - .sorted(Comparator.comparing(entry -> entry.getValue().first().age)) - .forEach(entry -> put(entry.getKey(), entry.getValue().first())); } - } catch (SQLException e) { - LOGGER.error("Unable while insert objects in disk cache! (${e.getMessage()})", e); + Map>> map = tempCache.asMap(); + map.entrySet().stream() + .filter(entry -> entry.getValue().size() > 1) + .forEach(entry -> { + doublesToRemove.add(entry.getKey()); + removedToAdd.put(entry.getKey(), entry.getValue().last()); + }); + map.entrySet() + .stream() + .sorted(Comparator.comparing(entry -> entry.getValue().first().age)) + .forEach(entry -> put(entry.getKey(), entry.getValue().first())); } - if (errorWhileReadingCacheFile) { - LOGGER.error("Deleting cache file to fix errors"); - connection.close(); - try { - path.deletePath(); - } catch (IOException e) { - LOGGER.error("Error while deleting the cache file, please delete it yourself: $path " + - "(${e.getMessage()})", e); - } - connection = DriverManager.getConnection( - "jdbc:hsqldb:file:$path/diskcache.hsqldb;hsqldb.write_delay=false;shutdown=true", - "user", "pass"); + } catch (SQLException e) { + LOGGER.error("Unable while insert objects in disk cache! (${e.getMessage()})", e); + } + if (errorWhileReadingCacheFile) { + LOGGER.error("Deleting cache file to fix errors"); + connection.close(); + try { + path.deletePath(); + } catch (IOException e) { + LOGGER.error("Error while deleting the cache file, please delete it yourself: $path " + + "(${e.getMessage()})", e); } - return connection; + connection = DriverManager.getConnection( + "jdbc:hsqldb:file:$path/diskcache.hsqldb;hsqldb.write_delay=false;shutdown=true", + "user", "pass"); } - } catch (ClassNotFoundException e) { - throw new RuntimeException("Unable to load jdbcdriver for diskcache"); - } catch (SQLException e) { - throw new RuntimeException(e); + return connection; } - }); + } catch (ClassNotFoundException e) { + throw new RuntimeException("Unable to load jdbcdriver for diskcache"); + } catch (SQLException e) { + throw new RuntimeException(e); + } + }); @NullMarked public ProviderCacheDisk( diff --git a/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/data/imdb/ImdbAdapter.java b/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/data/imdb/ImdbAdapter.java index b88591f4..cb6b8f03 100644 --- a/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/data/imdb/ImdbAdapter.java +++ b/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/data/imdb/ImdbAdapter.java @@ -8,6 +8,8 @@ import java.util.Optional; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; import manifold.ext.props.rt.api.override; import manifold.ext.props.rt.api.val; @@ -63,9 +65,10 @@ public Optional getImdbId(String title, VideoType videoType, @Nullable I @SuppressWarnings("unchecked") Optional releaseMapping = (Optional) getCache(videoType.name() + "mapping", b -> b.add("title", title).add("videoType", videoType).add("year", year)).getOptional( - () -> getImdbIdOnImdb(title, year, videoType).orElseMap( - () -> getImdbIdOnGoogle(title, year, videoType)) - .orElseMap(() -> getImdbIdOnYahoo(title, year, videoType)).orElseMap( + () -> getImdbIdOnImdb(title, year, videoType) + .orElseMap(() -> getImdbIdOnGoogle(title, year, videoType)) + .orElseMap(() -> getImdbIdOnYahoo(title, year, videoType)) + .orElseMap( () -> promptUserToEnterImdbId(title).flatMap(imdbId -> getImdbIdOnImdb(title, imdbId))) .map(imdbId -> switch (videoType) { case EPISODE -> new SerieMapping(title, imdbId.id, imdbId.name); @@ -119,7 +122,8 @@ private Optional getImdbIdCommon(String title, @Nullable Integer year, V Pattern yearPattern = Pattern.compile("(?[1-2]\\d{3})"); return userInteractionHandler.selectFromList(providerIds.stream().sorted( Comparator.comparing((ImdbId imdbPID) -> imdbPID.videoType == videoType ? -1 : 1) - .thenComparing(imdbPID -> imdbPID.calculateLevenshteinDistance(title)).thenComparing(imdbPID -> { + .thenComparing(imdbPID -> imdbPID.calculateLevenshteinDistance(title)) + .thenComparing(imdbPID -> { if (imdbPID.year != null) { Matcher matcher = yearPattern.matcher(imdbPID.year); Integer lastYear = null; @@ -133,7 +137,8 @@ private Optional getImdbIdCommon(String title, @Nullable Integer year, V return 0; })).toList(), getText("Prompter.SelectImdbMatchForSerie", title), provider, providerId -> providerId.name + - (StringUtils.isNotBlank(providerId.otherInfo) ? " (" + providerId.otherInfo + ")" : "")); + Stream.of(providerId.year, providerId.otherInfo).mapFilterNonNull(StringUtils::trimToNull).collect( + Collectors.joining(" - ", " (", ")"))); } private Optional promptUserToEnterImdbId(String title) { diff --git a/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/data/imdb/ImdbSearchIdApi.java b/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/data/imdb/ImdbSearchIdApi.java index f62c1f67..7b682688 100755 --- a/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/data/imdb/ImdbSearchIdApi.java +++ b/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/data/imdb/ImdbSearchIdApi.java @@ -1,5 +1,7 @@ package org.lodder.subtools.sublibrary.data.imdb; +import static util.Utils.*; + import java.net.URLDecoder; import java.net.URLEncoder; import java.nio.charset.StandardCharsets; @@ -8,9 +10,12 @@ import java.util.function.Function; import java.util.regex.Matcher; import java.util.regex.Pattern; +import java.util.stream.Collectors; +import java.util.stream.Stream; import com.google.gson.JsonObject; import com.google.gson.JsonParser; +import extensions.org.jsoup.nodes.Element.ElementExt; import org.apache.commons.lang3.StringUtils; import org.jsoup.nodes.Element; import org.jsoup.select.Elements; @@ -46,14 +51,19 @@ public Set getImdbIdOnImdb(String title, @Nullable Integer year, VideoTy }); String url = sb.toString().replace("+", "%20"); try { - Elements searchResults = - manager.getAsJsoupDocument(new PageContentParams(url)).select(".find-result-item"); + Elements searchResults = manager.getAsJsoupDocument(new PageContentParams(url)) + .select(".ipc-metadata-list-summary-item .cli-children"); return getImdbIdCommon(searchResults, e -> e.selectFirst("a").text(), - e -> e.selectFirst("a").attr("href"), e -> e.selectFirst("span").text(), - e -> e.selectFirst("a").siblingElements().stream().map(s -> s.text()).findFirst().orElse(""), - e -> e.selectFirst("a").siblingElements().stream().map(s -> s.text().contains("Series") ? - VideoType.EPISODE : VideoType.MOVIE).findFirst().orElse(null)); + e -> e.selectFirst("a").attr("href"), + e -> e.selectFirst(".cli-title-metadata .cli-title-metadata-item").text().split("–")[0], + e -> Stream.of(e.selectFirst(".cli-title-metadata .cli-title-type-data"), + e.selectFirst(".cli-title-metadata .cli-title-metadata-item:nth-child(2)")) + .map(ElementExt::text) + .mapFilterNonNull(StringUtils::trimToNull).collect(Collectors.joining(" - ")), + e -> ifNotNull( + StringUtils.trimToNull(e.selectFirst(".cli-title-metadata .cli-title-type-data").text()), + t -> t.contains("Series") ? VideoType.EPISODE : VideoType.MOVIE)); } catch (Exception e) { throw new ImdbSearchIdException("Error getImdbIdOnImdb", url, e); } @@ -141,9 +151,9 @@ public Set getImdbIdOnGoogle(String title, @Nullable Integer year, Video } private Set getImdbIdCommon(Elements searchResults, Function toNameMapper, - Function toHrefMapper, Function toYearMapper=_ -> null, - Function toOtherInfoMapper=_ -> null, - Function toVideoTypeMapper=_ -> null) { + Function toHrefMapper, Function toYearMapper=_ -> null, + Function toOtherInfoMapper=_ -> null, + Function toVideoTypeMapper=_ -> null) { return searchResults.stream().collect(Utils.setCollector( (set, element) -> { String name = toNameMapper.apply(element); diff --git a/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/model/Release.java b/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/model/Release.java index f6b78606..ffcf12a4 100755 --- a/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/model/Release.java +++ b/SubLibrary/src/main/java/org/lodder/subtools/sublibrary/model/Release.java @@ -17,8 +17,8 @@ public sealed interface Release permits ReleaseWithoutPath, ReleaseWithPath, Mov @val String releaseDescription; @val String completeName; - @val String fileNameOrName = switch (this) { - case ReleaseWithPath r -> r.fileName; + @val String folderNameOrName = switch (this) { + case ReleaseWithPath r -> r.path.parent.toString(); case ReleaseWithoutPath r -> r.completeName; }; @val int matchingSubCount = matchingSubs.size(); diff --git a/SubLibrary/src/main/java/util/Utils.java b/SubLibrary/src/main/java/util/Utils.java index f2f0d833..67d51123 100644 --- a/SubLibrary/src/main/java/util/Utils.java +++ b/SubLibrary/src/main/java/util/Utils.java @@ -70,7 +70,12 @@ public static void ifNotNullDo(@Nullable T value, Throw return value != null ? mapper.apply(value) : orElseValue; } - public static R ifNotNullOrElseGet(@Nullable T value, + public static R ifNotNullOrElseGet(@Nullable T value, + ThrowingFunction mapper, Supplier orElseSupplier) throws X { + return value != null ? mapper.apply(value) : orElseSupplier.get(); + } + + public static R ifNotNullOrElseGetNullable(@Nullable T value, ThrowingFunction mapper, Supplier orElseSupplier) throws X { return value != null ? mapper.apply(value) : orElseSupplier.get(); } diff --git a/SubLibrary/src/test/java/org/lodder/subtools/sublibrary/assertions/ReleaseAssert.java b/SubLibrary/src/test/java/org/lodder/subtools/sublibrary/assertions/ReleaseAssert.java index 4d61d723..079feff7 100644 --- a/SubLibrary/src/test/java/org/lodder/subtools/sublibrary/assertions/ReleaseAssert.java +++ b/SubLibrary/src/test/java/org/lodder/subtools/sublibrary/assertions/ReleaseAssert.java @@ -28,13 +28,13 @@ public TvReleaseAssert isSerie() { public @Self ReleaseAssert hasFileName(String fileName) { isNotNull(); - assertThat(actual.fileNameOrName).isEqualTo(fileName); + assertThat(actual.folderNameOrName).isEqualTo(fileName); return this; } public @Self ReleaseAssert hasExtension(String extension) { isNotNull(); - assertThat(actual.fileNameOrName.endsWith(extension)).isTrue(); + assertThat(actual.folderNameOrName.endsWith(extension)).isTrue(); return this; }