您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Выводит список подписок в сайдбаре и раскрывает список комментов
当前为
// ==UserScript== // @name DTF Enhancer // @namespace http://tampermonkey.net/ // @version 0.0.5 // @description Выводит список подписок в сайдбаре и раскрывает список комментов // @author You // @match *://dtf.ru/* // @icon https://www.google.com/s2/favicons?sz=64&domain=dtf.ru // @run-at document-end // @grant GM.getValue // @grant GM.setValue // @license MIT // ==/UserScript== (function() { const dict = {"Ё":"YO","Й":"I","Ц":"TS","У":"U","К":"K","Е":"E","Н":"N","Г":"G","Ш":"SH","Щ":"SCH","З":"Z","Х":"H","Ъ":"'","ё":"yo","й":"i","ц":"ts","у":"u","к":"k","е":"e","н":"n","г":"g","ш":"sh","щ":"sch","з":"z","х":"h","ъ":"'","Ф":"F","Ы":"I","В":"V","А":"A","П":"P","Р":"R","О":"O","Л":"L","Д":"D","Ж":"ZH","Э":"E","ф":"f","ы":"i","в":"v","а":"a","п":"p","р":"r","о":"o","л":"l","д":"d","ж":"zh","э":"e","Я":"Ya","Ч":"CH","С":"S","М":"M","И":"I","Т":"T","Ь":"'","Б":"B","Ю":"YU","я":"ya","ч":"ch","с":"s","м":"m","и":"i","т":"t","ь":"'","б":"b","ю":"yu"}; const transliterate = (word) => word.split('').map((char) => dict[char] || char).join(""); const cn = (tagName, attrs = {}, childrenList = [], parentNode = null) => { const node = document.createElement(tagName); if (typeof attrs === 'object') { for (const attrsKey in attrs) node.setAttribute(attrsKey, attrs[attrsKey]); } if (Array.isArray(childrenList)) { childrenList.forEach(child => { node.appendChild(typeof child === 'string' ? document.createTextNode(child) : child); }); } if (parentNode) { parentNode.appendChild(node); } return node; }; const getDomElementAsync = (selector, timerLimit = 10000) => { return new Promise((resolve, reject) => { try { setTimeout(() => { console.log(`Время ожидания DOM элемента ${selector} истекло (${timerLimit / 1000}s)`); resolve(null); }, timerLimit); let timerId; const tick = () => { const element = document.querySelector(selector); if (element) { clearTimeout(timerId); resolve(element); } else { timerId = setTimeout(tick, 100); } }; tick(); } catch (e) { reject(e); } }); }; const debounce = (func, wait) => { let timeout; return function (...args) { return new Promise(resolve => { clearTimeout(timeout); timeout = setTimeout(() => { timeout = null; Promise.resolve(func.apply(this, [...args])).then(resolve); }, wait); }); }; }; const observeUrlChange = async (onChange) => { await GM.setValue('currentUrl', window.location.href); const onChangeHandler = async () => { const oldHref = await GM.getValue('currentUrl'); const newHref = window.location.href; if (oldHref !== newHref) { console.log('observeUrlChange'); await GM.setValue('currentUrl', newHref); onChange?.(); } }; const debouncedOnChangeHandler = debounce(onChangeHandler, 500); const observer = new MutationObserver(debouncedOnChangeHandler); observer.observe(document.body, { childList: true, subtree: true, }); }; const injectStyles = () => { const styles = ` .sidebar-subs { display: flex; flex-direction: column; overflow: auto; margin: 24px 0; } .sidebar-sibs__title { margin-bottom: 16px; padding: 0 8px; font-weight: 500; font-size: 18px; } .sidebar-sibs__list { padding: 0; } .sidebar-item._sub img.icon { width: 24px; border-radius: 50%; } .sidebar-item._sub span { white-space: nowrap; overflow: hidden; text-overflow: ellipsis; min-width: 1px; } /* перебиваем стили DTF */ .sidebar__main { display: flex; flex-direction: column; flex-shrink: 0; min-width: 1px; overflow: auto; } .sidebar-item { flex-shrink: 0; } .sidebar-editor-button { margin-top: 24px; } .sidebar-editor-buttons { margin-top: auto; margin-bottom: 16px; } .account-menu { visibility: hidden; } body.dtf-subs-script-inited .account-menu { visibility: visible; } `; document.head.insertAdjacentHTML("beforeend", `<style type="text/css" id="dtfSubsStyles">${styles}</style>`) }; const fetchSubs = async (userId) => { const resp = await fetch(`https://api.dtf.ru/v2.5/subsite/subscriptions?subsiteId=${userId}`); const { result } = await resp.json(); return result.items; } const getImageUrl = (uuid) => `https://leonardo.osnova.io/${uuid}/-/scale_crop/32x32/`; const createSidebarItem = (name, imageId, href) => { const imgEl = cn('img', { class: 'icon', src: getImageUrl(imageId) }); const nameEl = cn('span', {}, [name]); const result = cn('a', { class: 'sidebar-item _sub', href: transliterate(href), alt: name }, [imgEl, nameEl]); return result; }; const createSidebarList = (items) => { const sidebarItems = items.map((item) => { const href = item.uri || `/u/${item.id}-${item.name.toLowerCase()}`; return createSidebarItem(item.name, item.avatar.data.uuid, href); }); const title = cn('div', { class: 'sidebar-sibs__title' }, ['Подписки:']); const listWrapper = cn('div', { class: 'sidebar-sibs__list modal-window__content' }, sidebarItems); return cn('div', { class: 'sidebar-subs' }, [title, listWrapper]); }; const getProfileUrl = async () => { const userButton = await getDomElementAsync('.user'); userButton.click(); const profileMenuItem = await getDomElementAsync('.account-menu__user-card'); userButton.click(); return profileMenuItem.href; } const getUserId = async () => { const profileUrl = await getProfileUrl(); const userId = profileUrl.split('/u/')[1].split('-')[0]; return userId || null; }; const injectSubscriptions = async () => { const userId = await getUserId(); document.body.classList.add('dtf-subs-script-inited'); if (!userId) { return; } const subs = await fetchSubs(userId); const list = createSidebarList(subs); const sidebarButton = await getDomElementAsync('.sidebar-editor-button'); sidebarButton.after(list); }; const runAutoExpandComments = () => { const expandComments = async () => { const expandCommentsButton = await getDomElementAsync('.comments-limit__expand'); expandCommentsButton?.click(); }; observeUrlChange(expandComments); expandComments(); }; const init = async () => { injectStyles(); injectSubscriptions(); runAutoExpandComments(); }; init(); })();