async def on_message(self, message: discord.Message): # Update active if not ChannelUtil.is_private(message.channel) and len( message.content) > 0 and message.content[0] not in [ '`', '\'', '.', '?', '!', "\"", "+", ";", ":", "," ]: await self.update_activity_stats(message)
async def cog_before_invoke(self, ctx: Context): ctx.error = False # Remove duplicate mentions ctx.message.mentions = set(ctx.message.mentions) # Only allow giveaway commands in public channels msg = ctx.message if ChannelUtil.is_private(msg.channel) and ctx.command.name not in [ 'ticketstatus_cmd', 'ticket_cmd' ]: ctx.error = True await Messages.send_error_dm( msg.author, "You need to use giveaway commands in a public channel") return else: # Determine if user is admin ctx.god = msg.author.id in config.Config.instance().get_admin_ids() if not ctx.god: ctx.admin = False for g in self.bot.guilds: member = g.get_member(msg.author.id) if member is not None: for role in member.roles: if role.id in config.Config.instance( ).get_admin_roles(): ctx.admin = True break if ctx.admin: break else: ctx.admin = True if ctx.command.name not in 'giveaway_stats_cmd': # See if user exists in DB user = await User.get_user(msg.author) if user is None: ctx.error = True await Messages.send_error_dm( msg.author, f"You should create an account with me first, send me `{config.Config.instance().command_prefix}help` to get started." ) return elif user.frozen: ctx.error = True await Messages.send_error_dm( msg.author, f"Your account is frozen. Contact an admin if you need further assistance." ) return # Update name, if applicable await user.update_name(msg.author.name) ctx.user = user
async def statsban_cmd(self, ctx: Context): if ctx.error: return msg = ctx.message if ChannelUtil.is_private(msg.channel): await Messages.add_x_reaction(msg) await Messages.send_error_dm(msg.author, "You can only stats ban in a public channel") return ban_ids = [] # Get mentioned users for m in msg.mentions: ban_ids.append(m.id) # Get users they are banning by ID alone for sec in msg.content.split(): try: numeric = int(sec.strip()) user = await self.bot.fetch_user(numeric) if user is not None: ban_ids.append(user.id) except Exception: pass # remove duplicates and admins ban_ids = set(ban_ids) ban_ids = [x for x in ban_ids if x not in config.Config.instance().get_admin_ids()] for f in ban_ids: memba = msg.guild.get_member(f) if memba is not None: for r in memba.roles: if r.id in [config.Config.instance().get_admin_roles()]: ban_ids.remove(r.id) if len(ban_ids) < 1: await Messages.add_x_reaction(msg) await msg.author.send("Your message has no users to ban") return # We need to make sure that the stats objects are created for these users before banning them to_ban = await User.filter(id__in=ban_ids).all() async with in_transaction() as conn: for u in to_ban: stats = await u.get_stats(msg.guild.id) stats.banned = True await stats.save(update_fields=['banned'], using_db=conn) await msg.author.send(f"{len(ban_ids)} users have been banned") await msg.add_reaction("\U0001F528")
async def cog_before_invoke(self, ctx: Context): ctx.error = False # Only allow tip commands in public channels msg = ctx.message if ChannelUtil.is_private( msg.channel) and ctx.command.name != 'blocks_cmd': await Messages.send_error_dm( msg.author, "You can only view statistics in a server, not via DM.") ctx.error = True return else: # Determine if user is admin ctx.god = msg.author.id in config.Config.instance().get_admin_ids() if not ctx.god: ctx.admin = False for g in self.bot.guilds: member = g.get_member(msg.author.id) if member is not None: for role in member.roles: if role.id in config.Config.instance( ).get_admin_roles(): ctx.admin = True break if ctx.admin: break else: ctx.admin = True # Can't spam stats commands if msg.channel.id in config.Config.instance().get_no_spam_channels(): ctx.error = True await Messages.send_error_dm( msg.author, "I can't post stats in that channel.") return if ctx.command.name in ['tipstats_cmd']: # Make sure user exists in DB user = await User.get_user(msg.author) if user is None: ctx.error = True await Messages.send_error_dm( msg.author, f"You should create an account with me first, send me `{config.Config.instance().command_prefix}help` to get started." ) return # Update name, if applicable await user.update_name(msg.author.name) ctx.user = user
async def cog_before_invoke(self, ctx: Context): ctx.error = False msg = ctx.message if ChannelUtil.is_private(msg.channel): ctx.error = True return # See if user exists in DB user = await User.get_user(msg.author) if user is None: ctx.error = True await Messages.send_error_dm( msg.author, f"You should create an account with me first, send me `{config.Config.instance().command_prefix}help` to get started." ) return
async def tipban_cmd(self, ctx: Context): if ctx.error: return msg = ctx.message if ChannelUtil.is_private(msg.channel): await Messages.add_x_reaction(msg) await Messages.send_error_dm(msg.author, "You can't ban via DM, need to do it in a server channel") return ban_ids = [] # Get mentioned users for m in msg.mentions: ban_ids.append(m.id) # Get users they are banning by ID alone for sec in msg.content.split(): try: numeric = int(sec.strip()) user = await self.bot.fetch_user(numeric) if user is not None: ban_ids.append(user.id) except Exception: pass # remove duplicates and admins ban_ids = set(ban_ids) ban_ids = [x for x in ban_ids if x not in config.Config.instance().get_admin_ids()] for f in ban_ids: memba = msg.guild.get_member(f) if memba is not None: for r in memba.roles: if r.id in [config.Config.instance().get_admin_roles()]: ban_ids.remove(r.id) if len(ban_ids) < 1: await Messages.add_x_reaction(msg) await msg.author.send("Your message has no users to ban") return await User.filter(id__in=ban_ids).update(tip_banned=True) await msg.author.send(f"{len(ban_ids)} users have been banned") await msg.add_reaction("\U0001F528")
async def muted_cmd(self, ctx: Context): if ctx.error: return msg = ctx.message user = ctx.user if not ChannelUtil.is_private(msg.channel): await Messages.add_x_reaction(msg) await Messages.send_error_dm(msg.author, "You can only view users you have muted in DM") return muted_list = await Muted.filter(user=ctx.user).prefetch_related('target_user').all() if len(muted_list) < 1: await msg.author.send("You haven't muted anybody.") return # Build user list entries = [] for u in muted_list: entries.append(Entry(f"{u.target_user.name}", f"Unmute with `{config.Config.instance().command_prefix}unmute {u.target_user.id}`")) # Build pages pages = [] # Overview author=f"Muted Users" description = f"Use `{config.Config.instance().command_prefix}unmute <user_id>` to unmute a user" i = 0 entry_subset = [] for e in entries: entry_subset.append(e) if i == 14: pages.append(Page(entries=entry_subset, author=author, description=description)) i = 0 entry_subset = [] else: i += 1 if len(entry_subset) > 0: pages.append(Page(entries=entry_subset, author=author, description=description)) # Start pagination pages = Paginator(self.bot, message=msg, page_list=pages,as_dm=True) await pages.paginate(start_page=1)
async def cog_before_invoke(self, ctx: Context): ctx.error = False # Only allow mute commands in private channels msg = ctx.message if not ChannelUtil.is_private(msg.channel): ctx.error = True await Messages.send_error_dm(msg.author, "You can only do this in DM") return # See if user exists in DB user = await User.get_user(msg.author) if user is None: ctx.error = True await Messages.send_error_dm(msg.author, f"You should create an account with me first, send me `{config.Config.instance().command_prefix}help` to get started.") return elif user.frozen: ctx.error = True await Messages.send_error_dm(msg.author, f"Your account is frozen. Contact an admin if you need further assistance.") return ctx.user = user
async def statsbanned_cmd(self, ctx: Context): if ctx.error: return msg = ctx.message if ChannelUtil.is_private(msg.channel): await Messages.add_x_reaction(msg) await Messages.send_error_dm(msg.author, "You can only view stats banned in a public channel") return banned_list = await Stats.filter(banned=True, server_id=msg.guild.id).prefetch_related('user').all() if len(banned_list) < 1: await msg.author.send("There aren't any banned users") return # Build user list entries = [] for u in banned_list: entries.append(Entry(f"{u.user.id}:{u.user.name}", f"Unban with `{config.Config.instance().command_prefix}statsunban {u.user.id}`")) # Build pages pages = [] # Overview author=f"Stats Banned Users" description = f"Use `{config.Config.instance().command_prefix}statsunban <user_id>` to unban a user" i = 0 entry_subset = [] for e in entries: entry_subset.append(e) if i == 14: pages.append(Page(entries=entry_subset, author=author, description=description)) i = 0 entry_subset = [] else: i += 1 if len(entry_subset) > 0: pages.append(Page(entries=entry_subset, author=author, description=description)) # Start pagination pages = Paginator(self.bot, message=msg, page_list=pages,as_dm=True) await pages.paginate(start_page=1)
async def blocks_cmd(self, ctx: Context): if ctx.error: await Messages.add_x_reaction(ctx.message) return msg = ctx.message is_private = ChannelUtil.is_private(msg.channel) if not ctx.god and await RedisDB.instance().exists( f"blocksspam{msg.channel.id if not is_private else msg.author.id}" ): await Messages.add_timer_reaction(msg) await Messages.send_error_dm( msg.author, "Why don't you wait awhile before checking the block count again?" ) return count, unchecked = await RPCClient.instance().block_count() if count is None or unchecked is None: await Messages.send_error_dm( msg.author, "I couldn't retrieve the current block count") return embed = discord.Embed( colour=0xFBDD11 if Env.banano() else discord.Colour.dark_blue()) embed.set_author( name=f"Here's how many blocks I have", icon_url= "https://github.com/bbedward/graham_discord_bot/raw/master/assets/banano_logo.png" if Env.banano() else "https://github.com/bbedward/graham_discord_bot/raw/master/assets/nano_logo.png" ) embed.description = f"```Count: {count:,}\nUnchecked: {unchecked:,}```" await RedisDB.instance().set( f"blocksspam{msg.channel.id if not is_private else msg.author.id}", "as", expires=120) if is_private: await msg.author.send(embed=embed) else: await msg.channel.send(f"<@{msg.author.id}>", embed=embed)
async def statsunban_cmd(self, ctx: Context): if ctx.error: return msg = ctx.message if ChannelUtil.is_private(msg.channel): await Messages.add_x_reaction(msg) await Messages.send_error_dm(msg.author, "You can only stats unban in a public channel") return ban_ids = [] # Get mentioned users for m in msg.mentions: ban_ids.append(m.id) # Get users they are banning by ID alone for sec in msg.content.split(): try: numeric = int(sec.strip()) user = await self.bot.fetch_user(numeric) if user is not None: ban_ids.append(user.id) except Exception: pass # remove duplicates and admins ban_ids = set(ban_ids) if len(ban_ids) < 1: await Messages.add_x_reaction(msg) await msg.author.send("Your message has no users to unban") return # TODO - tortoise doesnt give us any feedback on update counts atm # https://github.com/tortoise/tortoise-orm/issues/126 await Stats.filter(user_id__in=ban_ids, server_id=msg.guild.id, banned=True).update(banned=False) await msg.author.send(f"{len(ban_ids)} users have been unbanned") await msg.add_reaction("\U0001F5FD")
async def cog_before_invoke(self, ctx: Context): ctx.error = False msg = ctx.message if ChannelUtil.is_private(ctx.message.channel): ctx.error = True return else: # Check admins ctx.god = msg.author.id in config.Config.instance().get_admin_ids() ctx.admin = False author: discord.Member = msg.author for role in author.roles: if role.id in config.Config.instance().get_admin_roles(): ctx.admin = True break # Check paused if await RedisDB.instance().is_paused(): ctx.error = True await Messages.send_error_dm( msg.author, f"Transaction activity is currently suspended. I'll be back online soon!" ) return # Check anti-spam if not ctx.god and await RedisDB.instance().exists( f"rainspam{msg.author.id}"): ctx.error = True await Messages.add_timer_reaction(msg) await Messages.send_basic_dm( msg.author, "You can only rain once every 5 minutes") return # Parse some info try: ctx.send_amount = RegexUtil.find_send_amounts(msg.content) if Validators.too_many_decimals(ctx.send_amount): await Messages.add_x_reaction(msg) await Messages.send_error_dm( msg.author, f"You are only allowed to use {Env.precision_digits()} digits after the decimal." ) ctx.error = True return elif ctx.send_amount < config.Config.instance().get_rain_minimum(): ctx.error = True await Messages.add_x_reaction(msg) await Messages.send_usage_dm(msg.author, RAIN_INFO) return # See if user exists in DB user = await User.get_user(msg.author) if user is None: await Messages.add_x_reaction(msg) await Messages.send_error_dm( msg.author, f"You should create an account with me first, send me `{config.Config.instance().command_prefix}help` to get started." ) ctx.error = True return elif user.frozen: ctx.error = True await Messages.add_x_reaction(msg) await Messages.send_error_dm( msg.author, f"Your account is frozen. Contact an admin if you need further assistance." ) return # Update name, if applicable await user.update_name(msg.author.name) ctx.user = user except AmountMissingException: await Messages.add_x_reaction(msg) await Messages.send_usage_dm(msg.author, RAIN_INFO) ctx.error = True return except AmountAmbiguousException: await Messages.add_x_reaction(msg) await Messages.send_error_dm( msg.author, "You can only specify 1 amount to send") ctx.error = True return
async def update_activity_stats(msg: discord.Message): """Update activity statistics for a user""" if ChannelUtil.is_private(msg.channel): return member = msg.author # Ignore if user doesnt have rain role has_rain_role = False rain_roles = config.Config.instance().get_rain_roles() if len(rain_roles) > 0: for role in member.roles: if role.id in rain_roles: has_rain_role = True break if not has_rain_role: return content_adjusted = Utils.emoji_strip(msg.content) if len(content_adjusted) == 0: return # Get user OBJ from redis if it exists, else create one user_key = f"activity:{msg.guild.id}:{msg.author.id}" active_stats = await RedisDB.instance().get(user_key) if active_stats is None: # Create stats and save active_stats = { 'user_id': msg.author.id, 'last_msg': datetime.datetime.utcnow().strftime('%m/%d/%Y %H:%M:%S'), 'msg_count': 1 } await RedisDB.instance().set(user_key, json.dumps(active_stats), expires=1800) return else: active_stats = json.loads(active_stats) # Ignore em if they've messaged too recently last_msg_dt = datetime.datetime.strptime(active_stats['last_msg'], '%m/%d/%Y %H:%M:%S') delta_s = (datetime.datetime.utcnow() - last_msg_dt).total_seconds() if 90 > delta_s: return elif delta_s > 1200: # Deduct a point if active_stats['msg_count'] > 1: active_stats['msg_count'] -= 1 active_stats['last_msg'] = datetime.datetime.utcnow().strftime( '%m/%d/%Y %H:%M:%S') await RedisDB.instance().set(user_key, json.dumps(active_stats), expires=1800) else: # add a point if active_stats['msg_count'] <= Constants.RAIN_MSG_REQUIREMENT * 2: active_stats['msg_count'] += 1 active_stats['last_msg'] = datetime.datetime.utcnow().strftime( '%m/%d/%Y %H:%M:%S') await RedisDB.instance().set(user_key, json.dumps(active_stats), expires=1800) else: # Reset key expiry active_stats['last_msg'] = datetime.datetime.utcnow().strftime( '%m/%d/%Y %H:%M:%S') await RedisDB.instance().set(user_key, json.dumps(active_stats), expires=1800)
async def ticketstatus_cmd(self, ctx: Context): if ctx.error: return msg = ctx.message user = ctx.user author = msg.author content = msg.content # If private, see what servers they are part of guilds = None if ChannelUtil.is_private(msg.channel): guilds = [] for g in self.bot.guilds: if g.get_member(msg.author.id) is not None: guilds.append(g) if len(guilds) == 0: return # See if they've been spamming redis_key = f"ticketspam:{msg.author.id}" if not ctx.god: spam = await RedisDB.instance().get(redis_key) if spam is not None: spam = int(spam) if spam >= 3: await Messages.send_error_dm(msg.author, "You're temporarily banned from entering giveaways") await Messages.delete_message(msg) return else: spam = 0 else: spam = 0 # Get active giveaway(s) - public channel if guilds == None: gw = await Giveaway.get_active_giveaway(server_id=msg.guild.id) if gw is None: await Messages.send_error_dm(msg.author, "There aren't any active giveaways.") await Messages.delete_message(msg) # Block ticket spam await RedisDB.instance().set(f"ticketspam:{msg.author.id}", str(spam + 1), expires=3600) return # Get their active giveaway transaction active_tx = await Transaction.filter(giveaway__id=gw.id, sending_user__id=user.id).first() response = None if active_tx is None: if int(gw.entry_fee) > 0: fee_converted = Env.raw_to_amount(int(gw.entry_fee)) response = f"There is a fee of **{fee_converted} {Env.currency_symbol()}**!\n" response+= f"Use `{config.Config.instance().command_prefix}ticket {fee_converted}` to pay the fee and enter" else: response = f"This giveaway is free to enter\n" response+= f"Use `{config.Config.instance().command_prefix}ticket` to enter." else: needed = int(gw.entry_fee) - int(active_tx.amount) if needed <= 0: response = f"You're already entered into this giveaway" else: fee_converted = Env.raw_to_amount(int(gw.entry_fee)) paid_converted = Env.raw_to_amount(int(active_tx.amount)) response = f"There is a fee of **{fee_converted} {Env.currency_symbol()}**! You've donated **{paid_converted} {Env.currency_symbol()}** but that's not enough to enter!\n" response+= f"Use `{config.Config.instance().command_prefix}ticket {NumberUtil.format_float(fee_converted - paid_converted)}` to pay the fee and enter" # Build response embed = discord.Embed(colour=0xFBDD11 if Env.banano() else discord.Colour.dark_blue()) embed.set_author(name=f"Giveaway #{gw.id} is active!", icon_url="https://github.com/bbedward/graham_discord_bot/raw/master/assets/banano_logo.png" if Env.banano() else "https://github.com/bbedward/graham_discord_bot/raw/master/assets/nano_logo.png") embed.description = response await msg.author.send(embed=embed) await Messages.delete_message(msg) return # Get active giveaways (private channel) gws = await Giveaway.get_active_giveaways(server_ids=[g.id for g in guilds]) if gws is None or len(gws) == 0: await Messages.send_error_dm(msg.author, "There aren't any active giveaways.") await Messages.delete_message(msg) # Block ticket spam await RedisDB.instance().set(f"ticketspam:{msg.author.id}", str(spam + 1), expires=3600) return # Get their active giveaway transaction response = None for gw in gws: active_tx = await Transaction.filter(giveaway__id=gw.id, sending_user__id=user.id).first() response = f"**Giveaway #{gw.id}**\n" if response is None else f"**Giveaway #{gw.id}**:\n" if active_tx is None: if int(gw.entry_fee) > 0: fee_converted = Env.raw_to_amount(int(gw.entry_fee)) response+= f"There is a fee of **{fee_converted} {Env.currency_symbol()}**!\n" response+= f"Use `{config.Config.instance().command_prefix}ticket {fee_converted} id={gw.id}` to pay the fee and enter\n" else: response+= f"This giveaway is free to enter\n" response+= f"Use `{config.Config.instance().command_prefix}ticket id={gw.id}` to enter.\n" else: needed = int(gw.entry_fee) - int(active_tx.amount) if needed <= 0: response+= f"You're already entered into this giveaway" else: fee_converted = Env.raw_to_amount(int(gw.entry_fee)) paid_converted = Env.raw_to_amount(int(active_tx.amount)) response+= f"There is a fee of **{fee_converted} {Env.currency_symbol()}**! You've donated **{paid_converted} {Env.currency_symbol()}** but that's not enough to enter!\n" response+= f"Use `{config.Config.instance().command_prefix}ticket {NumberUtil.format_float(fee_converted - paid_converted)} id={gw.id}` to pay the fee and enter\n" # Build response embed = discord.Embed(colour=0xFBDD11 if Env.banano() else discord.Colour.dark_blue()) embed.set_author(name=f"Here are the active giveaways!", icon_url="https://github.com/bbedward/graham_discord_bot/raw/master/assets/banano_logo.png" if Env.banano() else "https://github.com/bbedward/graham_discord_bot/raw/master/assets/nano_logo.png") embed.description = response await msg.author.send(embed=embed) await Messages.delete_message(msg)
async def ticket_cmd(self, ctx: Context): if ctx.error: return msg = ctx.message user = ctx.user author = msg.author content = msg.content is_private = ChannelUtil.is_private(msg.channel) id=None if is_private: if 'id=' not in msg.content: await Messages.send_usage_dm(msg.author, TICKET_INFO) await Messages.add_x_reaction(msg) return # Parse message split_content = msg.content.split(' ') cleaned_content = msg.content for split in split_content: if split.startswith('id='): cleaned_content.replace(split, "") split = split.replace('id=','').strip() if not split: continue try: id = int(split) except ValueError as e: await Messages.add_x_reaction(msg) await Messages.send_usage_dm(msg.author, TICKET_INFO) return # See if they've been spamming redis_key = f"ticketspam:{msg.author.id}" if not ctx.god: spam = await RedisDB.instance().get(redis_key) if spam is not None: spam = int(spam) if spam >= 3: await Messages.send_error_dm(msg.author, "You're temporarily banned from entering giveaways") await Messages.delete_message_if_ok(msg) return else: spam = 0 else: spam = 0 # Get active giveaway if id is None: gw = await Giveaway.get_active_giveaway(server_id=msg.guild.id) else: gw = await Giveaway.get_active_giveaway_by_id(id=id) if gw is None: await Messages.send_error_dm(msg.author, "There aren't any active giveaways to enter.") await Messages.delete_message_if_ok(msg) # Block ticket spam await RedisDB.instance().set(f"ticketspam:{msg.author.id}", str(spam + 1), expires=3600) return # Check roles if is_private: guild = self.bot.get_guild(gw.server_id) if guild is None: await Messages.send_error_dm(msg.author, "Something went wrong, ask my master for help") return member = guild.get_member(msg.author.id) if member is None: await "You're not a member of that server" return msg.author = member if not await self.role_check(msg): return # There is an active giveaway, enter em if not already entered. active_tx = await Transaction.filter(giveaway__id=gw.id, sending_user__id=user.id).first() if active_tx is not None and int(gw.entry_fee) == 0: await Messages.send_error_dm(msg.author, "You've already entered this giveaway.") await Messages.delete_message_if_ok(msg) return elif active_tx is None: paid_already = 0 else: paid_already = int(active_tx.amount) if paid_already >= int(gw.entry_fee) and int(gw.entry_fee) > 0: await Messages.send_error_dm(msg.author, "You've already entered this giveaway.") await Messages.delete_message_if_ok(msg) return # Enter em fee_raw = int(gw.entry_fee) - paid_already fee = Env.raw_to_amount(fee_raw) # Check balance if fee is > 0 if fee > 0: try: amount = RegexUtil.find_float(msg.content) if amount < fee: await Messages.send_error_dm(msg.author, f"This giveaway has a fee of {fee} {Env.currency_symbol()}. The amount you specified isn't enough to cover the entry fee") await Messages.delete_message_if_ok(msg) return except AmountMissingException: await Messages.send_error_dm(msg.author, f"This giveaway has a fee, you need to specify the amount to enter. `{config.Config.instance().command_prefix}ticket {fee}`") await Messages.delete_message_if_ok(msg) return available_balance = Env.raw_to_amount(await user.get_available_balance()) if fee > available_balance: await Messages.add_x_reaction(ctx.message) await Messages.send_error_dm(msg.author, f"Your balance isn't high enough to complete this tip. You have **{available_balance} {Env.currency_symbol()}**, but this entry would cost you **{fee} {Env.currency_symbol()}**") await Messages.delete_message_if_ok(msg) await RedisDB.instance().set(f"ticketspam:{msg.author.id}", str(spam + 1), expires=3600) return await Transaction.create_transaction_giveaway( user, fee, gw ) await Messages.send_success_dm(msg.author, f"You've successfully been entered into giveaway #{gw.id}") await Messages.delete_message_if_ok(msg) return
async def cog_before_invoke(self, ctx: Context): ctx.error = False # Remove duplicate mentions ctx.message.mentions = set(ctx.message.mentions) # Only allow tip commands in public channels msg = ctx.message if ChannelUtil.is_private(msg.channel): ctx.error = True return else: # Check admins ctx.god = msg.author.id in config.Config.instance().get_admin_ids() ctx.admin = False author: discord.Member = msg.author for role in author.roles: if role.id in config.Config.instance().get_admin_roles(): ctx.admin = True break # Check paused if await RedisDB.instance().is_paused(): ctx.error = True await Messages.send_error_dm( msg.author, f"Transaction activity is currently suspended. I'll be back online soon!" ) return # See if user exists in DB user = await User.get_user(msg.author) if user is None: ctx.error = True await Messages.send_error_dm( msg.author, f"You should create an account with me first, send me `{config.Config.instance().command_prefix}help` to get started." ) return elif user.frozen: ctx.error = True await Messages.send_error_dm( msg.author, f"Your account is frozen. Contact an admin if you need further assistance." ) return # Update name, if applicable await user.update_name(msg.author.name) ctx.user = user # See if amount meets tip_minimum requirement try: send_amount = RegexUtil.find_float(msg.content) if ctx.command.name == 'tiprandom_cmd' and send_amount < Constants.TIPRANDOM_MINIMUM: raise AmountMissingException( f"Tip random amount is too low, minimum is {Constants.TIPRANDOM_MINIMUM}" ) elif ctx.command.name != 'tiprandom_cmd' and send_amount < Constants.TIP_MINIMUM: raise AmountMissingException( f"Tip amount is too low, minimum is {Constants.TIP_MINIMUM}" ) elif Validators.too_many_decimals(send_amount): await Messages.send_error_dm( ctx.message.author, f"You are only allowed to use {Env.precision_digits()} digits after the decimal." ) ctx.error = True return except AmountMissingException: ctx.error = True if ctx.command.name == 'tip_cmd': await Messages.send_usage_dm(msg.author, TIP_INFO) elif ctx.command.name == 'tipsplit_cmd': await Messages.send_usage_dm(msg.author, TIPSPLIT_INFO) elif ctx.command.name == 'tiprandom_cmd': await Messages.send_usage_dm(msg.author, TIPRANDOM_INFO) return ctx.send_amount = send_amount