Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Identify #101

Merged
merged 5 commits into from
Aug 11, 2019
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions tle/cogs/handles.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import io

import discord
import random
from discord.ext import commands

from tle.util import codeforces_api as cf
Expand Down Expand Up @@ -128,6 +129,7 @@ def _make_pages(users):
class Handles(commands.Cog):
def __init__(self, bot):
self.bot = bot
self.identify_map = {}

@commands.group(brief='Commands that have to do with handles', invoke_without_command=True)
async def handle(self, ctx):
Expand All @@ -136,6 +138,8 @@ async def handle(self, ctx):

async def update_member_rank_role(self, member, role_to_assign):
role_names_to_remove = {rank.title for rank in cf.RATED_RANKS} - {role_to_assign.name}
if role_to_assign.name not in ['Newbie', 'Pupil', 'Specialist', 'Expert']:
role_names_to_remove.add('Purgatory')
to_remove = [role for role in member.roles if role.name in role_names_to_remove]
if to_remove:
await member.remove_roles(*to_remove, reason='Codeforces rank update')
Expand All @@ -146,10 +150,11 @@ async def update_member_rank_role(self, member, role_to_assign):
@commands.has_role('Admin')
async def set(self, ctx, member: discord.Member, handle: str):
"""Set Codeforces handle of a user."""
# CF API returns correct handle ignoring case, update to it
users = await cf.user.info(handles=[handle])
user = users[0]
await self._set(ctx, member, users[0])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this a typical case where you would write a decorator, but this is fine.


# CF API returns correct handle ignoring case, update to it
async def _set(self, ctx, member, user):
handle = user.handle
cf_common.user_db.cache_cfuser(user)
cf_common.user_db.sethandle(member.id, handle)
Expand All @@ -163,6 +168,35 @@ async def set(self, ctx, member: discord.Member, handle: str):
raise HandleCogError(f'Role for rank `{user.rank.title}` not present in the server')
await self.update_member_rank_role(member, roles[0])

@handle.command(brief='Identify yourself', usage='[handle]')
async def identify(self, ctx, handle: str):
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Docstring and usage?

"""Link a codeforces account to discord account by submitting a compile error to a random problem"""
users = await cf.user.info(handles=[handle])
if not users:
await ctx.send('`{handle}` not found on codeforces')
return

invoker = str(ctx.author)
problem = random.choice(cf_common.cache2.problem_cache.problems)
self.identify_map[invoker] = (users[0].handle, problem.name)
await ctx.send(f'`{invoker}`, submit a compile error to <{problem.url}> and then run `;handle report`')

@handle.command(brief='Report identification')
async def report(self, ctx):
invoker = str(ctx.author)
if not invoker in self.identify_map:
await ctx.send(f'`{invoker}`, you have nothing to report')
return

handle, prob = self.identify_map[invoker]
subs = await cf.user.status(handle=handle, count=5)
if any(sub.problem.name == prob and sub.verdict == 'COMPILATION_ERROR' for sub in subs):
del self.identify_map[invoker]
users = await cf.user.info(handles=[handle])
await self._set(ctx, ctx.author, users[0])
else:
await ctx.send(f'Sorry `{invoker}`, can you try again?')
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

General note: We probably should write a function that escapes usernames so we actually print the correct thing. Something that prepends *_` with a backslash would do the job.


@handle.command(brief='Get handle by Discord username')
async def get(self, ctx, member: discord.Member):
"""Show Codeforces handle of a user."""
Expand Down Expand Up @@ -202,6 +236,8 @@ async def gudgitters(self, ctx):
handle_display = f'{member.display_name} ({score})'
t += table.Data(index, handle_display)
index += 1
if index == 20:
break
if index > 0:
msg = '```\n' + str(t) + '\n```'
else:
Expand Down