mirror of
https://github.com/EstrellaXD/Auto_Bangumi.git
synced 2026-02-03 02:04:06 +08:00
2.5.0-pre5 更新文件目录,修复大量bug
This commit is contained in:
@@ -19,5 +19,5 @@ coverage.xml
|
||||
.pytest_cache
|
||||
.hypothesis
|
||||
|
||||
auto_bangumi/const_dev.py
|
||||
auto_bangumi/conf/const_dev.py
|
||||
config/bangumi.json/config/bangumi.json
|
||||
|
||||
5
.gitignore
vendored
5
.gitignore
vendored
@@ -160,9 +160,10 @@ cython_debug/
|
||||
#.idea/
|
||||
|
||||
# Custom
|
||||
/auto_bangumi/const_dev.py
|
||||
/auto_bangumi/conf/const_dev.py
|
||||
/config/bangumi.json
|
||||
/auto_bangumi/tester.py
|
||||
/resource/names.txt
|
||||
|
||||
/auto_bangumi/webui/
|
||||
|
||||
|
||||
|
||||
2
.idea/Bangumi_Auto_Rename.iml
generated
2
.idea/Bangumi_Auto_Rename.iml
generated
@@ -4,7 +4,7 @@
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/auto_bangumi" isTestSource="false" />
|
||||
</content>
|
||||
<orderEntry type="jdk" jdkName="Python 3.10 (auto_bangumi)" jdkType="Python SDK" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
<orderEntry type="library" name="bootstrap" level="application" />
|
||||
</component>
|
||||
|
||||
2
.idea/misc.xml
generated
2
.idea/misc.xml
generated
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (auto_bangumi)" project-jdk-type="Python SDK" />
|
||||
<component name="ProjectRootManager" version="2" project-jdk-name="Python 3.10 (np_veclib)" project-jdk-type="Python SDK" />
|
||||
</project>
|
||||
@@ -11,6 +11,6 @@ ENV TZ=Asia/Shanghai
|
||||
|
||||
ADD ./auto_bangumi /auto_bangumi
|
||||
ADD ./config /config
|
||||
ADD ./templates /templates
|
||||
|
||||
CMD [ "python3", "app.py"]
|
||||
CMD [ "uvicorn", "api:app", "--reload" ]
|
||||
CMD [ "run.sh"]
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
from ast import arg
|
||||
import os
|
||||
import time
|
||||
import logging
|
||||
|
||||
from conf import settings
|
||||
from argument_parser import parse
|
||||
from log import setup_logger
|
||||
from conf.argument_parser import parse
|
||||
from conf.log import setup_logger
|
||||
from utils import json_config
|
||||
|
||||
from core.rss_collector import RSSCollector
|
||||
from mikanani.rss_collector import RSSCollector
|
||||
from core.download_client import DownloadClient
|
||||
from core.renamer import Renamer
|
||||
from network.request import RequestsURL
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -55,42 +55,48 @@ def show_info():
|
||||
logger.info("Starting AutoBangumi...")
|
||||
|
||||
|
||||
|
||||
def run():
|
||||
# DEBUG 模式初始化
|
||||
args = parse()
|
||||
if args.debug:
|
||||
try:
|
||||
from const_dev import DEV_SETTINGS
|
||||
import sys
|
||||
from conf.const_dev import DEV_SETTINGS
|
||||
settings.init(DEV_SETTINGS)
|
||||
except ModuleNotFoundError:
|
||||
logger.debug("Please copy `const_dev.py` to `const_dev.py` to use custom settings")
|
||||
sys.path.append('/opt/homebrew/Caskroom/miniforge/base/envs/auto_bangumi/bin/python')
|
||||
settings.init(DEV_SETTINGS)
|
||||
else:
|
||||
settings.init()
|
||||
# 初始化
|
||||
setup_logger()
|
||||
show_info()
|
||||
time.sleep(3)
|
||||
download_client = DownloadClient()
|
||||
url_request = RequestsURL()
|
||||
download_client.init_downloader()
|
||||
if settings.rss_link is None:
|
||||
logger.error("Please add RIGHT RSS url.")
|
||||
quit()
|
||||
download_client.rss_feed()
|
||||
rss_collector = RSSCollector()
|
||||
rss_collector = RSSCollector(url_request)
|
||||
rename = Renamer(download_client)
|
||||
# 主程序循环
|
||||
while True:
|
||||
bangumi_data = load_data_file()
|
||||
try:
|
||||
# 解析 RSS
|
||||
rss_collector.collect(bangumi_data)
|
||||
# 历史剧集收集
|
||||
if settings.enable_eps_complete:
|
||||
download_client.eps_collect(bangumi_data["bangumi_info"])
|
||||
download_client.eps_collect(bangumi_data["bangumi_info"], url_request)
|
||||
url_request.close()
|
||||
download_client.add_rules(bangumi_data["bangumi_info"], settings.rss_link)
|
||||
# 首次等待
|
||||
if bangumi_data["first_run"]:
|
||||
logger.info(f"Waiting for downloading torrents...")
|
||||
time.sleep(settings.first_sleep)
|
||||
bangumi_data["first_run"] = False
|
||||
save_data_file(bangumi_data)
|
||||
# rename
|
||||
if settings.method != "none":
|
||||
rename.refresh()
|
||||
rename.run()
|
||||
|
||||
@@ -42,7 +42,7 @@ class FuzzMatch:
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from const_dev import DEV_SETTINGS
|
||||
from conf.const_dev import DEV_SETTINGS
|
||||
settings.init(DEV_SETTINGS)
|
||||
f = FuzzMatch()
|
||||
name = "勇者、辞职不干了"
|
||||
|
||||
@@ -24,8 +24,8 @@ if __name__ == "__main__":
|
||||
import sys, os
|
||||
|
||||
sys.path.append(os.path.dirname(".."))
|
||||
from log import setup_logger
|
||||
from const import BCOLORS
|
||||
from conf.log import setup_logger
|
||||
from conf.const import BCOLORS
|
||||
|
||||
setup_logger()
|
||||
parser = Parser()
|
||||
|
||||
0
auto_bangumi/conf/__init__.py
Normal file
0
auto_bangumi/conf/__init__.py
Normal file
@@ -45,7 +45,8 @@ ENV_TO_ATTR = {
|
||||
"AB_REMOVE_BAD_BT": ("remove_bad_torrent", lambda e: e.lower() in ("true", "1", "t")),
|
||||
"AB_FIRST_SLEEP": ("first_sleep", lambda e: float(e)),
|
||||
"AB_WEBUI_PORT": ("webui_port", lambda e: int(e)),
|
||||
"AB_FUZZ_MATCH": ("enable_fuzz_match", lambda e: e.lower() in ("true", "1", "t"))
|
||||
"AB_FUZZ_MATCH": ("enable_fuzz_match", lambda e: e.lower() in ("true", "1", "t")),
|
||||
"AB_HTTP_PROXY": "http_proxy"
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,7 @@ from downloader.exceptions import ConflictError
|
||||
|
||||
from conf import settings
|
||||
|
||||
from core.eps_complete import FullSeasonGet
|
||||
from mikanani.eps_complete import FullSeasonGet
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -81,7 +81,7 @@ class DownloadClient:
|
||||
info["added"] = True
|
||||
logger.info("Finished.")
|
||||
|
||||
def eps_collect(self, bangumi_info):
|
||||
def eps_collect(self, bangumi_info, request):
|
||||
logger.info("Start collecting past episodes.")
|
||||
for info in bangumi_info:
|
||||
if info["download_past"]:
|
||||
@@ -91,7 +91,8 @@ class DownloadClient:
|
||||
info["season"],
|
||||
info["subtitle"],
|
||||
info["source"],
|
||||
info["dpi"]
|
||||
info["dpi"],
|
||||
request
|
||||
).add_torrents_info()
|
||||
for download in downloads:
|
||||
self.client.torrents_add(
|
||||
|
||||
@@ -56,7 +56,7 @@ class Renamer:
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from const_dev import DEV_SETTINGS
|
||||
from conf.const_dev import DEV_SETTINGS
|
||||
settings.init(DEV_SETTINGS)
|
||||
client = DownloadClient()
|
||||
rename = Renamer(client)
|
||||
|
||||
@@ -75,7 +75,7 @@ class QbDownloader:
|
||||
|
||||
if __name__ == "__main__":
|
||||
try:
|
||||
from const_dev import DEV_SETTINGS
|
||||
from conf.const_dev import DEV_SETTINGS
|
||||
except ModuleNotFoundError:
|
||||
logger.debug("Please copy `const_dev.py` to `const_dev.py` to use custom settings")
|
||||
settings.init(DEV_SETTINGS)
|
||||
|
||||
0
auto_bangumi/mikanani/__init__.py
Normal file
0
auto_bangumi/mikanani/__init__.py
Normal file
@@ -6,18 +6,20 @@ from bs4 import BeautifulSoup
|
||||
import logging
|
||||
|
||||
from conf import settings
|
||||
from network.request import RequestsURL
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class FullSeasonGet:
|
||||
def __init__(self, group, bangumi_name, season, sub, source, dpi):
|
||||
def __init__(self, group, bangumi_name, season, sub, source, dpi , request: RequestsURL):
|
||||
self.bangumi_name = re.sub(settings.rule_name_re, " ", bangumi_name).strip()
|
||||
self.group = "" if group is None else group
|
||||
self.season = season
|
||||
self.subtitle = "" if sub is None else sub
|
||||
self.source = "" if source is None else source
|
||||
self.dpi = dpi
|
||||
self._req = request
|
||||
|
||||
def get_season_rss(self):
|
||||
if self.season == "S01":
|
||||
@@ -26,11 +28,8 @@ class FullSeasonGet:
|
||||
season = self.season
|
||||
search_str = re.sub(r"[\W_]", "+",
|
||||
f"{self.group} {self.bangumi_name} {season} {self.subtitle} {self.source} {self.dpi}")
|
||||
season = requests.get(
|
||||
f"https://mikanani.me/RSS/Search?searchstr={search_str}"
|
||||
)
|
||||
soup = BeautifulSoup(season.content, "xml")
|
||||
torrents = soup.find_all("enclosure")
|
||||
season = self._req.get_url(search_str)
|
||||
torrents = season.find_all("enclosure")
|
||||
return torrents
|
||||
|
||||
def add_torrents_info(self):
|
||||
@@ -1,29 +1,19 @@
|
||||
# -*- coding: UTF-8 -*-
|
||||
import os
|
||||
import logging
|
||||
import requests
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from conf import settings
|
||||
from bangumi_parser.analyser.rss_parser import ParserLV2
|
||||
from bangumi_parser.fuzz_match import FuzzMatch
|
||||
from network.request import RequestsURL
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RSSCollector:
|
||||
def __init__(self):
|
||||
def __init__(self, request: RequestsURL):
|
||||
self._simple_analyser = ParserLV2()
|
||||
self._fuzz_match = FuzzMatch()
|
||||
|
||||
def get_rss_info(self, rss_link):
|
||||
try:
|
||||
req = requests.get(rss_link, "utf-8")
|
||||
rss = BeautifulSoup(req.text, "xml")
|
||||
return rss
|
||||
except Exception as e:
|
||||
# logger.exception(e)
|
||||
logger.error("ERROR with DNS/Connection.")
|
||||
self._req = request
|
||||
|
||||
def title_parser(self, title, fuzz_match=True):
|
||||
episode = self._simple_analyser.analyse(title)
|
||||
@@ -53,8 +43,8 @@ class RSSCollector:
|
||||
return episode, data, title_official
|
||||
|
||||
def collect(self, bangumi_data):
|
||||
rss = self.get_rss_info(settings.rss_link)
|
||||
items = rss.find_all("item")
|
||||
req = self._req.get_url(settings.rss_link)
|
||||
items = req.find_all("item")
|
||||
for item in items:
|
||||
add = True
|
||||
name = item.title.string
|
||||
@@ -70,19 +60,19 @@ class RSSCollector:
|
||||
logger.info(f"Adding {title_official} Season {episode.season_info.number}")
|
||||
|
||||
def collect_collection(self, rss_link):
|
||||
rss = self.get_rss_info(rss_link)
|
||||
item = rss.find("item")
|
||||
req = self._req.get_url(rss_link)
|
||||
item = req.find("item")
|
||||
title = item.title.string
|
||||
_, data, _ = self.title_parser(title, fuzz_match=False)
|
||||
return data
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
from const_dev import DEV_SETTINGS
|
||||
from conf.const_dev import DEV_SETTINGS
|
||||
from utils import json_config
|
||||
settings.init(DEV_SETTINGS)
|
||||
rss = RSSCollector()
|
||||
info = json_config.load("/Users/Estrella/Developer/Bangumi_Auto_Collector/config/bangumi.json")
|
||||
info = json_config.load("/config/bangumi.json")
|
||||
rss.collect(info)
|
||||
print(info)
|
||||
|
||||
0
auto_bangumi/network/__init__.py
Normal file
0
auto_bangumi/network/__init__.py
Normal file
46
auto_bangumi/network/request.py
Normal file
46
auto_bangumi/network/request.py
Normal file
@@ -0,0 +1,46 @@
|
||||
import time
|
||||
|
||||
import requests
|
||||
import logging
|
||||
|
||||
from bs4 import BeautifulSoup
|
||||
|
||||
from conf import settings
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class RequestsURL:
|
||||
def __init__(self):
|
||||
self.session = requests.session()
|
||||
if settings.http_proxy is not None:
|
||||
self.proxy = {
|
||||
"https": settings.http_proxy,
|
||||
"http": settings.http_proxy
|
||||
}
|
||||
else:
|
||||
self.proxy = None
|
||||
|
||||
def get_url(self, url):
|
||||
times = 1
|
||||
while times < 5:
|
||||
try:
|
||||
req = self.session.get(url, proxies=self.proxy)
|
||||
return BeautifulSoup(req.text, "xml")
|
||||
except Exception:
|
||||
# logger.exception(e)
|
||||
logger.error("ERROR with DNS/Connection.")
|
||||
time.sleep(settings.connect_retry_interval)
|
||||
times += 1
|
||||
|
||||
def close(self):
|
||||
self.session.close()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
network_req = RequestsURL()
|
||||
req = network_req.get_url("https://mikanani.me/RSS/Classic")
|
||||
print(req.find_all("item"))
|
||||
network_req.close()
|
||||
req = network_req.get_url("https://mikanani.me/RSS/Classic")
|
||||
print(req.find_all("item"))
|
||||
@@ -1,5 +1,3 @@
|
||||
from typing import Union
|
||||
|
||||
import uvicorn
|
||||
from fastapi import FastAPI, Request
|
||||
from fastapi.responses import HTMLResponse
|
||||
@@ -7,7 +5,7 @@ from fastapi.templating import Jinja2Templates
|
||||
from pydantic import BaseModel
|
||||
import logging
|
||||
|
||||
from core.rss_collector import RSSCollector
|
||||
from mikanani.rss_collector import RSSCollector
|
||||
from core.download_client import DownloadClient
|
||||
from conf import settings
|
||||
from utils import json_config
|
||||
@@ -68,7 +66,7 @@ class RSS(BaseModel):
|
||||
@app.post("/api/v1/subscriptions")
|
||||
async def receive(link: RSS):
|
||||
data = RSSCollector().collect_collection(link.link)
|
||||
from const_dev import DEV_SETTINGS
|
||||
from conf.const_dev import DEV_SETTINGS
|
||||
settings.init(DEV_SETTINGS)
|
||||
client = DownloadClient()
|
||||
client.add_collection_feed(link.link, item_path=data["title"])
|
||||
|
||||
162
templates/index.html
Normal file
162
templates/index.html
Normal file
@@ -0,0 +1,162 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>AutoBangumi</title>
|
||||
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-0evHe/X+R7YkIZDRvuzKMRqM+OrBnVFBL6DOitfPri4tjfHxaWutUpFmBp4vmVor" crossorigin="anonymous">
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-3"></div>
|
||||
<div class="col-auto text-center p-3">
|
||||
<img src="/docs/image/auto_bangumi_v2.png" class="img-fluid" width=50%>
|
||||
</div>
|
||||
<div class="col-3"></div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col text-center">
|
||||
<h2>Configuration</h2>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center p-3">
|
||||
<div class="col-8">
|
||||
<h2>基础配置</h2>
|
||||
<ui class="list-group list-group-flush gap-1 shadow p-3 mb-5 rounded-3">
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="col-3">
|
||||
<h4>RSS link</h4>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<input type="rss" class="form-control" id="rsslink" aria-describedby="rsslinkHelp">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="col-2">
|
||||
<h4 class="text-left">HOST</h4>
|
||||
</div>
|
||||
<div class="col-8">
|
||||
<input type="rss" class="form-control" id="hostip" aria-describedby="hostipHelp">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="col-2">
|
||||
<h4 class="text-left">Username</h4>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<input type="rss" class="form-control" id="username" aria-describedby="emailHelp">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="col-2">
|
||||
<h4 class="text-left">Password</h4>
|
||||
</div>
|
||||
<div class="col-4">
|
||||
<input type="rss" class="form-control" id="password" aria-describedby="emailHelp">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-between">
|
||||
<div class="col-4">
|
||||
<h4 class="text-left">Download Path</h4>
|
||||
</div>
|
||||
<div class="col-6">
|
||||
<input type="rss" class="form-control" id="downloadpath" aria-describedby="emailHelp">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
|
||||
</ui>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row justify-content-center">
|
||||
<div class="col-8">
|
||||
<h2>进阶配置</h2>
|
||||
<ui class="list-group list-group-flush gap-1 shadow p-3 mb-5 rounded-3">
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-between">
|
||||
<h4 class="text-center">字幕组 TAG</h4>
|
||||
<div class="btn-group" role="group" aria-label="Basic radio toggle button group">
|
||||
<input type="radio" class="btn-check" name="grouptag" id="grouptag1" autocomplete="off" checked>
|
||||
<label class="btn btn-primary" for="grouptag1">ON</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="grouptag" id="grouptag2" autocomplete="off">
|
||||
<label class="btn btn-primary" for="grouptag2">OFF</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-between">
|
||||
<h4 class="text-center">历史补全</h4>
|
||||
<div class="btn-group" role="group" aria-label="Basic radio toggle button group">
|
||||
<input type="radio" class="btn-check" name="btnradio" id="btnradio1" autocomplete="off" checked>
|
||||
<label class="btn btn-primary" for="btnradio1">ON</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btnradio" id="btnradio2" autocomplete="off">
|
||||
<label class="btn btn-primary" for="btnradio2">OFF</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
<li class="list-group-item">
|
||||
<div class="row">
|
||||
<div class="col">
|
||||
<div class="d-flex justify-content-between">
|
||||
<h4 class="text-center">坏种移除</h4>
|
||||
<div class="btn-group" role="group" aria-label="Basic radio toggle button group">
|
||||
<input type="radio" class="btn-check" name="btnradio" id="btnradio1" autocomplete="off" checked>
|
||||
<label class="btn btn-primary" for="btnradio1">ON</label>
|
||||
|
||||
<input type="radio" class="btn-check" name="btnradio" id="btnradio2" autocomplete="off">
|
||||
<label class="btn btn-primary" for="btnradio2">OFF</label>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</li>
|
||||
</ui>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.2.0-beta1/dist/js/bootstrap.bundle.min.js" integrity="sha384-pprn3073KE6tl6bjs2QrFaJGz5/SUsLqktiwsUTF55Jfv3qYSDhgCecCxMW52nD2" crossorigin="anonymous"></script>
|
||||
</body>
|
||||
</html>
|
||||
5
templates/index.js
Normal file
5
templates/index.js
Normal file
@@ -0,0 +1,5 @@
|
||||
function postConfig(){
|
||||
var httpRequest = new XMLHttpRequest();
|
||||
httpRequest.open("POST", "autobangumi", ture)
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user