diff --git a/youtube_dlc/downloader/common.py b/youtube_dlc/downloader/common.py index 460364a0b..8803c5a95 100644 --- a/youtube_dlc/downloader/common.py +++ b/youtube_dlc/downloader/common.py @@ -7,6 +7,7 @@ import time import random from ..compat import compat_os_name +from ..heartbeat import Heartbeat from ..utils import ( decodeArgument, encodeFilename, @@ -369,6 +370,12 @@ class FileDownloader(object): '[download] Sleeping %s seconds...' % ( int(sleep_interval_sub))) time.sleep(sleep_interval_sub) + + if info_dict.get('heartbeat'): + self.heartbeat = Heartbeat(self.ydl, info_dict.get('heartbeat')) + self.add_progress_hook(self.heartbeat.check_download_status) + self.heartbeat.start() + return self.real_download(filename, info_dict) def real_download(self, filename, info_dict): diff --git a/youtube_dlc/heartbeat.py b/youtube_dlc/heartbeat.py new file mode 100644 index 000000000..a7d3229a3 --- /dev/null +++ b/youtube_dlc/heartbeat.py @@ -0,0 +1,51 @@ +import time +import threading +import traceback + +from .utils import ( + sanitized_Request +) + + +class Heartbeat(object): + def __init__(self, ydl, params): + self.ydl = ydl + + data = params.get('data') + if type(data) is str: + data = data.encode() + self.request = sanitized_Request( + params.get('url'), + data=data, + headers=params.get('headers', {}), + method=params.get('method') + ) + + self.interval = params.get('interval') + self.stopped = False + self.thread = threading.Thread(target=self.__heartbeat, daemon=True) + + def start(self): + if self.ydl.params.get('verbose'): + self.ydl.to_screen('[heartbeat] Heartbeat every %s seconds' % self.interval) + self.thread.start() + + def stop(self): + self.stopped = True + + def check_download_status(self, progress): + status = progress.get('status') + if status == 'finished' or status == 'error': + self.stop() + + def __heartbeat(self): + while not self.stopped: + try: + if self.ydl.params.get('verbose'): + self.ydl.to_screen('[heartbeat]') + self.ydl.urlopen(self.request) + except Exception: + if self.ydl.params.get('verbose'): + traceback.print_exc() + self.ydl.to_screen("[heartbeat] Heartbeat failed") + time.sleep(self.interval)