Compare commits
No commits in common. "main" and "1.1.1-indev" have entirely different histories.
main
...
1.1.1-inde
42
LICENSE
42
LICENSE
|
|
@ -1282,6 +1282,48 @@ copy of the Program in return for a fee.
|
||||||
|
|
||||||
END OF TERMS AND CONDITIONS
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
state the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero 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 Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If your software can interact with users remotely through a computer
|
||||||
|
network, you should also make sure that it provides a way for users to
|
||||||
|
get its source. For example, if your program is a web application, its
|
||||||
|
interface could display a "Source" link that leads users to an archive
|
||||||
|
of the code. There are many ways you could offer source, and different
|
||||||
|
solutions will be better for different programs; see section 13 for the
|
||||||
|
specific requirements.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or school,
|
||||||
|
if any, to sign a "copyright disclaimer" for the program, if necessary.
|
||||||
|
For more information on this, and how to apply and follow the GNU AGPL, see
|
||||||
|
<https://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
-------Original Cytube License-------
|
-------Original Cytube License-------
|
||||||
The MIT License (MIT)
|
The MIT License (MIT)
|
||||||
Copyright (c) 2013-2021 Calvin Montgomery and contributors
|
Copyright (c) 2013-2021 Calvin Montgomery and contributors
|
||||||
|
|
|
||||||
42
README.md
42
README.md
|
|
@ -1,4 +1,4 @@
|
||||||
fore.st - Pineapple Express += 3 (v1.1.3)
|
fore.st - Pineapple Express++ (v1.1.1)
|
||||||
======
|
======
|
||||||
|
|
||||||
fore.st is the server software for ourfore.st, a community based chat & synced video embedding site tailored to service
|
fore.st is the server software for ourfore.st, a community based chat & synced video embedding site tailored to service
|
||||||
|
|
@ -24,8 +24,44 @@ You can reach out by bugging rainbownapkin on the ttn discord or ourfore.st, you
|
||||||
- Thanks to calzoneman for making [cytube](https://github.com/calzoneman/sync), that saved our asses.
|
- Thanks to calzoneman for making [cytube](https://github.com/calzoneman/sync), that saved our asses.
|
||||||
- Thanks to the core TTN community and everyone else who's ever used it, I was only there for the last handful of years but it was an absolute fuckin' ride. You guys are the best, it isn't TTN but I hope this at least help fills the gap.
|
- Thanks to the core TTN community and everyone else who's ever used it, I was only there for the last handful of years but it was an absolute fuckin' ride. You guys are the best, it isn't TTN but I hope this at least help fills the gap.
|
||||||
|
|
||||||
## Pineapple Express += 3 1.1.3 Release Notes
|
## Pineapple Express++ 1.1.1 Release Notes
|
||||||
- Add bulk-queueing from Internet Archive
|
Abriged Patchnotes:
|
||||||
|
- bugfixes/QoL tweaks
|
||||||
|
- remove duplicated blazem from tokefile
|
||||||
|
- fix playlist on submit channel for standard users
|
||||||
|
- only show nested menu on playlist if user rank is <= 2
|
||||||
|
- show "playlist" button for users rank 1 on r/submit channel
|
||||||
|
- stop tokebot from including full toke messages
|
||||||
|
- fully disconnect/kick unregistered users from channels connect
|
||||||
|
- limit words/link display text(DO NOT MODIFY LINK HREF) to 40 chars to prevent breaking chat width
|
||||||
|
- limit image embed width
|
||||||
|
- fix video/chat/autobump UI components not expanding after collapsing in chromium based browsers
|
||||||
|
- remove close playlist button when legacy playlist is disabled
|
||||||
|
- fix expand/shade playlist items button
|
||||||
|
- add end date to playlist items
|
||||||
|
- userlist collapse/expand persistent accross browser sessions
|
||||||
|
- cinema mode persistent accross browser sessions
|
||||||
|
- dissapearing server whispers/join messages
|
||||||
|
- fix input field lengths in quicksettings
|
||||||
|
- prevent temporary items on submit channel
|
||||||
|
- always block anonymous user (ignore channel setting)
|
||||||
|
- use regex for whitespace detection in commands
|
||||||
|
|
||||||
|
- client side commands
|
||||||
|
- process commands that start with "/" or "(whitespace)/" in the browser
|
||||||
|
- allow admins to trigger client side commands remotely
|
||||||
|
- show words that start with "/" as a link that chatsmacks command(similiar to behavior with words that start with !)
|
||||||
|
- /thunder
|
||||||
|
- Disable lightning (seizure prevention)
|
||||||
|
|
||||||
|
- update tab completion
|
||||||
|
- add non-toke server-side commands to tab completion(check perms for respective commands)
|
||||||
|
- add client-side commands to tab completion
|
||||||
|
- show autocomplete in text box
|
||||||
|
|
||||||
|
- kick users w/ old client
|
||||||
|
|
||||||
|
- spooktober themes
|
||||||
|
|
||||||
## License
|
## License
|
||||||
Original fore.st code is provided under the Affero General Public License v3 in order to prevent fore.st being used in proprietary software.
|
Original fore.st code is provided under the Affero General Public License v3 in order to prevent fore.st being used in proprietary software.
|
||||||
|
|
|
||||||
|
|
@ -114,7 +114,6 @@ io:
|
||||||
|
|
||||||
#pull info from invidious
|
#pull info from invidious
|
||||||
invidious-backend: true
|
invidious-backend: true
|
||||||
yt-dlp-path: 'yt-dlp'
|
|
||||||
#invidious source, defaults to vid.puffyan.us, not affiliated, simply a well known US based instance
|
#invidious source, defaults to vid.puffyan.us, not affiliated, simply a well known US based instance
|
||||||
#invidious-source: 'vid.puffyan.us'
|
#invidious-source: 'vid.puffyan.us'
|
||||||
|
|
||||||
|
|
|
||||||
3299
package-lock.json
generated
3299
package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "fore.st",
|
"name": "fore.st",
|
||||||
"version": "1.1.3",
|
"version": "1.1.1",
|
||||||
"description": "fore.st: A fork of cytube tailored for the TTN Community",
|
"description": "fore.st: A fork of cytube tailored for the TTN Community",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"directories": {
|
"directories": {
|
||||||
|
|
@ -23,7 +23,7 @@
|
||||||
"express": "^4.17.1",
|
"express": "^4.17.1",
|
||||||
"express-minify": "^1.0.0",
|
"express-minify": "^1.0.0",
|
||||||
"json-typecheck": "^0.1.3",
|
"json-typecheck": "^0.1.3",
|
||||||
"knex": "^3.1.0",
|
"knex": "^0.95.2",
|
||||||
"lodash": "^4.17.21",
|
"lodash": "^4.17.21",
|
||||||
"morgan": "^1.10.0",
|
"morgan": "^1.10.0",
|
||||||
"mysql": "^2.18.1",
|
"mysql": "^2.18.1",
|
||||||
|
|
@ -38,8 +38,7 @@
|
||||||
"source-map-support": "^0.5.19",
|
"source-map-support": "^0.5.19",
|
||||||
"toml": "^3.0.0",
|
"toml": "^3.0.0",
|
||||||
"uuid": "^8.3.2",
|
"uuid": "^8.3.2",
|
||||||
"yamljs": "^0.2.8",
|
"yamljs": "^0.2.8"
|
||||||
"youtube-dl-exec": "^3.0.10"
|
|
||||||
},
|
},
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build-server": "babel -D --source-maps --out-dir lib/ src/",
|
"build-server": "babel -D --source-maps --out-dir lib/ src/",
|
||||||
|
|
|
||||||
|
|
@ -1,5 +1,60 @@
|
||||||
dev goals for 1.1.3 pineapple Express += 3:
|
dev goals for 1.1.1 pineapple express++:
|
||||||
-- Add bulk-queueing from Internet Archive
|
|
||||||
- automagically pull most web-compatible version of all videos within a specific upload to IA
|
- bugfixes/QoL tweaks
|
||||||
- allow queueing admin to filter directory by video length in minutes
|
- remove duplicated blazem from tokefile
|
||||||
- allow for bulk naming
|
- fix playlist on submit channel for standard users
|
||||||
|
- only show nested menu on playlist if user rank is <= 2
|
||||||
|
- show "playlist" button for users rank 1 on r/submit channel
|
||||||
|
- stop tokebot from including full toke messages
|
||||||
|
- fully disconnect/kick unregistered users from channels connect
|
||||||
|
- limit words/link display text(DO NOT MODIFY LINK HREF) to 40 chars to prevent breaking chat width
|
||||||
|
- limit image embed width
|
||||||
|
- fix video/chat/autobump UI components not expanding after collapsing in chromium based browsers
|
||||||
|
- remove close playlist button when legacy playlist is disabled
|
||||||
|
- fix expand/shade playlist items button
|
||||||
|
- add end date to playlist items
|
||||||
|
- userlist collapse/expand persistent accross browser sessions
|
||||||
|
- cinema mode persistent accross browser sessions
|
||||||
|
- dissapearing server whispers/join messages
|
||||||
|
- fix input field lengths in quicksettings
|
||||||
|
- prevent temporary items on submit channel
|
||||||
|
- always block anonymous user (ignore channel setting)
|
||||||
|
- use regex for whitespace detection in commands
|
||||||
|
|
||||||
|
- client side commands
|
||||||
|
- process commands that start with "/" or "(whitespace)/" in the browser
|
||||||
|
- allow admins to trigger client side commands remotely
|
||||||
|
- remove / from client command when calling sendcmd if present
|
||||||
|
- do not send command as chat (unless it starts with whitespace, matching serverside command behavior)
|
||||||
|
- show words that start with "/" as a link that chatsmacks command(similiar to behavior with words that start with !)
|
||||||
|
- /thunder
|
||||||
|
- Disable lightning (seizure prevention)
|
||||||
|
|
||||||
|
- update tab completion
|
||||||
|
- add non-toke server-side commands to tab completion(check perms for respective commands)
|
||||||
|
- me
|
||||||
|
- announce
|
||||||
|
- af
|
||||||
|
- sp
|
||||||
|
- afk
|
||||||
|
- poll
|
||||||
|
- hpoll
|
||||||
|
- mute
|
||||||
|
- smute
|
||||||
|
- unmute
|
||||||
|
- kick
|
||||||
|
- ban
|
||||||
|
- ipban
|
||||||
|
- clear
|
||||||
|
- clean
|
||||||
|
- cleantitle
|
||||||
|
- sendcmd
|
||||||
|
- add client-side commands to tab completion
|
||||||
|
- show autocomplete in text box
|
||||||
|
|
||||||
|
- send clientside version on connect
|
||||||
|
- kick if version old/not received
|
||||||
|
|
||||||
|
- spooktober themes
|
||||||
|
- Candycorn
|
||||||
|
- Candycorn lite
|
||||||
|
|
|
||||||
|
|
@ -107,13 +107,11 @@ function loadLists(cb, callp){
|
||||||
|
|
||||||
bumplists = new Map();//create new map to load lists into, this clears the variable as well as lets the channel know whether or not they have been loaded yet.
|
bumplists = new Map();//create new map to load lists into, this clears the variable as well as lets the channel know whether or not they have been loaded yet.
|
||||||
|
|
||||||
if(item != null){
|
|
||||||
item.forEach(function(list, i){
|
item.forEach(function(list, i){
|
||||||
if(list != configFolder.slice(bumpFolder.length, configFolder.length - 1) && list.slice(list.length - 5) === ".bump"){
|
if(list != configFolder.slice(bumpFolder.length, configFolder.length - 1) && list.slice(list.length - 5) === ".bump"){
|
||||||
loadList("bumps/" + list);
|
loadList("bumps/" + list);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
|
||||||
|
|
||||||
if(cb != null){//lil' nasty but it calls loadconfig after loading lists :P
|
if(cb != null){//lil' nasty but it calls loadconfig after loading lists :P
|
||||||
if(callp != null){
|
if(callp != null){
|
||||||
|
|
@ -624,13 +622,6 @@ AutobumpModule.prototype.loadConfig = function(_this){
|
||||||
|
|
||||||
if(err){
|
if(err){
|
||||||
console.log("[Autobump Config] " + err);
|
console.log("[Autobump Config] " + err);
|
||||||
|
|
||||||
_this.agro = defAgro ;
|
|
||||||
_this.bumpFreq = defFreq;
|
|
||||||
_this.minBump = defMin;
|
|
||||||
_this.selmed = _this.lastHalfRandom;
|
|
||||||
_this.listsel = _this.smashList;
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,6 @@ const TYPE_QUEUE = {
|
||||||
pos: "string",
|
pos: "string",
|
||||||
title: "string,boolean,optional",
|
title: "string,boolean,optional",
|
||||||
duration: "number,optional",
|
duration: "number,optional",
|
||||||
minDuration: "number,optional",
|
|
||||||
temp: "boolean,optional",
|
temp: "boolean,optional",
|
||||||
subtitle: "string"
|
subtitle: "string"
|
||||||
};
|
};
|
||||||
|
|
@ -446,7 +445,7 @@ PlaylistModule.prototype.handleQueue = function (user, data) {
|
||||||
* Specifying a custom title is currently only allowed for custom media
|
* Specifying a custom title is currently only allowed for custom media
|
||||||
* and raw files
|
* and raw files
|
||||||
*/
|
*/
|
||||||
if (typeof data.title !== "string" || (data.type !== "cu" && data.type !== "fi" && data.type !== "ia")) {
|
if (typeof data.title !== "string" || (data.type !== "cu" && data.type !== "fi")) {
|
||||||
data.title = false;
|
data.title = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -467,9 +466,9 @@ PlaylistModule.prototype.handleQueue = function (user, data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Certain media types require special permission to add */
|
/* Certain media types require special permission to add */
|
||||||
if ((data.type === "yp" || data.type === "ia") && !perms.canAddList(user)) {
|
if (data.type === "yp" && !perms.canAddList(user)) {
|
||||||
user.socket.emit("queueFail", {
|
user.socket.emit("queueFail", {
|
||||||
msg: "You don't have permission to bulk queue",
|
msg: "You don't have permission to add playlists",
|
||||||
link: link,
|
link: link,
|
||||||
id: id
|
id: id
|
||||||
});
|
});
|
||||||
|
|
@ -505,11 +504,6 @@ PlaylistModule.prototype.handleQueue = function (user, data) {
|
||||||
duration = !isNaN(data.duration) ? data.duration : undefined;
|
duration = !isNaN(data.duration) ? data.duration : undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
var minDuration = undefined;
|
|
||||||
if (typeof data.minDuration === "number") {
|
|
||||||
minDuration = !isNaN(data.minDuration) ? data.minDuration : 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
var limit = {
|
var limit = {
|
||||||
burst: 3,
|
burst: 3,
|
||||||
sustained: 1
|
sustained: 1
|
||||||
|
|
@ -549,14 +543,11 @@ PlaylistModule.prototype.handleQueue = function (user, data) {
|
||||||
shouldAddToLibrary: true,//for now chan library will act as a history
|
shouldAddToLibrary: true,//for now chan library will act as a history
|
||||||
queueby: queueby,
|
queueby: queueby,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
minDuration: minDuration,
|
|
||||||
maxlength: maxlength
|
maxlength: maxlength
|
||||||
};
|
};
|
||||||
|
|
||||||
if (data.type === "yp") {
|
if (data.type === "yp") {
|
||||||
this.queueYouTubePlaylist(user, data);
|
this.queueYouTubePlaylist(user, data);
|
||||||
} else if (data.type === "ia") {
|
|
||||||
this.queueBulkIA(user, data);
|
|
||||||
} else {
|
} else {
|
||||||
this.queueStandard(user, data);
|
this.queueStandard(user, data);
|
||||||
}
|
}
|
||||||
|
|
@ -585,38 +576,7 @@ PlaylistModule.prototype.queueStandard = function (user, data) {
|
||||||
lock.release();
|
lock.release();
|
||||||
self.channel.refCounter.unref("PlaylistModule::queueStandard");
|
self.channel.refCounter.unref("PlaylistModule::queueStandard");
|
||||||
});
|
});
|
||||||
}, data.minDuration);
|
|
||||||
});
|
});
|
||||||
};
|
|
||||||
|
|
||||||
PlaylistModule.prototype.queueBulkIA = function (user, data) {
|
|
||||||
var error = function (what) {
|
|
||||||
user.socket.emit("queueFail", {
|
|
||||||
msg: what,
|
|
||||||
link: data.link,
|
|
||||||
id: data.id
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const self = this;
|
|
||||||
this.channel.refCounter.ref("PlaylistModule::queueBulkIA");
|
|
||||||
this.semaphore.queue(function (lock) {
|
|
||||||
InfoGetter.getMedia(data.id, data.type, function (err, vids) {
|
|
||||||
if (err) {
|
|
||||||
error(XSS.sanitizeText(String(err)));
|
|
||||||
self.channel.refCounter.unref("PlaylistModule::queueBulkIA");
|
|
||||||
return lock.release();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
vids.forEach(function(media){
|
|
||||||
self._addItem(media, data, user, null, data.minDuration);
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
self.channel.refCounter.unref("PlaylistModule::queueBulkIA");
|
|
||||||
lock.release();
|
|
||||||
}, data.minDuration);
|
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -1157,7 +1117,7 @@ PlaylistModule.prototype._addItem = function (media, data, user, cb, abump) {
|
||||||
queueby: data.queueby
|
queueby: data.queueby
|
||||||
});
|
});
|
||||||
|
|
||||||
if (data.title && (media.type === "cu" || media.type === "fi" || media.type === "ia")) {
|
if (data.title && (media.type === "cu" || media.type === "fi")) {
|
||||||
media.setTitle(data.title);
|
media.setTitle(data.title);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -1329,16 +1289,11 @@ PlaylistModule.prototype.startPlayback = function (time) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self.current.media.type == "yt"){//if its yt
|
if(self.current.media.type == "yt"){//if its yt
|
||||||
InfoGetter.getRawCopy(self.current.media.id,function(url){//get raw link from invidious api
|
InfoGetter.getYTRaw(self.current.media.id,function(url){//get raw link from invidious api
|
||||||
self.current.media.meta.rawLink = url;//set to meta
|
self.current.media.meta.rawLink = url;//set to meta
|
||||||
self.sendChangeMedia(self.channel.users);//fuggin SEND IT
|
self.sendChangeMedia(self.channel.users);//fuggin SEND IT
|
||||||
});
|
});
|
||||||
|
|
||||||
}else if(self.current.media.type == "dm"){
|
|
||||||
InfoGetter.getRawCopy(`https://dailymotion.com/video/${self.current.media.id}`,function(url){//get raw link from invidious api
|
|
||||||
self.current.media.meta.rawLink = url;//set to meta
|
|
||||||
self.sendChangeMedia(self.channel.users);//fuggin SEND IT
|
|
||||||
});
|
|
||||||
}else{
|
}else{
|
||||||
self.sendChangeMedia(self.channel.users);
|
self.sendChangeMedia(self.channel.users);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -67,7 +67,6 @@ var defaults = {
|
||||||
},
|
},
|
||||||
"invidious-backend": true,
|
"invidious-backend": true,
|
||||||
"invidious-source": 'inv.riverside.rocks',
|
"invidious-source": 'inv.riverside.rocks',
|
||||||
"yt-dlp-path": 'yt-dlp',
|
|
||||||
"youtube-v3-key": "",
|
"youtube-v3-key": "",
|
||||||
"channel-blacklist": [],
|
"channel-blacklist": [],
|
||||||
"channel-path": "r",
|
"channel-path": "r",
|
||||||
|
|
|
||||||
208
src/get-info.js
208
src/get-info.js
|
|
@ -49,14 +49,9 @@ const Vimeo = require("@cytube/mediaquery/lib/provider/vimeo");
|
||||||
const Streamable = require("@cytube/mediaquery/lib/provider/streamable");
|
const Streamable = require("@cytube/mediaquery/lib/provider/streamable");
|
||||||
const TwitchVOD = require("@cytube/mediaquery/lib/provider/twitch-vod");
|
const TwitchVOD = require("@cytube/mediaquery/lib/provider/twitch-vod");
|
||||||
const TwitchClip = require("@cytube/mediaquery/lib/provider/twitch-clip");
|
const TwitchClip = require("@cytube/mediaquery/lib/provider/twitch-clip");
|
||||||
const { create: makeYTDLP } = require('youtube-dl-exec')
|
|
||||||
//Specify path assuming yt-dlp is installed locally with path set properly (version packaged w/ npm package doesn't behave)
|
|
||||||
const YTDLP = makeYTDLP(Config.get('yt-dlp-path'));
|
|
||||||
|
|
||||||
import { Counter } from 'prom-client';
|
import { Counter } from 'prom-client';
|
||||||
import { lookup as lookupCustomMetadata } from './custom-media';
|
import { lookup as lookupCustomMetadata } from './custom-media';
|
||||||
|
|
||||||
|
|
||||||
const LOGGER = require('@calzoneman/jsli')('get-info');
|
const LOGGER = require('@calzoneman/jsli')('get-info');
|
||||||
const lookupCounter = new Counter({
|
const lookupCounter = new Counter({
|
||||||
name: 'cytube_media_lookups_total',
|
name: 'cytube_media_lookups_total',
|
||||||
|
|
@ -116,7 +111,7 @@ function getBlocked(reg){
|
||||||
|
|
||||||
var Getters = {
|
var Getters = {
|
||||||
/* youtube.com */
|
/* youtube.com */
|
||||||
yt: async function (id, callback) {
|
yt: function (id, callback) {
|
||||||
|
|
||||||
if(!Config.get("invidious-backend")){//legacy youtube backend (fucking yicky)
|
if(!Config.get("invidious-backend")){//legacy youtube backend (fucking yicky)
|
||||||
if (!Config.get("youtube-v3-key")) {
|
if (!Config.get("youtube-v3-key")) {
|
||||||
|
|
@ -127,11 +122,9 @@ var Getters = {
|
||||||
|
|
||||||
YouTube.lookup(id).then(function (video) {
|
YouTube.lookup(id).then(function (video) {
|
||||||
var meta = {};
|
var meta = {};
|
||||||
|
|
||||||
if (video.meta.blocked) {
|
if (video.meta.blocked) {
|
||||||
meta.restricted = video.meta.blocked;
|
meta.restricted = video.meta.blocked;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (video.meta.ytRating) {
|
if (video.meta.ytRating) {
|
||||||
meta.ytRating = video.meta.ytRating;
|
meta.ytRating = video.meta.ytRating;
|
||||||
}
|
}
|
||||||
|
|
@ -141,31 +134,8 @@ var Getters = {
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
callback(err.message || err, null);
|
callback(err.message || err, null);
|
||||||
});
|
});
|
||||||
}else{
|
}else{//invidious api calls (google bad)
|
||||||
//yt-dlp calls (google bad)
|
var options = {
|
||||||
try{
|
|
||||||
var video = await YTDLP(`youtu.be/${id}`,{
|
|
||||||
dumpSingleJson: true,
|
|
||||||
format: "b"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
var meta = {
|
|
||||||
ytRating: video.like_count,
|
|
||||||
rawLink: video.requested_downloads[0].url
|
|
||||||
}
|
|
||||||
|
|
||||||
var media = new Media(video.id, video.title, video.duration, "yt", meta);
|
|
||||||
|
|
||||||
|
|
||||||
callback(false, media);
|
|
||||||
}catch(err){
|
|
||||||
callback(err.message || err, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
//callback("test funciton, remove this call!" || err, null);
|
|
||||||
//invidious api calls (o7 Stream on, you magnificent bastard. We'll always remember you! <3 2018-2024)
|
|
||||||
/*var options = {
|
|
||||||
host: Config.get("invidious-source"),
|
host: Config.get("invidious-source"),
|
||||||
port: 443,
|
port: 443,
|
||||||
path: "/api/v1/videos/" + id,
|
path: "/api/v1/videos/" + id,
|
||||||
|
|
@ -191,13 +161,13 @@ var Getters = {
|
||||||
|
|
||||||
var media = new Media(vid.videoId, vid.title, vid.lengthSeconds, "yt", meta);
|
var media = new Media(vid.videoId, vid.title, vid.lengthSeconds, "yt", meta);
|
||||||
return callback(false, media);
|
return callback(false, media);
|
||||||
});*/
|
});
|
||||||
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/* youtube.com playlists */
|
/* youtube.com playlists */
|
||||||
yp: async function (id, callback) {
|
yp: function (id, callback) {
|
||||||
if(!Config.get("invidious-backend")){//legacy youtube backend (fucking yicky)
|
if(!Config.get("invidious-backend")){//legacy youtube backend (fucking yicky)
|
||||||
if (!Config.get("youtube-v3-key")) {
|
if (!Config.get("youtube-v3-key")) {
|
||||||
return callback("The YouTube API now requires an API key. You could sign up for an API key, but you're a lot better off using the invidious backend!" +
|
return callback("The YouTube API now requires an API key. You could sign up for an API key, but you're a lot better off using the invidious backend!" +
|
||||||
|
|
@ -218,35 +188,7 @@ var Getters = {
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
callback(err.message || err, null);
|
callback(err.message || err, null);
|
||||||
});
|
});
|
||||||
}else{//yt-dlp wrapper calls (google bad)
|
}else{//invidious api calls (google bad)
|
||||||
try{
|
|
||||||
var list = await YTDLP(`youtu.be/${id}`,{
|
|
||||||
dumpSingleJson: true,
|
|
||||||
format: "b"
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
var videos = new Array;
|
|
||||||
|
|
||||||
list.entries.forEach(function(video){
|
|
||||||
if(video != null){
|
|
||||||
var meta = {
|
|
||||||
ytRating: video.like_count,
|
|
||||||
rawLink: video.requested_downloads[0].url
|
|
||||||
}
|
|
||||||
|
|
||||||
videos.push(new Media(video.id, video.title, video.duration, "yt", meta));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
callback(null, videos);
|
|
||||||
}catch(err){
|
|
||||||
callback(err.message || err, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*invidious api calls (o7 RIP 2018-2024)
|
|
||||||
var options = {
|
var options = {
|
||||||
host: Config.get("invidious-source"),
|
host: Config.get("invidious-source"),
|
||||||
port: 443,
|
port: 443,
|
||||||
|
|
@ -267,12 +209,12 @@ var Getters = {
|
||||||
});
|
});
|
||||||
|
|
||||||
return callback(null, vids);
|
return callback(null, vids);
|
||||||
});*/
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/* youtube.com search */
|
/* youtube.com search */
|
||||||
ytSearch: async function (query, callback) {
|
ytSearch: function (query, callback) {
|
||||||
|
|
||||||
if(!Config.get("invidious-backend")){//legacy youtube backend (fucking yicky)
|
if(!Config.get("invidious-backend")){//legacy youtube backend (fucking yicky)
|
||||||
if (!Config.get("youtube-v3-key")) {
|
if (!Config.get("youtube-v3-key")) {
|
||||||
|
|
@ -297,33 +239,7 @@ var Getters = {
|
||||||
}).catch(function (err) {
|
}).catch(function (err) {
|
||||||
callback(err.message || err, null);
|
callback(err.message || err, null);
|
||||||
});
|
});
|
||||||
}else{
|
}else{//invidious api calls (google bad)
|
||||||
|
|
||||||
try{
|
|
||||||
var results = await YTDLP(`ytsearch8:${query}`,{
|
|
||||||
dumpSingleJson: true,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
var videos = new Array;
|
|
||||||
|
|
||||||
results.entries.forEach(function(result){
|
|
||||||
var meta = {
|
|
||||||
ytRating: result.like_count
|
|
||||||
}
|
|
||||||
|
|
||||||
var video = new Media(result.id, result.title, result.duration, "yt", meta);
|
|
||||||
video.thumb = {url: result.thumbnails[5].url};
|
|
||||||
|
|
||||||
videos.push(video);
|
|
||||||
});
|
|
||||||
|
|
||||||
callback(null, videos);
|
|
||||||
}catch(err){
|
|
||||||
callback(err.message || err, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
/*invidious api calls (o7 RIP 2018-2024)
|
|
||||||
var options = {
|
var options = {
|
||||||
host: Config.get("invidious-source"),
|
host: Config.get("invidious-source"),
|
||||||
port: 443,
|
port: 443,
|
||||||
|
|
@ -348,7 +264,7 @@ var Getters = {
|
||||||
});
|
});
|
||||||
|
|
||||||
return callback(null, vids.filter(rs => rs != null));
|
return callback(null, vids.filter(rs => rs != null));
|
||||||
});*/
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
@ -371,8 +287,6 @@ var Getters = {
|
||||||
},
|
},
|
||||||
|
|
||||||
/* dailymotion.com */
|
/* dailymotion.com */
|
||||||
//The dailymotion player has been broken, however their basic API remains intact.
|
|
||||||
//This will stay *for now* but will be replaced by yt-dlp at the first sign of resistance.
|
|
||||||
dm: function (id, callback) {
|
dm: function (id, callback) {
|
||||||
var m = id.match(/([\w-]+)/);
|
var m = id.match(/([\w-]+)/);
|
||||||
if (m) {
|
if (m) {
|
||||||
|
|
@ -668,114 +582,21 @@ var Getters = {
|
||||||
callback,
|
callback,
|
||||||
"As of July 2020, Mixer is no longer in service."
|
"As of July 2020, Mixer is no longer in service."
|
||||||
);
|
);
|
||||||
},
|
|
||||||
|
|
||||||
/*Internet Archive Bulk Grabber*/
|
|
||||||
ia: function(id, minDuration, callback){
|
|
||||||
try{
|
|
||||||
//Get metadata on the directory
|
|
||||||
var options = {
|
|
||||||
host: "archive.org",
|
|
||||||
port: 443,
|
|
||||||
path: "/metadata/" + id,
|
|
||||||
method: "GET",
|
|
||||||
timeout: 1000
|
|
||||||
};
|
|
||||||
|
|
||||||
//pull the URL
|
|
||||||
urlRetrieve(https, options, function (status, data) {
|
|
||||||
//if we fucked up
|
|
||||||
if(status !== 200) {
|
|
||||||
return callback("Archive.org HTTPS error code: " + status, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
//Parse the dump
|
|
||||||
var dump = JSON.parse(data);
|
|
||||||
|
|
||||||
|
|
||||||
//if we have files
|
|
||||||
if(dump.files != null){
|
|
||||||
var vids = new Array;
|
|
||||||
var derivative = new Array;
|
|
||||||
var media = new Array;
|
|
||||||
|
|
||||||
//sift through files to find .mp4's
|
|
||||||
dump.files.forEach(function(file){
|
|
||||||
//Skip out on videos that dont meet the requested minimum duration
|
|
||||||
if(file.length >= minDuration){
|
|
||||||
//if its a standard .mp4 (either MPEG, or h.264)
|
|
||||||
if(file.format == "h.264" || file.format == "MPEG4"){
|
|
||||||
//add the file to the video array
|
|
||||||
vids.push(file);
|
|
||||||
//if it's been transcoded by archive.org to ensure web-compatibility
|
|
||||||
}else if(file.format == "h.264 IA"){
|
|
||||||
//add the file to the derivative array
|
|
||||||
derivative.push(file);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//chose derivatives over originals to save on bandwith and ensure web-compatibility, even if they don't always look as nice :P
|
|
||||||
derivative.forEach(function(file){
|
|
||||||
//sift through standard files to find matching originals
|
|
||||||
for(var i = 0; i < vids.length; i++){
|
|
||||||
//if we have a match
|
|
||||||
if(vids[i].name == file.original){
|
|
||||||
//replace the file with the correct derivative
|
|
||||||
vids[i] = file;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
//Lets try this just using info from IA's api. It would take up way less fucking time, even if we can't fill in everything...
|
|
||||||
vids = vids.map(function (file) {
|
|
||||||
return new Media(`https://${dump.d1}${dump.dir}/${file.name}`, dump.metadata.title, file.length, "fi", {codec: "mov/h264"});
|
|
||||||
});
|
|
||||||
|
|
||||||
process.nextTick(callback, false, vids);
|
|
||||||
|
|
||||||
//if we fucked up some other way
|
|
||||||
}else if(dump.error != null){
|
|
||||||
return callback(`Archive.org error: ${dump.error}`);
|
|
||||||
}else{
|
|
||||||
return callback("Unkown metadata error from archive.org!");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
} catch (err) {
|
|
||||||
callback(err.message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
Getters: Getters,
|
Getters: Getters,
|
||||||
getMedia: function (id, type, callback, minDuration) {
|
getMedia: function (id, type, callback) {
|
||||||
if(type in this.Getters) {
|
if(type in this.Getters) {
|
||||||
LOGGER.info("Looking up %s:%s", type, id);
|
LOGGER.info("Looking up %s:%s", type, id);
|
||||||
lookupCounter.labels(type).inc(1, new Date());
|
lookupCounter.labels(type).inc(1, new Date());
|
||||||
if(type == "ia"){
|
|
||||||
this.Getters.ia(id, minDuration, callback);
|
|
||||||
}else{
|
|
||||||
this.Getters[type](id, callback);
|
this.Getters[type](id, callback);
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
callback("Unknown media type '" + type + "'", null);
|
callback("Unknown media type '" + type + "'", null);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
getRawCopy: async function (id, cb){
|
getYTRaw: function (id, cb){
|
||||||
try{
|
|
||||||
var video = await YTDLP(`youtu.be/${id}`,{
|
|
||||||
dumpSingleJson: true,
|
|
||||||
format: "b"
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
cb(video.requested_downloads[0].url);
|
|
||||||
}catch(err){
|
|
||||||
console.log(err.message);
|
|
||||||
}
|
|
||||||
/* Invidious Code (o7 RIP 2018-2024)
|
|
||||||
var options = {
|
var options = {
|
||||||
host: Config.get("invidious-source"),
|
host: Config.get("invidious-source"),
|
||||||
port: 443,
|
port: 443,
|
||||||
|
|
@ -785,8 +606,6 @@ module.exports = {
|
||||||
};
|
};
|
||||||
|
|
||||||
urlRetrieve(https, options, function (status, data) {
|
urlRetrieve(https, options, function (status, data) {
|
||||||
|
|
||||||
old invidious code (o7 2018 - 2024)
|
|
||||||
if(status !== 200) {
|
if(status !== 200) {
|
||||||
console.log("Invidious HTTPS error code: " + status);
|
console.log("Invidious HTTPS error code: " + status);
|
||||||
}
|
}
|
||||||
|
|
@ -796,7 +615,6 @@ module.exports = {
|
||||||
if(vid.formatStreams[0] != null){//TEMPORARY FOR FRONTEND DEV PURPOSES, PULL LINK AND SET AGAIN WHEN VIDEO QUEUED(shit expires)
|
if(vid.formatStreams[0] != null){//TEMPORARY FOR FRONTEND DEV PURPOSES, PULL LINK AND SET AGAIN WHEN VIDEO QUEUED(shit expires)
|
||||||
cb(vid.formatStreams[vid.formatStreams.length - 1].url);
|
cb(vid.formatStreams[vid.formatStreams.length - 1].url);
|
||||||
}
|
}
|
||||||
|
});
|
||||||
});*/
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -56,4 +56,4 @@ block content
|
||||||
| No spamming submit channel or chat
|
| No spamming submit channel or chat
|
||||||
p.
|
p.
|
||||||
Comments? Questions? Feature requests? DMCA Notices? <a href="mailto:ourforest@420blaze.it">Email us!</a>
|
Comments? Questions? Feature requests? DMCA Notices? <a href="mailto:ourforest@420blaze.it">Email us!</a>
|
||||||
h4 fore.st version: Pineapple Express += 3 (v1.1.3)
|
h4 fore.st version: Pineapple Express++ (v1.1.1)
|
||||||
|
|
|
||||||
|
|
@ -131,8 +131,6 @@ html(lang="en")
|
||||||
#plcontrol.btn-group
|
#plcontrol.btn-group
|
||||||
button#showmediaurl.btn.btn-sm.btn-default(title="Add video from URL", data-toggle="collapse", data-target="#addfromurl")
|
button#showmediaurl.btn.btn-sm.btn-default(title="Add video from URL", data-toggle="collapse", data-target="#addfromurl")
|
||||||
span.glyphicon.glyphicon-plus
|
span.glyphicon.glyphicon-plus
|
||||||
button#golive.btn.btn-sm.btn-danger(title="Go Live")
|
|
||||||
span.glyphicon.glyphicon-record
|
|
||||||
button#showsearch.btn.btn-sm.btn-default(title="Channel History + Video Search", data-toggle="collapse", data-target="#searchcontrol")
|
button#showsearch.btn.btn-sm.btn-default(title="Channel History + Video Search", data-toggle="collapse", data-target="#searchcontrol")
|
||||||
span.glyphicon.glyphicon-search
|
span.glyphicon.glyphicon-search
|
||||||
button#showplaylistmanager.btn.btn-sm.btn-default(title="Manage playlists", data-toggle="collapse", data-target="#playlistmanager")
|
button#showplaylistmanager.btn.btn-sm.btn-default(title="Manage playlists", data-toggle="collapse", data-target="#playlistmanager")
|
||||||
|
|
|
||||||
47
templates/google_drive_userscript.pug
Normal file
47
templates/google_drive_userscript.pug
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
extends layout.pug
|
||||||
|
|
||||||
|
block content
|
||||||
|
.col-md-8.col-md-offset-2
|
||||||
|
h1 Google Drive Userscript
|
||||||
|
h2 Disclaimer
|
||||||
|
.alert.alert-danger.messagebox
|
||||||
|
strong Unsupported
|
||||||
|
p.
|
||||||
|
This functionality is provided <strong>as-is</strong> for backwards
|
||||||
|
compatibility for existing users for whom it already is known to work.
|
||||||
|
There are many reasons, known and unknown, for which it may
|
||||||
|
<strong>not</strong> work for you; please note the staff in CyTube
|
||||||
|
support channels cannot provide any troubleshooting assistance and you
|
||||||
|
will be asked to simply use a different video provider.
|
||||||
|
p.
|
||||||
|
This functionality was originally added so that users could share their
|
||||||
|
own personal videos stored in their Drive. No support whatsoever will
|
||||||
|
be provided to users attempting to use it to circumvent copyright
|
||||||
|
restrictions on third-party video hosts.
|
||||||
|
h2 How It Works
|
||||||
|
p.
|
||||||
|
The userscript is a short script that you can install using a browser
|
||||||
|
extension such as Greasemonkey or Tampermonkey that runs on the page
|
||||||
|
and provides additional functionality needed to play Google Drive
|
||||||
|
videos.
|
||||||
|
h2 Installation
|
||||||
|
ul
|
||||||
|
li
|
||||||
|
strong Chrome
|
||||||
|
| —Install <a href="https://chrome.google.com/webstore/detail/tampermonkey/dhdgffkkebhmkfjojejmpbldmpobfkfo" target="_blank">Tampermonkey</a>.
|
||||||
|
li
|
||||||
|
strong Firefox
|
||||||
|
| —Install <a href="https://addons.mozilla.org/en-US/firefox/addon/tampermonkey/" target="_blank">Tampermonkey</a>
|
||||||
|
| or <a href="https://addons.mozilla.org/en-US/firefox/addon/greasemonkey/" target="_blank">Greasemonkey</a>.
|
||||||
|
li
|
||||||
|
strong Other Browsers
|
||||||
|
| —Install the appropriate userscript plugin for your browser.
|
||||||
|
| Tampermonkey supports many browsers besides Chrome.
|
||||||
|
p.
|
||||||
|
Once you have installed the userscript manager addon for your browser,
|
||||||
|
you can <a href="/js/cytube-google-drive.user.js" target="_blank">
|
||||||
|
install the userscript</a>. If this link 404s, it means the administrator
|
||||||
|
of this server hasn't generated it yet.
|
||||||
|
p.
|
||||||
|
You can find a guide with screenshots of the installation process
|
||||||
|
<a href="https://github.com/calzoneman/sync/wiki/Google-Drive-Userscript-Installation-Guide" target="_blank">on GitHub</a>.
|
||||||
|
|
@ -36,11 +36,8 @@ mixin us-general
|
||||||
option(value="/css/themes/fore.st.dusk.lite.css") Dusk [Smoked Quartz]
|
option(value="/css/themes/fore.st.dusk.lite.css") Dusk [Smoked Quartz]
|
||||||
option(value="/css/themes/fore.st.neon.css") Neon [Frosted Glass]
|
option(value="/css/themes/fore.st.neon.css") Neon [Frosted Glass]
|
||||||
option(value="/css/themes/fore.st.neon.lite.css") Neon [Smoked Quartz]
|
option(value="/css/themes/fore.st.neon.lite.css") Neon [Smoked Quartz]
|
||||||
option(disabled="true") ---Holiday Themes---
|
|
||||||
option(value="/css/themes/fore.st.candycorn.css") Candycorn [Frosted Glass]
|
option(value="/css/themes/fore.st.candycorn.css") Candycorn [Frosted Glass]
|
||||||
option(value="/css/themes/fore.st.candycorn.lite.css") Candycorn [Smoked Quartz]
|
option(value="/css/themes/fore.st.candycorn.lite.css") Candycorn [Smoked Quartz]
|
||||||
option(value="/css/themes/fore.st.mistletoe.css") Mistletoe [Frosted Glass]
|
|
||||||
option(value="/css/themes/fore.st.mistletoe.lite.css") Mistletoe [Smoked Quartz]
|
|
||||||
.col-sm-4
|
.col-sm-4
|
||||||
.col-sm-8
|
.col-sm-8
|
||||||
+rcheckbox("us-no-channelcss", "Ignore Channel CSS")
|
+rcheckbox("us-no-channelcss", "Ignore Channel CSS")
|
||||||
|
|
|
||||||
|
|
@ -297,39 +297,3 @@ wrasslin
|
||||||
her
|
her
|
||||||
yikes
|
yikes
|
||||||
booyak
|
booyak
|
||||||
bust
|
|
||||||
bustin
|
|
||||||
weedeven
|
|
||||||
even
|
|
||||||
succ
|
|
||||||
barm
|
|
||||||
propane
|
|
||||||
dope
|
|
||||||
yep
|
|
||||||
dangit
|
|
||||||
bobby
|
|
||||||
dabs
|
|
||||||
mclovin
|
|
||||||
delaware
|
|
||||||
tight
|
|
||||||
doh
|
|
||||||
ass
|
|
||||||
dick
|
|
||||||
scottbaio
|
|
||||||
resin
|
|
||||||
penisman
|
|
||||||
punchy
|
|
||||||
hotto
|
|
||||||
geekedup
|
|
||||||
comedy
|
|
||||||
bake
|
|
||||||
baked
|
|
||||||
shweed
|
|
||||||
kungfu
|
|
||||||
dream
|
|
||||||
MDK
|
|
||||||
3ven
|
|
||||||
SmoothAsEggs
|
|
||||||
nosedive
|
|
||||||
rip
|
|
||||||
slorp
|
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
BIN
www/img/snow.png
BIN
www/img/snow.png
Binary file not shown.
|
Before Width: | Height: | Size: 40 KiB |
BIN
www/img/xmas.png
BIN
www/img/xmas.png
Binary file not shown.
|
Before Width: | Height: | Size: 17 MiB |
|
|
@ -748,7 +748,7 @@ Callbacks = {
|
||||||
li.attr("title", data[i].queueby
|
li.attr("title", data[i].queueby
|
||||||
? ("Added by: " + data[i].queueby)
|
? ("Added by: " + data[i].queueby)
|
||||||
: "Added by: Unknown");
|
: "Added by: Unknown");
|
||||||
if(data[i].media.type === "fi" && data[i].media.id.includes("expires=")){
|
if(data[i].media.type === "fi"){
|
||||||
li.attr("id", "filei");
|
li.attr("id", "filei");
|
||||||
}
|
}
|
||||||
if(data[i].media.isBump){
|
if(data[i].media.isBump){
|
||||||
|
|
@ -779,7 +779,7 @@ Callbacks = {
|
||||||
activeItem = data.uid;
|
activeItem = data.uid;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(data.item.media.type === "fi" && data.item.media.id.includes("expires=")){
|
if(data.item.media.type === "fi"){
|
||||||
li.attr("id", "filei");
|
li.attr("id", "filei");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var CL_VERSION = "1.1.3";
|
var CL_VERSION = "1.1.1";
|
||||||
var GS_VERSION = 1.7; // Google Drive Userscript
|
var GS_VERSION = 1.7; // Google Drive Userscript
|
||||||
|
|
||||||
var CLIENT = {
|
var CLIENT = {
|
||||||
|
|
|
||||||
|
|
@ -40,9 +40,7 @@ function dispSTimes(){//update sTimes
|
||||||
$(".pluid-" + startTimes[0][i]).children(".qe_sTime").text(ltimeString);// set current item qe_sTime innerHTML to ptimeString
|
$(".pluid-" + startTimes[0][i]).children(".qe_sTime").text(ltimeString);// set current item qe_sTime innerHTML to ptimeString
|
||||||
$(".pluid-" + startTimes[0][i]).children(".qe_pref").text(ptimeString);// set current item qe_sTime innerHTML to ptimeString
|
$(".pluid-" + startTimes[0][i]).children(".qe_pref").text(ptimeString);// set current item qe_sTime innerHTML to ptimeString
|
||||||
|
|
||||||
if($(".pluid-" + startTimes[0][i]) != null && $(".pluid-" + startTimes[0][i]).data("media") != null){
|
|
||||||
st.setTime(st.getTime() + ($(".pluid-" + startTimes[0][i]).data("media").seconds * 1000));//calc end time
|
st.setTime(st.getTime() + ($(".pluid-" + startTimes[0][i]).data("media").seconds * 1000));//calc end time
|
||||||
}
|
|
||||||
|
|
||||||
$(".pluid-" + startTimes[0][i]).children(".qe_etime").text("enddate: " + st.toLocaleTimeString().replace(" ","") + " " + st.toLocaleDateString());//Set endtime (lil dirty but so is this script :P)
|
$(".pluid-" + startTimes[0][i]).children(".qe_etime").text("enddate: " + st.toLocaleTimeString().replace(" ","") + " " + st.toLocaleDateString());//Set endtime (lil dirty but so is this script :P)
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1773,7 +1773,7 @@
|
||||||
e = error1;
|
e = error1;
|
||||||
return console.error(e);
|
return console.error(e);
|
||||||
}
|
}
|
||||||
} else if ((USEROPTS.yt_source !== "OFYT" && data.type == "yt") || data.type == "dm") {
|
} else if ((USEROPTS.yt_source !== "OFYT" && data.type == "yt")) {
|
||||||
data.ofyt = data.id;
|
data.ofyt = data.id;
|
||||||
data.id = data.meta.rawLink;//set link and spoof mov/h264
|
data.id = data.meta.rawLink;//set link and spoof mov/h264
|
||||||
data.type = "fi";
|
data.type = "fi";
|
||||||
|
|
|
||||||
35
www/js/ui.js
35
www/js/ui.js
|
|
@ -686,7 +686,6 @@ function queue(pos, src) {
|
||||||
var duration = undefined;
|
var duration = undefined;
|
||||||
var title = undefined;
|
var title = undefined;
|
||||||
var subtitle = "";
|
var subtitle = "";
|
||||||
var minDuration = 0;
|
|
||||||
if (data.type === "fi") {
|
if (data.type === "fi") {
|
||||||
if (data.id.match(/^http:/)) {
|
if (data.id.match(/^http:/)) {
|
||||||
Callbacks.queueFail({
|
Callbacks.queueFail({
|
||||||
|
|
@ -717,12 +716,7 @@ function queue(pos, src) {
|
||||||
// Raw files allow title overrides since the ffprobe tag data
|
// Raw files allow title overrides since the ffprobe tag data
|
||||||
// is not always correct.
|
// is not always correct.
|
||||||
title = $("#addfromurl-title-val").val();
|
title = $("#addfromurl-title-val").val();
|
||||||
subtitle = "";
|
subtitle = $("#addfromurl-subtitle-val").val();
|
||||||
}else if(data.type === "ia"){
|
|
||||||
title = $("#addfromurl-title-val").val();
|
|
||||||
minDuration = $("#addfromurl-duration-val").val();
|
|
||||||
//Convert minDuration to a number that represents seconds instead of a string which represents minutes
|
|
||||||
minDuration = (minDuration == "" ? 0 : (Number.parseInt(minDuration) * 60));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (data.id == null || data.type == null) {
|
if (data.id == null || data.type == null) {
|
||||||
|
|
@ -737,7 +731,6 @@ function queue(pos, src) {
|
||||||
pos: pos,
|
pos: pos,
|
||||||
duration: duration,
|
duration: duration,
|
||||||
title: title,
|
title: title,
|
||||||
minDuration: minDuration,
|
|
||||||
temp: addTemp,
|
temp: addTemp,
|
||||||
link: link,
|
link: link,
|
||||||
subtitle: subtitle
|
subtitle: subtitle
|
||||||
|
|
@ -777,28 +770,15 @@ $("#queue_end").click(queue.bind(this, "end", "url"));
|
||||||
$("#ce_queue_next").click(queue.bind(this, "next", "customembed"));
|
$("#ce_queue_next").click(queue.bind(this, "next", "customembed"));
|
||||||
$("#ce_queue_end").click(queue.bind(this, "end", "customembed"));
|
$("#ce_queue_end").click(queue.bind(this, "end", "customembed"));
|
||||||
|
|
||||||
$("#golive").click(function(ev){
|
|
||||||
socket.emit('queue', {
|
|
||||||
id: "https://stream.ourfore.st",
|
|
||||||
type: 'hl',
|
|
||||||
pos: "next",
|
|
||||||
minDuration: 0,
|
|
||||||
temp: true,
|
|
||||||
subtitle: ''
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#mediaurl").keyup(function(ev) {
|
$("#mediaurl").keyup(function(ev) {
|
||||||
if (ev.keyCode === 13) {
|
if (ev.keyCode === 13) {
|
||||||
queue("end", "url");
|
queue("end", "url");
|
||||||
} else {
|
} else {
|
||||||
var editTitle = false;
|
var editTitle = false;
|
||||||
var editDur = false;
|
|
||||||
try {
|
try {
|
||||||
editTitle = (parseMediaLink($("#mediaurl").val()).type === "fi" || parseMediaLink($("#mediaurl").val()).type === "ia");
|
if (parseMediaLink($("#mediaurl").val()).type === "fi") {
|
||||||
|
editTitle = true;
|
||||||
|
}
|
||||||
editDur = (parseMediaLink($("#mediaurl").val()).type === "ia");
|
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -824,11 +804,10 @@ $("#mediaurl").keyup(function(ev) {
|
||||||
})
|
})
|
||||||
.appendTo($("#addfromurl-title")).show("blind");//append and show
|
.appendTo($("#addfromurl-title")).show("blind");//append and show
|
||||||
|
|
||||||
if(editDur){
|
|
||||||
$("<input/>").addClass("form-control")//create title field
|
$("<input/>").addClass("form-control")//create title field
|
||||||
.attr("type", "text")//the attributes
|
.attr("type", "text")//the attributes
|
||||||
.attr("id", "addfromurl-duration-val")
|
.attr("id", "addfromurl-subtitle-val")
|
||||||
.attr("placeholder", "Minimum Duration Filter")
|
.attr("placeholder", "Alternate Subtitle Track")
|
||||||
.attr("style", "display: none; width: 100%;")
|
.attr("style", "display: none; width: 100%;")
|
||||||
.keydown(function (ev) {
|
.keydown(function (ev) {
|
||||||
if (ev.keyCode === 13) {
|
if (ev.keyCode === 13) {
|
||||||
|
|
@ -837,8 +816,6 @@ $("#mediaurl").keyup(function(ev) {
|
||||||
})
|
})
|
||||||
.appendTo($("#addfromurl-title")).show("blind");//append and show
|
.appendTo($("#addfromurl-title")).show("blind");//append and show
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
$("#addfromurl-title").hide("blind");
|
$("#addfromurl-title").hide("blind");
|
||||||
$("#addfromurl-title").remove();//otherwise remove
|
$("#addfromurl-title").remove();//otherwise remove
|
||||||
|
|
|
||||||
|
|
@ -1615,13 +1615,6 @@ function parseMediaLink(url) {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
if((m = url.match(/archive\.org\/(?:details|download)\/([a-zA-Z0-9_-]+)(?!.|\/)/))){
|
|
||||||
return{
|
|
||||||
id: m[1],
|
|
||||||
type: "ia"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Shorthand URIs */
|
/* Shorthand URIs */
|
||||||
// So we still trim DailyMotion URLs
|
// So we still trim DailyMotion URLs
|
||||||
if((m = url.match(/^dm:([^\?&#_]+)/))) {
|
if((m = url.match(/^dm:([^\?&#_]+)/))) {
|
||||||
|
|
@ -3452,7 +3445,7 @@ function startQueueSpinner(data) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var id = data.id;
|
var id = data.id;
|
||||||
if (data.type === "yp" || data.type === "ia") {
|
if (data.type === "yp") {
|
||||||
id = "$any";
|
id = "$any";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3500,7 +3493,6 @@ function stopQueueSpinner(data) {
|
||||||
$("#queueprogress").data("queue-id") === data.id);
|
$("#queueprogress").data("queue-id") === data.id);
|
||||||
shouldRemove = shouldRemove || data === null;
|
shouldRemove = shouldRemove || data === null;
|
||||||
shouldRemove = shouldRemove || $("#queueprogress").data("queue-id") === "$any";
|
shouldRemove = shouldRemove || $("#queueprogress").data("queue-id") === "$any";
|
||||||
//This is a gross way to fix the issue with IA but it works, and it's not like cytube was a pretty codebase anywho...
|
|
||||||
if (shouldRemove) {
|
if (shouldRemove) {
|
||||||
$("#queueprogress").remove();
|
$("#queueprogress").remove();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue