Merge pull request #592 from wushuo894/test

refactor: 拆分tmdb-api
This commit is contained in:
wushuo
2025-12-22 16:52:49 +08:00
committed by GitHub
34 changed files with 406 additions and 1352 deletions

View File

@@ -18,6 +18,10 @@
</properties>
<dependencies>
<dependency>
<groupId>wushuo.tmdb.api</groupId>
<artifactId>tmdb-api</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>

View File

@@ -1,8 +1,8 @@
package ani.rss.entity;
import ani.rss.entity.tmdb.Tmdb;
import lombok.Data;
import lombok.experimental.Accessors;
import wushuo.tmdb.api.entity.Tmdb;
import java.io.Serializable;
import java.util.List;

View File

@@ -1,141 +0,0 @@
package ani.rss.entity.tmdb;
import ani.rss.enums.TmdbTypeEnum;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* tmdb
*/
@Data
@Accessors(chain = true)
public class Tmdb implements Serializable {
/**
* id
*/
private String id;
/**
* 名称
*/
@SerializedName(value = "name", alternate = "title")
private String name;
/**
* 原名
*/
@SerializedName(value = "originalName", alternate = {"original_name", "original_title"})
private String originalName;
/**
* 剧集组id
*/
@SerializedName(value = "tmdbGroupId", alternate = "tmdb_group_id")
private String tmdbGroupId;
/**
* 概述
*/
private String overview;
/**
* 平均评分
*/
@SerializedName(value = "voteAverage", alternate = "vote_average")
private String voteAverage;
/**
* 评分人数
*/
@SerializedName(value = "voteCount", alternate = "vote_count")
private String voteCount;
/**
* 封面
*/
@SerializedName(value = "posterPath", alternate = "poster_path")
private String posterPath;
/**
* 背景图
*/
@SerializedName(value = "backdropPath", alternate = "backdrop_path")
private String backdropPath;
/**
* 成人
*/
private Boolean adult;
/**
* 原语言
*/
@SerializedName(value = "originalLanguage", alternate = "original_language")
private String originalLanguage;
/**
* 原产地
*/
@SerializedName(value = "originCountry", alternate = "origin_country")
private List<String> originCountry;
/**
* 首映日期
*/
@SerializedName(value = "date", alternate = {"first_air_date", "release_date"})
private Date date;
/**
* 种类
*/
@SerializedName(value = "genreIds", alternate = "genre_ids")
private List<Integer> genreIds;
/**
* 主页
*/
private String homepage;
/**
* 种类
*/
private List<TmdbGenres> genres;
/**
* 演职人员
*/
private TmdbCredits credits;
/**
* 工作室
*/
@SerializedName(value = "networks", alternate = "production_companies")
private List<TmdbNetwork> networks;
/**
* 预告片
*/
private List<TmdbVideo> videos;
/**
* 时长
*/
private Integer runtime;
/**
* 宣传语
*/
private String tagline;
/**
* 翻译
*/
private TmdbTranslations translations;
private TmdbTypeEnum tmdbType;
}

View File

@@ -1,16 +0,0 @@
package ani.rss.entity.tmdb;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
* 演职人员
*/
@Data
@Accessors(chain = true)
public class TmdbCredits implements Serializable {
private List<TmdbCreditsCast> cast;
}

View File

@@ -1,46 +0,0 @@
package ani.rss.entity.tmdb;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 演职人员
*/
@Data
@Accessors(chain = true)
public class TmdbCreditsCast implements Serializable {
private Integer id;
private String name;
@SerializedName(value = "originalName", alternate = "original_name")
private String originalName;
private Double popularity;
@SerializedName(value = "profilePath", alternate = "profile_path")
private String profilePath;
private String character;
@SerializedName(value = "creditId", alternate = "credit_id")
private String creditId;
private String order;
/**
* 成人
*/
private Boolean adult;
/**
* 性别
*/
public Integer gender;
@SerializedName(value = "knownForDepartment", alternate = "known_for_department")
private String knownForDepartment;
}

View File

@@ -1,46 +0,0 @@
package ani.rss.entity.tmdb;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
/**
* 集
*/
@Data
@Accessors(chain = true)
public class TmdbEpisode implements Serializable {
private Integer id;
@SerializedName(value = "airDate", alternate = "air_date")
private Date airDate;
@SerializedName(value = "episodeNumber", alternate = "episode_number")
private Integer episodeNumber;
@SerializedName(value = "episodeType", alternate = "episode_type")
private String episodeType;
private String name;
private String overview;
private String runtime;
@SerializedName(value = "seasonNumber", alternate = "season_number")
private Integer seasonNumber;
@SerializedName(value = "showId", alternate = "show_id")
private Integer showId;
@SerializedName(value = "stillPath", alternate = "still_path")
private String stillPath;
@SerializedName(value = "voteAverage", alternate = "vote_average")
private Double voteAverage;
private Integer order;
}

View File

@@ -1,16 +0,0 @@
package ani.rss.entity.tmdb;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 类型
*/
@Data
@Accessors(chain = true)
public class TmdbGenres implements Serializable {
private Integer id;
private String name;
}

View File

@@ -1,52 +0,0 @@
package ani.rss.entity.tmdb;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* tmdb剧集组
*/
@Data
@Accessors(chain = true)
public class TmdbGroup implements Serializable {
/**
* id
*/
private String id;
/**
* 剧集组名
*/
private String name;
/**
* 类型
*/
private Integer type;
/**
* 类型名
*/
@SerializedName(value = "typeName", alternate = "type_name")
private String typeName;
/**
* 集数量
*/
@SerializedName(value = "episodeCount", alternate = "episode_count")
private String episodeCount;
/**
* 组数量
*/
@SerializedName(value = "groupCount", alternate = "group_count")
private String groupCount;
/**
* 描述
*/
private String description;
}

View File

@@ -1,36 +0,0 @@
package ani.rss.entity.tmdb;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 图片
*/
@Data
@Accessors(chain = true)
public class TmdbImage implements Serializable {
@SerializedName(value = "aspectRatio", alternate = "aspect_ratio")
private Double aspectRatio;
private Integer width;
private Integer height;
@SerializedName(value = "iso31661", alternate = "iso_3166_1")
private String iso31661;
@SerializedName(value = "iso6391", alternate = "iso_639_1")
private String iso6391;
@SerializedName(value = "filePath", alternate = "file_path")
private String filePath;
@SerializedName(value = "voteAverage", alternate = "vote_average")
private Double voteAverage;
@SerializedName(value = "voteCount", alternate = "vote_count")
private Integer voteCount;
}

View File

