Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

优化番剧添加重复的问题 #727

Open
wants to merge 36 commits into
base: 3.2-dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
4499dc1
feat: default hidden downloader page
Rewrite0 Mar 5, 2024
c20369f
feat: Enable Vue JSX support
Rewrite0 Mar 5, 2024
c95fe89
refactor: 整理unocss,重构useApi,完善通知i18n,调整了一些代码写法,调整了一些样式,清理了一些无用依赖和代码
Rewrite0 Mar 7, 2024
b3f6255
feat: 修改RSS条目样式
Rewrite0 Mar 7, 2024
6a0ffa4
feat: 日志着色 & 日志更新时间更改为 10s & 增加立即更新日志按钮
Rewrite0 Mar 8, 2024
4194a67
fix: setConfig
Rewrite0 Mar 8, 2024
13cca79
feat: bangumi-card 增加字幕组信息
Rewrite0 Mar 8, 2024
7279830
fix: 重回log页log没有置底的问题
Rewrite0 Mar 8, 2024
7e9ca33
Merge pull request #713 from Rewrite0/refactor-webui
Rewrite0 Mar 8, 2024
f0f01c6
Update proxy.md Reverse proxy
Nchyn Mar 12, 2024
dfc5119
Merge pull request #716 from Nchyn/main
EstrellaXD Mar 12, 2024
6ddcbae
feat: 新增通过官方名称搜索番剧接口
unknown-o Mar 31, 2024
5015a68
fix: 修正RSS重复添加相同official_title的番剧
unknown-o Mar 31, 2024
8b2711b
mod: dev模式时,监听0.0.0.0
unknown-o Mar 31, 2024
fe8cadb
mod: 锁定前端package包
unknown-o Mar 31, 2024
8ad5993
fix: RSS获取的番剧列表会重复添加
unknown-o Mar 31, 2024
9a38ed0
mod: 将搜索番剧标题失败降级为debug消息
unknown-o Mar 31, 2024
118563a
feat: Torrent表新增字段save_path
unknown-o Mar 31, 2024
4549d82
feat: 启动时自动更新torrent数据表
unknown-o Mar 31, 2024
1120e80
feat: 为torrent数据表新增finished字段
unknown-o Mar 31, 2024
65e199b
feat: 自动补全的番剧种子中包含番剧ID以及保存路径
unknown-o Mar 31, 2024
7ba42ea
feat: 去除季度补全时重复的种子
unknown-o Mar 31, 2024
284730e
fix: 季度补全种子反复添加的问题
unknown-o Mar 31, 2024
a26b06c
feat: 允许同时收集多种视频格式的番剧季度全集
unknown-o Mar 31, 2024
edee82b
feat 将检查种子是否重复函数独立出来
unknown-o Mar 31, 2024
215f9aa
mod: 移动check_torrent_duplicate函数位置
unknown-o Mar 31, 2024
0a6e6c3
fix: 修正函数名错误
unknown-o Mar 31, 2024
1e9c1ca
feat: 录入番剧时,生成番剧保存路径
unknown-o Mar 31, 2024
6ba6f19
feat: 优化重复下载多个字幕组视频的问题
unknown-o Mar 31, 2024
4915d50
fix: 种子可能被重复添加的问题
unknown-o Mar 31, 2024
12fe5f5
feat: 优化季度补全功能搜索能力
unknown-o Mar 31, 2024
dfe2e0d
fix: 修正自动补全第二季即以上番剧时出现错误
unknown-o Mar 31, 2024
8c32ea4
fix: 修正无法添加两季及以上番剧的问题
unknown-o Mar 31, 2024
b43de57
mod: 捕获download异常
unknown-o Mar 31, 2024
b144580
feat: 捕获重命名时异常
unknown-o Mar 31, 2024
71e8831
mod: 优化季度补全功能
unknown-o Mar 31, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion backend/dev.sh
Original file line number Diff line number Diff line change
Expand Up @@ -25,4 +25,4 @@ if [ ! -f "$VERSION_FILE" ]; then
echo "VERSION='DEV_VERSION'" >>"$VERSION_FILE"
fi

