def play(self, driveid, item_driveid=None, item_id=None): find_subtitles = self._addon.getSetting( 'set_subtitle') == 'true' and self._content_type == 'video' item = self.get_item(driveid, item_driveid, item_id, find_subtitles=find_subtitles) file_name = Utils.unicode(item['name']) list_item = xbmcgui.ListItem(file_name) if 'audio' in item: list_item.setInfo('music', item['audio']) elif 'video' in item: list_item.addStreamInfo('video', item['video']) list_item.select(True) list_item.setPath( DownloadServiceUtil.build_download_url( self._addonid, driveid, item_driveid, item_id, urllib.quote(Utils.str(file_name)))) list_item.setProperty('mimetype', Utils.get_safe_value(item, 'mimetype')) if find_subtitles and 'subtitles' in item: subtitles = [] for subtitle in item['subtitles']: subtitles.append( DownloadServiceUtil.build_download_url( self._addonid, driveid, Utils.default( Utils.get_safe_value(subtitle, 'drive_id'), driveid), subtitle['id'], urllib.quote(Utils.str(subtitle['name'])))) list_item.setSubtitles(subtitles) xbmcplugin.setResolvedUrl(self._addon_handle, True, list_item)
def _run_export(self, driveid, item_id=None): export_manager = ExportManager(self._account_manager._addon_data_path) export = export_manager.load()[item_id] Logger.debug('Running export:') Logger.debug(export) if Utils.get_safe_value(export, 'exporting', False): self._dialog.ok( self._addon_name, self._common_addon.getLocalizedString(32059) + ' ' + self._common_addon.getLocalizedString(32038)) else: export['exporting'] = True export_manager.save() export_folder = export['destination_folder'] if xbmcvfs.exists(export_folder): self.get_provider().configure(self._account_manager, driveid) self._export_progress_dialog_bg.create( self._addon_name + ' ' + self._common_addon.getLocalizedString(32024), self._common_addon.getLocalizedString(32025)) self._export_progress_dialog_bg.update(0) item = self.get_provider().get_item(export['item_driveid'], item_id) if self.cancel_operation(): return if self._child_count_supported: self._exporting_target = int(item['folder']['child_count']) self._exporting_target += 1 folder_name = Utils.unicode(item['name']) folder_path = os.path.join( os.path.join(export_folder, folder_name), '') if self._addon.getSetting( 'clean_folder') != 'true' or not xbmcvfs.exists( folder_path) or self._remove_folder(folder_path): self._exporting = item_id export_items_info = {} ExportManager.add_item_info(export_items_info, item_id, folder_name, folder_path, None) self.__export_folder(driveid, item, export_folder, export, export_items_info) export_manager.save_items_info(item_id, export_items_info) if Utils.get_safe_value(export, 'update_library', False) and self._content_type: database = self._content_type if database == 'audio': database = 'music' KodiUtils.update_library(database) else: error = self._common_addon.getLocalizedString( 32066) % folder_path Logger.debug(error) self._dialog.ok(self._addon_name, error) self._export_progress_dialog_bg.close() else: error = self._common_addon.getLocalizedString( 32026) % export_folder Logger.debug(error) self._dialog.ok(self._addon_name, error) export['exporting'] = False export_manager.save()
def _select_stream_format(self, driveid, item_driveid=None, item_id=None): url = None self._progress_dialog.update(0, self._addon.getLocalizedString(32009)) self._provider.configure(self._account_manager, driveid) self.get_item(driveid, item_driveid, item_id) request = Request('https://drive.google.com/get_video_info', urllib.urlencode({'docid' : item_id}), {'authorization': 'Bearer %s' % self._provider.get_access_tokens()['access_token']}) response_text = request.request() response_params = dict(urlparse.parse_qsl(response_text)) self._progress_dialog.close() if Utils.get_safe_value(response_params, 'status', '') == 'ok': fmt_list = Utils.get_safe_value(response_params, 'fmt_list', '').split(',') stream_formats = [self._addon.getLocalizedString(32015)] for fmt in fmt_list: data = fmt.split('/') stream_formats.append(data[1]) select = self._dialog.select(self._addon.getLocalizedString(32016), stream_formats, 8000) if select > 0: data = fmt_list[select-1].split('/') fmt_stream_map = Utils.get_safe_value(response_params, 'fmt_stream_map', '').split(',') for fmt in fmt_stream_map: stream_data = fmt.split('|') if stream_data[0] == data[0]: url = stream_data[1] break if url: cookie_header = '' for cookie in request.response_cookies: if cookie_header: cookie_header += ';' cookie_header += cookie.name + '=' + cookie.value; url += '|cookie=' + urllib.quote(cookie_header) return url;
def get_item(self, driveid, item_driveid=None, item_id=None, path=None, find_subtitles=False, include_download_info=False): self._provider.configure(self._account_manager, driveid) item_driveid = Utils.default(item_driveid, driveid) cache_key = self._addonid+'-drive-'+driveid+'-item_driveid-'+Utils.str(item_driveid)+'-item_id-'+Utils.str(item_id)+'-path-'+Utils.str(path) f = self._cache.get(cache_key) if not f : if item_id: f = self._provider.get('/drives/'+item_driveid+'/items/' + item_id, parameters = self._extra_parameters) elif path == 'sharedWithMe' or path == 'recent': return else: if path == '/': path = 'root' else: parts = path.split('/') if len(parts) > 1 and not parts[0]: path = 'root:'+path+':' f = self._provider.get('/drives/'+driveid+'/' + path, parameters = self._extra_parameters) self._cache.set(cache_key, f, expiration=datetime.timedelta(seconds=59)) item = self._extract_item(f, include_download_info) if find_subtitles: subtitles = [] parent_id = Utils.get_safe_value(Utils.get_safe_value(f, 'parentReference', {}), 'id') search_url = '/drives/'+item_driveid+'/items/' + parent_id + '/search(q=\'{'+urllib.quote(Utils.remove_extension(item['name']))+'}\')' files = self._provider.get(search_url) for f in files['value']: subtitle = self._extract_item(f, include_download_info) if subtitle['name_extension'] == 'srt' or subtitle['name_extension'] == 'sub' or subtitle['name_extension'] == 'sbv': subtitles.append(subtitle) if subtitles: item['subtitles'] = subtitles return item
def get_drives(self, request_params=None, access_tokens=None): drives = [] drives_id_list = [] try: response = self.get('/drives', request_params=request_params, access_tokens=access_tokens) for drive in response['value']: drives_id_list.append(drive['id']) drives.append({ 'id': drive['id'], 'name': Utils.get_safe_value(drive, 'name', ''), 'type': drive['driveType'] }) except RequestException as ex: httpex = ExceptionUtils.extract_exception(ex, HTTPError) if not httpex or httpex.code != 403: raise ex response = self.get('/me/drives', request_params=request_params, access_tokens=access_tokens) for drive in response['value']: if not drive['id'] in drives_id_list: drives_id_list.append(drive['id']) drives.append({ 'id': drive['id'], 'name': Utils.get_safe_value(drive, 'name', ''), 'type': drive['driveType'] }) return drives
def do_POST(self): content = Utils.get_file_buffer() data = self.path.split('/') if len(data) > 1 and data[1] == self.server.service.name: try: size = int(self.headers.getheader('content-length', 0)) cmd = eval(self.rfile.read(size)) method = Utils.get_safe_value(cmd, 'method') if method: code = 200 args = Utils.get_safe_value(cmd, 'args', []) kwargs = Utils.get_safe_value(cmd, 'kwargs', {}) Logger.debug('Command received:\n%s' % cmd) content.write( repr(self.server.data.rpc(method, args, kwargs))) else: code = 400 content.write('Method required') except Exception as e: httpex = ExceptionUtils.extract_exception(e, HTTPError) if httpex: code = httpex.code else: code = 500 content.write(ExceptionUtils.full_stacktrace(e)) else: code = 404 self.write_response(code, content=content)
def process_schedules(self, export_map, now, startup=False): Logger.debug('now: %s, startup: %s' % (Utils.str(now), Utils.str(startup))) export_list = [] if startup: export_list.extend( Utils.get_safe_value(export_map, self._startup_type, [])) else: key = 'run_immediately' run_immediately_list = Utils.get_safe_value(export_map, key, []) export_list.extend(run_immediately_list) at = '%02d:%02d' % ( now.hour, now.minute, ) Logger.debug('at: %s' % Utils.str(at)) daily_list = Utils.get_safe_value( export_map, Utils.str(ExportScheduleDialog._daily_type) + at, []) export_list.extend(daily_list) Logger.debug('daily_list: %s' % Utils.str(daily_list)) weekday = now.weekday() + 11 weekday_list = Utils.get_safe_value(export_map, Utils.str(weekday) + at, []) export_list.extend(weekday_list) Logger.debug('weekday_list: %s' % Utils.str(weekday_list)) Logger.debug('export_list: %s' % Utils.str(export_list)) for export in export_list: self.run_export(export)
def process_files(self, files, parameters, on_items_page_completed=None, include_download_info=False): items = [] if files: is_album = Utils.get_safe_value(files, 'is_album', False) is_media_items = Utils.get_safe_value(files, 'is_media_items', False) if is_album: collection = 'albums' elif is_media_items: collection = 'mediaItems' else: collection = 'files' if collection in files: for f in files[collection]: f['is_album'] = is_album f['is_media_items'] = is_media_items item = self._extract_item(f, include_download_info) items.append(item) if on_items_page_completed: on_items_page_completed(items) if 'nextPageToken' in files: parameters['pageToken'] = files['nextPageToken'] next_files = self.get('/files', parameters=parameters) if self.cancel_operation(): return next_files['is_album'] = is_album items.extend( self.process_files(next_files, parameters, on_items_page_completed, include_download_info)) return items
def run_export(self, export): exporting = Utils.get_safe_value(export, 'exporting', False) Logger.debug('Run export requested. Exporting = %s' % (exporting, )) if not exporting: export['exporting'] = True export['origin'] = 'schedule' self.export_manager.save_export(export) try: self._export_progress_dialog_bg.create( self._addon_name + ' ' + self._common_addon.getLocalizedString(32024), self._common_addon.getLocalizedString(32025)) export_folder = export['destination_folder'] if not KodiUtils.file_exists(export_folder): Logger.debug('creating folder: %s' % (export_folder, )) if not KodiUtils.mkdirs(export_folder): Logger.debug('unable to create folder %s' % (export_folder, )) if KodiUtils.file_exists(export_folder): driveid = export['driveid'] self.provider.configure(self._account_manager, driveid) exportid = export['id'] items_info = {} ExportManager.add_item_info(items_info, 'root-folder', None, export_folder, None, 'folder') self.export_manager.save_items_info(exportid, items_info) item = self.provider.get_item(export['item_driveid'], exportid) item.update({ 'parent': 'root-folder', 'origin': 'schedule' }) self.export_manager.save_pending_changes( exportid, deque([item])) self.export_manager.save_retry_changes(exportid, deque([])) self.process_pending_changes( exportid, on_before_change=self._show_progress_before_change) if Utils.get_safe_value(export, 'update_library', False): if Utils.get_safe_value(export, 'content_type', '') == 'audio': KodiUtils.update_library('music') else: KodiUtils.update_library('video') except Exception as e: ErrorReport.handle_exception(e) KodiUtils.show_notification( self._common_addon.getLocalizedString(32027) + ' ' + Utils.unicode(e)) finally: export['exporting'] = False del export['origin'] self.export_manager.save_export(export) self._export_progress_dialog_bg.close() else: KodiUtils.show_notification( self._common_addon.getLocalizedString(32059) + ' ' + self._common_addon.getLocalizedString(32038))
def _select_stream_format(self, driveid, item_driveid=None, item_id=None, auto=False): url = None if not auto: self._progress_dialog.update(0, self._addon.getLocalizedString(32009)) self._provider.configure(self._account_manager, driveid) self._provider.get_item(item_driveid, item_id) request = Request( 'https://drive.google.com/get_video_info', urllib.parse.urlencode({'docid': item_id}), { 'authorization': 'Bearer %s' % self._provider.get_access_tokens()['access_token'] }) response_text = request.request() response_params = dict(urllib.parse.parse_qsl(response_text)) if not auto: self._progress_dialog.close() if Utils.get_safe_value(response_params, 'status', '') == 'ok': fmt_list = Utils.get_safe_value(response_params, 'fmt_list', '').split(',') stream_formats = [] for fmt in fmt_list: data = fmt.split('/') stream_formats.append(data[1]) stream_formats.append(self._addon.getLocalizedString(32015)) Logger.debug('Stream formats: %s' % Utils.str(stream_formats)) select = -1 if auto: select = self._auto_select_stream(stream_formats) else: select = self._dialog.select( self._addon.getLocalizedString(32016), stream_formats, 8000, 0) Logger.debug('Selected: %s' % Utils.str(select)) if select == -1: self._cancel_operation = True elif select != len(stream_formats) - 1: data = fmt_list[select].split('/') fmt_stream_map = Utils.get_safe_value(response_params, 'fmt_stream_map', '').split(',') for fmt in fmt_stream_map: stream_data = fmt.split('|') if stream_data[0] == data[0]: url = stream_data[1] break if url: cookie_header = '' for cookie in request.response_cookies: if cookie_header: cookie_header += ';' cookie_header += cookie.name + '=' + cookie.value url += '|cookie=' + urllib.parse.quote(cookie_header) return url
def run_export(self, export): export['exporting'] = True params = { 'action': '_run_export', 'content_type': Utils.get_safe_value(export, 'content_type', ''), 'driveid': Utils.get_safe_value(export, 'driveid', ''), 'item_id': export['id'] } KodiUtils.run_plugin(self.addonid, params, False)
def get_cloud_drive_addons(self): addons = [] response = KodiUtils.execute_json_rpc('Addons.GetAddons', {'type':'xbmc.python.pluginsource', 'enabled': True, 'properties': ['dependencies', 'name']}) for addon in Utils.get_safe_value(Utils.get_safe_value(response, 'result', {}), 'addons', []): for dependency in addon['dependencies']: if dependency['addonid'] == self._addonid: addons.append(addon) break return addons
def _rename_action(self): if self._action == 'open_drive_folder': self._addon_params['path'] = Utils.get_safe_value( self._addon_params, 'folder') self._action = Utils.get_safe_value( { 'open_folder': '_list_folder', 'open_drive': '_list_drive', 'open_drive_folder': '_list_folder' }, self._action, self._action)
def process_files(self, files, parameters, on_items_page_completed=None, include_download_info=False, extra_info=None, on_before_add_item=None): items = [] if files: kind = Utils.get_safe_value(files, 'kind', '') collection = [] if kind == 'drive#fileList': collection = files['files'] elif kind == 'drive#changeList': collection = files['changes'] elif 'albums' in files: kind = 'album' collection = files['albums'] elif 'mediaItems' in files: kind = 'media_item' collection = files['mediaItems'] if collection: for f in collection: f['kind'] = Utils.get_safe_value(f, 'kind', kind) item = self._extract_item(f, include_download_info) if item: if on_before_add_item: on_before_add_item(item) items.append(item) if on_items_page_completed: on_items_page_completed(items) if type(extra_info) is dict: if 'newStartPageToken' in files: extra_info['change_token'] = files['newStartPageToken'] if 'nextPageToken' in files: parameters['pageToken'] = files['nextPageToken'] url = '/files' provider_method = self.get if kind == 'drive#changeList': url = '/changes' elif kind == 'album': url = '/albums' provider_method = self._photos_provider.get elif kind == 'media_item': url = '/mediaItems:search' provider_method = self._photos_provider.post next_files = provider_method(url, parameters=parameters) if self.cancel_operation(): return items.extend( self.process_files(next_files, parameters, on_items_page_completed, include_download_info, extra_info, on_before_add_item)) return items
def _extract_item(self, f, include_download_info=False): size = long('%s' % Utils.get_safe_value(f, 'size', 0)) item = { 'id': f['id'], 'name': f['name'], 'name_extension': Utils.get_extension(f['name']), 'drive_id': Utils.get_safe_value( Utils.get_safe_value(f, 'owners', [{}])[0], 'permissionId'), 'mimetype': Utils.get_safe_value(f, 'mimeType', ''), 'last_modified_date': Utils.get_safe_value(f, 'modifiedTime'), 'size': size, 'description': Utils.get_safe_value(f, 'description', '') } if item['mimetype'] == 'application/vnd.google-apps.folder': item['folder'] = {'child_count': 0} if 'videoMediaMetadata' in f: video = f['videoMediaMetadata'] item['video'] = { 'width': Utils.get_safe_value(video, 'width'), 'height': Utils.get_safe_value(video, 'height'), 'duration': long('%s' % Utils.get_safe_value(video, 'durationMillis', 0)) / 1000 } if 'imageMediaMetadata' in f: item['image'] = {'size': size} if 'hasThumbnail' in f and f['hasThumbnail']: item['thumbnail'] = Utils.get_safe_value(f, 'thumbnailLink') if include_download_info: parameters = { 'alt': 'media', 'access_token': self._provider.get_access_tokens()['access_token'] } url = self._provider._get_api_url() + '/files/%s' % item['id'] if 'size' not in f and item[ 'mimetype'] == 'application/vnd.google-apps.document': url += '/export' parameters['mimeType'] = self.get_mimetype_by_extension( item['name_extension']) item['download_info'] = { 'url': url + '?%s' % urllib.urlencode(parameters) } return item
def changes(self): change_token = self.get_change_token() if not change_token: change_token = Utils.get_safe_value(self.get('/changes/startPageToken', parameters = self.prepare_parameters()), 'startPageToken') extra_info = {} parameters = self.prepare_parameters() parameters['pageToken'] = change_token parameters['fields'] = 'kind,nextPageToken,newStartPageToken,changes(kind,type,removed,file(%s))' % self._get_field_parameters() f = self.get('/changes', parameters = parameters) changes = self.process_files(f, parameters, include_download_info=True, extra_info=extra_info) self.persist_change_token(Utils.get_safe_value(extra_info, 'change_token')) return changes
def get_scheduled_export_map(self): exports = self.export_manager.get_exports() export_map = {} for exportid in exports: export = exports[exportid] schedules = Utils.get_safe_value(export, 'schedules', []) exporting = Utils.get_safe_value(export, 'exporting', False) if not exporting: if Utils.get_safe_value(export, 'schedule', False) and schedules: for schedule in schedules: key = Utils.str( Utils.get_safe_value(schedule, 'type', '')) if key != self._startup_type: key += Utils.get_safe_value(schedule, 'at', '') export_map[key] = Utils.get_safe_value( export_map, key, []) export_map[key].append(export) key = 'run_immediately' if Utils.get_safe_value(export, key, False): export_map[key] = Utils.get_safe_value(export_map, key, []) export_map[key].append(export) export[key] = False self.export_manager.save_export(export) Logger.debug('scheduled export_map: %s' % Utils.str(export_map)) return export_map
def show_folder(self, driveid, path): items = self.get_folder_items(driveid, path) html, table = self.open_table('Index of ' + self.path) self.add_row(table, '../') for item in items: file_name = Utils.str(item['name']) if 'folder' in item: file_name += '/' date = Utils.default(self.date_time_string(KodiUtils.to_timestamp(Utils.get_safe_value(item, 'last_modified_date'))), ' - ') size = self.get_size(Utils.default(Utils.get_safe_value(item, 'size'), -1)) description = Utils.default(Utils.get_safe_value(item, 'description'), ' ') self.add_row(table, file_name, date, size, description) self.close_table(table) return html
def process_files(self, files, on_items_page_completed=None, include_download_info=False, extra_info=None, on_before_add_item=None): items = [] for f in files['value']: f = Utils.get_safe_value(f, 'remoteItem', f) item = self._extract_item(f, include_download_info) if on_before_add_item: on_before_add_item(item) items.append(item) if on_items_page_completed: on_items_page_completed(items) if type(extra_info) is dict: if '@odata.deltaLink' in files: extra_info['change_token'] = files['@odata.deltaLink'] if '@odata.nextLink' in files: next_files = self.get(files['@odata.nextLink']) if self.cancel_operation(): return items.extend( self.process_files(next_files, on_items_page_completed, include_download_info, extra_info, on_before_add_item)) return items
def get_strm_link(driveid, item, content_type, addon_url): item_id = Utils.str(item['id']) item_drive_id = Utils.default(Utils.get_safe_value(item, 'drive_id'), driveid) content = addon_url + '?' + urllib.urlencode( {'action': 'play', 'content_type': content_type, 'item_driveid': item_drive_id, 'item_id': item_id, 'driveid': driveid}) return Utils.str(content)
def get_context_options(self, list_item, params, is_folder): context_options = [] if Utils.get_safe_value(params, 'action', '') == 'play': p = params.copy() p['action'] = 'check_google_ban' context_options.append((self._addon.getLocalizedString(32071), 'RunPlugin('+self._addon_url + '?' + urllib.urlencode(p)+')')) return context_options
def route(self): try: Logger.debug(self._addon_params) self._action = Utils.get_safe_value(self._addon_params, 'action') if self._action: self._rename_action() method = getattr(self, self._action) arguments = {} for name in inspect.getargspec(method)[0]: if name in self._addon_params: arguments[name] = self._addon_params[name] method(**arguments) else: self.list_accounts() except Exception as ex: self._handle_exception(ex) finally: self._progress_dialog.close() self._progress_dialog_bg.close() self._export_progress_dialog_bg.close() if self._pin_dialog: self._pin_dialog.close() if self._exporting: self._export_manager = ExportManager(self._account_manager._addon_data_path) export = self._export_manager.load()[self._exporting] export['exporting'] = False self._export_manager.save()
def get_drives(self, request_params=None, access_tokens=None): drives = [{ 'id' : self._user['permissionId'], 'name' : '', 'type' : '' }] try: all_teamdrives_fetch = False page_token = None parameters = {'pageSize': 100} while not all_teamdrives_fetch: if page_token: parameters['nextPageToken'] = page_token response = self.get('/teamdrives', parameters=parameters, request_params=request_params, access_tokens=access_tokens) if response and 'teamDrives' in response: for drive in response['teamDrives']: drives.append({ 'id' : drive['id'], 'name' : Utils.get_safe_value(drive, 'name', drive['id']), 'type' : drive['kind'] }) if response and 'nextPageToken' in response: page_token = response['nextPageToken'] else: all_teamdrives_fetch = True except RequestException as ex: httpex = ExceptionUtils.extract_exception(ex, HTTPError) if not httpex or httpex.code != 403: raise ex return drives
def _wrap_on_exception(self, request_params=None): request_params = Utils.default(request_params, {}) original_on_exception = Utils.get_safe_value(request_params, 'on_exception', None) request_params['on_exception'] = lambda request, e: self._on_exception( request, e, original_on_exception) return request_params
def prepare_request(self, method, path, parameters=None, request_params=None, access_tokens=None, headers=None): parameters = Utils.default(parameters, {}) access_tokens = Utils.default(access_tokens, {}) encoded_parameters = urllib.urlencode(parameters) url = self._build_url(method, path, encoded_parameters) request_params = self._wrap_on_exception(request_params) if not headers: headers = Utils.default(self._get_request_headers(), {}) content_type = Utils.get_safe_value(headers, 'content-type', '') if content_type == 'application/json': data = json.dumps(parameters) else: data = None if method == 'get' else encoded_parameters if not access_tokens: access_tokens = self.get_access_tokens() self._validate_access_tokens(access_tokens, url, data, headers) if time.time() > (access_tokens['date'] + access_tokens['expires_in']): access_tokens.update(self.refresh_access_tokens(request_params)) self._validate_access_tokens(access_tokens, 'refresh_access_tokens', 'Unknown', 'Unknown') self.persist_access_tokens(access_tokens) headers['authorization'] = 'Bearer ' + access_tokens['access_token'] return Request(url, data, headers, **request_params)
def download_item(driveid, item, item_name): item_id = Utils.str(item['id']) item_drive_id = Utils.default(Utils.get_safe_value(item, 'drive_id'), driveid) content = DownloadServiceUtil.build_download_url( driveid, item_drive_id, item_id, item_name) return content
def _show_progress_before_change(self, change, pending_changes, changes_done, retry_changes, export): completed = len(changes_done) + len(retry_changes) target = len(pending_changes) + completed + 1 self._export_progress_dialog_bg.update( self._get_percent(completed, target), self._addon_name + ' ' + self._get_progress_header(export), Utils.get_safe_value(change, 'name', 'n/a'))
def show_folder(self, addonid, driveid, path): path_len = len(path) if path_len > 1: path = path[:path_len-1] items = RpcUtil.rpc(addonid, 'get_folder_items', kwargs={'driveid': driveid, 'path': path}) html, table = self.open_table('Index of ' + self.path) self.add_row(table, '../') for item in items: file_name = Utils.str(item['name']) if 'folder' in item: file_name += '/' date = Utils.default(self.date_time_string(KodiUtils.to_timestamp(Utils.get_safe_value(item, 'last_modified_date'))), ' - ') size = self.get_size(Utils.default(Utils.get_safe_value(item, 'size'), -1)) description = Utils.default(Utils.get_safe_value(item, 'description'), ' ') self.add_row(table, file_name, date, size, description) self.close_table(table) return html
def __export_folder(self, driveid, folder, export_folder, export, items_info): folder_id = Utils.str(folder['id']) folder_name = Utils.unicode(folder['name']) folder_path = os.path.join(os.path.join(export_folder, folder_name), '') if not xbmcvfs.exists(folder_path): try: xbmcvfs.mkdirs(folder_path) except: if self._system_monitor.waitForAbort(3): return xbmcvfs.mkdirs(folder_path) items = self.get_provider().get_folder_items( Utils.default(Utils.get_safe_value(folder, 'drive_id'), driveid), folder['id']) if self.cancel_operation(): return for item in items: if 'folder' in item: if self._child_count_supported: self._exporting_target += int( item['folder']['child_count']) else: self._exporting_target += 1 for item in items: is_folder = 'folder' in item item_id = Utils.str(item['id']) item_name = Utils.unicode(item['name']) item_name_extension = item['name_extension'] file_path = os.path.join(folder_path, item_name) if is_folder: ExportManager.add_item_info(items_info, item_id, item_name, os.path.join(file_path, ''), folder_id) self.__export_folder(driveid, item, folder_path, export, items_info) elif (('video' in item or item_name_extension in self._video_file_extensions) and export['content_type'] == 'video') or ( 'audio' in item and export['content_type'] == 'audio'): item_name += ExportManager._strm_extension file_path += ExportManager._strm_extension ExportManager.create_strm(driveid, item, file_path, export['content_type'], self._addon_url) ExportManager.add_item_info(items_info, item_id, item_name, file_path, folder_id) self._exporting_count += 1 p = int(self._exporting_count / float(self._exporting_target) * 100) if self._exporting_percent < p: self._exporting_percent = p self._export_progress_dialog_bg.update( self._exporting_percent, self._addon_name + ' ' + self._common_addon.getLocalizedString(32024), file_path[len(export['destination_folder']):])
def process_change(self, change, items_info, export): change_type = None changed_item_id = change['id'] Logger.debug('Change: %s' % Utils.str(change)) if changed_item_id != export['id']: changed_item_name = change['name'] deleted = Utils.get_safe_value(change, 'deleted') parent_id = change['parent'] is_folder = 'folder' in change if not is_folder: changed_item_name += ExportManager._strm_extension if changed_item_id in items_info: item_info = items_info[changed_item_id] Logger.debug('item_info: %s' % Utils.str(item_info)) item_info_path = item_info['full_local_path'] if KodiUtils.file_exists(item_info_path): if deleted: change_type = self.process_change_delete(items_info, changed_item_id, is_folder) elif parent_id != item_info['parent'] or changed_item_name != item_info['name']: if parent_id in items_info: change_type = 'move' Logger.debug('Change is move') parent_item_info = items_info[parent_id] parent_item_path = parent_item_info['full_local_path'] new_path = os.path.join(parent_item_path, changed_item_name) if is_folder: new_path = os.path.join(new_path, '') if KodiUtils.file_rename(item_info_path, new_path): ExportManager.remove_item_info(items_info, changed_item_id) ExportManager.add_item_info(items_info, changed_item_id, changed_item_name, new_path, parent_id) else: change_type = 'retry' else: Logger.debug('Change is move but parent not in item list. Change is delete') change_type = self.process_change_delete(items_info, changed_item_id, is_folder) else: Logger.debug('Invalid state. Changed item not found: %s. Deleting from item list.' % item_info_path) change_type = self.process_change_delete(items_info, changed_item_id, is_folder) elif parent_id in items_info and not deleted: content_type = export['content_type'] item_name_extension = change['name_extension'] if is_folder or (('video' in change or item_name_extension in self._video_file_extensions) and content_type == 'video') or ('audio' in change and content_type == 'audio'): change_type = 'add' Logger.debug('Change is new item') parent_item_info = items_info[parent_id] parent_item_path = parent_item_info['full_local_path'] new_path = os.path.join(parent_item_path, changed_item_name) if is_folder: new_path = os.path.join(new_path, '') if not KodiUtils.mkdirs(new_path): change_type = 'retry' else: ExportManager.create_strm(export['driveid'], change, new_path, content_type, 'plugin://%s/' % self.addonid) if change_type != 'retry': ExportManager.add_item_info(items_info, changed_item_id, changed_item_name, new_path, parent_id) Logger.debug('change type: %s ' % Utils.str(change_type)) return change_type
def _show_progress_after_change(self, change, change_type, pending_changes, changes_done, retry_changes, export): completed = len(changes_done) + len(retry_changes) target = len(pending_changes) + completed msg = self._common_addon.getLocalizedString(32041) if change_type: msg = Utils.get_safe_value(change, 'name', 'n/a') self._export_progress_dialog_bg.update( self._get_percent(completed, target), self._addon_name + ' ' + self._get_progress_header(export), msg)
def _extract_item(self, f, include_download_info=False): size = long('%s' % Utils.get_safe_value(f, 'size', 0)) item = { 'id': f['id'], 'name': f['name'], 'name_extension' : Utils.get_extension(f['name']), 'drive_id' : Utils.get_safe_value(Utils.get_safe_value(f, 'owners', [{}])[0], 'permissionId'), 'mimetype' : Utils.get_safe_value(f, 'mimeType', ''), 'last_modified_date' : Utils.get_safe_value(f,'modifiedTime'), 'size': size, 'description': Utils.get_safe_value(f, 'description', '') } if item['mimetype'] == 'application/vnd.google-apps.folder': item['folder'] = { 'child_count' : 0 } if 'videoMediaMetadata' in f: video = f['videoMediaMetadata'] item['video'] = { 'width' : Utils.get_safe_value(video, 'width'), 'height' : Utils.get_safe_value(video, 'height'), 'duration' : long('%s' % Utils.get_safe_value(video, 'durationMillis', 0)) / 1000 } if 'imageMediaMetadata' in f: item['image'] = { 'size' : size } if 'hasThumbnail' in f and f['hasThumbnail']: item['thumbnail'] = Utils.get_safe_value(f, 'thumbnailLink') if include_download_info: parameters = { 'alt': 'media', 'access_token': self._provider.get_access_tokens()['access_token'] } url = self._provider._get_api_url() + '/files/%s' % item['id'] if 'size' not in f and item['mimetype'] == 'application/vnd.google-apps.document': url += '/export' parameters['mimeType'] = self.get_mimetype_by_extension(item['name_extension']) item['download_info'] = { 'url' : url + '?%s' % urllib.urlencode(parameters) } return item
def get_drives(self, request_params={}, access_tokens={}): response = self.get('/drives', request_params=request_params, access_tokens=access_tokens) drives = [] drives_id_list =[] for drive in response['value']: drives_id_list.append(drive['id']) drives.append({ 'id' : drive['id'], 'name' : Utils.get_safe_value(drive, 'name', ''), 'type' : drive['driveType'] }) response = self.get('/me/drives', request_params=request_params, access_tokens=access_tokens) for drive in response['value']: if not drive['id'] in drives_id_list: drives_id_list.append(drive['id']) drives.append({ 'id' : drive['id'], 'name' : Utils.get_safe_value(drive, 'name', ''), 'type' : drive['driveType'] }) return drives
def process_files(self, driveid, files, on_items_page_completed=None): items = [] for f in files['value']: f = Utils.get_safe_value(f, 'remoteItem', f) item = self._extract_item(f) cache_key = self._addonid+'-drive-'+driveid+'-item_driveid-'+item['drive_id']+'-item_id-'+item['id']+'-path-None' self._cache.set(cache_key, f, expiration=datetime.timedelta(minutes=1)) items.append(item) if on_items_page_completed: on_items_page_completed(items) if '@odata.nextLink' in files: next_files = self._provider.get(files['@odata.nextLink']) if self.cancel_operation(): return items.extend(self.process_files(driveid, next_files, on_items_page_completed)) return items
def new_change_token_slideshow(self, change_token, driveid, item_driveid=None, item_id=None, path=None): self._provider.configure(self._account_manager, driveid) if not change_token: response = self._provider.get('/changes/startPageToken', parameters = self._parameters) self._change_token = Utils.get_safe_value(response, 'startPageToken') change_token = 1 else: page_token = self._change_token while page_token: self._parameters['pageToken'] = page_token self._parameters['fields'] = 'nextPageToken,newStartPageToken,changes(file(id,name,parents))' response = self._provider.get('/changes', parameters = self._parameters) if self.cancel_operation(): return self._change_token = Utils.get_safe_value(response, 'newStartPageToken', self._change_token) changes = Utils.get_safe_value(response, 'changes', []) for change in changes: f = Utils.get_safe_value(change, 'file', {}) parents = Utils.get_safe_value(f, 'parents', []) parents.append(f['id']) if item_id in parents: return change_token + 1 page_token = Utils.get_safe_value(response, 'nextPageToken') return change_token
def _extract_item(self, f, include_download_info=False): item = { 'id': f['id'], 'name': f['name'], 'name_extension' : Utils.get_extension(f['name']), 'drive_id' : Utils.get_safe_value(Utils.get_safe_value(f, 'parentReference', {}), 'driveId'), 'mimetype' : Utils.get_safe_value(Utils.get_safe_value(f, 'file', {}), 'mimeType'), 'last_modified_date' : Utils.get_safe_value(f,'lastModifiedDateTime'), 'size': Utils.get_safe_value(f, 'size', 0), 'description': Utils.get_safe_value(f, 'description', '') } if 'folder' in f: item['folder'] = { 'child_count' : Utils.get_safe_value(f['folder'],'childCount',0) } if 'video' in f: video = f['video'] item['video'] = { 'width' : Utils.get_safe_value(video,'width', 0), 'height' : Utils.get_safe_value(video, 'height', 0), 'duration' : Utils.get_safe_value(video, 'duration', 0) /1000 } if 'audio' in f: audio = f['audio'] item['audio'] = { 'tracknumber' : Utils.get_safe_value(audio, 'track'), 'discnumber' : Utils.get_safe_value(audio, 'disc'), 'duration' : int(Utils.get_safe_value(audio, 'duration') or '0') / 1000, 'year' : Utils.get_safe_value(audio, 'year'), 'genre' : Utils.get_safe_value(audio, 'genre'), 'album': Utils.get_safe_value(audio, 'album'), 'artist': Utils.get_safe_value(audio, 'artist'), 'title': Utils.get_safe_value(audio, 'title') } if 'image' in f or 'photo' in f: item['image'] = { 'size' : Utils.get_safe_value(f, 'size', 0) } if 'thumbnails' in f and type(f['thumbnails']) == list and len(f['thumbnails']) > 0: thumbnails = f['thumbnails'][0] item['thumbnail'] = Utils.get_safe_value(Utils.get_safe_value(thumbnails, 'large', {}), 'url', '') if include_download_info: item['download_info'] = { 'url' : Utils.get_safe_value(f,'@microsoft.graph.downloadUrl') } return item
def _rename_action(self): self._action = Utils.get_safe_value({ 'open_folder': '_list_folder', 'open_drive': '_list_drive', }, self._action, self._action)