A userscript that adds an about tab to channel pages in Invidious
// ==UserScript== // @name About tab for Invidious // @namespace https://greasyfork.org/en/users/1028674-yacine-book // @version 1.0.1 // @license MIT // @description A userscript that adds an about tab to channel pages in Invidious // @author Yacine Book // @match https://yewtu.be/channel/* // @match https://invidious.flokinet.to/channel/* // @match https://invidious.protokolla.fi/channel/* // @icon https://www.google.com/s2/favicons?sz=64&domain=yewtu.be // @connect yt.lemnoslife.com // @connect * // @run-at document-end // @grant GM.xmlHttpRequest // @grant GM_xmlhttpRequest // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js // ==/UserScript== (function() { 'use strict'; const queryString = window.location.search; console.log(queryString); const urlParams = new URLSearchParams(queryString); const about = urlParams.get('/about') console.log(about); const node = document.getElementById("descriptionWrapper"); node.setAttribute("hidden", ""); const tabContainer = document.querySelector(".flexible.title~.pure-g.h-box>.pure-u-1-2:nth-of-type(1)"); const aboutTabContainer = document.createElement("div"); aboutTabContainer.classList.add("pure-u-1", "pure-md-1-3"); tabContainer.appendChild(aboutTabContainer); const aboutTab = document.createElement("a"); aboutTab.innerHTML = 'About'; aboutTab.href = '/channel/' + window.location.pathname.split("/").slice(2, 3) + '/?/about=1'; aboutTab.classList.add("about-tab"); aboutTabContainer.appendChild(aboutTab); const style = document.createElement('style'); style.innerHTML = ` .about-page-columns { display: flex; flex-direction: row; flex-wrap: wrap; } #descriptionWrapper { max-width: unset; border-bottom: 1px solid; padding-bottom: 10px; margin-bottom: 10px; } .ap-col { flex: 2; } .ap-col.num-2 { flex: 1; } .ap-col.num-1 { min-width: 0; padding-right: 60px; } p#apJoinDate.join-date-mobile { display: none; } div#linkListContainer.link-list-mobile { display: none; } @media (max-width: 760px) { .about-page-columns { flex-direction: column; } .ap-col.num-1 { padding-right: 0; } p#apJoinDate.join-date-mobile { display: block; } .ap-col.num-2 p { text-align: center; } .ap-col.num-2 p#apJoinDate { display: none; } .ap-redirect-links-container { text-align: center; } .ap-col.num-2 h3.about-page-subheadline { display: none; } div#linkListContainer.link-list-mobile { display: block; } h3.about-page-subheadline#subheadlineLinks { display: none; } h3.about-page-subheadline#subheadlineLinks~#descriptionWrapper { display: none; } } h3.about-page-subheadline { margin-bottom: 5px; } .ap-col.num-2 h3.about-page-subheadline, .ap-col.num-2 p { margin-bottom: 0px; margin-top: 10px; padding: 8px 0; border-bottom: 1px solid; } .ap-col.num-2 p { margin-top: 0; } .flexible.title~.pure-g.h-box>.pure-u-1-2:nth-of-type(1) .pure-u-1.pure-md-1-3:nth-of-type(1), .flexible.title~.pure-g.h-box>.pure-u-1-2:nth-of-type(1) .pure-u-1.pure-md-1-3:nth-of-type(2) { display: none; } .ap-redirect-links-container { display: flex; flex-direction: column; margin-top: 13px; } .ap-redirect-links-container a { padding: 8px 0; border-bottom: 1px solid; font-size: 14px; } .channel-external-link { margin: 10px 0; font-size: 14px; display: flex; flex-direction: row; align-items: center; } `; style.id = 'aboutPageStyle'; style.type = 'text/css'; document.querySelector("html").appendChild(style); if (about == "1") { node.removeAttribute("hidden"); const hBox = document.createElement("div"); hBox.classList.add("h-box"); document.getElementById("contents").appendChild(hBox); const aboutPage = document.createElement("div"); aboutPage.classList.add("about-page"); hBox.appendChild(aboutPage); const aboutPageCols = document.createElement("div"); aboutPageCols.classList.add("about-page-columns"); aboutPage.appendChild(aboutPageCols); const apCol1 = document.createElement("div"); apCol1.classList.add("ap-col", "num-1"); aboutPageCols.appendChild(apCol1); const apCol2 = document.createElement("div"); apCol2.classList.add("ap-col", "num-2"); aboutPageCols.appendChild(apCol2); const aboutPageHeader = document.createElement("h3"); aboutPageHeader.classList.add("about-page-subheadline"); aboutPageHeader.innerHTML = 'About'; apCol1.appendChild(aboutPageHeader); const aboutPageHeader2 = document.createElement("h3"); aboutPageHeader2.classList.add("about-page-subheadline"); aboutPageHeader2.innerHTML = 'Stats'; apCol2.appendChild(aboutPageHeader2); const aboutPageJoin = document.createElement("p"); aboutPageJoin.id = "apJoinDate"; aboutPageJoin.innerHTML = ` <div style="opacity: 0.5; font-style: italic;">Retrieving info from server...</div> `; apCol2.appendChild(aboutPageJoin); const aboutPageViews = document.createElement("p"); aboutPageViews.id = "apViewCount"; aboutPageViews.innerHTML = ` <div style="opacity: 0.5; font-style: italic;">Retrieving info from server...</div> `; apCol2.appendChild(aboutPageViews); const aboutPageVideoCount = document.createElement("p"); aboutPageVideoCount.id = "apVideoCount"; aboutPageVideoCount.innerHTML = ` <div style="opacity: 0.5; font-style: italic;">Retrieving info from server...</div> `; apCol2.appendChild(aboutPageVideoCount); const apLinksCont = document.createElement("div"); apLinksCont.classList.add("ap-redirect-links-container"); apCol2.appendChild(apLinksCont); const node2 = document.getElementById("descriptionWrapper"); const clone = node2.cloneNode(true); node.setAttribute("hidden", ""); apCol1.appendChild(clone); const aboutPageJoinMob = document.createElement("p"); aboutPageJoinMob.id = "apJoinDate"; aboutPageJoinMob.classList.add("join-date-mobile"); aboutPageJoinMob.innerHTML = ` <div style="opacity: 0.5; margin: -37px 0; font-style: italic;">Retrieving info from server...</div> `; clone.appendChild(aboutPageJoinMob); const aboutPageLinks = document.createElement("div"); aboutPageLinks.id = "linkListContainer"; const aboutPageLinksMob = document.createElement("div"); aboutPageLinksMob.id = "linkListContainer"; aboutPageLinksMob.classList.add("link-list-mobile"); clone.appendChild(aboutPageLinksMob); const viewOnYT = document.querySelector('a[href*="youtube.com"]'); apLinksCont.appendChild(viewOnYT); const switchInstance = document.querySelector('a[href*="redirect.invidious.io"]'); apLinksCont.appendChild(switchInstance); const hideVideos = document.createElement('style'); hideVideos.innerHTML = ` .pure-u-1.pure-u-md-1-4 { display: none!important; } .page-nav-container { display: none; } `; document.querySelector("body").appendChild(hideVideos); const footer = document.querySelector("footer"); document.getElementById("contents").appendChild(footer); const newAboutTab = document.createElement("b"); newAboutTab.innerHTML = 'About'; newAboutTab.classList.add("about-tab"); aboutTab.replaceWith(newAboutTab); var videoTab = document.querySelectorAll('b'); for(var i=0;i<videoTab.length;i++){ console.log(videoTab[i].innerHTML) if(videoTab[i].innerHTML == 'Videos'){ var newVideoTab = document.createElement('a'); newVideoTab.innerHTML = 'Videos'; newVideoTab.href = '/channel/' + window.location.pathname.split("/").slice(2, 3) + '/videos'; videoTab[i].replaceWith(newVideoTab); break; } } const options = document.querySelector(".flexible.title~.pure-g.h-box>.pure-u-1-2~.pure-u-1-2 .pure-md-1-3"); options.remove(); const options2 = document.querySelector(".flexible.title~.pure-g.h-box>.pure-u-1-2~.pure-u-1-2 .pure-md-1-3"); options2.remove(); const options3 = document.querySelector(".flexible.title~.pure-g.h-box>.pure-u-1-2~.pure-u-1-2 .pure-md-1-3"); options3.remove(); const ucid = window.location.pathname.split("/").slice(2, 3); const descWrapper = document.getElementById("descriptionWrapper"); if (descWrapper && aboutPageJoin) { GM.xmlHttpRequest({ url: "https://yt.lemnoslife.com/noKey/channels?part=snippet,status&id=" + ucid, onload: (response) => { const data = JSON.parse(response.responseText); console.log(data); aboutPageJoin.innerHTML = '<span>Joined </span>' + data.items[0].snippet.publishedAt.toLocaleString(); aboutPageJoinMob.innerHTML = '<span>Joined </span>' + data.items[0].snippet.publishedAt.toLocaleString(); }, }); } if (descWrapper && aboutPageViews) { GM.xmlHttpRequest({ url: "https://yt.lemnoslife.com/channels?part=snippet,status,about&id=" + ucid, onload: (response) => { const data = JSON.parse(response.responseText); console.log(data); aboutPageViews.innerHTML = "<b>" + data.items[0].about.stats.viewCount.toLocaleString() + "</b> views"; aboutPageVideoCount.innerHTML = "<b>" + data.items[0].about.stats.videoCount.toLocaleString() + "</b> videos"; if (data.items[0].about.details.location) { const aboutPageHeaderDetails = document.createElement("h3"); aboutPageHeaderDetails.classList.add("about-page-subheadline"); aboutPageHeaderDetails.id = "subheadlineDetails"; aboutPageHeaderDetails.innerHTML = 'Details'; apCol1.appendChild(aboutPageHeaderDetails); const detailsWrapper = document.createElement("div"); detailsWrapper.id = "descriptionWrapper"; apCol1.appendChild(detailsWrapper); const detailsWrapperP = document.createElement("p"); detailsWrapperP.innerHTML = '<b>Location: </b>' + data.items[0].about.details.location; detailsWrapperP.style = "opacity: 0.8;"; detailsWrapper.appendChild(detailsWrapperP); } if (!data.items[0].about.links.length == 0) { const aboutPageHeaderLinks = document.createElement("h3"); aboutPageHeaderLinks.classList.add("about-page-subheadline"); aboutPageHeaderLinks.id = "subheadlineLinks"; aboutPageHeaderLinks.innerHTML = 'Links'; apCol1.appendChild(aboutPageHeaderLinks); const linksWrapper = document.createElement("div"); linksWrapper.id = "descriptionWrapper"; apCol1.appendChild(linksWrapper); linksWrapper.appendChild(aboutPageLinks); data.items[0].about.links.forEach(item => { const externalLink = document.createElement("div"); externalLink.classList.add("channel-external-link"); aboutPageLinks.appendChild(externalLink); const externalLinkTextCont = document.createElement("div"); externalLinkTextCont.classList.add("channel-external-link-text-container"); externalLink.appendChild(externalLinkTextCont); const externalLinkText = document.createElement("a"); externalLinkText.classList.add("channel-external-link-text"); externalLinkText.innerHTML = item.title; externalLinkText.href = item.url; externalLinkText.target = "_blank"; externalLinkTextCont.appendChild(externalLinkText); }); data.items[0].about.links.forEach(item => { const externalLink = document.createElement("div"); externalLink.classList.add("channel-external-link"); aboutPageLinksMob.appendChild(externalLink); const externalLinkTextCont = document.createElement("div"); externalLinkTextCont.classList.add("channel-external-link-text-container"); externalLink.appendChild(externalLinkTextCont); const externalLinkText = document.createElement("a"); externalLinkText.classList.add("channel-external-link-text"); externalLinkText.innerHTML = item.title; externalLinkText.href = item.url; externalLinkText.target = "_blank"; externalLinkTextCont.appendChild(externalLinkText); }); } }, }); } } })();