Merge pull request #4 from Leonetienne/develop

Readme chrome extension
This commit is contained in:
Leon Etienne authored and GitHub committed 2021-03-13 19:08:20 +01:00
commit 7eeac4ac91
30 files changed
+399

No files matched your search

+3
View File
@@ -0,0 +1,3 @@
*.zip
*.rar
*.6zip
+58
View File
@@ -0,0 +1,58 @@
function QueueDownloadByInfo(info, mode, quality) {
// Select either the current page location, or the target of a href (if the user clicked on one)
QueueDownload(
urlToDownload = typeof(info.linkUrl) != 'undefined' ? info.linkUrl : info.pageUrl,
mode,
quality
); // <- Defined in queueDwonload.js
return;
}
// Create main context menu entry
chrome.contextMenus.create({
title: "Tubio",
contexts:["all"],
id: "tubio-parent-contextmenu-entry",
});
// Automate creating a lot of entries
function CreateContextMenuOption(optionName, callback) {
chrome.contextMenus.create({
title: optionName,
contexts: ["all"],
type: "normal",
parentId: "tubio-parent-contextmenu-entry",
onclick: callback
});
}
// Create all download methods
CreateContextMenuOption("Download Video - Best", function(info) {
QueueDownloadByInfo(info, "video", "best");
});
CreateContextMenuOption("Download Video - 1440p", function(info) {
QueueDownloadByInfo(info, "video", "1440p");
});
CreateContextMenuOption("Download Video - 1080p", function(info) {
QueueDownloadByInfo(info, "video", "1080p");
});
CreateContextMenuOption("Download Video - 720p", function(info) {
QueueDownloadByInfo(info, "video", "720p");
});
CreateContextMenuOption("Download Video - 480p", function(info) {
QueueDownloadByInfo(info, "video", "480p");
});
CreateContextMenuOption("Download Video - 360p", function(info) {
QueueDownloadByInfo(info, "video", "360p");
});
CreateContextMenuOption("Download Video - 240p", function(info) {
QueueDownloadByInfo(info, "video", "240p");
});
CreateContextMenuOption("Download Video - 144p", function(info) {
QueueDownloadByInfo(info, "video", "144p");
});
CreateContextMenuOption("Download Audio", function(info) {
QueueDownloadByInfo(info, "audio", "best"); // <- Quality is ignored when downloading audio only
});
Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.3 KiB

