Ejemplo n.º 1
0
        public SlackResponseDoc SubmitQuestion(SlackRequestDoc requestDoc, string question)
        {
            try
            {
                _workflowService.OnQuestionSubmitted(requestDoc.ChannelId, requestDoc.UserId, question);
            }
            catch (GameNotStartedException)
            {
                return(SlackResponseDoc.Failure(String.Format(GAME_NOT_STARTED_FORMAT, requestDoc.Command)));
            }
            catch (WorkflowException e)
            {
                return(SlackResponseDoc.Failure(e.Message));
            }

            SlackResponseDoc delayedResponseDoc = new SlackResponseDoc
            {
                ResponseType = SlackResponseType.IN_CHANNEL,
                Text         = String.Format("<@{0}> asked the following question:\n\n{1}", requestDoc.UserId, question)
            };

            _delayedSlackService.sendResponse(requestDoc.ResponseUrl, delayedResponseDoc);

            return(new SlackResponseDoc
            {
                ResponseType = SlackResponseType.EPHEMERAL,
                Text = "Question posted."
            });
        }
Ejemplo n.º 2
0
        public SlackResponseDoc Join(SlackRequestDoc requestDoc)
        {
            SlackUser user        = new SlackUser(requestDoc.UserId, requestDoc.Username);
            bool      userCreated = _scoreService.CreateUserIfNotExists(requestDoc.ChannelId, user);

            SlackResponseDoc responseDoc = new SlackResponseDoc
            {
                ResponseType = SlackResponseType.EPHEMERAL
            };

            if (userCreated)
            {
                responseDoc.Text = "Joining game.";

                SlackResponseDoc delayedResponseDoc = new SlackResponseDoc
                {
                    ResponseType = SlackResponseType.IN_CHANNEL,
                    Text         = String.Format("<@{0}> has joined the game!", user.UserId)
                };

                _delayedSlackService.sendResponse(requestDoc.ResponseUrl, delayedResponseDoc);
            }
            else
            {
                responseDoc.Text = "You're already in the game.";
            }

            return(responseDoc);
        }
Ejemplo n.º 3
0
        public SlackResponseDoc MarkAnswerIncorrect(SlackRequestDoc requestDoc, string target)
        {
            string userId = SlackUtils.NormalizeId(target);

            try
            {
                _workflowService.OnIncorrectAnswerSelected(requestDoc.ChannelId, requestDoc.UserId, userId);
            }
            catch (GameNotStartedException e)
            {
                return(SlackResponseDoc.Failure(String.Format(GAME_NOT_STARTED_FORMAT, requestDoc.Command)));
            }
            catch (WorkflowException e)
            {
                return(SlackResponseDoc.Failure(e.Message));
            }

            SlackResponseDoc delayedResponseDoc = new SlackResponseDoc
            {
                ResponseType = SlackResponseType.IN_CHANNEL,
                Text         = String.Format("You couldn't be more wrong, <@{0}>", userId)
            };

            _delayedSlackService.sendResponse(requestDoc.ResponseUrl, delayedResponseDoc);

            return(new SlackResponseDoc
            {
                ResponseType = SlackResponseType.EPHEMERAL,
                Text = "Marked answer incorrect."
            });
        }
Ejemplo n.º 4
0
        private string generateScoreText(SlackRequestDoc requestDoc)
        {
            Dictionary <SlackUser, long> scoresByUser = _scoreService.GetAllScoresByUser(requestDoc.ChannelId);

            string scoreText;

            if (!scoresByUser.Any())
            {
                scoreText = "No scores yet...";
            }
            else
            {
                int maxUsernameLength = 1 + scoresByUser.Keys
                                        .Select(e => e.Username.Length)
                                        .Max();

                //sort by score desc, username
                var scoresByUserSorted = from pair in scoresByUser
                                         orderby pair.Value descending, pair.Key.Username ascending
                select pair;

                scoreText = scoresByUserSorted
                            .Select(e => String.Format("@{0,-" + maxUsernameLength + "} {1,3}", e.Key.Username + ":", e.Value))
                            .Aggregate((a, b) => a + "\n" + b);
            }

            return(String.Format(SCORES_FORMAT, scoreText));
        }
