azot 0.9.3 → 5.0.0-alpha.2

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/out/azt.js ADDED
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ const e=require(`./chunk-nOFOJqeH.js`),t=e.__toESM(require(`node:path`)),n=e.__toESM(require(`node:fs`)),r=e.__toESM(require(`node:util`)),i=e.__toESM(require(`tsdown`)),a=e.__toESM(require(`node:crypto`)),o=e.__toESM(require(`javascript-obfuscator`)),s=Buffer.from(`STX`,`utf8`),c=(e,t,r)=>{let i=(0,a.randomBytes)(32),o=(0,a.randomBytes)(16),c=(0,n.readFileSync)(t),l=(0,a.createCipheriv)(`aes-256-cbc`,i,o),u=Buffer.concat([l.update(c),l.final()]),d=(0,a.publicEncrypt)(e,i),f=Buffer.concat([s,o,d,u]);return r&&(0,n.writeFileSync)(r,f),{aesIv:o,encryptedAesKey:d,encryptedCode:u}},l=(e,t,r)=>{let i=(0,n.readFileSync)(t),o=s.byteLength,c=i.subarray(0,o);if(!c.equals(s))throw Error(`Incorrect file format`);let l=o,u=l+16,d=u+512,f=i.subarray(l,u),p=i.subarray(u,d),m=i.subarray(d),h=(0,a.privateDecrypt)(e,p),g=(0,a.createDecipheriv)(`aes-256-cbc`,h,f),_=Buffer.concat([g.update(m),g.final()]),v=_.toString(`utf8`);return r&&(0,n.writeFileSync)(r,v),v},u=(e,t)=>{let r=(0,n.readFileSync)(e,`utf8`);console.log(`Obfuscating...`),console.time(`Obfuscation complete in`);let i=o.default.obfuscate(r,{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 a=i.getObfuscatedCode();return(0,n.writeFileSync)(t||e,a),a},d=(0,r.parseArgs)({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`},format:{type:`string`,short:`f`,description:`Output format`},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`}}}),f=()=>{let e=[process.cwd(),t.default.join(process.cwd(),`src`),t.default.join(process.cwd(),`lib`)];for(let r of e){let e=(0,n.readdirSync)(r),i=e.filter(e=>!e.endsWith(`.d.ts`)).filter(e=>new Set([`.ts`,`.js`]).has(t.default.extname(e))),a=e=>t.default.basename(e,t.default.extname(e)),o=i.find(e=>a(e)===`index`)||i.find(e=>a(e)===`main`)||i[0];if(o)return t.default.join(r,o)}};(async()=>{let[e,...r]=d.positionals,a=d.values.input||r[0]||f();if(!a)throw Error(`No entry file found`);if(e===`build`||e===`pack`){let r=typeof d.values.minify==`boolean`?d.values.minify:!0;await(0,i.build)({entry:a,format:d.values.format??`cjs`,platform:`node`,target:`node22`,watch:d.values.watch,minify:r}),d.values.input=t.default.join(process.cwd(),`dist`,t.default.basename(a).replace(/\.ts$/,`.js`));let o=require(t.default.join(process.cwd(),`package.json`)),s=typeof d.values.obfuscate==`boolean`,l=s?d.values.obfuscate:o.private;l&&u(d.values.input,d.values.input);let f=d.values.encrypt||e===`pack`;if(f){let e=(0,n.readFileSync)(d.values.key||t.default.join(__dirname,`../public.pem`),`utf8`),r=d.values.output||d.values.input.replace(/\.js$/,`-${o.version}.stx`);c(e,d.values.input,r),(0,n.rmSync)(d.values.input)}}else if(e===`decrypt`){let e=(0,n.readFileSync)(d.values.key||t.default.join(__dirname,`../private.pem`),`utf8`),r=d.values.output||a.replace(/\.stx$/,`.js`);l(e,a,r),d.values.input&&(0,n.rmSync)(d.values.input)}else if(e===`dev`||e===`develop`||!e){let e=typeof d.values.minify==`boolean`?d.values.minify:!1;await(0,i.build)({entry:a,format:d.values.format??`cjs`,platform:`node`,target:`node20`,watch:!0,minify:e})}})();
@@ -0,0 +1 @@
1
+ var e=Object.create,t=Object.defineProperty,n=Object.getOwnPropertyDescriptor,r=Object.getOwnPropertyNames,i=Object.getPrototypeOf,a=Object.prototype.hasOwnProperty,o=(e,i,o,s)=>{if(i&&typeof i==`object`||typeof i==`function`)for(var c=r(i),l=0,u=c.length,d;l<u;l++)d=c[l],!a.call(e,d)&&d!==o&&t(e,d,{get:(e=>i[e]).bind(null,d),enumerable:!(s=n(i,d))||s.enumerable});return e},s=(n,r,a)=>(a=n==null?{}:e(i(n)),o(r||!n||!n.__esModule?t(a,`default`,{value:n,enumerable:!0}):a,n));Object.defineProperty(exports,`__toESM`,{enumerable:!0,get:function(){return s}});
package/out/main.js ADDED
@@ -0,0 +1 @@
1
+ const e=`Streamyx`in globalThis?globalThis.Streamyx:{},t=`Azot`in globalThis?globalThis.Azot:{};if(!globalThis.Azot&&globalThis.Streamyx&&(globalThis.Azot=globalThis.Streamyx),globalThis.Azot&&!globalThis.Azot.input){let e=async(e,t)=>{let n=t?.fields??{answer:{label:e}},r=await globalThis.Azot.prompt.ask({title:t?.title,description:e,fields:n});return r};globalThis.Azot.input=e}var n={...e,...t};module.exports=n;
package/out/test.js ADDED
@@ -0,0 +1,3 @@
1
+ const e=require(`./chunk-nOFOJqeH.js`),t=e.__toESM(require(`node:os`)),n=e.__toESM(require(`node:path`)),r=e.__toESM(require(`node:timers/promises`)),i=e.__toESM(require(`node:fs/promises`)),a=e.__toESM(require(`@logtape/logtape`)),o=e.__toESM(require(`@logtape/file`)),s=e.__toESM(require(`@logtape/pretty`)),c=e.__toESM(require(`node:fs`)),l=e.__toESM(require(`node:process`));require(`urlpattern-polyfill`);const u=e.__toESM(require(`node:events`)),d=e.__toESM(require(`node:readline/promises`)),f=e.__toESM(require(`node:url`)),p=e.__toESM(require(`undici`)),m=e.__toESM(require(`impit`)),h=e.__toESM(require(`metavm`));require(`picocolors`),require(`nanospinner`);const g=e.__toESM(require(`conf`));var _=`azot`,v=`Azot`,y=`5.0.0-alpha.2`,b=`./out/main.js`,x=`./types/main.d.ts`,S={".":{types:`./types/main.d.ts`,import:`./out/main.js`,require:`./out/main.js`},"./test":{types:`./types/test.d.ts`,import:`./out/test.js`,require:`./out/test.js`}},C={azt:`out/azt.js`},ee=[`out`,`azot.d.ts`,`types`,`.npmrc`],te=`Vitaly Gashkov <vitalygashkov@vk.com>`,ne=`A powerful, extensible app for downloading videos`,re={type:`git`,url:`https://github.com/azot-labs/azot.git`},ie=`https://azot.so`,ae={start:`tsx --env-file .env ./src/main/cli.ts`,preview:`electron-vite preview --config vite.desktop.config.mjs`,dev:`electron-vite dev --config vite.desktop.config.mjs --watch`,test:`vitest`,coverage:`vitest run --coverage`,"bundle:lib":`tsdown`,"bundle:cli":`electron-vite build --config vite.cli.config.mjs`,bundle:`npm run bundle:cli && electron-vite build --config vite.desktop.config.mjs`,build:`npm run bundle && electron-builder build --config electron-builder.config.js`,"build:mac":`npm run bundle && electron-builder build --mac --config electron-builder.config.js`,"build:win":`npm run bundle && electron-builder build --win --config electron-builder.config.js`,"build:linux":`npm run bundle && electron-builder build --linux --config electron-builder.config.js`,publish:`npm run bundle && electron-builder build --publish always --config electron-builder.config.js`,"publish:lib":`npm run bundle:lib && npm publish --tag alpha`,typecheck:`npm run typecheck:node && npm run typecheck:web`,"typecheck:node":`tsc --noEmit -p tsconfig.node.json --composite false`,"typecheck:web":`vue-tsc --noEmit -p tsconfig.web.json --composite false`,format:`prettier --write .`,lint:`eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix`},oe={node:`22`},se=[`darwin`,`linux`,`win32`],ce=[{type:`individual`,url:`https://t.me/tribute/app?startapp=dqW2`}],le={"@electron-toolkit/preload":`^3.0.2`,"@electron-toolkit/utils":`^4.0.0`,"@inquirer/prompts":`^7.8.3`,"@logtape/file":`^1.0.4`,"@logtape/logtape":`^1.0.4`,"@logtape/pretty":`^1.0.4`,"@tanstack/query-core":`^5.85.5`,"@tribute-tg/better-auth":`^1.0.9`,"better-auth":`^1.3.7`,bytenode:`^1.5.7`,conf:`^14.0.0`,"cross-spawn":`^7.0.6`,dasha:`3.1.8`,"electron-squirrel-startup":`^1.0.1`,"electron-updater":`^6.6.2`,impit:`^0.5.4`,"javascript-obfuscator":`^4.1.1`,metavm:`^1.4.4`,molnia:`^0.1.5`,nanospinner:`^1.2.2`,okova:`^0.9.3`,"p-queue":`^8.1.0`,picocolors:`^1.1.1`,tsdown:`^0.14.2`,undici:`^7.15.0`,"urlpattern-polyfill":`^10.1.0`,yargs:`^18.0.0`,yauzl:`^3.2.0`},w={"@electron-toolkit/eslint-config":`^2.1.0`,"@electron-toolkit/eslint-config-prettier":`^3.0.0`,"@electron-toolkit/eslint-config-ts":`^3.1.0`,"@electron-toolkit/tsconfig":`^1.0.1`,"@eslint/js":`^9.26.0`,"@iconify/vue":`^4.3.0`,"@intlify/unplugin-vue-i18n":`^6.0.8`,"@rushstack/eslint-patch":`^1.10.5`,"@tailwindcss/vite":`^4.1.12`,"@tanstack/vue-query":`^5.85.5`,"@types/node":`^24.3.0`,"@types/wicg-file-system-access":`^2023.10.5`,"@types/yargs":`^17.0.33`,"@vee-validate/zod":`^4.15.1`,"@vitejs/plugin-vue":`^6.0.1`,"@vue/eslint-config-prettier":`^10.2.0`,"@vue/eslint-config-typescript":`^14.5.0`,"@vueuse/core":`^13.7.0`,"class-variance-authority":`^0.7.1`,clsx:`^2.1.1`,dotenv:`^17.2.1`,electron:`37.3.1`,"electron-builder":`^26.0.12`,"electron-vite":`^4.0.0`,eslint:`^9.34.0`,"eslint-plugin-import":`^2.32.0`,"eslint-plugin-n":`^17.21.3`,"eslint-plugin-vue":`^10.4.0`,execa:`^9.6.0`,globals:`^16.3.0`,"lucide-vue-next":`^0.541.0`,"non.geist":`^1.0.4`,pinia:`^3.0.3`,postcss:`^8.5.6`,prettier:`^3.6.2`,"reka-ui":`^2.4.1`,sass:`^1.90.0`,"tailwind-merge":`^3.3.1`,tailwindcss:`^4.1.12`,"tailwindcss-animate":`^1.0.7`,tsx:`^4.20.5`,typescript:`^5.9.2`,"vee-validate":`^4.15.1`,vite:`^7.1.3`,"vite-plugin-static-copy":`^3.1.2`,vitest:`^3.2.4`,vue:`^3.5.18`,"vue-eslint-parser":`^10.2.0`,"vue-i18n":`^11.1.11`,"vue-sonner":`^1.3.0`,"vue-tsc":`^3.0.6`,zod:`^3.25.42`},T={name:_,productName:v,version:y,main:b,types:x,exports:S,bin:C,files:ee,author:te,description:ne,repository:re,homepage:ie,scripts:ae,engines:oe,os:se,funding:ce,dependencies:le,devDependencies:w};const ue=`pkg`in process&&process.pkg!==void 0,E=!!process.versions.electron&&!1,D=!E,de=`v${T.version} ${l.platform}-${l.arch} node-${l.version}`,fe=`v${T.version}`,pe=T.name,O=T.productName,k={darwin:`macOS`,win32:`Windows`,linux:`Linux`},A=k[process.platform],j=e=>{let t=typeof e==`string`?e:e[A];return(0,c.existsSync)(t)||(0,c.mkdirSync)(t,{recursive:!0}),t},M=(0,t.homedir)(),N=(0,t.tmpdir)(),P=j({Windows:process.env.APPDATA||(0,n.join)(M,`AppData`,`Roaming`),macOS:(0,n.join)(M,`Library`,`Application Support`),Linux:process.env.XDG_DATA_HOME||(0,n.join)(M,`.local`,`share`)}),F=j({Windows:process.env.APPDATA||(0,n.join)(M,`AppData`,`Roaming`),macOS:(0,n.join)(M,`Library`,`Application Support`),Linux:process.env.XDG_CONFIG_HOME||(0,n.join)(M,`.config`)}),me=j({Windows:process.env.LOCALAPPDATA||(0,n.join)(M,`AppData`,`Local`),macOS:(0,n.join)(M,`Library`,`Caches`),Linux:process.env.XDG_CACHE_HOME||(0,n.join)(M,`.cache`)}),he=j({Windows:(0,n.join)(M,`Downloads`),macOS:(0,n.join)(M,`Downloads`),Linux:process.env.XDG_DOWNLOAD_DIR||(0,n.join)(M,`Downloads`)}),I=j({Windows:(0,n.join)(P,O),macOS:(0,n.join)(P,O),Linux:(0,n.join)(P,O.toLowerCase())}),L=j({Windows:(0,n.join)(F,O),macOS:(0,n.join)(F,O),Linux:(0,n.join)(F,O.toLowerCase())}),R=j({Windows:(0,n.join)(F,O,`logs`),macOS:(0,n.join)(M,`Library`,`Logs`,O),Linux:(0,n.join)(F,O.toLowerCase(),`logs`)}),ge=(0,n.join)(N,O.toLowerCase()),z=j((0,n.join)(I,`extensions`)),_e=j((0,n.join)(z,`installed`)),ve=j((0,n.join)(z,`work`)),ye=(0,n.join)(L,`settings.json`),B=process.argv.includes(`-d`)||process.argv.includes(`--debug`)||process.env.NODE_ENV_ELECTRON_VITE===`development`||!!process.env.ELECTRON_CLI_ARGS,V=()=>{let e=new Date().toISOString().split(`.`)[0].replace(`T`,`_`).replaceAll(`-`,``).replaceAll(`:`,``);return`Azot_${e}.log`},be=()=>(0,n.join)(R,V()),H=(0,s.getPrettyFormatter)({timestamp:`time`,levelStyle:null,icons:!1,colors:!0,level:`FULL`,categoryWidth:0,categoryStyle:null,categoryTruncate:`end`,wordWrap:!0});(0,a.configureSync)({sinks:{console:(0,a.withFilter)((0,a.getConsoleSink)({formatter:H}),B?`debug`:`info`),file:(0,o.getFileSink)(be(),{flushInterval:0})},loggers:[{category:[],lowestLevel:`trace`,sinks:[`console`,`file`]},{category:[`logtape`,`meta`],lowestLevel:`error`,sinks:[`console`]}]});const U=(0,a.getLogger)([]),W=e=>{let t=[`}`,`{`,`%`,`>`,`<`,`^`,`;`,"`",`$`,`"`,`@`,`=`],n=e;for(let e in t)n=n.replaceAll(`/`,`_`).replaceAll(t[e],``);return n},G=(e,t,n)=>{let r={},i={};for(let a of n)for(let n of t){let t=new URLPattern(n,a),o=t.exec(e);o&&(Object.assign(r,o.pathname.groups),Object.assign(i,o.search.groups))}return{pathname:r,search:i}},K=(e=new Map)=>{let t=(t,n)=>{for(let r of e.keys())for(let i of e.get(r)||[]){let e=n===void 0||isNaN(n),a=t===void 0||isNaN(t),o=!1;if(o=a?r===n:(e?isNaN(r):r===n)&&i===t,o)return!0}return!1},n=(t,n)=>{let r=n||NaN,i=t||NaN;e.has(r)?e.get(r)?.add(i):e.set(r,new Set([i]))},r=()=>Array.from(e.values()).flatMap(e=>Array.from(e)),i=e.size,a=r(),o=a.length,s=()=>Math.min(...a),c=()=>Math.max(...a);return{items:e,has:t,set:n,getMin:s,getMax:c,seasonsCount:i,episodesCount:o}},xe=new Intl.DateTimeFormat(`en-US`,{year:`numeric`,month:`2-digit`,day:`2-digit`,hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1}),Se=new Intl.DateTimeFormat(`en-US`,{hour:`2-digit`,minute:`2-digit`,second:`2-digit`,hour12:!1});var Ce=class e extends u.EventEmitter{static{this.requestEventName=`form`}static{this.responseEventName=`form:response`}constructor(){super(),D&&this.listen(async e=>{let t=(0,d.createInterface)({input:l.stdin,output:l.stdout}),{title:n,description:i,fields:a,...o}=e,s={};for(let[e,{label:c,type:l}]of Object.entries(a||o)){let a=l===`confirm`,o=[n,i,c].filter(Boolean).join(`. `)+(a?` (y/n)`:``)+`: `,u=await Promise.race([t.question(o),(0,r.setTimeout)(Te,``)]);s[e]=u}return t.close(),s})}async ask(t){let n=new Promise(n=>{this.emit(e.requestEventName,t),this.addListener(e.responseEventName,e=>{n(e)})});return n}listen(t){this.addListener(e.requestEventName,async n=>{let r=await t(n);this.emit(e.responseEventName,r)})}};const q=new Ce,we=async(e,t)=>{let n=t?.fields??{answer:{label:e}},r=await q.ask({title:t?.title,description:e,fields:n});return r},Te=12e4,Ee=(e,t)=>{(0,c.writeSync)(1,e||``);let n=Buffer.alloc(1),r=``;for(;;){try{(0,c.readSync)(0,n,0,1,null)}catch(e){if(e.code===`EOF`)break;throw e}let e=n.toString(`utf-8`);if(e===`
2
+ `||e===`\r`){if(e===`\r`)try{(0,c.readSync)(0,n,0,1,null),n.toString(`utf-8`)}catch(e){if(e.code===`EOF`)break;throw e}break}r+=e}return r.trim()||t},De=e=>{let t=e.expires instanceof Date?e.expires.getTime():e.expires,n;return e.sameSite===`Strict`?n=`strict`:e.sameSite===`Lax`&&(n=`lax`),{name:e.name,value:e.value,expires:t,domain:e.domain,path:e.path,sameSite:n,partitioned:!1,maxAge:e.maxAge,secure:e.secure,httpOnly:e.httpOnly,unparsed:e.unparsed}},J=e=>{let t=[];for(let n of e)try{let e=(0,p.parseCookie)(n);e&&t.push(De(e))}catch(e){U.debug(e)}return t},Y=async e=>{let n=await(0,i.readFile)(e,`utf8`).catch(()=>``);if(!n)return[];let r=n.split(t.EOL).flatMap(e=>e.split(`
3
+ `)),a=r.filter(e=>!!e.trim()&&!e.startsWith(`# `)),o=a.map(e=>e.split(` `)),s=[];for(let e of o){let[t,n,r,i,a,o,c]=e;s.push({name:o,value:c,expires:Number(a),maxAge:void 0,domain:t.replace(`#HttpOnly_`,``),path:r,secure:i===`TRUE`,httpOnly:void 0,sameSite:void 0,unparsed:e})}return s};var X=class{#data={};#cookies;#storagePath;#hasBeenRead=!1;static parse(e){return J(e)}constructor({storagePath:e}={}){this.#storagePath=e,this.#cookies=[]}async import(e){let t=await(0,i.stat)(e).catch(()=>null);t?.isFile()&&(this.#cookies=await Y(e),await(0,i.rm)(e,{recursive:!0,force:!0}))}async#read(){if(!this.#storagePath||this.#hasBeenRead)return;let e=await(0,i.stat)(this.#storagePath).catch(()=>null);if(e?.isFile()){let e=await(0,i.readFile)(this.#storagePath,`utf8`);this.#data=e?JSON.parse(e):{},this.#cookies=`cookies`in this.#data?this.#data.cookies:[]}this.#hasBeenRead=!0}async#write(){if(!this.#storagePath)return;let e=JSON.stringify({...this.#data,cookies:this.#cookies},null,2);await(0,i.writeFile)(this.#storagePath,e,`utf8`)}async get(e){await this.#read();let t=typeof e==`string`?e:e.name;return this.#cookies.find(e=>e.name===t)??null}async getAll(e){if(await this.#read(),!e)return this.#cookies;let t=typeof e==`string`?e:e.name;return this.#cookies.filter(e=>e.name===t)??null}async set(e){await this.#read(),this.#cookies=this.#cookies.filter(t=>!(t.name===e.name&&t.domain===e.domain)),this.#cookies.push(e),await this.#write()}async delete(e){if(await this.#read(),!e)this.#cookies=[];else{let t=typeof e==`string`?e:e.name;this.#cookies=this.#cookies.filter(e=>e.name!==t)}}toString(){return this.#cookies.map(e=>`${e.name}=${e.value}`).join(`; `)}},Z=class{#impit;#agent;#retryThreshold;#retryDelayMs;#failures=new Map;constructor(e={}){this.headers=new Headers,this.#retryThreshold=3,this.#retryDelayMs=1500,this.configure(e)}configure({proxyUrl:e,allowH2:t=!0,maxRedirections:n=3,maxRetries:r=3,cookieStore:i}={}){this.cookieStore=i??this.cookieStore??new X,this.#impit=new m.Impit({browser:`chrome`,ignoreTlsErrors:!0,proxyUrl:e,followRedirects:!0,maxRedirects:n});let{redirect:a,retry:o}=p.interceptors;e?this.#agent=new p.ProxyAgent({uri:e,allowH2:t}).compose(a({maxRedirections:n}),o({maxRetries:r})):this.#agent=new p.Agent({allowH2:t}).compose(a({maxRedirections:n}),o({maxRetries:r}))}get retries(){return this.#retryThreshold}async fetch(e,t={}){let n=t.headers&&(t.headers instanceof Headers?t.headers.has(`User-Agent`):`User-Agent`in t.headers),r=this.appendHeaders(t?.headers||{}),i=await this.cookieStore.getAll(),a=i.filter(t=>!t.domain||new f.URL(e).hostname.includes(t.domain));for(let e of i){let t=a.find(t=>t.name===e.name);if(t)continue;e.domain||a.push(e)}let o=a.map(e=>`${e.name}=${e.value}`).join(`; `);r.has(`cookie`)?r.get(`cookie`)||r.delete(`cookie`):r.set(`cookie`,o);let s={...t,body:t?.body,headers:r};t&&(t.headers=r);let c=await(n?(0,p.fetch)(e,{...s,dispatcher:this.#agent}):this.withRetry(this.#impit.fetch.bind(this.#impit),e,s)),l=c.headers.getSetCookie();return l&&await this.setCookies(l),c}async withRetry(e,t,n){try{let r=await e(t,n),i=r.status>=300&&r.status<=399,a=r.status>=200&&r.status<=299||i;return!a&&this.#hasAttempts(t)?(await this.#nextRetry(t),U.debug(await r.text()),U.debug(String(r.status)),this.withRetry(e,t,n)):r}catch(r){let i=r;if(U.debug(i.stack),U.debug({input:t,init:{method:n?.method,headers:n?.headers,body:`...`}}),!this.#hasAttempts(t))throw r;return await this.#nextRetry(t),this.withRetry(e,t,n)}}async setCookies(e){let t=[];if(typeof e==`string`){let[n]=J([e]);n&&t.push(n)}else if(Array.isArray(e)&&typeof e.at(0)==`string`){let n=J(e);t.push(...n)}else Array.isArray(e)&&typeof e[0]!=`string`&&t.push(...e);if(!(!t||!t?.length))for(let e of t)await this.cookieStore.set(e)}appendHeaders(e){let t=new Headers(this.headers);for(let[n,r]of Object.entries(e))t.set(n,r);return t}#hasAttempts(e){return this.#getFailuresCount(e)<=this.#retryThreshold}#getFailuresCount(e){return this.#failures.get(e)||1}#addFailure(e){this.#failures.set(e,this.#getFailuresCount(e)+1)}async#nextRetry(e){let t=this.#getFailuresCount(e);t&&await new Promise(e=>setTimeout(e,this.#retryDelayMs)),this.#addFailure(e),U.debug(`Retry ${t}/${this.#retryThreshold}: ${String(e)}`)}setHeader(e,t){this.headers.set(e,t)}removeHeader(e){this.headers.delete(e)}setRetryCount(e){e>1&&(this.#retryThreshold=e)}};const Oe=new Z,{COMMON_CONTEXT:ke}=h.default,Ae=(e,t=`Eval`)=>{try{let n=h.default.createScript(t,e);return n}catch(e){return console.error(`Syntax Error: ${e.message}`),null}},Q=(e,t=1)=>{if(Array.isArray(e)||typeof e==`string`){let n=[];for(let r=1;r<=t;r++)n.push(e[Math.floor(Math.random()*e.length)]);return n}else return[]},je=e=>{let t=`default`in g.default?g.default.default:g.default;return new t(e)};var Me=class{#store;constructor({storagePath:e}){this.#store=je({cwd:(0,n.dirname)(e),configName:(0,n.basename)(e,`.json`)})}get length(){return Object.keys(this.#store.store).length}clear(){this.#store.clear()}getItem(e){return this.#store.get(e)??null}key(e){return Object.keys(this.#store.store).at(e)??null}removeItem(e){this.#store.delete(e)}setItem(e,t){this.#store.set(e,t)}};const $=()=>{switch(t.default.type()){case`Darwin`:return`macOS`;case`Windows_NT`:return`Windows`;default:return`Linux`}};Object.defineProperties(Uint8Array.prototype,{toBase64:{value:function(){return Buffer.from(this).toString(`base64`)},writable:!0,configurable:!0},toHex:{value:function(){return Buffer.from(this).toString(`hex`)},writable:!0,configurable:!0}}),Object.defineProperties(Uint8Array,{fromBase64:{value:function(e){return new Uint8Array(Buffer.from(e,`base64`))},writable:!0,configurable:!0},fromHex:{value:function(e){return new Uint8Array(Buffer.from(e,`hex`))},writable:!0,configurable:!0}});const Ne=new Map([[24,[`Sequoia`,`15`]],[23,[`Sonoma`,`14`]],[22,[`Ventura`,`13`]],[21,[`Monterey`,`12`]],[20,[`Big Sur`,`11`]],[19,[`Catalina`,`10.15`]],[18,[`Mojave`,`10.14`]],[17,[`High Sierra`,`10.13`]],[16,[`Sierra`,`10.12`]],[15,[`El Capitan`,`10.11`]],[14,[`Yosemite`,`10.10`]],[13,[`Mavericks`,`10.9`]],[12,[`Mountain Lion`,`10.8`]],[11,[`Lion`,`10.7`]],[10,[`Snow Leopard`,`10.6`]],[9,[`Leopard`,`10.5`]],[8,[`Tiger`,`10.4`]],[7,[`Panther`,`10.3`]],[6,[`Jaguar`,`10.2`]],[5,[`Puma`,`10.1`]]]),Pe=()=>{let e=Number(t.default.release().split(`.`)[0]),[n,r]=Ne.get(e)||[`Unknown`,``];return{name:n,version:r}},Fe=()=>{switch($()){case`macOS`:return Pe().version;case`Windows`:return t.default.release();case`Linux`:return t.default.release()}},Ie=()=>{let e=[{brand:`Azot`,version:T.version.split(`.`).slice(0,2).join(`.`)},{brand:`Node.js`,version:process.version.replace(`v`,``).split(`.`).slice(0,1).join(`.`)}];return{mobile:!1,platform:$(),brands:e,getHighEntropyValues:async n=>{let r={mobile:!1,platform:$(),brands:e};return n.includes(`architecture`)&&(r.architecture=t.default.arch()),n.includes(`platform`)&&(r.platform=$()),n.includes(`platformVersion`)&&(r.platformVersion=Fe()),n.includes(`fullVersionList`)&&(r.fullVersionList=[{brand:`Azot`,version:T.version},{brand:`Node.js`,version:process.version}]),r}}},Le=({name:e=`extension`,dir:t=process.cwd()}={})=>{let i=j((0,n.join)(t,e)),a=new Me({storagePath:(0,n.join)(i,`storage.json`)}),o=new X({storagePath:(0,n.join)(i,`cookies.json`)}),s=new Z({cookieStore:o}),c=(e,t,n)=>e.split(t)[1]?.split(n)[0]?.trim(),l={sanitizeString:W,execUrlPatterns:G,extendEpisodes:K,between:c,getRandomElements:Q},u={defineExtension:e=>e,version:T.version,input:we,sleep:r.setTimeout,sanitizeString:W,execUrlPatterns:G,extendEpisodes:K,between:c,getRandomElements:Q,utils:l,prompt:q.ask.bind(q)};class d{get cookie(){return o.toString()}}let f={fetch:s.fetch.bind(s),Response,Request,Headers,AbortController,AbortSignal,URL,URLSearchParams,URLPattern,Blob,structuredClone,btoa,atob,TextEncoder,TextDecoder,Uint8Array,crypto,console:U,prompt:Ee,alert:e=>{U.warn(e)},Event,EventTarget,localStorage:a,cookieStore:o,document:new d,eval:e=>Ae(e)?.exports,navigator:{appName:`Azot`,appVersion:T.version,platform:process.platform,userAgentData:Ie()}},p={http:s,question:q,common:l,Streamyx:u,Azot:u,window:f,...f};return p};exports.createContext=Le;
package/package.json CHANGED
@@ -1,71 +1,154 @@
1
1
  {
2
2
  "name": "azot",
3
- "version": "0.9.3",
4
- "description": "Build extensions for Azot with Node.js",
5
- "homepage": "https://developers.azot.so",
6
- "main": "./dist/index.js",
3
+ "productName": "Azot",
4
+ "version": "5.0.0-alpha.2",
5
+ "main": "./out/main.js",
6
+ "types": "./types/main.d.ts",
7
+ "exports": {
8
+ ".": {
9
+ "types": "./types/main.d.ts",
10
+ "import": "./out/main.js",
11
+ "require": "./out/main.js"
12
+ },
13
+ "./test": {
14
+ "types": "./types/test.d.ts",
15
+ "import": "./out/test.js",
16
+ "require": "./out/test.js"
17
+ }
18
+ },
7
19
  "bin": {
8
- "azt": "./bin/cli.js"
20
+ "azt": "out/azt.js"
9
21
  },
10
- "types": "index.d.ts",
11
22
  "files": [
12
- "index.d.ts",
13
- "bin",
14
- "dist",
23
+ "out",
24
+ "azot.d.ts",
15
25
  "types",
16
- "public.pem"
26
+ ".npmrc"
17
27
  ],
18
- "scripts": {
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 ."
25
- },
28
+ "author": "Vitaly Gashkov <vitalygashkov@vk.com>",
29
+ "description": "A powerful, extensible app for downloading videos",
26
30
  "repository": {
27
31
  "type": "git",
28
- "url": "git+https://github.com/azot-labs/extensions.git"
32
+ "url": "https://github.com/azot-labs/azot.git"
29
33
  },
30
- "keywords": [
31
- "azot",
32
- "extensions",
33
- "types",
34
- "api"
35
- ],
36
- "bugs": {
37
- "url": "https://github.com/azot-labs/extensions/issues",
38
- "email": "vitalygashkov@vk.com"
34
+ "homepage": "https://azot.so",
35
+ "scripts": {
36
+ "start": "tsx --env-file .env ./src/main/cli.ts",
37
+ "preview": "electron-vite preview --config vite.desktop.config.mjs",
38
+ "dev": "electron-vite dev --config vite.desktop.config.mjs --watch",
39
+ "test": "vitest",
40
+ "coverage": "vitest run --coverage",
41
+ "bundle:lib": "tsdown",
42
+ "bundle:cli": "electron-vite build --config vite.cli.config.mjs",
43
+ "bundle": "npm run bundle:cli && electron-vite build --config vite.desktop.config.mjs",
44
+ "build": "npm run bundle && electron-builder build --config electron-builder.config.js",
45
+ "build:mac": "npm run bundle && electron-builder build --mac --config electron-builder.config.js",
46
+ "build:win": "npm run bundle && electron-builder build --win --config electron-builder.config.js",
47
+ "build:linux": "npm run bundle && electron-builder build --linux --config electron-builder.config.js",
48
+ "publish": "npm run bundle && electron-builder build --publish always --config electron-builder.config.js",
49
+ "publish:lib": "npm run bundle:lib && npm publish --tag alpha",
50
+ "typecheck": "npm run typecheck:node && npm run typecheck:web",
51
+ "typecheck:node": "tsc --noEmit -p tsconfig.node.json --composite false",
52
+ "typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
53
+ "format": "prettier --write .",
54
+ "lint": "eslint . --ext .js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts,.vue --fix"
39
55
  },
40
- "author": "Vitaly Gashkov <vitalygashkov@vk.com>",
41
- "license": "MIT",
42
- "readmeFilename": "README.md",
56
+ "engines": {
57
+ "node": "22"
58
+ },
59
+ "os": [
60
+ "darwin",
61
+ "linux",
62
+ "win32"
63
+ ],
43
64
  "funding": [
44
65
  {
45
66
  "type": "individual",
46
- "url": "https://boosty.to/vitalygashkov"
47
- },
48
- {
49
- "type": "patreon",
50
- "url": "https://www.patreon.com/vitalygashkov"
67
+ "url": "https://t.me/tribute/app?startapp=dqW2"
51
68
  }
52
69
  ],
53
- "engines": {
54
- "node": ">=20"
70
+ "dependencies": {
71
+ "@electron-toolkit/preload": "^3.0.2",
72
+ "@electron-toolkit/utils": "^4.0.0",
73
+ "@inquirer/prompts": "^7.8.3",
74
+ "@logtape/file": "^1.0.4",
75
+ "@logtape/logtape": "^1.0.4",
76
+ "@logtape/pretty": "^1.0.4",
77
+ "@tanstack/query-core": "^5.85.5",
78
+ "@tribute-tg/better-auth": "^1.0.9",
79
+ "better-auth": "^1.3.7",
80
+ "bytenode": "^1.5.7",
81
+ "conf": "^14.0.0",
82
+ "cross-spawn": "^7.0.6",
83
+ "dasha": "3.1.8",
84
+ "electron-squirrel-startup": "^1.0.1",
85
+ "electron-updater": "^6.6.2",
86
+ "impit": "^0.5.4",
87
+ "javascript-obfuscator": "^4.1.1",
88
+ "metavm": "^1.4.4",
89
+ "molnia": "^0.1.5",
90
+ "nanospinner": "^1.2.2",
91
+ "okova": "^0.9.3",
92
+ "p-queue": "^8.1.0",
93
+ "picocolors": "^1.1.1",
94
+ "tsdown": "^0.14.2",
95
+ "undici": "^7.15.0",
96
+ "urlpattern-polyfill": "^10.1.0",
97
+ "yargs": "^18.0.0",
98
+ "yauzl": "^3.2.0"
55
99
  },
56
100
  "devDependencies": {
57
- "@eslint/js": "^9.33.0",
58
- "@types/node": "^24.2.1",
59
- "dasha": "^3.1.6",
60
- "eslint": "^9.33.0",
61
- "eslint-config-prettier": "^10.1.8",
62
- "eslint-plugin-prettier": "^5.5.4",
101
+ "@electron-toolkit/eslint-config": "^2.1.0",
102
+ "@electron-toolkit/eslint-config-prettier": "^3.0.0",
103
+ "@electron-toolkit/eslint-config-ts": "^3.1.0",
104
+ "@electron-toolkit/tsconfig": "^1.0.1",
105
+ "@eslint/js": "^9.26.0",
106
+ "@iconify/vue": "^4.3.0",
107
+ "@intlify/unplugin-vue-i18n": "^6.0.8",
108
+ "@rushstack/eslint-patch": "^1.10.5",
109
+ "@tailwindcss/vite": "^4.1.12",
110
+ "@tanstack/vue-query": "^5.85.5",
111
+ "@types/node": "^24.3.0",
112
+ "@types/wicg-file-system-access": "^2023.10.5",
113
+ "@types/yargs": "^17.0.33",
114
+ "@vee-validate/zod": "^4.15.1",
115
+ "@vitejs/plugin-vue": "^6.0.1",
116
+ "@vue/eslint-config-prettier": "^10.2.0",
117
+ "@vue/eslint-config-typescript": "^14.5.0",
118
+ "@vueuse/core": "^13.7.0",
119
+ "class-variance-authority": "^0.7.1",
120
+ "clsx": "^2.1.1",
121
+ "dotenv": "^17.2.1",
122
+ "electron": "37.3.1",
123
+ "electron-builder": "^26.0.12",
124
+ "electron-vite": "^4.0.0",
125
+ "eslint": "^9.34.0",
126
+ "eslint-plugin-import": "^2.32.0",
127
+ "eslint-plugin-n": "^17.21.3",
128
+ "eslint-plugin-vue": "^10.4.0",
129
+ "execa": "^9.6.0",
63
130
  "globals": "^16.3.0",
131
+ "lucide-vue-next": "^0.541.0",
132
+ "non.geist": "^1.0.4",
133
+ "pinia": "^3.0.3",
134
+ "postcss": "^8.5.6",
64
135
  "prettier": "^3.6.2",
65
- "typescript": "^5.9.2"
66
- },
67
- "dependencies": {
68
- "javascript-obfuscator": "^4.1.1",
69
- "tsdown": "^0.14.1"
136
+ "reka-ui": "^2.4.1",
137
+ "sass": "^1.90.0",
138
+ "tailwind-merge": "^3.3.1",
139
+ "tailwindcss": "^4.1.12",
140
+ "tailwindcss-animate": "^1.0.7",
141
+ "tsx": "^4.20.5",
142
+ "typescript": "^5.9.2",
143
+ "vee-validate": "^4.15.1",
144
+ "vite": "^7.1.3",
145
+ "vite-plugin-static-copy": "^3.1.2",
146
+ "vitest": "^3.2.4",
147
+ "vue": "^3.5.18",
148
+ "vue-eslint-parser": "^10.2.0",
149
+ "vue-i18n": "^11.1.11",
150
+ "vue-sonner": "^1.3.0",
151
+ "vue-tsc": "^3.0.6",
152
+ "zod": "^3.25.42"
70
153
  }
71
154
  }
@@ -1,4 +1,4 @@
1
- import { Options } from './options';
1
+ import type { VideoCodec, DynamicRange, AudioCodec } from 'dasha';
2
2
 
3
3
  export interface ExtensionConfig {
4
4
  id: string;
@@ -12,7 +12,7 @@ export interface Extension {
12
12
  /**
13
13
  * Can handle URL or URL pattern
14
14
  */
15
- canHandle?: ((url: URL) => boolean | Promise<boolean>) | string;
15
+ canHandle?: ((url: string) => boolean | Promise<boolean>) | string;
16
16
 
17
17
  /**
18
18
  * Performs initialization of extension (e.g. token refresh)
@@ -26,18 +26,12 @@ export interface Extension {
26
26
  /**
27
27
  * Fetches content metadata from URL
28
28
  */
29
- fetchContentMetadata: (
30
- url: string,
31
- options: Options,
32
- ) => Promise<ContentMetadata[]>;
29
+ fetchContentMetadata: (url: string, options: Options) => Promise<ContentMetadata[]>;
33
30
 
34
31
  /**
35
32
  * Fetches data about content source (e.g. manifest URL, external subtitles, etc.)
36
33
  */
37
- fetchContentSource?: (
38
- contentId: string,
39
- options: Options,
40
- ) => Promise<ContentSource | null>;
34
+ fetchContentSource?: (contentId: string, options: Options) => Promise<ContentSource | null>;
41
35
 
42
36
  /**
43
37
  * Fetches just content DRM config (e.g. license server URL, request headers, etc.)
@@ -71,6 +65,51 @@ export interface Extension {
71
65
  match?: string;
72
66
  }
73
67
 
68
+ export type Options = {
69
+ videoQuality?: string;
70
+ videoCodecs?: VideoCodec[];
71
+ videoRange?: DynamicRange;
72
+ videoBitrate?: number;
73
+ videoDimension?: '2D' | '3D';
74
+
75
+ audioCodecs?: AudioCodec[];
76
+ audioChannels?: number;
77
+ audioBitrate?: number;
78
+
79
+ subtitleFormat?: string;
80
+ subtitleLanguages?: string[];
81
+
82
+ languages?: string[];
83
+
84
+ skipVideo?: boolean;
85
+ skipAudio?: boolean;
86
+ skipSubtitles?: boolean;
87
+ skipMux?: boolean;
88
+
89
+ experimentalSelectTracks?: boolean;
90
+
91
+ episodes?: Map<number, Set<number>>;
92
+ retry?: number;
93
+ connections?: number;
94
+ proxy?: string | null;
95
+ proxyMeta?: string | null;
96
+ proxyMedia?: string | null;
97
+
98
+ movieTemplate?: string;
99
+ episodeTemplate?: string;
100
+ hardsub?: boolean;
101
+ trimBegin?: string;
102
+ trimEnd?: string;
103
+
104
+ pssh?: string;
105
+ drmTemplate?: string;
106
+ header?: Record<string, string>;
107
+
108
+ http2?: boolean;
109
+ keys?: { kid: string; key: string }[];
110
+ debug?: boolean;
111
+ };
112
+
74
113
  export interface MediaInfo {
75
114
  id: string;
76
115
  type?: 'movie' | 'tv';
@@ -109,10 +148,7 @@ export interface MediaDrm {
109
148
  transformRequest?(request: Request): Request;
110
149
  transformResponse?(response: Response): Response;
111
150
 
112
- fetchCertificate?(
113
- message: Uint8Array,
114
- sessionId: string,
115
- ): Promise<Uint8Array>;
151
+ fetchCertificate?(message: Uint8Array, sessionId: string): Promise<Uint8Array>;
116
152
  fetchLicense?(message: Uint8Array, sessionId: string): Promise<Uint8Array>;
117
153
  }
118
154
 
@@ -0,0 +1,15 @@
1
+ export interface DialogOptions<T extends string> {
2
+ title?: string;
3
+ fields?: Record<T, InputField>;
4
+ }
5
+
6
+ export type InputType = 'text' | 'password' | 'number' | 'checkbox' | 'select' | 'date' | 'confirm';
7
+
8
+ export type InputField = {
9
+ type?: InputType;
10
+ label: string;
11
+ placeholder?: string;
12
+ defaultValue?: string;
13
+ required?: boolean;
14
+ options?: string[];
15
+ };
@@ -0,0 +1,143 @@
1
+ import { Extension } from './extension';
2
+ import { DialogOptions } from './input';
3
+
4
+ export * from './extension';
5
+
6
+ /**
7
+ * Simple wrapper to support type checking
8
+ */
9
+ export function defineExtension(extension: Extension): Extension;
10
+
11
+ /**
12
+ * Get Azot version
13
+ */
14
+ export const version: string;
15
+
16
+ export const utils: {
17
+ sanitizeString: (text: string) => string;
18
+
19
+ execUrlPatterns: (
20
+ url: string,
21
+ patterns: string[],
22
+ baseUrls: string[],
23
+ ) => {
24
+ pathname: Record<string, string | undefined>;
25
+ search: Record<string, string | undefined>;
26
+ };
27
+
28
+ extendEpisodes: (episodesBySeasons?: Map<number, Set<number>>) => {
29
+ items: Map<number, Set<number>>;
30
+ has: (episode?: number, season?: number) => boolean;
31
+ set: (episode?: number, season?: number) => void;
32
+ getMin: () => number;
33
+ getMax: () => number;
34
+ seasonsCount: number;
35
+ episodesCount: number;
36
+ };
37
+
38
+ getRandomElements: (array: unknown, count?: number) => unknown[];
39
+ };
40
+
41
+ export function input<T extends string = 'answer'>(
42
+ message: string,
43
+ options?: DialogOptions<T>,
44
+ ): Promise<Record<T, string>>;
45
+
46
+ declare global {
47
+ /**
48
+ *
49
+ * A partial implementation of [Navigator](https://developer.mozilla.org/ru/docs/Web/API/Navigator) for Azot
50
+ */
51
+ var navigator: Navigator;
52
+
53
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/cookieStore) */
54
+ const cookieStore: CookieStore;
55
+
56
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/prompt) */
57
+ function prompt(message?: string, _default?: string): string | null;
58
+
59
+ /** [MDN Reference](https://developer.mozilla.org/ru/docs/Web/API/Window/alert) */
60
+ function alert(message?: any): void;
61
+
62
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/Window/fetch) */
63
+ function fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
64
+
65
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval) */
66
+ function eval(x: string): any;
67
+
68
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/CookieStore) */
69
+ interface CookieStore {
70
+ get(cookie: string | { name: string; url: string }): Promise<Cookie | null>;
71
+ getAll(cookie?: string | { name: string; url: string }): Promise<Cookie[]>;
72
+ set(cookie: Cookie): Promise<void>;
73
+ delete(
74
+ cookie?:
75
+ | string
76
+ | {
77
+ name: string;
78
+ domain?: string;
79
+ path?: string;
80
+ partitioned?: boolean;
81
+ },
82
+ ): Promise<void>;
83
+ addToHeaders(headers: Headers): void;
84
+ toString(): string;
85
+ }
86
+
87
+ /** [MDN Reference](https://developer.mozilla.org/en-US/docs/Web/API/CookieStore/get#return_value) */
88
+ interface Cookie {
89
+ name: string;
90
+ value: string;
91
+ domain?: string;
92
+ path?: string;
93
+ expires?: string;
94
+ httpOnly?: boolean;
95
+ secure?: boolean;
96
+ sameSite?: 'Strict' | 'Lax' | 'None';
97
+ partitioned?: boolean;
98
+ }
99
+
100
+ /** A partial implementation of [Navigator](https://developer.mozilla.org/ru/docs/Web/API/Navigator) for Azot */
101
+ interface Navigator {
102
+ appName: string;
103
+ appVersion: string;
104
+ platform: string;
105
+ userAgentData: {
106
+ mobile: boolean;
107
+ platform: string;
108
+ getHighEntropyValues(hints: string[]): Promise<UADataValues>;
109
+ };
110
+ }
111
+
112
+ interface NavigatorUABrandVersion {
113
+ brand: string;
114
+ version: string;
115
+ }
116
+
117
+ interface UADataValues {
118
+ architecture: string;
119
+ fullVersionList: NavigatorUABrandVersion[];
120
+ mobile: boolean;
121
+ platform: string;
122
+ platformVersion: string;
123
+ }
124
+
125
+ /** A partial implementation of the [Document](https://developer.mozilla.org/en-US/docs/Web/API/Document) for Azot */
126
+ interface Document {
127
+ readonly cookie: string;
128
+ }
129
+
130
+ interface Uint8Array {
131
+ /** [TC39 proposal](https://github.com/tc39/proposal-arraybuffer-base64) */
132
+ toBase64(): string;
133
+ /** [TC39 proposal](https://github.com/tc39/proposal-arraybuffer-base64) */
134
+ toHex(): string;
135
+ }
136
+
137
+ interface Uint8ArrayConstructor {
138
+ /** [TC39 proposal](https://github.com/tc39/proposal-arraybuffer-base64) */
139
+ fromBase64(base64String: string): Uint8Array;
140
+ /** [TC39 proposal](https://github.com/tc39/proposal-arraybuffer-base64) */
141
+ fromHex(hexString: string): Uint8Array;
142
+ }
143
+ }
@@ -0,0 +1,4 @@
1
+ /**
2
+ * Create a new context for extension script
3
+ */
4
+ export function createContext(options?: { name?: string; dir?: string }): Record<string, any>;
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Vitaly Gashkov <vitalygashkov@vk.com>
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
package/bin/cli.js DELETED
@@ -1,2 +0,0 @@
1
- #!/usr/bin/env node
2
- var e=(e,t)=>()=>(t||e((t={exports:{}}).exports,t),t.exports),t=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}})),n=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:r}=require(`node:util`),{rmSync:i,readdirSync:a,readFileSync:o}=require(`node:fs`),s=require(`node:path`),{build:c}=require(`tsdown`),{encrypt:l,decrypt:u}=t(),{obfuscate:d}=n(),f=r({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`},format:{type:`string`,short:`f`,description:`Output format`},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`}}}),p=()=>{let e=[process.cwd(),s.join(process.cwd(),`src`),s.join(process.cwd(),`lib`)];for(let t of e){let e=a(t),n=e.filter(e=>!e.endsWith(`.d.ts`)).filter(e=>new Set([`.ts`,`.js`]).has(s.extname(e))),r=e=>s.basename(e,s.extname(e)),i=n.find(e=>r(e)===`index`)||n.find(e=>r(e)===`main`)||n[0];if(i)return s.join(t,i)}};(async()=>{let[e,...t]=f.positionals,n=f.values.input||t[0]||p();if(e===`build`||e===`pack`){let t=typeof f.values.minify==`boolean`?f.values.minify:!0;await c({entry:n,format:f.values.format??`cjs`,platform:`node`,target:`node22`,watch:f.values.watch,minify:t}),f.values.input=s.join(process.cwd(),`dist`,s.basename(n).replace(/\.ts$/,`.js`));let r=require(s.join(process.cwd(),`package.json`)),a=typeof f.values.obfuscate==`boolean`,u=a?f.values.obfuscate:r.private;u&&d(f.values.input,f.values.input);let p=f.values.encrypt||e===`pack`;if(p){let e=o(f.values.key||s.join(__dirname,`../public.pem`)),t=f.values.output||f.values.input.replace(/\.js$/,`-${r.version}.stx`);l(e,f.values.input,t),i(f.values.input)}}else if(e===`decrypt`){let e=o(f.values.key||s.join(__dirname,`../private.pem`)),t=f.values.output||n.replace(/\.stx$/,`.js`);u(e,n,t),i(f.values.input)}else if(e===`dev`||e===`develop`||!e){let e=typeof f.values.minify==`boolean`?f.values.minify:!1;await c({entry:n,format:f.values.format??`cjs`,platform:`node`,target:`node20`,watch:!0,minify:e})}})();
package/dist/index.js DELETED
@@ -1 +0,0 @@
1
- const e=e=>e,t=`Streamyx`in globalThis?globalThis.Streamyx:{},n=`Azot`in globalThis?globalThis.Azot:{};if(!globalThis.Azot&&globalThis.Streamyx&&(globalThis.Azot=globalThis.Streamyx),globalThis.Azot&&!globalThis.Azot.input){let e=async(e,t)=>{let n=t?.fields??{answer:{label:e}},r=await globalThis.Azot.prompt.ask({title:t?.title,description:e,fields:n});return r};globalThis.Azot.input=e}module.exports={defineExtension:e,...t,...n};
package/index.d.ts DELETED
@@ -1,10 +0,0 @@
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/public.pem DELETED
@@ -1,14 +0,0 @@
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-----
package/types/azot.d.ts DELETED
@@ -1,116 +0,0 @@
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
- input<T extends string = 'answer'>(
30
- message: string,
31
- options?: DialogOptions<T>,
32
- ): Promise<Record<T, string>>;
33
- }
34
- }
35
-
36
- export interface DialogOptions<T extends string> {
37
- title?: string;
38
- fields?: Record<T, InputField>;
39
- }
40
-
41
- export type InputType =
42
- | 'text'
43
- | 'password'
44
- | 'number'
45
- | 'checkbox'
46
- | 'select'
47
- | 'date'
48
- | 'confirm';
49
-
50
- export type InputField = {
51
- type?: InputType;
52
- label: string;
53
- placeholder?: string;
54
- defaultValue?: string;
55
- required?: boolean;
56
- options?: string[];
57
- };
58
-
59
- export type PromptRequest = {
60
- title?: string;
61
- description?: string;
62
- fields: Record<string, InputField>;
63
- };
64
-
65
- export type PromptResponse = {
66
- [field: string]: string; // TODO: Add more types with inference from InputField type
67
- };
68
-
69
- export type Common = {
70
- sanitizeString: (text: string) => string;
71
-
72
- execUrlPatterns: (
73
- url: string,
74
- patterns: string[],
75
- baseUrls: string[],
76
- ) => {
77
- pathname: Record<string, string | undefined>;
78
- search: Record<string, string | undefined>;
79
- };
80
-
81
- extendEpisodes: (episodesBySeasons?: Map<number, Set<number>>) => {
82
- items: Map<number, Set<number>>;
83
- has: (episode?: number, season?: number) => boolean;
84
- set: (episode?: number, season?: number) => void;
85
- getMin: () => number;
86
- getMax: () => number;
87
- seasonsCount: number;
88
- episodesCount: number;
89
- };
90
-
91
- getRandomElements: (array: unknown, count?: number) => unknown[];
92
- };
93
-
94
- export type HttpClient = {
95
- headers: Record<string, string>;
96
- cookies: string[];
97
- userAgents: Record<
98
- 'chromeWindows' | 'chromeMacOS' | 'chromeLinux' | 'smartTv' | 'tizen',
99
- string
100
- >;
101
- fetch(
102
- resource: string | URL | Request,
103
- options?: RequestInit,
104
- ): Promise<Response>;
105
- fetchAsChrome(
106
- resource: string | URL | Request,
107
- options?: RequestInit,
108
- ): Promise<Response>;
109
- appendCookies(setCookie: string | string[]): void;
110
- setAgent(proxy?: string | null): void;
111
- setCookies(cookies: string[]): void;
112
- setHeader(name: string, value: string): void;
113
- setHeaders(headers: Record<string, string>): void;
114
- removeHeader(name: string): void;
115
- destroySessions(): Promise<void>;
116
- };
@@ -1,34 +0,0 @@
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 {};
@@ -1,8 +0,0 @@
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 {};
@@ -1,33 +0,0 @@
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 {};
@@ -1,28 +0,0 @@
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 {};
@@ -1,46 +0,0 @@
1
- import type { VideoCodec, DynamicRange, AudioCodec } from 'dasha';
2
-
3
- export type Options = {
4
- videoQuality?: string;
5
- videoCodecs?: VideoCodec[];
6
- videoRange?: DynamicRange;
7
- videoBitrate?: number;
8
- videoDimension?: '2D' | '3D';
9
-
10
- audioCodecs?: AudioCodec[];
11
- audioChannels?: number;
12
- audioBitrate?: number;
13
-
14
- subtitleFormat?: string;
15
- subtitleLanguages?: string[];
16
-
17
- languages?: string[];
18
-
19
- skipVideo?: boolean;
20
- skipAudio?: boolean;
21
- skipSubtitles?: boolean;
22
- skipMux?: boolean;
23
-
24
- experimentalSelectTracks?: boolean;
25
-
26
- episodes?: Map<number, Set<number>>;
27
- retry?: number;
28
- connections?: number;
29
- proxy?: string | null;
30
- proxyMeta?: string | null;
31
- proxyMedia?: string | null;
32
-
33
- movieTemplate?: string;
34
- episodeTemplate?: string;
35
- hardsub?: boolean;
36
- trimBegin?: string;
37
- trimEnd?: string;
38
-
39
- pssh?: string;
40
- drmTemplate?: string;
41
- header?: Record<string, string>;
42
-
43
- http2?: boolean;
44
- keys?: { kid: string; key: string }[];
45
- debug?: boolean;
46
- };
@@ -1,17 +0,0 @@
1
- declare global {
2
- interface Uint8Array {
3
- /** [TC39 proposal](https://github.com/tc39/proposal-arraybuffer-base64) */
4
- toBase64(): string;
5
- /** [TC39 proposal](https://github.com/tc39/proposal-arraybuffer-base64) */
6
- toHex(): string;
7
- }
8
-
9
- interface Uint8ArrayConstructor {
10
- /** [TC39 proposal](https://github.com/tc39/proposal-arraybuffer-base64) */
11
- fromBase64(base64String: string): Uint8Array;
12
- /** [TC39 proposal](https://github.com/tc39/proposal-arraybuffer-base64) */
13
- fromHex(hexString: string): Uint8Array;
14
- }
15
- }
16
-
17
- export {};