From 670e980e2bf46096d03a2592cefbe38f463b3879 Mon Sep 17 00:00:00 2001 From: tanmaypardeshi Date: Tue, 17 Oct 2023 03:31:07 -0400 Subject: [PATCH 1/9] Added Rank Feature --- src/bot.py | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 73 insertions(+), 3 deletions(-) diff --git a/src/bot.py b/src/bot.py index a8b0a9b8..b7feefc1 100644 --- a/src/bot.py +++ b/src/bot.py @@ -122,6 +122,14 @@ async def on_ready(): ) ''') + db.mutation_query(''' + CREATE TABLE IF NOT EXISTS rank ( + user_id INT NOT NULL, + experience INT DEFAULT 0, + level INT DEFAULT 0 + ) + ''') + event_creation.init(bot) office_hours.init(bot) await cal.init(bot) @@ -163,7 +171,17 @@ async def on_guild_join(guild): await channel.send(instructors + " is the Instructor!") else: await channel.send(instructors + " are the Instructors!") - await channel.send("To add Instructors, type \"!setInstructor @\"") + await channel.send("To add Instructors, type \"!setInstructor @\"")\ + + # Initialize ranking system + + for x in guild.members: + if x.bot == False: + insert_query = f"INSERT INTO rank (user_id) VALUES ({x.id})" + db.mutation_query(insert_query) + print("Ranking system initialized!") + await channel.send("Ranking system initialized!") + #await channel.send("To remove instructors, type \"!removeInstructor @\"") #Create Text channels if they don't exist overwrites = {guild.default_role: discord.PermissionOverwrite(read_messages=False, @@ -189,6 +207,7 @@ async def on_guild_join(guild): await channel.send("regrade-requests channel has been added!") else: await channel.send("regrade-requests channel is already present!") + ########################### # Function: on_member_join @@ -199,9 +218,12 @@ async def on_guild_join(guild): @bot.event async def on_member_join(member): channel = get(member.guild.text_channels, name='general') - await channel.send(f"Hello {member}!") + insert_query = f"INSERT INTO rank (user_id) VALUES (?)" + db.mutation_query(insert_query, (member.id,)) + await channel.send(f"Hello {member}! Your rank details are as follows. Level: 0, Experience: 0") await member.send(f'You have joined {member.guild.name}!') + ########################### # Function: on_member_remove # Description: run when member leaves a guild in which bot is alreay present @@ -211,6 +233,8 @@ async def on_member_join(member): @bot.event async def on_member_remove(member): channel = get(member.guild.text_channels, name='general') + delete_query = f"DELETE FROM rank where user_id=?" + db.mutation_query(delete_query, (member.id,)) await channel.send(f"{member.name} has left") ########################### @@ -280,6 +304,19 @@ async def on_message(message): else: pass + # Ranking System + if message.author.bot == False: + id_query = f"SELECT * FROM rank where user_id=?" + result = db.select_query(id_query, (message.author.id,)) + result = result.fetchone() + if result[1] == 99: + message.channel.send(f"{message.author.mention} has advanced to level {result[2]+1}!") + update_query = f"UPDATE rank SET experience=0, level=? WHERE user_id=?" + db.mutation_query(update_query, (result[2]+1, message.author.id)) + else: + update_query = f"UPDATE rank SET experience=? WHERE user_id=?" + db.mutation_query(update_query, (result[1]+1, message.author.id)) + ########################### # Function: on_message_edit @@ -309,6 +346,39 @@ async def test(ctx): ''' simple sanity check ''' await ctx.send('test successful') +########################### +# Function: get_rank +# Description: Command used to get level and experience +# Inputs: +# - ctx: context of the command +# - member: user to whose rank is to be printed +# Outputs: +# - Sends information back to channel +########################### +@bot.command(name='rank', help='Get rank of user') +async def get_rank(ctx, member: discord.User = None): + query = "SELECT * FROM rank where user_id=?" + rank_query = "SELECT p1.*, (SELECT COUNT(*) FROM rank AS p2 WHERE p2.level < p1.level) AS level_rank FROM rank AS p1 WHERE p1.user_id=?" + # Get your own rank + if member == None: + result = db.select_query(query, (ctx.author.id,)) + rank_result = db.select_query(rank_query, (ctx.author.id,)) + result = result.fetchone() + rank = rank_result.fetchone() + print(rank) + await ctx.channel.send(f"{ctx.author.mention}'s Rank = {rank[3]}, Level = {result[2]} and Experience = {result[1]}") + # Get some other users rank + else: + result = db.select_query(query, (member.id,)) + rank_result = db.select_query(rank_query, (member.id,)) + result = result.fetchone() + rank = rank_result.fetchone() + print(rank) + if result == None: + await ctx.channel.send("No such user in the database") + else: + await ctx.channel.send(f"{member.mention}'s Rank = {rank[3]}, Level = {result[2]} and Experience = {result[1]}") + ########################### # Function: get_instructor # Description: Command used to give Instructor role out by instructors @@ -982,4 +1052,4 @@ async def end_tests(ctx): ########################### def test_dummy(): ''' run bot command ''' - bot.run(TOKEN) + bot.run(TOKEN) \ No newline at end of file From 5703c8ede1f63a45b1b5c09f6f3028516c7e5bb0 Mon Sep 17 00:00:00 2001 From: tanmaypardeshi Date: Thu, 19 Oct 2023 12:08:28 -0400 Subject: [PATCH 2/9] Added card UI for rank feature --- spam.txt | 3 +++ src/bot.py | 44 ++++++++++++++++++++++++++++---------------- src/rank_card.py | 26 ++++++++++++++++++++++++++ 3 files changed, 57 insertions(+), 16 deletions(-) create mode 100644 src/rank_card.py diff --git a/spam.txt b/spam.txt index e69de29b..1597f0d1 100644 --- a/spam.txt +++ b/spam.txt @@ -0,0 +1,3 @@ +1152806796566745088 +1152806796566745088 +1152806796566745088 diff --git a/src/bot.py b/src/bot.py index 6f47b699..3a927dee 100644 --- a/src/bot.py +++ b/src/bot.py @@ -9,13 +9,11 @@ from psutil import Process, virtual_memory from apscheduler.schedulers.asyncio import AsyncIOScheduler - import discord from discord import Embed from discord.ext import commands from discord.utils import get from discord import __version__ as discord_version -#from discord_components import DiscordComponents from dotenv import load_dotenv @@ -31,8 +29,9 @@ import attendance import help_command import regrade -import utils import spam +from rank_card import draw_card + os.environ['TF_CPP_MIN_LOG_LEVEL'] = '1' @@ -182,17 +181,14 @@ async def on_guild_join(guild): await channel.send(instructors + " is the Instructor!") else: await channel.send(instructors + " are the Instructors!") - await channel.send("To add Instructors, type \"!setInstructor @\"")\ - - # Initialize ranking system - + await channel.send("To add Instructors, type \"!setInstructor @\"") + # Initialize ranking system for x in guild.members: if x.bot == False: insert_query = f"INSERT INTO rank (user_id) VALUES ({x.id})" db.mutation_query(insert_query) print("Ranking system initialized!") await channel.send("Ranking system initialized!") - #await channel.send("To remove instructors, type \"!removeInstructor @\"") #Create Text channels if they don't exist overwrites = {guild.default_role: discord.PermissionOverwrite(read_messages=False, @@ -217,8 +213,7 @@ async def on_guild_join(guild): await guild.create_text_channel('regrade-requests') await channel.send("regrade-requests channel has been added!") else: - await channel.send("regrade-requests channel is already present!") - + await channel.send("regrade-requests channel is already present!") ########################### # Function: on_member_join @@ -362,24 +357,41 @@ async def get_rank(ctx, member: discord.User = None): query = "SELECT * FROM rank where user_id=?" rank_query = "SELECT p1.*, (SELECT COUNT(*) FROM rank AS p2 WHERE p2.level < p1.level) AS level_rank FROM rank AS p1 WHERE p1.user_id=?" # Get your own rank - if member == None: + if member is None: result = db.select_query(query, (ctx.author.id,)) rank_result = db.select_query(rank_query, (ctx.author.id,)) result = result.fetchone() rank = rank_result.fetchone() - print(rank) - await ctx.channel.send(f"{ctx.author.mention}'s Rank = {rank[3]}, Level = {result[2]} and Experience = {result[1]}") + card = await draw_card( + xp=result[1], + level=result[2], + rank=rank[3], + name=ctx.author.name, + image_url=ctx.author.display_avatar, + next_level_xp=100, + ) + file = discord.File(card, filename="levelcard.png") + await ctx.channel.send(file=file) # Get some other users rank else: result = db.select_query(query, (member.id,)) rank_result = db.select_query(rank_query, (member.id,)) result = result.fetchone() rank = rank_result.fetchone() - print(rank) - if result == None: + if result is None: await ctx.channel.send("No such user in the database") else: - await ctx.channel.send(f"{member.mention}'s Rank = {rank[3]}, Level = {result[2]} and Experience = {result[1]}") + card = await draw_card( + xp=result[1], + level=result[2], + rank=rank[3], + name=member.name, + image_url=member.display_avatar, + next_level_xp=100, + ) + file = discord.File(card, filename="levelcard.png") + await ctx.channel.send(file=file) + ########################### # Function: get_instructor diff --git a/src/rank_card.py b/src/rank_card.py new file mode 100644 index 00000000..523bafd5 --- /dev/null +++ b/src/rank_card.py @@ -0,0 +1,26 @@ +from easy_pil import * + +async def draw_card(xp, level, rank, name, image_url, next_level_xp): + # Create a blank canvas with colour #141414 + background = Editor(Canvas((900,300), color="#141414")) + # Load the profile picture from discoerd and resize it to 200x200. + profile_picture = await load_image_async(str(image_url)) + profile = Editor(profile_picture).resize((200,200)).circle_image() + # Create two font sizes for font "poppin" + poppins = Font.poppins(size=40) + poppins_small = Font.poppins(size=20) + # Reshape the card for stylinhg + card_shape = [(600,0),(750,300),(900,300),(900,0)] + # Paste the profile picture on the polygon + background.polygon(card_shape, color="#5865F2") + background.paste(profile, (30,30)) + # Write text on the card + background.text((250,40), f"{name}", font=poppins, color="#FFFFFF") + background.rectangle((250, 100), width=350, height=2, fill="#FFFFFF") + background.text((250,130), f"Rank - {rank}", font=poppins, color="#FFFFFF") + background.text((250,180), + f"Level - {level} | XP - {xp}/{next_level_xp}", + font=poppins_small, + color="#FFFFFF") + return background.image_bytes + \ No newline at end of file From 8ce9710cdedb216d16e4387bf5ae620f79fb8322 Mon Sep 17 00:00:00 2001 From: tanmaypardeshi Date: Thu, 19 Oct 2023 12:10:02 -0400 Subject: [PATCH 3/9] Testing if code is lined properly - v1 --- src/bot.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/bot.py b/src/bot.py index 3a927dee..23e493a3 100644 --- a/src/bot.py +++ b/src/bot.py @@ -184,7 +184,7 @@ async def on_guild_join(guild): await channel.send("To add Instructors, type \"!setInstructor @\"") # Initialize ranking system for x in guild.members: - if x.bot == False: + if x.bot is False: insert_query = f"INSERT INTO rank (user_id) VALUES ({x.id})" db.mutation_query(insert_query) print("Ranking system initialized!") @@ -302,7 +302,7 @@ async def on_message(message): pass # Ranking System - if message.author.bot == False: + if message.author.bot is False: id_query = f"SELECT * FROM rank where user_id=?" result = db.select_query(id_query, (message.author.id,)) result = result.fetchone() @@ -1077,4 +1077,4 @@ async def end_tests(ctx): ########################### def test_dummy(): ''' run bot command ''' - bot.run(TOKEN) \ No newline at end of file + bot.run(TOKEN) From 73b12a528e0ded58996f72b4afdfbcbd2838ede6 Mon Sep 17 00:00:00 2001 From: tanmaypardeshi Date: Thu, 19 Oct 2023 12:13:33 -0400 Subject: [PATCH 4/9] Testing if code is lined properly - v2 --- src/bot.py | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/bot.py b/src/bot.py index 23e493a3..7c213a2a 100644 --- a/src/bot.py +++ b/src/bot.py @@ -213,7 +213,7 @@ async def on_guild_join(guild): await guild.create_text_channel('regrade-requests') await channel.send("regrade-requests channel has been added!") else: - await channel.send("regrade-requests channel is already present!") + await channel.send("regrade-requests channel is already present!") ########################### # Function: on_member_join @@ -301,18 +301,18 @@ async def on_message(message): else: pass - # Ranking System + # Ranking System if message.author.bot is False: id_query = f"SELECT * FROM rank where user_id=?" result = db.select_query(id_query, (message.author.id,)) result = result.fetchone() - if result[1] == 99: + if result[1] == 99: message.channel.send(f"{message.author.mention} has advanced to level {result[2]+1}!") update_query = f"UPDATE rank SET experience=0, level=? WHERE user_id=?" db.mutation_query(update_query, (result[2]+1, message.author.id)) else: - update_query = f"UPDATE rank SET experience=? WHERE user_id=?" - db.mutation_query(update_query, (result[1]+1, message.author.id)) + update_query = f"UPDATE rank SET experience=? WHERE user_id=?" + db.mutation_query(update_query, (result[1]+1, message.author.id)) ########################### @@ -355,7 +355,8 @@ async def test(ctx): @bot.command(name='rank', help='Get rank of user') async def get_rank(ctx, member: discord.User = None): query = "SELECT * FROM rank where user_id=?" - rank_query = "SELECT p1.*, (SELECT COUNT(*) FROM rank AS p2 WHERE p2.level < p1.level) AS level_rank FROM rank AS p1 WHERE p1.user_id=?" + rank_query = "SELECT p1.*, (SELECT COUNT(*) FROM rank AS p2 WHERE p2.level < p1.level) AS \ + level_rank FROM rank AS p1 WHERE p1.user_id=?" # Get your own rank if member is None: result = db.select_query(query, (ctx.author.id,)) @@ -368,13 +369,13 @@ async def get_rank(ctx, member: discord.User = None): rank=rank[3], name=ctx.author.name, image_url=ctx.author.display_avatar, - next_level_xp=100, + next_level_xp=100, ) - file = discord.File(card, filename="levelcard.png") + file = discord.File(card, filename="levelcard.png") await ctx.channel.send(file=file) # Get some other users rank else: - result = db.select_query(query, (member.id,)) + result = db.select_query(query, (member.id,)) rank_result = db.select_query(rank_query, (member.id,)) result = result.fetchone() rank = rank_result.fetchone() @@ -387,11 +388,10 @@ async def get_rank(ctx, member: discord.User = None): rank=rank[3], name=member.name, image_url=member.display_avatar, - next_level_xp=100, + next_level_xp=100, ) - file = discord.File(card, filename="levelcard.png") + file = discord.File(card, filename="levelcard.png") await ctx.channel.send(file=file) - ########################### # Function: get_instructor From cbd97211217aabb8c474ac52e8277546a94a36fd Mon Sep 17 00:00:00 2001 From: tanmaypardeshi Date: Thu, 19 Oct 2023 12:36:22 -0400 Subject: [PATCH 5/9] Testing if code is lined properly - v3 --- src/bot.py | 85 ++---------------------------------------------------- 1 file changed, 2 insertions(+), 83 deletions(-) diff --git a/src/bot.py b/src/bot.py index 7c213a2a..8f78bf70 100644 --- a/src/bot.py +++ b/src/bot.py @@ -75,7 +75,6 @@ async def on_ready(): end_time DATETIME ) ''') - db.mutation_query(''' CREATE TABLE IF NOT EXISTS exams ( guild_id INT, @@ -86,7 +85,6 @@ async def on_ready(): end_date DATETIME ) ''') - db.mutation_query(''' CREATE TABLE IF NOT EXISTS assignments ( guild_id INT, @@ -96,7 +94,6 @@ async def on_ready(): date DATETIME ) ''') - db.mutation_query(''' CREATE TABLE IF NOT EXISTS qna ( guild_id INT, @@ -105,7 +102,6 @@ async def on_ready(): qnumber INT ) ''') - db.mutation_query(''' CREATE TABLE IF NOT EXISTS regrade ( guild_id INT, @@ -113,7 +109,6 @@ async def on_ready(): questions VARCHAR(50) ) ''') - db.mutation_query(''' CREATE TABLE IF NOT EXISTS email_address ( author_id INT, @@ -121,7 +116,6 @@ async def on_ready(): is_active BOOLEAN NOT NULL CHECK (is_active IN (0, 1)) ) ''') - db.mutation_query(''' CREATE TABLE IF NOT EXISTS rank ( user_id INT NOT NULL, @@ -229,7 +223,6 @@ async def on_member_join(member): await channel.send(f"Hello {member}! Your rank details are as follows. Level: 0, Experience: 0") await member.send(f'You have joined {member.guild.name}!') - ########################### # Function: on_member_remove # Description: run when member leaves a guild in which bot is alreay present @@ -272,15 +265,12 @@ async def on_message(message): if message.author.bot and message.author.id == Test_bot_application_ID: ctx = await bot.get_context(message) await bot.invoke(ctx) - if message.author == bot.user: return - if profanity.check_profanity(message.content): await message.channel.send(message.author.name + ' says: ' + profanity.censor_profanity(message.content)) await message.delete() - await bot.process_commands(message) if message.content == 'hey bot': @@ -300,7 +290,6 @@ async def on_message(message): text_file.close() else: pass - # Ranking System if message.author.bot is False: id_query = f"SELECT * FROM rank where user_id=?" @@ -314,7 +303,6 @@ async def on_message(message): update_query = f"UPDATE rank SET experience=? WHERE user_id=?" db.mutation_query(update_query, (result[1]+1, message.author.id)) - ########################### # Function: on_message_edit # Description: run when a user edits a message @@ -564,7 +552,6 @@ async def answer_question(ctx, q_num, answer): await ctx.author.send('Please send answers to the #q-and-a channel.') await ctx.message.delete() - @bot.command(name='regrade-request', help='add regrade-request') async def submit_regrade_request(ctx,name:str,questions:str): @@ -764,7 +751,6 @@ async def checkchart(ctx, name: str): await ctx.send(f"Your requested chart:") await ctx.send(f"{storage[name]['URL']}") - async def update_chart(storage, name, link): """ Updates the URL of the chart @@ -783,13 +769,11 @@ async def update_chart(storage, name, link): ########################### @bot.command(name='stats', help='shows bot stats') - async def show_stats(ctx): embed = Embed(title="Bot stats", colour=ctx.author.colour, #thumbnail=bot.user.avatar_url, timestamp=datetime.utcnow()) - proc = Process() with proc.oneshot(): uptime = timedelta(seconds=time()-proc.create_time()) @@ -797,7 +781,6 @@ async def show_stats(ctx): mem_total = virtual_memory().total / (1024**2) mem_of_total = proc.memory_percent() mem_usage = mem_total * (mem_of_total / 100) - fields = [ ("Bot version", BOT_VERSION, True), ("Python version", python_version(), True), @@ -807,10 +790,8 @@ async def show_stats(ctx): ("Memory usage", f"{mem_usage:,.3f} / {mem_total:,.0f} MiB ({mem_of_total:.0f}%)", True), ("Users", f"{ctx.guild.member_count:,}", True) ] - for name, value, inline in fields: embed.add_field(name=name, value=value, inline=inline) - await ctx.send(embed=embed) ########################### # Function: poll @@ -826,33 +807,24 @@ async def show_stats(ctx): polls=[] scheduler = AsyncIOScheduler() - @bot.command(name='poll', help='Set Poll for a specified time and topic.') @commands.has_role('Instructor') async def create_poll(ctx, hours: int, question: str, *options): if len(options) > 10: await ctx.send("You can only supply a maximum of 10 options.") - else: - embed = Embed(title="Poll ‼", - description=question, - colour=ctx.author.colour, - timestamp=datetime.utcnow()) - + embed = Embed(title="Poll ‼",description=question,colour=ctx.author.colour, + timestamp=datetime.utcnow()) fields = [("Options", "\n".join([f"{numbers[idx]} {option}" for idx, option in enumerate(options)]), False), ("Instructions", "React to cast a vote!", False), ("Duration","The Voting will end in "+str(hours)+" Minutes",False)] - for name, value, inline in fields: embed.add_field(name=name, value=value, inline=inline) - message = await ctx.send(embed=embed) - for emoji in numbers[:len(options)]: await message.add_reaction(emoji) - polls.append((message.channel.id, message.id)) scheduler.add_job(complete_poll, "interval", minutes=hours,args=(message.channel.id, message.id)) @@ -860,9 +832,7 @@ async def create_poll(ctx, hours: int, question: str, *options): async def complete_poll(channel_id, message_id): message = await bot.get_channel(channel_id).fetch_message(message_id) - most_voted = max(message.reactions, key=lambda r: r.count) - await message.channel.send("The results are in and option "+most_voted.emoji+ " was the most popular with "+str(most_voted.count-1)+" votes!") polls.remove((message.channel.id, message.id)) @@ -872,7 +842,6 @@ async def complete_poll(channel_id, message_id): async def on_raw_reaction_add(payload): if payload.message_id in (poll[1] for poll in polls): message = await bot.get_channel(payload.channel_id).fetch_message(payload.message_id) - for reaction in message.reactions: if (not payload.member.bot and payload.member in await reaction.users().flatten() @@ -902,26 +871,21 @@ async def custom_profanity(ctx, pword): async def attend(ctx): await attendance.compute(bot, ctx) - @bot.command(name='create_email', help='Configures the specified email address against user.') async def create_email(ctx, email_id): await email_address.create_email(ctx, email_id) - @bot.command(name='update_email', help='Updates the configured email address against user.') async def update_email(ctx, email_id): await email_address.update_email(ctx, email_id) - @bot.command(name='view_email', help='displays the configured email address against user.') async def view_email(ctx): await email_address.view_email(ctx) - @bot.command(name='remove_email', help='deletes the configured email address against user.') async def delete_email(ctx): await email_address.delete_email(ctx) - ########################### # Function: help # Description: Describes the help @@ -931,108 +895,66 @@ async def delete_email(ctx): @bot.group(name='help', invoke_without_command=True) async def custom_help(ctx): await help_command.helper(ctx) - - @custom_help.command('answer') async def custom_answer(ctx): await help_command.answer(ctx) - - @custom_help.command('ask') async def custom_ask(ctx): await help_command.ask(ctx) - - @custom_help.command('attendance') async def custom_attendance(ctx): await help_command.attendance(ctx) - - @custom_help.command('begin-tests') async def custom_begin_tests(ctx): await help_command.begin_tests(ctx) - - @custom_help.command('create') async def custom_create(ctx): await help_command.create(ctx) - - @custom_help.command('end-tests') async def custom_end_tests(ctx): await help_command.end_tests(ctx) - - @custom_help.command('oh') async def custom_oh(ctx): await help_command.oh(ctx) - - @custom_help.command('ping') async def custom_ping(ctx): await help_command.ping(ctx) - - @custom_help.command('poll') async def custom_poll(ctx): await help_command.poll(ctx) - - @custom_help.command('setInstructor') async def custom_setInstructor(ctx): await help_command.setInstructor(ctx) - - @custom_help.command('stats') async def custom_stats(ctx): await help_command.stats(ctx) - - @custom_help.command('test') async def custom_test(ctx): await help_command.test(ctx) - - @custom_help.command('regrade-request') async def custom_regrade_request(ctx): await help_command.regrade_request(ctx) - - @custom_help.command('update-request') async def custom_update_request(ctx): await help_command.update_request(ctx) - - @custom_help.command('display-requests') async def custom_display_requests(ctx): await help_command.display_requests(ctx) - - @custom_help.command('remove-request') async def custom_remove_request(ctx): await help_command.remove_request(ctx) - - @custom_help.command('create_email') async def custom_create_email(ctx): await help_command.create_email(ctx) - - @custom_help.command('update_email') async def custom_update_email(ctx): await help_command.update_email(ctx) - - @custom_help.command('remove_email') async def custom_remove_email(ctx): await help_command.remove_email(ctx) - - @custom_help.command('view_email') async def custom_view_email(ctx): await help_command.view_email(ctx) - - ########################### # Function: begin_tests # Description: Start the automated testing @@ -1043,12 +965,9 @@ async def custom_view_email(ctx): async def begin_tests(ctx): ''' start test command ''' global TESTING_MODE - if ctx.author.id != Test_bot_application_ID: return - TESTING_MODE = True - test_oh_chan = next((ch for ch in ctx.guild.text_channels if 'office-hour-test' in ch.name), None) if test_oh_chan: From 9bafb8cc9e8c4daf2100d23fb66d105e8d974151 Mon Sep 17 00:00:00 2001 From: tanmaypardeshi Date: Thu, 19 Oct 2023 12:41:02 -0400 Subject: [PATCH 6/9] Updated requirements file --- requirements.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.txt b/requirements.txt index 30950b18..af41c602 100644 --- a/requirements.txt +++ b/requirements.txt @@ -9,4 +9,5 @@ pylint==3.0.1 psutil==5.9.5 apscheduler==3.10.4 pyshorteners~=1.0.1 -quickchart.io==1.0.0 \ No newline at end of file +quickchart.io==1.0.0 +easy-pil==0.3.0 \ No newline at end of file From e9d3cfbe0b30ea9605e080af378c6c7f773692fb Mon Sep 17 00:00:00 2001 From: tanmaypardeshi Date: Thu, 19 Oct 2023 15:19:06 -0400 Subject: [PATCH 7/9] need work on testcases --- spam.txt | 3 --- src/bot.py | 30 ++++++++++++------------- test/test_ranking.py | 53 ++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+), 19 deletions(-) create mode 100644 test/test_ranking.py diff --git a/spam.txt b/spam.txt index 1597f0d1..e69de29b 100644 --- a/spam.txt +++ b/spam.txt @@ -1,3 +0,0 @@ -1152806796566745088 -1152806796566745088 -1152806796566745088 diff --git a/src/bot.py b/src/bot.py index 8f78bf70..5edc2587 100644 --- a/src/bot.py +++ b/src/bot.py @@ -296,7 +296,9 @@ async def on_message(message): result = db.select_query(id_query, (message.author.id,)) result = result.fetchone() if result[1] == 99: - message.channel.send(f"{message.author.mention} has advanced to level {result[2]+1}!") + await message.channel.send( + f"{message.author.mention} has advanced to level {result[2]+1}!" + ) update_query = f"UPDATE rank SET experience=0, level=? WHERE user_id=?" db.mutation_query(update_query, (result[2]+1, message.author.id)) else: @@ -341,12 +343,12 @@ async def test(ctx): # - Sends information back to channel ########################### @bot.command(name='rank', help='Get rank of user') -async def get_rank(ctx, member: discord.User = None): +async def get_rank(ctx, member_id=None): query = "SELECT * FROM rank where user_id=?" rank_query = "SELECT p1.*, (SELECT COUNT(*) FROM rank AS p2 WHERE p2.level < p1.level) AS \ level_rank FROM rank AS p1 WHERE p1.user_id=?" # Get your own rank - if member is None: + if member_id is None: result = db.select_query(query, (ctx.author.id,)) rank_result = db.select_query(rank_query, (ctx.author.id,)) result = result.fetchone() @@ -363,13 +365,12 @@ async def get_rank(ctx, member: discord.User = None): await ctx.channel.send(file=file) # Get some other users rank else: - result = db.select_query(query, (member.id,)) - rank_result = db.select_query(rank_query, (member.id,)) - result = result.fetchone() - rank = rank_result.fetchone() - if result is None: - await ctx.channel.send("No such user in the database") - else: + try: + member = ctx.guild.get_member(int(member_id[2:-1])) + result = db.select_query(query, (member.id,)) + rank_result = db.select_query(rank_query, (member.id,)) + result = result.fetchone() + rank = rank_result.fetchone() card = await draw_card( xp=result[1], level=result[2], @@ -380,6 +381,8 @@ async def get_rank(ctx, member: discord.User = None): ) file = discord.File(card, filename="levelcard.png") await ctx.channel.send(file=file) + except Exception as e: + await ctx.channel.send(f"No {member_id} in the database") ########################### # Function: get_instructor @@ -770,10 +773,7 @@ async def update_chart(storage, name, link): @bot.command(name='stats', help='shows bot stats') async def show_stats(ctx): - embed = Embed(title="Bot stats", - colour=ctx.author.colour, - #thumbnail=bot.user.avatar_url, - timestamp=datetime.utcnow()) + embed = Embed(title="Bot stats",colour=ctx.author.colour, timestamp=datetime.utcnow()) proc = Process() with proc.oneshot(): uptime = timedelta(seconds=time()-proc.create_time()) @@ -810,7 +810,6 @@ async def show_stats(ctx): @bot.command(name='poll', help='Set Poll for a specified time and topic.') @commands.has_role('Instructor') async def create_poll(ctx, hours: int, question: str, *options): - if len(options) > 10: await ctx.send("You can only supply a maximum of 10 options.") else: @@ -859,7 +858,6 @@ async def custom_profanity(ctx, pword): ''' adding custom word to profanity list ''' profanity.custom_words.append(pword) await ctx.message.delete() - ########################### # Function: attendance # Description: Gets the attendance when requested by the instructor for audio channel diff --git a/test/test_ranking.py b/test/test_ranking.py new file mode 100644 index 00000000..c9093a3b --- /dev/null +++ b/test/test_ranking.py @@ -0,0 +1,53 @@ +# ########################### +# # Tests Ranking +# ########################### +# from time import sleep +# import discord +# from utils import wait_for_msg + +# ########################### +# # Function: test +# # Description: runs each test for ranking +# # Inputs: +# # - testing_bot: bot that sends commands to test TeachersPetBot +# # - guild_id: id of the guild that is using the TeachersPetBot +# # Outputs: None +# ########################### +# async def test(testing_bot): +# general_channel = discord.utils.get(testing_bot.get_all_channels(), name='general') +# await test_rank_for_same_user(testing_bot, general_channel) +# await test_rank_for_other_user(testing_bot, general_channel) +# await test_rank_for_other_user_who_does_not_exist(testing_bot, general_channel) + + +# ########################### +# # Function: test +# # Description: runs each test for command - !rank +# # Inputs: +# # - testing_bot: bot that sends commands to test TeachersPetBot +# # Outputs: None +# ########################### + +# async def test_rank_for_same_user(testing_bot, general_channel): +# print("testing ranking for same user") +# await general_channel.send('!rank') +# print('a') +# response = await testing_bot.wait_for('message', check=lambda x: x.guild.id==general_channel.guild.id and bool(x.attachments)) +# print('b') +# return response + +# async def test_rank_for_other_user(testing_bot, general_channel): +# await general_channel.send('!rank @Clorox-B2') +# response = await testing_bot.wait_for('message', check=lambda x: x.guild.id==general_channel.guild.id and bool(x.attachments)) +# print(response) +# return response + + +# async def test_rank_for_other_user_who_does_not_exist(testing_bot, general_channel): +# await general_channel.send('!rank @Clorox-B3') +# response = await testing_bot.wait_for('message', check=lambda x: x.guild.id==general_channel.guild.id and bool(x.attachments)) +# print(response) +# return response + + + From 9a3858428c67efe8e3f5af0009cb480894cef972 Mon Sep 17 00:00:00 2001 From: samuellouiskwiatkowski-martin Date: Thu, 19 Oct 2023 20:34:24 -0400 Subject: [PATCH 8/9] Fixing all rank tests --- src/bot.py | 12 ++++++--- test/test_ranking.py | 61 +++++++++++++++++++++----------------------- test/tests.py | 3 +++ 3 files changed, 41 insertions(+), 35 deletions(-) diff --git a/src/bot.py b/src/bot.py index 5edc2587..3177c8b9 100644 --- a/src/bot.py +++ b/src/bot.py @@ -137,6 +137,12 @@ async def on_ready(): office_hours.init(bot) spam.init(bot) #initialize the spam function of the bot so spam.py has # access to the bot and clearing starts + # Initialize ranking system + for x in bot.get_guild(guild_id).members: + # if x.bot is False: bots must have rank in order to do testing + insert_query = f"INSERT INTO rank (user_id) VALUES ({x.id})" + db.mutation_query(insert_query) + print("Ranking system initialized!") print('Logged in as') print(bot.user.name) print(bot.user.id) @@ -178,9 +184,9 @@ async def on_guild_join(guild): await channel.send("To add Instructors, type \"!setInstructor @\"") # Initialize ranking system for x in guild.members: - if x.bot is False: - insert_query = f"INSERT INTO rank (user_id) VALUES ({x.id})" - db.mutation_query(insert_query) + # if x.bot is False: bots must have rank in order to do testing + insert_query = f"INSERT INTO rank (user_id) VALUES ({x.id})" + db.mutation_query(insert_query) print("Ranking system initialized!") await channel.send("Ranking system initialized!") #await channel.send("To remove instructors, type \"!removeInstructor @\"") diff --git a/test/test_ranking.py b/test/test_ranking.py index c9093a3b..c16d514d 100644 --- a/test/test_ranking.py +++ b/test/test_ranking.py @@ -1,9 +1,9 @@ # ########################### # # Tests Ranking # ########################### -# from time import sleep -# import discord -# from utils import wait_for_msg +from time import sleep +import discord +from utils import wait_for_msg # ########################### # # Function: test @@ -13,11 +13,11 @@ # # - guild_id: id of the guild that is using the TeachersPetBot # # Outputs: None # ########################### -# async def test(testing_bot): -# general_channel = discord.utils.get(testing_bot.get_all_channels(), name='general') -# await test_rank_for_same_user(testing_bot, general_channel) -# await test_rank_for_other_user(testing_bot, general_channel) -# await test_rank_for_other_user_who_does_not_exist(testing_bot, general_channel) +async def test(testing_bot): + general_channel = discord.utils.get(testing_bot.get_all_channels(), name='general') + await test_rank_for_same_user(testing_bot, general_channel) + await test_rank_for_other_user(testing_bot, general_channel) + await test_rank_for_other_user_who_does_not_exist(testing_bot, general_channel) # ########################### @@ -27,27 +27,24 @@ # # - testing_bot: bot that sends commands to test TeachersPetBot # # Outputs: None # ########################### - -# async def test_rank_for_same_user(testing_bot, general_channel): -# print("testing ranking for same user") -# await general_channel.send('!rank') -# print('a') -# response = await testing_bot.wait_for('message', check=lambda x: x.guild.id==general_channel.guild.id and bool(x.attachments)) -# print('b') -# return response - -# async def test_rank_for_other_user(testing_bot, general_channel): -# await general_channel.send('!rank @Clorox-B2') -# response = await testing_bot.wait_for('message', check=lambda x: x.guild.id==general_channel.guild.id and bool(x.attachments)) -# print(response) -# return response - - -# async def test_rank_for_other_user_who_does_not_exist(testing_bot, general_channel): -# await general_channel.send('!rank @Clorox-B3') -# response = await testing_bot.wait_for('message', check=lambda x: x.guild.id==general_channel.guild.id and bool(x.attachments)) -# print(response) -# return response - - - +async def test_rank_for_same_user(testing_bot, general_channel): + print("testing ranking for same user") + await general_channel.send('!rank') + response = await testing_bot.wait_for('message', check=lambda x: x.guild.id==general_channel.guild.id and bool(x.attachments)) + return response + +async def test_rank_for_other_user(testing_bot, general_channel): + for member1 in testing_bot.get_all_members(): + if member1.name == 'cloroxb2': # enter the username of a member + member = member1 + print(member1.name) + await general_channel.send(f'!rank {member.mention}') + response = await testing_bot.wait_for('message', check=lambda x: x.guild.id==general_channel.guild.id and bool(x.attachments)) + print(response) + return response + + +async def test_rank_for_other_user_who_does_not_exist(testing_bot, general_channel): + await general_channel.send('!rank @Clorox-B3') + #response = await testing_bot.wait_for('message', check=lambda x: x.guild.id==general_channel.guild.id and bool(x.attachments)) + await wait_for_msg(testing_bot, general_channel, 'No @Clorox-B3 in the database') diff --git a/test/tests.py b/test/tests.py index acc6e95c..71220806 100644 --- a/test/tests.py +++ b/test/tests.py @@ -16,6 +16,7 @@ import test_regrade import test_email_address import test_spam +import test_ranking if platform.system() == 'Windows': asyncio.set_event_loop_policy(asyncio.WindowsSelectorEventLoopPolicy()) @@ -55,6 +56,8 @@ async def run_tests(): #await test_email_utility.test() print('testing spam\n----------') await test_spam.test(testing_bot, TEST_GUILD_ID) + print('testing rank card\n----------') + await test_ranking.test(testing_bot) except AssertionError as ex: print('exception: ', type(ex).__name__ + ':', ex) print('--') From a3cfcced821bb3193d27e3bed6600bcee5ba1978 Mon Sep 17 00:00:00 2001 From: samuellouiskwiatkowski-martin Date: Thu, 19 Oct 2023 20:35:44 -0400 Subject: [PATCH 9/9] Removed something that isn't needed in the final build --- src/bot.py | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/bot.py b/src/bot.py index 3177c8b9..d173c1b6 100644 --- a/src/bot.py +++ b/src/bot.py @@ -137,11 +137,6 @@ async def on_ready(): office_hours.init(bot) spam.init(bot) #initialize the spam function of the bot so spam.py has # access to the bot and clearing starts - # Initialize ranking system - for x in bot.get_guild(guild_id).members: - # if x.bot is False: bots must have rank in order to do testing - insert_query = f"INSERT INTO rank (user_id) VALUES ({x.id})" - db.mutation_query(insert_query) print("Ranking system initialized!") print('Logged in as') print(bot.user.name)