Exemple #1
0
def RetryFailedDownloads(session):

	if AuthTools.CheckAdmin() == False:
		return MC.message_container('Admin Access Only', 'Only the Admin can perform this action !')

	items_to_change = []
	
	for each in Dict:
		if 'Down5Split' in each:
			try:
				longstringObjs = JSON.ObjectFromString(D(Dict[each]))
				if longstringObjs['status'] == common.DOWNLOAD_STATUS[3]:
					items_to_change.append(each)
			except Exception as e:
				Log("============RetryFailedDownloads=============")
				Log(e)
				
	if len(items_to_change) > 0:
		for each in items_to_change:
			file_meta_enc = Dict[each]
			file_meta = JSON.ObjectFromString(D(file_meta_enc))
			
			file_meta['status'] = common.DOWNLOAD_STATUS[0]
			file_meta['action'] = common.DOWNLOAD_ACTIONS[4]
			
			Dict[each] = E(JSON.StringFromObject(file_meta))
			
		Dict.Save()
		Thread.Create(download.trigger_que_run)
		
		time.sleep(7)

	return MC.message_container('Retry Failed', 'Failed Videos have been added to Queue')
Exemple #2
0
def PostponeDownloadingDownloads(session):

	if AuthTools.CheckAdmin() == False:
		return MC.message_container('Admin Access Only', 'Only the Admin can perform this action !')

	for each in Dict:
		if 'Down5Split' in each:
			longstringObjs = JSON.ObjectFromString(D(Dict[each]))
			if longstringObjs['status'] == common.DOWNLOAD_STATUS[1]:
				uid = longstringObjs['uid']
				longstringObjs['action'] = common.DOWNLOAD_ACTIONS[3]
				EncTxt = E(JSON.StringFromObject(longstringObjs))
				Dict[uid] = EncTxt
	
	return MC.message_container('Postpone Downloads', 'All Current Downloads have been Postponed (by 2hrs.)')
Exemple #3
0
def SetReqDownloadLocation(uid, type):

	if AuthTools.CheckAdmin() == False:
		return MC.message_container('Admin Access Only', 'Only the Admin can perform this action !')
		
	oc = ObjectContainer(title1='Select Location', no_cache=common.isForceNoCache())
	
	DOWNLOAD_OPTIONS_SECTION_TEMP = {}
	for x in common.DOWNLOAD_OPTIONS.keys():
		DOWNLOAD_OPTIONS_SECTION_TEMP[x] = common.DOWNLOAD_OPTIONS[x]
	
	for item in DOWNLOAD_OPTIONS_SECTION_TEMP[type]:
		if item['enabled']:
			oc.add(DirectoryObject(
				key = Callback(SetReqDownloadLocationSave, uid=uid, section_title=item['title'], section_key=item['key'], section_path=item['path']),
				title = '%s | %s' % (item['title'], item['path'])
				)
			)

	if len(oc) == 0:
		return MC.message_container('Download Sources', 'No Download Location set under Download Options')
	return oc
