Exemplo n.º 1
0
        public async Task StartMovie(int movieNightId)
        {
            GuildMovieNight movieNight = await GetGuildMovieNightAsync(movieNightId);

            if (movieNight.WinningMovieImdbId == null)
            {
                throw new Exception("The Winning Movie IMDb ID was null at the point in time of the Start Movie.");
            }

            (DiscordClient _, DiscordGuild guild, DiscordChannel channel) = await this.GetCommonDiscordObjects(movieNight);

            DiscordMember host = await guild.GetMemberAsync(movieNight.HostId);

            OmdbMovie movieInfo = await this.omdbClient.GetByImdbIdAsync(movieNight.WinningMovieImdbId, omdbPlotOption : OmdbPlotOption.SHORT);

            DiscordEmbedBuilder announceWinnerEmbed = movieInfo.ToDiscordEmbedBuilder()
                                                      .WithAuthor(host.DisplayName, iconUrl: host.AvatarUrl);
            DiscordMessageBuilder announceWinnerMessage = new DiscordMessageBuilder()
                                                          .WithContent($"@everyone, the movie below is starting now!")
                                                          .WithEmbed(announceWinnerEmbed.Build());

            await channel.SendMessageAsync(announceWinnerMessage);

            // Update movie suggestion with the time watched
            DbResult <GuildMovieSuggestion> getWinningMovieSuggestion = await this.mediator.Send(new GuildMovieSuggestions.GetMovieSuggestion(movieNight.WinningMovieImdbId, guild));

            if (!getWinningMovieSuggestion.TryGetValue(out GuildMovieSuggestion? winningMovieSuggestion))
            {
                return;
            }

            winningMovieSuggestion.InstantWatched = this.clock.GetCurrentInstant();
            await this.mediator.Send(new GuildMovieSuggestions.Update(winningMovieSuggestion));
        }
            public async Task StartMovieAsync(CommandContext context)
            {
                if (options.DevGuildId != context.Guild.Id)
                {
                    await context.RespondAsync("I'm sorry, but these commands should only be run in the bot dev guild");

                    return;
                }

                GuildMovieNight testMovieNight = await this.AddTestMovieNight(context.Guild, context.Channel, context.User);

                IEnumerable <GuildMovieSuggestion> testMovieSuggestions = await this.AddTestMovies(context.User, context.Guild);

                await this.mns.StartVoting(testMovieNight.Id);

                await Task.Delay(15 * 1000);

                await this.mns.CalculateVotes(testMovieNight.Id);

                await Task.Delay(15 * 1000);

                await this.mns.StartMovie(testMovieNight.Id);

                await this.DeleteTestMovieNight(testMovieNight);

                await this.DeleteTestMovieSuggestions(testMovieSuggestions);
            }
 private async Task DeleteTestMovieNight(GuildMovieNight testMovieNight)
 {
     RecurringJob.RemoveIfExists(testMovieNight.VotingStartHangfireId);
     RecurringJob.RemoveIfExists(testMovieNight.VotingEndHangfireId);
     RecurringJob.RemoveIfExists(testMovieNight.MovieNightStartHangfireId);
     await this.mediator.Send(new GuildMovieNights.Delete(testMovieNight));
 }
