LinkTube

Replaces an embedded video with a link to the video page.

当前为 2016-08-29 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name LinkTube
  3. // @version 2016.08.26
  4. // @description Replaces an embedded video with a link to the video page.
  5. // @author sebaro
  6. // @namespace http://isebaro.com/linktube
  7. // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
  8. // @icon https://raw.githubusercontent.com/sebaro/linktube/master/linktube.png
  9. // @include *
  10. // @grant GM_xmlhttpRequest
  11. // ==/UserScript==
  12.  
  13.  
  14. /*
  15.  
  16. Copyright (C) 2011 - 2016 Sebastian Luncan
  17.  
  18. This program is free software: you can redistribute it and/or modify
  19. it under the terms of the GNU General Public License as published by
  20. the Free Software Foundation, either version 3 of the License, or
  21. (at your option) any later version.
  22.  
  23. This program is distributed in the hope that it will be useful,
  24. but WITHOUT ANY WARRANTY; without even the implied warranty of
  25. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  26. GNU General Public License for more details.
  27.  
  28. You should have received a copy of the GNU General Public License
  29. along with this program. If not, see <http://www.gnu.org/licenses/>.
  30.  
  31. Website: http://isebaro.com/linktube
  32. Contact: http://isebaro.com/contact
  33.  
  34. */
  35.  
  36.  
  37. (function() {
  38.  
  39.  
  40. // ==========Variables========== //
  41.  
  42. // Userscript
  43. var userscript = 'LinkTube';
  44.  
  45. // Contact
  46. var contact = 'http://isebaro.com/contact/?ln=en&sb=linktube';
  47.  
  48. // Warning
  49. var warning = 'Couldn\'t get the video link. Please report it <a href="' + contact + '">here</a>.';
  50.  
  51. // Options
  52. var option = {'secure': true};
  53.  
  54.  
  55. // ==========Fixes========== //
  56.  
  57. // Don't run on frames or iframes
  58. if (window.top != window.self) return;
  59.  
  60.  
  61. // ==========Functions========== //
  62.  
  63. function createMyElement (type, content) {
  64. var obj = document.createElement(type);
  65. if (type == 'div') {
  66. if (content) obj.innerHTML = content;
  67. }
  68. return obj;
  69. }
  70.  
  71. function getMyElement (element, get, tag) {
  72. var obj;
  73. if (get == 'parent') obj = element.parentNode;
  74. else if (get == 'source') obj = element.src;
  75. else if (get == 'name') obj = element.name;
  76. else if (get == 'value') obj = element.value;
  77. else if (get == 'children') obj = element.getElementsByTagName(tag);
  78. return obj;
  79. }
  80.  
  81. function modifyMyElement (obj, type, content, clear) {
  82. if (type == 'div') {
  83. if (content) obj.innerHTML = content;
  84. }
  85. if (clear) {
  86. if (obj.hasChildNodes()) {
  87. while (obj.childNodes.length >= 1) {
  88. obj.removeChild(obj.firstChild);
  89. }
  90. }
  91. }
  92. }
  93.  
  94. function styleMyElement (obj, styles) {
  95. for (var property in styles) {
  96. if (styles.hasOwnProperty(property)) obj.style[property] = styles[property];
  97. }
  98. }
  99.  
  100. function appendMyElement (parent, child) {
  101. if (parent == 'body') document.body.appendChild(child);
  102. else parent.appendChild(child);
  103. }
  104.  
  105. function removeMyElement (parent, child) {
  106. if (parent == 'body') document.body.removeChild(child);
  107. else parent.removeChild(child);
  108. }
  109.  
  110. function replaceMyElement (parent, orphan, child) {
  111. parent.replaceChild(orphan, child);
  112. }
  113.  
  114. function cleanMyContent (content, unesc) {
  115. var myNewContent = content;
  116. if (unesc) myNewContent = unescape (myNewContent);
  117. myNewContent = myNewContent.replace (/\\u0025/g,'%');
  118. myNewContent = myNewContent.replace (/\\u0026/g,'&');
  119. myNewContent = myNewContent.replace (/\\/g,'');
  120. myNewContent = myNewContent.replace (/\n/g,'');
  121. return myNewContent;
  122. }
  123.  
  124. function getMyContent (url, pattern, clean) {
  125. var myPageContent, myVideosParse, myVideosContent;
  126. var xmlHTTP = GM_xmlhttpRequest({
  127. method: 'GET',
  128. url: url,
  129. synchronous: true
  130. });
  131. if (pattern == 'TEXT') {
  132. myVideosContent = xmlHTTP.responseText;
  133. }
  134. else {
  135. myPageContent = xmlHTTP.responseText;
  136. if (clean) myPageContent = cleanMyContent (myPageContent, true);
  137. myVideosParse = myPageContent.match (pattern);
  138. myVideosContent = (myVideosParse) ? myVideosParse[1] : null;
  139. }
  140. return myVideosContent;
  141. }
  142.  
  143. function YouTube (url, target) {
  144.  
  145. var ytVideoTitle;
  146. var ytVideoLength;
  147. GM_xmlhttpRequest({
  148. method: 'GET',
  149. url: url,
  150. onload: function(response) {
  151. if (response.readyState === 4 && response.status === 200) {
  152.  
  153. /* Get Page Source */
  154. ytPageSource = response.responseText;
  155.  
  156. /* Get Video Title */
  157. ytVideoTitle = ytPageSource.match(/meta\s+itemprop="name"\s+content="(.*?)"/);
  158. ytVideoTitle = (ytVideoTitle) ? ytVideoTitle[1] : null;
  159. if (!ytVideoTitle) {
  160. ytVideoTitle = ytPageSource.match(/meta\s+property="og:title"\s+content="(.*?)"/);
  161. ytVideoTitle = (ytVideoTitle) ? ytVideoTitle[1] : null;
  162. }
  163. if (ytVideoTitle) {
  164. ytVideoTitle = ytVideoTitle.replace(/&quot;/g, '\'').replace(/&#34;/g, '\'').replace(/"/g, '\'');
  165. ytVideoTitle = ytVideoTitle.replace(/&#39;/g, '\'').replace(/'/g, '\'');
  166. ytVideoTitle = ytVideoTitle.replace(/&amp;/g, 'and').replace(/&/g, 'and');
  167. ytVideoTitle = ytVideoTitle.replace(/\?/g, '').replace(/[#:\*]/g, '-').replace(/\//g, '-');
  168. ytVideoTitle = ytVideoTitle.replace(/^\s+|\s+$/, '').replace(/\.+$/g, '');
  169. ytVideoTitle = ytVideoTitle.replace(/^YouTube\s-\s/, '');
  170. }
  171.  
  172. /* Get Video Length */
  173. ytVideoLength = ytPageSource.match(/meta\s+itemprop="duration"\s+content="(.*?)"/);
  174. ytVideoLength = (ytVideoLength) ? ytVideoLength[1].replace('PT', '').replace('M', ':').replace('S', '') : null;
  175.  
  176. ytVideoList = ytVideoTitle + ' (' + ytVideoLength + ')<br>' + '<a href="' + url + '">' + url + '</a>';
  177. modifyMyElement (target, 'div', ytVideoList, false);
  178. }
  179. else {
  180. ytVideoList = '<a href="' + url + '">' + url + '</a>';
  181. modifyMyElement (target, 'div', ytVideoList, false);
  182. }
  183. }
  184. });
  185. }
  186.  
  187. function embedMyLinks (element) {
  188. var elements;
  189. if (element == 'iframe') elements = iframeElements;
  190. else if (element == 'object') elements = objectElements;
  191. else if (element == 'embed') elements = embedElements;
  192. var child, parent, video, param, name;
  193. var foundSite;
  194. var linkID, videoID, videoLink, videoURL;
  195. var myScriptLogo = [];
  196. myScriptLogo[element] = [];
  197. var myScriptMess = [];
  198. myScriptMess[element] = [];
  199. var myLinkWindow = [];
  200. myLinkWindow[element] = [];
  201. for (var e = elements.length - 1; e >= 0; e--) {
  202. foundSite = false;
  203. child = elements[e];
  204. parent = getMyElement (child, 'parent', '');
  205. if (element == 'iframe' || element == 'embed') {
  206. video = getMyElement (child, 'source', '');
  207. }
  208. else if (element == 'object') {
  209. params = getMyElement (child, 'children', 'param');
  210. for (var p = 0; p < params.length; p++) {
  211. name = getMyElement (params[p], 'name', '');
  212. if (name == 'movie' || name == 'src') {
  213. video = getMyElement (params[p], 'value', '');
  214. if (!video) video = getMyElement (params[p], 'source', '');
  215. }
  216. }
  217. }
  218. if (video) {
  219. for (var l = 0; l < linkParsers.length; l++) {
  220. if (video.match(linkParsers[l]['source'])) {
  221. foundSite = true;
  222. linkID = l;
  223. break;
  224. }
  225. }
  226. }
  227. if (foundSite) {
  228. myScriptLogo[element][e] = createMyElement ('div', userscript);
  229. styleMyElement (myScriptLogo[element][e], {margin: '0px auto', padding: '10px', color: '#666666', fontSize: '20px', textAlign: 'center', textShadow: '#FFFFFF -1px -1px 2px'});
  230. myScriptMess[element][e] = createMyElement ('div', '');
  231. myLinkWindow[element][e] = createMyElement ('div', '');
  232. appendMyElement (myLinkWindow[element][e], myScriptLogo[element][e]);
  233. appendMyElement (myLinkWindow[element][e], myScriptMess[element][e]);
  234. var childStyles = child.getAttribute('style');
  235. if (childStyles) {
  236. myLinkWindow[element][e].setAttribute('style', childStyles);
  237. styleMyElement (myLinkWindow[element][e], {backgroundColor: '#F4F4F4'});
  238. }
  239. else styleMyElement (myLinkWindow[element][e], {width: '100%', height: '100%', backgroundColor: '#F4F4F4'});
  240. styleMyElement (parent, {padding: '0px', height: '100%'});
  241. replaceMyElement(parent, myLinkWindow[element][e], child);
  242. videoID = video.match(linkParsers[linkID]['pattern']);
  243. videoID = (videoID) ? videoID[1] : null;
  244. if (videoID) {
  245. videoURL = linkParsers[linkID]['link'] + videoID;
  246. if (!option['secure']) videoURL = videoURL.replace(/^https/, 'http');
  247. styleMyElement (myScriptMess[element][e], {border: '3px solid #F4F4F4', margin: '5px auto 5px auto', padding: '10px', backgroundColor: '#FFFFFF', color: '#00C000', textAlign: 'center', fontSize: '16px'});
  248. if (videoURL.indexOf('youtube.com') != -1) {
  249. YouTube(videoURL, myScriptMess[element][e]);
  250. }
  251. else {
  252. videoLink = '<a href="' + videoURL + '">' + videoURL + '</a>';
  253. modifyMyElement (myScriptMess[element][e], 'div', videoLink, false);
  254. }
  255. }
  256. else {
  257. styleMyElement (myScriptMess[element][e], {border: '3px solid #F4F4F4', margin: '5px auto 5px auto', padding: '10px', backgroundColor: '#FFFFFF', color: '#AD0000', textAlign: 'center', fontSize: '16px'});
  258. modifyMyElement (myScriptMess[element][e], 'div', warning, false);
  259. }
  260. }
  261. }
  262.  
  263. }
  264.  
  265.  
  266. // ==========Websites========== //
  267.  
  268. /* Parsers */
  269. var linkParsers = [
  270. {'source': 'youtube(.com|-nocookie.com)/embed/(videoseries|\\?list)', 'pattern': 'list=(.*?)(&|$)', 'link': 'https://youtube.com/playlist?list='},
  271. {'source': 'youtube(.com|-nocookie.com)/embed/', 'pattern': '/embed/(.*?)(\\?|&|$)', 'link': 'https://youtube.com/watch?v='},
  272. {'source': 'youtube(.com|-nocookie.com)/v/', 'pattern': '/v/(.*?)(\\?|&|$)', 'link': 'https://youtube.com/watch?v='},
  273. {'source': 'dailymotion.com/embed/', 'pattern': '/video/(.*?)$', 'link': 'https://dailymotion.com/video/'},
  274. {'source': 'dailymotion.com/swf/(?!video)', 'pattern': '/swf/(.*?)$', 'link': 'https://dailymotion.com/video/'},
  275. {'source': 'dailymotion.com/swf/(?=video)', 'pattern': '/video/(.*?)$', 'link': 'https://dailymotion.com/video/'},
  276. {'source': 'vimeo.com/video/', 'pattern': '/video/(.*?)(\\?|&|$)', 'link': 'https://vimeo.com/'},
  277. {'source': 'vimeo.com/moogaloop', 'pattern': '/moogaloop.swf\\?clip_id=(.*?)(&|$)', 'link': 'https://vimeo.com/'},
  278. {'source': 'metacafe.com/embed/', 'pattern': '/embed/(.*?)/', 'link': 'https://metacafe.com/watch/'},
  279. {'source': 'metacafe.com/fplayer/', 'pattern': '/fplayer/(.*?)/', 'link': 'https://metacafe.com/watch/'},
  280. {'source': 'funnyordie.com/embed/', 'pattern': '/embed/(.*?)$', 'link': 'https://funnyordie.com/videos/'},
  281. {'source': 'blip.tv/play/', 'pattern': '/play/(.*?)$', 'link': 'https://blip.tv/players/episode/'},
  282. {'source': 'vk.com/video', 'pattern': 'video_ext.php\\?(.*?)$', 'link': 'http://vk.com/video_ext.php?'},
  283. {'source': 'hostname=www.twitch.tv', 'pattern': 'channel=(.*?)(&|$)', 'link': 'http://www.twitch.tv/'}
  284. ];
  285.  
  286. /* IFrame */
  287. var iframeElements = getMyElement (document, 'children', 'iframe');
  288. if (iframeElements.length > 0 ) embedMyLinks ('iframe');
  289.  
  290. /* Object */
  291. var objectElements = getMyElement (document, 'children', 'object');
  292. if (objectElements.length > 0 ) embedMyLinks ('object');
  293.  
  294. /* Embed */
  295. var embedElements = getMyElement (document, 'children', 'embed');
  296. if (embedElements.length > 0 ) embedMyLinks ('embed');
  297.  
  298.  
  299. })();