def DevToolsC(title=None, header=None, message=None, session=None, **kwargs):
	"""Tools to Remove all Covers/URLs cached files"""

	if not common.interface.isInitialized():
		return MC.message_container(common.MSG0, '%s. Progress %s%s (%s)' % (common.MSG1, common.interface.getProvidersInitStatus(), '%', common.interface.getCurrentProviderInProcess()))
		
	if AuthTools.CheckAdmin() == False:
		return MC.message_container('Admin Access Only', 'Only the Admin can perform this action !')

	oc = ObjectContainer(title2='Tools', header=header, message=message)

	if title:
		if title == 'plex_cache':
			count = ClearCache(caches_path, Datetime.Delta())
			message = 'Cleaned {} Cached files'.format(count)
			Log(u'\n----------Removed {} Cached files from {}----------'.format(count, caches_path))
		elif title == 'save_bm':
			count = SaveBookmarks()
			message = 'Saved {} Bookmarks'.format(count)
			Log(u'\n----------Saved {} Bookmarks to {}----------'.format(count, resources_path))
		elif title == 'load_bm':
			count = LoadBookmarks()
			if count == -1:
				message='Bookmarks file (bookmarks.json) does not exist in Resource folder !'
			else:
				message = 'Loaded {} Bookmarks'.format(count)
			Log(u'\n----------Loaded {} Bookmarks from {}----------'.format(count, resources_path))
		elif title == 'save_config':
			bool = SaveConfig()
			if bool == True:
				message = 'Saved Config file'
				Log(u'\n----------Saved Config to {}----------'.format(resources_path))
			else:
				message = 'Error: Could not Save Config file (config.json)'
		elif title == 'load_config':
			bool = LoadConfig()
			if bool == True:
				message = 'Loaded Config file'
				Log(u'\n----------Loaded Config from {}----------'.format(resources_path))
			else:
				message='Error: Could not Load Config file (config.json)'
		elif title == 'check_externals':
			if len(externals.BUSY_BOOL) > 0:
				message = 'Checking externals. Please wait and try again.'
			else:
				Thread.Create(externals.checkRoutine, {}, session)
				time.sleep(7)
				if len(externals.BUSY_BOOL) > 0:
					message = 'Checking externals. Please wait and try again.'
				else:
					if len(externals.CHECK_ROUTINE_LOG) > 0:
						for item in externals.CHECK_ROUTINE_LOG:
							if 'VerifiedForDownload' in item:
								comps = item.split('|')
								oc.add(DirectoryObject(title = '%s Download/Install %s %s' % (common.EMOJI_DOWNARROW3x, comps[1], common.EMOJI_DOWNARROW3x), thumb = R(common.ICON_OTHERSOURCESDOWNLOAD), key=Callback(SaveUrlToDest, filedata=E(JSON.StringFromObject(comps[2:])))))
							else:
								oc.add(DirectoryObject(title=item,key=Callback(MyMessage, 'Info', item)))
						return oc
					else:
						message = 'Could not retrieve output from externals.'
		elif title == 'set_base_url':
			oc = ObjectContainer(title2='Set Base URL')
			base_url_match = False
			for u in common.BASE_URLS:
				if u == fmovies.BASE_URL:
					base_url_match = True
				ch = common.GetEmoji(type=True) if u == fmovies.BASE_URL else common.GetEmoji(type=False)
				oc.add(DirectoryObject(title='%s | Base URL : %s' % (ch, u),key=Callback(SetBaseUrl, url=u)))
			if base_url_match == False:
				u = fmovies.BASE_URL
				ch = common.GetEmoji(type=True) if u == fmovies.BASE_URL else common.GetEmoji(type=False)
				oc.add(DirectoryObject(title='%s | Base URL : %s (set by redirection detector)' % (ch, u),key=Callback(SetBaseUrl, url=u)))
				
			return oc
		elif title == 'set_9base_url':
			oc = ObjectContainer(title2='Set 9Anime Base URL')
			base9_url_match = False
			for d in common.ANIME_DOMS:
				u = 'https://%s.%s' % (common.ANIME_KEY, d)
				if u == common.ANIME_URL:
					base9_url_match = True
				ch = common.GetEmoji(type=True) if u == common.ANIME_URL else common.GetEmoji(type=False)
				oc.add(DirectoryObject(title='%s | 9Anime Base URL : %s' % (ch, u),key=Callback(Set9BaseUrl, url=u)))
			if base9_url_match == False:
				u = common.ANIME_URL
				ch = common.GetEmoji(type=True) if u == common.ANIME_URL else common.GetEmoji(type=False)
				oc.add(DirectoryObject(title='%s | 9Anime Base URL : %s (set by redirection detector)' % (ch, u),key=Callback(Set9BaseUrl, url=u)))
				
			return oc
		elif title == 'set_ext_list_url':
			oc = ObjectContainer(title2='Set External Listing URL')
			ext_list_url_match = False
			for u in common.EXT_LIST_URLS:
				if u == common.ES_API_URL:
					ext_list_url_match = True
				ch = common.GetEmoji(type=True) if u == common.ES_API_URL else common.GetEmoji(type=False)
				oc.add(DirectoryObject(title='%s | External Listing URL : %s' % (ch, u),key=Callback(SetExtListUrl, url=u)))
			if ext_list_url_match == False:
				u = common.ES_API_URL
				ch = common.GetEmoji(type=True) if u == common.ES_API_URL else common.GetEmoji(type=False)
				oc.add(DirectoryObject(title='%s | External Listing URL : %s (set by redirection detector)' % (ch, u),key=Callback(SetExtListUrl, url=u)))
				
			return oc
		elif title == 'openload_input_id':
			oc = ObjectContainer(title2='OpenLoad Video ID')
			if common.UsingOption(key=common.DEVICE_OPTIONS[0], session=session):
				DumbKeyboard(PREFIX, oc, openloadID,
						dktitle = 'OpenLoad Video ID'
				)
			else:
				oc.add(InputDirectoryObject(key = Callback(openloadID, session = session), title='OpenLoad Video ID', summary='OpenLoad Video ID', prompt='OpenLoad Video ID...'))
				for q in RECENT_IMDB_SEARCHES.keys():
					q_msg = '%s (%s) | %s | %s | %s' % (RECENT_IMDB_SEARCHES[q]['title'], RECENT_IMDB_SEARCHES[q]['year'], RECENT_IMDB_SEARCHES[q]['file_size'], RECENT_IMDB_SEARCHES[q]['quality'], RECENT_IMDB_SEARCHES[q]['rip'])
					q_sum = q_msg if RECENT_IMDB_SEARCHES[q]['summary'] == None else RECENT_IMDB_SEARCHES[q]['summary']
					data = RECENT_IMDB_SEARCHES[q]['data']
					oc.add(DirectoryObject(title=q_msg, summary=q_sum, thumb=RECENT_IMDB_SEARCHES[q]['thumb'],key=Callback(openloadID, query=q, dataIMDb=data, direct=True, session=session)))
				if len(RECENT_IMDB_SEARCHES.keys()) > 0:
					oc.add(DirectoryObject(title='Clear Recent Items',key=Callback(clearRecentOpenLoadID), thumb=R(common.ICON_CLEAR)))
			return oc
		elif title == 'imdb_input_id':
			oc = ObjectContainer(title2='Input IMDb ID')
			if common.UsingOption(key=common.DEVICE_OPTIONS[0], session=session):
				DumbKeyboard(PREFIX, oc, imdbID,
						dktitle = 'Input IMDb ID'
				)
			else:
				oc.add(InputDirectoryObject(key = Callback(imdbID, session = session), title='Input IMDb ID', summary='Input IMDb ID', prompt='Input IMDb ID...'))
				
			for q in RECENT_IMDB_SEARCHES.keys():
				q_msg = '%s (%s) | %s | %s | %s' % (RECENT_IMDB_SEARCHES[q]['title'], RECENT_IMDB_SEARCHES[q]['year'], RECENT_IMDB_SEARCHES[q]['file_size'], RECENT_IMDB_SEARCHES[q]['quality'], RECENT_IMDB_SEARCHES[q]['rip'])
				q_sum = q_msg if RECENT_IMDB_SEARCHES[q]['summary'] == None else RECENT_IMDB_SEARCHES[q]['summary']
				data = RECENT_IMDB_SEARCHES[q]['data']
				oc.add(DirectoryObject(title=q_msg, summary=q_sum, thumb=RECENT_IMDB_SEARCHES[q]['thumb'],key=Callback(openloadID, query=q, dataIMDb=data, direct=True, session=session)))
			if len(RECENT_IMDB_SEARCHES.keys()) > 0:
				oc.add(DirectoryObject(title='Clear Recent Items',key=Callback(clearRecentOpenLoadID), thumb=R(common.ICON_CLEAR)))
				
			return oc

		return MC.message_container('Info', message)

	# oc.add(DirectoryObject(key=Callback(DevToolsC, title='plex_cache', session=session),
		# title=u'Reset {} Cache'.format(PLEX_CACHE_DIR),
		# thumb = R(common.ICON_TOOLS),
		# summary=u'Remove cached files from {} directory.'.format(caches_path)))
	oc.add(DirectoryObject(key=Callback(DevToolsC, title='save_bm', session=session),
		title=u'Save Bookmarks',
		thumb = R(common.ICON_FL_SAVE),
		summary=u'Save Bookmarks to the Resource dir. (file: bookmarks.json)'))
	oc.add(DirectoryObject(key=Callback(DevToolsC, title='load_bm', session=session),
		title=u'Load Bookmarks',
		thumb = R(common.ICON_FL_LOAD),
		summary=u'Load Bookmarks from the Resource dir. (file: bookmarks.json)'))
	oc.add(DirectoryObject(key=Callback(DevToolsC, title='save_config', session=session),
		title=u'Save Config',
		thumb = R(common.ICON_FL_SAVE),
		summary=u'Save Config to the Resource dir. (file: config.json). Device Options (all clients), Bookmarks, Recent WatchList, SearchQue, Downloads and Interface Options can be saved and restored using Config file.'))
	oc.add(DirectoryObject(key=Callback(DevToolsC, title='load_config', session=session),
		title=u'Load Config',
		thumb = R(common.ICON_FL_LOAD),
		summary=u'Load Config from the Resource dir. (file: config.json). Device Options (all clients), Bookmarks, Recent WatchList, SearchQue, Downloads and Interface Options can be saved and restored using Config file.'))
	oc.add(DirectoryObject(key=Callback(DevToolsC, title='check_externals', session=session),
		title=u'Check Externals',
		thumb = R(common.ICON_TOOLS),
		summary=u'Check externals like PhantomJS and Cryptodome have been installed or not'))
	oc.add(DirectoryObject(key=Callback(DevToolsC, title='set_base_url', session=session),
		title=u'Set Base URL',
		thumb = R(common.ICON_TOOLS),
		summary=u'Set the Base URL to be used by the Channel'))
	oc.add(DirectoryObject(key=Callback(DevToolsC, title='set_9base_url', session=session),
		title=u'Set 9Anime Base URL',
		thumb = R(common.ICON_TOOLS),
		summary=u'Set the 9Anime Base URL to be used by the Channel'))
	oc.add(DirectoryObject(key=Callback(DevToolsC, title='set_ext_list_url', session=session),
		title=u'Set External Listing URL',
		thumb = R(common.ICON_TOOLS),
		summary=u'Set the External Listing URL to be used by the Channel'))
	oc.add(DirectoryObject(key=Callback(DevToolsC, title='openload_input_id', session=session),
		title=u'OpenLoad Video ID',
		thumb = Resource.ContentsOfURLWithFallback(url = common.ICON_OPENLOAD, fallback=common.ICON_TOOLS),
		summary=u'OpenLoad Video ID'))
		
	cc = Dict['VSPAPI']['count']
	if common.control.get_setting('control_videospider_api_key') == None and cc >= common.control.setting('vspapicount'):
		videospider_msg = u'IMDb Video Search (requires VideoSpider API Key in Prefs)'
	else:
		if common.control.get_setting('control_videospider_api_key') != None:
			videospider_msg = u'IMDb Video Search (via VideoSpider) | User API Key'
		else:
			videospider_msg = u'IMDb Video Search (via VideoSpider) | %s Free Trials left' % (common.control.setting('vspapicount')-cc)
		
	oc.add(DirectoryObject(key=Callback(DevToolsC, title='imdb_input_id', session=session),
		title=videospider_msg,
		thumb = Resource.ContentsOfURLWithFallback(url = common.ICON_IMDB, fallback=common.ICON_TOOLS),
		summary=videospider_msg))

	oc.add(DirectoryObject(key = Callback(main.MainMenu), title = '<< Main Menu', thumb = R(common.ICON)))
	return oc
