docs: def enforce_service_mode(services, FetcherClass, kwargs, modes):
      """
      Fetches the value according to the mode of execution desired.
      `FetcherClass` must be a class that is subclassed from AutoFallbackFetcher.
      `services` must be a list of Service classes.
      `kwargs` is a list of arguments used to make the service call, usually
        something like {crypto: 'btc', address: '1HwY...'} or
        {crypto: 'ltc', fiat: 'rur'}, (depends on the what FetcherClass.action takes)
  
      Modes can be:
  
           average = positive int. 1 by default. Takes average of n fetches.
           verbose = [True|False] False by default. Extra output.
           random = [True|False] False by default. Randomizes service order.
           paranoid = positive int. 1 by default. Redundant Fetching.
           fast = positive int. 0 by default. Return as soon as recieved first n results.
  
      """
      fast_level = modes.get('fast', 0)
      average_level = modes.get('average', 0)
      paranoid_level = modes.get('paranoid', 0)
      private_level = modes.get('private', 0)
      verbose = modes.get('verbose', False)
      timeout = modes.get('timeout', None)
  
      if len(services) == 0:
          raise NoService("No services defined")
  
      if modes.get('random', False):
          random.shuffle(services)
  
      if private_level  > 0:
          results = _do_private_mode(
              FetcherClass, services, kwargs, random_wait_seconds=private_level,
              verbose=verbose, timeout=timeout
          )
          return results
  
      elif average_level <= 1 and paranoid_level <= 1 and fast_level == 0:
          # only need to make 1 external call, no need for threading...
          fetcher = FetcherClass(services=services, verbose=verbose, timeout=timeout)
          consensus_results = fetcher.action(**kwargs)
          used_services = [fetcher._successful_service]
  
      elif average_level > 1:
          # instead of checking that all results are the same, we just return the average of all results.
          # mostly useful for non-blockchain operations like price and optimal fee.
          results = _get_results(
              FetcherClass, services, kwargs, num_results=average_level, verbose=verbose, timeout=timeout
          )
  
          to_compare, used_services = _prepare_consensus(FetcherClass, results)
          consensus_results = sum(to_compare) / len(to_compare)
  
      elif paranoid_level > 1:
          results = _get_results(
              FetcherClass, services, kwargs, num_results=paranoid_level, verbose=verbose, timeout=timeout
          )
          to_compare, used_services = _prepare_consensus(FetcherClass, results)
  
          if len(set(to_compare)) > 1:
              full_results = zip(used_services, to_compare)
              show_error = ", ".join("%s: %s" % (s.name, v) for s, v in full_results)
              sd = ServiceDisagreement("No service consensus: %s" % show_error)
              sd.network_results = {
                  service: result for service, result in full_results
              }
              raise sd
  
          # if all values match, return any one (in this case the first one).
          # also return the list of all services that confirm this result.
          consensus_results = results[0][1]
  
      elif fast_level >= 1:
          raise Exception("Fast mode not yet working")
          results = _get_results(
              FetcherClass, services, kwargs, fast=fast_level, verbose=verbose
          )
  
      else:
          raise Exception("No mode specified.")
  
      if modes.get('report_services'):
          return used_services, consensus_results
      else:
          return consensus_results