evandcoleman/node-appletv

View on GitHub
src/lib/browser.ts

Summary

Maintainability
A
0 mins
Test Coverage
import { EventEmitter } from 'events';
import * as mdns from 'mdns';

import { AppleTV } from './appletv';

export class Browser {
  private browser: mdns.Browser;
  private services: AppleTV[];
  private uniqueIdentifier: string;
  private onComplete: (device: AppleTV[]) => void;
  private onFailure: (error: Error) => void;

  /**
  * Creates a new Browser
  * @param log  An optional function that takes a string to provide verbose logging.
  */
  constructor() {
    let sequence = [
      mdns.rst.DNSServiceResolve(),
      'DNSServiceGetAddrInfo' in (<any>mdns).dns_sd ? mdns.rst.DNSServiceGetAddrInfo() : mdns.rst.getaddrinfo({ families: [4] }),
      mdns.rst.makeAddressesUnique()
    ];
    this.browser = mdns.createBrowser(mdns.tcp('mediaremotetv'), { resolverSequence: sequence });
    this.services = [];

    let that = this;
    this.browser.on('serviceUp', function(service) {
      let device = new AppleTV(service);
      if (that.uniqueIdentifier && device.uid == that.uniqueIdentifier) {
        that.browser.stop();
        that.onComplete([device]);
      } else {
        that.services.push(device);
      }
    });
  }

  /**
  * Scans for AppleTVs on the local network.
  * @param uniqueIdentifier  An optional identifier for the AppleTV to scan for. The AppleTV advertises this via Bonjour.
  * @param timeout  An optional timeout value (in seconds) to give up the search after.
  * @returns A promise that resolves to an array of AppleTV objects. If you provide a `uniqueIdentifier` the array is guaranteed to only contain one object.
  */
  scan(uniqueIdentifier?: string, timeout?: number): Promise<AppleTV[]> {
    this.services = [];
    this.uniqueIdentifier = uniqueIdentifier;
    this.browser.start();
    let that = this;
    let to = timeout == null ? 5 : timeout;

    return new Promise((resolve, reject) => {
      that.onComplete = resolve;
      that.onFailure = reject;
      setTimeout(() => {
        that.browser.stop();
        if (that.uniqueIdentifier) {
          reject(new Error("Failed to locate specified AppleTV on the network"));
        } else {
          resolve(that.services
             .sort((a, b) => {
               return a > b ? 1 : -1;
             }));
        }
      }, to * 1000);
    });
  }
}