Untitled
unknown
plain_text
21 hours ago
9.7 kB
9
No Index
// ==UserScript== // @name Reddit Crosspost Restorer // @version 3 // @description Box to view crossposts // @author raidprincess // @match https://www.reddit.com/* // @match https://sh.reddit.com/* // @grant GM_xmlhttpRequest // @grant GM_setValue // @grant GM_getValue // @connect old.reddit.com // ==/UserScript== (function() { 'use strict'; let duplicatesData = []; let viewCrosspostButton = null; let popup = null; let isDarkMode = GM_getValue('isDarkMode', true); let customLinkColor = GM_getValue('customLinkColor', '#f7b500'); function getPostInfo() { const pathParts = window.location.pathname.split('/'); const idx = pathParts.indexOf('comments'); if (idx !== -1 && pathParts.length > idx + 1) { return { subreddit: pathParts[idx - 1], postid: pathParts[idx + 1] }; } return null; } function createViewCrosspostButton() { if (viewCrosspostButton) return; const existingButton = document.getElementById('view-crosspost-button'); if (existingButton) existingButton.remove(); viewCrosspostButton = document.createElement('span'); viewCrosspostButton.id = 'view-crosspost-button'; viewCrosspostButton.style.fontSize = '14px'; viewCrosspostButton.style.marginLeft = '10px'; viewCrosspostButton.style.cursor = 'pointer'; viewCrosspostButton.style.color = customLinkColor; viewCrosspostButton.style.textDecoration = 'underline'; viewCrosspostButton.addEventListener('click', togglePopup); const titleElement = document.querySelector('h1'); if (titleElement && titleElement.parentElement) { titleElement.parentElement.appendChild(viewCrosspostButton); } } function createPopup() { if (popup) return; popup = document.createElement('div'); popup.id = 'duplicates-popup'; applyPopupStyles(); const header = document.createElement('div'); header.style.display = 'flex'; header.style.justifyContent = 'space-between'; header.style.alignItems = 'center'; const title = document.createElement('div'); title.innerText = 'Other Reddit Discussions'; title.style.fontWeight = 'bold'; title.style.fontSize = '16px'; const controls = document.createElement('div'); controls.style.display = 'flex'; controls.style.alignItems = 'center'; controls.style.gap = '6px'; const modeToggle = document.createElement('div'); modeToggle.innerText = isDarkMode ? '⚫' : '⚪'; modeToggle.style.cursor = 'pointer'; modeToggle.addEventListener('click', () => { toggleMode(); modeToggle.innerText = isDarkMode ? '⚫' : '⚪'; }); const colorPickerIcon = document.createElement('div'); colorPickerIcon.innerText = '🖉'; colorPickerIcon.style.cursor = 'pointer'; colorPickerIcon.style.fontSize = '16px'; colorPickerIcon.addEventListener('click', () => { colorInput.click(); }); const colorInput = document.createElement('input'); colorInput.type = 'color'; colorInput.value = customLinkColor; colorInput.style.display = 'none'; colorInput.addEventListener('input', (e) => { customLinkColor = e.target.value; GM_setValue('customLinkColor', customLinkColor); updatePopupContent(); if (viewCrosspostButton) viewCrosspostButton.style.color = customLinkColor; }); controls.appendChild(modeToggle); controls.appendChild(colorPickerIcon); header.appendChild(title); header.appendChild(controls); popup.appendChild(header); popup.appendChild(colorInput); const content = document.createElement('div'); content.id = 'duplicates-content'; content.innerText = 'Loading...'; popup.appendChild(content); document.body.appendChild(popup); document.addEventListener('click', (e) => { if (popup && !popup.contains(e.target) && e.target !== viewCrosspostButton) { popup.style.display = 'none'; } }); positionPopup(); } function applyPopupStyles() { if (!popup) return; Object.assign(popup.style, { position: 'absolute', width: '320px', maxHeight: '400px', overflowY: 'auto', border: '1px solid #333', borderRadius: '6px', boxShadow: '0 2px 10px rgba(0,0,0,0.5)', padding: '10px', zIndex: '10000', display: 'none', backgroundColor: isDarkMode ? '#1b1b1b' : '#f6f7f8', color: isDarkMode ? '#fff' : '#000' }); } function positionPopup() { if (!viewCrosspostButton || !popup) return; const rect = viewCrosspostButton.getBoundingClientRect(); popup.style.top = (window.scrollY + rect.bottom + 5) + 'px'; popup.style.left = (window.scrollX + rect.left) + 'px'; } function toggleMode() { isDarkMode = !isDarkMode; GM_setValue('isDarkMode', isDarkMode); applyPopupStyles(); updatePopupContent(); } function togglePopup() { if (!popup) return; if (popup.style.display === 'none') { positionPopup(); popup.style.display = 'block'; } else { popup.style.display = 'none'; } } function fetchDuplicates(subreddit, postid) { const url = `https://old.reddit.com/r/${subreddit}/duplicates/${postid}/`; GM_xmlhttpRequest({ method: 'GET', url: url, onload: function(response) { if (response.status === 200) { parseDuplicates(response.responseText, postid); } else { updateContentNoResults(); } } }); } function parseDuplicates(html, currentPostId) { const parser = new DOMParser(); const doc = parser.parseFromString(html, 'text/html'); const posts = doc.querySelectorAll('#siteTable .thing.link'); if (!posts.length) return; duplicatesData = []; const currentFullname = 't3_' + currentPostId; posts.forEach(postDiv => { const postId = postDiv.getAttribute('data-fullname'); if (!postId || postId === currentFullname) return; const a = postDiv.querySelector('a.title'); const commentsLink = postDiv.querySelector('a.comments'); const subreddit = postDiv.getAttribute('data-subreddit') || 'Unknown Sub'; if (!a || !commentsLink) return; const postTitle = a.textContent.trim(); let postPermalink = commentsLink.href; postPermalink = postPermalink.replace('old.reddit.com', 'www.reddit.com'); duplicatesData.push({ title: postTitle, url: postPermalink, subreddit }); }); if (duplicatesData.length) { createViewCrosspostButton(); viewCrosspostButton.innerText = `View discussions in ${duplicatesData.length} other${duplicatesData.length > 1 ? ' communities' : ' community'}`; createPopup(); updatePopupContent(); } } function updateContentNoResults() { const content = document.getElementById('duplicates-content'); if (content) { content.innerHTML = '<i>No crossposts found.</i>'; } } function updatePopupContent() { const content = document.getElementById('duplicates-content'); if (!content) return; const ul = document.createElement('ul'); ul.style.paddingLeft = '0'; ul.style.margin = '0'; ul.style.listStyle = 'none'; duplicatesData.forEach(post => { const li = document.createElement('li'); li.style.marginBottom = '8px'; const sub = document.createElement('div'); sub.textContent = `r/${post.subreddit}`; sub.style.fontSize = '12px'; sub.style.color = shadeColor(customLinkColor, -30); const a = document.createElement('a'); a.href = post.url; a.textContent = post.title; a.target = '_blank'; a.style.color = customLinkColor; a.style.textDecoration = 'none'; a.addEventListener('mouseover', () => a.style.textDecoration = 'underline'); a.addEventListener('mouseout', () => a.style.textDecoration = 'none'); li.appendChild(sub); li.appendChild(a); const line = document.createElement('hr'); line.style.border = 'none'; line.style.borderTop = '1px solid #444'; line.style.margin = '6px 0'; ul.appendChild(li); ul.appendChild(line); }); content.innerHTML = ''; content.appendChild(ul); } function shadeColor(color, percent) { let num = parseInt(color.slice(1), 16), amt = Math.round(2.55 * percent), R = (num >> 16) + amt, G = (num >> 8 & 0x00FF) + amt, B = (num & 0x0000FF) + amt; return "#" + (0x1000000 + (R<255? (R<1?0:R):255)*0x10000 + (G<255? (G<1?0:G):255)*0x100 + (B<255? (B<1?0:B):255)).toString(16).slice(1); } function monitorPageChanges() { let lastUrl = location.href; new MutationObserver(() => { const currentUrl = location.href; if (currentUrl !== lastUrl) { lastUrl = currentUrl; duplicatesData = []; if (popup) popup.remove(); popup = null; viewCrosspostButton = null; waitForPost(); } }).observe(document, { subtree: true, childList: true }); } function waitForPost() { const info = getPostInfo(); if (info) { fetchDuplicates(info.subreddit, info.postid); } else { setTimeout(waitForPost, 500); } } waitForPost(); monitorPageChanges(); })();
Editor is loading...
Leave a Comment