Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

feature: change submission retrieval methods#16

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 ourterms of service andprivacy statement. We’ll occasionally send you account related emails.

Already on GitHub?Sign in to your account

Merged
codewithsathya merged 2 commits intomainfromfeature/enhance-submissions-retrieval
Oct 15, 2024
Merged
Show file tree
Hide file tree
Changes fromall 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
2 changes: 1 addition & 1 deletionpackage.json
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
{
"name": "@leetnotion/leetcode-api",
"version": "1.8.4",
"version": "1.9.0",
"description": "Get user profiles, submissions, and problems on LeetCode.",
"type": "module",
"types": "lib/index.d.ts",
Expand Down
24 changes: 2 additions & 22 deletionssrc/_tests/leetcode-advanced.test.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -136,32 +136,12 @@ describe('LeetCode Advanced', { timeout: 60_000 * 60 }, () => {
);

it.skipIf(!process.env['TEST_LEETCODE_SESSION'])(
'should be able to getdetailed submission of a user',
'should be able to getrecent submission of a user',
async () => {
const recentSubmission = await lc.recentSubmissionOfUser('jacoblincool');
expect(recentSubmission).not.toBeNull();
expect(recentSubmission).toBeTruthy();
expect(recentSubmission?.id).toBeGreaterThan(0);
},
);

it.skipIf(!process.env['TEST_LEETCODE_SESSION'])(
'should be able to get recent detailed submission',
async () => {
const recentSubmission = await lc.recentSubmissionDetail();
expect(recentSubmission).not.toBeNull();
expect(recentSubmission?.code.length).toBeGreaterThan(0);
expect(recentSubmission?.id).toBeGreaterThan(0);
},
);

it.skipIf(!process.env['TEST_LEETCODE_SESSION'])(
'should be able to get recent detailed submission of a user',
async () => {
const recentSubmission = await lc.recentSubmissionDetailOfUser('jacoblincool');
expect(recentSubmission).not.toBeNull();
expect(recentSubmission?.code.length).toBeGreaterThan(0);
expect(recentSubmission?.id).toBeGreaterThan(0);
expect(parseInt(recentSubmission?.id as string)).toBeGreaterThan(0);
},
);
});
Expand Down
12 changes: 6 additions & 6 deletionssrc/_tests/leetcode.test.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -32,7 +32,7 @@ describe('LeetCode', { timeout: 15_000 }, () => {
});

it("should be able to get user's recent submissions", async () => {
const recent_submissions = await lc.recent_submissions('jacoblincool', 10);
const recent_submissions = await lc.recent_user_submissions('jacoblincool', 10);
expect(recent_submissions.length).toBe(10);
});

