Skip to content

Commit

Permalink
Merge pull request #50 from vitalygashkov/next
Browse files Browse the repository at this point in the history
Kinopoisk captcha improvements, IVI streams debug logging
  • Loading branch information
vitalygashkov authored Nov 25, 2023
2 parents 1eca81a + 04fddae commit d2114b3
Show file tree
Hide file tree
Showing 13 changed files with 200 additions and 224 deletions.
4 changes: 3 additions & 1 deletion .github/FUNDING.yml
Original file line number Diff line number Diff line change
@@ -1 +1,3 @@
custom: ['boosty.to/vitalygashkov']
patreon: vitalygashkov
ko_fi: vitalygashkov
custom: ['PayPal.me/vitalygashkov', 'boosty.to/vitalygashkov/donate']
5 changes: 3 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "streamyx",
"version": "3.6.30",
"version": "3.6.31",
"author": "Vitaly Gashkov <[email protected]>",
"description": "Command-line video downloader",
"main": "dist/streamyx.js",
Expand Down
74 changes: 54 additions & 20 deletions src/args.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ const config: ParseArgsConfigWithDescriptions = {
},
};

const getProcessedArgs = () => {
const getProcessedArgs = (): RunArgs => {
const args = parseArgs(config);

// TODO: Remove when parseArgs will be stable
Expand All @@ -112,30 +112,30 @@ const getProcessedArgs = () => {
}

return {
urls: args.positionals,
urls: args.positionals as string[],
videoHeight: parseInt(String(values['video-quality'] || '').replaceAll('p', '')),
audioQuality: values['audio-quality'],
audioQuality: values['audio-quality'] ? String(values['audio-quality']) : undefined,
episodes: parseNumberRange(String(values['episodes'] || '')),
seasons: parseNumberRange(String(values['seasons'] || '')),
movieTemplate: values['movie-template'],
episodeTemplate: values['episode-template'],
movieTemplate: String(values['movie-template']),
episodeTemplate: String(values['episode-template']),
connections: parseInt(String(values['connections'])),
hdr: values['hdr'],
'3d': values['3d'],
hardsub: values['hardsub'],
hdr: Boolean(values['hdr']),
'3d': Boolean(values['3d']),
hardsub: Boolean(values['hardsub']),
subtitleLanguages: parseArrayFromString(String(values['subs-lang'] || '')),
audioLanguages: parseArrayFromString(String(values['audio-lang'] || '')),
skipSubtitles: values['skip-subs'],
skipAudio: values['skip-audio'],
skipVideo: values['skip-video'],
skipMux: values['skip-mux'],
trimBegin: values['trim-begin'],
trimEnd: values['trim-end'],
pssh: String(values['pssh'] || ''),
headers: parseHeadersFromString(String(values['headers'] || '')),
debug: values['debug'],
version: values['version'],
help: values['help'],
skipSubtitles: Boolean(values['skip-subs']),
skipAudio: Boolean(values['skip-audio']),
skipVideo: Boolean(values['skip-video']),
skipMux: Boolean(values['skip-mux']),
trimBegin: values['trim-begin'] ? String(values['trim-begin']) : undefined,
trimEnd: values['trim-end'] ? String(values['trim-end']) : undefined,
pssh: values['pssh'] ? String(values['pssh']) : undefined,
headers: values['headers'] ? parseHeadersFromString(String(values['headers'])) : undefined,
debug: Boolean(values['debug']),
version: Boolean(values['version']),
help: Boolean(values['help']),
};
};

Expand Down Expand Up @@ -170,6 +170,33 @@ const printOptions = (options: Record<string, Option> = {}) => {
}
};

export type RunArgs = {
urls: string[];
videoHeight?: number;
audioQuality?: string;
episodes: number[];
seasons: number[];
movieTemplate: string;
episodeTemplate: string;
connections: number;
hdr: boolean;
'3d': boolean;
hardsub: boolean;
subtitleLanguages: string[];
audioLanguages: string[];
skipSubtitles: boolean;
skipAudio: boolean;
skipVideo: boolean;
skipMux: boolean;
trimBegin?: string;
trimEnd?: string;
pssh?: string;
headers?: Record<string, string>;
debug: boolean;
version: boolean;
help: boolean;
};