Ejemplo n.º 5
0
        public SlackResponseDoc Stop(SlackRequestDoc requestDoc)
        {
            try
            {
                _workflowService.OnGameStopped(requestDoc.ChannelId, requestDoc.UserId);
            }
            catch (GameNotStartedException)
            {
                return(SlackResponseDoc.Failure(String.Format(GAME_NOT_STARTED_FORMAT, requestDoc.Command)));
            }
            catch (WorkflowException e)
            {
                return(SlackResponseDoc.Failure(e.Message));
            }

            return(new SlackResponseDoc
            {
                ResponseType = SlackResponseType.IN_CHANNEL,
                Text = String.Format(
                    "The game has been stopped but scores have not been cleared. If you'd like to start a new game, try `{0} start`.",
                    requestDoc.Command,
                    requestDoc.UserId
                    )
            });
        }
Ejemplo n.º 6
0
 public SlackResponseDoc GetScores(SlackRequestDoc requestDoc)
 {
     return(new SlackResponseDoc
     {
         ResponseType = SlackResponseType.EPHEMERAL,
         Text = generateScoreText(requestDoc)
     });
 }
Ejemplo n.º 7
0
        public SlackResponseDoc GetStatus(SlackRequestDoc requestDoc)
        {
            GameState gameState = _workflowService.GetCurrentGameState(requestDoc.ChannelId);

            return(new SlackResponseDoc
            {
                ResponseType = SlackResponseType.EPHEMERAL,
                Text = generateStatusText(requestDoc, gameState)
            });
        }
Ejemplo n.º 8
0
        public SlackResponseDoc ResetScores(SlackRequestDoc requestDoc)
        {
            _scoreService.ResetScores(requestDoc.ChannelId);

            return(new SlackResponseDoc
            {
                ResponseType = SlackResponseType.IN_CHANNEL,
                Text = "Scores have been reset!",
                Attachments = new List <SlackAttachment> {
                    new SlackAttachment(generateScoreText(requestDoc))
                }
            });
        }
Ejemplo n.º 9
0
        public void TestMarkCorrectCommandWithAnswer()
        {
            SlackRequestDoc requestDoc = new SlackRequestDoc
            {
                Text = "correct <@12345>   I    do not    know"
            };
            SlackResponseDoc responseDoc = new SlackResponseDoc();

            triviaGameService.Setup(x => x.MarkAnswerCorrect(It.IsAny <SlackRequestDoc>(), It.IsAny <string>(), It.IsAny <string>())).Returns(responseDoc);

            SlackResponseDoc result = cut.ProcessSlashCommand(requestDoc);

            Assert.AreSame(responseDoc, result);

            triviaGameService.Verify(x => x.MarkAnswerCorrect(requestDoc, "<@12345>", "I    do not    know"));
        }
Ejemplo n.º 10
0
        public void TestAnswerCommand()
        {
            SlackRequestDoc requestDoc = new SlackRequestDoc
            {
                Text = "  answer   I    do not    know   "
            };
            SlackResponseDoc responseDoc = new SlackResponseDoc();

            triviaGameService.Setup(x => x.SubmitAnswer(It.IsAny <SlackRequestDoc>(), It.IsAny <string>())).Returns(responseDoc);

            SlackResponseDoc result = cut.ProcessSlashCommand(requestDoc);

            Assert.AreSame(responseDoc, result);

            triviaGameService.Verify(x => x.SubmitAnswer(requestDoc, "I    do not    know"));
        }
