您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Display download (source) links for Vimeo videos
// ==UserScript== // @name Download Vimeo // @version 1.0.1 // @description Display download (source) links for Vimeo videos // @namespace bp // @author Benjamin Philipp <dev [at - please don't spam] benjamin-philipp.com> // @include /^(https?:\/\/(www\.)?vimeo\.[a-zA-Z]{2,10}\/\d+([\/?#].*)?)|(https?:\/\/player\.vimeo\.com\/video\/\d+([\/?#].*)?)$/ // @require http://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js // @run-at document-body // @grant GM_xmlhttpRequest // @connect * // ==/UserScript== /* globals $, GM_info, GM_xmlhttpRequest, debugging, waitFor */ var maxTries=40; // try to find the config script or insert the links a maximum of n times var interval=500; // interval in ms before the above actions are tried again, if they fail. var rex = { embed: /^https?:\/\/player\.vimeo\.com\/video\/\d+([\/?#].*)?$/i, onsite: /^https?:\/\/(www\.)?vimeo\.[a-zA-Z]{2,10}\/\d+([\/?#].*)?$/i }; // RegEx to check which kind of site we're on: embedded video page or main video page on Vimeo? const prefix = GM_info.script.name; function main(){ $("head").append( `<style> .vp-controls .bpDownloads{ /* opacity: 0.3; */ transition: opacity 0.5s; font-size: 12pt; } .vp-controls .bpDownloads:hover{ opacity: 1; } .vp-controls .bpDownloads h3{ color: #ccc; background: #333; display: block; margin: 0; padding: 6px 10px; font-size: 15px; border-radius: 3px; transition: all 0.5s; } .vp-controls .bpDownloads:hover h3{ padding: 10px; border-radius: 0; } .vp-controls .bpDownloads a{ background: #333; color: #ddd; color: #fff; text-decoration: none; display: block; margin: 0; padding: 0 10px; height: 0; transition: all 0.5s; box-sizing: content-box; overflow: hidden; } .vp-controls .bpDownloads:hover a{ height: 1rem; padding: 10px; } .vp-controls .bpDownloads a:hover{ background: #000; } </style>`); var isEmbed = rex.embed.test(location.href); if(isEmbed){ log("is embedded vimeo"); getScript(function(s){ // log("callback", s); var links = s.request.files.progressive; links.sort(function(a,b){return a.height - b.height;}); // log(links); insertLinks(links, "#player"); }); } else{ log("is on vimeo site"); waitFor("#main .player[data-config-url]", function(o){ o.each(function(){ var player = $(this); var configUrl = player.attr("data-config-url"); log("Config URL:", configUrl); GM_xmlhttpRequest({ url: configUrl, method: "GET", timeout: 15000, onload: function(res){ // log("got:", [res.responseText], res); var cfg = JSON.parse(res.responseText); var links = cfg.request.files.progressive; links.sort(function(a,b){return a.height - b.height;}); // log(links); insertLinks(links, player); }, onerror: function(res){ log({error: "Error loading page", page: configUrl}); }, ontimeout: function(res){ log({error: "Connection timed out", page: configUrl}); } }); }); }); } } function insertLinks(links, player){ var str = ""; for(let l of links){ str += "<a href='" + l.url + "'><b>" + l.quality + " " + l.mime + "</b> (" + l.width + "x" + l.height + ")</a>"; } str = "<div class='bpDownloads'><h3>Download</h3>" + str + "</div>"; // log(str); makeSureIsInserted(str, ".bpDownloads", player, ".vp-controls-wrapper .vp-controls"); } function makeSureIsInserted(o, sel, container, targetSel=false, tries=0){ var findIn = document; var target = container; if(targetSel){ findIn = $(container); target = targetSel; } waitFor({sel: target, findIn: findIn, cb: function(){ var exist=$(target).children(sel); if(!exist || exist.length<=0){ // log("not in target, insert", exist); $(target).append(o); } if(tries<maxTries) setTimeout(function(){ makeSureIsInserted(o, sel, container, targetSel, tries+1); }, interval); }, cbFail: function(){log("Failed to find target for insertion");}}); } function getScript(cb, tries=0){ var scripts = $("body>script"); log("try getting config script", scripts); var gotit=false; if(scripts && scripts.length>=1){ scripts.each(function(){ // log(this); var str = $(this).html(); var rex = /var\s+config\s*=\s*(\{.*?"files"\s*:.*?"progressive"\s*:.+?\.mp4.+?\})\s*?;/i; var m = str.match(rex); if(m && m.length>=2){ // log("matches config"); // log(m[1]); var cfg = JSON.parse(m[1]); //eval(m[1]); gotit=true; return cb(cfg); } }); } if(gotit) return; if(tries>maxTries) return log("Could not get script"); // log("will retry"); setTimeout(function(){ getScript(cb, tries+1); }, interval); } function parseSources(s){ } function log(...args){ if("undefined" != typeof(prefix) && !!prefix) args = [prefix + ":", ...args]; if("undefined" != typeof(debugging) && !!debugging) args = [...args, new Error().stack.replace(/^\s*(Error|Stack trace):?\n/gi, "").replace(/^([^\n]*\n)/, "\n")]; console.log(...args); } // UGH, why must GreasyFork block custom @includes >.< class eleWaiter{ constructor(sel, cb, cbFail=null, findIn="document", delay=500, maxTries=50, alwaysOn=false, autoStart=true, debug = false){ this.sel = ""; this.cb = null; this.cbFail = null; this.findIn = "document"; this.delay = 500; this.maxTries = 50; this.alwaysOn = false; this.autoStart = true; this.debug = false; this.__running = false; this.__tries = 0; this.__timer = 0; this.__jqo = {}; if(typeof sel == "object"){ // log("got object"); Object.assign(this, sel); } else{ this.sel = sel; this.cb = cb; if(cbFail!== undefined || cbFail!== null) this.cbFail = cbFail; if(findIn!== undefined || findIn!== null) this.findIn = findIn; this.delay = delay; this.maxTries = maxTries; this.alwaysOn = alwaysOn; this.autoStart = autoStart; this.debug = debug; } if(this.debug){ if(typeof this.debug != "object"){ this.debug = { prefix: this.debug + " ", level: 1 }; } else{ if(!this.debug.prefix) this.debug.prefix = ""; else this.debug.prefix += " "; if(!this.debug.level) this.debug.level = 1; } } // this.log(this.cb); this.log(this); if(this.autoStart) this.__wait(); } log(...args){ if(!this.debug) return; if(typeof args == "object" && args.length>=2 && typeof args[args.length-1] == "string" && args[args.length-1].toLowerCase().indexOf("loglevel:")===0){ var level = args[args.length-1].substr(9)*1; if(level>this.debug.level){ return; } args.pop(); } console.log(this.debug.prefix + "EleWaiter:", ...args); } start(){ if(!this.__running){ this.log("Start waiting", this.findIn, this.sel); this.__wait(); } } stop(){ clearTimeout(this.__timer); this.__running = false; } __wait(){ // if(!this.findIn) // this.findIn = document; if(this.findIn == "document" && !!document) this.findIn = document; this.__running = true; if(this.maxTries!=-1) this.__tries++; var triesLeft = this.alwaysOn?1:(this.maxTries - this.__tries); this.log("tries left:", triesLeft, "loglevel:3"); this.__jqo = $(this.findIn).find(this.sel); if(this.__jqo.length<=0){ if(this.debug && this.debug.level>2 || !this.alwaysOn) this.log("Not found: " + this.sel); if(triesLeft!==0){ this.__timer = setTimeout(function(){this.__wait();}.bind(this), this.delay); } else this.__result(false); return; } this.__result(this.__jqo); if(this.alwaysOn){ this.log("Always on, repeat", "loglevel:3"); this.__timer = setTimeout(function(){this.__wait();}.bind(this), this.delay); } } __result(success=false){ if(this.debug.level>2 || !this.alwaysOn) this.log("Result:", success); this.__running = false; if(success){ if(this.cb!==undefined && typeof this.cb == "function") this.cb(this.__jqo); else console.log("Warning: callback cb not function", this.cb); } else{ if(this.cbFail!==undefined && typeof this.cbFail == "function") this.cbFail(this.__jqo); } } } if("undefined" === typeof eleWaiters){ // jshint ignore:line var eleWaiters ={}; // jshint ignore:line } function waitFor(sel, cb, cbFail=null, findIn="document", delay=500, maxTries=50, alwaysOn=false, debug = false){ // 2021-01-29 return new eleWaiter(sel, cb, cbFail, findIn, delay, maxTries, alwaysOn, true, debug); } setTimeout(main, 0);
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址