async def whois(self, ctx, member: typing.Optional[discord.Member] = None, handle: typing.Optional[str] = None): # TODO: Use embeds and pfps query = Query() if handle: user = await query.get_user(handle) handle = user.username author_id = query.get_handle_user(handle, ctx.guild.id) if author_id: # member = await self.bot.fetch_user(author_id) name = ctx.message.guild.get_member(author_id) await ctx.send(f'`{handle}` is `{name.nick or name.name}`') else: await ctx.send( f'`{handle}` is not linked with any account here...') elif member: handle = query.get_handle(member.id, ctx.guild.id) if handle: await ctx.send(f'`{member.nick or member.name}` is `{handle}`') else: await ctx.send( f'`{member.nick or member.name}` is not linked with any account here' ) else: # wtf pass
async def link(self, ctx, username: str): """Links your discord account to your dmoj account""" # Check if user exists query = Query() user = await query.get_user(username) if user is None: await ctx.send(f"{username} does not exist on DMOJ") return username = user.username if query.get_handle(ctx.author.id, ctx.guild.id): await ctx.send('%s, your handle is already linked with %s.' % (ctx.author.mention, query.get_handle(ctx.author.id, ctx.guild.id))) return if query.get_handle_user(username, ctx.guild.id): await ctx.send('This handle is already linked with another user') return problem = query.get_random_problem() if problem is None: await ctx.send('No problems are cached.. ' 'Pls do something about that') # Will implement this # Just cache the problems and get a random one return await ctx.send( '%s, submit a compiler error to <https://dmoj.ca/problem/%s> ' 'within 60 seconds' % (ctx.author.mention, problem.code)) await asyncio.sleep(60) submissions = await query.get_latest_submissions(username, 10) # if the user links twice, it might break the db # Should add decorator to prevent this if query.get_handle(ctx.author.id, ctx.guild.id): return for submission in submissions: if (submission.result == 'CE' and submission.problem[0].code == problem.code): handle = Handle_DB() handle.id = ctx.author.id handle.handle = username handle.user_id = user.id handle.guild_id = ctx.guild.id session.add(handle) session.commit() return await ctx.send( "%s, you now have linked your account to %s." % (ctx.author.name, username)) else: return await ctx.send('I don\'t see anything :monkey: ' '(Failed to link accounts)')
async def _set(self, ctx, member: discord.Member, username: str): """Manually link two accounts together""" query = Query() user = await query.get_user(username) if user is None: await ctx.send(f'{username} does not exist on dmoj') return username = user.username if query.get_handle(member.id, ctx.guild.id): await ctx.send( '%s, this handle is already linked with %s.' % (ctx.author.mention, query.get_handle(member.id, ctx.guild.id)) ) return if query.get_handle_user(username, ctx.guild.id): await ctx.send('This handle is already linked with another user') return handle = Handle_DB() handle.id = member.id handle.handle = username handle.user_id = user.id handle.guild_id = ctx.guild.id session.add(handle) session.commit() return await ctx.send("%s, %s is now linked with %s." % (ctx.author.name, member.name, username))
async def link(ctx: lightbulb.Context) -> None: username = ctx.options.username # Check if user exists query = Query() try: user = await query.get_user(username) if user is None: raise ObjectNotFound() except ObjectNotFound: await ctx.respond(escape_markdown(f"{username} does not exist on DMOJ")) return username = user.username if query.get_handle(ctx.author.id, ctx.get_guild().id): await ctx.respond( "%s, your handle is already linked with %s." % (ctx.author.mention, query.get_handle(ctx.author.id, ctx.get_guild().id)) ) return if query.get_handle_user(username, ctx.get_guild().id): await ctx.respond("This handle is already linked with another user") return # verify from dmoj user description description = await query.get_user_description(username) userKey = hashlib.sha256(str(ctx.author.id).encode()).hexdigest() if userKey not in description: await ctx.respond( "Put `" + userKey + "` in your DMOJ user description (https://dmoj.ca/edit/profile/) " "and run the command again." ) return handle = Handle_DB() handle.id = ctx.author.id handle.handle = username handle.user_id = user.id handle.guild_id = ctx.get_guild().id session.add(handle) session.commit() await ctx.respond(escape_markdown("%s, you now have linked your account to %s" % (ctx.author, username))) rank_to_role = {} rc = lightbulb.RoleConverter(ctx) for role_id in ctx.get_guild().get_roles(): role = await rc.convert(str(role_id)) if role.name in RANKS: rank_to_role[role.name] = role rank = rating_to_rank(user.rating) # TODO Add guild specific option to disable updating roles if rank in rank_to_role: await _update_rank(ctx.member, rank_to_role[rank], "Dmoj account linked") else: await ctx.respond("You are missing the `" + rank + "` role")
async def _set(self, ctx, member, username: str): """Manually link two accounts together""" query = Query() member = await query.parseUser(ctx, member) if username != "+remove": user = await query.get_user(username) if user is None: await ctx.send(f'{username} does not exist on dmoj') return username = user.username handle = query.get_handle(member.id, ctx.guild.id) if handle == username: return await ctx.send( f'{member.display_name} is already linked with {handle}') if handle: handle = session.query(Handle_DB)\ .filter(Handle_DB.id == member.id)\ .filter(Handle_DB.guild_id == ctx.guild.id).first() session.delete(handle) session.commit() await ctx.send( f'Unlinked {member.display_name} with handle {handle.handle}') if username == "+remove": return if query.get_handle_user(username, ctx.guild.id): await ctx.send('This handle is already linked with another user') return handle = Handle_DB() handle.id = member.id handle.handle = username handle.user_id = user.id handle.guild_id = ctx.guild.id session.add(handle) session.commit() await ctx.send(f"Linked {member.name} with {username}.") rank_to_role = { role.name: role for role in ctx.guild.roles if role.name in RANKS } rank = self.rating_to_rank(user.rating) if rank in rank_to_role: await self._update_rank(ctx.author, rank_to_role[rank], 'Dmoj account linked') else: await ctx.send("You are missing the " + rank.name + " role")
async def link(self, ctx, username: str): '''Links your discord account to your dmoj account''' # Check if user exists query = Query() user = await query.get_user(username) if user is None: await ctx.send(f'{username} does not exist on DMOJ') return username = user.username if query.get_handle(ctx.author.id, ctx.guild.id): await ctx.send('%s, your handle is already linked with %s.' % (ctx.author.mention, query.get_handle(ctx.author.id, ctx.guild.id))) return if query.get_handle_user(username, ctx.guild.id): await ctx.send('This handle is already linked with another user') return # verify from dmoj user description description = await query.get_user_description(username) userKey = hashlib.sha256(str(ctx.author.id).encode()).hexdigest() if userKey not in description: await ctx.send( 'Put `' + userKey + '` in your DMOJ user description (https://dmoj.ca/edit/profile/) ' 'and run the command again.') return handle = Handle_DB() handle.id = ctx.author.id handle.handle = username handle.user_id = user.id handle.guild_id = ctx.guild.id session.add(handle) session.commit() await ctx.send('%s, you now have linked your account to %s' % (ctx.author.name, username)) return rank_to_role = { role.name: role for role in ctx.guild.roles if role.name in RANKS } rank = self.rating_to_rank(user.rating) if rank in rank_to_role: await self._update_rank(ctx.author, rank_to_role[rank], 'Dmoj account linked') else: await ctx.send('You are missing the ' + rank.name + ' role')
async def whois(self, ctx, member: typing.Optional[discord.Member] = None, handle: typing.Optional[str] = None): query = Query() username, linked_username, pfp = None, None, None if handle: user = None try: user = await query.get_user(handle) except ObjectNotFound: username = None if user: handle = user.username author_id = query.get_handle_user(handle, ctx.guild.id) username = handle if author_id: member = ctx.message.guild.get_member(author_id) linked_username = member.nick or member.name pfp = member.avatar_url elif member: handle = query.get_handle(member.id, ctx.guild.id) username = member.nick or member.name if handle: linked_username = handle pfp = await query.get_pfp(handle) if linked_username: embed = discord.Embed( color=0xfcdb05, title=f'{username} is {linked_username}', ) embed.set_thumbnail(url=pfp) await ctx.send(embed=embed) elif username: embed = discord.Embed( title=f'{username} is not linked with any account here', color=0xfcdb05, ) await ctx.send(embed=embed) else: name = None if member: name = member.nick or member.name embed = discord.Embed( title=f'Nothing found on {handle or name}', color=0xfcdb05, ) await ctx.send(embed=embed)
async def whois(ctx): member = ctx.options.member handle = ctx.options.handle query = Query() username, linked_username, pfp = None, None, None if handle: user = None try: user = await query.get_user(handle) except ObjectNotFound: username = None if user: handle = user.username author_id = query.get_handle_user(handle, ctx.get_guild().id) username = handle if author_id: member = ctx.get_guild().get_member(author_id) linked_username = member.nickname or member.username pfp = member.avatar_url elif member: handle = query.get_handle(member.id, ctx.get_guild().id) username = member.nickname or member.username if handle: linked_username = handle pfp = await query.get_pfp(handle) if linked_username: embed = hikari.Embed( color=0xFCDB05, title=escape_markdown(f"{username} is {linked_username}"), ) embed.set_thumbnail(pfp) return await ctx.respond(embed=embed) elif username: embed = hikari.Embed( title=escape_markdown(f"{username} is not linked with any account here"), color=0xFCDB05, ) return await ctx.respond(embed=embed) name = None if member: name = member.nickname or member.username embed = hikari.Embed( title=escape_markdown(f"Nothing found on {handle or name}"), color=0xFCDB05, ) await ctx.respond(embed=embed)
async def userinfo(ctx): """Show user profile and latest submissions Use surround your username with '' if it can be interpreted as a number """ username = ctx.options.username amount = ctx.options.amount query = Query() username = username or query.get_handle(ctx.author.id, ctx.get_guild().id) # If user is not found in db if username is None: username = str(amount) amount = None if username is None: return await ctx.respond("No username given!") username = username.replace("'", "") if amount is not None: amount = min(amount, 8) if amount < 1: return await ctx.respond("Please request at least one submission") try: user = await query.get_user(username) except ObjectNotFound: return await ctx.respond(f"{username} does not exist on DMOJ") username = user.username def is_rated(contest): return 1 if contest.is_rated else 0 discordHandle = ctx.get_guild().get_member( query.get_handle_user(username, ctx.get_guild().id)) if discordHandle: discordHandle = discordHandle.nickname or discordHandle.username else: discordHandle = "Unknown" if user.rating is None: color = 0xFEFEFE # it breaks when I set it to white elif user.rating >= 3000: color = 0x000000 elif user.rating >= 2700: color = 0xA00000 elif user.rating >= 2400: color = 0xEE0000 elif user.rating >= 1900: color = 0xFFB100 elif user.rating >= 1600: color = 0x800080 elif user.rating >= 1300: color = 0x0000FF elif user.rating >= 1000: color = 0x00A900 elif user.rating >= 0: color = 0x999999 else: color = 0x000000 description = f"Discord name: {discordHandle}" embed = hikari.Embed( title=username, url=f"https://dmoj.ca/user/{username}", description=description, color=color, # rating color ) embed.set_thumbnail(await query.get_pfp(username)) embed.add_field(name="Points", value=str(round(user.performance_points)) + "/" + str(round(user.points)), inline=True) embed.add_field(name="Problems Solved", value=user.problem_count, inline=True) embed.add_field(name="Rating", value=str(user.rating) + "/" + str(user.max_rating), inline=True) embed.add_field(name="Contests Written", value=sum(map(is_rated, user.contests)), inline=True) await ctx.respond(embed=embed) if amount is None: return submissions = await query.get_latest_submissions(username, amount) embed = hikari.Embed(title=f"{username}'s latest submissions", color=0xFFFF00) for submission in submissions: problem = submission.problem[0] if problem.points is not None: points = str(int(problem.points)) + "p" if problem.partial: points += "p" else: points = "???" true_short_name = submission.language[0].short_name if true_short_name == "": # wtf dmoj true_short_name = submission.language[0].key embed.add_field( name="%s / %s" % (str(submission.score_num), str(submission.score_denom)), value="%s | %s" % (submission.result, true_short_name), inline=True, ) embed.add_field( name="%s (%s)" % (submission.problem[0].name, points), value="%s | [Problem](https://dmoj.ca/problem/%s)" % ( submission.date.astimezone(TZ).strftime("%b. %d, %Y, %I:%M %p") .replace("AM", "a.m.").replace("PM", "p.m."), submission.problem[0].code, ), # Jan. 13, 2021, 12:17 a.m. # %b. %d, %Y, %I:%M %p inline=True, ) try: embed.add_field( name="%.2fs" % submission.time, value="%s" % submission.memory_str, inline=True, ) except TypeError: embed.add_field( name="---", value="%s" % submission.memory_str, inline=True, ) await ctx.respond(embed=embed) return None
async def userinfo(self, ctx, username: typing.Optional[str_not_int] = None, amount: typing.Optional[int] = None): """Show user profile and latest submissions Use surround your username with '' if it can be interpreted as a number """ query = Query() username = username or query.get_handle(ctx.author.id, ctx.guild.id) # If user is not found in db if username is None: username = str(amount) amount = None if username is None: return if amount is not None: amount = min(amount, 8) if amount < 1: return await ctx.send('Please request at least one submission') try: user = await query.get_user(username) except ObjectNotFound: return await ctx.send(f'{username} does not exist on DMOJ') username = user.username def is_rated(contest): return 1 if contest.is_rated else 0 discordHandle = ctx.message.guild.get_member(query.get_handle_user(username, ctx.guild.id)) if discordHandle: discordHandle = discordHandle.nick or discordHandle.name else: discordHandle = "Unknown" if user.rating is None: color = 0xfefefe # it breaks when I set it to white elif user.rating >= 3000: color = 0x000000 elif user.rating >= 2600: color = 0xa00000 elif user.rating >= 2200: color = 0xee0000 elif user.rating >= 1800: color = 0xffb100 elif user.rating >= 1500: color = 0x800080 elif user.rating >= 1200: color = 0x0000ff elif user.rating >= 1000: color = 0x00a900 elif user.rating >= 0: color = 0x999999 else: color = 0x000000 description = f'Discord name: {discordHandle}' embed = discord.Embed( title=username, url=f'https://dmoj.ca/user/{username}', description=description, color=color, # rating color ) embed.set_thumbnail(url=await query.get_pfp(username)) embed.add_field( name="Points", value=str(round(user.performance_points)) + "/" + str(round(user.points)), inline=True ) embed.add_field( name="Problems Solved", value=user.problem_count, inline=True ) embed.add_field( name="Rating", value=str(user.rating) + "/" + str(user.max_rating), inline=True ) embed.add_field( name="Contests Written", value=sum(map(is_rated, user.contests)), inline=True ) await ctx.send(embed=embed) if amount is None: return submissions = await query.get_latest_submissions(username, amount) embed = discord.Embed( title=f"{username}'s latest submissions", color=0xffff00 ) for submission in submissions: problem = submission.problem[0] if problem.points is not None: points = str(int(problem.points)) + 'p' if problem.partial: points += 'p' else: points = '???' true_short_name = submission.language[0].short_name if true_short_name == '': # wtf dmoj true_short_name = submission.language[0].key embed.add_field( name="%s / %s" % (str(submission.score_num), str(submission.score_denom)), value="%s | %s" % (submission.result, true_short_name), inline=True ) embed.add_field( name="%s (%s)" % (submission.problem[0].name, points), value="%s | [Problem](https://dmoj.ca/problem/%s)" % (submission.date.astimezone(TZ). strftime("%b. %d, %Y, %I:%M %p"). replace('AM', 'a.m.'). replace('PM', 'p.m.'), submission.problem[0].code), # Jan. 13, 2021, 12:17 a.m. # %b. %d, %Y, %I:%M %p inline=True ) try: embed.add_field( name="%.2fs" % submission.time, value="%s" % submission.memory_str, inline=True, ) except TypeError: embed.add_field( name="---", value="%s" % submission.memory_str, inline=True, ) await ctx.send(embed=embed) return None
async def _set(ctx): """Manually link two accounts together""" # TODO: I don't like the bot spamming replies to itself, figure out a way to lessen that member = ctx.options.member username = ctx.options.handle query = Query() if username != "+remove": try: user = await query.get_user(username) if user is None: raise ObjectNotFound() except ObjectNotFound: await ctx.respond(escape_markdown(f"{username} does not exist on dmoj")) return username = user.username handle = query.get_handle(member.id, ctx.get_guild().id) if handle == username: return await ctx.respond(escape_markdown(f"{member.display_name} is already linked with {handle}")) if handle: handle = ( session.query(Handle_DB) .filter(Handle_DB.id == member.id) .filter(Handle_DB.guild_id == ctx.get_guild().id) .first() ) session.delete(handle) session.commit() await ctx.respond(escape_markdown(f"Unlinked {member.display_name} with handle {handle.handle}")) if username == "+remove": return if query.get_handle_user(username, ctx.get_guild().id): await ctx.respond("This handle is already linked with another user") return handle = Handle_DB() handle.id = member.id handle.handle = username handle.user_id = user.id handle.guild_id = ctx.get_guild().id session.add(handle) session.commit() await ctx.respond(escape_markdown(f"Linked {member.display_name} with {username}")) rank_to_role = {} rc = lightbulb.RoleConverter(ctx) for role_id in ctx.get_guild().get_roles(): role = await rc.convert(str(role_id)) if role.name in RANKS: rank_to_role[role.name] = role rank = rating_to_rank(user.rating) if rank in rank_to_role: await _update_rank(member, rank_to_role[rank], "Dmoj account linked") else: await ctx.respond("You are missing the `" + rank.name + "` role")