Skip to content

Instantly share code, notes, and snippets.

@nickfox-taterli
Created June 20, 2020 09:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save nickfox-taterli/759cb3b57e49433d9e7b4d50eaa18b83 to your computer and use it in GitHub Desktop.
Save nickfox-taterli/759cb3b57e49433d9e7b4d50eaa18b83 to your computer and use it in GitHub Desktop.
PT自动刷+GD上传
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