您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Auto-Saves your post drafts on BitcoinTalk.org
// ==UserScript== // @name Auto-Save Draft for BitcoinTalk.org // @description Auto-Saves your post drafts on BitcoinTalk.org // @match https://bitcointalk.org/index.php?action=post* // @grant none // @version 1.2 // @author TryNinja // @namespace https://greatest.deepsurf.us/users/1070272 // ==/UserScript== // "Drafts are saved whenever you preview or post a topic, post, or PM. Up to 100 drafts are kept. Drafts are deleted after 7 days." // WARNING: Be mindful that a low interval might make you override your entire draft history in a go, since there is a limit of 100 drafts. const INTERVAL_SECONDS = 60; let initialMessage = getCurrentMessage(); let lastModifiedMessage; let draftIndicatorElement; function currentTimeUTC() { const date = new Date(); const horaUTC = date.getUTCHours(); const minutoUTC = date.getUTCMinutes(); const segundoUTC = date.getUTCSeconds(); return `${horaUTC.toString().padStart(2, '0')}:${minutoUTC.toString().padStart(2, '0')}:${segundoUTC.toString().padStart(2, '0')} UTC`; } function textToEntities(text) { let entities = ""; for (let i = 0; i < text.length; i++) { if (text.charCodeAt(i) > 127) entities += "&#" + text.charCodeAt(i) + ";"; else entities += text.charAt(i); } return entities; } function insertDraftStatusIndicator() { const messageArea = document.querySelector("#postmodify textarea[name=message]"); const indicatorElement = document.createElement("p"); indicatorElement.id = "draftIndicator"; indicatorElement.textContent = "Auto-Save draft is activated!"; messageArea.after(indicatorElement); draftIndicatorElement = document.querySelector('p[id=draftIndicator]'); } function addEventListenerToPreviewButton() { const previewButton = document.querySelector('input[name=preview]'); previewButton.addEventListener('click', function() { const currentMessage = getCurrentMessage(); lastModifiedMessage = currentMessage; draftIndicatorElement.style = "color: green;"; draftIndicatorElement.textContent = `Draft saved manually @ ${currentTimeUTC()}`; }); } function getCurrentMessage() { const message = document.querySelector("#postmodify textarea[name=message]").value; return textToEntities(message.replace(/&#/g, "&#")).replace(/\+/g, "%2B"); } async function draft(message) { const formData = new FormData(); formData.append("message", message); const res = await fetch("https://bitcointalk.org/index.php?action=post2;preview;xml", { "body": formData, "method": "POST", "mode": "cors", "credentials": "include" }); if (res.status === 200) { lastModifiedMessage = message; draftIndicatorElement.style = "color: green;"; draftIndicatorElement.textContent = `Draft saved @ ${currentTimeUTC()}`; } else { draftIndicatorElement.style = "color: red;"; draftIndicatorElement.textContent = `Draft failed @ ${currentTimeUTC()}`; } } (() => { insertDraftStatusIndicator(); addEventListenerToPreviewButton(); setInterval(() => { const currentMessage = getCurrentMessage(); if (initialMessage !== currentMessage && lastModifiedMessage !== currentMessage) { draft(currentMessage); } }, INTERVAL_SECONDS * 1000) })()