Created
June 20, 2020 09:06
-
-
Save nickfox-taterli/759cb3b57e49433d9e7b4d50eaa18b83 to your computer and use it in GitHub Desktop.
PT自动刷+GD上传
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import json | |
import time | |
from datetime import datetime | |
import feedparser | |
import pymongo | |
import qbittorrentapi | |
import requests | |
# 需求: | |
# | |
# 1)贪婪地接受所有种子. | |
# 2)不管靠谱不靠谱,先添加再说. | |
# 3)添加上传表,调用rclone进行上传.参考文档 => https://rclone.org/rc/ | |
# 3.1)服务器启动命令:rclone rcd --rc-addr=0.0.0.0:5572 --rc-user=root --rc-pass=XXXXXX | |
# 3.2)参考文档:https://rclone.org/rc/ | |
# 4)检查到磁盘可用空间小于10G,则删除种子进行释放. | |
# 4.1)删除Tracker失效的种子. | |
# 4.2)删除下载了很久都没下载完的种子.(可能特别大,可能特别慢) | |
# 4.3)如果还是无法释放,那就随机丢一个. | |
# 5)获取当前系统上传,下载,磁盘延迟,磁盘剩余空间信息. | |
# 6)查询rclone状态,及时更新标记. | |
# 7)不添加比硬盘还大的种子(明知没办法下载完成) | |
# | |
# 其他未实现功能: | |
# | |
# 1)适配慢速机(可能会出现全部种子都在下载,没有可以删除的种子,所以可以提前判断,如果磁盘空间太小,不添加任何新种.) | |
client = pymongo.MongoClient( | |
"mongodb+srv://root:x@cluster0-x.mongodb.net/torrent?retryWrites=true&w=majority") | |
db = client.cloudraft | |
source_rss = db["source"] | |
server_status = db["status"] | |
source = 'pt.msg.vg' | |
announce = 'pt.msg.vg' | |
destination = '127.0.0.1' | |
limit = str(5) | |
passkey = 'x' | |
# 实例化QB对象 | |
QBClient = qbittorrentapi.Client(host=destination + ':8080', username='admin', password='TaterLi1024') | |
QBClient.auth_log_in() | |
# 不管有没有空间,先添加再说. | |
torrents = feedparser.parse( | |
'https://' + source + '/torrentrss.php?rows=' + limit + '&linktype=dl&passkey=' + passkey) | |
for torrent in torrents['entries']: | |
torrent_title = torrent['title'] | |
torrent_id = torrent['id'] | |
torrent_size = torrent['links'][1]['length'] | |
torrent_size_gb = int(torrent_size) / 1024 / 1024 / 1024 | |
if torrent_size_gb > 300.0: | |
break | |
elif torrent_size_gb < 0.1: | |
break | |
if source_rss.find_one({"torrent_id": torrent['id']}) is None: | |
source_rss.insert_one({"torrent_id": torrent['id'], | |
"torrent_title": torrent['title'], | |
"torrent_size": torrent_size, | |
"upload_status": False, | |
"upload_jobid": 0, | |
"created_time": datetime.now()}) | |
QBClient.torrents_add(urls=torrent['links'][1]['href'], category=source, save_path='/downloads/') | |
torrents = QBClient.torrents_info(status_filter='all', SIMPLE_RESPONSES=True) | |
for torrent in torrents: | |
# 只有本源的才会进行处理. | |
if announce in torrent['magnet_uri']: | |
# 种子名称 | |
torrent_name = torrent['name'] | |
# 种子状态 | |
torrent_state = torrent['state'] | |
# 已运行时间 | |
time_active = torrent['time_active'] | |
# Tracker 时间 | |
tracker_status = QBClient.torrents_trackers(torrent['hash'], SIMPLE_RESPONSES=True)[3]['status'] | |
# Tracker 状态码 | |
tracker_msg = QBClient.torrents_trackers(torrent['hash'], SIMPLE_RESPONSES=True)[3]['msg'] | |
# 有下载完成的种子,去查数据库看看是否已经被上传,如果没有被上传,就要上传处理. | |
if torrent['completion_on'] > 0: | |
result = source_rss.find_one({"torrent_id": torrent['hash'], 'upload_status': False}) | |
if result is not None: | |
url = "http://" + destination + ":5572/sync/copy" | |
payload = dict() | |
payload['srcFs'] = "/mnt/downloads/" + torrent_name | |
payload['dstFs'] = "blay:/" + torrent_name | |
payload['_async'] = True | |
headers = { | |
'Authorization': 'Basic xxxxx', | |
'Content-Type': 'application/json' | |
} | |
response = requests.post(url, headers=headers, data=json.dumps(payload)) | |
# 提交就当上传成功了.(后续在主循环根据ID判断上传成功与否) | |
# 如果jobid是大于0的数字则还在上传,如果jobid为0,则上传完成. | |
source_rss.update_one({"torrent_id": torrent['hash']}, | |
{"$set": {"upload_status": True, | |
"upload_jobid": json.loads(response.text)['jobid']}}) | |
break | |
sync_maindata = QBClient.sync_maindata(SIMPLE_RESPONSES=True) | |
server_state = sync_maindata['server_state'] | |
# 磁盘空间余量(GB) | |
free_space_on_disk = round(server_state['free_space_on_disk'] / 1024 / 1024 / 1024, 2) | |
# 上传总量(GB) | |
alltime_ul = round(server_state['alltime_ul'] / 1024 / 1024 / 1024, 2) | |
# 下载总量(GB) | |
alltime_dl = round(server_state['alltime_dl'] / 1024 / 1024 / 1024, 2) | |
# 上传速度(MB/s) | |
up_info_speed = round(server_state['up_info_speed'] / 1024 / 1024, 2) | |
# 下载速度(MB/s) | |
dl_info_speed = round(server_state['dl_info_speed'] / 1024 / 1024, 2) | |
# 磁盘延迟(ms) | |
disk_latency = server_state['average_time_queue'] | |
server_status.insert_one({"free_space_on_disk": free_space_on_disk, | |
"alltime_ul": alltime_ul, | |
"alltime_dl": alltime_dl, | |
"up_info_speed": up_info_speed, | |
"dl_info_speed": dl_info_speed, | |
"disk_latency": disk_latency, | |
"created_time": datetime.now()}) | |
print('[主程序]当前磁盘空间余量 %.2f,上传总量 %.2f GB,下传总量 %.2f GB,上传速度 %.2f MB/s,下载速度 %.2f MB/s,磁盘延迟 %d ms.' % ( | |
free_space_on_disk, alltime_ul, alltime_dl, up_info_speed, dl_info_speed, disk_latency)) | |
# 剩余空间太小,执行删除策略. | |
deleted_flag = False | |
if free_space_on_disk < 10.0: | |
torrents = QBClient.torrents_info(status_filter='all', SIMPLE_RESPONSES=True) | |
for torrent in torrents: | |
# 只有本源的才会进行处理. | |
if announce in torrent['magnet_uri']: | |
# 下载完成,上传完成,无上传速度(小于1B). | |
if torrent['completion_on'] > 0 and torrent['upspeed'] < 1: | |
print('[测试]删除下载完成,上传完成且无速度内容.') | |
result = source_rss.find_one({"torrent_id": torrent['hash'], 'upload_status': True, 'upload_jobid': 0}) | |
if result is not None: | |
print('[删除]删除下载完成,上传完成且无速度内容:' + torrent['name']) | |
QBClient.torrents_delete(hashes=torrent['hash'], delete_files=True) | |
deleted_flag = True | |
# 24小时都无法下载完成(禁用) | |
elif torrent['time_active'] > 86400 and torrent['seen_complete'] < 0: | |
# QBClient.torrents_delete(hashes=torrent['hash'], delete_files=True) | |
deleted_flag = True | |
# 如果种子被取消注册,则取消这个种子,清空文件. | |
elif tracker_status == 4 and 'torrent not registered with this tracker' in tracker_msg: | |
print('[删除]删除失效内容:' + torrent['name']) | |
QBClient.torrents_delete(hashes=torrent['hash'], delete_files=True) | |
deleted_flag = True | |
# 没有可删除怎么办?那就循环找,找到下载上传都无速度,删除. | |
if deleted_flag is False: | |
torrents = QBClient.torrents_info(status_filter='all', SIMPLE_RESPONSES=True) | |
for torrent in torrents: | |
# 只有本源的才会进行处理. | |
if announce in torrent['magnet_uri']: | |
if torrent['dlspeed'] + torrent['upspeed'] == 0: | |
print('[删除]删除无速度但是未完成种子') | |
# QBClient.torrents_delete(hashes=torrent['hash'], delete_files=True) | |
# deleted_flag = True | |
break | |
# 终极大招,删除占用空间最大的那一个. | |
if deleted_flag is False: | |
torrents = QBClient.torrents_info(status_filter='all', SIMPLE_RESPONSES=True) | |
for torrent in torrents: | |
# 只有本源的才会进行处理. | |
max_downloaded = 0 | |
torrent_hash = '' | |
if announce in torrent['magnet_uri']: | |
if max_downloaded < torrent['downloaded']: | |
max_downloaded = torrent['downloaded'] | |
torrent_hash = torrent['hash'] | |
print('[删除]删除最大的进行中种子:' + torrent['name']) | |
QBClient.torrents_delete(hashes=torrent_hash, delete_files=True) | |
time.sleep(60) | |
# 如果没法完成删除,那只能随便删一个了.(这个功能还没做) | |
if deleted_flag is False: | |
pass | |
# 执行rclone检查(为了防止rclone压力过大,每次检查一个就算了!) | |
result = source_rss.find_one( | |
{"$and": [ | |
{"upload_status": True}, | |
{"upload_jobid": { | |
"$ne": 0 | |
}} | |
]}) | |
if result is not None: | |
url = "http://" + destination + ":5572/job/status" | |
payload = dict() | |
torrent_id = result['torrent_id'] | |
payload['jobid'] = result['upload_jobid'] | |
headers = { | |
'Authorization': 'Basic xxxx', | |
'Content-Type': 'application/json' | |
} | |
response = requests.post(url, headers=headers, data=json.dumps(payload)) | |
result = json.loads(response.text) | |
print('[Rclone]有正在进行的上传任务,种子ID:' + str(torrent_id) + ',任务ID:' + str(payload['jobid'])) | |
if 'finished' in result: | |
if 'is a file not a directory' in result['error']: | |
url = "http://" + destination + ":5572/operations/copyfile" | |
payload = dict() | |
payload['srcFs'] = "/mnt/downloads/" | |
payload['dstFs'] = "blay:/" | |
payload['srcRemote'] = QBClient.torrents_info(hashes=torrent_id, SIMPLE_RESPONSES=True)[0]['name'] | |
payload['dstRemote'] = payload['srcRemote'] | |
payload['_async'] = True | |
headers = { | |
'Authorization': 'Basic xxxxx', | |
'Content-Type': 'application/json' | |
} | |
response = requests.post(url, headers=headers, data=json.dumps(payload)) | |
# 提交就当上传成功了.(后续在主循环根据ID判断上传成功与否) | |
# 如果jobid是大于0的数字则还在上传,如果jobid为0,则上传完成. | |
source_rss.update_one({"torrent_id": torrent['hash']}, | |
{"$set": {"upload_status": True, | |
"upload_jobid": json.loads(response.text)['jobid']}}) | |
elif result['finished'] is True: | |
source_rss.update_one({"upload_jobid": payload['jobid']}, | |
{"$set": {"upload_jobid": 0}}) | |
# 任务意外结束,重来一次. | |
elif 'job not found' in result['error']: | |
source_rss.update_one({"upload_jobid": payload['jobid']}, | |
{"$set": {"upload_status": False}}) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment