diff --git a/cogs/daily_cp.py b/cogs/daily_cp.py new file mode 100644 index 0000000..1ad1ffa --- /dev/null +++ b/cogs/daily_cp.py @@ -0,0 +1,69 @@ +from discord.ext import commands +from discord import Interaction, ApplicationContext +from codeforces_api import CodeforcesApi +from datetime import datetime +from utils.mongo import problems_collection, user_collection +from utils.codeforces import getTwoProblems +from requests import get + + +class DailyCP(commands.Cog): + def __init__(self, bot: commands.Bot): + self.bot = bot + self.cf_api = CodeforcesApi() + + @commands.slash_command(description="Get your daily challenge") + async def daily_cp(self, ctx: Interaction | ApplicationContext): + await ctx.response.defer() + user_id = ctx.author.id + dateAndTime = datetime.now() + date = dateAndTime.strftime("%d/%m/%Y") + user_obj = user_collection.find_one({"discord_id": user_id}) + if user_obj is None: + await ctx.respond("First you need to register using `/register` command") + today_problems = problems_collection.find_one( + {"discord_id": user_id, "date": date} + ) + if today_problems is not None: + given_problems = today_problems["problems"] + msg = f"problem 1 - {given_problems[0]['link']}\nproblem 1 - {given_problems[1]['link']}" + await ctx.respond(msg) + return + username = user_obj["username"] + url = f"https://codeforces.com/api/user.info?handles={username}" + formatted_response = get(url) + if formatted_response.status_code != 200: + await ctx.respond("Oopsie, an error occurred") + return + try: + data = formatted_response.json() + except ValueError: + await ctx.respond("Oopsie, an error occurred") + return + if "rating" not in data["result"][0]: + await ctx.respond("Skill Issue: you are unrated") + return + new_problems = getTwoProblems(username, data["result"][0]["rating"]) + new_problems_doc = { + "discord_id": user_id, + "problems": [ + { + "contestId": new_problems[0]["contestId"], + "index": new_problems[0]["index"], + "link": f"https://codeforces.com/problemset/problem/{new_problems[0]['contestId']}/{new_problems[0]['index']}", + }, + { + "contestId": new_problems[1]["contestId"], + "index": new_problems[1]["index"], + "link": f"https://codeforces.com/problemset/problem/{new_problems[1]['contestId']}/{new_problems[1]['index']}", + }, + ], + "date": date, + } + problems_collection.insert_one(new_problems_doc) + msg = f"problem 1 - {new_problems_doc['problems'][0]['link']}\nproblem 2 - {new_problems_doc['problems'][1]['link']}" + await ctx.respond(msg) + + +def setup(bot): + bot.add_cog(DailyCP(bot)) diff --git a/main.py b/main.py index 7bfa315..272b63d 100644 --- a/main.py +++ b/main.py @@ -1,5 +1,6 @@ from discord import ApplicationContext, Bot from utils.env import DISCORD_BOT_TOKEN +from utils.mongo import user_collection import os bot = Bot() @@ -15,6 +16,21 @@ async def on_ready(): print(f"Saini Certified is online.") +@bot.command(description="register for daily cp questions") +async def register(ctx: ApplicationContext, username: str): + if user_collection.find_one({"discord_id": ctx.author.id}) is not None: + await ctx.respond(f"Already Registered") + return + user_collection.insert_one( + { + "discord_id": ctx.author.id, + "discord_username": ctx.author.name, + "username": username, + } + ) + await ctx.respond("Registered!") + + for filename in os.listdir("./cogs"): if filename.endswith(".py"): bot.load_extension(f"cogs.{filename[:-3]}") diff --git a/utils/codeforces.py b/utils/codeforces.py new file mode 100644 index 0000000..705d26e --- /dev/null +++ b/utils/codeforces.py @@ -0,0 +1,50 @@ +import requests + + +def getTwoProblems(username, rating): + rounded_rating = round(rating / 100) * 100 + higher_rating = rounded_rating + 200 + + submissions_url = ( + f"https://codeforces.com/api/user.status?handle={username}&from=1&count=1000000" + ) + response = requests.get(submissions_url) + data = response.json() + if data["status"] != "OK": + return [] + + solved_problems = set() + for submission in data["result"]: + if submission["verdict"] == "OK": + problem_id = ( + submission["problem"]["contestId"], + submission["problem"]["index"], + ) + solved_problems.add(problem_id) + + problems_url = "https://codeforces.com/api/problemset.problems" + response = requests.get(problems_url) + data = response.json() + if data["status"] != "OK": + return [] + + selected_problems = [] + for problem in data["result"]["problems"]: + if "rating" not in problem: + continue + if ( + problem["rating"] == rounded_rating + and (problem["contestId"], problem["index"]) not in solved_problems + ): + selected_problems.append(problem) + if len(selected_problems) == 2: + break + elif ( + problem["rating"] == higher_rating + and (problem["contestId"], problem["index"]) not in solved_problems + ): + selected_problems.append(problem) + if len(selected_problems) == 2: + break + + return selected_problems diff --git a/utils/env.py b/utils/env.py index fe3452e..325dd57 100644 --- a/utils/env.py +++ b/utils/env.py @@ -3,3 +3,4 @@ load_dotenv() DISCORD_BOT_TOKEN = environ.get("DISCORD_BOT_TOKEN") +MONGO_URI = environ.get("MONGO_URI") diff --git a/utils/mongo.py b/utils/mongo.py new file mode 100644 index 0000000..50b38db --- /dev/null +++ b/utils/mongo.py @@ -0,0 +1,7 @@ +from pymongo import MongoClient, database +from .env import MONGO_URI + +client = MongoClient(MONGO_URI) +db = client.saini_certified +user_collection = db.users +problems_collection = db.problems