├── .gitignore ├── netlify.toml ├── router ├── ratingRouter.js └── scheduleRoute.js ├── package.json ├── .github └── ISSUE_TEMPLATE │ ├── feature_request.md │ └── bug_report.md ├── functions └── index.js ├── CONTRIBUTING.md ├── CODE_OF_CONDUCT.md ├── controller ├── ratingsController.js └── scheduleController.js └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | package-lock.json 3 | 4 | # Local Netlify folder 5 | .netlify 6 | -------------------------------------------------------------------------------- /netlify.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | functions = "functions/" 3 | 4 | [[redirects]] 5 | from = '/*' 6 | to = '/.netlify/functions/index/:splat' 7 | status = 200 8 | -------------------------------------------------------------------------------- /router/ratingRouter.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const {atCoderRating, codechefRating,codeforcesRating,leetCodeRating, GeeksForGeeksProfile} = require('../controller/ratingsController') 3 | 4 | const ratingRouter = express.Router(); 5 | 6 | ratingRouter.get('/code_chef/:username', codechefRating) 7 | ratingRouter.get('/codeforces/:users',codeforcesRating) 8 | ratingRouter.get('/at_coder/:username',atCoderRating) 9 | ratingRouter.get('/leet_code/:username',leetCodeRating) 10 | ratingRouter.get('/geeks_for_geeks/:username',GeeksForGeeksProfile) 11 | 12 | module.exports=ratingRouter -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "crazycoder", 3 | "version": "1.0.0", 4 | "description": "CrazyCoder Backend", 5 | "main": "index.js", 6 | "scripts": { 7 | "start": "node index.js" 8 | }, 9 | "author": "Yash Parsana", 10 | "license": "MIT", 11 | "dependencies": { 12 | "axios": "^1.3.2", 13 | "body-parser": "^1.20.1", 14 | "cheerio": "^1.0.0-rc.12", 15 | "cors": "^2.8.5", 16 | "dotenv": "^16.0.3", 17 | "express": "^4.18.2", 18 | "graphql-request": "^6.1.0", 19 | "http": "^0.0.1-security", 20 | "node-fetch": "^2.6.9", 21 | "pretty": "^2.0.0", 22 | "puppeteer": "^19.11.1", 23 | "serverless-http": "^3.2.0" 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] 12 | 13 | **Describe the solution you'd like** 14 | A clear and concise description of what you want to happen. 15 | 16 | **Describe alternatives you've considered** 17 | A clear and concise description of any alternative solutions or features you've considered. 18 | 19 | **Additional context** 20 | Add any other context or screenshots about the feature request here. 21 | -------------------------------------------------------------------------------- /functions/index.js: -------------------------------------------------------------------------------- 1 | const express = require('express'); 2 | const cors =require('cors') 3 | const serverless = require('serverless-http'); 4 | 5 | const app = express(); 6 | app.use(cors()); 7 | 8 | const router = express.Router(); 9 | 10 | const scheduleRouter = require('../router/scheduleRoute'); 11 | const ratingRouter = require('../router/ratingRouter'); 12 | 13 | router.use('/schedule', scheduleRouter); 14 | router.use('/ranking', ratingRouter); 15 | 16 | router.get('/', (req,res) => { 17 | res.send("You are in default Rought") 18 | }); 19 | 20 | app.use('/', router); 21 | 22 | module.exports.handler = serverless(app); 23 | 24 | //app.listen(3000, () => { 25 | // console.log("Server is Runnig on Port : ",3000); 26 | //}) 27 | -------------------------------------------------------------------------------- /router/scheduleRoute.js: -------------------------------------------------------------------------------- 1 | const express=require('express') 2 | const { atCoderSchedule,codechefSchedule,codeforcesSchedule,hackerRankSchedule,hackerEarthSchedule,leetCodeSchedule, gfgSchedule, codingNinjasSchedule } = require('../controller/scheduleController') 3 | const scheduleRouter = express.Router() 4 | 5 | scheduleRouter.get('/at_coder', atCoderSchedule) 6 | scheduleRouter.get('/code_chef', codechefSchedule) 7 | scheduleRouter.get('/codeforces', codeforcesSchedule) 8 | scheduleRouter.get('/hacker_rank', hackerRankSchedule) 9 | scheduleRouter.get('/hacker_earth', hackerEarthSchedule) 10 | scheduleRouter.get('/leet_code', leetCodeSchedule) 11 | scheduleRouter.get('/geeks_for_geeks', gfgSchedule); 12 | scheduleRouter.get('/coding_ninjas',codingNinjasSchedule) 13 | 14 | 15 | 16 | module.exports=scheduleRouter -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Describe the bug** 11 | A clear and concise description of what the bug is. 12 | 13 | **To Reproduce** 14 | Steps to reproduce the behavior: 15 | 1. Go to '...' 16 | 2. Click on '....' 17 | 3. Scroll down to '....' 18 | 4. See error 19 | 20 | **Expected behavior** 21 | A clear and concise description of what you expected to happen. 22 | 23 | **Screenshots** 24 | If applicable, add screenshots to help explain your problem. 25 | 26 | **Desktop (please complete the following information):** 27 | - OS: [e.g. iOS] 28 | - Browser [e.g. chrome, safari] 29 | - Version [e.g. 22] 30 | 31 | **Smartphone (please complete the following information):** 32 | - Device: [e.g. iPhone6] 33 | - OS: [e.g. iOS8.1] 34 | - Browser [e.g. stock browser, safari] 35 | - Version [e.g. 22] 36 | 37 | **Additional context** 38 | Add any other context about the problem here. 39 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to CrazyCoderServerlessApi 2 | 3 | ## Code of Conduct 4 | 5 | This project and its community adhere to the [Code of Conduct](CODE_OF_CONDUCT.md). By participating, you are expected to uphold this code. 6 | ## How Can I Contribute? 7 | 8 | ### Reporting Bugs : 9 | 10 | If you come across a bug or an issue with CrazyCoderServerlessApi, please take the following steps: 11 | 12 | 1. Search the [issue tracker](https://github.com/Yash-Parsana/CrazyCoderServerlessApi/issues) to check if the issue has already been reported. If it has, feel free to add any additional information or subscribe to the existing issue. 13 | 14 | 2. If the issue hasn't been reported yet, create a new issue with a descriptive title and a clear description of the problem. Include any relevant details such as operating system, browser version, and steps to reproduce the issue. 15 | 16 | ### Requesting Features : 17 | 18 | If you have an idea for a new feature or improvement, please follow these steps: 19 | 20 | 1. Search the [issue tracker](https://github.com/Yash-Parsana/CrazyCoderServerlessApi/issues) to check if the feature request already exists. If it does, you can comment on the existing request to provide more information or express your interest. 21 | 22 | 2. If the feature request doesn't exist, create a new issue with a clear and concise title and a detailed description of the feature or enhancement you're proposing. Explain why it's valuable and how it aligns with the project's goals. 23 | 24 | ### Submitting Changes : 25 | 26 | If you want to contribute in this repo,then follow these steps: 27 | 28 | ## Step 1 : Fork the Project 29 | - Fork this Repository. This will create a Local Copy of this Repository on your Github Profile. 30 | 31 | ```bash 32 | $ git clone https://github.com/Yash-Parsana/CrazyCoderServerlessApi.git 33 | $ cd CrazyCoderServerlessApi 34 | ``` 35 | 36 | ## Step 2 : Branch 37 | - To create a new branch with name branch_name and switch to that branch 38 | 39 | ```bash 40 | git checkout -b 41 | ``` 42 | ## Step 3 : Work on the issue assigned 43 | - Work on the issue assigned to you. 44 | - After you've made changes or made your contribution to the project add changes to the branch you've just created by: 45 | 46 | ```bash 47 | git add . 48 | ``` 49 | ## Step 4 : Commit 50 | 51 | - To commit give a descriptive message for the convenience of reveiwer by: 52 | 53 | ```bash 54 | git commit -m "descriptive message" 55 | ``` 56 | 57 | ## Step 5 : Push 58 | - Push your changes to your forked repository on GitHub. 59 | 60 | ```bash 61 | git push origin 62 | ``` 63 | 64 | ## Step 6 : Pull Request 65 | - Go to your repository in browser and click on compare and pull requests. Then add a title and description to your pull request that explains your contribution. 66 | - Then add a title to your pull request. 67 | - Mention the issue number in your PR. 68 | - Give a brief description about the changes. 69 | - Your Pull Request has been submitted and will be reviewed by the owner and merged. 70 | 71 | 🎉 🎉 Thank you for considering contributing to CrazyCoderServerlessApi. Whether it's fixing a bug , proposing a new feature , or improving documentation, your contributions are greatly appreciated. 72 | 73 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Code Of Conduct-CrazyCoderServerlessApi 2 | 3 | ## Our Pledge 4 | 5 | We as members, contributors, and leaders pledge to make participation in our 6 | community a harassment-free experience for everyone, regardless of age, body 7 | size, visible or invisible disability, ethnicity, sex characteristics, gender 8 | identity and expression, level of experience, education, socio-economic status, 9 | nationality, personal appearance, race, religion, or sexual identity 10 | and orientation. 11 | 12 | We pledge to act and interact in ways that contribute to an open, welcoming, 13 | diverse, inclusive, and healthy community. 14 | 15 | ## Our Standards 16 | 17 | Examples of behavior that contributes to a positive environment for our 18 | community include: 19 | 20 | * Demonstrating empathy and kindness toward other people 21 | * Being respectful of differing opinions, viewpoints, and experiences 22 | * Giving and gracefully accepting constructive feedback 23 | * Accepting responsibility and apologizing to those affected by our mistakes, 24 | and learning from the experience 25 | * Focusing on what is best not just for us as individuals, but for the 26 | overall community 27 | 28 | Examples of unacceptable behavior include: 29 | 30 | * The use of sexualized language or imagery, and sexual attention or 31 | advances of any kind 32 | * Trolling, insulting or derogatory comments, and personal or political attacks 33 | * Public or private harassment 34 | * Publishing others' private information, such as a physical or email 35 | address, without their explicit permission 36 | * Other conduct which could reasonably be considered inappropriate in a 37 | professional setting 38 | 39 | ## Enforcement Responsibilities 40 | 41 | Community leaders are responsible for clarifying and enforcing our standards of 42 | acceptable behavior and will take appropriate and fair corrective action in 43 | response to any behavior that they deem inappropriate, threatening, offensive, 44 | or harmful. 45 | 46 | Community leaders have the right and responsibility to remove, edit, or reject 47 | comments, commits, code, wiki edits, issues, and other contributions that are 48 | not aligned to this Code of Conduct, and will communicate reasons for moderation 49 | decisions when appropriate. 50 | 51 | ## Scope 52 | 53 | This Code of Conduct applies within all community spaces, and also applies when 54 | an individual is officially representing the community in public spaces. 55 | Examples of representing our community include using an official e-mail address, 56 | posting via an official social media account, or acting as an appointed 57 | representative at an online or offline event. 58 | 59 | ## Enforcement 60 | 61 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 62 | reported to the community leaders responsible for enforcement at 63 | yashparsana135@gmail.com. 64 | All complaints will be reviewed and investigated promptly and fairly. 65 | 66 | All community leaders are obligated to respect the privacy and security of the 67 | reporter of any incident. 68 | 69 | ## Enforcement Guidelines 70 | 71 | Community leaders will follow these Community Impact Guidelines in determining 72 | the consequences for any action they deem in violation of this Code of Conduct: 73 | 74 | ### 1. Correction 75 | 76 | **Community Impact**: Use of inappropriate language or other behavior deemed 77 | unprofessional or unwelcome in the community. 78 | 79 | **Consequence**: A private, written warning from community leaders, providing 80 | clarity around the nature of the violation and an explanation of why the 81 | behavior was inappropriate. A public apology may be requested. 82 | 83 | ### 2. Warning 84 | 85 | **Community Impact**: A violation through a single incident or series 86 | of actions. 87 | 88 | **Consequence**: A warning with consequences for continued behavior. No 89 | interaction with the people involved, including unsolicited interaction with 90 | those enforcing the Code of Conduct, for a specified period of time. This 91 | includes avoiding interactions in community spaces as well as external channels 92 | like social media. Violating these terms may lead to a temporary or 93 | permanent ban. 94 | 95 | ### 3. Temporary Ban 96 | 97 | **Community Impact**: A serious violation of community standards, including 98 | sustained inappropriate behavior. 99 | 100 | **Consequence**: A temporary ban from any sort of interaction or public 101 | communication with the community for a specified period of time. No public or 102 | private interaction with the people involved, including unsolicited interaction 103 | with those enforcing the Code of Conduct, is allowed during this period. 104 | Violating these terms may lead to a permanent ban. 105 | 106 | ### 4. Permanent Ban 107 | 108 | **Community Impact**: Demonstrating a pattern of violation of community 109 | standards, including sustained inappropriate behavior, harassment of an 110 | individual, or aggression toward or disparagement of classes of individuals. 111 | 112 | **Consequence**: A permanent ban from any sort of public interaction within 113 | the community. 114 | 115 | ## Attribution 116 | 117 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], 118 | version 2.0, available at 119 | https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. 120 | 121 | Community Impact Guidelines were inspired by [Mozilla's code of conduct 122 | enforcement ladder](https://github.com/mozilla/diversity). 123 | 124 | [homepage]: https://www.contributor-covenant.org 125 | 126 | For answers to common questions about this code of conduct, see the FAQ at 127 | https://www.contributor-covenant.org/faq. Translations are available at 128 | https://www.contributor-covenant.org/translations. 129 | -------------------------------------------------------------------------------- /controller/ratingsController.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios'); 2 | const cheerio = require('cheerio'); 3 | const fetch = require('node-fetch'); 4 | const pretty = require('pretty'); 5 | const { request, gql } = require('graphql-request'); 6 | 7 | const atcoderBaseUrl = 'https://atcoder.jp/users/'; 8 | const codeChefBaseUrl = 'https://www.codechef.com/users/'; 9 | const codeforcesBaseUrl = 'https://codeforces.com/api/user.info?handles='; 10 | const leetCodeBaseUrl = 'https://leetcode.com/graphql'; 11 | 12 | const atCoderRating = async (req, res) => { 13 | try { 14 | const url = atcoderBaseUrl + req.params.username; 15 | const { data } = await axios.get(url); 16 | 17 | const $ = cheerio.load(data); 18 | 19 | const rt = $('.mt-2 tbody tr:nth-child(2) td span'); 20 | const rating = pretty(rt.html()); 21 | res.status(200).json({ 22 | status: 'success', 23 | handle: req.params.username, 24 | rating: rating, 25 | }); 26 | } catch (err) { 27 | console.log('Error while Fetching atcoderRating -> ', err); 28 | res.status(503).json({ 29 | success: false, 30 | message: 'Opps! Some error occurred', 31 | }); 32 | } 33 | }; 34 | 35 | const codechefRating = async (req, res) => { 36 | const username = req.params.username; 37 | try { 38 | const url = codeChefBaseUrl + username; 39 | const { data } = await axios.get(url); 40 | 41 | const $ = cheerio.load(data); 42 | const ratingDiv = $('.user-profile-container .row .sidebar .content .rating-header .rating-number'); 43 | const stars = $('.user-profile-container .row .sidebar .content .rating-header .rating-star'); 44 | const rating = parseInt(pretty(ratingDiv.html())); 45 | let star = 1; 46 | if (rating >= 1400 && rating < 1600) { 47 | star = 2; 48 | } else if (rating >= 1600 && rating < 1800) { 49 | star = 3; 50 | } else if (rating >= 1800 && rating < 2000) { 51 | star = 4; 52 | } else if (rating >= 2000 && rating < 2200) { 53 | star = 5; 54 | } else if (rating >= 2200 && rating < 2500) { 55 | star = 6; 56 | } else if (rating >= 2500) { 57 | star = 7; 58 | } 59 | res.status(200).json({ 60 | status: 'success', 61 | handle: username, 62 | rating: rating, 63 | stars: star, 64 | }); 65 | } catch (err) { 66 | console.log('Error in codechef Rating Fun -> ', err); 67 | res.status(503).json({ 68 | success: false, 69 | message: 'Opps! Some error occurred', 70 | }); 71 | } 72 | }; 73 | 74 | const codeforcesRating = async (req, res) => { 75 | const users = req.params.users; 76 | const url = codeforcesBaseUrl + users; 77 | const response = await fetch(url, { method: 'GET' }); 78 | 79 | try { 80 | const jsonArray = []; 81 | if (response.ok) { 82 | const jsonObject = await response.json(); 83 | if (jsonObject.status == 'OK') { 84 | const arr = jsonObject.result; 85 | 86 | for (let i = 0; i < arr.length; i++) { 87 | const curr = arr[i]; 88 | const obj = { 89 | handle: curr.handle, 90 | rating: curr.rating, 91 | rank: curr.rank, 92 | maxRating: curr.maxRating, 93 | maxRank: curr.maxRank, 94 | }; 95 | jsonArray.push(obj); 96 | } 97 | } 98 | res.status(200).send(jsonArray); 99 | } else { 100 | console.log('Error in fetching codeforces ratings -> ', response.error); 101 | res.status(503).json({ 102 | success: false, 103 | message: 'Opps! Some error occurred', 104 | }); 105 | } 106 | } catch (err) { 107 | console.log('Error in codeforces Rating Fun -> ', err); 108 | res.status(503).json({ 109 | status: 'failed', 110 | message: 'Opps! Some error occurred', 111 | }); 112 | } 113 | }; 114 | 115 | const leetCodeRating = async (req, res) => { 116 | const username = req.params.username; 117 | try { 118 | const query = gql` 119 | query getUserProfile($username: String!) { 120 | userContestRanking(username: $username) { 121 | rating 122 | } 123 | matchedUser(username: $username) { 124 | username 125 | submitStats: submitStatsGlobal { 126 | acSubmissionNum { 127 | difficulty 128 | count 129 | submissions 130 | } 131 | } 132 | } 133 | } 134 | `; 135 | const variables = { username }; 136 | const data = await request(leetCodeBaseUrl, query, variables); 137 | const rating = Math.floor((data?.userContestRanking?.rating)); 138 | const solvedQuestions = {} 139 | data?.matchedUser?.submitStats?.acSubmissionNum.forEach(element => { 140 | solvedQuestions[(element?.difficulty)?.toLowerCase()] = element.count; 141 | }); 142 | res.status(200).json({ 143 | status: 'success', 144 | handle: username, 145 | rating: rating, 146 | ...solvedQuestions 147 | }); 148 | } catch (err) { 149 | console.log('Error in leetCode Rating Fun -> ', err); 150 | res.status(503).json({ 151 | status: 'failed', 152 | message: 'Opps! Some error occurred', 153 | }); 154 | } 155 | }; 156 | 157 | const GeeksForGeeksProfile = async (req, res) => { 158 | const username = req.params.username; 159 | const BASE_URL = `https://auth.geeksforgeeks.org/user/${username}/practice/`; 160 | 161 | try { 162 | const profilePage = await axios.get(BASE_URL); 163 | 164 | if (profilePage.status !== 200) { 165 | return res.status(503).json({ 166 | status: 'failure', 167 | message: 'Profile Not Found' 168 | }); 169 | } 170 | 171 | const $ = cheerio.load(profilePage.data); 172 | 173 | const additionalDetails = extractDetails($); 174 | const codingScores = additionalDetails.coding_scores; 175 | 176 | const response = { 177 | status: "success", 178 | handle: username, 179 | over_all_coding_score: parseInt(codingScores.codingScore || 0, 10), 180 | total_problem_solved: parseInt(codingScores.totalProblemsSolved || 0, 10), 181 | monthly_coding_score: parseInt(codingScores.monthlyCodingScore || 0, 10), 182 | over_all_article_published: parseInt(codingScores.articlesPublished || 0, 10) 183 | }; 184 | 185 | res.status(200).send(response); 186 | } catch (error) { 187 | console.log('Error fetching GeeksForGeeks profile ->', error); 188 | res.status(503).json({ 189 | status: 'failed', 190 | message: 'Oops! Some error occurred' 191 | }); 192 | } 193 | }; 194 | 195 | const extractTextFromElements = ($, elements, elementKeys) => { 196 | const result = {}; 197 | elements.each((index, element) => { 198 | const innerText = $(element).text().trim(); 199 | result[elementKeys[index]] = innerText === '_ _' ? "" : innerText; 200 | }); 201 | return result; 202 | }; 203 | 204 | const extractDetails = ($) => { 205 | const codingScoresByIndex = ["codingScore", "totalProblemsSolved", "monthlyCodingScore", "articlesPublished"]; 206 | 207 | let codingScores = $("span.score_card_value"); 208 | if (codingScores.length === 0) { 209 | codingScores = $("div:contains('Coding Score')").nextAll("span"); 210 | } 211 | 212 | return { 213 | coding_scores: extractTextFromElements($, codingScores, codingScoresByIndex) 214 | }; 215 | }; 216 | 217 | module.exports = { atCoderRating, codechefRating, codeforcesRating, leetCodeRating, GeeksForGeeksProfile }; 218 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |
2 | 3 |

4 | 5 |

6 | 7 | # CrazyCoder 8 | 9 | Competitive programming (CP) a large growing community is very well known for algorithms, data structures and Mathematics, and is a must have skill for any computer science student or top tech companies job aspirant.
10 |
11 | CrazyCoder is born out of our need to have a single place to view all the coding contests happening across many platforms. The app automatically updates all the coding contests and hackathons. You will never miss any contest. 12 | CrazyCoder aims to promote and help grow the competitive programming community worldwide.
13 | 14 | CrazyCoder is a comprehensive app designed to cater to the needs of the competitive programming community. It serves as a one-stop solution for viewing coding contests and hackathons happening across multiple platforms. With its user-friendly interface and automatic updates, CrazyCoder ensures that you never miss any contest, enabling you to stay on top of your competitive programming journey. 15 | 16 |
17 |
18 | 19 | 20 | 21 | 22 |
23 |
24 | 25 | ## Key Features 26 | 27 | CrazyCoder offers a range of features to enhance your competitive programming experience : 28 | 29 | 1. **Contest Tracking**: See contests platform-wise and easily differentiate between running and upcoming contests. 30 | 31 | 2. **Reminder**: Set reminders for contests to receive notifications before they start, so you never miss an important competition. 32 | 33 | 3. **Leaderboard**: Compare your rank with friends and engage in healthy competition to motivate each other. 34 | 35 | 4. **SDE Interview Section**: Access a dedicated section for interview preparation, recommended by employees of top tech companies (MAANG companies). 36 | 37 | 5. **Chat With Friends**: Connect with fellow programmers, discuss coding problems, and share your progress. 38 | 39 | 6. **Progress Tracking**: Keep track of your own progress and see how you are improving over time. 40 | 41 | 7. **Profile Page**: Visit your profile page directly from the app to manage your personal information and preferences. 42 | 43 |
44 | 45 | ## Supported Platforms 46 | 47 | CrazyCoder supports the following coding contest platforms : 48 |
49 |
50 | 51 | 52 | 53 | 54 | 55 |
56 | 57 |

