diff --git a/AutoBangumi2.0/Dockerfile b/AutoBangumi2.0/Dockerfile new file mode 100644 index 00000000..100900e6 --- /dev/null +++ b/AutoBangumi2.0/Dockerfile @@ -0,0 +1,11 @@ +# syntax=docker/dockerfile:1 +FROM python:3.10-slim-buster +WORKDIR /auto-bangumi +COPY requirements.txt . +RUN pip3 install -r requirements.txt + +COPY ./app /app +COPY ./config /config + + +CMD [ "python3", "/app/docker_main.py"] \ No newline at end of file diff --git a/Docker/auto_set_rule.py b/AutoBangumi2.0/app/auto_set_rule.py similarity index 53% rename from Docker/auto_set_rule.py rename to AutoBangumi2.0/app/auto_set_rule.py index 78be1eb0..8cba2e00 100644 --- a/Docker/auto_set_rule.py +++ b/AutoBangumi2.0/app/auto_set_rule.py @@ -4,23 +4,19 @@ import os class SetRule: - def __init__(self): - with open("config.json") as f: - info = json.load(f) - - with open("bangumi.json") as f: - self.bangumi_info = json.load(f) - self.rss_link = info["rss_link"] - self.host_ip = "192.168.31.10:8181" - self.user_name = "admin" - self.password = "adminadmin" - - def set_rule(self, bangumi_name, season): - qb = qbittorrentapi.Client(host=self.host_ip, username=self.user_name, password=self.password) + def __init__(self, config, info): + self.bangumi_info = info + self.rss_link = config["rss_link"] + self.host_ip = config["host_ip"] + self.user_name = config["user_name"] + self.password = config["password"] + self.qb = qbittorrentapi.Client(host=self.host_ip, username=self.user_name, password=self.password) try: - qb.auth_log_in() + self.qb.auth_log_in() except qbittorrentapi.LoginFailed as e: print(e) + + def set_rule(self, bangumi_name, season): rule = { 'enable': False, 'mustContain': bangumi_name, @@ -29,20 +25,16 @@ class SetRule: 'episodeFilter': '', 'smartFilter': False, 'previouslyMatchedEpisodes': [], - 'affectedFeeds': [rss_link], + 'affectedFeeds': [self.rss_link], 'ignoreDays': 0, 'lastMatch': '', 'addPaused': False, 'assignedCategory': 'Bangumi', 'savePath': os.path.join('/downloads', bangumi_name, season) } - qb.rss_set_rule(rule_name=bangumi_name, rule_def=rule) + self.qb.rss_set_rule(rule_name=bangumi_name, rule_def=rule) - def set_rule_main(self): + def run(self): for info in self.bangumi_info: self.set_rule(info["title"], info["season"]) - -if __name__ == "__main__": - rule = SetRule() - rule.set_rule_main() \ No newline at end of file diff --git a/AutoBangumi2.0/app/collect_bangumi_info.py b/AutoBangumi2.0/app/collect_bangumi_info.py new file mode 100644 index 00000000..f9c8fb52 --- /dev/null +++ b/AutoBangumi2.0/app/collect_bangumi_info.py @@ -0,0 +1,66 @@ +# -*- coding: UTF-8 -*- +import requests +from bs4 import BeautifulSoup +import json +import re + + +class CollectRSS: + def __init__(self, config, info): + self.info = info + self.config = config + self.bangumi_title = [] + + def collect_info(self): + episode_rules = [r'(.*)\[(\d{1,3}|\d{1,3}\.\d{1,2})(?:v\d{1,2})?(?:END)?\](.*)', + r'(.*)\[E(\d{1,3}|\d{1,3}\.\d{1,2})(?:v\d{1,2})?(?:END)?\](.*)', + r'(.*)\[第(\d*\.*\d*)话(?:END)?\](.*)', + r'(.*)\[第(\d*\.*\d*)話(?:END)?\](.*)', + r'(.*)第(\d*\.*\d*)话(?:END)?(.*)', + r'(.*)第(\d*\.*\d*)話(?:END)?(.*)', + r'(.*)- (\d{1,3}|\d{1,3}\.\d{1,2})(?:v\d{1,2})?(?:END)? (.*)'] + url = self.config["rss_link"] + rss = requests.get(url, 'utf-8') + soup = BeautifulSoup(rss.text, 'xml') + item = soup.find_all('item') + bangumi_title = [] + for a in item: + name = str(a.find('title')) + name = re.sub('|', '', name) + parrten = r'\[|\]|\u3010|\u3011|\★|\*' + for i in range(2): + n = re.split(parrten, name) + name = re.sub(f'\[{n[1]}\]|【{n[1]}】|★{n[1]}★', '', name) + for rule in episode_rules: + matchObj = re.match(rule, name, re.I) + if matchObj is not None: + new_name = re.sub(r'\[|\]', '', f'{matchObj.group(1)}') + new_name = re.split(r'/', new_name)[-1].strip() + if new_name not in self.bangumi_title: + self.bangumi_title.append(new_name) + + def write_info(self): + bangumi_info = self.info + had_data = [] + for data in bangumi_info: + had_data.append(data["title"]) + for title in self.bangumi_title: + a = re.match(r'(.*)(S.\d)', title, re.I) + if a is not None: + title = a.group(1).strip() + season = a.group(2).strip() + else: + season = '' + if title not in had_data: + bangumi_info.append({ + "title": title, + "season": season + }) + print(f"add {title} {season}") + # 写入数据 + with open("../config/bangumi.json", 'w', encoding='utf8') as f: + json.dump(bangumi_info, f, indent=4, separators=(',', ': '), ensure_ascii=False) + + def run(self): + self.collect_info() + self.write_info() \ No newline at end of file diff --git a/AutoBangumi2.0/app/docker_main.py b/AutoBangumi2.0/app/docker_main.py new file mode 100644 index 00000000..d5480e4c --- /dev/null +++ b/AutoBangumi2.0/app/docker_main.py @@ -0,0 +1,19 @@ +import os +import time +from collect_bangumi_info import CollectRSS +from auto_set_rule import SetRule +from rename_qb import QbittorrentRename +import json + +#sleep_time = os.environ["TIME"] + +if __name__ == "__main__": + while True: + with open("../config/config.json") as f: + config = json.load(f) + with open("../config/bangumi.json") as f: + info = json.load(f) + CollectRSS(config, info).run() + SetRule(config, info).run() + QbittorrentRename(config).run() + time.sleep(1800) diff --git a/AutoBangumi2.0/app/rename_qb.py b/AutoBangumi2.0/app/rename_qb.py new file mode 100644 index 00000000..41ab7439 --- /dev/null +++ b/AutoBangumi2.0/app/rename_qb.py @@ -0,0 +1,94 @@ +import re +import io +import sys +import qbittorrentapi +from os import environ +import time + + +class QbittorrentRename: + def __init__(self, config): + self.qbt_client = qbittorrentapi.Client(host=config['host_ip'], username=config['user_name'], password=config['password']) + try: + self.qbt_client.auth_log_in() + except qbittorrentapi.LoginFailed as e: + print(e) + self.recent_info = self.qbt_client.torrents_info(status_filter='completed') + self.hash = None + self.name = None + self.new_name = None + self.path_name = None + self.count = 0 + self.rename_count = 0 + self.torrent_count = len(self.recent_info) + self.method = config['method'] + self.rules = [r'(.*)\[(\d{1,3}|\d{1,3}\.\d{1,2})(?:v\d{1,2})?(?:END)?\](.*)', + r'(.*)\[E(\d{1,3}|\d{1,3}\.\d{1,2})(?:v\d{1,2})?(?:END)?\](.*)', + r'(.*)\[第(\d*\.*\d*)话(?:END)?\](.*)', + r'(.*)\[第(\d*\.*\d*)話(?:END)?\](.*)', + r'(.*)第(\d*\.*\d*)话(?:END)?(.*)', + r'(.*)第(\d*\.*\d*)話(?:END)?(.*)', + r'(.*)- (\d{1,3}|\d{1,3}\.\d{1,2})(?:v\d{1,2})?(?:END)? (.*)'] + + def rename_normal(self, idx): + self.name = self.recent_info[idx].name + self.hash = self.recent_info[idx].hash + self.path_name = self.recent_info[idx].content_path.split("/")[-1] + file_name = self.name + for rule in self.rules: + matchObj = re.match(rule, file_name, re.I) + if matchObj is not None: + self.new_name = f'{matchObj.group(1).strip()} E{matchObj.group(2)}{matchObj.group(3)}' + + def rename_pn(self, idx): + self.name = self.recent_info[idx].name + self.hash = self.recent_info[idx].hash + self.path_name = self.recent_info[idx].content_path.split("/")[-1] + n = re.split(r'\[|\]', self.name) + file_name = self.name.replace(f'[{n[1]}]', '') + for rule in self.rules: + matchObj = re.match(rule, file_name, re.I) + if matchObj is not None: + self.new_name = re.sub(r'\[|\]', '', f'{matchObj.group(1).strip()} E{matchObj.group(2)}{n[-1]}') + + def rename(self): + if self.path_name != self.new_name: + self.qbt_client.torrents_rename_file(torrent_hash=self.hash, old_path=self.name, new_path=self.new_name) + print(f'{self.name} >> {self.new_name}') + self.count += 1 + else: + return + + def clear_info(self): + self.name = None + self.hash = None + self.new_name = None + + def print_result(self): + sys.stdout.write(f"[{time.strftime('%X')}] 已完成对{self.torrent_count}个文件的检查" + '\n') + sys.stdout.write(f"[{time.strftime('%X')}] 已对其中{self.count}个文件进行重命名" + '\n') + sys.stdout.write(f"[{time.strftime('%X')}] 完成" + '\n') + sys.stdout.flush() + + def run(self): + if self.method not in ['pn', 'normal']: + print('error method') + elif self.method == 'normal': + for i in range(0, self.torrent_count + 1): + try: + self.rename_normal(i) + self.rename() + self.clear_info() + except: + self.print_result() + elif self.method == 'pn': + for i in range(0, self.torrent_count + 1): + try: + self.rename_pn(i) + self.rename() + self.clear_info() + except: + self.print_result() + + + diff --git a/Docker/data/bangumi.json b/AutoBangumi2.0/config/bangumi.json similarity index 100% rename from Docker/data/bangumi.json rename to AutoBangumi2.0/config/bangumi.json diff --git a/Docker/config/config.json b/AutoBangumi2.0/config/config.json similarity index 92% rename from Docker/config/config.json rename to AutoBangumi2.0/config/config.json index c75b5345..31c36bf7 100644 --- a/Docker/config/config.json +++ b/AutoBangumi2.0/config/config.json @@ -2,6 +2,7 @@ "host_ip": "192.168.31.10:8181", "user_name": "admin", "password": "adminadmin", + "method": "pn", "rss_link": "https://mikanani.me/RSS/MyBangumi?token=Td8ceWZZv3s2OZm5ji9RoMer8vk5VS3xzC1Hmg8A26E%3d", "download_path": "/downloads/Bangumi" } \ No newline at end of file diff --git a/AutoBangumi2.0/config/rename_rule.txt b/AutoBangumi2.0/config/rename_rule.txt new file mode 100644 index 00000000..e69de29b diff --git a/AutoBangumi2.0/requirements.txt b/AutoBangumi2.0/requirements.txt new file mode 100644 index 00000000..dd08288c --- /dev/null +++ b/AutoBangumi2.0/requirements.txt @@ -0,0 +1,5 @@ +qbittorrent-api==2022.4.30 +requests-html==0.10.0 +requests-oauthlib==1.3.1 +requests==2.27.1 + diff --git a/Docker/collect_bangumi_info.py b/Docker/collect_bangumi_info.py deleted file mode 100644 index e79fa8c0..00000000 --- a/Docker/collect_bangumi_info.py +++ /dev/null @@ -1,61 +0,0 @@ -# -*- coding: UTF-8 -*- -import requests -from bs4 import BeautifulSoup -import json -import re - - -def collect_info(): - episode_rules = [r'(.*)\[(\d{1,3}|\d{1,3}\.\d{1,2})(?:v\d{1,2})?(?:END)?\](.*)', - r'(.*)\[E(\d{1,3}|\d{1,3}\.\d{1,2})(?:v\d{1,2})?(?:END)?\](.*)', - r'(.*)\[第(\d*\.*\d*)话(?:END)?\](.*)', - r'(.*)\[第(\d*\.*\d*)話(?:END)?\](.*)', - r'(.*)第(\d*\.*\d*)话(?:END)?(.*)', - r'(.*)第(\d*\.*\d*)話(?:END)?(.*)', - r'(.*)- (\d{1,3}|\d{1,3}\.\d{1,2})(?:v\d{1,2})?(?:END)? (.*)'] - with open('./config/config.json') as f: - config = json.load(f) - url = config["rss_link"] - rss = requests.get(url, 'utf-8') - soup = BeautifulSoup(rss.text, 'xml') - item = soup.find_all('item') - bangumi_title = [] - for a in item: - name = str(a.find('title')) - name = re.sub('|', '', name) - parrten = r'\[|\]|\u3010|\u3011|\★|\*' - symbol = [['[', ']'], ['【', '】'], ['★', '★']] - for i in range(2): - n = re.split(parrten, name) - name = re.sub(f'\[{n[1]}\]|【{n[1]}】|★{n[1]}★', '', name) - for rule in episode_rules: - matchObj = re.match(rule, name, re.I) - if matchObj is not None: - new_name = re.sub(r'\[|\]', '', f'{matchObj.group(1)}') - new_name = re.split(r'/', new_name)[-1].strip() - if new_name not in bangumi_title: - bangumi_title.append(new_name) - - with open("./data/bangumi.json", encoding='utf-8') as f: - bangumi_info = json.load(f) - had_data = [] - for data in bangumi_info: - had_data.append(data["title"]) - - season_rules = r'(.*)(S.\d)' - for title in bangumi_title: - a = re.match(season_rules, title, re.I) - if a is not None: - title = a.group(1).strip() - season = a.group(2).strip() - else: - season = '' - if title not in had_data: - bangumi_info.append({ - "title": title, - "season": season - }) - print(f"add {title} {season}") - # 写入数据 - with open("./data/bangumi.json", 'w', encoding='utf8') as f: - json.dump(bangumi_info, f, indent=4, separators=(',', ': '), ensure_ascii=False) \ No newline at end of file diff --git a/Docker/docker_main.py b/Docker/docker_main.py deleted file mode 100644 index b6d85859..00000000 --- a/Docker/docker_main.py +++ /dev/null @@ -1,15 +0,0 @@ -import os -import time -from collect_bangumi_info import collect_info -from rename_qb import rename_main -from auto_set_rule import SetRule - -sleep_time = os.environ["TIME"] - -if __name__ == "__main__": - while True: - collect_info() - rename_main() - rule = SetRule() - rule.set_rule_main() - time.sleep(float(sleep_time))