您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
save all browsing history to Omnivore
当前为
// ==UserScript== // @name Omnivore Everything // @namespace Violentmonkey Scripts // @version 0.1 // @description save all browsing history to Omnivore // @author fankaidev // @match *://*/* // @exclude *://omnivore.app/* // @exclude *://cubox.pro/* // @exclude *://readwise.io/* // @exclude *://localhost:*/* // @exclude *://127.0.0.1:*/* // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @grant GM_registerMenuCommand // @require https://cdn.jsdelivr.net/npm/[email protected]/crypto-js.js // @license MIT // ==/UserScript== (function () { "use strict"; function uuid() { return CryptoJS.lib.WordArray.random(16).toString(CryptoJS.enc.Hex); } let hrefHistory = []; const omnivoreSchema = { saveUrl: ` mutation SaveUrl($input: SaveUrlInput!) { saveUrl(input: $input) { ... on SaveSuccess { url clientRequestId } ... on SaveError { errorCodes message } } }`, savePage: ` mutation SavePage($input: SavePageInput!) { savePage(input: $input) { ... on SaveSuccess { url clientRequestId } ... on SaveError { errorCodes message } } }`, }; // Function to get or initialize global state function getGlobalState(key, defaultValue) { return GM_getValue(key, defaultValue); } // Function to update global state function updateGlobalState(key, value) { GM_setValue(key, value); } function getApiKey() { let apiKey = getGlobalState("omnivoreApiKey", null); if (!apiKey) { apiKey = prompt("[Omni] Please enter Omnivore API key:", ""); if (apiKey) { updateGlobalState("omnivoreApiKey", apiKey); } else { console.error("[Omni] No API key provided. Script will not function correctly."); } } return apiKey; } function changeEndpoint() { let newApiKey = prompt("[Omni] Enter new Omnivore API key:", getGlobalState("omnivoreApiKey", "")); if (newApiKey) { updateGlobalState("omnivoreApiKey", newApiKey); console.log("[Omni] API key updated to", newApiKey); } } GM_registerMenuCommand("Change Omnivore API key", changeEndpoint); function saveToOmniovre(url, title, content) { const variables = { input: { url, title, originalContent: content, source: "chrome", clientRequestId: uuid(), }, }; const apiKey = getApiKey(); const apiUrl = "https://api-prod.omnivore.app/api/graphql"; if (!apiKey || !apiUrl) { return; } GM_xmlhttpRequest({ method: "POST", url: apiUrl, headers: { "Content-Type": "application/json", Authorization: apiKey, }, data: JSON.stringify({ query: omnivoreSchema.savePage, variables }), onload: function (response) { if (response.status === 200) { console.log("[Omni] saved to omnivore"); } else { console.error("[Omni] Failed to save to omnivore", response.responseText); } }, onerror: function (error) { console.error("Request failed:", error); }, }); } function process() { const url = window.location.href.split("#")[0]; if (hrefHistory.includes(url)) { console.log("[Omni] skip processed url", url); return; } console.log("[Omni] processing url", url); hrefHistory.push(url); saveToOmniovre(url, document.title, document.documentElement.outerHTML); } function scheduleProcess() { if (window.self === window.top) { console.log(`[Omni] current href is`, window.location.href); setTimeout(() => { process(); }, 5000); } } // Intercept pushState and replaceState const originalPushState = history.pushState; const originalReplaceState = history.replaceState; history.pushState = function () { originalPushState.apply(this, arguments); scheduleProcess(); }; history.replaceState = function () { originalReplaceState.apply(this, arguments); scheduleProcess(); }; window.addEventListener("load", function () { scheduleProcess(); }); window.addEventListener("popstate", function (event) { scheduleProcess(); }); })();