Exemplo n.º 4
0
        private static RecurringJobDto GetMovieNightStartRecurringJobInfo(GuildMovieNight movieNight)
        {
            RecurringJobDto?rJobDto = JobStorage.Current.GetConnection().GetRecurringJobs().FirstOrDefault(x => x.Id == movieNight.MovieNightStartHangfireId);

            if (rJobDto == null || !rJobDto.NextExecution.HasValue)
            {
                throw new Exception("That Hangfire Job no longer exists or was never scheduled");
            }

            return(rJobDto);
        }
        public async Task DeleteAsync(CommandContext context)
        {
            DbResult <IEnumerable <GuildMovieNight> > getMovieNightsResult = await this.mediator.Send(new GuildMovieNights.GetAllGuildsMovieNights(context.Guild.Id));

            if (!getMovieNightsResult.TryGetValue(out IEnumerable <GuildMovieNight>?guildMovieNights))
            {
                throw new Exception("An error occured while retrieving guild movie nights");
            }
            bool hasManageServer = context.Member.Roles.Select(x => x.CheckPermission(Permissions.ManageGuild)).Any();

            if (!hasManageServer)
            {
                guildMovieNights = guildMovieNights.Where(mn => mn.HostId == context.Member.Id);
            }
            List <GuildMovieNight> movieNights   = guildMovieNights.ToList();
            InteractivityExtension interactivity = context.Client.GetInteractivity();
            IEnumerable <Page>     pages         = await GetGuildMovieNightsPages(context.Guild, movieNights, interactivity, hasManageServer);

            CustomResult <int> result = await context.WaitForMessageAndPaginateOnMsg(pages,
                                                                                     PaginationMessageFunction.CreateWaitForMessageWithIntInRange(context.User, context.Channel, 1, movieNights.Count + 1)
                                                                                     );

            if (result.TimedOut || result.Cancelled)
            {
                await context.RespondAsync("You never gave me a valid input. Please try again if so desired.");

                return;
            }

            Reaction reaction = await interactivity.AddAndWaitForYesNoReaction(await context.Channel.SendMessageAsync($"You want me to do delete movie night {result.Result}?"), context.Member);

            if (reaction != Reaction.Yes)
            {
                await context.Channel.SendMessageAsync("Ok!");

                return;
            }

            GuildMovieNight chosen = movieNights[result.Result - 1];

            RecurringJob.RemoveIfExists(chosen.MovieNightStartHangfireId);
            RecurringJob.RemoveIfExists(chosen.VotingStartHangfireId);
            RecurringJob.RemoveIfExists(chosen.VotingEndHangfireId);
            await this.mediator.Send(new GuildMovieNights.Delete(chosen));

            await context.Channel.SendMessageAsync($"{context.Member.Mention}, I have deleted movie night {result.Result}");
        }
Exemplo n.º 6
0
        /// <summary>
        /// Generate the embed with the randomly selected movies and add emojis to allow for voting
        /// </summary>
        /// <param name="movieNightId">ID for the movie night in the data store</param>
        /// <exception cref="ArgumentException">Thrown when an unknown movie night ID is provided</exception>
        public async Task StartVoting(int movieNightId)
        {
            GuildMovieNight movieNight = await GetGuildMovieNightAsync(movieNightId);

            (DiscordClient client, DiscordGuild guild, DiscordChannel channel) = await this.GetCommonDiscordObjects(movieNight);

            DbResult <IEnumerable <GuildMovieSuggestion> > randomSuggestionsResult = await this
                                                                                     .mediator.Send(new GuildMovieSuggestions.GetRandomGuildMovieSuggestions(guild, movieNight.NumberOfSuggestions, movieNight.MaximumRating));

            if (!randomSuggestionsResult.TryGetValue(out IEnumerable <GuildMovieSuggestion>?randomSuggestions))
            {
                throw new Exception("Something went wrong with getting the random suggestions.");
            }

            string          description = AddMovieSuggestionsAndGenerateDescription(client, movieNight, randomSuggestions);
            RecurringJobDto rJobDto     = GetMovieNightStartRecurringJobInfo(movieNight);

            DateTimeZone hostDTZ = await GetUserDateTimeZone(movieNight.HostId);

            ZonedDateTime zdt = GetJobsZonedDateTime(rJobDto, hostDTZ);

            DiscordEmbed eBuilder = new DiscordEmbedBuilder()
                                    .WithTitle($"Time to vote for a movie!")
                                    .WithDescription(description)
                                    .AddField("Date and Time of Movie", zdt.ToString("MM/dd/yyyy hh:mm x", null), true)
                                    .AddField("Maximum Parental Rating", movieNight.MaximumRating.ToQueryValue(), true);

            DiscordMessageBuilder mBuilder = new DiscordMessageBuilder()
                                             .WithContent("@everyone")
                                             .WithEmbed(eBuilder);

            DiscordMessage votingMessage = await channel.SendMessageAsync(mBuilder);

            movieNight.VotingMessageId = votingMessage.Id;

            await this.mediator.Send(new GuildMovieNights.Update(movieNight));

            foreach (DiscordEmoji emoji in GetNumberEmojis(client).Take(randomSuggestions.Count()))
            {
                await votingMessage.CreateReactionAsync(emoji);
            }
        }
