qBittorrent + Rclone 自动上传脚本

因为在设置 qBittorrent 的时候发现有一个“Torrent 完成时运行外部程序”的设置,我就在想能不能用这个方法下载 PT 然后自动传到 Google Drive,一番寻找找到了两种办法,在此记录一下过程。

方法一原文链接:https://www.hostloc.com/thread-612238-1-1.html

方法二原文链接:https://www.hostloc.com/thread-639215-1-1.html

脚本下载

首先先在设置中的 Web UI 中把“对本地主机上的客户端跳过身份验证”勾上,我一开始没有勾上,获取不了 cookie 加不了标签。先勾上有备无患。

没有勾上获取不了 cookie

方法一

新建一个qb_auto.sh 写入:

#!/bin/sh
torrent_name=$1
content_dir=$2
root_dir=$3
save_dir=$4
files_num=$5
torrent_size=$6
file_hash=$7

qb_version="4.2.0" #如4.0.4、4.1.9.1、4.2.0等,不支持3.1.X
qb_username="hostloc" #qb用户名
qb_password="hostloc.com" #qb密码
qb_web_url="https://hostloc.com" #QB web路径,可以填写本地http://localhost:8080
leeching_mode="true" #吸血模式 设为true 上传完后自动删除种子及数据 否则不删除,继续做种
log_dir="/root/qbauto" #日志目录
rclone_dest="gdrive" #rclone destination关键字 运行rclone config查看name字段即可
rclone_parallel="32" #rclone上传线程 默认4
auto_del_flag="rclone"#添加标签或者分类来标识已上传的种子 v4.0.4+版本添加标签“rclone”,低版本通过添加分类“rclone”标识

if [ ! -d ${log_dir} ]
then
        mkdir -p ${log_dir}
fi