Exemple #5
0
def ClearDownLoadSection(status, session, confirm=False):

	if AuthTools.CheckAdmin() == False:
		return MC.message_container('Admin Access Only', 'Only the Admin can perform this action !')

	if confirm == False:
		oc = ObjectContainer(title1=unicode('Confirm ?'), no_cache=common.isForceNoCache())
		oc.add(DirectoryObject(title = 'YES - Clear %s Entries' % status, key = Callback(ClearDownLoadSection, status=status, session=session, confirm=True),thumb = R(common.ICON_OK)))
		oc.add(DirectoryObject(title = 'NO - Dont Clear %s Entries' % status, key = Callback(MyMessage, title='No Selected', msg='Return to previous screen'),thumb = R(common.ICON_NOTOK)))
		return oc

	items_to_del = []
	
	for each in Dict:
		if 'Down5Split' in each:
			try:
				longstringObjs = JSON.ObjectFromString(D(Dict[each]))
				if longstringObjs['status'] == status or status == common.DOWNLOAD_STATUS[5]:
					items_to_del.append(each)
				elif longstringObjs['status'] not in common.DOWNLOAD_STATUS:
					items_to_del.append(each)
			except Exception as e:
				Log("=============ClearDownLoadSection Error============")
				Log(e)
				
	if len(items_to_del) > 0:
		for each in items_to_del:
			if status == common.DOWNLOAD_STATUS[1]: # Downloading
				longstringObjs = JSON.ObjectFromString(D(Dict[each]))
				longstringObjs['action'] = common.DOWNLOAD_ACTIONS[0]
				uid = longstringObjs['uid']
				EncTxt = E(JSON.StringFromObject(longstringObjs))
				Dict[uid] = EncTxt
			elif status == common.DOWNLOAD_STATUS[3]: # Failed
				longstringObjs = JSON.ObjectFromString(D(Dict[each]))
				if 'temp_file' in longstringObjs:
					filepath = longstringObjs['temp_file']
					try:
						Core.storage.remove_data_item(filepath)
					except Exception as e:
						Log("=============ClearDownLoadSection Error============")
						Log(e)
				del Dict[each]
			elif status == common.DOWNLOAD_STATUS[5]: # All
				longstringObjs = JSON.ObjectFromString(D(Dict[each]))
				if longstringObjs['status'] == common.DOWNLOAD_STATUS[1]: # Downloading
					longstringObjs['action'] = common.DOWNLOAD_ACTIONS[0]
					uid = longstringObjs['uid']
					EncTxt = E(JSON.StringFromObject(longstringObjs))
					Dict[uid] = EncTxt
				elif longstringObjs['status'] == common.DOWNLOAD_STATUS[3]: # Failed
					if 'temp_file' in longstringObjs:
						filepath = longstringObjs['temp_file']
						try:
							Core.storage.remove_data_item(filepath)
						except Exception as e:
							Log("=============ClearDownLoadSection Error============")
							Log(e)
					del Dict[each]
				else:
					del Dict[each]
			else: # Queued, Completed
				del Dict[each]
		Dict.Save()
		
		if status == common.DOWNLOAD_STATUS[1]:
			time.sleep(7)

	return MC.message_container('Clear %s' % status, 'Download %s Videos Cleared' % status)