Ejemplo n.º 11
0
        public void TestQuestionCommand()
        {
            SlackRequestDoc requestDoc = new SlackRequestDoc
            {
                Text = "  question   What    does ATM stand for?   "
            };
            SlackResponseDoc responseDoc = new SlackResponseDoc();

            triviaGameService.Setup(x => x.SubmitQuestion(It.IsAny <SlackRequestDoc>(), It.IsAny <string>())).Returns(responseDoc);

            SlackResponseDoc result = cut.ProcessSlashCommand(requestDoc);

            Assert.AreSame(responseDoc, result);

            triviaGameService.Verify(x => x.SubmitQuestion(requestDoc, "What    does ATM stand for?"));
        }
Ejemplo n.º 12
0
        public void TestStopCommand()
        {
            SlackRequestDoc requestDoc = new SlackRequestDoc
            {
                Text = "  stop  "
            };
            SlackResponseDoc responseDoc = new SlackResponseDoc();

            triviaGameService.Setup(x => x.Stop(It.IsAny <SlackRequestDoc>())).Returns(responseDoc);

            SlackResponseDoc result = cut.ProcessSlashCommand(requestDoc);

            Assert.AreSame(responseDoc, result);

            triviaGameService.Verify(x => x.Stop(requestDoc));
        }
Ejemplo n.º 13
0
        public void TestStartCommandWithTopic()
        {
            SlackRequestDoc requestDoc = new SlackRequestDoc
            {
                Text = "  start  movie quotes"
            };
            SlackResponseDoc responseDoc = new SlackResponseDoc();

            triviaGameService.Setup(x => x.Start(It.IsAny <SlackRequestDoc>(), It.IsAny <string>())).Returns(responseDoc);

            SlackResponseDoc result = cut.ProcessSlashCommand(requestDoc);

            Assert.AreSame(responseDoc, result);

            triviaGameService.Verify(x => x.Start(requestDoc, "movie quotes"));
        }
Ejemplo n.º 14
0
        private string generateStatusText(SlackRequestDoc requestDoc, GameState gameState)
        {
            if (gameState == null || gameState.ControllingUserId == null)
            {
                return(String.Format(GAME_NOT_STARTED_FORMAT, requestDoc.Command));
            }

            bool isControllingUser = gameState.ControllingUserId == requestDoc.UserId;

            string topic    = gameState.Topic == null ? "None" : gameState.Topic;
            string turn     = isControllingUser ? "Yours" : "<@" + gameState.ControllingUserId + ">";
            string question = gameState.Question == null ? " Waiting..." : ("\n\n" + gameState.Question);

            string statusText = String.Format(BASE_STATUS_FORMAT, topic, turn, question);

            if (gameState.Question != null)
            {
                string answerText;

                if (gameState.Answers == null || !gameState.Answers.Any())
                {
                    answerText = " Waiting...";
                }
                else
                {
                    int maxUsernameLength = 1 + gameState.Answers
                                            .Select(a => a.Username.Length)
                                            .Max();

                    answerText = "\n\n```" + gameState.Answers
                                 .OrderBy(answer => answer.CreatedDate)
                                 .Select(answer =>
                                         String.Format(
                                             SINGLE_ANSWER_FORMAT,
                                             TimeZoneInfo.ConvertTimeFromUtc(answer.CreatedDate, TimeZoneInfo.FindSystemTimeZoneById(LOCAL_TIMEZONE_NAME)).ToString(DATE_FORMAT),
                                             String.Format("@{0,-" + maxUsernameLength + "}", answer.Username),
                                             answer.Text
                                             )
                                         )
                                 .Aggregate((a, b) => a + "\n" + b) + "```";
                }

                statusText += String.Format(ANSWERS_FORMAT, answerText);
            }

            return(statusText);
        }
