Skip to content

Commit

Permalink
0.2.0-pre
Browse files Browse the repository at this point in the history
  • Loading branch information
LeiShi1313 committed Nov 18, 2021
1 parent f9dbb07 commit e98f647
Show file tree
Hide file tree
Showing 16 changed files with 505 additions and 182 deletions.
12 changes: 4 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ pip install Differential

# 如何使用差速器

差速器支持未经过重大修改的NexusPHP站点以及部分支持[easy-upload](https://github.com/techmovie/easy-upload)支持的站点。
差速器支持未经过重大修改的NexusPHP/Gazelle/Unit3D站点以及部分支持[easy-upload](https://github.com/techmovie/easy-upload)[auto_feed_js](https://github.com/tomorrow505/auto_feed_js)支持的站点。
在使用前,请先使用`dft -h`查看本工具支持的站点/现有的插件。

请先参考`config.ini.example`,在`Default`块填上各个站点/插件通用的参数,比如图床相关的几个参数,然后在各站点/插件名字对应的块填上各自特有的参数,比如截图张数等等。
Expand All @@ -54,21 +54,17 @@ dft [插件名字] -f [种子文件夹] -u [豆瓣URL]
- `log`: log文件的路径
- `folder`: 种子文件或文件夹的路径
- `url`: 影片的豆瓣链接,事实上,所有PTGen支持的链接这里都支持
- `upload_url`: 发种页面的地址
- `make_torrent`: 是否制种,默认关闭
- `geenrate_nfo`: 是否利用mediainfo生成nfo文件,默认关闭
- `screenshot_count`: 截图生成的张数,默认为0,即不生成截图
- `image_hosting`: 图床的名称,现在支持ptpimg,chevereto,imgurl和SM.MS
- `image_hosting_url`: 如果是自建的图床,提供图床链接
- `ptgen_url`: PTGen的地址,默认是我自建的PTGen,可能会不稳定
- `announce_url`: 制种时的announce地址

## NexusPHP

相比基础参数,`NexusPHP`插件特有的参数有:

- `upload_url`: 发种页面的地址
- `encoder_log`: 压制log的地址,如果提供的话会在介绍的mediainfo部分附上压制log
- `easy_upload`: 默认开启,关闭的话会直接在命令行输出主/副标题,描述和mediainfo
- `easy_upload`: 默认关闭,开启的话会利用[easy-upload](https://github.com/techmovie/easy-upload)自动填充发种页面表单
- `auto_feed`: 默认关闭,开启的话会利用[auto_feed_js](https://github.com/tomorrow505/auto_feed_js)自动填充发种页面表单
- `trim_description`: 默认关闭,开启的话会省略掉上传链接的描述部分,以避免链接过长浏览器无法打开的问题

## 其他插件
Expand Down
6 changes: 3 additions & 3 deletions differential/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,11 @@ def main():
logger.trace(config)
REGISTERED_PLUGINS[plugin](**config).upload()
except TypeError as e:
m = re.search(r'missing \d+ required positional arguments: (.*?)$', str(e))
m = re.search(r'missing \d+ required positional argument[s]{0,1}: (.*?)$', str(e))
if m:
logger.error("缺少插件必需的参数,请检查输入的参数: {}".format(m.groups()[0]))
else:
logger.error(e)
return
raise e
else:
PARSER.print_help()

Expand Down
143 changes: 85 additions & 58 deletions differential/plugins/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
from pathlib import Path
from decimal import Decimal
from typing import Optional
from urllib.parse import quote
from abc import ABC, ABCMeta, abstractmethod

import requests
Expand All @@ -16,10 +17,15 @@
from loguru import logger
from pymediainfo import MediaInfo

from differential.torrent import TorrnetBase
from differential.version import version
from differential.constants import ImageHosting
from differential.utils.browser import open_link
from differential.utils.mediainfo import get_track_attr
from differential.utils.torrent import make_torrent
from differential.utils.parse import parse_encoder_log
from differential.utils.binary import ffprobe, execute
from differential.utils.uploader import EasyUpload, AutoFeed
from differential.utils.mediainfo import get_track_attr, get_full_mediainfo, get_resolution, get_duration
from differential.utils.image import byr_upload, ptpimg_upload, smms_upload, imgurl_upload, chevereto_api_upload, chevereto_username_upload

Expand Down Expand Up @@ -62,7 +68,7 @@ def add_parser(mcs, parser: argparse.ArgumentParser):
raise NotImplementedError()


class Base(ABC, metaclass=PluginRegister):
class Base(ABC, TorrnetBase, metaclass=PluginRegister):

@classmethod
@abstractmethod
Expand All @@ -71,6 +77,7 @@ def add_parser(cls, parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
parser.add_argument('-l', '--log', type=str, help='log文件的路径', default=argparse.SUPPRESS)
parser.add_argument('-f', '--folder', type=str, help='种子文件夹的路径', default=argparse.SUPPRESS)
parser.add_argument('-u', '--url', type=str, help='豆瓣链接', default=argparse.SUPPRESS)
parser.add_argument("-uu",'--upload-url', type=str, help="PT站点上传的路径,一般为https://xxxxx.com/upload.php", default=argparse.SUPPRESS)
parser.add_argument('-t', '--make-torrent', action="store_true", help="是否制种,默认否", default=argparse.SUPPRESS)
parser.add_argument('-n', '--generate-nfo', action="store_true", help="是否用MediaInfo生成NFO文件,默认否",
default=argparse.SUPPRESS)
Expand All @@ -87,17 +94,24 @@ def add_parser(cls, parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
parser.add_argument('--chevereto-password', type=str, help="如果自建Chevereto的API未开放,请设置username和password", default=argparse.SUPPRESS)
parser.add_argument('--imgurl-api-key', type=str, help="Imgurl的API Key", default=argparse.SUPPRESS)
parser.add_argument('--smms-api-key', type=str, help="SM.MS的API Key", default=argparse.SUPPRESS)
parser.add_argument('--byr-authorization', type=str, help="BYR的Authorization头,可登录后访问任意页面F12查看,形如Basic bGVpxxxxxxxxxxx2whQA==", default=argparse.SUPPRESS)
parser.add_argument('--byr-authorization', type=str, help="BYR的Authorization头,可登录后访问任意页面F12查看,形如Basic xxxxxxxxxxxxxxxx==", default=argparse.SUPPRESS)
parser.add_argument('--byr-alternative-url', type=str, help="BYR反代地址(如有),可为空", default=argparse.SUPPRESS)
parser.add_argument('--ptgen-url', type=str, help="自定义PTGEN的地址", default=argparse.SUPPRESS)
parser.add_argument('--ptgen-retry', type=int, help="PTGEN重试次数,默认为3次", default=argparse.SUPPRESS)
parser.add_argument('--announce-url', type=str, help="制种时announce地址", default=argparse.SUPPRESS)

parser.add_argument("--encoder-log", type=str, help="压制log的路径", default=argparse.SUPPRESS)
upload_option_group = parser.add_mutually_exclusive_group()
upload_option_group.add_argument("--easy-upload", action="store_true", help="使用树大Easy Upload插件自动填充", dest="easy_upload", default=argparse.SUPPRESS)
upload_option_group.add_argument("--auto-feed", action="store_true", help="使用明日大Auto Feed插件自动填充", dest="auto_feed",default=argparse.SUPPRESS)
parser.add_argument("--trim-description", action="store_true", help="是否在生成的链接中省略种子描述,该选项主要是为了解决浏览器限制URL长度的问题,默认关闭", default=argparse.SUPPRESS)
return parser

def __init__(
self,
folder: str,
url: str,
upload_url: str,
screenshot_count: int = 0,
optimize_screenshot: bool = True,
image_hosting: ImageHosting = ImageHosting.PTPIMG,
Expand All @@ -116,10 +130,15 @@ def __init__(
ptgen_retry: int = 3,
generate_nfo: bool = False,
make_torrent: bool = False,
easy_upload: bool = False,
auto_feed: bool = False,
trim_description: bool = False,
encoder_log: str = "",
**kwargs,
):
self.folder = Path(folder)
self.url = url
self.upload_url = upload_url
self.screenshot_count = screenshot_count
self.optimize_screenshot = optimize_screenshot
self.image_hosting = image_hosting
Expand All @@ -138,6 +157,10 @@ def __init__(
self.ptgen_retry = ptgen_retry
self.generate_nfo = generate_nfo
self.make_torrent = make_torrent
self.easy_upload = easy_upload
self.auto_feed = auto_feed
self.trim_description = trim_description
self.encoder_log = encoder_log

self._main_file: Optional[Path] = None
self._ptgen: dict = {}
Expand Down Expand Up @@ -211,7 +234,7 @@ def _get_ptgen(self) -> dict:
logger.info(f"获取PTGen成功 {req.json().get('chinese_title', '')}")
return req.json()

def _get_mediainfo(self) -> MediaInfo:
def _find_mediainfo(self) -> MediaInfo:
# Always find the biggest file in the folder
logger.info(f"正在获取Mediainfo: {self.folder}")
if self.folder.is_file():
Expand Down Expand Up @@ -240,10 +263,10 @@ def _generate_nfo(self):
logger.info("正在生成nfo文件...")
if self.folder.is_file():
with open(f"{self.folder.resolve().parent.joinpath(self.folder.stem)}.nfo", 'wb') as f:
f.write(self.mediaInfo.encode())
f.write(self.media_info.encode())
elif self.folder.is_dir():
with open(self.folder.joinpath(f"{self.folder.name}.nfo"), 'wb') as f:
f.write(self.mediaInfo.encode())
f.write(self.media_info.encode())

def _make_screenshots(self) -> Optional[str]:
resolution = get_resolution(self._main_file, self._mediainfo)
Expand Down Expand Up @@ -298,13 +321,17 @@ def _prepare(self):
while self._ptgen.get('failed') and ptgen_retry > 0:
self._ptgen = self._get_ptgen()
ptgen_retry -= 1
self._mediainfo = self._get_mediainfo()
self._mediainfo = self._find_mediainfo()
if self.generate_nfo:
self._generate_nfo()
self._screenshots = self._get_screenshots()
if self.make_torrent:
make_torrent(self.folder, [self.announce_url])

@property
def parsed_encoder_log(self):
return parse_encoder_log(self.encoder_log)

@property
def title(self):
# TODO: Either use file name or generate from mediainfo and ptgen
Expand Down Expand Up @@ -336,38 +363,38 @@ def subtitle(self):
return subtitle

@property
def mediaInfo(self):
def media_info(self):
return get_full_mediainfo(self._mediainfo)

@property
def mediaInfos(self):
def media_infos(self):
return []

@property
def description(self):
return "{}\n\n[quote]{}{}[/quote]\n\n{}".format(
self._ptgen.get("format"),
self.mediaInfo,
self.media_info,
"\n\n" + self.parsed_encoder_log if self.parsed_encoder_log else "",
"\n".join([f"[img]{url}[/img]" for url in self._screenshots]),
)

@property
def originalDescription(self):
def original_description(self):
return ''

@property
def doubanUrl(self):
def douban_url(self):
if self._ptgen.get("site") == "douban":
return f"https://movie.douban.com/subject/{self._ptgen.get('sid')}"
return ""

@property
def doubanInfo(self):
def douban_info(self):
return ''

@property
def imdbUrl(self):
def imdb_url(self):
return self._ptgen.get("imdb_link", "")

@property
Expand Down Expand Up @@ -399,7 +426,7 @@ def category(self):
return imdb_type

@property
def videoType(self):
def video_type(self):
if "webdl" in self.folder.name.lower() or "web-dl" in self.folder.name.lower():
return "web"
elif "remux" in self.folder.name.lower():
Expand Down Expand Up @@ -430,7 +457,7 @@ def source(self):
return ""

@property
def videoCodec(self):
def video_codec(self):
for track in self._mediainfo.tracks:
if track.track_type == "Video":
if track.encoded_library_name:
Expand All @@ -451,7 +478,7 @@ def videoCodec(self):
return ""

@property
def audioCodec(self):
def audio_codec(self):
codec_map = {
"AAC": "aac",
"Dolby Digital Plus": "dd+",
Expand Down Expand Up @@ -509,12 +536,12 @@ def area(self):
"美国": "US",
"日本": "JP",
"韩国": "KR",
"印度": "IND",
"法国": "EU",
"意大利": "EU",
"德国": "EU",
"西班牙": "EU",
"葡萄牙": "EU",
"印度": "IN",
"法国": "FR",
"意大利": "IT",
"德国": "GE",
"西班牙": "ES",
"葡萄牙": "PT",
}
regions = self._ptgen.get("region", [])
for area in area_map.keys():
Expand All @@ -523,15 +550,15 @@ def area(self):
return ""

@property
def movieName(self):
def movie_name(self):
if self._ptgen.get("site") == "imdb":
return self._ptgen.get("name", "")
if self._ptgen.get("site") == "douban":
return self._ptgen.get("aka", [""])[0]
return ""

@property
def movieAkaName(self):
def movie_aka_name(self):
return ""

@property
Expand All @@ -554,46 +581,46 @@ def tags(self):
return tags

@property
def otherTags(self):
def other_tags(self):
return []

@property
def comparisons(self):
return []

# Auto feed
@property
def torrentInfo(self):
return {
"title": self.title,
"subtitle": self.subtitle,
"description": self.description,
"originalDescription": self.originalDescription,
"doubanUrl": self.doubanUrl,
"doubanInfo": self.doubanInfo,
"imdbUrl": self.imdbUrl,
"mediaInfo": self.mediaInfo,
"mediaInfos": self.mediaInfos,
"screenshots": self.screenshots,
"poster": self.poster,
"year": self.year,
"category": self.category,
"videoType": self.videoType,
"format": self.format,
"source": self.source,
"videoCodec": self.videoCodec,
"audioCodec": self.audioCodec,
"resolution": self.resolution,
"area": self.area,
"movieAkaName": self.movieAkaName,
"movieName": self.movieName,
"size": self.size,
"tags": self.tags,
"otherTags": self.otherTags,
"comparisons": self.comparisons,
"isForbidden": False,
"sourceSiteType": "NexusPHP",
}
def uploader_auto_feed(self):
return AutoFeed(plugin=self)

@abstractmethod
def upload(self):
raise NotImplementedError()
self._prepare()
if self.easy_upload:
easy_upload = EasyUpload(plugin=self)
torrent_info = easy_upload.torrent_info
if self.trim_description:
# 直接打印简介部分来绕过浏览器的链接长度限制
torrent_info["description"] = ""
logger.trace(f"torrent_info: {torrent_info}")
link = f"{self.upload_url}#torrentInfo={quote(json.dumps(torrent_info))}"
logger.trace(f"已生成自动上传链接:{link}")
if self.trim_description:
logger.info(f"种子描述:\n{self.description}")
open_link(link)
elif self.auto_feed:
auto_feed = AutoFeed(plugin=self)
link = f"{self.upload_url}{quote(auto_feed.info, safe='#:/=@')}"
if self.trim_description:
logger.info(f"种子描述:\n{self.description}")
logger.trace(f"已生成自动上传链接:{link}")
open_link(link)
else:
logger.info(
"\n"
f"标题: {self.title}\n"
f"副标题: {self.subtitle}\n"
f"豆瓣: {self.douban_url}\n"
f"IMDB: {self.imdb_url}\n"
f"视频编码: {self.video_codec} 音频编码: {self.audio_codec} 分辨率: {self.resolution}\n"
f"描述:\n{self.description}"
)
4 changes: 2 additions & 2 deletions differential/plugins/chdbits.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,5 @@ def get_help(cls):
def add_parser(cls, parser: argparse.ArgumentParser) -> argparse.ArgumentParser:
return super().add_parser(parser)

def __init__(self, folder: str, url: str, **kwargs):
super().__init__(folder, url, upload_url="https://chdbits.co/upload.php", **kwargs)
def __init__(self, **kwargs):
super().__init__(upload_url="https://chdbits.co/upload.php", **kwargs)
Loading

0 comments on commit e98f647

Please sign in to comment.