def ranking_system(ranking): if misc.is_str(ranking) or misc.is_int(ranking): return True elif not misc.is_dict(ranking): return False nodes = ranking.get('Nodes') if nodes is None: return '"Nodes" property required' is_list = misc.is_list(nodes) if not is_list and not misc.is_str(nodes): return '"Nodes" property must be a list or a string containing a XML structure' for key, value in ranking.items(): if key == 'Nodes': pass elif key == 'Rank' and is_list: if not misc.is_str(value) or value not in ('Lower', 'Higher', 'Summation'): return '"Rank" property is invalid' elif key == 'Method': if not misc.is_str(value) or value.lower( ) not in cons.RANKING_METHOD: return '"Method" property is invalid' else: return f'Unexpected "{key}" property' if is_list: ret = screen_ranking_nodes(nodes) if not misc.is_bool(ret) or not ret: return ret return True
def data_p123_uids(val): if misc.is_int(val): val = [val] elif misc.is_str(val): val = val.split(' ') if not misc.is_list(val): return False for item in val: try: int(item) except ValueError: return False return True
def validate_data_settings(settings, logger: logging.Logger): if 'Start Date' not in settings: logger.error( '"Default Settings" section needs to contain the "Start Date" property' ) return False items_def_cnt = 0 items_def_cnt += 1 if 'P123 UIDs' in settings else 0 items_def_cnt += 1 if 'Tickers' in settings else 0 items_def_cnt += 1 if 'Cusips' in settings else 0 items_def_cnt += 1 if 'Gvkeys' in settings else 0 items_def_cnt += 1 if 'Ciks' in settings else 0 if not items_def_cnt: logger.error( '"Default Settings" section needs to contain one of the following properties: ' '"P123 UIDs", "Tickers", "Cusips", "Gvkeys" or "Ciks"') return False if items_def_cnt > 1: logger.error( '"Default Settings" section can only contain one of the following properties: ' '"P123 UIDs", "Tickers", "Cusips", "Gvkeys" or "Ciks"') return False if 'P123 UIDs' in settings: items = settings['P123 UIDs'] elif 'Tickers' in settings: items = settings['Tickers'] elif 'Cusips' in settings: items = settings['Cusips'] elif 'Gvkeys' in settings: items = settings['Gvkeys'] else: items = settings['Ciks'] if misc.is_int(items): items = [items] elif misc.is_str(items): items = items.split(' ') items_cnt = len(items) if items_cnt > 100: logger.error('"Default Settings" can only contain at most 100 ' '"P123 UIDs", "Tickers", "Cusips", "Gvkeys" or "Ciks"') return False return True
async def select_button(self, button, interaction): if interaction.user.id == self.ctx.author.id: await interaction.response.defer() bm_page = None if self.parent.code in self.bot.user_data['UserData'][str(self.ctx.author.id)]['Lists']['Built-in']['Bookmarks|*n*|bm']: bm_page = self.bot.user_data['UserData'][str(self.ctx.author.id)]['Lists']['Built-in']['Bookmarks|*n*|bm'][self.parent.code] conf = await self.parent.am_channel.send(embed=Embed( description=localization[self.parent.language]['page_reader']['select_inquiry']['description'] ).set_footer( text=localization[self.parent.language]['page_reader']['select_inquiry']['footer'].format(bookmarked_page=str(bm_page+1) if bm_page else 'N/A'))) while True: try: m = await self.bot.wait_for("message", timeout=15, bypass_cooldown=True, check=lambda m: m.author.id == self.ctx.author.id and m.channel.id == self.parent.am_channel.id) except TimeoutError: await conf.delete() break else: with suppress(Forbidden): await m.delete() if m.content == "n-cancel": await conf.delete() break if is_int(m.content) and (int(m.content)-1) in range(0, len(self.parent.images)): await conf.delete() self.parent.current_page = int(m.content)-1 return self.stop() else: with suppress(Forbidden): await m.delete() continue
def screen_ranking(*, value, settings: dict, api_client: Client): if misc.is_str(value) or misc.is_int(value): return value params = {} if 'Formula' in value: params['formula'] = value['Formula'] if 'Lower is Better' in value: params['lowerIsBetter'] = value['Lower is Better'] else: nodes = value['Nodes'] if misc.is_list(nodes): nodes = screen_ranking_nodes_to_xml(nodes, main_rank=value.get('Rank')) rank_params = {'type': settings['Type'], 'nodes': nodes} if 'Method' in value: rank_params['rankingMethod'] = cons.RANKING_METHOD[value['Method'].lower()] api_client.rank_update(rank_params) params = 'ApiRankingSystem' return params
async def select_button(self, button, interaction): if interaction.user.id == self.ctx.author.id: await interaction.response.defer() conf = await self.ctx.send(embed=Embed( description=localization[self.parent.language]['results_browser']['buttons']['select'])) while True: try: m = await self.bot.wait_for("message", timeout=15, bypass_cooldown=True, check=lambda m: m.author.id == self.ctx.author.id and m.channel.id == self.ctx.channel.id) except TimeoutError: await conf.delete() self.stop() return else: with suppress(Forbidden): await m.delete() if m.content == "n-cancel": await conf.delete() self.stop() return if is_int(m.content) and (int(m.content)-1) in range(0, len(self.parent.doujins)): await conf.delete() self.parent.index = int(m.content)-1 self.stop() return else: continue self.stop() # unreachable, but just to be consistant with design
def data_formula(val): return misc.is_int(val) or misc.is_str(val)
def data_tickers_cusips(val): return misc.is_int(val) or misc.is_str(val) or misc.is_list(val)
def rank_perf_buckets(val): return misc.is_int(val) and 1 <= val <= 20
def screen_rolling_backtest_holding_period(val): return misc.is_int(val) and 1 <= val <= 730
async def start(self): def payload_check( payload): # Use raw payload to compensate for the longer wait return \ payload.message_id==self.active_message.id and \ payload.user_id==self.ctx.author.id and \ str(payload.emoji) in ["⏮", "⏭", "🔢", "⏹", "⏯", "▶", "❌"] while True: try: payload = await self.bot.wait_for("raw_reaction_add", timeout=60 * 5, check=payload_check) except BotInteractionCooldown: continue except TimeoutError: with suppress(NotFound): await self.active_message.clear_reactions() self.am_embed.description = "" self.am_embed.set_footer( text= f"You timed out on page [{self.current_page+1}/{len(self.images)}].\n" ) self.am_embed.set_image(url=Embed.Empty) self.am_embed.set_thumbnail(url=Embed.Empty) await self.active_message.edit(embed=self.am_embed) await self.am_channel.send( content= f"{self.ctx.author.mention}, you timed out in your doujin. Forgot to press pause?", delete_after=1) await sleep(10) await self.active_message.edit( content= "<a:nreader_loading:810936543401213953> Closing...", embed=None) await sleep(1) await self.am_channel.delete() break except BotInteractionCooldown: continue else: self.bot.inactive = 0 with suppress(Forbidden): user = await self.bot.fetch_user(payload.user_id) await self.active_message.remove_reaction( str(payload.emoji), user) if str(payload.emoji) == "⏭": # Next page self.current_page = self.current_page + 1 if self.current_page > ( len(self.images) - 1): # Finish the doujin if at last page await self.active_message.clear_reactions() self.am_embed.set_image(url=Embed.Empty) self.am_embed.set_thumbnail(url=Embed.Empty) self.am_embed.description = Embed.Empty self.am_embed.set_footer( text="You finished this doujin.") await self.active_message.edit(embed=self.am_embed) await sleep(2) await self.active_message.edit( content= "<a:nreader_loading:810936543401213953> Closing...", embed=None) await sleep(1) await self.am_channel.delete() break else: pass self.am_embed.set_footer( text=f"Page [{self.current_page+1}/{len(self.images)}]" ) self.am_embed.set_image( url=self.images[self.current_page].src) self.am_embed.set_thumbnail( url=self.images[self.current_page + 1].src if ( self.current_page + 1) in range(0, len(self.images)) else Embed.Empty) self.am_embed.description = f"⏮⏭ Previous|{'**__Finish__**' if self.current_page == (len(self.images)-1) else 'Next'}\n🔢⏹ Select|Stop\n⏯ Pause" await self.active_message.edit(embed=self.am_embed) continue elif str(payload.emoji) == "⏮": # Previous page if self.current_page == 0: # Not allowed to go behind zero continue else: self.current_page = self.current_page - 1 self.am_embed.set_footer( text=f"Page [{self.current_page+1}/{len(self.images)}]" ) self.am_embed.set_image( url=self.images[self.current_page].src) self.am_embed.set_thumbnail( url=self.images[self.current_page + 1].src if ( self.current_page + 1) in range(0, len(self.images)) else Embed.Empty) self.am_embed.description = f"⏮⏭ Previous|Next\n🔢⏹ Select|Stop\n⏯ Pause" await self.active_message.edit(embed=self.am_embed) continue elif str(payload.emoji) == "🔢": # Select page conf = await self.am_channel.send(embed=Embed( description= f"Enter the page number you would like to go to.")) while True: try: resp = await self.bot.wait_for( "message", timeout=10, bypass_cooldown=True, check=lambda m: m.channel.id == self.am_channel .id and m.author.id == self.ctx.author.id) except TimeoutError: await conf.delete() break except BotInteractionCooldown: continue else: if is_int(resp.content) and ( int(resp.content) - 1) in range( 0, len(self.images)): self.current_page = (int(resp.content) - 1) await resp.delete() await conf.delete() self.am_embed.set_footer( text= f"Page [{self.current_page+1}/{len(self.images)}]" ) self.am_embed.set_image( url=self.images[self.current_page].src) self.am_embed.set_thumbnail( url=self.images[self.current_page + 1].src if (self.current_page + 1) in range(0, len(self.images) ) else Embed.Empty) self.am_embed.description = f"⏮⏭ Previous|{'**__Finish__**' if self.current_page == (len(self.images)-1) else 'Next'}\n🔢⏹ Select|Stop\n⏯ Pause" await self.active_message.edit( embed=self.am_embed) break else: await resp.delete() await self.am_channel.send(embed=Embed( color=0xFF0000, description="Not a valid number!"), delete_after=2) continue elif str(payload.emoji ) == "⏯": # Pause for a maximum of one hour self.am_embed.set_image(url=Embed.Empty) self.am_embed.set_thumbnail(url=self.images[0].src) self.am_embed.description = "⏯ Play" self.am_embed.set_footer( text= "You've paused this doujin. Come back within an hour!") await self.active_message.edit(embed=self.am_embed) def payload_check_pause( payload ): # Use raw payload to compensate for the longer wait return \ payload.message_id==self.active_message.id and \ payload.user_id==self.ctx.author.id and \ str(payload.emoji)=="⏯" try: await self.bot.wait_for("raw_reaction_add", timeout=(60 * 55), bypass_cooldown=True, check=payload_check_pause) except TimeoutError: warning = await self.am_channel.send( f"{self.ctx.author.mention}, you're about to time out in 5 minutes. Press play and pause again if you need more time." ) try: await self.bot.wait_for("raw_reaction_add", timeout=(60 * 5), bypass_cooldown=True, check=payload_check_pause) except TimeoutError: await warning.delete() await self.active_message.delete() conf = await self.am_channel.send( f"{self.ctx.author.mention}, you timed out on page [{self.current_page+1}/{len(self.images)}]. This reader will be terminated." ) await sleep(10) await conf.edit( content= "<a:nreader_loading:810936543401213953> Closing...", embed=None) await sleep(1) await self.am_channel.delete() return else: await warning.delete() with suppress(Forbidden): await self.active_message.remove_reaction( "⏯", self.ctx.author) self.am_embed.set_footer( text= f"Page [{self.current_page+1}/{len(self.images)}]" ) self.am_embed.set_image( url=self.images[self.current_page].src) self.am_embed.set_thumbnail( url=self.images[self.current_page + 1].src if (self.current_page + 1) in range(0, len(self.images)) else Embed.Empty) self.am_embed.description = f"⏮⏭ Previous|Next\n🔢⏹ Select|Stop\n⏯ Pause" await self.active_message.edit(embed=self.am_embed) else: with suppress(Forbidden): await self.active_message.remove_reaction( "⏯", self.ctx.author) self.am_embed.set_footer( text= f"Page [{self.current_page+1}/{len(self.images)}]") self.am_embed.set_image( url=self.images[self.current_page].src) self.am_embed.set_thumbnail( url=self.images[self.current_page + 1].src if (self.current_page + 1) in range(0, len(self.images)) else Embed.Empty) self.am_embed.description = f"⏮⏭ Previous|Next\n🔢⏹ Select|Stop\n⏯ Pause" await self.active_message.edit(embed=self.am_embed) elif str(payload.emoji) == "⏹": # Stop entirely self.am_embed.set_image(url=Embed.Empty) self.am_embed.set_thumbnail(url=Embed.Empty) self.am_embed.description = Embed.Empty self.am_embed.set_footer( text= f"You stopped this doujin on page [{self.current_page+1}/{len(self.images)}]." ) await self.active_message.edit(embed=self.am_embed) await sleep(2) await self.active_message.edit( content= "<a:nreader_loading:810936543401213953> Closing...", embed=None) await sleep(1) await self.am_channel.delete() break return
def data_items(*, value, **kwargs): if misc.is_int(value): value = [value] elif misc.is_str(value): value = value.split(' ') return value