File size: 3,442 Bytes
3d23b0f |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 |
import { httpClient } from '../../shared/utils/http-client';
import * as cheerio from 'cheerio';
import type {
GFGSubmissionsResponse,
SubmissionsQuery,
UserPostsQuery,
LeaderboardQuery,
PromotionalEventsQuery,
GFGUserRating,
GFGPost,
GFGPromotionalEvent,
GFGLeaderboard,
} from './types';
import { GFG_BASE_URL, GFG_SELECTORS } from './constants';
export async function fetchUserRating(username: string): Promise<GFGUserRating> {
const url = `${GFG_BASE_URL}${username}/`;
try {
const { data } = await httpClient.get(url);
const $ = cheerio.load(data);
// Check for 404 or "User not found"
if ($('title').text().includes('404') || $('body').text().includes('User not found')) {
throw new Error(`User '${username}' not found on GeeksforGeeks`);
}
const scriptContent = $(GFG_SELECTORS.NEXT_DATA).html();
if (!scriptContent) {
throw new Error('GeeksforGeeks schema change detected: NEXT_DATA script not found');
}
const jsonData = JSON.parse(scriptContent);
const userData = jsonData?.props?.pageProps?.contestData?.user_contest_data;
const stars = jsonData?.props?.pageProps?.contestData?.user_stars;
if (!userData && !jsonData?.props?.pageProps?.contestData) {
throw new Error(`User '${username}' contest data not found. Profile might be private or schema changed.`);
}
return {
rating: userData?.current_rating || 'Unrated',
stars: stars ? `${stars} star` : 'Unrated',
};
} catch (error: any) {
if (error.response?.status === 404) {
throw new Error(`User '${username}' not found on GeeksforGeeks`);
}
throw error;
}
}
export async function fetchUserSubmissions(query: SubmissionsQuery): Promise<GFGSubmissionsResponse> {
const url = 'https://practiceapi.geeksforgeeks.org/api/v1/user/problems/submissions/';
const { data } = await httpClient.post(url, {
handle: query.handle,
requestType: query.requestType || "",
year: query.year || "",
month: query.month || ""
});
return data;
}
export async function fetchUserPosts(query: UserPostsQuery): Promise<GFGPost[]> {
const url = `https://communityapi.geeksforgeeks.org/post/user/${query.username}/`;
const { data } = await httpClient.get(url, {
params: {
fetch_type: query.fetch_type || 'posts',
page: query.page || 1
}
});
return data;
}
export async function fetchPromotionalEvents(query: PromotionalEventsQuery): Promise<GFGPromotionalEvent[]> {
const url = 'https://practiceapi.geeksforgeeks.org/api/vr/events/promotional/';
const { data } = await httpClient.get(url, {
params: {
page_source: query.page_source,
user_country_code: query.user_country_code || 'IN'
}
});
return data;
}
export async function fetchContestLeaderboard(query: LeaderboardQuery): Promise<GFGLeaderboard> {
const url = 'https://practiceapi.geeksforgeeks.org/api/latest/events/recurring/gfg-weekly-coding-contest/leaderboard/';
const { data } = await httpClient.get(url, {
params: {
leaderboard_type: query.leaderboard_type || 0,
page: query.page || 1,
year_month: query.year_month || ""
}
});
return data;
}
|