Added GUI & fixed bugs

This commit is contained in:
Filip Znachor 2022-11-13 11:37:30 +01:00
parent 51d31d16fa
commit a04efa5042
7 changed files with 99 additions and 36 deletions

View file

@ -6,7 +6,8 @@ export class Downloader {
pool: UrlPool;
chunks: {[U: string]: (Buffer | null)} = {};
chunk_size = Math.round(0.3*1024*1024);
chunk_size = Math.round(1*1024*1024);
cache_size = 15;
loading: boolean = false;
destroyed: boolean = false;
@ -44,7 +45,7 @@ export class Downloader {
cache() {
let chunks: string[] = [];
let existing_chunks = Object.keys(this.chunks);
for(let i=0; i<15; i++) {
for(let i=0; i<this.cache_size; i++) {
chunks.push((this.from+(this.chunk_size*i)).toString());
}
chunks.forEach(from => {

View file

@ -1,30 +0,0 @@
<head>
<link href="https://vjs.zencdn.net/7.17.0/video-js.css" rel="stylesheet" />
<!-- If you'd like to support IE8 (for Video.js versions prior to v7) -->
<!-- <script src="https://vjs.zencdn.net/ie8/1.1.2/videojs-ie8.min.js"></script> -->
</head>
<body>
<video
id="my-video"
class="video-js"
controls
preload="auto"
width="640"
height="264"
poster="MY_VIDEO_POSTER.jpg"
data-setup="{}"
>
<source src="/api/stream/ulozto_id" type="video/mp4" />
<p class="vjs-no-js">
To view this video please enable JavaScript, and consider upgrading to a
web browser that
<a href="https://videojs.com/html5-video-support/" target="_blank"
>supports HTML5 video</a
>
</p>
</video>
<script src="https://vjs.zencdn.net/7.17.0/video.min.js"></script>
</body>

View file

@ -1,4 +1,4 @@
lockfileVersion: 5.3
lockfileVersion: 5.4
specifiers:
'@types/express': ^4.17.13
@ -130,6 +130,8 @@ packages:
dependencies:
follow-redirects: 1.5.10
is-buffer: 2.0.5
transitivePeerDependencies:
- supports-color
dev: false
/axios/0.26.0:
@ -160,6 +162,8 @@ packages:
qs: 6.9.7
raw-body: 2.4.3
type-is: 1.6.18
transitivePeerDependencies:
- supports-color
dev: false
/bytes/3.1.2:
@ -212,12 +216,22 @@ packages:
/debug/2.6.9:
resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.0.0
dev: false
/debug/3.1.0:
resolution: {integrity: sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==}
peerDependencies:
supports-color: '*'
peerDependenciesMeta:
supports-color:
optional: true
dependencies:
ms: 2.0.0
dev: false
@ -305,6 +319,8 @@ packages:
type-is: 1.6.18
utils-merge: 1.0.1
vary: 1.1.2
transitivePeerDependencies:
- supports-color
dev: false
/extend/3.0.2:
@ -335,6 +351,8 @@ packages:
parseurl: 1.3.3
statuses: 1.5.0
unpipe: 1.0.0
transitivePeerDependencies:
- supports-color
dev: false
/follow-redirects/1.14.9:
@ -352,6 +370,8 @@ packages:
engines: {node: '>=4.0'}
dependencies:
debug: 3.1.0
transitivePeerDependencies:
- supports-color
dev: false
/forever-agent/0.6.1:
@ -639,6 +659,8 @@ packages:
on-finished: 2.3.0
range-parser: 1.2.1
statuses: 1.5.0
transitivePeerDependencies:
- supports-color
dev: false
/serve-static/1.14.2:
@ -649,6 +671,8 @@ packages:
escape-html: 1.0.3
parseurl: 1.3.3
send: 0.17.2
transitivePeerDependencies:
- supports-color
dev: false
/setprototypeof/1.2.0:
@ -707,6 +731,8 @@ packages:
dependencies:
axios: 0.18.1
socks-proxy-agent: 4.0.2
transitivePeerDependencies:
- supports-color
dev: false
/tor-request/3.1.0:

BIN
public/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

38
public/index.html Normal file
View file

@ -0,0 +1,38 @@
<!DOCTYPE html>
<html>
<head>
<title>Ulož.to Rychle</title>
<style>
body {display: flex; justify-content: center; align-items: center; height: 100vh; font-family: sans-serif; text-align: center; font-size: 20px; background: #4a0f4d; color: #fff;}
.page {max-width: 550px; width: 100%;}
.input {display: flex; gap: 5px; flex-flow: row; justify-content: space-between; width: 100%; margin-top: 30px;}
.input * {background-color: #702673; border: 2px solid #330a35; border-radius: 5px; padding: 10px 15px; font-size: 17px; outline: 0; color: #fff;}
.input input {width: 100%;}
.input button {background: #702673;}
.input button:hover {background-color: #4a0f4d; cursor: pointer;}
.result {justify-content: center; margin-top: 20px; font-size: 17px; display: block; display: flex; gap: 10px;}
.result a {color: #fff5;}
</style>
</head>
<body>
<div class="page">
<h1>Ulož.to Rychle</h1>
<p>Stahujte z Ulož.to vysokou rychlostí</p>
<div class="input">
<input placeholder="Vložte odkaz z Ulož.to" /> <button onclick="download();">Získat</button>
</div>
<div class="result"></div>
</div>
<script>
function download() {
let url = document.querySelector("input").value;
let regex = new RegExp(/https:\/\/.*(ulozto\.cz|uloz\.to)\/file\/(.*?)\/.*/gm);
let res = regex.exec(url);
if(!res) return alert("Neplatná URL!");
let id = res[2];
let new_url = new URL(`/u/${id}`, location.origin);
document.querySelector(".result").innerHTML = `<code>${new_url}</code> <a href="${new_url}" download>Stáhnout</a>`;
}
</script>
</body>
</html>

View file

@ -12,10 +12,13 @@ function sleep(ms: number) {
export class UrlPool {
id: string;
storage: UrlPoolStorage;
urls: string[] = [];
used: boolean[] = [];
valid_to: Date;
generating = false;
downloaders: Downloader[] = [];
@ -23,8 +26,11 @@ export class UrlPool {
is_direct = false;
ready = false;
constructor(id: string) {
constructor(storage: UrlPoolStorage, id: string) {
this.valid_to = new Date();
this.valid_to.setDate(this.valid_to.getDate() + 1);
this.id = id;
this.storage = storage;
}
async init() {
@ -49,6 +55,7 @@ export class UrlPool {
this.ready = true;
return true;
}
get_raw(): [number, string] | undefined {
@ -119,18 +126,37 @@ export class UrlPool {
return d;
}
destroy() {
this.downloaders.forEach(d => d.destroy());
delete this.storage.pools[this.id];
}
}
export class UrlPoolStorage {
validity_interval: NodeJS.Timer;
pools: {[U: string]: UrlPool} = {};
constructor() {
this.validity_interval = setInterval(this.validity_check, 1000*60*60);
}
validity_check() {
for(let i in this.pools) {
if(this.pools[i].valid_to.getTime() < new Date().getTime()) {
this.pools[i].destroy();
}
}
}
async get(id: string): Promise<UrlPool | undefined> {
return this.pools[id] ? this.pools[id] : await this.new(id);
}
async new(id: string): Promise<UrlPool | undefined> {
let pool = new UrlPool(id);
let pool = new UrlPool(this, id);
let check = await pool.init();
if(!check) return undefined;
pool.start_generation();

View file

@ -11,6 +11,8 @@ export class Webserver {
const app = express();
app.use(express.static('public'));
app.get("/status/:id", async (req, res) => {
let p = await storage.get(req.params.id);
@ -37,7 +39,7 @@ export class Webserver {
});
app.get("/stream/:id", async (req, res) => {
app.get("/u/:id", async (req, res) => {
let p = await storage.get(req.params.id);
if(!p) {