您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Save LeetCode problems to Notion after clicking a button.
当前为
您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
- // ==UserScript==
- // @name leetcode2notion
- // @namespace wuyifff
- // @version 1.1
- // @description Save LeetCode problems to Notion after clicking a button.
- // @author wuyifff
- // @match https://leetcode.cn/problems/*
- // @match https://leetcode.com/problems/*
- // @connect api.notion.com
- // @icon https://www.google.com/s2/favicons?sz=64&domain=leetcode.com
- // @grant GM_xmlhttpRequest
- // @license MIT
- // @homepage https://github.com/wuyifff/leetcode2notion
- // ==/UserScript==
- (function() {
- 'use strict';
- // replace to your own token and ID
- const notionToken = '';
- const databaseId = '';
- // 1. add save button
- // select language button (optional)
- function addUIElements() {
- const button = document.createElement("button");
- button.innerHTML = "Save to Notion";
- button.style.position = "fixed";
- button.style.bottom = "10px";
- button.style.right = "10px";
- button.style.zIndex = 1000;
- button.style.padding = "10px 20px";
- button.style.backgroundColor = "#4CAF50";
- button.style.color = "white";
- button.style.border = "none";
- button.style.borderRadius = "5px";
- button.style.cursor = "pointer";
- button.onclick = saveProblemToNotion;
- const select = document.createElement("select");
- select.id = "languageSelect";
- select.style.position = "fixed";
- select.style.bottom = "50px";
- select.style.right = "10px";
- select.style.zIndex = 1000;
- select.style.padding = "10px";
- select.style.backgroundColor = "#4CAF50";
- select.style.color = "white";
- select.style.border = "none";
- select.style.borderRadius = "5px";
- select.style.cursor = "pointer";
- const optionPython = document.createElement("option");
- optionPython.value = "python";
- optionPython.innerText = "Python";
- const optionCpp = document.createElement("option");
- optionCpp.value = "cpp";
- optionCpp.innerText = "C++";
- select.appendChild(optionPython);
- select.appendChild(optionCpp);
- const container = document.createElement("div");
- container.style.display = "flex";
- container.style.flexDirection = "column";
- container.style.alignItems = "center";
- container.style.marginLeft = "10px";
- //container.appendChild(select);
- container.appendChild(button);
- container.style.position = "fixed";
- container.style.bottom = "10px";
- container.style.right = "10px";
- document.body.appendChild(container);
- }
- // 2. get leetcode problem info
- function getProblemData() {
- const title = document.querySelector('.text-title-large a')?.innerText || 'No title found';
- const difficultyElement = document.querySelector("div[class*='text-difficulty-']");
- const difficulty = difficultyElement ? difficultyElement.innerText : 'No difficulty found';
- const url = window.location.href;
- const tagElements = document.querySelectorAll("a[href*='/tag/']");
- const tagTexts = Array.from(tagElements).map(element => element.innerText);
- const codeDiv = document.querySelector('.view-lines.monaco-mouse-cursor-text[role="presentation"]');
- let codeText = '';
- if (codeDiv) {
- const codeLines = codeDiv.querySelectorAll('div');
- codeText = Array.from(codeLines).map(line => line.innerText).join('\n');
- } else {
- codeText = 'No code found';
- }
- //console.log(codeText);
- //const selectedLanguage = document.getElementById("languageSelect").value;
- const selectedLanguage = 'python';
- return {
- title: title,
- difficulty: difficulty,
- url: url,
- tag: tagTexts,
- code: codeText,
- language: selectedLanguage
- };
- }
- // 3. save to notion and check if duplicate
- async function saveProblemToNotion() {
- const problemData = getProblemData();
- console.log(problemData);
- const searchUrl = `https://api.notion.com/v1/search`;
- const searchBody = {
- "query": problemData.title,
- "filter": {
- "value": "page",
- "property": "object"
- },
- "sort": {
- "direction": "ascending",
- "timestamp": "last_edited_time"
- }
- };
- GM_xmlhttpRequest({
- method: 'POST',
- url: searchUrl,
- headers: {
- 'Authorization': `Bearer ${notionToken}`,
- 'Content-Type': 'application/json',
- 'Notion-Version': '2022-06-28'
- },
- data: JSON.stringify(searchBody),
- onload: function(searchResponse) {
- if (searchResponse.status === 200) {
- const searchResult = JSON.parse(searchResponse.responseText);
- const existingPage = searchResult.results.find(result => result.properties?.Title?.title[0]?.text?.content === problemData.title);
- if (existingPage) {
- const existingPageUrl = existingPage.url;
- alert('Problem already exists in Notion! Opening existing page...');
- window.open(existingPageUrl, '_blank');
- } else {
- createNewNotionPage(problemData);
- }
- } else {
- console.error('Error searching Notion database', searchResponse.responseText);
- alert('Failed to search Notion database. Check the console for details.');
- }
- },
- onerror: function(error) {
- console.error('Error in searching Notion database', error);
- alert('An error occurred while searching Notion database.');
- }
- });
- }
- // 4. create new page
- function createNewNotionPage(problemData) {
- const tags = problemData.tag.map(tag => ({
- name: tag
- }));
- const url = `https://api.notion.com/v1/pages`;
- const body = {
- parent: { database_id: databaseId },
- properties: {
- 'Title': {
- title: [
- {
- text: {
- content: problemData.title
- }
- }
- ]
- },
- 'Difficulty': {
- select: {
- name: problemData.difficulty
- }
- },
- 'Link': {
- url: problemData.url
- },
- 'Date': {
- date: {
- start: new Date().toISOString().split('T')[0] // format YYYY-MM-DD
- }
- },
- 'Tags': {
- multi_select: tags
- }
- },
- children: [
- {
- object: 'block',
- type: 'code',
- code: {
- rich_text: [
- {
- type: 'text',
- text: {
- content: problemData.code
- }
- }
- ],
- language: problemData.language
- }
- }
- ]
- };
- GM_xmlhttpRequest({
- method: 'POST',
- url: url,
- headers: {
- 'Authorization': `Bearer ${notionToken}`,
- 'Content-Type': 'application/json',
- 'Notion-Version': '2022-06-28'
- },
- data: JSON.stringify(body),
- onload: function(response) {
- if (response.status === 200) {
- const responseData = JSON.parse(response.responseText);
- const notionPageUrl = responseData.url;
- alert('Problem saved to Notion!');
- window.open(notionPageUrl, '_blank');
- } else {
- console.error('Failed to save to Notion', response.responseText);
- alert('Failed to save to Notion. Check the console for more details.');
- }
- },
- onerror: function(error) {
- console.error('Error in saving to Notion', error);
- alert('An error occurred while saving to Notion.');
- }
- });
- }
- addUIElements();
- })();