import axios from "axios"; import { Downloader } from "./downloader"; import { Links } from "./links"; import { random_int } from "./tools"; let links = new Links; let unixtime = () => { return new Date().getTime()/1000; }; export class UrlPool { id: string; storage: UrlPoolStorage; urls: string[] = []; used: boolean[] = []; valid_to: Date; generating = false; last_generated: number = unixtime(); downloaders: Downloader[] = []; total_size: number = 0; is_direct = false; 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() { let page = await axios.get("https://uloz.to/file/"+this.id, {validateStatus: null}); if(page.status == 404) return false; // TODO: Add quick download support // let quick_dl_url = links.regex_parse(new RegExp('href="(/quickDownload/[^"]*)"'), page.data, 1); this.is_direct = 'js-free-download-button-direct' == links.regex_parse(new RegExp('data-href="/download-dialog/free/[^"]+" +class=".+(js-free-download-button-direct).+"'), page.data, 1); 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]); this.generating = true; return true; } get_raw(): [number, string] | undefined { for(let i=0; i { 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); } else { this.request_generation(); } }, 100); }); } return(i: number, sucess: boolean = true) { setTimeout(() => this.used[i] = false, sucess ? random_int(1000, 5000) : random_int(5000, 60000)); } add(url: string) { this.urls.push(url); this.used.push(false); } available(count?: number) { let available: number[] = []; for(let i=0; i unixtime()) return; console.log(this.id, "| new link:", (await this.generate()) ? true : false); } async generate(): Promise { this.last_generated = unixtime(); try { let link = await (this.is_direct ? links.direct_link(this.id) : links.captcha_link(this.id)); if(link) this.add(link); return link; } catch(e) { console.log(e); this.generating = false; return undefined; } } get_downloader(from: number) { let d = new Downloader(this, from); this.downloaders.push(d); 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 { return this.pools[id] ? this.pools[id] : await this.new(id); } async new(id: string): Promise { let pool = new UrlPool(this, id); let check = await pool.init(); if(!check) return undefined; pool.request_generation(); this.pools[id] = pool; return pool; } }