66 * to continue fetching more questions until all are processed.
77 */
88import { Question , SeedCursor } from "../db/model/question.js" ;
9- import { gql } from "./client.js" ;
10- import { QUERY_LIST , QUERY_DETAIL } from "./queries.js" ;
11- import type { BasicInformation , QuestionList , Details } from "./types.js" ;
9+ import { QUERY_DETAIL } from "./queries.js" ;
10+ import type { BasicInformation , Details } from "./types.js" ;
1211import pLimit from "p-limit" ;
1312import { logger } from "../logger.js" ;
1413import { checkQuestionServiceHealth } from "../health.js" ;
14+ import { LeetCode } from "leetcode-query" ;
1515
1616const PAGE_SIZE = 200 ;
1717/**
@@ -32,6 +32,8 @@ const DIFFICULTY_TIME_LIMITS: Record<string, number> = {
3232 Hard : 120 ,
3333} ;
3434
35+ const leetcode = new LeetCode ( ) ;
36+
3537/**
3638 * Run one batch (default pageSize=200). Returns a summary.
3739 * @returns An object containing the result of the seeding operation.
@@ -63,10 +65,16 @@ export async function seedLeetCodeBatch() {
6365 let total = 0 ;
6466
6567 try {
66- const { questionList : fetchedQuestionList , total : fetchedTotal } =
67- await fetchNonPaidQuestionList ( pageSize , nextSkip ) ;
68- questionList = fetchedQuestionList ;
69- total = fetchedTotal ;
68+ const res = await leetcode . problems ( { limit : pageSize , offset : nextSkip } ) ;
69+
70+ questionList = res . questions
71+ . filter ( ( p ) => ! p . isPaidOnly )
72+ . map ( ( p ) => ( {
73+ titleSlug : p . titleSlug ,
74+ title : p . title ,
75+ isPaidOnly : p . isPaidOnly ,
76+ } ) ) ;
77+ total = res . total ?? res . questions . length ;
7078 } catch ( err ) {
7179 logger . error (
7280 `Failed to fetch question list from LeetCode: ${ ( err as Error ) . message } ` ,
@@ -95,7 +103,6 @@ export async function seedLeetCodeBatch() {
95103
96104 const questionInfos : QuestionDetail [ ] =
97105 await fetchNonPaidQuestionInfo ( questionList ) ;
98-
99106 const ops = questionInfos . map ( ( q ) => ( {
100107 updateOne : {
101108 filter : { titleSlug : q . titleSlug } ,
@@ -180,40 +187,14 @@ export async function fetchNonPaidQuestionInfo(
180187 return results . filter ( ( d ) : d is QuestionDetail => d !== null ) ;
181188}
182189
183- /**
184- * Fetch non-paid question list.
185- * We will only store non-paid questions in our database because
186- * content of paid questions will not be accessible without a premium account.
187- */
188- export async function fetchNonPaidQuestionList (
189- limit : number ,
190- skip : number ,
191- ) : Promise < {
192- questionList : BasicInformation [ ] ;
193- total : number ;
194- } > {
195- const res = await gql <
196- QuestionList ,
197- {
198- categorySlug : string ;
199- limit : number ;
200- skip : number ;
201- filters : Record < string , unknown > ;
202- }
203- > ( QUERY_LIST , { categorySlug : "" , limit : limit , skip : skip , filters : { } } ) ;
190+ export async function getQuestionDetail ( slug : string ) {
191+ const res = ( await leetcode . graphql ( {
192+ query : QUERY_DETAIL ,
193+ variables : { titleSlug : slug } ,
194+ } ) ) as { data : { question : QuestionDetail | null } | null } ;
204195
205- if ( ! res . problemsetQuestionList ) {
206- throw new Error ( "Failed to fetch question list from LeetCode" ) ;
196+ if ( ! res || ! res . data || ! res . data . question ) {
197+ return null ;
207198 }
208-
209- const { total, questions } = res . problemsetQuestionList ;
210- const questionList = questions . filter ( ( q ) => ! q . isPaidOnly ) ;
211- return { questionList, total } ;
212- }
213-
214- export async function getQuestionDetail ( slug : string ) {
215- const res = await gql < Details , { titleSlug : string } > ( QUERY_DETAIL , {
216- titleSlug : slug ,
217- } ) ;
218- return res . question ;
199+ return res . data . question ;
219200}
0 commit comments