Example #1
0
        /// <summary>
        /// Syncs a srl race with it's persistent euivalent
        /// </summary>
        /// <param name="context">The database context</param>
        /// <param name="srlRace">The srl race</param>
        /// <returns>Returns the persisted race</returns>
        private static Race?SyncRace(
            DatabaseContext context
            , SRLRace srlRace
            )
        {
            Logger.Info($"({srlRace.Id}) Synchronizing...");

            Game g = SyncGame(context, srlRace);

            if (srlRace.State == SRLApiClient.Endpoints.RaceState.Over &&
                context.GetRace(srlRace.Id) == null)
            {
                Logger.Info($"({srlRace.Id}) Race over and not persisted, continuing.");
                return(null);
            }

            Race?race = srlRace.Convert(g);

            race = context.AddOrUpdate(race);

            if (race != null)
            {
                race.ConsecutiveUpdateFailures = 0;
                SyncEntrants(context, srlRace, race);
            }

            return(race);
        }
Example #2
0
        /// <summary>
        /// Updates the existing or adss a new game entity based on the
        /// <paramref name="srlRace"/>
        /// </summary>
        /// <param name="context">The database context</param>
        /// <param name="srlRace">The SRL race</param>
        /// <returns>The updated game entity</returns>
        private static Game SyncGame(
            DatabaseContext context
            , SRLRace srlRace)
        {
            Game game = srlRace.Game.Convert();

            return(context.AddOrUpdate(game));
        }
 /// <summary>
 /// Creates/updates and activates a guild
 /// </summary>
 /// <param name="context">The database context</param>
 /// <param name="guild">The guild</param>
 /// <returns>Returns the updated guild</returns>
 public static Guild EnableGuild(
     DatabaseContext context
     , SocketGuild guild)
 => context.AddOrUpdate(
     new Guild(
         guild.Id
         , guild.Name)
 {
     IsActive = true
 });
 /// <summary>
 /// Creates/updates and activates a channel
 /// </summary>
 /// <param name="context">The database context</param>
 /// <param name="channel">The channel</param>
 /// <returns>Returns the updated guild</returns>
 public static Channel EnableChannel(
     DatabaseContext context
     , SocketTextChannel channel)
 => context.AddOrUpdate(
     new Channel(
         EnableGuild(context, channel.Guild)
         , channel.Id
         , channel.Name)
 {
     IsActive = true
 });
