Ejemplo n.º 1
0
        public override Task <PreconditionResult> CheckPermissionsAsync(
            ICommandContext context, CommandInfo command, IServiceProvider serviceProvider)
        {
            Verify.IsNotNull(context, nameof(context));

            GlobalTournamentsManager globalManager = serviceProvider.GetService <GlobalTournamentsManager>();
            TournamentsManager       manager       = globalManager.GetOrAdd(context.Guild.Id, CreateTournamentsManager);

            // TD is only allowed to run commands when they are a director of the current tournament.
            Result <bool> result = manager.TryReadActionOnCurrentTournament(currentTournament =>
                                                                            currentTournament.GuildId == context.Guild.Id && CanActAsTournamentDirector(context, currentTournament)
                                                                            );

            if (result.Success && result.Value)
            {
                return(Task.FromResult(PreconditionResult.FromSuccess()));
            }
            else if (command.Name == SetupCommandName && context.Message.Content.Length > SetupCommand.Length)
            {
                // TODO: We should investigate if there's a better place to make this check, because the attribute
                // now knows about "setup"
                string tournamentName = context.Message.Content.Substring(SetupCommand.Length).Trim();
                if (IsAdminUser(context) ||
                    (manager.TryGetTournament(tournamentName, out ITournamentState tournament) &&
                     CanActAsTournamentDirector(context, tournament)))
                {
                    return(Task.FromResult(PreconditionResult.FromSuccess()));
                }
            }

            return(Task.FromResult(PreconditionResult.FromError("User did not have tournament director privileges.")));
        }
Ejemplo n.º 2
0
        public async Task AddTwoTournamentDirectors()
        {
            const ulong              firstUserId   = 123;
            const ulong              secondUserId  = 1234;
            MessageStore             messageStore  = new MessageStore();
            ICommandContext          context       = this.CreateCommandContext(messageStore);
            GlobalTournamentsManager globalManager = new GlobalTournamentsManager();

            AddTournamentDirectorDirectly(globalManager, firstUserId);

            BotCommandHandler commandHandler = new BotCommandHandler(context, globalManager);

            IGuildUser guildUser = this.CreateGuildUser(secondUserId);
            await commandHandler.AddTournamentDirectorAsync(guildUser, DefaultTournamentName);

            string expectedMessage = BotStrings.AddTournamentDirectorSuccessful(
                DefaultTournamentName, DefaultGuildName);

            messageStore.VerifyChannelMessages(expectedMessage);

            TournamentsManager manager = globalManager.GetOrAdd(DefaultGuildId, id => new TournamentsManager());

            Assert.IsTrue(
                manager.TryGetTournament(DefaultTournamentName, out ITournamentState state),
                "Could not find tournament.");
            Assert.IsTrue(state.IsDirector(firstUserId), "First director was not added.");
            Assert.IsTrue(state.IsDirector(secondUserId), "Second director was not added.");
        }
Ejemplo n.º 3
0
        public Bot(BotConfiguration configuration)
        {
            DiscordSocketConfig clientConfig = new DiscordSocketConfig()
            {
                // 16 kb?
                MessageCacheSize = 1024 * 16
            };

            this.Client         = new DiscordSocketClient(clientConfig);
            this.Configuration  = configuration;
            this.CommandService = new CommandService(new CommandServiceConfig()
            {
                CaseSensitiveCommands = false,
                LogLevel = LogSeverity.Info
            });

            this.Logger = Log.ForContext(this.GetType());

            GlobalTournamentsManager globalManager     = new GlobalTournamentsManager();
            IServiceCollection       serviceCollection = new ServiceCollection();

            serviceCollection.AddSingleton(this.Client);
            serviceCollection.AddSingleton(globalManager);
            serviceCollection.AddSingleton(this.Configuration);
            this.ServiceProvider = serviceCollection.BuildServiceProvider();

            this.EventHandler = new BotEventHandler(this.Client, globalManager);

            // TODO: If we want to split up BotCommands, use Assembly.GetEntryAssembly.
            Task.WaitAll(this.CommandService.AddModulesAsync(Assembly.GetExecutingAssembly(), this.ServiceProvider));
        }