../venv/bin/uvicorn main:app --reload --port 7892
../venv/bin/uvicorn main:app --reload --port 7892 --host 0.0.0.0
10 changes: 10 additions & 0 deletions backend/src/module/checker/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

from module.conf import VERSION, settings
from module.downloader import DownloadClient
from module.rss import RSSEngine
from module.models import Config
from module.update import version_check

Expand Down Expand Up @@ -83,3 +84,12 @@ def check_img_cache() -> bool:
else:
img_path.mkdir()
return False

@staticmethod
def check_torrent_table() -> bool:
with RSSEngine() as engine:
table_info = engine.exec("PRAGMA table_info(torrent)").all()
for item in table_info:
if(item[1] == 'save_path'):
return False
return True
5 changes: 4 additions & 1 deletion backend/src/module/core/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from module.conf import VERSION, settings
from module.models import ResponseModel
from module.update import data_migration, first_run, from_30_to_31, start_up, cache_image
from module.update import data_migration, torrent_table_migration, first_run, from_30_to_31, start_up, cache_image

from .sub_thread import RenameThread, RSSThread

Expand Down Expand Up @@ -46,6 +46,9 @@ def startup(self):
# Update database
from_30_to_31()
logger.info("[Core] Database updated.")
if self.update_torrent_table:
torrent_table_migration()
logger.info("[Core] Torrent table updated.")
if not self.img_cache:
logger.info("[Core] No image cache exists, create image cache.")
cache_image()
Expand Down
4 changes: 4 additions & 0 deletions backend/src/module/core/status.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,7 @@ def database(self):
@property
def img_cache(self):
return self.check_img_cache()

@property
def update_torrent_table(self):
return self.check_torrent_table()
10 changes: 10 additions & 0 deletions backend/src/module/database/bangumi.py
Original file line number Diff line number Diff line change
Expand Up @@ -96,6 +96,16 @@ def search_id(self, _id: int) -> Optional[Bangumi]:
else:
logger.debug(f"[Database] Find bangumi id: {_id}.")
return self.session.exec(statement).first()

def search_official_title(self, _official_title: str) -> Optional[Bangumi]:
statement = select(Bangumi).where(Bangumi.official_title == _official_title)
bangumi = self.session.exec(statement).first()
if bangumi is None:
logger.debug(f"[Database] Cannot find bangumi title: {_official_title}.")
return None
else:
logger.debug(f"[Database] Find bangumi title: {_official_title}.")
return self.session.exec(statement).first()

def match_poster(self, bangumi_name: str) -> str:
# Use like to match
Expand Down
4 changes: 4 additions & 0 deletions backend/src/module/database/combine.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ def create_table(self):
def drop_table(self):
SQLModel.metadata.drop_all(self.engine)

def migrate_torrent(self):
self.exec("ALTER TABLE torrent ADD COLUMN save_path varchar(255)")
self.exec("ALTER TABLE torrent ADD COLUMN finished int")

def migrate(self):
# Run migration online
bangumi_data = self.bangumi.search_all()
Expand Down
3 changes: 3 additions & 0 deletions backend/src/module/database/torrent.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,9 @@ def search(self, _id: int) -> Torrent:
def search_all(self) -> list[Torrent]:
return self.session.exec(select(Torrent)).all()

def search_finished(self, _save_path = "") -> list[Torrent]:
return self.session.exec(select(Torrent).where(Torrent.save_path == _save_path)).first()

def search_rss(self, rss_id: int) -> list[Torrent]:
return self.session.exec(select(Torrent).where(Torrent.rss_id == rss_id)).all()

