Skip to content

Commit 9ca5316

Browse files
committed
Add sftp
1 parent 7bb2d10 commit 9ca5316

File tree

3 files changed

+72
-4
lines changed

3 files changed

+72
-4
lines changed

config.yml

+13-2
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,20 @@ qbitorrent:
1414
password: "" # qbittorrent password
1515
port: 8080 # qbitorrent port
1616

17-
ftp:
17+
# Either use ftp or sftp depending on your remote.
18+
# Only one of those 2 dict should be filles
19+
# If not, ftp will prevail
20+
ftp: {}
21+
#domain: "" # FTP hostname
22+
#port: 21 # FTP port
23+
#user: "" # FTP user
24+
#password: "" # FTP password
25+
# Remote path on the FTP server
26+
#remote_path: "" # Example: "/torrents/qbittorrent/"
27+
28+
sftp:
1829
domain: "" # FTP hostname
19-
port: 21 # FTP port
30+
port: 22 # FTP port
2031
user: "" # FTP user
2132
password: "" # FTP password
2233
# Remote path on the FTP server

qbit_watcher/sftp.py

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
import logging
2+
import shutil
3+
4+
from pysftp import Connection, CnOpts
5+
from pathlib import Path
6+
7+
LOGGER = logging.getLogger(__name__)
8+
9+
class TorrentSftp:
10+
def __init__(self, conf, dest_folder, toaster):
11+
self.conf = conf
12+
self.dest = dest_folder
13+
self.sftp = self.get_client()
14+
self.toaster = toaster
15+
16+
def get_client(self):
17+
cnopts = CnOpts()
18+
cnopts.hostkeys = None
19+
sftp = Connection(
20+
self.conf['domain'],
21+
username=self.conf['user'],
22+
password=self.conf['password'],
23+
cnopts=cnopts,
24+
default_path=self.conf['remote_path']
25+
)
26+
LOGGER.info("Successfully connected to '%s' SFTP server", self.conf['domain'])
27+
return sftp
28+
29+
def download(self, fname):
30+
"""
31+
Download torrent to local workstation
32+
"""
33+
LOGGER.info("Retrieving '%s'" % fname)
34+
if self.sftp.isfile(fname):
35+
self.sftp.get(fname, localpath="%s/%s" %(self.dest, fname))
36+
elif self.sftp.isdir(fname):
37+
# Cannot get folder if its already exists on local.
38+
# Therefore remove it before downloading again
39+
path = Path("%s/%s" % (self.dest, fname))
40+
if path.exists():
41+
shutil.rmtree(path)
42+
self.sftp.get_r(fname, self.dest)
43+
else:
44+
LOGGER.info("No file to download found")
45+
return
46+
self.toaster.notif("%s is downloaded" % (fname))
47+
48+
def close(self):
49+
self.sftp.close()

qbit_watcher/watcher.py

+10-2
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
from qbit_watcher.qbittorrent import QBittorrent
99
from qbit_watcher.ftp import TorrentFTP
10+
from qbit_watcher.sftp import TorrentSftp
1011
from qbit_watcher.toaster import TorrentToaster
1112

1213
from watchdog.events import FileSystemEventHandler
@@ -41,8 +42,15 @@ def manage(self, torrent_filename, torrent_name):
4142
if client.torrent_complete(torrent_name):
4243
break
4344

44-
ftpCli = TorrentFTP(self.conf['ftp'], self.dest_folder, self.toaster)
45-
ftpCli.download(torrent_name)
45+
if self.conf['ftp']:
46+
LOGGER.info("Using FTP")
47+
ftpCli = TorrentFTP(self.conf['ftp'], self.dest_folder, self.toaster)
48+
ftpCli.download(torrent_name)
49+
elif self.conf['sftp']:
50+
LOGGER.info("Using SFTP")
51+
sftpCli = TorrentSftp(self.conf['sftp'], self.dest_folder, self.toaster)
52+
sftpCli.download(torrent_name)
53+
sftpCli.close()
4654

4755
def on_modified(self, event):
4856
"""

0 commit comments

Comments
 (0)