Ejemplo n.º 4
0
        public async Task ScheduleRequiresMultipleEmbeds()
        {
            const int teamsCount   = 50;
            const int readersCount = teamsCount / 2;

            MessageStore             messageStore  = new MessageStore();
            ICommandContext          context       = this.CreateCommandContext(messageStore, guildId: DefaultGuildId);
            GlobalTournamentsManager globalManager = new GlobalTournamentsManager();
            TournamentsManager       manager       = globalManager.GetOrAdd(DefaultGuildId, id => new TournamentsManager());

            HashSet <Team> teams = new HashSet <Team>(
                Enumerable.Range(1, teamsCount).Select(id => new Team()
            {
                Name = $"#Team{id}"
            }));
            HashSet <Reader> readers = new HashSet <Reader>(
                Enumerable.Range(1, readersCount).Select(id => new Reader()
            {
                Id = (ulong)id, Name = $"#Reader{id}"
            }));

            RoundRobinScheduleFactory factory = new RoundRobinScheduleFactory(1, 0);
            Schedule schedule = factory.Generate(teams, readers);

            ITournamentState state = new TournamentState(DefaultGuildId, "T");

            state.Schedule = schedule;
            manager.AddOrUpdateTournament(state.Name, state, (name, oldState) => oldState);
            Assert.IsTrue(
                manager.TrySetCurrentTournament(state.Name, out string errorMessage),
                $"Failed to set the tournament: '{errorMessage}'");
            globalManager.GetOrAdd(DefaultGuildId, id => manager);

            BotCommandHandler commandHandler = new BotCommandHandler(context, globalManager);

            await commandHandler.GetScheduleAsync();

            Assert.IsTrue(
                messageStore.ChannelEmbeds.Count > 1,
                $"Expected more than 1 embed, got {messageStore.ChannelEmbeds.Count}");

            string allEmbeds = string.Join('\n', messageStore.ChannelEmbeds);

            for (int round = 0; round < schedule.Rounds.Count; round++)
            {
                Assert.IsTrue(
                    allEmbeds.Contains(BotStrings.RoundNumber(round + 1)),
                    $"Round {round + 1} not found in the embeds. Embeds: '{allEmbeds}'");
                foreach (Game game in schedule.Rounds[round].Games)
                {
                    string expectedGame = BotStrings.ScheduleLine(
                        game.Reader.Name, game.Teams.Select(team => team.Name).ToArray());
                    Assert.IsTrue(
                        allEmbeds.Contains(expectedGame),
                        $"Game '{expectedGame}' not foudn in embed. Embed: '{allEmbeds}'");
                }
            }
        }
Ejemplo n.º 5
0
        public BotCommandHandler(ICommandContext context, GlobalTournamentsManager globalManager)
        {
            Verify.IsNotNull(context, nameof(context));
            Verify.IsNotNull(globalManager, nameof(globalManager));

            this.ChannelManager = new TournamentChannelManager(context.Guild);
            this.Context        = context;
            this.GlobalManager  = globalManager;
            this.Logger         = Log
                                  .ForContext <BotCommandHandler>()
                                  .ForContext("guildId", this.Context.Guild?.Id);
        }
Ejemplo n.º 6
0
        public async Task NoCurrentTournament()
        {
            MessageStore             messageStore  = new MessageStore();
            ICommandContext          context       = this.CreateCommandContext(messageStore);
            GlobalTournamentsManager globalManager = new GlobalTournamentsManager();

            BotCommandHandler commandHandler = new BotCommandHandler(context, globalManager);
            await commandHandler.GetCurrentTournamentAsync();

            string expectedMessage = BotStrings.UnableToPerformCommand(TournamentStrings.NoCurrentTournamentRunning);

            messageStore.VerifyDirectMessages(expectedMessage);
        }
Ejemplo n.º 7
0
        // TODO: Add wrapper class/interface for the client to let us test the event handlers.
        // The events themselves pass in SocketMessages, so perhaps grab some fields and abstract the logic. Let's do a
        // straight transfer first.
        public BotEventHandler(DiscordSocketClient client, GlobalTournamentsManager globalManager)
        {
            Verify.IsNotNull(client, nameof(client));

            this.IsDisposed    = false;
            this.Client        = client;
            this.GlobalManager = globalManager;

            this.Client.MessageReceived += this.OnMessageReceived;
            this.Client.ReactionAdded   += this.OnReactionAdded;
            this.Client.ReactionRemoved += this.OnReactionRemoved;

            this.Logger = Log.ForContext <BotEventHandler>();
        }
