docs: def start(token, client_id, loop, on_ready_handler=None):
      """Start the Discord client and log Modis into Discord."""
      import discord
      import asyncio
  
      # Create client
      logger.debug("Creating Discord client")
      asyncio.set_event_loop(loop)
      client = discord.Client()
      from . import _client
      _client.client = client
  
      from .. import datatools
      if datatools.has_data():
          data = datatools.get_data()
      else:
          # Create a blank data file
          data = {"discord": {}}
  
      # Save default server info to data
      if "servers" not in data["discord"]:
          data["discord"]["servers"] = {}
  
      # Save default key info to data
      if "keys" not in data["discord"]:
          data["discord"]["keys"] = {}
  
      # Save logger info to data
      if "log_level" not in data:
          data["log_level"] = "DEBUG"
  
      data["discord"]["token"] = token
      data["discord"]["client_id"] = client_id
      datatools.write_data(data)
  
      # Import event handlers
      logger.debug("Importing event handlers")
      event_handlers = _get_event_handlers()
  
      # Create event handler combiner
      logger.debug("Compiling event handlers")
  
      def create_event_handler(event_handler_type):
          async def func(*args, **kwargs):
              for module_event_handler in event_handlers[event_handler_type]:
                  # Check for errors in the module event
                  try:
                      module_event_handler_func = getattr(module_event_handler,
                                                          event_handler_type)
                      await module_event_handler_func(*args, **kwargs)
                  except Exception as module_exception:
                      logger.error("An error occured in '{}'".format(module_event_handler))
                      logger.exception(module_exception)
  
              if on_ready_handler is not None and event_handler_type == "on_ready":
                  await on_ready_handler()
  
          func.__name__ = event_handler_type
          return func
  
      # Register event handlers
      logger.debug("Registering event handlers into client")
      for event_handler in event_handlers.keys():
          client.event(create_event_handler(event_handler))
  
      # Run the client loop
      logger.info("Connecting to Discord")
      try:
          client.loop.run_until_complete(client.login(token))
      except Exception as e:
          logger.exception(e)
          logger.critical("Could not connect to Discord")
      else:
          logger.debug("Running the bot")
          try:
              client.loop.run_until_complete(client.connect())
          except KeyboardInterrupt:
              client.loop.run_until_complete(client.logout())
              pending = asyncio.Task.all_tasks(loop=client.loop)
              gathered = asyncio.gather(*pending, loop=client.loop)
              try:
                  gathered.cancel()
                  client.loop.run_until_complete(gathered)
  
                  # we want to retrieve any exceptions to make sure that
                  # they don't nag us about it being un-retrieved.
                  gathered.exception()
              except Exception as e:
                  logger.exception(e)
          except Exception as e:
              logger.exception(e)
              pending = asyncio.Task.all_tasks(loop=client.loop)
              gathered = asyncio.gather(*pending, loop=client.loop)
              gathered.exception()
          finally:
              try:
                  client.loop.run_until_complete(client.logout())
              except Exception as e:
                  logger.exception(e)
  
              logger.critical("Bot stopped\n")
              client.loop.close()