* added fallback for movie identification by scanning .nfo files for an imdb id
This commit is contained in:
parent
7a87ea9573
commit
5519c1440d
|
@ -13,6 +13,10 @@
|
|||
<extension>txt</extension>
|
||||
</type>
|
||||
|
||||
<type name="application/nfo">
|
||||
<extension>nfo</extension>
|
||||
</type>
|
||||
|
||||
|
||||
<!--
|
||||
Verification
|
||||
|
|
|
@ -3,12 +3,24 @@ package net.sourceforge.filebot.ui.panel.rename;
|
|||
|
||||
|
||||
import static net.sourceforge.filebot.MediaTypes.*;
|
||||
import static net.sourceforge.tuned.ui.TunedUtilities.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Scanner;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Callable;
|
||||
import java.util.concurrent.FutureTask;
|
||||
import java.util.concurrent.RunnableFuture;
|
||||
|
||||
import javax.swing.Action;
|
||||
import javax.swing.SwingUtilities;
|
||||
|
||||
import net.sourceforge.filebot.similarity.Match;
|
||||
import net.sourceforge.filebot.ui.SelectDialog;
|
||||
import net.sourceforge.filebot.web.MovieDescriptor;
|
||||
import net.sourceforge.filebot.web.MovieIdentificationService;
|
||||
import net.sourceforge.tuned.FileUtilities;
|
||||
|
@ -35,10 +47,84 @@ class MovieHashMatcher implements AutoCompleteMatcher {
|
|||
for (int i = 0; i < movieDescriptors.length; i++) {
|
||||
if (movieDescriptors[i] != null) {
|
||||
matches.add(new Match<File, MovieDescriptor>(movieFiles[i], movieDescriptors[i]));
|
||||
} else {
|
||||
// unknown hash, try via imdb id from nfo file
|
||||
MovieDescriptor movie = determineMovie(movieFiles[i]);
|
||||
|
||||
if (movie != null) {
|
||||
matches.add(new Match<File, MovieDescriptor>(movieFiles[i], movie));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return matches;
|
||||
}
|
||||
|
||||
|
||||
protected Set<Integer> grepImdbId(File... files) throws IOException {
|
||||
Set<Integer> collection = new HashSet<Integer>();
|
||||
|
||||
for (File file : files) {
|
||||
Scanner scanner = new Scanner(file);
|
||||
String imdb = null;
|
||||
|
||||
// scan for imdb id patterns like tt1234567
|
||||
while ((imdb = scanner.findWithinHorizon("(?<=tt)\\d{7}", 32 * 1024)) != null) {
|
||||
collection.add(Integer.parseInt(imdb));
|
||||
}
|
||||
}
|
||||
|
||||
return collection;
|
||||
}
|
||||
|
||||
|
||||
protected MovieDescriptor determineMovie(File movieFile) throws Exception {
|
||||
List<MovieDescriptor> options = new ArrayList<MovieDescriptor>();
|
||||
|
||||
for (int imdbid : grepImdbId(movieFile.getParentFile().listFiles(getDefaultFilter("application/nfo")))) {
|
||||
MovieDescriptor movie = service.getMovieDescriptor(imdbid);
|
||||
|
||||
if (movie != null) {
|
||||
options.add(movie);
|
||||
}
|
||||
}
|
||||
|
||||
return options.isEmpty() ? null : selectMovie(options);
|
||||
}
|
||||
|
||||
|
||||
protected MovieDescriptor selectMovie(final List<MovieDescriptor> options) throws Exception {
|
||||
if (options.size() == 1) {
|
||||
return options.get(0);
|
||||
}
|
||||
|
||||
// show selection dialog on EDT
|
||||
final RunnableFuture<MovieDescriptor> showSelectDialog = new FutureTask<MovieDescriptor>(new Callable<MovieDescriptor>() {
|
||||
|
||||
@Override
|
||||
public MovieDescriptor call() throws Exception {
|
||||
// multiple results have been found, user must select one
|
||||
SelectDialog<MovieDescriptor> selectDialog = new SelectDialog<MovieDescriptor>(null, options);
|
||||
|
||||
selectDialog.getHeaderLabel().setText("Select Movie:");
|
||||
selectDialog.getCancelAction().putValue(Action.NAME, "Ignore");
|
||||
|
||||
// show dialog
|
||||
selectDialog.setLocation(getOffsetLocation(selectDialog.getOwner()));
|
||||
selectDialog.setVisible(true);
|
||||
|
||||
// selected value or null if the dialog was canceled by the user
|
||||
return selectDialog.getSelectedValue();
|
||||
}
|
||||
});
|
||||
|
||||
// allow only one select dialog at a time
|
||||
synchronized (this) {
|
||||
SwingUtilities.invokeAndWait(showSelectDialog);
|
||||
}
|
||||
|
||||
// selected value or null
|
||||
return showSelectDialog.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,5 +7,9 @@ import java.io.File;
|
|||
|
||||
public interface MovieIdentificationService {
|
||||
|
||||
public MovieDescriptor getMovieDescriptor(int imdbid) throws Exception;
|
||||
|
||||
|
||||
public MovieDescriptor[] getMovieDescriptors(File[] movieFiles) throws Exception;
|
||||
|
||||
}
|
||||
|
|
|
@ -146,6 +146,15 @@ public class OpenSubtitlesClient implements SubtitleProvider, VideoHashSubtitleS
|
|||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MovieDescriptor getMovieDescriptor(int imdbid) throws Exception {
|
||||
// require login
|
||||
login();
|
||||
|
||||
return xmlrpc.getIMDBMovieDetails(imdbid);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MovieDescriptor[] getMovieDescriptors(File[] movieFiles) throws Exception {
|
||||
// create result array
|
||||
|
|
|
@ -243,6 +243,25 @@ public class OpenSubtitlesXmlRpc {
|
|||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public MovieDescriptor getIMDBMovieDetails(int imdbid) throws XmlRpcFault {
|
||||
Map<?, ?> response = invoke("GetIMDBMovieDetails", token, imdbid);
|
||||
|
||||
try {
|
||||
Map<String, String> data = (Map<String, String>) response.get("data");
|
||||
|
||||
String name = data.get("title");
|
||||
int year = Integer.parseInt(data.get("year"));
|
||||
|
||||
return new MovieDescriptor(name, year, imdbid);
|
||||
} catch (RuntimeException e) {
|
||||
// ignore, invalid response
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String> getSubLanguages(String languageCode) throws XmlRpcFault {
|
||||
Map<String, List<Map<String, String>>> response = (Map<String, List<Map<String, String>>>) invoke("GetSubLanguages", languageCode);
|
||||
|
|
|
@ -54,6 +54,20 @@ public class TMDbClient implements MovieIdentificationService {
|
|||
}
|
||||
|
||||
|
||||
public MovieDescriptor getMovieDescriptor(int imdbid) throws Exception {
|
||||
URL resource = getResource("Movie.imdbLookup", String.format("tt%07d", imdbid));
|
||||
Node movie = selectNode("//movie", getDocument(resource));
|
||||
|
||||
if (movie == null)
|
||||
return null;
|
||||
|
||||
String name = getTextContent("name", movie);
|
||||
int year = new Scanner(getTextContent("released", movie)).useDelimiter("\\D+").nextInt();
|
||||
|
||||
return new MovieDescriptor(name, year, imdbid);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public MovieDescriptor[] getMovieDescriptors(File[] movieFiles) throws Exception {
|
||||
MovieDescriptor[] movies = new MovieDescriptor[movieFiles.length];
|
||||
|
|
|
@ -140,6 +140,26 @@ public class OpenSubtitlesXmlRpcTest {
|
|||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getIMDBMovieDetails() throws Exception {
|
||||
MovieDescriptor movie = xmlrpc.getIMDBMovieDetails(371746);
|
||||
|
||||
assertEquals("Iron Man", movie.getName());
|
||||
assertEquals(2008, movie.getYear());
|
||||
assertEquals(371746, movie.getImdbId());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void getIMDBMovieDetailsInvalid() throws Exception {
|
||||
MovieDescriptor movie = xmlrpc.getIMDBMovieDetails(371746);
|
||||
|
||||
assertEquals("Iron Man", movie.getName());
|
||||
assertEquals(2008, movie.getYear());
|
||||
assertEquals(371746, movie.getImdbId());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void detectLanguage() throws Exception {
|
||||
String text = "Only those that are prepared to fire should be fired at.";
|
||||
|
|
|
@ -36,4 +36,14 @@ public class TMDbClientTest {
|
|||
assertEquals(371746, movie.getImdbId());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void searchByIMDB() throws Exception {
|
||||
MovieDescriptor movie = tmdb.getMovieDescriptor(418279);
|
||||
|
||||
assertEquals("Transformers", movie.getName());
|
||||
assertEquals(2007, movie.getYear());
|
||||
assertEquals(418279, movie.getImdbId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue