├── public ├── Screenshot 2024-10-28 235216.png └── index.html ├── vercel.json ├── package.json ├── index.js ├── leetcode.js └── Readme.md /public/Screenshot 2024-10-28 235216.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/faisal-shohag/leetcode_api/HEAD/public/Screenshot 2024-10-28 235216.png -------------------------------------------------------------------------------- /vercel.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": 2, 3 | "name": "leetcode_api", 4 | "builds": [ 5 | { "src": "index.js", "use": "@vercel/node" } 6 | ], 7 | "routes": [ 8 | { "src": "/(.*)", "dest": "/index.js" } 9 | ] 10 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "dependencies": { 3 | "cors": "^2.8.5", 4 | "express": "^4.18.2", 5 | "express-rate-limit": "^7.5.0", 6 | "node-fetch": "^3.3.2" 7 | }, 8 | "name": "leetcode_api", 9 | "version": "1.0.0", 10 | "description": "leetcode api", 11 | "main": "index.js", 12 | "scripts": { 13 | "test": "echo \"Error: no test specified\" && exit 1", 14 | "start": "node index.js", 15 | "server": "nodemon index.js" 16 | }, 17 | "repository": { 18 | "type": "git", 19 | "url": "git+https://github.com/faisal-shohag/leetcode_api.git" 20 | }, 21 | "keywords": [ 22 | "leetcode" 23 | ], 24 | "author": "faisal_shohag", 25 | "license": "ISC", 26 | "bugs": { 27 | "url": "https://github.com/faisal-shohag/leetcode_api/issues" 28 | }, 29 | "homepage": "https://github.com/faisal-shohag/leetcode_api#readme" 30 | } 31 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | const express = require('express') 2 | const app = express(); 3 | const cors = require('cors') 4 | const path = require('path'); 5 | const {rateLimit} = require('express-rate-limit'); 6 | 7 | const limiter = rateLimit({ 8 | windowMs: 15 * 60 * 1000, 9 | limit: 100, 10 | standardHeaders: 'draft-7', 11 | legacyHeaders: false 12 | }) 13 | 14 | const specificLimiter = rateLimit({ 15 | windowMs: 1 * 60 * 1000, 16 | max: 10, 17 | message: 'Too many requests for this route, please try again later.' 18 | }); 19 | 20 | 21 | app.use(limiter); 22 | 23 | app.use(express.static('public')); 24 | 25 | app.use(cors({ 26 | origin: '*' 27 | })) 28 | 29 | let leet = require('./leetcode'); 30 | app.get('/', (req, res) => { 31 | res.sendFile(path.join(__dirname, 'public', 'index.html')); 32 | }); 33 | app.get('/:id', specificLimiter, leet.leetcode); 34 | 35 | app.listen(3000, () => { 36 | console.log(`App is running on port 3000`); 37 | }); -------------------------------------------------------------------------------- /leetcode.js: -------------------------------------------------------------------------------- 1 | //graphql query 2 | const query = ` 3 | query getUserProfile($username: String!) { 4 | allQuestionsCount { 5 | difficulty 6 | count 7 | } 8 | matchedUser(username: $username) { 9 | contributions { 10 | points 11 | } 12 | profile { 13 | reputation 14 | ranking 15 | } 16 | submissionCalendar 17 | submitStats { 18 | acSubmissionNum { 19 | difficulty 20 | count 21 | submissions 22 | } 23 | totalSubmissionNum { 24 | difficulty 25 | count 26 | submissions 27 | } 28 | } 29 | } 30 | recentSubmissionList(username: $username) { 31 | title 32 | titleSlug 33 | timestamp 34 | statusDisplay 35 | lang 36 | __typename 37 | } 38 | matchedUserStats: matchedUser(username: $username) { 39 | submitStats: submitStatsGlobal { 40 | acSubmissionNum { 41 | difficulty 42 | count 43 | submissions 44 | __typename 45 | } 46 | totalSubmissionNum { 47 | difficulty 48 | count 49 | submissions 50 | __typename 51 | } 52 | __typename 53 | } 54 | } 55 | } 56 | `; 57 | 58 | 59 | // format data 60 | const formatData = (data) => { 61 | let sendData = { 62 | totalSolved: data.matchedUser.submitStats.acSubmissionNum[0].count, 63 | totalSubmissions: data.matchedUser.submitStats.totalSubmissionNum, 64 | totalQuestions: data.allQuestionsCount[0].count, 65 | easySolved: data.matchedUser.submitStats.acSubmissionNum[1].count, 66 | totalEasy: data.allQuestionsCount[1].count, 67 | mediumSolved: data.matchedUser.submitStats.acSubmissionNum[2].count, 68 | totalMedium: data.allQuestionsCount[2].count, 69 | hardSolved: data.matchedUser.submitStats.acSubmissionNum[3].count, 70 | totalHard: data.allQuestionsCount[3].count, 71 | ranking: data.matchedUser.profile.ranking, 72 | contributionPoint: data.matchedUser.contributions.points, 73 | reputation: data.matchedUser.profile.reputation, 74 | submissionCalendar: JSON.parse(data.matchedUser.submissionCalendar), 75 | recentSubmissions: data.recentSubmissionList, 76 | matchedUserStats: data.matchedUser.submitStats 77 | } 78 | return sendData; 79 | } 80 | 81 | //fetching the data 82 | exports.leetcode = (req, res) => { 83 | let user = req.params.id; 84 | fetch('https://leetcode.com/graphql', { 85 | method: 'POST', 86 | headers: { 87 | 'Content-Type': 'application/json', 88 | 'Referer': 'https://leetcode.com' 89 | }, 90 | body: JSON.stringify({query: query, variables: {username: user}}), 91 | 92 | }) 93 | .then(result => result.json()) 94 | .then(data => { 95 | if(data.errors){ 96 | res.send(data); 97 | }else { 98 | res.send(formatData(data.data)); 99 | } 100 | }) 101 | .catch(err=>{ 102 | console.error('Error', err); 103 | res.send(err); 104 | }); 105 | } -------------------------------------------------------------------------------- /Readme.md: -------------------------------------------------------------------------------- 1 | # LeetCode API 2 | ![alt text](https://github.com/faisal-shohag/leetcode_api/blob/master/public/Screenshot%202024-10-28%20235216.png?raw=true) 3 | ## Overview 4 | 5 | This project provides a working Node.js API to interact with LeetCode's public GraphQL API, focusing on fetching submission calendars and other user statistics. The API simplifies querying LeetCode's data by providing structured endpoints. 6 | 7 | ## Features 8 | 9 | - Fetch user profile information from LeetCode 10 | - Retrieve submission statistics and calendar data 11 | - Simplified GraphQL querying through a RESTful API 12 | 13 | ## Technologies Used 14 | 15 | - **Node.js** 16 | - **Express.js** 17 | - **GraphQL** 18 | - **Fetch API** 19 | 20 | ## Installation 21 | 22 | 1. Clone the repository: 23 | ```bash 24 | git clone https://github.com/faisal-shohag/leetcode_api.git 25 | ``` 26 | 2. Navigate to the project directory: 27 | ```bash 28 | cd leetcode_api 29 | ``` 30 | 3. Install the dependencies: 31 | ```bash 32 | npm install 33 | ``` 34 | 35 | ## Usage 36 | 37 | 1. Start the server: 38 | ```bash 39 | node index.js 40 | ``` 41 | 2. Access the API at `http://localhost:3000/yourLeetcodeUsername` 42 | 43 | ## API Endpoint 44 | 45 | - **GET /:username** - Fetches the LeetCode profile and submission data for the specified username. 46 | 47 | ### Example Response 48 | 49 | ```json 50 | { 51 | "totalSolved": 43, 52 | "totalSubmissions": [ 53 | { 54 | "difficulty": "All", 55 | "count": 58, 56 | "submissions": 116 57 | }, 58 | { 59 | "difficulty": "Easy", 60 | "count": 15, 61 | "submissions": 34 62 | }, 63 | { 64 | "difficulty": "Medium", 65 | "count": 33, 66 | "submissions": 54 67 | }, 68 | { 69 | "difficulty": "Hard", 70 | "count": 10, 71 | "submissions": 27 72 | } 73 | ], 74 | "totalQuestions": 2738, 75 | "easySolved": 12, 76 | "totalEasy": 686, 77 | "mediumSolved": 21, 78 | "totalMedium": 1449, 79 | "hardSolved": 10, 80 | "totalHard": 603, 81 | "ranking": 1139392, 82 | "contributionPoint": 217, 83 | "reputation": 28067, 84 | "submissionCalendar": { 85 | "1664323200": 1, 86 | "1664496000": 1, 87 | "1664755200": 4, 88 | "1664841600": 5, 89 | "1667865600": 3, 90 | "1678060800": 1 91 | } 92 | } 93 | ``` 94 | ## Project Structure 95 | - `index.js` -Main server file that sets up the Express server and API routes. 96 | - `leetcode.js` -Contains the logic for interacting with LeetCode's GraphQL API. 97 | - `package.json` - Project metadata and dependencies. 98 | 99 | ## Demo 100 | 101 | You can view a live demo of the project [here](https://leetcode-api-faisalshohag.vercel.app/). *(Please note that it may take a few seconds for the server to wake up.)* 102 | 103 | ## Contributing 104 | 105 | Contributions are welcome! Please feel free to submit a pull request or open an issue to discuss improvements or bugs. 106 | 107 | ## License 108 | 109 | This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. 110 | 111 | ## Contact 112 | 113 | - **Author:** Faisal Shohag 114 | - **Email:** faisalshohagprog@gmail.com 115 | - **LinkedIn:** [faisal-shohag](http://linkedin.com/in/faisal-shohag) 116 | - **GitHub:** [faisal-shohag](http://github.com/faisal-shohag) 117 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | LeetCode User Stats 7 | 8 | 9 | 10 | 25 | 102 | 103 | 104 |
105 |

108 | 112 | api 113 |

114 |
115 | 121 | 127 |
128 | 129 |
133 |
134 |
135 |
136 | LeetCode api with recentSubmissions and submissionCalendar! 137 |
138 |
139 |
140 |
141 |
142 | https://leetcode-api-faisalshohag.vercel.app/username 143 |
144 |
145 | 151 |
152 |
153 | 154 |
155 | Star at 156 |
161 |
162 | 163 | 522 | 523 | 524 | --------------------------------------------------------------------------------