version=$(echo $qb_version | grep -P -o "([0-9]\.){2}[0-9]" | sed s/\\.//g)

function qb_login(){
        if [ ${version} -gt 404 ]
        then
                qb_v="1"
                cookie=$(curl -i --header "Referer: ${qb_web_url}" --data "username=${qb_username}&password=${qb_password}" "${qb_web_url}/api/v2/auth/login" | grep -P -o 'SID=\S{32}')
                if [ -n ${cookie} ]
                then
                        echo "[$(date '+%Y-%m-%d %H:%M:%S')] 登录成功!cookie:${cookie}" >> ${log_dir}/autodel.log

                else
                        echo "[$(date '+%Y-%m-%d %H:%M:%S')] 登录失败!" >> ${log_dir}/autodel.log
                fi
        elif [[ ${version} -le 404 && ${version} -ge 320 ]]
        then
                qb_v="2"
                cookie=$(curl -i --header "Referer: ${qb_web_url}" --data "username=${qb_username}&password=${qb_password}" "${qb_web_url}/login" | grep -P -o 'SID=\S{32}')
                if [ -n ${cookie} ]
                then
                        echo "[$(date '+%Y-%m-%d %H:%M:%S')] 登录成功!cookie:${cookie}" >> ${log_dir}/autodel.log
                else
                        echo "[$(date '+%Y-%m-%d %H:%M:%S')] 登录失败" >> ${log_dir}/autodel.log
                fi
        elif [[ ${version} -ge 310 && ${version} -lt 320 ]]
        then
                qb_v="3"
                echo "陈年老版本,请及时升级"
                exit
        else
                qb_v="0"
                exit
        fi
\}

function qb_del(){
        if [ ${leeching_mode} == "true" ]
        then
                if [ ${qb_v} == "1" ]
                then
                        curl "${qb_web_url}/api/v2/torrents/delete?hashes=${file_hash}&deleteFiles=true" --cookie ${cookie}
                        echo "[$(date '+%Y-%m-%d %H:%M:%S')] 删除成功!种子名称:${torrent_name}" >> ${log_dir}/qb.log
                elif [ ${qb_v} == "2" ]
                then
                        curl -X POST -d "hashes=${file_hash}" "${qb_web_url}/command/deletePerm" --cookie ${cookie}
                else
                        echo "[$(date '+%Y-%m-%d %H:%M:%S')] 删除成功!种子文件:${torrent_name}" >> ${log_dir}/qb.log
                        echo "qb_v=${qb_v}" >> ${log_dir}/qb.log
                fi
        else
                echo "[$(date '+%Y-%m-%d %H:%M:%S')] 不自动删除已上传种子" >> ${log_dir}/qb.log
        fi
}

function rclone_copy(){
        if [ ${type} == "file" ]
        then
                rclone_copy_cmd=$(rclone -v copy --transfers ${rclone_parallel} --log-file  ${log_dir}/qbauto_copy.log "${content_dir}" ${rclone_dest}:qbauto/)
        elif [ ${type} == "dir" ]
        then
                rclone_copy_cmd=$(rclone -v copy --transfers ${rclone_parallel} --log-file ${log_dir}/qbauto_copy.log "${content_dir}"/ ${rclone_dest}:qbauto/"${torrent_name}")
        fi
}

function qb_add_auto_del_tags(){
        if [ ${qb_v} == "1" ]
        then
                curl -X POST -d "hashes=${file_hash}&tags=${auto_del_flag}" "${qb_web_url}/api/v2/torrents/addTags" --cookie "${cookie}"
        elif [ ${qb_v} == "2" ]
        then
                curl -X POST -d "hashes=${file_hash}&category=${auto_del_flag}" "${qb_web_url}/command/setCategory" --cookie ${cookie}
        else
                echo "qb_v=${qb_v}" >> ${log_dir}/qb.log
        fi
}

if [ -f "${content_dir}" ]
then
   echo "[$(date '+%Y-%m-%d %H:%M:%S')] 类型:文件" >> ${log_dir}/qb.log
   type="file"
   rclone_copy
   qb_login
   qb_add_auto_del_tags
   qb_del
elif [ -d "${content_dir}" ]
then
   echo "[$(date '+%Y-%m-%d %H:%M:%S')] 类型:目录" >> ${log_dir}/qb.log
   type="dir"
   rclone_copy
   qb_login
   qb_add_auto_del_tags
   qb_del
else
   echo "[$(date '+%Y-%m-%d %H:%M:%S')] 未知类型,取消上传" >> ${log_dir}/qb.log
fi

echo "种子名称:${torrent_name}" >> ${log_dir}/qb.log
echo "内容路径:${content_dir}" >> ${log_dir}/qb.log
echo "根目录:${root_dir}" >> ${log_dir}/qb.log
echo "保存路径:${save_dir}" >> ${log_dir}/qb.log
echo "文件数:${files_num}" >> ${log_dir}/qb.log
echo "文件大小:${torrent_size}Bytes" >> ${log_dir}/qb.log
echo "HASH:${file_hash}" >> ${log_dir}/qb.log
echo "Cookie:${cookie}" >> ${log_dir}/qb.log
echo -e "-------------------------------------------------------------\n" >> ${log_dir}/qb.log

然后给脚本权限chmod +x qb_auto.sh

在 WEB UI 勾选“Torrent 完成时运行外部程序”填上:

bash /root/qb_auto.sh  "%N" "%F" "%R" "%D" "%C" "%Z" "%I"

即可下载完自动上传

方法二

先在 qBittorrent 中添加标签

然后安装jq

# debian & linux
apt-get install -y jq
# centos 下
yum install -y jq

新建脚本

#!/bin/sh

qb_version="4.2.5"
qb_username=""
qb_password="" 
qb_web_url="http://127.0.0.1:1080" 
log_dir="/root/log"
rclone_dest=""
from_dc_tag="" 
rclone_parallel="4" 

unfinished_tag="Wait_to_upload" 
uploading_tag="Uploading"
finished_tag="Uploaded"
noupload_tag="Not_upload"


if [ ! -d ${log_dir} ]
then
	mkdir -p ${log_dir}
fi

version=$(echo ${qb_version} | grep -P -o "([0-9]\.){2}[0-9]" | sed s/\\.//g)
startPat=`date +'%Y-%m-%d %H:%M:%S'`  
start_seconds=$(date --date="$startPat" +%s);

function qb_login() {
	if [ ${version} -gt 404 ]
	then
		qb_v="1"
		cookie=$(curl -i --header "Referer: ${qb_web_url}" --data "username=${qb_username}&password=${qb_password}" "${qb_web_url}/api/v2/auth/login" | grep -P -o 'SID=\S{32}')
		if [ -n ${cookie} ]
		then
			echo "[$(date '+%Y-%m-%d %H:%M:%S')] 登录成功!cookie:${cookie}" 

		else
			echo "[$(date '+%Y-%m-%d %H:%M:%S')] 登录失败!" 
		fi
	elif [[ ${version} -le 404 && ${version} -ge 320 ]]
	then
		qb_v="2"
		cookie=$(curl -i --header "Referer: ${qb_web_url}" --data "username=${qb_username}&password=${qb_password}" "${qb_web_url}/login" | grep -P -o 'SID=\S{32}')
		if [ -n ${cookie} ]
		then
			echo "[$(date '+%Y-%m-%d %H:%M:%S')] 登录成功!cookie:${cookie}" 
		else
			echo "[$(date '+%Y-%m-%d %H:%M:%S')] 登录失败" 
		fi
	elif [[ ${version} -ge 310 && ${version} -lt 320 ]]
	then
		qb_v="3"
		echo "陈年老版本,请及时升级"
		exit
	else
		qb_v="0"
		exit
	fi
}

# 先移除指定tag,后增加自己的tag
function qb_change_hash_tag(){
    file_hash=$1
    fromTag=$2
    toTag=$3
    if [ ${qb_v} == "1" ]
    then # 这里是添加某些tag的方法
		curl -s -X POST -d "hashes=${file_hash}&tags=${fromTag}" "${qb_web_url}/api/v2/torrents/removeTags" --cookie "${cookie}"
        curl -s -X POST -d "hashes=${file_hash}&tags=${toTag}" "${qb_web_url}/api/v2/torrents/addTags" --cookie "${cookie}"
    elif [ ${qb_v} == "2" ]
    then
        curl -s -X POST -d "hashes=${file_hash}&category=${fromTag}" "${qb_web_url}/command/removeCategories" --cookie ${cookie}
        curl -s -X POST -d "hashes=${file_hash}&category=${toTag}" "${qb_web_url}/command/setCategory" --cookie ${cookie}
    else
        echo "qb_v=${qb_v}"
    fi
}

function rclone_copy(){
    torrent_name=$1
    torrent_hash=$2
    torrent_path=$3
    
    echo "${torrent_name}"  >> ${log_dir}/qb.log
    echo "${torrent_hash}"  >> ${log_dir}/qb.log
    echo "${torrent_path}"  >> ${log_dir}/qb.log

    # tag = 待上传
    # 这里执行上传程序
    if [ -f "${torrent_path}" ]
    then
       echo "[$(date '+%Y-%m-%d %H:%M:%S')] 类型:文件"
       echo "[$(date '+%Y-%m-%d %H:%M:%S')] 类型:文件" >> ${log_dir}/qb.log
       type="file"
    elif [ -d "${torrent_path}" ]
    then
       echo "[$(date '+%Y-%m-%d %H:%M:%S')] 类型:目录"
       echo "[$(date '+%Y-%m-%d %H:%M:%S')] 类型:目录" >> ${log_dir}/qb.log
       type="dir"
    else
       echo "[$(date '+%Y-%m-%d %H:%M:%S')] 未知类型,取消上传"
       echo "[$(date '+%Y-%m-%d %H:%M:%S')] 未知类型,取消上传" >> ${log_dir}/qb.log
       # tag = 不上传
       qb_change_hash_tag ${torrent_hash} ${unfinished_tag} ${noupload_tag}
       return
    fi
    # tag = 上传中
    qb_change_hash_tag ${torrent_hash} ${unfinished_tag} ${uploading_tag}
    # 执行上传
    if [ ${type} == "file" ]
    then # 这里是rclone上传的方法
        rclone_copy_cmd=$(rclone -v copy --transfers ${rclone_parallel} --log-file  ${log_dir}/qbauto_copy.log "${torrent_path}" ${rclone_dest}/${from_dc_tag})
    elif [ ${type} == "dir" ]
    then
		rclone_copy_cmd=$(rclone -v copy --transfers ${rclone_parallel} --log-file ${log_dir}/qbauto_copy.log "${torrent_path}"/ ${rclone_dest}/${from_dc_tag}/"${torrent_name}")
    fi

    # tag = 已上传
    qb_change_hash_tag ${torrent_hash} ${uploading_tag} ${finished_tag}

    endPat=`date +'%Y-%m-%d %H:%M:%S'`
    end_seconds=$(date --date="$endPat" +%s);
    use_seconds=$((end_seconds-start_seconds));
    use_min=$((use_seconds/60));
    use_sec=$((use_seconds%60));
    echo "上传完成-耗时:${use_min}分${use_sec}秒"
}

function file_lock(){
    $(touch qbup.lock)
}
function can_go_lock(){
    lockStatus=$(ls | grep qbup.lock)
    if [ -z "${lockStatus}" ]
    then
        noLock="1"
        return
    fi
    noLock="0"
}
function file_unlock(){
    $(rm -rf qbup.lock)
}

function doUpload(){
    torrentInfo=$1
    i=$2
    echo $2
    echo ${i}
    
    # IFS保存,因为名字中可能出现多个空格
	OLD_IFS=$IFS
	IFS="\n"
	
    torrent_name=$(echo "${torrentInfo}" | jq ".[$i] | .name" | sed s/\"//g)
    torrent_hash=$(echo "${torrentInfo}" | jq ".[$i] | .hash" | sed s/\"//g)
    save_path=$(echo "${torrentInfo}" | jq ".[$i] | .save_path" | sed s/\"//g)
    
    IFS=$OLD_IFS
    
    echo "${torrent_name}";
    
    if [[ $save_path != /* ]]
    then
		save_path="/${save_path}"
    fi
    
    torrent_path="${save_path}${torrent_name}" # 这里就是他的本地实际路径,尝试将这里上传上去

    can_go_lock
    if [[ ${noLock} == "1" ]] # 厕所门能开
    then
        file_lock # 锁上厕所门
        echo '执行上传没事的~~~';
        echo ${torrent_name}
        echo ${torrent_hash}
        echo ${torrent_path}
        rclone_copy "${torrent_name}" "${torrent_hash}" "${torrent_path}"
    else
        echo '已有程序在上传,退出'
        return # 打不开门,换个时间来
    fi
    file_unlock # 打开厕所门,出去
}

\# 每次只查询一条数据,!!上传一条数据!!
function qb_get_status(){
	qb_login
	if [ ${qb_v} == "1" ]
	then
		completed_torrents_num=$(curl -s "${qb_web_url}/api/v2/torrents/info?filter=completed" --cookie "${cookie}" | jq '.[] | length' | wc -l)
		echo "任务数:".${completed_torrents_num}
		for((i=0;i<${completed_torrents_num};i++));
		do
			curtag=$(curl -s "${qb_web_url}/api/v2/torrents/info?filter=completed" --cookie "${cookie}" | jq ".[$i] | .tags" | sed s/\"//g | grep -P -o "${unfinished_tag}")
			if [ -z "${curtag}" ]
			then
				curtag="null"
			fi
			if [ ${curtag} == "${unfinished_tag}" ]
			then
			    torrentInfo=$(curl -s "${qb_web_url}/api/v2/torrents/info?filter=completed" --cookie "${cookie}")

				doUpload "${torrentInfo}" ${i}
                # 每次只上传一个数据,否则的话,可能会导致多线程的争用问题
                break
			fi
		done
	elif [ ${qb_v} == "2" ]
	then
		completed_torrents_num=$(curl -s "${qb_web_url}/query/torrents?filter=completed" --cookie "${cookie}" | jq '.[] | length' | wc -l)
		for((i=0;i<${completed_torrents_num};i++));
		do
			curtag=$(curl -s "${qb_web_url}/query/torrents?filter=completed" --cookie "${cookie}" | jq ".[$i] | .category" | sed s/\"//g)
			if [ -z "${curtag}" ]
			then
				curtag="null"
			fi
			if [ ${curtag} == "${unfinished_tag}" ]
			then
				torrentInfo=$(curl -s "${qb_web_url}/query/torrents?filter=completed" --cookie "${cookie}")

                doUpload "${torrentInfo}" ${i}
                # 每次只上传一个数据,否则的话,可能会导致多线程的争用问题
                break
			fi
		done
		echo "啥事都不干";
	else
		echo "获取错误"
		echo "qb_v=${qb_v}"
	fi
}

qb_get_status

设置定时任务crontab -e 在后面加上

*/1 * * * * bash /root/qb_auto_rclone.sh

然后把想要上传的种子任务打上标签,下载完坐等上传就行了