@@ -1,31 +0,0 @@
package ani.rss.entity.tmdb;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
* 图片列表
*/
@Data
@Accessors(chain = true)
public class TmdbImages implements Serializable {
private String id;
/**
* logo
*/
private List<TmdbImage> logos;
/**
* 封面
*/
private List<TmdbImage> posters;
/**
* 背景
*/
private List<TmdbImage> backdrops;
}

View File

@@ -1,24 +0,0 @@
package ani.rss.entity.tmdb;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 工作室
*/
@Data
@Accessors(chain = true)
public class TmdbNetwork implements Serializable {
private String id;
@SerializedName(value = "logoPath", alternate = "logo_path")
private String logoPath;
private String name;
@SerializedName(value = "originCountry", alternate = "origin_country")
private String originCountry;
}

View File

@@ -1,41 +0,0 @@
package ani.rss.entity.tmdb;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
/**
* 季
*/
@Data
@Accessors(chain = true)
public class TmdbSeason implements Serializable {
private String id;
@SerializedName(value = "seasonNumber", alternate = "season_number")
private Integer seasonNumber;
@SerializedName(value = "voteAverage", alternate = "vote_average")
private Double voteAverage;
@SerializedName(value = "airDate", alternate = "air_date")
private Date airDate;
private String name;
private String overview;
@SerializedName(value = "episodes")
private List<TmdbEpisode> episodes;
@SerializedName(value = "posterPath", alternate = "poster_path")
private String posterPath;
private Integer order;
}

View File

@@ -1,21 +0,0 @@
package ani.rss.entity.tmdb;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 标题
*/
@Data
@Accessors(chain = true)
public class TmdbTitle implements Serializable {
private String title;
private String type;
@SerializedName(value = "iso31661", alternate = "iso_3166_1")
private String iso31661;
}

View File

@@ -1,27 +0,0 @@
package ani.rss.entity.tmdb;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 翻译
*/
@Data
@Accessors(chain = true)
public class TmdbTranslation implements Serializable {
@SerializedName(value = "iso31661", alternate = "iso_3166_1")
private String iso31661;
@SerializedName(value = "iso6391", alternate = "iso_639_1")
private String iso6391;
private String name;
@SerializedName(value = "englishName", alternate = "english_name")
private String englishName;
private TmdbTranslationData data;
}

View File

@@ -1,21 +0,0 @@
package ani.rss.entity.tmdb;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
/**
* 翻译
*/
@Data
@Accessors(chain = true)
public class TmdbTranslationData implements Serializable {
private String name;
private String overview;
private String homepage;
private String tagline;
}

View File

@@ -1,16 +0,0 @@
package ani.rss.entity.tmdb;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.List;
/**
* 翻译
*/
@Data
@Accessors(chain = true)
public class TmdbTranslations implements Serializable {
private List<TmdbTranslation> translations;
}

View File

@@ -1,35 +0,0 @@
package ani.rss.entity.tmdb;
import com.google.gson.annotations.SerializedName;
import lombok.Data;
import lombok.experimental.Accessors;
import java.io.Serializable;
import java.util.Date;
@Data
@Accessors(chain = true)
public class TmdbVideo implements Serializable {
private String id;
private String name;
private String key;
private String site;
private Integer size;
private String type;
private Boolean official;
@SerializedName(value = "publishedAt", alternate = "published_at")
private Date publishedAt;
@SerializedName(value = "iso31661", alternate = "iso_3166_1")
private String iso31661;
@SerializedName(value = "iso6391", alternate = "iso_639_1")
private String iso6391;
}

View File

@@ -1,12 +0,0 @@
package ani.rss.enums;
import lombok.AllArgsConstructor;
import lombok.Getter;
@AllArgsConstructor
public enum TmdbTypeEnum {
MOVIE("movie"), TV("tv");
@Getter
private final String value;
}

View File

@@ -2,7 +2,6 @@ package ani.rss.action;
import ani.rss.entity.Ani;
import ani.rss.entity.BgmInfo;
import ani.rss.entity.tmdb.Tmdb;
import ani.rss.util.other.AniUtil;
import ani.rss.util.other.BgmUtil;
import ani.rss.web.action.BaseAction;
@@ -13,6 +12,7 @@ import cn.hutool.http.server.HttpServerRequest;
import cn.hutool.http.server.HttpServerResponse;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import wushuo.tmdb.api.entity.Tmdb;
import java.io.IOException;
import java.util.Objects;

View File

@@ -3,7 +3,6 @@ package ani.rss.action;
import ani.rss.entity.Ani;
import ani.rss.entity.BgmInfo;
import ani.rss.entity.NotificationConfig;
import ani.rss.entity.tmdb.Tmdb;
import ani.rss.enums.NotificationStatusEnum;
import ani.rss.enums.NotificationTypeEnum;
import ani.rss.notification.BaseNotification;
@@ -16,6 +15,7 @@ import ani.rss.web.annotation.Path;
import cn.hutool.core.util.ReflectUtil;
import cn.hutool.http.server.HttpServerRequest;
import cn.hutool.http.server.HttpServerResponse;
import wushuo.tmdb.api.entity.Tmdb;
import java.io.IOException;
import java.util.Date;

View File

@@ -2,8 +2,7 @@ package ani.rss.action;
import ani.rss.entity.Ani;
import ani.rss.entity.Result;
import ani.rss.entity.tmdb.Tmdb;
import ani.rss.util.other.TmdbUtil;
import ani.rss.util.other.TmdbUtils;
import ani.rss.web.action.BaseAction;
import ani.rss.web.annotation.Auth;
import ani.rss.web.annotation.Path;
@@ -12,6 +11,7 @@ import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpStatus;
import cn.hutool.http.server.HttpServerRequest;
import cn.hutool.http.server.HttpServerResponse;
import wushuo.tmdb.api.entity.Tmdb;
import java.io.IOException;
@@ -26,7 +26,7 @@ public class ThemoviedbAction implements BaseAction {
String s = request.getParam("method");
if ("getThemoviedbName".equals(s)) {
Ani ani = getBody(Ani.class);
String themoviedbName = TmdbUtil.getFinalName(ani);
String themoviedbName = TmdbUtils.getFinalName(ani);
Result<Ani> result = new Result<Ani>()
.setCode(HttpStatus.HTTP_OK)
.setMessage("获取TMDB成功")
@@ -44,7 +44,7 @@ public class ThemoviedbAction implements BaseAction {
Tmdb tmdb = ani.getTmdb();
Assert.notNull(tmdb, "tmdb is null");
Assert.notBlank(tmdb.getId(), "tmdb is null");
resultSuccess(TmdbUtil.getTmdbGroup(tmdb));
resultSuccess(TmdbUtils.getTmdbGroup(tmdb));
}
}
}

View File