const printHelp = () => {
printDescription();
printVersion();
Expand All @@ -178,4 +205,11 @@ const printHelp = () => {
printOptions(config.options);
};

export { getProcessedArgs, printVersion, printHelp };
const loadArgs = () => {
const args = getProcessedArgs();
if (args.version) printVersion();
if (args.help) printHelp();
return args;
};

export { getProcessedArgs, printVersion, printHelp, loadArgs };
29 changes: 22 additions & 7 deletions src/browser.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,20 @@
import { Browser, LaunchOptions, Page, Protocol } from 'puppeteer-core';
import { Browser, BrowserLaunchArgumentOptions, Page, Protocol } from 'puppeteer-core';
import puppeteer from 'puppeteer-extra';
import StealthPlugin from 'puppeteer-extra-plugin-stealth';
import { logger } from './logger';
import { prompt } from './utils';
import { loadSettings, saveSettings } from './settings';
import { getSettings, saveSettings } from './settings';

puppeteer.use(StealthPlugin());

export const launchBrowser = async (options: LaunchOptions = {}) => {
const { chromePath } = await loadSettings();
export const launchBrowser = async (options: BrowserLaunchArgumentOptions = {}) => {
const { chromePath } = getSettings();
let executablePath: string | null = chromePath;
let browser: Browser | null = null;
let page: Page | null = null;
const mainOptions = {
const mainOptions: BrowserLaunchArgumentOptions = {
headless: true,
args: ['--no-sandbox'],
args: ['--no-sandbox', '--start-maximized', '--lang=ru'],
userDataDir: './config/chrome',
...options,
};
Expand All @@ -33,7 +33,22 @@ export const launchBrowser = async (options: LaunchOptions = {}) => {
if (executablePath !== chromePath) saveSettings({ chromePath: executablePath });
const aboutBlankPage = (await browser.pages())[0];
if (aboutBlankPage) await aboutBlankPage.close();
return { browser, page, executablePath };

await page.evaluateOnNewDocument(() => {
Object.defineProperty(navigator, 'language', {
get: function () {
return 'ru';
},
});
Object.defineProperty(navigator, 'languages', {
get: function () {
return ['ru'];
},
});
});
await page.setExtraHTTPHeaders({ 'Accept-Language': 'ru' });

return { browser, page };
};

export const browserCookiesToList = (cookies: Protocol.Network.Cookie[]) => {
Expand Down
12 changes: 6 additions & 6 deletions src/downloader.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ import { logger } from './logger';
import { Http } from './http';
import fs from './fs';
import { getDecryptersPool, getDecryptionKeys } from './drm';
import { decrypt } from './mp4decrypt';
import { mux } from './ffmpeg';
import { ffmpeg, mp4decrypt } from './process';
import { RunArgs } from './args';

interface DownloadOptions {
numberOfConnections: number;
Expand All @@ -26,7 +26,7 @@ class Downloader {
_config: any;
_workDir = fs.join(fs.appDir, 'downloads');

constructor(params: any) {
constructor(params: RunArgs) {
this._params = params;
this.http = new Http();
}
Expand All @@ -47,7 +47,7 @@ class Downloader {
if (drmConfig) {
if (pssh) {
contentKeys = await getDecryptionKeys(pssh, drmConfig);
if (!contentKeys.length) {
if (!contentKeys?.length) {
logger.debug(`Decryption keys could not be obtained`);
logger.debug(`Trying to decrypt through a CDM adapter (slower process)`);
decryptersPool = await getDecryptersPool(pssh, drmConfig, this._params.connections);
Expand All @@ -69,7 +69,7 @@ class Downloader {
const kid = contentKeys[0].kid;
const input = this.getFilepath(this.getTrackFilename(track.type, track.id, 'enc'));
const output = this.getFilepath(this.getTrackFilename(track.type, track.id, 'dec'));
decryptQueue.push(decrypt(key, kid, input, output, true));
decryptQueue.push(mp4decrypt(key, kid, input, output, true));
}
await Promise.all(decryptQueue);
logger.info(`Decrypted successfully`);
Expand Down Expand Up @@ -102,7 +102,7 @@ class Downloader {
}
const output = this.getFilepath(this.getTrackFilename('', '', '', 'mkv'));
const { trimBegin, trimEnd } = this._params;
await mux({ inputs, output, trimBegin, trimEnd, cleanup: true });
await ffmpeg({ inputs, output, trimBegin, trimEnd, cleanup: true });
logger.info(`Muxed successfully`);
}

Expand Down
16 changes: 9 additions & 7 deletions src/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ import http2, {
} from 'node:http2';
import { IncomingHttpHeaders } from 'node:http';
import { URL } from 'node:url';
import { request, fetch, Request, RequestInit, Response } from 'undici';
import { request, fetch, Request, RequestInit, Response, Headers, HeadersInit } from 'undici';
import BodyReadable from 'undici/types/readable';
import { Browser } from 'puppeteer-core';
import { Browser, Page } from 'puppeteer-core';
import { logger } from './logger';
import { sleep } from './utils';
import { launchBrowser } from './browser';
Expand Down Expand Up @@ -51,7 +51,7 @@ class Http {
#session?: ClientHttp2Session;
#lastOrigin?: string;
browser: Browser | null;
browserPage: any;
browserPage: Page | null;

constructor() {
this.headers = { 'User-Agent': USER_AGENTS.tizen };
Expand All @@ -62,6 +62,7 @@ class Http {
this.#retryThreshold = 3;
this.#retryDelayMs = 1500;
this.browser = null;
this.browserPage = null;
}

get hasSessions() {
Expand All @@ -87,9 +88,10 @@ class Http {
}

async fetchViaBrowser(resource: string | URL | Request, options?: RequestInit) {
await this.browserPage.goto(resource);
if (!this.browserPage) throw new Error('Launch browser before using fetch via browser');
await this.browserPage.goto(resource.toString());
const { body, init } = await this.browserPage.evaluate(
(resource: any, options: any) => {
(resource, options) => {
const fetchData = async () => {
const response = await globalThis.fetch(
resource as globalThis.RequestInfo,
Expand All @@ -98,10 +100,10 @@ class Http {
return {
body: await response.text(),
init: {
headers: response.headers,
headers: response.headers as unknown as Headers,
status: response.status,
statusText: response.statusText,
},
} as RequestInit,
};
};
return fetchData();
Expand Down
42 changes: 0 additions & 42 deletions src/mp4decrypt.ts

This file was deleted.

Loading

0 comments on commit d2114b3

Please sign in to comment.