mirror of
https://github.com/jxxghp/MoviePilot.git
synced 2026-03-20 03:57:30 +08:00
210 lines
6.8 KiB
Python
210 lines
6.8 KiB
Python
from typing import Tuple, List, Optional
|
|
|
|
from app.core.config import settings
|
|
from app.db.systemconfig_oper import SystemConfigOper
|
|
from app.log import logger
|
|
from app.schemas import MediaType
|
|
from app.utils.http import RequestUtils, AsyncRequestUtils
|
|
from app.utils.string import StringUtils
|
|
|
|
|
|
class YemaSpider:
|
|
"""
|
|
YemaPT API
|
|
"""
|
|
_indexerid = None
|
|
_domain = None
|
|
_name = ""
|
|
_proxy = None
|
|
_cookie = None
|
|
_ua = None
|
|
_size = 40
|
|
_searchurl = "%sapi/torrent/fetchOpenTorrentList"
|
|
_downloadurl = "%sapi/torrent/download?id=%s"
|
|
_pageurl = "%s#/torrent/detail/%s/"
|
|
_timeout = 15
|
|
|
|
# 分类
|
|
_movie_category = [4]
|
|
_tv_category = [5, 13, 14, 17, 15, 6, 16]
|
|
|
|
# 标签 https://wiki.yemapt.org/developer/constants
|
|
_labels = {
|
|
"1": "禁转",
|
|
"2": "首发",
|
|
"3": "官方",
|
|
"4": "自制",
|
|
"5": "国语",
|
|
"6": "中字",
|
|
"7": "粤语",
|
|
"8": "英字",
|
|
"9": "HDR10",
|
|
"10": "杜比视界",
|
|
"11": "分集",
|
|
"12": "完结",
|
|
}
|
|
|
|
def __init__(self, indexer: dict):
|
|
self.systemconfig = SystemConfigOper()
|
|
if indexer:
|
|
self._indexerid = indexer.get('id')
|
|
self._domain = indexer.get('domain')
|
|
self._searchurl = self._searchurl % self._domain
|
|
self._name = indexer.get('name')
|
|
if indexer.get('proxy'):
|
|
self._proxy = settings.PROXY
|
|
self._cookie = indexer.get('cookie')
|
|
self._ua = indexer.get('ua')
|
|
self._timeout = indexer.get('timeout') or 15
|
|
|
|
def __get_params(self, keyword: str = None, page: Optional[int] = 0) -> dict:
|
|
"""
|
|
获取搜索参数
|
|
"""
|
|
params = {
|
|
"pageParam": {
|
|
"current": page + 1,
|
|
"pageSize": self._size,
|
|
"total": self._size
|
|
},
|
|
"sorter": {}
|
|
}
|
|
if keyword:
|
|
params.update({
|
|
"keyword": keyword,
|
|
})
|
|
return params
|
|
|
|
def __parse_result(self, results: List[dict]) -> List[dict]:
|
|
"""
|
|
解析搜索结果
|
|
"""
|
|
torrents = []
|
|
if not results:
|
|
return torrents
|
|
|
|
for result in results:
|
|
category_value = result.get('categoryId')
|
|
if category_value in self._tv_category:
|
|
category = MediaType.TV.value
|
|
elif category_value in self._movie_category:
|
|
category = MediaType.MOVIE.value
|
|
else:
|
|
category = MediaType.UNKNOWN.value
|
|
pass
|
|
|
|
torrentLabelIds = result.get('tagList', []) or []
|
|
torrentLabels = []
|
|
for labelId in torrentLabelIds:
|
|
if self._labels.get(labelId) is not None:
|
|
torrentLabels.append(self._labels.get(labelId))
|
|
pass
|
|
pass
|
|
torrent = {
|
|
'title': result.get('showName'),
|
|
'description': result.get('shortDesc'),
|
|
'enclosure': self.__get_download_url(result.get('id')),
|
|
'pubdate': StringUtils.unify_datetime_str(result.get('listingTime')),
|
|
'size': result.get('fileSize'),
|
|
'seeders': result.get('seedNum'),
|
|
'peers': result.get('leechNum'),
|
|
'grabs': result.get('completedNum'),
|
|
'downloadvolumefactor': self.__get_downloadvolumefactor(result.get('downloadPromotion')),
|
|
'uploadvolumefactor': self.__get_uploadvolumefactor(result.get('uploadPromotion')),
|
|
'freedate': StringUtils.unify_datetime_str(result.get('downloadPromotionEndTime')),
|
|
'page_url': self._pageurl % (self._domain, result.get('id')),
|
|
'labels': torrentLabels,
|
|
'category': category
|
|
}
|
|
torrents.append(torrent)
|
|
|
|
return torrents
|
|
|
|
def search(self, keyword: str,
|
|
mtype: MediaType = None, page: Optional[int] = 0) -> Tuple[bool, List[dict]]:
|
|
"""
|
|
搜索
|
|
"""
|
|
|
|
res = RequestUtils(
|
|
headers={
|
|
"Content-Type": "application/json",
|
|
"User-Agent": f"{self._ua}",
|
|
"Accept": "application/json, text/plain, */*"
|
|
},
|
|
cookies=self._cookie,
|
|
proxies=self._proxy,
|
|
referer=f"{self._domain}",
|
|
timeout=self._timeout
|
|
).post_res(url=self._searchurl, json=self.__get_params(keyword, page))
|
|
if res and res.status_code == 200:
|
|
results = res.json().get('data', []) or []
|
|
return False, self.__parse_result(results)
|
|
elif res is not None:
|
|
logger.warn(f"{self._name} 搜索失败,错误码:{res.status_code}")
|
|
return True, []
|
|
else:
|
|
logger.warn(f"{self._name} 搜索失败,无法连接 {self._domain}")
|
|
return True, []
|
|
|
|
async def async_search(self, keyword: str,
|
|
mtype: MediaType = None, page: Optional[int] = 0) -> Tuple[bool, List[dict]]:
|
|
"""
|
|
异步搜索
|
|
"""
|
|
res = await AsyncRequestUtils(
|
|
headers={
|
|
"Content-Type": "application/json",
|
|
"User-Agent": f"{self._ua}",
|
|
"Accept": "application/json, text/plain, */*"
|
|
},
|
|
cookies=self._cookie,
|
|
proxies=self._proxy,
|
|
referer=f"{self._domain}",
|
|
timeout=self._timeout
|
|
).post_res(url=self._searchurl, json=self.__get_params(keyword, page))
|
|
|
|
if res and res.status_code == 200:
|
|
results = res.json().get('data', []) or []
|
|
return False, self.__parse_result(results)
|
|
elif res is not None:
|
|
logger.warn(f"{self._name} 搜索失败,错误码:{res.status_code}")
|
|
return True, []
|
|
else:
|
|
logger.warn(f"{self._name} 搜索失败,无法连接 {self._domain}")
|
|
return True, []
|
|
|
|
@staticmethod
|
|
def __get_downloadvolumefactor(discount: str) -> float:
|
|
"""
|
|
获取下载系数
|
|
"""
|
|
discount_dict = {
|
|
"free": 0,
|
|
"half": 0.5,
|
|
"none": 1
|
|
}
|
|
if discount:
|
|
return discount_dict.get(discount, 1)
|
|
return 1
|
|
|
|
@staticmethod
|
|
def __get_uploadvolumefactor(discount: str) -> float:
|
|
"""
|
|
获取上传系数
|
|
"""
|
|
discount_dict = {
|
|
"none": 1,
|
|
"one_half": 1.5,
|
|
"double_upload": 2
|
|
}
|
|
if discount:
|
|
return discount_dict.get(discount, 1)
|
|
return 1
|
|
|
|
def __get_download_url(self, torrent_id: str) -> str:
|
|
"""
|
|
获取下载链接
|
|
"""
|
|
return self._downloadurl % (self._domain, torrent_id)
|