diff --git a/README.md b/README.md index 929bfab1..19755e2f 100644 --- a/README.md +++ b/README.md @@ -55,7 +55,7 @@ GitHub Action for automatically syncing LeetCode submissions to a GitHub reposit leetcode-session: ${{ secrets.LEETCODE_SESSION }} destination-folder: my-folder verbose: true - commit-header: '[LeetCode Sync]' + commit-header: "[LeetCode Sync]" ``` 6. After you've submitted a LeetCode solution, run the workflow by going to the `Actions` tab, clicking the action name, e.g. `Sync Leetcode`, and then clicking `Run workflow`. The workflow will also automatically run once a week by default (can be configured via the `cron` parameter). @@ -101,6 +101,7 @@ Since this file is in the `.gitignore` file to avoid users accidentally committi This likely means that you hit a rate limit when committing to GitHub (this may happen if you have over ~300 submissions initially). Since the syncer writes in reverse chronological order, it should pick up syncing submissions from where it left off on the next run of the workflow, so just retry the workflow manually after some time. #### Job fails with "HttpError: Resource not accessible by integration" + This means the github token you're using does not have permission to write to your repo. If you're using the default `github.token` method follow the instructions [here] (https://docs.github.com/en/actions/security-guides/automatic-token-authentication) ## Acknowledgements diff --git a/src/action.js b/src/action.js index 76d01cf8..4d2bc439 100644 --- a/src/action.js +++ b/src/action.js @@ -113,12 +113,17 @@ async function getInfo(submission, session, csrfToken) { }; } catch (exception) { if (retryCount >= maxRetries) { + // If problem is locked due to user not having LeetCode Premium + if (exception.response && exception.response.status === 403) { + log(`Skipping locked problem: ${submission.title}`); + return null; + } throw exception; } log( "Error fetching submission info, retrying in " + 3 ** retryCount + - " seconds...", + " seconds..." ); await delay(3 ** retryCount * 1000); return getInfo(maxRetries, retryCount + 1); @@ -238,11 +243,16 @@ async function getQuestionData(titleSlug, leetcodeSession, csrfToken) { const response = await axios.post( "https://leetcode.com/graphql/", graphql, - { headers }, + { headers } ); const result = await response.data; return result.data.question.content; } catch (error) { + // If problem is locked due to user not having LeetCode Premium + if (error.response && error.response.status === 403) { + log(`Skipping locked problem: ${titleSlug}`); + return null; + } console.log("error", error); } } @@ -315,7 +325,7 @@ async function sync(inputs) { for (const commit of commits.data) { if ( !commit.commit.message.startsWith( - !!commitHeader ? commitHeader : COMMIT_MESSAGE, + !!commitHeader ? commitHeader : COMMIT_MESSAGE ) ) { continue; @@ -363,7 +373,7 @@ async function sync(inputs) { const response = await axios.post( "https://leetcode.com/graphql/", graphql, - { headers }, + { headers } ); log(`Successfully fetched submission from LeetCode, offset ${offset}`); return response; @@ -374,7 +384,7 @@ async function sync(inputs) { log( "Error fetching submissions, retrying in " + 3 ** retryCount + - " seconds...", + " seconds..." ); // There's a rate limit on LeetCode API, so wait with backoff before retrying. await delay(3 ** retryCount * 1000); @@ -421,15 +431,24 @@ async function sync(inputs) { submission = await getInfo( submissions[i], leetcodeSession, - leetcodeCSRFToken, + leetcodeCSRFToken ); + if (submission === null) { + // Skip this submission if it is null (locked problem) + continue; + } + // Get the question data for the submission. const questionData = await getQuestionData( submission.titleSlug, leetcodeSession, - leetcodeCSRFToken, + leetcodeCSRFToken ); + if (questionData === null) { + // Skip this submission if question data is null (locked problem) + continue; + } [treeSHA, latestCommitSHA] = await commit({ octokit, owner,