diff --git a/.github/workflows/unittest.yml b/.github/workflows/unittest.yml index 202eb51d..f41e613a 100644 --- a/.github/workflows/unittest.yml +++ b/.github/workflows/unittest.yml @@ -26,6 +26,7 @@ jobs: run: | python -m pip install --upgrade pip if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install pytest - name: Test run: python -m unittest discover tests \ No newline at end of file diff --git a/module/conf/__init__.py b/module/conf/__init__.py index 9a155ab3..3c427e05 100644 --- a/module/conf/__init__.py +++ b/module/conf/__init__.py @@ -1,6 +1,5 @@ from .config import settings from .log import setup_logger, LOG_PATH -from .version import VERSION TMDB_API = "32b19d6a05b512190a056fa4e747cbbc" DATA_PATH = "data/data.json" diff --git a/module/conf/config.py b/module/conf/config.py index 9c4b1887..20b74813 100644 --- a/module/conf/config.py +++ b/module/conf/config.py @@ -2,13 +2,8 @@ import json import os from dataclasses import dataclass -from .const import DEFAULT_SETTINGS, ENV_TO_ATTR -from .version import VERSION -if VERSION == "DEV_VERSION": - CONFIG_PATH = "config/config_dev.json" -else: - CONFIG_PATH = "config/config.json" +from .const import DEFAULT_SETTINGS, ENV_TO_ATTR class ConfLoad(dict): @@ -20,7 +15,7 @@ class ConfLoad(dict): @dataclass -class Settings(): +class Settings: program: ConfLoad downloader: ConfLoad rss_parser: ConfLoad @@ -28,11 +23,14 @@ class Settings(): debug: ConfLoad proxy: ConfLoad notification: ConfLoad - def __init__(self): - self.load(CONFIG_PATH) - def load(self, path): - if os.path.isfile(path): + def __init__(self, path: str | None): + self.load(path) + + def load(self, path: str | None): + if isinstance(path, dict): + conf = DEFAULT_SETTINGS + elif os.path.isfile(path): with open(path, "r") as f: conf = json.load(f) else: @@ -40,7 +38,8 @@ class Settings(): for key, section in conf.items(): setattr(self, key, ConfLoad(section)) - def _val_from_env(self, env, attr): + @staticmethod + def _val_from_env(env, attr): val = os.environ[env] if isinstance(attr, tuple): conv_func = attr[1] @@ -58,6 +57,14 @@ class Settings(): return settings -settings = Settings() +if os.path.isfile("version.py"): + from .version import VERSION + if VERSION == "DEV_VERSION": + CONFIG_PATH = "config/config_dev.json" + else: + CONFIG_PATH = "config/config.json" + settings = Settings(CONFIG_PATH) +else: + settings = Settings(DEFAULT_SETTINGS) diff --git a/module/network/request_contents.py b/module/network/request_contents.py new file mode 100644 index 00000000..d436bd0d --- /dev/null +++ b/module/network/request_contents.py @@ -0,0 +1,41 @@ +from dataclasses import dataclass + +from .request_url import RequestURL +from module.conf import settings + +import re + + +@dataclass +class TorrentInfo: + name: str + torrent_link: str + + +class RequestContent: + def __init__(self): + self._req = RequestURL() + + # Mikanani RSS + def get_torrents(self, _url: str) -> [TorrentInfo]: + soup = self._req.get_content(_url) + torrent_titles = [item.title.string for item in soup.find_all("item")] + torrent_urls = [item.get("url") for item in soup.find_all("enclosure")] + torrents = [] + for _title, torrent_url in zip(torrent_titles, torrent_urls): + if re.search(settings.not_contain, _title) is None: + torrents.append(TorrentInfo(_title, torrent_url)) + return torrents + + def get_torrent(self, _url) -> TorrentInfo: + soup = self._req.get_content(_url) + item = soup.find("item") + enclosure = item.find("enclosure") + return TorrentInfo(item.title.string, enclosure["url"]) + + # API JSON + def get_json(self, _url) -> dict: + return self._req.get_content(_url, content="json") + + def close_session(self): + self._req.close() diff --git a/module/parser/analyser/raw_parser.py b/module/parser/analyser/raw_parser.py index a14f80e5..72fb7713 100644 --- a/module/parser/analyser/raw_parser.py +++ b/module/parser/analyser/raw_parser.py @@ -14,6 +14,8 @@ RESOLUTION_RE = re.compile(r"1080|720|2160|4K") SOURCE_RE = re.compile(r"B-Global|[Bb]aha|[Bb]ilibili|AT-X|Web") SUB_RE = re.compile(r"[简繁日字幕]|CH|BIG5|GB") +PREFIX_RE = re.compile(r"[^\w\s\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff-]") + CHINESE_NUMBER_MAP = { "一": 1, "二": 2, @@ -51,32 +53,25 @@ class RawParser: def pre_process(raw_name: str) -> str: return raw_name.replace("【", "[").replace("】", "]") - def preffix_process(self, raw: str, group: str) -> str: - raw_process = re.sub(r"[^\w\s\u4e00-\u9fff\u3040-\u309f\u30a0-\u30ff-]", "/", raw) + @staticmethod + def prefix_process(raw: str, group: str) -> str: + raw = re.sub(f".{group}.", "", raw) + raw_process = PREFIX_RE.sub("/", raw) arg_group = raw_process.split("/") - title_list = [] for arg in arg_group: - if re.search(group, arg): - pass - elif re.search(r"新番|月?番", arg) and len(arg) <= 5: - pass + if re.search(r"新番|月?番", arg) and len(arg) <= 5: + raw = re.sub(f".{arg}.", "", raw) elif re.search(r"港澳台地区", arg): - pass - elif arg == "": - pass - else: - title_list.append(arg) - if len(title_list) == 1: - return title_list[0] - return "/".join(arg_group) + raw = re.sub(f".{arg}.", "", raw) + return raw @staticmethod def season_process(season_info: str): name_season = season_info - if re.search(r"新番|月?番", season_info): - name_season = re.sub(".*新番.", "", season_info) - # 去除「新番」信息 - name_season = re.sub(r"^[^]】]*[]】]", "", name_season).strip() + # if re.search(r"新番|月?番", season_info): + # name_season = re.sub(".*新番.", "", season_info) + # # 去除「新番」信息 + # name_season = re.sub(r"^[^]】]*[]】]", "", name_season).strip() season_rule = r"S\d{1,2}|Season \d{1,2}|[第].[季期]" name_season = re.sub(r"[\[\]]", " ", name_season) seasons = re.findall(season_rule, name_season) @@ -157,7 +152,7 @@ class RawParser: season_info, episode_info, other = list(map( lambda x: x.strip(), match_obj.groups() )) - process_raw = self.preffix_process(season_info, group) + process_raw = self.prefix_process(season_info, group) # 处理 前缀 raw_name, season_raw, season = self.season_process(process_raw) # 处理 第n季 @@ -184,3 +179,15 @@ class RawParser: sub, dpi, source, group = ret return Episode(name_en, name_zh, name_jp, season, sr, episode, sub, group, dpi, source) + +if __name__ == '__main__': + test_list = [ + "[Lilith-Raws] 关于我在无意间被隔壁的天使变成废柴这件事 / Otonari no Tenshi-sama - 09 [Baha][WEB-DL][1080p][AVC AAC][CHT][MP4]", + "【幻樱字幕组】【4月新番】【古见同学有交流障碍症 第二季 Komi-san wa, Komyushou Desu. S02】【22】【GB_MP4】【1920X1080】", + "[百冬练习组&LoliHouse] BanG Dream! 少女乐团派对!☆PICO FEVER! / Garupa Pico: Fever! - 26 [WebRip 1080p HEVC-10bit AAC][简繁内封字幕][END]" + ] + parser = RawParser() + for l in test_list: + ep = parser.analyse(l) + print(f"en: {ep.title_en}, zh: {ep.title_zh}, jp: {ep.title_jp}, group: {ep.group}") + diff --git a/module/run.sh b/module/run.sh deleted file mode 100755 index 39b6916d..00000000 --- a/module/run.sh +++ /dev/null @@ -1,9 +0,0 @@ -#!/bin/bash - -sh ./getWebUI.sh - -sh ./setID.sh - -umask ${UMASK} -exec su-exec auto_bangumi:auto_bangumi python3 app.py & -exec su-exec auto_bangumi:auto_bangumi python3 api.py diff --git a/run.sh b/run.sh new file mode 100755 index 00000000..d38b7ada --- /dev/null +++ b/run.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +# Check old version +if [ ]; then + mv /config/bangumi.json /data/bangumi.json +fi + + + +umask ${UMASK} +exec su-exec auto_bangumi:auto_bangumi python3 main.py & +exec su-exec auto_bangumi:auto_bangumi python3 api.py diff --git a/test/test_raw_parser.py b/test/test_raw_parser.py index 438ea106..9c3c75d7 100644 --- a/test/test_raw_parser.py +++ b/test/test_raw_parser.py @@ -1,7 +1,36 @@ -import unittest from random import randrange -from module.parser.analyser import RawParser +import unittest + +from module.parser.analyser.raw_parser import RawParser + + +def test_raw_parser(): + parser = RawParser() + content = "【幻樱字幕组】【4月新番】【古见同学有交流障碍症 第二季 Komi-san wa, Komyushou Desu. S02】【22】【GB_MP4】【1920X1080】" + info = parser.analyse(content) + assert info.title_en == "Komi-san wa, Komyushou Desu." + assert info.resolution == "1920X1080" + assert info.episode == 22 + assert info.season == 2 + + content = "[百冬练习组&LoliHouse] BanG Dream! 少女乐团派对!☆PICO FEVER! / Garupa Pico: Fever! - 26 [WebRip 1080p HEVC-10bit AAC][简繁内封字幕][END] [101.69 MB]" + info = parser.analyse(content) + assert info.group == "百冬练习组&LoliHouse" + assert info.title_zh == "BanG Dream! 少女乐团派对!☆PICO FEVER!" + assert info.resolution == "1080p" + assert info.episode == 26 + assert info.season == 1 + + content = "【喵萌奶茶屋】★04月新番★[夏日重现/Summer Time Rendering][11][1080p][繁日双语][招募翻译]" + info = parser.analyse(content) + assert info.group == "喵萌奶茶屋" + assert info.title_en == "Summer Time Rendering" + assert info.resolution == "1080p" + assert info.episode == 11 + assert info.season == 1 + + class TestRawParser(unittest.TestCase): @@ -25,7 +54,7 @@ class TestRawParser(unittest.TestCase): self.assertEqual(info.episode, 26) self.assertEqual(info.season, 1) - content = "【喵萌奶茶屋】★04月新番★[夏日重现/Summer Time Rendering][11][1080p][繁日双语][招募翻译] [539.4 MB]" + content = "【喵萌奶茶屋】★04月新番★[夏日重现/Summer Time Rendering][11][1080p][繁日双语][招募翻译]" info = parser.analyse(content) self.assertEqual(info.group, "喵萌奶茶屋") self.assertEqual(info.title_en, "Summer Time Rendering") @@ -33,7 +62,7 @@ class TestRawParser(unittest.TestCase): self.assertEqual(info.episode, 11) self.assertEqual(info.season, 1) - content = "【喵萌奶茶屋】★04月新番★夏日重现/Summer Time Rendering[11][1080p][繁日双语][招募翻译] [539.4 MB]" + content = "【喵萌奶茶屋】★04月新番★夏日重现/Summer Time Rendering[11][1080p][繁日双语][招募翻译]" info = parser.analyse(content) self.assertEqual(info.title_en, "Summer Time Rendering")