Exemple #6
0
def DownloadingFilesMenu(title, uid, choice=None, session=None, status=None, confirm=False, refresh=0):
	
	oc = ObjectContainer(title1=title, no_cache=common.isForceNoCache())
	
	if choice == None and uid in Dict:
		try:
			longstringObjs = JSON.ObjectFromString(D(Dict[uid]))
			#status = longstringObjs['status']
			fileinfo = longstringObjs
			
			if status == common.DOWNLOAD_STATUS[1]:
				if uid in common.DOWNLOAD_STATS.keys():
					fileinfo = common.DOWNLOAD_STATS[uid]
				else:
					pass #fileinfo = Dict[uid]
				try:
					eta = float(fileinfo['eta'])
				except:
					eta = '?'
					
				if eta == '?' or str(eta) == '0':
					eta_str = 'calculating time'
				elif eta < 0.1:
					eta_str = 'almost done'
				elif eta < 1:
					eta_str = '%02d sec. remaining' % int(int(float(eta) * 60.0))
				elif eta > 60:
					eta_str = '%s hr. %02d min. %02d sec. remaining' % (int(int(eta)/60), (float(int(int(eta)/60))-float(int((float(eta)/60.0)/100)*100)), int(60 * (float(eta) - float(int(eta)))))
				else:
					eta_str = '%s min. %02d sec. remaining' % (int(eta), int(60 * (float(eta) - float(int(eta)))))
				
				i_title = '%s | %s | %s MB/s ~ %s MB/s ~ %s MB/s | %s - %s | %s' % (str(fileinfo['progress'])+'%', eta_str, str(fileinfo['chunk_speed']), str(fileinfo['avg_speed_curr']), str(fileinfo['avg_speed']), fileinfo['fs'], fileinfo['quality'], common.DOWNLOAD_ACTIONS_K[fileinfo['action']])
			else:
				i_title = '%s | %s MB/s ~ %s MB/s ~ %s MB/s | %s - %s | %s' % (str(fileinfo['progress'])+'%', str(fileinfo['chunk_speed']), str(fileinfo['avg_speed_curr']), str(fileinfo['avg_speed']), fileinfo['fs'], fileinfo['quality'], common.DOWNLOAD_ACTIONS_K[fileinfo['action']])
			i_title = unicode(i_title)
			oc.add(DirectoryObject(
				title = i_title,
				summary = i_title,
				key = Callback(MyMessage, title='Info', msg=i_title),
				thumb = common.GetThumb(R(common.ICON_ENTER), session=session)
				)
			)
			
			c = 0
			for opt in common.DOWNLOAD_ACTIONS:
				if (status == common.DOWNLOAD_STATUS[0] and opt in [common.DOWNLOAD_ACTIONS[0], common.DOWNLOAD_ACTIONS[3], common.DOWNLOAD_ACTIONS[4]]) or (status == common.DOWNLOAD_STATUS[1] and opt in [common.DOWNLOAD_ACTIONS[0], common.DOWNLOAD_ACTIONS[1], common.DOWNLOAD_ACTIONS[2], common.DOWNLOAD_ACTIONS[3]]) or (status == common.DOWNLOAD_STATUS[3] and opt in [common.DOWNLOAD_ACTIONS[0], common.DOWNLOAD_ACTIONS[4]]) or (status == common.DOWNLOAD_STATUS[4] and opt in [common.DOWNLOAD_ACTIONS[0], common.DOWNLOAD_ACTIONS[4]]):
					if longstringObjs['action'] != opt and not (opt == common.DOWNLOAD_ACTIONS[2] and longstringObjs['action'] == common.DOWNLOAD_ACTIONS[4]) or status == common.DOWNLOAD_STATUS[3] and not(status == common.DOWNLOAD_STATUS[1] and longstringObjs['action'] in [common.DOWNLOAD_ACTIONS[2], common.DOWNLOAD_ACTIONS[4]]):
						opt_txt = opt
						if opt == common.DOWNLOAD_ACTIONS[3] or (opt == common.DOWNLOAD_ACTIONS[4] and longstringObjs['progress'] != '?' and float(longstringObjs['progress']) > 0):
							postpone_subtext = '(resumable download)' if longstringObjs['resumable']==True else '(non-resumable download)'
							opt_txt = '%s %s' % (opt,postpone_subtext) 
						oc.add(DirectoryObject(
							title = opt_txt,
							summary = common.DOWNLOAD_ACTIONS_INFO[c],
							key = Callback(DownloadingFilesMenu, title=title, uid=uid, choice=opt, session=session, status=status),
							thumb = common.GetThumb(R(common.ICON_ENTER), session=session)
							)
						)
				c += 1
			if longstringObjs['section_key'] == None:
				oc.add(DirectoryObject(
					title = 'Set Download Location',
					summary = '%s | Download path: %s' % (longstringObjs['section_title'], longstringObjs['section_path']),
					key = Callback(SetReqDownloadLocation, uid=longstringObjs['uid'], type=longstringObjs['type']),
					thumb = common.GetThumb(R(common.ICON_ENTER), session=session)
					)
				)
			else:
				oc.add(DirectoryObject(
					title = '%s | Download path: %s' % (longstringObjs['section_title'], longstringObjs['section_path']),
					summary = '%s | Download path: %s' % (longstringObjs['section_title'], longstringObjs['section_path']),
					key = Callback(MyMessage, title='Download Path', msg=longstringObjs['section_path']),
					thumb = common.GetThumb(R(common.ICON_ENTER), session=session)
					)
				)
			if longstringObjs['purl'] != None:
				oc.add(DirectoryObject(
					title = 'Video Page (Other Download Sources)',
					summary = 'Video Page: %s' % longstringObjs['title'],
					key = Callback(main.EpisodeDetail, title=longstringObjs['title'], url=longstringObjs['purl'], thumb=longstringObjs['thumb'], session = session),
					thumb = common.GetThumb(R(common.ICON_ENTER), session=session)
					)
				)
			else:
				oc.add(DirectoryObject(
					title = 'Video Page (Unavailable)',
					summary = 'Video Page: %s' % longstringObjs['title'],
					key = Callback(MyMessage, title='Video Page', msg='This Video Page is Unavailable'),
					thumb = common.GetThumb(R(common.ICON_ENTER), session=session)
					)
				)
			if status == common.DOWNLOAD_STATUS[2]:
				oc.add(DirectoryObject(
					title = 'Clear',
					key = Callback(DownloadingFilesMenu, title=longstringObjs['title'], uid=uid, choice=common.DOWNLOAD_ACTIONS[0], session=session, status=status),
					summary = 'Clear %s' % longstringObjs['title'],
					thumb = common.GetThumb(R(common.ICON_ENTER), session=session)
					)
				)
			oc.add(DirectoryObject(
				title = 'Refresh',
				key = Callback(DownloadingFilesMenu, title=title, uid=uid, choice=choice, session=session, status=status, confirm=confirm, refresh=int(refresh)+1),
				summary = 'Refresh Stats for %s' % longstringObjs['title'],
				thumb = common.GetThumb(R(common.ICON_REFRESH), session=session)
				)
			)
		except Exception as e:
			Log(e)
			return MC.message_container('Unavailable', 'Item removed or no longer available')

		return oc
		
	else:
		if AuthTools.CheckAdmin() == False:
			return MC.message_container('Admin Access Only', 'Only the Admin can perform this action !')
		
		if uid in Dict and choice != None:
			if choice == common.DOWNLOAD_ACTIONS[0] and confirm == False:
				oc = ObjectContainer(title1=unicode('Confirm ?'), no_cache=common.isForceNoCache())
				oc.add(DirectoryObject(title = 'YES - Clear %s Entry' % title, key = Callback(DownloadingFilesMenu, title=title, uid=uid, choice=choice, session=session, status=status, confirm=True), thumb = R(common.ICON_OK)))
				oc.add(DirectoryObject(title = 'NO - Dont Clear %s Entry' % title, key = Callback(MyMessage, title='No Selected', msg='Return to previous screen'),thumb = R(common.ICON_NOTOK)))
				return oc
			
			longstringObjs = JSON.ObjectFromString(D(Dict[uid]))
			longstringObjs['action'] = choice
			status = longstringObjs['status']
			doTrigger = True
				
			if status == common.DOWNLOAD_STATUS[0]: # Queued
				if choice == common.DOWNLOAD_ACTIONS[0]:
					if 'temp_file' in longstringObjs:
						filepath = longstringObjs['temp_file']
						try:
							Core.storage.remove_data_item(filepath)
						except Exception as e:
							Log("=============ClearDownLoadSection Error============")
							Log(e)
					del Dict[uid]
				elif choice == common.DOWNLOAD_ACTIONS[4]:
					longstringObjs['timeAdded'] = time.time()
					#doTrigger = True
					EncTxt = E(JSON.StringFromObject(longstringObjs))
					Dict[uid] = EncTxt	
			elif status == common.DOWNLOAD_STATUS[1]: # Downloading
				uid = longstringObjs['uid']
				if uid in common.DOWNLOAD_STATS.keys():
					EncTxt = E(JSON.StringFromObject(longstringObjs))
					Dict[uid] = EncTxt
				else:
					if uid in Dict.keys():
						del Dict[uid]
					if uid in common.DOWNLOAD_TEMP.keys():
						del common.DOWNLOAD_TEMP[uid]
					try:
						DOWNLOAD_TEMP = Dict['DOWNLOAD_TEMP']
						DOWNLOAD_TEMP = JSON.ObjectFromString(D(DOWNLOAD_TEMP))
						if uid in DOWNLOAD_TEMP.keys():
							del DOWNLOAD_TEMP[uid]
							Dict['DOWNLOAD_TEMP'] = E(JSON.StringFromObject(DOWNLOAD_TEMP))
					except:
						pass
			elif status == common.DOWNLOAD_STATUS[2]: # Completed
				uid = longstringObjs['uid']
				if choice == common.DOWNLOAD_ACTIONS[0]:
					del Dict[uid]
			elif status == common.DOWNLOAD_STATUS[3]: # Failed
				#doTrigger = True
				if choice in [common.DOWNLOAD_ACTIONS[2], common.DOWNLOAD_ACTIONS[4]]:
					longstringObjs['status'] = common.DOWNLOAD_STATUS[0]
					EncTxt = E(JSON.StringFromObject(longstringObjs))
					Dict[uid] = EncTxt
				elif choice == common.DOWNLOAD_ACTIONS[3]:
					longstringObjs['status'] = common.DOWNLOAD_STATUS[0]
					longstringObjs['timeAdded'] = time.time() + float(60*60*2)
					EncTxt = E(JSON.StringFromObject(longstringObjs))
					Dict[uid] = EncTxt
				elif choice == common.DOWNLOAD_ACTIONS[0]:
					if 'temp_file' in longstringObjs:
						filepath = longstringObjs['temp_file']
						try:
							Core.storage.remove_data_item(filepath)
						except Exception as e:
							Log("=============ClearDownLoadSection Error============")
							Log(e)
					del Dict[uid]
			elif status == common.DOWNLOAD_STATUS[4]: # Requested
				uid = longstringObjs['uid']
				if choice == common.DOWNLOAD_ACTIONS[0]:
					del Dict[uid]
				elif choice == common.DOWNLOAD_ACTIONS[4]:
					if longstringObjs['section_key'] == None:
						return MC.message_container('Define Location', 'Please define Download Location first !')
					longstringObjs['status'] = common.DOWNLOAD_STATUS[0]
					longstringObjs['timeAdded'] = time.time()
					EncTxt = E(JSON.StringFromObject(longstringObjs))
					Dict[uid] = EncTxt

			Dict.Save()
			
			if doTrigger == True:
				Thread.Create(download.trigger_que_run)
			
			time.sleep(2)
			
			if choice == common.DOWNLOAD_ACTIONS[3]:
				return MC.message_container('%s' % choice, '%s (by 2 hrs.) applied to %s' % (choice, title))
			return MC.message_container('%s' % choice, '%s applied to %s' % (choice, title))
		else:
			return MC.message_container('Unavailable', 'Item removed or no longer available')
