This commit is contained in:
commit
854504eae9
Binary file not shown.
|
|
@ -0,0 +1,16 @@
|
||||||
|
---
|
||||||
|
name: 功能新增请求
|
||||||
|
about: 请求添加一个新的功能
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**问题描述**
|
||||||
|
|
||||||
|
简要描述新的功能要解决的问题
|
||||||
|
|
||||||
|
**功能描述**
|
||||||
|
|
||||||
|
简要描述你想要新增的功能
|
||||||
|
|
@ -0,0 +1,20 @@
|
||||||
|
---
|
||||||
|
name: 规则问题反馈
|
||||||
|
about: 剧集规则或电影规则问题反馈
|
||||||
|
title: ''
|
||||||
|
labels: enhancement
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**原始标题**
|
||||||
|
|
||||||
|
```text
|
||||||
|
[Lilith-Raws] 鬼滅之刃 刀匠村篇 / Kimetsu no Yaiba - Katanakaji no Sato-Hen - 01 [Baha][WEB-DL][1080p][AVC AAC][CHT][MP4]
|
||||||
|
```
|
||||||
|
|
||||||
|
> 建议附上原始种子页面的链接
|
||||||
|
|
||||||
|
**问题描述**
|
||||||
|
|
||||||
|
简要描述有什么问题
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
---
|
||||||
|
name: 项目问题反馈
|
||||||
|
about: 反馈项目相关的问题
|
||||||
|
title: ''
|
||||||
|
labels: bug
|
||||||
|
assignees: ''
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
**部署环境(windows / docker)**
|
||||||
|
|
||||||
|
docker
|
||||||
|
|
||||||
|
**问题描述**
|
||||||
|
|
||||||
|
简要描述复现问题的操作,以及出现的具体问题
|
||||||
|
|
||||||
|
**相关日志**
|
||||||
|
|
||||||
|
docker 请执行 `docker logs -f jproxy` 并重新执行复现问题的操作截取重新操作后的日志
|
||||||
|
windows 在 logs 目录下
|
||||||
|
|
||||||
|
```text
|
||||||
|
请以代码的形式附上
|
||||||
|
```
|
||||||
|
|
||||||
|
**相关截图**
|
||||||
|
|
@ -0,0 +1,13 @@
|
||||||
|
[core]
|
||||||
|
repositoryformatversion = 0
|
||||||
|
filemode = true
|
||||||
|
bare = false
|
||||||
|
logallrefupdates = true
|
||||||
|
ignorecase = true
|
||||||
|
precomposeunicode = true
|
||||||
|
[remote "origin"]
|
||||||
|
url = https://github.com/LuckyPuppy514/jproxy.git
|
||||||
|
fetch = +refs/heads/*:refs/remotes/origin/*
|
||||||
|
[branch "main"]
|
||||||
|
remote = origin
|
||||||
|
merge = refs/heads/main
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
name: docker-build-test
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOCKERHUB_REPO: luckypuppy514/jproxy
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Cache local Maven repository
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository
|
||||||
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-maven-
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: Build with Maven
|
||||||
|
run: mvn clean package -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -B -V -P prod && java -Djarmode=layertools -jar target/jproxy.jar extract
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: ${{ env.DOCKERHUB_REPO }}
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./docker/Dockerfile
|
||||||
|
platforms: |
|
||||||
|
linux/amd64
|
||||||
|
linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ env.DOCKERHUB_REPO }}:test
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
name: docker-build
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- v*
|
||||||
|
|
||||||
|
env:
|
||||||
|
DOCKERHUB_REPO: luckypuppy514/jproxy
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
docker:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
- name: Cache local Maven repository
|
||||||
|
uses: actions/cache@v3
|
||||||
|
with:
|
||||||
|
path: ~/.m2/repository
|
||||||
|
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||||
|
restore-keys: |
|
||||||
|
${{ runner.os }}-maven-
|
||||||
|
- name: Set up JDK 17
|
||||||
|
uses: actions/setup-java@v3
|
||||||
|
with:
|
||||||
|
java-version: '17'
|
||||||
|
distribution: 'temurin'
|
||||||
|
- name: Build with Maven
|
||||||
|
run: mvn clean package -Dmaven.test.skip=true -Dmaven.javadoc.skip=true -B -V -P prod && java -Djarmode=layertools -jar target/jproxy.jar extract
|
||||||
|
- name: Set up QEMU
|
||||||
|
uses: docker/setup-qemu-action@v1
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v1
|
||||||
|
- name: Login to DockerHub
|
||||||
|
uses: docker/login-action@v1
|
||||||
|
with:
|
||||||
|
username: ${{ secrets.DOCKERHUB_USERNAME }}
|
||||||
|
password: ${{ secrets.DOCKERHUB_TOKEN }}
|
||||||
|
- name: Docker meta
|
||||||
|
id: meta
|
||||||
|
uses: docker/metadata-action@v4
|
||||||
|
with:
|
||||||
|
images: ${{ env.DOCKERHUB_REPO }}
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v2
|
||||||
|
with:
|
||||||
|
context: .
|
||||||
|
file: ./docker/Dockerfile
|
||||||
|
platforms: |
|
||||||
|
linux/amd64
|
||||||
|
linux/arm64
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ env.DOCKERHUB_REPO }}:latest
|
||||||
|
${{ env.DOCKERHUB_REPO }}:${{ steps.meta.outputs.version }}
|
||||||
|
labels: ${{ steps.meta.outputs.labels }}
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
.settings
|
||||||
|
logs
|
||||||
|
target
|
||||||
|
.classpath
|
||||||
|
.factorypath
|
||||||
|
.project
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.7/apache-maven-3.8.7-bin.zip
|
||||||
|
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.1/maven-wrapper-3.1.1.jar
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Copyright (c) 2023 LuckyPuppy514
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/LuckyPuppy514/jproxy">
|
||||||
|
<img alt="JProxy Logo" width="200" src="https://raw.githubusercontent.com/LuckyPuppy514/image/main/2023/2023-04-02/logo.png">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/LuckyPuppy514/jproxy"><img alt="stars" src="https://badgen.net/github/stars/LuckyPuppy514/jproxy"/></a>
|
||||||
|
<a href="https://github.com/LuckyPuppy514/jproxy"><img alt="forks" src="https://badgen.net/github/forks/LuckyPuppy514/jproxy"/></a>
|
||||||
|
<a href="https://hub.docker.com/r/luckypuppy514/jproxy"><img alt="docker pulls" src="https://img.shields.io/docker/pulls/luckypuppy514/jproxy.svg"/></a>
|
||||||
|
<a href="https://github.com/LuckyPuppy514/jproxy/blob/main/LICENSE.txt"><img alt="MIT License" src="https://badgen.net/github/license/LuckyPuppy514/jproxy"/></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
<a href="https://github.com/LuckyPuppy514/jproxy/blob/main/README.md">简体中文</a> | English
|
||||||
|
</div>
|
||||||
|
|
||||||
|
- [🌟 Introduce](#-introduce)
|
||||||
|
- [🧱 Install](#-install)
|
||||||
|
- [Docker](#docker)
|
||||||
|
- [Windows](#windows)
|
||||||
|
- [☃️ Basic Configuration](#️-basic-configuration)
|
||||||
|
- [😘 Contributing](#-contributing)
|
||||||
|
- [👏 Related Efforts](#-related-efforts)
|
||||||
|
- [🃏 License](#-license)
|
||||||
|
|
||||||
|
## 🌟 Introduce
|
||||||
|
|
||||||
|
A proxy between `Sonarr / Radarr` and `Jackett / Prowlarr`, mainly used to optimize search and improve recognition rate
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph LR
|
||||||
|
1[Sonarr / Radarr] == request Jackett / Prowlarr Torznab interface ==> 2(JProxy) == proxy Sonarr / Radarr request ==> 3(Jackett / Prowlarr)
|
||||||
|
|
||||||
|
3(Jackett / Prowlarr) == return raw result ==> 2(JProxy) == return formatted result ==> 1(Sonarr / Radarr)
|
||||||
|
|
||||||
|
2(JProxy) == optimize search keywords ==> 2(JProxy)
|
||||||
|
2(JProxy) == format search result ==> 2(JProxy)
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
## 🧱 Install
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
```text
|
||||||
|
version: '3.0'
|
||||||
|
services:
|
||||||
|
jproxy:
|
||||||
|
image: luckypuppy514/jproxy:latest
|
||||||
|
container_name: jproxy
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
- JAVA_OPTS=-Xms512m -Xmx512m
|
||||||
|
ports:
|
||||||
|
- 8117:8117
|
||||||
|
volumes:
|
||||||
|
- /docker/jproxy/database:/app/database
|
||||||
|
```
|
||||||
|
|
||||||
|
If you want deploy via `docker run` ,see [docker-run.sh](https://github.com/LuckyPuppy514/jproxy/blob/main/docker/docker-run.sh)
|
||||||
|
|
||||||
|
| Parameter | Default | Description |
|
||||||
|
| :--------------------------: | :---------------: | :----------------------------------------------------------------------------------------------------------------------------: |
|
||||||
|
| PUID | 0 | User ID |
|
||||||
|
| PGID | 0 | Group ID |
|
||||||
|
| TZ | Asia/Shanghai | Timezone |
|
||||||
|
| JAVA_OPTS | -Xms512m -Xmx512m | JVM parameters |
|
||||||
|
| CACHE_EXPIRES | 4320 | Cache expiration time (minutes) |
|
||||||
|
| TOKEN_EXPIRES | 10080 | Login expiration time (minutes) |
|
||||||
|
| SYNC_INTERVAL | 3 | Synchronization interval (minutes) |
|
||||||
|
| RENAME_FILE | true | File rename switch (true/false) |
|
||||||
|
| MIN_COUNT | 8 | Append title of primary language (without season and episode number) to search while current result count less than this value |
|
||||||
|
| INDEXER_RESULT_CACHE_EXPIRES | 15 | Indexer result cache expiration time (minutes) |
|
||||||
|
|
||||||
|
If you need to set a proxy, you can append the corresponding proxy parameters in `JAVA_OPTS`
|
||||||
|
|
||||||
|
- HTTP Proxy
|
||||||
|
`-Xms512m -Xmx512m -Dhttp.proxyHost=192.168.6.2 -Dhttp.proxyPort=12345`
|
||||||
|
- SOCKS Proxy
|
||||||
|
`-Xms512m -Xmx512m -DsocksProxyHost=192.168.6.2 -DsocksProxyPort=54321`
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
1. [Download jdk17](https://kutt.lckp.top/yrnerc), install and configure environment variables
|
||||||
|
2. [Download windows.zip](https://github.com/LuckyPuppy514/jproxy/releases) ,unzip to the installation directory
|
||||||
|
|
||||||
|
| Filename | Explanation | Remark |
|
||||||
|
| :----------------: | :-----------------------: | :-------------------------------------: |
|
||||||
|
| startup.bat | starup script | - |
|
||||||
|
| shutdown.bat | shutdown script | - |
|
||||||
|
| startup-daemon.bat | startup background script | hidden window running in the background |
|
||||||
|
| database | database | keep it while upgrade |
|
||||||
|
| config | configuration files | - |
|
||||||
|
| jproxy.jar | Runnable jar package | - |
|
||||||
|
|
||||||
|
## ☃️ Basic Configuration
|
||||||
|
|
||||||
|
- URL: `http://127.0.0.1:8117/login`
|
||||||
|
- User: `jproxy`
|
||||||
|
- Password: `jproxy@2023`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
① Fill in `Sonarr Server Url`, `API KEY`, and `Indexer Address` in `System - Configure` (Jackett or Prowlarr)
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
💡 After saving, it should normally be as shown in the picture below ✅, otherwise please check the input and network connectivity
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
② For the first use, it is recommended to manually synchronize `Series Title` and `Series Rule` once (it will be automatically synchronized later)
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
③ Modify the `IP` and `Port` of the indexer to the `IP` and `Port` of JProxy, and append the path
|
||||||
|
|
||||||
|
Jackett
|
||||||
|
|
||||||
|
`http://192.168.6.15:9117/api/v2.0/......` ➡️ `http://192.168.6.14:8117/sonarr/jackett/api/v2.0/......`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Prowlarr
|
||||||
|
|
||||||
|
`http://192.168.6.15:9696` ➡️ `http://192.168.6.14:8117/sonarr/prowlarr`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
And change `Authentication Required` to `Disabled for Local Addresses`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[🎗️ For advanced configuration and usage, see wiki](https://github.com/LuckyPuppy514/jproxy/wiki)
|
||||||
|
|
||||||
|
## 😘 Contributing
|
||||||
|
|
||||||
|
Feel free to dive in or submit PRs.
|
||||||
|
|
||||||
|
- [arco-design-pro-vue](https://github.com/arco-design/arco-design-pro-vue)
|
||||||
|
- [spring-boot](https://github.com/spring-projects/spring-boot)
|
||||||
|
- [sqlite](https://github.com/sqlite/sqlite)
|
||||||
|
- [liquibase](https://github.com/liquibase/liquibase)
|
||||||
|
- [mybatis](https://github.com/mybatis/mybatis-3)
|
||||||
|
- [mybatis-plus](https://github.com/baomidou/mybatis-plus)
|
||||||
|
- [caffeine](https://github.com/ben-manes/caffeine)
|
||||||
|
- [knife4j](https://github.com/xiaoymin/knife4j)
|
||||||
|
- [charon](https://github.com/mkopylec/charon-spring-boot-starter)
|
||||||
|
- [jib](https://github.com/GoogleContainerTools/jib)
|
||||||
|
|
||||||
|
## 👏 Related Efforts
|
||||||
|
|
||||||
|
- [Sonarr](https://github.com/Sonarr/Sonarr)
|
||||||
|
- [Radarr](https://github.com/radarr/radarr)
|
||||||
|
- [Jackett](https://github.com/Jackett/Jackett)
|
||||||
|
- [Prowlarr](https://github.com/Prowlarr/Prowlarr)
|
||||||
|
- [qBittorrent](https://github.com/qbittorrent/qBittorrent)
|
||||||
|
|
||||||
|
## 🃏 License
|
||||||
|
|
||||||
|
[MIT](https://github.com/LuckyPuppy514/jproxy/blob/main/LICENSE) © LuckyPuppy514
|
||||||
|
|
@ -0,0 +1,169 @@
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/LuckyPuppy514/jproxy">
|
||||||
|
<img alt="JProxy Logo" width="200" src="https://raw.githubusercontent.com/LuckyPuppy514/image/main/2023/2023-04-02/logo.png">
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://github.com/LuckyPuppy514/jproxy"><img alt="stars" src="https://badgen.net/github/stars/LuckyPuppy514/jproxy"/></a>
|
||||||
|
<a href="https://github.com/LuckyPuppy514/jproxy"><img alt="forks" src="https://badgen.net/github/forks/LuckyPuppy514/jproxy"/></a>
|
||||||
|
<a href="https://hub.docker.com/r/luckypuppy514/jproxy"><img alt="docker pulls" src="https://img.shields.io/docker/pulls/luckypuppy514/jproxy.svg"/></a>
|
||||||
|
<a href="https://github.com/LuckyPuppy514/jproxy/blob/main/LICENSE.txt"><img alt="MIT License" src="https://badgen.net/github/license/LuckyPuppy514/jproxy"/></a>
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<div align="center">
|
||||||
|
简体中文 | <a href="https://github.com/LuckyPuppy514/jproxy/blob/main/README.en_US.md">English</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
- [🌟 项目简介](#-项目简介)
|
||||||
|
- [🧱 项目安装](#-项目安装)
|
||||||
|
- [Docker](#docker)
|
||||||
|
- [Windows](#windows)
|
||||||
|
- [☃️ 基础配置](#️-基础配置)
|
||||||
|
- [😘 如何贡献](#-如何贡献)
|
||||||
|
- [👏 相关仓库](#-相关仓库)
|
||||||
|
- [🃏 使用许可](#-使用许可)
|
||||||
|
|
||||||
|
## 🌟 项目简介
|
||||||
|
|
||||||
|
介于 `Sonarr / Radarr` 和 `Jackett / Prowlarr` 之间的代理,主要用于优化查询和提升识别率
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
graph LR
|
||||||
|
1[Sonarr / Radarr] == 请求 Jackett / Prowlarr Torznab 接口 ==> 2(JProxy) == 代理 Sonarr / Radarr 请求 ==> 3(Jackett / Prowlarr)
|
||||||
|
|
||||||
|
3(Jackett / Prowlarr) == 返回原始结果 ==> 2(JProxy) == 返回格式化结果 ==> 1(Sonarr / Radarr)
|
||||||
|
|
||||||
|
2(JProxy) == 优化查询关键字 ==> 2(JProxy)
|
||||||
|
2(JProxy) == 格式化查询结果 ==> 2(JProxy)
|
||||||
|
```
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
## 🧱 项目安装
|
||||||
|
|
||||||
|
### Docker
|
||||||
|
|
||||||
|
```text
|
||||||
|
version: '3.0'
|
||||||
|
services:
|
||||||
|
jproxy:
|
||||||
|
image: luckypuppy514/jproxy:latest
|
||||||
|
container_name: jproxy
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
- JAVA_OPTS=-Xms512m -Xmx512m
|
||||||
|
ports:
|
||||||
|
- 8117:8117
|
||||||
|
volumes:
|
||||||
|
- /docker/jproxy/database:/app/database
|
||||||
|
```
|
||||||
|
|
||||||
|
如需使用 `docker run` 进行部署,请参考 [docker-run.sh](https://github.com/LuckyPuppy514/jproxy/blob/main/docker/docker-run.sh)
|
||||||
|
|
||||||
|
| 参数名 | 默认值 | 说明 |
|
||||||
|
| :--------------------------: | :---------------: | :----------------------------------------------------------: |
|
||||||
|
| PUID | 0 | 用户 ID |
|
||||||
|
| PGID | 0 | 组 ID |
|
||||||
|
| TZ | Asia/Shanghai | 时区 |
|
||||||
|
| JAVA_OPTS | -Xms512m -Xmx512m | JVM 运行参数 |
|
||||||
|
| CACHE_EXPIRES | 4320 | 缓存过期时间(分钟) |
|
||||||
|
| TOKEN_EXPIRES | 10080 | 登录过期时间(分钟) |
|
||||||
|
| SYNC_INTERVAL | 3 | 同步间隔(分钟) |
|
||||||
|
| RENAME_FILE | true | 文件重命名开关(true/false) |
|
||||||
|
| MIN_COUNT | 6 | 当结果数量少于该值时,会追加主语言标题(去除季数和集数)搜索 |
|
||||||
|
| INDEXER_RESULT_CACHE_EXPIRES | 15 | 索引器结果缓存过期时间(分钟) |
|
||||||
|
|
||||||
|
如需设置代理,可在 `JAVA_OPTS` 添加对应的代理参数
|
||||||
|
|
||||||
|
- HTTP 代理
|
||||||
|
`-Xms512m -Xmx512m -Dhttp.proxyHost=192.168.6.2 -Dhttp.proxyPort=12345`
|
||||||
|
- SOCKS 代理
|
||||||
|
`-Xms512m -Xmx512m -DsocksProxyHost=192.168.6.2 -DsocksProxyPort=54321`
|
||||||
|
|
||||||
|
### Windows
|
||||||
|
|
||||||
|
1. [下载 jdk17](https://kutt.lckp.top/yrnerc),安装并配置好环境变量
|
||||||
|
2. [下载 windows.zip](https://github.com/LuckyPuppy514/jproxy/releases) ,解压到安装目录
|
||||||
|
|
||||||
|
| 文件名 | 说明 | 备注 |
|
||||||
|
| :----------------: | :-----------: | :--------------: |
|
||||||
|
| startup.bat | 启动脚本 | - |
|
||||||
|
| shutdown.bat | 关闭脚本 | - |
|
||||||
|
| startup-daemon.bat | 后台启动脚本 | 隐藏窗口后台运行 |
|
||||||
|
| database | 数据库 | 升级请保留数据库 |
|
||||||
|
| config | 配置文件 | - |
|
||||||
|
| jproxy.jar | 可执行 jar 包 | - |
|
||||||
|
|
||||||
|
## ☃️ 基础配置
|
||||||
|
|
||||||
|
- 地址:`http://127.0.0.1:8117/login`
|
||||||
|
- 用户:`jproxy`
|
||||||
|
- 密码:`jproxy@2023`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
① 在 `系统配置 - 基础配置` 中填写 `Sonarr 服务地址` 和 `API 密钥`,以及 `索引器地址`(Jackett / Prowlarr 二选一即可)
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
💡 保存后,正常应如下图所示 ✅ ,否则请检查输入和网络连通性
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
② 首次使用,建议手动同步一次 `剧集标题` 和 `剧集规则`(后续会自动同步)
|
||||||
|
|
||||||
|

|
||||||
|

|
||||||
|
|
||||||
|
③ 修改索引器地址的 `IP` 和 `端口号` 为 JProxy 的 `IP` 和 `端口号`,并追加相应路径
|
||||||
|
|
||||||
|
Jackett
|
||||||
|
|
||||||
|
`http://192.168.6.15:9117/api/v2.0/......` ➡️ `http://192.168.6.14:8117/sonarr/jackett/api/v2.0/......`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
Prowlarr
|
||||||
|
|
||||||
|
`http://192.168.6.15:9696` ➡️ `http://192.168.6.14:8117/sonarr/prowlarr`
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
并关闭本地安全认证
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
[🎗️ 进阶配置和使用说明请查看 Wiki](https://github.com/LuckyPuppy514/jproxy/wiki)
|
||||||
|
|
||||||
|
## 😘 如何贡献
|
||||||
|
|
||||||
|
非常欢迎你的加入 或者提交一个 Pull Request
|
||||||
|
|
||||||
|
- [arco-design-pro-vue](https://github.com/arco-design/arco-design-pro-vue)
|
||||||
|
- [spring-boot](https://github.com/spring-projects/spring-boot)
|
||||||
|
- [sqlite](https://github.com/sqlite/sqlite)
|
||||||
|
- [liquibase](https://github.com/liquibase/liquibase)
|
||||||
|
- [mybatis](https://github.com/mybatis/mybatis-3)
|
||||||
|
- [mybatis-plus](https://github.com/baomidou/mybatis-plus)
|
||||||
|
- [caffeine](https://github.com/ben-manes/caffeine)
|
||||||
|
- [knife4j](https://github.com/xiaoymin/knife4j)
|
||||||
|
- [charon](https://github.com/mkopylec/charon-spring-boot-starter)
|
||||||
|
- [jib](https://github.com/GoogleContainerTools/jib)
|
||||||
|
|
||||||
|
## 👏 相关仓库
|
||||||
|
|
||||||
|
- [Sonarr](https://github.com/Sonarr/Sonarr)
|
||||||
|
- [Radarr](https://github.com/radarr/radarr)
|
||||||
|
- [Jackett](https://github.com/Jackett/Jackett)
|
||||||
|
- [Prowlarr](https://github.com/Prowlarr/Prowlarr)
|
||||||
|
- [qBittorrent](https://github.com/qbittorrent/qBittorrent)
|
||||||
|
|
||||||
|
## 🃏 使用许可
|
||||||
|
|
||||||
|
[MIT](https://github.com/LuckyPuppy514/jproxy/blob/main/LICENSE) © LuckyPuppy514
|
||||||
|
|
@ -0,0 +1,244 @@
|
||||||
|
|
||||||
|
[中文](https://github.com/LuckyPuppy514/jproxy/blob/main/changelog.md) | English
|
||||||
|
|
||||||
|
# Change Logs
|
||||||
|
|
||||||
|
## v3.4.5 2024-06-18
|
||||||
|
|
||||||
|
👻 Fix the issue of NullPointerException
|
||||||
|
|
||||||
|
## v3.4.4 2024-06-04
|
||||||
|
|
||||||
|
👻 Fix the issue of nested path while renaming
|
||||||
|
|
||||||
|
## v3.4.3 2024-02-20
|
||||||
|
|
||||||
|
🚀 Optimize radarr title matching logic
|
||||||
|
|
||||||
|
## v3.4.2 2024-02-19
|
||||||
|
|
||||||
|
👻 Fix bug of rename
|
||||||
|
|
||||||
|
## v3.4.1 2023-10-13
|
||||||
|
|
||||||
|
🚀 Append other info while rename file
|
||||||
|
|
||||||
|
## v3.4.0 2023-08-09
|
||||||
|
|
||||||
|
👻 Fix the problem that appending the main language title actually appends the alternate language title
|
||||||
|
|
||||||
|
## v3.3.9 2023-08-08
|
||||||
|
|
||||||
|
🆕 Caching indexer query result
|
||||||
|
|
||||||
|
## v3.3.8 2023-08-06
|
||||||
|
|
||||||
|
👻 Fix bug of pagination
|
||||||
|
|
||||||
|
## v3.3.7 2023-08-06
|
||||||
|
|
||||||
|
🚀 Optimize search logic
|
||||||
|
|
||||||
|
## v3.3.6 2023-08-06
|
||||||
|
|
||||||
|
🚀 Optimize matching logic
|
||||||
|
|
||||||
|
## v3.3.5 2023-08-06
|
||||||
|
|
||||||
|
🚀 Optimize language matching logic
|
||||||
|
|
||||||
|
## v3.3.4 2023-07-27
|
||||||
|
|
||||||
|
🆕 New parameter `min-count`:append primary title (without season and episode number) to search while current result count less than this value
|
||||||
|
|
||||||
|
## v3.3.3 2023-07-17
|
||||||
|
|
||||||
|
🚀 Optimize title matching logic
|
||||||
|
|
||||||
|
## v3.3.2 2023-07-14
|
||||||
|
|
||||||
|
🚀 Optimize search logic
|
||||||
|
|
||||||
|
## v3.3.1 2023-07-08
|
||||||
|
|
||||||
|
🚀 Optimize import logic
|
||||||
|
|
||||||
|
## v3.3.0 2023-06-27
|
||||||
|
|
||||||
|
🚀 Optimize file rename logic
|
||||||
|
|
||||||
|
## v3.2.9 2023-06-22
|
||||||
|
|
||||||
|
🚀 Optimize file rename logic
|
||||||
|
|
||||||
|
## v3.2.8 2023-06-13
|
||||||
|
|
||||||
|
🚀 Optimize clean title logic
|
||||||
|
|
||||||
|
## v3.2.7 2023-06-04
|
||||||
|
|
||||||
|
👻 Fix bug of clean title
|
||||||
|
👻 Fix bug about TMDB sync
|
||||||
|
|
||||||
|
## v3.2.6 2023-06-03
|
||||||
|
|
||||||
|
🚀 Optimize title matching logic
|
||||||
|
|
||||||
|
## v3.2.5 2023-06-03
|
||||||
|
|
||||||
|
🚀 Optimize title matching logic
|
||||||
|
|
||||||
|
## v3.2.4 2023-05-29
|
||||||
|
|
||||||
|
👏 Merge pull request [#41](https://github.com/LuckyPuppy514/jproxy/pull/41) from DDS-Derek/main
|
||||||
|
|
||||||
|
## v3.2.3 2023-05-28
|
||||||
|
|
||||||
|
🚀 Optimize downloader file rename logic
|
||||||
|
|
||||||
|
## v3.2.2 2023-05-23
|
||||||
|
|
||||||
|
🚀 Optimize search logic
|
||||||
|
|
||||||
|
## v3.2.1 2023-04-30
|
||||||
|
|
||||||
|
🆕 Add title at TMDB Menu
|
||||||
|
🚀 Optimize search logic
|
||||||
|
|
||||||
|
## v3.2.0 2023-04-30
|
||||||
|
|
||||||
|
🚀 Optimize clean title logic
|
||||||
|
|
||||||
|
## v3.1.9 2023-04-29
|
||||||
|
|
||||||
|
👻 Fix downloader rename bug
|
||||||
|
|
||||||
|
## v3.1.8 2023-04-17
|
||||||
|
|
||||||
|
🆕 Added version display and upgrade prompt
|
||||||
|
|
||||||
|
## v3.1.7 2023-04-16
|
||||||
|
|
||||||
|
🆕 Add file rename switch
|
||||||
|
|
||||||
|
## v3.1.6 2023-04-14
|
||||||
|
|
||||||
|
👻 Fix downloader rename bug
|
||||||
|
|
||||||
|
## v3.1.4 2023-04-14
|
||||||
|
|
||||||
|
🚀 Optimize downloader rename
|
||||||
|
|
||||||
|
## v3.1.3 2023-04-14
|
||||||
|
|
||||||
|
🚀 Optimize qBittorrent rename
|
||||||
|
🆕 Added Transmission rename
|
||||||
|
🚀 Optimize search of series without absolute number
|
||||||
|
|
||||||
|
## v3.1.2 2023-04-12
|
||||||
|
|
||||||
|
👏 Merge pull request [#27](https://github.com/LuckyPuppy514/jproxy/pull/27)
|
||||||
|
|
||||||
|
## v3.1.1 2023-04-12
|
||||||
|
|
||||||
|
🚀 Optimize qBittorrent rename
|
||||||
|
|
||||||
|
## v3.1.0 2023-04-11
|
||||||
|
|
||||||
|
🚮 Remove the proxy of qBittorrent (if you set the proxy in Sonarr according to the old version, please restore the settings)
|
||||||
|
🆕 Add qBittorrent rename function, support Sonarr and Radarr
|
||||||
|
|
||||||
|
## v3.0.9 2023-04-10
|
||||||
|
|
||||||
|
🆕 Switch cache database: Redis => Caffeine
|
||||||
|
🚀 Optimize title matching logic
|
||||||
|
|
||||||
|
## v3.0.8 2023-04-09
|
||||||
|
|
||||||
|
🆕 Add liquibase config
|
||||||
|
|
||||||
|
## v3.0.7 2023-04-09
|
||||||
|
|
||||||
|
🆕 Add package way
|
||||||
|
|
||||||
|
## v3.0.6 2023-04-08
|
||||||
|
|
||||||
|
🆕 Added the function to modify the TMDB title
|
||||||
|
|
||||||
|
## v3.0.5 2023-04-08
|
||||||
|
|
||||||
|
👻 Fix the downloaded bug
|
||||||
|
|
||||||
|
## v3.0.4 2023-04-08
|
||||||
|
|
||||||
|
👻 Fix BUG of append TMDB title to search
|
||||||
|
|
||||||
|
## v3.0.3 2023-04-07
|
||||||
|
|
||||||
|
🚀 Optimize title matching logic
|
||||||
|
|
||||||
|
## v3.0.2 2023-04-07
|
||||||
|
|
||||||
|
🚀 Optimize Radarr title matching logic
|
||||||
|
|
||||||
|
## v3.0.1 2023-04-07
|
||||||
|
|
||||||
|
🆕 Add a backup address for the rule to avoid the inability to synchronize the rules due to the inability to access github
|
||||||
|
🚀 Docker basic image changes to support ARM architecture
|
||||||
|
|
||||||
|
## v3.0.0 2023-04-06
|
||||||
|
|
||||||
|
🚨 Code refactoring, not compatible with v2 version
|
||||||
|
|
||||||
|
🆕 Separation of front and back ends, new WebUI
|
||||||
|
🆕 Logical reconstruction, the matching method is separated from the original single rule into multiple marking rules, which is more free and has a higher recognition rate
|
||||||
|
🆕 Automatically append the selected language title to optimize Sonarr search via TMDB
|
||||||
|
🆕 Add support for Radarr, automatically add the main language title to optimize the search, adapt to the new logic, format the results, and improve the recognition rate
|
||||||
|
🆕 The rule sharing is changed to Pull Request, and the rule download is changed to directly synchronize the rules under the `src/main/resources/rule` directory of this project
|
||||||
|
|
||||||
|
## v2.6.5 2023-01-17
|
||||||
|
|
||||||
|
🚀 Improve: torrent name format(reduce import error)
|
||||||
|
|
||||||
|
## v2.6.4 2022-09-21
|
||||||
|
|
||||||
|
👻 Fixed: Market-Search, sort bug of download count
|
||||||
|
🆕 New Function: enable modify username while change password
|
||||||
|
|
||||||
|
## v2.6.3 2022-09-02
|
||||||
|
|
||||||
|
👻 Fixed: replace WebClient with RestTemplate to solve request error sometime
|
||||||
|
|
||||||
|
## v2.6.2 2022-08-10
|
||||||
|
|
||||||
|
👻 Fixed: can not format season and ep or date in search key while series type is Standard or Daily
|
||||||
|
|
||||||
|
## v2.6.1 2022-08-07
|
||||||
|
|
||||||
|
👻 Fixed: part of BT/PT indexers can not download while use qBittorrent proxy
|
||||||
|
|
||||||
|
## v2.6.0 2022-08-05
|
||||||
|
|
||||||
|
🆕 New Function: qBittorrent Proxy
|
||||||
|
🆕 New Function: add search condition: remark
|
||||||
|
👻 Fixed: import wrong season while sonarr unrecognize the title of torrent
|
||||||
|
|
||||||
|
## v2.5.2 2022-08-01
|
||||||
|
|
||||||
|
🆕 New Function: Reachalbe test first when save proxy config
|
||||||
|
|
||||||
|
## v2.5.1 2022-07-31
|
||||||
|
|
||||||
|
🆕 Add README.md
|
||||||
|
👻 Fixed: docker build error at aarch64 by changing sqlite-jdbc version to: 3.39.2-SNAPSHOT
|
||||||
|
👻 Fixed: sync error
|
||||||
|
👻 Fixed: prowlarr error
|
||||||
|
|
||||||
|
## v2.5.0 2022-07-30
|
||||||
|
|
||||||
|
🆕 Web UI: Chinese or English
|
||||||
|
🆕 Proxy Config: Jackett / Prowlarr ip, port setting
|
||||||
|
🆕 Add Rule: Include search and result rule
|
||||||
|
🆕 Rule Manage: Search, edit, delete, share and import or export
|
||||||
|
🆕 Rule Market: Search rules shared by others and download
|
||||||
|
🆕 Rule Test: Add title list and check the result after format
|
||||||
|
|
@ -0,0 +1,244 @@
|
||||||
|
|
||||||
|
简体中文 | [English](https://github.com/LuckyPuppy514/jproxy/blob/main/changelog.en_US.md)
|
||||||
|
|
||||||
|
# 变更日志
|
||||||
|
|
||||||
|
## v3.4.5 2024-06-18
|
||||||
|
|
||||||
|
👻 修复空指针问题
|
||||||
|
|
||||||
|
## v3.4.4 2024-06-04
|
||||||
|
|
||||||
|
👻 修复重命名时路径嵌套的问题
|
||||||
|
|
||||||
|
## v3.4.3 2024-02-20
|
||||||
|
|
||||||
|
🚀 优化 Radarr 标题匹配逻辑
|
||||||
|
|
||||||
|
## v3.4.2 2024-02-19
|
||||||
|
|
||||||
|
👻 修复重命名问题
|
||||||
|
|
||||||
|
## v3.4.1 2023-10-13
|
||||||
|
|
||||||
|
🚀 文件重命名追加其他信息
|
||||||
|
|
||||||
|
## v3.4.0 2023-08-09
|
||||||
|
|
||||||
|
👻 修复追加主语言标题实际上追加的是备用语言标题的问题
|
||||||
|
|
||||||
|
## v3.3.9 2023-08-08
|
||||||
|
|
||||||
|
🆕 缓存索引器查询结果
|
||||||
|
|
||||||
|
## v3.3.8 2023-08-06
|
||||||
|
|
||||||
|
👻 处理分页异常问题
|
||||||
|
|
||||||
|
## v3.3.7 2023-08-06
|
||||||
|
|
||||||
|
🚀 优化查询逻辑
|
||||||
|
|
||||||
|
## v3.3.6 2023-08-06
|
||||||
|
|
||||||
|
🚀 优化匹配逻辑
|
||||||
|
|
||||||
|
## v3.3.5 2023-08-06
|
||||||
|
|
||||||
|
🚀 优化语言匹配逻辑
|
||||||
|
|
||||||
|
## v3.3.4 2023-07-27
|
||||||
|
|
||||||
|
🆕 新增配置参数 `min-count`:当结果数量少于该值时,会追加主标题(去除季数和集数)搜索
|
||||||
|
|
||||||
|
## v3.3.3 2023-07-17
|
||||||
|
|
||||||
|
🚀 优化标题匹配逻辑
|
||||||
|
|
||||||
|
## v3.3.2 2023-07-14
|
||||||
|
|
||||||
|
🚀 优化查询逻辑
|
||||||
|
|
||||||
|
## v3.3.1 2023-07-08
|
||||||
|
|
||||||
|
🚀 优化导入逻辑
|
||||||
|
|
||||||
|
## v3.3.0 2023-06-27
|
||||||
|
|
||||||
|
🚀 优化文件重命名逻辑
|
||||||
|
|
||||||
|
## v3.2.9 2023-06-22
|
||||||
|
|
||||||
|
🚀 优化文件重命名逻辑
|
||||||
|
|
||||||
|
## v3.2.8 2023-06-13
|
||||||
|
|
||||||
|
🚀 优化净标题逻辑
|
||||||
|
|
||||||
|
## v3.2.7 2023-06-04
|
||||||
|
|
||||||
|
👻 修复净标题 BUG
|
||||||
|
👻 修复 TMDB 同步 BUG
|
||||||
|
|
||||||
|
## v3.2.6 2023-06-03
|
||||||
|
|
||||||
|
🚀 优化标题匹配逻辑
|
||||||
|
|
||||||
|
## v3.2.5 2023-06-03
|
||||||
|
|
||||||
|
🚀 优化标题匹配逻辑
|
||||||
|
|
||||||
|
## v3.2.4 2023-05-29
|
||||||
|
|
||||||
|
👏 合并来自 DDS-Derek/main 的 PR [#41](https://github.com/LuckyPuppy514/jproxy/pull/41)
|
||||||
|
|
||||||
|
## v3.2.3 2023-05-28
|
||||||
|
|
||||||
|
🚀 优化下载器文件重命名逻辑
|
||||||
|
|
||||||
|
## v3.2.2 2023-05-23
|
||||||
|
|
||||||
|
🚀 优化查询逻辑
|
||||||
|
|
||||||
|
## v3.2.1 2023-04-30
|
||||||
|
|
||||||
|
🆕 TMDB 新增标题新增功能
|
||||||
|
🚀 优化查询逻辑
|
||||||
|
|
||||||
|
## v3.2.0 2023-04-30
|
||||||
|
|
||||||
|
🚀 优化净标题逻辑
|
||||||
|
|
||||||
|
## v3.1.9 2023-04-29
|
||||||
|
|
||||||
|
👻 修复下载器重命名BUG
|
||||||
|
|
||||||
|
## v3.1.8 2023-04-17
|
||||||
|
|
||||||
|
🆕 新增版本号展示及版本升级提示
|
||||||
|
|
||||||
|
## v3.1.7 2023-04-16
|
||||||
|
|
||||||
|
🆕 新增文件重命名开关
|
||||||
|
|
||||||
|
## v3.1.6 2023-04-14
|
||||||
|
|
||||||
|
👻 修复下载器重命名BUG
|
||||||
|
|
||||||
|
## v3.1.4 2023-04-14
|
||||||
|
|
||||||
|
🚀 优化下载器重命名
|
||||||
|
|
||||||
|
## v3.1.3 2023-04-14
|
||||||
|
|
||||||
|
🚀 优化 qBittorrent 重命名
|
||||||
|
🆕 新增 Transmission 重命名
|
||||||
|
🚀 优化无绝对集数剧集查询
|
||||||
|
|
||||||
|
## v3.1.2 2023-04-12
|
||||||
|
|
||||||
|
👏 合并 PR [#27](https://github.com/LuckyPuppy514/jproxy/pull/27)
|
||||||
|
|
||||||
|
## v3.1.1 2023-04-12
|
||||||
|
|
||||||
|
🚀 优化 qBittorrent 重命名
|
||||||
|
|
||||||
|
## v3.1.0 2023-04-11
|
||||||
|
|
||||||
|
🚮 移除 qBittorrent 代理(如按旧版在 Sonarr 设置了代理,请还原设置)
|
||||||
|
🆕 新增 qBittorrent 重命名,支持 Sonarr 和 Radarr
|
||||||
|
|
||||||
|
## v3.0.9 2023-04-10
|
||||||
|
|
||||||
|
🆕 切换缓存数据库:Redis => Caffeine
|
||||||
|
🚀 优化标题匹配逻辑
|
||||||
|
|
||||||
|
## v3.0.8 2023-04-09
|
||||||
|
|
||||||
|
🆕 更新 liquibase 配置
|
||||||
|
|
||||||
|
## v3.0.7 2023-04-09
|
||||||
|
|
||||||
|
🆕 打包方式更新
|
||||||
|
|
||||||
|
## v3.0.6 2023-04-08
|
||||||
|
|
||||||
|
🆕 新增修改 TMDB 标题的功能
|
||||||
|
|
||||||
|
## v3.0.5 2023-04-08
|
||||||
|
|
||||||
|
👻 修复部分数据无法下载的问题
|
||||||
|
|
||||||
|
## v3.0.4 2023-04-08
|
||||||
|
|
||||||
|
👻 修复追加 TMDB 标题查询 BUG
|
||||||
|
|
||||||
|
## v3.0.3 2023-04-07
|
||||||
|
|
||||||
|
🚀 优化标题匹配逻辑
|
||||||
|
|
||||||
|
## v3.0.2 2023-04-07
|
||||||
|
|
||||||
|
🚀 优化 Radarr 标题匹配逻辑
|
||||||
|
|
||||||
|
## v3.0.1 2023-04-07
|
||||||
|
|
||||||
|
🆕 新增规则备用地址,避免因无法访问 github 导致无法同步规则
|
||||||
|
2. Docker 底层镜像变更,以支持 ARM 架构
|
||||||
|
|
||||||
|
## v3.0.0 2023-04-06
|
||||||
|
|
||||||
|
🚨 代码重构,不兼容 v2 版本
|
||||||
|
|
||||||
|
🆕 前后端分离,全新 WebUI
|
||||||
|
🆕 格式化逻辑重构,匹配方式由原来的单一规则,分离成多个标记规则,更自由且识别率更高
|
||||||
|
🆕 引入 TMDB,自动追加所选语言标题优化 Sonarr 查询
|
||||||
|
🆕 添加对 Radarr 的支持,自动追加主语言标题优化查询,同时适配新逻辑,格式化结果,提升识别率
|
||||||
|
🆕 规则分享改成 Pull Request 形式,规则下载改为直接同步本仓库 `src/main/resources/rule` 目录下规则
|
||||||
|
|
||||||
|
## v2.6.5 2023-01-17
|
||||||
|
|
||||||
|
🚀 提升: 种子名称格式化(减少因为种子名称不规范导致不自动导入或导入错误季的问题)
|
||||||
|
|
||||||
|
## v2.6.4 2022-09-21
|
||||||
|
|
||||||
|
👻 修复:市场-查询,下载次数排序问题
|
||||||
|
🆕 新增:修改密码时可修改用户名
|
||||||
|
|
||||||
|
## v2.6.3 2022-09-02
|
||||||
|
|
||||||
|
👻 修复:使用 RestTemplate 代替 WebClient 以解决偶尔请求异常的问题
|
||||||
|
|
||||||
|
## v2.6.2 2022-08-10
|
||||||
|
|
||||||
|
👻 修复:当系列类型为:Standard, Daily 时,查询关键字季集,日期等参数无法格式化的问题
|
||||||
|
|
||||||
|
## v2.6.1 2022-08-07
|
||||||
|
|
||||||
|
👻 修复:部分 BT/PT 站当使用 qBittorrent 代理时无法下载的问题
|
||||||
|
|
||||||
|
## v2.6.0 2022-08-05
|
||||||
|
|
||||||
|
🆕 新增 qBittorrent 代理
|
||||||
|
🆕 新增搜索条件:备注
|
||||||
|
👻 修复:当 sonarr 无法识别种子标题时,导入错误季的问题
|
||||||
|
|
||||||
|
## v2.5.2 2022-08-01
|
||||||
|
|
||||||
|
🆕 新功能:保存代理配置时,先进行连通性测试
|
||||||
|
|
||||||
|
## v2.5.1 2022-07-30
|
||||||
|
|
||||||
|
🆕 更新 README.md
|
||||||
|
👻 变更:sqlite-jdbc 版本到:3.39.2-SNAPSHOT,用于修复在 aarch64 机器上 docker build 出错的问题
|
||||||
|
👻 修复:同步出错的问题
|
||||||
|
👻 修复:prowlarr 错误
|
||||||
|
|
||||||
|
## v2.5.0 2022-07-30
|
||||||
|
|
||||||
|
🆕 简单界面:支持中文和英文
|
||||||
|
🆕 代理配置:配置 Jackett / Prowlarr 的地址,端口等信息
|
||||||
|
🆕 新增规则:包括查询规则和结果规则
|
||||||
|
🆕 规则管理:查询,编辑,删除,分享,以及导入导出等
|
||||||
|
🆕 规则市场:可以查询大家分享的规则,并下载
|
||||||
|
🆕 用例测试:可以批量添加标题进行测试,查看格式化后的效果
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
FROM eclipse-temurin:17-jre
|
||||||
|
|
||||||
|
ENV TERM="xterm" \
|
||||||
|
TZ=Asia/Shanghai \
|
||||||
|
PUID=0 \
|
||||||
|
PGID=0 \
|
||||||
|
UMASK=022 \
|
||||||
|
JAVA_OPTS="-Xms512m -Xmx512m"
|
||||||
|
|
||||||
|
RUN set -ex && \
|
||||||
|
export DEBIAN_FRONTEND=noninteractive && \
|
||||||
|
apt update -y && \
|
||||||
|
apt install -y gosu dumb-init && \
|
||||||
|
apt autoremove -y && \
|
||||||
|
apt clean && \
|
||||||
|
rm -rf /var/lib/apt/lists/*
|
||||||
|
|
||||||
|
WORKDIR /app
|
||||||
|
COPY ./dependencies/ ./
|
||||||
|
COPY ./spring-boot-loader/ ./
|
||||||
|
COPY ./snapshot-dependencies/ ./
|
||||||
|
COPY ./application/ ./
|
||||||
|
COPY --chmod=755 ./docker/entrypoint.sh ./entrypoint.sh
|
||||||
|
|
||||||
|
ENTRYPOINT [ "/app/entrypoint.sh" ]
|
||||||
|
|
@ -0,0 +1,15 @@
|
||||||
|
version: '3.0'
|
||||||
|
services:
|
||||||
|
jproxy:
|
||||||
|
image: luckypuppy514/jproxy:latest
|
||||||
|
container_name: jproxy
|
||||||
|
restart: unless-stopped
|
||||||
|
environment:
|
||||||
|
- PUID=1000
|
||||||
|
- PGID=1000
|
||||||
|
- TZ=Asia/Shanghai
|
||||||
|
- JAVA_OPTS=-Xms512m -Xmx512m
|
||||||
|
ports:
|
||||||
|
- 8117:8117
|
||||||
|
volumes:
|
||||||
|
- /docker/jproxy/database:/app/database
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
#!/bin/bash
|
||||||
|
docker run --name jproxy \
|
||||||
|
--restart unless-stopped \
|
||||||
|
-e PUID=1000 \
|
||||||
|
-e PGID=1000 \
|
||||||
|
-e TZ=Asia/Shanghai \
|
||||||
|
-e JAVA_OPTS="-Xms512m -Xmx512m" \
|
||||||
|
-p 8117:8117 \
|
||||||
|
-v /docker/jproxy/database:/app/database \
|
||||||
|
-d luckypuppy514/jproxy:latest
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
# 初始化持久化目录
|
||||||
|
CONFIG_PATH=/app/config
|
||||||
|
DATABASE_PATH=/app/database
|
||||||
|
if [ ! -d "${CONFIG_PATH}" ]; then
|
||||||
|
mkdir -p ${CONFIG_PATH}
|
||||||
|
fi
|
||||||
|
if [ ! -d "${DATABASE_PATH}" ]; then
|
||||||
|
mkdir -p ${DATABASE_PATH}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# 初始化持久化配置
|
||||||
|
cp -n /app/BOOT-INF/classes/application.yml ${CONFIG_PATH}/application.yml
|
||||||
|
cp -n /app/BOOT-INF/classes/application-prod.yml ${CONFIG_PATH}/application-prod.yml
|
||||||
|
cp -n /app/BOOT-INF/classes/database/jproxy.db ${DATABASE_PATH}/jproxy.db
|
||||||
|
|
||||||
|
# 设置权限
|
||||||
|
chown -R ${PUID}:${PGID} /app/
|
||||||
|
umask ${UMASK}
|
||||||
|
|
||||||
|
# 启动应用
|
||||||
|
exec gosu ${PUID}:${PGID} dumb-init java ${JAVA_OPTS} -Dfile.encoding=utf-8 -Dspring.config.location=${CONFIG_PATH}/ org.springframework.boot.loader.JarLauncher
|
||||||
|
|
@ -0,0 +1,316 @@
|
||||||
|
#!/bin/sh
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
# or more contributor license agreements. See the NOTICE file
|
||||||
|
# distributed with this work for additional information
|
||||||
|
# regarding copyright ownership. The ASF licenses this file
|
||||||
|
# to you under the Apache License, Version 2.0 (the
|
||||||
|
# "License"); you may not use this file except in compliance
|
||||||
|
# with the License. You may obtain a copy of the License at
|
||||||
|
#
|
||||||
|
# https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
#
|
||||||
|
# Unless required by applicable law or agreed to in writing,
|
||||||
|
# software distributed under the License is distributed on an
|
||||||
|
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
# KIND, either express or implied. See the License for the
|
||||||
|
# specific language governing permissions and limitations
|
||||||
|
# under the License.
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
# Maven Start Up Batch script
|
||||||
|
#
|
||||||
|
# Required ENV vars:
|
||||||
|
# ------------------
|
||||||
|
# JAVA_HOME - location of a JDK home dir
|
||||||
|
#
|
||||||
|
# Optional ENV vars
|
||||||
|
# -----------------
|
||||||
|
# M2_HOME - location of maven2's installed home dir
|
||||||
|
# MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
# e.g. to debug Maven itself, use
|
||||||
|
# set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
# MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
# ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
if [ -z "$MAVEN_SKIP_RC" ] ; then
|
||||||
|
|
||||||
|
if [ -f /usr/local/etc/mavenrc ] ; then
|
||||||
|
. /usr/local/etc/mavenrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f /etc/mavenrc ] ; then
|
||||||
|
. /etc/mavenrc
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -f "$HOME/.mavenrc" ] ; then
|
||||||
|
. "$HOME/.mavenrc"
|
||||||
|
fi
|
||||||
|
|
||||||
|
fi
|
||||||
|
|
||||||
|
# OS specific support. $var _must_ be set to either true or false.
|
||||||
|
cygwin=false;
|
||||||
|
darwin=false;
|
||||||
|
mingw=false
|
||||||
|
case "`uname`" in
|
||||||
|
CYGWIN*) cygwin=true ;;
|
||||||
|
MINGW*) mingw=true;;
|
||||||
|
Darwin*) darwin=true
|
||||||
|
# Use /usr/libexec/java_home if available, otherwise fall back to /Library/Java/Home
|
||||||
|
# See https://developer.apple.com/library/mac/qa/qa1170/_index.html
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
if [ -x "/usr/libexec/java_home" ]; then
|
||||||
|
export JAVA_HOME="`/usr/libexec/java_home`"
|
||||||
|
else
|
||||||
|
export JAVA_HOME="/Library/Java/Home"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
if [ -r /etc/gentoo-release ] ; then
|
||||||
|
JAVA_HOME=`java-config --jre-home`
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$M2_HOME" ] ; then
|
||||||
|
## resolve links - $0 may be a link to maven's home
|
||||||
|
PRG="$0"
|
||||||
|
|
||||||
|
# need this for relative symlinks
|
||||||
|
while [ -h "$PRG" ] ; do
|
||||||
|
ls=`ls -ld "$PRG"`
|
||||||
|
link=`expr "$ls" : '.*-> \(.*\)$'`
|
||||||
|
if expr "$link" : '/.*' > /dev/null; then
|
||||||
|
PRG="$link"
|
||||||
|
else
|
||||||
|
PRG="`dirname "$PRG"`/$link"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
saveddir=`pwd`
|
||||||
|
|
||||||
|
M2_HOME=`dirname "$PRG"`/..
|
||||||
|
|
||||||
|
# make it fully qualified
|
||||||
|
M2_HOME=`cd "$M2_HOME" && pwd`
|
||||||
|
|
||||||
|
cd "$saveddir"
|
||||||
|
# echo Using m2 at $M2_HOME
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Cygwin, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $cygwin ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --unix "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --unix "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --unix "$CLASSPATH"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# For Mingw, ensure paths are in UNIX format before anything is touched
|
||||||
|
if $mingw ; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME="`(cd "$M2_HOME"; pwd)`"
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME="`(cd "$JAVA_HOME"; pwd)`"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ]; then
|
||||||
|
javaExecutable="`which javac`"
|
||||||
|
if [ -n "$javaExecutable" ] && ! [ "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ]; then
|
||||||
|
# readlink(1) is not available as standard on Solaris 10.
|
||||||
|
readLink=`which readlink`
|
||||||
|
if [ ! `expr "$readLink" : '\([^ ]*\)'` = "no" ]; then
|
||||||
|
if $darwin ; then
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaExecutable="`cd \"$javaHome\" && pwd -P`/javac"
|
||||||
|
else
|
||||||
|
javaExecutable="`readlink -f \"$javaExecutable\"`"
|
||||||
|
fi
|
||||||
|
javaHome="`dirname \"$javaExecutable\"`"
|
||||||
|
javaHome=`expr "$javaHome" : '\(.*\)/bin'`
|
||||||
|
JAVA_HOME="$javaHome"
|
||||||
|
export JAVA_HOME
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVACMD" ] ; then
|
||||||
|
if [ -n "$JAVA_HOME" ] ; then
|
||||||
|
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||||
|
# IBM's JDK on AIX uses strange locations for the executables
|
||||||
|
JAVACMD="$JAVA_HOME/jre/sh/java"
|
||||||
|
else
|
||||||
|
JAVACMD="$JAVA_HOME/bin/java"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
JAVACMD="`\\unset -f command; \\command -v java`"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ ! -x "$JAVACMD" ] ; then
|
||||||
|
echo "Error: JAVA_HOME is not defined correctly." >&2
|
||||||
|
echo " We cannot execute $JAVACMD" >&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$JAVA_HOME" ] ; then
|
||||||
|
echo "Warning: JAVA_HOME environment variable is not set."
|
||||||
|
fi
|
||||||
|
|
||||||
|
CLASSWORLDS_LAUNCHER=org.codehaus.plexus.classworlds.launcher.Launcher
|
||||||
|
|
||||||
|
# traverses directory structure from process work directory to filesystem root
|
||||||
|
# first directory with .mvn subdirectory is considered project base directory
|
||||||
|
find_maven_basedir() {
|
||||||
|
|
||||||
|
if [ -z "$1" ]
|
||||||
|
then
|
||||||
|
echo "Path not specified to find_maven_basedir"
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
basedir="$1"
|
||||||
|
wdir="$1"
|
||||||
|
while [ "$wdir" != '/' ] ; do
|
||||||
|
if [ -d "$wdir"/.mvn ] ; then
|
||||||
|
basedir=$wdir
|
||||||
|
break
|
||||||
|
fi
|
||||||
|
# workaround for JBEAP-8937 (on Solaris 10/Sparc)
|
||||||
|
if [ -d "${wdir}" ]; then
|
||||||
|
wdir=`cd "$wdir/.."; pwd`
|
||||||
|
fi
|
||||||
|
# end of workaround
|
||||||
|
done
|
||||||
|
echo "${basedir}"
|
||||||
|
}
|
||||||
|
|
||||||
|
# concatenates all lines of a file
|
||||||
|
concat_lines() {
|
||||||
|
if [ -f "$1" ]; then
|
||||||
|
echo "$(tr -s '\n' ' ' < "$1")"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
BASE_DIR=`find_maven_basedir "$(pwd)"`
|
||||||
|
if [ -z "$BASE_DIR" ]; then
|
||||||
|
exit 1;
|
||||||
|
fi
|
||||||
|
|
||||||
|
##########################################################################################
|
||||||
|
# Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
|
# This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
|
##########################################################################################
|
||||||
|
if [ -r "$BASE_DIR/.mvn/wrapper/maven-wrapper.jar" ]; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found .mvn/wrapper/maven-wrapper.jar"
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Couldn't find .mvn/wrapper/maven-wrapper.jar, downloading it ..."
|
||||||
|
fi
|
||||||
|
if [ -n "$MVNW_REPOURL" ]; then
|
||||||
|
jarUrl="$MVNW_REPOURL/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||||
|
else
|
||||||
|
jarUrl="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||||
|
fi
|
||||||
|
while IFS="=" read key value; do
|
||||||
|
case "$key" in (wrapperUrl) jarUrl="$value"; break ;;
|
||||||
|
esac
|
||||||
|
done < "$BASE_DIR/.mvn/wrapper/maven-wrapper.properties"
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Downloading from: $jarUrl"
|
||||||
|
fi
|
||||||
|
wrapperJarPath="$BASE_DIR/.mvn/wrapper/maven-wrapper.jar"
|
||||||
|
if $cygwin; then
|
||||||
|
wrapperJarPath=`cygpath --path --windows "$wrapperJarPath"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
if command -v wget > /dev/null; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found wget ... using wget"
|
||||||
|
fi
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
wget "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||||
|
else
|
||||||
|
wget --http-user=$MVNW_USERNAME --http-password=$MVNW_PASSWORD "$jarUrl" -O "$wrapperJarPath" || rm -f "$wrapperJarPath"
|
||||||
|
fi
|
||||||
|
elif command -v curl > /dev/null; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Found curl ... using curl"
|
||||||
|
fi
|
||||||
|
if [ -z "$MVNW_USERNAME" ] || [ -z "$MVNW_PASSWORD" ]; then
|
||||||
|
curl -o "$wrapperJarPath" "$jarUrl" -f
|
||||||
|
else
|
||||||
|
curl --user $MVNW_USERNAME:$MVNW_PASSWORD -o "$wrapperJarPath" "$jarUrl" -f
|
||||||
|
fi
|
||||||
|
|
||||||
|
else
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo "Falling back to using Java to download"
|
||||||
|
fi
|
||||||
|
javaClass="$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.java"
|
||||||
|
# For Cygwin, switch paths to Windows format before running javac
|
||||||
|
if $cygwin; then
|
||||||
|
javaClass=`cygpath --path --windows "$javaClass"`
|
||||||
|
fi
|
||||||
|
if [ -e "$javaClass" ]; then
|
||||||
|
if [ ! -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo " - Compiling MavenWrapperDownloader.java ..."
|
||||||
|
fi
|
||||||
|
# Compiling the Java class
|
||||||
|
("$JAVA_HOME/bin/javac" "$javaClass")
|
||||||
|
fi
|
||||||
|
if [ -e "$BASE_DIR/.mvn/wrapper/MavenWrapperDownloader.class" ]; then
|
||||||
|
# Running the downloader
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo " - Running MavenWrapperDownloader.java ..."
|
||||||
|
fi
|
||||||
|
("$JAVA_HOME/bin/java" -cp .mvn/wrapper MavenWrapperDownloader "$MAVEN_PROJECTBASEDIR")
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
##########################################################################################
|
||||||
|
# End of extension
|
||||||
|
##########################################################################################
|
||||||
|
|
||||||
|
export MAVEN_PROJECTBASEDIR=${MAVEN_BASEDIR:-"$BASE_DIR"}
|
||||||
|
if [ "$MVNW_VERBOSE" = true ]; then
|
||||||
|
echo $MAVEN_PROJECTBASEDIR
|
||||||
|
fi
|
||||||
|
MAVEN_OPTS="$(concat_lines "$MAVEN_PROJECTBASEDIR/.mvn/jvm.config") $MAVEN_OPTS"
|
||||||
|
|
||||||
|
# For Cygwin, switch paths to Windows format before running java
|
||||||
|
if $cygwin; then
|
||||||
|
[ -n "$M2_HOME" ] &&
|
||||||
|
M2_HOME=`cygpath --path --windows "$M2_HOME"`
|
||||||
|
[ -n "$JAVA_HOME" ] &&
|
||||||
|
JAVA_HOME=`cygpath --path --windows "$JAVA_HOME"`
|
||||||
|
[ -n "$CLASSPATH" ] &&
|
||||||
|
CLASSPATH=`cygpath --path --windows "$CLASSPATH"`
|
||||||
|
[ -n "$MAVEN_PROJECTBASEDIR" ] &&
|
||||||
|
MAVEN_PROJECTBASEDIR=`cygpath --path --windows "$MAVEN_PROJECTBASEDIR"`
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Provide a "standardized" way to retrieve the CLI args that will
|
||||||
|
# work with both Windows and non-Windows executions.
|
||||||
|
MAVEN_CMD_LINE_ARGS="$MAVEN_CONFIG $@"
|
||||||
|
export MAVEN_CMD_LINE_ARGS
|
||||||
|
|
||||||
|
WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
exec "$JAVACMD" \
|
||||||
|
$MAVEN_OPTS \
|
||||||
|
$MAVEN_DEBUG_OPTS \
|
||||||
|
-classpath "$MAVEN_PROJECTBASEDIR/.mvn/wrapper/maven-wrapper.jar" \
|
||||||
|
"-Dmaven.home=${M2_HOME}" \
|
||||||
|
"-Dmaven.multiModuleProjectDirectory=${MAVEN_PROJECTBASEDIR}" \
|
||||||
|
${WRAPPER_LAUNCHER} $MAVEN_CONFIG "$@"
|
||||||
|
|
@ -0,0 +1,188 @@
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Licensed to the Apache Software Foundation (ASF) under one
|
||||||
|
@REM or more contributor license agreements. See the NOTICE file
|
||||||
|
@REM distributed with this work for additional information
|
||||||
|
@REM regarding copyright ownership. The ASF licenses this file
|
||||||
|
@REM to you under the Apache License, Version 2.0 (the
|
||||||
|
@REM "License"); you may not use this file except in compliance
|
||||||
|
@REM with the License. You may obtain a copy of the License at
|
||||||
|
@REM
|
||||||
|
@REM https://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
@REM
|
||||||
|
@REM Unless required by applicable law or agreed to in writing,
|
||||||
|
@REM software distributed under the License is distributed on an
|
||||||
|
@REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
@REM KIND, either express or implied. See the License for the
|
||||||
|
@REM specific language governing permissions and limitations
|
||||||
|
@REM under the License.
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
@REM Maven Start Up Batch script
|
||||||
|
@REM
|
||||||
|
@REM Required ENV vars:
|
||||||
|
@REM JAVA_HOME - location of a JDK home dir
|
||||||
|
@REM
|
||||||
|
@REM Optional ENV vars
|
||||||
|
@REM M2_HOME - location of maven2's installed home dir
|
||||||
|
@REM MAVEN_BATCH_ECHO - set to 'on' to enable the echoing of the batch commands
|
||||||
|
@REM MAVEN_BATCH_PAUSE - set to 'on' to wait for a keystroke before ending
|
||||||
|
@REM MAVEN_OPTS - parameters passed to the Java VM when running Maven
|
||||||
|
@REM e.g. to debug Maven itself, use
|
||||||
|
@REM set MAVEN_OPTS=-Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000
|
||||||
|
@REM MAVEN_SKIP_RC - flag to disable loading of mavenrc files
|
||||||
|
@REM ----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
@REM Begin all REM lines with '@' in case MAVEN_BATCH_ECHO is 'on'
|
||||||
|
@echo off
|
||||||
|
@REM set title of command window
|
||||||
|
title %0
|
||||||
|
@REM enable echoing by setting MAVEN_BATCH_ECHO to 'on'
|
||||||
|
@if "%MAVEN_BATCH_ECHO%" == "on" echo %MAVEN_BATCH_ECHO%
|
||||||
|
|
||||||
|
@REM set %HOME% to equivalent of $HOME
|
||||||
|
if "%HOME%" == "" (set "HOME=%HOMEDRIVE%%HOMEPATH%")
|
||||||
|
|
||||||
|
@REM Execute a user defined script before this one
|
||||||
|
if not "%MAVEN_SKIP_RC%" == "" goto skipRcPre
|
||||||
|
@REM check for pre script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%USERPROFILE%\mavenrc_pre.bat" call "%USERPROFILE%\mavenrc_pre.bat" %*
|
||||||
|
if exist "%USERPROFILE%\mavenrc_pre.cmd" call "%USERPROFILE%\mavenrc_pre.cmd" %*
|
||||||
|
:skipRcPre
|
||||||
|
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
set ERROR_CODE=0
|
||||||
|
|
||||||
|
@REM To isolate internal variables from possible post scripts, we use another setlocal
|
||||||
|
@setlocal
|
||||||
|
|
||||||
|
@REM ==== START VALIDATION ====
|
||||||
|
if not "%JAVA_HOME%" == "" goto OkJHome
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME not found in your environment. >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
:OkJHome
|
||||||
|
if exist "%JAVA_HOME%\bin\java.exe" goto init
|
||||||
|
|
||||||
|
echo.
|
||||||
|
echo Error: JAVA_HOME is set to an invalid directory. >&2
|
||||||
|
echo JAVA_HOME = "%JAVA_HOME%" >&2
|
||||||
|
echo Please set the JAVA_HOME variable in your environment to match the >&2
|
||||||
|
echo location of your Java installation. >&2
|
||||||
|
echo.
|
||||||
|
goto error
|
||||||
|
|
||||||
|
@REM ==== END VALIDATION ====
|
||||||
|
|
||||||
|
:init
|
||||||
|
|
||||||
|
@REM Find the project base dir, i.e. the directory that contains the folder ".mvn".
|
||||||
|
@REM Fallback to current working directory if not found.
|
||||||
|
|
||||||
|
set MAVEN_PROJECTBASEDIR=%MAVEN_BASEDIR%
|
||||||
|
IF NOT "%MAVEN_PROJECTBASEDIR%"=="" goto endDetectBaseDir
|
||||||
|
|
||||||
|
set EXEC_DIR=%CD%
|
||||||
|
set WDIR=%EXEC_DIR%
|
||||||
|
:findBaseDir
|
||||||
|
IF EXIST "%WDIR%"\.mvn goto baseDirFound
|
||||||
|
cd ..
|
||||||
|
IF "%WDIR%"=="%CD%" goto baseDirNotFound
|
||||||
|
set WDIR=%CD%
|
||||||
|
goto findBaseDir
|
||||||
|
|
||||||
|
:baseDirFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%WDIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
goto endDetectBaseDir
|
||||||
|
|
||||||
|
:baseDirNotFound
|
||||||
|
set MAVEN_PROJECTBASEDIR=%EXEC_DIR%
|
||||||
|
cd "%EXEC_DIR%"
|
||||||
|
|
||||||
|
:endDetectBaseDir
|
||||||
|
|
||||||
|
IF NOT EXIST "%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config" goto endReadAdditionalConfig
|
||||||
|
|
||||||
|
@setlocal EnableExtensions EnableDelayedExpansion
|
||||||
|
for /F "usebackq delims=" %%a in ("%MAVEN_PROJECTBASEDIR%\.mvn\jvm.config") do set JVM_CONFIG_MAVEN_PROPS=!JVM_CONFIG_MAVEN_PROPS! %%a
|
||||||
|
@endlocal & set JVM_CONFIG_MAVEN_PROPS=%JVM_CONFIG_MAVEN_PROPS%
|
||||||
|
|
||||||
|
:endReadAdditionalConfig
|
||||||
|
|
||||||
|
SET MAVEN_JAVA_EXE="%JAVA_HOME%\bin\java.exe"
|
||||||
|
set WRAPPER_JAR="%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.jar"
|
||||||
|
set WRAPPER_LAUNCHER=org.apache.maven.wrapper.MavenWrapperMain
|
||||||
|
|
||||||
|
set DOWNLOAD_URL="https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||||
|
|
||||||
|
FOR /F "usebackq tokens=1,2 delims==" %%A IN ("%MAVEN_PROJECTBASEDIR%\.mvn\wrapper\maven-wrapper.properties") DO (
|
||||||
|
IF "%%A"=="wrapperUrl" SET DOWNLOAD_URL=%%B
|
||||||
|
)
|
||||||
|
|
||||||
|
@REM Extension to allow automatically downloading the maven-wrapper.jar from Maven-central
|
||||||
|
@REM This allows using the maven wrapper in projects that prohibit checking in binary data.
|
||||||
|
if exist %WRAPPER_JAR% (
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
|
echo Found %WRAPPER_JAR%
|
||||||
|
)
|
||||||
|
) else (
|
||||||
|
if not "%MVNW_REPOURL%" == "" (
|
||||||
|
SET DOWNLOAD_URL="%MVNW_REPOURL%/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar"
|
||||||
|
)
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
|
echo Couldn't find %WRAPPER_JAR%, downloading it ...
|
||||||
|
echo Downloading from: %DOWNLOAD_URL%
|
||||||
|
)
|
||||||
|
|
||||||
|
powershell -Command "&{"^
|
||||||
|
"$webclient = new-object System.Net.WebClient;"^
|
||||||
|
"if (-not ([string]::IsNullOrEmpty('%MVNW_USERNAME%') -and [string]::IsNullOrEmpty('%MVNW_PASSWORD%'))) {"^
|
||||||
|
"$webclient.Credentials = new-object System.Net.NetworkCredential('%MVNW_USERNAME%', '%MVNW_PASSWORD%');"^
|
||||||
|
"}"^
|
||||||
|
"[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12; $webclient.DownloadFile('%DOWNLOAD_URL%', '%WRAPPER_JAR%')"^
|
||||||
|
"}"
|
||||||
|
if "%MVNW_VERBOSE%" == "true" (
|
||||||
|
echo Finished downloading %WRAPPER_JAR%
|
||||||
|
)
|
||||||
|
)
|
||||||
|
@REM End of extension
|
||||||
|
|
||||||
|
@REM Provide a "standardized" way to retrieve the CLI args that will
|
||||||
|
@REM work with both Windows and non-Windows executions.
|
||||||
|
set MAVEN_CMD_LINE_ARGS=%*
|
||||||
|
|
||||||
|
%MAVEN_JAVA_EXE% ^
|
||||||
|
%JVM_CONFIG_MAVEN_PROPS% ^
|
||||||
|
%MAVEN_OPTS% ^
|
||||||
|
%MAVEN_DEBUG_OPTS% ^
|
||||||
|
-classpath %WRAPPER_JAR% ^
|
||||||
|
"-Dmaven.multiModuleProjectDirectory=%MAVEN_PROJECTBASEDIR%" ^
|
||||||
|
%WRAPPER_LAUNCHER% %MAVEN_CONFIG% %*
|
||||||
|
if ERRORLEVEL 1 goto error
|
||||||
|
goto end
|
||||||
|
|
||||||
|
:error
|
||||||
|
set ERROR_CODE=1
|
||||||
|
|
||||||
|
:end
|
||||||
|
@endlocal & set ERROR_CODE=%ERROR_CODE%
|
||||||
|
|
||||||
|
if not "%MAVEN_SKIP_RC%"=="" goto skipRcPost
|
||||||
|
@REM check for post script, once with legacy .bat ending and once with .cmd ending
|
||||||
|
if exist "%USERPROFILE%\mavenrc_post.bat" call "%USERPROFILE%\mavenrc_post.bat"
|
||||||
|
if exist "%USERPROFILE%\mavenrc_post.cmd" call "%USERPROFILE%\mavenrc_post.cmd"
|
||||||
|
:skipRcPost
|
||||||
|
|
||||||
|
@REM pause the script if MAVEN_BATCH_PAUSE is set to 'on'
|
||||||
|
if "%MAVEN_BATCH_PAUSE%"=="on" pause
|
||||||
|
|
||||||
|
if "%MAVEN_TERMINATE_CMD%"=="on" exit %ERROR_CODE%
|
||||||
|
|
||||||
|
cmd /C exit /B %ERROR_CODE%
|
||||||
|
|
@ -0,0 +1,187 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<parent>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-parent</artifactId>
|
||||||
|
<version>3.0.5</version>
|
||||||
|
</parent>
|
||||||
|
<!-- 项目信息 -->
|
||||||
|
<groupId>com.lckp</groupId>
|
||||||
|
<artifactId>jproxy</artifactId>
|
||||||
|
<version>3.4.5</version>
|
||||||
|
<name>JProxy</name>
|
||||||
|
<description>介于 Sonarr/Radarr 和 Jackett/Prowlarr 之间的代理,主要用于优化查询和提升识别率</description>
|
||||||
|
<!-- 依赖版本 -->
|
||||||
|
<properties>
|
||||||
|
<java.version>17</java.version>
|
||||||
|
<java-jwt.version>4.3.0</java-jwt.version>
|
||||||
|
<knife4j.version>4.0.0</knife4j.version>
|
||||||
|
<fastjson2.version>2.0.24</fastjson2.version>
|
||||||
|
<mybatis-plus.version>3.5.3</mybatis-plus.version>
|
||||||
|
<mybatis-plus-generator.version>3.5.3</mybatis-plus-generator.version>
|
||||||
|
<dom4j.version>2.1.4</dom4j.version>
|
||||||
|
</properties>
|
||||||
|
<!-- 依赖 -->
|
||||||
|
<dependencies>
|
||||||
|
<!-- spring -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-test</artifactId>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-web</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-aop</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- 参数校验 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-validation</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- 日志 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-logging</artifactId>
|
||||||
|
<exclusions>
|
||||||
|
<exclusion>
|
||||||
|
<groupId>*</groupId>
|
||||||
|
<artifactId>*</artifactId>
|
||||||
|
</exclusion>
|
||||||
|
</exclusions>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-starter-log4j2</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- token -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.auth0</groupId>
|
||||||
|
<artifactId>java-jwt</artifactId>
|
||||||
|
<version>${java-jwt.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 接口文档 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-openapi3-jakarta-spring-boot-starter</artifactId>
|
||||||
|
<version>${knife4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- fastjson2 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba.fastjson2</groupId>
|
||||||
|
<artifactId>fastjson2</artifactId>
|
||||||
|
<version>${fastjson2.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- mybatis-plus -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-boot-starter</artifactId>
|
||||||
|
<version>${mybatis-plus.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<!-- 代码生成器 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-generator</artifactId>
|
||||||
|
<version>${mybatis-plus-generator.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.freemarker</groupId>
|
||||||
|
<artifactId>freemarker</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- sqlite 数据库驱动 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.xerial</groupId>
|
||||||
|
<artifactId>sqlite-jdbc</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- 数据库版本控制 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.liquibase</groupId>
|
||||||
|
<artifactId>liquibase-core</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- 缓存 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||||
|
<artifactId>caffeine</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.springframework</groupId>
|
||||||
|
<artifactId>spring-context-support</artifactId>
|
||||||
|
</dependency>
|
||||||
|
<!-- xml 处理 -->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.dom4j</groupId>
|
||||||
|
<artifactId>dom4j</artifactId>
|
||||||
|
<version>${dom4j.version}</version>
|
||||||
|
</dependency>
|
||||||
|
</dependencies>
|
||||||
|
<build>
|
||||||
|
<!-- 打包文件名 -->
|
||||||
|
<finalName>${project.artifactId}</finalName>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.springframework.boot</groupId>
|
||||||
|
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||||
|
<configuration>
|
||||||
|
<mainClass>com.lckp.jproxy.Application</mainClass>
|
||||||
|
<layers>
|
||||||
|
<enabled>true</enabled>
|
||||||
|
</layers>
|
||||||
|
<!-- 去除生产不需要的依赖 -->
|
||||||
|
<excludeDevtools>true</excludeDevtools>
|
||||||
|
<excludes>
|
||||||
|
<exclude>
|
||||||
|
<groupId>com.github.xiaoymin</groupId>
|
||||||
|
<artifactId>knife4j-openapi3-ui</artifactId>
|
||||||
|
</exclude>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.webjars</groupId>
|
||||||
|
<artifactId>swagger-ui</artifactId>
|
||||||
|
</exclude>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.projectlombok</groupId>
|
||||||
|
<artifactId>lombok</artifactId>
|
||||||
|
</exclude>
|
||||||
|
<exclude>
|
||||||
|
<groupId>com.baomidou</groupId>
|
||||||
|
<artifactId>mybatis-plus-generator</artifactId>
|
||||||
|
</exclude>
|
||||||
|
<exclude>
|
||||||
|
<groupId>org.freemarker</groupId>
|
||||||
|
<artifactId>freemarker</artifactId>
|
||||||
|
</exclude>
|
||||||
|
</excludes>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
<!-- 配置 -->
|
||||||
|
<profiles>
|
||||||
|
<!-- 开发环境 -->
|
||||||
|
<profile>
|
||||||
|
<id>dev</id>
|
||||||
|
<properties>
|
||||||
|
<spring.profiles.active>dev</spring.profiles.active>
|
||||||
|
</properties>
|
||||||
|
<activation>
|
||||||
|
<activeByDefault>true</activeByDefault>
|
||||||
|
</activation>
|
||||||
|
</profile>
|
||||||
|
<!-- 生产环境 -->
|
||||||
|
<profile>
|
||||||
|
<id>prod</id>
|
||||||
|
<properties>
|
||||||
|
<spring.profiles.active>prod</spring.profiles.active>
|
||||||
|
</properties>
|
||||||
|
</profile>
|
||||||
|
</profiles>
|
||||||
|
</project>
|
||||||
Binary file not shown.
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.lckp.jproxy;
|
||||||
|
|
||||||
|
import org.mybatis.spring.annotation.MapperScan;
|
||||||
|
import org.springframework.boot.SpringApplication;
|
||||||
|
import org.springframework.boot.autoconfigure.SpringBootApplication;
|
||||||
|
import org.springframework.boot.web.servlet.ServletComponentScan;
|
||||||
|
import org.springframework.cache.annotation.EnableCaching;
|
||||||
|
import org.springframework.context.annotation.EnableAspectJAutoProxy;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 主类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-04
|
||||||
|
*/
|
||||||
|
@SpringBootApplication
|
||||||
|
@MapperScan("com.lckp.jproxy.mapper")
|
||||||
|
@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true)
|
||||||
|
@ServletComponentScan
|
||||||
|
@EnableCaching
|
||||||
|
public class Application {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
SpringApplication.run(Application.class, args);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,59 @@
|
||||||
|
package com.lckp.jproxy;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
|
||||||
|
import com.baomidou.mybatisplus.generator.config.OutputFile;
|
||||||
|
import com.baomidou.mybatisplus.generator.engine.FreemarkerTemplateEngine;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 代码生成器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-04
|
||||||
|
*/
|
||||||
|
public class CodeGenerator {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// 数据库
|
||||||
|
String tableName = "system_user";
|
||||||
|
String dbUsername = "";
|
||||||
|
String dbPassword = "";
|
||||||
|
String dbUrl = "jdbc:sqlite:target\\classes\\database\\jproxy.db";
|
||||||
|
|
||||||
|
// 作者
|
||||||
|
String author = "LuckyPuppy514";
|
||||||
|
// 包名
|
||||||
|
String packageName = CodeGenerator.class.getPackageName();
|
||||||
|
// 输出目录
|
||||||
|
String outputDir = System.getProperty("user.dir") + "/src/main/java/";
|
||||||
|
String xmlOutputDir = System.getProperty("user.dir") + "/src/main/resources/mapper";
|
||||||
|
|
||||||
|
FastAutoGenerator.create(dbUrl, dbUsername, dbPassword)
|
||||||
|
.globalConfig(builder -> builder.author(author)
|
||||||
|
.disableOpenDir()
|
||||||
|
.enableSpringdoc()
|
||||||
|
.outputDir(outputDir)
|
||||||
|
)
|
||||||
|
.packageConfig(builder -> builder.parent(packageName)
|
||||||
|
.pathInfo(Collections.singletonMap(OutputFile.xml, xmlOutputDir))
|
||||||
|
)
|
||||||
|
.strategyConfig(builder -> builder.addInclude(tableName)
|
||||||
|
.controllerBuilder().enableRestStyle()
|
||||||
|
.entityBuilder().enableLombok()
|
||||||
|
)
|
||||||
|
.templateEngine(new FreemarkerTemplateEngine())
|
||||||
|
.templateConfig(builder -> builder.disable()
|
||||||
|
.entity("/templates/entity.java")
|
||||||
|
.service("/templates/service.java")
|
||||||
|
.serviceImpl("/templates/serviceImpl.java")
|
||||||
|
.mapper("/templates/mapper.java")
|
||||||
|
.xml("/templates/mapper.xml")
|
||||||
|
.controller("/templates/controller.java")
|
||||||
|
)
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.lckp.jproxy.aspect;
|
||||||
|
|
||||||
|
import java.util.concurrent.locks.ReadWriteLock;
|
||||||
|
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||||
|
|
||||||
|
import org.aspectj.lang.ProceedingJoinPoint;
|
||||||
|
import org.aspectj.lang.annotation.Around;
|
||||||
|
import org.aspectj.lang.annotation.Aspect;
|
||||||
|
import org.aspectj.lang.annotation.Pointcut;
|
||||||
|
import org.springframework.stereotype.Component;
|
||||||
|
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* sqlite 读写锁
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-04-02
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Aspect
|
||||||
|
@Component
|
||||||
|
public class SqliteAspect {
|
||||||
|
|
||||||
|
private final ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
|
||||||
|
|
||||||
|
@Pointcut("execution(* com.baomidou.mybatisplus.extension.service..*.*(..))"
|
||||||
|
+ " || execution(* com.lckp.jproxy.mapper..*.*(..))")
|
||||||
|
public void pointCut() {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Around("pointCut()")
|
||||||
|
public Object around(ProceedingJoinPoint pjp) throws Throwable {
|
||||||
|
String name = pjp.getSignature().getName();
|
||||||
|
log.trace("切入点:{}", pjp.getTarget().getClass().getName());
|
||||||
|
if (name.contains("save") || name.contains("update") || name.contains("remove")) {
|
||||||
|
log.trace("{} 开始获取写锁", name);
|
||||||
|
readWriteLock.writeLock().lock();
|
||||||
|
try {
|
||||||
|
log.trace("{} 获得了写锁", name);
|
||||||
|
return pjp.proceed();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("{} 写保护出错:{}", name, e.getMessage());
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
readWriteLock.writeLock().unlock();
|
||||||
|
log.trace("{} 释放了写锁", name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
log.trace("{} 开始获取读锁", name);
|
||||||
|
readWriteLock.readLock().lock();
|
||||||
|
try {
|
||||||
|
log.trace("{} 获得了读锁", name);
|
||||||
|
return pjp.proceed();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("{} 读保护出错:{}", name, e.getMessage());
|
||||||
|
throw e;
|
||||||
|
} finally {
|
||||||
|
readWriteLock.readLock().unlock();
|
||||||
|
log.trace("{} 释放了读锁", name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,76 @@
|
||||||
|
package com.lckp.jproxy.config;
|
||||||
|
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.cache.CacheManager;
|
||||||
|
import org.springframework.cache.caffeine.CaffeineCacheManager;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.github.benmanes.caffeine.cache.Caffeine;
|
||||||
|
import com.github.benmanes.caffeine.cache.Expiry;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 缓存配置
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-04-10
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class CacheConfig {
|
||||||
|
|
||||||
|
@Value("${time.cache-expires}")
|
||||||
|
private long cacheExpires;
|
||||||
|
|
||||||
|
@Value("${time.sync-interval}")
|
||||||
|
private long syncInterval;
|
||||||
|
|
||||||
|
@Value("${time.indexer-result-cache-expires}")
|
||||||
|
private long indexerResultCacheExpires;
|
||||||
|
|
||||||
|
@Bean(name = "syncIntervalCache")
|
||||||
|
Cache<String, Integer> syncIntervalCache() {
|
||||||
|
return Caffeine.newBuilder().expireAfter(new Expiry<String, Object>() {
|
||||||
|
public long expireAfterCreate(String key, Object graph, long currentTime) {
|
||||||
|
return TimeUnit.MINUTES.toNanos(syncInterval);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long expireAfterUpdate(String key, Object graph, long currentTime, long currentDuration) {
|
||||||
|
return currentDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long expireAfterRead(String key, Object graph, long currentTime, long currentDuration) {
|
||||||
|
return currentDuration;
|
||||||
|
}
|
||||||
|
}).initialCapacity(3).maximumSize(10).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean(name = "indexerResultCache")
|
||||||
|
Cache<String, String> indexerResultCache() {
|
||||||
|
return Caffeine.newBuilder().expireAfter(new Expiry<String, Object>() {
|
||||||
|
public long expireAfterCreate(String key, Object graph, long currentTime) {
|
||||||
|
return TimeUnit.MINUTES.toNanos(indexerResultCacheExpires);
|
||||||
|
}
|
||||||
|
|
||||||
|
public long expireAfterUpdate(String key, Object graph, long currentTime, long currentDuration) {
|
||||||
|
return currentDuration;
|
||||||
|
}
|
||||||
|
|
||||||
|
public long expireAfterRead(String key, Object graph, long currentTime, long currentDuration) {
|
||||||
|
return currentDuration;
|
||||||
|
}
|
||||||
|
}).initialCapacity(100).maximumSize(1000).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
CacheManager cacheManager() {
|
||||||
|
CaffeineCacheManager cacheManager = new CaffeineCacheManager();
|
||||||
|
cacheManager.setCaffeine(Caffeine.newBuilder().expireAfterAccess(cacheExpires, TimeUnit.MINUTES)
|
||||||
|
.initialCapacity(100).maximumSize(1000));
|
||||||
|
return cacheManager;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.lckp.jproxy.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.server.ErrorPage;
|
||||||
|
import org.springframework.boot.web.server.ErrorPageRegistrar;
|
||||||
|
import org.springframework.boot.web.server.ErrorPageRegistry;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 错误页面配置
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-30
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class ErrorPageConfig implements ErrorPageRegistrar {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param registry
|
||||||
|
* @see org.springframework.boot.web.server.ErrorPageRegistrar#registerErrorPages(org.springframework.boot.web.server.ErrorPageRegistry)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void registerErrorPages(ErrorPageRegistry registry) {
|
||||||
|
registry.addErrorPages(new ErrorPage(HttpStatus.NOT_FOUND, "/index.html"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,74 @@
|
||||||
|
package com.lckp.jproxy.config;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.servlet.FilterRegistrationBean;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.constant.Common;
|
||||||
|
import com.lckp.jproxy.filter.RadarrJackettFilter;
|
||||||
|
import com.lckp.jproxy.filter.RadarrProwlarrFilter;
|
||||||
|
import com.lckp.jproxy.filter.SonarrJackettFilter;
|
||||||
|
import com.lckp.jproxy.filter.SonarrProwlarrFilter;
|
||||||
|
import com.lckp.jproxy.service.IRadarrJackettService;
|
||||||
|
import com.lckp.jproxy.service.IRadarrProwlarrService;
|
||||||
|
import com.lckp.jproxy.service.ISonarrJackettService;
|
||||||
|
import com.lckp.jproxy.service.ISonarrProwlarrService;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 过滤器配置
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-07
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class FilterConfig {
|
||||||
|
|
||||||
|
private final ISonarrJackettService sonarrJackettService;
|
||||||
|
|
||||||
|
private final ISonarrProwlarrService sonarrProwlarrService;
|
||||||
|
|
||||||
|
private final IRadarrJackettService radarrJackettService;
|
||||||
|
|
||||||
|
private final IRadarrProwlarrService radarrProwlarrService;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
FilterRegistrationBean<SonarrJackettFilter> sonarrJackettFilter() {
|
||||||
|
FilterRegistrationBean<SonarrJackettFilter> bean = new FilterRegistrationBean<>();
|
||||||
|
bean.setFilter(new SonarrJackettFilter(sonarrJackettService));
|
||||||
|
bean.setOrder(Integer.MIN_VALUE);
|
||||||
|
bean.addUrlPatterns(Common.FILTER_SONARR_JACKETT_PATH);
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
FilterRegistrationBean<SonarrProwlarrFilter> sonarrProwlarrFilter() {
|
||||||
|
FilterRegistrationBean<SonarrProwlarrFilter> bean = new FilterRegistrationBean<>();
|
||||||
|
bean.setFilter(new SonarrProwlarrFilter(sonarrProwlarrService));
|
||||||
|
bean.setOrder(Integer.MIN_VALUE);
|
||||||
|
bean.addUrlPatterns(Common.FILTER_SONARR_PROWLARR_PATH);
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
FilterRegistrationBean<RadarrJackettFilter> radarrJackettFilter() {
|
||||||
|
FilterRegistrationBean<RadarrJackettFilter> bean = new FilterRegistrationBean<>();
|
||||||
|
bean.setFilter(new RadarrJackettFilter(radarrJackettService));
|
||||||
|
bean.setOrder(Integer.MIN_VALUE);
|
||||||
|
bean.addUrlPatterns(Common.FILTER_RADARR_JACKETT_PATH);
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
FilterRegistrationBean<RadarrProwlarrFilter> radarrProwlarrFilter() {
|
||||||
|
FilterRegistrationBean<RadarrProwlarrFilter> bean = new FilterRegistrationBean<>();
|
||||||
|
bean.setFilter(new RadarrProwlarrFilter(radarrProwlarrService));
|
||||||
|
bean.setOrder(Integer.MIN_VALUE);
|
||||||
|
bean.addUrlPatterns(Common.FILTER_RADARR_PROWLARR_PATH);
|
||||||
|
return bean;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.lckp.jproxy.config;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
|
||||||
|
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.constant.Common;
|
||||||
|
import com.lckp.jproxy.interceptor.LoginInterceptor;
|
||||||
|
import com.lckp.jproxy.service.ISystemUserService;
|
||||||
|
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 拦截器配置
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-23
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class InterceptorConfig implements WebMvcConfigurer {
|
||||||
|
|
||||||
|
private final ISystemUserService systemUserService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addInterceptors(InterceptorRegistry registry) {
|
||||||
|
registry.addInterceptor(new LoginInterceptor(systemUserService))
|
||||||
|
.addPathPatterns(Common.INTERCEPTOR_ALL_PATH)
|
||||||
|
.excludePathPatterns(Common.INTERCEPTOR_SONARR_API_PATH)
|
||||||
|
.excludePathPatterns(Common.INTERCEPTOR_RADARR_API_PATH)
|
||||||
|
.excludePathPatterns(Common.INTERCEPTOR_LOGIN_API_PATH)
|
||||||
|
.excludePathPatterns(Common.INTERCEPTOR_LOGIN_PAGE_PATH)
|
||||||
|
.excludePathPatterns(Common.INTERCEPTOR_INDEX_PAGE_PATH)
|
||||||
|
.excludePathPatterns(Common.INTERCEPTOR_STATIC_PATH)
|
||||||
|
.excludePathPatterns(Common.INTERCEPTOR_KNFIE4J_PATHS)
|
||||||
|
.excludePathPatterns(Common.INTERCEPTOR_OTHER_PATHS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.lckp.jproxy.config;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.web.servlet.LocaleResolver;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 本地化配置
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-25
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class LocaleResolverConfig implements LocaleResolver {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Locale resolveLocale(HttpServletRequest httpServletRequest) {
|
||||||
|
Locale locale = httpServletRequest.getLocale();
|
||||||
|
locale = locale == null ? Locale.getDefault() : locale;
|
||||||
|
return locale;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setLocale(HttpServletRequest request, HttpServletResponse response, Locale locale) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
LocaleResolver localeResolver() {
|
||||||
|
return new LocaleResolverConfig();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.lckp.jproxy.config;
|
||||||
|
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import org.apache.ibatis.reflection.MetaObject;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.transaction.annotation.EnableTransactionManagement;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.DbType;
|
||||||
|
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
|
||||||
|
import com.lckp.jproxy.constant.TableField;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Mybatis-Plus 配置类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-04
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
@EnableTransactionManagement
|
||||||
|
public class MybatisPlusConfig implements MetaObjectHandler {
|
||||||
|
|
||||||
|
private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
MybatisPlusInterceptor mybatisPlusInterceptor() {
|
||||||
|
PaginationInnerInterceptor pagination = new PaginationInnerInterceptor(DbType.SQLITE);
|
||||||
|
pagination.setOverflow(true);
|
||||||
|
pagination.setMaxLimit(1000L);
|
||||||
|
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
|
||||||
|
interceptor.addInnerInterceptor(pagination);
|
||||||
|
return interceptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param metaObject
|
||||||
|
* @see com.baomidou.mybatisplus.core.handlers.MetaObjectHandler#insertFill(org.apache.ibatis.reflection.MetaObject)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void insertFill(MetaObject metaObject) {
|
||||||
|
this.setFieldValByName(TableField.CREATE_TIME_CAMEL, dateFormat.format(new Date()), metaObject);
|
||||||
|
this.setFieldValByName(TableField.UPDATE_TIME_CAMEL, dateFormat.format(new Date()), metaObject);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param metaObject
|
||||||
|
* @see com.baomidou.mybatisplus.core.handlers.MetaObjectHandler#updateFill(org.apache.ibatis.reflection.MetaObject)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void updateFill(MetaObject metaObject) {
|
||||||
|
this.setFieldValByName(TableField.UPDATE_TIME_CAMEL, dateFormat.format(new Date()), metaObject);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,48 @@
|
||||||
|
package com.lckp.jproxy.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.time.Duration;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.boot.web.client.RestTemplateBuilder;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
import org.springframework.http.HttpStatusCode;
|
||||||
|
import org.springframework.http.MediaType;
|
||||||
|
import org.springframework.http.client.ClientHttpResponse;
|
||||||
|
import org.springframework.http.converter.HttpMessageConverter;
|
||||||
|
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
|
||||||
|
import org.springframework.web.client.ExtractingResponseErrorHandler;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* RestTemplate 配置
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-25
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class RestTemplateConfig {
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
RestTemplate restTemplate(RestTemplateBuilder restTemplateBuilder) {
|
||||||
|
List<HttpMessageConverter<?>> messageConverters = new ArrayList<>();
|
||||||
|
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
|
||||||
|
converter.setSupportedMediaTypes(Collections.singletonList(MediaType.ALL));
|
||||||
|
messageConverters.add(converter);
|
||||||
|
return restTemplateBuilder.setReadTimeout(Duration.ofMinutes(15))
|
||||||
|
.setConnectTimeout(Duration.ofMinutes(15))
|
||||||
|
.additionalMessageConverters(messageConverters)
|
||||||
|
.errorHandler(new ExtractingResponseErrorHandler() {
|
||||||
|
@Override
|
||||||
|
public boolean hasError(ClientHttpResponse response) throws IOException {
|
||||||
|
return !response.getStatusCode().is2xxSuccessful()
|
||||||
|
&& !HttpStatusCode.valueOf(409).equals(response.getStatusCode());
|
||||||
|
}
|
||||||
|
}).build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
package com.lckp.jproxy.config;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.context.annotation.Bean;
|
||||||
|
import org.springframework.context.annotation.Configuration;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.models.OpenAPI;
|
||||||
|
import io.swagger.v3.oas.models.info.Info;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Swagger 配置类
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-04
|
||||||
|
*/
|
||||||
|
@Configuration
|
||||||
|
public class SwaggerConfig {
|
||||||
|
|
||||||
|
@Value("${project.name}")
|
||||||
|
private String projectName;
|
||||||
|
|
||||||
|
@Value("${project.version}")
|
||||||
|
private String projectVersion;
|
||||||
|
|
||||||
|
@Value("${project.description}")
|
||||||
|
private String projectDescription;
|
||||||
|
|
||||||
|
@Bean
|
||||||
|
OpenAPI customOpenAPI() {
|
||||||
|
return new OpenAPI()
|
||||||
|
.info(new Info().title(projectName).version(projectVersion).description(projectDescription));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,168 @@
|
||||||
|
package com.lckp.jproxy.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 接口字段
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-18
|
||||||
|
*/
|
||||||
|
public class ApiField {
|
||||||
|
ApiField() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String INDEXER_SEARCH_KEY = "q";
|
||||||
|
|
||||||
|
public static final String INDEXER_SEARCH_TYPE = "t";
|
||||||
|
|
||||||
|
public static final String INDEXER_SEASON_NUMBER = "season";
|
||||||
|
|
||||||
|
public static final String INDEXER_EPISODE_NUMBER = "ep";
|
||||||
|
|
||||||
|
public static final String INDEXER_LIMIT = "limit";
|
||||||
|
|
||||||
|
public static final String INDEXER_OFFSET = "offset";
|
||||||
|
|
||||||
|
public static final String INDEXER_CHANNEL = "channel";
|
||||||
|
|
||||||
|
public static final String INDEXER_ITEM = "item";
|
||||||
|
|
||||||
|
public static final String INDEXER_TITLE = "title";
|
||||||
|
|
||||||
|
public static final String INDEXER_DESCRIPTION = "description";
|
||||||
|
|
||||||
|
public static final String INDEXER_LINK = "link";
|
||||||
|
|
||||||
|
public static final String SONARR_APIKEY = "apikey";
|
||||||
|
|
||||||
|
public static final String SONARR_ID = "id";
|
||||||
|
|
||||||
|
public static final String SONARR_SERIES_ID = "seriesId";
|
||||||
|
|
||||||
|
public static final String SONARR_TVDB_ID = "tvdbId";
|
||||||
|
|
||||||
|
public static final String SONARR_TITLE = "title";
|
||||||
|
|
||||||
|
public static final String SONARR_TITLE_SLUG = "titleSlug";
|
||||||
|
|
||||||
|
public static final String SONARR_SERIES_TYPE = "seriesType";
|
||||||
|
|
||||||
|
public static final String SONARR_STATUS = "status";
|
||||||
|
|
||||||
|
public static final String SONARR_MONITORED = "monitored";
|
||||||
|
|
||||||
|
public static final String SONARR_ALTERNATE_TITLES = "alternateTitles";
|
||||||
|
|
||||||
|
public static final String SONARR_SCENE_SEASON_NUMBER = "sceneSeasonNumber";
|
||||||
|
|
||||||
|
public static final String SONARR_DOWNLOAD_ID = "downloadId";
|
||||||
|
|
||||||
|
public static final String SONARR_EPISODE = "episode";
|
||||||
|
|
||||||
|
public static final String SONARR_SEASON_NUMBER = "seasonNumber";
|
||||||
|
|
||||||
|
public static final String SONARR_EPISODE_NUMBER = "episodeNumber";
|
||||||
|
|
||||||
|
public static final String SONARR_LANGUAGE = "language";
|
||||||
|
|
||||||
|
public static final String SONARR_QUALITY = "quality";
|
||||||
|
|
||||||
|
public static final String SONARR_NAME = "name";
|
||||||
|
|
||||||
|
public static final String SONARR_RECORDS = "records";
|
||||||
|
|
||||||
|
public static final String SONARR_SOURCES_TITLE = "sourceTitle";
|
||||||
|
|
||||||
|
public static final String SONARR_DATA = "data";
|
||||||
|
|
||||||
|
public static final String SONARR_DATE = "date";
|
||||||
|
|
||||||
|
public static final String SONARR_TZ = "UTC";
|
||||||
|
|
||||||
|
public static final String SONARR_TORRENT_INFO_HASH = "torrentInfoHash";
|
||||||
|
|
||||||
|
public static final String SONARR_DOWNLOAD_CLIENT = "downloadClient";
|
||||||
|
|
||||||
|
public static final String RADARR_APIKEY = "apikey";
|
||||||
|
|
||||||
|
public static final String RADARR_TMDB_ID = "tmdbId";
|
||||||
|
|
||||||
|
public static final String RADARR_ID = "id";
|
||||||
|
|
||||||
|
public static final String RADARR_MOVIE_ID = "movieId";
|
||||||
|
|
||||||
|
public static final String RADARR_DOWNLOAD_ID = "downloadId";
|
||||||
|
|
||||||
|
public static final String RADARR_LANGUAGES = "languages";
|
||||||
|
|
||||||
|
public static final String RADARR_QUALITY = "quality";
|
||||||
|
|
||||||
|
public static final String RADARR_NAME = "name";
|
||||||
|
|
||||||
|
public static final String RADARR_RECORDS = "records";
|
||||||
|
|
||||||
|
public static final String RADARR_SOURCES_TITLE = "sourceTitle";
|
||||||
|
|
||||||
|
public static final String RADARR_DATA = "data";
|
||||||
|
|
||||||
|
public static final String RADARR_DATE = "date";
|
||||||
|
|
||||||
|
public static final String RADARR_TZ = "UTC";
|
||||||
|
|
||||||
|
public static final String RADARR_TORRENT_INFO_HASH = "torrentInfoHash";
|
||||||
|
|
||||||
|
public static final String RADARR_TITLE = "title";
|
||||||
|
|
||||||
|
public static final String RADARR_CLEAN_TITLE = "cleanTitle";
|
||||||
|
|
||||||
|
public static final String RADARR_PATH = "path";
|
||||||
|
|
||||||
|
public static final String RADARR_ORIGINAL_TITLE = "originalTitle";
|
||||||
|
|
||||||
|
public static final String RADARR_ALTERNATE_TITLES = "alternateTitles";
|
||||||
|
|
||||||
|
public static final String RADARR_MONITORED = "monitored";
|
||||||
|
|
||||||
|
public static final String RADARR_YEAR = "year";
|
||||||
|
|
||||||
|
public static final String RADARR_DOWNLOAD_CLIENT = "downloadClient";
|
||||||
|
|
||||||
|
public static final String TMDB_API_KEY = "api_key";
|
||||||
|
|
||||||
|
public static final String TMDB_TVDB_ID = "tvdb_id";
|
||||||
|
|
||||||
|
public static final String TMDB_ID = "id";
|
||||||
|
|
||||||
|
public static final String TMDB_LANGUAGE = "language";
|
||||||
|
|
||||||
|
public static final String TMDB_TV_RESULTS = "tv_results";
|
||||||
|
|
||||||
|
public static final String TMDB_EXTERNAL_SOURCE = "external_source";
|
||||||
|
|
||||||
|
public static final String TMDB_NAME = "name";
|
||||||
|
|
||||||
|
public static final String QBITTORRENT_HASH = "hash";
|
||||||
|
|
||||||
|
public static final String QBITTORRENT_NAME = "name";
|
||||||
|
|
||||||
|
public static final String QBITTORRENT_USERNAME = "username";
|
||||||
|
|
||||||
|
public static final String QBITTORRENT_PASSWORD = "password";
|
||||||
|
|
||||||
|
public static final String QBITTORRENT_OLD_PATH = "oldPath";
|
||||||
|
|
||||||
|
public static final String QBITTORRENT_NEW_PATH = "newPath";
|
||||||
|
|
||||||
|
public static final String TRANSMISSION_METHOD = "method";
|
||||||
|
|
||||||
|
public static final String TRANSMISSION_ARGUMENTS = "arguments";
|
||||||
|
|
||||||
|
public static final String TRANSMISSION_SESSION_ID = "X-Transmission-Session-Id";
|
||||||
|
|
||||||
|
public static final String TRANSMISSION_TORRENTS = "torrents";
|
||||||
|
|
||||||
|
public static final String TRANSMISSION_NAME = "name";
|
||||||
|
|
||||||
|
public static final String GITHUB_TAG_NAME = "tag_name";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.lckp.jproxy.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 缓存名称
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-16
|
||||||
|
*/
|
||||||
|
public class CacheName {
|
||||||
|
CacheName() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 注解
|
||||||
|
public static final String SYSTEM_CONFIG = "system_config";
|
||||||
|
public static final String SONARR_SEARCH_TITLE = "sonarr_search_title";
|
||||||
|
public static final String INDEXER_SEARCH_OFFSET = "indexer_search_offset";
|
||||||
|
public static final String SONARR_RULE = "sonarr_rule";
|
||||||
|
public static final String SONARR_RESULT_TITLE = "sonarr_result_title";
|
||||||
|
public static final String RADARR_SEARCH_TITLE = "radarr_search_title";
|
||||||
|
public static final String RADARR_RULE = "radarr_rule";
|
||||||
|
public static final String RADARR_RESULT_TITLE = "radarr_result_title";
|
||||||
|
|
||||||
|
// Bean
|
||||||
|
public static final String SONARR_TITLE_SYNC_INTERVAL = "sonarr_title_sync_interval";
|
||||||
|
public static final String TMDB_TITLE_SYNC_INTERVAL = "tmdb_title_sync_interval";
|
||||||
|
public static final String RADARR_TITLE_SYNC_INTERVAL = "radarr_title_sync_interval";
|
||||||
|
public static final String TOKEN_SECRET = "token_secret";
|
||||||
|
public static final String TOKEN_BLACK_LIST = "token_black_list";
|
||||||
|
public static final String INDEXER_RESULT = "indexer_result";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,55 @@
|
||||||
|
package com.lckp.jproxy.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 通用常量
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-19
|
||||||
|
*/
|
||||||
|
public class Common {
|
||||||
|
Common() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// 登陆拦截器路径
|
||||||
|
public static final String INTERCEPTOR_ALL_PATH = "/**";
|
||||||
|
public static final String INTERCEPTOR_SONARR_API_PATH = "/sonarr/**";
|
||||||
|
public static final String INTERCEPTOR_RADARR_API_PATH = "/radarr/**";
|
||||||
|
public static final String INTERCEPTOR_LOGIN_API_PATH = "/api/system/user/login";
|
||||||
|
public static final String INTERCEPTOR_LOGIN_PAGE_PATH = "/login";
|
||||||
|
public static final String INTERCEPTOR_INDEX_PAGE_PATH = "/index.html";
|
||||||
|
public static final String INTERCEPTOR_STATIC_PATH = "/assets/**";
|
||||||
|
public static final String[] INTERCEPTOR_KNFIE4J_PATHS = { "/doc.html", "/webjars/**",
|
||||||
|
"/v3/api-docs/**" };
|
||||||
|
public static final String[] INTERCEPTOR_OTHER_PATHS = { "/error", "/*.json", "/", "/favicon.ico",
|
||||||
|
"/system/**" };
|
||||||
|
|
||||||
|
// Charon
|
||||||
|
public static final String CHARON_ALL_PATH = "/.*";
|
||||||
|
public static final String CHARON_IN_PATH = "/(?<path>.*)";
|
||||||
|
public static final String CHARON_OUT_PATH = "/<path>";
|
||||||
|
public static final String CHARON_JACKETT_PATH = "/(sonarr|radarr)/jackett";
|
||||||
|
public static final String CHARON_PROWLARR_PATH = "/(sonarr|radarr)/prowlarr";
|
||||||
|
public static final String CHARON_QBITTORRENT_PATH = "/(sonarr|radarr)/qbittorrent";
|
||||||
|
public static final String CHARON_TRANSMISSION_PATH = "/(sonarr|radarr)/transmission";
|
||||||
|
// Filter
|
||||||
|
public static final String FILTER_SONARR_JACKETT_PATH = "/sonarr/jackett/*";
|
||||||
|
public static final String FILTER_SONARR_PROWLARR_PATH = "/sonarr/prowlarr/*";
|
||||||
|
public static final String FILTER_RADARR_JACKETT_PATH = "/radarr/jackett/*";
|
||||||
|
public static final String FILTER_RADARR_PROWLARR_PATH = "/radarr/prowlarr/*";
|
||||||
|
public static final String FILTER_SONARR_QBITTORRENT_PATH = "/sonarr/qbittorrent/api/v2/torrents/info";
|
||||||
|
public static final String FILTER_SONARR_TRANSMISSION_PATH = "/sonarr/transmission/*";
|
||||||
|
// 批量保存大小
|
||||||
|
public static final int BATCH_SIZE = 200;
|
||||||
|
// 规则同步作者
|
||||||
|
public static final String RULE_SYNC_AUTHORS_ALL = "ALL";
|
||||||
|
// 标题主规则 ID
|
||||||
|
public static final String MOST_IMPORTANT_TITLE_RULE_ID = "00000000000000000000000000000000";
|
||||||
|
// 视频文件扩展名正则表达式
|
||||||
|
public static final String VIDEO_AND_SUBTITLE_EXTENSION_REGEX = "(\\.(mp4|avi|wmv|flv|mov|mkv|webm|mpg|mpeg|3gp|iso|ts|ass|srt|ssa|idx|sub))$";
|
||||||
|
// 字幕文件扩展名正则表达式
|
||||||
|
public static final String SUBTITLE_EXTENSION_REGEX = "(\\.(ass|srt|ssa|idx|sub))$";
|
||||||
|
// 时间格式
|
||||||
|
public static final String DATE_TIME_FORMAT = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,23 @@
|
||||||
|
package com.lckp.jproxy.constant;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 下载器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-04-13
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum Downloader {
|
||||||
|
|
||||||
|
QBITTORRENT("qBittorrent"),
|
||||||
|
|
||||||
|
TRANSMISSION("Transmission");
|
||||||
|
|
||||||
|
private final String name;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.lckp.jproxy.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 信息
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-25
|
||||||
|
*/
|
||||||
|
public class Messages {
|
||||||
|
Messages() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String LOGIN_WRONG_TOO_MANY_TIMES = "login.wrong.too.many.times";
|
||||||
|
|
||||||
|
public static final String LOGIN_WRONG_USER = "login.wrong.user";
|
||||||
|
|
||||||
|
public static final String TITLE_SYNC_TOO_OFTEN = "title.sync.too.often";
|
||||||
|
|
||||||
|
public static final String RULE_MODIFY_PRIMARY_FORBIDDEN = "rule.modify.primary.forbidden";
|
||||||
|
|
||||||
|
public static final String EXAMPLE_MATCH_TITLE_FAIL = "example.match.title.fail";
|
||||||
|
|
||||||
|
public static final String SYSTEM_CONFIG_INVALID_PREFIX = "system.config.invalid.";
|
||||||
|
|
||||||
|
public static final String DATABASE_BUSY = "database.busy";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.lckp.jproxy.constant;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 监控状态
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-06
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum Monitored {
|
||||||
|
|
||||||
|
CONTINUING(0, false, "未监控"),
|
||||||
|
|
||||||
|
ENDED(1, true, "监控中");
|
||||||
|
|
||||||
|
private final Integer code;
|
||||||
|
|
||||||
|
private final boolean flag;
|
||||||
|
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 根据 flag 获取对应的 Monitored
|
||||||
|
*
|
||||||
|
* @param flag
|
||||||
|
* @return Monitored
|
||||||
|
*/
|
||||||
|
public static Monitored getByFlag(boolean flag) {
|
||||||
|
if (flag) {
|
||||||
|
return ENDED;
|
||||||
|
}
|
||||||
|
return CONTINUING;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.lckp.jproxy.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 系统配置 Key
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-19
|
||||||
|
*/
|
||||||
|
public class SystemConfigKey {
|
||||||
|
SystemConfigKey() {
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sonarr
|
||||||
|
public static final String SONARR_URL = "sonarrUrl";
|
||||||
|
public static final String SONARR_APIKEY = "sonarrApikey";
|
||||||
|
public static final String SONARR_INDEXER_FORMAT = "sonarrIndexerFormat";
|
||||||
|
public static final String SONARR_LANGUAGE_1 = "sonarrLanguage1";
|
||||||
|
public static final String SONARR_LANGUAGE_2 = "sonarrLanguage2";
|
||||||
|
// Radarr
|
||||||
|
public static final String RADARR_URL = "radarrUrl";
|
||||||
|
public static final String RADARR_APIKEY = "radarrApikey";
|
||||||
|
public static final String RADARR_INDEXER_FORMAT = "radarrIndexerFormat";
|
||||||
|
// 索引器
|
||||||
|
public static final String JACKETT_URL = "jackettUrl";
|
||||||
|
public static final String PROWLARR_URL = "prowlarrUrl";
|
||||||
|
// 下载器
|
||||||
|
public static final String QBITTORRENT_URL = "qbittorrentUrl";
|
||||||
|
public static final String QBITTORRENT_USERNAME = "qbittorrentUsername";
|
||||||
|
public static final String QBITTORRENT_PASSWORD = "qbittorrentPassword";
|
||||||
|
public static final String TRANSMISSION_URL = "transmissionUrl";
|
||||||
|
public static final String TRANSMISSION_USERNAME = "transmissionUsername";
|
||||||
|
public static final String TRANSMISSION_PASSWORD = "transmissionPassword";
|
||||||
|
// TMDB
|
||||||
|
public static final String TMDB_URL = "tmdbUrl";
|
||||||
|
public static final String TMDB_APIKEY = "tmdbApikey";
|
||||||
|
// 净标题排除字符正则
|
||||||
|
public static final String CLEAN_TITLE_REGEX = "cleanTitleRegex";
|
||||||
|
// 规则同步作者
|
||||||
|
public static final String RULE_SYNC_AUTHORS = "ruleSyncAuthors";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.lckp.jproxy.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 表字段名
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-16
|
||||||
|
*/
|
||||||
|
public class TableField {
|
||||||
|
TableField() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String VALID_STATUS = "valid_status";
|
||||||
|
|
||||||
|
public static final String TMDB_ID = "tmdb_id";
|
||||||
|
|
||||||
|
public static final String TITLE = "title";
|
||||||
|
|
||||||
|
public static final String CLEAN_TITLE = "clean_title";
|
||||||
|
|
||||||
|
public static final String TVDB_ID = "tvdb_id";
|
||||||
|
|
||||||
|
public static final String SERIES_ID = "series_id";
|
||||||
|
|
||||||
|
public static final String MOVIE_ID = "movie_id";
|
||||||
|
|
||||||
|
public static final String PRIORITY = "priority";
|
||||||
|
|
||||||
|
public static final String KEY = "key";
|
||||||
|
|
||||||
|
public static final String TOKEN = "token";
|
||||||
|
|
||||||
|
public static final String OFFSET = "offset";
|
||||||
|
|
||||||
|
public static final String EXAMPLE = "example";
|
||||||
|
|
||||||
|
public static final String AUTHOR = "author";
|
||||||
|
|
||||||
|
public static final String REMARK = "remark";
|
||||||
|
|
||||||
|
public static final String MONITORED = "monitored";
|
||||||
|
|
||||||
|
public static final String SNO = "sno";
|
||||||
|
|
||||||
|
public static final String USERNAME = "username";
|
||||||
|
|
||||||
|
public static final String PASSWORD = "password";
|
||||||
|
|
||||||
|
public static final String ID = "id";
|
||||||
|
|
||||||
|
public static final String ROLE = "role";
|
||||||
|
|
||||||
|
public static final String YEAR = "year";
|
||||||
|
|
||||||
|
public static final String ORIGINAL_TEXT = "original_text";
|
||||||
|
|
||||||
|
public static final String FORMAT_TEXT = "format_text";
|
||||||
|
|
||||||
|
public static final String REGEX = "regex";
|
||||||
|
|
||||||
|
public static final String REPLACEMENT = "replacement";
|
||||||
|
|
||||||
|
public static final String CREATE_TIME = "create_time";
|
||||||
|
|
||||||
|
public static final String UPDATE_TIME = "update_time";
|
||||||
|
|
||||||
|
public static final String CREATE_TIME_CAMEL = "createTime";
|
||||||
|
|
||||||
|
public static final String UPDATE_TIME_CAMEL = "updateTime";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,34 @@
|
||||||
|
package com.lckp.jproxy.constant;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 规则标记
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-16
|
||||||
|
*/
|
||||||
|
public class Token {
|
||||||
|
Token() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public static final String REGEX = "\\{([^}]+)\\}";
|
||||||
|
|
||||||
|
public static final String TITLE = "title";
|
||||||
|
|
||||||
|
public static final String SEASON = "season";
|
||||||
|
|
||||||
|
public static final String EPISODE = "episode";
|
||||||
|
|
||||||
|
public static final String LANGUAGE = "language";
|
||||||
|
|
||||||
|
public static final String RESOLUTION = "resolution";
|
||||||
|
|
||||||
|
public static final String QUALITY = "quality";
|
||||||
|
|
||||||
|
public static final String GROUP = "group";
|
||||||
|
|
||||||
|
public static final String CLEAN_TITLE = "cleanTitle";
|
||||||
|
|
||||||
|
public static final String YEAR = "year";
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.lckp.jproxy.constant;
|
||||||
|
|
||||||
|
import lombok.AllArgsConstructor;
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 有效状态
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-06
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@AllArgsConstructor
|
||||||
|
public enum ValidStatus {
|
||||||
|
VALID(1, "有效"),
|
||||||
|
|
||||||
|
INVALID(0, "无效");
|
||||||
|
|
||||||
|
private final Integer code;
|
||||||
|
|
||||||
|
private final String description;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 根据 code 获取对应的 ValidStatus
|
||||||
|
*
|
||||||
|
* @param code
|
||||||
|
* @return ValidStatus
|
||||||
|
*/
|
||||||
|
public static ValidStatus getByCode(Integer code) {
|
||||||
|
for (ValidStatus validStatus : ValidStatus.values()) {
|
||||||
|
if (validStatus.code.equals(code)) {
|
||||||
|
return validStatus;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return INVALID;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 根据 boolean 值获取 code
|
||||||
|
*
|
||||||
|
* @param flag
|
||||||
|
* @return Integer
|
||||||
|
*/
|
||||||
|
public static Integer getCode(boolean flag) {
|
||||||
|
if (flag) {
|
||||||
|
return VALID.getCode();
|
||||||
|
}
|
||||||
|
return INVALID.getCode();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.springdoc.core.annotations.ParameterObject;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.entity.RadarrExample;
|
||||||
|
import com.lckp.jproxy.model.request.RadarrExampleQueryRequest;
|
||||||
|
import com.lckp.jproxy.model.request.RadarrExampleSaveRequest;
|
||||||
|
import com.lckp.jproxy.model.response.PageResponse;
|
||||||
|
import com.lckp.jproxy.service.IRadarrExampleService;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import liquibase.util.MD5Util;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 电影范例
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-30
|
||||||
|
*/
|
||||||
|
@Tag(name = "电影范例")
|
||||||
|
@RequestMapping("/api/radarr/example")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RadarrExampleController {
|
||||||
|
|
||||||
|
private final IRadarrExampleService radarrExampleService;
|
||||||
|
|
||||||
|
@Operation(summary = "保存")
|
||||||
|
@PostMapping("/save")
|
||||||
|
public ResponseEntity<Void> save(@Validated @RequestBody RadarrExampleSaveRequest request) {
|
||||||
|
String[] originalTexts = request.getOriginalText().split("\\n");
|
||||||
|
List<RadarrExample> radarrExampleList = new ArrayList<>(originalTexts.length);
|
||||||
|
for (String originalText : originalTexts) {
|
||||||
|
RadarrExample example = new RadarrExample();
|
||||||
|
example.setOriginalText(originalText);
|
||||||
|
example.setHash(MD5Util.computeMD5(originalText).toUpperCase());
|
||||||
|
radarrExampleList.add(example);
|
||||||
|
}
|
||||||
|
radarrExampleService.saveOrUpdateBatch(radarrExampleList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询")
|
||||||
|
@GetMapping("/query")
|
||||||
|
public ResponseEntity<PageResponse<RadarrExample>> query(
|
||||||
|
@ParameterObject RadarrExampleQueryRequest request, Locale locale) {
|
||||||
|
return ResponseEntity.ok(new PageResponse<>(radarrExampleService.query(request, locale)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "删除")
|
||||||
|
@PostMapping("/remove")
|
||||||
|
public ResponseEntity<Void> remove(@RequestBody List<String> idList) {
|
||||||
|
radarrExampleService.removeBatchByIds(idList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springdoc.core.annotations.ParameterObject;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.TypeReference;
|
||||||
|
import com.lckp.jproxy.constant.CacheName;
|
||||||
|
import com.lckp.jproxy.constant.Common;
|
||||||
|
import com.lckp.jproxy.constant.Messages;
|
||||||
|
import com.lckp.jproxy.constant.TableField;
|
||||||
|
import com.lckp.jproxy.constant.ValidStatus;
|
||||||
|
import com.lckp.jproxy.entity.RadarrRule;
|
||||||
|
import com.lckp.jproxy.model.request.RadarrRuleQueryRequest;
|
||||||
|
import com.lckp.jproxy.model.response.PageResponse;
|
||||||
|
import com.lckp.jproxy.service.IRadarrRuleService;
|
||||||
|
import com.lckp.jproxy.util.FileUtil;
|
||||||
|
import com.lckp.jproxy.util.Generator;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 电影规则
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-26
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Tag(name = "电影规则")
|
||||||
|
@RequestMapping("/api/radarr/rule")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RadarrRuleController {
|
||||||
|
|
||||||
|
private final IRadarrRuleService radarrRuleService;
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
@Operation(summary = "同步")
|
||||||
|
@PostMapping("/sync")
|
||||||
|
public ResponseEntity<String> sync(Locale locale) {
|
||||||
|
if (radarrRuleService.sync()) {
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
} else {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.TITLE_SYNC_TOO_OFTEN, null, locale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询")
|
||||||
|
@GetMapping("/query")
|
||||||
|
public ResponseEntity<PageResponse<RadarrRule>> query(@ParameterObject RadarrRuleQueryRequest request) {
|
||||||
|
return ResponseEntity.ok(new PageResponse<>(radarrRuleService.query(request)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "保存")
|
||||||
|
@PostMapping("/save")
|
||||||
|
@CacheEvict(cacheNames = CacheName.RADARR_RULE, allEntries = true)
|
||||||
|
public ResponseEntity<String> save(@Validated @RequestBody RadarrRule request, Locale locale) {
|
||||||
|
try {
|
||||||
|
Pattern.compile(request.getRegex()).matcher(request.getRegex())
|
||||||
|
.replaceAll(request.getReplacement());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ResponseEntity.internalServerError().body(e.getMessage());
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(request.getId())) {
|
||||||
|
request.setId(Generator.generateUUID());
|
||||||
|
} else if (Common.MOST_IMPORTANT_TITLE_RULE_ID.equals(request.getId())) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.RULE_MODIFY_PRIMARY_FORBIDDEN, null, locale));
|
||||||
|
}
|
||||||
|
radarrRuleService.saveOrUpdate(request);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "删除")
|
||||||
|
@PostMapping("/remove")
|
||||||
|
@CacheEvict(cacheNames = CacheName.RADARR_RULE, allEntries = true)
|
||||||
|
public ResponseEntity<String> remove(@RequestBody List<String> idList, Locale locale) {
|
||||||
|
for (String id : idList) {
|
||||||
|
if (Common.MOST_IMPORTANT_TITLE_RULE_ID.equals(id)) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.RULE_MODIFY_PRIMARY_FORBIDDEN, null, locale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
radarrRuleService.removeBatchByIds(idList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "启用")
|
||||||
|
@PostMapping("/enable")
|
||||||
|
public ResponseEntity<Void> enable(@RequestBody List<String> idList) {
|
||||||
|
radarrRuleService.switchValidStatus(idList, ValidStatus.VALID);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "禁用")
|
||||||
|
@PostMapping("/disable")
|
||||||
|
public ResponseEntity<String> disable(@RequestBody List<String> idList, Locale locale) {
|
||||||
|
for (String id : idList) {
|
||||||
|
if (Common.MOST_IMPORTANT_TITLE_RULE_ID.equals(id)) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.RULE_MODIFY_PRIMARY_FORBIDDEN, null, locale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
radarrRuleService.switchValidStatus(idList, ValidStatus.INVALID);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "导出")
|
||||||
|
@PostMapping("/export")
|
||||||
|
public ResponseEntity<List<RadarrRule>> export(@RequestBody List<String> idList) {
|
||||||
|
if (idList == null || idList.isEmpty()) {
|
||||||
|
return ResponseEntity.ok(radarrRuleService.query()
|
||||||
|
.select(TableField.ID, TableField.TOKEN, TableField.PRIORITY, TableField.REGEX,
|
||||||
|
TableField.REPLACEMENT, TableField.OFFSET, TableField.EXAMPLE, TableField.REMARK,
|
||||||
|
TableField.AUTHOR)
|
||||||
|
.list());
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(radarrRuleService.listByIds(idList));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "导入")
|
||||||
|
@PostMapping("/import")
|
||||||
|
@CacheEvict(cacheNames = CacheName.RADARR_RULE, allEntries = true)
|
||||||
|
public ResponseEntity<String> importRadarrRule(MultipartFile file) {
|
||||||
|
try {
|
||||||
|
String content = FileUtil.read(file);
|
||||||
|
if (content == null) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
List<RadarrRule> radarrRuleList = JSON.parseObject(content,
|
||||||
|
new TypeReference<List<RadarrRule>>() {
|
||||||
|
});
|
||||||
|
radarrRuleList.forEach(radarrRule -> {
|
||||||
|
if (ValidStatus.VALID.getCode().equals(radarrRule.getValidStatus())) {
|
||||||
|
radarrRule.setValidStatus(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
radarrRuleService.saveOrUpdateBatch(radarrRuleList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("导入出错:", e);
|
||||||
|
return ResponseEntity.internalServerError().body(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询 token 列表")
|
||||||
|
@GetMapping("/token/list")
|
||||||
|
public ResponseEntity<List<String>> listToken() {
|
||||||
|
List<RadarrRule> radarrRuleList = radarrRuleService.query().select(TableField.TOKEN)
|
||||||
|
.groupBy(TableField.TOKEN).list();
|
||||||
|
List<String> tokenList = new ArrayList<>(radarrRuleList.size());
|
||||||
|
for (RadarrRule radarrRule : radarrRuleList) {
|
||||||
|
tokenList.add(radarrRule.getToken());
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(tokenList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.springdoc.core.annotations.ParameterObject;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.constant.CacheName;
|
||||||
|
import com.lckp.jproxy.constant.Messages;
|
||||||
|
import com.lckp.jproxy.entity.RadarrTitle;
|
||||||
|
import com.lckp.jproxy.model.request.RadarrTitleQueryRequest;
|
||||||
|
import com.lckp.jproxy.model.response.PageResponse;
|
||||||
|
import com.lckp.jproxy.service.IRadarrTitleService;
|
||||||
|
import com.lckp.jproxy.service.ISystemCacheService;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 电影标题
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-26
|
||||||
|
*/
|
||||||
|
@Tag(name = "电影标题")
|
||||||
|
@RequestMapping("/api/radarr/title")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class RadarrTitleController {
|
||||||
|
|
||||||
|
private final IRadarrTitleService radarrTitleService;
|
||||||
|
|
||||||
|
private final ISystemCacheService systemCacheService;
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
@Operation(summary = "同步")
|
||||||
|
@PostMapping("/sync")
|
||||||
|
public ResponseEntity<String> sync(Locale locale) {
|
||||||
|
try {
|
||||||
|
if (radarrTitleService.sync()) {
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
} else {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.TITLE_SYNC_TOO_OFTEN, null, locale));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
systemCacheService.clear(CacheName.RADARR_TITLE_SYNC_INTERVAL);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询")
|
||||||
|
@GetMapping("/query")
|
||||||
|
public ResponseEntity<PageResponse<RadarrTitle>> query(@ParameterObject RadarrTitleQueryRequest request) {
|
||||||
|
return ResponseEntity.ok(new PageResponse<>(radarrTitleService.query(request)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "删除")
|
||||||
|
@PostMapping("/remove")
|
||||||
|
public ResponseEntity<Void> remove(@RequestBody List<Integer> idList) {
|
||||||
|
radarrTitleService.removeBatchByIds(idList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import org.springdoc.core.annotations.ParameterObject;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.model.request.RuleTestRequest;
|
||||||
|
import com.lckp.jproxy.util.FormatUtil;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 规则
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-29
|
||||||
|
*/
|
||||||
|
@Tag(name = "规则")
|
||||||
|
@RequestMapping("/api/rule")
|
||||||
|
@RestController
|
||||||
|
public class RuleController {
|
||||||
|
|
||||||
|
@Operation(summary = "测试")
|
||||||
|
@GetMapping("/test")
|
||||||
|
public ResponseEntity<String> test(@Validated @ParameterObject RuleTestRequest request) {
|
||||||
|
String[] examples = request.getExample().split("\\n");
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (String example : examples) {
|
||||||
|
String value = example.replaceAll(request.getRegex(), request.getReplacement());
|
||||||
|
value = FormatUtil.executeOffset(value, request.getOffset());
|
||||||
|
builder.append(value + "\n");
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(builder.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,71 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.springdoc.core.annotations.ParameterObject;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.entity.SonarrExample;
|
||||||
|
import com.lckp.jproxy.model.request.SonarrExampleQueryRequest;
|
||||||
|
import com.lckp.jproxy.model.request.SonarrExampleSaveRequest;
|
||||||
|
import com.lckp.jproxy.model.response.PageResponse;
|
||||||
|
import com.lckp.jproxy.service.ISonarrExampleService;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import liquibase.util.MD5Util;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 剧集范例
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-30
|
||||||
|
*/
|
||||||
|
@Tag(name = "剧集范例")
|
||||||
|
@RequestMapping("/api/sonarr/example")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SonarrExampleController {
|
||||||
|
|
||||||
|
private final ISonarrExampleService sonarrExampleService;
|
||||||
|
|
||||||
|
@Operation(summary = "保存")
|
||||||
|
@PostMapping("/save")
|
||||||
|
public ResponseEntity<Void> save(@Validated @RequestBody SonarrExampleSaveRequest request) {
|
||||||
|
String[] originalTexts = request.getOriginalText().split("\\n");
|
||||||
|
List<SonarrExample> sonarrExampleList = new ArrayList<>(originalTexts.length);
|
||||||
|
for (String originalText : originalTexts) {
|
||||||
|
SonarrExample example = new SonarrExample();
|
||||||
|
example.setOriginalText(originalText);
|
||||||
|
example.setHash(MD5Util.computeMD5(originalText).toUpperCase());
|
||||||
|
sonarrExampleList.add(example);
|
||||||
|
}
|
||||||
|
sonarrExampleService.saveOrUpdateBatch(sonarrExampleList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询")
|
||||||
|
@GetMapping("/query")
|
||||||
|
public ResponseEntity<PageResponse<SonarrExample>> query(
|
||||||
|
@ParameterObject SonarrExampleQueryRequest request, Locale locale) {
|
||||||
|
return ResponseEntity.ok(new PageResponse<>(sonarrExampleService.query(request, locale)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "删除")
|
||||||
|
@PostMapping("/remove")
|
||||||
|
public ResponseEntity<Void> remove(@RequestBody List<String> idList) {
|
||||||
|
sonarrExampleService.removeBatchByIds(idList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,179 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springdoc.core.annotations.ParameterObject;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.multipart.MultipartFile;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.alibaba.fastjson2.TypeReference;
|
||||||
|
import com.lckp.jproxy.constant.CacheName;
|
||||||
|
import com.lckp.jproxy.constant.Common;
|
||||||
|
import com.lckp.jproxy.constant.Messages;
|
||||||
|
import com.lckp.jproxy.constant.TableField;
|
||||||
|
import com.lckp.jproxy.constant.ValidStatus;
|
||||||
|
import com.lckp.jproxy.entity.SonarrRule;
|
||||||
|
import com.lckp.jproxy.model.request.SonarrRuleQueryRequest;
|
||||||
|
import com.lckp.jproxy.model.response.PageResponse;
|
||||||
|
import com.lckp.jproxy.service.ISonarrRuleService;
|
||||||
|
import com.lckp.jproxy.util.FileUtil;
|
||||||
|
import com.lckp.jproxy.util.Generator;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 剧集规则
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-26
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Tag(name = "剧集规则")
|
||||||
|
@RequestMapping("/api/sonarr/rule")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SonarrRuleController {
|
||||||
|
|
||||||
|
private final ISonarrRuleService sonarrRuleService;
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
@Operation(summary = "同步")
|
||||||
|
@PostMapping("/sync")
|
||||||
|
public ResponseEntity<String> sync(Locale locale) {
|
||||||
|
if (sonarrRuleService.sync()) {
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
} else {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.TITLE_SYNC_TOO_OFTEN, null, locale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询")
|
||||||
|
@GetMapping("/query")
|
||||||
|
public ResponseEntity<PageResponse<SonarrRule>> query(@ParameterObject SonarrRuleQueryRequest request) {
|
||||||
|
return ResponseEntity.ok(new PageResponse<>(sonarrRuleService.query(request)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "保存")
|
||||||
|
@PostMapping("/save")
|
||||||
|
@CacheEvict(cacheNames = CacheName.SONARR_RULE, allEntries = true)
|
||||||
|
public ResponseEntity<String> save(@Validated @RequestBody SonarrRule request, Locale locale) {
|
||||||
|
try {
|
||||||
|
Pattern.compile(request.getRegex()).matcher(request.getRegex())
|
||||||
|
.replaceAll(request.getReplacement());
|
||||||
|
} catch (Exception e) {
|
||||||
|
return ResponseEntity.internalServerError().body(e.getMessage());
|
||||||
|
}
|
||||||
|
if (StringUtils.isBlank(request.getId())) {
|
||||||
|
request.setId(Generator.generateUUID());
|
||||||
|
} else if (Common.MOST_IMPORTANT_TITLE_RULE_ID.equals(request.getId())) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.RULE_MODIFY_PRIMARY_FORBIDDEN, null, locale));
|
||||||
|
}
|
||||||
|
sonarrRuleService.saveOrUpdate(request);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "删除")
|
||||||
|
@PostMapping("/remove")
|
||||||
|
@CacheEvict(cacheNames = CacheName.SONARR_RULE, allEntries = true)
|
||||||
|
public ResponseEntity<String> remove(@RequestBody List<String> idList, Locale locale) {
|
||||||
|
for (String id : idList) {
|
||||||
|
if (Common.MOST_IMPORTANT_TITLE_RULE_ID.equals(id)) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.RULE_MODIFY_PRIMARY_FORBIDDEN, null, locale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sonarrRuleService.removeBatchByIds(idList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "启用")
|
||||||
|
@PostMapping("/enable")
|
||||||
|
public ResponseEntity<Void> enable(@RequestBody List<String> idList) {
|
||||||
|
sonarrRuleService.switchValidStatus(idList, ValidStatus.VALID);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "禁用")
|
||||||
|
@PostMapping("/disable")
|
||||||
|
public ResponseEntity<String> disable(@RequestBody List<String> idList, Locale locale) {
|
||||||
|
for (String id : idList) {
|
||||||
|
if (Common.MOST_IMPORTANT_TITLE_RULE_ID.equals(id)) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.RULE_MODIFY_PRIMARY_FORBIDDEN, null, locale));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sonarrRuleService.switchValidStatus(idList, ValidStatus.INVALID);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "导出")
|
||||||
|
@PostMapping("/export")
|
||||||
|
public ResponseEntity<List<SonarrRule>> export(@RequestBody List<String> idList) {
|
||||||
|
if (idList == null || idList.isEmpty()) {
|
||||||
|
return ResponseEntity.ok(sonarrRuleService.query()
|
||||||
|
.select(TableField.ID, TableField.TOKEN, TableField.PRIORITY, TableField.REGEX,
|
||||||
|
TableField.REPLACEMENT, TableField.OFFSET, TableField.EXAMPLE, TableField.REMARK,
|
||||||
|
TableField.AUTHOR)
|
||||||
|
.list());
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(sonarrRuleService.listByIds(idList));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "导入")
|
||||||
|
@PostMapping("/import")
|
||||||
|
@CacheEvict(cacheNames = CacheName.SONARR_RULE, allEntries = true)
|
||||||
|
public ResponseEntity<String> importSonarrRule(MultipartFile file) {
|
||||||
|
try {
|
||||||
|
String content = FileUtil.read(file);
|
||||||
|
if (content == null) {
|
||||||
|
return ResponseEntity.badRequest().build();
|
||||||
|
}
|
||||||
|
List<SonarrRule> sonarrRuleList = JSON.parseObject(content,
|
||||||
|
new TypeReference<List<SonarrRule>>() {
|
||||||
|
});
|
||||||
|
sonarrRuleList.forEach(sonarrRule -> {
|
||||||
|
if (ValidStatus.VALID.getCode().equals(sonarrRule.getValidStatus())) {
|
||||||
|
sonarrRule.setValidStatus(null);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
sonarrRuleService.saveOrUpdateBatch(sonarrRuleList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("导入出错:", e);
|
||||||
|
return ResponseEntity.internalServerError().body(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询 token 列表")
|
||||||
|
@GetMapping("/token/list")
|
||||||
|
public ResponseEntity<List<String>> listToken() {
|
||||||
|
List<SonarrRule> sonarrRuleList = sonarrRuleService.query().select(TableField.TOKEN)
|
||||||
|
.groupBy(TableField.TOKEN).list();
|
||||||
|
List<String> tokenList = new ArrayList<>(sonarrRuleList.size());
|
||||||
|
for (SonarrRule sonarrRule : sonarrRuleList) {
|
||||||
|
tokenList.add(sonarrRule.getToken());
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(tokenList);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.springdoc.core.annotations.ParameterObject;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.constant.CacheName;
|
||||||
|
import com.lckp.jproxy.constant.Messages;
|
||||||
|
import com.lckp.jproxy.entity.SonarrTitle;
|
||||||
|
import com.lckp.jproxy.model.request.SonarrTitleQueryRequest;
|
||||||
|
import com.lckp.jproxy.model.response.PageResponse;
|
||||||
|
import com.lckp.jproxy.service.ISonarrTitleService;
|
||||||
|
import com.lckp.jproxy.service.ISystemCacheService;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 剧集标题
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-26
|
||||||
|
*/
|
||||||
|
@Tag(name = "剧集标题")
|
||||||
|
@RequestMapping("/api/sonarr/title")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SonarrTitleController {
|
||||||
|
|
||||||
|
private final ISonarrTitleService sonarrTitleService;
|
||||||
|
|
||||||
|
private final ISystemCacheService systemCacheService;
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
@Operation(summary = "同步")
|
||||||
|
@PostMapping("/sync")
|
||||||
|
public ResponseEntity<String> sync(Locale locale) {
|
||||||
|
try {
|
||||||
|
if (sonarrTitleService.sync()) {
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
} else {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.TITLE_SYNC_TOO_OFTEN, null, locale));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
systemCacheService.clear(CacheName.SONARR_TITLE_SYNC_INTERVAL);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询")
|
||||||
|
@GetMapping("/query")
|
||||||
|
public ResponseEntity<PageResponse<SonarrTitle>> query(@ParameterObject SonarrTitleQueryRequest request) {
|
||||||
|
return ResponseEntity.ok(new PageResponse<>(sonarrTitleService.query(request)));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "删除")
|
||||||
|
@PostMapping("/remove")
|
||||||
|
public ResponseEntity<Void> remove(@RequestBody List<Integer> idList) {
|
||||||
|
sonarrTitleService.removeBatchByIds(idList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.model.request.SystemCacheClearRequest;
|
||||||
|
import com.lckp.jproxy.service.ISystemCacheService;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 系统缓存
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-26
|
||||||
|
*/
|
||||||
|
@Tag(name = "系统缓存")
|
||||||
|
@RequestMapping("/api/system/cache")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SystemCacheController {
|
||||||
|
|
||||||
|
private final ISystemCacheService systemCacheService;
|
||||||
|
|
||||||
|
@Operation(summary = "清除所有")
|
||||||
|
@PostMapping("/clearAll")
|
||||||
|
public ResponseEntity<Void> clearAll() {
|
||||||
|
systemCacheService.clearAll();
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "清除")
|
||||||
|
@PostMapping("/clear")
|
||||||
|
public ResponseEntity<Void> clear(@Validated @RequestBody SystemCacheClearRequest request) {
|
||||||
|
systemCacheService.clear(request.getCacheName());
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.boot.CommandLineRunner;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
|
import com.alibaba.fastjson2.JSON;
|
||||||
|
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
|
||||||
|
import com.lckp.jproxy.constant.ApiField;
|
||||||
|
import com.lckp.jproxy.constant.CacheName;
|
||||||
|
import com.lckp.jproxy.entity.SystemConfig;
|
||||||
|
import com.lckp.jproxy.service.ISystemCacheService;
|
||||||
|
import com.lckp.jproxy.service.ISystemConfigService;
|
||||||
|
import com.lckp.jproxy.task.SonarrRenameTask;
|
||||||
|
import com.lckp.jproxy.util.Generator;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 系统配置
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-12
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@Tag(name = "系统配置")
|
||||||
|
@RequestMapping("/api/system/config")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SystemConfigController implements CommandLineRunner {
|
||||||
|
|
||||||
|
private final ISystemConfigService systemConfigService;
|
||||||
|
|
||||||
|
private final ISystemCacheService systemCacheService;
|
||||||
|
|
||||||
|
private final SonarrRenameTask sonarrRenameTask;
|
||||||
|
|
||||||
|
private final RestTemplate restTemplate;
|
||||||
|
|
||||||
|
@Value("${project.version}")
|
||||||
|
private String projectVersion;
|
||||||
|
|
||||||
|
@Value("${rule.location}")
|
||||||
|
private String ruleLocation;
|
||||||
|
|
||||||
|
@Value("${rule.location-backup}")
|
||||||
|
private String ruleLocationBackup;
|
||||||
|
|
||||||
|
@Operation(summary = "版本号")
|
||||||
|
@GetMapping("/version")
|
||||||
|
public ResponseEntity<String> version() {
|
||||||
|
String latestVersion = null;
|
||||||
|
try {
|
||||||
|
latestVersion = JSON.parseObject(restTemplate.getForObject(
|
||||||
|
"https://api.github.com/repos/LuckyPuppy514/jproxy/releases/latest", String.class))
|
||||||
|
.getString(ApiField.GITHUB_TAG_NAME);
|
||||||
|
if (StringUtils.isNotBlank(latestVersion)) {
|
||||||
|
latestVersion = latestVersion.replace("v", "");
|
||||||
|
if (!projectVersion.equals(latestVersion)) {
|
||||||
|
return ResponseEntity.ok(projectVersion + " 🚨");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.debug("获取最新版本号出错:{}", e.getMessage());
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(projectVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询")
|
||||||
|
@GetMapping("/query")
|
||||||
|
public ResponseEntity<List<SystemConfig>> query() {
|
||||||
|
sonarrRenameTask.run();
|
||||||
|
return ResponseEntity.ok(systemConfigService.query().list());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "更新")
|
||||||
|
@PostMapping("/update")
|
||||||
|
public ResponseEntity<Void> update(@RequestBody List<SystemConfig> systemConfigList) {
|
||||||
|
systemConfigService.updateSystemConfig(systemConfigList);
|
||||||
|
systemCacheService.clear(CacheName.SONARR_TITLE_SYNC_INTERVAL);
|
||||||
|
systemCacheService.clear(CacheName.TMDB_TITLE_SYNC_INTERVAL);
|
||||||
|
systemCacheService.clear(CacheName.RADARR_TITLE_SYNC_INTERVAL);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询作者列表")
|
||||||
|
@GetMapping("/author/list")
|
||||||
|
public ResponseEntity<String[]> listAuthor() {
|
||||||
|
String authorUrl = Generator.generateAuthorUrl();
|
||||||
|
String[] authorList = { "LuckyPuppy514" };
|
||||||
|
try {
|
||||||
|
authorList = restTemplate.getForEntity(authorUrl, String[].class).getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error("获取作者列表出错:{}", e.getMessage());
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(authorList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param args
|
||||||
|
* @throws Exception
|
||||||
|
* @see org.springframework.boot.CommandLineRunner#run(java.lang.String[])
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void run(String... args) throws Exception {
|
||||||
|
try {
|
||||||
|
Generator.setRuleLocation(ruleLocation);
|
||||||
|
restTemplate.getForEntity(Generator.generateAuthorUrl(), String[].class).getBody();
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.info("无法访问规则地址:{} - {}", ruleLocation, e.getMessage());
|
||||||
|
Generator.setRuleLocation(ruleLocationBackup);
|
||||||
|
log.info("已切换到备用地址:{}", ruleLocationBackup);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,96 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.validation.annotation.Validated;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.constant.Messages;
|
||||||
|
import com.lckp.jproxy.entity.SystemUser;
|
||||||
|
import com.lckp.jproxy.model.request.SystemUserLoginRequest;
|
||||||
|
import com.lckp.jproxy.service.ISystemUserService;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 系统用户
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-12
|
||||||
|
*/
|
||||||
|
@Tag(name = "系统用户")
|
||||||
|
@RequestMapping("/api/system/user")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class SystemUserController {
|
||||||
|
|
||||||
|
private final ISystemUserService systemUserService;
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
private int loginWrongCount = 0;
|
||||||
|
|
||||||
|
@Operation(summary = "登陆")
|
||||||
|
@PostMapping("/login")
|
||||||
|
public ResponseEntity<String> login(@RequestBody @Validated SystemUserLoginRequest request,
|
||||||
|
Locale locale) {
|
||||||
|
if (loginWrongCount > 10) {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.LOGIN_WRONG_TOO_MANY_TIMES, null, locale));
|
||||||
|
}
|
||||||
|
SystemUser systemUser = new SystemUser();
|
||||||
|
systemUser.setUsername(request.getUsername());
|
||||||
|
systemUser.setPassword(request.getPassword());
|
||||||
|
if (systemUserService.check(systemUser)) {
|
||||||
|
return ResponseEntity.ok(systemUserService.sign(systemUser));
|
||||||
|
}
|
||||||
|
loginWrongCount++;
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.LOGIN_WRONG_USER, null, locale));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "信息")
|
||||||
|
@GetMapping("/info")
|
||||||
|
public ResponseEntity<SystemUser> info(HttpServletRequest servletRequest) {
|
||||||
|
String token = servletRequest.getHeader(HttpHeaders.AUTHORIZATION);
|
||||||
|
SystemUser systemUser = systemUserService.getSystemUser(token);
|
||||||
|
systemUser.setPassword("******");
|
||||||
|
return ResponseEntity.ok(systemUser);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "更新")
|
||||||
|
@PostMapping("/update")
|
||||||
|
public ResponseEntity<Void> update(@RequestBody SystemUser systemUser,
|
||||||
|
HttpServletRequest servletRequest) {
|
||||||
|
String token = servletRequest.getHeader(HttpHeaders.AUTHORIZATION);
|
||||||
|
SystemUser currentSystemUser = systemUserService.getSystemUser(token);
|
||||||
|
if (StringUtils.isNotBlank(systemUser.getUsername())) {
|
||||||
|
currentSystemUser.setUsername(systemUser.getUsername());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(systemUser.getPassword())) {
|
||||||
|
currentSystemUser.setPassword(systemUser.getPassword());
|
||||||
|
}
|
||||||
|
systemUserService.update(currentSystemUser);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "注销")
|
||||||
|
@PostMapping("/logout")
|
||||||
|
public ResponseEntity<Void> logout(HttpServletRequest servletRequest) {
|
||||||
|
systemUserService.logout(servletRequest.getHeader(HttpHeaders.AUTHORIZATION));
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
package com.lckp.jproxy.controller;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
|
import org.springdoc.core.annotations.ParameterObject;
|
||||||
|
import org.springframework.cache.annotation.CacheEvict;
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.web.bind.annotation.GetMapping;
|
||||||
|
import org.springframework.web.bind.annotation.PostMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RequestBody;
|
||||||
|
import org.springframework.web.bind.annotation.RequestMapping;
|
||||||
|
import org.springframework.web.bind.annotation.RestController;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.constant.CacheName;
|
||||||
|
import com.lckp.jproxy.constant.Messages;
|
||||||
|
import com.lckp.jproxy.constant.SystemConfigKey;
|
||||||
|
import com.lckp.jproxy.constant.TableField;
|
||||||
|
import com.lckp.jproxy.entity.TmdbTitle;
|
||||||
|
import com.lckp.jproxy.model.request.TmdbTitleQueryRequest;
|
||||||
|
import com.lckp.jproxy.model.response.PageResponse;
|
||||||
|
import com.lckp.jproxy.service.ISonarrTitleService;
|
||||||
|
import com.lckp.jproxy.service.ISystemCacheService;
|
||||||
|
import com.lckp.jproxy.service.ISystemConfigService;
|
||||||
|
import com.lckp.jproxy.service.ITmdbTitleService;
|
||||||
|
import com.lckp.jproxy.util.FormatUtil;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.Operation;
|
||||||
|
import io.swagger.v3.oas.annotations.tags.Tag;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* TMDB 标题
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-26
|
||||||
|
*/
|
||||||
|
@Tag(name = "TMDB 标题")
|
||||||
|
@RequestMapping("/api/tmdb/title")
|
||||||
|
@RestController
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class TmdbTitleController {
|
||||||
|
|
||||||
|
private final ITmdbTitleService tmdbTitleService;
|
||||||
|
|
||||||
|
private final ISonarrTitleService sonarrTitleService;
|
||||||
|
|
||||||
|
private final ISystemConfigService systemConfigService;
|
||||||
|
|
||||||
|
private final ISystemCacheService systemCacheService;
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
@Operation(summary = "同步")
|
||||||
|
@PostMapping("/sync")
|
||||||
|
public ResponseEntity<String> sync(Locale locale) {
|
||||||
|
try {
|
||||||
|
if (tmdbTitleService.sync(sonarrTitleService.queryNeedSyncTmdbTitle())) {
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
} else {
|
||||||
|
return ResponseEntity.badRequest()
|
||||||
|
.body(messageSource.getMessage(Messages.TITLE_SYNC_TOO_OFTEN, null, locale));
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
systemCacheService.clear(CacheName.TMDB_TITLE_SYNC_INTERVAL);
|
||||||
|
throw e;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "查询")
|
||||||
|
@GetMapping("/query")
|
||||||
|
public ResponseEntity<PageResponse<TmdbTitle>> query(@ParameterObject TmdbTitleQueryRequest request) {
|
||||||
|
PageResponse<TmdbTitle> response = new PageResponse<>(tmdbTitleService.query(request));
|
||||||
|
String cleanTitleRegex = systemConfigService.queryValueByKey(SystemConfigKey.CLEAN_TITLE_REGEX);
|
||||||
|
List<TmdbTitle> tmdbTitleList = response.getList();
|
||||||
|
for (TmdbTitle tmdbTitle : tmdbTitleList) {
|
||||||
|
tmdbTitle.setCleanTitle(FormatUtil.cleanTitle(tmdbTitle.getTitle(), cleanTitleRegex));
|
||||||
|
}
|
||||||
|
return ResponseEntity.ok(response);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "删除")
|
||||||
|
@PostMapping("/remove")
|
||||||
|
public ResponseEntity<Void> remove(@RequestBody List<Integer> idList) {
|
||||||
|
tmdbTitleService.removeBatchByIds(idList);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Operation(summary = "保存")
|
||||||
|
@PostMapping("/save")
|
||||||
|
@CacheEvict(cacheNames = { CacheName.SONARR_SEARCH_TITLE, CacheName.INDEXER_SEARCH_OFFSET,
|
||||||
|
CacheName.SONARR_RESULT_TITLE }, allEntries = true)
|
||||||
|
public ResponseEntity<Void> save(@RequestBody TmdbTitle tmdbTitle) {
|
||||||
|
if (tmdbTitle.getTmdbId() == null) {
|
||||||
|
List<TmdbTitle> tmdbTitleList = tmdbTitleService.query()
|
||||||
|
.eq(TableField.TVDB_ID, tmdbTitle.getTvdbId()).list();
|
||||||
|
if (!tmdbTitleList.isEmpty()) {
|
||||||
|
tmdbTitle.setTmdbId(tmdbTitleList.get(0).getTmdbId());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
tmdbTitleService.saveOrUpdate(tmdbTitle);
|
||||||
|
return ResponseEntity.ok().build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.lckp.jproxy.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* RadarrExample
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-30
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("radarr_example")
|
||||||
|
@Schema(name = "RadarrExample", description = "RadarrExample")
|
||||||
|
public class RadarrExample implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId
|
||||||
|
private String hash;
|
||||||
|
|
||||||
|
private String originalText;
|
||||||
|
|
||||||
|
private String formatText;
|
||||||
|
|
||||||
|
private Integer validStatus;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateTime;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.lckp.jproxy.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* RadarrRule
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-20
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("radarr_rule")
|
||||||
|
@Schema(name = "RadarrRule", description = "RadarrRule")
|
||||||
|
public class RadarrRule implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Integer priority;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String regex;
|
||||||
|
|
||||||
|
private String replacement;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Integer offset;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String example;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
private Integer validStatus;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateTime;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.lckp.jproxy.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* RadarrTitle
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-20
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("radarr_title")
|
||||||
|
@Schema(name = "RadarrTitle", description = "RadarrTitle")
|
||||||
|
public class RadarrTitle implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private Integer movieId;
|
||||||
|
|
||||||
|
private Integer tmdbId;
|
||||||
|
|
||||||
|
private Integer sno;
|
||||||
|
|
||||||
|
private String mainTitle;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String cleanTitle;
|
||||||
|
|
||||||
|
private Integer year;
|
||||||
|
|
||||||
|
private Integer monitored;
|
||||||
|
|
||||||
|
private Integer validStatus;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateTime;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.lckp.jproxy.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SonarrExample
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-30
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("sonarr_example")
|
||||||
|
@Schema(name = "SonarrExample", description = "SonarrExample")
|
||||||
|
public class SonarrExample implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId
|
||||||
|
private String hash;
|
||||||
|
|
||||||
|
private String originalText;
|
||||||
|
|
||||||
|
private String formatText;
|
||||||
|
|
||||||
|
private Integer validStatus;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateTime;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.lckp.jproxy.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import jakarta.validation.constraints.NotNull;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SonarrRule
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-20
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("sonarr_rule")
|
||||||
|
@Schema(name = "SonarrRule", description = "SonarrRule")
|
||||||
|
public class SonarrRule implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId
|
||||||
|
private String id;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Integer priority;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String regex;
|
||||||
|
|
||||||
|
private String replacement;
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
private Integer offset;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String example;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String remark;
|
||||||
|
|
||||||
|
@NotBlank
|
||||||
|
private String author;
|
||||||
|
|
||||||
|
private Integer validStatus;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateTime;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,56 @@
|
||||||
|
package com.lckp.jproxy.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SonarrTitle
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-19
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("sonarr_title")
|
||||||
|
@Schema(name = "SonarrTitle", description = "SonarrTitle")
|
||||||
|
public class SonarrTitle implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private Integer seriesId;
|
||||||
|
|
||||||
|
private Integer tvdbId;
|
||||||
|
|
||||||
|
private Integer sno;
|
||||||
|
|
||||||
|
private String mainTitle;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
private String cleanTitle;
|
||||||
|
|
||||||
|
private Integer seasonNumber;
|
||||||
|
|
||||||
|
private Integer monitored;
|
||||||
|
|
||||||
|
private Integer validStatus;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateTime;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,44 @@
|
||||||
|
package com.lckp.jproxy.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SystemConfig
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-19
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("system_config")
|
||||||
|
@Schema(name = "SystemConfig", description = "SystemConfig")
|
||||||
|
public class SystemConfig implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private String key;
|
||||||
|
|
||||||
|
private String value;
|
||||||
|
|
||||||
|
private Integer validStatus;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateTime;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,46 @@
|
||||||
|
package com.lckp.jproxy.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SystemUser
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-30
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("system_user")
|
||||||
|
@Schema(name = "SystemUser", description = "SystemUser")
|
||||||
|
public class SystemUser implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private String username;
|
||||||
|
|
||||||
|
private String password;
|
||||||
|
|
||||||
|
private String role;
|
||||||
|
|
||||||
|
private Integer validStatus;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateTime;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,52 @@
|
||||||
|
package com.lckp.jproxy.entity;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.annotation.FieldFill;
|
||||||
|
import com.baomidou.mybatisplus.annotation.IdType;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableField;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableId;
|
||||||
|
import com.baomidou.mybatisplus.annotation.TableName;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* TmdbTitle
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-19
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@TableName("tmdb_title")
|
||||||
|
@Schema(name = "TmdbTitle", description = "TmdbTitle")
|
||||||
|
public class TmdbTitle implements Serializable {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@TableId(value = "id", type = IdType.AUTO)
|
||||||
|
private Integer id;
|
||||||
|
|
||||||
|
private Integer tvdbId;
|
||||||
|
|
||||||
|
private Integer tmdbId;
|
||||||
|
|
||||||
|
private String language;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@TableField(exist = false)
|
||||||
|
private String cleanTitle;
|
||||||
|
|
||||||
|
private Integer validStatus;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT)
|
||||||
|
private String createTime;
|
||||||
|
|
||||||
|
@TableField(fill = FieldFill.INSERT_UPDATE)
|
||||||
|
private String updateTime;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,128 @@
|
||||||
|
package com.lckp.jproxy.exception;
|
||||||
|
|
||||||
|
import org.springframework.context.MessageSource;
|
||||||
|
import org.springframework.http.ResponseEntity;
|
||||||
|
import org.springframework.jdbc.UncategorizedSQLException;
|
||||||
|
import org.springframework.validation.BindException;
|
||||||
|
import org.springframework.validation.BindingResult;
|
||||||
|
import org.springframework.validation.FieldError;
|
||||||
|
import org.springframework.validation.ObjectError;
|
||||||
|
import org.springframework.web.bind.annotation.ControllerAdvice;
|
||||||
|
import org.springframework.web.bind.annotation.ExceptionHandler;
|
||||||
|
import org.springframework.web.bind.annotation.ResponseBody;
|
||||||
|
import org.springframework.web.client.HttpClientErrorException;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.constant.Messages;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 全局异常处理
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-23
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@ControllerAdvice
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class GlobalExceptionHandler {
|
||||||
|
|
||||||
|
private final MessageSource messageSource;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 处理请求参数异常
|
||||||
|
*
|
||||||
|
* @param e
|
||||||
|
* @param request
|
||||||
|
* @return ResponseEntity<Object>
|
||||||
|
*/
|
||||||
|
@ResponseBody
|
||||||
|
@ExceptionHandler(BindException.class)
|
||||||
|
public ResponseEntity<Object> dealBindException(BindException e, HttpServletRequest request) {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
BindingResult bindingResult = e.getBindingResult();
|
||||||
|
for (ObjectError objectError : bindingResult.getAllErrors()) {
|
||||||
|
FieldError fieldError = (FieldError) objectError;
|
||||||
|
builder.append("\n" + fieldError.getField() + ": " + fieldError.getDefaultMessage());
|
||||||
|
}
|
||||||
|
String message = builder.toString();
|
||||||
|
if (message.length() > 0) {
|
||||||
|
message = message.substring(1);
|
||||||
|
}
|
||||||
|
log.error("请求参数异常:{}", message);
|
||||||
|
return ResponseEntity.badRequest().body(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 处理系统配置异常
|
||||||
|
*
|
||||||
|
* @param e
|
||||||
|
* @param request
|
||||||
|
* @return ResponseEntity<Object>
|
||||||
|
*/
|
||||||
|
@ResponseBody
|
||||||
|
@ExceptionHandler(SystemConfigException.class)
|
||||||
|
public ResponseEntity<Object> dealSystemConfigException(SystemConfigException e,
|
||||||
|
HttpServletRequest request) {
|
||||||
|
String message = messageSource.getMessage(e.getMessage(), null, request.getLocale());
|
||||||
|
log.error("系统配置异常:{}", message);
|
||||||
|
return ResponseEntity.internalServerError().body(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 处理 Http 请求异常
|
||||||
|
*
|
||||||
|
* @param e
|
||||||
|
* @param request
|
||||||
|
* @return ResponseEntity<Object>
|
||||||
|
*/
|
||||||
|
@ResponseBody
|
||||||
|
@ExceptionHandler(HttpClientErrorException.class)
|
||||||
|
public ResponseEntity<Object> dealHttpClientErrorException(HttpClientErrorException e,
|
||||||
|
HttpServletRequest request) {
|
||||||
|
log.error("Http 请求异常:{}", e.getMessage());
|
||||||
|
return ResponseEntity.internalServerError().body(e.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 处理数据库异常
|
||||||
|
*
|
||||||
|
* @param e
|
||||||
|
* @param request
|
||||||
|
* @return ResponseEntity<Object>
|
||||||
|
*/
|
||||||
|
@ResponseBody
|
||||||
|
@ExceptionHandler(UncategorizedSQLException.class)
|
||||||
|
public ResponseEntity<Object> dealUncategorizedSQLException(UncategorizedSQLException e,
|
||||||
|
HttpServletRequest request) {
|
||||||
|
String message = e.getMessage();
|
||||||
|
if (message.contains("SQLITE_BUSY")) {
|
||||||
|
message = messageSource.getMessage(Messages.DATABASE_BUSY, null, request.getLocale());
|
||||||
|
}
|
||||||
|
log.error("数据库异常:{}", message);
|
||||||
|
return ResponseEntity.internalServerError().body(message);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 处理其他异常
|
||||||
|
*
|
||||||
|
* @param e
|
||||||
|
* @param request
|
||||||
|
* @return ResponseEntity<Object>
|
||||||
|
*/
|
||||||
|
@ResponseBody
|
||||||
|
@ExceptionHandler(Exception.class)
|
||||||
|
public ResponseEntity<Object> dealException(Exception e, HttpServletRequest request) {
|
||||||
|
log.error("其他异常:{}", e.getMessage(), e);
|
||||||
|
return ResponseEntity.internalServerError().body(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,17 @@
|
||||||
|
package com.lckp.jproxy.exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 系统配置异常
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-31
|
||||||
|
*/
|
||||||
|
public class SystemConfigException extends RuntimeException {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
public SystemConfigException(String message) {
|
||||||
|
super(message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,66 @@
|
||||||
|
package com.lckp.jproxy.filter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
|
||||||
|
import jakarta.servlet.Filter;
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.ServletOutputStream;
|
||||||
|
import jakarta.servlet.ServletRequest;
|
||||||
|
import jakarta.servlet.ServletResponse;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 基础过滤器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-19
|
||||||
|
*/
|
||||||
|
public abstract class BaseFilter implements Filter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param request
|
||||||
|
* @param response
|
||||||
|
* @param chain
|
||||||
|
* @throws IOException
|
||||||
|
* @throws ServletException
|
||||||
|
* @see jakarta.servlet.Filter#doFilter(jakarta.servlet.ServletRequest,
|
||||||
|
* jakarta.servlet.ServletResponse, jakarta.servlet.FilterChain)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
chain.doFilter(request, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 把结果写入 response
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @param response
|
||||||
|
* @throws IOException void
|
||||||
|
*/
|
||||||
|
public void writeToResponse(byte[] content, ServletResponse response) throws IOException {
|
||||||
|
ServletOutputStream out = response.getOutputStream();
|
||||||
|
response.setContentLength(content.length);
|
||||||
|
response.setCharacterEncoding(StandardCharsets.UTF_8.toString());
|
||||||
|
out.write(content);
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 把结果写入 response
|
||||||
|
*
|
||||||
|
* @param content
|
||||||
|
* @param response
|
||||||
|
* @throws IOException void
|
||||||
|
*/
|
||||||
|
public void writeToResponse(String content, ServletResponse response) throws IOException {
|
||||||
|
content = content == null ? "" : content;
|
||||||
|
writeToResponse(content.getBytes(StandardCharsets.UTF_8), response);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,175 @@
|
||||||
|
package com.lckp.jproxy.filter;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
|
import com.github.benmanes.caffeine.cache.Cache;
|
||||||
|
import com.lckp.jproxy.constant.ApiField;
|
||||||
|
import com.lckp.jproxy.filter.wrapper.RequestWrapper;
|
||||||
|
import com.lckp.jproxy.model.request.IndexerRequest;
|
||||||
|
import com.lckp.jproxy.service.IIndexerService;
|
||||||
|
import com.lckp.jproxy.util.ApplicationContextHolder;
|
||||||
|
import com.lckp.jproxy.util.FormatUtil;
|
||||||
|
import com.lckp.jproxy.util.XmlUtil;
|
||||||
|
|
||||||
|
import jakarta.servlet.FilterChain;
|
||||||
|
import jakarta.servlet.ServletException;
|
||||||
|
import jakarta.servlet.ServletRequest;
|
||||||
|
import jakarta.servlet.ServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 索引器过滤器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-20
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public abstract class IndexerFilter extends BaseFilter {
|
||||||
|
|
||||||
|
private final IIndexerService indexerService;
|
||||||
|
|
||||||
|
private Cache<String, String> indexerResultCache;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
|
||||||
|
throws IOException, ServletException {
|
||||||
|
RequestWrapper requestWrapper = new RequestWrapper((HttpServletRequest) request);
|
||||||
|
// 读取缓存
|
||||||
|
if (indexerResultCache == null) {
|
||||||
|
indexerResultCache = (Cache<String, String>) ApplicationContextHolder
|
||||||
|
.getBean("indexerResultCache");
|
||||||
|
}
|
||||||
|
String cacheKey = indexerService.generateCacheKey(requestWrapper);
|
||||||
|
String xml = indexerResultCache.asMap().get(cacheKey);
|
||||||
|
if (xml != null) {
|
||||||
|
log.debug("From cache: {}", cacheKey);
|
||||||
|
log.trace("{}", xml);
|
||||||
|
writeToResponse(xml, response);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// 处理查询
|
||||||
|
IndexerRequest indexerRequest = getIndexerRequest(requestWrapper);
|
||||||
|
String searchKey = indexerRequest.getSearchKey();
|
||||||
|
if (StringUtils.isNotBlank(searchKey)) {
|
||||||
|
// 无绝对集数,去除 00
|
||||||
|
searchKey = searchKey.replaceAll(" 00$", "");
|
||||||
|
indexerRequest.setSearchKey(searchKey);
|
||||||
|
// 获取所有待查询标题
|
||||||
|
String title = indexerService.getTitle(indexerRequest.getSearchKey());
|
||||||
|
List<String> searchTitleList = indexerService.getSearchTitle(title);
|
||||||
|
// 计算 offset
|
||||||
|
int offset = indexerRequest.getOffset();
|
||||||
|
int size = searchTitleList.size();
|
||||||
|
String offsetKey = indexerService.generateOffsetKey(requestWrapper);
|
||||||
|
List<Integer> offsetList = indexerService.getOffsetList(offsetKey, size);
|
||||||
|
// 计算当前标题下标
|
||||||
|
int index = indexerService.calculateCurrentIndex(offset, offsetList);
|
||||||
|
int count = 0;
|
||||||
|
int minCount = indexerService.getMinCount();
|
||||||
|
do {
|
||||||
|
if (size > 2 && index == size - 1) {
|
||||||
|
// 已查询到的结果数量少于 minCount 则去除季集信息尝试查询
|
||||||
|
if (minCount > 0 && offsetList.get(index - 1) < minCount) {
|
||||||
|
if (StringUtils.isNotBlank(indexerRequest.getSeasonNumber())) {
|
||||||
|
indexerRequest.setSeasonNumber("");
|
||||||
|
indexerRequest.setEpisodeNumber("");
|
||||||
|
} else {
|
||||||
|
indexerRequest.setSearchKey(
|
||||||
|
FormatUtil.removeSeasonEpisode(indexerRequest.getSearchKey()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// 请求
|
||||||
|
indexerService.updateIndexerRequest(index, searchTitleList, offsetList, indexerRequest);
|
||||||
|
updateRequestWrapper(indexerRequest, requestWrapper);
|
||||||
|
String newXml = indexerService.executeNewRequest(requestWrapper);
|
||||||
|
count = XmlUtil.count(newXml);
|
||||||
|
// 处理 Prowlarr 分页异常
|
||||||
|
if (count > indexerRequest.getLimit()) {
|
||||||
|
count = indexerRequest.getLimit();
|
||||||
|
newXml = XmlUtil.remove(newXml, count);
|
||||||
|
offset = offset - count;
|
||||||
|
}
|
||||||
|
if (count > 0 || xml == null) {
|
||||||
|
xml = XmlUtil.merger(xml, newXml);
|
||||||
|
}
|
||||||
|
// 更新参数
|
||||||
|
offset = offset + count;
|
||||||
|
indexerRequest.setOffset(offset);
|
||||||
|
offsetList.set(index, offset);
|
||||||
|
indexerService.updateOffsetList(offsetKey, offsetList);
|
||||||
|
indexerRequest.setLimit(indexerRequest.getLimit() - count);
|
||||||
|
} while (++index < size && indexerRequest.getLimit() > 0);
|
||||||
|
} else {
|
||||||
|
xml = indexerService.executeNewRequest(requestWrapper);
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(xml) && xml.contains("<" + ApiField.INDEXER_CHANNEL + ">")) {
|
||||||
|
// 执行格式化规则
|
||||||
|
xml = indexerService.executeFormatRule(xml);
|
||||||
|
// 缓存结果
|
||||||
|
indexerResultCache.asMap().put(cacheKey, xml);
|
||||||
|
}
|
||||||
|
log.debug("From request: {}", cacheKey);
|
||||||
|
log.trace("{}", xml);
|
||||||
|
writeToResponse(xml, response);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 获取索引器参数
|
||||||
|
*
|
||||||
|
* @param requestWrapper
|
||||||
|
* @return IndexerRequest
|
||||||
|
*/
|
||||||
|
public IndexerRequest getIndexerRequest(RequestWrapper requestWrapper) {
|
||||||
|
IndexerRequest indexerRequest = new IndexerRequest();
|
||||||
|
indexerRequest.setSearchKey(requestWrapper.getParameter(ApiField.INDEXER_SEARCH_KEY));
|
||||||
|
indexerRequest.setSearchType(requestWrapper.getParameter(ApiField.INDEXER_SEARCH_TYPE));
|
||||||
|
String seasonNumber = requestWrapper.getParameter(ApiField.INDEXER_SEASON_NUMBER);
|
||||||
|
indexerRequest.setSeasonNumber(seasonNumber);
|
||||||
|
String episodeNumber = requestWrapper.getParameter(ApiField.INDEXER_EPISODE_NUMBER);
|
||||||
|
indexerRequest.setEpisodeNumber(episodeNumber);
|
||||||
|
String offset = requestWrapper.getParameter(ApiField.INDEXER_OFFSET);
|
||||||
|
indexerRequest.setOffset(offset == null ? null : Integer.valueOf(offset));
|
||||||
|
String limit = requestWrapper.getParameter(ApiField.INDEXER_LIMIT);
|
||||||
|
indexerRequest.setLimit(limit == null ? null : Integer.valueOf(limit));
|
||||||
|
return indexerRequest;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 更新请求参数
|
||||||
|
*
|
||||||
|
* @param indexerRequest
|
||||||
|
* @param requestWrapper void
|
||||||
|
*/
|
||||||
|
public void updateRequestWrapper(IndexerRequest indexerRequest, RequestWrapper requestWrapper) {
|
||||||
|
if (StringUtils.isNotBlank(indexerRequest.getSearchKey())) {
|
||||||
|
requestWrapper.setParameter(ApiField.INDEXER_SEARCH_KEY, indexerRequest.getSearchKey());
|
||||||
|
}
|
||||||
|
if (StringUtils.isNotBlank(indexerRequest.getSearchType())) {
|
||||||
|
requestWrapper.setParameter(ApiField.INDEXER_SEARCH_TYPE, indexerRequest.getSearchType());
|
||||||
|
}
|
||||||
|
if (indexerRequest.getSeasonNumber() != null) {
|
||||||
|
requestWrapper.setParameter(ApiField.INDEXER_SEASON_NUMBER, indexerRequest.getSeasonNumber());
|
||||||
|
}
|
||||||
|
if (indexerRequest.getEpisodeNumber() != null) {
|
||||||
|
requestWrapper.setParameter(ApiField.INDEXER_EPISODE_NUMBER, indexerRequest.getEpisodeNumber());
|
||||||
|
}
|
||||||
|
if (indexerRequest.getOffset() != null) {
|
||||||
|
requestWrapper.setParameter(ApiField.INDEXER_OFFSET, String.valueOf(indexerRequest.getOffset()));
|
||||||
|
}
|
||||||
|
if (indexerRequest.getLimit() != null) {
|
||||||
|
requestWrapper.setParameter(ApiField.INDEXER_LIMIT, String.valueOf(indexerRequest.getLimit()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.lckp.jproxy.filter;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.service.IIndexerService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Radarr 索引器过滤器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-20
|
||||||
|
*/
|
||||||
|
public abstract class RadarrIndexerFilter extends IndexerFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param indexerService
|
||||||
|
*/
|
||||||
|
protected RadarrIndexerFilter(IIndexerService indexerService) {
|
||||||
|
super(indexerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.lckp.jproxy.filter;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.service.IRadarrIndexerService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Radarr Jackett 过滤器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-19
|
||||||
|
*/
|
||||||
|
public class RadarrJackettFilter extends RadarrIndexerFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param radarrIndexerService
|
||||||
|
*/
|
||||||
|
public RadarrJackettFilter(IRadarrIndexerService radarrIndexerService) {
|
||||||
|
super(radarrIndexerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.lckp.jproxy.filter;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.service.IRadarrIndexerService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Radarr Prowlarr 过滤器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-19
|
||||||
|
*/
|
||||||
|
public class RadarrProwlarrFilter extends RadarrIndexerFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param radarrIndexerService
|
||||||
|
*/
|
||||||
|
public RadarrProwlarrFilter(IRadarrIndexerService radarrIndexerService) {
|
||||||
|
super(radarrIndexerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.lckp.jproxy.filter;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.service.IIndexerService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Sonarr 索引器过滤器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-20
|
||||||
|
*/
|
||||||
|
public abstract class SonarrIndexerFilter extends IndexerFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param indexerService
|
||||||
|
*/
|
||||||
|
protected SonarrIndexerFilter(IIndexerService indexerService) {
|
||||||
|
super(indexerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.lckp.jproxy.filter;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.service.ISonarrIndexerService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Sonarr Jackett 过滤器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-19
|
||||||
|
*/
|
||||||
|
public class SonarrJackettFilter extends SonarrIndexerFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sonarrIndexerService
|
||||||
|
*/
|
||||||
|
public SonarrJackettFilter(ISonarrIndexerService sonarrIndexerService) {
|
||||||
|
super(sonarrIndexerService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,22 @@
|
||||||
|
package com.lckp.jproxy.filter;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.service.ISonarrIndexerService;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Sonarr Prowlarr 过滤器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-19
|
||||||
|
*/
|
||||||
|
public class SonarrProwlarrFilter extends SonarrIndexerFilter {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param sonarrIndexerService
|
||||||
|
*/
|
||||||
|
public SonarrProwlarrFilter(ISonarrIndexerService sonarrIndexerService) {
|
||||||
|
super(sonarrIndexerService);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,82 @@
|
||||||
|
package com.lckp.jproxy.filter.wrapper;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.net.URLEncoder;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
import java.nio.charset.StandardCharsets;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Vector;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletRequestWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 重写 HttpServletRequestWrapper 以复用
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-04
|
||||||
|
*/
|
||||||
|
public class RequestWrapper extends HttpServletRequestWrapper {
|
||||||
|
|
||||||
|
private Map<String, String[]> parameterMap;
|
||||||
|
|
||||||
|
private Charset charset;
|
||||||
|
|
||||||
|
public RequestWrapper(HttpServletRequest request) throws IOException {
|
||||||
|
super(request);
|
||||||
|
parameterMap = new HashMap<>(request.getParameterMap());
|
||||||
|
String encode = getCharacterEncoding();
|
||||||
|
try {
|
||||||
|
charset = Charset.forName(encode);
|
||||||
|
} catch (Exception e) {
|
||||||
|
charset = Charset.forName(StandardCharsets.UTF_8.name());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setParameter(String name, String value) {
|
||||||
|
parameterMap.put(name, new String[] { value });
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String[]> getParameterMap() {
|
||||||
|
return parameterMap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Enumeration<String> getParameterNames() {
|
||||||
|
return new Vector<String>(parameterMap.keySet()).elements();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String[] getParameterValues(String name) {
|
||||||
|
return parameterMap.get(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getParameter(String name) {
|
||||||
|
String[] values = parameterMap.get(name);
|
||||||
|
if (values != null && values.length > 0) {
|
||||||
|
return values[0];
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getQueryString() {
|
||||||
|
StringBuilder builder = new StringBuilder();
|
||||||
|
for (Map.Entry<String, String[]> entry : parameterMap.entrySet()) {
|
||||||
|
builder.append("&");
|
||||||
|
builder.append(URLEncoder.encode(entry.getKey(), charset));
|
||||||
|
builder.append("=");
|
||||||
|
builder.append(URLEncoder.encode(entry.getValue()[0], charset));
|
||||||
|
}
|
||||||
|
if (builder.length() > 0) {
|
||||||
|
builder.replace(0, 1, "");
|
||||||
|
}
|
||||||
|
return builder.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,72 @@
|
||||||
|
package com.lckp.jproxy.filter.wrapper;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import jakarta.servlet.ServletOutputStream;
|
||||||
|
import jakarta.servlet.WriteListener;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import jakarta.servlet.http.HttpServletResponseWrapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 重写 HttpServletResponseWrapper 以复用
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-04
|
||||||
|
*/
|
||||||
|
public class ResponseWrapper extends HttpServletResponseWrapper {
|
||||||
|
|
||||||
|
private ByteArrayOutputStream buffer;
|
||||||
|
private ServletOutputStream out;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param response
|
||||||
|
*/
|
||||||
|
public ResponseWrapper(HttpServletResponse response) {
|
||||||
|
super(response);
|
||||||
|
buffer = new ByteArrayOutputStream();
|
||||||
|
out = new WrapperOutputStream(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public ServletOutputStream getOutputStream() throws IOException {
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void flushBuffer() throws IOException {
|
||||||
|
if (out != null) {
|
||||||
|
out.flush();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getContent() throws IOException {
|
||||||
|
flushBuffer();
|
||||||
|
return buffer.toByteArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
class WrapperOutputStream extends ServletOutputStream {
|
||||||
|
private ByteArrayOutputStream bos;
|
||||||
|
|
||||||
|
public WrapperOutputStream(ByteArrayOutputStream bos) {
|
||||||
|
this.bos = bos;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void write(int b) throws IOException {
|
||||||
|
bos.write(b);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isReady() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setWriteListener(WriteListener arg0) {
|
||||||
|
// do nothing
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.lckp.jproxy.interceptor;
|
||||||
|
|
||||||
|
import org.springframework.http.HttpHeaders;
|
||||||
|
import org.springframework.http.HttpStatus;
|
||||||
|
import org.springframework.web.servlet.HandlerInterceptor;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.service.ISystemUserService;
|
||||||
|
|
||||||
|
import jakarta.servlet.http.HttpServletRequest;
|
||||||
|
import jakarta.servlet.http.HttpServletResponse;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import lombok.extern.slf4j.Slf4j;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 登陆拦截器
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-23
|
||||||
|
*/
|
||||||
|
@Slf4j
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
public class LoginInterceptor implements HandlerInterceptor {
|
||||||
|
|
||||||
|
private final ISystemUserService systemUserService;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
|
||||||
|
throws Exception {
|
||||||
|
log.debug("登陆拦截器: {}", request.getServletPath());
|
||||||
|
String token = request.getHeader(HttpHeaders.AUTHORIZATION);
|
||||||
|
if (systemUserService.verify(token)) {
|
||||||
|
log.debug("token: {}", token.substring(0, 12) + "******" + token.substring(token.length() - 5));
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
response.sendError(HttpStatus.FORBIDDEN.value());
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.lckp.jproxy.mapper;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.entity.RadarrExample;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* RadarrExample Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @since 2023-03-30
|
||||||
|
*/
|
||||||
|
public interface RadarrExampleMapper extends BaseMapper<RadarrExample> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.lckp.jproxy.mapper;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.entity.RadarrRule;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* RadarrRule Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @since 2023-03-20
|
||||||
|
*/
|
||||||
|
public interface RadarrRuleMapper extends BaseMapper<RadarrRule> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.lckp.jproxy.mapper;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.entity.RadarrTitle;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* RadarrTitle Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @since 2023-03-20
|
||||||
|
*/
|
||||||
|
public interface RadarrTitleMapper extends BaseMapper<RadarrTitle> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.lckp.jproxy.mapper;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.entity.SonarrExample;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SonarrExample Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @since 2023-03-30
|
||||||
|
*/
|
||||||
|
public interface SonarrExampleMapper extends BaseMapper<SonarrExample> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.lckp.jproxy.mapper;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.entity.SonarrRule;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SonarrRule Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @since 2023-03-20
|
||||||
|
*/
|
||||||
|
public interface SonarrRuleMapper extends BaseMapper<SonarrRule> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,32 @@
|
||||||
|
package com.lckp.jproxy.mapper;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
import com.lckp.jproxy.entity.SonarrTitle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SonarrTitle Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @since 2023-03-19
|
||||||
|
*/
|
||||||
|
public interface SonarrTitleMapper extends BaseMapper<SonarrTitle> {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 查询需要同步 TMBD 标题的 tvdbId
|
||||||
|
*
|
||||||
|
* @return List<Integer>
|
||||||
|
*/
|
||||||
|
public List<Integer> selectNeedSyncTmdbTitle();
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 查询 Sonarr 标题和 TMDB 标题
|
||||||
|
*
|
||||||
|
* @return List<SonarrTitle>
|
||||||
|
*/
|
||||||
|
public List<SonarrTitle> selectSonarrTitleAndTmdbTitle();
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.lckp.jproxy.mapper;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.entity.SystemConfig;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SystemConfig Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @since 2023-03-12
|
||||||
|
*/
|
||||||
|
public interface SystemConfigMapper extends BaseMapper<SystemConfig> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.lckp.jproxy.mapper;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.entity.SystemUser;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* SystemUser Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @since 2023-03-24
|
||||||
|
*/
|
||||||
|
public interface SystemUserMapper extends BaseMapper<SystemUser> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.lckp.jproxy.mapper;
|
||||||
|
|
||||||
|
import com.lckp.jproxy.entity.TmdbTitle;
|
||||||
|
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* TmdbTitle Mapper 接口
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @since 2023-03-19
|
||||||
|
*/
|
||||||
|
public interface TmdbTitleMapper extends BaseMapper<TmdbTitle> {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 索引器请求参数
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-12
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "索引器请求参数")
|
||||||
|
public class IndexerRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "查询关键字")
|
||||||
|
private String searchKey;
|
||||||
|
|
||||||
|
@Schema(description = "查询类型")
|
||||||
|
private String searchType;
|
||||||
|
|
||||||
|
@Schema(description = "季数")
|
||||||
|
private String seasonNumber;
|
||||||
|
|
||||||
|
@Schema(description = "集数")
|
||||||
|
private String episodeNumber;
|
||||||
|
|
||||||
|
@Schema(description = "偏移量")
|
||||||
|
private Integer offset;
|
||||||
|
|
||||||
|
@Schema(description = "数量限制")
|
||||||
|
private Integer limit;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* 分页查询入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-04
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "分页查询入参")
|
||||||
|
public class PageRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "页码")
|
||||||
|
protected long current = 1;
|
||||||
|
|
||||||
|
@Schema(description = "页长")
|
||||||
|
protected long pageSize = 10;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* 获取 Mybatis-Plus 分页参数
|
||||||
|
*
|
||||||
|
* @param <T>
|
||||||
|
* @return Page<T>
|
||||||
|
*/
|
||||||
|
public <T> Page<T> mybatisPlusPage() {
|
||||||
|
return new Page<T>().setCurrent(this.current).setSize(this.pageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 电影范例查询入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-27
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "电影范例查询入参")
|
||||||
|
public class RadarrExampleQueryRequest extends PageRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "原始文本")
|
||||||
|
private String originalText;
|
||||||
|
|
||||||
|
@Schema(description = "状态")
|
||||||
|
private Integer validStatus;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 保存电影范例入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-30
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "保存电影范例入参")
|
||||||
|
public class RadarrExampleSaveRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "原始文本")
|
||||||
|
@NotBlank
|
||||||
|
private String originalText;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Radarr 规则查询入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-27
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "Radarr 规则查询入参")
|
||||||
|
public class RadarrRuleQueryRequest extends PageRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "标记")
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Radarr 标题查询入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-25
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "Radarr 标题查询入参")
|
||||||
|
public class RadarrTitleQueryRequest extends PageRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "标题")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Schema(description = "TMDB ID")
|
||||||
|
private Integer tmdbId;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,38 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 规则测试入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-29
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "规则测试入参")
|
||||||
|
public class RuleTestRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "匹配正则")
|
||||||
|
@NotBlank
|
||||||
|
private String regex;
|
||||||
|
|
||||||
|
@Schema(description = "替换内容")
|
||||||
|
@NotBlank
|
||||||
|
private String replacement;
|
||||||
|
|
||||||
|
@Schema(description = "偏移量")
|
||||||
|
private Integer offset = 0;
|
||||||
|
|
||||||
|
@Schema(description = "例子")
|
||||||
|
@NotBlank
|
||||||
|
private String example;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 剧集范例查询入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-27
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "剧集范例查询入参")
|
||||||
|
public class SonarrExampleQueryRequest extends PageRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "原始文本")
|
||||||
|
private String originalText;
|
||||||
|
|
||||||
|
@Schema(description = "状态")
|
||||||
|
private Integer validStatus;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 保存剧集范例入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-30
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "保存剧集范例入参")
|
||||||
|
public class SonarrExampleSaveRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "原始文本")
|
||||||
|
@NotBlank
|
||||||
|
private String originalText;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Sonarr 格式化入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-18
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "格式化入参")
|
||||||
|
public class SonarrFormatRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "文本", example = "[ANi] By the Grace of the Gods - 众神眷顾的男人 2 - 10 [1080P][Baha][WEB-DL][AAC AVC][CHT][MP4]")
|
||||||
|
@NotBlank
|
||||||
|
private String text;
|
||||||
|
|
||||||
|
@Schema(description = "格式", example = "{title} {season}{episode} {language}{resolution}")
|
||||||
|
@NotBlank
|
||||||
|
private String format;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Sonarr 规则查询入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-27
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "Sonarr 规则查询入参")
|
||||||
|
public class SonarrRuleQueryRequest extends PageRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "标记")
|
||||||
|
private String token;
|
||||||
|
|
||||||
|
@Schema(description = "备注")
|
||||||
|
private String remark;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* Sonarr 标题查询入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-25
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "Sonarr 标题查询入参")
|
||||||
|
public class SonarrTitleQueryRequest extends PageRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "标题")
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
@Schema(description = "TVDB 编号")
|
||||||
|
private Integer tvdbId;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.lckp.jproxy.model.request;
|
||||||
|
|
||||||
|
import java.io.Serializable;
|
||||||
|
|
||||||
|
import io.swagger.v3.oas.annotations.media.Schema;
|
||||||
|
import jakarta.validation.constraints.NotBlank;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.Setter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* <p>
|
||||||
|
* 清除系统缓存入参
|
||||||
|
* </p>
|
||||||
|
*
|
||||||
|
* @author LuckyPuppy514
|
||||||
|
* @date 2023-03-27
|
||||||
|
*/
|
||||||
|
@Getter
|
||||||
|
@Setter
|
||||||
|
@Schema(description = "清除系统缓存入参")
|
||||||
|
public class SystemCacheClearRequest implements Serializable {
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
@Schema(description = "缓存名称", example = "sonarr_rule")
|
||||||
|
@NotBlank
|
||||||
|
private String cacheName;
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue