def download_video(video_url): """Callback function of the 'Download' context menu Args: video_url (str): URL of the video to download """ # print('URL Video to download ' + video_url) # Now that we have video URL we can try to download this one YDStreamUtils = __import__('YDStreamUtils') YDStreamExtractor = __import__('YDStreamExtractor') vid = YDStreamExtractor.getVideoInfo( video_url, quality=get_quality_YTDL(download_mode=True), resolve_redirects=True) if vid is None: Script.log( 'YDStreamExtractor.getVideoInfo() failed for video URL: %s' % video_url) return False path = Script.setting.get_string('dl_folder') download_ok = False with YDStreamUtils.DownloadProgress() as prog: try: YDStreamExtractor.setOutputCallback(prog) result = YDStreamExtractor.handleDownload( vid, bg=Script.setting.get_boolean('dl_background'), path=path) if result: if result.status == 'canceled': error_message = result.message Script.log('Download failed: %s' % error_message) else: full_path_to_file = result.filepath Script.log('Download success: %s' % full_path_to_file) download_ok = True finally: YDStreamExtractor.setOutputCallback(None) if path != '' and \ Script.setting.get_boolean('dl_item_filename') and \ download_ok: try: filename = os.path.basename(full_path_to_file) _, file_extension = os.path.splitext(full_path_to_file) current_filepath = os.path.join(path, filename) video_name = get_selected_item_label() final_filepath = os.path.join(path, video_name + file_extension) xbmcvfs.rename(current_filepath, final_filepath) except Exception: Script.log('Failed to rename video file') return False
def rename(path, newpath): log("FileAccess: rename " + path + " to " + newpath) try: if xbmcvfs.rename(path, newpath): return True except Exception as e: log("FileAccess: rename, Failed! %s"%(e), xbmc.LOGERROR) if path[0:6].lower() == 'smb://' or newpath[0:6].lower() == 'smb://': if os.name.lower() == 'nt': log("FileAccess: Modifying name") if path[0:6].lower() == 'smb://': path = '\\\\' + path[6:] if newpath[0:6].lower() == 'smb://': newpath = '\\\\' + newpath[6:] try: log("FileAccess: os.rename") os.rename(xbmcvfs.translatePath(path), xbmcvfs.translatePath(newpath)) return True except Exception as e: log("FileAccess: rename, Failed! %s"%(e), xbmc.LOGERROR) try: log("FileAccess: shutil.move") shutil.move(xbmcvfs.translatePath(path), xbmcvfs.translatePath(newpath)) return True except Exception as e: log("FileAccess: rename, Failed! %s"%(e), xbmc.LOGERROR) log("FileAccess: OSError") raise OSError()
def downloadVideo(title, vid): global downloadDir if not downloadDir: xbmcgui.Dialog().notification('Download:', translation(30110), _icon, 5000, False) return url, hstr = getStreamUrl(vid).split('|') if six.PY2: vidfile = xbmc.makeLegalFilename( (downloadDir + title.decode('utf-8') + '.mp4').encode('utf-8')) else: vidfile = xbmcvfs.makeLegalFilename(downloadDir + title + '.mp4') if not xbmcvfs.exists(vidfile): tmp_file = tempfile.mktemp(dir=downloadDir, suffix='.mp4') if six.PY2: tmp_file = xbmc.makeLegalFilename(tmp_file) else: tmp_file = xbmcvfs.makeLegalFilename(tmp_file) pDialog.create('Dailymotion', '{0}[CR]{1}'.format(translation(30044), title)) dfile = requests.get(url, headers=dict(urllib_parse.parse_qsl(hstr)), stream=True) totalsize = float(dfile.headers['content-length']) handle = open(tmp_file, "wb") chunks = 0 for chunk in dfile.iter_content(chunk_size=2097152): if chunk: # filter out keep-alive new chunks handle.write(chunk) chunks += 1 percent = int(float(chunks * 209715200) / totalsize) pDialog.update(percent) if pDialog.iscanceled(): handle.close() xbmcvfs.delete(tmp_file) break handle.close() try: xbmcvfs.rename(tmp_file, vidfile) return vidfile except: return tmp_file else: xbmcgui.Dialog().notification('Download:', translation(30109), _icon, 5000, False)
def downloadVideo(url, name): def _pbhook(downloaded, filesize, url=None, dp=None, name=''): try: percent = min(int((downloaded * 100) / filesize), 100) currently_downloaded = float(downloaded) / (1024 * 1024) kbps_speed = int(downloaded / (time.perf_counter() if PY3 else time.clock() - start)) if kbps_speed > 0: eta = (filesize - downloaded) / kbps_speed else: eta = 0 kbps_speed = kbps_speed / 1024 total = float(filesize) / (1024 * 1024) mbs = '%.02f MB of %.02f MB' % (currently_downloaded, total) e = 'Speed: %.02f Kb/s ' % kbps_speed e += 'ETA: %02d:%02d' % divmod(eta, 60) dp.update(percent, '{0}[CR]{1}[CR]{2}'.format(name[:50], mbs, e)) except: percent = 100 dp.update(percent) if dp.iscanceled(): dp.close() raise StopDownloading('Stopped Downloading') def getResponse(url, headers2, size): try: if size > 0: size = int(size) headers2['Range'] = 'bytes=%d-' % size req = Request(url, headers=headers2) resp = urlopen(req, timeout=30) return resp except: return None def doDownload(url, dest, dp, name): headers = {} if '|' in url: url, uheaders = url.split('|') headers = dict(urllib_parse.parse_qsl(uheaders)) if 'User-Agent' not in list(headers.keys()): headers.update({'User-Agent': USER_AGENT}) resp = getResponse(url, headers, 0) if not resp: dialog.ok("Cumination", '{0}[CR]{1}'.format(i18n('dnld_fail'), i18n('no_resp'))) return False try: content = int(resp.headers['Content-Length']) except: content = 0 try: resumable = 'bytes' in resp.headers['Accept-Ranges'].lower() except: resumable = False if resumable: six.print_("Download is resumable") if content < 1: dialog.ok("Cumination", '{0}[CR]{1}'.format(i18n('unkn_size'), i18n('no_dnld'))) return False size = 8192 mb = content / (1024 * 1024) if content < size: size = content total = 0 errors = 0 count = 0 resume = 0 sleep = 0 six.print_('{0} : {1}MB {2} '.format(i18n('file_size'), mb, dest)) f = xbmcvfs.File(dest, 'w') chunk = None chunks = [] while True: downloaded = total for c in chunks: downloaded += len(c) percent = min(100 * downloaded / content, 100) _pbhook(downloaded, content, url, dp, name) chunk = None error = False try: chunk = resp.read(size) if not chunk: if percent < 99: error = True else: while len(chunks) > 0: c = chunks.pop(0) f.write(c) del c f.close() return True except Exception as e: six.print_(str(e)) error = True sleep = 10 errno = 0 if hasattr(e, 'errno'): errno = e.errno if errno == 10035: # 'A non-blocking socket operation could not be completed immediately' pass if errno == 10054: # 'An existing connection was forcibly closed by the remote host' errors = 10 # force resume sleep = 30 if errno == 11001: # 'getaddrinfo failed' errors = 10 # force resume sleep = 30 if chunk: errors = 0 chunks.append(chunk) if len(chunks) > 5: c = chunks.pop(0) f.write(c) total += len(c) del c if error: errors += 1 count += 1 xbmc.sleep(sleep * 1000) if (resumable and errors > 0) or errors >= 10: if (not resumable and resume >= 50) or resume >= 500: # Give up! return False resume += 1 errors = 0 if resumable: chunks = [] # create new response resp = getResponse(url, headers, total) else: # use existing response pass def clean_filename(s): if not s: return '' badchars = '\\/:*?\"<>|\'' for c in badchars: s = s.replace(c, '') return s.strip() download_path = addon.getSetting('download_path') if download_path == '': try: download_path = dialog.browse(0, i18n('dnld_path'), "", "", False, False) addon.setSetting(id='download_path', value=download_path) if not xbmcvfs.exists(download_path): xbmcvfs.mkdir(download_path) except: pass if download_path != '': dp = xbmcgui.DialogProgress() name = re.sub(r'\[COLOR.+?\/COLOR\]', '', name).strip() dp.create(i18n('cum_dnld'), name[:50]) tmp_file = tempfile.mktemp(dir=download_path, suffix=".mp4") tmp_file = xbmc.makeLegalFilename(tmp_file) if PY2 else xbmcvfs.makeLegalFilename(tmp_file) start = time.perf_counter() if PY3 else time.clock() try: downloaded = doDownload(url, tmp_file, dp, name) if downloaded: if PY2: vidfile = xbmc.makeLegalFilename(download_path + clean_filename(name) + ".mp4") else: vidfile = xbmcvfs.makeLegalFilename(download_path + clean_filename(name) + ".mp4") try: xbmcvfs.rename(tmp_file, vidfile) return vidfile except: return tmp_file else: raise StopDownloading(i18n('stop_dnld')) except: while xbmcvfs.exists(tmp_file): try: xbmcvfs.delete(tmp_file) break except: pass