Exemplo n.º 7
0
        /// <summary>
        /// Determine the number of votes that each movie got and then select the highest ranked movie.
        /// If there is a tie on more than one of the movies, message the movie night creator with an
        /// embed where they will break the tie.
        /// </summary>
        /// <param name="movieNightId">ID for the movie night in the data store</param>
        public async Task CalculateVotes(int movieNightId)
        {
            GuildMovieNight movieNight = await GetGuildMovieNightAsync(movieNightId);

            (DiscordClient client, DiscordGuild guild, DiscordChannel channel) = await this.GetCommonDiscordObjects(movieNight);

            DiscordMessage votingMessage = await channel.GetMessageAsync(movieNight.VotingMessageId ?? throw new Exception("Somehow, some way, the voting message id was null... something done f$*@ed up."));

            Dictionary <string, DiscordReaction> mostReactedReactions = GetMostReactedReactons(votingMessage);

            DiscordMember host = await guild.GetMemberAsync(movieNight.HostId);

            GuildMovieSuggestion winningSuggestion = await GetWinningSuggestion(client, guild, host, movieNight, mostReactedReactions);

            movieNight.WinningMovieImdbId = winningSuggestion.ImdbId;
            DbResult movieNightUpdateResult = await this.mediator.Send(new GuildMovieNights.Update(movieNight));

            if (!movieNightUpdateResult.Success)
            {
                throw new Exception("An error occurred in updating the movie night with the winning suggestion");
            }

            RecurringJobDto rJobDto = GetMovieNightStartRecurringJobInfo(movieNight);

            LocalDateTime ldt     = LocalDateTime.FromDateTime(rJobDto.NextExecution !.Value);
            DateTimeZone  hostDTZ = await GetUserDateTimeZone(movieNight.HostId);

            ZonedDateTime zdt = ldt.InUtc();

            zdt = zdt.WithZone(hostDTZ);

            OmdbMovie movieInfo = await this.omdbClient.GetByImdbIdAsync(winningSuggestion.ImdbId, omdbPlotOption : OmdbPlotOption.SHORT);

            DiscordEmbedBuilder announceWinnerEmbed = movieInfo.ToDiscordEmbedBuilder(true)
                                                      .WithAuthor(host.DisplayName, iconUrl: host.AvatarUrl);
            DiscordMessageBuilder announceWinnerMessage = new DiscordMessageBuilder()
                                                          .WithContent($"@everyone, here's what {host.Mention} is showing {zdt.ToString("MM/dd/yyyy hh:mm x", null)}")
                                                          .WithEmbed(announceWinnerEmbed.Build());

            await channel.SendMessageAsync(announceWinnerMessage);
        }
Exemplo n.º 8
0
        // Private Static Methods
        private static string AddMovieSuggestionsAndGenerateDescription(DiscordClient client, GuildMovieNight movieNight, IEnumerable <GuildMovieSuggestion> suggestions)
        {
            if (GetNumberEmojis(client).Count() < suggestions.Count())
            {
                throw new ArgumentException("Attempted to use more suggestions than is allowed by the system");
            }

            StringBuilder descriptionBuilder = new();

            foreach ((GuildMovieSuggestion gms, DiscordEmoji emoji) in suggestions.Zip(GetNumberEmojis(client)))
            {
                movieNight.MovieNightAndSuggestions.Add(new MovieNightAndSuggestion(movieNight.Id, gms.ImdbId, emoji.Name, gms.GuildId));
                descriptionBuilder.AppendLine($"{emoji}. {gms.Title}");
            }

            return(descriptionBuilder.ToString());
        }
