mirror of
https://github.com/mitb-archive/filebot
synced 2024-12-24 16:58:51 -05:00
* refactored anidb client a bit (added internal support for multi-language episode titles)
This commit is contained in:
parent
270a0409ca
commit
038dcb38e8
@ -5,9 +5,7 @@ package net.sourceforge.filebot.web;
|
|||||||
import static net.sourceforge.filebot.web.WebRequest.*;
|
import static net.sourceforge.filebot.web.WebRequest.*;
|
||||||
import static net.sourceforge.tuned.XPathUtilities.*;
|
import static net.sourceforge.tuned.XPathUtilities.*;
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
@ -15,16 +13,17 @@ import java.net.URLConnection;
|
|||||||
import java.util.AbstractList;
|
import java.util.AbstractList;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Scanner;
|
import java.util.Scanner;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
import java.util.AbstractMap.SimpleEntry;
|
import java.util.AbstractMap.SimpleEntry;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.logging.Logger;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
@ -33,7 +32,6 @@ import javax.swing.Icon;
|
|||||||
|
|
||||||
import org.w3c.dom.Document;
|
import org.w3c.dom.Document;
|
||||||
import org.w3c.dom.Node;
|
import org.w3c.dom.Node;
|
||||||
import org.xml.sax.SAXException;
|
|
||||||
|
|
||||||
import uk.ac.shef.wit.simmetrics.similaritymetrics.AbstractStringMetric;
|
import uk.ac.shef.wit.simmetrics.similaritymetrics.AbstractStringMetric;
|
||||||
import uk.ac.shef.wit.simmetrics.similaritymetrics.QGramsDistance;
|
import uk.ac.shef.wit.simmetrics.similaritymetrics.QGramsDistance;
|
||||||
@ -48,7 +46,7 @@ public class AnidbClient implements EpisodeListProvider {
|
|||||||
|
|
||||||
private static final String host = "anidb.net";
|
private static final String host = "anidb.net";
|
||||||
|
|
||||||
private static final Cache cache = CacheManager.getInstance().getCache("anidb");
|
private static final AnidbCache cache = new AnidbCache(CacheManager.getInstance().getCache("anidb"));
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -64,7 +62,7 @@ public class AnidbClient implements EpisodeListProvider {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<SearchResult> search(String query) throws IOException, SAXException {
|
public List<SearchResult> search(String query) throws Exception {
|
||||||
// normalize
|
// normalize
|
||||||
query = query.toLowerCase();
|
query = query.toLowerCase();
|
||||||
|
|
||||||
@ -117,16 +115,18 @@ public class AnidbClient implements EpisodeListProvider {
|
|||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<Episode> getEpisodeList(SearchResult searchResult) throws IOException, SAXException {
|
public List<Episode> getEpisodeList(SearchResult searchResult) throws Exception {
|
||||||
int aid = ((AnidbSearchResult) searchResult).getAnimeId();
|
return getEpisodeList((AnidbSearchResult) searchResult, Locale.ENGLISH);
|
||||||
URL url = new URL("http", host, "/perl-bin/animedb.pl?show=xml&t=anime&aid=" + aid);
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<Episode> getEpisodeList(AnidbSearchResult anime, Locale language) throws Exception {
|
||||||
|
URL url = new URL("http", host, "/perl-bin/animedb.pl?show=xml&t=anime&aid=" + anime.getAnimeId());
|
||||||
|
|
||||||
// try cache first
|
// try cache first
|
||||||
try {
|
List<Episode> episodes = cache.getEpisodeList(anime.getAnimeId(), language.getLanguage());
|
||||||
return Arrays.asList((Episode[]) cache.get(url.toString()).getValue());
|
if (episodes != null)
|
||||||
} catch (Exception e) {
|
return episodes;
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
// set request headers to resemble an ajax request
|
// set request headers to resemble an ajax request
|
||||||
URLConnection connection = url.openConnection();
|
URLConnection connection = url.openConnection();
|
||||||
@ -138,14 +138,14 @@ public class AnidbClient implements EpisodeListProvider {
|
|||||||
// select main title
|
// select main title
|
||||||
String animeTitle = selectString("//title[@type='main']", dom);
|
String animeTitle = selectString("//title[@type='main']", dom);
|
||||||
|
|
||||||
List<Episode> episodes = new ArrayList<Episode>(25);
|
episodes = new ArrayList<Episode>(25);
|
||||||
|
|
||||||
for (Node node : selectNodes("//ep", dom)) {
|
for (Node node : selectNodes("//ep", dom)) {
|
||||||
Integer number = getIntegerContent("epno", node);
|
Integer number = getIntegerContent("epno", node);
|
||||||
|
|
||||||
// ignore special episodes
|
// ignore special episodes
|
||||||
if (number != null) {
|
if (number != null) {
|
||||||
String title = selectString(".//title[@lang='en']", node);
|
String title = selectString(".//title[@lang='" + language.getLanguage() + "']", node);
|
||||||
String airdate = selectString(".//date/@rel", node);
|
String airdate = selectString(".//date/@rel", node);
|
||||||
|
|
||||||
// no seasons for anime
|
// no seasons for anime
|
||||||
@ -156,10 +156,10 @@ public class AnidbClient implements EpisodeListProvider {
|
|||||||
// sanity check
|
// sanity check
|
||||||
if (episodes.size() > 0) {
|
if (episodes.size() > 0) {
|
||||||
// populate cache
|
// populate cache
|
||||||
cache.put(new Element(url.toString(), episodes.toArray(new Episode[0])));
|
cache.putEpisodeList(episodes, anime.getAnimeId(), language.getLanguage());
|
||||||
} else {
|
} else {
|
||||||
// anime page xml doesn't work sometimes
|
// anime page xml doesn't work sometimes
|
||||||
Logger.getLogger(getClass().getName()).warning(String.format("Failed to parse episode data from xml: %s (%d)", searchResult, aid));
|
throw new RuntimeException(String.format("Failed to parse episode data from xml: %s (%d)", anime, anime.getAnimeId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
return episodes;
|
return episodes;
|
||||||
@ -196,15 +196,13 @@ public class AnidbClient implements EpisodeListProvider {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private AnidbSearchResult[] getAnimeTitles() throws MalformedURLException, IOException, SAXException {
|
private List<AnidbSearchResult> getAnimeTitles() throws Exception {
|
||||||
URL url = new URL("http", host, "/api/animetitles.dat.gz");
|
URL url = new URL("http", host, "/api/animetitles.dat.gz");
|
||||||
|
|
||||||
// try cache first
|
// try cache first
|
||||||
try {
|
List<AnidbSearchResult> anime = cache.getAnimeList();
|
||||||
return (AnidbSearchResult[]) cache.get(url.toString()).getValue();
|
if (anime != null)
|
||||||
} catch (Exception e) {
|
return anime;
|
||||||
// ignore
|
|
||||||
}
|
|
||||||
|
|
||||||
// <aid>|<type>|<language>|<title>
|
// <aid>|<type>|<language>|<title>
|
||||||
// type: 1=primary title (one per anime), 2=synonyms (multiple per anime), 3=shorttitles (multiple per anime), 4=official title (one per language)
|
// type: 1=primary title (one per anime), 2=synonyms (multiple per anime), 3=shorttitles (multiple per anime), 4=official title (one per language)
|
||||||
@ -232,17 +230,17 @@ public class AnidbClient implements EpisodeListProvider {
|
|||||||
scanner.close();
|
scanner.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
List<AnidbSearchResult> anime = new ArrayList<AnidbSearchResult>(primaryTitleMap.size());
|
// build up a list of all possible anidb search results
|
||||||
|
anime = new ArrayList<AnidbSearchResult>(primaryTitleMap.size());
|
||||||
|
|
||||||
for (Entry<Integer, String> entry : primaryTitleMap.entrySet()) {
|
for (Entry<Integer, String> entry : primaryTitleMap.entrySet()) {
|
||||||
anime.add(new AnidbSearchResult(entry.getKey(), entry.getValue(), englishTitleMap.get(entry.getKey())));
|
anime.add(new AnidbSearchResult(entry.getKey(), entry.getValue(), englishTitleMap.get(entry.getKey())));
|
||||||
}
|
}
|
||||||
|
|
||||||
// populate cache
|
// populate cache
|
||||||
AnidbSearchResult[] result = anime.toArray(new AnidbSearchResult[0]);
|
cache.putAnimeList(anime);
|
||||||
cache.put(new Element(url.toString(), result));
|
|
||||||
|
|
||||||
return result;
|
return anime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -286,4 +284,46 @@ public class AnidbClient implements EpisodeListProvider {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private static class AnidbCache {
|
||||||
|
|
||||||
|
private final Cache cache;
|
||||||
|
|
||||||
|
|
||||||
|
public AnidbCache(Cache cache) {
|
||||||
|
this.cache = cache;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void putAnimeList(Collection<AnidbSearchResult> anime) {
|
||||||
|
cache.put(new Element(host + "AnimeList", anime.toArray(new AnidbSearchResult[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<AnidbSearchResult> getAnimeList() {
|
||||||
|
Element element = cache.get(host + "AnimeList");
|
||||||
|
|
||||||
|
if (element != null)
|
||||||
|
return Arrays.asList((AnidbSearchResult[]) element.getValue());
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void putEpisodeList(Collection<Episode> episodes, int aid, String lang) {
|
||||||
|
cache.put(new Element(host + "EpisodeList" + aid + lang, episodes.toArray(new Episode[0])));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public List<Episode> getEpisodeList(int aid, String lang) {
|
||||||
|
Element element = cache.get(host + "EpisodeList" + aid + lang);
|
||||||
|
|
||||||
|
if (element != null)
|
||||||
|
return Arrays.asList((Episode[]) element.getValue());
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -5,6 +5,7 @@ package net.sourceforge.filebot.web;
|
|||||||
import static org.junit.Assert.*;
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
import org.junit.AfterClass;
|
import org.junit.AfterClass;
|
||||||
import org.junit.BeforeClass;
|
import org.junit.BeforeClass;
|
||||||
@ -113,6 +114,20 @@ public class AnidbClientTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void getEpisodeListI18N() throws Exception {
|
||||||
|
List<Episode> list = anidb.getEpisodeList(monsterSearchResult, Locale.JAPANESE);
|
||||||
|
|
||||||
|
Episode last = list.get(73);
|
||||||
|
assertEquals("Monster", last.getSeriesName());
|
||||||
|
assertEquals("本当の怪物", last.getTitle());
|
||||||
|
assertEquals("74", last.getEpisode().toString());
|
||||||
|
assertEquals("74", last.getAbsolute().toString());
|
||||||
|
assertEquals(null, last.getSeason());
|
||||||
|
assertEquals("2005-09-28", last.airdate().toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void getEpisodeListTrimRecap() throws Exception {
|
public void getEpisodeListTrimRecap() throws Exception {
|
||||||
assertEquals("Sea God of the East, Azure Sea of the West - Transition Chapter", anidb.getEpisodeList(twelvekingdomsSearchResult).get(44).getTitle());
|
assertEquals("Sea God of the East, Azure Sea of the West - Transition Chapter", anidb.getEpisodeList(twelvekingdomsSearchResult).get(44).getTitle());
|
||||||
|
Loading…
Reference in New Issue
Block a user