public void saveServerConfig(TempServerConfig storage) {
   try {
     Files.createDirectories(serverStorageDir);
   } catch (IOException e) {
     LOGGER.warn("Unable to create server storage directory", e);
     return;
   }
   Path serverStorageFile = serverStorageDir.resolve(storage.getServerId() + ".json");
   try (BufferedWriter writer =
       Files.newBufferedWriter(serverStorageFile, UTF_8, CREATE, TRUNCATE_EXISTING)) {
     gson.toJson(storage, writer);
     writer.flush();
   } catch (IOException e) {
     LOGGER.warn("Unable to write server storage file for " + storage.getServerId(), e);
     return;
   }
   LOGGER.info("Saved server {}", storage.getServerId());
 }
  public void loadServerConfig(Path path) {
    boolean purge = false;
    TempServerConfig config;
    ServerTimeoutStorage storage;
    try (Reader reader = Files.newBufferedReader(path, UTF_8)) {
      config = gson.fromJson(reader, TempServerConfig.class);
      serverStorage.put(config.getServerId(), config);
      storage = config.getServerTimeouts();
      if (storage != null) {
        Server server = apiClient.getServerByID(config.getServerId());
        if (server == NO_SERVER) {
          LOGGER.warn("Rejecting {} server storage file: server not found", config.getServerId());
          return;
        }
        LOGGER.info(
            "Loaded {} ({}) server storage file",
            server.getName(),
            server.getId(),
            storage.getTimeoutRoleId());
        //  Prune expired entries
        for (Iterator<Map.Entry<String, ServerTimeout>> iter =
                storage.getTimeouts().entrySet().iterator();
            iter.hasNext(); ) {
          Map.Entry<String, ServerTimeout> e = iter.next();
          ServerTimeout timeout = e.getValue();
          String userId = timeout.getUserId();
          User user = apiClient.getUserById(userId, server);
          if (!isUserTimedOut(userId, server.getId())) {
            //  Purge!
            purge = true;
            if (user == NO_USER) {
              LOGGER.info(
                  "Ending timeout for departed user {} ({}) in {} ({})",
                  timeout.getLastUsername(),
                  userId,
                  server.getName(),
                  server.getId());
              //
              // apiClient.sendMessage(loc.localize("message.mod.timeout.expire.not_found",
              //                                    user.getId()),
              //                                    server.getId());
              //  Don't need to remove the timeout role because leaving does that for us
            } else {
              //  Duplicated from onTimeoutExpire except without remove since we're removing in an
              // iter
              LOGGER.info(
                  "Expiring timeout for {} ({}) in {} ({})",
                  user.getUsername(),
                  user.getId(),
                  server.getName(),
                  server.getId());
              //  Only send message if they still have the role
              if (removeTimeoutRole(user, server, apiClient.getChannelById(server.getId()))) {
                //
                // apiClient.sendMessage(loc.localize("message.mod.timeout.expire",
                //                                        user.getId()),
                //                                        server.getId());
              }
            }
            SafeNav.of(timeout.getTimerFuture()).ifPresent(f -> f.cancel(true));
            iter.remove();
          } else {
            //  Start our futures
            Duration duration = Duration.between(Instant.now(), timeout.getEndTime());
            ScheduledFuture future =
                timeoutService.schedule(
                    () -> onTimeoutExpire(user, server), duration.getSeconds(), TimeUnit.SECONDS);
            timeout.setTimerFuture(future);
          }
        }
      }
    } catch (IOException | JsonParseException e) {
      LOGGER.warn("Unable to load server storage file " + path.toString(), e);
      return;
    }

    if (purge) {
      saveServerConfig(config);
    }
  }