YT2Invidio

Point YouTube links to Invidious, Twitter to Nitter, Instagram to Bibliogram, Reddit to Teddit, Medium to Scribe

  1. // ==UserScript==
  2. // @name YT2Invidio
  3. // @namespace de.izzysoft
  4. // @author Izzy
  5. // @description Point YouTube links to Invidious, Twitter to Nitter, Instagram to Bibliogram, Reddit to Teddit, Medium to Scribe
  6. // @license CC BY-NC-SA
  7. // @include *
  8. // @version 1.6.3
  9. // @run-at document-idle
  10. // @grant GM.getValue
  11. // @grant GM.setValue
  12. // @grant GM_getValue
  13. // @grant GM_setValue
  14. // @grant GM_registerMenuCommand
  15. // @grant GM.registerMenuCommand
  16. // @grant GM_openInTab
  17. // @grant GM.openInTab
  18. // @grant unsafeWindow
  19. // @homepageURL https://codeberg.org/izzy/userscripts
  20. // @require https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
  21. // ==/UserScript==
  22.  
  23. // Default Config
  24. const defaultConfig = {
  25. hosts: {invidious: "invidious.snopyta.org", nitter: "nitter.net", bibliogram: "bibliogram.art", teddit: "teddit.net", scribe: "scribe.rip"},
  26. invProxy: 0
  27. };
  28. /*
  29. console.log(defaultConfig.hosts);
  30. console.log(obj.hosts.hasOwnProperty('bibliogram')); // true
  31. */
  32.  
  33. // Get the Invidious instance to use for rewrite
  34. function doRewrite() {
  35. GM.getValue('YT2IConfig',JSON.stringify(defaultConfig)).then(function(result) {
  36. rewriteLinks(result);
  37. });
  38. }
  39. doRewrite();
  40.  
  41. // Do the actual rewrite
  42. function rewriteLinks(config) {
  43. console.log(`Using '${config}' for rewrite`);
  44. var cfg = JSON.parse(config);
  45. var videohost = cfg.hosts.invidious;
  46. var nitterhost = cfg.hosts.nitter;
  47. var bibliogramhost = cfg.hosts.bibliogram;
  48. var teddithost = cfg.hosts.teddit;
  49. var scribehost = cfg.hosts.scribe || 'scribe.rip';
  50. var invProxy = 'local=0';
  51. if ( cfg.invProxy == 1 ) { invProxy = 'local=1'; }
  52. console.log('Invidious: '+videohost+', Params: '+invProxy);
  53. console.log('Nitter: '+nitterhost);
  54. console.log('Bibliogram: '+bibliogramhost);
  55. console.log('Teddit: '+teddithost);
  56. console.log('Scribe: '+scribehost)
  57. // --=[ document links ]=--
  58. console.log('Checking '+document.links.length+' links for YT, Twitter, Insta, Reddit & Co.');
  59. for(var i = 0; i < document.links.length; i++) {
  60. var elem = document.links[i];
  61.  
  62. // Youtube: https://www.youtube.com/watch?v=cRRA2xRRgl8 || https://www.youtube.com/channel/dfqwfhqQ34er || https://www.youtube.com/playlist?list=PLjV3HijScGMynGvjJrvNNd5Q9pPy255dL
  63. // only rewrite if we're not on Invidious already (too keep the "watch this on YouTube" links intact)
  64. if (videohost != '' && elem.href.match(/((www|m)\.)?youtube.com(\/(watch\?v|playlist\?list)=[a-z0-9_-]+)/i)) {
  65. if (location.hostname != videohost) { elem.href='https://'+videohost+RegExp.$3+'&'+invProxy; }
  66. } else if (videohost != '' && elem.href.match(/((www|m)\.)?youtu.be\/([a-z0-9_-]+)/i)) {
  67. if (location.hostname != videohost) { elem.href='https://'+videohost+'/watch?v='+RegExp.$3+'?'+invProxy; }
  68. } else if (videohost != '' && elem.href.match(/((www|m)\.)?youtube.com(\/channel\/[a-z0-9_-]+)/i)) {
  69. if (location.hostname != videohost) { elem.href='https://'+videohost+RegExp.$3+'?'+invProxy; }
  70.  
  71. // Twitter
  72. } else if (nitterhost != '' && elem.href.match(/(mobile\.)?twitter\.com\/([^&#]+)/i)) {
  73. if (location.hostname != nitterhost) elem.href='https://'+nitterhost+'/'+RegExp.$2;
  74. }
  75.  
  76. // Bibliogram
  77. else if (bibliogramhost != '' && elem.href.match(/(www\.)?instagram\.com\/(p|tv)\/([^&#/]+)/i)) { // profile
  78. if (location.hostname != bibliogramhost) {
  79. elem.href = 'https://'+bibliogramhost+'/p/' + RegExp.$3;
  80. }
  81. } else if (bibliogramhost != '' && elem.href.match(/(www\.)?instagram\.com\/([^&#/]+)/i)) { // image or video
  82. if (location.hostname != bibliogramhost) {
  83. elem.href = 'https://'+bibliogramhost+'/u/' + RegExp.$2;
  84. }
  85. }
  86.  
  87. // Teddit
  88. else if (teddithost != '' && elem.href.match(/((www|old)\.)?reddit.com\/(.*)/i)) {
  89. if (location.hostname != teddithost) { elem.href = 'https://'+teddithost+'/'+RegExp.$3; }
  90. }
  91. else if (teddithost != '' && elem.href.match(/(r.nf)\/(.*)/i)) {
  92. if (location.hostname != teddithost) { elem.href = 'https://'+teddithost+'/'+RegExp.$2; }
  93. }
  94.  
  95. // Scribe
  96. else if (scribehost != '' && elem.href.match(/(www\.)?medium\.com\/([^&#]+)/i)) {
  97. if (location.hostname != scribehost) elem.href='https://'+scribehost+'/'+RegExp.$2;
  98. }
  99.  
  100. }
  101.  
  102. // --=[ embedded links ]=--
  103. // based on https://gf.qytechs.cn/en/scripts/394841-youtube-to-invidio-us-embed
  104. if (videohost != '') {
  105. var src, dataSrc, iframes = document.getElementsByTagName('iframe');
  106. var embProxy
  107. console.log('Checking '+iframes.length+' frames for embedded videos');
  108. for (var i = 0; i < iframes.length; i++) {
  109. src = iframes[i].getAttribute('src');
  110. dataSrc = false;
  111. if ( src == null ) { src = iframes[i].getAttribute('data-s9e-mediaembed-src'); dataSrc = true; }
  112. if ( src == null ) continue;
  113. if ( src.match(/((www|m)\.)?youtube.com(\/(watch\?v|playlist\?list)=[a-z0-9_-]+)/i) || src.match(/((www|m)\.)?youtube.com(\/(channel|embed)\/[a-z0-9_-]+)/i) ) {
  114. if ( RegExp.$4 == 'channel' || RegExp.$4 == 'embed' ) { embProxy = '?'+invProxy; }
  115. else { embProxy = '&'+invProxy; }
  116. if ( dataSrc ) {
  117. iframes[i].setAttribute('data-s9e-mediaembed-src','https://'+videohost+RegExp.$3+embProxy);
  118. } else {
  119. iframes[i].setAttribute('src','https://'+videohost+RegExp.$3+embProxy);
  120. }
  121. // iframes[i].setAttribute('style', 'min-height:100%; min-width:100%;');
  122. iframes[i].setAttribute('frameborder', '0');
  123. iframes[i].setAttribute('allowfullscreen', '1');
  124. }
  125. }
  126. }
  127.  
  128. console.log('Rewrite done.');
  129. }
  130.  
  131.  
  132. // Give the user the possibility to set a different preferred instance
  133. // A list of available instances can be found at
  134. // https://github.com/omarroth/invidious/wiki/Invidious-Instances
  135. // https://github.com/zedeus/nitter/wiki/Instances
  136. // https://github.com/cloudrac3r/bibliogram/wiki/Instances
  137. async function setInvidiousInstance() {
  138. let cfgs = await GM.getValue('YT2IConfig',JSON.stringify(defaultConfig));
  139. cfg = JSON.parse(cfgs);
  140. var vhost = prompt('Set Invidious instance to:', cfg.hosts.invidious);
  141. if ( vhost == '' || vhost.match(/^(https?)?:?[\/]*(.+?)(\/.*)?$/) ) {
  142. if ( vhost == '' ) { cfg.hosts.invidious = ''; }
  143. else { cfg.hosts.invidious = RegExp.$2; }
  144. GM.setValue('YT2IConfig',JSON.stringify(cfg));
  145. }
  146. }
  147. async function setNitterInstance() {
  148. let cfgs = await GM.getValue('YT2IConfig',JSON.stringify(defaultConfig));
  149. cfg = JSON.parse(cfgs);
  150. var vhost = prompt('Set Nitter instance to:', cfg.hosts.nitter);
  151. if ( vhost == '' || vhost.match(/^(https?)?:?[\/]*(.+?)(\/.*)?$/) ) {
  152. if ( vhost == '' ) { cfg.hosts.nitter = ''; }
  153. else { cfg.hosts.nitter = RegExp.$2; }
  154. GM.setValue('YT2IConfig',JSON.stringify(cfg));
  155. }
  156. }
  157. async function setBibliogramInstance() {
  158. let cfgs = await GM.getValue('YT2IConfig',JSON.stringify(defaultConfig));
  159. cfg = JSON.parse(cfgs);
  160. var vhost = prompt('Set Bibliogram instance to:', cfg.hosts.bibliogram);
  161. if ( vhost == '' || vhost.match(/^(https?)?:?[\/]*(.+?)(\/.*)?$/) ) {
  162. if ( vhost == '' ) { cfg.hosts.bibliogram = ''; }
  163. else { cfg.hosts.bibliogram = RegExp.$2; }
  164. GM.setValue('YT2IConfig',JSON.stringify(cfg));
  165. }
  166. }
  167. async function toggleInvidiousProxy() {
  168. let cfgs = await GM.getValue('YT2IConfig',JSON.stringify(defaultConfig));
  169. cfg = JSON.parse(cfgs);
  170. if ( cfg.invProxy == 1 ) { cfg.invProxy = 0; console.log('Invidious proxying turned off.'); }
  171. else { cfg.invProxy = 1; console.log('Invidious proxying turned on.'); }
  172. GM.setValue('YT2IConfig',JSON.stringify(cfg));
  173. }
  174. async function setTedditInstance() {
  175. let cfgs = await GM.getValue('YT2IConfig',JSON.stringify(defaultConfig));
  176. cfg = JSON.parse(cfgs);
  177. var vhost = prompt('Set Teddit instance to:', cfg.hosts.teddit);
  178. if ( vhost == '' || vhost.match(/^(https?)?:?[\/]*(.+?)(\/.*)?$/) ) {
  179. if (vhost=='') { cfg.hosts.teddit = ''; }
  180. else { cfg.hosts.teddit = RegExp.$2; }
  181. GM.setValue('YT2IConfig',JSON.stringify(cfg));
  182. }
  183. }
  184. async function setScribeInstance() {
  185. let cfgs = await GM.getValue('YT2IConfig',JSON.stringify(defaultConfig));
  186. cfg = JSON.parse(cfgs);
  187. var vhost = prompt('Set Scribe instance to:', cfg.hosts.scribe);
  188. if ( vhost == '' || vhost.match(/^(https?)?:?[\/]*(.+?)(\/.*)?$/) ) {
  189. if (vhost=='') { cfg.hosts.scribe = ''; }
  190. else { cfg.hosts.scribe = RegExp.$2; }
  191. GM.setValue('YT2IConfig',JSON.stringify(cfg));
  192. }
  193. }
  194.  
  195. // open tab with instance list from Invidious/Nitter/Bibliogram/Teddit wiki
  196. function openInvidiousList() {
  197. GM.openInTab('https://github.com/iv-org/documentation/blob/master/Invidious-Instances.md', { active: true, insert: true });
  198. }
  199. function openNitterList() {
  200. GM.openInTab('https://github.com/zedeus/nitter/wiki/Instances', { active: true, insert: true });
  201. }
  202. function openBibliogramList() {
  203. GM.openInTab('https://git.sr.ht/~cadence/bibliogram-docs/tree/master/docs/Instances.md', { active: true, insert: true });
  204. }
  205. function openTedditList() {
  206. GM.openInTab('https://codeberg.org/teddit/teddit#instances', { active: true, insert: true });
  207. }
  208.  
  209. if ( location.href != 'https://duckduckgo.com/post3.html' ) { // somehow this is called from within a search and causes our script to run again
  210. GM.registerMenuCommand('Set Invidious instance',setInvidiousInstance);
  211. GM.registerMenuCommand('Show list of known Invidious instances', openInvidiousList );
  212. GM.registerMenuCommand('Toggle Invidious proxy state', toggleInvidiousProxy);
  213. GM.registerMenuCommand('Set Nitter instance',setNitterInstance);
  214. GM.registerMenuCommand('Show list of known Nitter instances', openNitterList );
  215. GM.registerMenuCommand('Set Bibliogram instance',setBibliogramInstance);
  216. GM.registerMenuCommand('Show list of known Bibliogram instances', openBibliogramList );
  217. GM.registerMenuCommand('Set Teddit instance',setTedditInstance);
  218. GM.registerMenuCommand('Show list of known Teddit instances', openTedditList );
  219. GM.registerMenuCommand('Set Scribe instance',setScribeInstance);
  220.  
  221. GM.registerMenuCommand('Rewrite now', doRewrite);
  222. console.log('registered menus.');
  223. }
  224.  
  225. // register keyboard shortcut Alt+Y to trigger rewrite
  226. document.onkeyup=function(e) {
  227. var e = e || window.event; // for IE to cover IEs window event-object
  228. if(e.altKey && e.which == 89) {
  229. doRewrite();
  230. return false;
  231. }
  232. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址