Ejemplo n.º 15
0
        public void TestQuestionCommandWithTooFewArguments()
        {
            SlackRequestDoc requestDoc = new SlackRequestDoc
            {
                Command = "/command",
                Text    = "question"
            };

            SlackResponseDoc result = cut.ProcessSlashCommand(requestDoc);

            Assert.IsNotNull(result);
            Assert.AreEqual(SlackResponseType.EPHEMERAL, result.ResponseType);
            Assert.AreEqual("To submit a question, use `/command question <QUESTION_TEXT>`.\n\nFor example, `/command question In what year did WWII officially begin?`", result.Text);
            Assert.IsNull(result.Attachments);

            triviaGameService.VerifyNoOtherCalls();
        }
Ejemplo n.º 16
0
        public void TestAnswerCommandWithTooFewArguments()
        {
            SlackRequestDoc requestDoc = new SlackRequestDoc
            {
                Command = "/command",
                Text    = "answer"
            };

            SlackResponseDoc result = cut.ProcessSlashCommand(requestDoc);

            Assert.IsNotNull(result);
            Assert.AreEqual(SlackResponseType.EPHEMERAL, result.ResponseType);
            Assert.AreEqual("To submit an answer, use `/command answer <ANSWER_TEXT>`.\n\nFor example, `/command answer Blue skies`", result.Text);
            Assert.IsNull(result.Attachments);

            triviaGameService.VerifyNoOtherCalls();
        }
Ejemplo n.º 17
0
        public SlackResponseDoc Pass(SlackRequestDoc requestDoc, string target)
        {
            string userId = SlackUtils.NormalizeId(target);

            try
            {
                bool userExists = _scoreService.DoesUserExist(requestDoc.ChannelId, userId);

                if (!userExists)
                {
                    SlackResponseDoc responseDoc = SlackResponseDoc.Failure("User " + target + " does not exist. Please choose a valid user.");
                    responseDoc.Attachments = new List <SlackAttachment> {
                        new SlackAttachment("Usage: `" + requestDoc.Command + " pass @jsmith`")
                    };
                    return(responseDoc);
                }

                _workflowService.OnTurnChanged(requestDoc.ChannelId, requestDoc.UserId, userId);
            }
            catch (GameNotStartedException)
            {
                return(SlackResponseDoc.Failure(String.Format(GAME_NOT_STARTED_FORMAT, requestDoc.Command)));
            }
            catch (WorkflowException e)
            {
                return(SlackResponseDoc.Failure(e.Message));
            }

            SlackResponseDoc delayedResponseDoc = new SlackResponseDoc
            {
                ResponseType = SlackResponseType.IN_CHANNEL,
                Text         = String.Format("<@{0}> has decided to pass his/her turn to <@{1}>.\n\nOK, <@{1}>, it's your turn to ask a question!", requestDoc.UserId, userId)
            };

            _delayedSlackService.sendResponse(requestDoc.ResponseUrl, delayedResponseDoc);

            return(new SlackResponseDoc
            {
                ResponseType = SlackResponseType.EPHEMERAL,
                Text = "Turn passed to <@" + userId + ">."
            });
        }
Ejemplo n.º 18
0
        public SlackResponseDoc SubmitAnswer(SlackRequestDoc requestDoc, string answer)
        {
            try
            {
                _workflowService.OnAnswerSubmitted(
                    requestDoc.ChannelId,
                    requestDoc.UserId,
                    requestDoc.Username,
                    answer,
                    requestDoc.RequestTime
                    );
            }
            catch (GameNotStartedException)
            {
                return(SlackResponseDoc.Failure(String.Format(GAME_NOT_STARTED_FORMAT, requestDoc.Command)));
            }
            catch (WorkflowException e)
            {
                return(SlackResponseDoc.Failure(e.Message));
            }

            SlackUser user = new SlackUser(requestDoc.UserId, requestDoc.Username);

            _scoreService.CreateUserIfNotExists(requestDoc.ChannelId, user);

            SlackResponseDoc delayedResponseDoc = new SlackResponseDoc
            {
                ResponseType = SlackResponseType.IN_CHANNEL,
                Text         = String.Format("<@{0}> answers:", requestDoc.UserId),
                Attachments  = new List <SlackAttachment> {
                    new SlackAttachment(answer, false)
                }
            };

            _delayedSlackService.sendResponse(requestDoc.ResponseUrl, delayedResponseDoc);

            return(new SlackResponseDoc
            {
                ResponseType = SlackResponseType.EPHEMERAL,
                Text = "Answer submitted."
            });
        }