Expand Down
25 changes: 14 additions & 11 deletions backend/src/module/downloader/download_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -135,17 +135,20 @@ def add_torrent(self, torrent: Torrent | list, bangumi: Bangumi) -> bool:
else:
torrent_file = req.get_content(torrent.url)
torrent_url = None
if self.client.add_torrents(
torrent_urls=torrent_url,
torrent_files=torrent_file,
save_path=bangumi.save_path,
category="Bangumi",
):
logger.debug(f"[Downloader] Add torrent: {bangumi.official_title}")
return True
else:
logger.debug(f"[Downloader] Torrent added before: {bangumi.official_title}")
return False
try:
if self.client.add_torrents(
torrent_urls=torrent_url,
torrent_files=torrent_file,
save_path=bangumi.save_path,
category="Bangumi",
):
logger.debug(f"[Downloader] Add torrent: {bangumi.official_title}")
return True
else:
logger.debug(f"[Downloader] Torrent added before: {bangumi.official_title}")
return False
except Exception as e:
logger.debug(f"[Downloader] error: {str(e)}")

def move_torrent(self, hashes, location):
self.client.move_torrent(hashes=hashes, new_location=location)
Expand Down
16 changes: 13 additions & 3 deletions backend/src/module/manager/collector.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,16 +18,26 @@ def collect_season(self, bangumi: Bangumi, link: str = None):
torrents = st.search_season(bangumi)
else:
torrents = st.get_torrents(link, bangumi.filter.replace(",", "|"))
if self.add_torrent(torrents, bangumi):
# 去除重复的种子
new_torrents = []
save_path_list = []
for item in torrents:
if(item.save_path in save_path_list):
continue
torrents_info = engine.torrent.search_finished(item.save_path)
if(not torrents_info):
new_torrents.append(item)
save_path_list.append(item.save_path)
if self.add_torrent(new_torrents, bangumi):
logger.info(
f"Collections of {bangumi.official_title} Season {bangumi.season} completed."
)
for torrent in torrents:
for torrent in new_torrents:
torrent.downloaded = True
bangumi.eps_collect = True
if engine.bangumi.update(bangumi):
engine.bangumi.add(bangumi)
engine.torrent.add_all(torrents)
engine.torrent.add_all(new_torrents)
return ResponseModel(
status=True,
status_code=200,
Expand Down
55 changes: 29 additions & 26 deletions backend/src/module/manager/renamer.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,32 +143,35 @@ def rename(self) -> list[Notification]:
torrents_info = self.get_torrent_info()
renamed_info: list[Notification] = []
for info in torrents_info:
media_list, subtitle_list = self.check_files(info)
bangumi_name, season = self._path_to_bangumi(info.save_path)
kwargs = {
"torrent_name": info.name,
"bangumi_name": bangumi_name,
"method": rename_method,
"season": season,
"_hash": info.hash,
}
# Rename single media file
if len(media_list) == 1:
notify_info = self.rename_file(media_path=media_list[0], **kwargs)
if notify_info:
renamed_info.append(notify_info)
# Rename subtitle file
if len(subtitle_list) > 0:
self.rename_subtitles(subtitle_list=subtitle_list, **kwargs)
# Rename collection
elif len(media_list) > 1:
logger.info("[Renamer] Start rename collection")
self.rename_collection(media_list=media_list, **kwargs)
if len(subtitle_list) > 0:
self.rename_subtitles(subtitle_list=subtitle_list, **kwargs)
self.set_category(info.hash, "BangumiCollection")
else:
logger.warning(f"[Renamer] {info.name} has no media file")
try:
media_list, subtitle_list = self.check_files(info)
bangumi_name, season = self._path_to_bangumi(info.save_path)
kwargs = {
"torrent_name": info.name,
"bangumi_name": bangumi_name,
"method": rename_method,
"season": season,
"_hash": info.hash,
}
# Rename single media file
if len(media_list) == 1:
notify_info = self.rename_file(media_path=media_list[0], **kwargs)
if notify_info:
renamed_info.append(notify_info)
# Rename subtitle file
if len(subtitle_list) > 0:
self.rename_subtitles(subtitle_list=subtitle_list, **kwargs)
# Rename collection
elif len(media_list) > 1:
logger.info("[Renamer] Start rename collection")
self.rename_collection(media_list=media_list, **kwargs)
if len(subtitle_list) > 0:
self.rename_subtitles(subtitle_list=subtitle_list, **kwargs)
self.set_category(info.hash, "BangumiCollection")
else:
logger.warning(f"[Renamer] {info.name} has no media file")
except Exception as e:
logger.error(f"[Renamer] error: {str(e)}")
logger.debug("[Renamer] Rename process finished.")
return renamed_info

Expand Down
23 changes: 22 additions & 1 deletion backend/src/module/manager/torrent.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import logging

from module.conf import settings
from module.database import Database
from module.downloader import DownloadClient
from module.models import Bangumi, BangumiUpdate, ResponseModel
from module.models import Torrent, Bangumi, BangumiUpdate, ResponseModel
from module.parser import TitleParser
from module.manager.renamer import Renamer

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -174,6 +176,25 @@ def search_one(self, _id: int | str):
return data


def refine_torrent(self, bangumi: Bangumi, torrent: Torrent):
rename_method = settings.bangumi_manage.rename_method
# 查找视频是否包含关键字
keywords = ['内嵌','外挂','封装','MKV','内挂']
suffix = 'mp4'
for item1 in keywords:
if(item1 in torrent.name):
suffix = 'mkv'
# 解析视频
ep = TitleParser().torrent_parser(
torrent_path=f"{torrent.name}.{suffix}"
)
if(ep):
ep_name = Renamer().gen_path(ep, bangumi.official_title, method=rename_method)
torrent.bangumi_id = bangumi.id
torrent.save_path = f'{bangumi.save_path}/{ep_name}'
return torrent
return False

if __name__ == "__main__":
with TorrentManager() as manager:
manager.refresh_poster()
2 changes: 2 additions & 0 deletions backend/src/module/models/torrent.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@ class Torrent(SQLModel, table=True):
url: str = Field("https://example.com/torrent", alias="url")
homepage: Optional[str] = Field(None, alias="homepage")
downloaded: bool = Field(False, alias="downloaded")
save_path: Optional[str] = Field(None, alias="save_path")
finished: bool = Field(False, alias="finished")


class TorrentUpdate(SQLModel):
Expand Down
22 changes: 15 additions & 7 deletions backend/src/module/rss/analyser.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from module.models import Bangumi, ResponseModel, RSSItem, Torrent
from module.network import RequestContent
from module.parser import TitleParser

from module.downloader.path import TorrentPath
from .engine import RSSEngine

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -66,13 +66,21 @@ def torrent_to_data(self, torrent: Torrent, rss: RSSItem) -> Bangumi:
def rss_to_data(
self, rss: RSSItem, engine: RSSEngine, full_parse: bool = True
) -> list[Bangumi]:
rss_torrents = self.get_rss_torrents(rss.url, full_parse)
torrents_to_add = engine.bangumi.match_list(rss_torrents, rss.url)
if not torrents_to_add:
logger.debug("[RSS] No new title has been found.")
return []
all_rss_torrents = self.get_rss_torrents(rss.url, full_parse)
new_data = []
title_list = []
for torrent in all_rss_torrents:
bangumi = self.torrent_to_data(torrent, rss)
if(not bangumi):
continue
if(f'{bangumi.official_title}{bangumi.season}' in title_list):
continue
title_list.append(f'{bangumi.official_title}{bangumi.season}')
q_bangumi = engine.bangumi.search_official_title(bangumi.official_title)
if(not q_bangumi):
bangumi.save_path = TorrentPath()._gen_save_path(bangumi)
new_data.append(bangumi)
# New List
new_data = self.torrents_to_data(torrents_to_add, rss, full_parse)
if new_data:
# Add to database
engine.bangumi.add_all(new_data)
Expand Down
28 changes: 23 additions & 5 deletions backend/src/module/rss/engine.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
from module.downloader import DownloadClient
from module.models import Bangumi, ResponseModel, RSSItem, Torrent
from module.network import RequestContent
from module.manager.torrent import TorrentManager

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -97,6 +98,8 @@ def delete_list(self, rss_id_list: list[int]):
def pull_rss(self, rss_item: RSSItem) -> list[Torrent]:
torrents = self._get_torrents(rss_item)
new_torrents = self.torrent.check_new(torrents)
# 检查相同视频是否已经呗下载过
#for torrent in new_torrents
return new_torrents

def match_torrent(self, torrent: Torrent) -> Optional[Bangumi]:
Expand All @@ -120,14 +123,29 @@ def refresh_rss(self, client: DownloadClient, rss_id: Optional[int] = None):
# From RSS Items, get all torrents
logger.debug(f"[Engine] Get {len(rss_items)} RSS items")
for rss_item in rss_items:
new_torrents = self.pull_rss(rss_item)
pulled_torrents = self.pull_rss(rss_item)
# Get all enabled bangumi data
for torrent in new_torrents:
save_path_list = []
new_torrents = []
for torrent in pulled_torrents:
matched_data = self.match_torrent(torrent)
if matched_data:
if client.add_torrent(torrent, matched_data):
logger.debug(f"[Engine] Add torrent {torrent.name} to client")
torrent.downloaded = True
torrent = TorrentManager().refine_torrent(matched_data, torrent)
if(torrent):
torrents_info = self.torrent.search_finished(torrent.save_path)
if(not torrents_info):
if(torrent.save_path in save_path_list):
logger.debug(f"[Engine] Ignore torrent {torrent.name}")
continue
save_path_list.append(torrent.save_path)
new_torrents.append(torrent)
if client.add_torrent(torrent, matched_data):
logger.debug(f"[Engine] Add torrent {torrent.name} to client")
torrent.downloaded = True
else:
logger.warning(f"[Engine] Torrent {torrent.name} has already been added")
else:
logger.debug(f"[Engine] Ignore torrent {torrent.name}")
# Add all torrents to database
self.torrent.add_all(new_torrents)

Expand Down
21 changes: 18 additions & 3 deletions backend/src/module/searcher/searcher.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

from module.models import Bangumi, RSSItem, Torrent
from module.network import RequestContent
from module.manager.torrent import TorrentManager
from module.rss import RSSAnalyser

from .provider import search_url
Expand All @@ -19,7 +20,7 @@
BangumiJSON: TypeAlias = str


class SearchTorrent(RequestContent, RSSAnalyser):
class SearchTorrent(RequestContent, RSSAnalyser, TorrentManager):
def search_torrents(self, rss_item: RSSItem) -> list[Torrent]:
return self.get_torrents(rss_item.url)
# torrents = self.get_torrents(rss_item.url)
Expand Down Expand Up @@ -48,8 +49,22 @@ def special_url(data: Bangumi, site: str) -> RSSItem:
keywords = [getattr(data, key) for key in SEARCH_KEY if getattr(data, key)]
url = search_url(site, keywords)
return url

def build_search_url(self, data: Bangumi, site: str) -> RSSItem:
keywords = []
keywords.append(data.official_title)
if(int(data.season) != 1):
keywords.append(data.season_raw)
url = search_url(site, keywords)
return url

def search_season(self, data: Bangumi, site: str = "mikan") -> list[Torrent]:
rss_item = self.special_url(data, site)
rss_item = self.build_search_url(data, site)
torrents = self.search_torrents(rss_item)
return [torrent for torrent in torrents if data.title_raw in torrent.name]
new_torrents = []
for item1 in torrents:
if(str(data.season_raw) in item1.name or data.season_raw == None):
res = self.refine_torrent(data, item1)
if(res):
new_torrents.append(res)
return new_torrents
Loading