Replaces an embedded video with a link to the video page.
- // ==UserScript==
- // @name LinkTube
- // @version 2017.11.23
- // @description Replaces an embedded video with a link to the video page.
- // @author sebaro
- // @namespace http://isebaro.com/linktube
- // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
- // @icon https://raw.githubusercontent.com/sebaro/linktube/master/linktube.png
- // @include *
- // @grant GM_xmlhttpRequest
- // @grant GM.xmlHttpRequest
- // ==/UserScript==
- /*
- Copyright (C) 2011 - 2017 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 <http://www.gnu.org/licenses/>.
- Website: http://isebaro.com/linktube
- Contact: http://isebaro.com/contact
- */
- (function() {
- // ==========Variables========== //
- // Userscript
- var userscript = 'LinkTube';
- // Contact
- var contact = 'http://isebaro.com/contact';
- // Warning
- var warning = 'Couldn\'t get the video link. Please report it <a href="' + contact + '">here</a>.';
- // 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;
- 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 YouTube (url, target) {
- var ytVideoTitle;
- var ytVideoLength;
- function ytVideoInfo(ytPageSource) {
- /* Get Video Title */
- ytVideoTitle = ytPageSource.match(/"title":"(.*?)","lengthSeconds"/);
- ytVideoTitle = (ytVideoTitle) ? ytVideoTitle[1] : null;
- if (!ytVideoTitle) {
- ytVideoTitle = ytPageSource.match(/document.title\s*=\s*"(.*?)"/);
- ytVideoTitle = (ytVideoTitle) ? ytVideoTitle[1] : null;
- }
- if (!ytVideoTitle) {
- ytVideoTitle = ytPageSource.match(/meta\s+itemprop="name"\s+content="(.*?)"/);
- ytVideoTitle = (ytVideoTitle) ? ytVideoTitle[1] : null;
- }
- if (!ytVideoTitle) {
- ytVideoTitle = ytPageSource.match(/meta\s+property="og:title"\s+content="(.*?)"/);
- ytVideoTitle = (ytVideoTitle) ? ytVideoTitle[1] : null;
- }
- if (ytVideoTitle) {
- ytVideoTitle = ytVideoTitle.replace(/"/g, '\'').replace(/"/g, '\'').replace(/"/g, '\'');
- ytVideoTitle = ytVideoTitle.replace(/'/g, '\'').replace(/'/g, '\'');
- ytVideoTitle = ytVideoTitle.replace(/&/g, 'and').replace(/&/g, 'and');
- ytVideoTitle = ytVideoTitle.replace(/\?/g, '').replace(/[#:\*]/g, '-').replace(/\//g, '-');
- ytVideoTitle = ytVideoTitle.replace(/^\s+|\s+$/, '').replace(/\.+$/g, '');
- ytVideoTitle = ytVideoTitle.replace(/^YouTube\s-\s/, '');
- }
- /* Get Video Length */
- ytVideoLength = ytPageSource.match(/"lengthSeconds":"(.*?)"/);
- ytVideoLength = (ytVideoLength) ? ytVideoLength[1] : null;
- if (ytVideoLength) {
- ytVideoLength = new Date(ytVideoLength * 1000).toISOString().substr(11, 8).replace(/00:0?/, '');
- }
- else {
- ytVideoLength = ytPageSource.match(/meta\s+itemprop="duration"\s+content="(.*?)"/);
- ytVideoLength = (ytVideoLength) ? ytVideoLength[1].replace('PT', '').replace('M', ':').replace('S', '') : null;
- }
- }
- try {
- GM.xmlHttpRequest({
- method: 'GET',
- url: url,
- onload: function(response) {
- if (response.readyState === 4 && response.status === 200) {
- ytVideoInfo(response.responseText);
- ytVideoList = ytVideoTitle + ' (' + ytVideoLength + ')<br>' + '<a href="' + url + '">' + url + '</a>';
- modifyMyElement (target, 'div', ytVideoList, false);
- }
- else {
- ytVideoList = '<a href="' + url + '">' + url + '</a>';
- modifyMyElement (target, 'div', ytVideoList, false);
- }
- }
- });
- }
- catch(e) {
- try {
- GM_xmlhttpRequest({
- method: 'GET',
- url: url,
- onload: function(response) {
- if (response.readyState === 4 && response.status === 200) {
- ytVideoInfo(response.responseText);
- ytVideoList = ytVideoTitle + ' (' + ytVideoLength + ')<br>' + '<a href="' + url + '">' + url + '</a>';
- modifyMyElement (target, 'div', ytVideoList, false);
- }
- else {
- ytVideoList = '<a href="' + url + '">' + url + '</a>';
- modifyMyElement (target, 'div', ytVideoList, false);
- }
- }
- });
- }
- catch(e) {
- ytVideoList = '<a href="' + url + '">' + url + '</a>';
- modifyMyElement (target, 'div', ytVideoList, false);
- }
- }
- }
- 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') {
- 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], {backgroundColor: '#F4F4F4'});
- }
- else styleMyElement (myLinkWindow[element][e], {width: '100%', height: '100%', backgroundColor: '#F4F4F4'});
- 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');
- styleMyElement (myScriptMess[element][e], {border: '3px solid #F4F4F4', margin: '0px auto', padding: '10px', backgroundColor: '#FFFFFF', color: '#00C000', textAlign: 'center', fontSize: '16px'});
- if (videoURL.indexOf('youtube.com') != -1) {
- YouTube(videoURL, myScriptMess[element][e]);
- }
- else {
- videoLink = '<a href="' + videoURL + '">' + videoURL + '</a>';
- modifyMyElement (myScriptMess[element][e], 'div', videoLink, false);
- }
- }
- else {
- styleMyElement (myScriptMess[element][e], {border: '3px solid #F4F4F4', margin: '0px auto', padding: '10px', 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://www.youtube.com/playlist?list='},
- {'source': 'youtube(.com|-nocookie.com)/embed/', 'pattern': '/embed/(.*?)(\\?|&|$)', 'link': 'https://www.youtube.com/watch?v='},
- {'source': 'youtube(.com|-nocookie.com)/v/', 'pattern': '/v/(.*?)(\\?|&|$)', 'link': 'https://www.youtube.com/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': 'http://vk.com/video_ext.php?'},
- {'source': 'hostname=www.twitch.tv', 'pattern': 'channel=(.*?)(&|$)', 'link': 'http://www.twitch.tv/'}
- ];
- /* IFrame */
- var iframeElements = getMyElement (document, 'children', 'iframe');
- if (iframeElements.length > 0 ) embedMyLinks ('iframe');
- /* Object */
- var objectElements = getMyElement (document, 'children', 'object');
- if (objectElements.length > 0 ) embedMyLinks ('object');
- /* Embed */
- var embedElements = getMyElement (document, 'children', 'embed');
- if (embedElements.length > 0 ) embedMyLinks ('embed');
- })();