def create_legal_filename(title, year): filename = title if year: filename += ' %s' % (year) filename = re.sub(r'(?!%s)[^\w\-_\.]', '.', filename) filename = re.sub('\.+', '.', filename) xbmc.makeLegalFilename(filename) return filename
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 download_media(url, path, file_name, translations, progress=None): try: if progress is None: progress = int(kodi.get_setting('down_progress')) i18n = translations.i18n active = not progress == PROGRESS.OFF background = progress == PROGRESS.BACKGROUND with kodi.ProgressDialog(kodi.get_name(), i18n('downloading') % (file_name), background=background, active=active) as pd: try: headers = dict([ item.split('=') for item in (url.split('|')[1]).split('&') ]) for key in headers: headers[key] = urllib.unquote(headers[key]) except: headers = {} if 'User-Agent' not in headers: headers['User-Agent'] = BROWSER_UA request = urllib2.Request(url.split('|')[0], headers=headers) response = urllib2.urlopen(request) if 'Content-Length' in response.info(): content_length = int(response.info()['Content-Length']) else: content_length = 0 file_name += '.' + get_extension(url, response) full_path = os.path.join(path, file_name) logger.log('Downloading: %s -> %s' % (url, full_path), log_utils.LOGDEBUG) path = kodi.translate_path(xbmc.makeLegalFilename(path)) try: try: xbmcvfs.mkdirs(path) except: os.makedirs(path) except Exception as e: logger.log('Path Create Failed: %s (%s)' % (e, path), log_utils.LOGDEBUG) if not path.endswith(os.sep): path += os.sep if not xbmcvfs.exists(path): raise Exception(i18n('failed_create_dir')) file_desc = xbmcvfs.File(full_path, 'w') total_len = 0 cancel = False while True: data = response.read(CHUNK_SIZE) if not data: break if pd.is_canceled(): cancel = True break total_len += len(data) if not file_desc.write(data): raise Exception(i18n('failed_write_file')) percent_progress = ( total_len ) * 100 / content_length if content_length > 0 else 0 logger.log( 'Position : %s / %s = %s%%' % (total_len, content_length, percent_progress), log_utils.LOGDEBUG) pd.update(percent_progress) file_desc.close() if not cancel: kodi.notify(msg=i18n('download_complete') % (file_name), duration=5000) logger.log('Download Complete: %s -> %s' % (url, full_path), log_utils.LOGDEBUG) except Exception as e: logger.log( 'Error (%s) during download: %s -> %s' % (str(e), url, file_name), log_utils.LOGERROR) kodi.notify(msg=i18n('download_error') % (str(e), file_name), duration=5000)
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