From 28a9fdcdc8fdf7e4b6ded79d12b64b89b384b0b0 Mon Sep 17 00:00:00 2001 From: midoks Date: Mon, 26 Aug 2019 22:14:22 +0800 Subject: [PATCH] update --- .gitignore | 1 - plugins/qbittorrent/LICENSE | 21 + plugins/qbittorrent/README.md | 14 + plugins/qbittorrent/conf/qb.conf | 35 + plugins/qbittorrent/conf/qb.sql | 34 + plugins/qbittorrent/ico.png | Bin 0 -> 3035 bytes plugins/qbittorrent/index.html | 23 + plugins/qbittorrent/index.py | 357 +++++++++ plugins/qbittorrent/info.json | 18 + plugins/qbittorrent/init.d/qbittorrent.tpl | 46 ++ plugins/qbittorrent/install.sh | 74 ++ plugins/qbittorrent/js/qbittorrent.js | 186 +++++ plugins/qbittorrent/screenshot/ss1.jpg | Bin 0 -> 12592 bytes .../qbittorrent/workers/qbittorrent_worker.py | 719 ++++++++++++++++++ plugins/qbittorrent/workers/rsync.sh | 5 + 15 files changed, 1532 insertions(+), 1 deletion(-) create mode 100644 plugins/qbittorrent/LICENSE create mode 100644 plugins/qbittorrent/README.md create mode 100755 plugins/qbittorrent/conf/qb.conf create mode 100755 plugins/qbittorrent/conf/qb.sql create mode 100755 plugins/qbittorrent/ico.png create mode 100755 plugins/qbittorrent/index.html create mode 100755 plugins/qbittorrent/index.py create mode 100755 plugins/qbittorrent/info.json create mode 100755 plugins/qbittorrent/init.d/qbittorrent.tpl create mode 100755 plugins/qbittorrent/install.sh create mode 100755 plugins/qbittorrent/js/qbittorrent.js create mode 100644 plugins/qbittorrent/screenshot/ss1.jpg create mode 100755 plugins/qbittorrent/workers/qbittorrent_worker.py create mode 100755 plugins/qbittorrent/workers/rsync.sh diff --git a/.gitignore b/.gitignore index 59324bd41..b846f4b9f 100644 --- a/.gitignore +++ b/.gitignore @@ -121,6 +121,5 @@ data/close.pl ssl/input.pl data/datadir.pl data/502Task.pl -plugins/qbittorrent/ data/default.pl data/backup.pl diff --git a/plugins/qbittorrent/LICENSE b/plugins/qbittorrent/LICENSE new file mode 100644 index 000000000..b89fade39 --- /dev/null +++ b/plugins/qbittorrent/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2019 Mr Chen + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/plugins/qbittorrent/README.md b/plugins/qbittorrent/README.md new file mode 100644 index 000000000..6ae4b8a7b --- /dev/null +++ b/plugins/qbittorrent/README.md @@ -0,0 +1,14 @@ +# mw-qbittorrent +mdserver-web|qbittorrent管理 + + +### 安装过程 + +``` +* 先进行压缩 `cd mw-qbittorrent && zip qbittorrent.zip -r ./* ` +* 在mdserver-web点击`添加插件` +``` + +### 截图 + +[![截图1](/screenshot/ss1.jpg)](/screenshot/ss1.jpg) \ No newline at end of file diff --git a/plugins/qbittorrent/conf/qb.conf b/plugins/qbittorrent/conf/qb.conf new file mode 100755 index 000000000..765541ada --- /dev/null +++ b/plugins/qbittorrent/conf/qb.conf @@ -0,0 +1,35 @@ +[db] +DB_HOST = 127.0.0.1 +DB_PORT = 3306 +DB_USER = qbittorrent +DB_PASS = qbittorrent +DB_NAME = qbittorrent + +[qb] +QB_HOST = 127.0.0.1 +QB_PORT = 8080 +QB_USER = admin +QB_PWD = adminadmin + + +[file] +FILE_TO={$SERVER_PATH}/tmp +FILE_TRANSFER_TO={$SERVER_PATH}/tmp +FILE_OWN=www +FILE_GROUP=www +FILE_ENC_SWITCH=0 +FILE_API_URL=http://v.demo.com/api/key/id/{$KEY} +FILE_ASYNC_SWITCH=0 + +[task] +TASK_SIZE_LIMIT=1 +TASK_RATE=4 +TASK_COMPLETED_RATE=10 +TASK_DEBUG=0 + +[setting] +QUEUE_SWITCH = 1 +MAX_ACTIVE_UPLOADS = 1 +MAX_ACTIVE_TORRENTS = 10 +MAX_ACTIVE_DOWNLOADS = 10 + diff --git a/plugins/qbittorrent/conf/qb.sql b/plugins/qbittorrent/conf/qb.sql new file mode 100755 index 000000000..08baac3a7 --- /dev/null +++ b/plugins/qbittorrent/conf/qb.sql @@ -0,0 +1,34 @@ +CREATE TABLE `pl_hash_list` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `name` text NOT NULL, + `info_hash` varchar(40) NOT NULL, + `length` bigint(20) NOT NULL, + `status` char(10) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL, + `create_time` datetime NOT NULL, + PRIMARY KEY (`id`), + UNIQUE KEY `info_hash` (`info_hash`), + KEY `create_time` (`create_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE `pl_hash_file` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `pid` bigint(20) NOT NULL, + `name` text NOT NULL, + `m3u8` varchar(40) NOT NULL, + `key` char(40) NULL DEFAULT '', + `length` bigint(20) NULL DEFAULT 0, + `create_time` datetime NOT NULL, + PRIMARY KEY (`id`), + KEY `create_time` (`create_time`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; + +CREATE TABLE `pl_hash_queue` ( + `id` bigint(20) NOT NULL AUTO_INCREMENT, + `info_hash` char(40) NOT NULL, + `length` bigint(20) NOT NULL DEFAULT 0, + `created_at` datetime NOT NULL, + `updated_at` datetime NOT NULL, + PRIMARY KEY (`id`), + INDEX `length`(`length`) USING BTREE, + KEY `created_at` (`created_at`) +) ENGINE=MyISAM DEFAULT CHARSET=utf8; \ No newline at end of file diff --git a/plugins/qbittorrent/ico.png b/plugins/qbittorrent/ico.png new file mode 100755 index 0000000000000000000000000000000000000000..99808f6448d49d5f287d1dd15bf870b6d2e4295f GIT binary patch literal 3035 zcmV<13ncW3P)dwwsfYg%SCZ z84Z@DInXZg%#k`z9jeo=+H@+=D1S@Mj7ZhH(TvAC~$NpSkKW4s=d;3)Mh~D6$9W)NOwF^Eymd zZT|h-R>G7~PGUuSjy%o3Bp_y|T%7$433~NXRuUP_iWNfqz3qs9KR;sIi;)eLd69Y6 zxn~11%VpPwBQqsV%$I4`oynY;H(>I8a~$y(uXS17@Jap)jX*JgK>(Yc;=eAA=?!;? zCr4~C;bhiQ1k6Y|H&^^@)^_^=fBpI@{c$Wb7OGGf!MdjKo+n2F!B{=mwbXqIFR8kyKzi9xj9m` zLRyZy#XWC#K^XJa<-QpAx+lMH07zmM!L44vN;CqidELd88M33Y88j+nw|W#@dL$R7_sd|c!8E|vQf2#)U8p3 znh>OvF*Q-2q}MAJt(wb1vqZgYF&M>k2O<4Y#K@0RAUW0guMh6=;;A;n(2{J{4Hc3O z-`NPcI|vKIKN{wnE>9n=b9k;wwQOTqmdyE~VtL)?!)sfNgP5;=X-)|Lo7e8LIf`=L zNhx?f+2^aDZu0nn8dFs#-Ajo7;O3COf49fQ<#AzfynS!XwUr@LN2gF4+#p88ac;>& z6$c|)HHR;KrbTC}gwhDXcQ<_T#|!N;M;B|%wMru5os2RF6=3WE*%vYBrw`Zoh8J42 z>m@F&jJV$QP{65$Dv#{1^TkiJIFXEh`7dvBdo3u8=x<)^@z@~)fKjNpz3z)>HGoMI zgvif-qRGs3883+W@6#JxUK*l|nsIox!dJdH$1}&900KZM=>kA$0YurgdGT0-m43j_ z|H)0xFO4AGMj;0Q@nV5s?gJo{fKVg!;8QUV;GDhd3k|nNJLeaJfyc3aD8QTUyrl0?s2#0 zleSzCL>iY@Jg#;9`+A$xH@A0uzA)k|pXp5Y$Ob?^h*{qZMD^`R!_ZR%Q9Kd5Mt;T$ z$I{F-O8~45LOegh%xg1NI+>GAGu|fcCOB!9Hhe~2l$lp%AMt3n);s`?CX%m|Kxftp zt!#}#LIt+c;3cEDATU)*Hm;ns5uFR;`{pd-en);}ycgsG5+I%_j8a#f%dtcgHiqHO zv)D|t>c|*n)<%&MCPWHctsxR_<_{K*Wr--$NGNMe`jAVTQ^JZsg3urYKIo(-DiX@~ zqPiv5HmZm$CRQNt0$h`y`1wtZK+VVS?0y$n9fP)3M|=e?C$)j-Dk7y~&npQI8m&f+?GHL8^?zUK?~GuJFL z7=`@9+ucHyEx8smtqPLN?RT^p^VT=v%+gnZ`AI$!$yJWm~O(x|z-e)b+KYh$!y zvDm5d^5Zj{I5@@7i)d8c+`(NyBA!F?`EUE&Me*@}`9?QMkB3A`@p$t4-}glac>ZKl zH12o*^%i&5#>UW%*Gqsp?3<}kb-^t=(5N`chGp( z`-voGu~Q??Is^Xa+=l4=J6AV(|Jo*B`gDh9j!tu6wo1jd-optEPVsD1%{CWG>z6OsTX;O1106^;V3|xyZ zdaBJI|Idnu?tWD_Ki2rfMfFg_B{{fcgJT@!>!Cw$r)Nu!Dqj>!n-KhUpMRLLV^eo0 z7bie^(ZHz#4LNZY*J*Y?%VyrTdkv|uY(r*Drky&}ysp^7+p!GFy|HP;q6hRfcxW;oHApKMSqOLze$AV@!Ks zxkQoM=Rs}%Y>glJ`bTKjU7F+&nKKJn%dFfyO{}O{?2xRJ{hQM6`7`OPat=Vw- z?yoq(7eBX{-qL);E2fd=^3oQ+|F1XX;BI_*aiKR)v{}1*Gdlkh-}ESt9c?pju9!aF zCEs#y%pd;S4KCf@OwS0rUZFwOMNRQG!ue12PYooIyPT-h|DC?eg&PCLUW6aUgi$Pj4G!cW zR7yS)HId`sey6idX51cdzbV%YXVR@cX@^*si|fUzH^MP4~U z)vK +
+
+

