// ==UserScript== // @name LinkTube // @version 2019.11.25 // @description Replaces an embedded video with a link to the video page. // @author sebaro // @namespace http://sebaro.pro/linktube // @downloadURL https://gitlab.com/sebaro/linktube/raw/master/linktube.user.js // @updateURL https://gitlab.com/sebaro/linktube/raw/master/linktube.user.js // @icon https://gitlab.com/sebaro/linktube/raw/master/linktube.png // @include * // ==/UserScript== /* Copyright (C) 2011 - 2019 Sebastian Luncan This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . Website: http://sebaro.pro/linktube Contact: http://sebaro.pro/contact */ (function() { // ==========Variables========== // // Userscript var userscript = 'LinkTube'; // Page var page = {win: window, doc: window.document, url: window.location.href}; // Contact var contact = 'http://sebaro.pro/contact'; // Warning var warning = 'Couldn\'t get the video link. Please report it here.'; // Options var option = {'secure': true}; // ==========Fixes========== // // Don't run on frames or iframes if (window.top != window.self) return; // ==========Functions========== // function createMyElement(type, content) { var obj = document.createElement(type); if (type == 'div') { if (content) obj.innerHTML = content; } return obj; } function getMyElement(element, get, tag) { var obj; if (get == 'parent') obj = element.parentNode; else if (get == 'source') { obj = element.src; if (!obj) { for (var i = 0; i < element.attributes.length; i++) { if (element.attributes[i].name.match(/^data.*src$/)) { obj = element.attributes[i].value; break; } } } } else if (get == 'name') obj = element.name; else if (get == 'value') obj = element.value; else if (get == 'children') obj = element.getElementsByTagName(tag); return obj; } function modifyMyElement(obj, type, content, clear) { if (type == 'div') { if (content) obj.innerHTML = content; } if (clear) { if (obj.hasChildNodes()) { while (obj.childNodes.length >= 1) { obj.removeChild(obj.firstChild); } } } } function styleMyElement(obj, styles) { for (var property in styles) { if (styles.hasOwnProperty(property)) obj.style[property] = styles[property]; } } function appendMyElement(parent, child) { if (parent == 'body') document.body.appendChild(child); else parent.appendChild(child); } function removeMyElement(parent, child) { if (parent == 'body') document.body.removeChild(child); else parent.removeChild(child); } function replaceMyElement(parent, orphan, child) { parent.replaceChild(orphan, child); } function embedMyLinks(element) { var elements; if (element == 'iframe') elements = iframeElements; else if (element == 'object') elements = objectElements; else if (element == 'embed') elements = embedElements; var child, parent, video, param, name; var foundSite; var linkID, videoID, videoLink, videoURL; var myScriptLogo = []; myScriptLogo[element] = []; var myScriptMess = []; myScriptMess[element] = []; var myLinkWindow = []; myLinkWindow[element] = []; for (var e = elements.length - 1; e >= 0; e--) { foundSite = false; child = elements[e]; parent = getMyElement(child, 'parent', ''); if (element == 'iframe' || element == 'embed') { video = getMyElement(child, 'source', ''); } else if (element == 'object') { params = getMyElement(child, 'children', 'param'); for (var p = 0; p < params.length; p++) { name = getMyElement(params[p], 'name', ''); if (name == 'movie' || name == 'src' || name == 'flashvars') { video = getMyElement(params[p], 'value', ''); if (!video) video = getMyElement(params[p], 'source', ''); } } } if (video) { for (var l = 0; l < linkParsers.length; l++) { if (video.match(linkParsers[l]['source'])) { foundSite = true; linkID = l; break; } } } if (foundSite) { myScriptLogo[element][e] = createMyElement('div', userscript); styleMyElement(myScriptLogo[element][e], {margin: '0px auto', padding: '10px', color: '#FFFFFF', fontSize: '20px', textAlign: 'center', textShadow: '#000000 -1px 1px 1px'}); myScriptMess[element][e] = createMyElement('div', ''); myLinkWindow[element][e] = createMyElement('div', ''); appendMyElement(myLinkWindow[element][e], myScriptLogo[element][e]); appendMyElement(myLinkWindow[element][e], myScriptMess[element][e]); var childStyles = child.getAttribute('style'); if (childStyles) { childStyles = childStyles.replace('absolute', 'relative'); myLinkWindow[element][e].setAttribute('style', childStyles); styleMyElement(myLinkWindow[element][e], {border: '3px solid #F4F4F4', backgroundColor: 'transparent'}); } else styleMyElement(myLinkWindow[element][e], {width: '100%', height: '100%', border: '3px solid #F4F4F4', backgroundColor: 'transparent'}); styleMyElement(parent, {padding: '0px', height: '100%'}); replaceMyElement(parent, myLinkWindow[element][e], child); videoID = video.match(linkParsers[linkID]['pattern']); videoID = (videoID) ? videoID[1] : null; if (videoID) { videoURL = linkParsers[linkID]['link'] + videoID; if (!option['secure']) videoURL = videoURL.replace(/^https/, 'http'); videoLink = '' + videoURL + ''; styleMyElement(myScriptMess[element][e], {border: '1px solid #F4F4F4', margin: '5px', padding: '5px', backgroundColor: '#FFFFFF', color: '#00C000', textAlign: 'center', fontSize: '16px'}); modifyMyElement(myScriptMess[element][e], 'div', videoLink, false); } else { styleMyElement(myScriptMess[element][e], {border: '1px solid #F4F4F4', margin: '5px', padding: '5px', backgroundColor: '#FFFFFF', color: '#AD0000', textAlign: 'center', fontSize: '16px'}); modifyMyElement(myScriptMess[element][e], 'div', warning, false); } } } } // ==========Websites========== // /* Parsers */ var linkParsers = [ {'source': 'youtube(.com|-nocookie.com)/embed/(videoseries|\\?list)', 'pattern': 'list=(.*?)(&|$)', 'link': 'https://invidious.ggc-project.de/playlist?list='}, {'source': 'youtube(.com|-nocookie.com)/embed/', 'pattern': '/embed/(.*?)(\\?|&|$)', 'link': 'https://invidious.ggc-project.de/watch?v='}, {'source': 'youtube(.com|-nocookie.com)/v/', 'pattern': '/v/(.*?)(\\?|&|$)', 'link': 'https://invidious.ggc-project.de/watch?v='}, {'source': 'dailymotion.com/embed/', 'pattern': '/video/(.*?)$', 'link': 'https://www.dailymotion.com/video/'}, {'source': 'dailymotion.com/swf/(?!video)', 'pattern': '/swf/(.*?)$', 'link': 'https://www.dailymotion.com/video/'}, {'source': 'dailymotion.com/swf/(?=video)', 'pattern': '/video/(.*?)$', 'link': 'https://www.dailymotion.com/video/'}, {'source': 'vimeo.com/video/', 'pattern': '/video/(.*?)(\\?|&|$)', 'link': 'https://vimeo.com/'}, {'source': 'vimeo.com/moogaloop', 'pattern': '/moogaloop.swf\\?clip_id=(.*?)(&|$)', 'link': 'https://vimeo.com/'}, {'source': 'metacafe.com/embed/', 'pattern': '/embed/(.*?)/', 'link': 'https://www.metacafe.com/watch/'}, {'source': 'metacafe.com/fplayer/', 'pattern': '/fplayer/(.*?)/', 'link': 'https://www.metacafe.com/watch/'}, {'source': 'funnyordie.com/embed/', 'pattern': '/embed/(.*?)$', 'link': 'https://www.funnyordie.com/videos/'}, {'source': 'vk.com/video', 'pattern': 'video_ext.php\\?(.*?)$', 'link': 'https://m.vk.com/video_ext.php?'}, {'source': 'hostname=www.twitch.tv', 'pattern': 'channel=(.*?)(&|$)', 'link': 'https://m.twitch.tv/'}, {'source': 'reddit.com/r/', 'pattern': '/r/(.*?)(\\?|&|$)', 'link': 'https://ld.reddit.com/r/'}, {'source': 'twitter.com/', 'pattern': 'twitter.com/(.*?)(\\?|&|$)', 'link': 'https://nitter.net/'}, {'source': 'instagram.com/p/', 'pattern': '/p/(.*?)(\\?|&|$)', 'link': 'https://bibliogram.art/p/'} ]; var iframeElements; var objectElements; var embedElements; function LinkTube() { /* IFrame */ iframeElements = getMyElement(document, 'children', 'iframe'); if (iframeElements.length > 0 ) embedMyLinks('iframe'); /* Object */ objectElements = getMyElement(document, 'children', 'object'); if (objectElements.length > 0 ) embedMyLinks('object'); /* Embed */ embedElements = getMyElement(document, 'children', 'embed'); if (embedElements.length > 0 ) embedMyLinks('embed'); } // ==========Run========== // LinkTube(); page.win.setInterval(function() { if (page.url != page.win.location.href) { page.doc = page.win.document; page.url = page.win.location.href; LinkTube(); } }, 500); })();