Create an unshortener instance  options: - cache   (Object) - cache instance - get(key) -> Promise - set(key, value)  -> Promise - nesting (Number) - max amount of redirects to follow, default: `3` - request (Object) - default options for `got` in `.request()` method
function Unshort(options) {
  if (!(this instanceof Unshort)) return new Unshort(options);

  options = options || {};

  this._options = merge.all(
    [
      {
        timeout: 30 * 1000,
        retries: 1,
        followRedirect: false,  // redirects are handled manually
        maxBuffer: 1000 * 1024, // too big reply -> not redirect
        headers: {
          'User-Agent': defaultAgent
        }
      },
      options.request || {}
    ],
    { clone: true }
  );

  // config data with compiled regexps and fetch functions attached
  this._domains = [];

  this.cache = options.cache || {
    get() { return Promise.resolve(); },
    set() { return Promise.resolve(); }
  };

  this.nesting = options.nesting || 3;

  // Regexp that matches links to all the known services, it is used
  // to determine whether url should be processed at all or not.
  //
  // Initialized to regexp that matches nothing, it gets overwritten
  // when domains are added.
  //
  this._matchAllRE = /(?!)/;

  let customProviders = requireAll(path.join(__dirname, 'providers'));

  let domainMap = {};

  config.forEach(domain => {
    if (typeof domain === 'string') {
      domainMap[domain] = {};
      return;
    }

    Object.keys(domain).forEach(d => {
      domainMap[d] = Object.assign({}, domain[d]);
    });
  });

  Object.keys(domainMap).forEach(domain => {
    if (customProviders[domain]) {
      domainMap[domain].fetch = customProviders[domain].fetch;
      domainMap[domain].validate = customProviders[domain].validate;
    }

    this.add(domain, domainMap[domain]);
  });
}