private async Task HeartbeatCheck()
        {
            Logger.Log(LogLevel.Info, $"Heartbeat check - {_apiRequestService.totalCustomAPIRequestsMade} API requests made ({_apiRequestService.totalCustomAPIRequestsMadeSinceHeartbeat} requests in the last hour) - starting server checks.");
            // thread-safe reset 30m counter
            Interlocked.Exchange(ref _apiRequestService.totalCustomAPIRequestsMadeSinceHeartbeat, 0);

            // do a global companion status check to see if the API is down or if something else is wrong
            CustomApiStatus globalCompanionStatusRequestResult = GetCompanionApiStatus().Result;

            // if companion is in maintenance, reset timer and don't do anything else
            if (globalCompanionStatusRequestResult == CustomApiStatus.UnderMaintenance)
            {
                AdjustHeartbeatTimer();
                Logger.Log(LogLevel.Info, $"The SE API is down for maintenance at the moment. Trying again later.");
                return;
            }

            // log any error responses that aren't logged-out or maintenance issues & send DM to bot owner
            // this is deprecated now as any errors from the APIRequestService will give us logs and DMs already

            /*
             * if (globalCompanionStatusRequestResult != CustomApiStatus.OK && globalCompanionStatusRequestResult != CustomApiStatus.NotLoggedIn && globalCompanionStatusRequestResult != CustomApiStatus.UnderMaintenance)
             * {
             *  Logger.Log(LogLevel.Info, $"SE API error - received error: {globalCompanionStatusRequestResult}.");
             *
             *  var dm = await _discord.GetUser(ulong.Parse(_config["discordBotOwnerId"])).GetOrCreateDMChannelAsync();
             *  await dm.SendMessageAsync($"Something's wrong with the API - received error: {globalCompanionStatusRequestResult}.");
             * } */

            // figure out each server's login status
            serverLoginStatusTracker.Clear();
            var tasks = Task.Run(() => Parallel.ForEach((Worldss[])Enum.GetValues(typeof(Worldss)), parallelOptions, async server =>
            {
                CustomApiStatus serverStatusRequestResult = GetCompanionApiStatus(server.ToString()).Result;
                bool serverLoggedIn = false;

                if (serverStatusRequestResult == CustomApiStatus.OK) // logged in, continue processing
                {
                    serverLoggedIn = true;
                }
                else if (serverStatusRequestResult == CustomApiStatus.NotLoggedIn) // not logged in, continue processing
                {
                    serverLoggedIn = false;
                }

                // runs if servers are logged in or not logged in, will not run if api error or maintenance
                serverLoginStatusTracker.TryAdd(server, serverLoggedIn);
            }));
            await Task.WhenAll(tasks);

            // get how many servers are logged in currently
            var serverLoggedInCount = serverLoginStatusTracker.Count(x => x.Value == true);

            Logger.Log(LogLevel.Info, $"{serverLoggedInCount} of {serverLoginStatusTracker.Count} game servers are logged in. ");

            // if any servers are down, try to log them in
            // use a random delay to avoid potential bans
            if (serverLoggedInCount != serverLoginStatusTracker.Count)
            {
                int errorCount = 0;
                foreach (var serverStatus in serverLoginStatusTracker.Where(x => x.Value == false))
                {
                    var server = serverStatus.Key;
                    Logger.Log(LogLevel.Info, $"Logging into {server}...");
                    var loginResult = await _apiRequestService.LoginToCompanionApi(server.ToString());

                    Logger.Log(LogLevel.Info, $"Login to {server} was {(loginResult ? "successful" : "unsuccessful")}.");
                    if (!loginResult)
                    {
                        errorCount++;                         // increment on unsuccessful logins
                    }
                    await Task.Delay(_rng.Next(5000, 10000)); // random delay between 5-10 seconds
                }
                Logger.Log(LogLevel.Info, $"Login process completed with {errorCount} error(s).");
            }

            AdjustHeartbeatTimer();
        }