您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
save all browsing history to Omnivore
当前为
// ==UserScript== // @name Omnivore Everything // @namespace Violentmonkey Scripts // @version 0.9 // @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 Omnivore API key:", getGlobalState("omnivoreApiKey", "")); if (newApiKey) { updateGlobalState("omnivoreApiKey", newApiKey); console.log("[Omni] API key updated to", newApiKey); } } function getBlacklistPattern() { let val = getGlobalState("blacklistPattern", null); if (!val) { val = `omnivore.app/.*|readwise.io/.*|cubox.pro/.*|localhost:.*|mail.google.com/.*`; updateGlobalState("blacklistPattern", val); } return new RegExp(val.trim()); } function getWhitelistPattern() { let val = getGlobalState("whitelistPattern", null); if (!val) { val = ".*"; updateGlobalState("whitelistPattern", val); } return new RegExp(val.trim()); } function changeEndpoint() { let newApiKey = prompt("[Omni] Enter Omnivore API key:", getGlobalState("omnivoreApiKey", "")); if (newApiKey) { updateGlobalState("omnivoreApiKey", newApiKey); console.log("[Omni] API key updated to", newApiKey); } } function changeBlacklistPattern() { let newVal = prompt("[Omni] blacklist pattern in regex", getGlobalState("blacklistPattern", "")); updateGlobalState("blacklistPattern", newVal); console.log("[Omni] blacklist patterns", newVal); } function changeWhitelistPattern() { let newVal = prompt("[Omni] whitelist pattern in regex", getGlobalState("whitelistPattern", "")); updateGlobalState("whitelistPattern", newVal); console.log("[Omni] whitelist patterns", newVal); } GM_registerMenuCommand("Change Omnivore API key", changeEndpoint); GM_registerMenuCommand("Change blacklist pattern", changeBlacklistPattern); GM_registerMenuCommand("Change whitelist pattern", changeWhitelistPattern); function savePage(url) { const variables = { input: { url, title: document.title, originalContent: document.documentElement.outerHTML, 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 page to omnivore"); } else { console.error("[Omni] Failed to save to omnivore", response.responseText); } }, onerror: function (error) { console.error("Request failed:", error); }, }); } function saveUrl(url) { const variables = { input: { url, 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.saveUrl, variables }), onload: function (response) { if (response.status === 200) { console.log("[Omni] saved url 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); const blacklistPattern = getBlacklistPattern(); const whitelistPattern = getWhitelistPattern(); if (!whitelistPattern.test(url)) { console.log("[Omni] ignore non-whitelisted url"); return; } if (blacklistPattern.test(url)) { console.log("[Omni] ignore blacklisted url"); return; } if (document.contentType === "application/pdf") { saveUrl(url); } else { savePage(url); } } 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(); }); })();