private async Task <string> ProcessVoteAnswer(string roomId, string userId, string voice)
        {
            if (!TelegramFrontendExtensions.IsActiveVote(roomId))
            {
                return("Действие не актуально!");
            }

            var voteInfo = TelegramFrontendExtensions.GetVoteInfo(roomId);

            // check allowance
            if (!voteInfo.AllowedToPassVoteUsersIds.ContainsKey(userId))
            {
                return("Действие запрещено!");
            }
            if (!_gameSettings.DevelopmentMode && voteInfo.VoteAllowedPredicate != null &&
                !voteInfo.VoteAllowedPredicate.Invoke((userId, voice)))
            {
                return("Голос отклонен");
            }

            voteInfo.AddOrUpdateVote(userId, voice);
            await UpdateVote(roomId, voteInfo);

            return("Голос принят");
        }
        private void ProcessMessageDefault(Message message)
        {
            var chatId     = message.Chat.Id.ToString();
            var isPersonal = message.Chat.Type == ChatType.Private;

            // mb last words?
            if (isPersonal && TelegramFrontendExtensions.IsLastWordsActual(chatId))
            {
                TelegramFrontendExtensions.SaveLastWords(chatId, message.Text);
            }
        }
        private async Task BotOnCallbackQueryReceived(CallbackQuery callBackQuery)
        {
            var data = callBackQuery.Data;

            Log.Debug("User {0} doing action {1}", callBackQuery.From.Id, data);
            if (string.IsNullOrWhiteSpace(data))
            {
                return;
            }

            var requestArgs = data.Split("-");
            var actionName  = requestArgs[0];

            if (string.IsNullOrWhiteSpace(actionName))
            {
                return;
            }

            if (actionName == "vote")
            {
                if (requestArgs.Length < 2)
                {
                    return;
                }
                callBackQuery.Message.EnsurePublicChat();
                var roomId = callBackQuery.Message.Chat.Id.ToString();
                var userId = callBackQuery.From.Id.ToString();
                var voice  = requestArgs[1];
                var answer = await ProcessVoteAnswer(roomId, userId, voice);

                await _bot.LockAndDo(() => _bot.AnswerCallbackQueryAsync(
                                         callBackQuery.Id,
                                         answer
                                         ));

                return;
            }

            // parsing args
            if (requestArgs.Length < 2)
            {
                return;
            }
            if (!int.TryParse(requestArgs[1], out var actionFromId))
            {
                return;
            }
            var parsedActionToId = 0;

            if (requestArgs.Length > 2 && !int.TryParse(requestArgs[2], out parsedActionToId))
            {
                return;
            }
            var actionToId = parsedActionToId > 0 ? parsedActionToId : (int?)null;

            var actionDoneText = "Действие выбрано!";

            try
            {
                TelegramFrontendExtensions.SaveAction(actionFromId, (actionName, actionToId.Value));
            }
            catch (Exception ex)
            {
                Log.Error(ex, "Error occured when user tried to give a voice");
                actionDoneText = $"Не удалось выбрать действие. {ex.Message}";
            }

            var message = callBackQuery.Message;
            await _bot.LockAndDo(async() =>
            {
                await _bot.AnswerCallbackQueryAsync(
                    callBackQuery.Id,
                    actionDoneText
                    );
                await Task.Delay(100);
                await _bot.EditMessageTextAsync(message.Chat.Id, message.MessageId, actionDoneText);
            });
        }