Ejemplo n.º 8
0
        protected ITournamentState AddCurrentTournament(
            GlobalTournamentsManager globalManager,
            ulong guildId         = DefaultGuildId,
            string tournamentName = DefaultTournamentName)
        {
            TournamentsManager manager = globalManager.GetOrAdd(guildId, id => new TournamentsManager());
            ITournamentState   state   = new TournamentState(guildId, tournamentName);

            state = manager.AddOrUpdateTournament(tournamentName, state, (name, oldState) => state);
            Assert.IsTrue(
                manager.TrySetCurrentTournament(tournamentName, out string errorMessage),
                "We should be able to set the current tournament.");
            return(state);
        }
Ejemplo n.º 9
0
        public async Task GetCurrentTournament()
        {
            MessageStore             messageStore  = new MessageStore();
            ICommandContext          context       = this.CreateCommandContext(messageStore);
            GlobalTournamentsManager globalManager = new GlobalTournamentsManager();

            this.AddCurrentTournament(globalManager);

            BotCommandHandler commandHandler = new BotCommandHandler(context, globalManager);
            await commandHandler.GetCurrentTournamentAsync();

            string expectedMessage = BotStrings.CurrentTournamentInGuild(DefaultGuildName, DefaultTournamentName);

            messageStore.VerifyDirectMessages(expectedMessage);
        }
Ejemplo n.º 10
0
        // TODO: Add test for ClearAll that checks that all artifacts are cleared.

        private static void AddTournamentDirectorDirectly(GlobalTournamentsManager globalManager, ulong userId)
        {
            TournamentsManager manager = globalManager.GetOrAdd(
                DefaultGuildId,
                id => new TournamentsManager()
            {
                GuildId = id
            });
            ITournamentState state = manager.AddOrUpdateTournament(
                DefaultTournamentName,
                new TournamentState(DefaultGuildId, DefaultTournamentName),
                (name, oldState) => oldState);

            Assert.IsTrue(state.TryAddDirector(userId), "First TD added should occur.");
        }
Ejemplo n.º 11
0
        public async Task RemoveFromNonexistentTournament()
        {
            const ulong              otherId        = DefaultUserId + 1;
            MessageStore             messageStore   = new MessageStore();
            ICommandContext          context        = this.CreateCommandContext(messageStore);
            GlobalTournamentsManager globalManager  = new GlobalTournamentsManager();
            BotCommandHandler        commandHandler = new BotCommandHandler(context, globalManager);

            IGuildUser guildUser = this.CreateGuildUser(otherId);
            await commandHandler.RemoveTournamentDirectorAsync(guildUser, DefaultTournamentName);

            string expectedMessage = BotStrings.TournamentDoesNotExist(DefaultTournamentName, DefaultGuildName);

            messageStore.VerifyChannelMessages(expectedMessage);
        }
Ejemplo n.º 12
0
        public async Task RemoveNonexistentTournamentDirector()
        {
            const ulong              otherId        = DefaultUserId + 1;
            MessageStore             messageStore   = new MessageStore();
            ICommandContext          context        = this.CreateCommandContext(messageStore);
            GlobalTournamentsManager globalManager  = new GlobalTournamentsManager();
            BotCommandHandler        commandHandler = new BotCommandHandler(context, globalManager);

            AddTournamentDirectorDirectly(globalManager, DefaultUserId);

            IGuildUser guildUser = this.CreateGuildUser(otherId);
            await commandHandler.RemoveTournamentDirectorAsync(guildUser, DefaultTournamentName);

            string expectedMessage = BotStrings.UserNotTournamentDirector(DefaultTournamentName, DefaultGuildName);

            messageStore.VerifyChannelMessages(expectedMessage);

            TournamentsManager manager = globalManager.GetOrAdd(DefaultGuildId, id => new TournamentsManager());

            Assert.IsTrue(
                manager.TryGetTournament(DefaultTournamentName, out ITournamentState state), "Could not find tournament.");
            Assert.IsFalse(state.IsDirector(otherId), "Director should not have been added.");
        }
