mirror of
https://github.com/mitb-archive/filebot
synced 2024-12-22 07:48:52 -05:00
Refactor AnimeList client
This commit is contained in:
parent
b8d9f75de8
commit
9d0f7c9220
@ -27,7 +27,6 @@ import javax.swing.Icon;
|
|||||||
import net.filebot.media.LocalDatasource;
|
import net.filebot.media.LocalDatasource;
|
||||||
import net.filebot.similarity.MetricAvg;
|
import net.filebot.similarity.MetricAvg;
|
||||||
import net.filebot.web.AcoustIDClient;
|
import net.filebot.web.AcoustIDClient;
|
||||||
import net.filebot.web.AnidbClient;
|
|
||||||
import net.filebot.web.Artwork;
|
import net.filebot.web.Artwork;
|
||||||
import net.filebot.web.Datasource;
|
import net.filebot.web.Datasource;
|
||||||
import net.filebot.web.EpisodeListProvider;
|
import net.filebot.web.EpisodeListProvider;
|
||||||
@ -39,15 +38,12 @@ import net.filebot.web.Movie;
|
|||||||
import net.filebot.web.MovieIdentificationService;
|
import net.filebot.web.MovieIdentificationService;
|
||||||
import net.filebot.web.MusicIdentificationService;
|
import net.filebot.web.MusicIdentificationService;
|
||||||
import net.filebot.web.OMDbClient;
|
import net.filebot.web.OMDbClient;
|
||||||
import net.filebot.web.OpenSubtitlesClient;
|
|
||||||
import net.filebot.web.SearchResult;
|
import net.filebot.web.SearchResult;
|
||||||
import net.filebot.web.ShooterSubtitles;
|
import net.filebot.web.ShooterSubtitles;
|
||||||
import net.filebot.web.SubtitleProvider;
|
import net.filebot.web.SubtitleProvider;
|
||||||
import net.filebot.web.SubtitleSearchResult;
|
import net.filebot.web.SubtitleSearchResult;
|
||||||
import net.filebot.web.TMDbClient;
|
|
||||||
import net.filebot.web.TMDbTVClient;
|
import net.filebot.web.TMDbTVClient;
|
||||||
import net.filebot.web.TVMazeClient;
|
import net.filebot.web.TVMazeClient;
|
||||||
import net.filebot.web.TheTVDBClient;
|
|
||||||
import net.filebot.web.TheTVDBSearchResult;
|
import net.filebot.web.TheTVDBSearchResult;
|
||||||
import net.filebot.web.ThumbnailProvider;
|
import net.filebot.web.ThumbnailProvider;
|
||||||
import net.filebot.web.VideoHashSubtitleService;
|
import net.filebot.web.VideoHashSubtitleService;
|
||||||
@ -59,27 +55,28 @@ public final class WebServices {
|
|||||||
|
|
||||||
// movie sources
|
// movie sources
|
||||||
public static final OMDbClient OMDb = new OMDbClient(getApiKey("omdb"));
|
public static final OMDbClient OMDb = new OMDbClient(getApiKey("omdb"));
|
||||||
public static final TMDbClient TheMovieDB = new TMDbClientWithLocalSearch(getApiKey("themoviedb"));
|
public static final net.filebot.web.TMDbClient TheMovieDB = new TMDbClient(getApiKey("themoviedb"));
|
||||||
|
|
||||||
// episode sources
|
// episode sources
|
||||||
public static final TVMazeClient TVmaze = new TVMazeClient();
|
public static final TVMazeClient TVmaze = new TVMazeClient();
|
||||||
public static final AnidbClient AniDB = new AnidbClientWithLocalSearch(getApiKey("anidb"), 7);
|
public static final net.filebot.web.AnidbClient AniDB = new AnidbClient(getApiKey("anidb"), 7);
|
||||||
|
|
||||||
// extended TheTVDB module with local search
|
// extended TheTVDB module with local search
|
||||||
public static final TheTVDBClientWithLocalSearch TheTVDB = new TheTVDBClientWithLocalSearch(getApiKey("thetvdb"));
|
public static final net.filebot.web.TheTVDBClient TheTVDB = new TheTVDBClient(getApiKey("thetvdb"));
|
||||||
public static final TMDbTVClient TheMovieDB_TV = new TMDbTVClient(TheMovieDB);
|
public static final TMDbTVClient TheMovieDB_TV = new TMDbTVClient(TheMovieDB);
|
||||||
|
|
||||||
// subtitle sources
|
// subtitle sources
|
||||||
public static final OpenSubtitlesClient OpenSubtitles = new OpenSubtitlesClientWithLocalSearch(getApiKey("opensubtitles"), getApplicationVersion());
|
public static final net.filebot.web.OpenSubtitlesClient OpenSubtitles = new OpenSubtitlesClient(getApiKey("opensubtitles"), getApplicationVersion());
|
||||||
public static final ShooterSubtitles Shooter = new ShooterSubtitles();
|
public static final ShooterSubtitles Shooter = new ShooterSubtitles();
|
||||||
|
|
||||||
// other sources
|
// other sources
|
||||||
|
public static final net.filebot.web.AnimeLists AnimeList = new AnimeLists();
|
||||||
public static final FanartTVClient FanartTV = new FanartTVClient(getApiKey("fanart.tv"));
|
public static final FanartTVClient FanartTV = new FanartTVClient(getApiKey("fanart.tv"));
|
||||||
public static final AcoustIDClient AcoustID = new AcoustIDClient(getApiKey("acoustid"));
|
public static final AcoustIDClient AcoustID = new AcoustIDClient(getApiKey("acoustid"));
|
||||||
public static final ID3Lookup MediaInfoID3 = new ID3Lookup();
|
public static final ID3Lookup MediaInfoID3 = new ID3Lookup();
|
||||||
|
|
||||||
public static Datasource[] getServices() {
|
public static Datasource[] getServices() {
|
||||||
return new Datasource[] { TheMovieDB, OMDb, TheTVDB, AniDB, TheMovieDB_TV, TVmaze, AcoustID, MediaInfoID3, LocalDatasource.EXIF, LocalDatasource.XATTR, LocalDatasource.FILE, OpenSubtitles, Shooter, FanartTV };
|
return new Datasource[] { TheMovieDB, OMDb, TheTVDB, AniDB, TheMovieDB_TV, TVmaze, AcoustID, MediaInfoID3, LocalDatasource.EXIF, LocalDatasource.XATTR, LocalDatasource.FILE, OpenSubtitles, Shooter, AnimeList, FanartTV };
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MovieIdentificationService[] getMovieIdentificationServices() {
|
public static MovieIdentificationService[] getMovieIdentificationServices() {
|
||||||
@ -135,9 +132,9 @@ public final class WebServices {
|
|||||||
|
|
||||||
public static final ExecutorService requestThreadPool = Executors.newCachedThreadPool();
|
public static final ExecutorService requestThreadPool = Executors.newCachedThreadPool();
|
||||||
|
|
||||||
public static class TMDbClientWithLocalSearch extends TMDbClient implements ThumbnailProvider {
|
private static class TMDbClient extends net.filebot.web.TMDbClient implements ThumbnailProvider {
|
||||||
|
|
||||||
public TMDbClientWithLocalSearch(String apikey) {
|
public TMDbClient(String apikey) {
|
||||||
super(apikey);
|
super(apikey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -172,7 +169,7 @@ public final class WebServices {
|
|||||||
List<Callable<List<Movie>>> searches = new ArrayList<>();
|
List<Callable<List<Movie>>> searches = new ArrayList<>();
|
||||||
|
|
||||||
// online API search first
|
// online API search first
|
||||||
searches.add(() -> TMDbClientWithLocalSearch.super.searchMovie(movieName, movieYear, locale, extendedInfo));
|
searches.add(() -> TMDbClient.super.searchMovie(movieName, movieYear, locale, extendedInfo));
|
||||||
|
|
||||||
if (movieYear > 0) {
|
if (movieYear > 0) {
|
||||||
// the year might be off by 1 so we also check movies from the previous year and the next year
|
// the year might be off by 1 so we also check movies from the previous year and the next year
|
||||||
@ -200,9 +197,9 @@ public final class WebServices {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class TheTVDBClientWithLocalSearch extends TheTVDBClient implements ThumbnailProvider {
|
private static class TheTVDBClient extends net.filebot.web.TheTVDBClient implements ThumbnailProvider {
|
||||||
|
|
||||||
public TheTVDBClientWithLocalSearch(String apikey) {
|
public TheTVDBClient(String apikey) {
|
||||||
super(apikey);
|
super(apikey);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -227,7 +224,7 @@ public final class WebServices {
|
|||||||
@Override
|
@Override
|
||||||
public List<SearchResult> fetchSearchResult(String query, Locale locale) throws Exception {
|
public List<SearchResult> fetchSearchResult(String query, Locale locale) throws Exception {
|
||||||
// run local search and API search in parallel
|
// run local search and API search in parallel
|
||||||
Future<List<SearchResult>> apiSearch = requestThreadPool.submit(() -> TheTVDBClientWithLocalSearch.super.fetchSearchResult(query, locale));
|
Future<List<SearchResult>> apiSearch = requestThreadPool.submit(() -> TheTVDBClient.super.fetchSearchResult(query, locale));
|
||||||
Future<List<SearchResult>> localSearch = requestThreadPool.submit(() -> localIndex.get().search(query));
|
Future<List<SearchResult>> localSearch = requestThreadPool.submit(() -> localIndex.get().search(query));
|
||||||
|
|
||||||
// combine alias names into a single search results, and keep API search name as primary name
|
// combine alias names into a single search results, and keep API search name as primary name
|
||||||
@ -242,9 +239,9 @@ public final class WebServices {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class AnidbClientWithLocalSearch extends AnidbClient implements ThumbnailProvider {
|
private static class AnidbClient extends net.filebot.web.AnidbClient implements ThumbnailProvider {
|
||||||
|
|
||||||
public AnidbClientWithLocalSearch(String client, int clientver) {
|
public AnidbClient(String client, int clientver) {
|
||||||
super(client, clientver);
|
super(client, clientver);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -264,9 +261,17 @@ public final class WebServices {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class OpenSubtitlesClientWithLocalSearch extends OpenSubtitlesClient {
|
private static class AnimeLists extends net.filebot.web.AnimeLists {
|
||||||
|
|
||||||
public OpenSubtitlesClientWithLocalSearch(String name, String version) {
|
@Override
|
||||||
|
public net.filebot.web.AnimeLists.Model getModel() throws Exception {
|
||||||
|
return releaseInfo.getAnimeListModel();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class OpenSubtitlesClient extends net.filebot.web.OpenSubtitlesClient {
|
||||||
|
|
||||||
|
public OpenSubtitlesClient(String name, String version) {
|
||||||
super(name, version);
|
super(name, version);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ import net.filebot.mediainfo.MediaInfoException;
|
|||||||
import net.filebot.similarity.Normalization;
|
import net.filebot.similarity.Normalization;
|
||||||
import net.filebot.similarity.SimilarityComparator;
|
import net.filebot.similarity.SimilarityComparator;
|
||||||
import net.filebot.util.FileUtilities;
|
import net.filebot.util.FileUtilities;
|
||||||
import net.filebot.web.AnimeList;
|
import net.filebot.web.AnimeLists;
|
||||||
import net.filebot.web.AudioTrack;
|
import net.filebot.web.AudioTrack;
|
||||||
import net.filebot.web.Episode;
|
import net.filebot.web.Episode;
|
||||||
import net.filebot.web.EpisodeFormat;
|
import net.filebot.web.EpisodeFormat;
|
||||||
@ -797,7 +797,7 @@ public class MediaBindingBean {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (AniDB.getIdentifier().equals(e.getSeriesInfo().getDatabase())) {
|
if (AniDB.getIdentifier().equals(e.getSeriesInfo().getDatabase())) {
|
||||||
return new AnimeList().map(e, AnimeList.getDB(e), AnimeList.DB.TheTVDB).map(this::createBindingObject).orElse(null); // map AniDB to TheTVDB bindings
|
return AnimeList.map(e, AnimeLists.getDB(e), AnimeLists.DB.TheTVDB).map(this::createBindingObject).orElse(null); // map AniDB to TheTVDB bindings
|
||||||
}
|
}
|
||||||
|
|
||||||
return createBindingObject(fetchEpisode(e, SortOrder.Airdate, null));
|
return createBindingObject(fetchEpisode(e, SortOrder.Airdate, null));
|
||||||
@ -1175,13 +1175,13 @@ public class MediaBindingBean {
|
|||||||
|
|
||||||
@Define("AnimeList")
|
@Define("AnimeList")
|
||||||
public DynamicBindings getAnimeLists() {
|
public DynamicBindings getAnimeLists() {
|
||||||
return new DynamicBindings(AnimeList.DB::names, k -> {
|
return new DynamicBindings(AnimeLists.DB::names, k -> {
|
||||||
if (infoObject instanceof Episode) {
|
if (infoObject instanceof Episode) {
|
||||||
Episode e = getEpisode();
|
Episode e = getEpisode();
|
||||||
if (AnimeList.getDB(e) == AnimeList.getDB(k)) {
|
if (AnimeLists.getDB(e) == AnimeLists.getDB(k)) {
|
||||||
return e;
|
return e;
|
||||||
}
|
}
|
||||||
return new AnimeList().map(e, AnimeList.getDB(e), AnimeList.getDB(k)).orElse(e);
|
return AnimeList.map(e, AnimeLists.getDB(e), AnimeLists.getDB(k)).orElse(e);
|
||||||
}
|
}
|
||||||
return undefined(k);
|
return undefined(k);
|
||||||
});
|
});
|
||||||
|
@ -36,7 +36,6 @@ import java.util.function.IntFunction;
|
|||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
import java.util.stream.Stream;
|
|
||||||
|
|
||||||
import org.tukaani.xz.XZInputStream;
|
import org.tukaani.xz.XZInputStream;
|
||||||
|
|
||||||
@ -47,6 +46,7 @@ import net.filebot.Resource;
|
|||||||
import net.filebot.util.FileUtilities.RegexFindFilter;
|
import net.filebot.util.FileUtilities.RegexFindFilter;
|
||||||
import net.filebot.util.FileUtilities.RegexMatchFilter;
|
import net.filebot.util.FileUtilities.RegexMatchFilter;
|
||||||
import net.filebot.util.SystemProperty;
|
import net.filebot.util.SystemProperty;
|
||||||
|
import net.filebot.web.AnimeLists;
|
||||||
import net.filebot.web.Movie;
|
import net.filebot.web.Movie;
|
||||||
import net.filebot.web.SearchResult;
|
import net.filebot.web.SearchResult;
|
||||||
import net.filebot.web.SubtitleSearchResult;
|
import net.filebot.web.SubtitleSearchResult;
|
||||||
@ -385,6 +385,10 @@ public class ReleaseInfo {
|
|||||||
return osdbIndex.get();
|
return osdbIndex.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AnimeLists.Model getAnimeListModel() throws Exception {
|
||||||
|
return animeListModel.get();
|
||||||
|
}
|
||||||
|
|
||||||
private static FolderEntryFilter diskFolderFilter;
|
private static FolderEntryFilter diskFolderFilter;
|
||||||
|
|
||||||
public FileFilter getDiskFolderFilter() {
|
public FileFilter getDiskFolderFilter() {
|
||||||
@ -449,6 +453,10 @@ public class ReleaseInfo {
|
|||||||
return unmodifiableMap(map);
|
return unmodifiableMap(map);
|
||||||
}).memoize();
|
}).memoize();
|
||||||
|
|
||||||
|
private final Resource<AnimeLists.Model> animeListModel = resource("url.anime-list", Cache.ONE_WEEK, bytes -> {
|
||||||
|
return AnimeLists.unmarshal(bytes, AnimeLists.Model.class);
|
||||||
|
}).memoize();
|
||||||
|
|
||||||
private final Resource<String[]> releaseGroup = lines("url.release-groups", Cache.ONE_WEEK);
|
private final Resource<String[]> releaseGroup = lines("url.release-groups", Cache.ONE_WEEK);
|
||||||
private final Resource<String[]> queryBlacklist = lines("url.query-blacklist", Cache.ONE_WEEK);
|
private final Resource<String[]> queryBlacklist = lines("url.query-blacklist", Cache.ONE_WEEK);
|
||||||
|
|
||||||
@ -495,14 +503,17 @@ public class ReleaseInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected <A> Resource<A[]> resource(String name, Duration expirationTime, Function<String, A> parse, IntFunction<A[]> generator) {
|
protected <A> Resource<A[]> resource(String name, Duration expirationTime, Function<String, A> parse, IntFunction<A[]> generator) {
|
||||||
|
// all data files are UTF-8 encoded XZ compressed text files
|
||||||
|
return resource(name, expirationTime, bytes -> {
|
||||||
|
return NEWLINE.splitAsStream(UTF_8.decode(ByteBuffer.wrap(bytes))).filter(s -> s.length() > 0).map(parse).filter(Objects::nonNull).toArray(generator);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected <A> Resource<A> resource(String name, Duration expirationTime, Function<byte[], A> parse) {
|
||||||
return () -> {
|
return () -> {
|
||||||
Cache cache = Cache.getCache("data", CacheType.Persistent);
|
Cache cache = Cache.getCache("data", CacheType.Persistent);
|
||||||
byte[] bytes = cache.bytes(name, n -> new URL(getProperty(n)), XZInputStream::new).expire(refreshDuration.optional().orElse(expirationTime)).get();
|
byte[] bytes = cache.bytes(name, n -> new URL(getProperty(n)), XZInputStream::new).expire(refreshDuration.optional().orElse(expirationTime)).get();
|
||||||
|
return parse.apply(bytes);
|
||||||
// all data files are UTF-8 encoded XZ compressed text files
|
|
||||||
Stream<String> lines = NEWLINE.splitAsStream(UTF_8.decode(ByteBuffer.wrap(bytes)));
|
|
||||||
|
|
||||||
return lines.filter(s -> s.length() > 0).map(parse).filter(Objects::nonNull).toArray(generator);
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -46,6 +46,9 @@ url.anidb-index: @{url.data}/anidb.txt.xz
|
|||||||
# OpenSubtitles index
|
# OpenSubtitles index
|
||||||
url.osdb-index: @{url.data}/osdb.txt.xz
|
url.osdb-index: @{url.data}/osdb.txt.xz
|
||||||
|
|
||||||
|
# Anime List mappings
|
||||||
|
url.anime-list: @{url.data}/anime-list.xml.xz
|
||||||
|
|
||||||
# disk folder matcher
|
# disk folder matcher
|
||||||
pattern.diskfolder.entry: BDMV|HVDVD_TS|VIDEO_TS|AUDIO_TS|VCD|MovieObject.bdmv|VIDEO_TS.VOB|VTS_[0-9]+_[0-9]+.VOB
|
pattern.diskfolder.entry: BDMV|HVDVD_TS|VIDEO_TS|AUDIO_TS|VCD|MovieObject.bdmv|VIDEO_TS.VOB|VTS_[0-9]+_[0-9]+.VOB
|
||||||
|
|
||||||
|
@ -223,7 +223,7 @@ public class AnidbClient extends AbstractEpisodeListProvider implements ArtworkP
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is overridden in {@link net.filebot.WebServices.AnidbClientWithLocalSearch} to fetch the Anime Index from our own host and not anidb.net
|
* This method is overridden in {@link net.filebot.WebServices.AnidbClient} to fetch the Anime Index from our own host and not anidb.net
|
||||||
*/
|
*/
|
||||||
public SearchResult[] getAnimeTitles() throws Exception {
|
public SearchResult[] getAnimeTitles() throws Exception {
|
||||||
// get data file (unzip and cache)
|
// get data file (unzip and cache)
|
||||||
|
@ -2,7 +2,6 @@ package net.filebot.web;
|
|||||||
|
|
||||||
import static java.util.Arrays.*;
|
import static java.util.Arrays.*;
|
||||||
import static java.util.stream.Collectors.*;
|
import static java.util.stream.Collectors.*;
|
||||||
import static net.filebot.CachedResource.*;
|
|
||||||
import static net.filebot.Logging.*;
|
import static net.filebot.Logging.*;
|
||||||
import static net.filebot.util.RegularExpressions.*;
|
import static net.filebot.util.RegularExpressions.*;
|
||||||
import static net.filebot.util.StringUtilities.*;
|
import static net.filebot.util.StringUtilities.*;
|
||||||
@ -16,6 +15,7 @@ import java.util.Optional;
|
|||||||
import java.util.stream.IntStream;
|
import java.util.stream.IntStream;
|
||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import javax.swing.Icon;
|
||||||
import javax.xml.bind.JAXBContext;
|
import javax.xml.bind.JAXBContext;
|
||||||
import javax.xml.bind.Marshaller;
|
import javax.xml.bind.Marshaller;
|
||||||
import javax.xml.bind.annotation.XmlAttribute;
|
import javax.xml.bind.annotation.XmlAttribute;
|
||||||
@ -28,19 +28,18 @@ import javax.xml.bind.annotation.adapters.XmlJavaTypeAdapter;
|
|||||||
|
|
||||||
import net.filebot.Cache;
|
import net.filebot.Cache;
|
||||||
import net.filebot.CacheType;
|
import net.filebot.CacheType;
|
||||||
import net.filebot.Resource;
|
|
||||||
import net.filebot.WebServices;
|
import net.filebot.WebServices;
|
||||||
|
|
||||||
public class AnimeList {
|
public class AnimeLists implements Datasource {
|
||||||
|
|
||||||
private Model model;
|
@Override
|
||||||
|
public String getIdentifier() {
|
||||||
public AnimeList() throws Exception {
|
return "AnimeLists";
|
||||||
this.model = MODEL.get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Model getModel() {
|
@Override
|
||||||
return model;
|
public Icon getIcon() {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Episode> map(Episode episode, DB source, DB destination) throws Exception {
|
public Optional<Episode> map(Episode episode, DB source, DB destination) throws Exception {
|
||||||
@ -84,7 +83,7 @@ public class AnimeList {
|
|||||||
}).findFirst();
|
}).findFirst();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Episode derive(DB db, Entry a, Episode episode, int s, int e) {
|
protected Episode derive(DB db, Entry a, Episode episode, int s, int e) {
|
||||||
if (s == 0) {
|
if (s == 0) {
|
||||||
// special
|
// special
|
||||||
switch (db) {
|
switch (db) {
|
||||||
@ -202,7 +201,7 @@ public class AnimeList {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Stream<Entry> find(DB db, int id) throws Exception {
|
public Stream<Entry> find(DB db, int id) throws Exception {
|
||||||
return stream(model.anime).filter(this::isValid).filter(a -> id == getId(db, a));
|
return stream(getModel().anime).filter(this::isValid).filter(a -> id == getId(db, a));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Stream<Entry> find(DB db, int id, int s) throws Exception {
|
public Stream<Entry> find(DB db, int id, int s) throws Exception {
|
||||||
@ -214,21 +213,10 @@ public class AnimeList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static Cache getCache() {
|
public Model getModel() throws Exception {
|
||||||
return Cache.getCache("animelists", CacheType.Persistent);
|
return Cache.getCache(getIdentifier(), CacheType.Monthly).bytes("https://github.com/ScudLee/anime-lists/raw/master/anime-list.xml", URL::new).transform(bytes -> {
|
||||||
}
|
return unmarshal(bytes, Model.class);
|
||||||
|
}).get();
|
||||||
protected static final Resource<Model> MODEL = Resource.lazy(() -> unmarshal(request("anime-list.xml"), Model.class));
|
|
||||||
|
|
||||||
protected static byte[] request(String file) throws Exception {
|
|
||||||
// NOTE: GitHub only supports If-None-Match (If-Modified-Since is ignored)
|
|
||||||
Cache cache = getCache();
|
|
||||||
|
|
||||||
return cache.bytes(file, AnimeList::getResource).fetch(fetchIfNoneMatch(url -> file, cache)).expire(Cache.ONE_MONTH).get();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected static URL getResource(String file) throws Exception {
|
|
||||||
return new URL("https://raw.githubusercontent.com/ScudLee/anime-lists/master/" + file);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static DB getDB(Episode e) {
|
public static DB getDB(Episode e) {
|
||||||
@ -325,10 +313,9 @@ public class AnimeList {
|
|||||||
public String toString() {
|
public String toString() {
|
||||||
return marshal(this, Mapping.class);
|
return marshal(this, Mapping.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NumberAdapter extends XmlAdapter<String, Integer> {
|
protected static class NumberAdapter extends XmlAdapter<String, Integer> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Integer unmarshal(String s) throws Exception {
|
public Integer unmarshal(String s) throws Exception {
|
||||||
@ -341,7 +328,7 @@ public class AnimeList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class NumberMapAdapter extends XmlAdapter<String, int[][]> {
|
protected static class NumberMapAdapter extends XmlAdapter<String, int[][]> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int[][] unmarshal(String s) throws Exception {
|
public int[][] unmarshal(String s) throws Exception {
|
||||||
@ -354,15 +341,19 @@ public class AnimeList {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> T unmarshal(byte[] bytes, Class<T> type) throws Exception {
|
public static <T> T unmarshal(byte[] bytes, Class<T> type) {
|
||||||
return (T) JAXBContext.newInstance(type).createUnmarshaller().unmarshal(new ByteArrayInputStream(bytes));
|
try {
|
||||||
|
return (T) JAXBContext.newInstance(type).createUnmarshaller().unmarshal(new ByteArrayInputStream(bytes));
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new IllegalArgumentException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static <T> String marshal(T object, Class<T> type) {
|
public static <T> String marshal(T object, Class<T> type) {
|
||||||
try {
|
try {
|
||||||
StringWriter buffer = new StringWriter();
|
StringWriter buffer = new StringWriter();
|
||||||
Marshaller marshaller = JAXBContext.newInstance(type).createMarshaller();
|
Marshaller marshaller = JAXBContext.newInstance(type).createMarshaller();
|
||||||
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
|
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.FALSE);
|
||||||
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
|
marshaller.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
|
||||||
marshaller.marshal(object, buffer);
|
marshaller.marshal(object, buffer);
|
||||||
return buffer.toString();
|
return buffer.toString();
|
@ -55,7 +55,7 @@ public final class EpisodeUtilities {
|
|||||||
if (episode.isAnime() && episode.isRegular()) {
|
if (episode.isAnime() && episode.isRegular()) {
|
||||||
return mapEpisode(episode, e -> {
|
return mapEpisode(episode, e -> {
|
||||||
try {
|
try {
|
||||||
return new AnimeList().map(e, AnimeList.getDB(e), AnimeList.DB.TheTVDB).orElse(e);
|
return AnimeList.map(e, AnimeLists.getDB(e), AnimeLists.DB.TheTVDB).orElse(e);
|
||||||
} catch (Exception ioe) {
|
} catch (Exception ioe) {
|
||||||
debug.warning(ioe::toString);
|
debug.warning(ioe::toString);
|
||||||
return e;
|
return e;
|
||||||
|
Loading…
Reference in New Issue
Block a user