服务

+

自启动

+

导入SQL

+

配置

+

异步脚本

+

日志

+

列表

+ +
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/plugins/qbittorrent/index.py b/plugins/qbittorrent/index.py new file mode 100755 index 000000000..c7b6abbe3 --- /dev/null +++ b/plugins/qbittorrent/index.py @@ -0,0 +1,357 @@ +# coding: utf-8 + +import time +import random +import os +import json +import re +import sys + +sys.path.append(os.getcwd() + "/class/core") +import public + +reload(sys) +sys.setdefaultencoding('utf8') + +sys.path.append('/usr/local/lib/python2.7/site-packages') + + +app_debug = False +if public.isAppleSystem(): + app_debug = True + + +def getPluginName(): + return 'qbittorrent' + + +def getPluginDir(): + return public.getPluginDir() + '/' + getPluginName() + + +def getServerDir(): + return public.getServerDir() + '/' + getPluginName() + + +def getInitDFile(): + if app_debug: + return '/tmp/' + getPluginName() + return '/etc/init.d/' + getPluginName() + + +def getArgs(): + args = sys.argv[2:] + tmp = {} + args_len = len(args) + + if args_len == 1: + t = args[0].strip('{').strip('}') + t = t.split(':') + tmp[t[0]] = t[1] + elif args_len > 1: + for i in range(len(args)): + t = args[i].split(':') + tmp[t[0]] = t[1] + + return tmp + + +def checkArgs(data, ck=[]): + for i in range(len(ck)): + if not ck[i] in data: + return (False, public.returnJson(False, '参数:(' + ck[i] + ')没有!')) + return (True, public.returnJson(True, 'ok')) + + +def getInitDTpl(): + path = getPluginDir() + "/init.d/" + getPluginName() + ".tpl" + return path + + +def getSqlFile(): + file = getPluginDir() + "/conf/qb.sql" + return file + + +def getRsyncShell(): + file = getServerDir() + "/workers/rsync.sh" + return file + + +def getConf(): + file = getServerDir() + "/qb.conf" + return file + + +def getRunLog(): + file = getServerDir() + "/logs.pl" + return file + + +def contentReplace(content): + service_path = public.getServerDir() + content = content.replace('{$SERVER_PATH}', service_path) + return content + + +def initDreplace(): + + ddir = getServerDir() + '/workers' + if not os.path.exists(ddir): + sdir = getPluginDir() + '/workers' + public.execShell('cp -rf ' + sdir + ' ' + getServerDir()) + + cfg = getServerDir() + '/qb.conf' + if not os.path.exists(cfg): + cfg_tpl = getPluginDir() + '/conf/qb.conf' + content = public.readFile(cfg_tpl) + content = contentReplace(content) + public.writeFile(cfg, content) + + file_tpl = getInitDTpl() + service_path = os.path.dirname(os.getcwd()) + + initD_path = getServerDir() + '/init.d' + if not os.path.exists(initD_path): + os.mkdir(initD_path) + file_bin = initD_path + '/' + getPluginName() + + # initd replace + if not os.path.exists(file_bin): + content = public.readFile(file_tpl) + content = contentReplace(content) + public.writeFile(file_bin, content) + public.execShell('chmod +x ' + file_bin) + + return file_bin + + +def status(): + data = public.execShell( + "ps -ef|grep qbittorrent_worker | grep -v grep | awk '{print $2}'") + if data[0] == '': + return 'stop' + return 'start' + + +def start(): + + cmd = "ps -ef | grep qbittorrent-nox |grep -v grep |awk '{print $2}'" + ret = public.execShell(cmd) + if ret[0] == '': + public.execShell('qbittorrent-nox -d') + + file = initDreplace() + + data = public.execShell(file + ' start') + if data[1] == '': + return 'ok' + return data[1] + + +def stop(): + file = initDreplace() + data = public.execShell(file + ' stop') + # cmd = "ps -ef | grep qbittorrent-nox |grep -v grep |awk '{print $2}' | xargs kill" + # public.execShell(cmd) + if data[1] == '': + return 'ok' + return data[1] + + +def restart(): + file = initDreplace() + data = public.execShell(file + ' restart') + if data[1] == '': + return 'ok' + return data[1] + + +def reload(): + file = initDreplace() + data = public.execShell(file + ' reload') + if data[1] == '': + return 'ok' + return data[1] + + +def initdStatus(): + if not app_debug: + if public.isAppleSystem(): + return "Apple Computer does not support" + + initd_bin = getInitDFile() + if os.path.exists(initd_bin): + return 'ok' + return 'fail' + + +def initdInstall(): + import shutil + if not app_debug: + if public.isAppleSystem(): + return "Apple Computer does not support" + + mysql_bin = initDreplace() + initd_bin = getInitDFile() + shutil.copyfile(mysql_bin, initd_bin) + public.execShell('chmod +x ' + initd_bin) + public.execShell('chkconfig --add ' + getPluginName()) + return 'ok' + + +def initdUinstall(): + if not app_debug: + if public.isAppleSystem(): + return "Apple Computer does not support" + initd_bin = getInitDFile() + os.remove(initd_bin) + public.execShell('chkconfig --del ' + getPluginName()) + return 'ok' + + +def matchData(reg, content): + tmp = re.search(reg, content).groups() + return tmp[0] + + +def getDbConfInfo(): + cfg = getConf() + content = public.readFile(cfg) + data = {} + data['DB_HOST'] = matchData("DB_HOST\s*=\s(.*)", content) + data['DB_USER'] = matchData("DB_USER\s*=\s(.*)", content) + data['DB_PORT'] = matchData("DB_PORT\s*=\s(.*)", content) + data['DB_PASS'] = matchData("DB_PASS\s*=\s(.*)", content) + data['DB_NAME'] = matchData("DB_NAME\s*=\s(.*)", content) + return data + + +def getQbConf(): + cfg = getConf() + content = public.readFile(cfg) + data = {} + data['QB_HOST'] = matchData("QB_HOST\s*=\s(.*)", content) + data['QB_PORT'] = matchData("QB_PORT\s*=\s(.*)", content) + data['QB_USER'] = matchData("QB_USER\s*=\s(.*)", content) + data['QB_PWD'] = matchData("QB_PWD\s*=\s(.*)", content) + return data + + +def pMysqlDb(): + data = getDbConfInfo() + conn = mysql.mysql() + conn.setHost(data['DB_HOST']) + conn.setUser(data['DB_USER']) + conn.setPwd(data['DB_PASS']) + conn.setPort(int(data['DB_PORT'])) + conn.setDb(data['DB_NAME']) + return conn + + +def pQbClient(): + from qbittorrent import Client + info = getQbConf() + url = 'http://' + info['QB_HOST'] + ':' + info['QB_PORT'] + '/' + qb = Client(url) + qb.login(info['QB_USER'], info['QB_PWD']) + return qb + + +def getQbUrl(): + info = getQbConf() + url = 'http://' + info['QB_HOST'] + ':' + info['QB_PORT'] + '/' + return public.returnJson(True, 'ok', url) + + +def qbList(): + args = getArgs() + # data = checkArgs(args, ['type']) + # if not data[0]: + # return data[1] + args_type = '' + if 'type' in args: + args_type = args['type'] + + f = ['downloading', 'completed'] + tfilter = '' + if args_type in f: + tfilter = args['type'] + try: + qb = pQbClient() + torrents = qb.torrents(filter=tfilter) + data = {} + data['type'] = tfilter + data['torrents'] = torrents + return public.returnJson(True, 'ok', data) + except Exception as e: + return public.returnJson(False, str(e)) + + +def qbDel(): + args = getArgs() + data = checkArgs(args, ['hash']) + if not data[0]: + return data[1] + qb = pQbClient() + data = qb.delete(args['hash']) + return public.returnJson(True, '操作成功!', data) + + +def qbAdd(): + args = getArgs() + data = checkArgs(args, ['hash']) + if not data[0]: + return data[1] + url = 'magnet:?xt=urn:btih:' + args['hash'] + qb = pQbClient() + data = qb.download_from_link(url) + return public.returnJson(True, '操作成功!', data) + + +def test(): + qb = pQbClient() + # magnet_link = "magnet:?xt=urn:btih:57a0ec92a61c60585f1b7a206a75798aa69285a5" + # print qb.download_from_link(magnet_link) + torrents = qb.torrents(filter='downloading') + for torrent in torrents: + print public.returnJson(False, torrent) + +if __name__ == "__main__": + func = sys.argv[1] + if func == 'status': + print status() + elif func == 'start': + print start() + elif func == 'stop': + print stop() + elif func == 'restart': + print restart() + elif func == 'reload': + print reload() + elif func == 'initd_status': + print initdStatus() + elif func == 'initd_install': + print initdInstall() + elif func == 'initd_uninstall': + print initdUinstall() + elif func == 'get_sql': + print getSqlFile() + elif func == 'rsync_shell': + print getRsyncShell() + elif func == 'conf': + print getConf() + elif func == 'get_run_Log': + print getRunLog() + elif func == 'qb_list': + print qbList() + elif func == 'qb_del': + print qbDel() + elif func == 'qb_add': + print qbAdd() + elif func == 'qb_url': + print getQbUrl() + elif func == 'test': + print test() + else: + print 'error' diff --git a/plugins/qbittorrent/info.json b/plugins/qbittorrent/info.json new file mode 100755 index 000000000..c77d22c60 --- /dev/null +++ b/plugins/qbittorrent/info.json @@ -0,0 +1,18 @@ +{ + "sort": 7, + "ps": "一个新的轻量级BitTorrent客户端", + "name": "qbittorrent", + "title": "qBittorrent", + "shell": "install.sh", + "versions":["4.1.5"], + "updates":["4.1.5"], + "tip": "soft", + "checks": "server/qbittorrent", + "path": "server/qbittorrent", + "display": 1, + "author": "Zend", + "date": "2017-04-01", + "home": "https://www.qbittorrent.org", + "type": 0, + "pid": "5" +} \ No newline at end of file diff --git a/plugins/qbittorrent/init.d/qbittorrent.tpl b/plugins/qbittorrent/init.d/qbittorrent.tpl new file mode 100755 index 000000000..a6fb06707 --- /dev/null +++ b/plugins/qbittorrent/init.d/qbittorrent.tpl @@ -0,0 +1,46 @@ +#!/bin/sh +# chkconfig: 2345 55 25 +# description: qbittorrent Service + +### BEGIN INIT INFO +# Provides: qbittorrent +# Required-Start: $all +# Required-Stop: $all +# Default-Start: 2 3 4 5 +# Default-Stop: 0 1 6 +# Short-Description: starts qbittorrent +# Description: starts the MDW-Web +### END INIT INFO + + +qb_start(){ + cd {$SERVER_PATH}/qbittorrent/workers + nohup python qbittorrent_worker.py > {$SERVER_PATH}/qbittorrent/logs.pl 2>&1 & + echo "qbittorrent started" +} + +qb_stop(){ + echo "Stopping ..." + #ps -ef | grep qbittorrent-nox-bin | grep -v grep | awk '{print $2}' | xargs kill -9 + ps -ef | grep "qbittorrent_worker.py" | grep -v grep | awk '{print $2}' | xargs kill -9 + echo "qbittorrent stopped" +} + + +case "$1" in + start) + qb_start + ;; + stop) + qb_stop + ;; + restart|reload) + qb_stop + sleep 0.3 + qb_start + ;; + *) + echo "Please use start or stop as first argument" + ;; +esac + diff --git a/plugins/qbittorrent/install.sh b/plugins/qbittorrent/install.sh new file mode 100755 index 000000000..f72dfa7b6 --- /dev/null +++ b/plugins/qbittorrent/install.sh @@ -0,0 +1,74 @@ +#!/bin/bash +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin +export PATH + +curPath=`pwd` +rootPath=$(dirname "$curPath") +rootPath=$(dirname "$rootPath") +serverPath=$(dirname "$rootPath") +sysName=`uname` + +install_tmp=${rootPath}/tmp/bt_install.pl + +#https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz + +Install_mac_ffmpeg() +{ + if [ ! -f $serverPath/source/ffmpeg-20180702-3c4af57-macos64-static.zip ];then + wget -O $serverPath/source/ffmpeg-20180702-3c4af57-macos64-static.zip https://ffmpeg.zeranoe.com/builds/macos64/static/ffmpeg-20180702-3c4af57-macos64-static.zip + fi + + if [ ! -d $serverPath/lib/ffmpeg ];then + cd $serverPath/source && tar -xvf $serverPath/source/ffmpeg-20180702-3c4af57-macos64-static.zip + mv ffmpeg-20180702-3c4af57-macos64-static $serverPath/lib/ffmpeg + fi +} + +Install_linux_ffmpeg() +{ + if [ ! -f $serverPath/source/ffmpeg-release-amd64-static.tar.xz ];then + wget -O $serverPath/source/ffmpeg-release-amd64-static.tar.xz https://johnvansickle.com/ffmpeg/releases/ffmpeg-release-amd64-static.tar.xz + fi + + if [ ! -d $serverPath/lib/ffmpeg ];then + cd $serverPath/source && tar -xvf $serverPath/source/ffmpeg-release-amd64-static.tar.xz + mv ffmpeg-4.1.2-amd64-static $serverPath/lib/ffmpeg + fi +} + +Install_qbittorrent() +{ + if [ $sysName == 'Darwin' ]; then + Install_mac_ffmpeg + else + yum -y install qbittorrent-nox + #qbittorrent-nox -d + + Install_linux_ffmpeg + fi + + pip install python-qbittorrent==0.2 + + echo '正在安装脚本文件...' > $install_tmp + mkdir -p $serverPath/qbittorrent + + QB_DIR=${serverPath}/source/qbittorrent + mkdir -p $QB_DIR + + echo '4.1.5' > $serverPath/qbittorrent/version.pl + echo '安装完成' > $install_tmp +} + +Uninstall_qbittorrent() +{ + rm -rf $serverPath/qbittorrent + which yum && yum -y remove qbittorrent-nox + echo "Uninstall_qbittorrent" > $install_tmp +} + +action=$1 +if [ "${1}" == 'install' ];then + Install_qbittorrent +else + Uninstall_qbittorrent +fi diff --git a/plugins/qbittorrent/js/qbittorrent.js b/plugins/qbittorrent/js/qbittorrent.js new file mode 100755 index 000000000..e00249172 --- /dev/null +++ b/plugins/qbittorrent/js/qbittorrent.js @@ -0,0 +1,186 @@ +function qbPostMin(method, args, callback){ + + var req_data = {}; + req_data['name'] = 'qbittorrent'; + req_data['func'] = method; + + if (typeof(args) != 'undefined' && args!=''){ + req_data['args'] = JSON.stringify(args); + } + + $.post('/plugins/run', req_data, function(data) { + if (!data.status){ + layer.msg(data.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + if(typeof(callback) == 'function'){ + callback(data); + } + },'json'); +} + +function qbPost(method, args, callback){ + var loadT = layer.msg('正在获取...', { icon: 16, time: 0, shade: 0.3 }); + qbPostMin(method,args,function(data){ + layer.close(loadT); + if(typeof(callback) == 'function'){ + callback(data); + } + }); +} + +function showHideHash(obj){ + var a = "glyphicon-eye-open"; + var b = "glyphicon-eye-close"; + + if($(obj).hasClass(a)){ + $(obj).removeClass(a).addClass(b); + $(obj).prev().text($(obj).prev().attr('data-pw')) + } else{ + $(obj).removeClass(b).addClass(a); + $(obj).prev().text($(obj).attr('data-pw')); + } +} + + +function copyText(password){ + var clipboard = new ClipboardJS('#bt_copys'); + clipboard.on('success', function (e) { + layer.msg('复制成功',{icon:1,time:2000}); + }); + + clipboard.on('error', function (e) { + layer.msg('复制失败,浏览器不兼容!',{icon:2,time:2000}); + }); + $("#bt_copys").attr('data-clipboard-text',password); + $("#bt_copys").click(); +} + +function getLocalTime(nS) { + return new Date(parseInt(nS) * 1000).toLocaleString().replace(/:\d{1,2}$/,' '); +} + + + +function qbAdd(){ + + var loadOpen = layer.open({ + type: 1, + title: '添加资源', + area: '400px', + content:"
\ +
\ +
\ +
\ +
\ + \ + \ +
\ +
" + }); + + $('#qb_close').click(function(){ + layer.close(loadOpen); + }); + + $('#qb_ok').click(function(){ + var hash = $('#qb_hash').val(); + qbPost('qb_add', {hash:hash}, function(data){ + + var rdata = $.parseJSON(data.data); + if (rdata['status']){ + showMsg(rdata.msg, function(){ + qbList(); + },{icon:1,time:2000,shade: [0.3, '#000']}); + layer.close(loadOpen); + } else { + layer.msg(rdata.msg,{icon:2,time:2000,shade: [0.3, '#000']}); + } + }); + }); +} + + +function qbDel(hash){ + qbPost('qb_del', {hash:hash}, function(data){ + var rdata = $.parseJSON(data.data); + if (rdata['status']){ + layer.msg(rdata.msg,{icon:1,time:2000,shade: [0.3, '#000']}); + } else { + layer.msg(rdata.msg,{icon:2,time:2000,shade: [0.3, '#000']}); + } + }); +} + +function qbListFind(){ + var qbs = $('#qb_selected').val(); + if ( qbs == '0' ){ + qbList(); + } else { + qbList(qbs); + } +} + +function openAdminUrl(){ + qbPost('qb_url', '', function(data){ + var rdata = $.parseJSON(data.data); + window.open(rdata.data); + }); +} + +function qbList(search){ + var _data = {}; + _data['test'] ='yes'; + if(typeof(search) != 'undefined'){ + _data['type'] = search; + } + + qbPost('qb_list', _data, function(data){ + + var rdata = $.parseJSON(data.data); + if (!rdata['status']){ + layer.msg(rdata.msg,{icon:0,time:2000,shade: [0.3, '#000']}); + return; + } + + content = ''; + content += ''; + + content += '
'; + content += ''; + content += ''; + content += ''; + content += ''; + content += ''; + + content += ''; + + ulist = rdata.data.torrents; + for (i in ulist){ + content += ''+ + ''+ + ''; + } + + content += ''; + content += '
种子(hash)添加时间操作(添加 | 管理)
'+ + ''+ulist[i]['hash'].substr(0,3)+'' + + ''+ + ''+ + ''+getLocalTime(ulist[i]['added_on'])+'删除
'; + + $(".soft-man-con").html(content); + + var type = rdata.data.type; + if (type == ''){ + $("#qb_selected option[value='0']").attr("selected", true); + } else { + $("#qb_selected option[value='"+type+"']").attr("selected", true); + } + }); +} diff --git a/plugins/qbittorrent/screenshot/ss1.jpg b/plugins/qbittorrent/screenshot/ss1.jpg new file mode 100644 index 0000000000000000000000000000000000000000..807c51660d5e61c5b916a2c6d45aff5973a2b085 GIT binary patch literal 12592 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 ' + + enc_dir + '/enc.key') + self.execShell('rm -rf ' + enc_dir + '/enc.keyinfo.txt') + + try: + fid = self.add_hash(fname, md5Fname) + except Exception as e: + print 'add_hash_enc:' + str(e) + return + fid = self.add_hash(fname, md5Fname) + key = self.readFile(enc_dir + '/enc.key').strip() + self.set_hashfile_key(fid, key) + + # FILE_API_URL + url = FILE_API_URL.replace('{$KEY}', fid) + enc_url = 'echo ' + url + ' >> ' + enc_dir + '/enc.keyinfo.txt' + self.execShell(enc_url) + enc_path = 'echo ' + enc_dir + '/enc.key >> ' + enc_dir + '/enc.keyinfo.txt' + self.execShell(enc_path) + enc_iv = 'openssl rand -hex 16 >> ' + enc_dir + '/enc.keyinfo.txt' + self.execShell(enc_iv) + + os.system(cmd) + else: + + if os.path.exists(m3u8_file): + print self.debug('m3u8 exists:' + tofile) + self.ffmpeg_file_sync() + self.ffmpeg_del_file(mp4file, tsfile, m3u8_dir) + return + + cmd_m3u8 = self.fg_m3u8_cmd(tsfile, m3u8_file, tofile) + print self.debug('cmd_m3u8:' + cmd_m3u8) + os.system(cmd_m3u8) + + try: + self.add_hash(fname, md5Fname) + except Exception as e: + print 'add_hash', str(e) + + self.execShell('chown -R ' + FILE_OWN + ':' + + FILE_GROUP + ' ' + m3u8_dir) + self.execShell('chmod -R 755 ' + m3u8_dir) + + self.ffmpeg_file_sync() + self.ffmpeg_del_file(mp4file, tsfile, m3u8_dir) + + def get_bt_size(self, torrent): + total_size = '0' + if 'size' in torrent: + total_size = str(torrent['size']) + + if 'total_size' in torrent: + total_size = str(torrent['total_size']) + return total_size + + def get_hashlist_id(self): + ct = formatTime() + + total_size = self.get_bt_size(self.sign_torrent) + + shash = self.sign_torrent['hash'] + sname = self.sign_torrent['name'] + sname = mdb.escape_string(sname) + + info = self.query( + "select id from pl_hash_list where info_hash='" + shash + "'") + if len(info) > 0: + pid = str(info[0][0]) + else: + print 'insert into pl_hash_list data' + pid = self.execute("insert into pl_hash_list (`name`,`info_hash`,`length`,`create_time`) values('" + + sname + "','" + shash + "','" + total_size + "','" + ct + "')") + return pid + + def set_hashlist_status(self, torrent, status): + ct = formatTime() + + shash = torrent['hash'] + + info = self.query( + "select id from pl_hash_list where info_hash='" + shash + "'") + if len(info) > 0: + print 'set_hashlist_status update' + usql = "update pl_hash_list set `status`='" + \ + str(status) + "' where info_hash='" + shash + "'" + self.execute(usql) + else: + print 'set_hashlist_status insert' + total_size = self.get_bt_size(torrent) + sname = torrent['name'] + sname = mdb.escape_string(sname) + return self.execute("insert into pl_hash_list (`name`,`info_hash`,`length`,`status`,`create_time`) values('" + + sname + "','" + shash + "','" + total_size + "','" + str(status) + "','" + ct + "')") + + def get_hashfile_id(self, fname, m3u8_name, pid): + ct = formatTime() + + info = self.query( + "select id from pl_hash_file where name='" + fname + "' and pid='" + pid + "'") + if len(info) == 0: + print 'insert into pl_hash_file data !' + fid = self.execute("insert into pl_hash_file (`pid`,`name`,`m3u8`,`create_time`) values('" + + pid + "','" + fname + "','" + m3u8_name + "','" + ct + "')") + else: + print fname, ':', m3u8_name, 'already is exists!' + fid = str(info[0][0]) + return fid + + def set_hashfile_key(self, fid, key): + self.execute("update pl_hash_file set `key`='" + + mdb.escape_string(key) + "' where id=" + fid) + + def add_queue(self, shash, size): + ct = formatTime() + + info = self.query( + "select id from pl_hash_queue where info_hash='" + shash + "'") + if len(info) == 0: + sql = "insert into pl_hash_queue (`info_hash`,`length`,`created_at`,`updated_at`) values('" + \ + shash + "','" + str(size) + "','" + ct + "','" + ct + "')" + return self.execute(sql) + else: + print 'queue:', shash, 'already is exists!' + + def add_hash(self, fname, m3u8_name): + print '-------------------------add_hash---start-----------------------' + + pid = self.get_hashlist_id() + fid = self.get_hashfile_id(fname, m3u8_name, pid) + + print '-------------------------add_hash---end--------------------------' + + return fid + + def file_arr(self, path, filters=['.DS_Store']): + file_list = [] + flist = os.listdir(path) + + for i in range(len(flist)): + # 下载缓存文件过滤 + if flist[i] == '.unwanted': + continue + + file_path = os.path.join(path, flist[i]) + if flist[i] in filters: + continue + if os.path.isdir(file_path): + tmp = self.file_arr(file_path, filters) + file_list.extend(tmp) + else: + file_list.append(file_path) + return file_list + + def find_dir_video(self, path): + flist = self.file_arr(path) + video = [] + for i in range(len(flist)): + if self.is_video(flist[i]): + video.append(flist[i]) + return video + + def video_do(self, path): + if os.path.isfile(path): + if self.is_video(path): + self.ffmpeg(path) + else: + vlist = self.find_dir_video(path) + for v in vlist: + self.ffmpeg(v) + return '' + + def is_video(self, path): + t = os.path.splitext(path) + if t[1] in self.has_suffix: + return True + return False + + def non_download(self, torrent): + flist = self.qb.get_torrent_files(torrent['hash']) + is_video = False + for pos in range(len(flist)): + file = torrent['save_path'] + flist[pos]['name'] + if not self.is_video(file): + self.qb.set_file_priority(torrent['hash'], pos, 0) + else: + is_video = True + + # is video + if not is_video: + self.set_status(torrent, 1) + + def set_status(self, torrent, status): + self.set_hashlist_status(torrent, status) + if TASK_DEBUG == 0 and status != 0: + self.qb.delete_permanently(torrent['hash']) + + def is_downloading(self, torrent): + if torrent['name'] == torrent['hash']: + return True + else: + return False + + def is_nondownload_overtime(self, torrent, sec): + ct = time.time() + use_time = int(ct) - int(torrent['added_on']) + + flist = self.qb.get_torrent_files(torrent['hash']) + # print flist + flist_len = len(flist) + # 没有获取种子信息 + # print 'ddd:',flist_len,use_time,sec + if flist_len == 0 and use_time > sec: + self.set_status(torrent, 2) + return True + + is_video_download = False + + # 获取了种子信息,但是没有下载 + for pos in range(len(flist)): + file = torrent['save_path'] + flist[pos]['name'] + if self.is_video(file): + if flist[pos]['progress'] != '0': + is_video_download = True + + if not is_video_download and use_time > sec: + self.set_status(torrent, 3) + return True + return False + + def is_downloading_overtime(self, torrent, sec): + ct = time.time() + use_time = int(ct) - int(torrent['added_on']) + if use_time > sec: + self.set_status(torrent, 4) + return True + return False + + def is_downloading_overlimit(self, torrent): + sz = self.get_bt_size(torrent) + ct = formatTime() + size_limit = float(TASK_SIZE_LIMIT) * 1024 * 1024 * 1024 + size_limit = int(size_limit) + print 'is_downloading_overlimit:', toSize(sz), toSize(size_limit) + if int(sz) > int(size_limit): + print 'overlimit sz:' + sz + self.add_queue(torrent['hash'], str(sz)) + self.qb.delete_permanently(torrent['hash']) + + def check_task(self): + while True: + torrents = self.qb.torrents(filter='downloading') + tlen = len(torrents) + if tlen > 0: + print "downloading torrents count:", tlen + for torrent in torrents: + if self.is_nondownload_overtime(torrent, 5 * 60): + pass + elif self.is_downloading_overtime(torrent, 7 * 24 * 60 * 60): + pass + elif self.is_downloading(torrent): + pass + elif self.is_downloading_overlimit(torrent): + pass + else: + self.non_download(torrent) + print torrent['name'], ' task downloading!' + else: + print self.debug("no downloading task!") + time.sleep(TASK_RATE) + + def completed(self): + while True: + + torrents = self.qb.torrents(filter='completed') + tlen = len(torrents) + print "completed torrents count:", tlen + if tlen > 0: + for torrent in torrents: + self.sign_torrent = torrent + path = torrent['save_path'] + torrent['name'] + path = path.encode() + try: + self.video_do(path) + + hash_dir = self.get_transfer_hash_dir(torrent['hash']) + self.ffmpeg_del_hfile(hash_dir) + if TASK_DEBUG == 0: + self.qb.delete_permanently(torrent['hash']) + except Exception as e: + print formatTime(), str(e) + print self.debug("done task!") + else: + print self.debug("no completed task!") + time.sleep(TASK_COMPLETED_RATE) + + def add_hash_task(self, shash): + url = 'magnet:?xt=urn:btih:' + shash + self.qb.download_from_link(url) + print self.debug('queue add_hash_task is ok ... ') + + def queue(self): + while True: + if QUEUE_SWITCH == '1': + print self.debug("------------ do queue task start! ---------------") + + setting = self.qb.preferences() + torrents = self.qb.torrents() + tlen = len(torrents) + # print tlen, setting['max_active_torrents'] + add = int(setting['max_active_torrents']) - tlen + + if add == 0: + print self.debug('the download queue is full ... ') + else: + size_limit = float(TASK_SIZE_LIMIT) * 1024 * 1024 * 1024 + size_limit = int(size_limit) + size_sql_where = '' + size_sql = '' + if size_limit != 0: + size_sql = ',`length` desc ' + size_sql_where = 'where `length`<=' + str(size_limit) + + sql = "select * from pl_hash_queue " + size_sql_where + \ + " order by created_at desc " + \ + size_sql + " limit " + str(add) + info = self.query(sql) + info_len = len(info) + + if info_len == 0: + print self.debug('queue data is empty ... ') + else: + for x in range(info_len): + self.add_hash_task(info[x][1]) + self.execute( + 'delete from pl_hash_queue where id=' + str(info[x][0])) + print self.debug("------------ do queue task end ! ---------------") + time.sleep(TASK_RATE) + + +def test(): + while True: + print self.debug("no download task!") + time.sleep(1) + test() + +if __name__ == "__main__": + + dl = downloadBT() + + import threading + check_task = threading.Thread(target=dl.check_task) + check_task.start() + + completed = threading.Thread(target=dl.completed) + completed.start() + + queue = threading.Thread(target=dl.queue) + queue.start() diff --git a/plugins/qbittorrent/workers/rsync.sh b/plugins/qbittorrent/workers/rsync.sh new file mode 100755 index 000000000..311108f21 --- /dev/null +++ b/plugins/qbittorrent/workers/rsync.sh @@ -0,0 +1,5 @@ +#!/bin/bash +PATH=/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin:/usr/local/sbin:~/bin +export PATH + +echo 'hello world'