From 256b5be2d3401671c23cf7406cb5993146ad8c17 Mon Sep 17 00:00:00 2001 From: Reinhard Pointner Date: Mon, 31 Oct 2016 07:19:11 +0800 Subject: [PATCH] Experimental support for episode level extended info (only supported with TheTVDB data) --- .../format/ExpressionFormatMethods.java | 13 ++ .../net/filebot/format/MediaBindingBean.java | 4 +- source/net/filebot/web/EpisodeInfo.java | 120 ++++++++++++++++++ source/net/filebot/web/Person.java | 2 +- source/net/filebot/web/TheTVDBClient.java | 29 ++++- test/net/filebot/web/TheTVDBClientTest.java | 14 ++ 6 files changed, 178 insertions(+), 4 deletions(-) create mode 100644 source/net/filebot/web/EpisodeInfo.java diff --git a/source/net/filebot/format/ExpressionFormatMethods.java b/source/net/filebot/format/ExpressionFormatMethods.java index e8f8f322..e2b9bd84 100644 --- a/source/net/filebot/format/ExpressionFormatMethods.java +++ b/source/net/filebot/format/ExpressionFormatMethods.java @@ -3,6 +3,7 @@ package net.filebot.format; import static java.util.Arrays.*; import static java.util.regex.Pattern.*; import static net.filebot.MediaTypes.*; +import static net.filebot.WebServices.*; import static net.filebot.format.ExpressionFormatFunctions.*; import static net.filebot.media.MediaDetection.*; import static net.filebot.util.RegularExpressions.*; @@ -33,6 +34,8 @@ import groovy.lang.Closure; import net.filebot.Language; import net.filebot.similarity.Normalization; import net.filebot.util.FileUtilities; +import net.filebot.web.Episode; +import net.filebot.web.EpisodeInfo; import net.filebot.web.SimpleDate; public class ExpressionFormatMethods { @@ -498,4 +501,14 @@ public class ExpressionFormatMethods { return concat(self, other); } + /** + * Episode utilities (EXPERIMENTAL) + */ + public static EpisodeInfo getInfo(Episode self) throws Exception { + if (TheTVDB.getIdentifier().equals(self.getSeriesInfo().getDatabase())) + return TheTVDBv2.getEpisodeInfo(self.getId(), Locale.ENGLISH); + + return null; + } + } diff --git a/source/net/filebot/format/MediaBindingBean.java b/source/net/filebot/format/MediaBindingBean.java index e41059c0..fd69b9ee 100644 --- a/source/net/filebot/format/MediaBindingBean.java +++ b/source/net/filebot/format/MediaBindingBean.java @@ -601,9 +601,11 @@ public class MediaBindingBean { } @Define("director") - public Object getDirector() throws Exception { + public String getDirector() throws Exception { if (infoObject instanceof Movie) return getMovieInfo().getDirector(); + if (infoObject instanceof Episode) + return getInfo(getEpisode()).getDirectors().iterator().next(); return null; } diff --git a/source/net/filebot/web/EpisodeInfo.java b/source/net/filebot/web/EpisodeInfo.java new file mode 100644 index 00000000..49ac66c6 --- /dev/null +++ b/source/net/filebot/web/EpisodeInfo.java @@ -0,0 +1,120 @@ +package net.filebot.web; + +import static java.util.Arrays.*; +import static java.util.Collections.*; +import static java.util.stream.Collectors.*; + +import java.io.Serializable; +import java.util.List; +import java.util.Locale; +import java.util.Objects; + +public class EpisodeInfo implements Serializable { + + protected String database; + protected Integer seriesId; + protected Integer id; + protected String language; + + protected Person[] people; + protected String overview; + + protected Double rating; + protected Integer votes; + + public EpisodeInfo() { + // used by deserializer + } + + public EpisodeInfo(EpisodeInfo other) { + database = other.database; + seriesId = other.seriesId; + id = other.id; + language = other.language; + people = other.people == null ? null : other.people.clone(); + overview = other.overview; + rating = other.rating; + votes = other.votes; + } + + public EpisodeInfo(Datasource database, Locale language, Integer seriesId, Integer id, List people, String overview, Double rating, Integer votes) { + this.database = database.getIdentifier(); + this.language = language.getLanguage(); + this.seriesId = seriesId; + this.id = id; + this.people = people.toArray(new Person[0]); + this.overview = overview; + this.votes = votes; + this.rating = rating; + } + + public String getDatabase() { + return database; + } + + public Integer getSeriesId() { + return seriesId; + } + + public Integer getId() { + return id; + } + + public String getLanguage() { + return language; + } + + public List getPeople() { + return unmodifiableList(asList(people)); + } + + public List getDirectors() { + return stream(people).filter(Person::isDirector).map(Person::getName).collect(toList()); + } + + public List getWriters() { + return stream(people).filter(Person::isWriter).map(Person::getName).collect(toList()); + } + + public List getGuestStars() { + return stream(people).filter(Person::isActor).map(Person::getName).collect(toList()); + } + + public String getOverview() { + return overview; + } + + public Double getRating() { + return rating; + } + + public Integer getVotes() { + return votes; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof EpisodeInfo) { + EpisodeInfo other = (EpisodeInfo) obj; + return Objects.equals(id, other.id) && Objects.equals(database, other.database); + } + + return false; + } + + @Override + public int hashCode() { + return id == null ? 0 : id; + } + + @Override + public EpisodeInfo clone() { + return new EpisodeInfo(this); + } + + @Override + public String toString() { + return database + "::" + seriesId + "::" + id; + } + +} diff --git a/source/net/filebot/web/Person.java b/source/net/filebot/web/Person.java index c136660d..55f76899 100644 --- a/source/net/filebot/web/Person.java +++ b/source/net/filebot/web/Person.java @@ -70,7 +70,7 @@ public class Person implements Serializable { @Override public String toString() { - return String.format("%s (%s)", name, isActor() ? character : job); + return String.format("%s (%s)", name, character != null ? character : job); } public static final String WRITER = "Writer"; diff --git a/source/net/filebot/web/TheTVDBClient.java b/source/net/filebot/web/TheTVDBClient.java index 8400a03e..aeaf471a 100644 --- a/source/net/filebot/web/TheTVDBClient.java +++ b/source/net/filebot/web/TheTVDBClient.java @@ -276,8 +276,8 @@ public class TheTVDBClient extends AbstractEpisodeListProvider implements Artwor return streamJsonObjects(response, "data").map(it -> getString(it, "abbreviation")).collect(toList()); } - public List getActors(int id, Locale locale) throws Exception { - Object response = requestJson("series/" + id + "/actors", locale, Cache.ONE_MONTH); + public List getActors(int seriesId, Locale locale) throws Exception { + Object response = requestJson("series/" + seriesId + "/actors", locale, Cache.ONE_MONTH); // e.g. [id:68414, seriesId:78874, name:Summer Glau, role:River Tam, sortOrder:2, image:actors/68414.jpg, imageAuthor:513, imageAdded:0000-00-00 00:00:00, lastUpdated:2011-08-18 11:53:14] return streamJsonObjects(response, "data").map(it -> { @@ -290,4 +290,29 @@ public class TheTVDBClient extends AbstractEpisodeListProvider implements Artwor }).sorted(Person.CREDIT_ORDER).collect(toList()); } + public EpisodeInfo getEpisodeInfo(int id, Locale locale) throws Exception { + Object response = requestJson("episodes/" + id, locale, Cache.ONE_MONTH); + Object data = getMap(response, "data"); + + Integer seriesId = getInteger(data, "seriesId"); + String overview = getString(data, "overview"); + + Double rating = getDecimal(data, "siteRating"); + Integer votes = getInteger(data, "siteRatingCount"); + + List people = new ArrayList(); + + for (Object it : getArray(data, "directors")) { + people.add(new Person(it.toString(), Person.DIRECTOR)); + } + for (Object it : getArray(data, "writers")) { + people.add(new Person(it.toString(), Person.WRITER)); + } + for (Object it : getArray(data, "guestStars")) { + people.add(new Person(it.toString(), Person.ACTOR)); + } + + return new EpisodeInfo(this, locale, seriesId, id, people, overview, rating, votes); + } + } diff --git a/test/net/filebot/web/TheTVDBClientTest.java b/test/net/filebot/web/TheTVDBClientTest.java index 4397739a..3654c272 100644 --- a/test/net/filebot/web/TheTVDBClientTest.java +++ b/test/net/filebot/web/TheTVDBClientTest.java @@ -164,4 +164,18 @@ public class TheTVDBClientTest { assertEquals("http://thetvdb.com/banners/actors/68409.jpg", p.getImage().toString()); } + @Test + public void getEpisodeInfo() throws Exception { + EpisodeInfo i = db.getEpisodeInfo(296337, Locale.ENGLISH); + + assertEquals("78845", i.getSeriesId().toString()); + assertEquals("296337", i.getId().toString()); + assertEquals(8.2, i.getRating(), 0.1); + assertEquals(6, i.getVotes(), 5); + assertEquals("When Jaye Tyler is convinced by a waxed lion to chase after a shinny quarter, she finds herself returning a lost purse to a lady (who instead of thanking her, is punched in the face), meeting an attractive and sweet bartender names Eric, introducing her sister, Sharon to the EPS newly divorced bachelor, Thomas, she knows, and later discovering her sister, Sharon's sexuality.", i.getOverview().toString()); + assertEquals("[Todd Holland, Bryan Fuller, Todd Holland]", i.getDirectors().toString()); + assertEquals("[Todd Holland, Bryan Fuller]", i.getWriters().toString()); + assertEquals("[Scotch Ellis Loring, Gerry Fiorini, Kim Roberts, Corry Karpf, Curt Wu, Bailey Stocker, Lisa Marcos, Jorge Molina, Morgan Drmaj, Chantal Purdy, Kari Matchett, Neil Grayston, Anna Starnino, Melissa Grelo, Brandon Oakes, Scotch Ellis Loring, Ted Dykstra, Kathryn Greenwood, G]", i.getGuestStars().toString()); + } + }