Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
758ac48627 | ||
|
|
4af5166003 | ||
|
|
793ce9a20d | ||
|
|
82df0d274c | ||
|
|
2a09fb46af | ||
|
|
d74a4198d6 | ||
|
|
1de2605158 | ||
|
|
6a214d9cb3 |
+27
@@ -0,0 +1,27 @@
|
|||||||
|
# 使用支持Maven打包的Java 11环境的基础镜像
|
||||||
|
FROM maven:3.8.4-openjdk-11 AS build
|
||||||
|
|
||||||
|
# 设置工作目录
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 拉取项目代码
|
||||||
|
COPY src/ ./src/
|
||||||
|
COPY pom.xml .
|
||||||
|
|
||||||
|
# 使用Maven进行构建和打包
|
||||||
|
RUN mvn clean package
|
||||||
|
|
||||||
|
# 使用一个仅包含JRE 17的运行时镜像
|
||||||
|
FROM openjdk:11-jre-slim
|
||||||
|
|
||||||
|
# 设置工作目录
|
||||||
|
WORKDIR /app
|
||||||
|
|
||||||
|
# 从构建镜像中复制打包好的jar文件到运行镜像中
|
||||||
|
COPY --from=build /app/target/tvbox-mv-0.0.1-SNAPSHOT.jar /app/tvbox-mv-0.0.1-SNAPSHOT.jar
|
||||||
|
|
||||||
|
# 暴露端口
|
||||||
|
EXPOSE 7777
|
||||||
|
|
||||||
|
# 运行应用程序
|
||||||
|
CMD ["java", "-jar", "tvbox-mv-0.0.1-SNAPSHOT.jar"]
|
||||||
@@ -3,9 +3,11 @@ mv视频搜索服务
|
|||||||
|
|
||||||
# 请求接口
|
# 请求接口
|
||||||
|
|
||||||
## Vod搜索接口
|
## MV视频Vod搜索接口
|
||||||
http://localhost:7777/mv/vod?maxCount=100&wd=五月天后来的我们
|
http://localhost:7777/mv/vod?maxCount=100&wd=五月天后来的我们
|
||||||
|
|
||||||
|
该接口只请求MV视频
|
||||||
|
|
||||||
请求参数定义
|
请求参数定义
|
||||||
~~~
|
~~~
|
||||||
wd :搜索值,mv名称或者歌手名 都可以
|
wd :搜索值,mv名称或者歌手名 都可以
|
||||||
@@ -31,8 +33,34 @@ maxCount:最大返回值,返回结果里面 list 最大数量。 最大值10
|
|||||||
}
|
}
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
## 自定义数据源-Vod搜索接口
|
||||||
|
http://localhost:7777/vod/:index?maxCount=100&wd=五月天后来的我们
|
||||||
|
|
||||||
## 搜素接口
|
### 使用方法
|
||||||
|
1. 在`jar`所在文件目录下创建`data`文件夹
|
||||||
|
2. 将自定义数据源文件放入`data`文件夹下
|
||||||
|
3. 自定义数据源名称为数据源文件名,如`dome.json`,则数据源名称为`dome`
|
||||||
|
4. 自定义数据源文件格式如下: `视频名称,视频链接`
|
||||||
|
4. 请求接口`http://localhost:7777/vod/dome?maxCount=100&wd=五月天后来的我们`
|
||||||
|
|
||||||
|
请求路径参数定义
|
||||||
|
~~~
|
||||||
|
:index :数据源名称,如:dome,不带文件后缀
|
||||||
|
~~~
|
||||||
|
|
||||||
|
请求参数定义
|
||||||
|
~~~
|
||||||
|
wd :搜索值,mv名称或者歌手名 都可以
|
||||||
|
ids :vodId,同wd
|
||||||
|
maxCount:最大返回值,返回结果里面 list 最大数量。 最大值1000
|
||||||
|
~~~
|
||||||
|
返回参数结果
|
||||||
|
~~~
|
||||||
|
同上
|
||||||
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
## MV视频搜素接口
|
||||||
http://localhost:7777/mv/search?maxCount=100&query=五月天后来的我们
|
http://localhost:7777/mv/search?maxCount=100&query=五月天后来的我们
|
||||||
|
|
||||||
请求参数定义
|
请求参数定义
|
||||||
@@ -71,6 +99,7 @@ maxCount:最大返回值,返回结果里面 list 最大数量。 最大值10
|
|||||||
|
|
||||||
# TvBox配置
|
# TvBox配置
|
||||||
~~~ json
|
~~~ json
|
||||||
|
// 示例
|
||||||
{
|
{
|
||||||
"sites": [
|
"sites": [
|
||||||
{
|
{
|
||||||
@@ -81,8 +110,94 @@ maxCount:最大返回值,返回结果里面 list 最大数量。 最大值10
|
|||||||
"searchable": 1,
|
"searchable": 1,
|
||||||
"quickSearch": 1,
|
"quickSearch": 1,
|
||||||
"filterable": 1
|
"filterable": 1
|
||||||
|
}, {
|
||||||
|
"key": "MV_vod_DOME",
|
||||||
|
"name": "👀┃DOME┃视频",
|
||||||
|
"type": 1,
|
||||||
|
"api": "http://你自己域名:7777/dome",
|
||||||
|
"searchable": 1,
|
||||||
|
"quickSearch": 1,
|
||||||
|
"filterable": 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
// 已有接口-任选其一即可
|
||||||
|
{
|
||||||
|
"sites": [
|
||||||
|
{
|
||||||
|
"key": "MV_vod",
|
||||||
|
"name": "🎸┃明星-接口1┃MV",
|
||||||
|
"type": 1,
|
||||||
|
"api": "https://tvbox-mv--leosam2048.repl.co/mv/vod",
|
||||||
|
"searchable": 1,
|
||||||
|
"quickSearch": 1,
|
||||||
|
"filterable": 1
|
||||||
|
}, {
|
||||||
|
"key": "MV_vod",
|
||||||
|
"name": "🎸┃明星-接口2┃MV",
|
||||||
|
"type": 1,
|
||||||
|
"api": "https://mv.饭太硬.ml/mv/vod",
|
||||||
|
"searchable": 1,
|
||||||
|
"quickSearch": 1,
|
||||||
|
"filterable": 1
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
# 安装和启动
|
||||||
|
|
||||||
|
## 使用docker进行启动
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
### 镜像获取(二选一)
|
||||||
|
|
||||||
|
docker中央仓库拉取
|
||||||
|
|
||||||
|
|
||||||
|
~~~sh
|
||||||
|
# 注:需要自行安装docker环境
|
||||||
|
|
||||||
|
# 拉取git仓库
|
||||||
|
docker pull leosam1024/tvbox-mv:latest
|
||||||
|
~~~
|
||||||
|
|
||||||
|
本地构建docker镜像
|
||||||
|
|
||||||
|
~~~sh
|
||||||
|
# 注:需要自行安装git和docker环境
|
||||||
|
|
||||||
|
# 拉取git仓库
|
||||||
|
git clone https://github.com/leosam1024/tvbox-mv.git
|
||||||
|
|
||||||
|
# 进入仓库
|
||||||
|
cd tvbox-mv
|
||||||
|
|
||||||
|
# 构建docker镜像
|
||||||
|
docker build ./ -t leosam1024/tvbox-mv:latest
|
||||||
|
~~~
|
||||||
|
|
||||||
|
### 启动
|
||||||
|
|
||||||
|
~~~sh
|
||||||
|
# 运行docker镜像(前台运行)
|
||||||
|
docker run -p 7777:7777 leosam1024/tvbox-mv:latest
|
||||||
|
|
||||||
|
# 运行docker镜像(后台运行)
|
||||||
|
docker run -dit --restart always -p 8898:7777 leosam1024/tvbox-mv:latest
|
||||||
|
|
||||||
|
# 运行docker镜像(后台运行+指定容器名称) -- 推荐
|
||||||
|
docker run -dit --name tvbox-mv --hostname tvbox-mv --restart always -p 7777:7777 leosam1024/tvbox-mv:latest
|
||||||
|
|
||||||
|
# 运行docker镜像(后台运行+指定容器名称+自定义数据)
|
||||||
|
docker run -dit --name tvbox-mv --hostname tvbox-mv --restart always -p 7777:7777 -v /opt/mv/data:/app/data leosam1024/tvbox-mv:latest
|
||||||
|
|
||||||
|
# 如果再次构建运行的时候,出现说container冲突的话,删除container对应的的ID就行
|
||||||
|
docker rm container对应的的ID
|
||||||
~~~
|
~~~
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,6 @@
|
|||||||
|
docker build -t tvbox-mv:latest .
|
||||||
|
|
||||||
|
# docker login
|
||||||
|
# docker images
|
||||||
|
# docker tag d4c90f23cb5f leosam1024/tvbox-mv:latest
|
||||||
|
# docker push leosam1024/tvbox-mv:latest
|
||||||
@@ -0,0 +1,24 @@
|
|||||||
|
水陆古法养鱼池塘缸,保姆级教程,https://www.bilibili.com/video/BV1Bg4y1K7yC/
|
||||||
|
伤心情歌,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAgmvmc4gUo8NSjoQI.mp4
|
||||||
|
等你等到我心痛,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAg5fTW4gUoypKv_AQ.mp4
|
||||||
|
高安杭娇_一生无悔,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAgtL6q4gUojIS-mQE.mp4
|
||||||
|
刚好遇见你,http://15799848.s21v.faiusr.com/58/ABUIABA6GAAg3q6M5gUohPidmQc.mp4
|
||||||
|
甘心情愿爱着你.安东阳张怡诺,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAgq_2a4gUo686M8wc.mp4
|
||||||
|
风中花雨楼.任妙音,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAgypLV4gUo-ZmUhwc.mp4
|
||||||
|
分手.冷漠,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAgwsfE4gUokp27lAQ.mp4
|
||||||
|
放狠爱.慕容晓晓肖玄,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAgpoLG4gUo0JOBggI.mp4
|
||||||
|
渡红尘.张碧晨,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAgkN-64wUorOL7mQI.mp4
|
||||||
|
都说.龙梅子老猫,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAghPbQ7AUohPLwrAM.mp4
|
||||||
|
丁当_野兽,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAg0MOm4gUo-LnKpQE.mp4
|
||||||
|
邓紫棋_喜欢你,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAg6uyj4QUosO5G.mp4
|
||||||
|
等你一万年.白雪,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAgyKyM5gUooJurKA.mp4
|
||||||
|
等你一万年,http://15799848.s21v.faiusr.com/58/ABUIABA6GAAgyKyM5gUooJurKA.mp4
|
||||||
|
等到山花开_钟小冰,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAggcOv5wUo4pShggc.mp4
|
||||||
|
当爱离别时,http://15799848.s21v.faiusr.com/58/ABUIABA6GAAgstTE4gUo856frgY.mp4
|
||||||
|
当,http://15799848.s21v.faiusr.com/58/ABUIABA6GAAgpPTW4gUoz_DgdQ.mp4
|
||||||
|
单身情歌_黄晓凤,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAgjfPW4gUo4umD3QE.mp4
|
||||||
|
错过了缘分错过你_候俊辉,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAgqfLW4gUogNTT1wY.mp4
|
||||||
|
崔子格老猫_老婆最大,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAg29is4gUopvmF8wI.mp4
|
||||||
|
传奇_黄晓凤,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAg9b62-AUomeie4gY.mp4
|
||||||
|
成龙金喜善_美丽的神话,https://15799848.s21v.faiusr.com/58/ABUIABA6GAAg_tma4gUowLvk9wM.mp4
|
||||||
|
陈慧娴-逝去的诺言,http://bizcommon.alicdn.com/l2nDqpMmn6DGHnWzZQA/i78cWdjCSglPJHDaedL%40%40ld.m3u8
|
||||||
@@ -9,7 +9,9 @@
|
|||||||
|
|
||||||
<description>Demo project for Spring Boot</description>
|
<description>Demo project for Spring Boot</description>
|
||||||
<properties>
|
<properties>
|
||||||
<java.version>17</java.version>
|
<java.version>11</java.version>
|
||||||
|
<maven.compiler.source>11</maven.compiler.source>
|
||||||
|
<maven.compiler.target>11</maven.compiler.target>
|
||||||
|
|
||||||
<project.encoding>UTF-8</project.encoding>
|
<project.encoding>UTF-8</project.encoding>
|
||||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
@@ -116,9 +118,6 @@
|
|||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
<version>${maven-compiler-plugin.version}</version>
|
<version>${maven-compiler-plugin.version}</version>
|
||||||
<configuration>
|
|
||||||
<release>17</release>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
</plugin>
|
||||||
<plugin>
|
<plugin>
|
||||||
<artifactId>maven-shade-plugin</artifactId>
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
|||||||
@@ -53,6 +53,8 @@ public class MainVerticle extends AbstractVerticle {
|
|||||||
Router router = Router.router(vertx);
|
Router router = Router.router(vertx);
|
||||||
router.route("/mv/search").handler(this::searchMv);
|
router.route("/mv/search").handler(this::searchMv);
|
||||||
router.route("/mv/vod").handler(this::searchMvVod);
|
router.route("/mv/vod").handler(this::searchMvVod);
|
||||||
|
router.route("/vod").handler(this::searchVod);
|
||||||
|
router.route("/vod/:index").handler(this::searchVod);
|
||||||
router.route("/*").handler(StaticHandler.create("static"));
|
router.route("/*").handler(StaticHandler.create("static"));
|
||||||
router.route().handler(this::home);
|
router.route().handler(this::home);
|
||||||
httpServer.requestHandler(router);
|
httpServer.requestHandler(router);
|
||||||
@@ -63,49 +65,63 @@ public class MainVerticle extends AbstractVerticle {
|
|||||||
logger.info("HTTP server started on port 7777");
|
logger.info("HTTP server started on port 7777");
|
||||||
} else {
|
} else {
|
||||||
startPromise.fail(http.cause());
|
startPromise.fail(http.cause());
|
||||||
|
logger.info("HTTP server fail, on port 7777, 启动失败,更换端口重试", http.cause());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
port = httpServer.actualPort();
|
port = httpServer.actualPort();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void searchMvVod(RoutingContext req) {
|
||||||
|
searchVod(req, MvService.MV_FILE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void searchVod(RoutingContext req) {
|
||||||
|
searchVod(req, StringUtils.EMPTY);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 参考 <a href="https://github.com/FongMi/TV/blob/release/app/src/main/java/com/fongmi/android/tv/model/SiteViewModel.java#L32">...</a>
|
* 参考 <a href="https://github.com/FongMi/TV/blob/release/app/src/main/java/com/fongmi/android/tv/model/SiteViewModel.java#L32">...</a>
|
||||||
* @param req
|
* @param req
|
||||||
*/
|
*/
|
||||||
private void searchMvVod(RoutingContext req) {
|
private void searchVod(RoutingContext req, String index) {
|
||||||
// 获取参数
|
// 获取参数
|
||||||
String wd = VertxUtils.queryParam(req, "wd");
|
String wd = VertxUtils.queryParam(req, "wd");
|
||||||
String ids = VertxUtils.queryParam(req, "ids");
|
String ids = VertxUtils.queryParam(req, "ids");
|
||||||
String query = StringUtils.isNotEmpty(wd) ? wd : ids;
|
String query = StringUtils.trimToEmpty(StringUtils.defaultIfEmpty(wd, ids));
|
||||||
|
query = StringUtils.cleanString(query);
|
||||||
String ac = VertxUtils.queryParam(req, "ac");
|
String ac = VertxUtils.queryParam(req, "ac");
|
||||||
String type = VertxUtils.queryParam(req, "t");
|
String type = VertxUtils.queryParam(req, "t");
|
||||||
//query = StringUtils.isNotEmpty(query) ? query : "我";
|
|
||||||
String maxCount = VertxUtils.queryParam(req, "maxCount");
|
String maxCount = VertxUtils.queryParam(req, "maxCount");
|
||||||
int max = Math.min(Math.max(NumberUtils.toInt(maxCount, 200), 10), 1000);
|
int max = Math.min(Math.max(NumberUtils.toInt(maxCount, 200), 10), 1000);
|
||||||
String pg = VertxUtils.queryParam(req, "pg");
|
String pg = VertxUtils.queryParam(req, "pg");
|
||||||
int page = NumberUtils.toInt(pg, 0);
|
int page = NumberUtils.toInt(pg, 0);
|
||||||
|
if(StringUtils.isEmpty(index)){
|
||||||
|
String pathIndex = req.pathParam("index");
|
||||||
|
String queryIndex = VertxUtils.queryParam(req, "index");
|
||||||
|
index = StringUtils.trimToEmpty(StringUtils.defaultIfEmpty(pathIndex, queryIndex));
|
||||||
|
}
|
||||||
|
|
||||||
// 处理结果
|
// 处理结果
|
||||||
VodResult vodResult = null;
|
VodResult vodResult = null;
|
||||||
try {
|
try {
|
||||||
// 搜索
|
// 搜索
|
||||||
if (mvService != null && StringUtils.isNotEmpty(query) && page <= 0) {
|
if (mvService != null && StringUtils.isNotEmpty(query) && page <= 0) {
|
||||||
vodResult = mvService.searchVod(query, max);
|
vodResult = mvService.searchVod(index, query, max);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 首页
|
// 首页
|
||||||
if (mvService != null && StringUtils.isEmpty(query)) {
|
if (mvService != null && StringUtils.isEmpty(query)) {
|
||||||
vodResult = mvService.searchVodHome(type, page);
|
vodResult = mvService.searchVodHome(index, type, page);
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
logger.error("searchVod fail, index={}, query={}, page={} ", index, query, page, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回数据
|
// 返回数据
|
||||||
String jsonString = Json.encode(vodResult);
|
String jsonString = Json.encode(vodResult);
|
||||||
req.response()
|
req.response()
|
||||||
.putHeader("content-type", "application/json")
|
.putHeader("content-type", "application/json;charset=utf-8")
|
||||||
.end(jsonString);
|
.end(jsonString);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -114,6 +130,7 @@ public class MainVerticle extends AbstractVerticle {
|
|||||||
String query = VertxUtils.queryParam(req, "query");
|
String query = VertxUtils.queryParam(req, "query");
|
||||||
String wd = VertxUtils.queryParam(req, "wd");
|
String wd = VertxUtils.queryParam(req, "wd");
|
||||||
query = StringUtils.isNotEmpty(query) ? query : wd;
|
query = StringUtils.isNotEmpty(query) ? query : wd;
|
||||||
|
query = StringUtils.cleanString(query);
|
||||||
String maxCount = VertxUtils.queryParam(req, "maxCount");
|
String maxCount = VertxUtils.queryParam(req, "maxCount");
|
||||||
int max = Math.min(Math.max(NumberUtils.toInt(maxCount, 200), 10), 1000);
|
int max = Math.min(Math.max(NumberUtils.toInt(maxCount, 200), 10), 1000);
|
||||||
|
|
||||||
@@ -121,16 +138,16 @@ public class MainVerticle extends AbstractVerticle {
|
|||||||
MvResult search = null;
|
MvResult search = null;
|
||||||
try {
|
try {
|
||||||
if (mvService != null) {
|
if (mvService != null) {
|
||||||
search = mvService.search(query, max);
|
search = mvService.search(null, query, max);
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw new RuntimeException(e);
|
logger.error("searchMv fail, query={}, maxCount={} ", query, maxCount, e);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 返回数据
|
// 返回数据
|
||||||
String jsonString = Json.encode(search);
|
String jsonString = Json.encode(search);
|
||||||
req.response()
|
req.response()
|
||||||
.putHeader("content-type", "application/json")
|
.putHeader("content-type", "application/json;charset=utf-8")
|
||||||
.end(jsonString);
|
.end(jsonString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.leosam.tvbox.mv.lucene;
|
package com.leosam.tvbox.mv.lucene;
|
||||||
|
|
||||||
|
import com.leosam.tvbox.mv.utils.StringUtils;
|
||||||
import io.vertx.ext.web.impl.LRUCache;
|
import io.vertx.ext.web.impl.LRUCache;
|
||||||
import org.apache.lucene.analysis.Analyzer;
|
import org.apache.lucene.analysis.Analyzer;
|
||||||
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
|
import org.apache.lucene.analysis.cn.smart.SmartChineseAnalyzer;
|
||||||
@@ -7,10 +8,14 @@ import org.apache.lucene.document.Document;
|
|||||||
import org.apache.lucene.index.DirectoryReader;
|
import org.apache.lucene.index.DirectoryReader;
|
||||||
import org.apache.lucene.index.IndexReader;
|
import org.apache.lucene.index.IndexReader;
|
||||||
import org.apache.lucene.index.StoredFields;
|
import org.apache.lucene.index.StoredFields;
|
||||||
|
import org.apache.lucene.index.Term;
|
||||||
import org.apache.lucene.queryparser.classic.QueryParser;
|
import org.apache.lucene.queryparser.classic.QueryParser;
|
||||||
|
import org.apache.lucene.search.BooleanClause;
|
||||||
|
import org.apache.lucene.search.BooleanQuery;
|
||||||
import org.apache.lucene.search.IndexSearcher;
|
import org.apache.lucene.search.IndexSearcher;
|
||||||
import org.apache.lucene.search.Query;
|
import org.apache.lucene.search.Query;
|
||||||
import org.apache.lucene.search.ScoreDoc;
|
import org.apache.lucene.search.ScoreDoc;
|
||||||
|
import org.apache.lucene.search.TermQuery;
|
||||||
import org.apache.lucene.search.TopDocs;
|
import org.apache.lucene.search.TopDocs;
|
||||||
import org.apache.lucene.store.Directory;
|
import org.apache.lucene.store.Directory;
|
||||||
import org.apache.lucene.store.FSDirectory;
|
import org.apache.lucene.store.FSDirectory;
|
||||||
@@ -55,6 +60,34 @@ public class MvSearcher {
|
|||||||
return docs;
|
return docs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public TopDocs searchTopDocs(String field, String queryStr, String termField, String termQueryStr, int maxHit) throws Exception {
|
||||||
|
String cacheKey = field + "_" + queryStr + "_" + termField + "_" + termQueryStr + "_" + maxHit;
|
||||||
|
TopDocs topDocs = topDocsLruCache.get(cacheKey);
|
||||||
|
if (topDocs != null) {
|
||||||
|
return topDocs;
|
||||||
|
}
|
||||||
|
|
||||||
|
BooleanQuery.Builder queryBuilder = new BooleanQuery.Builder();
|
||||||
|
// 全文检索
|
||||||
|
if(StringUtils.isNotEmpty(queryStr)){
|
||||||
|
Analyzer analyzer = new SmartChineseAnalyzer();
|
||||||
|
// Analyzer analyzer = new StandardAnalyzer();
|
||||||
|
QueryParser parser = new QueryParser(field, analyzer);
|
||||||
|
Query query = parser.parse(queryStr);
|
||||||
|
queryBuilder.add(query, BooleanClause.Occur.MUST);
|
||||||
|
}
|
||||||
|
// 关键字检索
|
||||||
|
if (StringUtils.isNotEmpty(termQueryStr)) {
|
||||||
|
Query keywordQuery = new TermQuery(new Term(termField, termQueryStr));
|
||||||
|
queryBuilder.add(keywordQuery, BooleanClause.Occur.MUST);
|
||||||
|
}
|
||||||
|
BooleanQuery combinedQuery = queryBuilder.build();
|
||||||
|
|
||||||
|
TopDocs docs = searcher.search(combinedQuery, maxHit);
|
||||||
|
topDocsLruCache.put(cacheKey, docs);
|
||||||
|
return docs;
|
||||||
|
}
|
||||||
|
|
||||||
public void search(String field, String queryStr) throws Exception {
|
public void search(String field, String queryStr) throws Exception {
|
||||||
Analyzer analyzer = new SmartChineseAnalyzer();
|
Analyzer analyzer = new SmartChineseAnalyzer();
|
||||||
// Analyzer analyzer = new StandardAnalyzer();
|
// Analyzer analyzer = new StandardAnalyzer();
|
||||||
|
|||||||
@@ -26,7 +26,6 @@ import java.io.File;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedHashSet;
|
import java.util.LinkedHashSet;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@@ -41,11 +40,16 @@ import java.util.concurrent.atomic.AtomicInteger;
|
|||||||
*/
|
*/
|
||||||
public class MvService {
|
public class MvService {
|
||||||
private static final Logger logger = LoggerFactory.getLogger(MvService.class);
|
private static final Logger logger = LoggerFactory.getLogger(MvService.class);
|
||||||
|
public static final String MV_FILE_NAME = "16wMV";
|
||||||
private static final String indexDirectoryPath = "index";
|
private static final String indexDirectoryPath = "index";
|
||||||
private static final String MV_FILE = "tvbox/16wMV.txt";
|
|
||||||
private static final Map<String, List<String>> homeConfigMap = new LinkedHashMap<>();
|
private static final Map<String, List<String>> homeConfigMap = new LinkedHashMap<>();
|
||||||
private static final Map<String, String> singerMap = new LinkedHashMap<>();
|
private static final Map<String, String> singerMap = new LinkedHashMap<>();
|
||||||
private static final String HOME_KEY = "HOME";
|
private static final String HOME_KEY = "HOME";
|
||||||
|
private static final List<String> FILE_PATH_LIST = List.of(
|
||||||
|
"classpath:tvbox/16wMV.txt",
|
||||||
|
"./data/",
|
||||||
|
"../data/"
|
||||||
|
);
|
||||||
/**
|
/**
|
||||||
* 最低相似分数
|
* 最低相似分数
|
||||||
*/
|
*/
|
||||||
@@ -53,15 +57,18 @@ public class MvService {
|
|||||||
|
|
||||||
private MvSearcher mvSearcher;
|
private MvSearcher mvSearcher;
|
||||||
|
|
||||||
public MvResult search(String query, int max) throws Exception {
|
public MvResult search(String index, String query, int max) throws Exception {
|
||||||
if (StringUtils.isEmpty(query) || mvSearcher == null) {
|
if (mvSearcher == null || max > 10000) {
|
||||||
|
return new MvResult();
|
||||||
|
}
|
||||||
|
if (StringUtils.isEmpty(index) && StringUtils.isEmpty(query)) {
|
||||||
return new MvResult();
|
return new MvResult();
|
||||||
}
|
}
|
||||||
|
|
||||||
StopWatch stopWatch = new StopWatch();
|
StopWatch stopWatch = new StopWatch();
|
||||||
stopWatch.start();
|
stopWatch.start();
|
||||||
|
|
||||||
TopDocs topDocs = mvSearcher.searchTopDocs("name", query, max);
|
TopDocs topDocs = mvSearcher.searchTopDocs("name", query, "index", index, max);
|
||||||
|
|
||||||
MvResult result = new MvResult();
|
MvResult result = new MvResult();
|
||||||
result.setQuery(query);
|
result.setQuery(query);
|
||||||
@@ -69,7 +76,7 @@ public class MvService {
|
|||||||
result.setList(new ArrayList<>(topDocs.scoreDocs.length));
|
result.setList(new ArrayList<>(topDocs.scoreDocs.length));
|
||||||
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
|
for (ScoreDoc scoreDoc : topDocs.scoreDocs) {
|
||||||
// 分数太低 忽略
|
// 分数太低 忽略
|
||||||
if (scoreDoc.score < MIN_QUERY_SCORE) {
|
if (scoreDoc.score < MIN_QUERY_SCORE && result.getList().size() > 50) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Document document = mvSearcher.getDocument(scoreDoc.doc);
|
Document document = mvSearcher.getDocument(scoreDoc.doc);
|
||||||
@@ -103,16 +110,16 @@ public class MvService {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VodResult searchVod(String wd, int max) throws Exception {
|
public VodResult searchVod(String index, String wd, int max) throws Exception {
|
||||||
MvResult search = search(wd, max);
|
MvResult search = this.search(index, wd, max);
|
||||||
if (CollectionUtils.isEmpty(search.getList())) {
|
if (CollectionUtils.isEmpty(search.getList())) {
|
||||||
return new VodResult();
|
return new VodResult();
|
||||||
}
|
}
|
||||||
Vod vod = new Vod();
|
Vod vod = new Vod();
|
||||||
vod.setVodId(wd);
|
vod.setVodId(wd);
|
||||||
vod.setVodName(wd);
|
vod.setVodName(wd);
|
||||||
vod.setVodPlayFrom("mv");
|
vod.setVodPlayFrom(StringUtils.defaultIfEmpty(index, "mv"));
|
||||||
vod.setVodPic(getVodPic(wd));
|
vod.setVodPic(getVodPic(index, wd));
|
||||||
List<String> playUrlList = new LinkedList<>();
|
List<String> playUrlList = new LinkedList<>();
|
||||||
Set<String> vodActorList = new LinkedHashSet<>();
|
Set<String> vodActorList = new LinkedHashSet<>();
|
||||||
for (MvContent content : search.getList()) {
|
for (MvContent content : search.getList()) {
|
||||||
@@ -130,7 +137,7 @@ public class MvService {
|
|||||||
return vodResult;
|
return vodResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
public VodResult searchVodHome(String type, int page) throws Exception {
|
public VodResult searchVodHome(String index, String type, int page) throws Exception {
|
||||||
// 防止分页请求
|
// 防止分页请求
|
||||||
if (page > 1) {
|
if (page > 1) {
|
||||||
return new VodResult();
|
return new VodResult();
|
||||||
@@ -141,6 +148,7 @@ public class MvService {
|
|||||||
|
|
||||||
VodResult vodResult = new VodResult().init();
|
VodResult vodResult = new VodResult().init();
|
||||||
|
|
||||||
|
if (MV_FILE_NAME.equals(index)) {
|
||||||
// 分类
|
// 分类
|
||||||
if (StringUtils.isEmpty(type)) {
|
if (StringUtils.isEmpty(type)) {
|
||||||
vodResult.setVodClassList(new ArrayList<>(homeConfigMap.size()));
|
vodResult.setVodClassList(new ArrayList<>(homeConfigMap.size()));
|
||||||
@@ -162,21 +170,34 @@ public class MvService {
|
|||||||
Vod vod = new Vod();
|
Vod vod = new Vod();
|
||||||
vod.setVodId(singer);
|
vod.setVodId(singer);
|
||||||
vod.setVodName(singer);
|
vod.setVodName(singer);
|
||||||
vod.setVodPlayFrom("mv");
|
vod.setVodPlayFrom(StringUtils.defaultIfEmpty(index, "mv"));
|
||||||
vod.setVodPic(getVodPic(singer));
|
vod.setVodPic(getVodPic(index, singer));
|
||||||
vodResult.getList().add(vod);
|
vodResult.getList().add(vod);
|
||||||
}
|
}
|
||||||
|
|
||||||
stopWatch.stop();
|
stopWatch.stop();
|
||||||
logger.info("加载首页成功,类型={}, 返回={}条, 耗时{}毫秒", thisType, vodResult.getList().size(), stopWatch.getTotalTimeMillis());
|
logger.info("加载首页成功,类型={}, 返回={}条, 耗时{}毫秒", thisType, vodResult.getList().size(), stopWatch.getTotalTimeMillis());
|
||||||
|
} else {
|
||||||
|
vodResult.setList(new ArrayList<>());
|
||||||
|
MvResult search = search(index, "", 100);
|
||||||
|
if (CollectionUtils.isNotEmpty(search.getList())) {
|
||||||
|
for (MvContent content : search.getList()) {
|
||||||
|
Vod vod = new Vod();
|
||||||
|
vod.setVodId(content.getName());
|
||||||
|
vod.setVodName(content.getName());
|
||||||
|
vod.setVodPlayFrom(StringUtils.defaultIfEmpty(index, "mv"));
|
||||||
|
vod.setVodPic(getVodPic(index, content.getName()));
|
||||||
|
vodResult.getList().add(vod);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.info("加载首页成功,文件={}, 返回={}条, 耗时{}毫秒", index, vodResult.getList().size(), stopWatch.getTotalTimeMillis());
|
||||||
|
}
|
||||||
return vodResult;
|
return vodResult;
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getVodPic(String vodName) {
|
private String getVodPic(String index, String vodName) {
|
||||||
String vodPic = null;
|
String vodPic = null;
|
||||||
if (StringUtils.isEmpty(vodName)) {
|
if (StringUtils.isNotEmpty(vodName)) {
|
||||||
vodPic = "http://yanxuan.nosdn.127.net/b6fb987ce79f308949e44f5129a4b51c.jpeg";
|
if (singerMap.containsKey(vodName)) {
|
||||||
} else if (singerMap.containsKey(vodName)) {
|
|
||||||
vodPic = singerMap.get(vodName);
|
vodPic = singerMap.get(vodName);
|
||||||
} else if (vodName.contains(",")) {
|
} else if (vodName.contains(",")) {
|
||||||
String[] split = vodName.split(",", 2);
|
String[] split = vodName.split(",", 2);
|
||||||
@@ -184,7 +205,11 @@ public class MvService {
|
|||||||
vodPic = singerMap.get(split[0]);
|
vodPic = singerMap.get(split[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
vodPic = StringUtils.isNotEmpty(vodPic) ? vodPic : "http://yanxuan.nosdn.127.net/b6fb987ce79f308949e44f5129a4b51c.jpeg";
|
}
|
||||||
|
if (StringUtils.isEmpty(vodPic) && StringUtils.isNotEmpty(index)) {
|
||||||
|
vodPic = singerMap.get(index);
|
||||||
|
}
|
||||||
|
vodPic = StringUtils.defaultIfEmpty(vodPic, "http://yanxuan.nosdn.127.net/b6fb987ce79f308949e44f5129a4b51c.jpeg");
|
||||||
return vodPic;
|
return vodPic;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,13 +225,13 @@ public class MvService {
|
|||||||
mvSearcher = new MvSearcher(indexAbsolutePath);
|
mvSearcher = new MvSearcher(indexAbsolutePath);
|
||||||
|
|
||||||
// 搜索一下,看看是否加载成功
|
// 搜索一下,看看是否加载成功
|
||||||
search("五月天", 10);
|
search(MV_FILE_NAME, "五月天", 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildHomeConfig() {
|
private void buildHomeConfig() {
|
||||||
// 首页配置
|
// 首页配置
|
||||||
try {
|
try {
|
||||||
String content = ClassPathReaderUtils.getContent("tvbox/home.json");
|
String content = ClassPathReaderUtils.getContent("config/home.json");
|
||||||
Map<String, List<String>> map = new ObjectMapper().readValue(content, new TypeReference<LinkedHashMap<String, List<String>>>() {
|
Map<String, List<String>> map = new ObjectMapper().readValue(content, new TypeReference<LinkedHashMap<String, List<String>>>() {
|
||||||
});
|
});
|
||||||
homeConfigMap.putAll(map);
|
homeConfigMap.putAll(map);
|
||||||
@@ -216,7 +241,7 @@ public class MvService {
|
|||||||
}
|
}
|
||||||
// 歌手详情配置
|
// 歌手详情配置
|
||||||
try {
|
try {
|
||||||
String content = ClassPathReaderUtils.getContent("tvbox/singerPic.json");
|
String content = ClassPathReaderUtils.getContent("config/singerPic.json");
|
||||||
Map<String, String> map = new ObjectMapper().readValue(content, new TypeReference<LinkedHashMap<String, String>>() {
|
Map<String, String> map = new ObjectMapper().readValue(content, new TypeReference<LinkedHashMap<String, String>>() {
|
||||||
});
|
});
|
||||||
singerMap.putAll(map);
|
singerMap.putAll(map);
|
||||||
@@ -228,14 +253,17 @@ public class MvService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static void reBuildIndex(String indexDirectoryPath) throws IOException {
|
private static void reBuildIndex(String indexDirectoryPath) throws IOException {
|
||||||
|
Set<String> dataFilePath = getDataFilePath();
|
||||||
|
if (dataFilePath.isEmpty()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
File file = new File(indexDirectoryPath).getAbsoluteFile();
|
File file = new File(indexDirectoryPath).getAbsoluteFile();
|
||||||
int mvFileSize = ClassPathReaderUtils.getSize(MV_FILE);
|
long dataFileSize = ClassPathReaderUtils.getAllFileSize(dataFilePath);
|
||||||
File mvFileSizeTxt = Path.of(file.getAbsolutePath(), "" + mvFileSize + ".txt").toFile();
|
File mvFileSizeTxt = Path.of(file.getAbsolutePath(), "" + dataFileSize + ".txt").toFile();
|
||||||
if (mvFileSizeTxt.exists()) {
|
if (mvFileSizeTxt.exists()) {
|
||||||
logger.info("{}已经索引, 跳过索引", MV_FILE);
|
logger.info("所有数据都已经索引, 跳过索引");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
StopWatch stopWatch = new StopWatch();
|
StopWatch stopWatch = new StopWatch();
|
||||||
logger.info("重建索引中....");
|
logger.info("重建索引中....");
|
||||||
@@ -243,32 +271,57 @@ public class MvService {
|
|||||||
// 清空以前的索引
|
// 清空以前的索引
|
||||||
stopWatch.start("清空以前索引");
|
stopWatch.start("清空以前索引");
|
||||||
logger.info("清空历史索引....");
|
logger.info("清空历史索引....");
|
||||||
|
ClassPathReaderUtils.deleteAllFile(file);
|
||||||
if (file.isDirectory()) {
|
|
||||||
File[] files = file.listFiles();
|
|
||||||
for (File file1 : files) {
|
|
||||||
if (file1.isFile()) {
|
|
||||||
file1.delete();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.info("清空历史索引....完成");
|
logger.info("清空历史索引....完成");
|
||||||
stopWatch.stop();
|
stopWatch.stop();
|
||||||
|
|
||||||
|
// 创建索引
|
||||||
stopWatch.start("创建索引");
|
stopWatch.start("创建索引");
|
||||||
logger.info("创建索引中....");
|
logger.info("创建索引中....");
|
||||||
AtomicInteger line = new AtomicInteger();
|
|
||||||
MvIndex mvIndex = new MvIndex(indexDirectoryPath);
|
MvIndex mvIndex = new MvIndex(indexDirectoryPath);
|
||||||
ClassPathReaderUtils.getBufferedReader(MV_FILE).lines()
|
for (String path : dataFilePath) {
|
||||||
.filter(l -> l.contains(",h"))
|
buildIndex(mvIndex, path);
|
||||||
.filter(l -> l.contains("-"))
|
}
|
||||||
|
mvIndex.close();
|
||||||
|
mvFileSizeTxt.createNewFile();
|
||||||
|
stopWatch.stop();
|
||||||
|
logger.info("重建索引中....完成,耗时 {} 毫秒, 索引位置:{}", stopWatch.getTotalTimeMillis(), file.getPath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Set<String> getDataFilePath() throws IOException {
|
||||||
|
Map<String, String> pathMap = new LinkedHashMap<>();
|
||||||
|
for (String filePath : FILE_PATH_LIST) {
|
||||||
|
if (filePath.startsWith(ClassPathReaderUtils.CLASS_PATH_PREFIX)) {
|
||||||
|
pathMap.put(filePath, new File(filePath).getName());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Map<String, String> directoryFiles = ClassPathReaderUtils.getDirectoryFiles(filePath);
|
||||||
|
if (directoryFiles.isEmpty()) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
pathMap.putAll(directoryFiles);
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("↓↓↓↓↓ 搜集数据文件目录 ↓↓↓↓↓↓");
|
||||||
|
for (Map.Entry<String, String> entry : pathMap.entrySet()) {
|
||||||
|
logger.info("*** 数据文件:{}", entry.getValue());
|
||||||
|
}
|
||||||
|
logger.info("↑↑↑↑↑ 搜集数据文件目录 ↑↑↑↑↑↑");
|
||||||
|
return new LinkedHashSet<>(pathMap.keySet());
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void buildIndex(MvIndex mvIndex, String path) {
|
||||||
|
String fileName = ClassPathReaderUtils.extractFileNameWithoutExtension(path);
|
||||||
|
AtomicInteger line = new AtomicInteger();
|
||||||
|
ClassPathReaderUtils.getBufferedReader(path).lines()
|
||||||
|
.filter(l -> l.contains(",http"))
|
||||||
.forEach(l -> {
|
.forEach(l -> {
|
||||||
String[] split = l.split(",", 2);
|
List<String> split = StringUtils.reverseSplit(l, ",http", 2);
|
||||||
if (split.length != 2) {
|
if (split.size() != 2) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
String name = split[0].trim();
|
String name = split.get(0).trim();
|
||||||
String url = split[1].trim();
|
String url = "http" + split.get(1).trim();
|
||||||
String shortUrl = url;
|
String shortUrl = url;
|
||||||
if (shortUrl.startsWith("http://em.21dtv")) {
|
if (shortUrl.startsWith("http://em.21dtv")) {
|
||||||
shortUrl = shortUrl
|
shortUrl = shortUrl
|
||||||
@@ -278,21 +331,19 @@ public class MvService {
|
|||||||
try {
|
try {
|
||||||
Document document = new Document();
|
Document document = new Document();
|
||||||
document.add(new TextField("name", name, Field.Store.YES));
|
document.add(new TextField("name", name, Field.Store.YES));
|
||||||
|
document.add(new StringField("index", fileName, Field.Store.YES));
|
||||||
document.add(new StringField("url", shortUrl, Field.Store.YES));
|
document.add(new StringField("url", shortUrl, Field.Store.YES));
|
||||||
mvIndex.indexFile(document);
|
mvIndex.indexFile(document);
|
||||||
int i = line.incrementAndGet();
|
int i = line.incrementAndGet();
|
||||||
if (i % 10000 == 0) {
|
if (i % 10000 == 0) {
|
||||||
logger.info("创建索引中....已完成{}万条索引", i / 10000);
|
logger.info("创建{}索引中....已完成{}万条索引", fileName, i / 10000);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
mvIndex.close();
|
|
||||||
mvFileSizeTxt.createNewFile();
|
logger.info("创建索引中....完成, 源文件:{}, 总共{}条", new File(path).getName(), line.get());
|
||||||
logger.info("创建索引中....完成, 总共{}条", line.get());
|
|
||||||
stopWatch.stop();
|
|
||||||
logger.info("重建索引中....完成,耗时 {} 毫秒, 索引位置:{}", stopWatch.getTotalTimeMillis(), file.getPath());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -2,11 +2,19 @@ package com.leosam.tvbox.mv.utils;
|
|||||||
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
|
import java.net.URL;
|
||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.Paths;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author admin
|
* @author admin
|
||||||
@@ -14,7 +22,72 @@ import java.nio.charset.StandardCharsets;
|
|||||||
*/
|
*/
|
||||||
public class ClassPathReaderUtils {
|
public class ClassPathReaderUtils {
|
||||||
|
|
||||||
public static int getSize(String path) {
|
public static final String CLASS_PATH_PREFIX = "classpath:";
|
||||||
|
|
||||||
|
public static Map<String, String> getDirectoryFiles(String filePath) throws IOException {
|
||||||
|
Map<String, String> pathMap = new LinkedHashMap<>();
|
||||||
|
if (StringUtils.isEmpty(filePath) || filePath.startsWith(CLASS_PATH_PREFIX)) {
|
||||||
|
return pathMap;
|
||||||
|
}
|
||||||
|
File data = new File(filePath);
|
||||||
|
if (data.exists() && data.isFile()) {
|
||||||
|
pathMap.put(data.getCanonicalPath(), data.getName());
|
||||||
|
}
|
||||||
|
if (data.exists() && data.isDirectory()) {
|
||||||
|
File[] files = data.listFiles();
|
||||||
|
for (File file : files) {
|
||||||
|
if (file.isFile()) {
|
||||||
|
pathMap.put(filePath + file.getName(), file.getName());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return pathMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String extractFileNameWithoutExtension(String filePath) {
|
||||||
|
filePath = filePath.replace(CLASS_PATH_PREFIX, "");
|
||||||
|
Path path = Paths.get(filePath);
|
||||||
|
String fileNameWithExtension = path.getFileName().toString();
|
||||||
|
int lastDotIndex = fileNameWithExtension.lastIndexOf(".");
|
||||||
|
String fileNameWithoutExtension = lastDotIndex == -1 ? fileNameWithExtension
|
||||||
|
: fileNameWithExtension.substring(0, lastDotIndex);
|
||||||
|
return fileNameWithoutExtension;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void deleteAllFile(File file) {
|
||||||
|
if (file == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (file.isFile()) {
|
||||||
|
file.delete();
|
||||||
|
}
|
||||||
|
if (file.isDirectory()) {
|
||||||
|
File[] files = file.listFiles();
|
||||||
|
for (File file1 : files) {
|
||||||
|
if (file1.isFile()) {
|
||||||
|
file1.delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static long getAllFileSize(Set<String> dataPath) {
|
||||||
|
long size = 0;
|
||||||
|
for (String path : dataPath) {
|
||||||
|
if (path.startsWith(CLASS_PATH_PREFIX)) {
|
||||||
|
String pathName = path.replace(CLASS_PATH_PREFIX, "");
|
||||||
|
size += getClassPathFileSize(pathName);
|
||||||
|
} else {
|
||||||
|
File file = new File(path);
|
||||||
|
if (file.exists() && file.isFile()) {
|
||||||
|
size += file.length();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return size;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int getClassPathFileSize(String path) {
|
||||||
try {
|
try {
|
||||||
ClassPathResource resource = new ClassPathResource(path);
|
ClassPathResource resource = new ClassPathResource(path);
|
||||||
InputStream inputStream = resource.getInputStream();
|
InputStream inputStream = resource.getInputStream();
|
||||||
@@ -38,10 +111,14 @@ public class ClassPathReaderUtils {
|
|||||||
|
|
||||||
public static BufferedReader getBufferedReader(String path) {
|
public static BufferedReader getBufferedReader(String path) {
|
||||||
try {
|
try {
|
||||||
|
InputStreamReader inputStreamReader = null;
|
||||||
|
if (path.startsWith(CLASS_PATH_PREFIX)) {
|
||||||
|
path = path.replace(CLASS_PATH_PREFIX, "");
|
||||||
ClassPathResource resource = new ClassPathResource(path);
|
ClassPathResource resource = new ClassPathResource(path);
|
||||||
|
inputStreamReader = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8);
|
||||||
|
} else {
|
||||||
InputStreamReader inputStreamReader = new InputStreamReader(resource.getInputStream(),StandardCharsets.UTF_8);
|
inputStreamReader = new InputStreamReader(new FileInputStream(path), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
BufferedReader reader = new BufferedReader(inputStreamReader);
|
BufferedReader reader = new BufferedReader(inputStreamReader);
|
||||||
return reader;
|
return reader;
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
@@ -79,6 +156,9 @@ public class ClassPathReaderUtils {
|
|||||||
private final ClassLoader classLoader;
|
private final ClassLoader classLoader;
|
||||||
|
|
||||||
public ClassPathResource(String path) {
|
public ClassPathResource(String path) {
|
||||||
|
if (path.startsWith(CLASS_PATH_PREFIX)) {
|
||||||
|
path = path.replace(CLASS_PATH_PREFIX, "");
|
||||||
|
}
|
||||||
this.path = path;
|
this.path = path;
|
||||||
this.classLoader = getDefaultClassLoader();
|
this.classLoader = getDefaultClassLoader();
|
||||||
}
|
}
|
||||||
@@ -96,8 +176,7 @@ public class ClassPathReaderUtils {
|
|||||||
return is;
|
return is;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static ClassLoader getDefaultClassLoader() {
|
||||||
public static ClassLoader getDefaultClassLoader() {
|
|
||||||
ClassLoader cl = null;
|
ClassLoader cl = null;
|
||||||
try {
|
try {
|
||||||
cl = Thread.currentThread().getContextClassLoader();
|
cl = Thread.currentThread().getContextClassLoader();
|
||||||
|
|||||||
@@ -12,4 +12,8 @@ public class CollectionUtils {
|
|||||||
return (collection == null || collection.isEmpty());
|
return (collection == null || collection.isEmpty());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static boolean isNotEmpty(Collection<?> collection) {
|
||||||
|
return !isEmpty(collection);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,17 @@
|
|||||||
package com.leosam.tvbox.mv.utils;
|
package com.leosam.tvbox.mv.utils;
|
||||||
|
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author admin
|
* @author admin
|
||||||
* @since 2023/6/12 21:32
|
* @since 2023/6/12 21:32
|
||||||
*/
|
*/
|
||||||
public class StringUtils {
|
public class StringUtils {
|
||||||
|
|
||||||
|
public static final String EMPTY = "";
|
||||||
|
|
||||||
public static boolean isNotEmpty(final CharSequence cs) {
|
public static boolean isNotEmpty(final CharSequence cs) {
|
||||||
return !isEmpty(cs);
|
return !isEmpty(cs);
|
||||||
}
|
}
|
||||||
@@ -13,4 +19,57 @@ public class StringUtils {
|
|||||||
public static boolean isEmpty(final CharSequence cs) {
|
public static boolean isEmpty(final CharSequence cs) {
|
||||||
return cs == null || cs.length() == 0;
|
return cs == null || cs.length() == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static String defaultIfEmpty(final String str, String defaultStr) {
|
||||||
|
return isNotEmpty(str) ? str : defaultStr;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String trimToEmpty(final String str) {
|
||||||
|
return str == null ? EMPTY : str.trim();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static List<String> reverseSplit(String s, String delimiter, int limit) {
|
||||||
|
List<String> result = new ArrayList<>();
|
||||||
|
if (s == null || delimiter == null || limit <= 0) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastIndex = s.lastIndexOf(delimiter);
|
||||||
|
while (limit > 1 && lastIndex != -1) {
|
||||||
|
result.add(0, s.substring(lastIndex + delimiter.length()));
|
||||||
|
s = s.substring(0, lastIndex);
|
||||||
|
lastIndex = s.lastIndexOf(delimiter);
|
||||||
|
limit--;
|
||||||
|
}
|
||||||
|
result.add(0, s);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String cleanString(String s) {
|
||||||
|
// 去除乱码 以ISO8859-1方式读取UTF-8编码的中文
|
||||||
|
if (s.contains("ç") ||
|
||||||
|
s.contains("å") ||
|
||||||
|
s.contains("ğ") ||
|
||||||
|
s.contains("è") ||
|
||||||
|
s.contains("â") ||
|
||||||
|
s.contains("Š") ||
|
||||||
|
s.contains("ã") ||
|
||||||
|
s.contains("é") ||
|
||||||
|
s.contains("æ") ||
|
||||||
|
s.contains("§") ||
|
||||||
|
s.contains("ï")) {
|
||||||
|
s = new String(s.getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
|
||||||
|
}
|
||||||
|
s = s
|
||||||
|
.replace('(', ' ')
|
||||||
|
.replace(')', ' ')
|
||||||
|
.replace('(', ' ')
|
||||||
|
.replace(')', ' ')
|
||||||
|
.replace('/', ' ')
|
||||||
|
.replace('[', ' ')
|
||||||
|
.replace(']', ' ')
|
||||||
|
.trim();
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@
|
|||||||
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
|
<statusListener class="ch.qos.logback.core.status.NopStatusListener" />
|
||||||
|
|
||||||
<property name="ENCODING" value="utf-8" />
|
<property name="ENCODING" value="utf-8" />
|
||||||
<property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg %n"/>
|
<property name="PATTERN" value="%d{yyyy-MM-dd HH:mm:ss.SSS, GMT+8} [%thread] %-5level %logger{36} - %msg %n"/>
|
||||||
<property name="PATTERN-COLOR" value="%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS}) [%thread] %highlight(%-5level) %green(%logger{36}) - %highlight(%msg) %n"/>
|
<property name="PATTERN-COLOR" value="%yellow(%d{yyyy-MM-dd HH:mm:ss.SSS, GMT+8}) [%thread] %highlight(%-5level) %green(%logger{36}) - %highlight(%msg) %n"/>
|
||||||
|
|
||||||
<!-- 控制台输出 -->
|
<!-- 控制台输出 -->
|
||||||
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
|
||||||
|
|||||||
@@ -8,6 +8,14 @@
|
|||||||
"searchable": 1,
|
"searchable": 1,
|
||||||
"quickSearch": 1,
|
"quickSearch": 1,
|
||||||
"filterable": 1
|
"filterable": 1
|
||||||
|
}, {
|
||||||
|
"key": "MV_vod_2",
|
||||||
|
"name": "👀┃DOME┃视频",
|
||||||
|
"type": 1,
|
||||||
|
"api": "./vod/dome",
|
||||||
|
"searchable": 1,
|
||||||
|
"quickSearch": 1,
|
||||||
|
"filterable": 1
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user