Expand DownExpand Up@@ -92,7 +92,7 @@ describe('LeetCode', { timeout: 15_000 }, () => {
it.skipIf(!process.env['TEST_LEETCODE_SESSION'])(
"should be able to get user's submissions",
async () => {
const submissions = await lc.submissions({ limit:100, offset: 0 });
const submissions = await lc.submissions({ limit:20, offset: 0 });
expect(submissions.length).toBeGreaterThan(0);
},
);
Expand All@@ -110,10 +110,10 @@ describe('LeetCode', { timeout: 15_000 }, () => {
it.skipIf(!process.env['TEST_LEETCODE_SESSION'])(
'should be able to get submission details',
async () => {
const submission = await lc.submission(333333333);
expect(submission.id).toBe(333333333);
expect(submission.memory).toBe(34096000);
expect(submission.runtime).toBe(200);
const submission = await lc.submission(1416118091);
expect(submission.id).toBe(1416118091);
expect(submission.memory).toBe(18152000);
expect(submission.runtime).toBe(8);
},
);
});
Expand Down
58 changes: 7 additions & 51 deletionssrc/leetcode-advanced.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -21,13 +21,11 @@ import {
MinimalCompanyTagDetail,
ProblemFieldDetails,
QueryParams,
RecentSubmission,
Submission,
SubmissionDetail,
TopicTagDetails,
UserSubmission,
} from './leetcode-types';
import problemProperties from './problem-properties';
import { memoryStringToNumber, runtimeStringToNumber } from './utils';

export class LeetCodeAdvanced extends LeetCode {
problemProperties = problemProperties;
Expand DownExpand Up@@ -157,22 +155,9 @@ export class LeetCodeAdvanced extends LeetCode {
* @returns null if there are no recent submissions
*/
public async recentSubmission(): Promise<Submission | null> {
const whoami = await this.whoami();
return await this.recentSubmissionOfUser(whoami.username);
}

/**
* Get detailed submission of current user.
* Need to be authenticated
* @returns SubmissionDetail
* @returns null if there are no recent submissions
*/
public async recentSubmissionDetail(): Promise<SubmissionDetail | null> {
const whoami = await this.whoami();
const recentSubmission = await this.recentSubmissionOfUser(whoami.username);
if (recentSubmission === null) return null;
const submissionId = recentSubmission.id;
return await this.submission(submissionId);
const submissions = await this.submissions({ limit: 1, offset: 0 });
if (submissions.length == 0) return null;
return submissions[0];
}

/**
Expand All@@ -182,23 +167,10 @@ export class LeetCodeAdvanced extends LeetCode {
* @returns Submission
* @returns null if there are no recent submissions
*/
public async recentSubmissionOfUser(username: string): Promise<Submission | null> {
const recentSubmissions = await this.recent_submissions(username, 1);
public async recentSubmissionOfUser(username: string): Promise<UserSubmission | null> {
const recentSubmissions = await this.recent_user_submissions(username, 1);
if (recentSubmissions.length == 0) return null;
return this.convertRecentSubmissionToSubmissionType(recentSubmissions[0]);
}

/**
* Get detail submission of a user by username
* Need to be authenticated
* @param username
* @returns SubmissionDetail
* @returns null if there are no recent submissions
*/
public async recentSubmissionDetailOfUser(username: string): Promise<SubmissionDetail | null> {
const recentSubmission = await this.recentSubmissionOfUser(username);
if (recentSubmission === null) return null;
return await this.submission(recentSubmission.id);
return recentSubmissions[0];
}

/**
Expand DownExpand Up@@ -389,22 +361,6 @@ export class LeetCodeAdvanced extends LeetCode {
return mapping;
}

private convertRecentSubmissionToSubmissionType(recentSubmission: RecentSubmission): Submission {
return {
id: parseInt(recentSubmission.id, 10),
lang: recentSubmission.lang,
time: recentSubmission.time,
timestamp: parseInt(recentSubmission.timestamp, 10),
statusDisplay: recentSubmission.statusDisplay,
runtime: runtimeStringToNumber(recentSubmission.runtime),
url: recentSubmission.url,
isPending: recentSubmission.isPending !== 'Not Pending',
title: recentSubmission.title,
memory: memoryStringToNumber(recentSubmission.memory),
titleSlug: recentSubmission.titleSlug,
} as Submission;
}

private combineProperties(arr1: DetailedProblem[], arr2: DetailedProblem[]) {
const uniquePropertyOfProblem = this.uniquePropertyOfProblem as keyof DetailedProblem;
const arr1Map = arr1.reduce(
Expand Down
25 changes: 19 additions & 6 deletionssrc/leetcode-types.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -268,7 +268,7 @@ export interface MatchedUser {
export interface UserProfile {
allQuestionsCount: AllQuestionsCount[];
matchedUser: MatchedUser | null;
recentSubmissionList:RecentSubmission[] | null;
recentSubmissionList:UserSubmission[] | null;
}

export interface Contest {
Expand DownExpand Up@@ -383,7 +383,7 @@ export type SubmissionStatus =
| 'Compile Error'
| 'Runtime Error';

export interfaceRecentSubmission {
export interfaceUserSubmission {
id: string;
isPending: string;
memory: string;
Expand All@@ -399,16 +399,29 @@ export interface RecentSubmission {

export interface Submission {
id: number;
question_id: number;
lang: string;
lang_name: string;
time: string;
timestamp: number;
statusDisplay: SubmissionStatus;
runtime: number;
status: number;
status_display: SubmissionStatus;
runtime: string;
url: string;
isPending: boolean;
is_pending: boolean;
title: string;
memory: number;
titleSlug: string;
code: string;
compare_result: string;
title_slug: string;
has_notes: boolean;
flat_type: number;
}

export interface SubmissionsDump {
submissions_dump: Submission[];
has_next: string;
last_key: string;
}

export interface Whoami {
Expand Down
100 changes: 52 additions & 48 deletionssrc/leetcode.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
Expand Up@@ -9,18 +9,18 @@ import PROBLEM from './graphql/problem.graphql?raw';
import PROBLEMS from './graphql/problems.graphql?raw';
import PROFILE from './graphql/profile.graphql?raw';
import RECENT_SUBMISSIONS from './graphql/recent-submissions.graphql?raw';
import SUBMISSIONS from './graphql/submissions.graphql?raw';
import WHOAMI from './graphql/whoami.graphql?raw';
import type {
DailyChallenge,
Problem,
ProblemList,
QueryParams,
RecentSubmission,
Submission,
SubmissionDetail,
SubmissionsDump,
UserContestInfo,
UserProfile,
UserSubmission,
Whoami,
} from './leetcode-types';
import { RateLimiter } from './mutex';
Expand DownExpand Up@@ -95,10 +95,6 @@ export class LeetCode extends EventEmitter {
* @param username
* @returns
*
* ```javascript
* const leetcode = new LeetCode();
* const profile = await leetcode.user_contest_info("jacoblincool");
* ```
*/
public async user_contest_info(username: string): Promise<UserContestInfo> {
await this.initialized;
Expand All@@ -117,16 +113,16 @@ export class LeetCode extends EventEmitter {
*
* ```javascript
* const leetcode = new LeetCode();
* const submissions = await leetcode.recent_submissions("jacoblincool");
* const submissions = await leetcode.recent_user_submissions("jacoblincool");
* ```
*/
public asyncrecent_submissions(username: string, limit = 20): Promise<RecentSubmission[]> {
public asyncrecent_user_submissions(username: string, limit = 20): Promise<UserSubmission[]> {
await this.initialized;
const { data } = await this.graphql({
variables: { username, limit },
query: RECENT_SUBMISSIONS,
});
return (data.recentSubmissionList asRecentSubmission[]) || [];
return (data.recentSubmissionList asUserSubmission[]) || [];
}

/**
Expand All@@ -144,54 +140,67 @@ export class LeetCode extends EventEmitter {
public async submissions({
limit = 20,
offset = 0,
slug,
}: { limit?: number; offset?: number; slug?: string } = {}): Promise<Submission[]> {
await this.initialized;

const submissions: Submission[] = [];
const set = new Set<number>();

let allSubmissions: Submission[] = [];
let cursor = offset;
while (submissions.length < limit) {
const { data } = await this.graphql({
variables: {
offset: cursor,
limit: limit - submissions.length > 20 ? 20 : limit - submissions.length,
slug,
},
query: SUBMISSIONS,
while (allSubmissions.length < limit) {
const { submissions_dump: submissions, has_next } = await this.submissionsApi({
offset: cursor,
limit: limit <= 20 ? limit : 20,
});

for (const submission of data.submissionList.submissions) {
submission.id = parseInt(submission.id, 10);
submission.timestamp = parseInt(submission.timestamp, 10) * 1000;
submission.isPending = submission.isPending !== 'Not Pending';
submission.runtime = parseInt(submission.runtime, 10) || 0;
submission.memory = parseFloat(submission.memory) || 0;

if (set.has(submission.id)) {
continue;
}

set.add(submission.id);
submissions.push(submission);
}

if (!data.submissionList.hasNext) {
allSubmissions = [...allSubmissions, ...submissions];
if (!has_next) {
break;
}

cursor += 20;
}
return allSubmissions;
}

private async submissionsApi({ offset = 0, limit = 20 }) {
await this.initialized;
if (limit > 20) limit = 20;
try {
await this.limiter.lock();
const res = await fetch(`${BASE_URL}/api/submissions/?offset=${offset}&limit=${limit}`, {
method: 'GET',
headers: {
'content-type': 'application/json',
origin: BASE_URL,
referer: BASE_URL,
cookie: `csrftoken=${this.credential.csrf || ''}; LEETCODE_SESSION=${
this.credential.session || ''
};`,
'x-csrftoken': this.credential.csrf || '',
'user-agent': USER_AGENT,
},
});
if (!res.ok) {
throw new Error(`HTTP ${res.status} ${res.statusText}: ${await res.text()}`);
}
if (res.headers.has('set-cookie')) {
const cookies = parse_cookie(res.headers.get('set-cookie') || '');

return submissions;
if (cookies['csrftoken']) {
this.credential.csrf = cookies['csrftoken'];
this.emit('update-csrf', this.credential);
}
}
this.limiter.unlock();
return (await res.json()) as Promise<SubmissionsDump>;
} catch (err) {
this.limiter.unlock();
throw err;
}
}

/**
* Get detail of a submission, including the code and percentiles.
* Need to be authenticated.
* @param id Submission ID
* @returns
* @deprecated
*
*/
public async submission(id: number): Promise<SubmissionDetail> {
await this.initialized;
Expand DownExpand Up@@ -279,13 +288,8 @@ export class LeetCode extends EventEmitter {

/**
* Get information of a problem by its slug.
* @param slug Problem slug
* @param slug
* @returns
*
* ```javascript
* const leetcode = new LeetCode();
* const problem = await leetcode.problem("two-sum");
* ```
*/
public async problem(slug: string): Promise<Problem> {
await this.initialized;
Expand Down
4 changes: 2 additions & 2 deletionssrc/types.ts
View file
Open in desktop
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
import type {RecentSubmission, UserProfile } from './leetcode-types';
import type {UserProfile, UserSubmission } from './leetcode-types';

///////////////////////////////////////////////////////////////////////////////
// Cache
Expand DownExpand Up@@ -51,5 +51,5 @@ export interface LeetCodeGraphQLQuery {

export interface LeetCodeGraphQLResponse {
// eslint-disable-next-line @typescript-eslint/no-explicit-any
data: UserProfile |RecentSubmission[] | any;
data: UserProfile |UserSubmission[] | any;
}

[8]ページ先頭

©2009-2025 Movatter.jp