58 | 59 | ## Technology Stack 🖥️ 60 | 61 | The different technologies used to build CrazyCoder : 62 |
63 | | Tech | Description 64 | |------|---------------------------------------------------------------------------------------------------------------- 65 | | | A JavaScript library for building user interfaces, known for its component-based structure and efficient rendering. 66 | | | An open-source, cross-platform runtime environment for executing JavaScript code. 67 | | | A backend web application framework for building API's with Node.js 68 | | | A set of cloud-based development tools to build, deploy and develop quality apps. 69 | 70 |
71 | 72 | ## Repo Status ✳️ 73 |
74 | 75 | 76 | 77 | 78 | 79 |
80 | 81 | 82 | 83 | 84 |

85 | 86 | ## Contribution Guidelines 87 | 88 | We welcome contributions from the open-source community to make CrazyCoder even better. To contribute, please follow these steps: 89 | 90 | :pushpin: Star the Repo: Start by giving our repository a star to show your support. 91 | 92 | :pushpin: Find or Create an Issue: Browse the existing issues or create a new one if you have a suggestion or find a bug. 93 | 94 | :pushpin: Fork the Repo: Fork the CrazyCoder repository to your GitHub account (Click the button in the top right of this page). 95 | 96 | :pushpin: Clone the Repo: Clone the forked repository to your local machine. 97 | ```markdown 98 | git clone https://github.com/your_username/CrazyCoderServerlessApi.git 99 | ``` 100 | Note: Replace `github_username` with your actual GitHub username. 101 | 102 | :pushpin: Create a New Branch: Create a new branch in your forked repository to work on your changes. 103 | ```markdown 104 | git checkout -b branch_name 105 | ``` 106 | 107 | :pushpin: Make your contribution: Improve the readme file of the project in your branch. Feel free to add more details, improve the formatting, or include additional information. 108 | 109 | :pushpin: Commit and push the changes: Commit your changes and push them to your forked repository. 110 | ```markdown 111 | git add . 112 | git commit -m 'Your message' 113 | git push origin branch_name 114 | ``` 115 | 116 | :pushpin: Open a Pull Request: Open a pull request from your branch to the main CrazyCoderServerlessApi repository. Provide a clear description of the changes you've made. Add screenshots or screen captures to your Pull Request to help us understand the effects of the changes proposed in your PR. 117 | 118 | :pushpin: Review and Merge: Wait for your PR review and approval from the maintainers. 119 | Once approved, it will be merged into the main repository. 120 | 121 |
122 | We appreciate your contributions and thank you for helping us make CrazyCoder a valuable resource for the competitive programming community!! 123 | 124 | ## Our Contributors ✨ 125 | 126 | 127 | 128 |

