azot 0.8.3 → 0.9.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,67 +1,11 @@
1
- # azot
1
+ # Azot API
2
2
 
3
- [![npm version](https://img.shields.io/npm/v/azot?style=flat&color=black)](https://www.npmjs.com/package/azot)
4
- ![GitHub Downloads (all assets, latest release)](https://img.shields.io/github/downloads/vitalygashkov/azot/latest/total?style=flat&color=black)
5
- [![npm downloads](https://img.shields.io/npm/dt/azot?style=flat&color=black)](https://www.npmjs.com/package/azot)
3
+ Type definitions for the latesst [Azot](https://azot.so) API.
6
4
 
7
- Azot (Russian word for "nitrogen", pronounced `/azо́t/`) is a set of tools (JavaScript library, command-line utility and browser extension) for diagnosing, researching, and pentesting [DRM](https://www.urbandictionary.com/define.php?term=DRM) systems like [Widevine](https://www.widevine.com/about).
5
+ ## Getting Started
8
6
 
9
- > Azot is still in the early stages of development, so until version 1.0 is released, performance may be unstable and major changes may be made
7
+ Check [TypeScript interfaces](https://github.com/azot-labs/azot/tree/main/packages/api/types) to get started with our API. If you want to discover and install extensions, check out [Extension List](https://github.com/azot-labs/azot/tree/main/extensions/).
10
8
 
11
- ## Features
9
+ ## Community
12
10
 
13
- - **Minimal** dependencies
14
- - **Runtime agnostic** core: works in Node.js, Bun, Deno, browsers and more
15
- - **Logging** details from EME events in Developer Tools console of current page
16
- - **Encrypted Media Extensions API** compatibility via `requestMediaKeySystemAccess()` method
17
- - **Converting clients** between formats via CLI
18
- - **Manifest V3** compliant browser extension
19
- - **Custom client support**: WVD v2, device_client_id_blob + device_private_key, client_id.bin + private_key.pem
20
- - **Network-independent interception**, so it doesn't matter if the request has one-time tokens or a custom request/response body format.
21
- - **Remote instance** to control sessions via REST API
22
-
23
- ## Installation
24
-
25
- > JavaScript library and command-line tool installation requires pre-installed JavaScript runtime (e.g. Node.js).
26
-
27
- ### JavaScript library
28
-
29
- ```bash
30
- npm install azot
31
- ```
32
-
33
- ### Command-line tool
34
-
35
- ```bash
36
- npm install -g azot
37
- ```
38
-
39
- ### Chrome extension
40
-
41
- **Developer Mode** needs to be enabled in `chrome://extensions/` page
42
-
43
- 1. Download archive from [latest release](https://github.com/vitalygashkov/azot/releases/latest)
44
- 2. Go to `chrome://extensions/` page
45
- 3. Ensure Developer Mode enabled and then drag and drop downloaded zip file to this page
46
-
47
- [Read Google's guide](https://developer.chrome.com/docs/extensions/get-started/tutorial/hello-world#load-unpacked)
48
-
49
- ### Firefox extension
50
-
51
- 1. Download archive from [latest release](https://github.com/vitalygashkov/azot/releases/latest)
52
- 2. Go to `about:debugging#/runtime/this-firefox` page
53
- 3. Click `Load Temporary Add-on` button and choose downloaded zip file
54
-
55
- > Temporary add-on is not persistent and will be removed after browser restart
56
-
57
- [Read Mozilla's guide](https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/Your_first_WebExtension#installing)
58
-
59
- ## Usage
60
-
61
- ### Library
62
-
63
- See [examples](https://github.com/vitalygashkov/azot/blob/main/examples).
64
-
65
- ### Command-line tool
66
-
67
- See help: `azot --help`
11
+ Join our [Discord community](https://discord.gg/fHMgAgc7gU) to share your extension, debug nasty bugs or simply get to know like-minded folks.
package/bin/cli.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ "use strict";var e=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),t=e((exports,t)=>{let{readFileSync:n,writeFileSync:r}=require(`node:fs`),{join:i}=require(`node:path`),a=(e,t)=>{let a=n(e,`utf8`),o=t||i(process.cwd(),`package.json`),s=require(o),c=/module\.exports\s*=\s*(\w+)/g,l,u;for(;(l=c.exec(a))!==null;)u=l;if(!u)throw Error(`No module.exports found in source file`);let d=u[1],f=a.replace(/(module\.exports\s*=\s*(\w+))(?![^]*module\.exports\s*=\s*\w+)/,`${d}.package=${JSON.stringify(s)};module.exports = $2`);return r(e,f,`utf8`),{code:f,packageJson:s}};t.exports={injectPackageJson:a}}),n=e((exports,t)=>{let{createCipheriv:n,createDecipheriv:r,publicEncrypt:i,privateDecrypt:a,randomBytes:o}=require(`node:crypto`),{readFileSync:s,writeFileSync:c}=require(`node:fs`),l=Buffer.from(`STX`,`utf8`),u=(e,t,r)=>{let a=o(32),u=o(16),d=s(t),f=n(`aes-256-cbc`,a,u),p=Buffer.concat([f.update(d),f.final()]),m=i(e,a),h=Buffer.concat([l,u,m,p]);return r&&c(r,h),{aesIv:u,encryptedAesKey:m,encryptedCode:p}},d=(e,t,n)=>{let i=s(t),o=l.byteLength,u=i.subarray(0,o);if(!u.equals(l))throw Error(`Incorrect file format`);let d=o,f=d+16,p=f+512,m=i.subarray(d,f),h=i.subarray(f,p),g=i.subarray(p),_=a(e,h),v=r(`aes-256-cbc`,_,m),y=Buffer.concat([v.update(g),v.final()]),b=y.toString(`utf8`);return n&&c(n,b),b};t.exports={encrypt:u,decrypt:d}}),r=e((exports,t)=>{let{readFileSync:n,writeFileSync:r}=require(`node:fs`),i=require(`javascript-obfuscator`),a=(e,t)=>{let a=n(e,`utf8`);console.log(`Obfuscating...`),console.time(`Obfuscation complete in`);let o=i.obfuscate(a,{target:`node`,compact:!0,controlFlowFlattening:!0,controlFlowFlatteningThreshold:1,deadCodeInjection:!0,debugProtection:!0,identifierNamesGenerator:`hexadecimal`,numbersToExpressions:!0,selfDefending:!0,simplify:!0,splitStrings:!0,splitStringsChunkLength:5,stringArray:!0,stringArrayCallsTransform:!0,stringArrayCallsTransformThreshold:1,stringArrayEncoding:[`base64`],stringArrayIndexShift:!0,stringArrayRotate:!0,stringArrayShuffle:!0,stringArrayWrappersCount:2,stringArrayWrappersChainedCalls:!0,stringArrayWrappersType:`function`,stringArrayThreshold:1,transformObjectKeys:!0,unicodeEscapeSequence:!1});console.timeEnd(`Obfuscation complete in`);let s=o.getObfuscatedCode();return r(t||e,s),s};t.exports={obfuscate:a}});const{parseArgs:i}=require(`node:util`),{rmSync:a,readdirSync:o,readFileSync:s}=require(`node:fs`),c=require(`node:path`),{build:l}=require(`tsdown`),{injectPackageJson:u}=t(),{encrypt:d,decrypt:f}=n(),{obfuscate:p}=r(),m=i({allowPositionals:!0,allowNegative:!0,options:{input:{type:`string`,short:`i`,description:`Path to the input file`},key:{type:`string`,short:`k`,description:`Path to the key file (public for encrypt, private for decrypt)`},output:{type:`string`,short:`o`,description:`Path to the output file`},watch:{type:`boolean`,description:`Watch file changes`},minify:{type:`boolean`,description:`Minify output`},obfuscate:{type:`boolean`,description:`Obfuscate output`},encrypt:{type:`boolean`,description:`Encrypt extension source code (.js will be packed inside .stx)`},decrypt:{type:`boolean`,description:`Decrypt encrypted extension`}}}),h=()=>{let e=[process.cwd(),c.join(process.cwd(),`src`),c.join(process.cwd(),`lib`)];for(let t of e){let e=o(t),n=e.filter(e=>!e.endsWith(`.d.ts`)).find(e=>new Set([`.ts`,`.js`]).has(c.extname(e)));if(n)return c.join(t,n)}};(async()=>{let[e,...t]=m.positionals,n=m.values.input||t[0]||h();if(e===`build`||e===`pack`){let t=typeof m.values.minify==`boolean`?m.values.minify:!0;await l({entry:n,format:`cjs`,platform:`node`,target:`node22`,watch:m.values.watch,minify:t}),m.values.input=c.join(process.cwd(),`dist`,c.basename(n).replace(/\.ts$/,`.js`));let{packageJson:r}=u(m.values.input),i=typeof m.values.obfuscate==`boolean`,o=i?m.values.obfuscate:r.private;o&&p(m.values.input,m.values.input);let f=m.values.encrypt||e===`pack`;if(f){let e=s(m.values.key||c.join(__dirname,`../public.pem`)),t=m.values.output||m.values.input.replace(/\.js$/,`-${r.version}.stx`);d(e,m.values.input,t),a(m.values.input)}}else if(e===`decrypt`){let e=s(m.values.key||c.join(__dirname,`../private.pem`)),t=m.values.output||n.replace(/\.stx$/,`.js`);f(e,n,t),a(m.values.input)}else if(e===`dev`||e===`develop`||!e){let e=typeof m.values.minify==`boolean`?m.values.minify:!1;await l({entry:n,format:`cjs`,platform:`node`,target:`node20`,watch:!0,minify:e})}})();
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ const e=e=>e,t=`Streamyx`in globalThis?globalThis.Streamyx:{},n=`Azot`in globalThis?globalThis.Azot:{};!globalThis.Azot&&globalThis.Streamyx&&(globalThis.Azot=globalThis.Streamyx),module.exports={defineExtension:e,...t,...n};
package/index.d.ts ADDED
@@ -0,0 +1,10 @@
1
+ import './types/globals';
2
+ import { Extension } from './types/extension';
3
+
4
+ export function defineExtension(extension: Extension): Extension;
5
+
6
+ export const version: AzotModule['version'];
7
+ export const utils: AzotModule['utils'];
8
+ export const prompt: AzotModule['prompt'];
9
+
10
+ export * from './types/extension';
package/package.json CHANGED
@@ -1,52 +1,45 @@
1
1
  {
2
2
  "name": "azot",
3
- "version": "0.8.3",
4
- "description": "The ultimate toolkit for pentesting DRM systems",
5
- "type": "module",
3
+ "version": "0.9.0-alpha.1",
4
+ "description": "Build extensions for Azot with Node.js",
5
+ "homepage": "https://developers.azot.so",
6
+ "main": "./dist/index.js",
7
+ "bin": {
8
+ "azt": "./bin/cli.js"
9
+ },
10
+ "types": "index.d.ts",
6
11
  "files": [
12
+ "index.d.ts",
13
+ "bin",
7
14
  "dist",
8
- "scripts"
15
+ "types",
16
+ "public.pem"
9
17
  ],
10
- "main": "dist/lib/main.cjs",
11
- "module": "dist/lib/main.js",
12
- "bin": {
13
- "azot": "dist/cli/main.cjs"
14
- },
15
18
  "scripts": {
16
- "prepublishOnly": "npm run build:lib && npm run build:cli",
17
- "dev": "wxt",
18
- "dev:firefox": "wxt -b firefox",
19
- "build": "npm run build:lib && npm run build:cli && npm run build:chrome",
20
- "build:lib": "tsup --config tsup.lib.config.ts",
21
- "build:cli": "tsup --config tsup.cli.config.ts",
22
- "build:chrome": "wxt build",
23
- "build:firefox": "wxt build -b firefox",
24
- "zip": "wxt zip",
25
- "zip:firefox": "wxt zip -b firefox",
26
- "compile": "tsc --noEmit",
27
- "postinstall": "node scripts/postinstall.js",
28
- "test": "vitest"
19
+ "dev": "tsdown ./lib/cli.js --target node22 --format cjs --watch --out-dir ./bin",
20
+ "build:cli": "tsdown ./lib/cli.js --target node22 --format cjs --minify --out-dir ./bin",
21
+ "build:lib": "tsdown index.js --target node22 --format cjs --minify",
22
+ "build": "npm run build:cli && npm run build:lib",
23
+ "lint": "eslint . && prettier --check .",
24
+ "fix": "eslint . --fix && prettier --write ."
29
25
  },
30
26
  "repository": {
31
27
  "type": "git",
32
- "url": "https://github.com/vitalygashkov/azot"
28
+ "url": "git+https://github.com/azot-labs/extensions.git"
33
29
  },
34
30
  "keywords": [
35
- "widevine",
36
- "drm",
37
- "google",
38
- "pssh",
39
- "eme",
40
- "encrypted-media-extensions",
41
- "media"
31
+ "azot",
32
+ "extensions",
33
+ "types",
34
+ "api"
42
35
  ],
43
- "author": "Vitaly Gashkov <vitalygashkov@vk.com>",
44
- "license": "AGPL-3.0",
45
- "readmeFilename": "README.md",
46
36
  "bugs": {
47
- "url": "https://github.com/vitalygashkov/azot/issues",
37
+ "url": "https://github.com/azot-labs/extensions/issues",
48
38
  "email": "vitalygashkov@vk.com"
49
39
  },
40
+ "author": "Vitaly Gashkov <vitalygashkov@vk.com>",
41
+ "license": "MIT",
42
+ "readmeFilename": "README.md",
50
43
  "funding": [
51
44
  {
52
45
  "type": "individual",
@@ -57,53 +50,22 @@
57
50
  "url": "https://www.patreon.com/vitalygashkov"
58
51
  }
59
52
  ],
60
- "exports": {
61
- ".": {
62
- "require": {
63
- "types": "./dist/lib/main.d.cts",
64
- "default": "./dist/lib/main.cjs"
65
- },
66
- "import": {
67
- "types": "./dist/lib/main.d.ts",
68
- "default": "./dist/lib/main.js"
69
- }
70
- }
71
- },
72
53
  "engines": {
73
- "node": "20 || 21 || 22 || 23"
74
- },
75
- "dependencies": {
76
- "@fastify/helmet": "^13.0.0",
77
- "@fastify/rate-limit": "^10.2.1",
78
- "@fastify/sensible": "^6.0.1",
79
- "@fastify/type-provider-typebox": "^5.1.0",
80
- "@sinclair/typebox": "^0.34.11",
81
- "fastify": "^5.1.0",
82
- "jsrsasign": "^11.1.0",
83
- "protobufjs": "^7.4.0"
54
+ "node": ">=20"
84
55
  },
85
56
  "devDependencies": {
86
- "@eslint/js": "^9.12.0",
87
- "@solidjs/router": "^0.14.10",
88
- "@types/jsrsasign": "^10.5.14",
89
- "@types/node": "^22.7.5",
90
- "@wxt-dev/module-solid": "^1.1.2",
91
- "autoprefixer": "^10.4.17",
92
- "clsx": "^2.1.1",
93
- "eslint": "^9.12.0",
94
- "eslint-config-prettier": "^9.1.0",
95
- "eslint-plugin-prettier": "^5.2.1",
96
- "globals": "^15.11.0",
97
- "postcss": "^8.4.33",
98
- "solid-icons": "^1.1.0",
99
- "solid-js": "^1.9.1",
100
- "tailwind-merge": "^2.5.4",
101
- "tailwindcss": "^3.4.1",
102
- "tsup": "^8.3.0",
103
- "typescript": "^5.6.2",
104
- "typescript-eslint": "^8.9.0",
105
- "vite-plugin-arraybuffer": "^0.0.8",
106
- "vitest": "^2.1.3",
107
- "wxt": "^0.19.11"
57
+ "@eslint/js": "^9.31.0",
58
+ "@types/node": "^24.0.14",
59
+ "dasha": "^3.1.6",
60
+ "eslint": "^9.31.0",
61
+ "eslint-config-prettier": "^10.1.5",
62
+ "eslint-plugin-prettier": "^5.5.1",
63
+ "globals": "^16.3.0",
64
+ "prettier": "^3.6.2",
65
+ "typescript": "^5.8.3"
66
+ },
67
+ "dependencies": {
68
+ "javascript-obfuscator": "^4.1.1",
69
+ "tsdown": "^0.12.9"
108
70
  }
109
71
  }
package/public.pem ADDED
@@ -0,0 +1,14 @@
1
+ -----BEGIN PUBLIC KEY-----
2
+ MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEApJVKjJzoV4ati1NHAXjN
3
+ D3CRULVU8g7OzFNCcjqH9fAeByTevYTo4ryttcaljf2qOBNE0RLVgMh1gaU/EjrA
4
+ CA+nXYU4USjknctSKFFspIdnPJfYTe2pu42tQeOr88AASYt/PjHBxHXSr/z2D7H/
5
+ GB51DaakFqM6T6wUyjXOduVuMnVkWtNDexQkjp6AItq2IRyCSjc8X4VtnuIm4D/F
6
+ /Ny7cw0+HBP3c58BBiTpjCc1EI/5gYfqzlo9bGKmbn/s8rRgGAA0v1aPGjjN0Ask
7
+ gTgd4iQE0Qjumu5QiaiYghWiGaiK9Q5RQW0YIu/vh59Ylyul62jUC0+1a+UsoW/U
8
+ 0ZQwqub0NnEpHeBboGYQzA6cjDFf7vvlpVp/7vHwsBXcub7pqmi1IVEEpvsaIy11
9
+ dnLFkfWsUHD8w0f6basX8gtd7HRacjWZD+SiBoGCfu3t8KQZizdMeUgBkDuNojij
10
+ UtpyQ5rczO+EuLjkHgjwFpplyOUme1ePENjRzhVdHzPMLohet4EFgMQV6s7vNJgA
11
+ rp71hOnAkOJJ/Pe2/PgFBBbQWgEOqsMopWesVDUV84rIkSnbsuzzzDT9Cfs5Veje
12
+ fyERt4rbt8EEUwDnqZl2vRNDGHjjCl/d1U1iITt6OVSeMd6jA8cg8PmDBq3Wl6bP
13
+ RMZ+4GiuFSJsJG3+bzKaFxMCAwEAAQ==
14
+ -----END PUBLIC KEY-----
@@ -0,0 +1,106 @@
1
+ declare global {
2
+ /**
3
+ * Azot runtime APIs
4
+ *
5
+ * @example
6
+ *
7
+ * ```js
8
+ * import { sanitizeString } from 'azot';
9
+ *
10
+ * const sanitized = sanitizeString('Hello, world!');
11
+ * // Sanitize string to be able use it in filenames
12
+ * console.log(sanitized);
13
+ * ```
14
+ *
15
+ * This module aliases `globalThis.Azot`.
16
+ */
17
+ const Azot: AzotModule;
18
+
19
+ /**
20
+ * In v5.0.0+ use `Azot` instead
21
+ */
22
+ const Streamyx: AzotModule;
23
+
24
+ interface AzotModule {
25
+ version: string;
26
+ utils: Common;
27
+ prompt<T = PromptResponse>(request: PromptRequest): Promise<T>;
28
+ }
29
+ }
30
+
31
+ export type InputType =
32
+ | 'text'
33
+ | 'password'
34
+ | 'number'
35
+ | 'checkbox'
36
+ | 'select'
37
+ | 'date'
38
+ | 'confirm';
39
+
40
+ export type InputField = {
41
+ type?: InputType;
42
+ label: string;
43
+ placeholder?: string;
44
+ defaultValue?: string;
45
+ required?: boolean;
46
+ options?: string[];
47
+ };
48
+
49
+ export type PromptRequest = {
50
+ title?: string;
51
+ description?: string;
52
+ fields: Record<string, InputField>;
53
+ };
54
+
55
+ export type PromptResponse = {
56
+ [field: string]: string; // TODO: Add more types with inference from InputField type
57
+ };
58
+
59
+ export type Common = {
60
+ sanitizeString: (text: string) => string;
61
+
62
+ execUrlPatterns: (
63
+ url: string,
64
+ patterns: string[],
65
+ baseUrls: string[],
66
+ ) => {
67
+ pathname: Record<string, string | undefined>;
68
+ search: Record<string, string | undefined>;
69
+ };
70
+
71
+ extendEpisodes: (episodesBySeasons?: Map<number, Set<number>>) => {
72
+ items: Map<number, Set<number>>;
73
+ has: (episode?: number, season?: number) => boolean;
74
+ set: (episode?: number, season?: number) => void;
75
+ getMin: () => number;
76
+ getMax: () => number;
77
+ seasonsCount: number;
78
+ episodesCount: number;
79
+ };
80
+
81
+ getRandomElements: (array: unknown, count?: number) => unknown[];
82
+ };
83
+
84
+ export type HttpClient = {
85
+ headers: Record<string, string>;
86
+ cookies: string[];
87
+ userAgents: Record<
88
+ 'chromeWindows' | 'chromeMacOS' | 'chromeLinux' | 'smartTv' | 'tizen',
89
+ string
90
+ >;
91
+ fetch(
92
+ resource: string | URL | Request,
93
+ options?: RequestInit,
94
+ ): Promise<Response>;
95
+ fetchAsChrome(
96
+ resource: string | URL | Request,
97
+ options?: RequestInit,
98
+ ): Promise<Response>;
99
+ appendCookies(setCookie: string | string[]): void;
100
+ setAgent(proxy?: string | null): void;
101
+ setCookies(cookies: string[]): void;
102
+ setHeader(name: string, value: string): void;
103
+ setHeaders(headers: Record<string, string>): void;
104
+ removeHeader(name: string): void;
105
+ destroySessions(): Promise<void>;
106
+ };
@@ -0,0 +1,34 @@
1
+ declare global {
2
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/CookieStore) */
3
+ interface CookieStore {
4
+ get(cookie: string | { name: string; url: string }): Promise<Cookie | null>;
5
+ getAll(cookie?: string | { name: string; url: string }): Promise<Cookie[]>;
6
+ set(cookie: Cookie): Promise<void>;
7
+ delete(
8
+ cookie?:
9
+ | string
10
+ | {
11
+ name: string;
12
+ domain?: string;
13
+ path?: string;
14
+ partitioned?: boolean;
15
+ },
16
+ ): Promise<void>;
17
+ addToHeaders(headers: Headers): void;
18
+ toString(): string;
19
+ }
20
+
21
+ interface Cookie {
22
+ name: string;
23
+ value: string;
24
+ domain?: string;
25
+ path?: string;
26
+ expires?: string;
27
+ httpOnly?: boolean;
28
+ secure?: boolean;
29
+ sameSite?: 'Strict' | 'Lax' | 'None';
30
+ partitioned?: boolean;
31
+ }
32
+ }
33
+
34
+ export {};
@@ -0,0 +1,8 @@
1
+ declare global {
2
+ /** A partial implementation of the [Document](https://developer.mozilla.org/en-US/docs/Web/API/Document) for Azot */
3
+ interface Document {
4
+ readonly cookie: string;
5
+ }
6
+ }
7
+
8
+ export {};
@@ -0,0 +1,164 @@
1
+ import { Options } from './options';
2
+
3
+ export interface ExtensionConfig {
4
+ id: string;
5
+ version: string;
6
+ name: string;
7
+ tag?: string;
8
+ icon?: string;
9
+ }
10
+
11
+ export interface Extension {
12
+ canHandle?(url: string): boolean | Promise<boolean>;
13
+
14
+ /**
15
+ * Performs initialization of extension (e.g. token refresh)
16
+ */
17
+ init?(): void | Promise<void>;
18
+
19
+ isAuthenticated?(): Promise<boolean>;
20
+ login?(username?: string, password?: string): Promise<void>;
21
+ logout?(): Promise<void>;
22
+
23
+ /**
24
+ * Fetches content metadata from URL
25
+ */
26
+ fetchContentMetadata: (
27
+ url: string,
28
+ options: Options,
29
+ ) => Promise<ContentMetadata[]>;
30
+
31
+ /**
32
+ * Fetches data about content source (e.g. manifest URL, external subtitles, etc.)
33
+ */
34
+ fetchContentSource?: (
35
+ contentId: string,
36
+ options: Options,
37
+ ) => Promise<ContentSource | null>;
38
+
39
+ /**
40
+ * Fetches just content DRM config (e.g. license server URL, request headers, etc.)
41
+ */
42
+ fetchContentDrm?: (payload: any, options: Options) => Promise<DrmConfig>;
43
+
44
+ onDownloadFinished?(): Promise<void>;
45
+
46
+ /**
47
+ * Extension name (e.g. Netflix, Prime Video, Apple TV+, etc.)
48
+ * @deprecated Use `config.title` field in package.json
49
+ */
50
+ name?: string;
51
+
52
+ /**
53
+ * Short tag which will be used in filename (e.g. NF, AMZN, ATVP, etc.)
54
+ * @deprecated Use `config.tag` field in package.json
55
+ */
56
+ tag?: string;
57
+
58
+ /**
59
+ * Logo icon URL
60
+ * @deprecated Use `config.icon` field in package.json
61
+ */
62
+ icon?: string;
63
+
64
+ /**
65
+ * Substring pattern to match URL host handled by this plugin
66
+ * @deprecated
67
+ */
68
+ match?: string;
69
+ }
70
+
71
+ export interface MediaInfo {
72
+ id: string;
73
+ type?: 'movie' | 'tv';
74
+ title?: string;
75
+ description?: string;
76
+ thumbnailUrl?: string;
77
+ author?: string;
78
+ year?: number;
79
+
80
+ season?: number;
81
+ episode?: number;
82
+ episodeTitle?: string;
83
+
84
+ sources: (MediaSource | string)[];
85
+
86
+ [key: string]: any;
87
+ }
88
+
89
+ export interface MediaSource {
90
+ url: string;
91
+
92
+ headers?: Record<string, string>;
93
+ drm?: string | MediaDrm | MediaDrm[];
94
+ type?: 'progressive' | 'direct' | 'hls' | 'dash';
95
+
96
+ language?: string;
97
+ size?: number;
98
+ }
99
+
100
+ export interface MediaDrm {
101
+ type?: 'widevine' | 'playready';
102
+ server: string;
103
+
104
+ headers?: Record<string, string>;
105
+
106
+ transformRequest?(request: Request): Request;
107
+ transformResponse?(response: Response): Response;
108
+
109
+ fetchCertificate?(
110
+ message: Uint8Array,
111
+ sessionId: string,
112
+ ): Promise<Uint8Array>;
113
+ fetchLicense?(message: Uint8Array, sessionId: string): Promise<Uint8Array>;
114
+ }
115
+
116
+ export { Options };
117
+
118
+ export interface CommonContentMetadata {
119
+ tag?: string;
120
+ /**
121
+ * Required if no `fetchContentSource` method is provided
122
+ */
123
+ source?: ContentSource;
124
+ }
125
+
126
+ export interface MovieMetadata extends CommonContentMetadata {
127
+ id?: string;
128
+ title?: string;
129
+ }
130
+
131
+ export interface EpisodeMetadata extends CommonContentMetadata {
132
+ id?: string;
133
+ title?: string;
134
+ episodeNumber: number;
135
+ seasonNumber?: number;
136
+ episodeTitle?: string;
137
+ }
138
+
139
+ export type ContentMetadata = MovieMetadata | EpisodeMetadata;
140
+
141
+ export type ContentSource = {
142
+ /**
143
+ * URL of the content: manifest URL / playlist URL / direct link to media file
144
+ */
145
+ url: string;
146
+ headers?: Record<string, string>;
147
+ http2?: boolean;
148
+ type?: 'video' | 'audio' | 'subtitle' | 'any';
149
+ audioLanguage?: string;
150
+ audioType?: string;
151
+ subtitles?: any[];
152
+ drm?: DrmConfig;
153
+ };
154
+
155
+ export type DrmConfig =
156
+ | {
157
+ server: string;
158
+ headers?: Record<string, string>;
159
+ params?: object;
160
+ template?: string;
161
+ http2?: boolean;
162
+ }
163
+ | { payload: any }
164
+ | { keys: { kid: string; key: string }[] };
@@ -0,0 +1,33 @@
1
+ import './azot';
2
+ import './cookie-store';
3
+ import './navigator';
4
+ import './document';
5
+ import './uin8array.extensions';
6
+
7
+ declare global {
8
+ /**
9
+ *
10
+ * A partial implementation of [Navigator](https://developer.mozilla.org/ru/docs/Web/API/Navigator) for Azot
11
+ */
12
+ var navigator: Navigator;
13
+
14
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/cookieStore) */
15
+ const cookieStore: CookieStore;
16
+
17
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt) */
18
+ function prompt(message?: string, _default?: string): string | null;
19
+
20
+ /** [MDN Reference](https://developer.mozilla.org/ru/docs/Web/API/Window/alert) */
21
+ function alert(message?: any): void;
22
+
23
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch) */
24
+ function fetch(
25
+ input: RequestInfo | URL,
26
+ init?: RequestInit,
27
+ ): Promise<Response>;
28
+
29
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) */
30
+ function eval(x: string): any;
31
+ }
32
+
33
+ export {};
@@ -0,0 +1,28 @@
1
+ declare global {
2
+ /** A partial implementation of [Navigator](https://developer.mozilla.org/ru/docs/Web/API/Navigator) for Azot */
3
+ interface Navigator {
4
+ appName: string;
5
+ appVersion: string;
6
+ platform: string;
7
+ userAgentData: {
8
+ mobile: boolean;
9
+ platform: string;
10
+ getHighEntropyValues(hints: string[]): Promise<UADataValues>;
11
+ };
12
+ }
13
+
14
+ interface NavigatorUABrandVersion {
15
+ brand: string;
16
+ version: string;
17
+ }
18
+
19
+ interface UADataValues {
20
+ architecture: string;
21
+ fullVersionList: NavigatorUABrandVersion[];
22
+ mobile: boolean;
23
+ platform: string;
24
+ platformVersion: string;
25
+ }
26
+ }
27
+
28
+ export {};