diff --git a/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy b/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy index 2a25c902..36132fd5 100644 --- a/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy +++ b/source/net/sourceforge/filebot/cli/ScriptShell.lib.groovy @@ -163,6 +163,10 @@ def getRenameLog(complete = false) { import net.sourceforge.filebot.media.* import net.sourceforge.filebot.similarity.* +def stripReleaseInfo(name, strict = true) { + return MediaDetection.stripReleaseInfo([name], strict)[0] +} + def isEpisode(path, strict = true) { def input = path instanceof File ? path.name : path.toString() return MediaDetection.isEpisode(input, strict) diff --git a/source/net/sourceforge/filebot/format/MediaBindingBean.java b/source/net/sourceforge/filebot/format/MediaBindingBean.java index d146c516..a2050a10 100644 --- a/source/net/sourceforge/filebot/format/MediaBindingBean.java +++ b/source/net/sourceforge/filebot/format/MediaBindingBean.java @@ -398,6 +398,23 @@ public class MediaBindingBean { } + @Define("imdbapi") + public synchronized AssociativeScriptObject getImdbApiInfo() { + Object data = null; + + try { + if (infoObject instanceof Episode) + data = WebServices.IMDb.getImdbApiMovieInfo(new Movie(getEpisode().getSeriesName(), getEpisode().getSeriesStartDate().getYear(), -1)); + if (infoObject instanceof Movie) + data = WebServices.IMDb.getImdbApiMovieInfo(getMovie()); + } catch (Exception e) { + throw new RuntimeException("Failed to retrieve metadata: " + infoObject, e); + } + + return createMapBindings(new PropertyBindings(data, null)); + } + + @Define("episodelist") public Object getEpisodeList() throws Exception { return WebServices.TheTVDB.getEpisodeList(WebServices.TheTVDB.search(getEpisode().getSeriesName()).get(0), SortOrder.Airdate, Locale.ENGLISH); diff --git a/source/net/sourceforge/filebot/ui/rename/BindingDialog.properties b/source/net/sourceforge/filebot/ui/rename/BindingDialog.properties index f012c456..b239f4b2 100644 --- a/source/net/sourceforge/filebot/ui/rename/BindingDialog.properties +++ b/source/net/sourceforge/filebot/ui/rename/BindingDialog.properties @@ -2,4 +2,4 @@ parameter.exclude: ^StreamKind|Count$ # preview expressions (keys are tagged so they can be sorted alphabetically) -expressions: n,y,s,e,t,airdate,startdate,absolute,special,imdb,episode,sxe,s00e00,movie,vc,ac,cf,vf,af,resolution,hpi,ws,sdhd,source,group,crc32,fn,ext,file,pi,pn,lang,actors,director,genres,certification,rating,dim,info.runtime,info.status,media.title,media.durationString,media.overallBitRateString,video.codecID,video.frameRate,video.displayAspectRatioString,video.height,video.scanType,audio.format,audio.bitRateString,audio.language,text.codecInfo,text.language +expressions: n,y,s,e,t,airdate,startdate,absolute,special,imdb,episode,sxe,s00e00,movie,vc,ac,cf,vf,af,resolution,hpi,ws,sdhd,source,group,crc32,fn,ext,file,pi,pn,lang,actors,director,genres,certification,rating,dim,info.runtime,info.status,imdbapi.rating,imdbapi.votes,media.title,media.durationString,media.overallBitRateString,video.codecID,video.frameRate,video.displayAspectRatioString,video.height,video.scanType,audio.format,audio.bitRateString,audio.language,text.codecInfo,text.language diff --git a/source/net/sourceforge/filebot/web/IMDbClient.java b/source/net/sourceforge/filebot/web/IMDbClient.java index d95760b4..67d5c894 100644 --- a/source/net/sourceforge/filebot/web/IMDbClient.java +++ b/source/net/sourceforge/filebot/web/IMDbClient.java @@ -2,6 +2,7 @@ package net.sourceforge.filebot.web; +import static java.util.Collections.*; import static net.sourceforge.filebot.web.WebRequest.*; import static net.sourceforge.tuned.XPathUtilities.*; @@ -11,8 +12,12 @@ import java.io.IOException; import java.io.Reader; import java.net.URL; import java.net.URLConnection; +import java.nio.ByteBuffer; +import java.nio.charset.Charset; import java.util.ArrayList; import java.util.Collection; +import java.util.EnumMap; +import java.util.HashMap; import java.util.List; import java.util.Locale; import java.util.Map; @@ -23,6 +28,10 @@ import java.util.regex.Pattern; import javax.swing.Icon; import net.sourceforge.filebot.ResourceManager; +import net.sourceforge.filebot.web.TMDbClient.Artwork; +import net.sourceforge.filebot.web.TMDbClient.MovieInfo; +import net.sourceforge.filebot.web.TMDbClient.MovieInfo.MovieProperty; +import net.sourceforge.filebot.web.TMDbClient.Person; import org.w3c.dom.Document; import org.w3c.dom.Node; @@ -165,4 +174,56 @@ public class IMDbClient implements MovieIdentificationService { throw new UnsupportedOperationException(); } + + @SuppressWarnings({ "unchecked", "rawtypes" }) + public Map getImdbApiData(String i, String t, String y) throws IOException { + // e.g. http://www.imdbapi.com/?i=tt0379786&r=xml&tomatoes=true + String url = String.format("http://www.imdbapi.com/?i=%s&t=%s&y=%s&r=xml", i, t, y); + CachedResource data = new CachedResource(url, HashMap.class, 7 * 24 * 60 * 60 * 1000) { + + @Override + public HashMap process(ByteBuffer data) throws Exception { + Document xml = getDocument(Charset.forName("UTF-8").decode(data).toString()); + HashMap attr = new HashMap(); + for (Node it : selectNodes("//@*", xml)) { + attr.put(it.getNodeName(), it.getTextContent()); + } + return attr; + } + }; + + return data.get(); + } + + + public MovieInfo getImdbApiMovieInfo(Movie movie) throws IOException { + Map data = movie.getImdbId() > 0 ? getImdbApiData(String.format("tt%07d", movie.getImdbId()), "", "") : getImdbApiData("", movie.getName(), String.valueOf(movie.getYear())); + + // sanity check + if (!Boolean.parseBoolean(data.get("response"))) { + throw new IllegalArgumentException("Movie not found: " + data); + } + + Map fields = new EnumMap(MovieProperty.class); + fields.put(MovieProperty.name, data.get("title")); + fields.put(MovieProperty.certification, data.get("rated")); + fields.put(MovieProperty.released, Date.parse(data.get("released"), "dd MMM yyyy").toString()); + fields.put(MovieProperty.tagline, data.get("plot")); + fields.put(MovieProperty.rating, data.get("imdbRating")); + fields.put(MovieProperty.votes, data.get("imdbVotes").replaceAll("\\D", "")); + fields.put(MovieProperty.imdb_id, data.get("imdbID")); + + List genres = new ArrayList(); + for (String it : data.get("genre").split(",")) { + genres.add(it.trim()); + } + + List actors = new ArrayList(); + for (String it : data.get("actors").split(",")) { + actors.add(new Person(it.trim(), null, "Actor", null, null)); + } + + List image = singletonList(new Artwork("poster", data.get("poster"), null, null, null)); + return new MovieInfo(fields, genres, actors, image); + } } diff --git a/source/net/sourceforge/filebot/web/TMDbClient.java b/source/net/sourceforge/filebot/web/TMDbClient.java index 8e67f925..43c23eb4 100644 --- a/source/net/sourceforge/filebot/web/TMDbClient.java +++ b/source/net/sourceforge/filebot/web/TMDbClient.java @@ -459,11 +459,21 @@ public class TMDbClient implements MovieIdentificationService { } - protected Artwork(Map fields) { + public Artwork(Map fields) { this.fields = new EnumMap(fields); } + public Artwork(String type, String url, String size, String width, String height) { + fields = new EnumMap(ArtworkProperty.class); + fields.put(ArtworkProperty.type, type); + fields.put(ArtworkProperty.url, url); + fields.put(ArtworkProperty.size, size); + fields.put(ArtworkProperty.width, width); + fields.put(ArtworkProperty.height, height); + } + + public String get(Object key) { return fields.get(ArtworkProperty.valueOf(key.toString())); } @@ -537,11 +547,21 @@ public class TMDbClient implements MovieIdentificationService { } - protected Person(Map fields) { + public Person(Map fields) { this.fields = new EnumMap(fields); } + public Person(String name, String character, String job, String thumb, String department) { + fields = new EnumMap(PersonProperty.class); + fields.put(PersonProperty.name, name); + fields.put(PersonProperty.character, character); + fields.put(PersonProperty.job, job); + fields.put(PersonProperty.thumb, thumb); + fields.put(PersonProperty.department, department); + } + + public String get(Object key) { return fields.get(PersonProperty.valueOf(key.toString())); }