129 | Thank you to all the amazing contributors who have made this project possible!!💝 130 | 131 | --- 132 | 133 | Please note that the above is an enhanced version of the readme file. Feel free to make any modifications or add more information as per your requirements. Good luck with your contribution to CrazyCoder! 134 | 135 |
136 |

Happy Coding!👨‍💻

137 |
138 |

Back To Top

139 | -------------------------------------------------------------------------------- /controller/scheduleController.js: -------------------------------------------------------------------------------- 1 | const axios = require('axios') 2 | const cheerio = require('cheerio') 3 | const pretty = require('pretty') 4 | const fetch=require('node-fetch') 5 | const url = require('url'); 6 | const puppeteer = require('puppeteer') 7 | 8 | const atCoderUrl = "https://atcoder.jp/contests" 9 | const codeChefUrl = "https://www.codechef.com/api/list/contests/all?sort_by=START&sorting_order=asc&offset=0&mode=all" 10 | const codeforcesUrl="https://codeforces.com/api/contest.list?" 11 | const hackerRankUrl = "https://www.hackerrank.com/rest/contests/upcoming?limit=100" 12 | const hackerEarthUrl = "https://www.hackerearth.com/chrome-extension/events/" 13 | const kickStartUrl = "https://codingcompetitions.withgoogle.com/kickstart/schedule" 14 | const leetCodeUrl="https://leetcode.com/graphql?query={%20allContests%20{%20title%20titleSlug%20startTime%20duration%20__typename%20}%20}" 15 | 16 | const atCoderSchedule = async (req, res) => { 17 | const jsonArray=[] 18 | const {data} =await axios.get(atCoderUrl) 19 | const $ = cheerio.load(data) 20 | const contests=$(".table-default tbody tr") 21 | contests.each((idx, ele) => { 22 | const curr=cheerio.load(ele) 23 | const name = pretty((curr("td:nth-child(2) a")).html()) 24 | const Stime = parseInt(Date.parse((pretty(curr("td:nth-child(1) a time").html())))) //from 2023-01-28(Sat) 08:30 to timestamp 25 | const str = pretty(curr("td:nth-child(3)").html()).toString() 26 | const hour = parseInt(str.split(":")[0]) 27 | const minute=parseInt(str.split(":")[1]) 28 | const Etime = Stime + hour * 60 * 60 * 1000 + minute * 60 * 1000 29 | if ((!isNaN(Stime)&&!isNaN(Etime))&&Etime > Date.now()) //avoiding finished contest and practice contest 30 | { 31 | const status=Date.now()>Stime?"ongoing":"upcoming" 32 | const obj = { 33 | name: name, 34 | start_time: Stime, 35 | end_time: Etime, 36 | status:status 37 | } 38 | jsonArray.push(obj); 39 | } 40 | }) 41 | res.status(200).send(jsonArray); 42 | } 43 | 44 | const codechefSchedule = async (req, res) => { 45 | const response=await fetch(codeChefUrl,{method: 'GET'}) 46 | const jsonArray = [] 47 | if (response.ok) 48 | { 49 | const jsonObject = await response.json() 50 | if (jsonObject.status != "success") 51 | { 52 | res.status(503).json({ 53 | success: false, 54 | message:"Sorry! We are not avaiable now" 55 | }) 56 | } 57 | else { 58 | 59 | const presentContest = jsonObject.present_contests 60 | const futureContest=jsonObject.future_contests 61 | 62 | for (let i = 0; i < presentContest.length; i++) 63 | { 64 | const curr =presentContest[i] 65 | 66 | if (curr.contest_code != "GAMES") 67 | { 68 | const contestStartUTC = Date.parse(curr.contest_start_date_iso); 69 | const contestEndUTC = Date.parse(curr.contest_end_date_iso) 70 | const obj = { 71 | name: curr.contest_name, 72 | start_time:contestStartUTC, 73 | end_time: contestEndUTC, 74 | status:"ongoing" 75 | } 76 | jsonArray.push(obj) 77 | } 78 | } 79 | for (let i = 0; i < futureContest.length; i++) 80 | { 81 | const curr =futureContest[i] 82 | 83 | const obj = { 84 | name: curr.contest_name, 85 | start_time:Date.parse(curr.contest_start_date_iso), 86 | end_time: Date.parse(curr.contest_end_date_iso), 87 | status:"upcoming" 88 | } 89 | jsonArray.push(obj) 90 | } 91 | } 92 | } 93 | else { 94 | res.status(503).json({ 95 | success: false, 96 | message:"Sorry! We are not avaiable now" 97 | }) 98 | } 99 | res.status(200).send(jsonArray) 100 | } 101 | 102 | const codeforcesSchedule = async (req, res) => { 103 | 104 | const response = await fetch(codeforcesUrl, { method: "GET" }) 105 | const jsonArray=[] 106 | if (response.ok) 107 | { 108 | const jsonObject = await response.json(); 109 | if (jsonObject.status == "OK") 110 | { 111 | const arr = jsonObject.result 112 | 113 | for (let i = 0; i < arr.length; i++) 114 | { 115 | const curr = arr[i] 116 | if (curr.phase == "BEFORE"||curr.phase=="CODING") 117 | { 118 | const obj = { 119 | name: curr.name, 120 | start_time: (curr.startTimeSeconds)*1000, 121 | end_time: (curr.startTimeSeconds + curr.durationSeconds) * 1000, 122 | status:(curr.phase=="BEFORE")?"upcoming":"ongoing" 123 | } 124 | jsonArray.push(obj) 125 | } 126 | } 127 | 128 | } 129 | } 130 | else { 131 | res.status(503).json({ 132 | success: false, 133 | message:"Can not load Contest" 134 | }) 135 | } 136 | 137 | res.status(200).send(jsonArray) 138 | 139 | } 140 | 141 | const hackerRankSchedule = async (req, res) => { 142 | 143 | const response = await fetch(hackerRankUrl, { method: "GET" }) 144 | 145 | const jsonArray=[] 146 | if (response.ok) 147 | { 148 | const jsonObject = await response.json(); 149 | 150 | const arr = jsonObject.models 151 | for (let i = 0; i < arr.length; i++) 152 | { 153 | const curr = arr[i] 154 | if (!(curr.ended)) 155 | { 156 | const obj = { 157 | name: curr.name, 158 | start_time: curr.epoch_starttime*1000, 159 | end_time:curr.epoch_endtime*1000, 160 | status:curr.started? "ongoing":"upcoming" 161 | } 162 | jsonArray.push(obj) 163 | } 164 | } 165 | } 166 | else { 167 | res.status(503).json({ 168 | success: false, 169 | message:"Can not load Contest" 170 | }) 171 | } 172 | res.status(200).send(jsonArray) 173 | } 174 | 175 | const hackerEarthSchedule = async (req, res) => { 176 | 177 | const response = await fetch(hackerEarthUrl, { method: "GET" }) 178 | const jsonArray=[] 179 | if (response.ok) 180 | { 181 | const jsonObject = await response.json() 182 | const arr = jsonObject.response 183 | 184 | for (let i = 0; i < arr.length; i++) 185 | { 186 | const curr=arr[i] 187 | const obj = { 188 | name: curr.title, 189 | start_time:parseInt(Date.parse(curr.start_tz)), 190 | end_time: parseInt(Date.parse(curr.end_tz)), 191 | status: curr.status.toString().toLowerCase() 192 | } 193 | jsonArray.push(obj) 194 | } 195 | } 196 | else { 197 | res.status(503).json({ 198 | success: false, 199 | message:"Can not load Contest" 200 | }) 201 | } 202 | res.status(200).send(jsonArray) 203 | } 204 | 205 | const leetCodeSchedule = async (req,res) => { 206 | 207 | const response = await fetch(leetCodeUrl) 208 | const jsonArray = [] 209 | if (response.ok) { 210 | 211 | const jsonObject = await response.json() 212 | 213 | const arr = jsonObject.data.allContests 214 | for (let i = 0; i < arr.length; i++) 215 | { 216 | const curr = arr[i] 217 | const name = curr.title 218 | const Stime = curr.startTime*1000 219 | const Etime = Stime + curr.duration * 1000 220 | if (Etime > Date.now()) 221 | { 222 | const obj = { 223 | name: name, 224 | start_time: Stime, 225 | end_time: Etime, 226 | status:Stime { 242 | try { 243 | let contests = []; 244 | let page = 1; 245 | 246 | while (true) { 247 | let gfgUrl = `https://practiceapi.geeksforgeeks.org/api/v1/events/?type=contest&page_number=${page}&sub_type=all`; 248 | let response = await axios.get(gfgUrl); 249 | 250 | if (!response.data || !response.data['results']) { 251 | break; 252 | } 253 | 254 | let upcoming = response.data['results']['upcoming']; 255 | let past = response.data['results']['past']; 256 | let allContests = upcoming.concat(past); 257 | 258 | for (let c of allContests) { 259 | let startTime = new Date(c['start_time']).getTime(); 260 | let endTime = new Date(c['end_time']).getTime(); 261 | let now = Date.now(); 262 | 263 | let status; 264 | if (now < startTime) { 265 | status = "upcoming"; 266 | } else if (now >= startTime && now <= endTime) { 267 | status = "ongoing"; 268 | } else { 269 | continue; 270 | } 271 | 272 | contests.push({ 273 | 'name': c['name'] || c['title'], 274 | 'start_time': startTime, 275 | 'end_time': endTime, 276 | 'status': status 277 | }); 278 | } 279 | 280 | if (!process.argv.includes('parse_full_list')) { 281 | break; 282 | } 283 | 284 | page += 1; 285 | } 286 | 287 | res.json(contests); 288 | } catch (err) { 289 | console.error(err); 290 | res.status(500).json({ message: 'Server error' }); 291 | } 292 | } 293 | 294 | const codingNinjasSchedule = async (req, res) => { 295 | let page = 0; 296 | let stop = false; 297 | let limit = 25; 298 | let jsonArray = []; 299 | const now = Date.now(); 300 | 301 | while (!stop) { 302 | page += 1; 303 | const url = `https://api.codingninjas.com/api/v3/public_section/contest_list?page=${page}`; 304 | const response = await fetch(url); 305 | 306 | if (!response.ok) { 307 | return res.status(503).json({ 308 | success: false, 309 | message: "Could not load Data" 310 | }); 311 | } 312 | 313 | const data = await response.json(); 314 | 315 | if (!data.data || !data.data.events) { 316 | break; 317 | } 318 | 319 | const events = data.data.events; 320 | 321 | for (let i = 0; i < events.length; i++) { 322 | const c = events[i]; 323 | const start_time = new Date(c.event_start_time * 1000).getTime(); 324 | const end_time = new Date(c.event_end_time * 1000).getTime(); 325 | 326 | if (!req.query.parse_full_list && start_time < now) { 327 | limit -= 1; 328 | if (limit === 0) { 329 | stop = true; 330 | break; 331 | } 332 | } 333 | 334 | let status; 335 | if (now < start_time) { 336 | status = "upcoming"; 337 | } else if (now >= start_time && now <= end_time) { 338 | status = "ongoing"; 339 | } else { 340 | continue; 341 | } 342 | 343 | jsonArray.push({ 344 | name: c.name, 345 | start_time: start_time, 346 | end_time: end_time, 347 | status: status 348 | }); 349 | } 350 | 351 | if (page >= data.data.total_pages) { 352 | break; 353 | } 354 | } 355 | res.status(200).json(jsonArray); 356 | }; 357 | 358 | 359 | module.exports = { atCoderSchedule, codechefSchedule, codeforcesSchedule, hackerRankSchedule, hackerEarthSchedule ,leetCodeSchedule, gfgSchedule, codingNinjasSchedule } --------------------------------------------------------------------------------