Ejemplo n.º 19
0
        public void TestMarkCorrectCommandWithTooFewArguments()
        {
            SlackRequestDoc requestDoc = new SlackRequestDoc
            {
                Command = "/command",
                Text    = "correct"
            };

            SlackResponseDoc result = cut.ProcessSlashCommand(requestDoc);

            Assert.IsNotNull(result);
            Assert.AreEqual(SlackResponseType.EPHEMERAL, result.ResponseType);
            Assert.AreEqual(
                "To mark an answer correct, use `/command correct <USERNAME>`.\n" +
                "Optional: To include the correct answer, use `/command correct <USERNAME> <CORRECT_ANSWER>`.\n\n" +
                "For example, `/command correct @jsmith Chris Farley`",
                result.Text
                );
            Assert.IsNull(result.Attachments);

            triviaGameService.VerifyNoOtherCalls();
        }
Ejemplo n.º 20
0
        public SlackResponseDoc Start(SlackRequestDoc requestDoc, string topic)
        {
            string channelId = requestDoc.ChannelId;
            string userId    = requestDoc.UserId;

            try
            {
                _workflowService.OnGameStarted(channelId, userId, topic);
            }
            catch (GameNotStartedException)
            {
                return(SlackResponseDoc.Failure(String.Format(GAME_NOT_STARTED_FORMAT, requestDoc.Command)));
            }
            catch (WorkflowException e)
            {
                return(SlackResponseDoc.Failure(e.Message));
            }

            return(new SlackResponseDoc
            {
                ResponseType = SlackResponseType.IN_CHANNEL,
                Text = String.Format("OK, <@{0}>, please ask a question.", userId)
            });
        }
Ejemplo n.º 21
0
 public SlackResponseDoc SlackSlashCommand([FromForm] SlackRequestDoc requestDoc)
 {
     return(_slackSlashCommandService.ProcessSlashCommand(requestDoc));
 }
        public SlackResponseDoc ProcessSlashCommand(SlackRequestDoc requestDoc)
        {
            //First thing, capture the timestamp
            requestDoc.RequestTime = DateTime.Now;

            string commandText = requestDoc.Text == null ? "" : requestDoc.Text.Trim();

            string[] commandParts = Regex.Split(commandText, "\\s+");

            string operatorText = null;

            if (commandParts.Length >= 1)
            {
                operatorText = commandParts[0];
                commandText  = commandText.Substring(operatorText.Length).Trim();
            }

            switch (operatorText)
            {
            case "start":
                return(_triviaGameService.Start(requestDoc, String.IsNullOrEmpty(commandText) ? null : commandText));

            case "stop":
                return(_triviaGameService.Stop(requestDoc));

            case "join":
                return(_triviaGameService.Join(requestDoc));

            case "pass":
                if (commandParts.Length < 2)
                {
                    return(getPassFormat(requestDoc.Command));
                }

                return(_triviaGameService.Pass(requestDoc, commandText));

            case "question":
                if (commandParts.Length < 2)
                {
                    return(getSubmitQuestionFormat(requestDoc.Command));
                }

                return(_triviaGameService.SubmitQuestion(requestDoc, commandText));

            case "answer":
                if (commandParts.Length < 2)
                {
                    return(getSubmitAnswerFormat(requestDoc.Command));
                }

                return(_triviaGameService.SubmitAnswer(requestDoc, commandText));

            case "incorrect":
                if (commandParts.Length < 2)
                {
                    return(getMarkAnswerIncorrectFormat(requestDoc.Command));
                }

                return(_triviaGameService.MarkAnswerIncorrect(requestDoc, commandText));

            case "correct":
                if (commandParts.Length < 2)
                {
                    return(getMarkAnswerCorrectFormat(requestDoc.Command));
                }

                return(_triviaGameService.MarkAnswerCorrect(
                           requestDoc,
                           commandParts[1],
                           commandParts.Length > 2 ? commandText.Substring(commandParts[1].Length).Trim() : null
                           ));

            case "status":
                return(_triviaGameService.GetStatus(requestDoc));

            case "scores":
                return(_triviaGameService.GetScores(requestDoc));

            case "reset":
                return(_triviaGameService.ResetScores(requestDoc));
            }

            return(getUsageFormat(requestDoc.Command));
        }