Ejemplo n.º 13
0
        public async Task AddSameTournamentDirectors()
        {
            MessageStore             messageStore  = new MessageStore();
            ICommandContext          context       = this.CreateCommandContext(messageStore);
            GlobalTournamentsManager globalManager = new GlobalTournamentsManager();

            AddTournamentDirectorDirectly(globalManager, DefaultUserId);

            BotCommandHandler commandHandler = new BotCommandHandler(context, globalManager);

            IGuildUser guildUser = this.CreateGuildUser(DefaultUserId);
            await commandHandler.AddTournamentDirectorAsync(guildUser, DefaultTournamentName);

            string expectedMessage = BotStrings.UserAlreadyTournamentDirector(DefaultTournamentName, DefaultGuildName);

            messageStore.VerifyChannelMessages(expectedMessage);

            TournamentsManager manager = globalManager.GetOrAdd(DefaultGuildId, id => new TournamentsManager());

            Assert.IsTrue(
                manager.TryGetTournament(DefaultTournamentName, out ITournamentState state),
                "Could not find tournament.");
            Assert.IsTrue(state.IsDirector(DefaultUserId), "User should still be a director.");
        }
Ejemplo n.º 14
0
 public TournamentDirectorBotCommands(GlobalTournamentsManager globalManager)
     : base(globalManager)
 {
 }
Ejemplo n.º 15
0
        public async Task SimplestSchedule()
        {
            const string readerName     = "#Reader";
            const string firstTeamName  = "#TeamA";
            const string secondTeamName = "#TeamB";

            MessageStore             messageStore  = new MessageStore();
            ICommandContext          context       = this.CreateCommandContext(messageStore, guildId: DefaultGuildId);
            GlobalTournamentsManager globalManager = new GlobalTournamentsManager();
            TournamentsManager       manager       = globalManager.GetOrAdd(DefaultGuildId, id => new TournamentsManager());

            HashSet <Team> teams = new HashSet <Team>()
            {
                new Team()
                {
                    Name = firstTeamName
                },
                new Team()
                {
                    Name = secondTeamName
                }
            };
            HashSet <Reader> readers = new HashSet <Reader>()
            {
                new Reader()
                {
                    Id   = 0,
                    Name = readerName
                }
            };
            RoundRobinScheduleFactory factory = new RoundRobinScheduleFactory(2, 0);
            Schedule schedule = factory.Generate(teams, readers);

            ITournamentState state = new TournamentState(DefaultGuildId, "T");

            state.Schedule = schedule;
            manager.AddOrUpdateTournament(state.Name, state, (name, oldState) => oldState);
            Assert.IsTrue(
                manager.TrySetCurrentTournament(state.Name, out string errorMessage),
                $"Failed to set the tournament: '{errorMessage}'");
            globalManager.GetOrAdd(DefaultGuildId, id => manager);

            BotCommandHandler commandHandler = new BotCommandHandler(context, globalManager);

            await commandHandler.GetScheduleAsync();

            Assert.AreEqual(1, messageStore.ChannelEmbeds.Count, "Unexpected number of embeds");

            string embed = messageStore.ChannelEmbeds[0];

            for (int round = 0; round < schedule.Rounds.Count; round++)
            {
                Assert.IsTrue(
                    embed.Contains(BotStrings.RoundNumber(round + 1)),
                    $"Round {round + 1} not found in embed. Embed: '{embed}'");
                string expectedGame = BotStrings.ScheduleLine(
                    readerName, schedule.Rounds[round].Games[0].Teams.Select(team => team.Name).ToArray());
                Assert.IsTrue(
                    embed.Contains(expectedGame),
                    $"Game '{expectedGame}' not foudn in embed. Embed: '{embed}'");
            }
        }
Ejemplo n.º 16
0
 public GuildBotCommands(GlobalTournamentsManager globalManager)
     : base(globalManager)
 {
 }
Ejemplo n.º 17
0
 public AdminBotCommands(GlobalTournamentsManager globalManager)
     : base(globalManager)
 {
 }
Ejemplo n.º 18
0
 public BotCommandsBase(GlobalTournamentsManager globalManager)
 {
     this.GlobalManager = globalManager;
     this.Logger        = Log.ForContext(this.GetType());
 }
Ejemplo n.º 19
0
 public GeneralBotCommands(GlobalTournamentsManager globalManager)
     : base(globalManager)
 {
 }