+3
View File
@@ -0,0 +1,3 @@
/* axios v0.21.1 | (c) 2020 by Matt Zabriskie */
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?exports.axios=t():e.axios=t()}(this,function(){return function(e){function t(r){if(n[r])return n[r].exports;var o=n[r]={exports:{},id:r,loaded:!1};return e[r].call(o.exports,o,o.exports,t),o.loaded=!0,o.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t,n){e.exports=n(1)},function(e,t,n){"use strict";function r(e){var t=new i(e),n=s(i.prototype.request,t);return o.extend(n,i.prototype,t),o.extend(n,t),n}var o=n(2),s=n(3),i=n(4),a=n(22),u=n(10),c=r(u);c.Axios=i,c.create=function(e){return r(a(c.defaults,e))},c.Cancel=n(23),c.CancelToken=n(24),c.isCancel=n(9),c.all=function(e){return Promise.all(e)},c.spread=n(25),c.isAxiosError=n(26),e.exports=c,e.exports.default=c},function(e,t,n){"use strict";function r(e){return"[object Array]"===R.call(e)}function o(e){return"undefined"==typeof e}function s(e){return null!==e&&!o(e)&&null!==e.constructor&&!o(e.constructor)&&"function"==typeof e.constructor.isBuffer&&e.constructor.isBuffer(e)}function i(e){return"[object ArrayBuffer]"===R.call(e)}function a(e){return"undefined"!=typeof FormData&&e instanceof FormData}function u(e){var t;return t="undefined"!=typeof ArrayBuffer&&ArrayBuffer.isView?ArrayBuffer.isView(e):e&&e.buffer&&e.buffer instanceof ArrayBuffer}function c(e){return"string"==typeof e}function f(e){return"number"==typeof e}function p(e){return null!==e&&"object"==typeof e}function d(e){if("[object Object]"!==R.call(e))return!1;var t=Object.getPrototypeOf(e);return null===t||t===Object.prototype}function l(e){return"[object Date]"===R.call(e)}function h(e){return"[object File]"===R.call(e)}function m(e){return"[object Blob]"===R.call(e)}function y(e){return"[object Function]"===R.call(e)}function g(e){return p(e)&&y(e.pipe)}function v(e){return"undefined"!=typeof URLSearchParams&&e instanceof URLSearchParams}function x(e){return e.replace(/^\s*/,"").replace(/\s*$/,"")}function w(){return("undefined"==typeof navigator||"ReactNative"!==navigator.product&&"NativeScript"!==navigator.product&&"NS"!==navigator.product)&&("undefined"!=typeof window&&"undefined"!=typeof document)}function b(e,t){if(null!==e&&"undefined"!=typeof e)if("object"!=typeof e&&(e=[e]),r(e))for(var n=0,o=e.length;n<o;n++)t.call(null,e[n],n,e);else for(var s in e)Object.prototype.hasOwnProperty.call(e,s)&&t.call(null,e[s],s,e)}function E(){function e(e,n){d(t[n])&&d(e)?t[n]=E(t[n],e):d(e)?t[n]=E({},e):r(e)?t[n]=e.slice():t[n]=e}for(var t={},n=0,o=arguments.length;n<o;n++)b(arguments[n],e);return t}function j(e,t,n){return b(t,function(t,r){n&&"function"==typeof t?e[r]=S(t,n):e[r]=t}),e}function C(e){return 65279===e.charCodeAt(0)&&(e=e.slice(1)),e}var S=n(3),R=Object.prototype.toString;e.exports={isArray:r,isArrayBuffer:i,isBuffer:s,isFormData:a,isArrayBufferView:u,isString:c,isNumber:f,isObject:p,isPlainObject:d,isUndefined:o,isDate:l,isFile:h,isBlob:m,isFunction:y,isStream:g,isURLSearchParams:v,isStandardBrowserEnv:w,forEach:b,merge:E,extend:j,trim:x,stripBOM:C}},function(e,t){"use strict";e.exports=function(e,t){return function(){for(var n=new Array(arguments.length),r=0;r<n.length;r++)n[r]=arguments[r];return e.apply(t,n)}}},function(e,t,n){"use strict";function r(e){this.defaults=e,this.interceptors={request:new i,response:new i}}var o=n(2),s=n(5),i=n(6),a=n(7),u=n(22);r.prototype.request=function(e){"string"==typeof e?(e=arguments[1]||{},e.url=arguments[0]):e=e||{},e=u(this.defaults,e),e.method?e.method=e.method.toLowerCase():this.defaults.method?e.method=this.defaults.method.toLowerCase():e.method="get";var t=[a,void 0],n=Promise.resolve(e);for(this.interceptors.request.forEach(function(e){t.unshift(e.fulfilled,e.rejected)}),this.interceptors.response.forEach(function(e){t.push(e.fulfilled,e.rejected)});t.length;)n=n.then(t.shift(),t.shift());return n},r.prototype.getUri=function(e){return e=u(this.defaults,e),s(e.url,e.params,e.paramsSerializer).replace(/^\?/,"")},o.forEach(["delete","get","head","options"],function(e){r.prototype[e]=function(t,n){return this.request(u(n||{},{method:e,url:t,data:(n||{}).data}))}}),o.forEach(["post","put","patch"],function(e){r.prototype[e]=function(t,n,r){return this.request(u(r||{},{method:e,url:t,data:n}))}}),e.exports=r},function(e,t,n){"use strict";function r(e){return encodeURIComponent(e).replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"+").replace(/%5B/gi,"[").replace(/%5D/gi,"]")}var o=n(2);e.exports=function(e,t,n){if(!t)return e;var s;if(n)s=n(t);else if(o.isURLSearchParams(t))s=t.toString();else{var i=[];o.forEach(t,function(e,t){null!==e&&"undefined"!=typeof e&&(o.isArray(e)?t+="[]":e=[e],o.forEach(e,function(e){o.isDate(e)?e=e.toISOString():o.isObject(e)&&(e=JSON.stringify(e)),i.push(r(t)+"="+r(e))}))}),s=i.join("&")}if(s){var a=e.indexOf("#");a!==-1&&(e=e.slice(0,a)),e+=(e.indexOf("?")===-1?"?":"&")+s}return e}},function(e,t,n){"use stricLine truncated
//# sourceMappingURL=axios.min.map
+2
View File
@@ -0,0 +1,2 @@
/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */
!function (e, t) { "use strict"; "object" == typeof module && "object" == typeof module.exports ? module.exports = e.document ? t(e, !0) : function (e) { if (!e.document) throw new Error("jQuery requires a window with a document"); return t(e) } : t(e) }("undefined" != typeof window ? window : this, function (C, e) { "use strict"; var t = [], r = Object.getPrototypeOf, s = t.slice, g = t.flat ? function (e) { return t.flat.call(e) } : function (e) { return t.concat.apply([], e) }, u = t.push, i = t.indexOf, n = {}, o = n.toString, v = n.hasOwnProperty, a = v.toString, l = a.call(Object), y = {}, m = function (e) { return "function" == typeof e && "number" != typeof e.nodeType }, x = function (e) { return null != e && e === e.window }, E = C.document, c = { type: !0, src: !0, nonce: !0, noModule: !0 }; function b(e, t, n) { var r, i, o = (n = n || E).createElement("script"); if (o.text = e, t) for (r in c) (i = t[r] || t.getAttribute && t.getAttribute(r)) && o.setAttribute(r, i); n.head.appendChild(o).parentNode.removeChild(o) } function w(e) { return null == e ? e + "" : "object" == typeof e || "function" == typeof e ? n[o.call(e)] || "object" : typeof e } var f = "3.5.1", S = function (e, t) { return new S.fn.init(e, t) }; function p(e) { var t = !!e && "length" in e && e.length, n = w(e); return !m(e) && !x(e) && ("array" === n || 0 === t || "number" == typeof t && 0 < t && t - 1 in e) } S.fn = S.prototype = { jquery: f, constructor: S, length: 0, toArray: function () { return s.call(this) }, get: function (e) { return null == e ? s.call(this) : e < 0 ? this[e + this.length] : this[e] }, pushStack: function (e) { var t = S.merge(this.constructor(), e); return t.prevObject = this, t }, each: function (e) { return S.each(this, e) }, map: function (n) { return this.pushStack(S.map(this, function (e, t) { return n.call(e, t, e) })) }, slice: function () { return this.pushStack(s.apply(this, arguments)) }, first: function () { return this.eq(0) }, last: function () { return this.eq(-1) }, even: function () { return this.pushStack(S.grep(this, function (e, t) { return (t + 1) % 2 })) }, odd: function () { return this.pushStack(S.grep(this, function (e, t) { return t % 2 })) }, eq: function (e) { var t = this.length, n = +e + (e < 0 ? t : 0); return this.pushStack(0 <= n && n < t ? [this[n]] : []) }, end: function () { return this.prevObject || this.constructor() }, push: u, sort: t.sort, splice: t.splice }, S.extend = S.fn.extend = function () { var e, t, n, r, i, o, a = arguments[0] || {}, s = 1, u = arguments.length, l = !1; for ("boolean" == typeof a && (l = a, a = arguments[s] || {}, s++), "object" == typeof a || m(a) || (a = {}), s === u && (a = this, s--); s < u; s++)if (null != (e = arguments[s])) for (t in e) r = e[t], "__proto__" !== t && a !== r && (l && r && (S.isPlainObject(r) || (i = Array.isArray(r))) ? (n = a[t], o = i && !Array.isArray(n) ? [] : i || S.isPlainObject(n) ? n : {}, i = !1, a[t] = S.extend(l, o, r)) : void 0 !== r && (a[t] = r)); return a }, S.extend({ expando: "jQuery" + (f + Math.random()).replace(/\D/g, ""), isReady: !0, error: function (e) { throw new Error(e) }, noop: function () { }, isPlainObject: function (e) { var t, n; return !(!e || "[object Object]" !== o.call(e)) && (!(t = r(e)) || "function" == typeof (n = v.call(t, "constructor") && t.constructor) && a.call(n) === l) }, isEmptyObject: function (e) { var t; for (t in e) return !1; return !0 }, globalEval: function (e, t, n) { b(e, { nonce: t && t.nonce }, n) }, each: function (e, t) { var n, r = 0; if (p(e)) { for (n = e.length; r < n; r++)if (!1 === t.call(e[r], r, e[r])) break } else for (r in e) if (!1 === t.call(e[r], r, e[r])) break; return e }, makeArray: function (e, t) { var n = t || []; return null != e && (p(Object(e)) ? S.merge(n, "string" == typeof e ? [e] : e) : u.call(n, e)), n }, inArray: function (e, t, n) { return null == t ? -1 : i.call(t, e, n) }, merge: function (e, t) { for (var n = +t.length, r = 0, i = e.length; r < n; r++)e[i++] = t[r]; return e.length = i, e }, grep: function (e, t, n) { for (var r = [], i = 0, o = e.length, a = !n; i < o; i++)!t(e[i], i) !== a && r.push(e[i]); return r }, map: function (e, t, n) { var r, i, o = 0, a = []; if (p(e)) for (r = e.length; o < r; o++)null != (i = t(e[o], o, n)) && a.push(i); else for (o in e) null != (i = t(e[o], o, n)) && a.push(i); return g(a) }, guid: 1, support: y }), "function" == typeof Symbol && (S.fn[Symbol.iterator] = t[Symbol.iterator]), S.each("Boolean Number String Function Array Date RegExp Object Error Symbol".split(" "), function (e, t) { n["[object " + t + "]"] = t.toLowerCase() }); var d = function (n) { var e, d, b, o, i, h, f, g, w, u, l, T, C, a, E, v, s, c, y, S = "sizzle" + 1 * new Date, p = n.document, k = 0, r = 0, m = ue(), x = ue(), A = ue(), N = ue(), D = function (e, t) { return e === t && (l = !0), 0 }, j = {}.hasOwnProperty, t = [], q = t.pop, L = t.push, H = t.push, O = t.slice, P = function (e, t) { for (var n = 0, rLine truncated
+33
View File
@@ -0,0 +1,33 @@
{
"manifest_version": 2,
"name": "Tubio - Companion Extension",
"version": "1.0",
"icons": {
"16": "icon/16.png",
"48": "icon/48.png",
"128": "icon/128.png"
},
"browser_action": {
"default_popup": "popup/index.html"
},
"permissions": [
"background",
"contextMenus",
"webRequest",
"windows",
"tabs",
"storage",
"*://*/*"
],
"background": {
"scripts": [
"lib/axios.js",
"queueDownload.js",
"background.js"
]
}
}
@@ -0,0 +1,37 @@
body {
width: 300px;
height: 310px;
margin: 0 !important;
}
body .bgmask {
width: 100vw;
height: 100vh;
position: fixed;
z-index: -8;
background-image: linear-gradient(#0000 50%, #04254e);
}
body .bggatter {
width: 100%;
height: 100%;
position: absolute;
z-index: -9;
-webkit-mask-image: url("../image/grid.png");
background-color: #5954a4;
}
body .bggatter__wrapper {
width: 100vw;
height: 100vh;
position: fixed;
overflow: hidden;
z-index: -9;
}
body .bgdrop {
width: 100vw;
height: 100vh;
position: fixed;
z-index: -10;
background-color: #04254e;
}
@@ -0,0 +1,42 @@
button {
padding: 0.5em 2em;
color: #04254e;
font-size: 14pt;
border-radius: 5px;
cursor: pointer;
transition:
color 0.15s ease,
transform 0.15s ease;
}
button.small {
padding: 0.15em 1em;
}
button:hover {
transform: scale(1.075);
color: #fff;
background-color: #5954a4;
}
button.special:hover {
/*background-color: #5954a4;*/
color: #fff;
animation: color-cycle;
animation-duration: 1s;
animation-iteration-count: infinite;
}
button.lock {
visibility: hidden;
}
@keyframes color-cycle {
0% {background-color: #ff6666; transform: scale(1.075);}
16.67% {background-color: #c966ff;}
33.33% {background-color: #6678ff;}
50% {background-color: #66edff; transform: scale(1.15);}
66.66% {background-color: #66ff70;}
83.33% {background-color: #fcff66;}
100% {background-color: #ff6666; transform: scale(1.075);}
}
@@ -0,0 +1 @@
@import "zilla-slab.css"
@@ -0,0 +1,49 @@
@font-face {
font-family: "ZillaSlab";
src: url("../../font/zilla-slab/ZillaSlab-Regular.ttf") format('truetype');
}
@font-face {
font-family: "ZillaSlab";
src: url("../../font/zilla-slab/ZillaSlab-Italic.ttf") format('truetype');
font-style: italic;
}
@font-face {
font-family: "ZillaSlab";
src: url("../../font/zilla-slab/ZillaSlab-Bold.ttf") format('truetype');
font-weight: bold;
}
@font-face {
font-family: "ZillaSlab";
src: url("../../font/zilla-slab/ZillaSlab-BoldItalic.ttf") format('truetype');
font-weight: bold;
font-style: italic;
}
@font-face {
font-family: "ZillaSlab";
src: url("../../font/zilla-slab/ZillaSlab-Light.ttf") format('truetype');
font-weight: lighter;
}
@font-face {
font-family: "ZillaSlab";
src: url("../../font/zilla-slab/ZillaSlab-Light.ttf") format('truetype');
font-weight: lighter;
font-style: italic;
}
@font-face {
font-family: "ZillaSlab";
src: url("../../font/zilla-slab/ZillaSlab-Medium.ttf") format('truetype');
font-weight: 500;
}
@font-face {
font-family: "ZillaSlab";
src: url("../../font/zilla-slab/ZillaSlab-Medium.ttf") format('truetype');
font-weight: 500;
font-style: italic;
}
@@ -0,0 +1,14 @@
label {
margin-bottom: 0.5em;
}
input {
border-radius: 5px;
height: 25pt;
}
input,
textarea {
color: #04254e;
font-size: 14pt;
}
@@ -0,0 +1,23 @@
.text-center {
text-align: center;
}
.pt-1 {
padding-top: 1em;
}
.flex {
display: flex;
}
.flex-col {
flex-direction: column;
}
.justify-content-center {
justify-content: center;
}
.align-items-center {
align-items: center;
}
@@ -0,0 +1,15 @@
* {
font-family: 'ZillaSlab' !important;
color: #dadada;
}
p,
a,
label {
font-size: 14pt;
}
h1,
h2 {
line-height: 1em;
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 527 B

+44
View File
@@ -0,0 +1,44 @@
<html>
<head>
<link rel="stylesheet" href="css/background.css">
<link rel="stylesheet" href="css/typography.css">
<link rel="stylesheet" href="css/modular.css">
<link rel="stylesheet" href="css/form.css">
<link rel="stylesheet" href="css/button.css">
<link rel="stylesheet" href="css/font/include.css">
<title>Tubio - Companion Extension</title>
</head>
<body>
<div class="bgdrop"></div>
<div class="bggatter__wrapper">
<div class="bggatter"></div>
</div>
<div class="bgmask"></div>
<h1 class="text-center pt-1" style="margin-bottom: 0;">Tubio</h1>
<h2 class="text-center" style="margin-top: 0; padding-top: 0;">Companion Extension</h2>
<div class="flex justify-content-center">
<div class="flex flex-col align-items-center">
<!-- Download this - button -->
<button class="special" id="button-download" title="Will download this pages URL as a video of highest quality.">
Download!
</button>
<!-- Tubio config form -->
<label for="tubio-address" style="margin-top: 3em;">Where can i reach tubio?</label>
<input type="text" id="tubio-address" class="text-center" />
<button class="small" id="button-save-settings" style="margin-top: 0.5em;">Save settings</button>
</div>
</div>
<script src="../lib/jquery-3.5.1.min.js"></script>
<script src="../lib/axios.js"></script>
<script src="../queueDownload.js"></script>
<script src="js/script.js"></script>
</body>
</html>
@@ -0,0 +1,32 @@
$("#button-download").click(function() {
$("#button-download").addClass("lock");
// Query active tab in active window...
chrome.windows.getCurrent(function(w) {
chrome.tabs.query({
active: true,
windowId: w.id
}, function(foundTabs) {
if (foundTabs.length > 0) {
QueueDownload(foundTabs[0].url, "video", "best", function(){
window.close();
});
} else {
console.log("Wtf, this should not happen. You don't have ANY open tab?...");
}
});
});
return;
});
chrome.storage.local.get(['tubio_address'], function(result) {
$("#tubio-address").val(result.tubio_address);
});
$("#button-save-settings").click(function() {
chrome.storage.local.set({
tubio_address: $("#tubio-address").val()
});
});
+38
View File
@@ -0,0 +1,38 @@
function QueueDownload(url, mode, quality, callback) {
console.log("Queueing '" + url + "'...");
// Fetch tubio address
chrome.storage.local.get(['tubio_address'], function(result) {
if ((typeof(result.tubio_address) == 'undefined') ||
(result.tubio_address.length == 0)) {
alert("Please first set an address to reach Tubio at in the extensions settings! (Click on the extensions icon in the toolbar).");
return;
} else {
tubioUrl = result.tubio_address;
if (tubioUrl[tubioUrl.length-1] != '/') { // Has the user not appended a /?
tubioUrl += '/';
}
axios.post(tubioUrl + "api", {
request: "queue_download",
video_url: url,
mode: mode,
quality: quality
}).then(function(response){
console.log("Queued successfully...");
if (typeof(callback) != 'undefined') callback(true, response);
}).catch(function(response){
console.log("Something went wrong...");
console.log(response);
if (typeof(callback) != 'undefined') callback(false, response);
});
}
});
return;
}
+5
View File
@@ -0,0 +1,5 @@
# Chrome Extension for Tubio
Adds a context-menu and a popup to download videos instantly.
It does not open tubio for you. It just downloads the videos.
For now this is not on the chrome store, but you can easily install unlisted extensions from source as shown [here](https://developer.chrome.com/docs/extensions/mv2/faq/#:~:text=Click%20the%20Chrome%20menu%20icon,a%20packaged%20extension%2C%20and%20more.).