async def cog_before_invoke(self, ctx: discord.ext.commands.Context): ctx.player = Player.objects(dis_id=str(ctx.author.id)).first() if ctx.player is None: ctx.player = Player(dis_id=str(ctx.author.id), name=ctx.author.name, house=[i.name for i in ctx.author.roles if i.name in self.houses][0], items=[]).save()
def init_cleanup(ctx: discord.ext.commands.Context) -> None: if not hasattr(ctx, "cleanup"): ref = CleanupReference(ctx) ctx.cleanup = ref # type: ignore old_send = ctx.send async def send(*args: Any, **kwargs: Any) -> discord.Message: msg = await old_send(*args, **kwargs) ref.add(msg) return msg ctx.send = send # type: ignore
async def iv(self, ctx: discord.ext.commands.Context, ticker: str = None): """Displays ticker options IV [Barchart] Parameters ----------- ticker: str ticker, """ async with ctx.typing(): await asyncio.sleep(0.2) await iv_command(ctx, ticker)
async def role(ctx: discord.ext.commands.Context, name: str = None, color: discord.ext.commands.ColourConverter = None): print(f"{ctx.author}: {ctx.message.content}") role = get_highest_editable_role(ctx.author, ctx.me) if not color: if role: color = role.color else: # gets @everyone and the default color (#000000) color = ctx.author.top_role.color async with ctx.typing(): # if this is not here it continues "typing" after done await asyncio.sleep(0.1) if name: if name in data["blacklisted_roles"]: await ctx.send( "That name is not allowed! Please choose another one instead." ) return if role: await role.edit(color=color, name=name, hoist=True) else: tmp_role: discord.Role = await ctx.guild.create_role( color=color, name=name, hoist=True) await tmp_role.edit(position=data["insert_role_position"]) await ctx.author.add_roles(tmp_role) if data["auto_role"]: await ctx.author.add_roles( ctx.guild.get_role(data["auto_role"])) embed = discord.Embed( title= f"Set {ctx.author.display_name}'s role to \"{name}\" with the color `{color}`" ) embed.color = color await ctx.send(embed=embed) else: if role: embed = discord.Embed( title= f"Your role name is \"{role.name}\" and has the color `{role.color}`" ) embed.color = role.color await ctx.send(embed=embed) else: await ctx.send( "It looks like you need to set a role first. Try `!role \"role name\" #789abc`" )
async def unu( self, ctx: discord.ext.commands.Context, num: int = None, ): """Unusual Options Parameters ----------- ticker: str ticker """ async with ctx.typing(): await asyncio.sleep(0.2) await unu_command(ctx, num)
async def automatic_get_jsons( self, ctx: discord.ext.commands.Context, last_message: Optional[discord.Message], channel: Optional[discord.TextChannel] = None, use_flashfreze: Optional[bool] = False): l.debug( f"pending fixes command invoked from {ctx.author.id} in channel {ctx.channel.id} - {ctx.message.jump_url}" ) if not channel: channel = self.bot.get_channel(PENDING_FIXES_CHANNEL) async with ctx.typing(): if last_message is not None: await ctx.send( f"Getting all jsons in {channel.mention} not marked with a тЪая╕П before <{last_message.jump_url}> and after the pin. " f"Sit back and relax, this will take a while {COOL_CRAB}.") final_folder, start_date, end_date = await self.get_raw_json_messages_in_pending_fixes( last_message, channel) else: await ctx.send( f"Getting all jsons in {channel.mention} not marked with a тЪая╕П since the pin. " f"Sit back and relax, this will take a while {COOL_CRAB}.") final_folder, start_date, end_date = await self.get_raw_json_messages_in_pending_fixes( None, channel) archive = shutil.make_archive( f'pending_fixes {start_date} to {end_date}', 'zip', final_folder) l.debug(f"Sending fetched pending fixes") try: if not use_flashfreze: await ctx.send(file=discord.File(archive)) else: await self.send_with_flashfreeze(ctx, archive) except HTTPException: await ctx.send( "Resulting file too large, sending as to flashfreeze instead." ) await self.send_with_flashfreeze(ctx, archive) shutil.rmtree(final_folder, True) os.remove(archive)
async def raw_react(cls, ctx: discord.ext.commands.Context, characters: str, member: discord.Member = None): """Adds provided emojis to the specified member's last non-command message in the form of reactions. If no member was specified, adds emojis to the last non-command message sent in the given channel. """ if member is not None and member != ctx.author: async for message in ctx.history(limit=15): if message.author == member: for reaction in characters: try: await message.add_reaction(reaction) except discord.HTTPException: pass break else: messages = await ctx.history(limit=2).flatten() for reaction in characters: try: await messages[1].add_reaction(reaction) except discord.HTTPException: pass
async def automod_add(ctx: discord.ext.commands.Context, kind: Literal["substring", "word", "regex"], patterns: discord.ext.commands.Greedy[Union[util.discord.CodeBlock, util.discord.Inline, str]]) -> None: """ Add an automod pattern with one or more keywords. "substring" means the patterns will be matched anywhere in a message; "word" means the patterns have to match a separate word; "regex" means the patterns are case-insensitive regexes (use (?-i) to enable case sensitivity) """ await ctx.message.delete() ctx.send = ctx.channel.send # type: ignore # Undoing the effect of cleanup if len(patterns) == 0: raise util.discord.InvocationError("Provide at least one pattern") keywords: List[str] = [] for pattern in patterns: if isinstance(pattern, (util.discord.CodeBlock, util.discord.Inline)): pattern = pattern.text if kind == "regex": try: regex = re.compile(pattern) except Exception as exc: raise util.discord.UserError("Could not compile regex: {}".format(exc)) if regex.search("") is not None: raise util.discord.UserError("Regex matches empty string, that's probably not good") else: if pattern == "": raise util.discord.UserError("The pattern is empty, that's probably not good") keywords.append(pattern) for i in range(conf.index): if conf[i, "keyword"] == keywords and conf[i, "type"] == kind and conf[i, "action"] == None: break else: i = conf.index conf.index += 1 conf[i, "keyword"] = util.frozen_list.FrozenList(keywords) conf[i, "type"] = kind conf[i, "action"] = None await conf await ctx.send("Added as pattern **{}** with no action".format(i))
async def calls(self, ctx: discord.ext.commands.Context, ticker: str = None, expiry: str = None): """Get call options for ticker and given expiration Parameters ---------- ticker: str Stock ticker expiry: str accepts 0-9 or YYYY-MM-DD 0 weeklies, 1+ for weeks out prompts reaction helper if empty """ logger.info("!stocks.opt.calls %s %s", ticker, expiry) async with ctx.typing(): await asyncio.sleep(0.2) func_cmd = calls_command await expiry_dates_reaction(ctx, ticker, expiry, func_cmd)
async def puts( self, ctx: discord.ext.commands.Context, ticker: str = None, expiry: str = None ): """Get put options for ticker and given expiration Parameters ---------- ticker: str Stock ticker expiry: str accepts 0-9 or YYYY-MM-DD 0 weeklies, 1+ for weeks out prompts reaction helper if empty """ async with ctx.typing(): await asyncio.sleep(0.2) if cfg.DEBUG: print(f"!stocks.opt.puts {ticker} {expiry}") func_cmd = puts_command await expiry_dates_reaction(ctx, ticker, expiry, func_cmd)
async def vol( self, ctx: discord.ext.commands.Context, ticker: str = None, expiry: str = None, min_sp: float = None, max_sp: float = None, ): """Display options volume for ticker and given expiration Parameters ----------- ticker: str ticker strike: float strike expiry: str accepts 0-9 or YYYY-MM-DD min_sp: float min strike price max_sp:float max strike price Sends a message to the discord user with the expiry dates if empty. The user can then select a reaction to trigger the selected date. """ logger.info("stocks.opt.vol %s %s %s %s", ticker, expiry, min_sp, max_sp) async with ctx.typing(): await asyncio.sleep(0.2) call_arg = (min_sp, max_sp) func_cmd = vol_command await expiry_dates_reaction(ctx, ticker, expiry, func_cmd, call_arg)
async def oi( self, ctx: discord.ext.commands.Context, ticker: str = None, expiry: str = None, min_sp: float = None, max_sp: float = None, ): """Display options open interest for ticker and given expiration [Max Pain] Parameters ----------- ticker: str ticker strike: float strike expiry: str accepts 0-9 or YYYY-MM-DD min_sp: float min strike price max_sp:float max strike price Sends a message to the discord user with the expiry dates if empty. The user can then select a reaction to trigger the selected date. """ async with ctx.typing(): await asyncio.sleep(0.2) if cfg.DEBUG: print(f"!stocks.opt.oi {ticker} {expiry} {min_sp} {max_sp}") call_arg = (min_sp, max_sp) func_cmd = oi_command await expiry_dates_reaction(ctx, ticker, expiry, func_cmd, call_arg)
async def opt( self, ctx: discord.ext.commands.Context, ticker="", expiration="", strike="", put="", ): """Stocks Context - Shows Options Menu Run `!help OptionsCommands` to see the list of available commands. Returns ------- Sends a message to the discord user with the commands from the stocks/options context. The user can then select a reaction to trigger a command. """ logger.info("!stocks.opt %s %s %s %s", ticker, expiration, strike, put) async with ctx.typing(): await asyncio.sleep(0.2) if TRADIER_TOKEN == "REPLACE_ME": # nosec dates = yfinance_model.option_expirations(ticker) else: dates = tradier_model.option_expirations(ticker) index_dates = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] if not ticker: current = 0 text = ( "```0️⃣ !stocks.opt.unu```\n" "Provide a ticker and expiration date with this menu,\n" "\ne.g.\n!stocks.opt TSLA 0-9\n!stocks.opt TSLA 2021-06-04" ) if (ticker != "") and (expiration == ""): current = 1 text = ("```0️⃣ !stocks.opt.unu\n" f"1️⃣ !stocks.opt.exp {ticker}\n" f"2️⃣ !stocks.opt.iv {ticker}\n```") if expiration: current = 2 exp = int(expiration.replace("-", "")) if exp > 9 and (expiration not in dates) and (exp not in index_dates): call_arg = (strike, put) func_cmd = opt_command expiry = None await expiry_dates_reaction(ctx, ticker, expiry, func_cmd, call_arg) return if exp in index_dates: expiration = dates[int(expiration)] hist = f"7️⃣ !stocks.opt.hist {ticker} (strike*) (c/p*) {expiration}\n\n* Required" if strike and put: hist = f"7️⃣ !stocks.opt.hist {ticker} {strike} {put} {expiration}" current = 3 text = ("```0️⃣ !stocks.opt.unu\n" f"1️⃣ !stocks.opt.exp {ticker}\n" f"2️⃣ !stocks.opt.iv {ticker}\n" f"3️⃣ !stocks.opt.calls {ticker} {expiration} \n" f"4️⃣ !stocks.opt.puts {ticker} {expiration} \n" f"5️⃣ !stocks.opt.oi {ticker} {expiration} \n" f"6️⃣ !stocks.opt.vol {ticker} {expiration} \n" f"{hist}```") if put == "p": put = bool(True) if put == "c": put = bool(False) title = "Stocks: Options Menu" embed = discord.Embed(title=title, description=text, colour=cfg.COLOR) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) msg = await ctx.send(embed=embed, delete_after=60.0) if current == 0: emoji_list = ["0️⃣"] if current == 1: emoji_list = ["0️⃣", "1️⃣", "2️⃣"] if current == 2: emoji_list = ["0️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣"] if current == 3: emoji_list = [ "0️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣" ] for emoji in emoji_list: await msg.add_reaction(emoji) def check(reaction, user): return user == ctx.message.author and str( reaction.emoji) in emoji_list try: reaction, _ = await gst_bot.wait_for("reaction_add", timeout=cfg.MENU_TIMEOUT, check=check) if reaction.emoji == "0️⃣": logger.info("Reaction selected: 0") await unu_command(ctx) elif reaction.emoji == "1️⃣": logger.info("Reaction selected: 1") await expirations_command(ctx, ticker) elif reaction.emoji == "2️⃣": logger.info("Reaction selected: 2") await iv_command(ctx, ticker) elif reaction.emoji == "3️⃣": logger.info("Reaction selected: 3") await calls_command(ctx, ticker, expiration) elif reaction.emoji == "4️⃣": logger.info("Reaction selected: 4") await puts_command(ctx, ticker, expiration) elif reaction.emoji == "5️⃣": logger.info("Reaction selected: 5") await oi_command(ctx, ticker, expiration) elif reaction.emoji == "6️⃣": logger.info("Reaction selected: 6") await vol_command(ctx, ticker, expiration) elif reaction.emoji == "7️⃣": logger.info("Reaction selected: 7") strike = float(strike) await hist_command(ctx, ticker, expiration, strike, put) for emoji in emoji_list: await msg.remove_reaction(emoji, ctx.bot.user) except asyncio.TimeoutError: for emoji in emoji_list: await msg.remove_reaction(emoji, ctx.bot.user) if cfg.DEBUG: embed = discord.Embed( description="Error timeout - you snooze you lose! 😋", colour=cfg.COLOR, title="TIMEOUT Stocks: Options Menu", ).set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) await ctx.send(embed=embed, delete_after=30.0)
async def hist( self, ctx: discord.ext.commands.Context, ticker: str = None, strike: float = None, put="", expiry: str = None, ): """Display chart of given option historical price [Tradier] Parameters ----------- ticker: str ticker strike: float strike put: bool c for call p for put expiry: str accepts 0-9 or YYYY-MM-DD Sends a message to the discord user with the expiry dates if empty. The user can then select a reaction to trigger the selected date. """ logger.info("!stocks.opt.hist %s %s %s %s", ticker, strike, put, expiry) async with ctx.typing(): await asyncio.sleep(0.2) try: error = "" if TRADIER_TOKEN == "REPLACE_ME": # nosec raise Exception("Tradier Token is required") if expiry in ("c", "p"): raise Exception( 'Invalid format.\n\nUse:\n```bash\n"!stocks.opt.hist {ticker} {strike} {c/p}"```' '```bash\n"!stocks.opt {ticker} {expiration} {strike} {c/p}"```' ) if strike is None or put == "": raise Exception( 'A strike and c/p is required\n```bash\n"!stocks.opt.hist {ticker} {strike} {c/p}"```' ) if put == "p": put = bool(True) if put == "c": put = bool(False) call_arg = ( strike, put, ) func_cmd = hist_command await expiry_dates_reaction(ctx, ticker, expiry, func_cmd, call_arg) except TypeError: error = ( 'Invalid format.\n\nUse:\n```bash\n"!stocks.opt.hist {ticker} {strike} {c/p}"```' '```bash\n"!stocks.opt {ticker} {expiration} {strike} {c/p}"```' ) except Exception as e: error = str(e) finally: if error: logger.error(error) embed = discord.Embed( title="ERROR Options: History", colour=cfg.COLOR, description=error, ) embed.set_author( name=cfg.AUTHOR_NAME, icon_url=cfg.AUTHOR_ICON_URL, ) await ctx.send(embed=embed, delete_after=30.0)