Exemple #7
0
def Downloads(title, session = None, status = None, refresh = 0, **kwargs):

	if not common.interface.isInitialized():
		return MC.message_container("Please wait..", "Please wait a few seconds for the Interface to Load & Initialize plugins")
	
	oc = ObjectContainer(title1=title, no_cache=common.isForceNoCache())
	
	if status == None:
		N_status = {}
		for dstatus in common.DOWNLOAD_STATUS:
			c = 0
			for each in Dict:
				if 'Down5Split' in each:
					try:
						longstringObjs = JSON.ObjectFromString(D(Dict[each]))
						if longstringObjs['status'] == dstatus  or dstatus == common.DOWNLOAD_STATUS[5]:
							c += 1
					except Exception as e:
						Log('ERROR: Downloads >> %s' % e)
			N_status[dstatus] = c
		for statusx in common.DOWNLOAD_STATUS:
			oc.add(DirectoryObject(
				key = Callback(Downloads, title="%s Downloads" % statusx, status = statusx, session = session),
				title = '%s (%s)' % (statusx, str(N_status[statusx]))
				)
			)
		return oc
	
	items_to_del = []
	doTrigger = False
	
	for each in Dict:
		if 'Down5Split' in each:
			try:
				longstringObjs = JSON.ObjectFromString(D(Dict[each]))
				if longstringObjs['status'] == status or status == common.DOWNLOAD_STATUS[5]:
					timestr = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(float(longstringObjs['timeAdded'])))
					key = None
					summary = longstringObjs['summary']
					has_sub = False if longstringObjs['sub_url'] == None else True
					
					if status == common.DOWNLOAD_STATUS[0]: # Queued
						wtitle = '%s (%s) | %s | %s - %s | %s | %s - %s | %s | Subtitle:%s' % (longstringObjs['title'], longstringObjs['year'], longstringObjs['type'].title(), longstringObjs['fs'], longstringObjs['quality'], longstringObjs['source'], longstringObjs['status'], common.DOWNLOAD_ACTIONS_K[longstringObjs['action']], str(longstringObjs['progress'])+'%', common.GetEmoji(type=has_sub, mode='simple', session=session))
						key = Callback(DownloadingFilesMenu, title=longstringObjs['title'], uid=longstringObjs['uid'], choice=None, session=session, status=status)
					elif status == common.DOWNLOAD_STATUS[1]: # Downloading
						if each not in common.DOWNLOAD_STATS.keys() and len(common.DOWNLOAD_STATS.keys()) < int(Prefs['download_connections']):
							longstringObjs['status'] = common.DOWNLOAD_STATUS[1]
							longstringObjs['action'] = common.DOWNLOAD_ACTIONS[4]
							Dict[each] = E(JSON.StringFromObject(longstringObjs))
							
							#longstringObjs['status'] = common.DOWNLOAD_STATUS[1]
							#common.DOWNLOAD_STATS[each] = Dict[each]
							#doTrigger = True
							
							EncTxt = E(JSON.StringFromObject(longstringObjs))
							Thread.Create(download.do_download, {}, file_meta_enc=EncTxt)
						elif each not in common.DOWNLOAD_STATS.keys():
							longstringObjs['status'] = common.DOWNLOAD_STATUS[0]
							longstringObjs['action'] = common.DOWNLOAD_ACTIONS[4]
							Dict[each] = E(JSON.StringFromObject(longstringObjs))
							doTrigger = True
						else:
							longstringObjs = common.DOWNLOAD_STATS[each]
							
						try:
							eta = float(longstringObjs['eta'])
						except:
							eta = '?'
							
						if eta == '?' or str(eta) == '0':
							eta_str = 'calculating time'
						elif eta < 0.1:
							eta_str = 'almost done'
						elif eta < 1:
							eta_str = '%02d sec. remaining' % int(int(float(eta) * 60.0))
						elif eta > 60:
							eta_str = '%s hr. %02d min. %02d sec. remaining' % (int(int(eta)/60), (float(int(int(eta)/60))-float(int((float(eta)/60.0)/100)*100)), int(60 * (float(eta) - float(int(eta)))))
						else:
							eta_str = '%s min. %02d sec. remaining' % (int(eta), int(60 * (float(eta) - float(int(eta)))))
							
						wtitle = '%s (%s) | %s | %s - %s | %s | %s - %s | %s | %s MB/s ~ %s MB/s ~ %s MB/s | %s | Subtitle:%s' % (longstringObjs['title'], longstringObjs['year'], longstringObjs['type'].title(), longstringObjs['fs'], longstringObjs['quality'], longstringObjs['source'], longstringObjs['status'], common.DOWNLOAD_ACTIONS_K[longstringObjs['action']], str(longstringObjs['progress'])+'%', str(longstringObjs['chunk_speed']), str(longstringObjs['avg_speed_curr']), str(longstringObjs['avg_speed']), str(eta_str), common.GetEmoji(type=has_sub, mode='simple', session=session))
						key = Callback(DownloadingFilesMenu, title=longstringObjs['title'], uid=longstringObjs['uid'], choice=None, session=session, status=status)
					elif status == common.DOWNLOAD_STATUS[2]: # Completed
						wtitle = '%s (%s) | %s | %s - %s | %s | %s - %s | %s | %s MB/s | Subtitle:%s' % (longstringObjs['title'], longstringObjs['year'], longstringObjs['type'].title(), longstringObjs['fs'], longstringObjs['quality'], longstringObjs['source'], longstringObjs['status'], common.DOWNLOAD_ACTIONS_K[longstringObjs['action']], str(longstringObjs['progress'])+'%', str(longstringObjs['avg_speed_curr']), common.GetEmoji(type=has_sub, mode='simple', session=session))
						key = Callback(DownloadingFilesMenu, title=longstringObjs['title'], uid=longstringObjs['uid'], choice=None, session=session, status=status)
					elif status == common.DOWNLOAD_STATUS[3]: # Failed
						err = longstringObjs['last_error'] if longstringObjs['error'] == '' else longstringObjs['error']
						wtitle = '%s (%s) | %s | %s - %s | %s | %s | %s - %s' % (longstringObjs['title'], longstringObjs['year'], longstringObjs['type'].title(), longstringObjs['fs'], longstringObjs['quality'], longstringObjs['source'], str(longstringObjs['progress'])+'%', longstringObjs['status'], err)
						key = Callback(DownloadingFilesMenu, title=longstringObjs['title'], uid=longstringObjs['uid'], choice=None, session=session, status=status)
						summary = '%s | %s' % (wtitle, summary)
					elif status == common.DOWNLOAD_STATUS[4]: # Requested
						if 'user' in longstringObjs.keys() and longstringObjs['user'] != None and AuthTools.CheckAdmin() == True:
							wtitle = '%s (%s) | %s | %s - %s | %s | %s (by %s) - %s | %s | %s MB/s | Subtitle:%s' % (longstringObjs['title'], longstringObjs['year'], longstringObjs['type'].title(), longstringObjs['fs'], longstringObjs['quality'], longstringObjs['source'], longstringObjs['status'], longstringObjs['user'], common.DOWNLOAD_ACTIONS_K[longstringObjs['action']], str(longstringObjs['progress'])+'%', str(longstringObjs['avg_speed_curr']), common.GetEmoji(type=has_sub, mode='simple', session=session))
						else:
							wtitle = '%s (%s) | %s | %s - %s | %s | %s - %s | %s | %s MB/s | Subtitle:%s' % (longstringObjs['title'], longstringObjs['year'], longstringObjs['type'].title(), longstringObjs['fs'], longstringObjs['quality'], longstringObjs['source'], longstringObjs['status'], common.DOWNLOAD_ACTIONS_K[longstringObjs['action']], str(longstringObjs['progress'])+'%', str(longstringObjs['avg_speed_curr']), common.GetEmoji(type=has_sub, mode='simple', session=session))
						key = Callback(DownloadingFilesMenu, title=longstringObjs['title'], uid=longstringObjs['uid'], choice=None, session=session, status=status)
					elif status == common.DOWNLOAD_STATUS[5]: # All
						if longstringObjs['status'] == common.DOWNLOAD_STATUS[1]: # Downloading
							if each not in common.DOWNLOAD_STATS.keys() and len(common.DOWNLOAD_STATS.keys()) < int(Prefs['download_connections']):
								longstringObjs['status'] = common.DOWNLOAD_STATUS[1]
								longstringObjs['action'] = common.DOWNLOAD_ACTIONS[4]
								Dict[each] = E(JSON.StringFromObject(longstringObjs))
								
								EncTxt = E(JSON.StringFromObject(longstringObjs))
								Thread.Create(download.do_download, {}, file_meta_enc=EncTxt)
							elif each not in common.DOWNLOAD_STATS.keys():
								longstringObjs['status'] = common.DOWNLOAD_STATUS[0]
								longstringObjs['action'] = common.DOWNLOAD_ACTIONS[4]
								Dict[each] = E(JSON.StringFromObject(longstringObjs))
								doTrigger = True
							else:
								longstringObjs = common.DOWNLOAD_STATS[each]
								
							try:
								eta = float(longstringObjs['eta'])
							except:
								eta = '?'
								
							if eta == '?' or str(eta) == '0':
								eta_str = 'calculating time'
							elif eta < 0.1:
								eta_str = 'almost done'
							elif eta < 1:
								eta_str = '%02d sec. remaining' % int(int(float(eta) * 60.0))
							elif eta > 60:
								eta_str = '%s hr. %02d min. %02d sec. remaining' % (int(int(eta)/60), (float(int(int(eta)/60))-float(int((float(eta)/60.0)/100)*100)), int(60 * (float(eta) - float(int(eta)))))
							else:
								eta_str = '%s min. %02d sec. remaining' % (int(eta), int(60 * (float(eta) - float(int(eta)))))
								
							wtitle = '%s (%s) | %s | %s - %s | %s | %s - %s | %s | %s MB/s ~ %s MB/s ~ %s MB/s | %s | Subtitle:%s' % (longstringObjs['title'], longstringObjs['year'], longstringObjs['type'].title(), longstringObjs['fs'], longstringObjs['quality'], longstringObjs['source'], longstringObjs['status'], common.DOWNLOAD_ACTIONS_K[longstringObjs['action']], str(longstringObjs['progress'])+'%', str(longstringObjs['chunk_speed']), str(longstringObjs['avg_speed_curr']), str(longstringObjs['avg_speed']), str(eta_str), common.GetEmoji(type=has_sub, mode='simple', session=session))
						else:
							wtitle = '%s (%s) | %s | %s - %s | %s | %s - %s | %s | %s MB/s | Subtitle:%s' % (longstringObjs['title'], longstringObjs['year'], longstringObjs['type'].title(), longstringObjs['fs'], longstringObjs['quality'], longstringObjs['source'], longstringObjs['status'], common.DOWNLOAD_ACTIONS_K[longstringObjs['action']], str(longstringObjs['progress'])+'%', str(longstringObjs['avg_speed_curr']), common.GetEmoji(type=has_sub, mode='simple', session=session))
							
						key = Callback(DownloadingFilesMenu, title=longstringObjs['title'], uid=longstringObjs['uid'], choice=None, session=session, status=longstringObjs['status'])
						
					oc.add(DirectoryObject(
						title = wtitle,
						key = key,
						thumb = common.GetThumb(longstringObjs['thumb'], session=session),
						tagline = timestr,
						summary = summary
						)
					)
			except Exception as e:
				Log("==============Downloads==============")
				#Log(longstringObjs)
				Log(e)
				#Log(common.DOWNLOAD_STATS)
				items_to_del.append(each)
				
	if len(items_to_del) > 0:
		for each in items_to_del:
			if each in common.DOWNLOAD_STATS.keys():
				del common.DOWNLOAD_STATS[each]
				
			try:
				encoded_str = Dict[each]
				decoded_str = D(encoded_str)
				longstringObjs = JSON.ObjectFromString(decoded_str)
				Log(longstringObjs)
				if 'temp_file' in longstringObjs:
					filepath = longstringObjs['temp_file']
					try:
						Core.storage.remove_data_item(filepath)
					except Exception as e:
						Log("=============ClearDownLoadSection Error============")
						Log(e)
				Log("Deleting: %s" % longstringObjs['title'])
				del Dict[each]
			except:
				Log("Deleting: %s" % each)
				del Dict[each]
			
		Dict.Save()
	
	if doTrigger == True:
		Thread.Create(download.trigger_que_run)

	if len(oc) == 0:
		return MC.message_container(title, 'No %s section videos available' % status)
			
	oc.objects.sort(key=lambda obj: obj.tagline, reverse=True)
		
	if status != None:
		if status == common.DOWNLOAD_STATUS[3]:
			oc.add(DirectoryObject(
				title = 'Retry All Downloads',
				key = Callback(RetryFailedDownloads, session=session),
				summary = 'Retry Failed Downloads',
				thumb = common.GetThumb(R(common.ICON_REFRESH), session=session)
				)
			)
		elif status == common.DOWNLOAD_STATUS[1]:
			oc.add(DirectoryObject(
				title = 'Pause %s Downloads' % status,
				key = Callback(PauseDownloadingDownloads, session=session),
				summary = 'Pause %s Download Entries' % status,
				thumb = common.GetThumb(R(common.ICON_ENTER), session=session)
				)
			)
			oc.add(DirectoryObject(
				title = 'Postpone %s Downloads' % status,
				key = Callback(PostponeDownloadingDownloads, session=session),
				summary = 'Postpone %s Download Entries' % status,
				thumb = common.GetThumb(R(common.ICON_ENTER), session=session)
				)
			)
		oc.add(DirectoryObject(
			title = 'Refresh %s Downloads' % status,
			key = Callback(Downloads,title="%s Downloads" % status, status=status, session=session, refresh=int(refresh)+1),
			summary = 'Refresh %s Download Entries' % status,
			thumb = common.GetThumb(R(common.ICON_REFRESH), session=session)
			)
		)
		oc.add(DirectoryObject(
			title = 'Clear %s Downloads' % status,
			key = Callback(ClearDownLoadSection, status=status, session=session),
			summary = 'Remove %s Download Entries' % status,
			thumb = common.GetThumb(R(common.ICON_NOTOK), session=session)
			)
		)
		
	#oc.objects.sort(key=lambda obj: obj.title, reverse=False)
		
	return oc