Example #5
0
        /// <summary>
        /// Updates existing, adds new and deletes removed entrants  from
        /// the <paramref name="race"/> entity
        /// </summary>
        /// <param name="context">The database context</param>
        /// <param name="srlRace">The SRL race</param>
        /// <param name="race">The race entity</param>
        private static void SyncEntrants
            (DatabaseContext context
            , SRLRace srlRace
            , Race race)
        {
            foreach (SRLApiClient.Endpoints.Races.Entrant entrant in srlRace.Entrants)
            {
                context.AddOrUpdate(entrant.Convert(race));
            }

            UpdateRemovedEntrants(context, srlRace, race);
            race.EntrantCount = srlRace.Entrants.Count;
        }
        /// <summary>
        /// Adds a tracker or updates it if it's already present in the current guild
        /// </summary>
        /// <param name="message">The request message</param>
        /// <param name="discordService">The discord service</param>
        /// <param name="context">The database context</param>
        /// <param name="args">The command arguments</param>
        private static async Task AddTrackerAsync(
            SocketMessage message,
            DiscordService discordService,
            DatabaseContext context,
            string[] args
            )
        {
            if (args.Length != 4)
            {
                Logger.Error("Invalid command pattern");
                await discordService.ReplyAsync(message, "Invalid command pattern. Command usage: track <srl abbreviation> <channel mention>").ConfigureAwait(false);

                return;
            }

            if (message.MentionedChannels.Count != 1)
            {
                await discordService.ReplyAsync(message, "No channel specified! Command usage: track <srl abbreviation> <channel mention>").ConfigureAwait(false);

                return;
            }

            Game?game = context.GetGame(args[2]);

            if (game == null)
            {
                await discordService.ReplyAsync(message, $"Game abbreviation '{args[2]}' not found").ConfigureAwait(false);

                return;
            }

            SocketGuildChannel mentionedChannel = message.MentionedChannels.First();
            Channel?           channel          = context.GetChannel(mentionedChannel.Id);

            if (channel == null)
            {
                await discordService.ReplyAsync(message, "Channel not registered yet, please try again later.").ConfigureAwait(false);

                return;
            }

            if (!channel.Guild.Snowflake.Equals(mentionedChannel.Guild.Id) || !channel.IsActive)
            {
                await discordService.ReplyAsync(message, "Channel not found.").ConfigureAwait(false);

                return;
            }

            if (discordService.HasRequiredPermissions(channel.Guild.Snowflake, channel.Snowflake) != true)
            {
                await discordService.ReplyAsync(message, $"Missing permissions in channel #{mentionedChannel.Name}").ConfigureAwait(false);

                return;
            }

            Tracker?tracker = context.GetActiveTracker(game, channel.Guild);

            if (tracker != null)
            {
                tracker.Channel = channel;
                tracker.State   = TrackerState.Active;
            }
            else
            {
                tracker = new Tracker(channel, game)
                {
                    State = TrackerState.Active
                };

                context.AddOrUpdate(tracker);
            }

            context.SaveChanges();
            await discordService.ReplyAsync(message, $"{game.Abbreviation} is now being tracked in {channel.DisplayName}").ConfigureAwait(false);
        }
        /// <summary>
        /// Creates and updates announcements for the specified <paramref name="races"/>
        /// if an active tracker is found
        /// </summary>
        /// <param name="context">The database context</param>
        /// <param name="discordService">The discord service</param>
        /// <param name="races">The races</param>
        public static async Task UpdateAnnouncementsAsync(
            DatabaseContext context
            , DiscordService discordService
            , List <Race> races)
        {
            foreach (Race race in races)
            {
                foreach (Tracker tracker in context.GetActiveTrackers(race.Game))
                {
                    Logger.Info($"({race.SrlId}) Updating tracker {tracker.Id}");

                    Announcement?announcement = context.GetAnnouncement(race, tracker);

                    try
                    {
                        if (discordService.HasRequiredPermissions(tracker.Channel.Guild.Snowflake, announcement?.Channel?.Snowflake ?? tracker.Channel.Snowflake) != true)
                        {
                            Logger.Error($"Missing permissions in channel {tracker.ChannelId}: {tracker.Channel.Guild.DisplayName}/{tracker.Channel.DisplayName}");
                            continue;
                        }
                    }
                    catch (Exception ex)
                    {
                        Logger.Error($"({announcement?.Race?.SrlId}) Exception thrown:", ex);
                        continue;
                    }

                    List <Entrant> entrants = new List <Entrant>();

                    foreach (Entrant e in context.GetEntrants(race))
                    {
                        if (context.Entry(e).State != EntityState.Deleted)
                        {
                            entrants.Add(e);
                        }
                    }

                    if (
                        announcement == null &&
                        race.State < SRLApiClient.Endpoints.RaceState.Finished &&
                        race.State != SRLApiClient.Endpoints.RaceState.Unknown
                        )
                    {
                        DateTime controlRange = DateTime.UtcNow.Subtract(TimeSpan.FromDays(7));

                        using DatabaseContext altContext = new ContextBuilder().CreateDbContext();
                        Race?persistedRace = await altContext
                                             .Races
                                             .AsQueryable()
                                             .FirstOrDefaultAsync(r => r
                                                                  .SrlId.Equals(race.SrlId, StringComparison.CurrentCultureIgnoreCase) &&
                                                                  r.CreatedAt > controlRange)
                                             .ConfigureAwait(false);

                        if (persistedRace != null)
                        {
                            // If a race with the same id was registered within the last week, skip announcement
                            Logger.Info($"({race.SrlId}) Persisted race found: {persistedRace.Id}/{persistedRace.SrlId}. Skipping announcement!");
                        }
                        else
                        {
                            announcement = await PostAnnouncementAsync(discordService, tracker, race, entrants).ConfigureAwait(false);

                            if (announcement != null)
                            {
                                context.AddOrUpdate(announcement);
                            }
                        }
                    }
                    else if (announcement != null)
                    {
                        await UpdateAnnouncementAsync(discordService, announcement, entrants).ConfigureAwait(false);
                    }
                }
            }
        }