예제 #1
0
            public static async Task <bool> CheckForRpcs3Updates(DiscordClient discordClient, DiscordChannel?channel, string?sinceCommit = null, DiscordMessage?emptyBotMsg = null)
            {
                var updateAnnouncement        = channel is null;
                var updateAnnouncementRestore = emptyBotMsg != null;
                var info = await Client.GetUpdateAsync(Config.Cts.Token, sinceCommit).ConfigureAwait(false);

                if (info?.ReturnCode != 1 && sinceCommit != null)
                {
                    info = await Client.GetUpdateAsync(Config.Cts.Token).ConfigureAwait(false);
                }

                if (updateAnnouncementRestore && info?.CurrentBuild != null)
                {
                    info.LatestBuild = info.CurrentBuild;
                }
                var embed = await info.AsEmbedAsync(discordClient, updateAnnouncement).ConfigureAwait(false);

                if (info == null || embed.Color.Value.Value == Config.Colors.Maintenance.Value)
                {
                    if (updateAnnouncementRestore)
                    {
                        Config.Log.Debug($"Failed to get update info for commit {sinceCommit}: {JsonSerializer.Serialize(info)}");
                        return(false);
                    }

                    embed = await cachedUpdateInfo.AsEmbedAsync(discordClient, updateAnnouncement).ConfigureAwait(false);
                }
                else if (!updateAnnouncementRestore)
                {
                    if (cachedUpdateInfo?.LatestBuild?.Datetime is string previousBuildTimeStr &&
                        info.LatestBuild?.Datetime is string newBuildTimeStr &&
                        DateTime.TryParse(previousBuildTimeStr, out var previousBuildTime) &&
                        DateTime.TryParse(newBuildTimeStr, out var newBuildTime) &&
                        newBuildTime > previousBuildTime)
                    {
                        cachedUpdateInfo = info;
                    }
                }
                if (!updateAnnouncement)
                {
                    await channel !.SendMessageAsync(embed: embed.Build()).ConfigureAwait(false);
                    return(true);
                }

                if (updateAnnouncementRestore)
                {
                    if (embed.Title == "Error")
                    {
                        return(false);
                    }

                    Config.Log.Debug($"Restoring update announcement for build {sinceCommit}: {embed.Title}\n{embed.Description}");
                    await emptyBotMsg !.ModifyAsync(embed: embed.Build()).ConfigureAwait(false);
                    return(true);
                }

                var latestUpdatePr = info?.LatestBuild?.Pr?.ToString();
                var match          = (
                    from field in embed.Fields
                    let m = UpdateVersionRegex.Match(field.Value)
                            where m.Success
                            select m
                    ).FirstOrDefault();
                var latestUpdateBuild = match?.Groups["build"].Value;

                if (string.IsNullOrEmpty(latestUpdatePr) ||
                    lastUpdateInfo == latestUpdatePr ||
                    !await UpdateCheck.WaitAsync(0).ConfigureAwait(false))
                {
                    return(false);
                }

                try
                {
                    if (!string.IsNullOrEmpty(lastFullBuildNumber) &&
                        !string.IsNullOrEmpty(latestUpdateBuild) &&
                        int.TryParse(lastFullBuildNumber, out var lastSaveBuild) &&
                        int.TryParse(latestUpdateBuild, out var latestBuild) &&
                        latestBuild <= lastSaveBuild)
                    {
                        return(false);
                    }

                    var compatChannel = await discordClient.GetChannelAsync(Config.BotChannelId).ConfigureAwait(false);

                    var botMember = discordClient.GetMember(compatChannel.Guild, discordClient.CurrentUser);
                    if (botMember == null)
                    {
                        return(false);
                    }

                    if (!compatChannel.PermissionsFor(botMember).HasPermission(Permissions.SendMessages))
                    {
                        NewBuildsMonitor.Reset();
                        return(false);
                    }

                    if (embed.Color.Value.Value == Config.Colors.Maintenance.Value)
                    {
                        return(false);
                    }

                    await CheckMissedBuildsBetween(discordClient, compatChannel, lastUpdateInfo, latestUpdatePr, Config.Cts.Token).ConfigureAwait(false);

                    await compatChannel.SendMessageAsync(embed : embed.Build()).ConfigureAwait(false);

                    lastUpdateInfo      = latestUpdatePr;
                    lastFullBuildNumber = latestUpdateBuild;
                    await using var db  = new BotDb();
                    var currentState = await db.BotState.FirstOrDefaultAsync(k => k.Key == Rpcs3UpdateStateKey).ConfigureAwait(false);

                    if (currentState == null)
                    {
                        await db.BotState.AddAsync(new() { Key = Rpcs3UpdateStateKey, Value = latestUpdatePr }).ConfigureAwait(false);
                    }
                    else
                    {
                        currentState.Value = latestUpdatePr;
                    }
                    var savedLastBuild = await db.BotState.FirstOrDefaultAsync(k => k.Key == Rpcs3UpdateBuildKey).ConfigureAwait(false);

                    if (savedLastBuild == null)
                    {
                        await db.BotState.AddAsync(new() { Key = Rpcs3UpdateBuildKey, Value = latestUpdateBuild }).ConfigureAwait(false);
                    }
                    else
                    {
                        savedLastBuild.Value = latestUpdateBuild;
                    }
                    await db.SaveChangesAsync(Config.Cts.Token).ConfigureAwait(false);

                    NewBuildsMonitor.Reset();
                    return(true);
                }
                catch (Exception e)
                {
                    Config.Log.Warn(e, "Failed to check for RPCS3 update info");
                }
                finally
                {
                    UpdateCheck.Release();
                }
                return(false);
            }