Exemple #8
0
def DevToolsC(title=None, header=None, message=None, **kwargs):
    """Tools to Remove all Covers/URLs cached files"""

    if not common.interface.isInitialized():
        return MC.message_container(
            "Please wait..",
            "Please wait a few seconds for the Interface to Load & Initialize plugins"
        )

    if AuthTools.CheckAdmin() == False:
        return MC.message_container(
            'Admin Access Only', 'Only the Admin can perform this action !')

    oc = ObjectContainer(title2='Tools', header=header, message=message)

    if title:
        if title == 'plex_cache':
            count = ClearCache(caches_path, Datetime.Delta())
            message = 'Cleaned {} Cached files'.format(count)
            Log(u'\n----------Removed {} Cached files from {}----------'.
                format(count, caches_path))
        elif title == 'save_bm':
            count = SaveBookmarks()
            message = 'Saved {} Bookmarks'.format(count)
            Log(u'\n----------Saved {} Bookmarks to {}----------'.format(
                count, resources_path))
        elif title == 'load_bm':
            count = LoadBookmarks()
            if count == -1:
                message = 'Bookmarks file (bookmarks.json) does not exist in Resource folder !'
            else:
                message = 'Loaded {} Bookmarks'.format(count)
            Log(u'\n----------Loaded {} Bookmarks from {}----------'.format(
                count, resources_path))
        elif title == 'save_config':
            bool = SaveConfig()
            if bool == True:
                message = 'Saved Config file'
                Log(u'\n----------Saved Config to {}----------'.format(
                    resources_path))
            else:
                message = 'Error: Could not Save Config file (config.json)'
        elif title == 'load_config':
            bool = LoadConfig()
            if bool == True:
                message = 'Loaded Config file'
                Log(u'\n----------Loaded Config from {}----------'.format(
                    resources_path))
            else:
                message = 'Error: Could not Load Config file (config.json)'
        elif title == 'check_externals':
            if len(externals.BUSY_BOOL) > 0:
                message = 'Checking externals. Please wait and try again.'
            else:
                Thread.Create(externals.checkRoutine)
                time.sleep(7)
                if len(externals.BUSY_BOOL) > 0:
                    message = 'Checking externals. Please wait and try again.'
                else:
                    if len(externals.CHECK_ROUTINE_LOG) > 0:
                        for item in externals.CHECK_ROUTINE_LOG:
                            oc.add(
                                DirectoryObject(title=item,
                                                key=Callback(
                                                    MyMessage, 'Info', item)))
                        return oc
                    else:
                        message = 'Could not retrieve output from externals.'
        elif title == 'set_base_url':
            base_urls = [
                "https://fmovies.is", "https://fmovies.to",
                "https://fmovies.se", "https://bmovies.is",
                "https://bmovies.to", "https://bmovies.pro",
                "https://bmovies.online", "https://bmovies.club",
                "https://bmovies.ru"
            ]
            oc = ObjectContainer(title2='Set Base URL')
            for u in base_urls:
                ch = common.GetEmoji(
                    type=True) if u == fmovies.BASE_URL else common.GetEmoji(
                        type=False)
                oc.add(
                    DirectoryObject(title='%s | Base URL : %s' % (ch, u),
                                    key=Callback(SetBaseUrl, url=u)))
            return oc

        return MC.message_container('Info', message)

    # oc.add(DirectoryObject(key=Callback(DevToolsC, title='plex_cache'),
    # title=u'Reset {} Cache'.format(PLEX_CACHE_DIR),
    # thumb = R(ICON_TOOLS),
    # summary=u'Remove cached files from {} directory.'.format(caches_path)))
    oc.add(
        DirectoryObject(
            key=Callback(DevToolsC, title='save_bm'),
            title=u'Save Bookmarks',
            thumb=R(ICON_TOOLS),
            summary=
            u'Save Bookmarks to the Resource dir. (file: bookmarks.json)'))
    oc.add(
        DirectoryObject(
            key=Callback(DevToolsC, title='load_bm'),
            title=u'Load Bookmarks',
            thumb=R(ICON_TOOLS),
            summary=
            u'Load Bookmarks from the Resource dir. (file: bookmarks.json)'))
    oc.add(
        DirectoryObject(
            key=Callback(DevToolsC, title='save_config'),
            title=u'Save Config',
            thumb=R(ICON_TOOLS),
            summary=
            u'Save Config to the Resource dir. (file: config.json). Device Options (all clients), Bookmarks, Recent WatchList, SearchQue, Downloads and Interface Options can be saved and restored using Config file.'
        ))
    oc.add(
        DirectoryObject(
            key=Callback(DevToolsC, title='load_config'),
            title=u'Load Config',
            thumb=R(ICON_TOOLS),
            summary=
            u'Load Config from the Resource dir. (file: config.json). Device Options (all clients), Bookmarks, Recent WatchList, SearchQue, Downloads and Interface Options can be saved and restored using Config file.'
        ))
    oc.add(
        DirectoryObject(
            key=Callback(DevToolsC, title='check_externals'),
            title=u'Check Externals',
            thumb=R(ICON_TOOLS),
            summary=
            u'Check externals like PhantomJS and Cryptodome have been installed or not'
        ))
    oc.add(
        DirectoryObject(key=Callback(DevToolsC, title='set_base_url'),
                        title=u'Set Base URL',
                        thumb=R(ICON_TOOLS),
                        summary=u'Set the Base URL to be used by the Channel'))

    return oc