async def trackword(self, ctx, *, word: str): Data.check_guild_entry(ctx.guild) guild_id = ctx.guild.id word = word.strip() Data.c.execute( "SELECT tracked_words FROM guilds WHERE id = :guild_id", {"guild_id": ctx.guild.id}, ) self.tracked_words[guild_id] = json.loads(Data.c.fetchone()[0]) if word in self.tracked_words[guild_id]: await ctx.send(f"The word **{word}** is already being tracked!") return self.tracked_words[guild_id][word] = -1 Data.c.execute( "UPDATE guilds SET tracked_words = :new_words WHERE id = :guild_id", { "new_words": json.dumps(self.tracked_words[guild_id]), "guild_id": ctx.guild.id, }, ) Data.conn.commit() await ctx.send(f"The word **{word}** is now being tracked!")
async def on_member_remove(self, member: discord.Member): guild: discord.Guild = member.guild Data.check_guild_entry(guild) Data.c.execute( """SELECT leave_message, leave_channel FROM guilds WHERE id = :guild_id""", {"guild_id": guild.id}, ) data = Data.c.fetchone() leave_message = data[0] leave_channel_id = data[1] if leave_channel_id == "disabled": return if not leave_channel_id: leave_channel = await self.find_leave_channel(guild) # Exit the function if no leave channel is provided or # automatically found if not leave_channel: return else: leave_channel = guild.get_channel(int(leave_channel_id)) if not leave_message: leave_message = self.default_leave_msg(guild) # Replace placeholders with actual information leave_message = leave_message.replace("[mention]", member.mention) leave_message = leave_message.replace("[member]", str(member)) await leave_channel.send(leave_message)
async def on_message(self, message): if message.author == self.bot.user: return guild_id = message.guild.id Data.check_guild_entry(message.guild) try: for word in self.tracked_words[guild_id]: if word in message.content: self.tracked_words[guild_id][ word ] += message.content.count(word) Data.c.execute( "UPDATE guilds SET tracked_words = :new_words WHERE id = :guild_id", { "new_words": json.dumps( self.tracked_words[guild_id] ), "guild_id": guild_id, }, ) Data.conn.commit() except KeyError: self.tracked_words[guild_id] = {}
async def on_dbl_vote(self, data): if data["type"] == "upvote": user = self.bot.get_user(int(data["user"])) Data.check_user_entry(user) print(f"{user} has upvoted the bot on Top.gg") try: await user.send( f"Thank you for voting for me on Top.gg. You have gotten {self.vote_reward} beans as a gift!" ) except discord.errors.Forbidden: print(f"Couldn't send a message to {user}") Data.c.execute( "SELECT wallet FROM users WHERE id = :user_id", {"user_id": user.id}, ) wallet = Data.c.fetchone()[0] Data.c.execute( "UPDATE users SET wallet = :new_amount WHERE id = :user_id", { "new_amount": wallet + self.vote_reward, "user_id": user.id }, ) Data.conn.commit()
async def on_message(self, message: discord.Message): if message.author == self.bot.user: return Data.c.execute("SELECT * FROM afks") afks = Data.c.fetchall() for afk in afks: guild_prefix = get_prefix(self.bot, message) if int( afk[0] ) == message.author.id and not message.content.startswith( guild_prefix ): await message.channel.send( f"{message.author.mention}, you have been un-AFK'd" ) Data.delete_afk_data(message.author) continue user = await self.bot.fetch_user(int(afk[0])) if user in message.mentions: afk_reason = afk[1] await message.channel.send( f"{message.author.mention}, {user} is currently AFK because:\n*{afk_reason}*" )
async def inventory(self, ctx, user: discord.Member = None): if user is None: user = ctx.author Data.check_user_entry(user) Data.c.execute( "SELECT inventory FROM users WHERE id = :user_id", {"user_id": user.id}, ) inventory = json.loads(Data.c.fetchone()[0]) inventory_embed = discord.Embed( title=f"{user.display_name}'s Inventory", color=self.theme_color) for item in inventory: item_name = item["name"] item_desc = item["description"] item_quantity = item["quantity"] inventory_embed.add_field( name=item_name, value=f"Quantity: {item_quantity}\n{item_desc}", inline=False, ) await ctx.send(embed=inventory_embed)
async def balance(self, ctx, user: discord.User = None): if user is None: user = ctx.author Data.check_user_entry(user) Data.c.execute( "SELECT wallet, bank, bank_capacity FROM users WHERE id = :user_id", {"user_id": user.id}, ) data = Data.c.fetchone() wallet = data[0] bank = data[1] bank_capacity = data[2] embed = discord.Embed( title=f"{user.display_name}'s Bean Balance", color=self.theme_color ) embed.add_field(name="Wallet", value=f"{wallet} beans") embed.add_field(name="Bank", value=f"{bank}/{bank_capacity} beans") await ctx.send( "You can get beans for free if you vote for me on Top.gg. Do `b.vote` for more info...", embed=embed, )
async def remove_auto_response(self, ctx: commands.Context, *, activation: str = None): Data.check_guild_entry(ctx.guild) if activation: Data.c.execute( "SELECT auto_responses FROM guilds WHERE id = :guild_id", {"guild_id": ctx.guild.id}, ) current_auto_resps = json.loads(Data.c.fetchone()[0]) if activation not in current_auto_resps: await ctx.send( "An auto response with this activation phrase does not exist" ) return del current_auto_resps[activation] Data.c.execute( "UPDATE guilds SET auto_responses = :new_responses WHERE id = :guild_id", { "new_responses": json.dumps(current_auto_resps), "guild_id": ctx.guild.id, }, ) Data.conn.commit() await ctx.send( f"Auto response with activation:```{activation}```has been removed" ) else: def check_msg(message: discord.Message): return (message.author == ctx.author and message.channel == ctx.channel) await ctx.send( "You are about to delete all auto responses in this server. Do you want to continue? (Yes to continue, anything else to abort)" ) try: confirmation: discord.Message = await self.bot.wait_for( "message", check=check_msg, timeout=30) if confirmation.content.lower() == "yes": Data.c.execute( "UPDATE guilds SET auto_responses = '{}' WHERE id = :guild_id", {"guild_id": ctx.guild.id}, ) Data.conn.commit() await ctx.send( "All auto responses in this server have been deleted") else: await ctx.send("Aborting!") except asyncio.TimeoutError: await ctx.send("No response received, aborting!")
async def untrackword(self, ctx, *, word: str): Data.check_guild_entry(ctx.guild) guild_id = ctx.guild.id word = word.strip() Data.c.execute( "SELECT tracked_words FROM guilds WHERE id = :guild_id", {"guild_id": ctx.guild.id}, ) self.tracked_words[guild_id] = json.loads(Data.c.fetchone()[0]) try: del self.tracked_words[guild_id][word] except KeyError: await ctx.send("This word was never being tracked...") return Data.c.execute( "UPDATE guilds SET tracked_words = :new_words WHERE id = :guild_id", { "new_words": json.dumps(self.tracked_words[guild_id]), "guild_id": ctx.guild.id, }, ) Data.conn.commit() await ctx.send(f"The word **{word}** is no longer being tracked!")
async def warn(self, ctx: commands.Context, member: discord.Member, *, reason: str): if ctx.author.top_role <= member.top_role: await ctx.send( f"You cannot use the command on this person because their top role is higher than or equal to yours." ) return Data.check_guild_entry(ctx.guild) Data.c.execute( "SELECT infractions FROM guilds WHERE id = :guild_id", {"guild_id": ctx.guild.id}, ) guild_infractions: list = json.loads(Data.c.fetchone()[0]) new_infraction = {"member": member.id, "reason": reason} guild_infractions.append(new_infraction) Data.c.execute( "UPDATE guilds SET infractions = :new_infractions WHERE id = :guild_id", { "new_infractions": json.dumps(guild_infractions), "guild_id": ctx.guild.id, }, ) Data.conn.commit() await ctx.send(f"**{member}** has been warned because: *{reason}*")
async def work(self, ctx): Data.check_user_entry(ctx.author) Data.c.execute( "SELECT wallet, job_id, job_streak, last_work_date FROM users WHERE id = :user_id", {"user_id": ctx.author.id}, ) data = Data.c.fetchone() current_balance = data[0] job_id = data[1] current_streak = data[2] last_work_date = datetime.strptime(data[3], "%Y-%m-%d %H:%M") today = datetime.now() if job_id == 0: await ctx.send("You're unemployed bro. Get a job...") return salary = self.jobs_data[job_id]["salary"] new_streak = current_streak + 1 time_diff = today - last_work_date if time_diff.days > 2: new_streak = 1 await ctx.send( "You didn't show up to work yesterday. Your work streak has been reset!" ) elif time_diff.days < 1: time_left = 24 - time_diff.total_seconds() / 3600 if time_left > 1: await ctx.send( f"You've done enough work for today, try again in {int(time_left)} hours..." ) else: time_left = time_left * 60 await ctx.send( f"You've done enough work for today, try again in {int(time_left)} minutes..." ) return Data.c.execute( "UPDATE users SET wallet = :new_amount, job_streak = :new_streak, last_work_date = :new_lwd WHERE id = :user_id", { "new_amount": current_balance + salary, "new_streak": new_streak, "new_lwd": today.strftime("%Y-%m-%d %H:%M"), "user_id": ctx.author.id, }, ) Data.conn.commit() await ctx.send( f"You finished a day's worth of work and feel satisfied! You earned **{salary} beans** and you're on a **{new_streak} day** streak!" )
async def pay(self, ctx, user: discord.User, amount: int): if ctx.author.id == user.id: await ctx.send("You can't do that to yourself, smh...") return if amount == 0: await ctx.send( "Why are you using this command if you aren't giving them beans?" ) return elif amount < 1: await ctx.send( "You can't trick me into taking away their money fool!" ) return Data.check_user_entry(ctx.author) Data.check_user_entry(user) # Get current wallet balances Data.c.execute( "SELECT wallet FROM users WHERE id = :user_id", {"user_id": ctx.author.id}, ) current_balance = Data.c.fetchone()[0] Data.c.execute( "SELECT wallet FROM users WHERE id = :user_id", {"user_id": user.id}, ) current_receiver_balance = Data.c.fetchone()[0] # Ensure user has enough to pay if amount > current_balance: amount_needed = amount - current_balance await ctx.send( f"You don't have enough beans for that. You need {amount_needed} more beans." ) return # Update balances Data.c.execute( "UPDATE users SET wallet = :new_amount WHERE id = :user_id", {"new_amount": current_balance - amount, "user_id": ctx.author.id}, ) Data.c.execute( "UPDATE users SET wallet = :new_amount WHERE id = :user_id", { "new_amount": current_receiver_balance + amount, "user_id": user.id, }, ) Data.conn.commit() await ctx.send(f"You paid **{amount} beans** to {user.display_name}.")
async def prefix(self, ctx: commands.Context, pref: str = "s!"): Data.check_guild_entry(ctx.guild) Data.c.execute( "UPDATE guilds SET prefix = :new_prefix WHERE id = :guild_id", {"new_prefix": pref, "guild_id": ctx.guild.id}, ) Data.conn.commit() await ctx.send(f"The prefix has been changed to **{pref}**")
async def set_mute_role(self, ctx: commands.Context, role: discord.Role): Data.check_guild_entry(ctx.guild) Data.c.execute( "UPDATE guilds SET mute_role = :mute_role_id WHERE id = :guild_id", {"mute_role_id": role.id, "guild_id": ctx.guild.id}, ) Data.conn.commit() await ctx.send(f"The mute role has been set to **{role}**")
async def add_auto_response(self, ctx: commands.Context, *, options: str): options_split = options.split(",", maxsplit=1) if len(options_split) < 2: await ctx.send("Please provide all the fields.") return Data.check_guild_entry(ctx.guild) activation = options_split[0].strip() response = options_split[1].strip() Data.c.execute( "SELECT auto_responses FROM guilds WHERE id = :guild_id", {"guild_id": ctx.guild.id}, ) current_auto_resps = json.loads(Data.c.fetchone()[0]) if activation in current_auto_resps: def check_msg(message: discord.Message): return (message.author == ctx.author and message.channel == ctx.channel) await ctx.send( "An auto response with this activation already exists and will be overwritten by the new one. Do you want to continue? (Yes to continue, anything else to abort)" ) try: confirmation: discord.Message = await self.bot.wait_for( "message", check=check_msg, timeout=30) if confirmation.content.lower() == "yes": await ctx.send("Overwriting existing auto response!") else: await ctx.send("Aborting!") return except asyncio.TimeoutError: await ctx.send("No response received, aborting!") return current_auto_resps[activation] = response Data.c.execute( "UPDATE guilds SET auto_responses = :new_responses WHERE id = :guild_id", { "new_responses": json.dumps(current_auto_resps), "guild_id": ctx.guild.id, }, ) Data.conn.commit() await ctx.send( f"New auto response added with\n\nActivation Phrase:```{activation}```\nResponse:```{response}```" )
def get_prefix(client, message): if not message.guild: return "sb!" Data.check_guild_entry(message.guild) Data.c.execute( "SELECT prefix FROM guilds WHERE id = :guild_id", {"guild_id": message.guild.id}, ) prefix = Data.c.fetchone()[0] return prefix
async def gamble(self, ctx, amount: int): Data.check_user_entry(ctx.author) Data.c.execute( "SELECT wallet FROM users WHERE id = :user_id", {"user_id": ctx.author.id}, ) wallet = Data.c.fetchone()[0] if amount > wallet: amount_needed = amount - wallet await ctx.send( f"You don't have enough beans for that. You need {amount_needed} more beans." ) return player_roll = random.randint(1, 6) dealer_roll = random.randint(1, 6) if player_roll > dealer_roll: amount_won = math.ceil((player_roll - dealer_roll) / 6 * amount) elif player_roll < dealer_roll: amount_won = -amount else: amount_won = 0 Data.c.execute( "UPDATE users SET wallet = :new_wallet WHERE id = :user_id", { "new_wallet": wallet + amount_won, "user_id": ctx.author.id }, ) Data.conn.commit() gamble_embed = discord.Embed(title="Gambling Results") gamble_embed.add_field(name="You rolled", value=str(player_roll)) gamble_embed.add_field(name="Dealer rolled", value=str(dealer_roll)) if player_roll > dealer_roll: gamble_embed.color = discord.Color.green() gamble_embed.set_footer(text=f"You won {amount_won} beans!") elif player_roll < dealer_roll: gamble_embed.color = discord.Color.red() gamble_embed.set_footer(text=f"You lost {abs(amount_won)} beans!") else: gamble_embed.color = discord.Color.gold() gamble_embed.set_footer(text="You won nothing!") await ctx.send(embed=gamble_embed)
async def reminder( self, reminder_id: str, user: discord.User, seconds: float, reminder_msg: str, reminder_start_time: datetime, ): await asyncio.sleep(seconds) rem_start_time_str = humanize.naturaltime(reminder_start_time) await user.send( f"You asked me to remind you {rem_start_time_str} about:" f"\n*{reminder_msg}*") Data.delete_reminder_entry(reminder_id)
def main(): Data.create_tables() add_cogs() try: from bot import ipc_routes bot.ipc.start() bot.run(TOKEN) except KeyboardInterrupt: pass except SystemExit: pass finally: print("Exiting...") Data.conn.close()
async def on_message(self, message: discord.Message): if not message.guild or message.author.bot: return def spam_check(msg): return ((msg.author == message.author) and len(msg.mentions) and ( (datetime.datetime.utcnow() - msg.created_at).seconds < 20)) Data.check_guild_entry(message.guild) Data.c.execute( "SELECT activated_automod FROM guilds WHERE id = :guild_id", {"guild_id": message.guild.id}, ) activated_features = json.loads(Data.c.fetchone()[0]) # if channel id's data contains "links": if "links" in activated_features: if search(self.url_regex, message.content): await message.delete() await message.channel.send( f"{message.author.mention}, You cannot send links " "in this channel!", delete_after=3, ) # if channel id's data contains "images" if "images" in activated_features: if any([hasattr(a, "width") for a in message.attachments]): await message.delete() await message.channel.send( f"{message.author.mention}, You cannot send images " "in this channel!", delete_after=3, ) # if channel id's data contains "spam": if "spam" in activated_features: if (len( list( filter(lambda m: spam_check(m), self.bot.cached_messages))) >= 5): await message.channel.send( f"{message.author.mention}, Do not spam mentions " "in this channel!", delete_after=3, )
async def withdraw(self, ctx, amount): Data.check_user_entry(ctx.author) # Get current wallet and banks balances Data.c.execute( "SELECT wallet, bank FROM users WHERE id = :user_id", {"user_id": ctx.author.id}, ) data = Data.c.fetchone() wallet_amount = data[0] bank_amount = data[1] if str(amount) == "all" or str(amount) == "max": amount = bank_amount else: amount = int(amount) if amount == 0: await ctx.send( "Why are you using this command if you aren't withdrawing anything?" ) return elif amount < 1: await ctx.send( "There's a command for depositing as well, you know..." ) return # Ensure user has enough to deposit if amount > bank_amount: await ctx.send("You don't have that many beans in your bank.") return # Update balances Data.c.execute( "UPDATE users SET wallet = :new_wallet_amount, bank = :new_bank_amount WHERE id = :user_id", { "new_wallet_amount": wallet_amount + amount, "new_bank_amount": bank_amount - amount, "user_id": ctx.author.id, }, ) Data.conn.commit() await ctx.send(f"You withdrew **{amount} beans** from your bank.")
async def takejob(self, ctx, *, job_name: str): Data.check_user_entry(ctx.author) jn = None js = None jr = None # Get current work streak Data.c.execute( "SELECT job_streak FROM users WHERE id = :user_id", {"user_id": ctx.author.id}, ) current_streak = Data.c.fetchone()[0] for (job_id, job) in enumerate(self.jobs_data): if job["name"].lower() == job_name.lower(): jn = job["name"] js = job["salary"] jr = job["streak_requirement"] if current_streak < jr: await ctx.send( f"You need a **{jr} day** streak to get this job! You're currently on a **{current_streak} day** streak." ) return # Set user's job_id to specified job Data.c.execute( "UPDATE users SET job_id = :job_id WHERE id = :user_id", { "job_id": job_id, "user_id": ctx.author.id }, ) Data.conn.commit() break if jn is None or js is None or jr is None: return embed = discord.Embed(title=f"You have become a {jn}!", color=self.theme_color) embed.add_field(name="You will earn", value=f"{js} beans per day") await ctx.send(embed=embed)
async def afk(self, ctx: commands.Context, *, reason: str): already_afk = Data.afk_entry_exists(ctx.author) if already_afk: Data.c.execute( """UPDATE afks SET afk_reason = :new_reason WHERE user_id = :user_id""", { "new_reason": reason, "user_id": ctx.author.id }, ) else: Data.create_new_afk_data(ctx.author, reason) Data.conn.commit() await ctx.send( f"You have been AFK'd for the following reason:\n*{reason}*")
async def on_member_join(self, member: discord.Member): guild: discord.Guild = member.guild Data.check_guild_entry(guild) Data.c.execute( """SELECT welcome_message, welcome_channel, auto_role FROM guilds WHERE id = :guild_id""", {"guild_id": guild.id}, ) data = Data.c.fetchone() welcome_message = data[0] welcome_channel_id = data[1] if welcome_channel_id == "disabled": return if not welcome_channel_id: welcome_channel = await self.find_welcome_channel(guild) # Exit the function if no welcome channel is provided or # automatically found if not welcome_channel: return else: welcome_channel = guild.get_channel(int(welcome_channel_id)) if data[2]: auto_role = guild.get_role(int(data[2])) else: auto_role = None if not welcome_message: welcome_message = self.default_welcome_msg(guild) # Replace placeholders with actual information welcome_message = welcome_message.replace("[mention]", member.mention) welcome_message = welcome_message.replace("[member]", str(member)) await welcome_channel.send(welcome_message) # Give auto role to new member if they are not a bot if not member.bot and auto_role: await member.add_roles(auto_role)
async def set_leave_message( self, ctx: commands.Context, *, message: str = None ): Data.check_guild_entry(ctx.guild) Data.c.execute( "UPDATE guilds SET leave_message = :new_message WHERE id = :guild_id", {"new_message": message, "guild_id": ctx.guild.id}, ) Data.conn.commit() if message: await ctx.send( f"This server's leave message has been set to:\n{message}" ) else: await ctx.send( "This server's leave message has been reset to default" )
async def powerups(self, ctx): Data.check_user_entry(ctx.author) Data.c.execute( "SELECT powerups FROM users WHERE id = :user_id", {"user_id": ctx.author.id}, ) powerups = json.loads(Data.c.fetchone()[0]) powerups_embed = discord.Embed( title=f"{ctx.author.display_name}'s Active Powerups", color=self.theme_color, ) for powerup in powerups: powerup_name = " ".join(powerup.split("_")).title() powerups_embed.add_field(name=powerup_name, value=powerups[powerup]) await ctx.send(embed=powerups_embed)
async def get_guild_mute_role(self, guild: discord.Guild): Data.check_guild_entry(guild) Data.c.execute( "SELECT mute_role FROM guilds WHERE id = :guild_id", {"guild_id": guild.id}, ) mute_role_id = Data.c.fetchone()[0] if mute_role_id is None: # Create mute role if none is provided mute_role = await self.create_mute_role(guild) else: # Get mute role if one was provided mute_role = guild.get_role(mute_role_id) # Check if the role provided still exists if mute_role is None: mute_role = await self.create_mute_role(guild) return mute_role
async def viewwordcount(self, ctx, *, word: str): Data.check_guild_entry(ctx.guild) guild_id = ctx.guild.id word = word.strip() Data.c.execute( "SELECT tracked_words FROM guilds WHERE id = :guild_id", {"guild_id": ctx.guild.id}, ) self.tracked_words[guild_id] = json.loads(Data.c.fetchone()[0]) try: word_count = self.tracked_words[guild_id][word] except KeyError: await ctx.send("This word is not being tracked...") return await ctx.send( f"The word **{word}** has been said **{word_count} times**!" )
async def set_welcome_channel( self, ctx: commands.Context, *, channel: discord.TextChannel = None ): Data.check_guild_entry(ctx.guild) if channel: channel_id = channel.id else: channel_id = "disabled" Data.c.execute( "UPDATE guilds SET welcome_channel = :channel_id WHERE id = :guild_id", {"channel_id": channel_id, "guild_id": ctx.guild.id}, ) Data.conn.commit() if channel: await ctx.send( f"The server's welcome channel has been set to {channel.mention}" ) else: await ctx.send("The server's welcome message has been disabled")
async def clear_infractions(self, ctx: commands.Context, member: discord.Member = None): if ctx.author.top_role <= member.top_role: await ctx.send( f"You cannot use the command on this person because their top role is higher than or equal to yours." ) return Data.check_guild_entry(ctx.guild) if member is None: Data.c.execute( "UPDATE guilds SET infractions = '[]' WHERE id = :guild_id", {"guild_id": ctx.guild.id}, ) Data.conn.commit() await ctx.send("Cleared all infractions in this server...") else: Data.c.execute( "SELECT infractions FROM guilds WHERE id = :guild_id", {"guild_id": ctx.guild.id}, ) user_infractions = json.loads(Data.c.fetchone()[0]) new_infractions = [ inf for inf in user_infractions if inf["member"] != member.id ] Data.c.execute( "UPDATE guilds SET infractions = :new_infractions WHERE id = :guild_id", { "new_infractions": json.dumps(new_infractions), "guild_id": ctx.guild.id, }, ) Data.conn.commit() await ctx.send( f"Cleared all infractions by **{member}** in this server...")