This repository has been archived on 2023-11-29. You can view files and clone it, but cannot push or open issues or pull requests.
Uloz.to-rychle/urlpool.ts

172 lines
3.8 KiB
TypeScript
Raw Permalink Normal View History

2022-04-23 01:37:41 +02:00
import axios from "axios";
2022-03-14 20:18:08 +01:00
import { Downloader } from "./downloader";
import { Links } from "./links";
import { random_int } from "./tools";
2023-02-06 22:18:56 +01:00
import { JSDOM } from "jsdom";
2022-03-14 20:18:08 +01:00
let links = new Links;
2023-02-06 21:43:07 +01:00
let unixtime = () => {
return new Date().getTime()/1000;
};
2022-03-14 20:18:08 +01:00
2022-02-23 19:50:47 +01:00
export class UrlPool {
2022-04-23 01:37:41 +02:00
id: string;
2022-11-13 11:37:30 +01:00
storage: UrlPoolStorage;
2022-04-23 14:49:12 +02:00
2022-04-23 01:37:41 +02:00
urls: string[] = [];
2022-02-23 19:50:47 +01:00
used: boolean[] = [];
2022-04-23 14:49:12 +02:00
2022-11-13 11:37:30 +01:00
valid_to: Date;
2022-03-14 20:18:08 +01:00
generating = false;
2023-02-06 21:43:07 +01:00
last_generated: number = unixtime();
2022-04-23 14:49:12 +02:00
downloaders: Downloader[] = [];
2023-02-06 22:18:56 +01:00
file_name?: string;
2022-04-23 14:49:12 +02:00
total_size: number = 0;
2022-02-23 19:50:47 +01:00
2022-11-13 11:37:30 +01:00
constructor(storage: UrlPoolStorage, id: string) {
this.valid_to = new Date();
this.valid_to.setDate(this.valid_to.getDate() + 1);
2022-04-23 01:37:41 +02:00
this.id = id;
2022-11-13 11:37:30 +01:00
this.storage = storage;
2022-04-23 01:37:41 +02:00
}
async init() {
2022-04-23 14:49:12 +02:00
2022-04-23 01:37:41 +02:00
let page = await axios.get("https://uloz.to/file/"+this.id, {validateStatus: null});
if(page.status == 404) return false;
2023-02-06 22:18:56 +01:00
let dom = new JSDOM(page.data);
2022-04-23 01:37:41 +02:00
// TODO: Add quick download support
// let quick_dl_url = links.regex_parse(new RegExp('href="(/quickDownload/[^"]*)"'), page.data, 1);
2023-02-06 22:18:56 +01:00
let filename = dom.window.document.querySelector(".jsFileTitle");
if(filename && filename.textContent) {
this.file_name = filename.textContent.trim();
}
2022-04-23 14:49:12 +02:00
await this.generate();
let url = await this.get();
if(!url) throw "No available URL in pool!";
let r = await axios.get(url[1], {
responseType: 'arraybuffer',
headers: {
Range: `bytes=0-0`
}
});
this.total_size = parseInt(r.headers["content-range"].split("/")[1]);
this.return(url[0]);
2023-02-06 21:43:07 +01:00
this.generating = true;
2022-04-23 01:37:41 +02:00
return true;
2022-11-13 11:37:30 +01:00
2022-02-23 19:50:47 +01:00
}
get_raw(): [number, string] | undefined {
for(let i=0; i<this.urls.length; i++) {
if(this.used[i]) continue;
this.used[i] = true;
return [i, this.urls[i]];
}
}
async get(): Promise<[number, string] | undefined> {
let url = this.get_raw();
if(url) return url;
return new Promise((complete) => {
let check = setInterval(() => {
let url = this.get_raw();
if(url) {
clearInterval(check);
complete(url);
2023-02-06 21:43:07 +01:00
} else {
this.request_generation();
2022-02-23 19:50:47 +01:00
}
2022-03-14 20:18:08 +01:00
}, 100);
2022-02-23 19:50:47 +01:00
});
}
return(i: number, sucess: boolean = true) {
2023-02-07 14:02:37 +01:00
setTimeout(() => this.used[i] = false, sucess ? random_int(2000, 5000) : random_int(10000, 60000));
2022-02-23 19:50:47 +01:00
}
2022-03-14 20:18:08 +01:00
add(url: string) {
this.urls.push(url);
this.used.push(false);
}
2022-02-23 19:50:47 +01:00
available(count?: number) {
let available: number[] = [];
for(let i=0; i<this.used.length; i++) {
if(!this.used[i]) {
available.push(i);
}
}
return count ? available.slice(0, count) : available;
}
2023-02-06 21:43:07 +01:00
async request_generation() {
if(!this.generating || this.last_generated+10 > unixtime()) return;
console.log(this.id, "| new link:", (await this.generate()) ? true : false);
2022-03-14 20:18:08 +01:00
}
2022-04-23 01:37:41 +02:00
async generate(): Promise<string | undefined> {
2023-02-06 21:43:07 +01:00
this.last_generated = unixtime();
2022-04-23 01:37:41 +02:00
try {
let link = await links.captcha_link(this.id);
2022-04-23 01:37:41 +02:00
if(link) this.add(link);
return link;
2022-04-23 14:49:12 +02:00
} catch(e) {
console.log(e);
this.generating = false;
2022-04-23 01:37:41 +02:00
return undefined;
}
}
2022-04-23 14:49:12 +02:00
get_downloader(from: number) {
let d = new Downloader(this, from);
this.downloaders.push(d);
return d;
2022-03-14 20:18:08 +01:00
}
2022-11-13 11:37:30 +01:00
destroy() {
this.downloaders.forEach(d => d.destroy());
delete this.storage.pools[this.id];
}
2022-03-14 20:18:08 +01:00
}
export class UrlPoolStorage {
2022-11-13 11:37:30 +01:00
validity_interval: NodeJS.Timer;
2022-03-14 20:18:08 +01:00
pools: {[U: string]: UrlPool} = {};
2022-11-13 11:37:30 +01:00
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();
}
}
}
2022-04-23 01:37:41 +02:00
async get(id: string): Promise<UrlPool | undefined> {
return this.pools[id] ? this.pools[id] : await this.new(id);
2022-03-14 20:18:08 +01:00
}
2022-04-23 01:37:41 +02:00
async new(id: string): Promise<UrlPool | undefined> {
2022-11-13 11:37:30 +01:00
let pool = new UrlPool(this, id);
2022-04-23 01:37:41 +02:00
let check = await pool.init();
if(!check) return undefined;
2023-02-06 21:43:07 +01:00
pool.request_generation();
2022-03-14 20:18:08 +01:00
this.pools[id] = pool;
return pool;
}
2022-02-23 19:50:47 +01:00
}