@@ -4,7 +4,6 @@ import ani.rss.commons.GsonStatic;
import ani.rss.entity.Ani;
import ani.rss.entity.Config;
import ani.rss.entity.EmbyWebHook;
import ani.rss.entity.tmdb.Tmdb;
import ani.rss.enums.StringEnum;
import ani.rss.service.DownloadService;
import ani.rss.util.other.*;
@@ -19,6 +18,7 @@ import cn.hutool.http.server.HttpServerRequest;
import cn.hutool.http.server.HttpServerResponse;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import wushuo.tmdb.api.entity.Tmdb;
import java.io.File;
import java.io.IOException;

View File

@@ -0,0 +1,61 @@
package ani.rss.entity;
import ani.rss.util.other.ConfigUtil;
import cn.hutool.core.util.StrUtil;
import wushuo.tmdb.api.entity.TmdbConfig;
public class CustomTmdbConfig extends TmdbConfig {
public final static Config CONFIG = ConfigUtil.CONFIG;
public CustomTmdbConfig() {
super("");
}
@Override
public String getTmdbApi() {
return CONFIG.getTmdbApi();
}
@Override
public String getTmdbApiKey() {
String tmdbApiKey = CONFIG.getTmdbApiKey();
tmdbApiKey = StrUtil.blankToDefault(tmdbApiKey, "450e4f651e1c93e31383e20f8e731e5f");
return tmdbApiKey;
}
@Override
public String getTmdbLanguage() {
return CONFIG.getTmdbLanguage();
}
@Override
public Boolean getTmdbAnime() {
return CONFIG.getTmdbAnime();
}
@Override
public Boolean getProxy() {
return CONFIG.getProxy();
}
@Override
public String getProxyHost() {
return CONFIG.getProxyHost();
}
@Override
public Integer getProxyPort() {
return CONFIG.getProxyPort();
}
@Override
public String getProxyUsername() {
return CONFIG.getProxyUsername();
}
@Override
public String getProxyPassword() {
return CONFIG.getProxyPassword();
}
}

View File

@@ -4,7 +4,6 @@ import ani.rss.commons.NumberFormatUtils;
import ani.rss.entity.Ani;
import ani.rss.entity.Config;
import ani.rss.entity.NotificationConfig;
import ani.rss.entity.tmdb.Tmdb;
import ani.rss.enums.NotificationStatusEnum;
import ani.rss.enums.StringEnum;
import ani.rss.service.DownloadService;
@@ -16,6 +15,7 @@ import cn.hutool.core.lang.func.Func1;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import wushuo.tmdb.api.entity.Tmdb;
import java.util.List;
import java.util.Optional;

View File

@@ -5,7 +5,6 @@ import ani.rss.commons.FileUtils;
import ani.rss.commons.GsonStatic;
import ani.rss.download.BaseDownload;
import ani.rss.entity.*;
import ani.rss.entity.tmdb.Tmdb;
import ani.rss.enums.NotificationStatusEnum;
import ani.rss.enums.StringEnum;
import ani.rss.enums.TorrentsTags;
@@ -24,6 +23,7 @@ import cn.hutool.extra.pinyin.PinyinUtil;
import cn.hutool.json.JSONUtil;
import lombok.Synchronized;
import lombok.extern.slf4j.Slf4j;
import wushuo.tmdb.api.entity.Tmdb;
import java.io.File;
import java.util.*;

View File

@@ -1,6 +1,5 @@
package ani.rss.service;
import ani.rss.entity.tmdb.*;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.FileUtil;
@@ -8,6 +7,7 @@ import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import wushuo.tmdb.api.entity.*;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

View File

@@ -3,16 +3,16 @@ package ani.rss.service;
import ani.rss.commons.FileUtils;
import ani.rss.download.BaseDownload;
import ani.rss.entity.Ani;
import ani.rss.entity.tmdb.*;
import ani.rss.enums.StringEnum;
import ani.rss.enums.TmdbTypeEnum;
import ani.rss.util.basic.HttpReq;
import ani.rss.util.other.TmdbUtil;
import ani.rss.util.other.TmdbUtils;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import wushuo.tmdb.api.entity.*;
import wushuo.tmdb.api.enums.TmdbTypeEnum;
import java.io.File;
import java.io.InputStream;
@@ -66,7 +66,12 @@ public class ScrapeService {
Tmdb tmdb = ani.getTmdb();
// 更新tmdb信息
tmdb = TmdbUtil.getTmdb(tmdb, TmdbTypeEnum.MOVIE);
Optional<Tmdb> tmdbOptional = TmdbUtils.getTmdb(tmdb, TmdbTypeEnum.MOVIE);
if (tmdbOptional.isEmpty()) {
log.warn("获取tmdb失败 {}", tmdb.getId());
return;
}
tmdb = tmdbOptional.get();
// 下载位置
String downloadPath = DownloadService.getDownloadPath(ani);
@@ -113,7 +118,7 @@ public class ScrapeService {
saveImages(posterPath, posterFile, force);
saveImages(fanartPath, fanartFile, force);
TmdbImages tmdbImages = TmdbUtil.getTmdbImages(tmdb, TmdbTypeEnum.MOVIE);
TmdbImages tmdbImages = TmdbUtils.getTmdbImages(tmdb, TmdbTypeEnum.MOVIE);
List<TmdbImage> logos = tmdbImages.getLogos();
if (logos.isEmpty()) {
return;
@@ -138,7 +143,12 @@ public class ScrapeService {
Tmdb tmdb = ani.getTmdb();
// 更新tmdb信息
tmdb = TmdbUtil.getTmdb(tmdb, TmdbTypeEnum.TV);
Optional<Tmdb> tmdbOptional = TmdbUtils.getTmdb(tmdb, TmdbTypeEnum.TV);
if (tmdbOptional.isEmpty()) {
log.warn("获取tmdb失败 {}", tmdb.getId());
return;
}
tmdb = tmdbOptional.get();
// 下载位置
File downloadPath = new File(DownloadService.getDownloadPath(ani));
@@ -166,7 +176,7 @@ public class ScrapeService {
saveImages(fanartPath, fanartFile, force);
// 保存logo
TmdbImages tmdbImages = TmdbUtil.getTmdbImages(tmdb, TmdbTypeEnum.TV);
TmdbImages tmdbImages = TmdbUtils.getTmdbImages(tmdb, TmdbTypeEnum.TV);
List<TmdbImage> logos = tmdbImages.getLogos();
if (!logos.isEmpty()) {
TmdbImage tmdbImage = logos.get(0);
@@ -178,7 +188,7 @@ public class ScrapeService {
Integer season = ani.getSeason();
Optional<TmdbSeason> optional = TmdbUtil.getTmdbSeason(tmdb, season);
Optional<TmdbSeason> optional = TmdbUtils.getTmdbSeason(tmdb, season);
if (optional.isEmpty()) {
return;
}

View File

@@ -3,7 +3,6 @@ package ani.rss.util.other;
import ani.rss.commons.FileUtils;
import ani.rss.commons.GsonStatic;
import ani.rss.entity.*;
import ani.rss.entity.tmdb.Tmdb;
import ani.rss.service.ClearService;
import ani.rss.service.DownloadService;
import ani.rss.util.basic.HttpReq;
@@ -20,6 +19,7 @@ import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import cn.hutool.json.JSONUtil;
import lombok.extern.slf4j.Slf4j;
import wushuo.tmdb.api.entity.Tmdb;
import java.io.File;
import java.nio.charset.StandardCharsets;

View File

@@ -5,7 +5,6 @@ import ani.rss.commons.GsonStatic;
import ani.rss.entity.Ani;
import ani.rss.entity.BgmInfo;
import ani.rss.entity.Config;
import ani.rss.entity.tmdb.Tmdb;
import ani.rss.enums.BgmTokenTypeEnum;
import ani.rss.service.DownloadService;
import ani.rss.util.basic.HttpReq;
@@ -29,6 +28,7 @@ import cn.hutool.json.JSONUtil;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import wushuo.tmdb.api.entity.Tmdb;
import java.util.*;
import java.util.concurrent.CompletableFuture;
@@ -89,7 +89,7 @@ public class BgmUtil {
title = StrFormatter.format("{} ({})", title, DateUtil.year(date));
}
return TmdbUtil.getFinalName(title, tmdb);
return TmdbUtils.getFinalName(title, tmdb);
}
/**
@@ -821,7 +821,7 @@ public class BgmUtil {
.setCover(AniUtil.saveJpg(image));
// 获取tmdb标题
String themoviedbName = TmdbUtil.getFinalName(ani);
String themoviedbName = TmdbUtils.getFinalName(ani);
// 是否使用tmdb标题
if (StrUtil.isNotBlank(themoviedbName) && tmdb) {

View File

@@ -5,7 +5,6 @@ import ani.rss.entity.Ani;
import ani.rss.entity.BgmInfo;
import ani.rss.entity.Config;
import ani.rss.entity.Item;
import ani.rss.entity.tmdb.Tmdb;
import ani.rss.enums.StringEnum;
import cn.hutool.core.lang.Opt;
import cn.hutool.core.lang.func.Func1;
@@ -14,6 +13,7 @@ import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import wushuo.tmdb.api.entity.Tmdb;
import java.util.*;
import java.util.function.Function;
@@ -189,7 +189,7 @@ public class RenameUtil {
Map<Integer, Function<Boolean, String>> bgmEpisodeTitleMap = new HashMap<>();
if (template.contains("${episodeTitle}")) {
episodeTitleMap = TmdbUtil.getEpisodeTitleMap(ani);
episodeTitleMap = TmdbUtils.getEpisodeTitleMap(ani);
}
if (template.contains("${bgmEpisodeTitle}") || template.contains("${bgmJpEpisodeTitle}")) {

View File

@@ -1,734 +0,0 @@
package ani.rss.util.other;
import ani.rss.commons.CacheUtils;
import ani.rss.commons.ExceptionUtils;
import ani.rss.commons.GsonStatic;
import ani.rss.entity.Ani;
import ani.rss.entity.Config;
import ani.rss.entity.tmdb.*;
import ani.rss.enums.TmdbTypeEnum;
import ani.rss.util.basic.HttpReq;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.thread.ThreadUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.core.util.URLUtil;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import lombok.extern.slf4j.Slf4j;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.function.ToDoubleFunction;
/**
* tmdb封装
*/
@Slf4j
public class TmdbUtil {
/**
* api
*
* @return
*/
public static String getTmdbApi() {
Config config = ConfigUtil.CONFIG;
String tmdbApi = config.getTmdbApi();
tmdbApi = StrUtil.blankToDefault(tmdbApi, "https://api.themoviedb.org");
return tmdbApi;
}
/**
* apiKey
*
* @return
*/
public static String getTmdbApiKey() {
Config config = ConfigUtil.CONFIG;
String tmdbApiKey = config.getTmdbApiKey();
return StrUtil.blankToDefault(tmdbApiKey, "450e4f651e1c93e31383e20f8e731e5f");
}
/**
* 获取番剧在tmdb的名称
*
* @param ani 订阅
* @return
*/
public synchronized static String getFinalName(Ani ani) {
Boolean ova = ani.getOva();
String name = ani.getTitle();
name = RenameUtil.renameDel(name, false);
if (StrUtil.isBlank(name)) {
return "";
}
Tmdb tmdb;
try {
if (ova) {
tmdb = getTmdbMovie(name);
} else {
tmdb = getTmdbTv(name);
}
} catch (Exception e) {
String message = ExceptionUtils.getMessage(e);
log.error(message, e);
return "";
}
ani.setTmdb(tmdb);
if (Objects.isNull(tmdb)) {
return "";
}
String themoviedbName = tmdb.getName();
return getFinalName(themoviedbName, tmdb);
}
/**
* 获取添加tmdbid与年份后的名称
*
* @param title 标题
* @param tmdb tmdb
* @return
*/
public static String getFinalName(String title, Tmdb tmdb) {
if (Objects.isNull(tmdb)) {
return title;
}
Config config = ConfigUtil.CONFIG;
boolean titleYear = config.getTitleYear();
if (titleYear) {
title = RenameUtil.renameDel(title, false);
title = StrFormatter.format("{} ({})", title, DateUtil.year(tmdb.getDate()));
}
boolean tmdbId = config.getTmdbId();
boolean tmdbIdPlexMode = config.getTmdbIdPlexMode();
if (tmdbId) {
if (tmdbIdPlexMode) {
title = StrFormatter.format("{} {tmdb-{}}", title, tmdb.getId());
} else {
title = StrFormatter.format("{} [tmdbid={}]", title, tmdb.getId());
}
}
return RenameUtil.getName(title);
}
/**
* 获取所有标题
*
* @param tmdb tmdb
* @param tmdbType 类型
* @return
*/
public static List<TmdbTitle> getTitles(Tmdb tmdb, TmdbTypeEnum tmdbType) {
if (Objects.isNull(tmdb)) {
return List.of();
}
String tmdbApi = getTmdbApi();
String tmdbApiKey = getTmdbApiKey();
String id = tmdb.getId();
String url = StrFormatter.format("{}/3/{}/{}/alternative_titles", tmdbApi, tmdbType.getValue(), id);
List<TmdbTitle> tmdbTitles = HttpReq.get(url)
.timeout(5000)
.form("api_key", tmdbApiKey)
.form("include_adult", "true")
.thenFunction(res -> {
HttpReq.assertStatus(res);
JsonObject jsonObject = GsonStatic.fromJson(res.body(), JsonObject.class);
return GsonStatic.fromJsonList(
jsonObject.getAsJsonArray("results"),
TmdbTitle.class);
});
for (TmdbTitle tmdbTitle : tmdbTitles) {
String name = RenameUtil.getName(tmdbTitle.getTitle());
tmdbTitle.setTitle(name);
}
return tmdbTitles;
}
/**
* 获取罗马音
*
* @param tmdb tmdb
* @param tmdbType 类型
*/
public static void getRomaji(Tmdb tmdb, TmdbTypeEnum tmdbType) {
if (Objects.isNull(tmdb)) {
return;
}
Config config = ConfigUtil.CONFIG;
Boolean tmdbRomaji = config.getTmdbRomaji();
if (!tmdbRomaji) {
// 未开启罗马音
return;
}
List<TmdbTitle> titles = getTitles(tmdb, tmdbType);
for (TmdbTitle tmdbTitle : titles) {
String iso31661 = tmdbTitle.getIso31661();
String type = tmdbTitle.getType();
String title = tmdbTitle.getTitle();
if (!iso31661.equals("JP")) {
continue;
}
if (List.of("romaji", "romanization").contains(type.toLowerCase())) {
title = RenameUtil.getName(title);
// 判断为罗马音
tmdb.setName(title);
return;
}
}
String romaji = "";
try {
romaji = AniListUtil.getRomaji(tmdb.getName());
romaji = RenameUtil.getName(romaji);
} catch (Exception e) {
log.error("通过AniList获取罗马音失败");
log.error(e.getMessage(), e);
}
if (StrUtil.isNotBlank(romaji)) {
tmdb.setName(romaji);
}
}
/**
* 根据标题获得tmdb
*
* @param titleName 标题名
* @return
*/
public static Tmdb getTmdbMovie(String titleName) {
Tmdb tmdb = getTmdb(titleName, TmdbTypeEnum.MOVIE);
getRomaji(tmdb, TmdbTypeEnum.MOVIE);
return tmdb;
}
/**
* 根据标题获得tmdb
*
* @param titleName 标题名
* @return
*/
public static Tmdb getTmdbTv(String titleName) {
Tmdb tmdb = getTmdb(titleName, TmdbTypeEnum.TV);
getRomaji(tmdb, TmdbTypeEnum.TV);
return tmdb;
}
/**
* 刷新tmdb信息
*
* @param tmdb tmdb
* @param tmdbType 类型
* @return
*/
public static Tmdb getTmdb(Tmdb tmdb, TmdbTypeEnum tmdbType) {
Config config = ConfigUtil.CONFIG;
String tmdbLanguage = config.getTmdbLanguage();
String tmdbApi = getTmdbApi();
String tmdbApiKey = getTmdbApiKey();
String id = tmdb.getId();
String url = StrFormatter.format("{}/3/{}/{}", tmdbApi, tmdbType.getValue(), id);
Tmdb newTmdb = HttpReq.get(url)
.timeout(5000)
.form("api_key", tmdbApiKey)
.form("include_adult", "true")
.form("append_to_response", "translations,credits")
.form("language", tmdbLanguage)
.thenFunction(res -> {
HttpReq.assertStatus(res);
return GsonStatic.fromJson(res.body(), Tmdb.class)
.setTmdbType(tmdbType);
});
BeanUtil.copyProperties(
newTmdb,
tmdb,
CopyOptions
.create()
.setIgnoreNullValue(true)
);
// 宣传语
String tagLine = tmdb.getTagline();
if (StrUtil.isBlank(tagLine)) {
TmdbTranslations translations = tmdb.getTranslations();
Optional<String> first = translations
.getTranslations()
.stream()
.sorted(Comparator.comparingInt(it -> {
int i = List.of("CN", "TW", "HK", "JP", "US").indexOf(it.getIso31661());
if (i > -1) {
return i;
}
return Integer.MAX_VALUE;
}))
.map(TmdbTranslation::getData)
.map(TmdbTranslationData::getTagline)
.filter(StrUtil::isNotBlank)
.findFirst();
if (first.isPresent()) {
tagLine = first.get();
}
}
// 宣传片
List<TmdbVideo> videos = getVideos(tmdb, tmdbType);
return tmdb
.setTagline(tagLine)
.setVideos(videos);
}
/**
* 根据名称获取tmdb信息
*
* @param titleName 标题名
* @param tmdbType 类型
* @return
*/
public static Tmdb getTmdb(String titleName, TmdbTypeEnum tmdbType) {
Config config = ConfigUtil.CONFIG;
String tmdbLanguage = config.getTmdbLanguage();
titleName = RenameUtil.renameDel(titleName, false);
if (StrUtil.isBlank(titleName)) {
return null;
}
String tmdbApi = getTmdbApi();
String tmdbApiKey = getTmdbApiKey();
String finalTitleName = titleName;
return HttpReq.get(tmdbApi + "/3/search/" + tmdbType.getValue())
.timeout(5000)
.form("query", URLUtil.encodeBlank(titleName))
.form("api_key", tmdbApiKey)
.form("include_adult", "true")
.form("language", tmdbLanguage)
.thenFunction(res -> {
HttpReq.assertStatus(res);
JsonObject body = GsonStatic.fromJson(res.body(), JsonObject.class);
List<Tmdb> tmdbs = new ArrayList<>();
for (JsonElement item : body.getAsJsonArray("results")) {
try {
Tmdb tmdb = GsonStatic.fromJson(item, Tmdb.class);
tmdb.setTmdbType(tmdbType);
tmdbs.add(tmdb);
} catch (Exception ignored) {
}
}
Boolean tmdbAnime = config.getTmdbAnime();
if (tmdbAnime) {
// 过滤出动漫 genreIds 16
tmdbs = tmdbs.stream()
.filter(it -> {
List<Integer> genreIds = it.getGenreIds();
return genreIds.contains(16);
}).toList();
}
if (tmdbs.isEmpty()) {
List<String> split = StrUtil.split(finalTitleName, " ", true, true);
if (split.size() < 2) {
return null;
}
ThreadUtil.sleep(500);
split.remove(split.size() - 1);
return getTmdb(CollUtil.join(split, " "), tmdbType);
}
List<Tmdb> tmdbList = tmdbs.stream()
.sorted(Comparator.comparingLong(tmdb -> Long.MAX_VALUE - tmdb.getDate().getTime()))
.toList();
// 优先使用名称完全匹配
Tmdb get = tmdbList.stream()
.filter(tmdb -> {
String name = tmdb.getName();
String originalName = tmdb.getOriginalName();
return List.of(name, originalName).contains(finalTitleName);
})
.findFirst()
.orElse(tmdbList.get(0));
String name = get.getName();
name = RenameUtil.getName(name);
get.setName(name);
return get;
});
}
/**
* 获取季信息
*
* @param tmdb tmdb
* @param season 季
* @return
*/
public static Optional<TmdbSeason> getTmdbSeason(Tmdb tmdb, Integer season) {
Config config = ConfigUtil.CONFIG;
String tmdbLanguage = config.getTmdbLanguage();
String id = tmdb.getId();
String tmdbApi = getTmdbApi();
String tmdbApiKey = getTmdbApiKey();
String tmdbGroupId = tmdb.getTmdbGroupId();
if (StrUtil.isBlank(tmdbGroupId)) {
String url = StrFormatter.format("{}/3/tv/{}/season/{}", tmdbApi, id, season);
return HttpReq.get(url)
.timeout(5000)
.form("api_key", tmdbApiKey)
.form("include_adult", "true")
.form("language", tmdbLanguage)
.thenFunction(res -> {
int status = res.getStatus();
if (status == 404) {
return Optional.empty();
}
HttpReq.assertStatus(res);
TmdbSeason tmdbSeason = GsonStatic.fromJson(res.body(), TmdbSeason.class);
return Optional.of(tmdbSeason);
});
}
String url = StrFormatter.format("{}/3/tv/episode_group/{}", tmdbApi, tmdbGroupId);
Optional<JsonObject> jsonObject = HttpReq.get(url)
.timeout(5000)
.form("api_key", tmdbApiKey)
.form("include_adult", "true")
.form("language", tmdbLanguage)
.thenFunction(res -> {
int status = res.getStatus();
if (status == 404) {
return Optional.empty();
}
HttpReq.assertStatus(res);
return Optional.of(
GsonStatic.fromJson(res.body(), JsonObject.class)
);
});
if (jsonObject.isEmpty()) {
return Optional.empty();
}
JsonArray groups = jsonObject
.get()
.getAsJsonArray("groups");
List<TmdbSeason> tmdbSeasons = GsonStatic.fromJsonList(groups, TmdbSeason.class);
Optional<TmdbSeason> first = tmdbSeasons
.stream()
.filter(it -> it.getOrder().intValue() == season)
.findFirst();
first.ifPresent(tmdbSeason -> {
List<TmdbEpisode> episodes = tmdbSeason.getEpisodes();
for (TmdbEpisode episode : episodes) {
Integer order = episode.getOrder();
episode
.setSeasonNumber(season)
.setEpisodeNumber(order + 1);
}
Date airDate = episodes
.get(0)
.getAirDate();
tmdbSeason
.setSeasonNumber(season)
.setOverview("")
.setVoteAverage(0.0)
.setAirDate(airDate);
});
return first;
}
/**
* 获取每集的标题
*
* @param ani 订阅
* @return
*/
public static synchronized Map<Integer, String> getEpisodeTitleMap(Ani ani) {
Map<Integer, String> episodeTitleMap = new HashMap<>();
if (Objects.isNull(ani)) {
return episodeTitleMap;
}
Tmdb tmdb = ani.getTmdb();
Integer season = ani.getSeason();
Boolean ova = ani.getOva();
if (ova) {
return episodeTitleMap;
}
if (Objects.isNull(tmdb)) {
return episodeTitleMap;
}
String tmdbId = tmdb.getId();
String tmdbGroupId = tmdb.getTmdbGroupId();
String key = StrFormatter.format("TMDB_getEpisodeTitleMap:{}:{}:{}", tmdbId, tmdbGroupId, season);
Map<Integer, String> cacheMap = CacheUtils.get(key);
if (Objects.nonNull(cacheMap)) {
return cacheMap;
}
episodeTitleMap = getEpisodeTitleMap(tmdb, season);
if (episodeTitleMap.isEmpty()) {
CacheUtils.put(key, episodeTitleMap, 1000 * 10);
} else {
CacheUtils.put(key, episodeTitleMap, TimeUnit.MINUTES.toMillis(5));
}
return episodeTitleMap;
}
/**
* 获取每集的标题
*
* @param tmdb tmdb
* @param season 季
* @return
*/
public static Map<Integer, String> getEpisodeTitleMap(Tmdb tmdb, Integer season) {
Map<Integer, String> map = new HashMap<>();
if (Objects.isNull(tmdb)) {
return map;
}
try {
Optional<TmdbSeason> tmdbSeason = getTmdbSeason(tmdb, season);
if (tmdbSeason.isEmpty()) {
return map;
}
List<TmdbEpisode> episodes = tmdbSeason.get()
.getEpisodes();
for (TmdbEpisode episode : episodes) {
Integer episodeNumber = episode.getEpisodeNumber();
String name = episode.getName();
name = RenameUtil.getName(name);
map.put(episodeNumber, name);
}
} catch (Exception e) {
log.error(ExceptionUtils.getMessage(e), e);
}
return map;
}
/**
* 获取剧集组
*
* @param tmdb tmdb
* @return
*/
public static List<TmdbGroup> getTmdbGroup(Tmdb tmdb) {
String tmdbApi = getTmdbApi();
String tmdbApiKey = getTmdbApiKey();
Config config = ConfigUtil.CONFIG;
String tmdbLanguage = config.getTmdbLanguage();
String id = tmdb.getId();
Map<Integer, String> typeMap = Map.of(
1, "首播日期",
2, "独立",
3, "DVD",
4, "数字",
5, "故事线",
6, "制片",
7, "电视"
);
String url = StrFormatter.format("{}/3/tv/{}/episode_groups", tmdbApi, id);
return HttpReq.get(url)
.timeout(5000)
.form("api_key", tmdbApiKey)
.form("include_adult", "true")
.form("language", tmdbLanguage)
.thenFunction(response -> {
HttpReq.assertStatus(response);
JsonObject body = GsonStatic.fromJson(response.body(), JsonObject.class);
JsonArray results = body.getAsJsonArray("results");
return GsonStatic.fromJsonList(results, TmdbGroup.class)
.stream()
.peek(tmdbGroup -> {
Integer type = tmdbGroup.getType();
String typeName = typeMap.getOrDefault(type, "其他");
tmdbGroup.setTypeName(typeName);
}).toList();
});
}
/**
* 演职人员
*
* @param tmdb tmdb
* @param tmdbType 类型
* @return
*/
public static List<TmdbCredits> getCredits(Tmdb tmdb, TmdbTypeEnum tmdbType) {
String tmdbApi = getTmdbApi();
String tmdbApiKey = getTmdbApiKey();
Config config = ConfigUtil.CONFIG;
String tmdbLanguage = config.getTmdbLanguage();
String id = tmdb.getId();
String url = StrFormatter.format("{}/3/{}/{}/credits", tmdbApi, tmdbType.getValue(), id);
return HttpReq.get(url)
.timeout(5000)
.form("api_key", tmdbApiKey)
.form("include_adult", "true")
.form("language", tmdbLanguage)
.thenFunction(res -> {
HttpReq.assertStatus(res);
JsonObject jsonObject = GsonStatic.fromJson(res.body(), JsonObject.class);
JsonArray cast = jsonObject.getAsJsonArray("cast");
return GsonStatic.fromJsonList(cast, TmdbCredits.class);
});
}
/**
* 获取图片
*
* @param tmdb tmdb
* @param tmdbType 类型
* @return
*/
public static TmdbImages getTmdbImages(Tmdb tmdb, TmdbTypeEnum tmdbType) {
String tmdbApi = getTmdbApi();
String tmdbApiKey = getTmdbApiKey();
String id = tmdb.getId();
Config config = ConfigUtil.CONFIG;
String tmdbLanguage = config.getTmdbLanguage();
String url = StrFormatter.format("{}/3/{}/{}/images", tmdbApi, tmdbType.getValue(), id);
TmdbImages tmdbImages = HttpReq.get(url)
.timeout(5000)
.form("api_key", tmdbApiKey)
.form("include_adult", "true")
.thenFunction(res -> {
HttpReq.assertStatus(res);
return GsonStatic.fromJson(res.body(), TmdbImages.class);
});
// 排序方法
ToDoubleFunction<TmdbImage> sortedFun = it -> {
Double voteAverage = it.getVoteAverage();
String iso6391 = it.getIso6391();
String iso31661 = it.getIso31661();
if (StrUtil.isBlank(iso6391)) {
return 50 + voteAverage;
}
String lang = iso6391 + "-" + iso31661;
if (tmdbLanguage.equals(lang)) {
return voteAverage;
}
if (lang.equals("zh-CN")) {
return 10 + voteAverage;
}
if (lang.startsWith("zh-")) {
return 20 + voteAverage;
}
if (lang.startsWith("ja-")) {
return 30 + voteAverage;
}
return 40 + voteAverage;
};
List<TmdbImage> logos = tmdbImages.getLogos();
List<TmdbImage> posters = tmdbImages.getPosters();
List<TmdbImage> backdrops = tmdbImages.getBackdrops();
// 图片排序
logos = logos.stream()
.sorted(Comparator.comparingDouble(sortedFun))
.toList();
posters = posters.stream()
.sorted(Comparator.comparingDouble(sortedFun))
.toList();
backdrops = backdrops.stream()
.sorted(Comparator.comparingDouble(sortedFun))
.toList();
return tmdbImages.setLogos(logos)
.setPosters(posters)
.setBackdrops(backdrops);
}
/**
* 获取预告片
*
* @param tmdb tmdb
* @param tmdbType 类型
* @return
*/
public static List<TmdbVideo> getVideos(Tmdb tmdb, TmdbTypeEnum tmdbType) {
String tmdbApi = getTmdbApi();
String tmdbApiKey = getTmdbApiKey();
String id = tmdb.getId();
String url = StrFormatter.format("{}/3/{}/{}/videos", tmdbApi, tmdbType.getValue(), id);
return HttpReq.get(url)
.timeout(5000)
.form("api_key", tmdbApiKey)
.form("include_adult", "true")
.thenFunction(res -> {
HttpReq.assertStatus(res);
JsonArray results = GsonStatic.fromJson(res.body(), JsonObject.class)
.getAsJsonArray("results");
return GsonStatic.fromJsonList(results, TmdbVideo.class);
});
}
}

View File

@@ -0,0 +1,279 @@
package ani.rss.util.other;
import ani.rss.commons.CacheUtils;
import ani.rss.commons.ExceptionUtils;
import ani.rss.entity.Ani;
import ani.rss.entity.Config;
import ani.rss.entity.CustomTmdbConfig;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.text.StrFormatter;
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import wushuo.tmdb.api.TmdbUtil;
import wushuo.tmdb.api.entity.*;
import wushuo.tmdb.api.enums.TmdbTypeEnum;
import java.util.*;
import java.util.concurrent.TimeUnit;
/**
* tmdb封装
*/
@Slf4j
public class TmdbUtils {
public final static TmdbConfig config = new CustomTmdbConfig();
public final static TmdbUtil TMDB_UTIL = new TmdbUtil(config);
/**
* 获取番剧在tmdb的名称
*
* @param ani 订阅
* @return
*/
public synchronized static String getFinalName(Ani ani) {
Boolean ova = ani.getOva();
String name = ani.getTitle();
name = RenameUtil.renameDel(name, false);
if (StrUtil.isBlank(name)) {
return "";
}
Optional<Tmdb> tmdb;
try {
if (ova) {
tmdb = getTmdbMovie(name);
} else {
tmdb = getTmdbTv(name);
}
} catch (Exception e) {
String message = ExceptionUtils.getMessage(e);
log.error(message, e);
return "";
}
tmdb.ifPresent(ani::setTmdb);
if (tmdb.isEmpty()) {
return "";
}
String themoviedbName = tmdb.get().getName();
return getFinalName(themoviedbName, tmdb.get());
}
/**
* 获取添加tmdbid与年份后的名称
*
* @param title 标题
* @param tmdb tmdb
* @return
*/
public static String getFinalName(String title, Tmdb tmdb) {
if (Objects.isNull(tmdb)) {
return title;
}
Config config = ConfigUtil.CONFIG;
boolean titleYear = config.getTitleYear();
if (titleYear) {
title = RenameUtil.renameDel(title, false);
title = StrFormatter.format("{} ({})", title, DateUtil.year(tmdb.getDate()));
}
boolean tmdbId = config.getTmdbId();
boolean tmdbIdPlexMode = config.getTmdbIdPlexMode();
if (tmdbId) {
if (tmdbIdPlexMode) {
title = StrFormatter.format("{} {tmdb-{}}", title, tmdb.getId());
} else {
title = StrFormatter.format("{} [tmdbid={}]", title, tmdb.getId());
}
}
return RenameUtil.getName(title);
}
/**
* 获取所有标题
*
* @param tmdb tmdb
* @param tmdbType 类型
* @return
*/
public static List<TmdbTitle> getTitles(Tmdb tmdb, TmdbTypeEnum tmdbType) {
return TMDB_UTIL.getTitles(tmdb, tmdbType);
}
/**
* 获取罗马音
*
* @param tmdb tmdb
* @param tmdbType 类型
*/
public static void getRomaji(Tmdb tmdb, TmdbTypeEnum tmdbType) {
if (Objects.isNull(tmdb)) {
return;
}
Config config = ConfigUtil.CONFIG;
Boolean tmdbRomaji = config.getTmdbRomaji();
if (!tmdbRomaji) {
// 未开启罗马音
return;
}
List<TmdbTitle> titles = getTitles(tmdb, tmdbType);
for (TmdbTitle tmdbTitle : titles) {
String iso31661 = tmdbTitle.getIso31661();
String type = tmdbTitle.getType();
String title = tmdbTitle.getTitle();
if (!iso31661.equals("JP")) {
continue;
}
if (List.of("romaji", "romanization").contains(type.toLowerCase())) {
title = RenameUtil.getName(title);
// 判断为罗马音
tmdb.setName(title);
return;
}
}
String romaji = "";
try {
romaji = AniListUtil.getRomaji(tmdb.getName());
romaji = RenameUtil.getName(romaji);
} catch (Exception e) {
log.error("通过AniList获取罗马音失败");
log.error(e.getMessage(), e);
}
if (StrUtil.isNotBlank(romaji)) {
tmdb.setName(romaji);
}
}
/**
* 根据标题获得tmdb
*
* @param titleName 标题名
* @return
*/
public static Optional<Tmdb> getTmdbMovie(String titleName) {
Optional<Tmdb> tmdb = getTmdb(titleName, TmdbTypeEnum.MOVIE);
tmdb.ifPresent(it -> getRomaji(it, TmdbTypeEnum.MOVIE));
return tmdb;
}
/**
* 根据标题获得tmdb
*
* @param titleName 标题名
* @return
*/
public static Optional<Tmdb> getTmdbTv(String titleName) {
Optional<Tmdb> tmdb = getTmdb(titleName, TmdbTypeEnum.TV);
tmdb.ifPresent(it -> getRomaji(it, TmdbTypeEnum.TV));
return tmdb;
}
/**
* 根据名称获取tmdb信息
*
* @param titleName 标题名
* @param tmdbType 类型
* @return
*/
public static Optional<Tmdb> getTmdb(String titleName, TmdbTypeEnum tmdbType) {
return TMDB_UTIL.getTmdb(titleName, tmdbType);
}
/**
* 获取季信息
*
* @param tmdb tmdb
* @param season 季
* @return
*/
public static Optional<TmdbSeason> getTmdbSeason(Tmdb tmdb, Integer season) {
return TMDB_UTIL.getTmdbSeason(tmdb, season);
}
/**
* 获取每集的标题
*
* @param ani 订阅
* @return
*/
public static synchronized Map<Integer, String> getEpisodeTitleMap(Ani ani) {
Map<Integer, String> episodeTitleMap = new HashMap<>();
if (Objects.isNull(ani)) {
return episodeTitleMap;
}
Tmdb tmdb = ani.getTmdb();
Integer season = ani.getSeason();
Boolean ova = ani.getOva();
if (ova) {
return episodeTitleMap;
}
if (Objects.isNull(tmdb)) {
return episodeTitleMap;
}
String tmdbId = tmdb.getId();
String tmdbGroupId = tmdb.getTmdbGroupId();
String key = StrFormatter.format("TMDB_getEpisodeTitleMap:{}:{}:{}", tmdbId, tmdbGroupId, season);
Map<Integer, String> cacheMap = CacheUtils.get(key);
if (Objects.nonNull(cacheMap)) {
return cacheMap;
}
episodeTitleMap = getEpisodeTitleMap(tmdb, season);
if (episodeTitleMap.isEmpty()) {
CacheUtils.put(key, episodeTitleMap, 1000 * 10);
} else {
CacheUtils.put(key, episodeTitleMap, TimeUnit.MINUTES.toMillis(5));
}
return episodeTitleMap;
}
/**
* 获取每集的标题
*
* @param tmdb tmdb
* @param season 季
* @return
*/
public static Map<Integer, String> getEpisodeTitleMap(Tmdb tmdb, Integer season) {
return TMDB_UTIL.getEpisodeTitleMap(tmdb, season);
}
/**
* 获取剧集组
*
* @param tmdb tmdb
* @return
*/
public static List<TmdbGroup> getTmdbGroup(Tmdb tmdb) {
return TMDB_UTIL.getTmdbGroup(tmdb);
}
/**
* 获取图片
*
* @param tmdb tmdb
* @param tmdbType 类型
* @return
*/
public static TmdbImages getTmdbImages(Tmdb tmdb, TmdbTypeEnum tmdbType) {
return TMDB_UTIL.getTmdbImages(tmdb, tmdbType);
}
public static Optional<Tmdb> getTmdb(Tmdb tmdb, TmdbTypeEnum tmdbTypeEnum) {
return TMDB_UTIL.getTmdb(tmdb, tmdbTypeEnum);
}
}

View File

@@ -1,8 +1,8 @@
<template>
<el-dialog v-model="dialogVisible" :title="playItem.name" center @close="onClose">
<div
class="flex-center content">
<Artplayer :playItem="playItem" v-if="dialogVisible"/>
class="flex-center content" v-loading="loading">
<Artplayer :playItem="playItem" v-if="dialogVisible && !loading"/>
</div>
</el-dialog>
</template>
@@ -13,27 +13,33 @@ import Artplayer from "./Artplayer.vue";
import {authorization} from "@/js/global.js";
import api from "@/js/api.js";
let loading = ref(false);
let dialogVisible = ref(false)
let playItem = ref({})
let show = async (pi) => {
let show = (pi) => {
playItem.value = {...pi};
playItem.value.src = `${location.href}api/files?filename=${playItem.value.filename}&s=${authorization.value}`
for (let subtitle of playItem.value.subtitles) {
subtitle.url = `${location.href}api/files?filename=${subtitle.url}&s=${authorization.value}`
}
loading.value = true;
// 获取内封字幕
let res = await api.post('api/playitem', {
api.post('api/playitem', {
'type': 'getSubtitles',
'file': playItem.value.filename,
});
for (let sub of res.data) {
const blob = new Blob([sub.content], {type: "text/plain"});
sub.url = URL.createObjectURL(blob);
playItem.value.subtitles.push(sub)
}
'file': playItem.value.filename
})
.then(res => {
for (let sub of res.data) {
const blob = new Blob([sub.content], {type: "text/plain"});
sub.url = URL.createObjectURL(blob);
playItem.value.subtitles.push(sub)
}
})
.finally(() => {
loading.value = false
});
dialogVisible.value = true
}

View File

@@ -33,6 +33,10 @@
<id>ebml-reader</id>
<url>https://raw.github.com/wushuo894/EBMLReader/mvn-repo</url>
</repository>
<repository>
<id>tmdb-api</id>
<url>https://raw.github.com/wushuo894/tmdb-api/mvn-repo</url>
</repository>
</repositories>
<dependencyManagement>
@@ -62,6 +66,11 @@
<artifactId>ani-rss-web</artifactId>
<version>${project.parent.version}</version>
</dependency>
<dependency>
<groupId>wushuo.tmdb.api</groupId>
<artifactId>tmdb-api</artifactId>
<version>1.0.0</version>
</dependency>
<dependency>
<groupId>ebml.reader</groupId>
<artifactId>ebml-reader</artifactId>