Ejemplo n.º 23
0
        public SlackResponseDoc MarkAnswerCorrect(SlackRequestDoc requestDoc, string target, string answer)
        {
            string text;

            try
            {
                _workflowService.OnCorrectAnswerSelected(requestDoc.ChannelId, requestDoc.UserId);

                if (target.Equals(NO_CORRECT_ANSWER_TARGET, StringComparison.InvariantCultureIgnoreCase))
                {
                    //"Change" back to the original host to reset the workflow state
                    _workflowService.OnTurnChanged(requestDoc.ChannelId, requestDoc.UserId, requestDoc.UserId);

                    if (answer == null)
                    {
                        text = String.Format(
                            "It looks like no one was able to answer that one!\n\n{0}\n\nOK, <@{1}>, let's try another one!",
                            generateScoreText(requestDoc),
                            requestDoc.UserId
                            );
                    }
                    else
                    {
                        text = String.Format(
                            "It looks like no one was able to answer that one! The correct answer was {0}.\n\n{1}\n\nOK, <@{2}>, let's try another one!",
                            answer,
                            generateScoreText(requestDoc),
                            requestDoc.UserId
                            );
                    }
                }
                else
                {
                    string userId = SlackUtils.NormalizeId(target);

                    _scoreService.IncrementScore(requestDoc.ChannelId, userId);
                    _workflowService.OnTurnChanged(requestDoc.ChannelId, requestDoc.UserId, userId);

                    if (answer == null)
                    {
                        text = String.Format(
                            "<@{1}> is correct!\n\n{0}\n\nOK, <@{1}>, you're up!",
                            generateScoreText(requestDoc),
                            userId
                            );
                    }
                    else
                    {
                        text = String.Format(
                            "<@{2}> is correct with {0}!\n\n{1}\n\nOK, <@{2}>, you're up!",
                            answer,
                            generateScoreText(requestDoc),
                            userId
                            );
                    }
                }
            }
            catch (GameNotStartedException)
            {
                return(SlackResponseDoc.Failure(String.Format(GAME_NOT_STARTED_FORMAT, requestDoc.Command)));
            }
            catch (WorkflowException e)
            {
                return(SlackResponseDoc.Failure(e.Message));
            }
            catch (ScoreException)
            {
                SlackResponseDoc responseDoc = SlackResponseDoc.Failure("User " + target + " does not exist. Please choose a valid user.");
                responseDoc.Attachments = new List <SlackAttachment> {
                    new SlackAttachment("Usage: `" + requestDoc.Command + " correct @jsmith Blue skies`")
                };
                return(responseDoc);
            }

            SlackResponseDoc delayedResponseDoc = new SlackResponseDoc
            {
                ResponseType = SlackResponseType.IN_CHANNEL,
                Text         = text
            };

            _delayedSlackService.sendResponse(requestDoc.ResponseUrl, delayedResponseDoc);

            return(new SlackResponseDoc
            {
                ResponseType = SlackResponseType.EPHEMERAL,
                Text = "Score updated."
            });
        }