@sebbo2002/node-pyatv 9.0.3-develop.4 → 9.0.3-develop.5
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/dist/bin/check.cjs +1 -1
- package/dist/bin/check.cjs.map +1 -1
- package/dist/lib/index.cjs +1 -1
- package/dist/lib/index.cjs.map +1 -1
- package/package.json +4 -4
package/dist/bin/check.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var B=Object.create;var L=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var Y=Object.getPrototypeOf,z=Object.prototype.hasOwnProperty;var Q=(s,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of H(e))!z.call(s,n)&&n!==t&&L(s,n,{get:()=>e[n],enumerable:!(i=q(e,n))||i.enumerable});return s};var X=(s,e,t)=>(t=s!=null?B(Y(s)):{},Q(e||!s||!s.__esModule?L(t,"default",{value:s,enumerable:!0}):t,s));var Z=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.src
|
|
1
|
+
"use strict";var B=Object.create;var L=Object.defineProperty;var q=Object.getOwnPropertyDescriptor;var H=Object.getOwnPropertyNames;var Y=Object.getPrototypeOf,z=Object.prototype.hasOwnProperty;var Q=(s,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of H(e))!z.call(s,n)&&n!==t&&L(s,n,{get:()=>e[n],enumerable:!(i=q(e,n))||i.enumerable});return s};var X=(s,e,t)=>(t=s!=null?B(Y(s)):{},Q(e||!s||!s.__esModule?L(t,"default",{value:s,enumerable:!0}):t,s));var Z=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,y=Z();var J=require("fs"),I=require("path"),C=X(require("semver"),1),M=require("url");var T=class{get device(){return this.values.device}get key(){return this.values.key}get newValue(){return this.values.new}get oldValue(){return this.values.old}get value(){return this.values.new}values;constructor(e){this.values=Object.assign({},e,{key:e.key})}};var W=require("events");var U=require("child_process");var O=(o=>(o.idle="idle",o.loading="loading",o.paused="paused",o.playing="playing",o.seeking="seeking",o.stopped="stopped",o))(O||{});var R=(i=>(i.focued="focused",i.focused="focused",i.unfocused="unfocused",i))(R||{}),j=(l=>(l.down="down",l.home="home",l.homeHold="home_hold",l.left="left",l.menu="menu",l.next="next",l.pause="pause",l.play="play",l.playPause="play_pause",l.previous="previous",l.right="right",l.select="select",l.skipBackward="skip_backward",l.skipForward="skip_forward",l.stop="stop",l.suspend="suspend",l.topMenu="top_menu",l.turnOff="turn_off",l.turnOn="turn_on",l.up="up",l.volumeDown="volume_down",l.volumeUp="volume_up",l.wakeup="wakeup",l))(j||{});var _=(n=>(n.music="music",n.tv="tv",n.unknown="unknown",n.video="video",n))(_||{}),k=(t=>(t.off="off",t.on="on",t))(k||{});var x=(i=>(i.all="all",i.off="off",i.track="track",i))(x||{}),E=(i=>(i.albums="albums",i.off="off",i.songs="songs",i))(E||{});var D=[];function m(){let s="?";for(let e=0;e<1e3;e+=1)if(s=Math.round(Math.random()*(e+6)*36).toString(36).toUpperCase(),!D.includes(s)){D.push(s);break}return s}function G(s,e){return!!(Array.isArray(s)&&Array.isArray(e)&&JSON.stringify(s.sort((t,i)=>t.identifier<i.identifier?-1:1))===JSON.stringify(e.sort((t,i)=>t.identifier<i.identifier?-1:1)))}function p(s,e,t){if(t.debug){let i=typeof t.debug=="function"?t.debug:console.log,n=!process.env.NO_COLOR&&!t.noColors,r=[n?"\x1B[0m":"",n?"\x1B[90m":"","[node-pyatv][",n?"\x1B[37m":"",s,n?"\x1B[90m":"","] ",n?"\x1B[0m":"",e];i.apply(null,[r.join("")])}}function F(s,e,t,i){let n=K(e,i),r=typeof i.spawn=="function"?i.spawn:U.spawn;p(s,`${n} ${t.join(" ")}`,i);let o=r(n,t,{env:process.env}),a=h=>p(s,`stdout: ${String(h).trim()}`,i),d=h=>p(s,`stderr: ${String(h).trim()}`,i),u=h=>p(s,`error: ${String(h).trim()}`,i),b=h=>{p(s,`${n} exited with code: ${h}`,i),o.stdout&&o.stdout.off("data",a),o.stderr&&o.stderr.off("data",d),o.off("error",u),o.off("close",b)};return o.stdout&&o.stdout.on("data",a),o.stderr&&o.stderr.on("data",d),o.on("error",u),o.on("close",b),o}function K(s,e){return s==="atvremote"&&typeof e.atvremotePath=="string"?e.atvremotePath:s==="atvscript"&&typeof e.atvscriptPath=="string"?e.atvscriptPath:s}function g(s={}){let e=[];return s.hosts?e.push("-s",s.hosts.join(",")):s.host&&e.push("-s",s.host),s.id&&e.push("-i",s.id),s.protocol&&e.push("--protocol",s.protocol),s.dmapCredentials&&e.push("--dmap-credentials",s.dmapCredentials),s.mrpCredentials&&e.push("--mrp-credentials",s.mrpCredentials),s.airplayCredentials&&e.push("--airplay-credentials",s.airplayCredentials),s.companionCredentials&&e.push("--companion-credentials",s.companionCredentials),s.raopCredentials&&e.push("--raop-credentials",s.raopCredentials),e}function A(s,e,t){let i=r=>p(e,r,t),n={album:null,app:null,appId:null,artist:null,contentIdentifier:null,dateTime:null,deviceState:null,episodeNumber:null,focusState:null,genre:null,hash:null,iTunesStoreIdentifier:null,mediaType:null,outputDevices:null,position:null,powerState:null,repeat:null,seasonNumber:null,seriesName:null,shuffle:null,title:null,totalTime:null,volume:null};if(!s||typeof s!="object")return n;if(s.exception){let r="Got pyatv Error: "+s.exception;throw s.stacktrace&&(r+=`
|
|
2
2
|
|
|
3
3
|
pyatv Stacktrace:
|
|
4
4
|
`+s.stacktrace),new Error(r)}if(typeof s.datetime=="string"){let r=new Date(s.datetime);isNaN(r.getTime())?i(`Invalid datetime value ${s.datetime}, ignore attribute`):n.dateTime=r}else i(`No datetime value found in input (${JSON.stringify(s)})`);return f(s,n,"hash","hash",i),typeof s.media_type=="string"?Object.keys(_).map(o=>String(o)).includes(s.media_type)?n.mediaType=_[s.media_type]:i(`Unsupported mediaType value ${s.media_type}, ignore attribute`):i(`No mediaType value found in input (${JSON.stringify(s)})`),typeof s.device_state=="string"?Object.keys(O).map(o=>String(o)).includes(s.device_state)?n.deviceState=O[s.device_state]:i(`Unsupported deviceState value ${s.device_state}, ignore attribute`):i(`No deviceState value found in input (${JSON.stringify(s)})`),f(s,n,"title","title",i),f(s,n,"artist","artist",i),f(s,n,"album","album",i),f(s,n,"genre","genre",i),N(s,n,"total_time","totalTime",i),N(s,n,"position","position",i),typeof s.shuffle=="string"?Object.keys(E).map(o=>String(o)).includes(s.shuffle)?n.shuffle=E[s.shuffle]:i(`Unsupported shuffle value ${s.shuffle}, ignore attribute`):i(`No shuffle value found in input (${JSON.stringify(s)})`),typeof s.repeat=="string"?Object.keys(x).map(o=>String(o)).includes(s.repeat)?n.repeat=x[s.repeat]:i(`Unsupported repeat value ${s.repeat}, ignore attribute`):i(`No repeat value found in input (${JSON.stringify(s)})`),f(s,n,"app","app",i),f(s,n,"app_id","appId",i),typeof s.power_state=="string"?Object.keys(k).map(o=>String(o)).includes(s.power_state)?n.powerState=k[s.power_state]:i(`Unsupported powerState value ${s.power_state}, ignore attribute`):i(`No powerState value found in input (${JSON.stringify(s)})`),N(s,n,"volume","volume",i),typeof s.focus_state=="string"?Object.keys(R).map(o=>String(o)).includes(s.focus_state)?n.focusState=R[s.focus_state]:i(`Unsupported focusState value ${s.focus_state}, ignore attribute`):i(`No focusState value found in input (${JSON.stringify(s)})`),Array.isArray(s.output_devices)&&(n.outputDevices=s.output_devices),f(s,n,"content_identifier","contentIdentifier",i),N(s,n,"itunes_store_identifier","iTunesStoreIdentifier",i),N(s,n,"episode_number","episodeNumber",i),N(s,n,"season_number","seasonNumber",i),f(s,n,"series_name","seriesName",i),n}function c(s){s&&D.includes(s)&&D.splice(D.indexOf(s),1)}async function P(s,e,t,i){let n={code:0,stderr:"",stdout:""};if(await new Promise((r,o)=>{let a=F(s,e,t,i),d=v=>n.stdout+=String(v).trim(),u=v=>n.stderr+=String(v).trim(),b=v=>o(v instanceof Error?v:new Error(String(v))),h=v=>{n.code=v,a.stdout&&a.stdout.off("data",d),a.stderr&&a.stderr.off("data",u),a.off("error",b),a.off("close",h),r(void 0)};a.stdout&&a.stdout.on("data",d),a.stderr&&a.stderr.on("data",u),a.on("error",b),a.on("close",h)}),n.stderr.length>0){let r=`Unable to execute request ${s}: ${n.stderr}`;throw p(s,r,i),new Error(r)}if(e==="atvscript")try{return i.allowMultipleResponses?n.stdout.split(`
|
package/dist/bin/check.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../node_modules/tsup/assets/cjs_shims.js","../../src/lib/instance.ts","../../src/lib/device-event.ts","../../src/lib/device-events.ts","../../src/lib/tools.ts","../../src/lib/types.ts","../../src/lib/device.ts","../../src/bin/check.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","'use strict';\n\nimport { promises as fsPromises } from 'fs';\nimport { dirname, join } from 'path';\nimport semver from 'semver';\nimport { fileURLToPath } from 'url';\n\nimport { NodePyATVDevice } from '../lib/index.js';\nimport {\n addRequestId,\n debug,\n getParameters,\n removeRequestId,\n request,\n} from './tools.js';\nimport {\n type NodePyATVDeviceOptions,\n NodePyATVExecutableType,\n type NodePyATVFindAndInstanceOptions,\n type NodePyATVFindResponseObject,\n type NodePyATVInstanceOptions,\n type NodePyATVInternalScanDevice,\n type NodePyATVVersionResponse,\n} from './types.js';\n\n/**\n * Default class exported by `@sebbo2002/node-pyatv`. Use [[find]] to scan for devices in your local network. Use\n * [[device]] to connect to a known device by passing (at least) it's name and IP.\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * ```\n */\nexport default class NodePyATVInstance {\n private readonly options: NodePyATVInstanceOptions = {};\n\n /**\n * Use this to apply [[NodePyATVInstanceOptions]]\n * (e.g. debug log method) to all further requests\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const myPyatv = new pyatv({debug: true});\n * const devices = myPyatv.find();\n * console.log(devices);\n * ```\n * @param options\n */\n public constructor(options: NodePyATVInstanceOptions = {}) {\n this.options = Object.assign({}, options);\n }\n\n /**\n * Checks if pyatv is installed and ready to be used.\n * Will throw an error if not.\n *\n * @param options\n */\n public static async check(\n options: NodePyATVInstanceOptions = {},\n ): Promise<void> {\n const versions = await this.version(options);\n if (!versions.pyatv) {\n throw new Error('Unable to find pyatv. Is it installed?');\n }\n if (semver.lt(versions.pyatv, '0.6.0')) {\n throw new Error(\n \"Found pyatv, but unforunately it's too old. Please update pyatv.\",\n );\n }\n\n try {\n await this.find(options);\n } catch (error) {\n throw new Error(\n `Unable to scan for devices: ${String(error).replace('Error: ', '')}`,\n );\n }\n }\n\n /**\n * Create a [[NodePyATVDevice]] to query the state and control it.\n * At least `host` and `name` are required.\n *\n * @param options\n */\n public static device(options: NodePyATVDeviceOptions): NodePyATVDevice {\n return new NodePyATVDevice(options);\n }\n /**\n * Scan the network for Apple TVs by using pyatv's atvscript. See [[NodePyATVFindAndInstanceOptions]]\n * for the options allowed. Use the `host` / `hosts` attribute to filter by IP addresses. Resolves with\n * an array of [[NodePyATVDevice]].\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const devices = await pyatv.find();\n * console.log(devices);\n * ```\n *\n * Normally `node-pyatv` ignores error messages if at least one device has been found, but if you\n * always want to receive the error messages, you can set the second argument to `true`:\n *\n * ```typescript\n * const result = await pyatv.find({}, true);\n * console.log(result.devices);\n * console.log(result.errors);\n * ```\n *\n * @param options\n */\n public static async find(\n options?: NodePyATVFindAndInstanceOptions,\n ): Promise<NodePyATVDevice[]>;\n public static async find(\n options: NodePyATVFindAndInstanceOptions,\n returnDevicesAndErrors: true,\n ): Promise<NodePyATVFindResponseObject>;\n public static async find(\n options: NodePyATVFindAndInstanceOptions = {},\n returnDevicesAndErrors?: boolean,\n ): Promise<NodePyATVDevice[] | NodePyATVFindResponseObject> {\n const id = addRequestId();\n const parameters = getParameters(options);\n\n const devices: NodePyATVDevice[] = [];\n const errors: Record<string, unknown>[] = [];\n const response = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'scan'],\n { ...(options || {}), allowMultipleResponses: true },\n );\n\n for (const item of response) {\n if (\n typeof item === 'object' &&\n 'result' in item &&\n item.result === 'failure'\n ) {\n errors.push(item);\n } else if (\n typeof item === 'object' &&\n 'result' in item &&\n item.result === 'success' &&\n Array.isArray(item.devices)\n ) {\n devices.push(\n ...item.devices.map((device: NodePyATVInternalScanDevice) =>\n this.device(\n Object.assign({}, options, {\n allIDs: device.all_identifiers,\n host: device.address,\n id: device.identifier,\n mac: device.device_info?.mac || undefined,\n model: device.device_info?.model,\n modelName: device.device_info?.model_str,\n name: device.name,\n os: device.device_info?.operating_system,\n services: device.services,\n version: device.device_info?.version,\n }),\n ),\n ),\n );\n } else {\n throw new Error(\n `Unable to parse pyatv response: ${JSON.stringify(item, null, ' ')}`,\n );\n }\n }\n removeRequestId(id);\n\n if (returnDevicesAndErrors) {\n return { devices, errors };\n }\n if (!devices.length && errors.length) {\n throw new Error(\n `Unable to find any devices, but received ${errors.length} error${errors.length !== 1 ? 's' : ''}: ${JSON.stringify(errors, null, ' ')}`,\n );\n }\n\n return devices;\n }\n\n /**\n * Resolves with the version of pyatv and of the module itself.\n * If a value can't be found, null is returned instead.\n *\n * @param options\n */\n public static async version(\n options: NodePyATVInstanceOptions = {},\n ): Promise<NodePyATVVersionResponse> {\n const id = addRequestId();\n let pyatv = null;\n let module = null;\n\n try {\n pyatv = (await request(\n id,\n NodePyATVExecutableType.atvremote,\n ['--version'],\n options,\n )) as string;\n } catch (error) {\n debug(id, `Unable to get pyatv version due to ${error}`, options);\n }\n\n if (pyatv && pyatv.substr(0, 10) === 'atvremote ') {\n pyatv = pyatv.substr(10);\n }\n if (!semver.valid(pyatv)) {\n debug(\n id,\n `String \"${pyatv}\" is not a valid pyatv version, set it to null`,\n options,\n );\n pyatv = null;\n }\n\n try {\n const packageJsonPath = join(\n dirname(fileURLToPath(import.meta.url)),\n '..',\n '..',\n 'package.json',\n );\n const json = JSON.parse(\n await fsPromises.readFile(packageJsonPath, 'utf8'),\n );\n module = json?.version || null;\n } catch (error) {\n debug(id, `Unable to get module version due to ${error}`, options);\n }\n if (module && !semver.valid(module)) {\n debug(\n id,\n `String \"${module}\" is not a valid module version, set it to null`,\n options,\n );\n module = null;\n }\n\n removeRequestId(id);\n return {\n module,\n pyatv,\n };\n }\n\n /**\n * Checks if pyatv is installed and ready to be used.\n * Will throw an error if not.\n *\n * @param options\n */\n public async check(options: NodePyATVInstanceOptions = {}): Promise<void> {\n return NodePyATVInstance.check(\n Object.assign({}, this.options, options),\n );\n }\n\n /**\n * Create a [[NodePyATVDevice]] to query the state and control it.\n * At least `host` and `name` are required.\n *\n * @param options\n */\n public device(options: NodePyATVDeviceOptions): NodePyATVDevice {\n return NodePyATVInstance.device(\n Object.assign({}, this.options, options),\n );\n }\n\n /**\n * Scan the network for Apple TVs by using pyatv's atvscript. See [[NodePyATVFindAndInstanceOptions]]\n * for the options allowed. Use the `host` / `hosts` attribute to filter by IP addresses. Resolves with\n * an array of [[NodePyATVDevice]].\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const myPyATV = new pyatv({debug: true});\n * const devices = await myPyATV.find();\n * console.log(devices);\n * ```\n *\n * @param options\n */\n public async find(\n options: NodePyATVFindAndInstanceOptions = {},\n ): Promise<NodePyATVDevice[]> {\n return NodePyATVInstance.find(Object.assign({}, this.options, options));\n }\n\n /**\n * Resolves with the version of pyatv and of the module itself.\n * If a value can't be found, null is returned instead.\n *\n * @param options\n */\n public async version(\n options: NodePyATVInstanceOptions = {},\n ): Promise<NodePyATVVersionResponse> {\n return NodePyATVInstance.version(\n Object.assign({}, this.options, options),\n );\n }\n}\n","'use strict';\n\nimport type { NodePyATVEventValueType, NodePyATVStateIndex } from './types.js';\n\nimport { NodePyATVDevice } from '../lib/index.js';\n\nexport default class NodePyATVDeviceEvent {\n /**\n * References the device instance this\n * event originates from\n */\n get device(): NodePyATVDevice {\n return this.values.device;\n }\n\n /**\n * References the attribute name which was changed. So if the\n * title has been updated, this would be `title`.\n */\n get key(): NodePyATVStateIndex {\n return this.values.key;\n }\n\n /**\n * @alias value\n */\n get newValue(): NodePyATVEventValueType {\n return this.values.new;\n }\n\n /**\n * Holds the old value which was there\n * before the value was changed.\n */\n get oldValue(): NodePyATVEventValueType {\n return this.values.old;\n }\n\n /**\n * New, current value for `key`\n */\n get value(): NodePyATVEventValueType {\n return this.values.new;\n }\n\n protected readonly values: {\n device: NodePyATVDevice;\n key: NodePyATVStateIndex;\n new: NodePyATVEventValueType;\n old: NodePyATVEventValueType;\n };\n\n /**\n *\n * @param values\n * @internal\n */\n constructor(values: {\n device: NodePyATVDevice;\n key: NodePyATVStateIndex;\n new: NodePyATVEventValueType;\n old: NodePyATVEventValueType;\n }) {\n this.values = Object.assign({}, values, {\n key: values.key as NodePyATVStateIndex,\n });\n }\n}\n","'use strict';\n\nimport { ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\n\nimport { NodePyATVDevice, NodePyATVDeviceEvent } from '../lib/index.js';\nimport { FakeChildProcess } from './fake-spawn.js';\nimport {\n addRequestId,\n compareOutputDevices,\n debug,\n execute,\n getParameters,\n parseState,\n removeRequestId,\n} from './tools.js';\nimport {\n type NodePyATVDeviceOptions,\n NodePyATVExecutableType,\n type NodePyATVInternalState,\n NodePyATVListenerState,\n type NodePyATVState,\n type NodePyATVStateIndex,\n} from './types.js';\n\n/**\n * @internal\n */\nexport default class NodePyATVDeviceEvents extends EventEmitter {\n private readonly device: NodePyATVDevice;\n private listenerState: NodePyATVListenerState;\n private readonly options: NodePyATVDeviceOptions;\n private pyatv: ChildProcess | FakeChildProcess | undefined;\n private readonly state: NodePyATVState;\n private timeout: NodeJS.Timeout | undefined;\n\n constructor(\n state: NodePyATVState,\n device: NodePyATVDevice,\n options: NodePyATVDeviceOptions,\n ) {\n super();\n\n this.state = state;\n this.device = device;\n this.options = Object.assign({}, options);\n this.listenerState = NodePyATVListenerState.stopped;\n }\n\n addListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.addListener(event, listener);\n this.checkListener();\n return this;\n }\n\n applyStateAndEmitEvents(newState: NodePyATVState): void {\n let keys = Object.keys(this.state);\n\n // Remove special fields from the list\n keys = keys.filter(\n (k) =>\n ![\n 'focusState',\n 'outputDevices',\n 'powerState',\n 'volume',\n ].includes(k),\n );\n\n if ('powerState' in newState && newState.powerState) {\n keys = ['powerState'];\n }\n if ('focusState' in newState && newState.focusState) {\n keys = ['focusState'];\n }\n if ('outputDevices' in newState && newState.outputDevices) {\n keys = ['outputDevices'];\n }\n\n // Volume events don't hold the complete state…\n // see https://github.com/sebbo2002/node-pyatv/pull/291\n if ('volume' in newState && newState.volume !== null) {\n keys = ['volume'];\n }\n\n // If all values are null, we don't need to emit events at all\n // https://github.com/sebbo2002/node-pyatv/issues/295#issuecomment-1888640079\n if (\n !Object.entries(newState).find(\n ([k, v]) => !['dateTime', 'result'].includes(k) && v !== null,\n )\n ) {\n return;\n }\n\n keys.forEach((key: string) => {\n // @ts-expect-error this.state has no index signature\n const oldValue = this.state[key];\n\n // @ts-expect-error same here\n const newValue = newState[key];\n\n if (\n oldValue === undefined ||\n newValue === undefined ||\n oldValue === newValue\n ) {\n return;\n }\n if (\n key === 'outputDevices' &&\n compareOutputDevices(oldValue, newValue)\n ) {\n return;\n }\n\n const event = new NodePyATVDeviceEvent({\n device: this.device,\n key: key as NodePyATVStateIndex,\n new: newValue,\n old: oldValue,\n });\n\n // @ts-expect-error and here\n this.state[key] = newState[key];\n\n try {\n this.emit('update:' + key, event);\n this.emit('update', event);\n } catch (error) {\n this.emit('error', error);\n }\n });\n }\n\n listenerCount(event?: string | symbol): number {\n if (event !== undefined) {\n return super.listenerCount(event);\n }\n\n return this.eventNames()\n .map((event) => this.listenerCount(event))\n .reduce((a, b) => a + b, 0);\n }\n\n off(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.off(event, listener);\n this.checkListener();\n return this;\n }\n\n on(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.on(event, listener);\n this.checkListener();\n return this;\n }\n\n once(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.once(event, (event: NodePyATVDeviceEvent) => {\n listener(event);\n setTimeout(() => this.checkListener(), 0);\n });\n this.checkListener();\n return this;\n }\n\n prependListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.prependListener(event, listener);\n this.checkListener();\n return this;\n }\n\n removeAllListeners(event?: string | symbol): this {\n super.removeAllListeners(event);\n this.checkListener();\n return this;\n }\n\n removeListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.removeListener(event, listener);\n this.checkListener();\n return this;\n }\n\n protected async stopListening(reqId: string): Promise<void> {\n if (\n this.listenerState !== NodePyATVListenerState.starting &&\n this.listenerState !== NodePyATVListenerState.started\n ) {\n return;\n }\n\n this.listenerState = NodePyATVListenerState.stopping;\n if (this.pyatv === undefined) {\n throw new Error(\n \"Unable to stop listening due to internal error: state is stopping, but there's no child process. \" +\n 'This should never happen, please report this.',\n );\n }\n\n if (this.pyatv.stdin) {\n debug(reqId, 'Pressing enter to close atvscript…', this.options);\n this.pyatv.stdin.write('\\n');\n\n await new Promise((cb) => (this.timeout = setTimeout(cb, 250)));\n }\n\n if (\n this.listenerState === NodePyATVListenerState.stopping &&\n this.pyatv\n ) {\n this.pyatv.kill();\n }\n\n this.listenerState = NodePyATVListenerState.stopped;\n return;\n }\n\n private applyPushUpdate(\n update: NodePyATVInternalState,\n reqId: string,\n ): void {\n try {\n const newState = parseState(update, reqId, this.options);\n this.applyStateAndEmitEvents(newState);\n } catch (error) {\n this.emit('error', error);\n }\n }\n\n private checkListener(): void {\n if (\n this.listenerState === NodePyATVListenerState.stopped &&\n this.listenerCount() === 0 &&\n this.timeout\n ) {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n } else if (\n this.listenerState === NodePyATVListenerState.stopped &&\n this.listenerCount() > 0\n ) {\n const id = addRequestId();\n debug(\n id,\n `Start listeing to events from device ${this.options.name}`,\n this.options,\n );\n\n this.startListening(id);\n removeRequestId(id);\n } else if (\n [\n NodePyATVListenerState.started,\n NodePyATVListenerState.starting,\n ].includes(this.listenerState) &&\n this.listenerCount() === 0\n ) {\n const id = addRequestId();\n debug(\n id,\n `Stop listening to events from device ${this.options.name}`,\n this.options,\n );\n\n this.stopListening(id)\n .catch((error) =>\n debug(\n id,\n `Unable to stop listeing: ${error}`,\n this.options,\n ),\n )\n .finally(() => removeRequestId(id));\n }\n }\n\n private parsePushUpdate(reqId: string, data: string): void {\n let json: NodePyATVInternalState;\n\n try {\n json = JSON.parse(data);\n } catch (error) {\n const msg = `Unable to parse stdout json: ${error}`;\n debug(reqId, msg, this.options);\n this.emit('error', new Error(msg));\n return;\n }\n\n this.applyPushUpdate(json, reqId);\n\n if (this.listenerState === NodePyATVListenerState.starting) {\n this.listenerState = NodePyATVListenerState.started;\n this.checkListener();\n }\n }\n\n private startListening(reqId: string): void {\n if (this.listenerState !== NodePyATVListenerState.stopped) {\n return;\n }\n\n this.listenerState = NodePyATVListenerState.starting;\n\n const listenStart = new Date().getTime();\n const parameters = getParameters(this.options);\n this.pyatv = execute(\n reqId,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'push_updates'],\n this.options,\n );\n if (!this.pyatv) {\n throw new Error(\n 'Unable to start listener: Unable to start atvscript',\n );\n }\n\n const onError = (error: Error) => {\n debug(\n reqId,\n `Got error from child process: ${error}`,\n this.options,\n );\n this.emit('error', error);\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onStdErr = (data: any) => {\n const error = new Error(`Got stderr output from pyatv: ${data}`);\n debug(reqId, data.toString(), this.options);\n this.emit('error', error);\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onStdOut = (data: any) => {\n String(data)\n .split('\\n')\n .map((s) => s.trim())\n .filter(Boolean)\n .forEach((s) => {\n debug(reqId, `> ${s}`, this.options);\n this.parsePushUpdate(reqId, s);\n });\n };\n const onClose = (code: number) => {\n if (this.pyatv === undefined) {\n // this should never happen… :/\n return;\n }\n\n this.listenerState = NodePyATVListenerState.stopped;\n debug(\n reqId,\n `Listening with atvscript exited with code ${code}`,\n this.options,\n );\n if (this.timeout !== undefined) {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n }\n\n if (this.pyatv.stdout) {\n this.pyatv.stdout.off('data', onStdOut);\n }\n if (this.pyatv.stderr) {\n this.pyatv.stderr.off('data', onStdErr);\n }\n this.pyatv.off('error', onError);\n this.pyatv.off('close', onClose);\n\n if (\n this.listenerCount() > 0 &&\n new Date().getTime() - listenStart < 30000\n ) {\n debug(\n reqId,\n `Wait 15s and restart listeing to events from device ${this.options.name}`,\n this.options,\n );\n\n this.timeout = setTimeout(() => {\n this.checkListener();\n }, 15000);\n } else if (this.listenerCount() > 0) {\n debug(\n reqId,\n `Restart listeing to events from device ${this.options.name}`,\n this.options,\n );\n this.checkListener();\n }\n\n removeRequestId(reqId);\n };\n\n this.pyatv.on('error', onError);\n this.pyatv.on('close', onClose);\n\n if (this.pyatv.stdout) {\n this.pyatv.stdout.on('data', onStdOut);\n }\n if (this.pyatv.stderr) {\n this.pyatv.stderr.on('data', onStdErr);\n }\n }\n}\n","'use strict';\n\nimport { ChildProcess, spawn, type SpawnOptions } from 'child_process';\n\nimport { FakeChildProcess } from './fake-spawn.js';\nimport {\n NodePyATVDeviceState,\n NodePyATVExecutableType,\n type NodePyATVFindAndInstanceOptions,\n NodePyATVFocusState,\n type NodePyATVInstanceOptions,\n type NodePyATVInternalState,\n NodePyATVMediaType,\n NodePyATVPowerState,\n NodePyATVRepeatState,\n type NodePyATVRequestOptions,\n NodePyATVShuffleState,\n type NodePyATVState,\n} from './types.js';\n\nconst requestIds: string[] = [];\n\ntype NodePyATVScriptResponse<O extends NodePyATVRequestOptions> =\n O['allowMultipleResponses'] extends true\n ? Record<string, unknown>[]\n : Record<string, unknown>;\n\nexport function addRequestId(): string {\n let id = '?';\n\n for (let i = 0; i < 1000; i += 1) {\n id = Math.round(Math.random() * (i + 6) * 36)\n .toString(36)\n .toUpperCase();\n if (!requestIds.includes(id)) {\n requestIds.push(id);\n break;\n }\n }\n\n return id;\n}\n\nexport function compareOutputDevices(\n a: NodePyATVState['outputDevices'],\n b: NodePyATVState['outputDevices'],\n) {\n return Boolean(\n Array.isArray(a) &&\n Array.isArray(b) &&\n JSON.stringify(\n a.sort((a, b) => (a.identifier < b.identifier ? -1 : 1)),\n ) ===\n JSON.stringify(\n b.sort((a, b) => (a.identifier < b.identifier ? -1 : 1)),\n ),\n );\n}\n\nexport function debug(\n id: string,\n message: string,\n options: NodePyATVInstanceOptions,\n): void {\n if (options.debug) {\n const log =\n typeof options.debug === 'function' ? options.debug : console.log;\n const enableColors = !process.env.NO_COLOR && !options.noColors;\n\n const parts = [\n enableColors ? '\\x1b[0m' : '', // Color Reset\n enableColors ? '\\x1b[90m' : '', // Grey\n '[node-pyatv][',\n enableColors ? '\\x1b[37m' : '', // Light Grey\n id,\n enableColors ? '\\x1b[90m' : '', // Grey\n '] ',\n enableColors ? '\\x1b[0m' : '', // Color Reset\n message,\n ];\n\n log.apply(null, [parts.join('')]);\n }\n}\n\nexport function execute(\n requestId: string,\n executableType: NodePyATVExecutableType,\n parameters: string[],\n options: NodePyATVInstanceOptions,\n): ChildProcess | FakeChildProcess {\n const executable = getExecutable(executableType, options);\n const mySpawn: (\n command: string,\n args: Array<string>,\n options: SpawnOptions,\n ) => ChildProcess | FakeChildProcess =\n typeof options.spawn === 'function' ? options.spawn : spawn;\n\n debug(requestId, `${executable} ${parameters.join(' ')}`, options);\n const child = mySpawn(executable, parameters, {\n env: process.env,\n });\n\n /* eslint-disable @typescript-eslint/no-explicit-any*/\n const onStdOut = (data: any) =>\n debug(requestId, `stdout: ${String(data).trim()}`, options);\n const onStdErr = (data: any) =>\n debug(requestId, `stderr: ${String(data).trim()}`, options);\n const onError = (data: any) =>\n debug(requestId, `error: ${String(data).trim()}`, options);\n /* eslint-enable @typescript-eslint/no-explicit-any*/\n\n const onClose = (code: number) => {\n debug(requestId, `${executable} exited with code: ${code}`, options);\n\n if (child.stdout) {\n child.stdout.off('data', onStdOut);\n }\n if (child.stderr) {\n child.stderr.off('data', onStdErr);\n }\n\n child.off('error', onError);\n child.off('close', onClose);\n };\n\n if (child.stdout) {\n child.stdout.on('data', onStdOut);\n }\n if (child.stderr) {\n child.stderr.on('data', onStdErr);\n }\n\n child.on('error', onError);\n child.on('close', onClose);\n\n return child;\n}\n\nexport function getExecutable(\n executable: NodePyATVExecutableType,\n options: NodePyATVInstanceOptions,\n): string {\n if (\n executable === NodePyATVExecutableType.atvremote &&\n typeof options.atvremotePath === 'string'\n ) {\n return options.atvremotePath;\n } else if (\n executable === NodePyATVExecutableType.atvscript &&\n typeof options.atvscriptPath === 'string'\n ) {\n return options.atvscriptPath;\n } else {\n return executable;\n }\n}\n\nexport function getParameters(\n options: NodePyATVFindAndInstanceOptions = {},\n): string[] {\n const parameters: string[] = [];\n\n if (options.hosts) {\n parameters.push('-s', options.hosts.join(','));\n } else if (options.host) {\n parameters.push('-s', options.host);\n }\n if (options.id) {\n parameters.push('-i', options.id);\n }\n if (options.protocol) {\n parameters.push('--protocol', options.protocol);\n }\n if (options.dmapCredentials) {\n parameters.push('--dmap-credentials', options.dmapCredentials);\n }\n if (options.mrpCredentials) {\n parameters.push('--mrp-credentials', options.mrpCredentials);\n }\n if (options.airplayCredentials) {\n parameters.push('--airplay-credentials', options.airplayCredentials);\n }\n if (options.companionCredentials) {\n parameters.push(\n '--companion-credentials',\n options.companionCredentials,\n );\n }\n if (options.raopCredentials) {\n parameters.push('--raop-credentials', options.raopCredentials);\n }\n\n return parameters;\n}\nexport function parseState(\n input: NodePyATVInternalState,\n id: string,\n options: NodePyATVInstanceOptions,\n): NodePyATVState {\n const d = (msg: string) => debug(id, msg, options);\n const result: NodePyATVState = {\n album: null,\n app: null,\n appId: null,\n artist: null,\n contentIdentifier: null,\n dateTime: null,\n deviceState: null,\n episodeNumber: null,\n focusState: null,\n genre: null,\n hash: null,\n iTunesStoreIdentifier: null,\n mediaType: null,\n outputDevices: null,\n position: null,\n powerState: null,\n repeat: null,\n seasonNumber: null,\n seriesName: null,\n shuffle: null,\n title: null,\n totalTime: null,\n volume: null,\n };\n if (!input || typeof input !== 'object') {\n return result;\n }\n if (input.exception) {\n let errorStr = 'Got pyatv Error: ' + input.exception;\n if (input.stacktrace) {\n errorStr += '\\n\\npyatv Stacktrace:\\n' + input.stacktrace;\n }\n\n throw new Error(errorStr);\n }\n\n // datetime\n if (typeof input.datetime === 'string') {\n const date = new Date(input.datetime);\n if (!isNaN(date.getTime())) {\n result.dateTime = date;\n } else {\n d(`Invalid datetime value ${input.datetime}, ignore attribute`);\n }\n } else {\n d(`No datetime value found in input (${JSON.stringify(input)})`);\n }\n\n // hash\n parseStateStringAttr(input, result, 'hash', 'hash', d);\n\n // mediaType\n if (typeof input.media_type === 'string') {\n const validValues = Object.keys(NodePyATVMediaType).map((o) =>\n String(o),\n );\n if (validValues.includes(input.media_type)) {\n result.mediaType =\n NodePyATVMediaType[input.media_type as NodePyATVMediaType];\n } else {\n d(\n `Unsupported mediaType value ${input.media_type}, ignore attribute`,\n );\n }\n } else {\n d(`No mediaType value found in input (${JSON.stringify(input)})`);\n }\n\n // deviceState\n if (typeof input.device_state === 'string') {\n const validValues = Object.keys(NodePyATVDeviceState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.device_state)) {\n result.deviceState =\n NodePyATVDeviceState[\n input.device_state as NodePyATVDeviceState\n ];\n } else {\n d(\n `Unsupported deviceState value ${input.device_state}, ignore attribute`,\n );\n }\n } else {\n d(`No deviceState value found in input (${JSON.stringify(input)})`);\n }\n\n // title\n parseStateStringAttr(input, result, 'title', 'title', d);\n\n // artist\n parseStateStringAttr(input, result, 'artist', 'artist', d);\n\n // album\n parseStateStringAttr(input, result, 'album', 'album', d);\n\n // genre\n parseStateStringAttr(input, result, 'genre', 'genre', d);\n\n // totalTime\n parseStateNumberAttr(input, result, 'total_time', 'totalTime', d);\n\n // position\n parseStateNumberAttr(input, result, 'position', 'position', d);\n\n // shuffle\n if (typeof input.shuffle === 'string') {\n const validValues = Object.keys(NodePyATVShuffleState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.shuffle)) {\n result.shuffle =\n NodePyATVShuffleState[input.shuffle as NodePyATVShuffleState];\n } else {\n d(`Unsupported shuffle value ${input.shuffle}, ignore attribute`);\n }\n } else {\n d(`No shuffle value found in input (${JSON.stringify(input)})`);\n }\n\n // repeat\n if (typeof input.repeat === 'string') {\n const validValues = Object.keys(NodePyATVRepeatState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.repeat)) {\n result.repeat =\n NodePyATVRepeatState[input.repeat as NodePyATVRepeatState];\n } else {\n d(`Unsupported repeat value ${input.repeat}, ignore attribute`);\n }\n } else {\n d(`No repeat value found in input (${JSON.stringify(input)})`);\n }\n\n // app\n parseStateStringAttr(input, result, 'app', 'app', d);\n parseStateStringAttr(input, result, 'app_id', 'appId', d);\n\n // powerState\n if (typeof input.power_state === 'string') {\n const validValues = Object.keys(NodePyATVPowerState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.power_state)) {\n result.powerState =\n NodePyATVPowerState[input.power_state as NodePyATVPowerState];\n } else {\n d(\n `Unsupported powerState value ${input.power_state}, ignore attribute`,\n );\n }\n } else {\n d(`No powerState value found in input (${JSON.stringify(input)})`);\n }\n\n // volume\n parseStateNumberAttr(input, result, 'volume', 'volume', d);\n\n // focusState\n if (typeof input.focus_state === 'string') {\n const validValues = Object.keys(NodePyATVFocusState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.focus_state)) {\n result.focusState =\n NodePyATVFocusState[input.focus_state as NodePyATVFocusState];\n } else {\n d(\n `Unsupported focusState value ${input.focus_state}, ignore attribute`,\n );\n }\n } else {\n d(`No focusState value found in input (${JSON.stringify(input)})`);\n }\n\n // outputDevices\n if (Array.isArray(input.output_devices)) {\n result.outputDevices = input.output_devices;\n }\n\n // contentIdentifier\n parseStateStringAttr(\n input,\n result,\n 'content_identifier',\n 'contentIdentifier',\n d,\n );\n\n // iTunesStoreIdentifier\n parseStateNumberAttr(\n input,\n result,\n 'itunes_store_identifier',\n 'iTunesStoreIdentifier',\n d,\n );\n\n // episodeNumber\n parseStateNumberAttr(input, result, 'episode_number', 'episodeNumber', d);\n\n // seasonNumber\n parseStateNumberAttr(input, result, 'season_number', 'seasonNumber', d);\n\n // seriesName\n parseStateStringAttr(input, result, 'series_name', 'seriesName', d);\n\n return result;\n}\nexport function removeRequestId(id: string | undefined): void {\n if (id && requestIds.includes(id)) {\n requestIds.splice(requestIds.indexOf(id), 1);\n }\n}\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType.atvscript,\n parameters: string[],\n options: O,\n): Promise<NodePyATVScriptResponse<O>>;\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType.atvremote,\n parameters: string[],\n options: O,\n): Promise<string>;\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType,\n parameters: string[],\n options: O,\n): Promise<Record<string, unknown> | Record<string, unknown>[] | string> {\n const result = {\n code: 0,\n stderr: '',\n stdout: '',\n };\n\n await new Promise((resolve, reject) => {\n const pyatv = execute(requestId, executableType, parameters, options);\n\n /* eslint-disable @typescript-eslint/no-explicit-any*/\n const onStdOut = (data: any) => (result.stdout += String(data).trim());\n const onStdErr = (data: any) => (result.stderr += String(data).trim());\n const onError = (data: any) =>\n reject(data instanceof Error ? data : new Error(String(data)));\n /* eslint-enable @typescript-eslint/no-explicit-any*/\n\n const onClose: (code: number) => void = (code: number) => {\n result.code = code;\n\n if (pyatv.stdout) {\n pyatv.stdout.off('data', onStdOut);\n }\n if (pyatv.stderr) {\n pyatv.stderr.off('data', onStdErr);\n }\n\n pyatv.off('error', onError);\n pyatv.off('close', onClose);\n resolve(undefined);\n };\n\n if (pyatv.stdout) {\n pyatv.stdout.on('data', onStdOut);\n }\n if (pyatv.stderr) {\n pyatv.stderr.on('data', onStdErr);\n }\n\n pyatv.on('error', onError);\n pyatv.on('close', onClose);\n });\n\n if (result.stderr.length > 0) {\n const msg = `Unable to execute request ${requestId}: ${result.stderr}`;\n debug(requestId, msg, options);\n throw new Error(msg);\n }\n\n if (executableType === NodePyATVExecutableType.atvscript) {\n try {\n // response with multiple lines\n // https://github.com/sebbo2002/node-pyatv/issues/324\n if (options.allowMultipleResponses) {\n return result.stdout\n .split('\\n')\n .filter((line) => line.trim().length > 0)\n .map((line) => JSON.parse(line));\n }\n\n return JSON.parse(result.stdout);\n } catch (error) {\n const msg = `Unable to parse result ${requestId} json: ${error}`;\n debug(requestId, msg, options);\n throw new Error(msg);\n }\n }\n\n return result.stdout;\n}\n\nfunction parseStateNumberAttr(\n input: NodePyATVInternalState,\n output: NodePyATVState,\n inputAttr:\n | 'episode_number'\n | 'itunes_store_identifier'\n | 'position'\n | 'season_number'\n | 'total_time'\n | 'volume',\n outputAttr:\n | 'episodeNumber'\n | 'iTunesStoreIdentifier'\n | 'position'\n | 'seasonNumber'\n | 'totalTime'\n | 'volume',\n d: (msg: string) => void,\n): void {\n if (typeof input[inputAttr] === 'number') {\n output[outputAttr] = input[inputAttr];\n return;\n }\n\n d(`No ${outputAttr} value found in input (${JSON.stringify(input)})`);\n}\n\nfunction parseStateStringAttr(\n input: NodePyATVInternalState,\n output: NodePyATVState,\n inputAttr:\n | 'album'\n | 'app'\n | 'app_id'\n | 'artist'\n | 'content_identifier'\n | 'genre'\n | 'hash'\n | 'series_name'\n | 'title',\n outputAttr:\n | 'album'\n | 'app'\n | 'appId'\n | 'artist'\n | 'contentIdentifier'\n | 'genre'\n | 'hash'\n | 'seriesName'\n | 'title',\n d: (msg: string) => void,\n): void {\n if (typeof input[inputAttr] === 'string') {\n output[outputAttr] = input[inputAttr] as string;\n return;\n }\n\n d(`No ${outputAttr} value found in input (${JSON.stringify(input)})`);\n}\n","import { ChildProcess, type SpawnOptions } from 'child_process';\n\nimport type NodePyATVDevice from './device.js';\n\nimport { FakeChildProcess } from './fake-spawn.js';\n\nexport enum NodePyATVDeviceState {\n idle = 'idle',\n loading = 'loading',\n paused = 'paused',\n playing = 'playing',\n seeking = 'seeking',\n stopped = 'stopped',\n}\n\nexport enum NodePyATVExecutableType {\n atvremote = 'atvremote',\n atvscript = 'atvscript',\n}\n\nexport enum NodePyATVFocusState {\n // @deprecated Please use `NodePyATVFocusState.focused` instead\n focued = 'focused',\n\n // Doublicate enum value due to typo, will be removed in next breaking change\n // @todo remove in next breaking change\n // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values\n focused = 'focused',\n\n unfocused = 'unfocused',\n}\n\n/**\n * @internal\n */\nexport enum NodePyATVInternalKeys {\n down = 'down',\n home = 'home',\n homeHold = 'home_hold',\n left = 'left',\n menu = 'menu',\n next = 'next',\n pause = 'pause',\n play = 'play',\n playPause = 'play_pause',\n previous = 'previous',\n right = 'right',\n select = 'select',\n skipBackward = 'skip_backward',\n skipForward = 'skip_forward',\n stop = 'stop',\n suspend = 'suspend',\n topMenu = 'top_menu',\n turnOff = 'turn_off',\n turnOn = 'turn_on',\n up = 'up',\n volumeDown = 'volume_down',\n volumeUp = 'volume_up',\n wakeup = 'wakeup',\n}\n\nexport enum NodePyATVKeys {\n down = 'down',\n home = 'home',\n homeHold = 'homeHold',\n left = 'left',\n menu = 'menu',\n next = 'next',\n pause = 'pause',\n play = 'play',\n playPause = 'playPause',\n previous = 'previous',\n right = 'right',\n select = 'select',\n skipBackward = 'skipBackward',\n skipForward = 'skipForward',\n stop = 'stop',\n suspend = 'suspend',\n topMenu = 'topMenu',\n turnOff = 'turnOff',\n turnOn = 'turnOn',\n up = 'up',\n volumeDown = 'volumeDown',\n volumeUp = 'volumeUp',\n wakeup = 'wakeup',\n}\n\nexport enum NodePyATVListenerState {\n stopped,\n starting,\n started,\n stopping,\n}\n\nexport enum NodePyATVMediaType {\n music = 'music',\n tv = 'tv',\n unknown = 'unknown',\n video = 'video',\n}\n\nexport enum NodePyATVPowerState {\n off = 'off',\n on = 'on',\n}\n\nexport enum NodePyATVProtocol {\n airplay = 'airplay',\n dmap = 'dmap',\n mdns = 'mdns',\n mrp = 'mrp',\n}\n\nexport enum NodePyATVRepeatState {\n all = 'all',\n off = 'off',\n track = 'track',\n}\n\nexport enum NodePyATVShuffleState {\n albums = 'albums',\n off = 'off',\n songs = 'songs',\n}\n\nexport interface NodePyATVApp {\n id: string;\n launch: () => Promise<void>;\n name: string;\n}\n\nexport interface NodePyATVDeviceOptions\n extends NodePyATVFindAndInstanceOptions {\n allIDs?: string[];\n host?: string;\n mac?: string;\n model?: string;\n modelName?: string;\n name: string;\n os?: string;\n services?: NodePyATVService[];\n version?: string;\n}\n\nexport type NodePyATVEventValueType =\n | NodePyATVDeviceState\n | NodePyATVMediaType\n | NodePyATVRepeatState\n | NodePyATVShuffleState\n | number\n | string;\n\nexport interface NodePyATVFindAndInstanceOptions\n extends NodePyATVFindOptions,\n NodePyATVInstanceOptions {}\n\nexport interface NodePyATVFindOptions {\n airplayCredentials?: string;\n companionCredentials?: string;\n dmapCredentials?: string;\n host?: string;\n hosts?: string[];\n id?: string;\n mrpCredentials?: string;\n protocol?: NodePyATVProtocol;\n raopCredentials?: string;\n}\n\nexport interface NodePyATVFindResponseObject {\n devices: NodePyATVDevice[];\n errors: Record<string, unknown>[];\n}\n\nexport interface NodePyATVGetStateOptions {\n maxAge?: number;\n}\n\nexport interface NodePyATVInstanceOptions {\n atvremotePath?: string;\n atvscriptPath?: string;\n debug?: ((msg: string) => void) | true;\n noColors?: true;\n spawn?: (\n command: string,\n args: Array<string>,\n options: SpawnOptions,\n ) => ChildProcess | FakeChildProcess;\n}\n\n/**\n * @internal\n */\nexport interface NodePyATVInternalScanDevice {\n address: string;\n all_identifiers: string[];\n device_info?: {\n mac: null | string;\n model: string;\n model_str: string;\n operating_system: string;\n version: string;\n };\n identifier: string;\n name: string;\n services?: NodePyATVService[];\n}\n\n/**\n * @internal\n */\nexport interface NodePyATVInternalState {\n album?: string | unknown;\n app?: string | unknown;\n app_id?: string | unknown;\n artist?: string | unknown;\n connection?: string | unknown;\n content_identifier?: null | string;\n datetime?: string | unknown;\n device_state?: string | unknown;\n episode_number?: null | number;\n exception?: string | unknown;\n focus_state?: string | unknown;\n genre?: string | unknown;\n hash?: string | unknown;\n itunes_store_identifier?: null | number;\n media_type?: string | unknown;\n output_devices?: Array<{ identifier: string; name: string }> | null;\n position?: 1 | unknown;\n power_state?: string | unknown;\n push_updates?: string | unknown;\n repeat?: string | unknown;\n result?: string | unknown;\n season_number?: null | number;\n series_name?: null | string;\n shuffle?: string | unknown;\n stacktrace?: string | unknown;\n title?: string | unknown;\n total_time?: number | unknown;\n volume?: number | unknown;\n}\n\nexport interface NodePyATVRequestOptions extends NodePyATVInstanceOptions {\n allowMultipleResponses?: boolean;\n}\n\nexport interface NodePyATVService {\n port: number;\n protocol: NodePyATVProtocol;\n}\n\nexport interface NodePyATVState {\n album: null | string;\n app: null | string;\n appId: null | string;\n artist: null | string;\n contentIdentifier: null | string;\n dateTime: Date | null;\n deviceState: NodePyATVDeviceState | null;\n episodeNumber: null | number;\n focusState: NodePyATVFocusState | null;\n genre: null | string;\n hash: null | string;\n iTunesStoreIdentifier: null | number;\n mediaType: NodePyATVMediaType | null;\n outputDevices: Array<{ identifier: string; name: string }> | null;\n position: null | number;\n powerState: NodePyATVPowerState | null;\n repeat: NodePyATVRepeatState | null;\n seasonNumber: null | number;\n seriesName: null | string;\n shuffle: NodePyATVShuffleState | null;\n title: null | string;\n totalTime: null | number;\n volume: null | number;\n}\n\nexport type NodePyATVStateIndex = keyof NodePyATVState;\n\nexport interface NodePyATVVersionResponse {\n module: null | string;\n pyatv: null | string;\n}\n","'use strict';\n\nimport { EventEmitter } from 'events';\n\nimport { NodePyATVDeviceEvent, NodePyATVDeviceEvents } from '../lib/index.js';\nimport {\n addRequestId,\n getParameters,\n parseState,\n removeRequestId,\n request,\n} from './tools.js';\nimport {\n type NodePyATVApp,\n type NodePyATVDeviceOptions,\n NodePyATVDeviceState,\n NodePyATVExecutableType,\n NodePyATVFocusState,\n type NodePyATVGetStateOptions,\n NodePyATVInternalKeys,\n NodePyATVKeys,\n NodePyATVMediaType,\n NodePyATVPowerState,\n NodePyATVProtocol,\n NodePyATVRepeatState,\n type NodePyATVService,\n NodePyATVShuffleState,\n type NodePyATVState,\n} from './types.js';\n\n/**\n * Represents an Apple TV. Use [[getState]] to query the current state (e.g. media\n * type and title). You can also use the attribute methods (e.g. [[getTitle]] to get\n * the state. If you want realtime updates, subscribe to it's events with an\n * `EventEmitter` like API, so for example by using [[on]], [[once]] or [[addListener]].\n * It's also possible to send key commands by using [[pressKey]] or methods like [[pause]].\n */\nexport default class NodePyATVDevice implements EventEmitter {\n /**\n * Get all IDs of the Apple TV.\n * Requires pyatv >= 0.14.5.\n */\n get allIDs(): string[] | undefined {\n return this.options.allIDs;\n }\n /**\n * Returns true, if debugging is enabled. Returns the custom\n * logging method, if one was specified. Otherwise, if debug\n * log is disabled, returns undefined.\n */\n get debug(): ((msg: string) => void) | true | undefined {\n return this.options.debug;\n }\n /**\n * Enable or disable debugging or set a custom\n * debugging method to use.\n *\n * @param debug\n */\n set debug(debug: ((msg: string) => void) | true | undefined) {\n if (typeof debug === 'function') {\n this.options.debug = debug;\n } else {\n this.options.debug = Boolean(debug) || undefined;\n }\n }\n\n /**\n * Get the IP address of the Apple TV.\n */\n get host(): string | undefined {\n return this.options.host;\n }\n\n /**\n * Get the ID of the Apple TV.\n */\n get id(): string | undefined {\n return this.options.id;\n }\n\n /**\n * Get the MAC address of the Apple TV.\n * Requires pyatv >= 0.14.5.\n */\n get mac(): string | undefined {\n return this.options.mac;\n }\n\n /**\n * Get the model identifier of the device. Only set, if the\n * device was found using [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.model → \"Gen4K\"\n */\n get model(): string | undefined {\n return this.options.model;\n }\n\n /**\n * Get the model name of the device. Only set, if the device\n * was found with [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.modelName → \"Apple TV 4K\"\n */\n get modelName(): string | undefined {\n return this.options.modelName;\n }\n\n /**\n * Get the name of the Apple TV.\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const devices = await pyatv.find();\n * devices.forEach(device =>\n * console.log(device.name)\n * );\n * ```\n */\n get name(): string {\n return this.options.name;\n }\n\n /**\n * Get the operating system of the device. Only set, if the\n * device was found with [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.os → \"TvOS\"\n */\n get os(): string | undefined {\n return this.options.os;\n }\n\n /**\n * Get the used protocol to connect to the Apple TV.\n */\n get protocol(): NodePyATVProtocol | undefined {\n return this.options.protocol;\n }\n\n /**\n * Returns a list of services supported by the device. Ony set, if\n * the device was found during a scan using [[find()]]. Requires\n * pyatv ≧ 0.10.3.\n *\n * @example device.services → [\n * {\n * \"protocol\": \"airplay\",\n * \"port\": 7000\n * },\n * {\n * \"protocol\": \"dmap\",\n * \"port\": 3689\n * }\n * ]\n */\n get services(): NodePyATVService[] | undefined {\n return this.options.services;\n }\n\n /**\n * Get the device version. Only set, if the device was found\n * during a scan using [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.version → \"15.5.1\"\n */\n get version(): string | undefined {\n return this.options.version;\n }\n\n private readonly events: NodePyATVDeviceEvents;\n\n private readonly options: NodePyATVDeviceOptions;\n\n private readonly state: NodePyATVState;\n\n constructor(options: NodePyATVDeviceOptions) {\n if (!options.host && !options.id && !options.mac) {\n throw new Error('Either host, id or mac must be set!');\n }\n\n this.options = Object.assign({}, options);\n this.state = parseState({}, '', {});\n this.events = new NodePyATVDeviceEvents(this.state, this, this.options);\n\n // @todo basic validation\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * @param event\n * @param listener\n * @category Event\n */\n addListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n this.events.addListener(event, listener);\n return this;\n }\n\n /**\n * Removes the state node-pyatv cached for this device.\n *\n * @category State\n */\n clearState(): void {\n this.applyState(parseState({}, '', {}));\n }\n\n /**\n * Send the \"down\" command\n * @category Control\n */\n async down(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.down);\n }\n\n /**\n * Emit an event.\n * @param event\n * @param payload\n * @category Event\n */\n emit(event: string | symbol, payload: NodePyATVDeviceEvent): boolean {\n return this.events.emit(event, payload);\n }\n\n /**\n * Get all event names which are currently known.\n * @category Event\n */\n eventNames(): Array<string | symbol> {\n return this.events.eventNames();\n }\n\n /**\n * Returns the album of the current playing media\n * @param options\n * @category State\n */\n async getAlbum(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.album;\n }\n\n /**\n * Returns the currently used app\n * @param options\n * @category State\n */\n async getApp(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.app;\n }\n\n /**\n * Returns the id of the currently used app\n * @param options\n * @category State\n */\n async getAppId(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.appId;\n }\n\n /**\n * Returns the artist of the current playing media\n * @param options\n * @category State\n */\n async getArtist(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.artist;\n }\n\n /**\n * Returns the app specific content identifier\n * @param options\n * @category State\n */\n async getContentIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n return this.getState(options).then((state) => state.contentIdentifier);\n }\n\n /**\n * Get the date and time when the state was last updated.\n * @param options\n * @category State\n */\n async getDateTime(\n options: NodePyATVGetStateOptions = {},\n ): Promise<Date | null> {\n const state = await this.getState(options);\n return state.dateTime;\n }\n\n /**\n * Get the state of this device (e.g. playing, etc.)\n * @param options\n * @category State\n */\n async getDeviceState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVDeviceState | null> {\n const state = await this.getState(options);\n return state.deviceState;\n }\n\n /**\n * Returns the episode number.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getEpisodeNumber(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.episodeNumber);\n }\n\n /**\n * Returns the current focus state of the device\n * @param options\n * @category State\n */\n async getFocusState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVFocusState | null> {\n return this.getState(options).then((state) => state.focusState);\n }\n\n /**\n * Returns the genre of the current playing media\n * @param options\n * @category State\n */\n async getGenre(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.genre;\n }\n\n /**\n * Get the hash of the current media\n * @param options\n * @category State\n */\n async getHash(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.hash;\n }\n\n /**\n * Returns the iTunes Store identifier if available.\n * Requires pyatv >= 0.16.0\n * @param options\n * @category State\n * @alias getiTunesStoreIdentifier\n */\n async getITunesStoreIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then(\n (state) => state.iTunesStoreIdentifier,\n );\n }\n\n async getiTunesStoreIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getITunesStoreIdentifier(options);\n }\n\n /**\n * Get max number of listeners allowed\n * @category Event\n */\n getMaxListeners(): number {\n return this.events.getMaxListeners();\n }\n\n /**\n * Get the media type of the current media\n * @param options\n * @category State\n */\n async getMediaType(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVMediaType | null> {\n const state = await this.getState(options);\n return state.mediaType;\n }\n\n /**\n * Returns the current output devices of the device\n * @param options\n * @category State\n */\n async getOutputDevices(\n options: NodePyATVGetStateOptions = {},\n ): Promise<Array<{ identifier: string; name: string }> | null> {\n return this.getState(options).then((state) => state.outputDevices);\n }\n\n /**\n * Returns the title of the current playing media\n * @param options\n * @category State\n */\n async getPosition(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n const state = await this.getState(options);\n return state.position;\n }\n\n /**\n * Returns the current power state (= is it on or off, see [[NodePyATVPowerState]]) of the device.\n * @param options\n * @category State\n */\n async getPowerState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVPowerState | null> {\n return this.getState(options).then((state) => state.powerState);\n }\n\n /**\n * Returns the repeat state\n * @param options\n * @category State\n */\n async getRepeat(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVRepeatState | null> {\n const state = await this.getState(options);\n return state.repeat;\n }\n\n /**\n * Returns the season number.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getSeasonNumber(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.seasonNumber);\n }\n /**\n * Returns the season name.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getSeriesName(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n return this.getState(options).then((state) => state.seriesName);\n }\n\n /**\n * Returns the shuffle state\n * @param options\n * @category State\n */\n async getShuffle(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVShuffleState | null> {\n const state = await this.getState(options);\n return state.shuffle;\n }\n\n /**\n * Returns an [[NodePyATVState]] object representing the current state\n * of the device. Has an internal cache, which has a default TTL of 5s.\n * You can change this default value by passing the `maxAge` option.\n *\n * ```typescript\n * await device.getState({maxAge: 10000}); // cache TTL: 10s\n * ```\n *\n * @param options\n * @category State\n */\n async getState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVState> {\n if (\n this.state?.dateTime &&\n new Date().getTime() - this.state.dateTime.getTime() <\n (options.maxAge || 5000)\n ) {\n let position = null;\n if (this.state.position && this.state.dateTime) {\n position = Math.round(\n this.state.position +\n (new Date().getTime() - this.state.dateTime.getTime()) /\n 1000,\n );\n }\n\n return Object.assign({}, this.state, { position });\n }\n\n const id = addRequestId();\n\n try {\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'playing'],\n this.options,\n );\n const newState = parseState(result, id, this.options);\n\n this.applyState(newState);\n return newState;\n } finally {\n removeRequestId(id);\n }\n }\n\n /**\n * Returns the title of the current playing media\n * @param options\n * @category State\n */\n async getTitle(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.title;\n }\n\n /**\n * Returns the media length of the current playing media\n * @param options\n * @category State\n */\n async getTotalTime(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n const state = await this.getState(options);\n return state.totalTime;\n }\n\n /**\n * Returns the current volume of the device in percent (0 - 100)\n * @param options\n * @category State\n */\n async getVolume(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.volume);\n }\n\n /**\n * Send the \"home\" command\n * @category Control\n */\n async home(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.home);\n }\n\n /**\n * Send the \"homeHold\" command\n * @category Control\n */\n async homeHold(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.homeHold);\n }\n\n /**\n * Launch an application. Probably requires `companionCredentials`, see\n * https://pyatv.dev/documentation/atvremote/#apps for more details.\n * @param id App identifier, e.g. `com.netflix.Netflix`\n */\n async launchApp(id: string): Promise<void> {\n await this._pressKeyWithRemote('launch_app=' + id);\n }\n\n /**\n * Send the \"left\" command\n * @category Control\n */\n async left(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.left);\n }\n\n /**\n * Returns the list of installed apps on the Apple TV. Probably requires `companionCredentials`,\n * see https://pyatv.dev/documentation/atvremote/#apps for more details.\n */\n async listApps(): Promise<NodePyATVApp[]> {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvremote,\n [...parameters, 'app_list'],\n this.options,\n );\n if (typeof result !== 'string' || !result.startsWith('App: ')) {\n throw new Error('Unexpected atvremote response: ' + result);\n }\n\n removeRequestId(id);\n const regex = /(.+) \\(([^)]+)\\)$/i;\n const items = result\n .substring(5)\n .split(', App: ')\n .map((i) => {\n const m = i.match(regex);\n if (m !== null) {\n return {\n id: m[2],\n launch: () => this.launchApp(m[2]),\n name: m[1],\n };\n }\n }) as Array<NodePyATVApp | undefined>;\n\n return items.filter(Boolean) as NodePyATVApp[];\n }\n\n /**\n * Get number of listeners for event\n * @param event\n * @category Event\n */\n listenerCount(event: string | symbol): number {\n return this.events.listenerCount(event);\n }\n\n /**\n * Get listeners for event. Will also return\n * node-pyatv wrappers (e.g. once)\n *\n * @param event\n * @category Event\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n listeners(event: string | symbol): Function[] {\n return this.events.listeners(event);\n }\n\n /**\n * Send the \"menu\" command\n * @category Control\n */\n async menu(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.menu);\n }\n\n /**\n * Send the \"next\" command\n * @category Control\n */\n async next(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.next);\n }\n\n /**\n * Remove an event listener. Will stop the event subscription with the\n * Apple TV if this was the last event listener.\n * @param event\n * @param listener\n * @category Event\n */\n off(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.off(event, listener);\n return this;\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * @param event\n * @param listener\n * @category Event\n */\n on(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.on(event, listener);\n return this;\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * Removes the listener automatically after the first occurrence.\n * @param event\n * @param listener\n * @category Event\n */\n once(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.once(event, listener);\n return this;\n }\n\n /**\n * Send the \"pause\" command\n * @category Control\n */\n async pause(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.pause);\n }\n\n /**\n * Send the \"play\" command\n * @category Control\n */\n async play(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.play);\n }\n\n /**\n * Send the \"playPause\" command\n * @category Control\n */\n async playPause(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.playPause);\n }\n\n /**\n * @param event\n * @param listener\n * @category Event\n */\n prependListener(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.prependListener(event, listener);\n return this;\n }\n\n /**\n * @param event\n * @param listener\n * @category Event\n */\n prependOnceListener(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.prependOnceListener(event, listener);\n return this;\n }\n\n /**\n * Send a key press to the Apple TV\n *\n * ```typescript\n * await device.pressKey(NodePyATVKeys.home);\n * ```\n *\n * <br />\n *\n * ```javascript\n * await device.pressKey('home');\n * ```\n *\n * @param key\n * @category Control\n */\n async pressKey(key: NodePyATVKeys): Promise<void> {\n const internalKeyEntry = Object.entries(NodePyATVInternalKeys).find(\n ([k]) => key === k,\n );\n\n if (!internalKeyEntry) {\n throw new Error(`Unsupported key value ${key}!`);\n }\n\n const internalKey = internalKeyEntry[1];\n if ([NodePyATVKeys.turnOff, NodePyATVKeys.turnOn].includes(key)) {\n await this._pressKeyWithRemote(internalKey);\n } else {\n await this._pressKeyWithScript(internalKey);\n }\n }\n\n /**\n * Send the \"previous\" command\n * @category Control\n */\n async previous(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.previous);\n }\n\n /**\n * @param event\n * @category Event\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n rawListeners(event: string | symbol): Function[] {\n return this.events.rawListeners(event);\n }\n\n /**\n * Removes all listeners, either for the given event or\n * for every event. Will stop the event subscription with\n * the Apple TV if this was the last event listener.\n *\n * @param event\n * @category Event\n */\n removeAllListeners(event?: string | symbol): this {\n this.events.removeAllListeners(event);\n return this;\n }\n\n /**\n * Remove an event listener. Will stop the event subscription with the\n * Apple TV if this was the last event listener.\n * @param event\n * @param listener\n * @category Event\n */\n removeListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n this.events.removeListener(event, listener);\n return this;\n }\n\n /**\n * Send the \"right\" command\n * @category Control\n */\n async right(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.right);\n }\n\n /**\n * Send the \"select\" command\n * @category Control\n */\n async select(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.select);\n }\n\n /**\n * @param n\n * @category Event\n */\n setMaxListeners(n: number): this {\n this.events.setMaxListeners(n);\n return this;\n }\n\n /**\n * Send the \"skipBackward\" command\n * @category Control\n */\n async skipBackward(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.skipBackward);\n }\n\n /**\n * Send the \"skipForward\" command\n * @category Control\n */\n async skipForward(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.skipForward);\n }\n\n /**\n * Send the \"stop\" command\n * @category Control\n */\n async stop(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.stop);\n }\n\n /**\n * Send the \"suspend\" command\n * @category Control\n * @deprecated\n */\n async suspend(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.suspend);\n }\n\n /**\n * Returns an object with `name`, `host`, `mac`, `id` and `protocol`.\n * Can be used to initiate a new device instance.\n *\n * @category Basic\n */\n toJSON(): Pick<\n NodePyATVDeviceOptions,\n 'host' | 'id' | 'mac' | 'name' | 'protocol'\n > {\n return {\n host: this.host,\n id: this.id,\n mac: this.mac,\n name: this.name,\n protocol: this.protocol,\n };\n }\n\n /**\n * Send the \"topMenu\" command\n * @category Control\n */\n async topMenu(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.topMenu);\n }\n\n /**\n * Returns a string. Just for debugging, etc.\n *\n * @category Basic\n */\n toString(): string {\n return `NodePyATVDevice(${this.name}, ${this.host})`;\n }\n\n /**\n * Send the \"turn_off\" command\n * @category Control\n */\n async turnOff(): Promise<void> {\n await this._pressKeyWithRemote(NodePyATVInternalKeys.turnOff);\n }\n\n /**\n * Send the \"turn_on\" command\n * @category Control\n */\n async turnOn(): Promise<void> {\n await this._pressKeyWithRemote(NodePyATVInternalKeys.turnOn);\n }\n\n /**\n * Send the \"up\" command\n * @category Control\n */\n async up(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.up);\n }\n\n /**\n * Send the \"volumeDown\" command\n * @category Control\n */\n async volumeDown(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.volumeDown);\n }\n\n /**\n * Send the \"volumeUp\" command\n * @category Control\n */\n async volumeUp(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.volumeUp);\n }\n\n /**\n * Send the \"wakeup\" command\n * @category Control\n * @deprecated\n */\n async wakeup(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.wakeup);\n }\n\n private async _pressKeyWithRemote(key: NodePyATVInternalKeys | string) {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n await request(\n id,\n NodePyATVExecutableType.atvremote,\n [...parameters, key],\n this.options,\n );\n removeRequestId(id);\n }\n\n private async _pressKeyWithScript(key: NodePyATVInternalKeys | string) {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, key],\n this.options,\n );\n if (typeof result !== 'object' || result.result !== 'success') {\n throw new Error(\n `Unable to parse pyatv response: ${JSON.stringify(result, null, ' ')}`,\n );\n }\n\n removeRequestId(id);\n }\n\n private applyState(newState: NodePyATVState): void {\n this.events.applyStateAndEmitEvents(newState);\n }\n}\n","'use strict';\n\nimport NodePyATVInstance from '../lib/instance.js';\n\n(async () => {\n try {\n await NodePyATVInstance.check();\n\n console.log('');\n console.log('✔ node-pyatv seems to be ready to use!');\n console.log(' Thank you and have a great day. Or night. Whatever.');\n console.log('');\n } catch (error) {\n console.log('');\n console.log('#'.repeat(60));\n console.log('#' + ' '.repeat(58) + '#');\n console.log(\n '# ⚠ Warning: node-pyatv is not ready to be used!' +\n ' '.repeat(10) +\n '#',\n );\n console.log('#' + ' '.repeat(58) + '#');\n console.log(\n '# To use the JavaScript module, pyatv >= 0.6.0 must be #',\n );\n console.log(\n '# installed. Unfortunately this could not be found. During #',\n );\n console.log(\n '# the check following error message was reported: #',\n );\n console.log('#' + ' '.repeat(58) + '#');\n console.log(\n String(error)\n .replace('Error: ', '')\n .replace(/(.{1,54})/g, '$1\\n')\n .split('\\n')\n .map((l) => l.trim())\n .filter((l) => Boolean(l))\n .map((l) => `# > ${l}${' '.repeat(55 - l.length)}#`)\n .join('\\n'),\n );\n console.log('#' + ' '.repeat(58) + '#');\n console.log(\n '# You can probably find more information here: #',\n );\n console.log(\n '# https://github.com/sebbo2002/node-pyatv #',\n );\n console.log('#' + ' '.repeat(58) + '#');\n console.log('#'.repeat(60));\n console.log('');\n }\n})();\n"],"mappings":"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","names":["getImportMetaUrl","importMetaUrl","import_fs","import_path","import_semver","import_url","NodePyATVDeviceEvent","values","import_events","import_child_process","NodePyATVDeviceState","NodePyATVFocusState","NodePyATVInternalKeys","NodePyATVMediaType","NodePyATVPowerState","NodePyATVRepeatState","NodePyATVShuffleState","requestIds","addRequestId","id","i","compareOutputDevices","a","b","debug","message","options","log","enableColors","parts","execute","requestId","executableType","parameters","executable","getExecutable","mySpawn","child","onStdOut","data","onStdErr","onError","onClose","code","getParameters","parseState","input","d","msg","result","errorStr","date","parseStateStringAttr","NodePyATVMediaType","NodePyATVDeviceState","parseStateNumberAttr","NodePyATVShuffleState","NodePyATVRepeatState","NodePyATVPowerState","NodePyATVFocusState","removeRequestId","request","resolve","reject","pyatv","line","error","output","inputAttr","outputAttr","NodePyATVDeviceEvents","state","device","options","event","listener","newState","keys","k","v","key","oldValue","newValue","compareOutputDevices","NodePyATVDeviceEvent","error","a","b","reqId","debug","cb","update","parseState","id","addRequestId","removeRequestId","data","json","msg","listenStart","parameters","getParameters","execute","onError","onStdErr","onStdOut","s","onClose","code","NodePyATVDevice","debug","options","parseState","NodePyATVDeviceEvents","event","listener","payload","state","position","id","addRequestId","parameters","getParameters","result","request","newState","removeRequestId","regex","i","m","key","internalKeyEntry","NodePyATVInternalKeys","k","internalKey","n","NodePyATVInstance","_NodePyATVInstance","options","versions","semver","error","NodePyATVDevice","returnDevicesAndErrors","id","addRequestId","parameters","getParameters","devices","errors","response","request","item","device","removeRequestId","pyatv","module","debug","packageJsonPath","importMetaUrl","fsPromises","NodePyATVInstance","error","l"]}
|
|
1
|
+
{"version":3,"sources":["../../node_modules/tsup/assets/cjs_shims.js","../../src/lib/instance.ts","../../src/lib/device-event.ts","../../src/lib/device-events.ts","../../src/lib/tools.ts","../../src/lib/types.ts","../../src/lib/device.ts","../../src/bin/check.ts"],"sourcesContent":["// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","'use strict';\n\nimport { promises as fsPromises } from 'fs';\nimport { dirname, join } from 'path';\nimport semver from 'semver';\nimport { fileURLToPath } from 'url';\n\nimport { NodePyATVDevice } from '../lib/index.js';\nimport {\n addRequestId,\n debug,\n getParameters,\n removeRequestId,\n request,\n} from './tools.js';\nimport {\n type NodePyATVDeviceOptions,\n NodePyATVExecutableType,\n type NodePyATVFindAndInstanceOptions,\n type NodePyATVFindResponseObject,\n type NodePyATVInstanceOptions,\n type NodePyATVInternalScanDevice,\n type NodePyATVVersionResponse,\n} from './types.js';\n\n/**\n * Default class exported by `@sebbo2002/node-pyatv`. Use [[find]] to scan for devices in your local network. Use\n * [[device]] to connect to a known device by passing (at least) it's name and IP.\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * ```\n */\nexport default class NodePyATVInstance {\n private readonly options: NodePyATVInstanceOptions = {};\n\n /**\n * Use this to apply [[NodePyATVInstanceOptions]]\n * (e.g. debug log method) to all further requests\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const myPyatv = new pyatv({debug: true});\n * const devices = myPyatv.find();\n * console.log(devices);\n * ```\n * @param options\n */\n public constructor(options: NodePyATVInstanceOptions = {}) {\n this.options = Object.assign({}, options);\n }\n\n /**\n * Checks if pyatv is installed and ready to be used.\n * Will throw an error if not.\n *\n * @param options\n */\n public static async check(\n options: NodePyATVInstanceOptions = {},\n ): Promise<void> {\n const versions = await this.version(options);\n if (!versions.pyatv) {\n throw new Error('Unable to find pyatv. Is it installed?');\n }\n if (semver.lt(versions.pyatv, '0.6.0')) {\n throw new Error(\n \"Found pyatv, but unforunately it's too old. Please update pyatv.\",\n );\n }\n\n try {\n await this.find(options);\n } catch (error) {\n throw new Error(\n `Unable to scan for devices: ${String(error).replace('Error: ', '')}`,\n );\n }\n }\n\n /**\n * Create a [[NodePyATVDevice]] to query the state and control it.\n * At least `host` and `name` are required.\n *\n * @param options\n */\n public static device(options: NodePyATVDeviceOptions): NodePyATVDevice {\n return new NodePyATVDevice(options);\n }\n /**\n * Scan the network for Apple TVs by using pyatv's atvscript. See [[NodePyATVFindAndInstanceOptions]]\n * for the options allowed. Use the `host` / `hosts` attribute to filter by IP addresses. Resolves with\n * an array of [[NodePyATVDevice]].\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const devices = await pyatv.find();\n * console.log(devices);\n * ```\n *\n * Normally `node-pyatv` ignores error messages if at least one device has been found, but if you\n * always want to receive the error messages, you can set the second argument to `true`:\n *\n * ```typescript\n * const result = await pyatv.find({}, true);\n * console.log(result.devices);\n * console.log(result.errors);\n * ```\n *\n * @param options\n */\n public static async find(\n options?: NodePyATVFindAndInstanceOptions,\n ): Promise<NodePyATVDevice[]>;\n public static async find(\n options: NodePyATVFindAndInstanceOptions,\n returnDevicesAndErrors: true,\n ): Promise<NodePyATVFindResponseObject>;\n public static async find(\n options: NodePyATVFindAndInstanceOptions = {},\n returnDevicesAndErrors?: boolean,\n ): Promise<NodePyATVDevice[] | NodePyATVFindResponseObject> {\n const id = addRequestId();\n const parameters = getParameters(options);\n\n const devices: NodePyATVDevice[] = [];\n const errors: Record<string, unknown>[] = [];\n const response = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'scan'],\n { ...(options || {}), allowMultipleResponses: true },\n );\n\n for (const item of response) {\n if (\n typeof item === 'object' &&\n 'result' in item &&\n item.result === 'failure'\n ) {\n errors.push(item);\n } else if (\n typeof item === 'object' &&\n 'result' in item &&\n item.result === 'success' &&\n Array.isArray(item.devices)\n ) {\n devices.push(\n ...item.devices.map((device: NodePyATVInternalScanDevice) =>\n this.device(\n Object.assign({}, options, {\n allIDs: device.all_identifiers,\n host: device.address,\n id: device.identifier,\n mac: device.device_info?.mac || undefined,\n model: device.device_info?.model,\n modelName: device.device_info?.model_str,\n name: device.name,\n os: device.device_info?.operating_system,\n services: device.services,\n version: device.device_info?.version,\n }),\n ),\n ),\n );\n } else {\n throw new Error(\n `Unable to parse pyatv response: ${JSON.stringify(item, null, ' ')}`,\n );\n }\n }\n removeRequestId(id);\n\n if (returnDevicesAndErrors) {\n return { devices, errors };\n }\n if (!devices.length && errors.length) {\n throw new Error(\n `Unable to find any devices, but received ${errors.length} error${errors.length !== 1 ? 's' : ''}: ${JSON.stringify(errors, null, ' ')}`,\n );\n }\n\n return devices;\n }\n\n /**\n * Resolves with the version of pyatv and of the module itself.\n * If a value can't be found, null is returned instead.\n *\n * @param options\n */\n public static async version(\n options: NodePyATVInstanceOptions = {},\n ): Promise<NodePyATVVersionResponse> {\n const id = addRequestId();\n let pyatv = null;\n let module = null;\n\n try {\n pyatv = (await request(\n id,\n NodePyATVExecutableType.atvremote,\n ['--version'],\n options,\n )) as string;\n } catch (error) {\n debug(id, `Unable to get pyatv version due to ${error}`, options);\n }\n\n if (pyatv && pyatv.substr(0, 10) === 'atvremote ') {\n pyatv = pyatv.substr(10);\n }\n if (!semver.valid(pyatv)) {\n debug(\n id,\n `String \"${pyatv}\" is not a valid pyatv version, set it to null`,\n options,\n );\n pyatv = null;\n }\n\n try {\n const packageJsonPath = join(\n dirname(fileURLToPath(import.meta.url)),\n '..',\n '..',\n 'package.json',\n );\n const json = JSON.parse(\n await fsPromises.readFile(packageJsonPath, 'utf8'),\n );\n module = json?.version || null;\n } catch (error) {\n debug(id, `Unable to get module version due to ${error}`, options);\n }\n if (module && !semver.valid(module)) {\n debug(\n id,\n `String \"${module}\" is not a valid module version, set it to null`,\n options,\n );\n module = null;\n }\n\n removeRequestId(id);\n return {\n module,\n pyatv,\n };\n }\n\n /**\n * Checks if pyatv is installed and ready to be used.\n * Will throw an error if not.\n *\n * @param options\n */\n public async check(options: NodePyATVInstanceOptions = {}): Promise<void> {\n return NodePyATVInstance.check(\n Object.assign({}, this.options, options),\n );\n }\n\n /**\n * Create a [[NodePyATVDevice]] to query the state and control it.\n * At least `host` and `name` are required.\n *\n * @param options\n */\n public device(options: NodePyATVDeviceOptions): NodePyATVDevice {\n return NodePyATVInstance.device(\n Object.assign({}, this.options, options),\n );\n }\n\n /**\n * Scan the network for Apple TVs by using pyatv's atvscript. See [[NodePyATVFindAndInstanceOptions]]\n * for the options allowed. Use the `host` / `hosts` attribute to filter by IP addresses. Resolves with\n * an array of [[NodePyATVDevice]].\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const myPyATV = new pyatv({debug: true});\n * const devices = await myPyATV.find();\n * console.log(devices);\n * ```\n *\n * @param options\n */\n public async find(\n options: NodePyATVFindAndInstanceOptions = {},\n ): Promise<NodePyATVDevice[]> {\n return NodePyATVInstance.find(Object.assign({}, this.options, options));\n }\n\n /**\n * Resolves with the version of pyatv and of the module itself.\n * If a value can't be found, null is returned instead.\n *\n * @param options\n */\n public async version(\n options: NodePyATVInstanceOptions = {},\n ): Promise<NodePyATVVersionResponse> {\n return NodePyATVInstance.version(\n Object.assign({}, this.options, options),\n );\n }\n}\n","'use strict';\n\nimport type { NodePyATVEventValueType, NodePyATVStateIndex } from './types.js';\n\nimport { NodePyATVDevice } from '../lib/index.js';\n\nexport default class NodePyATVDeviceEvent {\n /**\n * References the device instance this\n * event originates from\n */\n get device(): NodePyATVDevice {\n return this.values.device;\n }\n\n /**\n * References the attribute name which was changed. So if the\n * title has been updated, this would be `title`.\n */\n get key(): NodePyATVStateIndex {\n return this.values.key;\n }\n\n /**\n * @alias value\n */\n get newValue(): NodePyATVEventValueType {\n return this.values.new;\n }\n\n /**\n * Holds the old value which was there\n * before the value was changed.\n */\n get oldValue(): NodePyATVEventValueType {\n return this.values.old;\n }\n\n /**\n * New, current value for `key`\n */\n get value(): NodePyATVEventValueType {\n return this.values.new;\n }\n\n protected readonly values: {\n device: NodePyATVDevice;\n key: NodePyATVStateIndex;\n new: NodePyATVEventValueType;\n old: NodePyATVEventValueType;\n };\n\n /**\n *\n * @param values\n * @internal\n */\n constructor(values: {\n device: NodePyATVDevice;\n key: NodePyATVStateIndex;\n new: NodePyATVEventValueType;\n old: NodePyATVEventValueType;\n }) {\n this.values = Object.assign({}, values, {\n key: values.key as NodePyATVStateIndex,\n });\n }\n}\n","'use strict';\n\nimport { ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\n\nimport { NodePyATVDevice, NodePyATVDeviceEvent } from '../lib/index.js';\nimport { FakeChildProcess } from './fake-spawn.js';\nimport {\n addRequestId,\n compareOutputDevices,\n debug,\n execute,\n getParameters,\n parseState,\n removeRequestId,\n} from './tools.js';\nimport {\n type NodePyATVDeviceOptions,\n NodePyATVExecutableType,\n type NodePyATVInternalState,\n NodePyATVListenerState,\n type NodePyATVState,\n type NodePyATVStateIndex,\n} from './types.js';\n\n/**\n * @internal\n */\nexport default class NodePyATVDeviceEvents extends EventEmitter {\n private readonly device: NodePyATVDevice;\n private listenerState: NodePyATVListenerState;\n private readonly options: NodePyATVDeviceOptions;\n private pyatv: ChildProcess | FakeChildProcess | undefined;\n private readonly state: NodePyATVState;\n private timeout: NodeJS.Timeout | undefined;\n\n constructor(\n state: NodePyATVState,\n device: NodePyATVDevice,\n options: NodePyATVDeviceOptions,\n ) {\n super();\n\n this.state = state;\n this.device = device;\n this.options = Object.assign({}, options);\n this.listenerState = NodePyATVListenerState.stopped;\n }\n\n addListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.addListener(event, listener);\n this.checkListener();\n return this;\n }\n\n applyStateAndEmitEvents(newState: NodePyATVState): void {\n let keys = Object.keys(this.state);\n\n // Remove special fields from the list\n keys = keys.filter(\n (k) =>\n ![\n 'focusState',\n 'outputDevices',\n 'powerState',\n 'volume',\n ].includes(k),\n );\n\n if ('powerState' in newState && newState.powerState) {\n keys = ['powerState'];\n }\n if ('focusState' in newState && newState.focusState) {\n keys = ['focusState'];\n }\n if ('outputDevices' in newState && newState.outputDevices) {\n keys = ['outputDevices'];\n }\n\n // Volume events don't hold the complete state…\n // see https://github.com/sebbo2002/node-pyatv/pull/291\n if ('volume' in newState && newState.volume !== null) {\n keys = ['volume'];\n }\n\n // If all values are null, we don't need to emit events at all\n // https://github.com/sebbo2002/node-pyatv/issues/295#issuecomment-1888640079\n if (\n !Object.entries(newState).find(\n ([k, v]) => !['dateTime', 'result'].includes(k) && v !== null,\n )\n ) {\n return;\n }\n\n keys.forEach((key: string) => {\n // @ts-expect-error this.state has no index signature\n const oldValue = this.state[key];\n\n // @ts-expect-error same here\n const newValue = newState[key];\n\n if (\n oldValue === undefined ||\n newValue === undefined ||\n oldValue === newValue\n ) {\n return;\n }\n if (\n key === 'outputDevices' &&\n compareOutputDevices(oldValue, newValue)\n ) {\n return;\n }\n\n const event = new NodePyATVDeviceEvent({\n device: this.device,\n key: key as NodePyATVStateIndex,\n new: newValue,\n old: oldValue,\n });\n\n // @ts-expect-error and here\n this.state[key] = newState[key];\n\n try {\n this.emit('update:' + key, event);\n this.emit('update', event);\n } catch (error) {\n this.emit('error', error);\n }\n });\n }\n\n listenerCount(event?: string | symbol): number {\n if (event !== undefined) {\n return super.listenerCount(event);\n }\n\n return this.eventNames()\n .map((event) => this.listenerCount(event))\n .reduce((a, b) => a + b, 0);\n }\n\n off(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.off(event, listener);\n this.checkListener();\n return this;\n }\n\n on(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.on(event, listener);\n this.checkListener();\n return this;\n }\n\n once(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.once(event, (event: NodePyATVDeviceEvent) => {\n listener(event);\n setTimeout(() => this.checkListener(), 0);\n });\n this.checkListener();\n return this;\n }\n\n prependListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.prependListener(event, listener);\n this.checkListener();\n return this;\n }\n\n removeAllListeners(event?: string | symbol): this {\n super.removeAllListeners(event);\n this.checkListener();\n return this;\n }\n\n removeListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.removeListener(event, listener);\n this.checkListener();\n return this;\n }\n\n protected async stopListening(reqId: string): Promise<void> {\n if (\n this.listenerState !== NodePyATVListenerState.starting &&\n this.listenerState !== NodePyATVListenerState.started\n ) {\n return;\n }\n\n this.listenerState = NodePyATVListenerState.stopping;\n if (this.pyatv === undefined) {\n throw new Error(\n \"Unable to stop listening due to internal error: state is stopping, but there's no child process. \" +\n 'This should never happen, please report this.',\n );\n }\n\n if (this.pyatv.stdin) {\n debug(reqId, 'Pressing enter to close atvscript…', this.options);\n this.pyatv.stdin.write('\\n');\n\n await new Promise((cb) => (this.timeout = setTimeout(cb, 250)));\n }\n\n if (\n this.listenerState === NodePyATVListenerState.stopping &&\n this.pyatv\n ) {\n this.pyatv.kill();\n }\n\n this.listenerState = NodePyATVListenerState.stopped;\n return;\n }\n\n private applyPushUpdate(\n update: NodePyATVInternalState,\n reqId: string,\n ): void {\n try {\n const newState = parseState(update, reqId, this.options);\n this.applyStateAndEmitEvents(newState);\n } catch (error) {\n this.emit('error', error);\n }\n }\n\n private checkListener(): void {\n if (\n this.listenerState === NodePyATVListenerState.stopped &&\n this.listenerCount() === 0 &&\n this.timeout\n ) {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n } else if (\n this.listenerState === NodePyATVListenerState.stopped &&\n this.listenerCount() > 0\n ) {\n const id = addRequestId();\n debug(\n id,\n `Start listeing to events from device ${this.options.name}`,\n this.options,\n );\n\n this.startListening(id);\n removeRequestId(id);\n } else if (\n [\n NodePyATVListenerState.started,\n NodePyATVListenerState.starting,\n ].includes(this.listenerState) &&\n this.listenerCount() === 0\n ) {\n const id = addRequestId();\n debug(\n id,\n `Stop listening to events from device ${this.options.name}`,\n this.options,\n );\n\n this.stopListening(id)\n .catch((error) =>\n debug(\n id,\n `Unable to stop listeing: ${error}`,\n this.options,\n ),\n )\n .finally(() => removeRequestId(id));\n }\n }\n\n private parsePushUpdate(reqId: string, data: string): void {\n let json: NodePyATVInternalState;\n\n try {\n json = JSON.parse(data);\n } catch (error) {\n const msg = `Unable to parse stdout json: ${error}`;\n debug(reqId, msg, this.options);\n this.emit('error', new Error(msg));\n return;\n }\n\n this.applyPushUpdate(json, reqId);\n\n if (this.listenerState === NodePyATVListenerState.starting) {\n this.listenerState = NodePyATVListenerState.started;\n this.checkListener();\n }\n }\n\n private startListening(reqId: string): void {\n if (this.listenerState !== NodePyATVListenerState.stopped) {\n return;\n }\n\n this.listenerState = NodePyATVListenerState.starting;\n\n const listenStart = new Date().getTime();\n const parameters = getParameters(this.options);\n this.pyatv = execute(\n reqId,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'push_updates'],\n this.options,\n );\n if (!this.pyatv) {\n throw new Error(\n 'Unable to start listener: Unable to start atvscript',\n );\n }\n\n const onError = (error: Error) => {\n debug(\n reqId,\n `Got error from child process: ${error}`,\n this.options,\n );\n this.emit('error', error);\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onStdErr = (data: any) => {\n const error = new Error(`Got stderr output from pyatv: ${data}`);\n debug(reqId, data.toString(), this.options);\n this.emit('error', error);\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onStdOut = (data: any) => {\n String(data)\n .split('\\n')\n .map((s) => s.trim())\n .filter(Boolean)\n .forEach((s) => {\n debug(reqId, `> ${s}`, this.options);\n this.parsePushUpdate(reqId, s);\n });\n };\n const onClose = (code: number) => {\n if (this.pyatv === undefined) {\n // this should never happen… :/\n return;\n }\n\n this.listenerState = NodePyATVListenerState.stopped;\n debug(\n reqId,\n `Listening with atvscript exited with code ${code}`,\n this.options,\n );\n if (this.timeout !== undefined) {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n }\n\n if (this.pyatv.stdout) {\n this.pyatv.stdout.off('data', onStdOut);\n }\n if (this.pyatv.stderr) {\n this.pyatv.stderr.off('data', onStdErr);\n }\n this.pyatv.off('error', onError);\n this.pyatv.off('close', onClose);\n\n if (\n this.listenerCount() > 0 &&\n new Date().getTime() - listenStart < 30000\n ) {\n debug(\n reqId,\n `Wait 15s and restart listeing to events from device ${this.options.name}`,\n this.options,\n );\n\n this.timeout = setTimeout(() => {\n this.checkListener();\n }, 15000);\n } else if (this.listenerCount() > 0) {\n debug(\n reqId,\n `Restart listeing to events from device ${this.options.name}`,\n this.options,\n );\n this.checkListener();\n }\n\n removeRequestId(reqId);\n };\n\n this.pyatv.on('error', onError);\n this.pyatv.on('close', onClose);\n\n if (this.pyatv.stdout) {\n this.pyatv.stdout.on('data', onStdOut);\n }\n if (this.pyatv.stderr) {\n this.pyatv.stderr.on('data', onStdErr);\n }\n }\n}\n","'use strict';\n\nimport { ChildProcess, spawn, type SpawnOptions } from 'child_process';\n\nimport { FakeChildProcess } from './fake-spawn.js';\nimport {\n NodePyATVDeviceState,\n NodePyATVExecutableType,\n type NodePyATVFindAndInstanceOptions,\n NodePyATVFocusState,\n type NodePyATVInstanceOptions,\n type NodePyATVInternalState,\n NodePyATVMediaType,\n NodePyATVPowerState,\n NodePyATVRepeatState,\n type NodePyATVRequestOptions,\n NodePyATVShuffleState,\n type NodePyATVState,\n} from './types.js';\n\nconst requestIds: string[] = [];\n\ntype NodePyATVScriptResponse<O extends NodePyATVRequestOptions> =\n O['allowMultipleResponses'] extends true\n ? Record<string, unknown>[]\n : Record<string, unknown>;\n\nexport function addRequestId(): string {\n let id = '?';\n\n for (let i = 0; i < 1000; i += 1) {\n id = Math.round(Math.random() * (i + 6) * 36)\n .toString(36)\n .toUpperCase();\n if (!requestIds.includes(id)) {\n requestIds.push(id);\n break;\n }\n }\n\n return id;\n}\n\nexport function compareOutputDevices(\n a: NodePyATVState['outputDevices'],\n b: NodePyATVState['outputDevices'],\n) {\n return Boolean(\n Array.isArray(a) &&\n Array.isArray(b) &&\n JSON.stringify(\n a.sort((a, b) => (a.identifier < b.identifier ? -1 : 1)),\n ) ===\n JSON.stringify(\n b.sort((a, b) => (a.identifier < b.identifier ? -1 : 1)),\n ),\n );\n}\n\nexport function debug(\n id: string,\n message: string,\n options: NodePyATVInstanceOptions,\n): void {\n if (options.debug) {\n const log =\n typeof options.debug === 'function' ? options.debug : console.log;\n const enableColors = !process.env.NO_COLOR && !options.noColors;\n\n const parts = [\n enableColors ? '\\x1b[0m' : '', // Color Reset\n enableColors ? '\\x1b[90m' : '', // Grey\n '[node-pyatv][',\n enableColors ? '\\x1b[37m' : '', // Light Grey\n id,\n enableColors ? '\\x1b[90m' : '', // Grey\n '] ',\n enableColors ? '\\x1b[0m' : '', // Color Reset\n message,\n ];\n\n log.apply(null, [parts.join('')]);\n }\n}\n\nexport function execute(\n requestId: string,\n executableType: NodePyATVExecutableType,\n parameters: string[],\n options: NodePyATVInstanceOptions,\n): ChildProcess | FakeChildProcess {\n const executable = getExecutable(executableType, options);\n const mySpawn: (\n command: string,\n args: Array<string>,\n options: SpawnOptions,\n ) => ChildProcess | FakeChildProcess =\n typeof options.spawn === 'function' ? options.spawn : spawn;\n\n debug(requestId, `${executable} ${parameters.join(' ')}`, options);\n const child = mySpawn(executable, parameters, {\n env: process.env,\n });\n\n /* eslint-disable @typescript-eslint/no-explicit-any*/\n const onStdOut = (data: any) =>\n debug(requestId, `stdout: ${String(data).trim()}`, options);\n const onStdErr = (data: any) =>\n debug(requestId, `stderr: ${String(data).trim()}`, options);\n const onError = (data: any) =>\n debug(requestId, `error: ${String(data).trim()}`, options);\n /* eslint-enable @typescript-eslint/no-explicit-any*/\n\n const onClose = (code: number) => {\n debug(requestId, `${executable} exited with code: ${code}`, options);\n\n if (child.stdout) {\n child.stdout.off('data', onStdOut);\n }\n if (child.stderr) {\n child.stderr.off('data', onStdErr);\n }\n\n child.off('error', onError);\n child.off('close', onClose);\n };\n\n if (child.stdout) {\n child.stdout.on('data', onStdOut);\n }\n if (child.stderr) {\n child.stderr.on('data', onStdErr);\n }\n\n child.on('error', onError);\n child.on('close', onClose);\n\n return child;\n}\n\nexport function getExecutable(\n executable: NodePyATVExecutableType,\n options: NodePyATVInstanceOptions,\n): string {\n if (\n executable === NodePyATVExecutableType.atvremote &&\n typeof options.atvremotePath === 'string'\n ) {\n return options.atvremotePath;\n } else if (\n executable === NodePyATVExecutableType.atvscript &&\n typeof options.atvscriptPath === 'string'\n ) {\n return options.atvscriptPath;\n } else {\n return executable;\n }\n}\n\nexport function getParameters(\n options: NodePyATVFindAndInstanceOptions = {},\n): string[] {\n const parameters: string[] = [];\n\n if (options.hosts) {\n parameters.push('-s', options.hosts.join(','));\n } else if (options.host) {\n parameters.push('-s', options.host);\n }\n if (options.id) {\n parameters.push('-i', options.id);\n }\n if (options.protocol) {\n parameters.push('--protocol', options.protocol);\n }\n if (options.dmapCredentials) {\n parameters.push('--dmap-credentials', options.dmapCredentials);\n }\n if (options.mrpCredentials) {\n parameters.push('--mrp-credentials', options.mrpCredentials);\n }\n if (options.airplayCredentials) {\n parameters.push('--airplay-credentials', options.airplayCredentials);\n }\n if (options.companionCredentials) {\n parameters.push(\n '--companion-credentials',\n options.companionCredentials,\n );\n }\n if (options.raopCredentials) {\n parameters.push('--raop-credentials', options.raopCredentials);\n }\n\n return parameters;\n}\nexport function parseState(\n input: NodePyATVInternalState,\n id: string,\n options: NodePyATVInstanceOptions,\n): NodePyATVState {\n const d = (msg: string) => debug(id, msg, options);\n const result: NodePyATVState = {\n album: null,\n app: null,\n appId: null,\n artist: null,\n contentIdentifier: null,\n dateTime: null,\n deviceState: null,\n episodeNumber: null,\n focusState: null,\n genre: null,\n hash: null,\n iTunesStoreIdentifier: null,\n mediaType: null,\n outputDevices: null,\n position: null,\n powerState: null,\n repeat: null,\n seasonNumber: null,\n seriesName: null,\n shuffle: null,\n title: null,\n totalTime: null,\n volume: null,\n };\n if (!input || typeof input !== 'object') {\n return result;\n }\n if (input.exception) {\n let errorStr = 'Got pyatv Error: ' + input.exception;\n if (input.stacktrace) {\n errorStr += '\\n\\npyatv Stacktrace:\\n' + input.stacktrace;\n }\n\n throw new Error(errorStr);\n }\n\n // datetime\n if (typeof input.datetime === 'string') {\n const date = new Date(input.datetime);\n if (!isNaN(date.getTime())) {\n result.dateTime = date;\n } else {\n d(`Invalid datetime value ${input.datetime}, ignore attribute`);\n }\n } else {\n d(`No datetime value found in input (${JSON.stringify(input)})`);\n }\n\n // hash\n parseStateStringAttr(input, result, 'hash', 'hash', d);\n\n // mediaType\n if (typeof input.media_type === 'string') {\n const validValues = Object.keys(NodePyATVMediaType).map((o) =>\n String(o),\n );\n if (validValues.includes(input.media_type)) {\n result.mediaType =\n NodePyATVMediaType[input.media_type as NodePyATVMediaType];\n } else {\n d(\n `Unsupported mediaType value ${input.media_type}, ignore attribute`,\n );\n }\n } else {\n d(`No mediaType value found in input (${JSON.stringify(input)})`);\n }\n\n // deviceState\n if (typeof input.device_state === 'string') {\n const validValues = Object.keys(NodePyATVDeviceState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.device_state)) {\n result.deviceState =\n NodePyATVDeviceState[\n input.device_state as NodePyATVDeviceState\n ];\n } else {\n d(\n `Unsupported deviceState value ${input.device_state}, ignore attribute`,\n );\n }\n } else {\n d(`No deviceState value found in input (${JSON.stringify(input)})`);\n }\n\n // title\n parseStateStringAttr(input, result, 'title', 'title', d);\n\n // artist\n parseStateStringAttr(input, result, 'artist', 'artist', d);\n\n // album\n parseStateStringAttr(input, result, 'album', 'album', d);\n\n // genre\n parseStateStringAttr(input, result, 'genre', 'genre', d);\n\n // totalTime\n parseStateNumberAttr(input, result, 'total_time', 'totalTime', d);\n\n // position\n parseStateNumberAttr(input, result, 'position', 'position', d);\n\n // shuffle\n if (typeof input.shuffle === 'string') {\n const validValues = Object.keys(NodePyATVShuffleState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.shuffle)) {\n result.shuffle =\n NodePyATVShuffleState[input.shuffle as NodePyATVShuffleState];\n } else {\n d(`Unsupported shuffle value ${input.shuffle}, ignore attribute`);\n }\n } else {\n d(`No shuffle value found in input (${JSON.stringify(input)})`);\n }\n\n // repeat\n if (typeof input.repeat === 'string') {\n const validValues = Object.keys(NodePyATVRepeatState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.repeat)) {\n result.repeat =\n NodePyATVRepeatState[input.repeat as NodePyATVRepeatState];\n } else {\n d(`Unsupported repeat value ${input.repeat}, ignore attribute`);\n }\n } else {\n d(`No repeat value found in input (${JSON.stringify(input)})`);\n }\n\n // app\n parseStateStringAttr(input, result, 'app', 'app', d);\n parseStateStringAttr(input, result, 'app_id', 'appId', d);\n\n // powerState\n if (typeof input.power_state === 'string') {\n const validValues = Object.keys(NodePyATVPowerState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.power_state)) {\n result.powerState =\n NodePyATVPowerState[input.power_state as NodePyATVPowerState];\n } else {\n d(\n `Unsupported powerState value ${input.power_state}, ignore attribute`,\n );\n }\n } else {\n d(`No powerState value found in input (${JSON.stringify(input)})`);\n }\n\n // volume\n parseStateNumberAttr(input, result, 'volume', 'volume', d);\n\n // focusState\n if (typeof input.focus_state === 'string') {\n const validValues = Object.keys(NodePyATVFocusState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.focus_state)) {\n result.focusState =\n NodePyATVFocusState[input.focus_state as NodePyATVFocusState];\n } else {\n d(\n `Unsupported focusState value ${input.focus_state}, ignore attribute`,\n );\n }\n } else {\n d(`No focusState value found in input (${JSON.stringify(input)})`);\n }\n\n // outputDevices\n if (Array.isArray(input.output_devices)) {\n result.outputDevices = input.output_devices;\n }\n\n // contentIdentifier\n parseStateStringAttr(\n input,\n result,\n 'content_identifier',\n 'contentIdentifier',\n d,\n );\n\n // iTunesStoreIdentifier\n parseStateNumberAttr(\n input,\n result,\n 'itunes_store_identifier',\n 'iTunesStoreIdentifier',\n d,\n );\n\n // episodeNumber\n parseStateNumberAttr(input, result, 'episode_number', 'episodeNumber', d);\n\n // seasonNumber\n parseStateNumberAttr(input, result, 'season_number', 'seasonNumber', d);\n\n // seriesName\n parseStateStringAttr(input, result, 'series_name', 'seriesName', d);\n\n return result;\n}\nexport function removeRequestId(id: string | undefined): void {\n if (id && requestIds.includes(id)) {\n requestIds.splice(requestIds.indexOf(id), 1);\n }\n}\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType.atvscript,\n parameters: string[],\n options: O,\n): Promise<NodePyATVScriptResponse<O>>;\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType.atvremote,\n parameters: string[],\n options: O,\n): Promise<string>;\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType,\n parameters: string[],\n options: O,\n): Promise<Record<string, unknown> | Record<string, unknown>[] | string> {\n const result = {\n code: 0,\n stderr: '',\n stdout: '',\n };\n\n await new Promise((resolve, reject) => {\n const pyatv = execute(requestId, executableType, parameters, options);\n\n /* eslint-disable @typescript-eslint/no-explicit-any*/\n const onStdOut = (data: any) => (result.stdout += String(data).trim());\n const onStdErr = (data: any) => (result.stderr += String(data).trim());\n const onError = (data: any) =>\n reject(data instanceof Error ? data : new Error(String(data)));\n /* eslint-enable @typescript-eslint/no-explicit-any*/\n\n const onClose: (code: number) => void = (code: number) => {\n result.code = code;\n\n if (pyatv.stdout) {\n pyatv.stdout.off('data', onStdOut);\n }\n if (pyatv.stderr) {\n pyatv.stderr.off('data', onStdErr);\n }\n\n pyatv.off('error', onError);\n pyatv.off('close', onClose);\n resolve(undefined);\n };\n\n if (pyatv.stdout) {\n pyatv.stdout.on('data', onStdOut);\n }\n if (pyatv.stderr) {\n pyatv.stderr.on('data', onStdErr);\n }\n\n pyatv.on('error', onError);\n pyatv.on('close', onClose);\n });\n\n if (result.stderr.length > 0) {\n const msg = `Unable to execute request ${requestId}: ${result.stderr}`;\n debug(requestId, msg, options);\n throw new Error(msg);\n }\n\n if (executableType === NodePyATVExecutableType.atvscript) {\n try {\n // response with multiple lines\n // https://github.com/sebbo2002/node-pyatv/issues/324\n if (options.allowMultipleResponses) {\n return result.stdout\n .split('\\n')\n .filter((line) => line.trim().length > 0)\n .map((line) => JSON.parse(line));\n }\n\n return JSON.parse(result.stdout);\n } catch (error) {\n const msg = `Unable to parse result ${requestId} json: ${error}`;\n debug(requestId, msg, options);\n throw new Error(msg);\n }\n }\n\n return result.stdout;\n}\n\nfunction parseStateNumberAttr(\n input: NodePyATVInternalState,\n output: NodePyATVState,\n inputAttr:\n | 'episode_number'\n | 'itunes_store_identifier'\n | 'position'\n | 'season_number'\n | 'total_time'\n | 'volume',\n outputAttr:\n | 'episodeNumber'\n | 'iTunesStoreIdentifier'\n | 'position'\n | 'seasonNumber'\n | 'totalTime'\n | 'volume',\n d: (msg: string) => void,\n): void {\n if (typeof input[inputAttr] === 'number') {\n output[outputAttr] = input[inputAttr];\n return;\n }\n\n d(`No ${outputAttr} value found in input (${JSON.stringify(input)})`);\n}\n\nfunction parseStateStringAttr(\n input: NodePyATVInternalState,\n output: NodePyATVState,\n inputAttr:\n | 'album'\n | 'app'\n | 'app_id'\n | 'artist'\n | 'content_identifier'\n | 'genre'\n | 'hash'\n | 'series_name'\n | 'title',\n outputAttr:\n | 'album'\n | 'app'\n | 'appId'\n | 'artist'\n | 'contentIdentifier'\n | 'genre'\n | 'hash'\n | 'seriesName'\n | 'title',\n d: (msg: string) => void,\n): void {\n if (typeof input[inputAttr] === 'string') {\n output[outputAttr] = input[inputAttr] as string;\n return;\n }\n\n d(`No ${outputAttr} value found in input (${JSON.stringify(input)})`);\n}\n","import { ChildProcess, type SpawnOptions } from 'child_process';\n\nimport type NodePyATVDevice from './device.js';\n\nimport { FakeChildProcess } from './fake-spawn.js';\n\nexport enum NodePyATVDeviceState {\n idle = 'idle',\n loading = 'loading',\n paused = 'paused',\n playing = 'playing',\n seeking = 'seeking',\n stopped = 'stopped',\n}\n\nexport enum NodePyATVExecutableType {\n atvremote = 'atvremote',\n atvscript = 'atvscript',\n}\n\nexport enum NodePyATVFocusState {\n // @deprecated Please use `NodePyATVFocusState.focused` instead\n focued = 'focused',\n\n // Doublicate enum value due to typo, will be removed in next breaking change\n // @todo remove in next breaking change\n // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values\n focused = 'focused',\n\n unfocused = 'unfocused',\n}\n\n/**\n * @internal\n */\nexport enum NodePyATVInternalKeys {\n down = 'down',\n home = 'home',\n homeHold = 'home_hold',\n left = 'left',\n menu = 'menu',\n next = 'next',\n pause = 'pause',\n play = 'play',\n playPause = 'play_pause',\n previous = 'previous',\n right = 'right',\n select = 'select',\n skipBackward = 'skip_backward',\n skipForward = 'skip_forward',\n stop = 'stop',\n suspend = 'suspend',\n topMenu = 'top_menu',\n turnOff = 'turn_off',\n turnOn = 'turn_on',\n up = 'up',\n volumeDown = 'volume_down',\n volumeUp = 'volume_up',\n wakeup = 'wakeup',\n}\n\nexport enum NodePyATVKeys {\n down = 'down',\n home = 'home',\n homeHold = 'homeHold',\n left = 'left',\n menu = 'menu',\n next = 'next',\n pause = 'pause',\n play = 'play',\n playPause = 'playPause',\n previous = 'previous',\n right = 'right',\n select = 'select',\n skipBackward = 'skipBackward',\n skipForward = 'skipForward',\n stop = 'stop',\n suspend = 'suspend',\n topMenu = 'topMenu',\n turnOff = 'turnOff',\n turnOn = 'turnOn',\n up = 'up',\n volumeDown = 'volumeDown',\n volumeUp = 'volumeUp',\n wakeup = 'wakeup',\n}\n\nexport enum NodePyATVListenerState {\n stopped,\n starting,\n started,\n stopping,\n}\n\nexport enum NodePyATVMediaType {\n music = 'music',\n tv = 'tv',\n unknown = 'unknown',\n video = 'video',\n}\n\nexport enum NodePyATVPowerState {\n off = 'off',\n on = 'on',\n}\n\nexport enum NodePyATVProtocol {\n airplay = 'airplay',\n dmap = 'dmap',\n mdns = 'mdns',\n mrp = 'mrp',\n}\n\nexport enum NodePyATVRepeatState {\n all = 'all',\n off = 'off',\n track = 'track',\n}\n\nexport enum NodePyATVShuffleState {\n albums = 'albums',\n off = 'off',\n songs = 'songs',\n}\n\nexport interface NodePyATVApp {\n id: string;\n launch: () => Promise<void>;\n name: string;\n}\n\nexport interface NodePyATVDeviceOptions\n extends NodePyATVFindAndInstanceOptions {\n allIDs?: string[];\n host?: string;\n mac?: string;\n model?: string;\n modelName?: string;\n name: string;\n os?: string;\n services?: NodePyATVService[];\n version?: string;\n}\n\nexport type NodePyATVEventValueType =\n | NodePyATVDeviceState\n | NodePyATVMediaType\n | NodePyATVRepeatState\n | NodePyATVShuffleState\n | number\n | string;\n\nexport interface NodePyATVFindAndInstanceOptions\n extends NodePyATVFindOptions,\n NodePyATVInstanceOptions {}\n\nexport interface NodePyATVFindOptions {\n airplayCredentials?: string;\n companionCredentials?: string;\n dmapCredentials?: string;\n host?: string;\n hosts?: string[];\n id?: string;\n mrpCredentials?: string;\n protocol?: NodePyATVProtocol;\n raopCredentials?: string;\n}\n\nexport interface NodePyATVFindResponseObject {\n devices: NodePyATVDevice[];\n errors: Record<string, unknown>[];\n}\n\nexport interface NodePyATVGetStateOptions {\n maxAge?: number;\n}\n\nexport interface NodePyATVInstanceOptions {\n atvremotePath?: string;\n atvscriptPath?: string;\n debug?: ((msg: string) => void) | true;\n noColors?: true;\n spawn?: (\n command: string,\n args: Array<string>,\n options: SpawnOptions,\n ) => ChildProcess | FakeChildProcess;\n}\n\n/**\n * @internal\n */\nexport interface NodePyATVInternalScanDevice {\n address: string;\n all_identifiers: string[];\n device_info?: {\n mac: null | string;\n model: string;\n model_str: string;\n operating_system: string;\n version: string;\n };\n identifier: string;\n name: string;\n services?: NodePyATVService[];\n}\n\n/**\n * @internal\n */\nexport interface NodePyATVInternalState {\n album?: string | unknown;\n app?: string | unknown;\n app_id?: string | unknown;\n artist?: string | unknown;\n connection?: string | unknown;\n content_identifier?: null | string;\n datetime?: string | unknown;\n device_state?: string | unknown;\n episode_number?: null | number;\n exception?: string | unknown;\n focus_state?: string | unknown;\n genre?: string | unknown;\n hash?: string | unknown;\n itunes_store_identifier?: null | number;\n media_type?: string | unknown;\n output_devices?: Array<{ identifier: string; name: string }> | null;\n position?: 1 | unknown;\n power_state?: string | unknown;\n push_updates?: string | unknown;\n repeat?: string | unknown;\n result?: string | unknown;\n season_number?: null | number;\n series_name?: null | string;\n shuffle?: string | unknown;\n stacktrace?: string | unknown;\n title?: string | unknown;\n total_time?: number | unknown;\n volume?: number | unknown;\n}\n\nexport interface NodePyATVRequestOptions extends NodePyATVInstanceOptions {\n allowMultipleResponses?: boolean;\n}\n\nexport interface NodePyATVService {\n port: number;\n protocol: NodePyATVProtocol;\n}\n\nexport interface NodePyATVState {\n album: null | string;\n app: null | string;\n appId: null | string;\n artist: null | string;\n contentIdentifier: null | string;\n dateTime: Date | null;\n deviceState: NodePyATVDeviceState | null;\n episodeNumber: null | number;\n focusState: NodePyATVFocusState | null;\n genre: null | string;\n hash: null | string;\n iTunesStoreIdentifier: null | number;\n mediaType: NodePyATVMediaType | null;\n outputDevices: Array<{ identifier: string; name: string }> | null;\n position: null | number;\n powerState: NodePyATVPowerState | null;\n repeat: NodePyATVRepeatState | null;\n seasonNumber: null | number;\n seriesName: null | string;\n shuffle: NodePyATVShuffleState | null;\n title: null | string;\n totalTime: null | number;\n volume: null | number;\n}\n\nexport type NodePyATVStateIndex = keyof NodePyATVState;\n\nexport interface NodePyATVVersionResponse {\n module: null | string;\n pyatv: null | string;\n}\n","'use strict';\n\nimport { EventEmitter } from 'events';\n\nimport { NodePyATVDeviceEvent, NodePyATVDeviceEvents } from '../lib/index.js';\nimport {\n addRequestId,\n getParameters,\n parseState,\n removeRequestId,\n request,\n} from './tools.js';\nimport {\n type NodePyATVApp,\n type NodePyATVDeviceOptions,\n NodePyATVDeviceState,\n NodePyATVExecutableType,\n NodePyATVFocusState,\n type NodePyATVGetStateOptions,\n NodePyATVInternalKeys,\n NodePyATVKeys,\n NodePyATVMediaType,\n NodePyATVPowerState,\n NodePyATVProtocol,\n NodePyATVRepeatState,\n type NodePyATVService,\n NodePyATVShuffleState,\n type NodePyATVState,\n} from './types.js';\n\n/**\n * Represents an Apple TV. Use [[getState]] to query the current state (e.g. media\n * type and title). You can also use the attribute methods (e.g. [[getTitle]] to get\n * the state. If you want realtime updates, subscribe to it's events with an\n * `EventEmitter` like API, so for example by using [[on]], [[once]] or [[addListener]].\n * It's also possible to send key commands by using [[pressKey]] or methods like [[pause]].\n */\nexport default class NodePyATVDevice implements EventEmitter {\n /**\n * Get all IDs of the Apple TV.\n * Requires pyatv >= 0.14.5.\n */\n get allIDs(): string[] | undefined {\n return this.options.allIDs;\n }\n /**\n * Returns true, if debugging is enabled. Returns the custom\n * logging method, if one was specified. Otherwise, if debug\n * log is disabled, returns undefined.\n */\n get debug(): ((msg: string) => void) | true | undefined {\n return this.options.debug;\n }\n /**\n * Enable or disable debugging or set a custom\n * debugging method to use.\n *\n * @param debug\n */\n set debug(debug: ((msg: string) => void) | true | undefined) {\n if (typeof debug === 'function') {\n this.options.debug = debug;\n } else {\n this.options.debug = Boolean(debug) || undefined;\n }\n }\n\n /**\n * Get the IP address of the Apple TV.\n */\n get host(): string | undefined {\n return this.options.host;\n }\n\n /**\n * Get the ID of the Apple TV.\n */\n get id(): string | undefined {\n return this.options.id;\n }\n\n /**\n * Get the MAC address of the Apple TV.\n * Requires pyatv >= 0.14.5.\n */\n get mac(): string | undefined {\n return this.options.mac;\n }\n\n /**\n * Get the model identifier of the device. Only set, if the\n * device was found using [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.model → \"Gen4K\"\n */\n get model(): string | undefined {\n return this.options.model;\n }\n\n /**\n * Get the model name of the device. Only set, if the device\n * was found with [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.modelName → \"Apple TV 4K\"\n */\n get modelName(): string | undefined {\n return this.options.modelName;\n }\n\n /**\n * Get the name of the Apple TV.\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const devices = await pyatv.find();\n * devices.forEach(device =>\n * console.log(device.name)\n * );\n * ```\n */\n get name(): string {\n return this.options.name;\n }\n\n /**\n * Get the operating system of the device. Only set, if the\n * device was found with [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.os → \"TvOS\"\n */\n get os(): string | undefined {\n return this.options.os;\n }\n\n /**\n * Get the used protocol to connect to the Apple TV.\n */\n get protocol(): NodePyATVProtocol | undefined {\n return this.options.protocol;\n }\n\n /**\n * Returns a list of services supported by the device. Ony set, if\n * the device was found during a scan using [[find()]]. Requires\n * pyatv ≧ 0.10.3.\n *\n * @example device.services → [\n * {\n * \"protocol\": \"airplay\",\n * \"port\": 7000\n * },\n * {\n * \"protocol\": \"dmap\",\n * \"port\": 3689\n * }\n * ]\n */\n get services(): NodePyATVService[] | undefined {\n return this.options.services;\n }\n\n /**\n * Get the device version. Only set, if the device was found\n * during a scan using [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.version → \"15.5.1\"\n */\n get version(): string | undefined {\n return this.options.version;\n }\n\n private readonly events: NodePyATVDeviceEvents;\n\n private readonly options: NodePyATVDeviceOptions;\n\n private readonly state: NodePyATVState;\n\n constructor(options: NodePyATVDeviceOptions) {\n if (!options.host && !options.id && !options.mac) {\n throw new Error('Either host, id or mac must be set!');\n }\n\n this.options = Object.assign({}, options);\n this.state = parseState({}, '', {});\n this.events = new NodePyATVDeviceEvents(this.state, this, this.options);\n\n // @todo basic validation\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * @param event\n * @param listener\n * @category Event\n */\n addListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n this.events.addListener(event, listener);\n return this;\n }\n\n /**\n * Removes the state node-pyatv cached for this device.\n *\n * @category State\n */\n clearState(): void {\n this.applyState(parseState({}, '', {}));\n }\n\n /**\n * Send the \"down\" command\n * @category Control\n */\n async down(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.down);\n }\n\n /**\n * Emit an event.\n * @param event\n * @param payload\n * @category Event\n */\n emit(event: string | symbol, payload: NodePyATVDeviceEvent): boolean {\n return this.events.emit(event, payload);\n }\n\n /**\n * Get all event names which are currently known.\n * @category Event\n */\n eventNames(): Array<string | symbol> {\n return this.events.eventNames();\n }\n\n /**\n * Returns the album of the current playing media\n * @param options\n * @category State\n */\n async getAlbum(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.album;\n }\n\n /**\n * Returns the currently used app\n * @param options\n * @category State\n */\n async getApp(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.app;\n }\n\n /**\n * Returns the id of the currently used app\n * @param options\n * @category State\n */\n async getAppId(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.appId;\n }\n\n /**\n * Returns the artist of the current playing media\n * @param options\n * @category State\n */\n async getArtist(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.artist;\n }\n\n /**\n * Returns the app specific content identifier\n * @param options\n * @category State\n */\n async getContentIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n return this.getState(options).then((state) => state.contentIdentifier);\n }\n\n /**\n * Get the date and time when the state was last updated.\n * @param options\n * @category State\n */\n async getDateTime(\n options: NodePyATVGetStateOptions = {},\n ): Promise<Date | null> {\n const state = await this.getState(options);\n return state.dateTime;\n }\n\n /**\n * Get the state of this device (e.g. playing, etc.)\n * @param options\n * @category State\n */\n async getDeviceState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVDeviceState | null> {\n const state = await this.getState(options);\n return state.deviceState;\n }\n\n /**\n * Returns the episode number.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getEpisodeNumber(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.episodeNumber);\n }\n\n /**\n * Returns the current focus state of the device\n * @param options\n * @category State\n */\n async getFocusState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVFocusState | null> {\n return this.getState(options).then((state) => state.focusState);\n }\n\n /**\n * Returns the genre of the current playing media\n * @param options\n * @category State\n */\n async getGenre(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.genre;\n }\n\n /**\n * Get the hash of the current media\n * @param options\n * @category State\n */\n async getHash(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.hash;\n }\n\n /**\n * Returns the iTunes Store identifier if available.\n * Requires pyatv >= 0.16.0\n * @param options\n * @category State\n * @alias getiTunesStoreIdentifier\n */\n async getITunesStoreIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then(\n (state) => state.iTunesStoreIdentifier,\n );\n }\n\n async getiTunesStoreIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getITunesStoreIdentifier(options);\n }\n\n /**\n * Get max number of listeners allowed\n * @category Event\n */\n getMaxListeners(): number {\n return this.events.getMaxListeners();\n }\n\n /**\n * Get the media type of the current media\n * @param options\n * @category State\n */\n async getMediaType(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVMediaType | null> {\n const state = await this.getState(options);\n return state.mediaType;\n }\n\n /**\n * Returns the current output devices of the device\n * @param options\n * @category State\n */\n async getOutputDevices(\n options: NodePyATVGetStateOptions = {},\n ): Promise<Array<{ identifier: string; name: string }> | null> {\n return this.getState(options).then((state) => state.outputDevices);\n }\n\n /**\n * Returns the title of the current playing media\n * @param options\n * @category State\n */\n async getPosition(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n const state = await this.getState(options);\n return state.position;\n }\n\n /**\n * Returns the current power state (= is it on or off, see [[NodePyATVPowerState]]) of the device.\n * @param options\n * @category State\n */\n async getPowerState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVPowerState | null> {\n return this.getState(options).then((state) => state.powerState);\n }\n\n /**\n * Returns the repeat state\n * @param options\n * @category State\n */\n async getRepeat(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVRepeatState | null> {\n const state = await this.getState(options);\n return state.repeat;\n }\n\n /**\n * Returns the season number.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getSeasonNumber(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.seasonNumber);\n }\n /**\n * Returns the season name.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getSeriesName(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n return this.getState(options).then((state) => state.seriesName);\n }\n\n /**\n * Returns the shuffle state\n * @param options\n * @category State\n */\n async getShuffle(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVShuffleState | null> {\n const state = await this.getState(options);\n return state.shuffle;\n }\n\n /**\n * Returns an [[NodePyATVState]] object representing the current state\n * of the device. Has an internal cache, which has a default TTL of 5s.\n * You can change this default value by passing the `maxAge` option.\n *\n * ```typescript\n * await device.getState({maxAge: 10000}); // cache TTL: 10s\n * ```\n *\n * @param options\n * @category State\n */\n async getState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVState> {\n if (\n this.state?.dateTime &&\n new Date().getTime() - this.state.dateTime.getTime() <\n (options.maxAge || 5000)\n ) {\n let position = null;\n if (this.state.position && this.state.dateTime) {\n position = Math.round(\n this.state.position +\n (new Date().getTime() - this.state.dateTime.getTime()) /\n 1000,\n );\n }\n\n return Object.assign({}, this.state, { position });\n }\n\n const id = addRequestId();\n\n try {\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'playing'],\n this.options,\n );\n const newState = parseState(result, id, this.options);\n\n this.applyState(newState);\n return newState;\n } finally {\n removeRequestId(id);\n }\n }\n\n /**\n * Returns the title of the current playing media\n * @param options\n * @category State\n */\n async getTitle(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.title;\n }\n\n /**\n * Returns the media length of the current playing media\n * @param options\n * @category State\n */\n async getTotalTime(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n const state = await this.getState(options);\n return state.totalTime;\n }\n\n /**\n * Returns the current volume of the device in percent (0 - 100)\n * @param options\n * @category State\n */\n async getVolume(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.volume);\n }\n\n /**\n * Send the \"home\" command\n * @category Control\n */\n async home(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.home);\n }\n\n /**\n * Send the \"homeHold\" command\n * @category Control\n */\n async homeHold(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.homeHold);\n }\n\n /**\n * Launch an application. Probably requires `companionCredentials`, see\n * https://pyatv.dev/documentation/atvremote/#apps for more details.\n * @param id App identifier, e.g. `com.netflix.Netflix`\n */\n async launchApp(id: string): Promise<void> {\n await this._pressKeyWithRemote('launch_app=' + id);\n }\n\n /**\n * Send the \"left\" command\n * @category Control\n */\n async left(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.left);\n }\n\n /**\n * Returns the list of installed apps on the Apple TV. Probably requires `companionCredentials`,\n * see https://pyatv.dev/documentation/atvremote/#apps for more details.\n */\n async listApps(): Promise<NodePyATVApp[]> {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvremote,\n [...parameters, 'app_list'],\n this.options,\n );\n if (typeof result !== 'string' || !result.startsWith('App: ')) {\n throw new Error('Unexpected atvremote response: ' + result);\n }\n\n removeRequestId(id);\n const regex = /(.+) \\(([^)]+)\\)$/i;\n const items = result\n .substring(5)\n .split(', App: ')\n .map((i) => {\n const m = i.match(regex);\n if (m !== null) {\n return {\n id: m[2],\n launch: () => this.launchApp(m[2]),\n name: m[1],\n };\n }\n }) as Array<NodePyATVApp | undefined>;\n\n return items.filter(Boolean) as NodePyATVApp[];\n }\n\n /**\n * Get number of listeners for event\n * @param event\n * @category Event\n */\n listenerCount(event: string | symbol): number {\n return this.events.listenerCount(event);\n }\n\n /**\n * Get listeners for event. Will also return\n * node-pyatv wrappers (e.g. once)\n *\n * @param event\n * @category Event\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n listeners(event: string | symbol): Function[] {\n return this.events.listeners(event);\n }\n\n /**\n * Send the \"menu\" command\n * @category Control\n */\n async menu(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.menu);\n }\n\n /**\n * Send the \"next\" command\n * @category Control\n */\n async next(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.next);\n }\n\n /**\n * Remove an event listener. Will stop the event subscription with the\n * Apple TV if this was the last event listener.\n * @param event\n * @param listener\n * @category Event\n */\n off(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.off(event, listener);\n return this;\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * @param event\n * @param listener\n * @category Event\n */\n on(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.on(event, listener);\n return this;\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * Removes the listener automatically after the first occurrence.\n * @param event\n * @param listener\n * @category Event\n */\n once(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.once(event, listener);\n return this;\n }\n\n /**\n * Send the \"pause\" command\n * @category Control\n */\n async pause(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.pause);\n }\n\n /**\n * Send the \"play\" command\n * @category Control\n */\n async play(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.play);\n }\n\n /**\n * Send the \"playPause\" command\n * @category Control\n */\n async playPause(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.playPause);\n }\n\n /**\n * @param event\n * @param listener\n * @category Event\n */\n prependListener(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.prependListener(event, listener);\n return this;\n }\n\n /**\n * @param event\n * @param listener\n * @category Event\n */\n prependOnceListener(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.prependOnceListener(event, listener);\n return this;\n }\n\n /**\n * Send a key press to the Apple TV\n *\n * ```typescript\n * await device.pressKey(NodePyATVKeys.home);\n * ```\n *\n * <br />\n *\n * ```javascript\n * await device.pressKey('home');\n * ```\n *\n * @param key\n * @category Control\n */\n async pressKey(key: NodePyATVKeys): Promise<void> {\n const internalKeyEntry = Object.entries(NodePyATVInternalKeys).find(\n ([k]) => key === k,\n );\n\n if (!internalKeyEntry) {\n throw new Error(`Unsupported key value ${key}!`);\n }\n\n const internalKey = internalKeyEntry[1];\n if ([NodePyATVKeys.turnOff, NodePyATVKeys.turnOn].includes(key)) {\n await this._pressKeyWithRemote(internalKey);\n } else {\n await this._pressKeyWithScript(internalKey);\n }\n }\n\n /**\n * Send the \"previous\" command\n * @category Control\n */\n async previous(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.previous);\n }\n\n /**\n * @param event\n * @category Event\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n rawListeners(event: string | symbol): Function[] {\n return this.events.rawListeners(event);\n }\n\n /**\n * Removes all listeners, either for the given event or\n * for every event. Will stop the event subscription with\n * the Apple TV if this was the last event listener.\n *\n * @param event\n * @category Event\n */\n removeAllListeners(event?: string | symbol): this {\n this.events.removeAllListeners(event);\n return this;\n }\n\n /**\n * Remove an event listener. Will stop the event subscription with the\n * Apple TV if this was the last event listener.\n * @param event\n * @param listener\n * @category Event\n */\n removeListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n this.events.removeListener(event, listener);\n return this;\n }\n\n /**\n * Send the \"right\" command\n * @category Control\n */\n async right(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.right);\n }\n\n /**\n * Send the \"select\" command\n * @category Control\n */\n async select(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.select);\n }\n\n /**\n * @param n\n * @category Event\n */\n setMaxListeners(n: number): this {\n this.events.setMaxListeners(n);\n return this;\n }\n\n /**\n * Send the \"skipBackward\" command\n * @category Control\n */\n async skipBackward(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.skipBackward);\n }\n\n /**\n * Send the \"skipForward\" command\n * @category Control\n */\n async skipForward(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.skipForward);\n }\n\n /**\n * Send the \"stop\" command\n * @category Control\n */\n async stop(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.stop);\n }\n\n /**\n * Send the \"suspend\" command\n * @category Control\n * @deprecated\n */\n async suspend(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.suspend);\n }\n\n /**\n * Returns an object with `name`, `host`, `mac`, `id` and `protocol`.\n * Can be used to initiate a new device instance.\n *\n * @category Basic\n */\n toJSON(): Pick<\n NodePyATVDeviceOptions,\n 'host' | 'id' | 'mac' | 'name' | 'protocol'\n > {\n return {\n host: this.host,\n id: this.id,\n mac: this.mac,\n name: this.name,\n protocol: this.protocol,\n };\n }\n\n /**\n * Send the \"topMenu\" command\n * @category Control\n */\n async topMenu(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.topMenu);\n }\n\n /**\n * Returns a string. Just for debugging, etc.\n *\n * @category Basic\n */\n toString(): string {\n return `NodePyATVDevice(${this.name}, ${this.host})`;\n }\n\n /**\n * Send the \"turn_off\" command\n * @category Control\n */\n async turnOff(): Promise<void> {\n await this._pressKeyWithRemote(NodePyATVInternalKeys.turnOff);\n }\n\n /**\n * Send the \"turn_on\" command\n * @category Control\n */\n async turnOn(): Promise<void> {\n await this._pressKeyWithRemote(NodePyATVInternalKeys.turnOn);\n }\n\n /**\n * Send the \"up\" command\n * @category Control\n */\n async up(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.up);\n }\n\n /**\n * Send the \"volumeDown\" command\n * @category Control\n */\n async volumeDown(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.volumeDown);\n }\n\n /**\n * Send the \"volumeUp\" command\n * @category Control\n */\n async volumeUp(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.volumeUp);\n }\n\n /**\n * Send the \"wakeup\" command\n * @category Control\n * @deprecated\n */\n async wakeup(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.wakeup);\n }\n\n private async _pressKeyWithRemote(key: NodePyATVInternalKeys | string) {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n await request(\n id,\n NodePyATVExecutableType.atvremote,\n [...parameters, key],\n this.options,\n );\n removeRequestId(id);\n }\n\n private async _pressKeyWithScript(key: NodePyATVInternalKeys | string) {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, key],\n this.options,\n );\n if (typeof result !== 'object' || result.result !== 'success') {\n throw new Error(\n `Unable to parse pyatv response: ${JSON.stringify(result, null, ' ')}`,\n );\n }\n\n removeRequestId(id);\n }\n\n private applyState(newState: NodePyATVState): void {\n this.events.applyStateAndEmitEvents(newState);\n }\n}\n","'use strict';\n\nimport NodePyATVInstance from '../lib/instance.js';\n\n(async () => {\n try {\n await NodePyATVInstance.check();\n\n console.log('');\n console.log('✔ node-pyatv seems to be ready to use!');\n console.log(' Thank you and have a great day. Or night. Whatever.');\n console.log('');\n } catch (error) {\n console.log('');\n console.log('#'.repeat(60));\n console.log('#' + ' '.repeat(58) + '#');\n console.log(\n '# ⚠ Warning: node-pyatv is not ready to be used!' +\n ' '.repeat(10) +\n '#',\n );\n console.log('#' + ' '.repeat(58) + '#');\n console.log(\n '# To use the JavaScript module, pyatv >= 0.6.0 must be #',\n );\n console.log(\n '# installed. Unfortunately this could not be found. During #',\n );\n console.log(\n '# the check following error message was reported: #',\n );\n console.log('#' + ' '.repeat(58) + '#');\n console.log(\n String(error)\n .replace('Error: ', '')\n .replace(/(.{1,54})/g, '$1\\n')\n .split('\\n')\n .map((l) => l.trim())\n .filter((l) => Boolean(l))\n .map((l) => `# > ${l}${' '.repeat(55 - l.length)}#`)\n .join('\\n'),\n );\n console.log('#' + ' '.repeat(58) + '#');\n console.log(\n '# You can probably find more information here: #',\n );\n console.log(\n '# https://github.com/sebbo2002/node-pyatv #',\n );\n console.log('#' + ' '.repeat(58) + '#');\n console.log('#'.repeat(60));\n console.log('');\n }\n})();\n"],"mappings":"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","names":["getImportMetaUrl","importMetaUrl","import_fs","import_path","import_semver","import_url","NodePyATVDeviceEvent","values","import_events","import_child_process","NodePyATVDeviceState","NodePyATVFocusState","NodePyATVInternalKeys","NodePyATVMediaType","NodePyATVPowerState","NodePyATVRepeatState","NodePyATVShuffleState","requestIds","addRequestId","id","i","compareOutputDevices","a","b","debug","message","options","log","enableColors","parts","execute","requestId","executableType","parameters","executable","getExecutable","mySpawn","child","onStdOut","data","onStdErr","onError","onClose","code","getParameters","parseState","input","d","msg","result","errorStr","date","parseStateStringAttr","NodePyATVMediaType","NodePyATVDeviceState","parseStateNumberAttr","NodePyATVShuffleState","NodePyATVRepeatState","NodePyATVPowerState","NodePyATVFocusState","removeRequestId","request","resolve","reject","pyatv","line","error","output","inputAttr","outputAttr","NodePyATVDeviceEvents","state","device","options","event","listener","newState","keys","k","v","key","oldValue","newValue","compareOutputDevices","NodePyATVDeviceEvent","error","a","b","reqId","debug","cb","update","parseState","id","addRequestId","removeRequestId","data","json","msg","listenStart","parameters","getParameters","execute","onError","onStdErr","onStdOut","s","onClose","code","NodePyATVDevice","debug","options","parseState","NodePyATVDeviceEvents","event","listener","payload","state","position","id","addRequestId","parameters","getParameters","result","request","newState","removeRequestId","regex","i","m","key","internalKeyEntry","NodePyATVInternalKeys","k","internalKey","n","NodePyATVInstance","_NodePyATVInstance","options","versions","semver","error","NodePyATVDevice","returnDevicesAndErrors","id","addRequestId","parameters","getParameters","devices","errors","response","request","item","device","removeRequestId","pyatv","module","debug","packageJsonPath","importMetaUrl","fsPromises","NodePyATVInstance","error","l"]}
|
package/dist/lib/index.cjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
"use strict";var Q=Object.create;var $=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var Z=Object.getPrototypeOf,K=Object.prototype.hasOwnProperty;var ee=(s,e)=>{for(var t in e)$(s,t,{get:e[t],enumerable:!0})},J=(s,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Y(e))!K.call(s,n)&&n!==t&&$(s,n,{get:()=>e[n],enumerable:!(i=X(e,n))||i.enumerable});return s};var te=(s,e,t)=>(t=s!=null?Q(Z(s)):{},J(e||!s||!s.__esModule?$(t,"default",{value:s,enumerable:!0}):t,s)),se=s=>J($({},"__esModule",{value:!0}),s);var re={};ee(re,{NodePyATVDevice:()=>A,NodePyATVDeviceEvent:()=>S,NodePyATVDeviceEvents:()=>N,NodePyATVDeviceState:()=>w,NodePyATVExecutableType:()=>T,NodePyATVInstance:()=>E,NodePyATVKeys:()=>I,NodePyATVListenerState:()=>j,NodePyATVMediaType:()=>V,NodePyATVPowerState:()=>b,NodePyATVProtocol:()=>G,NodePyATVRepeatState:()=>O,NodePyATVShuffleState:()=>_,default:()=>E});module.exports=se(re);var ie=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.src
|
|
1
|
+
"use strict";var Q=Object.create;var $=Object.defineProperty;var X=Object.getOwnPropertyDescriptor;var Y=Object.getOwnPropertyNames;var Z=Object.getPrototypeOf,K=Object.prototype.hasOwnProperty;var ee=(s,e)=>{for(var t in e)$(s,t,{get:e[t],enumerable:!0})},J=(s,e,t,i)=>{if(e&&typeof e=="object"||typeof e=="function")for(let n of Y(e))!K.call(s,n)&&n!==t&&$(s,n,{get:()=>e[n],enumerable:!(i=X(e,n))||i.enumerable});return s};var te=(s,e,t)=>(t=s!=null?Q(Z(s)):{},J(e||!s||!s.__esModule?$(t,"default",{value:s,enumerable:!0}):t,s)),se=s=>J($({},"__esModule",{value:!0}),s);var re={};ee(re,{NodePyATVDevice:()=>A,NodePyATVDeviceEvent:()=>S,NodePyATVDeviceEvents:()=>N,NodePyATVDeviceState:()=>w,NodePyATVExecutableType:()=>T,NodePyATVInstance:()=>E,NodePyATVKeys:()=>I,NodePyATVListenerState:()=>j,NodePyATVMediaType:()=>V,NodePyATVPowerState:()=>b,NodePyATVProtocol:()=>G,NodePyATVRepeatState:()=>O,NodePyATVShuffleState:()=>_,default:()=>E});module.exports=se(re);var ie=()=>typeof document>"u"?new URL(`file:${__filename}`).href:document.currentScript&&document.currentScript.tagName.toUpperCase()==="SCRIPT"?document.currentScript.src:new URL("main.js",document.baseURI).href,v=ie();var S=class{get device(){return this.values.device}get key(){return this.values.key}get newValue(){return this.values.new}get oldValue(){return this.values.old}get value(){return this.values.new}values;constructor(e){this.values=Object.assign({},e,{key:e.key})}};var q=require("events");var M=require("child_process");var w=(o=>(o.idle="idle",o.loading="loading",o.paused="paused",o.playing="playing",o.seeking="seeking",o.stopped="stopped",o))(w||{}),T=(t=>(t.atvremote="atvremote",t.atvscript="atvscript",t))(T||{}),C=(i=>(i.focued="focused",i.focused="focused",i.unfocused="unfocused",i))(C||{}),U=(a=>(a.down="down",a.home="home",a.homeHold="home_hold",a.left="left",a.menu="menu",a.next="next",a.pause="pause",a.play="play",a.playPause="play_pause",a.previous="previous",a.right="right",a.select="select",a.skipBackward="skip_backward",a.skipForward="skip_forward",a.stop="stop",a.suspend="suspend",a.topMenu="top_menu",a.turnOff="turn_off",a.turnOn="turn_on",a.up="up",a.volumeDown="volume_down",a.volumeUp="volume_up",a.wakeup="wakeup",a))(U||{}),I=(a=>(a.down="down",a.home="home",a.homeHold="homeHold",a.left="left",a.menu="menu",a.next="next",a.pause="pause",a.play="play",a.playPause="playPause",a.previous="previous",a.right="right",a.select="select",a.skipBackward="skipBackward",a.skipForward="skipForward",a.stop="stop",a.suspend="suspend",a.topMenu="topMenu",a.turnOff="turnOff",a.turnOn="turnOn",a.up="up",a.volumeDown="volumeDown",a.volumeUp="volumeUp",a.wakeup="wakeup",a))(I||{}),j=(n=>(n[n.stopped=0]="stopped",n[n.starting=1]="starting",n[n.started=2]="started",n[n.stopping=3]="stopping",n))(j||{}),V=(n=>(n.music="music",n.tv="tv",n.unknown="unknown",n.video="video",n))(V||{}),b=(t=>(t.off="off",t.on="on",t))(b||{}),G=(n=>(n.airplay="airplay",n.dmap="dmap",n.mdns="mdns",n.mrp="mrp",n))(G||{}),O=(i=>(i.all="all",i.off="off",i.track="track",i))(O||{}),_=(i=>(i.albums="albums",i.off="off",i.songs="songs",i))(_||{});var R=[];function m(){let s="?";for(let e=0;e<1e3;e+=1)if(s=Math.round(Math.random()*(e+6)*36).toString(36).toUpperCase(),!R.includes(s)){R.push(s);break}return s}function B(s,e){return!!(Array.isArray(s)&&Array.isArray(e)&&JSON.stringify(s.sort((t,i)=>t.identifier<i.identifier?-1:1))===JSON.stringify(e.sort((t,i)=>t.identifier<i.identifier?-1:1)))}function u(s,e,t){if(t.debug){let i=typeof t.debug=="function"?t.debug:console.log,n=!process.env.NO_COLOR&&!t.noColors,r=[n?"\x1B[0m":"",n?"\x1B[90m":"","[node-pyatv][",n?"\x1B[37m":"",s,n?"\x1B[90m":"","] ",n?"\x1B[0m":"",e];i.apply(null,[r.join("")])}}function W(s,e,t,i){let n=ne(e,i),r=typeof i.spawn=="function"?i.spawn:M.spawn;u(s,`${n} ${t.join(" ")}`,i);let o=r(n,t,{env:process.env}),d=h=>u(s,`stdout: ${String(h).trim()}`,i),p=h=>u(s,`stderr: ${String(h).trim()}`,i),l=h=>u(s,`error: ${String(h).trim()}`,i),D=h=>{u(s,`${n} exited with code: ${h}`,i),o.stdout&&o.stdout.off("data",d),o.stderr&&o.stderr.off("data",p),o.off("error",l),o.off("close",D)};return o.stdout&&o.stdout.on("data",d),o.stderr&&o.stderr.on("data",p),o.on("error",l),o.on("close",D),o}function ne(s,e){return s==="atvremote"&&typeof e.atvremotePath=="string"?e.atvremotePath:s==="atvscript"&&typeof e.atvscriptPath=="string"?e.atvscriptPath:s}function g(s={}){let e=[];return s.hosts?e.push("-s",s.hosts.join(",")):s.host&&e.push("-s",s.host),s.id&&e.push("-i",s.id),s.protocol&&e.push("--protocol",s.protocol),s.dmapCredentials&&e.push("--dmap-credentials",s.dmapCredentials),s.mrpCredentials&&e.push("--mrp-credentials",s.mrpCredentials),s.airplayCredentials&&e.push("--airplay-credentials",s.airplayCredentials),s.companionCredentials&&e.push("--companion-credentials",s.companionCredentials),s.raopCredentials&&e.push("--raop-credentials",s.raopCredentials),e}function k(s,e,t){let i=r=>u(e,r,t),n={album:null,app:null,appId:null,artist:null,contentIdentifier:null,dateTime:null,deviceState:null,episodeNumber:null,focusState:null,genre:null,hash:null,iTunesStoreIdentifier:null,mediaType:null,outputDevices:null,position:null,powerState:null,repeat:null,seasonNumber:null,seriesName:null,shuffle:null,title:null,totalTime:null,volume:null};if(!s||typeof s!="object")return n;if(s.exception){let r="Got pyatv Error: "+s.exception;throw s.stacktrace&&(r+=`
|
|
2
2
|
|
|
3
3
|
pyatv Stacktrace:
|
|
4
4
|
`+s.stacktrace),new Error(r)}if(typeof s.datetime=="string"){let r=new Date(s.datetime);isNaN(r.getTime())?i(`Invalid datetime value ${s.datetime}, ignore attribute`):n.dateTime=r}else i(`No datetime value found in input (${JSON.stringify(s)})`);return f(s,n,"hash","hash",i),typeof s.media_type=="string"?Object.keys(V).map(o=>String(o)).includes(s.media_type)?n.mediaType=V[s.media_type]:i(`Unsupported mediaType value ${s.media_type}, ignore attribute`):i(`No mediaType value found in input (${JSON.stringify(s)})`),typeof s.device_state=="string"?Object.keys(w).map(o=>String(o)).includes(s.device_state)?n.deviceState=w[s.device_state]:i(`Unsupported deviceState value ${s.device_state}, ignore attribute`):i(`No deviceState value found in input (${JSON.stringify(s)})`),f(s,n,"title","title",i),f(s,n,"artist","artist",i),f(s,n,"album","album",i),f(s,n,"genre","genre",i),x(s,n,"total_time","totalTime",i),x(s,n,"position","position",i),typeof s.shuffle=="string"?Object.keys(_).map(o=>String(o)).includes(s.shuffle)?n.shuffle=_[s.shuffle]:i(`Unsupported shuffle value ${s.shuffle}, ignore attribute`):i(`No shuffle value found in input (${JSON.stringify(s)})`),typeof s.repeat=="string"?Object.keys(O).map(o=>String(o)).includes(s.repeat)?n.repeat=O[s.repeat]:i(`Unsupported repeat value ${s.repeat}, ignore attribute`):i(`No repeat value found in input (${JSON.stringify(s)})`),f(s,n,"app","app",i),f(s,n,"app_id","appId",i),typeof s.power_state=="string"?Object.keys(b).map(o=>String(o)).includes(s.power_state)?n.powerState=b[s.power_state]:i(`Unsupported powerState value ${s.power_state}, ignore attribute`):i(`No powerState value found in input (${JSON.stringify(s)})`),x(s,n,"volume","volume",i),typeof s.focus_state=="string"?Object.keys(C).map(o=>String(o)).includes(s.focus_state)?n.focusState=C[s.focus_state]:i(`Unsupported focusState value ${s.focus_state}, ignore attribute`):i(`No focusState value found in input (${JSON.stringify(s)})`),Array.isArray(s.output_devices)&&(n.outputDevices=s.output_devices),f(s,n,"content_identifier","contentIdentifier",i),x(s,n,"itunes_store_identifier","iTunesStoreIdentifier",i),x(s,n,"episode_number","episodeNumber",i),x(s,n,"season_number","seasonNumber",i),f(s,n,"series_name","seriesName",i),n}function c(s){s&&R.includes(s)&&R.splice(R.indexOf(s),1)}async function P(s,e,t,i){let n={code:0,stderr:"",stdout:""};if(await new Promise((r,o)=>{let d=W(s,e,t,i),p=y=>n.stdout+=String(y).trim(),l=y=>n.stderr+=String(y).trim(),D=y=>o(y instanceof Error?y:new Error(String(y))),h=y=>{n.code=y,d.stdout&&d.stdout.off("data",p),d.stderr&&d.stderr.off("data",l),d.off("error",D),d.off("close",h),r(void 0)};d.stdout&&d.stdout.on("data",p),d.stderr&&d.stderr.on("data",l),d.on("error",D),d.on("close",h)}),n.stderr.length>0){let r=`Unable to execute request ${s}: ${n.stderr}`;throw u(s,r,i),new Error(r)}if(e==="atvscript")try{return i.allowMultipleResponses?n.stdout.split(`
|
package/dist/lib/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/lib/index.ts","../../node_modules/tsup/assets/cjs_shims.js","../../src/lib/device-event.ts","../../src/lib/device-events.ts","../../src/lib/tools.ts","../../src/lib/types.ts","../../src/lib/device.ts","../../src/lib/instance.ts"],"sourcesContent":["'use strict';\n\nexport { default as NodePyATVDeviceEvent } from './device-event.js';\n\nexport { default as NodePyATVDeviceEvents } from './device-events.js';\nexport { default as NodePyATVDevice } from './device.js';\nexport { default as NodePyATVInstance } from './instance.js';\nexport { default } from './instance.js';\n\nexport {\n type NodePyATVDeviceOptions,\n NodePyATVDeviceState,\n type NodePyATVEventValueType,\n NodePyATVExecutableType,\n type NodePyATVFindAndInstanceOptions,\n type NodePyATVFindOptions,\n type NodePyATVFindResponseObject,\n type NodePyATVGetStateOptions,\n type NodePyATVInstanceOptions,\n NodePyATVKeys,\n NodePyATVListenerState,\n NodePyATVMediaType,\n NodePyATVPowerState,\n NodePyATVProtocol,\n NodePyATVRepeatState,\n type NodePyATVRequestOptions,\n type NodePyATVService,\n NodePyATVShuffleState,\n type NodePyATVState,\n type NodePyATVVersionResponse,\n} from './types.js';\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () =>\n typeof document === 'undefined'\n ? new URL(`file:${__filename}`).href\n : (document.currentScript && document.currentScript.src) ||\n new URL('main.js', document.baseURI).href\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","'use strict';\n\nimport type { NodePyATVEventValueType, NodePyATVStateIndex } from './types.js';\n\nimport { NodePyATVDevice } from '../lib/index.js';\n\nexport default class NodePyATVDeviceEvent {\n /**\n * References the device instance this\n * event originates from\n */\n get device(): NodePyATVDevice {\n return this.values.device;\n }\n\n /**\n * References the attribute name which was changed. So if the\n * title has been updated, this would be `title`.\n */\n get key(): NodePyATVStateIndex {\n return this.values.key;\n }\n\n /**\n * @alias value\n */\n get newValue(): NodePyATVEventValueType {\n return this.values.new;\n }\n\n /**\n * Holds the old value which was there\n * before the value was changed.\n */\n get oldValue(): NodePyATVEventValueType {\n return this.values.old;\n }\n\n /**\n * New, current value for `key`\n */\n get value(): NodePyATVEventValueType {\n return this.values.new;\n }\n\n protected readonly values: {\n device: NodePyATVDevice;\n key: NodePyATVStateIndex;\n new: NodePyATVEventValueType;\n old: NodePyATVEventValueType;\n };\n\n /**\n *\n * @param values\n * @internal\n */\n constructor(values: {\n device: NodePyATVDevice;\n key: NodePyATVStateIndex;\n new: NodePyATVEventValueType;\n old: NodePyATVEventValueType;\n }) {\n this.values = Object.assign({}, values, {\n key: values.key as NodePyATVStateIndex,\n });\n }\n}\n","'use strict';\n\nimport { ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\n\nimport { NodePyATVDevice, NodePyATVDeviceEvent } from '../lib/index.js';\nimport { FakeChildProcess } from './fake-spawn.js';\nimport {\n addRequestId,\n compareOutputDevices,\n debug,\n execute,\n getParameters,\n parseState,\n removeRequestId,\n} from './tools.js';\nimport {\n type NodePyATVDeviceOptions,\n NodePyATVExecutableType,\n type NodePyATVInternalState,\n NodePyATVListenerState,\n type NodePyATVState,\n type NodePyATVStateIndex,\n} from './types.js';\n\n/**\n * @internal\n */\nexport default class NodePyATVDeviceEvents extends EventEmitter {\n private readonly device: NodePyATVDevice;\n private listenerState: NodePyATVListenerState;\n private readonly options: NodePyATVDeviceOptions;\n private pyatv: ChildProcess | FakeChildProcess | undefined;\n private readonly state: NodePyATVState;\n private timeout: NodeJS.Timeout | undefined;\n\n constructor(\n state: NodePyATVState,\n device: NodePyATVDevice,\n options: NodePyATVDeviceOptions,\n ) {\n super();\n\n this.state = state;\n this.device = device;\n this.options = Object.assign({}, options);\n this.listenerState = NodePyATVListenerState.stopped;\n }\n\n addListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.addListener(event, listener);\n this.checkListener();\n return this;\n }\n\n applyStateAndEmitEvents(newState: NodePyATVState): void {\n let keys = Object.keys(this.state);\n\n // Remove special fields from the list\n keys = keys.filter(\n (k) =>\n ![\n 'focusState',\n 'outputDevices',\n 'powerState',\n 'volume',\n ].includes(k),\n );\n\n if ('powerState' in newState && newState.powerState) {\n keys = ['powerState'];\n }\n if ('focusState' in newState && newState.focusState) {\n keys = ['focusState'];\n }\n if ('outputDevices' in newState && newState.outputDevices) {\n keys = ['outputDevices'];\n }\n\n // Volume events don't hold the complete state…\n // see https://github.com/sebbo2002/node-pyatv/pull/291\n if ('volume' in newState && newState.volume !== null) {\n keys = ['volume'];\n }\n\n // If all values are null, we don't need to emit events at all\n // https://github.com/sebbo2002/node-pyatv/issues/295#issuecomment-1888640079\n if (\n !Object.entries(newState).find(\n ([k, v]) => !['dateTime', 'result'].includes(k) && v !== null,\n )\n ) {\n return;\n }\n\n keys.forEach((key: string) => {\n // @ts-expect-error this.state has no index signature\n const oldValue = this.state[key];\n\n // @ts-expect-error same here\n const newValue = newState[key];\n\n if (\n oldValue === undefined ||\n newValue === undefined ||\n oldValue === newValue\n ) {\n return;\n }\n if (\n key === 'outputDevices' &&\n compareOutputDevices(oldValue, newValue)\n ) {\n return;\n }\n\n const event = new NodePyATVDeviceEvent({\n device: this.device,\n key: key as NodePyATVStateIndex,\n new: newValue,\n old: oldValue,\n });\n\n // @ts-expect-error and here\n this.state[key] = newState[key];\n\n try {\n this.emit('update:' + key, event);\n this.emit('update', event);\n } catch (error) {\n this.emit('error', error);\n }\n });\n }\n\n listenerCount(event?: string | symbol): number {\n if (event !== undefined) {\n return super.listenerCount(event);\n }\n\n return this.eventNames()\n .map((event) => this.listenerCount(event))\n .reduce((a, b) => a + b, 0);\n }\n\n off(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.off(event, listener);\n this.checkListener();\n return this;\n }\n\n on(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.on(event, listener);\n this.checkListener();\n return this;\n }\n\n once(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.once(event, (event: NodePyATVDeviceEvent) => {\n listener(event);\n setTimeout(() => this.checkListener(), 0);\n });\n this.checkListener();\n return this;\n }\n\n prependListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.prependListener(event, listener);\n this.checkListener();\n return this;\n }\n\n removeAllListeners(event?: string | symbol): this {\n super.removeAllListeners(event);\n this.checkListener();\n return this;\n }\n\n removeListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.removeListener(event, listener);\n this.checkListener();\n return this;\n }\n\n protected async stopListening(reqId: string): Promise<void> {\n if (\n this.listenerState !== NodePyATVListenerState.starting &&\n this.listenerState !== NodePyATVListenerState.started\n ) {\n return;\n }\n\n this.listenerState = NodePyATVListenerState.stopping;\n if (this.pyatv === undefined) {\n throw new Error(\n \"Unable to stop listening due to internal error: state is stopping, but there's no child process. \" +\n 'This should never happen, please report this.',\n );\n }\n\n if (this.pyatv.stdin) {\n debug(reqId, 'Pressing enter to close atvscript…', this.options);\n this.pyatv.stdin.write('\\n');\n\n await new Promise((cb) => (this.timeout = setTimeout(cb, 250)));\n }\n\n if (\n this.listenerState === NodePyATVListenerState.stopping &&\n this.pyatv\n ) {\n this.pyatv.kill();\n }\n\n this.listenerState = NodePyATVListenerState.stopped;\n return;\n }\n\n private applyPushUpdate(\n update: NodePyATVInternalState,\n reqId: string,\n ): void {\n try {\n const newState = parseState(update, reqId, this.options);\n this.applyStateAndEmitEvents(newState);\n } catch (error) {\n this.emit('error', error);\n }\n }\n\n private checkListener(): void {\n if (\n this.listenerState === NodePyATVListenerState.stopped &&\n this.listenerCount() === 0 &&\n this.timeout\n ) {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n } else if (\n this.listenerState === NodePyATVListenerState.stopped &&\n this.listenerCount() > 0\n ) {\n const id = addRequestId();\n debug(\n id,\n `Start listeing to events from device ${this.options.name}`,\n this.options,\n );\n\n this.startListening(id);\n removeRequestId(id);\n } else if (\n [\n NodePyATVListenerState.started,\n NodePyATVListenerState.starting,\n ].includes(this.listenerState) &&\n this.listenerCount() === 0\n ) {\n const id = addRequestId();\n debug(\n id,\n `Stop listening to events from device ${this.options.name}`,\n this.options,\n );\n\n this.stopListening(id)\n .catch((error) =>\n debug(\n id,\n `Unable to stop listeing: ${error}`,\n this.options,\n ),\n )\n .finally(() => removeRequestId(id));\n }\n }\n\n private parsePushUpdate(reqId: string, data: string): void {\n let json: NodePyATVInternalState;\n\n try {\n json = JSON.parse(data);\n } catch (error) {\n const msg = `Unable to parse stdout json: ${error}`;\n debug(reqId, msg, this.options);\n this.emit('error', new Error(msg));\n return;\n }\n\n this.applyPushUpdate(json, reqId);\n\n if (this.listenerState === NodePyATVListenerState.starting) {\n this.listenerState = NodePyATVListenerState.started;\n this.checkListener();\n }\n }\n\n private startListening(reqId: string): void {\n if (this.listenerState !== NodePyATVListenerState.stopped) {\n return;\n }\n\n this.listenerState = NodePyATVListenerState.starting;\n\n const listenStart = new Date().getTime();\n const parameters = getParameters(this.options);\n this.pyatv = execute(\n reqId,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'push_updates'],\n this.options,\n );\n if (!this.pyatv) {\n throw new Error(\n 'Unable to start listener: Unable to start atvscript',\n );\n }\n\n const onError = (error: Error) => {\n debug(\n reqId,\n `Got error from child process: ${error}`,\n this.options,\n );\n this.emit('error', error);\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onStdErr = (data: any) => {\n const error = new Error(`Got stderr output from pyatv: ${data}`);\n debug(reqId, data.toString(), this.options);\n this.emit('error', error);\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onStdOut = (data: any) => {\n String(data)\n .split('\\n')\n .map((s) => s.trim())\n .filter(Boolean)\n .forEach((s) => {\n debug(reqId, `> ${s}`, this.options);\n this.parsePushUpdate(reqId, s);\n });\n };\n const onClose = (code: number) => {\n if (this.pyatv === undefined) {\n // this should never happen… :/\n return;\n }\n\n this.listenerState = NodePyATVListenerState.stopped;\n debug(\n reqId,\n `Listening with atvscript exited with code ${code}`,\n this.options,\n );\n if (this.timeout !== undefined) {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n }\n\n if (this.pyatv.stdout) {\n this.pyatv.stdout.off('data', onStdOut);\n }\n if (this.pyatv.stderr) {\n this.pyatv.stderr.off('data', onStdErr);\n }\n this.pyatv.off('error', onError);\n this.pyatv.off('close', onClose);\n\n if (\n this.listenerCount() > 0 &&\n new Date().getTime() - listenStart < 30000\n ) {\n debug(\n reqId,\n `Wait 15s and restart listeing to events from device ${this.options.name}`,\n this.options,\n );\n\n this.timeout = setTimeout(() => {\n this.checkListener();\n }, 15000);\n } else if (this.listenerCount() > 0) {\n debug(\n reqId,\n `Restart listeing to events from device ${this.options.name}`,\n this.options,\n );\n this.checkListener();\n }\n\n removeRequestId(reqId);\n };\n\n this.pyatv.on('error', onError);\n this.pyatv.on('close', onClose);\n\n if (this.pyatv.stdout) {\n this.pyatv.stdout.on('data', onStdOut);\n }\n if (this.pyatv.stderr) {\n this.pyatv.stderr.on('data', onStdErr);\n }\n }\n}\n","'use strict';\n\nimport { ChildProcess, spawn, type SpawnOptions } from 'child_process';\n\nimport { FakeChildProcess } from './fake-spawn.js';\nimport {\n NodePyATVDeviceState,\n NodePyATVExecutableType,\n type NodePyATVFindAndInstanceOptions,\n NodePyATVFocusState,\n type NodePyATVInstanceOptions,\n type NodePyATVInternalState,\n NodePyATVMediaType,\n NodePyATVPowerState,\n NodePyATVRepeatState,\n type NodePyATVRequestOptions,\n NodePyATVShuffleState,\n type NodePyATVState,\n} from './types.js';\n\nconst requestIds: string[] = [];\n\ntype NodePyATVScriptResponse<O extends NodePyATVRequestOptions> =\n O['allowMultipleResponses'] extends true\n ? Record<string, unknown>[]\n : Record<string, unknown>;\n\nexport function addRequestId(): string {\n let id = '?';\n\n for (let i = 0; i < 1000; i += 1) {\n id = Math.round(Math.random() * (i + 6) * 36)\n .toString(36)\n .toUpperCase();\n if (!requestIds.includes(id)) {\n requestIds.push(id);\n break;\n }\n }\n\n return id;\n}\n\nexport function compareOutputDevices(\n a: NodePyATVState['outputDevices'],\n b: NodePyATVState['outputDevices'],\n) {\n return Boolean(\n Array.isArray(a) &&\n Array.isArray(b) &&\n JSON.stringify(\n a.sort((a, b) => (a.identifier < b.identifier ? -1 : 1)),\n ) ===\n JSON.stringify(\n b.sort((a, b) => (a.identifier < b.identifier ? -1 : 1)),\n ),\n );\n}\n\nexport function debug(\n id: string,\n message: string,\n options: NodePyATVInstanceOptions,\n): void {\n if (options.debug) {\n const log =\n typeof options.debug === 'function' ? options.debug : console.log;\n const enableColors = !process.env.NO_COLOR && !options.noColors;\n\n const parts = [\n enableColors ? '\\x1b[0m' : '', // Color Reset\n enableColors ? '\\x1b[90m' : '', // Grey\n '[node-pyatv][',\n enableColors ? '\\x1b[37m' : '', // Light Grey\n id,\n enableColors ? '\\x1b[90m' : '', // Grey\n '] ',\n enableColors ? '\\x1b[0m' : '', // Color Reset\n message,\n ];\n\n log.apply(null, [parts.join('')]);\n }\n}\n\nexport function execute(\n requestId: string,\n executableType: NodePyATVExecutableType,\n parameters: string[],\n options: NodePyATVInstanceOptions,\n): ChildProcess | FakeChildProcess {\n const executable = getExecutable(executableType, options);\n const mySpawn: (\n command: string,\n args: Array<string>,\n options: SpawnOptions,\n ) => ChildProcess | FakeChildProcess =\n typeof options.spawn === 'function' ? options.spawn : spawn;\n\n debug(requestId, `${executable} ${parameters.join(' ')}`, options);\n const child = mySpawn(executable, parameters, {\n env: process.env,\n });\n\n /* eslint-disable @typescript-eslint/no-explicit-any*/\n const onStdOut = (data: any) =>\n debug(requestId, `stdout: ${String(data).trim()}`, options);\n const onStdErr = (data: any) =>\n debug(requestId, `stderr: ${String(data).trim()}`, options);\n const onError = (data: any) =>\n debug(requestId, `error: ${String(data).trim()}`, options);\n /* eslint-enable @typescript-eslint/no-explicit-any*/\n\n const onClose = (code: number) => {\n debug(requestId, `${executable} exited with code: ${code}`, options);\n\n if (child.stdout) {\n child.stdout.off('data', onStdOut);\n }\n if (child.stderr) {\n child.stderr.off('data', onStdErr);\n }\n\n child.off('error', onError);\n child.off('close', onClose);\n };\n\n if (child.stdout) {\n child.stdout.on('data', onStdOut);\n }\n if (child.stderr) {\n child.stderr.on('data', onStdErr);\n }\n\n child.on('error', onError);\n child.on('close', onClose);\n\n return child;\n}\n\nexport function getExecutable(\n executable: NodePyATVExecutableType,\n options: NodePyATVInstanceOptions,\n): string {\n if (\n executable === NodePyATVExecutableType.atvremote &&\n typeof options.atvremotePath === 'string'\n ) {\n return options.atvremotePath;\n } else if (\n executable === NodePyATVExecutableType.atvscript &&\n typeof options.atvscriptPath === 'string'\n ) {\n return options.atvscriptPath;\n } else {\n return executable;\n }\n}\n\nexport function getParameters(\n options: NodePyATVFindAndInstanceOptions = {},\n): string[] {\n const parameters: string[] = [];\n\n if (options.hosts) {\n parameters.push('-s', options.hosts.join(','));\n } else if (options.host) {\n parameters.push('-s', options.host);\n }\n if (options.id) {\n parameters.push('-i', options.id);\n }\n if (options.protocol) {\n parameters.push('--protocol', options.protocol);\n }\n if (options.dmapCredentials) {\n parameters.push('--dmap-credentials', options.dmapCredentials);\n }\n if (options.mrpCredentials) {\n parameters.push('--mrp-credentials', options.mrpCredentials);\n }\n if (options.airplayCredentials) {\n parameters.push('--airplay-credentials', options.airplayCredentials);\n }\n if (options.companionCredentials) {\n parameters.push(\n '--companion-credentials',\n options.companionCredentials,\n );\n }\n if (options.raopCredentials) {\n parameters.push('--raop-credentials', options.raopCredentials);\n }\n\n return parameters;\n}\nexport function parseState(\n input: NodePyATVInternalState,\n id: string,\n options: NodePyATVInstanceOptions,\n): NodePyATVState {\n const d = (msg: string) => debug(id, msg, options);\n const result: NodePyATVState = {\n album: null,\n app: null,\n appId: null,\n artist: null,\n contentIdentifier: null,\n dateTime: null,\n deviceState: null,\n episodeNumber: null,\n focusState: null,\n genre: null,\n hash: null,\n iTunesStoreIdentifier: null,\n mediaType: null,\n outputDevices: null,\n position: null,\n powerState: null,\n repeat: null,\n seasonNumber: null,\n seriesName: null,\n shuffle: null,\n title: null,\n totalTime: null,\n volume: null,\n };\n if (!input || typeof input !== 'object') {\n return result;\n }\n if (input.exception) {\n let errorStr = 'Got pyatv Error: ' + input.exception;\n if (input.stacktrace) {\n errorStr += '\\n\\npyatv Stacktrace:\\n' + input.stacktrace;\n }\n\n throw new Error(errorStr);\n }\n\n // datetime\n if (typeof input.datetime === 'string') {\n const date = new Date(input.datetime);\n if (!isNaN(date.getTime())) {\n result.dateTime = date;\n } else {\n d(`Invalid datetime value ${input.datetime}, ignore attribute`);\n }\n } else {\n d(`No datetime value found in input (${JSON.stringify(input)})`);\n }\n\n // hash\n parseStateStringAttr(input, result, 'hash', 'hash', d);\n\n // mediaType\n if (typeof input.media_type === 'string') {\n const validValues = Object.keys(NodePyATVMediaType).map((o) =>\n String(o),\n );\n if (validValues.includes(input.media_type)) {\n result.mediaType =\n NodePyATVMediaType[input.media_type as NodePyATVMediaType];\n } else {\n d(\n `Unsupported mediaType value ${input.media_type}, ignore attribute`,\n );\n }\n } else {\n d(`No mediaType value found in input (${JSON.stringify(input)})`);\n }\n\n // deviceState\n if (typeof input.device_state === 'string') {\n const validValues = Object.keys(NodePyATVDeviceState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.device_state)) {\n result.deviceState =\n NodePyATVDeviceState[\n input.device_state as NodePyATVDeviceState\n ];\n } else {\n d(\n `Unsupported deviceState value ${input.device_state}, ignore attribute`,\n );\n }\n } else {\n d(`No deviceState value found in input (${JSON.stringify(input)})`);\n }\n\n // title\n parseStateStringAttr(input, result, 'title', 'title', d);\n\n // artist\n parseStateStringAttr(input, result, 'artist', 'artist', d);\n\n // album\n parseStateStringAttr(input, result, 'album', 'album', d);\n\n // genre\n parseStateStringAttr(input, result, 'genre', 'genre', d);\n\n // totalTime\n parseStateNumberAttr(input, result, 'total_time', 'totalTime', d);\n\n // position\n parseStateNumberAttr(input, result, 'position', 'position', d);\n\n // shuffle\n if (typeof input.shuffle === 'string') {\n const validValues = Object.keys(NodePyATVShuffleState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.shuffle)) {\n result.shuffle =\n NodePyATVShuffleState[input.shuffle as NodePyATVShuffleState];\n } else {\n d(`Unsupported shuffle value ${input.shuffle}, ignore attribute`);\n }\n } else {\n d(`No shuffle value found in input (${JSON.stringify(input)})`);\n }\n\n // repeat\n if (typeof input.repeat === 'string') {\n const validValues = Object.keys(NodePyATVRepeatState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.repeat)) {\n result.repeat =\n NodePyATVRepeatState[input.repeat as NodePyATVRepeatState];\n } else {\n d(`Unsupported repeat value ${input.repeat}, ignore attribute`);\n }\n } else {\n d(`No repeat value found in input (${JSON.stringify(input)})`);\n }\n\n // app\n parseStateStringAttr(input, result, 'app', 'app', d);\n parseStateStringAttr(input, result, 'app_id', 'appId', d);\n\n // powerState\n if (typeof input.power_state === 'string') {\n const validValues = Object.keys(NodePyATVPowerState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.power_state)) {\n result.powerState =\n NodePyATVPowerState[input.power_state as NodePyATVPowerState];\n } else {\n d(\n `Unsupported powerState value ${input.power_state}, ignore attribute`,\n );\n }\n } else {\n d(`No powerState value found in input (${JSON.stringify(input)})`);\n }\n\n // volume\n parseStateNumberAttr(input, result, 'volume', 'volume', d);\n\n // focusState\n if (typeof input.focus_state === 'string') {\n const validValues = Object.keys(NodePyATVFocusState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.focus_state)) {\n result.focusState =\n NodePyATVFocusState[input.focus_state as NodePyATVFocusState];\n } else {\n d(\n `Unsupported focusState value ${input.focus_state}, ignore attribute`,\n );\n }\n } else {\n d(`No focusState value found in input (${JSON.stringify(input)})`);\n }\n\n // outputDevices\n if (Array.isArray(input.output_devices)) {\n result.outputDevices = input.output_devices;\n }\n\n // contentIdentifier\n parseStateStringAttr(\n input,\n result,\n 'content_identifier',\n 'contentIdentifier',\n d,\n );\n\n // iTunesStoreIdentifier\n parseStateNumberAttr(\n input,\n result,\n 'itunes_store_identifier',\n 'iTunesStoreIdentifier',\n d,\n );\n\n // episodeNumber\n parseStateNumberAttr(input, result, 'episode_number', 'episodeNumber', d);\n\n // seasonNumber\n parseStateNumberAttr(input, result, 'season_number', 'seasonNumber', d);\n\n // seriesName\n parseStateStringAttr(input, result, 'series_name', 'seriesName', d);\n\n return result;\n}\nexport function removeRequestId(id: string | undefined): void {\n if (id && requestIds.includes(id)) {\n requestIds.splice(requestIds.indexOf(id), 1);\n }\n}\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType.atvscript,\n parameters: string[],\n options: O,\n): Promise<NodePyATVScriptResponse<O>>;\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType.atvremote,\n parameters: string[],\n options: O,\n): Promise<string>;\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType,\n parameters: string[],\n options: O,\n): Promise<Record<string, unknown> | Record<string, unknown>[] | string> {\n const result = {\n code: 0,\n stderr: '',\n stdout: '',\n };\n\n await new Promise((resolve, reject) => {\n const pyatv = execute(requestId, executableType, parameters, options);\n\n /* eslint-disable @typescript-eslint/no-explicit-any*/\n const onStdOut = (data: any) => (result.stdout += String(data).trim());\n const onStdErr = (data: any) => (result.stderr += String(data).trim());\n const onError = (data: any) =>\n reject(data instanceof Error ? data : new Error(String(data)));\n /* eslint-enable @typescript-eslint/no-explicit-any*/\n\n const onClose: (code: number) => void = (code: number) => {\n result.code = code;\n\n if (pyatv.stdout) {\n pyatv.stdout.off('data', onStdOut);\n }\n if (pyatv.stderr) {\n pyatv.stderr.off('data', onStdErr);\n }\n\n pyatv.off('error', onError);\n pyatv.off('close', onClose);\n resolve(undefined);\n };\n\n if (pyatv.stdout) {\n pyatv.stdout.on('data', onStdOut);\n }\n if (pyatv.stderr) {\n pyatv.stderr.on('data', onStdErr);\n }\n\n pyatv.on('error', onError);\n pyatv.on('close', onClose);\n });\n\n if (result.stderr.length > 0) {\n const msg = `Unable to execute request ${requestId}: ${result.stderr}`;\n debug(requestId, msg, options);\n throw new Error(msg);\n }\n\n if (executableType === NodePyATVExecutableType.atvscript) {\n try {\n // response with multiple lines\n // https://github.com/sebbo2002/node-pyatv/issues/324\n if (options.allowMultipleResponses) {\n return result.stdout\n .split('\\n')\n .filter((line) => line.trim().length > 0)\n .map((line) => JSON.parse(line));\n }\n\n return JSON.parse(result.stdout);\n } catch (error) {\n const msg = `Unable to parse result ${requestId} json: ${error}`;\n debug(requestId, msg, options);\n throw new Error(msg);\n }\n }\n\n return result.stdout;\n}\n\nfunction parseStateNumberAttr(\n input: NodePyATVInternalState,\n output: NodePyATVState,\n inputAttr:\n | 'episode_number'\n | 'itunes_store_identifier'\n | 'position'\n | 'season_number'\n | 'total_time'\n | 'volume',\n outputAttr:\n | 'episodeNumber'\n | 'iTunesStoreIdentifier'\n | 'position'\n | 'seasonNumber'\n | 'totalTime'\n | 'volume',\n d: (msg: string) => void,\n): void {\n if (typeof input[inputAttr] === 'number') {\n output[outputAttr] = input[inputAttr];\n return;\n }\n\n d(`No ${outputAttr} value found in input (${JSON.stringify(input)})`);\n}\n\nfunction parseStateStringAttr(\n input: NodePyATVInternalState,\n output: NodePyATVState,\n inputAttr:\n | 'album'\n | 'app'\n | 'app_id'\n | 'artist'\n | 'content_identifier'\n | 'genre'\n | 'hash'\n | 'series_name'\n | 'title',\n outputAttr:\n | 'album'\n | 'app'\n | 'appId'\n | 'artist'\n | 'contentIdentifier'\n | 'genre'\n | 'hash'\n | 'seriesName'\n | 'title',\n d: (msg: string) => void,\n): void {\n if (typeof input[inputAttr] === 'string') {\n output[outputAttr] = input[inputAttr] as string;\n return;\n }\n\n d(`No ${outputAttr} value found in input (${JSON.stringify(input)})`);\n}\n","import { ChildProcess, type SpawnOptions } from 'child_process';\n\nimport type NodePyATVDevice from './device.js';\n\nimport { FakeChildProcess } from './fake-spawn.js';\n\nexport enum NodePyATVDeviceState {\n idle = 'idle',\n loading = 'loading',\n paused = 'paused',\n playing = 'playing',\n seeking = 'seeking',\n stopped = 'stopped',\n}\n\nexport enum NodePyATVExecutableType {\n atvremote = 'atvremote',\n atvscript = 'atvscript',\n}\n\nexport enum NodePyATVFocusState {\n // @deprecated Please use `NodePyATVFocusState.focused` instead\n focued = 'focused',\n\n // Doublicate enum value due to typo, will be removed in next breaking change\n // @todo remove in next breaking change\n // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values\n focused = 'focused',\n\n unfocused = 'unfocused',\n}\n\n/**\n * @internal\n */\nexport enum NodePyATVInternalKeys {\n down = 'down',\n home = 'home',\n homeHold = 'home_hold',\n left = 'left',\n menu = 'menu',\n next = 'next',\n pause = 'pause',\n play = 'play',\n playPause = 'play_pause',\n previous = 'previous',\n right = 'right',\n select = 'select',\n skipBackward = 'skip_backward',\n skipForward = 'skip_forward',\n stop = 'stop',\n suspend = 'suspend',\n topMenu = 'top_menu',\n turnOff = 'turn_off',\n turnOn = 'turn_on',\n up = 'up',\n volumeDown = 'volume_down',\n volumeUp = 'volume_up',\n wakeup = 'wakeup',\n}\n\nexport enum NodePyATVKeys {\n down = 'down',\n home = 'home',\n homeHold = 'homeHold',\n left = 'left',\n menu = 'menu',\n next = 'next',\n pause = 'pause',\n play = 'play',\n playPause = 'playPause',\n previous = 'previous',\n right = 'right',\n select = 'select',\n skipBackward = 'skipBackward',\n skipForward = 'skipForward',\n stop = 'stop',\n suspend = 'suspend',\n topMenu = 'topMenu',\n turnOff = 'turnOff',\n turnOn = 'turnOn',\n up = 'up',\n volumeDown = 'volumeDown',\n volumeUp = 'volumeUp',\n wakeup = 'wakeup',\n}\n\nexport enum NodePyATVListenerState {\n stopped,\n starting,\n started,\n stopping,\n}\n\nexport enum NodePyATVMediaType {\n music = 'music',\n tv = 'tv',\n unknown = 'unknown',\n video = 'video',\n}\n\nexport enum NodePyATVPowerState {\n off = 'off',\n on = 'on',\n}\n\nexport enum NodePyATVProtocol {\n airplay = 'airplay',\n dmap = 'dmap',\n mdns = 'mdns',\n mrp = 'mrp',\n}\n\nexport enum NodePyATVRepeatState {\n all = 'all',\n off = 'off',\n track = 'track',\n}\n\nexport enum NodePyATVShuffleState {\n albums = 'albums',\n off = 'off',\n songs = 'songs',\n}\n\nexport interface NodePyATVApp {\n id: string;\n launch: () => Promise<void>;\n name: string;\n}\n\nexport interface NodePyATVDeviceOptions\n extends NodePyATVFindAndInstanceOptions {\n allIDs?: string[];\n host?: string;\n mac?: string;\n model?: string;\n modelName?: string;\n name: string;\n os?: string;\n services?: NodePyATVService[];\n version?: string;\n}\n\nexport type NodePyATVEventValueType =\n | NodePyATVDeviceState\n | NodePyATVMediaType\n | NodePyATVRepeatState\n | NodePyATVShuffleState\n | number\n | string;\n\nexport interface NodePyATVFindAndInstanceOptions\n extends NodePyATVFindOptions,\n NodePyATVInstanceOptions {}\n\nexport interface NodePyATVFindOptions {\n airplayCredentials?: string;\n companionCredentials?: string;\n dmapCredentials?: string;\n host?: string;\n hosts?: string[];\n id?: string;\n mrpCredentials?: string;\n protocol?: NodePyATVProtocol;\n raopCredentials?: string;\n}\n\nexport interface NodePyATVFindResponseObject {\n devices: NodePyATVDevice[];\n errors: Record<string, unknown>[];\n}\n\nexport interface NodePyATVGetStateOptions {\n maxAge?: number;\n}\n\nexport interface NodePyATVInstanceOptions {\n atvremotePath?: string;\n atvscriptPath?: string;\n debug?: ((msg: string) => void) | true;\n noColors?: true;\n spawn?: (\n command: string,\n args: Array<string>,\n options: SpawnOptions,\n ) => ChildProcess | FakeChildProcess;\n}\n\n/**\n * @internal\n */\nexport interface NodePyATVInternalScanDevice {\n address: string;\n all_identifiers: string[];\n device_info?: {\n mac: null | string;\n model: string;\n model_str: string;\n operating_system: string;\n version: string;\n };\n identifier: string;\n name: string;\n services?: NodePyATVService[];\n}\n\n/**\n * @internal\n */\nexport interface NodePyATVInternalState {\n album?: string | unknown;\n app?: string | unknown;\n app_id?: string | unknown;\n artist?: string | unknown;\n connection?: string | unknown;\n content_identifier?: null | string;\n datetime?: string | unknown;\n device_state?: string | unknown;\n episode_number?: null | number;\n exception?: string | unknown;\n focus_state?: string | unknown;\n genre?: string | unknown;\n hash?: string | unknown;\n itunes_store_identifier?: null | number;\n media_type?: string | unknown;\n output_devices?: Array<{ identifier: string; name: string }> | null;\n position?: 1 | unknown;\n power_state?: string | unknown;\n push_updates?: string | unknown;\n repeat?: string | unknown;\n result?: string | unknown;\n season_number?: null | number;\n series_name?: null | string;\n shuffle?: string | unknown;\n stacktrace?: string | unknown;\n title?: string | unknown;\n total_time?: number | unknown;\n volume?: number | unknown;\n}\n\nexport interface NodePyATVRequestOptions extends NodePyATVInstanceOptions {\n allowMultipleResponses?: boolean;\n}\n\nexport interface NodePyATVService {\n port: number;\n protocol: NodePyATVProtocol;\n}\n\nexport interface NodePyATVState {\n album: null | string;\n app: null | string;\n appId: null | string;\n artist: null | string;\n contentIdentifier: null | string;\n dateTime: Date | null;\n deviceState: NodePyATVDeviceState | null;\n episodeNumber: null | number;\n focusState: NodePyATVFocusState | null;\n genre: null | string;\n hash: null | string;\n iTunesStoreIdentifier: null | number;\n mediaType: NodePyATVMediaType | null;\n outputDevices: Array<{ identifier: string; name: string }> | null;\n position: null | number;\n powerState: NodePyATVPowerState | null;\n repeat: NodePyATVRepeatState | null;\n seasonNumber: null | number;\n seriesName: null | string;\n shuffle: NodePyATVShuffleState | null;\n title: null | string;\n totalTime: null | number;\n volume: null | number;\n}\n\nexport type NodePyATVStateIndex = keyof NodePyATVState;\n\nexport interface NodePyATVVersionResponse {\n module: null | string;\n pyatv: null | string;\n}\n","'use strict';\n\nimport { EventEmitter } from 'events';\n\nimport { NodePyATVDeviceEvent, NodePyATVDeviceEvents } from '../lib/index.js';\nimport {\n addRequestId,\n getParameters,\n parseState,\n removeRequestId,\n request,\n} from './tools.js';\nimport {\n type NodePyATVApp,\n type NodePyATVDeviceOptions,\n NodePyATVDeviceState,\n NodePyATVExecutableType,\n NodePyATVFocusState,\n type NodePyATVGetStateOptions,\n NodePyATVInternalKeys,\n NodePyATVKeys,\n NodePyATVMediaType,\n NodePyATVPowerState,\n NodePyATVProtocol,\n NodePyATVRepeatState,\n type NodePyATVService,\n NodePyATVShuffleState,\n type NodePyATVState,\n} from './types.js';\n\n/**\n * Represents an Apple TV. Use [[getState]] to query the current state (e.g. media\n * type and title). You can also use the attribute methods (e.g. [[getTitle]] to get\n * the state. If you want realtime updates, subscribe to it's events with an\n * `EventEmitter` like API, so for example by using [[on]], [[once]] or [[addListener]].\n * It's also possible to send key commands by using [[pressKey]] or methods like [[pause]].\n */\nexport default class NodePyATVDevice implements EventEmitter {\n /**\n * Get all IDs of the Apple TV.\n * Requires pyatv >= 0.14.5.\n */\n get allIDs(): string[] | undefined {\n return this.options.allIDs;\n }\n /**\n * Returns true, if debugging is enabled. Returns the custom\n * logging method, if one was specified. Otherwise, if debug\n * log is disabled, returns undefined.\n */\n get debug(): ((msg: string) => void) | true | undefined {\n return this.options.debug;\n }\n /**\n * Enable or disable debugging or set a custom\n * debugging method to use.\n *\n * @param debug\n */\n set debug(debug: ((msg: string) => void) | true | undefined) {\n if (typeof debug === 'function') {\n this.options.debug = debug;\n } else {\n this.options.debug = Boolean(debug) || undefined;\n }\n }\n\n /**\n * Get the IP address of the Apple TV.\n */\n get host(): string | undefined {\n return this.options.host;\n }\n\n /**\n * Get the ID of the Apple TV.\n */\n get id(): string | undefined {\n return this.options.id;\n }\n\n /**\n * Get the MAC address of the Apple TV.\n * Requires pyatv >= 0.14.5.\n */\n get mac(): string | undefined {\n return this.options.mac;\n }\n\n /**\n * Get the model identifier of the device. Only set, if the\n * device was found using [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.model → \"Gen4K\"\n */\n get model(): string | undefined {\n return this.options.model;\n }\n\n /**\n * Get the model name of the device. Only set, if the device\n * was found with [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.modelName → \"Apple TV 4K\"\n */\n get modelName(): string | undefined {\n return this.options.modelName;\n }\n\n /**\n * Get the name of the Apple TV.\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const devices = await pyatv.find();\n * devices.forEach(device =>\n * console.log(device.name)\n * );\n * ```\n */\n get name(): string {\n return this.options.name;\n }\n\n /**\n * Get the operating system of the device. Only set, if the\n * device was found with [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.os → \"TvOS\"\n */\n get os(): string | undefined {\n return this.options.os;\n }\n\n /**\n * Get the used protocol to connect to the Apple TV.\n */\n get protocol(): NodePyATVProtocol | undefined {\n return this.options.protocol;\n }\n\n /**\n * Returns a list of services supported by the device. Ony set, if\n * the device was found during a scan using [[find()]]. Requires\n * pyatv ≧ 0.10.3.\n *\n * @example device.services → [\n * {\n * \"protocol\": \"airplay\",\n * \"port\": 7000\n * },\n * {\n * \"protocol\": \"dmap\",\n * \"port\": 3689\n * }\n * ]\n */\n get services(): NodePyATVService[] | undefined {\n return this.options.services;\n }\n\n /**\n * Get the device version. Only set, if the device was found\n * during a scan using [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.version → \"15.5.1\"\n */\n get version(): string | undefined {\n return this.options.version;\n }\n\n private readonly events: NodePyATVDeviceEvents;\n\n private readonly options: NodePyATVDeviceOptions;\n\n private readonly state: NodePyATVState;\n\n constructor(options: NodePyATVDeviceOptions) {\n if (!options.host && !options.id && !options.mac) {\n throw new Error('Either host, id or mac must be set!');\n }\n\n this.options = Object.assign({}, options);\n this.state = parseState({}, '', {});\n this.events = new NodePyATVDeviceEvents(this.state, this, this.options);\n\n // @todo basic validation\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * @param event\n * @param listener\n * @category Event\n */\n addListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n this.events.addListener(event, listener);\n return this;\n }\n\n /**\n * Removes the state node-pyatv cached for this device.\n *\n * @category State\n */\n clearState(): void {\n this.applyState(parseState({}, '', {}));\n }\n\n /**\n * Send the \"down\" command\n * @category Control\n */\n async down(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.down);\n }\n\n /**\n * Emit an event.\n * @param event\n * @param payload\n * @category Event\n */\n emit(event: string | symbol, payload: NodePyATVDeviceEvent): boolean {\n return this.events.emit(event, payload);\n }\n\n /**\n * Get all event names which are currently known.\n * @category Event\n */\n eventNames(): Array<string | symbol> {\n return this.events.eventNames();\n }\n\n /**\n * Returns the album of the current playing media\n * @param options\n * @category State\n */\n async getAlbum(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.album;\n }\n\n /**\n * Returns the currently used app\n * @param options\n * @category State\n */\n async getApp(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.app;\n }\n\n /**\n * Returns the id of the currently used app\n * @param options\n * @category State\n */\n async getAppId(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.appId;\n }\n\n /**\n * Returns the artist of the current playing media\n * @param options\n * @category State\n */\n async getArtist(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.artist;\n }\n\n /**\n * Returns the app specific content identifier\n * @param options\n * @category State\n */\n async getContentIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n return this.getState(options).then((state) => state.contentIdentifier);\n }\n\n /**\n * Get the date and time when the state was last updated.\n * @param options\n * @category State\n */\n async getDateTime(\n options: NodePyATVGetStateOptions = {},\n ): Promise<Date | null> {\n const state = await this.getState(options);\n return state.dateTime;\n }\n\n /**\n * Get the state of this device (e.g. playing, etc.)\n * @param options\n * @category State\n */\n async getDeviceState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVDeviceState | null> {\n const state = await this.getState(options);\n return state.deviceState;\n }\n\n /**\n * Returns the episode number.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getEpisodeNumber(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.episodeNumber);\n }\n\n /**\n * Returns the current focus state of the device\n * @param options\n * @category State\n */\n async getFocusState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVFocusState | null> {\n return this.getState(options).then((state) => state.focusState);\n }\n\n /**\n * Returns the genre of the current playing media\n * @param options\n * @category State\n */\n async getGenre(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.genre;\n }\n\n /**\n * Get the hash of the current media\n * @param options\n * @category State\n */\n async getHash(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.hash;\n }\n\n /**\n * Returns the iTunes Store identifier if available.\n * Requires pyatv >= 0.16.0\n * @param options\n * @category State\n * @alias getiTunesStoreIdentifier\n */\n async getITunesStoreIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then(\n (state) => state.iTunesStoreIdentifier,\n );\n }\n\n async getiTunesStoreIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getITunesStoreIdentifier(options);\n }\n\n /**\n * Get max number of listeners allowed\n * @category Event\n */\n getMaxListeners(): number {\n return this.events.getMaxListeners();\n }\n\n /**\n * Get the media type of the current media\n * @param options\n * @category State\n */\n async getMediaType(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVMediaType | null> {\n const state = await this.getState(options);\n return state.mediaType;\n }\n\n /**\n * Returns the current output devices of the device\n * @param options\n * @category State\n */\n async getOutputDevices(\n options: NodePyATVGetStateOptions = {},\n ): Promise<Array<{ identifier: string; name: string }> | null> {\n return this.getState(options).then((state) => state.outputDevices);\n }\n\n /**\n * Returns the title of the current playing media\n * @param options\n * @category State\n */\n async getPosition(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n const state = await this.getState(options);\n return state.position;\n }\n\n /**\n * Returns the current power state (= is it on or off, see [[NodePyATVPowerState]]) of the device.\n * @param options\n * @category State\n */\n async getPowerState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVPowerState | null> {\n return this.getState(options).then((state) => state.powerState);\n }\n\n /**\n * Returns the repeat state\n * @param options\n * @category State\n */\n async getRepeat(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVRepeatState | null> {\n const state = await this.getState(options);\n return state.repeat;\n }\n\n /**\n * Returns the season number.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getSeasonNumber(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.seasonNumber);\n }\n /**\n * Returns the season name.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getSeriesName(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n return this.getState(options).then((state) => state.seriesName);\n }\n\n /**\n * Returns the shuffle state\n * @param options\n * @category State\n */\n async getShuffle(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVShuffleState | null> {\n const state = await this.getState(options);\n return state.shuffle;\n }\n\n /**\n * Returns an [[NodePyATVState]] object representing the current state\n * of the device. Has an internal cache, which has a default TTL of 5s.\n * You can change this default value by passing the `maxAge` option.\n *\n * ```typescript\n * await device.getState({maxAge: 10000}); // cache TTL: 10s\n * ```\n *\n * @param options\n * @category State\n */\n async getState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVState> {\n if (\n this.state?.dateTime &&\n new Date().getTime() - this.state.dateTime.getTime() <\n (options.maxAge || 5000)\n ) {\n let position = null;\n if (this.state.position && this.state.dateTime) {\n position = Math.round(\n this.state.position +\n (new Date().getTime() - this.state.dateTime.getTime()) /\n 1000,\n );\n }\n\n return Object.assign({}, this.state, { position });\n }\n\n const id = addRequestId();\n\n try {\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'playing'],\n this.options,\n );\n const newState = parseState(result, id, this.options);\n\n this.applyState(newState);\n return newState;\n } finally {\n removeRequestId(id);\n }\n }\n\n /**\n * Returns the title of the current playing media\n * @param options\n * @category State\n */\n async getTitle(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.title;\n }\n\n /**\n * Returns the media length of the current playing media\n * @param options\n * @category State\n */\n async getTotalTime(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n const state = await this.getState(options);\n return state.totalTime;\n }\n\n /**\n * Returns the current volume of the device in percent (0 - 100)\n * @param options\n * @category State\n */\n async getVolume(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.volume);\n }\n\n /**\n * Send the \"home\" command\n * @category Control\n */\n async home(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.home);\n }\n\n /**\n * Send the \"homeHold\" command\n * @category Control\n */\n async homeHold(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.homeHold);\n }\n\n /**\n * Launch an application. Probably requires `companionCredentials`, see\n * https://pyatv.dev/documentation/atvremote/#apps for more details.\n * @param id App identifier, e.g. `com.netflix.Netflix`\n */\n async launchApp(id: string): Promise<void> {\n await this._pressKeyWithRemote('launch_app=' + id);\n }\n\n /**\n * Send the \"left\" command\n * @category Control\n */\n async left(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.left);\n }\n\n /**\n * Returns the list of installed apps on the Apple TV. Probably requires `companionCredentials`,\n * see https://pyatv.dev/documentation/atvremote/#apps for more details.\n */\n async listApps(): Promise<NodePyATVApp[]> {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvremote,\n [...parameters, 'app_list'],\n this.options,\n );\n if (typeof result !== 'string' || !result.startsWith('App: ')) {\n throw new Error('Unexpected atvremote response: ' + result);\n }\n\n removeRequestId(id);\n const regex = /(.+) \\(([^)]+)\\)$/i;\n const items = result\n .substring(5)\n .split(', App: ')\n .map((i) => {\n const m = i.match(regex);\n if (m !== null) {\n return {\n id: m[2],\n launch: () => this.launchApp(m[2]),\n name: m[1],\n };\n }\n }) as Array<NodePyATVApp | undefined>;\n\n return items.filter(Boolean) as NodePyATVApp[];\n }\n\n /**\n * Get number of listeners for event\n * @param event\n * @category Event\n */\n listenerCount(event: string | symbol): number {\n return this.events.listenerCount(event);\n }\n\n /**\n * Get listeners for event. Will also return\n * node-pyatv wrappers (e.g. once)\n *\n * @param event\n * @category Event\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n listeners(event: string | symbol): Function[] {\n return this.events.listeners(event);\n }\n\n /**\n * Send the \"menu\" command\n * @category Control\n */\n async menu(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.menu);\n }\n\n /**\n * Send the \"next\" command\n * @category Control\n */\n async next(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.next);\n }\n\n /**\n * Remove an event listener. Will stop the event subscription with the\n * Apple TV if this was the last event listener.\n * @param event\n * @param listener\n * @category Event\n */\n off(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.off(event, listener);\n return this;\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * @param event\n * @param listener\n * @category Event\n */\n on(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.on(event, listener);\n return this;\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * Removes the listener automatically after the first occurrence.\n * @param event\n * @param listener\n * @category Event\n */\n once(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.once(event, listener);\n return this;\n }\n\n /**\n * Send the \"pause\" command\n * @category Control\n */\n async pause(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.pause);\n }\n\n /**\n * Send the \"play\" command\n * @category Control\n */\n async play(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.play);\n }\n\n /**\n * Send the \"playPause\" command\n * @category Control\n */\n async playPause(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.playPause);\n }\n\n /**\n * @param event\n * @param listener\n * @category Event\n */\n prependListener(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.prependListener(event, listener);\n return this;\n }\n\n /**\n * @param event\n * @param listener\n * @category Event\n */\n prependOnceListener(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.prependOnceListener(event, listener);\n return this;\n }\n\n /**\n * Send a key press to the Apple TV\n *\n * ```typescript\n * await device.pressKey(NodePyATVKeys.home);\n * ```\n *\n * <br />\n *\n * ```javascript\n * await device.pressKey('home');\n * ```\n *\n * @param key\n * @category Control\n */\n async pressKey(key: NodePyATVKeys): Promise<void> {\n const internalKeyEntry = Object.entries(NodePyATVInternalKeys).find(\n ([k]) => key === k,\n );\n\n if (!internalKeyEntry) {\n throw new Error(`Unsupported key value ${key}!`);\n }\n\n const internalKey = internalKeyEntry[1];\n if ([NodePyATVKeys.turnOff, NodePyATVKeys.turnOn].includes(key)) {\n await this._pressKeyWithRemote(internalKey);\n } else {\n await this._pressKeyWithScript(internalKey);\n }\n }\n\n /**\n * Send the \"previous\" command\n * @category Control\n */\n async previous(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.previous);\n }\n\n /**\n * @param event\n * @category Event\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n rawListeners(event: string | symbol): Function[] {\n return this.events.rawListeners(event);\n }\n\n /**\n * Removes all listeners, either for the given event or\n * for every event. Will stop the event subscription with\n * the Apple TV if this was the last event listener.\n *\n * @param event\n * @category Event\n */\n removeAllListeners(event?: string | symbol): this {\n this.events.removeAllListeners(event);\n return this;\n }\n\n /**\n * Remove an event listener. Will stop the event subscription with the\n * Apple TV if this was the last event listener.\n * @param event\n * @param listener\n * @category Event\n */\n removeListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n this.events.removeListener(event, listener);\n return this;\n }\n\n /**\n * Send the \"right\" command\n * @category Control\n */\n async right(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.right);\n }\n\n /**\n * Send the \"select\" command\n * @category Control\n */\n async select(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.select);\n }\n\n /**\n * @param n\n * @category Event\n */\n setMaxListeners(n: number): this {\n this.events.setMaxListeners(n);\n return this;\n }\n\n /**\n * Send the \"skipBackward\" command\n * @category Control\n */\n async skipBackward(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.skipBackward);\n }\n\n /**\n * Send the \"skipForward\" command\n * @category Control\n */\n async skipForward(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.skipForward);\n }\n\n /**\n * Send the \"stop\" command\n * @category Control\n */\n async stop(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.stop);\n }\n\n /**\n * Send the \"suspend\" command\n * @category Control\n * @deprecated\n */\n async suspend(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.suspend);\n }\n\n /**\n * Returns an object with `name`, `host`, `mac`, `id` and `protocol`.\n * Can be used to initiate a new device instance.\n *\n * @category Basic\n */\n toJSON(): Pick<\n NodePyATVDeviceOptions,\n 'host' | 'id' | 'mac' | 'name' | 'protocol'\n > {\n return {\n host: this.host,\n id: this.id,\n mac: this.mac,\n name: this.name,\n protocol: this.protocol,\n };\n }\n\n /**\n * Send the \"topMenu\" command\n * @category Control\n */\n async topMenu(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.topMenu);\n }\n\n /**\n * Returns a string. Just for debugging, etc.\n *\n * @category Basic\n */\n toString(): string {\n return `NodePyATVDevice(${this.name}, ${this.host})`;\n }\n\n /**\n * Send the \"turn_off\" command\n * @category Control\n */\n async turnOff(): Promise<void> {\n await this._pressKeyWithRemote(NodePyATVInternalKeys.turnOff);\n }\n\n /**\n * Send the \"turn_on\" command\n * @category Control\n */\n async turnOn(): Promise<void> {\n await this._pressKeyWithRemote(NodePyATVInternalKeys.turnOn);\n }\n\n /**\n * Send the \"up\" command\n * @category Control\n */\n async up(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.up);\n }\n\n /**\n * Send the \"volumeDown\" command\n * @category Control\n */\n async volumeDown(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.volumeDown);\n }\n\n /**\n * Send the \"volumeUp\" command\n * @category Control\n */\n async volumeUp(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.volumeUp);\n }\n\n /**\n * Send the \"wakeup\" command\n * @category Control\n * @deprecated\n */\n async wakeup(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.wakeup);\n }\n\n private async _pressKeyWithRemote(key: NodePyATVInternalKeys | string) {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n await request(\n id,\n NodePyATVExecutableType.atvremote,\n [...parameters, key],\n this.options,\n );\n removeRequestId(id);\n }\n\n private async _pressKeyWithScript(key: NodePyATVInternalKeys | string) {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, key],\n this.options,\n );\n if (typeof result !== 'object' || result.result !== 'success') {\n throw new Error(\n `Unable to parse pyatv response: ${JSON.stringify(result, null, ' ')}`,\n );\n }\n\n removeRequestId(id);\n }\n\n private applyState(newState: NodePyATVState): void {\n this.events.applyStateAndEmitEvents(newState);\n }\n}\n","'use strict';\n\nimport { promises as fsPromises } from 'fs';\nimport { dirname, join } from 'path';\nimport semver from 'semver';\nimport { fileURLToPath } from 'url';\n\nimport { NodePyATVDevice } from '../lib/index.js';\nimport {\n addRequestId,\n debug,\n getParameters,\n removeRequestId,\n request,\n} from './tools.js';\nimport {\n type NodePyATVDeviceOptions,\n NodePyATVExecutableType,\n type NodePyATVFindAndInstanceOptions,\n type NodePyATVFindResponseObject,\n type NodePyATVInstanceOptions,\n type NodePyATVInternalScanDevice,\n type NodePyATVVersionResponse,\n} from './types.js';\n\n/**\n * Default class exported by `@sebbo2002/node-pyatv`. Use [[find]] to scan for devices in your local network. Use\n * [[device]] to connect to a known device by passing (at least) it's name and IP.\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * ```\n */\nexport default class NodePyATVInstance {\n private readonly options: NodePyATVInstanceOptions = {};\n\n /**\n * Use this to apply [[NodePyATVInstanceOptions]]\n * (e.g. debug log method) to all further requests\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const myPyatv = new pyatv({debug: true});\n * const devices = myPyatv.find();\n * console.log(devices);\n * ```\n * @param options\n */\n public constructor(options: NodePyATVInstanceOptions = {}) {\n this.options = Object.assign({}, options);\n }\n\n /**\n * Checks if pyatv is installed and ready to be used.\n * Will throw an error if not.\n *\n * @param options\n */\n public static async check(\n options: NodePyATVInstanceOptions = {},\n ): Promise<void> {\n const versions = await this.version(options);\n if (!versions.pyatv) {\n throw new Error('Unable to find pyatv. Is it installed?');\n }\n if (semver.lt(versions.pyatv, '0.6.0')) {\n throw new Error(\n \"Found pyatv, but unforunately it's too old. Please update pyatv.\",\n );\n }\n\n try {\n await this.find(options);\n } catch (error) {\n throw new Error(\n `Unable to scan for devices: ${String(error).replace('Error: ', '')}`,\n );\n }\n }\n\n /**\n * Create a [[NodePyATVDevice]] to query the state and control it.\n * At least `host` and `name` are required.\n *\n * @param options\n */\n public static device(options: NodePyATVDeviceOptions): NodePyATVDevice {\n return new NodePyATVDevice(options);\n }\n /**\n * Scan the network for Apple TVs by using pyatv's atvscript. See [[NodePyATVFindAndInstanceOptions]]\n * for the options allowed. Use the `host` / `hosts` attribute to filter by IP addresses. Resolves with\n * an array of [[NodePyATVDevice]].\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const devices = await pyatv.find();\n * console.log(devices);\n * ```\n *\n * Normally `node-pyatv` ignores error messages if at least one device has been found, but if you\n * always want to receive the error messages, you can set the second argument to `true`:\n *\n * ```typescript\n * const result = await pyatv.find({}, true);\n * console.log(result.devices);\n * console.log(result.errors);\n * ```\n *\n * @param options\n */\n public static async find(\n options?: NodePyATVFindAndInstanceOptions,\n ): Promise<NodePyATVDevice[]>;\n public static async find(\n options: NodePyATVFindAndInstanceOptions,\n returnDevicesAndErrors: true,\n ): Promise<NodePyATVFindResponseObject>;\n public static async find(\n options: NodePyATVFindAndInstanceOptions = {},\n returnDevicesAndErrors?: boolean,\n ): Promise<NodePyATVDevice[] | NodePyATVFindResponseObject> {\n const id = addRequestId();\n const parameters = getParameters(options);\n\n const devices: NodePyATVDevice[] = [];\n const errors: Record<string, unknown>[] = [];\n const response = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'scan'],\n { ...(options || {}), allowMultipleResponses: true },\n );\n\n for (const item of response) {\n if (\n typeof item === 'object' &&\n 'result' in item &&\n item.result === 'failure'\n ) {\n errors.push(item);\n } else if (\n typeof item === 'object' &&\n 'result' in item &&\n item.result === 'success' &&\n Array.isArray(item.devices)\n ) {\n devices.push(\n ...item.devices.map((device: NodePyATVInternalScanDevice) =>\n this.device(\n Object.assign({}, options, {\n allIDs: device.all_identifiers,\n host: device.address,\n id: device.identifier,\n mac: device.device_info?.mac || undefined,\n model: device.device_info?.model,\n modelName: device.device_info?.model_str,\n name: device.name,\n os: device.device_info?.operating_system,\n services: device.services,\n version: device.device_info?.version,\n }),\n ),\n ),\n );\n } else {\n throw new Error(\n `Unable to parse pyatv response: ${JSON.stringify(item, null, ' ')}`,\n );\n }\n }\n removeRequestId(id);\n\n if (returnDevicesAndErrors) {\n return { devices, errors };\n }\n if (!devices.length && errors.length) {\n throw new Error(\n `Unable to find any devices, but received ${errors.length} error${errors.length !== 1 ? 's' : ''}: ${JSON.stringify(errors, null, ' ')}`,\n );\n }\n\n return devices;\n }\n\n /**\n * Resolves with the version of pyatv and of the module itself.\n * If a value can't be found, null is returned instead.\n *\n * @param options\n */\n public static async version(\n options: NodePyATVInstanceOptions = {},\n ): Promise<NodePyATVVersionResponse> {\n const id = addRequestId();\n let pyatv = null;\n let module = null;\n\n try {\n pyatv = (await request(\n id,\n NodePyATVExecutableType.atvremote,\n ['--version'],\n options,\n )) as string;\n } catch (error) {\n debug(id, `Unable to get pyatv version due to ${error}`, options);\n }\n\n if (pyatv && pyatv.substr(0, 10) === 'atvremote ') {\n pyatv = pyatv.substr(10);\n }\n if (!semver.valid(pyatv)) {\n debug(\n id,\n `String \"${pyatv}\" is not a valid pyatv version, set it to null`,\n options,\n );\n pyatv = null;\n }\n\n try {\n const packageJsonPath = join(\n dirname(fileURLToPath(import.meta.url)),\n '..',\n '..',\n 'package.json',\n );\n const json = JSON.parse(\n await fsPromises.readFile(packageJsonPath, 'utf8'),\n );\n module = json?.version || null;\n } catch (error) {\n debug(id, `Unable to get module version due to ${error}`, options);\n }\n if (module && !semver.valid(module)) {\n debug(\n id,\n `String \"${module}\" is not a valid module version, set it to null`,\n options,\n );\n module = null;\n }\n\n removeRequestId(id);\n return {\n module,\n pyatv,\n };\n }\n\n /**\n * Checks if pyatv is installed and ready to be used.\n * Will throw an error if not.\n *\n * @param options\n */\n public async check(options: NodePyATVInstanceOptions = {}): Promise<void> {\n return NodePyATVInstance.check(\n Object.assign({}, this.options, options),\n );\n }\n\n /**\n * Create a [[NodePyATVDevice]] to query the state and control it.\n * At least `host` and `name` are required.\n *\n * @param options\n */\n public device(options: NodePyATVDeviceOptions): NodePyATVDevice {\n return NodePyATVInstance.device(\n Object.assign({}, this.options, options),\n );\n }\n\n /**\n * Scan the network for Apple TVs by using pyatv's atvscript. See [[NodePyATVFindAndInstanceOptions]]\n * for the options allowed. Use the `host` / `hosts` attribute to filter by IP addresses. Resolves with\n * an array of [[NodePyATVDevice]].\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const myPyATV = new pyatv({debug: true});\n * const devices = await myPyATV.find();\n * console.log(devices);\n * ```\n *\n * @param options\n */\n public async find(\n options: NodePyATVFindAndInstanceOptions = {},\n ): Promise<NodePyATVDevice[]> {\n return NodePyATVInstance.find(Object.assign({}, this.options, options));\n }\n\n /**\n * Resolves with the version of pyatv and of the module itself.\n * If a value can't be found, null is returned instead.\n *\n * @param options\n */\n public async version(\n options: NodePyATVInstanceOptions = {},\n ): Promise<NodePyATVVersionResponse> {\n return NodePyATVInstance.version(\n Object.assign({}, this.options, options),\n );\n }\n}\n"],"mappings":"6jBAAA,IAAAA,GAAA,GAAAC,GAAAD,GAAA,qBAAAE,EAAA,yBAAAC,EAAA,0BAAAC,EAAA,yBAAAC,EAAA,4BAAAC,EAAA,sBAAAC,EAAA,kBAAAC,EAAA,2BAAAC,EAAA,uBAAAC,EAAA,wBAAAC,EAAA,sBAAAC,EAAA,yBAAAC,EAAA,0BAAAC,EAAA,YAAAP,IAAA,eAAAQ,GAAAf,ICKA,IAAMgB,GAAmB,IACvB,OAAO,SAAa,IAChB,IAAI,IAAI,QAAQ,UAAU,EAAE,EAAE,KAC7B,SAAS,eAAiB,SAAS,cAAc,KAClD,IAAI,IAAI,UAAW,SAAS,OAAO,EAAE,KAE9BC,EAAgCD,GAAiB,ECL9D,IAAqBE,EAArB,KAA0C,CAKtC,IAAI,QAA0B,CAC1B,OAAO,KAAK,OAAO,MACvB,CAMA,IAAI,KAA2B,CAC3B,OAAO,KAAK,OAAO,GACvB,CAKA,IAAI,UAAoC,CACpC,OAAO,KAAK,OAAO,GACvB,CAMA,IAAI,UAAoC,CACpC,OAAO,KAAK,OAAO,GACvB,CAKA,IAAI,OAAiC,CACjC,OAAO,KAAK,OAAO,GACvB,CAEmB,OAYnB,YAAYC,EAKT,CACC,KAAK,OAAS,OAAO,OAAO,CAAC,EAAGA,EAAQ,CACpC,IAAKA,EAAO,GAChB,CAAC,CACL,CACJ,EChEA,IAAAC,EAA6B,kBCD7B,IAAAC,EAAuD,yBCIhD,IAAKC,OACRA,EAAA,KAAO,OACPA,EAAA,QAAU,UACVA,EAAA,OAAS,SACTA,EAAA,QAAU,UACVA,EAAA,QAAU,UACVA,EAAA,QAAU,UANFA,OAAA,IASAC,OACRA,EAAA,UAAY,YACZA,EAAA,UAAY,YAFJA,OAAA,IAKAC,OAERA,EAAA,OAAS,UAKTA,EAAA,QAAU,UAEVA,EAAA,UAAY,YATJA,OAAA,IAeAC,OACRA,EAAA,KAAO,OACPA,EAAA,KAAO,OACPA,EAAA,SAAW,YACXA,EAAA,KAAO,OACPA,EAAA,KAAO,OACPA,EAAA,KAAO,OACPA,EAAA,MAAQ,QACRA,EAAA,KAAO,OACPA,EAAA,UAAY,aACZA,EAAA,SAAW,WACXA,EAAA,MAAQ,QACRA,EAAA,OAAS,SACTA,EAAA,aAAe,gBACfA,EAAA,YAAc,eACdA,EAAA,KAAO,OACPA,EAAA,QAAU,UACVA,EAAA,QAAU,WACVA,EAAA,QAAU,WACVA,EAAA,OAAS,UACTA,EAAA,GAAK,KACLA,EAAA,WAAa,cACbA,EAAA,SAAW,YACXA,EAAA,OAAS,SAvBDA,OAAA,IA0BAC,OACRA,EAAA,KAAO,OACPA,EAAA,KAAO,OACPA,EAAA,SAAW,WACXA,EAAA,KAAO,OACPA,EAAA,KAAO,OACPA,EAAA,KAAO,OACPA,EAAA,MAAQ,QACRA,EAAA,KAAO,OACPA,EAAA,UAAY,YACZA,EAAA,SAAW,WACXA,EAAA,MAAQ,QACRA,EAAA,OAAS,SACTA,EAAA,aAAe,eACfA,EAAA,YAAc,cACdA,EAAA,KAAO,OACPA,EAAA,QAAU,UACVA,EAAA,QAAU,UACVA,EAAA,QAAU,UACVA,EAAA,OAAS,SACTA,EAAA,GAAK,KACLA,EAAA,WAAa,aACbA,EAAA,SAAW,WACXA,EAAA,OAAS,SAvBDA,OAAA,IA0BAC,OACRA,IAAA,qBACAA,IAAA,uBACAA,IAAA,qBACAA,IAAA,uBAJQA,OAAA,IAOAC,OACRA,EAAA,MAAQ,QACRA,EAAA,GAAK,KACLA,EAAA,QAAU,UACVA,EAAA,MAAQ,QAJAA,OAAA,IAOAC,OACRA,EAAA,IAAM,MACNA,EAAA,GAAK,KAFGA,OAAA,IAKAC,OACRA,EAAA,QAAU,UACVA,EAAA,KAAO,OACPA,EAAA,KAAO,OACPA,EAAA,IAAM,MAJEA,OAAA,IAOAC,OACRA,EAAA,IAAM,MACNA,EAAA,IAAM,MACNA,EAAA,MAAQ,QAHAA,OAAA,IAMAC,OACRA,EAAA,OAAS,SACTA,EAAA,IAAM,MACNA,EAAA,MAAQ,QAHAA,OAAA,IDnGZ,IAAMC,EAAuB,CAAC,EAOvB,SAASC,GAAuB,CACnC,IAAIC,EAAK,IAET,QAASC,EAAI,EAAGA,EAAI,IAAMA,GAAK,EAI3B,GAHAD,EAAK,KAAK,MAAM,KAAK,OAAO,GAAKC,EAAI,GAAK,EAAE,EACvC,SAAS,EAAE,EACX,YAAY,EACb,CAACH,EAAW,SAASE,CAAE,EAAG,CAC1BF,EAAW,KAAKE,CAAE,EAClB,KACJ,CAGJ,OAAOA,CACX,CAEO,SAASE,EACZC,EACAC,EACF,CACE,MAAO,GACH,MAAM,QAAQD,CAAC,GACX,MAAM,QAAQC,CAAC,GACf,KAAK,UACDD,EAAE,KAAK,CAACA,EAAGC,IAAOD,EAAE,WAAaC,EAAE,WAAa,GAAK,CAAE,CAC3D,IACI,KAAK,UACDA,EAAE,KAAK,CAACD,EAAGC,IAAOD,EAAE,WAAaC,EAAE,WAAa,GAAK,CAAE,CAC3D,EAEhB,CAEO,SAASC,EACZL,EACAM,EACAC,EACI,CACJ,GAAIA,EAAQ,MAAO,CACf,IAAMC,EACF,OAAOD,EAAQ,OAAU,WAAaA,EAAQ,MAAQ,QAAQ,IAC5DE,EAAe,CAAC,QAAQ,IAAI,UAAY,CAACF,EAAQ,SAEjDG,EAAQ,CACVD,EAAe,UAAY,GAC3BA,EAAe,WAAa,GAC5B,gBACAA,EAAe,WAAa,GAC5BT,EACAS,EAAe,WAAa,GAC5B,KACAA,EAAe,UAAY,GAC3BH,CACJ,EAEAE,EAAI,MAAM,KAAM,CAACE,EAAM,KAAK,EAAE,CAAC,CAAC,CACpC,CACJ,CAEO,SAASC,EACZC,EACAC,EACAC,EACAP,EAC+B,CAC/B,IAAMQ,EAAaC,GAAcH,EAAgBN,CAAO,EAClDU,EAKF,OAAOV,EAAQ,OAAU,WAAaA,EAAQ,MAAQ,QAE1DF,EAAMO,EAAW,GAAGG,CAAU,IAAID,EAAW,KAAK,GAAG,CAAC,GAAIP,CAAO,EACjE,IAAMW,EAAQD,EAAQF,EAAYD,EAAY,CAC1C,IAAK,QAAQ,GACjB,CAAC,EAGKK,EAAYC,GACdf,EAAMO,EAAW,WAAW,OAAOQ,CAAI,EAAE,KAAK,CAAC,GAAIb,CAAO,EACxDc,EAAYD,GACdf,EAAMO,EAAW,WAAW,OAAOQ,CAAI,EAAE,KAAK,CAAC,GAAIb,CAAO,EACxDe,EAAWF,GACbf,EAAMO,EAAW,UAAU,OAAOQ,CAAI,EAAE,KAAK,CAAC,GAAIb,CAAO,EAGvDgB,EAAWC,GAAiB,CAC9BnB,EAAMO,EAAW,GAAGG,CAAU,sBAAsBS,CAAI,GAAIjB,CAAO,EAE/DW,EAAM,QACNA,EAAM,OAAO,IAAI,OAAQC,CAAQ,EAEjCD,EAAM,QACNA,EAAM,OAAO,IAAI,OAAQG,CAAQ,EAGrCH,EAAM,IAAI,QAASI,CAAO,EAC1BJ,EAAM,IAAI,QAASK,CAAO,CAC9B,EAEA,OAAIL,EAAM,QACNA,EAAM,OAAO,GAAG,OAAQC,CAAQ,EAEhCD,EAAM,QACNA,EAAM,OAAO,GAAG,OAAQG,CAAQ,EAGpCH,EAAM,GAAG,QAASI,CAAO,EACzBJ,EAAM,GAAG,QAASK,CAAO,EAElBL,CACX,CAEO,SAASF,GACZD,EACAR,EACM,CACN,OACIQ,IAAe,aACf,OAAOR,EAAQ,eAAkB,SAE1BA,EAAQ,cAEfQ,IAAe,aACf,OAAOR,EAAQ,eAAkB,SAE1BA,EAAQ,cAERQ,CAEf,CAEO,SAASU,EACZlB,EAA2C,CAAC,EACpC,CACR,IAAMO,EAAuB,CAAC,EAE9B,OAAIP,EAAQ,MACRO,EAAW,KAAK,KAAMP,EAAQ,MAAM,KAAK,GAAG,CAAC,EACtCA,EAAQ,MACfO,EAAW,KAAK,KAAMP,EAAQ,IAAI,EAElCA,EAAQ,IACRO,EAAW,KAAK,KAAMP,EAAQ,EAAE,EAEhCA,EAAQ,UACRO,EAAW,KAAK,aAAcP,EAAQ,QAAQ,EAE9CA,EAAQ,iBACRO,EAAW,KAAK,qBAAsBP,EAAQ,eAAe,EAE7DA,EAAQ,gBACRO,EAAW,KAAK,oBAAqBP,EAAQ,cAAc,EAE3DA,EAAQ,oBACRO,EAAW,KAAK,wBAAyBP,EAAQ,kBAAkB,EAEnEA,EAAQ,sBACRO,EAAW,KACP,0BACAP,EAAQ,oBACZ,EAEAA,EAAQ,iBACRO,EAAW,KAAK,qBAAsBP,EAAQ,eAAe,EAG1DO,CACX,CACO,SAASY,EACZC,EACA3B,EACAO,EACc,CACd,IAAMqB,EAAKC,GAAgBxB,EAAML,EAAI6B,EAAKtB,CAAO,EAC3CuB,EAAyB,CAC3B,MAAO,KACP,IAAK,KACL,MAAO,KACP,OAAQ,KACR,kBAAmB,KACnB,SAAU,KACV,YAAa,KACb,cAAe,KACf,WAAY,KACZ,MAAO,KACP,KAAM,KACN,sBAAuB,KACvB,UAAW,KACX,cAAe,KACf,SAAU,KACV,WAAY,KACZ,OAAQ,KACR,aAAc,KACd,WAAY,KACZ,QAAS,KACT,MAAO,KACP,UAAW,KACX,OAAQ,IACZ,EACA,GAAI,CAACH,GAAS,OAAOA,GAAU,SAC3B,OAAOG,EAEX,GAAIH,EAAM,UAAW,CACjB,IAAII,EAAW,oBAAsBJ,EAAM,UAC3C,MAAIA,EAAM,aACNI,GAAY;AAAA;AAAA;AAAA,EAA4BJ,EAAM,YAG5C,IAAI,MAAMI,CAAQ,CAC5B,CAGA,GAAI,OAAOJ,EAAM,UAAa,SAAU,CACpC,IAAMK,EAAO,IAAI,KAAKL,EAAM,QAAQ,EAC/B,MAAMK,EAAK,QAAQ,CAAC,EAGrBJ,EAAE,0BAA0BD,EAAM,QAAQ,oBAAoB,EAF9DG,EAAO,SAAWE,CAI1B,MACIJ,EAAE,qCAAqC,KAAK,UAAUD,CAAK,CAAC,GAAG,EAInE,OAAAM,EAAqBN,EAAOG,EAAQ,OAAQ,OAAQF,CAAC,EAGjD,OAAOD,EAAM,YAAe,SACR,OAAO,KAAKO,CAAkB,EAAE,IAAK,GACrD,OAAO,CAAC,CACZ,EACgB,SAASP,EAAM,UAAU,EACrCG,EAAO,UACHI,EAAmBP,EAAM,UAAgC,EAE7DC,EACI,+BAA+BD,EAAM,UAAU,oBACnD,EAGJC,EAAE,sCAAsC,KAAK,UAAUD,CAAK,CAAC,GAAG,EAIhE,OAAOA,EAAM,cAAiB,SACV,OAAO,KAAKQ,CAAoB,EAAE,IAAK,GACvD,OAAO,CAAC,CACZ,EACgB,SAASR,EAAM,YAAY,EACvCG,EAAO,YACHK,EACIR,EAAM,YACV,EAEJC,EACI,iCAAiCD,EAAM,YAAY,oBACvD,EAGJC,EAAE,wCAAwC,KAAK,UAAUD,CAAK,CAAC,GAAG,EAItEM,EAAqBN,EAAOG,EAAQ,QAAS,QAASF,CAAC,EAGvDK,EAAqBN,EAAOG,EAAQ,SAAU,SAAUF,CAAC,EAGzDK,EAAqBN,EAAOG,EAAQ,QAAS,QAASF,CAAC,EAGvDK,EAAqBN,EAAOG,EAAQ,QAAS,QAASF,CAAC,EAGvDQ,EAAqBT,EAAOG,EAAQ,aAAc,YAAaF,CAAC,EAGhEQ,EAAqBT,EAAOG,EAAQ,WAAY,WAAYF,CAAC,EAGzD,OAAOD,EAAM,SAAY,SACL,OAAO,KAAKU,CAAqB,EAAE,IAAK,GACxD,OAAO,CAAC,CACZ,EACgB,SAASV,EAAM,OAAO,EAClCG,EAAO,QACHO,EAAsBV,EAAM,OAAgC,EAEhEC,EAAE,6BAA6BD,EAAM,OAAO,oBAAoB,EAGpEC,EAAE,oCAAoC,KAAK,UAAUD,CAAK,CAAC,GAAG,EAI9D,OAAOA,EAAM,QAAW,SACJ,OAAO,KAAKW,CAAoB,EAAE,IAAK,GACvD,OAAO,CAAC,CACZ,EACgB,SAASX,EAAM,MAAM,EACjCG,EAAO,OACHQ,EAAqBX,EAAM,MAA8B,EAE7DC,EAAE,4BAA4BD,EAAM,MAAM,oBAAoB,EAGlEC,EAAE,mCAAmC,KAAK,UAAUD,CAAK,CAAC,GAAG,EAIjEM,EAAqBN,EAAOG,EAAQ,MAAO,MAAOF,CAAC,EACnDK,EAAqBN,EAAOG,EAAQ,SAAU,QAASF,CAAC,EAGpD,OAAOD,EAAM,aAAgB,SACT,OAAO,KAAKY,CAAmB,EAAE,IAAK,GACtD,OAAO,CAAC,CACZ,EACgB,SAASZ,EAAM,WAAW,EACtCG,EAAO,WACHS,EAAoBZ,EAAM,WAAkC,EAEhEC,EACI,gCAAgCD,EAAM,WAAW,oBACrD,EAGJC,EAAE,uCAAuC,KAAK,UAAUD,CAAK,CAAC,GAAG,EAIrES,EAAqBT,EAAOG,EAAQ,SAAU,SAAUF,CAAC,EAGrD,OAAOD,EAAM,aAAgB,SACT,OAAO,KAAKa,CAAmB,EAAE,IAAK,GACtD,OAAO,CAAC,CACZ,EACgB,SAASb,EAAM,WAAW,EACtCG,EAAO,WACHU,EAAoBb,EAAM,WAAkC,EAEhEC,EACI,gCAAgCD,EAAM,WAAW,oBACrD,EAGJC,EAAE,uCAAuC,KAAK,UAAUD,CAAK,CAAC,GAAG,EAIjE,MAAM,QAAQA,EAAM,cAAc,IAClCG,EAAO,cAAgBH,EAAM,gBAIjCM,EACIN,EACAG,EACA,qBACA,oBACAF,CACJ,EAGAQ,EACIT,EACAG,EACA,0BACA,wBACAF,CACJ,EAGAQ,EAAqBT,EAAOG,EAAQ,iBAAkB,gBAAiBF,CAAC,EAGxEQ,EAAqBT,EAAOG,EAAQ,gBAAiB,eAAgBF,CAAC,EAGtEK,EAAqBN,EAAOG,EAAQ,cAAe,aAAcF,CAAC,EAE3DE,CACX,CACO,SAASW,EAAgBzC,EAA8B,CACtDA,GAAMF,EAAW,SAASE,CAAE,GAC5BF,EAAW,OAAOA,EAAW,QAAQE,CAAE,EAAG,CAAC,CAEnD,CAgBA,eAAsB0C,EAClB9B,EACAC,EACAC,EACAP,EACqE,CACrE,IAAMuB,EAAS,CACX,KAAM,EACN,OAAQ,GACR,OAAQ,EACZ,EAsCA,GApCA,MAAM,IAAI,QAAQ,CAACa,EAASC,IAAW,CACnC,IAAMC,EAAQlC,EAAQC,EAAWC,EAAgBC,EAAYP,CAAO,EAG9DY,EAAYC,GAAeU,EAAO,QAAU,OAAOV,CAAI,EAAE,KAAK,EAC9DC,EAAYD,GAAeU,EAAO,QAAU,OAAOV,CAAI,EAAE,KAAK,EAC9DE,EAAWF,GACbwB,EAAOxB,aAAgB,MAAQA,EAAO,IAAI,MAAM,OAAOA,CAAI,CAAC,CAAC,EAG3DG,EAAmCC,GAAiB,CACtDM,EAAO,KAAON,EAEVqB,EAAM,QACNA,EAAM,OAAO,IAAI,OAAQ1B,CAAQ,EAEjC0B,EAAM,QACNA,EAAM,OAAO,IAAI,OAAQxB,CAAQ,EAGrCwB,EAAM,IAAI,QAASvB,CAAO,EAC1BuB,EAAM,IAAI,QAAStB,CAAO,EAC1BoB,EAAQ,MAAS,CACrB,EAEIE,EAAM,QACNA,EAAM,OAAO,GAAG,OAAQ1B,CAAQ,EAEhC0B,EAAM,QACNA,EAAM,OAAO,GAAG,OAAQxB,CAAQ,EAGpCwB,EAAM,GAAG,QAASvB,CAAO,EACzBuB,EAAM,GAAG,QAAStB,CAAO,CAC7B,CAAC,EAEGO,EAAO,OAAO,OAAS,EAAG,CAC1B,IAAMD,EAAM,6BAA6BjB,CAAS,KAAKkB,EAAO,MAAM,GACpE,MAAAzB,EAAMO,EAAWiB,EAAKtB,CAAO,EACvB,IAAI,MAAMsB,CAAG,CACvB,CAEA,GAAIhB,IAAmB,YACnB,GAAI,CAGA,OAAIN,EAAQ,uBACDuB,EAAO,OACT,MAAM;AAAA,CAAI,EACV,OAAQgB,GAASA,EAAK,KAAK,EAAE,OAAS,CAAC,EACvC,IAAKA,GAAS,KAAK,MAAMA,CAAI,CAAC,EAGhC,KAAK,MAAMhB,EAAO,MAAM,CACnC,OAASiB,EAAO,CACZ,IAAMlB,EAAM,0BAA0BjB,CAAS,UAAUmC,CAAK,GAC9D,MAAA1C,EAAMO,EAAWiB,EAAKtB,CAAO,EACvB,IAAI,MAAMsB,CAAG,CACvB,CAGJ,OAAOC,EAAO,MAClB,CAEA,SAASM,EACLT,EACAqB,EACAC,EAOAC,EAOAtB,EACI,CACJ,GAAI,OAAOD,EAAMsB,CAAS,GAAM,SAAU,CACtCD,EAAOE,CAAU,EAAIvB,EAAMsB,CAAS,EACpC,MACJ,CAEArB,EAAE,MAAMsB,CAAU,0BAA0B,KAAK,UAAUvB,CAAK,CAAC,GAAG,CACxE,CAEA,SAASM,EACLN,EACAqB,EACAC,EAUAC,EAUAtB,EACI,CACJ,GAAI,OAAOD,EAAMsB,CAAS,GAAM,SAAU,CACtCD,EAAOE,CAAU,EAAIvB,EAAMsB,CAAS,EACpC,MACJ,CAEArB,EAAE,MAAMsB,CAAU,0BAA0B,KAAK,UAAUvB,CAAK,CAAC,GAAG,CACxE,CD3hBA,IAAqBwB,EAArB,cAAmD,cAAa,CAC3C,OACT,cACS,QACT,MACS,MACT,QAER,YACIC,EACAC,EACAC,EACF,CACE,MAAM,EAEN,KAAK,MAAQF,EACb,KAAK,OAASC,EACd,KAAK,QAAU,OAAO,OAAO,CAAC,EAAGC,CAAO,EACxC,KAAK,cAAgB,CACzB,CAEA,YACIC,EACAC,EACI,CACJ,aAAM,YAAYD,EAAOC,CAAQ,EACjC,KAAK,cAAc,EACZ,IACX,CAEA,wBAAwBC,EAAgC,CACpD,IAAIC,EAAO,OAAO,KAAK,KAAK,KAAK,EAGjCA,EAAOA,EAAK,OACPC,GACG,CAAC,CACG,aACA,gBACA,aACA,QACJ,EAAE,SAASA,CAAC,CACpB,EAEI,eAAgBF,GAAYA,EAAS,aACrCC,EAAO,CAAC,YAAY,GAEpB,eAAgBD,GAAYA,EAAS,aACrCC,EAAO,CAAC,YAAY,GAEpB,kBAAmBD,GAAYA,EAAS,gBACxCC,EAAO,CAAC,eAAe,GAKvB,WAAYD,GAAYA,EAAS,SAAW,OAC5CC,EAAO,CAAC,QAAQ,GAMf,OAAO,QAAQD,CAAQ,EAAE,KACtB,CAAC,CAACE,EAAGC,CAAC,IAAM,CAAC,CAAC,WAAY,QAAQ,EAAE,SAASD,CAAC,GAAKC,IAAM,IAC7D,GAKJF,EAAK,QAASG,GAAgB,CAE1B,IAAMC,EAAW,KAAK,MAAMD,CAAG,EAGzBE,EAAWN,EAASI,CAAG,EAS7B,GANIC,IAAa,QACbC,IAAa,QACbD,IAAaC,GAKbF,IAAQ,iBACRG,EAAqBF,EAAUC,CAAQ,EAEvC,OAGJ,IAAMR,EAAQ,IAAIU,EAAqB,CACnC,OAAQ,KAAK,OACb,IAAKJ,EACL,IAAKE,EACL,IAAKD,CACT,CAAC,EAGD,KAAK,MAAMD,CAAG,EAAIJ,EAASI,CAAG,EAE9B,GAAI,CACA,KAAK,KAAK,UAAYA,EAAKN,CAAK,EAChC,KAAK,KAAK,SAAUA,CAAK,CAC7B,OAASW,EAAO,CACZ,KAAK,KAAK,QAASA,CAAK,CAC5B,CACJ,CAAC,CACL,CAEA,cAAcX,EAAiC,CAC3C,OAAIA,IAAU,OACH,MAAM,cAAcA,CAAK,EAG7B,KAAK,WAAW,EAClB,IAAKA,GAAU,KAAK,cAAcA,CAAK,CAAC,EACxC,OAAO,CAACY,EAAGC,IAAMD,EAAIC,EAAG,CAAC,CAClC,CAEA,IACIb,EACAC,EACI,CACJ,aAAM,IAAID,EAAOC,CAAQ,EACzB,KAAK,cAAc,EACZ,IACX,CAEA,GACID,EACAC,EACI,CACJ,aAAM,GAAGD,EAAOC,CAAQ,EACxB,KAAK,cAAc,EACZ,IACX,CAEA,KACID,EACAC,EACI,CACJ,aAAM,KAAKD,EAAQA,GAAgC,CAC/CC,EAASD,CAAK,EACd,WAAW,IAAM,KAAK,cAAc,EAAG,CAAC,CAC5C,CAAC,EACD,KAAK,cAAc,EACZ,IACX,CAEA,gBACIA,EACAC,EACI,CACJ,aAAM,gBAAgBD,EAAOC,CAAQ,EACrC,KAAK,cAAc,EACZ,IACX,CAEA,mBAAmBD,EAA+B,CAC9C,aAAM,mBAAmBA,CAAK,EAC9B,KAAK,cAAc,EACZ,IACX,CAEA,eACIA,EACAC,EACI,CACJ,aAAM,eAAeD,EAAOC,CAAQ,EACpC,KAAK,cAAc,EACZ,IACX,CAEA,MAAgB,cAAca,EAA8B,CACxD,GACI,OAAK,gBAAkB,GACvB,KAAK,gBAAkB,GAM3B,IADA,KAAK,cAAgB,EACjB,KAAK,QAAU,OACf,MAAM,IAAI,MACN,gJAEJ,EAGA,KAAK,MAAM,QACXC,EAAMD,EAAO,0CAAsC,KAAK,OAAO,EAC/D,KAAK,MAAM,MAAM,MAAM;AAAA,CAAI,EAE3B,MAAM,IAAI,QAASE,GAAQ,KAAK,QAAU,WAAWA,EAAI,GAAG,CAAE,GAI9D,KAAK,gBAAkB,GACvB,KAAK,OAEL,KAAK,MAAM,KAAK,EAGpB,KAAK,cAAgB,EAEzB,CAEQ,gBACJC,EACAH,EACI,CACJ,GAAI,CACA,IAAMZ,EAAWgB,EAAWD,EAAQH,EAAO,KAAK,OAAO,EACvD,KAAK,wBAAwBZ,CAAQ,CACzC,OAASS,EAAO,CACZ,KAAK,KAAK,QAASA,CAAK,CAC5B,CACJ,CAEQ,eAAsB,CAC1B,GACI,KAAK,gBAAkB,GACvB,KAAK,cAAc,IAAM,GACzB,KAAK,QAEL,aAAa,KAAK,OAAO,EACzB,KAAK,QAAU,eAEf,KAAK,gBAAkB,GACvB,KAAK,cAAc,EAAI,EACzB,CACE,IAAMQ,EAAKC,EAAa,EACxBL,EACII,EACA,wCAAwC,KAAK,QAAQ,IAAI,GACzD,KAAK,OACT,EAEA,KAAK,eAAeA,CAAE,EACtBE,EAAgBF,CAAE,CACtB,SACI,IAGA,EAAE,SAAS,KAAK,aAAa,GAC7B,KAAK,cAAc,IAAM,EAC3B,CACE,IAAMA,EAAKC,EAAa,EACxBL,EACII,EACA,wCAAwC,KAAK,QAAQ,IAAI,GACzD,KAAK,OACT,EAEA,KAAK,cAAcA,CAAE,EAChB,MAAOR,GACJI,EACII,EACA,4BAA4BR,CAAK,GACjC,KAAK,OACT,CACJ,EACC,QAAQ,IAAMU,EAAgBF,CAAE,CAAC,CAC1C,CACJ,CAEQ,gBAAgBL,EAAeQ,EAAoB,CACvD,IAAIC,EAEJ,GAAI,CACAA,EAAO,KAAK,MAAMD,CAAI,CAC1B,OAASX,EAAO,CACZ,IAAMa,EAAM,gCAAgCb,CAAK,GACjDI,EAAMD,EAAOU,EAAK,KAAK,OAAO,EAC9B,KAAK,KAAK,QAAS,IAAI,MAAMA,CAAG,CAAC,EACjC,MACJ,CAEA,KAAK,gBAAgBD,EAAMT,CAAK,EAE5B,KAAK,gBAAkB,IACvB,KAAK,cAAgB,EACrB,KAAK,cAAc,EAE3B,CAEQ,eAAeA,EAAqB,CACxC,GAAI,KAAK,gBAAkB,EACvB,OAGJ,KAAK,cAAgB,EAErB,IAAMW,EAAc,IAAI,KAAK,EAAE,QAAQ,EACjCC,EAAaC,EAAc,KAAK,OAAO,EAO7C,GANA,KAAK,MAAQC,EACTd,cAEA,CAAC,GAAGY,EAAY,cAAc,EAC9B,KAAK,OACT,EACI,CAAC,KAAK,MACN,MAAM,IAAI,MACN,qDACJ,EAGJ,IAAMG,EAAWlB,GAAiB,CAC9BI,EACID,EACA,iCAAiCH,CAAK,GACtC,KAAK,OACT,EACA,KAAK,KAAK,QAASA,CAAK,CAC5B,EAGMmB,EAAYR,GAAc,CAC5B,IAAMX,EAAQ,IAAI,MAAM,iCAAiCW,CAAI,EAAE,EAC/DP,EAAMD,EAAOQ,EAAK,SAAS,EAAG,KAAK,OAAO,EAC1C,KAAK,KAAK,QAASX,CAAK,CAC5B,EAGMoB,EAAYT,GAAc,CAC5B,OAAOA,CAAI,EACN,MAAM;AAAA,CAAI,EACV,IAAKU,GAAMA,EAAE,KAAK,CAAC,EACnB,OAAO,OAAO,EACd,QAASA,GAAM,CACZjB,EAAMD,EAAO,KAAKkB,CAAC,GAAI,KAAK,OAAO,EACnC,KAAK,gBAAgBlB,EAAOkB,CAAC,CACjC,CAAC,CACT,EACMC,EAAWC,GAAiB,CAC1B,KAAK,QAAU,SAKnB,KAAK,cAAgB,EACrBnB,EACID,EACA,6CAA6CoB,CAAI,GACjD,KAAK,OACT,EACI,KAAK,UAAY,SACjB,aAAa,KAAK,OAAO,EACzB,KAAK,QAAU,QAGf,KAAK,MAAM,QACX,KAAK,MAAM,OAAO,IAAI,OAAQH,CAAQ,EAEtC,KAAK,MAAM,QACX,KAAK,MAAM,OAAO,IAAI,OAAQD,CAAQ,EAE1C,KAAK,MAAM,IAAI,QAASD,CAAO,EAC/B,KAAK,MAAM,IAAI,QAASI,CAAO,EAG3B,KAAK,cAAc,EAAI,GACvB,IAAI,KAAK,EAAE,QAAQ,EAAIR,EAAc,KAErCV,EACID,EACA,uDAAuD,KAAK,QAAQ,IAAI,GACxE,KAAK,OACT,EAEA,KAAK,QAAU,WAAW,IAAM,CAC5B,KAAK,cAAc,CACvB,EAAG,IAAK,GACD,KAAK,cAAc,EAAI,IAC9BC,EACID,EACA,0CAA0C,KAAK,QAAQ,IAAI,GAC3D,KAAK,OACT,EACA,KAAK,cAAc,GAGvBO,EAAgBP,CAAK,EACzB,EAEA,KAAK,MAAM,GAAG,QAASe,CAAO,EAC9B,KAAK,MAAM,GAAG,QAASI,CAAO,EAE1B,KAAK,MAAM,QACX,KAAK,MAAM,OAAO,GAAG,OAAQF,CAAQ,EAErC,KAAK,MAAM,QACX,KAAK,MAAM,OAAO,GAAG,OAAQD,CAAQ,CAE7C,CACJ,EGnYA,IAAqBK,EAArB,KAA6D,CAKzD,IAAI,QAA+B,CAC/B,OAAO,KAAK,QAAQ,MACxB,CAMA,IAAI,OAAoD,CACpD,OAAO,KAAK,QAAQ,KACxB,CAOA,IAAI,MAAMC,EAAmD,CACrD,OAAOA,GAAU,WACjB,KAAK,QAAQ,MAAQA,EAErB,KAAK,QAAQ,MAAQ,EAAQA,GAAU,MAE/C,CAKA,IAAI,MAA2B,CAC3B,OAAO,KAAK,QAAQ,IACxB,CAKA,IAAI,IAAyB,CACzB,OAAO,KAAK,QAAQ,EACxB,CAMA,IAAI,KAA0B,CAC1B,OAAO,KAAK,QAAQ,GACxB,CAQA,IAAI,OAA4B,CAC5B,OAAO,KAAK,QAAQ,KACxB,CAQA,IAAI,WAAgC,CAChC,OAAO,KAAK,QAAQ,SACxB,CAaA,IAAI,MAAe,CACf,OAAO,KAAK,QAAQ,IACxB,CAQA,IAAI,IAAyB,CACzB,OAAO,KAAK,QAAQ,EACxB,CAKA,IAAI,UAA0C,CAC1C,OAAO,KAAK,QAAQ,QACxB,CAkBA,IAAI,UAA2C,CAC3C,OAAO,KAAK,QAAQ,QACxB,CAQA,IAAI,SAA8B,CAC9B,OAAO,KAAK,QAAQ,OACxB,CAEiB,OAEA,QAEA,MAEjB,YAAYC,EAAiC,CACzC,GAAI,CAACA,EAAQ,MAAQ,CAACA,EAAQ,IAAM,CAACA,EAAQ,IACzC,MAAM,IAAI,MAAM,qCAAqC,EAGzD,KAAK,QAAU,OAAO,OAAO,CAAC,EAAGA,CAAO,EACxC,KAAK,MAAQC,EAAW,CAAC,EAAG,GAAI,CAAC,CAAC,EAClC,KAAK,OAAS,IAAIC,EAAsB,KAAK,MAAO,KAAM,KAAK,OAAO,CAG1E,CASA,YACIC,EACAC,EACI,CACJ,YAAK,OAAO,YAAYD,EAAOC,CAAQ,EAChC,IACX,CAOA,YAAmB,CACf,KAAK,WAAWH,EAAW,CAAC,EAAG,GAAI,CAAC,CAAC,CAAC,CAC1C,CAMA,MAAM,MAAsB,CACxB,MAAM,KAAK,0BAA8C,CAC7D,CAQA,KAAKE,EAAwBE,EAAwC,CACjE,OAAO,KAAK,OAAO,KAAKF,EAAOE,CAAO,CAC1C,CAMA,YAAqC,CACjC,OAAO,KAAK,OAAO,WAAW,CAClC,CAOA,MAAM,SACFL,EAAoC,CAAC,EACf,CAEtB,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,KACjB,CAOA,MAAM,OACFA,EAAoC,CAAC,EACf,CAEtB,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,GACjB,CAOA,MAAM,SACFA,EAAoC,CAAC,EACf,CAEtB,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,KACjB,CAOA,MAAM,UACFA,EAAoC,CAAC,EACf,CAEtB,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,MACjB,CAOA,MAAM,qBACFA,EAAoC,CAAC,EACf,CACtB,OAAO,KAAK,SAASA,CAAO,EAAE,KAAMM,GAAUA,EAAM,iBAAiB,CACzE,CAOA,MAAM,YACFN,EAAoC,CAAC,EACjB,CAEpB,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,QACjB,CAOA,MAAM,eACFA,EAAoC,CAAC,EACD,CAEpC,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,WACjB,CAQA,MAAM,iBACFA,EAAoC,CAAC,EACf,CACtB,OAAO,KAAK,SAASA,CAAO,EAAE,KAAMM,GAAUA,EAAM,aAAa,CACrE,CAOA,MAAM,cACFN,EAAoC,CAAC,EACF,CACnC,OAAO,KAAK,SAASA,CAAO,EAAE,KAAMM,GAAUA,EAAM,UAAU,CAClE,CAOA,MAAM,SACFN,EAAoC,CAAC,EACf,CAEtB,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,KACjB,CAOA,MAAM,QACFA,EAAoC,CAAC,EACf,CAEtB,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,IACjB,CASA,MAAM,yBACFA,EAAoC,CAAC,EACf,CACtB,OAAO,KAAK,SAASA,CAAO,EAAE,KACzBM,GAAUA,EAAM,qBACrB,CACJ,CAEA,MAAM,yBACFN,EAAoC,CAAC,EACf,CACtB,OAAO,KAAK,yBAAyBA,CAAO,CAChD,CAMA,iBAA0B,CACtB,OAAO,KAAK,OAAO,gBAAgB,CACvC,CAOA,MAAM,aACFA,EAAoC,CAAC,EACH,CAElC,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,SACjB,CAOA,MAAM,iBACFA,EAAoC,CAAC,EACsB,CAC3D,OAAO,KAAK,SAASA,CAAO,EAAE,KAAMM,GAAUA,EAAM,aAAa,CACrE,CAOA,MAAM,YACFN,EAAoC,CAAC,EACf,CAEtB,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,QACjB,CAOA,MAAM,cACFA,EAAoC,CAAC,EACF,CACnC,OAAO,KAAK,SAASA,CAAO,EAAE,KAAMM,GAAUA,EAAM,UAAU,CAClE,CAOA,MAAM,UACFN,EAAoC,CAAC,EACD,CAEpC,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,MACjB,CAQA,MAAM,gBACFA,EAAoC,CAAC,EACf,CACtB,OAAO,KAAK,SAASA,CAAO,EAAE,KAAMM,GAAUA,EAAM,YAAY,CACpE,CAOA,MAAM,cACFN,EAAoC,CAAC,EACf,CACtB,OAAO,KAAK,SAASA,CAAO,EAAE,KAAMM,GAAUA,EAAM,UAAU,CAClE,CAOA,MAAM,WACFN,EAAoC,CAAC,EACA,CAErC,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,OACjB,CAcA,MAAM,SACFA,EAAoC,CAAC,EACd,CACvB,GACI,KAAK,OAAO,UACZ,IAAI,KAAK,EAAE,QAAQ,EAAI,KAAK,MAAM,SAAS,QAAQ,GAC9CA,EAAQ,QAAU,KACzB,CACE,IAAIO,EAAW,KACf,OAAI,KAAK,MAAM,UAAY,KAAK,MAAM,WAClCA,EAAW,KAAK,MACZ,KAAK,MAAM,UACN,IAAI,KAAK,EAAE,QAAQ,EAAI,KAAK,MAAM,SAAS,QAAQ,GAChD,GACZ,GAGG,OAAO,OAAO,CAAC,EAAG,KAAK,MAAO,CAAE,SAAAA,CAAS,CAAC,CACrD,CAEA,IAAMC,EAAKC,EAAa,EAExB,GAAI,CACA,IAAMC,EAAaC,EAAc,KAAK,OAAO,EAEvCC,EAAS,MAAMC,EACjBL,cAEA,CAAC,GAAGE,EAAY,SAAS,EACzB,KAAK,OACT,EACMI,EAAWb,EAAWW,EAAQJ,EAAI,KAAK,OAAO,EAEpD,YAAK,WAAWM,CAAQ,EACjBA,CACX,QAAE,CACEC,EAAgBP,CAAE,CACtB,CACJ,CAOA,MAAM,SACFR,EAAoC,CAAC,EACf,CAEtB,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,KACjB,CAOA,MAAM,aACFA,EAAoC,CAAC,EACf,CAEtB,OADc,MAAM,KAAK,SAASA,CAAO,GAC5B,SACjB,CAOA,MAAM,UACFA,EAAoC,CAAC,EACf,CACtB,OAAO,KAAK,SAASA,CAAO,EAAE,KAAMM,GAAUA,EAAM,MAAM,CAC9D,CAMA,MAAM,MAAsB,CACxB,MAAM,KAAK,0BAA8C,CAC7D,CAMA,MAAM,UAA0B,CAC5B,MAAM,KAAK,+BAAkD,CACjE,CAOA,MAAM,UAAUE,EAA2B,CACvC,MAAM,KAAK,oBAAoB,cAAgBA,CAAE,CACrD,CAMA,MAAM,MAAsB,CACxB,MAAM,KAAK,0BAA8C,CAC7D,CAMA,MAAM,UAAoC,CACtC,IAAMA,EAAKC,EAAa,EAClBC,EAAaC,EAAc,KAAK,OAAO,EAEvCC,EAAS,MAAMC,EACjBL,cAEA,CAAC,GAAGE,EAAY,UAAU,EAC1B,KAAK,OACT,EACA,GAAI,OAAOE,GAAW,UAAY,CAACA,EAAO,WAAW,OAAO,EACxD,MAAM,IAAI,MAAM,kCAAoCA,CAAM,EAG9DG,EAAgBP,CAAE,EAClB,IAAMQ,EAAQ,qBAed,OAdcJ,EACT,UAAU,CAAC,EACX,MAAM,SAAS,EACf,IAAKK,GAAM,CACR,IAAMC,EAAID,EAAE,MAAMD,CAAK,EACvB,GAAIE,IAAM,KACN,MAAO,CACH,GAAIA,EAAE,CAAC,EACP,OAAQ,IAAM,KAAK,UAAUA,EAAE,CAAC,CAAC,EACjC,KAAMA,EAAE,CAAC,CACb,CAER,CAAC,EAEQ,OAAO,OAAO,CAC/B,CAOA,cAAcf,EAAgC,CAC1C,OAAO,KAAK,OAAO,cAAcA,CAAK,CAC1C,CAUA,UAAUA,EAAoC,CAC1C,OAAO,KAAK,OAAO,UAAUA,CAAK,CACtC,CAMA,MAAM,MAAsB,CACxB,MAAM,KAAK,0BAA8C,CAC7D,CAMA,MAAM,MAAsB,CACxB,MAAM,KAAK,0BAA8C,CAC7D,CASA,IACIA,EACAC,EACI,CACJ,YAAK,OAAO,IAAID,EAAOC,CAAQ,EACxB,IACX,CASA,GACID,EACAC,EACI,CACJ,YAAK,OAAO,GAAGD,EAAOC,CAAQ,EACvB,IACX,CAUA,KACID,EACAC,EACI,CACJ,YAAK,OAAO,KAAKD,EAAOC,CAAQ,EACzB,IACX,CAMA,MAAM,OAAuB,CACzB,MAAM,KAAK,2BAA+C,CAC9D,CAMA,MAAM,MAAsB,CACxB,MAAM,KAAK,0BAA8C,CAC7D,CAMA,MAAM,WAA2B,CAC7B,MAAM,KAAK,gCAAmD,CAClE,CAOA,gBACID,EACAC,EACI,CACJ,YAAK,OAAO,gBAAgBD,EAAOC,CAAQ,EACpC,IACX,CAOA,oBACID,EACAC,EACI,CACJ,YAAK,OAAO,oBAAoBD,EAAOC,CAAQ,EACxC,IACX,CAkBA,MAAM,SAASe,EAAmC,CAC9C,IAAMC,EAAmB,OAAO,QAAQC,CAAqB,EAAE,KAC3D,CAAC,CAACC,CAAC,IAAMH,IAAQG,CACrB,EAEA,GAAI,CAACF,EACD,MAAM,IAAI,MAAM,yBAAyBD,CAAG,GAAG,EAGnD,IAAMI,EAAcH,EAAiB,CAAC,EAClC,mBAA4C,EAAE,SAASD,CAAG,EAC1D,MAAM,KAAK,oBAAoBI,CAAW,EAE1C,MAAM,KAAK,oBAAoBA,CAAW,CAElD,CAMA,MAAM,UAA0B,CAC5B,MAAM,KAAK,8BAAkD,CACjE,CAOA,aAAapB,EAAoC,CAC7C,OAAO,KAAK,OAAO,aAAaA,CAAK,CACzC,CAUA,mBAAmBA,EAA+B,CAC9C,YAAK,OAAO,mBAAmBA,CAAK,EAC7B,IACX,CASA,eACIA,EACAC,EACI,CACJ,YAAK,OAAO,eAAeD,EAAOC,CAAQ,EACnC,IACX,CAMA,MAAM,OAAuB,CACzB,MAAM,KAAK,2BAA+C,CAC9D,CAMA,MAAM,QAAwB,CAC1B,MAAM,KAAK,4BAAgD,CAC/D,CAMA,gBAAgBoB,EAAiB,CAC7B,YAAK,OAAO,gBAAgBA,CAAC,EACtB,IACX,CAMA,MAAM,cAA8B,CAChC,MAAM,KAAK,mCAAsD,CACrE,CAMA,MAAM,aAA6B,CAC/B,MAAM,KAAK,kCAAqD,CACpE,CAMA,MAAM,MAAsB,CACxB,MAAM,KAAK,0BAA8C,CAC7D,CAOA,MAAM,SAAyB,CAC3B,MAAM,KAAK,6BAAiD,CAChE,CAQA,QAGE,CACE,MAAO,CACH,KAAM,KAAK,KACX,GAAI,KAAK,GACT,IAAK,KAAK,IACV,KAAM,KAAK,KACX,SAAU,KAAK,QACnB,CACJ,CAMA,MAAM,SAAyB,CAC3B,MAAM,KAAK,8BAAiD,CAChE,CAOA,UAAmB,CACf,MAAO,mBAAmB,KAAK,IAAI,KAAK,KAAK,IAAI,GACrD,CAMA,MAAM,SAAyB,CAC3B,MAAM,KAAK,8BAAiD,CAChE,CAMA,MAAM,QAAwB,CAC1B,MAAM,KAAK,6BAAgD,CAC/D,CAMA,MAAM,IAAoB,CACtB,MAAM,KAAK,wBAA4C,CAC3D,CAMA,MAAM,YAA4B,CAC9B,MAAM,KAAK,iCAAoD,CACnE,CAMA,MAAM,UAA0B,CAC5B,MAAM,KAAK,+BAAkD,CACjE,CAOA,MAAM,QAAwB,CAC1B,MAAM,KAAK,4BAAgD,CAC/D,CAEA,MAAc,oBAAoBL,EAAqC,CACnE,IAAMX,EAAKC,EAAa,EAClBC,EAAaC,EAAc,KAAK,OAAO,EAE7C,MAAME,EACFL,cAEA,CAAC,GAAGE,EAAYS,CAAG,EACnB,KAAK,OACT,EACAJ,EAAgBP,CAAE,CACtB,CAEA,MAAc,oBAAoBW,EAAqC,CACnE,IAAMX,EAAKC,EAAa,EAClBC,EAAaC,EAAc,KAAK,OAAO,EAEvCC,EAAS,MAAMC,EACjBL,cAEA,CAAC,GAAGE,EAAYS,CAAG,EACnB,KAAK,OACT,EACA,GAAI,OAAOP,GAAW,UAAYA,EAAO,SAAW,UAChD,MAAM,IAAI,MACN,mCAAmC,KAAK,UAAUA,EAAQ,KAAM,IAAI,CAAC,EACzE,EAGJG,EAAgBP,CAAE,CACtB,CAEQ,WAAWM,EAAgC,CAC/C,KAAK,OAAO,wBAAwBA,CAAQ,CAChD,CACJ,EC3gCA,IAAAW,EAAuC,cACvCC,EAA8B,gBAC9BC,EAAmB,wBACnBC,EAA8B,eA4B9B,IAAqBC,EAArB,MAAqBC,CAAkB,CAClB,QAAoC,CAAC,EAc/C,YAAYC,EAAoC,CAAC,EAAG,CACvD,KAAK,QAAU,OAAO,OAAO,CAAC,EAAGA,CAAO,CAC5C,CAQA,aAAoB,MAChBA,EAAoC,CAAC,EACxB,CACb,IAAMC,EAAW,MAAM,KAAK,QAAQD,CAAO,EAC3C,GAAI,CAACC,EAAS,MACV,MAAM,IAAI,MAAM,wCAAwC,EAE5D,GAAI,EAAAC,QAAO,GAAGD,EAAS,MAAO,OAAO,EACjC,MAAM,IAAI,MACN,kEACJ,EAGJ,GAAI,CACA,MAAM,KAAK,KAAKD,CAAO,CAC3B,OAASG,EAAO,CACZ,MAAM,IAAI,MACN,+BAA+B,OAAOA,CAAK,EAAE,QAAQ,UAAW,EAAE,CAAC,EACvE,CACJ,CACJ,CAQA,OAAc,OAAOH,EAAkD,CACnE,OAAO,IAAII,EAAgBJ,CAAO,CACtC,CA8BA,aAAoB,KAChBA,EAA2C,CAAC,EAC5CK,EACwD,CACxD,IAAMC,EAAKC,EAAa,EAClBC,EAAaC,EAAcT,CAAO,EAElCU,EAA6B,CAAC,EAC9BC,EAAoC,CAAC,EACrCC,EAAW,MAAMC,EACnBP,cAEA,CAAC,GAAGE,EAAY,MAAM,EACtB,CAAE,GAAIR,GAAW,CAAC,EAAI,uBAAwB,EAAK,CACvD,EAEA,QAAWc,KAAQF,EACf,GACI,OAAOE,GAAS,UAChB,WAAYA,GACZA,EAAK,SAAW,UAEhBH,EAAO,KAAKG,CAAI,UAEhB,OAAOA,GAAS,UAChB,WAAYA,GACZA,EAAK,SAAW,WAChB,MAAM,QAAQA,EAAK,OAAO,EAE1BJ,EAAQ,KACJ,GAAGI,EAAK,QAAQ,IAAKC,GACjB,KAAK,OACD,OAAO,OAAO,CAAC,EAAGf,EAAS,CACvB,OAAQe,EAAO,gBACf,KAAMA,EAAO,QACb,GAAIA,EAAO,WACX,IAAKA,EAAO,aAAa,KAAO,OAChC,MAAOA,EAAO,aAAa,MAC3B,UAAWA,EAAO,aAAa,UAC/B,KAAMA,EAAO,KACb,GAAIA,EAAO,aAAa,iBACxB,SAAUA,EAAO,SACjB,QAASA,EAAO,aAAa,OACjC,CAAC,CACL,CACJ,CACJ,MAEA,OAAM,IAAI,MACN,mCAAmC,KAAK,UAAUD,EAAM,KAAM,IAAI,CAAC,EACvE,EAKR,GAFAE,EAAgBV,CAAE,EAEdD,EACA,MAAO,CAAE,QAAAK,EAAS,OAAAC,CAAO,EAE7B,GAAI,CAACD,EAAQ,QAAUC,EAAO,OAC1B,MAAM,IAAI,MACN,4CAA4CA,EAAO,MAAM,SAASA,EAAO,SAAW,EAAI,IAAM,EAAE,KAAK,KAAK,UAAUA,EAAQ,KAAM,IAAI,CAAC,EAC3I,EAGJ,OAAOD,CACX,CAQA,aAAoB,QAChBV,EAAoC,CAAC,EACJ,CACjC,IAAMM,EAAKC,EAAa,EACpBU,EAAQ,KACRC,EAAS,KAEb,GAAI,CACAD,EAAS,MAAMJ,EACXP,cAEA,CAAC,WAAW,EACZN,CACJ,CACJ,OAASG,EAAO,CACZgB,EAAMb,EAAI,sCAAsCH,CAAK,GAAIH,CAAO,CACpE,CAEIiB,GAASA,EAAM,OAAO,EAAG,EAAE,IAAM,eACjCA,EAAQA,EAAM,OAAO,EAAE,GAEtB,EAAAf,QAAO,MAAMe,CAAK,IACnBE,EACIb,EACA,WAAWW,CAAK,iDAChBjB,CACJ,EACAiB,EAAQ,MAGZ,GAAI,CACA,IAAMG,KAAkB,WACpB,cAAQ,iBAAcC,CAAe,CAAC,EACtC,KACA,KACA,cACJ,EAIAH,EAHa,KAAK,MACd,MAAM,EAAAI,SAAW,SAASF,EAAiB,MAAM,CACrD,GACe,SAAW,IAC9B,OAASjB,EAAO,CACZgB,EAAMb,EAAI,uCAAuCH,CAAK,GAAIH,CAAO,CACrE,CACA,OAAIkB,GAAU,CAAC,EAAAhB,QAAO,MAAMgB,CAAM,IAC9BC,EACIb,EACA,WAAWY,CAAM,kDACjBlB,CACJ,EACAkB,EAAS,MAGbF,EAAgBV,CAAE,EACX,CACH,OAAAY,EACA,MAAAD,CACJ,CACJ,CAQA,MAAa,MAAMjB,EAAoC,CAAC,EAAkB,CACtE,OAAOD,EAAkB,MACrB,OAAO,OAAO,CAAC,EAAG,KAAK,QAASC,CAAO,CAC3C,CACJ,CAQO,OAAOA,EAAkD,CAC5D,OAAOD,EAAkB,OACrB,OAAO,OAAO,CAAC,EAAG,KAAK,QAASC,CAAO,CAC3C,CACJ,CAgBA,MAAa,KACTA,EAA2C,CAAC,EAClB,CAC1B,OAAOD,EAAkB,KAAK,OAAO,OAAO,CAAC,EAAG,KAAK,QAASC,CAAO,CAAC,CAC1E,CAQA,MAAa,QACTA,EAAoC,CAAC,EACJ,CACjC,OAAOD,EAAkB,QACrB,OAAO,OAAO,CAAC,EAAG,KAAK,QAASC,CAAO,CAC3C,CACJ,CACJ","names":["lib_exports","__export","NodePyATVDevice","NodePyATVDeviceEvent","NodePyATVDeviceEvents","NodePyATVDeviceState","NodePyATVExecutableType","NodePyATVInstance","NodePyATVKeys","NodePyATVListenerState","NodePyATVMediaType","NodePyATVPowerState","NodePyATVProtocol","NodePyATVRepeatState","NodePyATVShuffleState","__toCommonJS","getImportMetaUrl","importMetaUrl","NodePyATVDeviceEvent","values","import_events","import_child_process","NodePyATVDeviceState","NodePyATVExecutableType","NodePyATVFocusState","NodePyATVInternalKeys","NodePyATVKeys","NodePyATVListenerState","NodePyATVMediaType","NodePyATVPowerState","NodePyATVProtocol","NodePyATVRepeatState","NodePyATVShuffleState","requestIds","addRequestId","id","i","compareOutputDevices","a","b","debug","message","options","log","enableColors","parts","execute","requestId","executableType","parameters","executable","getExecutable","mySpawn","child","onStdOut","data","onStdErr","onError","onClose","code","getParameters","parseState","input","d","msg","result","errorStr","date","parseStateStringAttr","NodePyATVMediaType","NodePyATVDeviceState","parseStateNumberAttr","NodePyATVShuffleState","NodePyATVRepeatState","NodePyATVPowerState","NodePyATVFocusState","removeRequestId","request","resolve","reject","pyatv","line","error","output","inputAttr","outputAttr","NodePyATVDeviceEvents","state","device","options","event","listener","newState","keys","k","v","key","oldValue","newValue","compareOutputDevices","NodePyATVDeviceEvent","error","a","b","reqId","debug","cb","update","parseState","id","addRequestId","removeRequestId","data","json","msg","listenStart","parameters","getParameters","execute","onError","onStdErr","onStdOut","s","onClose","code","NodePyATVDevice","debug","options","parseState","NodePyATVDeviceEvents","event","listener","payload","state","position","id","addRequestId","parameters","getParameters","result","request","newState","removeRequestId","regex","i","m","key","internalKeyEntry","NodePyATVInternalKeys","k","internalKey","n","import_fs","import_path","import_semver","import_url","NodePyATVInstance","_NodePyATVInstance","options","versions","semver","error","NodePyATVDevice","returnDevicesAndErrors","id","addRequestId","parameters","getParameters","devices","errors","response","request","item","device","removeRequestId","pyatv","module","debug","packageJsonPath","importMetaUrl","fsPromises"]}
|
|
1
|
+
{"version":3,"sources":["../../src/lib/index.ts","../../node_modules/tsup/assets/cjs_shims.js","../../src/lib/device-event.ts","../../src/lib/device-events.ts","../../src/lib/tools.ts","../../src/lib/types.ts","../../src/lib/device.ts","../../src/lib/instance.ts"],"sourcesContent":["'use strict';\n\nexport { default as NodePyATVDeviceEvent } from './device-event.js';\n\nexport { default as NodePyATVDeviceEvents } from './device-events.js';\nexport { default as NodePyATVDevice } from './device.js';\nexport { default as NodePyATVInstance } from './instance.js';\nexport { default } from './instance.js';\n\nexport {\n type NodePyATVDeviceOptions,\n NodePyATVDeviceState,\n type NodePyATVEventValueType,\n NodePyATVExecutableType,\n type NodePyATVFindAndInstanceOptions,\n type NodePyATVFindOptions,\n type NodePyATVFindResponseObject,\n type NodePyATVGetStateOptions,\n type NodePyATVInstanceOptions,\n NodePyATVKeys,\n NodePyATVListenerState,\n NodePyATVMediaType,\n NodePyATVPowerState,\n NodePyATVProtocol,\n NodePyATVRepeatState,\n type NodePyATVRequestOptions,\n type NodePyATVService,\n NodePyATVShuffleState,\n type NodePyATVState,\n type NodePyATVVersionResponse,\n} from './types.js';\n","// Shim globals in cjs bundle\n// There's a weird bug that esbuild will always inject importMetaUrl\n// if we export it as `const importMetaUrl = ... __filename ...`\n// But using a function will not cause this issue\n\nconst getImportMetaUrl = () => \n typeof document === \"undefined\" \n ? new URL(`file:${__filename}`).href \n : (document.currentScript && document.currentScript.tagName.toUpperCase() === 'SCRIPT') \n ? document.currentScript.src \n : new URL(\"main.js\", document.baseURI).href;\n\nexport const importMetaUrl = /* @__PURE__ */ getImportMetaUrl()\n","'use strict';\n\nimport type { NodePyATVEventValueType, NodePyATVStateIndex } from './types.js';\n\nimport { NodePyATVDevice } from '../lib/index.js';\n\nexport default class NodePyATVDeviceEvent {\n /**\n * References the device instance this\n * event originates from\n */\n get device(): NodePyATVDevice {\n return this.values.device;\n }\n\n /**\n * References the attribute name which was changed. So if the\n * title has been updated, this would be `title`.\n */\n get key(): NodePyATVStateIndex {\n return this.values.key;\n }\n\n /**\n * @alias value\n */\n get newValue(): NodePyATVEventValueType {\n return this.values.new;\n }\n\n /**\n * Holds the old value which was there\n * before the value was changed.\n */\n get oldValue(): NodePyATVEventValueType {\n return this.values.old;\n }\n\n /**\n * New, current value for `key`\n */\n get value(): NodePyATVEventValueType {\n return this.values.new;\n }\n\n protected readonly values: {\n device: NodePyATVDevice;\n key: NodePyATVStateIndex;\n new: NodePyATVEventValueType;\n old: NodePyATVEventValueType;\n };\n\n /**\n *\n * @param values\n * @internal\n */\n constructor(values: {\n device: NodePyATVDevice;\n key: NodePyATVStateIndex;\n new: NodePyATVEventValueType;\n old: NodePyATVEventValueType;\n }) {\n this.values = Object.assign({}, values, {\n key: values.key as NodePyATVStateIndex,\n });\n }\n}\n","'use strict';\n\nimport { ChildProcess } from 'child_process';\nimport { EventEmitter } from 'events';\n\nimport { NodePyATVDevice, NodePyATVDeviceEvent } from '../lib/index.js';\nimport { FakeChildProcess } from './fake-spawn.js';\nimport {\n addRequestId,\n compareOutputDevices,\n debug,\n execute,\n getParameters,\n parseState,\n removeRequestId,\n} from './tools.js';\nimport {\n type NodePyATVDeviceOptions,\n NodePyATVExecutableType,\n type NodePyATVInternalState,\n NodePyATVListenerState,\n type NodePyATVState,\n type NodePyATVStateIndex,\n} from './types.js';\n\n/**\n * @internal\n */\nexport default class NodePyATVDeviceEvents extends EventEmitter {\n private readonly device: NodePyATVDevice;\n private listenerState: NodePyATVListenerState;\n private readonly options: NodePyATVDeviceOptions;\n private pyatv: ChildProcess | FakeChildProcess | undefined;\n private readonly state: NodePyATVState;\n private timeout: NodeJS.Timeout | undefined;\n\n constructor(\n state: NodePyATVState,\n device: NodePyATVDevice,\n options: NodePyATVDeviceOptions,\n ) {\n super();\n\n this.state = state;\n this.device = device;\n this.options = Object.assign({}, options);\n this.listenerState = NodePyATVListenerState.stopped;\n }\n\n addListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.addListener(event, listener);\n this.checkListener();\n return this;\n }\n\n applyStateAndEmitEvents(newState: NodePyATVState): void {\n let keys = Object.keys(this.state);\n\n // Remove special fields from the list\n keys = keys.filter(\n (k) =>\n ![\n 'focusState',\n 'outputDevices',\n 'powerState',\n 'volume',\n ].includes(k),\n );\n\n if ('powerState' in newState && newState.powerState) {\n keys = ['powerState'];\n }\n if ('focusState' in newState && newState.focusState) {\n keys = ['focusState'];\n }\n if ('outputDevices' in newState && newState.outputDevices) {\n keys = ['outputDevices'];\n }\n\n // Volume events don't hold the complete state…\n // see https://github.com/sebbo2002/node-pyatv/pull/291\n if ('volume' in newState && newState.volume !== null) {\n keys = ['volume'];\n }\n\n // If all values are null, we don't need to emit events at all\n // https://github.com/sebbo2002/node-pyatv/issues/295#issuecomment-1888640079\n if (\n !Object.entries(newState).find(\n ([k, v]) => !['dateTime', 'result'].includes(k) && v !== null,\n )\n ) {\n return;\n }\n\n keys.forEach((key: string) => {\n // @ts-expect-error this.state has no index signature\n const oldValue = this.state[key];\n\n // @ts-expect-error same here\n const newValue = newState[key];\n\n if (\n oldValue === undefined ||\n newValue === undefined ||\n oldValue === newValue\n ) {\n return;\n }\n if (\n key === 'outputDevices' &&\n compareOutputDevices(oldValue, newValue)\n ) {\n return;\n }\n\n const event = new NodePyATVDeviceEvent({\n device: this.device,\n key: key as NodePyATVStateIndex,\n new: newValue,\n old: oldValue,\n });\n\n // @ts-expect-error and here\n this.state[key] = newState[key];\n\n try {\n this.emit('update:' + key, event);\n this.emit('update', event);\n } catch (error) {\n this.emit('error', error);\n }\n });\n }\n\n listenerCount(event?: string | symbol): number {\n if (event !== undefined) {\n return super.listenerCount(event);\n }\n\n return this.eventNames()\n .map((event) => this.listenerCount(event))\n .reduce((a, b) => a + b, 0);\n }\n\n off(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.off(event, listener);\n this.checkListener();\n return this;\n }\n\n on(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.on(event, listener);\n this.checkListener();\n return this;\n }\n\n once(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.once(event, (event: NodePyATVDeviceEvent) => {\n listener(event);\n setTimeout(() => this.checkListener(), 0);\n });\n this.checkListener();\n return this;\n }\n\n prependListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.prependListener(event, listener);\n this.checkListener();\n return this;\n }\n\n removeAllListeners(event?: string | symbol): this {\n super.removeAllListeners(event);\n this.checkListener();\n return this;\n }\n\n removeListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n super.removeListener(event, listener);\n this.checkListener();\n return this;\n }\n\n protected async stopListening(reqId: string): Promise<void> {\n if (\n this.listenerState !== NodePyATVListenerState.starting &&\n this.listenerState !== NodePyATVListenerState.started\n ) {\n return;\n }\n\n this.listenerState = NodePyATVListenerState.stopping;\n if (this.pyatv === undefined) {\n throw new Error(\n \"Unable to stop listening due to internal error: state is stopping, but there's no child process. \" +\n 'This should never happen, please report this.',\n );\n }\n\n if (this.pyatv.stdin) {\n debug(reqId, 'Pressing enter to close atvscript…', this.options);\n this.pyatv.stdin.write('\\n');\n\n await new Promise((cb) => (this.timeout = setTimeout(cb, 250)));\n }\n\n if (\n this.listenerState === NodePyATVListenerState.stopping &&\n this.pyatv\n ) {\n this.pyatv.kill();\n }\n\n this.listenerState = NodePyATVListenerState.stopped;\n return;\n }\n\n private applyPushUpdate(\n update: NodePyATVInternalState,\n reqId: string,\n ): void {\n try {\n const newState = parseState(update, reqId, this.options);\n this.applyStateAndEmitEvents(newState);\n } catch (error) {\n this.emit('error', error);\n }\n }\n\n private checkListener(): void {\n if (\n this.listenerState === NodePyATVListenerState.stopped &&\n this.listenerCount() === 0 &&\n this.timeout\n ) {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n } else if (\n this.listenerState === NodePyATVListenerState.stopped &&\n this.listenerCount() > 0\n ) {\n const id = addRequestId();\n debug(\n id,\n `Start listeing to events from device ${this.options.name}`,\n this.options,\n );\n\n this.startListening(id);\n removeRequestId(id);\n } else if (\n [\n NodePyATVListenerState.started,\n NodePyATVListenerState.starting,\n ].includes(this.listenerState) &&\n this.listenerCount() === 0\n ) {\n const id = addRequestId();\n debug(\n id,\n `Stop listening to events from device ${this.options.name}`,\n this.options,\n );\n\n this.stopListening(id)\n .catch((error) =>\n debug(\n id,\n `Unable to stop listeing: ${error}`,\n this.options,\n ),\n )\n .finally(() => removeRequestId(id));\n }\n }\n\n private parsePushUpdate(reqId: string, data: string): void {\n let json: NodePyATVInternalState;\n\n try {\n json = JSON.parse(data);\n } catch (error) {\n const msg = `Unable to parse stdout json: ${error}`;\n debug(reqId, msg, this.options);\n this.emit('error', new Error(msg));\n return;\n }\n\n this.applyPushUpdate(json, reqId);\n\n if (this.listenerState === NodePyATVListenerState.starting) {\n this.listenerState = NodePyATVListenerState.started;\n this.checkListener();\n }\n }\n\n private startListening(reqId: string): void {\n if (this.listenerState !== NodePyATVListenerState.stopped) {\n return;\n }\n\n this.listenerState = NodePyATVListenerState.starting;\n\n const listenStart = new Date().getTime();\n const parameters = getParameters(this.options);\n this.pyatv = execute(\n reqId,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'push_updates'],\n this.options,\n );\n if (!this.pyatv) {\n throw new Error(\n 'Unable to start listener: Unable to start atvscript',\n );\n }\n\n const onError = (error: Error) => {\n debug(\n reqId,\n `Got error from child process: ${error}`,\n this.options,\n );\n this.emit('error', error);\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onStdErr = (data: any) => {\n const error = new Error(`Got stderr output from pyatv: ${data}`);\n debug(reqId, data.toString(), this.options);\n this.emit('error', error);\n };\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const onStdOut = (data: any) => {\n String(data)\n .split('\\n')\n .map((s) => s.trim())\n .filter(Boolean)\n .forEach((s) => {\n debug(reqId, `> ${s}`, this.options);\n this.parsePushUpdate(reqId, s);\n });\n };\n const onClose = (code: number) => {\n if (this.pyatv === undefined) {\n // this should never happen… :/\n return;\n }\n\n this.listenerState = NodePyATVListenerState.stopped;\n debug(\n reqId,\n `Listening with atvscript exited with code ${code}`,\n this.options,\n );\n if (this.timeout !== undefined) {\n clearTimeout(this.timeout);\n this.timeout = undefined;\n }\n\n if (this.pyatv.stdout) {\n this.pyatv.stdout.off('data', onStdOut);\n }\n if (this.pyatv.stderr) {\n this.pyatv.stderr.off('data', onStdErr);\n }\n this.pyatv.off('error', onError);\n this.pyatv.off('close', onClose);\n\n if (\n this.listenerCount() > 0 &&\n new Date().getTime() - listenStart < 30000\n ) {\n debug(\n reqId,\n `Wait 15s and restart listeing to events from device ${this.options.name}`,\n this.options,\n );\n\n this.timeout = setTimeout(() => {\n this.checkListener();\n }, 15000);\n } else if (this.listenerCount() > 0) {\n debug(\n reqId,\n `Restart listeing to events from device ${this.options.name}`,\n this.options,\n );\n this.checkListener();\n }\n\n removeRequestId(reqId);\n };\n\n this.pyatv.on('error', onError);\n this.pyatv.on('close', onClose);\n\n if (this.pyatv.stdout) {\n this.pyatv.stdout.on('data', onStdOut);\n }\n if (this.pyatv.stderr) {\n this.pyatv.stderr.on('data', onStdErr);\n }\n }\n}\n","'use strict';\n\nimport { ChildProcess, spawn, type SpawnOptions } from 'child_process';\n\nimport { FakeChildProcess } from './fake-spawn.js';\nimport {\n NodePyATVDeviceState,\n NodePyATVExecutableType,\n type NodePyATVFindAndInstanceOptions,\n NodePyATVFocusState,\n type NodePyATVInstanceOptions,\n type NodePyATVInternalState,\n NodePyATVMediaType,\n NodePyATVPowerState,\n NodePyATVRepeatState,\n type NodePyATVRequestOptions,\n NodePyATVShuffleState,\n type NodePyATVState,\n} from './types.js';\n\nconst requestIds: string[] = [];\n\ntype NodePyATVScriptResponse<O extends NodePyATVRequestOptions> =\n O['allowMultipleResponses'] extends true\n ? Record<string, unknown>[]\n : Record<string, unknown>;\n\nexport function addRequestId(): string {\n let id = '?';\n\n for (let i = 0; i < 1000; i += 1) {\n id = Math.round(Math.random() * (i + 6) * 36)\n .toString(36)\n .toUpperCase();\n if (!requestIds.includes(id)) {\n requestIds.push(id);\n break;\n }\n }\n\n return id;\n}\n\nexport function compareOutputDevices(\n a: NodePyATVState['outputDevices'],\n b: NodePyATVState['outputDevices'],\n) {\n return Boolean(\n Array.isArray(a) &&\n Array.isArray(b) &&\n JSON.stringify(\n a.sort((a, b) => (a.identifier < b.identifier ? -1 : 1)),\n ) ===\n JSON.stringify(\n b.sort((a, b) => (a.identifier < b.identifier ? -1 : 1)),\n ),\n );\n}\n\nexport function debug(\n id: string,\n message: string,\n options: NodePyATVInstanceOptions,\n): void {\n if (options.debug) {\n const log =\n typeof options.debug === 'function' ? options.debug : console.log;\n const enableColors = !process.env.NO_COLOR && !options.noColors;\n\n const parts = [\n enableColors ? '\\x1b[0m' : '', // Color Reset\n enableColors ? '\\x1b[90m' : '', // Grey\n '[node-pyatv][',\n enableColors ? '\\x1b[37m' : '', // Light Grey\n id,\n enableColors ? '\\x1b[90m' : '', // Grey\n '] ',\n enableColors ? '\\x1b[0m' : '', // Color Reset\n message,\n ];\n\n log.apply(null, [parts.join('')]);\n }\n}\n\nexport function execute(\n requestId: string,\n executableType: NodePyATVExecutableType,\n parameters: string[],\n options: NodePyATVInstanceOptions,\n): ChildProcess | FakeChildProcess {\n const executable = getExecutable(executableType, options);\n const mySpawn: (\n command: string,\n args: Array<string>,\n options: SpawnOptions,\n ) => ChildProcess | FakeChildProcess =\n typeof options.spawn === 'function' ? options.spawn : spawn;\n\n debug(requestId, `${executable} ${parameters.join(' ')}`, options);\n const child = mySpawn(executable, parameters, {\n env: process.env,\n });\n\n /* eslint-disable @typescript-eslint/no-explicit-any*/\n const onStdOut = (data: any) =>\n debug(requestId, `stdout: ${String(data).trim()}`, options);\n const onStdErr = (data: any) =>\n debug(requestId, `stderr: ${String(data).trim()}`, options);\n const onError = (data: any) =>\n debug(requestId, `error: ${String(data).trim()}`, options);\n /* eslint-enable @typescript-eslint/no-explicit-any*/\n\n const onClose = (code: number) => {\n debug(requestId, `${executable} exited with code: ${code}`, options);\n\n if (child.stdout) {\n child.stdout.off('data', onStdOut);\n }\n if (child.stderr) {\n child.stderr.off('data', onStdErr);\n }\n\n child.off('error', onError);\n child.off('close', onClose);\n };\n\n if (child.stdout) {\n child.stdout.on('data', onStdOut);\n }\n if (child.stderr) {\n child.stderr.on('data', onStdErr);\n }\n\n child.on('error', onError);\n child.on('close', onClose);\n\n return child;\n}\n\nexport function getExecutable(\n executable: NodePyATVExecutableType,\n options: NodePyATVInstanceOptions,\n): string {\n if (\n executable === NodePyATVExecutableType.atvremote &&\n typeof options.atvremotePath === 'string'\n ) {\n return options.atvremotePath;\n } else if (\n executable === NodePyATVExecutableType.atvscript &&\n typeof options.atvscriptPath === 'string'\n ) {\n return options.atvscriptPath;\n } else {\n return executable;\n }\n}\n\nexport function getParameters(\n options: NodePyATVFindAndInstanceOptions = {},\n): string[] {\n const parameters: string[] = [];\n\n if (options.hosts) {\n parameters.push('-s', options.hosts.join(','));\n } else if (options.host) {\n parameters.push('-s', options.host);\n }\n if (options.id) {\n parameters.push('-i', options.id);\n }\n if (options.protocol) {\n parameters.push('--protocol', options.protocol);\n }\n if (options.dmapCredentials) {\n parameters.push('--dmap-credentials', options.dmapCredentials);\n }\n if (options.mrpCredentials) {\n parameters.push('--mrp-credentials', options.mrpCredentials);\n }\n if (options.airplayCredentials) {\n parameters.push('--airplay-credentials', options.airplayCredentials);\n }\n if (options.companionCredentials) {\n parameters.push(\n '--companion-credentials',\n options.companionCredentials,\n );\n }\n if (options.raopCredentials) {\n parameters.push('--raop-credentials', options.raopCredentials);\n }\n\n return parameters;\n}\nexport function parseState(\n input: NodePyATVInternalState,\n id: string,\n options: NodePyATVInstanceOptions,\n): NodePyATVState {\n const d = (msg: string) => debug(id, msg, options);\n const result: NodePyATVState = {\n album: null,\n app: null,\n appId: null,\n artist: null,\n contentIdentifier: null,\n dateTime: null,\n deviceState: null,\n episodeNumber: null,\n focusState: null,\n genre: null,\n hash: null,\n iTunesStoreIdentifier: null,\n mediaType: null,\n outputDevices: null,\n position: null,\n powerState: null,\n repeat: null,\n seasonNumber: null,\n seriesName: null,\n shuffle: null,\n title: null,\n totalTime: null,\n volume: null,\n };\n if (!input || typeof input !== 'object') {\n return result;\n }\n if (input.exception) {\n let errorStr = 'Got pyatv Error: ' + input.exception;\n if (input.stacktrace) {\n errorStr += '\\n\\npyatv Stacktrace:\\n' + input.stacktrace;\n }\n\n throw new Error(errorStr);\n }\n\n // datetime\n if (typeof input.datetime === 'string') {\n const date = new Date(input.datetime);\n if (!isNaN(date.getTime())) {\n result.dateTime = date;\n } else {\n d(`Invalid datetime value ${input.datetime}, ignore attribute`);\n }\n } else {\n d(`No datetime value found in input (${JSON.stringify(input)})`);\n }\n\n // hash\n parseStateStringAttr(input, result, 'hash', 'hash', d);\n\n // mediaType\n if (typeof input.media_type === 'string') {\n const validValues = Object.keys(NodePyATVMediaType).map((o) =>\n String(o),\n );\n if (validValues.includes(input.media_type)) {\n result.mediaType =\n NodePyATVMediaType[input.media_type as NodePyATVMediaType];\n } else {\n d(\n `Unsupported mediaType value ${input.media_type}, ignore attribute`,\n );\n }\n } else {\n d(`No mediaType value found in input (${JSON.stringify(input)})`);\n }\n\n // deviceState\n if (typeof input.device_state === 'string') {\n const validValues = Object.keys(NodePyATVDeviceState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.device_state)) {\n result.deviceState =\n NodePyATVDeviceState[\n input.device_state as NodePyATVDeviceState\n ];\n } else {\n d(\n `Unsupported deviceState value ${input.device_state}, ignore attribute`,\n );\n }\n } else {\n d(`No deviceState value found in input (${JSON.stringify(input)})`);\n }\n\n // title\n parseStateStringAttr(input, result, 'title', 'title', d);\n\n // artist\n parseStateStringAttr(input, result, 'artist', 'artist', d);\n\n // album\n parseStateStringAttr(input, result, 'album', 'album', d);\n\n // genre\n parseStateStringAttr(input, result, 'genre', 'genre', d);\n\n // totalTime\n parseStateNumberAttr(input, result, 'total_time', 'totalTime', d);\n\n // position\n parseStateNumberAttr(input, result, 'position', 'position', d);\n\n // shuffle\n if (typeof input.shuffle === 'string') {\n const validValues = Object.keys(NodePyATVShuffleState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.shuffle)) {\n result.shuffle =\n NodePyATVShuffleState[input.shuffle as NodePyATVShuffleState];\n } else {\n d(`Unsupported shuffle value ${input.shuffle}, ignore attribute`);\n }\n } else {\n d(`No shuffle value found in input (${JSON.stringify(input)})`);\n }\n\n // repeat\n if (typeof input.repeat === 'string') {\n const validValues = Object.keys(NodePyATVRepeatState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.repeat)) {\n result.repeat =\n NodePyATVRepeatState[input.repeat as NodePyATVRepeatState];\n } else {\n d(`Unsupported repeat value ${input.repeat}, ignore attribute`);\n }\n } else {\n d(`No repeat value found in input (${JSON.stringify(input)})`);\n }\n\n // app\n parseStateStringAttr(input, result, 'app', 'app', d);\n parseStateStringAttr(input, result, 'app_id', 'appId', d);\n\n // powerState\n if (typeof input.power_state === 'string') {\n const validValues = Object.keys(NodePyATVPowerState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.power_state)) {\n result.powerState =\n NodePyATVPowerState[input.power_state as NodePyATVPowerState];\n } else {\n d(\n `Unsupported powerState value ${input.power_state}, ignore attribute`,\n );\n }\n } else {\n d(`No powerState value found in input (${JSON.stringify(input)})`);\n }\n\n // volume\n parseStateNumberAttr(input, result, 'volume', 'volume', d);\n\n // focusState\n if (typeof input.focus_state === 'string') {\n const validValues = Object.keys(NodePyATVFocusState).map((o) =>\n String(o),\n );\n if (validValues.includes(input.focus_state)) {\n result.focusState =\n NodePyATVFocusState[input.focus_state as NodePyATVFocusState];\n } else {\n d(\n `Unsupported focusState value ${input.focus_state}, ignore attribute`,\n );\n }\n } else {\n d(`No focusState value found in input (${JSON.stringify(input)})`);\n }\n\n // outputDevices\n if (Array.isArray(input.output_devices)) {\n result.outputDevices = input.output_devices;\n }\n\n // contentIdentifier\n parseStateStringAttr(\n input,\n result,\n 'content_identifier',\n 'contentIdentifier',\n d,\n );\n\n // iTunesStoreIdentifier\n parseStateNumberAttr(\n input,\n result,\n 'itunes_store_identifier',\n 'iTunesStoreIdentifier',\n d,\n );\n\n // episodeNumber\n parseStateNumberAttr(input, result, 'episode_number', 'episodeNumber', d);\n\n // seasonNumber\n parseStateNumberAttr(input, result, 'season_number', 'seasonNumber', d);\n\n // seriesName\n parseStateStringAttr(input, result, 'series_name', 'seriesName', d);\n\n return result;\n}\nexport function removeRequestId(id: string | undefined): void {\n if (id && requestIds.includes(id)) {\n requestIds.splice(requestIds.indexOf(id), 1);\n }\n}\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType.atvscript,\n parameters: string[],\n options: O,\n): Promise<NodePyATVScriptResponse<O>>;\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType.atvremote,\n parameters: string[],\n options: O,\n): Promise<string>;\n\nexport async function request<O extends NodePyATVRequestOptions>(\n requestId: string,\n executableType: NodePyATVExecutableType,\n parameters: string[],\n options: O,\n): Promise<Record<string, unknown> | Record<string, unknown>[] | string> {\n const result = {\n code: 0,\n stderr: '',\n stdout: '',\n };\n\n await new Promise((resolve, reject) => {\n const pyatv = execute(requestId, executableType, parameters, options);\n\n /* eslint-disable @typescript-eslint/no-explicit-any*/\n const onStdOut = (data: any) => (result.stdout += String(data).trim());\n const onStdErr = (data: any) => (result.stderr += String(data).trim());\n const onError = (data: any) =>\n reject(data instanceof Error ? data : new Error(String(data)));\n /* eslint-enable @typescript-eslint/no-explicit-any*/\n\n const onClose: (code: number) => void = (code: number) => {\n result.code = code;\n\n if (pyatv.stdout) {\n pyatv.stdout.off('data', onStdOut);\n }\n if (pyatv.stderr) {\n pyatv.stderr.off('data', onStdErr);\n }\n\n pyatv.off('error', onError);\n pyatv.off('close', onClose);\n resolve(undefined);\n };\n\n if (pyatv.stdout) {\n pyatv.stdout.on('data', onStdOut);\n }\n if (pyatv.stderr) {\n pyatv.stderr.on('data', onStdErr);\n }\n\n pyatv.on('error', onError);\n pyatv.on('close', onClose);\n });\n\n if (result.stderr.length > 0) {\n const msg = `Unable to execute request ${requestId}: ${result.stderr}`;\n debug(requestId, msg, options);\n throw new Error(msg);\n }\n\n if (executableType === NodePyATVExecutableType.atvscript) {\n try {\n // response with multiple lines\n // https://github.com/sebbo2002/node-pyatv/issues/324\n if (options.allowMultipleResponses) {\n return result.stdout\n .split('\\n')\n .filter((line) => line.trim().length > 0)\n .map((line) => JSON.parse(line));\n }\n\n return JSON.parse(result.stdout);\n } catch (error) {\n const msg = `Unable to parse result ${requestId} json: ${error}`;\n debug(requestId, msg, options);\n throw new Error(msg);\n }\n }\n\n return result.stdout;\n}\n\nfunction parseStateNumberAttr(\n input: NodePyATVInternalState,\n output: NodePyATVState,\n inputAttr:\n | 'episode_number'\n | 'itunes_store_identifier'\n | 'position'\n | 'season_number'\n | 'total_time'\n | 'volume',\n outputAttr:\n | 'episodeNumber'\n | 'iTunesStoreIdentifier'\n | 'position'\n | 'seasonNumber'\n | 'totalTime'\n | 'volume',\n d: (msg: string) => void,\n): void {\n if (typeof input[inputAttr] === 'number') {\n output[outputAttr] = input[inputAttr];\n return;\n }\n\n d(`No ${outputAttr} value found in input (${JSON.stringify(input)})`);\n}\n\nfunction parseStateStringAttr(\n input: NodePyATVInternalState,\n output: NodePyATVState,\n inputAttr:\n | 'album'\n | 'app'\n | 'app_id'\n | 'artist'\n | 'content_identifier'\n | 'genre'\n | 'hash'\n | 'series_name'\n | 'title',\n outputAttr:\n | 'album'\n | 'app'\n | 'appId'\n | 'artist'\n | 'contentIdentifier'\n | 'genre'\n | 'hash'\n | 'seriesName'\n | 'title',\n d: (msg: string) => void,\n): void {\n if (typeof input[inputAttr] === 'string') {\n output[outputAttr] = input[inputAttr] as string;\n return;\n }\n\n d(`No ${outputAttr} value found in input (${JSON.stringify(input)})`);\n}\n","import { ChildProcess, type SpawnOptions } from 'child_process';\n\nimport type NodePyATVDevice from './device.js';\n\nimport { FakeChildProcess } from './fake-spawn.js';\n\nexport enum NodePyATVDeviceState {\n idle = 'idle',\n loading = 'loading',\n paused = 'paused',\n playing = 'playing',\n seeking = 'seeking',\n stopped = 'stopped',\n}\n\nexport enum NodePyATVExecutableType {\n atvremote = 'atvremote',\n atvscript = 'atvscript',\n}\n\nexport enum NodePyATVFocusState {\n // @deprecated Please use `NodePyATVFocusState.focused` instead\n focued = 'focused',\n\n // Doublicate enum value due to typo, will be removed in next breaking change\n // @todo remove in next breaking change\n // eslint-disable-next-line @typescript-eslint/no-duplicate-enum-values\n focused = 'focused',\n\n unfocused = 'unfocused',\n}\n\n/**\n * @internal\n */\nexport enum NodePyATVInternalKeys {\n down = 'down',\n home = 'home',\n homeHold = 'home_hold',\n left = 'left',\n menu = 'menu',\n next = 'next',\n pause = 'pause',\n play = 'play',\n playPause = 'play_pause',\n previous = 'previous',\n right = 'right',\n select = 'select',\n skipBackward = 'skip_backward',\n skipForward = 'skip_forward',\n stop = 'stop',\n suspend = 'suspend',\n topMenu = 'top_menu',\n turnOff = 'turn_off',\n turnOn = 'turn_on',\n up = 'up',\n volumeDown = 'volume_down',\n volumeUp = 'volume_up',\n wakeup = 'wakeup',\n}\n\nexport enum NodePyATVKeys {\n down = 'down',\n home = 'home',\n homeHold = 'homeHold',\n left = 'left',\n menu = 'menu',\n next = 'next',\n pause = 'pause',\n play = 'play',\n playPause = 'playPause',\n previous = 'previous',\n right = 'right',\n select = 'select',\n skipBackward = 'skipBackward',\n skipForward = 'skipForward',\n stop = 'stop',\n suspend = 'suspend',\n topMenu = 'topMenu',\n turnOff = 'turnOff',\n turnOn = 'turnOn',\n up = 'up',\n volumeDown = 'volumeDown',\n volumeUp = 'volumeUp',\n wakeup = 'wakeup',\n}\n\nexport enum NodePyATVListenerState {\n stopped,\n starting,\n started,\n stopping,\n}\n\nexport enum NodePyATVMediaType {\n music = 'music',\n tv = 'tv',\n unknown = 'unknown',\n video = 'video',\n}\n\nexport enum NodePyATVPowerState {\n off = 'off',\n on = 'on',\n}\n\nexport enum NodePyATVProtocol {\n airplay = 'airplay',\n dmap = 'dmap',\n mdns = 'mdns',\n mrp = 'mrp',\n}\n\nexport enum NodePyATVRepeatState {\n all = 'all',\n off = 'off',\n track = 'track',\n}\n\nexport enum NodePyATVShuffleState {\n albums = 'albums',\n off = 'off',\n songs = 'songs',\n}\n\nexport interface NodePyATVApp {\n id: string;\n launch: () => Promise<void>;\n name: string;\n}\n\nexport interface NodePyATVDeviceOptions\n extends NodePyATVFindAndInstanceOptions {\n allIDs?: string[];\n host?: string;\n mac?: string;\n model?: string;\n modelName?: string;\n name: string;\n os?: string;\n services?: NodePyATVService[];\n version?: string;\n}\n\nexport type NodePyATVEventValueType =\n | NodePyATVDeviceState\n | NodePyATVMediaType\n | NodePyATVRepeatState\n | NodePyATVShuffleState\n | number\n | string;\n\nexport interface NodePyATVFindAndInstanceOptions\n extends NodePyATVFindOptions,\n NodePyATVInstanceOptions {}\n\nexport interface NodePyATVFindOptions {\n airplayCredentials?: string;\n companionCredentials?: string;\n dmapCredentials?: string;\n host?: string;\n hosts?: string[];\n id?: string;\n mrpCredentials?: string;\n protocol?: NodePyATVProtocol;\n raopCredentials?: string;\n}\n\nexport interface NodePyATVFindResponseObject {\n devices: NodePyATVDevice[];\n errors: Record<string, unknown>[];\n}\n\nexport interface NodePyATVGetStateOptions {\n maxAge?: number;\n}\n\nexport interface NodePyATVInstanceOptions {\n atvremotePath?: string;\n atvscriptPath?: string;\n debug?: ((msg: string) => void) | true;\n noColors?: true;\n spawn?: (\n command: string,\n args: Array<string>,\n options: SpawnOptions,\n ) => ChildProcess | FakeChildProcess;\n}\n\n/**\n * @internal\n */\nexport interface NodePyATVInternalScanDevice {\n address: string;\n all_identifiers: string[];\n device_info?: {\n mac: null | string;\n model: string;\n model_str: string;\n operating_system: string;\n version: string;\n };\n identifier: string;\n name: string;\n services?: NodePyATVService[];\n}\n\n/**\n * @internal\n */\nexport interface NodePyATVInternalState {\n album?: string | unknown;\n app?: string | unknown;\n app_id?: string | unknown;\n artist?: string | unknown;\n connection?: string | unknown;\n content_identifier?: null | string;\n datetime?: string | unknown;\n device_state?: string | unknown;\n episode_number?: null | number;\n exception?: string | unknown;\n focus_state?: string | unknown;\n genre?: string | unknown;\n hash?: string | unknown;\n itunes_store_identifier?: null | number;\n media_type?: string | unknown;\n output_devices?: Array<{ identifier: string; name: string }> | null;\n position?: 1 | unknown;\n power_state?: string | unknown;\n push_updates?: string | unknown;\n repeat?: string | unknown;\n result?: string | unknown;\n season_number?: null | number;\n series_name?: null | string;\n shuffle?: string | unknown;\n stacktrace?: string | unknown;\n title?: string | unknown;\n total_time?: number | unknown;\n volume?: number | unknown;\n}\n\nexport interface NodePyATVRequestOptions extends NodePyATVInstanceOptions {\n allowMultipleResponses?: boolean;\n}\n\nexport interface NodePyATVService {\n port: number;\n protocol: NodePyATVProtocol;\n}\n\nexport interface NodePyATVState {\n album: null | string;\n app: null | string;\n appId: null | string;\n artist: null | string;\n contentIdentifier: null | string;\n dateTime: Date | null;\n deviceState: NodePyATVDeviceState | null;\n episodeNumber: null | number;\n focusState: NodePyATVFocusState | null;\n genre: null | string;\n hash: null | string;\n iTunesStoreIdentifier: null | number;\n mediaType: NodePyATVMediaType | null;\n outputDevices: Array<{ identifier: string; name: string }> | null;\n position: null | number;\n powerState: NodePyATVPowerState | null;\n repeat: NodePyATVRepeatState | null;\n seasonNumber: null | number;\n seriesName: null | string;\n shuffle: NodePyATVShuffleState | null;\n title: null | string;\n totalTime: null | number;\n volume: null | number;\n}\n\nexport type NodePyATVStateIndex = keyof NodePyATVState;\n\nexport interface NodePyATVVersionResponse {\n module: null | string;\n pyatv: null | string;\n}\n","'use strict';\n\nimport { EventEmitter } from 'events';\n\nimport { NodePyATVDeviceEvent, NodePyATVDeviceEvents } from '../lib/index.js';\nimport {\n addRequestId,\n getParameters,\n parseState,\n removeRequestId,\n request,\n} from './tools.js';\nimport {\n type NodePyATVApp,\n type NodePyATVDeviceOptions,\n NodePyATVDeviceState,\n NodePyATVExecutableType,\n NodePyATVFocusState,\n type NodePyATVGetStateOptions,\n NodePyATVInternalKeys,\n NodePyATVKeys,\n NodePyATVMediaType,\n NodePyATVPowerState,\n NodePyATVProtocol,\n NodePyATVRepeatState,\n type NodePyATVService,\n NodePyATVShuffleState,\n type NodePyATVState,\n} from './types.js';\n\n/**\n * Represents an Apple TV. Use [[getState]] to query the current state (e.g. media\n * type and title). You can also use the attribute methods (e.g. [[getTitle]] to get\n * the state. If you want realtime updates, subscribe to it's events with an\n * `EventEmitter` like API, so for example by using [[on]], [[once]] or [[addListener]].\n * It's also possible to send key commands by using [[pressKey]] or methods like [[pause]].\n */\nexport default class NodePyATVDevice implements EventEmitter {\n /**\n * Get all IDs of the Apple TV.\n * Requires pyatv >= 0.14.5.\n */\n get allIDs(): string[] | undefined {\n return this.options.allIDs;\n }\n /**\n * Returns true, if debugging is enabled. Returns the custom\n * logging method, if one was specified. Otherwise, if debug\n * log is disabled, returns undefined.\n */\n get debug(): ((msg: string) => void) | true | undefined {\n return this.options.debug;\n }\n /**\n * Enable or disable debugging or set a custom\n * debugging method to use.\n *\n * @param debug\n */\n set debug(debug: ((msg: string) => void) | true | undefined) {\n if (typeof debug === 'function') {\n this.options.debug = debug;\n } else {\n this.options.debug = Boolean(debug) || undefined;\n }\n }\n\n /**\n * Get the IP address of the Apple TV.\n */\n get host(): string | undefined {\n return this.options.host;\n }\n\n /**\n * Get the ID of the Apple TV.\n */\n get id(): string | undefined {\n return this.options.id;\n }\n\n /**\n * Get the MAC address of the Apple TV.\n * Requires pyatv >= 0.14.5.\n */\n get mac(): string | undefined {\n return this.options.mac;\n }\n\n /**\n * Get the model identifier of the device. Only set, if the\n * device was found using [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.model → \"Gen4K\"\n */\n get model(): string | undefined {\n return this.options.model;\n }\n\n /**\n * Get the model name of the device. Only set, if the device\n * was found with [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.modelName → \"Apple TV 4K\"\n */\n get modelName(): string | undefined {\n return this.options.modelName;\n }\n\n /**\n * Get the name of the Apple TV.\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const devices = await pyatv.find();\n * devices.forEach(device =>\n * console.log(device.name)\n * );\n * ```\n */\n get name(): string {\n return this.options.name;\n }\n\n /**\n * Get the operating system of the device. Only set, if the\n * device was found with [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.os → \"TvOS\"\n */\n get os(): string | undefined {\n return this.options.os;\n }\n\n /**\n * Get the used protocol to connect to the Apple TV.\n */\n get protocol(): NodePyATVProtocol | undefined {\n return this.options.protocol;\n }\n\n /**\n * Returns a list of services supported by the device. Ony set, if\n * the device was found during a scan using [[find()]]. Requires\n * pyatv ≧ 0.10.3.\n *\n * @example device.services → [\n * {\n * \"protocol\": \"airplay\",\n * \"port\": 7000\n * },\n * {\n * \"protocol\": \"dmap\",\n * \"port\": 3689\n * }\n * ]\n */\n get services(): NodePyATVService[] | undefined {\n return this.options.services;\n }\n\n /**\n * Get the device version. Only set, if the device was found\n * during a scan using [[find()]]. Requires pyatv ≧ 0.10.3.\n *\n * @example device.version → \"15.5.1\"\n */\n get version(): string | undefined {\n return this.options.version;\n }\n\n private readonly events: NodePyATVDeviceEvents;\n\n private readonly options: NodePyATVDeviceOptions;\n\n private readonly state: NodePyATVState;\n\n constructor(options: NodePyATVDeviceOptions) {\n if (!options.host && !options.id && !options.mac) {\n throw new Error('Either host, id or mac must be set!');\n }\n\n this.options = Object.assign({}, options);\n this.state = parseState({}, '', {});\n this.events = new NodePyATVDeviceEvents(this.state, this, this.options);\n\n // @todo basic validation\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * @param event\n * @param listener\n * @category Event\n */\n addListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n this.events.addListener(event, listener);\n return this;\n }\n\n /**\n * Removes the state node-pyatv cached for this device.\n *\n * @category State\n */\n clearState(): void {\n this.applyState(parseState({}, '', {}));\n }\n\n /**\n * Send the \"down\" command\n * @category Control\n */\n async down(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.down);\n }\n\n /**\n * Emit an event.\n * @param event\n * @param payload\n * @category Event\n */\n emit(event: string | symbol, payload: NodePyATVDeviceEvent): boolean {\n return this.events.emit(event, payload);\n }\n\n /**\n * Get all event names which are currently known.\n * @category Event\n */\n eventNames(): Array<string | symbol> {\n return this.events.eventNames();\n }\n\n /**\n * Returns the album of the current playing media\n * @param options\n * @category State\n */\n async getAlbum(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.album;\n }\n\n /**\n * Returns the currently used app\n * @param options\n * @category State\n */\n async getApp(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.app;\n }\n\n /**\n * Returns the id of the currently used app\n * @param options\n * @category State\n */\n async getAppId(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.appId;\n }\n\n /**\n * Returns the artist of the current playing media\n * @param options\n * @category State\n */\n async getArtist(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.artist;\n }\n\n /**\n * Returns the app specific content identifier\n * @param options\n * @category State\n */\n async getContentIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n return this.getState(options).then((state) => state.contentIdentifier);\n }\n\n /**\n * Get the date and time when the state was last updated.\n * @param options\n * @category State\n */\n async getDateTime(\n options: NodePyATVGetStateOptions = {},\n ): Promise<Date | null> {\n const state = await this.getState(options);\n return state.dateTime;\n }\n\n /**\n * Get the state of this device (e.g. playing, etc.)\n * @param options\n * @category State\n */\n async getDeviceState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVDeviceState | null> {\n const state = await this.getState(options);\n return state.deviceState;\n }\n\n /**\n * Returns the episode number.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getEpisodeNumber(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.episodeNumber);\n }\n\n /**\n * Returns the current focus state of the device\n * @param options\n * @category State\n */\n async getFocusState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVFocusState | null> {\n return this.getState(options).then((state) => state.focusState);\n }\n\n /**\n * Returns the genre of the current playing media\n * @param options\n * @category State\n */\n async getGenre(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.genre;\n }\n\n /**\n * Get the hash of the current media\n * @param options\n * @category State\n */\n async getHash(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.hash;\n }\n\n /**\n * Returns the iTunes Store identifier if available.\n * Requires pyatv >= 0.16.0\n * @param options\n * @category State\n * @alias getiTunesStoreIdentifier\n */\n async getITunesStoreIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then(\n (state) => state.iTunesStoreIdentifier,\n );\n }\n\n async getiTunesStoreIdentifier(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getITunesStoreIdentifier(options);\n }\n\n /**\n * Get max number of listeners allowed\n * @category Event\n */\n getMaxListeners(): number {\n return this.events.getMaxListeners();\n }\n\n /**\n * Get the media type of the current media\n * @param options\n * @category State\n */\n async getMediaType(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVMediaType | null> {\n const state = await this.getState(options);\n return state.mediaType;\n }\n\n /**\n * Returns the current output devices of the device\n * @param options\n * @category State\n */\n async getOutputDevices(\n options: NodePyATVGetStateOptions = {},\n ): Promise<Array<{ identifier: string; name: string }> | null> {\n return this.getState(options).then((state) => state.outputDevices);\n }\n\n /**\n * Returns the title of the current playing media\n * @param options\n * @category State\n */\n async getPosition(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n const state = await this.getState(options);\n return state.position;\n }\n\n /**\n * Returns the current power state (= is it on or off, see [[NodePyATVPowerState]]) of the device.\n * @param options\n * @category State\n */\n async getPowerState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVPowerState | null> {\n return this.getState(options).then((state) => state.powerState);\n }\n\n /**\n * Returns the repeat state\n * @param options\n * @category State\n */\n async getRepeat(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVRepeatState | null> {\n const state = await this.getState(options);\n return state.repeat;\n }\n\n /**\n * Returns the season number.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getSeasonNumber(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.seasonNumber);\n }\n /**\n * Returns the season name.\n * Probably only set [if MRP is used](https://pyatv.dev/development/metadata/#currently-playing).\n * @param options\n * @category State\n */\n async getSeriesName(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n return this.getState(options).then((state) => state.seriesName);\n }\n\n /**\n * Returns the shuffle state\n * @param options\n * @category State\n */\n async getShuffle(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVShuffleState | null> {\n const state = await this.getState(options);\n return state.shuffle;\n }\n\n /**\n * Returns an [[NodePyATVState]] object representing the current state\n * of the device. Has an internal cache, which has a default TTL of 5s.\n * You can change this default value by passing the `maxAge` option.\n *\n * ```typescript\n * await device.getState({maxAge: 10000}); // cache TTL: 10s\n * ```\n *\n * @param options\n * @category State\n */\n async getState(\n options: NodePyATVGetStateOptions = {},\n ): Promise<NodePyATVState> {\n if (\n this.state?.dateTime &&\n new Date().getTime() - this.state.dateTime.getTime() <\n (options.maxAge || 5000)\n ) {\n let position = null;\n if (this.state.position && this.state.dateTime) {\n position = Math.round(\n this.state.position +\n (new Date().getTime() - this.state.dateTime.getTime()) /\n 1000,\n );\n }\n\n return Object.assign({}, this.state, { position });\n }\n\n const id = addRequestId();\n\n try {\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'playing'],\n this.options,\n );\n const newState = parseState(result, id, this.options);\n\n this.applyState(newState);\n return newState;\n } finally {\n removeRequestId(id);\n }\n }\n\n /**\n * Returns the title of the current playing media\n * @param options\n * @category State\n */\n async getTitle(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | string> {\n const state = await this.getState(options);\n return state.title;\n }\n\n /**\n * Returns the media length of the current playing media\n * @param options\n * @category State\n */\n async getTotalTime(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n const state = await this.getState(options);\n return state.totalTime;\n }\n\n /**\n * Returns the current volume of the device in percent (0 - 100)\n * @param options\n * @category State\n */\n async getVolume(\n options: NodePyATVGetStateOptions = {},\n ): Promise<null | number> {\n return this.getState(options).then((state) => state.volume);\n }\n\n /**\n * Send the \"home\" command\n * @category Control\n */\n async home(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.home);\n }\n\n /**\n * Send the \"homeHold\" command\n * @category Control\n */\n async homeHold(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.homeHold);\n }\n\n /**\n * Launch an application. Probably requires `companionCredentials`, see\n * https://pyatv.dev/documentation/atvremote/#apps for more details.\n * @param id App identifier, e.g. `com.netflix.Netflix`\n */\n async launchApp(id: string): Promise<void> {\n await this._pressKeyWithRemote('launch_app=' + id);\n }\n\n /**\n * Send the \"left\" command\n * @category Control\n */\n async left(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.left);\n }\n\n /**\n * Returns the list of installed apps on the Apple TV. Probably requires `companionCredentials`,\n * see https://pyatv.dev/documentation/atvremote/#apps for more details.\n */\n async listApps(): Promise<NodePyATVApp[]> {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvremote,\n [...parameters, 'app_list'],\n this.options,\n );\n if (typeof result !== 'string' || !result.startsWith('App: ')) {\n throw new Error('Unexpected atvremote response: ' + result);\n }\n\n removeRequestId(id);\n const regex = /(.+) \\(([^)]+)\\)$/i;\n const items = result\n .substring(5)\n .split(', App: ')\n .map((i) => {\n const m = i.match(regex);\n if (m !== null) {\n return {\n id: m[2],\n launch: () => this.launchApp(m[2]),\n name: m[1],\n };\n }\n }) as Array<NodePyATVApp | undefined>;\n\n return items.filter(Boolean) as NodePyATVApp[];\n }\n\n /**\n * Get number of listeners for event\n * @param event\n * @category Event\n */\n listenerCount(event: string | symbol): number {\n return this.events.listenerCount(event);\n }\n\n /**\n * Get listeners for event. Will also return\n * node-pyatv wrappers (e.g. once)\n *\n * @param event\n * @category Event\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n listeners(event: string | symbol): Function[] {\n return this.events.listeners(event);\n }\n\n /**\n * Send the \"menu\" command\n * @category Control\n */\n async menu(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.menu);\n }\n\n /**\n * Send the \"next\" command\n * @category Control\n */\n async next(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.next);\n }\n\n /**\n * Remove an event listener. Will stop the event subscription with the\n * Apple TV if this was the last event listener.\n * @param event\n * @param listener\n * @category Event\n */\n off(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.off(event, listener);\n return this;\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * @param event\n * @param listener\n * @category Event\n */\n on(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.on(event, listener);\n return this;\n }\n\n /**\n * Add an event listener. Will start the event subscription with the\n * Apple TV as long as there are listeners for any event registered.\n * Removes the listener automatically after the first occurrence.\n * @param event\n * @param listener\n * @category Event\n */\n once(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.once(event, listener);\n return this;\n }\n\n /**\n * Send the \"pause\" command\n * @category Control\n */\n async pause(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.pause);\n }\n\n /**\n * Send the \"play\" command\n * @category Control\n */\n async play(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.play);\n }\n\n /**\n * Send the \"playPause\" command\n * @category Control\n */\n async playPause(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.playPause);\n }\n\n /**\n * @param event\n * @param listener\n * @category Event\n */\n prependListener(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.prependListener(event, listener);\n return this;\n }\n\n /**\n * @param event\n * @param listener\n * @category Event\n */\n prependOnceListener(\n event: string | symbol,\n listener: (event: Error | NodePyATVDeviceEvent) => void,\n ): this {\n this.events.prependOnceListener(event, listener);\n return this;\n }\n\n /**\n * Send a key press to the Apple TV\n *\n * ```typescript\n * await device.pressKey(NodePyATVKeys.home);\n * ```\n *\n * <br />\n *\n * ```javascript\n * await device.pressKey('home');\n * ```\n *\n * @param key\n * @category Control\n */\n async pressKey(key: NodePyATVKeys): Promise<void> {\n const internalKeyEntry = Object.entries(NodePyATVInternalKeys).find(\n ([k]) => key === k,\n );\n\n if (!internalKeyEntry) {\n throw new Error(`Unsupported key value ${key}!`);\n }\n\n const internalKey = internalKeyEntry[1];\n if ([NodePyATVKeys.turnOff, NodePyATVKeys.turnOn].includes(key)) {\n await this._pressKeyWithRemote(internalKey);\n } else {\n await this._pressKeyWithScript(internalKey);\n }\n }\n\n /**\n * Send the \"previous\" command\n * @category Control\n */\n async previous(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.previous);\n }\n\n /**\n * @param event\n * @category Event\n */\n // eslint-disable-next-line @typescript-eslint/no-unsafe-function-type\n rawListeners(event: string | symbol): Function[] {\n return this.events.rawListeners(event);\n }\n\n /**\n * Removes all listeners, either for the given event or\n * for every event. Will stop the event subscription with\n * the Apple TV if this was the last event listener.\n *\n * @param event\n * @category Event\n */\n removeAllListeners(event?: string | symbol): this {\n this.events.removeAllListeners(event);\n return this;\n }\n\n /**\n * Remove an event listener. Will stop the event subscription with the\n * Apple TV if this was the last event listener.\n * @param event\n * @param listener\n * @category Event\n */\n removeListener(\n event: string | symbol,\n listener: (event: NodePyATVDeviceEvent) => void,\n ): this {\n this.events.removeListener(event, listener);\n return this;\n }\n\n /**\n * Send the \"right\" command\n * @category Control\n */\n async right(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.right);\n }\n\n /**\n * Send the \"select\" command\n * @category Control\n */\n async select(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.select);\n }\n\n /**\n * @param n\n * @category Event\n */\n setMaxListeners(n: number): this {\n this.events.setMaxListeners(n);\n return this;\n }\n\n /**\n * Send the \"skipBackward\" command\n * @category Control\n */\n async skipBackward(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.skipBackward);\n }\n\n /**\n * Send the \"skipForward\" command\n * @category Control\n */\n async skipForward(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.skipForward);\n }\n\n /**\n * Send the \"stop\" command\n * @category Control\n */\n async stop(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.stop);\n }\n\n /**\n * Send the \"suspend\" command\n * @category Control\n * @deprecated\n */\n async suspend(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.suspend);\n }\n\n /**\n * Returns an object with `name`, `host`, `mac`, `id` and `protocol`.\n * Can be used to initiate a new device instance.\n *\n * @category Basic\n */\n toJSON(): Pick<\n NodePyATVDeviceOptions,\n 'host' | 'id' | 'mac' | 'name' | 'protocol'\n > {\n return {\n host: this.host,\n id: this.id,\n mac: this.mac,\n name: this.name,\n protocol: this.protocol,\n };\n }\n\n /**\n * Send the \"topMenu\" command\n * @category Control\n */\n async topMenu(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.topMenu);\n }\n\n /**\n * Returns a string. Just for debugging, etc.\n *\n * @category Basic\n */\n toString(): string {\n return `NodePyATVDevice(${this.name}, ${this.host})`;\n }\n\n /**\n * Send the \"turn_off\" command\n * @category Control\n */\n async turnOff(): Promise<void> {\n await this._pressKeyWithRemote(NodePyATVInternalKeys.turnOff);\n }\n\n /**\n * Send the \"turn_on\" command\n * @category Control\n */\n async turnOn(): Promise<void> {\n await this._pressKeyWithRemote(NodePyATVInternalKeys.turnOn);\n }\n\n /**\n * Send the \"up\" command\n * @category Control\n */\n async up(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.up);\n }\n\n /**\n * Send the \"volumeDown\" command\n * @category Control\n */\n async volumeDown(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.volumeDown);\n }\n\n /**\n * Send the \"volumeUp\" command\n * @category Control\n */\n async volumeUp(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.volumeUp);\n }\n\n /**\n * Send the \"wakeup\" command\n * @category Control\n * @deprecated\n */\n async wakeup(): Promise<void> {\n await this._pressKeyWithScript(NodePyATVInternalKeys.wakeup);\n }\n\n private async _pressKeyWithRemote(key: NodePyATVInternalKeys | string) {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n await request(\n id,\n NodePyATVExecutableType.atvremote,\n [...parameters, key],\n this.options,\n );\n removeRequestId(id);\n }\n\n private async _pressKeyWithScript(key: NodePyATVInternalKeys | string) {\n const id = addRequestId();\n const parameters = getParameters(this.options);\n\n const result = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, key],\n this.options,\n );\n if (typeof result !== 'object' || result.result !== 'success') {\n throw new Error(\n `Unable to parse pyatv response: ${JSON.stringify(result, null, ' ')}`,\n );\n }\n\n removeRequestId(id);\n }\n\n private applyState(newState: NodePyATVState): void {\n this.events.applyStateAndEmitEvents(newState);\n }\n}\n","'use strict';\n\nimport { promises as fsPromises } from 'fs';\nimport { dirname, join } from 'path';\nimport semver from 'semver';\nimport { fileURLToPath } from 'url';\n\nimport { NodePyATVDevice } from '../lib/index.js';\nimport {\n addRequestId,\n debug,\n getParameters,\n removeRequestId,\n request,\n} from './tools.js';\nimport {\n type NodePyATVDeviceOptions,\n NodePyATVExecutableType,\n type NodePyATVFindAndInstanceOptions,\n type NodePyATVFindResponseObject,\n type NodePyATVInstanceOptions,\n type NodePyATVInternalScanDevice,\n type NodePyATVVersionResponse,\n} from './types.js';\n\n/**\n * Default class exported by `@sebbo2002/node-pyatv`. Use [[find]] to scan for devices in your local network. Use\n * [[device]] to connect to a known device by passing (at least) it's name and IP.\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * ```\n */\nexport default class NodePyATVInstance {\n private readonly options: NodePyATVInstanceOptions = {};\n\n /**\n * Use this to apply [[NodePyATVInstanceOptions]]\n * (e.g. debug log method) to all further requests\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const myPyatv = new pyatv({debug: true});\n * const devices = myPyatv.find();\n * console.log(devices);\n * ```\n * @param options\n */\n public constructor(options: NodePyATVInstanceOptions = {}) {\n this.options = Object.assign({}, options);\n }\n\n /**\n * Checks if pyatv is installed and ready to be used.\n * Will throw an error if not.\n *\n * @param options\n */\n public static async check(\n options: NodePyATVInstanceOptions = {},\n ): Promise<void> {\n const versions = await this.version(options);\n if (!versions.pyatv) {\n throw new Error('Unable to find pyatv. Is it installed?');\n }\n if (semver.lt(versions.pyatv, '0.6.0')) {\n throw new Error(\n \"Found pyatv, but unforunately it's too old. Please update pyatv.\",\n );\n }\n\n try {\n await this.find(options);\n } catch (error) {\n throw new Error(\n `Unable to scan for devices: ${String(error).replace('Error: ', '')}`,\n );\n }\n }\n\n /**\n * Create a [[NodePyATVDevice]] to query the state and control it.\n * At least `host` and `name` are required.\n *\n * @param options\n */\n public static device(options: NodePyATVDeviceOptions): NodePyATVDevice {\n return new NodePyATVDevice(options);\n }\n /**\n * Scan the network for Apple TVs by using pyatv's atvscript. See [[NodePyATVFindAndInstanceOptions]]\n * for the options allowed. Use the `host` / `hosts` attribute to filter by IP addresses. Resolves with\n * an array of [[NodePyATVDevice]].\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const devices = await pyatv.find();\n * console.log(devices);\n * ```\n *\n * Normally `node-pyatv` ignores error messages if at least one device has been found, but if you\n * always want to receive the error messages, you can set the second argument to `true`:\n *\n * ```typescript\n * const result = await pyatv.find({}, true);\n * console.log(result.devices);\n * console.log(result.errors);\n * ```\n *\n * @param options\n */\n public static async find(\n options?: NodePyATVFindAndInstanceOptions,\n ): Promise<NodePyATVDevice[]>;\n public static async find(\n options: NodePyATVFindAndInstanceOptions,\n returnDevicesAndErrors: true,\n ): Promise<NodePyATVFindResponseObject>;\n public static async find(\n options: NodePyATVFindAndInstanceOptions = {},\n returnDevicesAndErrors?: boolean,\n ): Promise<NodePyATVDevice[] | NodePyATVFindResponseObject> {\n const id = addRequestId();\n const parameters = getParameters(options);\n\n const devices: NodePyATVDevice[] = [];\n const errors: Record<string, unknown>[] = [];\n const response = await request(\n id,\n NodePyATVExecutableType.atvscript,\n [...parameters, 'scan'],\n { ...(options || {}), allowMultipleResponses: true },\n );\n\n for (const item of response) {\n if (\n typeof item === 'object' &&\n 'result' in item &&\n item.result === 'failure'\n ) {\n errors.push(item);\n } else if (\n typeof item === 'object' &&\n 'result' in item &&\n item.result === 'success' &&\n Array.isArray(item.devices)\n ) {\n devices.push(\n ...item.devices.map((device: NodePyATVInternalScanDevice) =>\n this.device(\n Object.assign({}, options, {\n allIDs: device.all_identifiers,\n host: device.address,\n id: device.identifier,\n mac: device.device_info?.mac || undefined,\n model: device.device_info?.model,\n modelName: device.device_info?.model_str,\n name: device.name,\n os: device.device_info?.operating_system,\n services: device.services,\n version: device.device_info?.version,\n }),\n ),\n ),\n );\n } else {\n throw new Error(\n `Unable to parse pyatv response: ${JSON.stringify(item, null, ' ')}`,\n );\n }\n }\n removeRequestId(id);\n\n if (returnDevicesAndErrors) {\n return { devices, errors };\n }\n if (!devices.length && errors.length) {\n throw new Error(\n `Unable to find any devices, but received ${errors.length} error${errors.length !== 1 ? 's' : ''}: ${JSON.stringify(errors, null, ' ')}`,\n );\n }\n\n return devices;\n }\n\n /**\n * Resolves with the version of pyatv and of the module itself.\n * If a value can't be found, null is returned instead.\n *\n * @param options\n */\n public static async version(\n options: NodePyATVInstanceOptions = {},\n ): Promise<NodePyATVVersionResponse> {\n const id = addRequestId();\n let pyatv = null;\n let module = null;\n\n try {\n pyatv = (await request(\n id,\n NodePyATVExecutableType.atvremote,\n ['--version'],\n options,\n )) as string;\n } catch (error) {\n debug(id, `Unable to get pyatv version due to ${error}`, options);\n }\n\n if (pyatv && pyatv.substr(0, 10) === 'atvremote ') {\n pyatv = pyatv.substr(10);\n }\n if (!semver.valid(pyatv)) {\n debug(\n id,\n `String \"${pyatv}\" is not a valid pyatv version, set it to null`,\n options,\n );\n pyatv = null;\n }\n\n try {\n const packageJsonPath = join(\n dirname(fileURLToPath(import.meta.url)),\n '..',\n '..',\n 'package.json',\n );\n const json = JSON.parse(\n await fsPromises.readFile(packageJsonPath, 'utf8'),\n );\n module = json?.version || null;\n } catch (error) {\n debug(id, `Unable to get module version due to ${error}`, options);\n }\n if (module && !semver.valid(module)) {\n debug(\n id,\n `String \"${module}\" is not a valid module version, set it to null`,\n options,\n );\n module = null;\n }\n\n removeRequestId(id);\n return {\n module,\n pyatv,\n };\n }\n\n /**\n * Checks if pyatv is installed and ready to be used.\n * Will throw an error if not.\n *\n * @param options\n */\n public async check(options: NodePyATVInstanceOptions = {}): Promise<void> {\n return NodePyATVInstance.check(\n Object.assign({}, this.options, options),\n );\n }\n\n /**\n * Create a [[NodePyATVDevice]] to query the state and control it.\n * At least `host` and `name` are required.\n *\n * @param options\n */\n public device(options: NodePyATVDeviceOptions): NodePyATVDevice {\n return NodePyATVInstance.device(\n Object.assign({}, this.options, options),\n );\n }\n\n /**\n * Scan the network for Apple TVs by using pyatv's atvscript. See [[NodePyATVFindAndInstanceOptions]]\n * for the options allowed. Use the `host` / `hosts` attribute to filter by IP addresses. Resolves with\n * an array of [[NodePyATVDevice]].\n *\n * ```typescript\n * import pyatv from '@sebbo2002/node-pyatv';\n * const myPyATV = new pyatv({debug: true});\n * const devices = await myPyATV.find();\n * console.log(devices);\n * ```\n *\n * @param options\n */\n public async find(\n options: NodePyATVFindAndInstanceOptions = {},\n ): Promise<NodePyATVDevice[]> {\n return NodePyATVInstance.find(Object.assign({}, this.options, options));\n }\n\n /**\n * Resolves with the version of pyatv and of the module itself.\n * If a value can't be found, null is returned instead.\n *\n * @param options\n */\n public async version(\n options: NodePyATVInstanceOptions = {},\n ): Promise<NodePyATVVersionResponse> {\n return NodePyATVInstance.version(\n Object.assign({}, this.options, options),\n );\n }\n}\n"],"mappings":"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","names":["lib_exports","__export","NodePyATVDevice","NodePyATVDeviceEvent","NodePyATVDeviceEvents","NodePyATVDeviceState","NodePyATVExecutableType","NodePyATVInstance","NodePyATVKeys","NodePyATVListenerState","NodePyATVMediaType","NodePyATVPowerState","NodePyATVProtocol","NodePyATVRepeatState","NodePyATVShuffleState","__toCommonJS","getImportMetaUrl","importMetaUrl","NodePyATVDeviceEvent","values","import_events","import_child_process","NodePyATVDeviceState","NodePyATVExecutableType","NodePyATVFocusState","NodePyATVInternalKeys","NodePyATVKeys","NodePyATVListenerState","NodePyATVMediaType","NodePyATVPowerState","NodePyATVProtocol","NodePyATVRepeatState","NodePyATVShuffleState","requestIds","addRequestId","id","i","compareOutputDevices","a","b","debug","message","options","log","enableColors","parts","execute","requestId","executableType","parameters","executable","getExecutable","mySpawn","child","onStdOut","data","onStdErr","onError","onClose","code","getParameters","parseState","input","d","msg","result","errorStr","date","parseStateStringAttr","NodePyATVMediaType","NodePyATVDeviceState","parseStateNumberAttr","NodePyATVShuffleState","NodePyATVRepeatState","NodePyATVPowerState","NodePyATVFocusState","removeRequestId","request","resolve","reject","pyatv","line","error","output","inputAttr","outputAttr","NodePyATVDeviceEvents","state","device","options","event","listener","newState","keys","k","v","key","oldValue","newValue","compareOutputDevices","NodePyATVDeviceEvent","error","a","b","reqId","debug","cb","update","parseState","id","addRequestId","removeRequestId","data","json","msg","listenStart","parameters","getParameters","execute","onError","onStdErr","onStdOut","s","onClose","code","NodePyATVDevice","debug","options","parseState","NodePyATVDeviceEvents","event","listener","payload","state","position","id","addRequestId","parameters","getParameters","result","request","newState","removeRequestId","regex","i","m","key","internalKeyEntry","NodePyATVInternalKeys","k","internalKey","n","import_fs","import_path","import_semver","import_url","NodePyATVInstance","_NodePyATVInstance","options","versions","semver","error","NodePyATVDevice","returnDevicesAndErrors","id","addRequestId","parameters","getParameters","devices","errors","response","request","item","device","removeRequestId","pyatv","module","debug","packageJsonPath","importMetaUrl","fsPromises"]}
|
package/package.json
CHANGED
|
@@ -13,10 +13,10 @@
|
|
|
13
13
|
"@semantic-release/changelog": "^6.0.3",
|
|
14
14
|
"@semantic-release/exec": "^7.1.0",
|
|
15
15
|
"@semantic-release/git": "^10.0.1",
|
|
16
|
-
"@semantic-release/npm": "^13.1.
|
|
16
|
+
"@semantic-release/npm": "^13.1.2",
|
|
17
17
|
"@types/express": "^5.0.5",
|
|
18
18
|
"@types/mocha": "^10.0.10",
|
|
19
|
-
"@types/node": "^24.
|
|
19
|
+
"@types/node": "^24.10.1",
|
|
20
20
|
"@types/semver": "^7.7.1",
|
|
21
21
|
"c8": "^10.1.3",
|
|
22
22
|
"eslint": "^9.39.1",
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"semantic-release": "^25.0.2",
|
|
33
33
|
"semantic-release-license": "^1.0.3",
|
|
34
34
|
"source-map-support": "^0.5.21",
|
|
35
|
-
"tsup": "^8.5.
|
|
35
|
+
"tsup": "^8.5.1",
|
|
36
36
|
"tsx": "^4.20.6",
|
|
37
37
|
"typedoc": "^0.28.14",
|
|
38
38
|
"typescript": "^5.9.3",
|
|
@@ -72,5 +72,5 @@
|
|
|
72
72
|
"test": "mocha"
|
|
73
73
|
},
|
|
74
74
|
"type": "module",
|
|
75
|
-
"version": "9.0.3-develop.
|
|
75
|
+
"version": "9.0.3-develop.5"
|
|
76
76
|
}
|