Exemplo n.º 9
0
        private static async Task <GuildMovieSuggestion> GetWinningSuggestion(DiscordClient client, DiscordGuild guild, DiscordMember host, GuildMovieNight movieNight, Dictionary <string, DiscordReaction> mostReactedReactions)
        {
            GuildMovieSuggestion winningSuggestion;

            if (mostReactedReactions.Count > 1)
            {
                winningSuggestion = await DoTiebreaker(client, host, movieNight, mostReactedReactions);
            }
            else
            {
                winningSuggestion = movieNight.MovieNightAndSuggestions.First(mns => mns.EmojiId == mostReactedReactions.First().Value.Emoji.Name).MovieSuggestion;
            }

            return(winningSuggestion);
        }
Exemplo n.º 10
0
        private async Task <(DiscordClient client, DiscordGuild guild, DiscordChannel channel)> GetCommonDiscordObjects(GuildMovieNight movieNight)
        {
            DiscordClient client = this.bot.ShardedClient.GetShard(movieNight.GuildId);
            DiscordGuild  guild  = await client.GetGuildAsync(movieNight.GuildId);

            DiscordChannel channel = guild.GetChannel(movieNight.AnnouncementChannelId);

            return(client, guild, channel);
        }
Exemplo n.º 11
0
        // Private Async Methods
        private static async Task <GuildMovieSuggestion> DoTiebreaker(DiscordClient client, DiscordMember host, GuildMovieNight movieNight, Dictionary <string, DiscordReaction> mostReactedReactions)
        {
            StringBuilder descriptionBuilder = new();
            var           tiedSuggestions    = movieNight.MovieNightAndSuggestions.Where(mns => mostReactedReactions.ContainsKey(mns.EmojiId)).Select(mns => mns.MovieSuggestion).ToList().Zip(GetNumberEmojis(client));

            DiscordEmbedBuilder tiebreakerEmbed = new DiscordEmbedBuilder().WithTitle("You need to break the tie, vote for your favorite of these options.");

            descriptionBuilder.AppendLine("If you don't respond within 10 minutes, a random movie will be selected");
            descriptionBuilder.AppendLine();
            foreach ((GuildMovieSuggestion gms, DiscordEmoji emoji) in tiedSuggestions)
            {
                descriptionBuilder.AppendLine($"{emoji}. {gms.Title}");
            }
            tiebreakerEmbed.WithDescription(descriptionBuilder.ToString());
            DiscordMessage tiebreakerMessage = await host.SendMessageAsync(tiebreakerEmbed);

            List <DiscordEmoji> emojis = tiedSuggestions.Select(x => x.Second).ToList();

            foreach (DiscordEmoji emoji in emojis)
            {
                await tiebreakerMessage.CreateReactionAsync(emoji);
            }

            HashSet <string> emojiNames = emojis.Select(x => x.Name).ToHashSet();
            InteractivityResult <MessageReactionAddEventArgs> tiebreakerReaction =
                await client
                .GetInteractivity()
                .WaitForReactionAsync(
                    x => x.Message.Id == tiebreakerMessage.Id &&
                    emojiNames.Contains(x.Emoji.Name),
                    host,
                    TimeSpan.FromMinutes(10)
                    );

            if (tiebreakerReaction.TimedOut)
            {
                List <GuildMovieSuggestion> tiedList = tiedSuggestions.Select(x => x.First).ToList();
                return(tiedList[new Random().Next(tiedList.Count)]);
            }
            else
            {
                return(tiedSuggestions.First(x => x.Second.Name == tiebreakerReaction.Result.Emoji.Name).First);
            }
        }
Exemplo n.º 12
0
 public Delete(GuildMovieNight movieNight)
 {
     this.GuildMovieNight = movieNight;
 }