public IActionResult GetBotForSalesStatistics(int botId)
        {
            _logger.Log(LogLevel.INFO, Source.WEBSITE, "Сайт. Опрос стастистики бота через " +
                        "ajax (на клиенте не доступен webSocket или кто-то балуется).");
            try
            {
                bool botWorks = _contextDb.RouteRecords.Find(botId) != null? true:false;
                BotForSalesStatistics stat = _contextDb.BotForSalesStatistics.Find(botId);
                JObject jObj = new JObject
                {
                    { "botWorks", botWorks },
                    { "ordersCount", stat.NumberOfOrders },
                    { "usersCount", stat.NumberOfUniqueUsers },
                    { "messagesCount", stat.NumberOfUniqueMessages },
                };
                return(Json(jObj));
            }catch (Exception ee)
            {
                _logger.Log(LogLevel.ERROR, Source.WEBSITE, "Сайт. Опрос стастистики бота через " +
                            "ajax (на клиенте не доступен webSocket или кто-то балуется). Не " +
                            "удаётся отправить статистику бота. Ошибка " + ee.Message);

                return(StatusCode(500));
            }
        }
        private async Task SendRelevantStatistics()
        {
            //выбрать всю статистику для ботов

            List <BotForSalesStatistics> allStat = _contextDb.BotForSalesStatistics.ToList();
            List <RouteRecord>           rrs     = _contextDb.RouteRecords.ToList();
            List <int> workingBotIds             = new List <int>();

            foreach (var routeRecord in rrs)
            {
                workingBotIds.Add(routeRecord.BotId);
            }


            try
            {
                //Перебор статистики по всем ботам
                for (int i = 0; i < allStat.Count; i++)
                {
                    int botId = allStat[i].BotId;

                    //Если есть подписанные на этого бота
                    if (_dict_botId_Websockets.ContainsKey(botId))
                    {
                        BotForSalesStatistics_Websockets bfs_websockets = _dict_botId_Websockets[botId];

                        //Какое-то значение поменялось
                        if (bfs_websockets.BotForSalesStatisticsOld.NumberOfOrders != allStat[i].NumberOfOrders ||
                            bfs_websockets.BotForSalesStatisticsOld.NumberOfUniqueUsers != allStat[i].NumberOfUniqueUsers ||
                            bfs_websockets.BotForSalesStatisticsOld.NumberOfUniqueMessages != allStat[i].NumberOfUniqueMessages ||
                            bfs_websockets.IsWorking != workingBotIds.Contains(botId))
                        {
                            for (int j = 0; j < bfs_websockets.WebSockets.Count; j++)
                            {
                                //Отправка нового значения

                                WebSocket             webSocket = bfs_websockets.WebSockets[j];
                                BotForSalesStatistics stat      = allStat[i];

                                JObject JObj = new JObject
                                {
                                    { "botWorks", workingBotIds.Contains(botId) },
                                    { "ordersCount", stat.NumberOfOrders },
                                    { "usersCount", stat.NumberOfUniqueUsers },
                                    { "messagesCount", stat.NumberOfUniqueMessages },
                                };

                                string jsonString   = JsonConvert.SerializeObject(JObj);
                                var    bytes        = Encoding.UTF8.GetBytes(jsonString);
                                var    arraySegment = new ArraySegment <byte>(bytes);

                                await webSocket.SendAsync(arraySegment, WebSocketMessageType.Text, true, CancellationToken.None);
                            }

                            //Обновление значений до текущих
                            bfs_websockets.BotForSalesStatisticsOld.NumberOfOrders         = allStat[i].NumberOfOrders;
                            bfs_websockets.BotForSalesStatisticsOld.NumberOfUniqueUsers    = allStat[i].NumberOfUniqueUsers;
                            bfs_websockets.BotForSalesStatisticsOld.NumberOfUniqueMessages = allStat[i].NumberOfUniqueMessages;
                            bfs_websockets.IsWorking = workingBotIds.Contains(botId);
                        }

                        bfs_websockets.BotForSalesStatisticsOld = allStat[i];
                    }
                }
            }
            catch (Exception ee)
            {
                _logger.Log(LogLevel.ERROR, Source.WEBSITE, "Сайт. При отправке статистики бота по websocket произошла ошибка. " + ee.Message);
            }
        }
        private void SyncBotData()
        {
            _logger.Log(LogLevel.INFO,
                        Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                        "Старт обновления статистики ботов");


            ApplicationContext context = _dbContextWrapper.CreateDbContext();


            List <BotForSalesStatistics> allStatistics = context
                                                         .BotForSalesStatistics
                                                         .ToList();


            List <Record_BotUsername_UserTelegramId> allBotsUsers = context
                                                                    .BotUsers
                                                                    .ToList();


            //Для всех ботов в этом лесу актуальные данные кол-ва сообщений
            //и данные о пользователях переносит в БД
            foreach (var(botUsername, botWrapper) in BotsStorage.BotsDictionary)
            {
                if (botWrapper == null)
                {
                    _logger.Log(
                        LogLevel.WARNING,
                        Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                        $"При обновлении статистики не удалось получить доступ к " +
                        $"боту botUsername={botUsername} в статическом контейнере");
                    continue;
                }

                if (!(botWrapper is IWithStatistics withStatistics))
                {
                    _logger.Log(LogLevel.IMPORTANT_INFO, Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                                $"При обновлении статистики обнаружен бот botUsername={botUsername} без статистики");
                    continue;
                }

                #region Обновление кол-ва сообщений в бд
                //запись статистики бота из бд
                BotForSalesStatistics statisticsDb = allStatistics
                                                     .SingleOrDefault(_stat => _stat.BotId == botWrapper.BotId);


                if (statisticsDb == null)
                {
                    _logger.Log(LogLevel.ERROR,
                                Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                                $"В бд нет статистики для бота, который запущен в лесу." +
                                $"botUsername={botUsername}, botWrapper.BotID{botWrapper.BotId}");
                    continue;
                }

                //кол-во сообщений из памяти
                long actualNumberOfMessages = withStatistics.StatisticsContainer.NumberOfMessages;

                if (actualNumberOfMessages < statisticsDb.NumberOfUniqueMessages)
                {
                    _logger.Log(LogLevel.ERROR,
                                Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                                $"Обновление статистики бота в бд. Количество сообщений у бота в памяти " +
                                $"меньше старого значения кол-ва сообщений у бота в БД." +
                                $"actualNumberOfMessages{actualNumberOfMessages}, " +
                                $"statisticsDb.NumberOfUniqueMessages = {statisticsDb.NumberOfUniqueMessages}");

                    //Это может произойти, если при старте бота из бд не была извлечена статистика бота,
                    //которая накопилась за прошлые запуски

                    //Заношу в память данные из бд, чтобы такой ошибки больше не было
                    withStatistics.StatisticsContainer.NumberOfMessages = statisticsDb.NumberOfUniqueMessages;
                }
                else
                {
                    //Обновление кол-ва сообщений
                    statisticsDb.NumberOfUniqueMessages = actualNumberOfMessages;
                }

                #endregion


                #region Обновление списка пользователей в бд
                var dbBotUsers = allBotsUsers
                                 .Where(_record => _record.BotUsername == botUsername)
                                 .Select(_record => _record.BotUserTelegramId)
                                 .ToHashSet();

                List <int> newUsersTelegramIds = null;

                //Упадёт, если в памяти не будет хотя бы одного Id из БД
                try
                {
                    newUsersTelegramIds = withStatistics
                                          .StatisticsContainer
                                          .GetNewUsersTelegramIds(dbBotUsers);
                }
                catch (Exception ee)
                {
                    _logger.Log(LogLevel.ERROR,
                                Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                                "При обновлении списка пользователей произошла ошибка", ex: ee);
                }

                if (newUsersTelegramIds == null)
                {
                    //Не удалось нормально извлечь новых пользователей
                    //Обновить память для соответствия в бд и попробовать снова
                    bool success = withStatistics.StatisticsContainer.TryExpandTheListOfUsers(dbBotUsers);
                    if (!success)
                    {
                        try
                        {
                            newUsersTelegramIds = withStatistics
                                                  .StatisticsContainer
                                                  .GetNewUsersTelegramIds(dbBotUsers);
                        }catch (Exception eee)
                        {
                            _logger.Log(LogLevel.ERROR,
                                        Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                                        "При повторной попытке синхронизировать кол-во пользователей было брошено исключение",
                                        ex: eee);
                            continue;
                        }
                    }
                    else
                    {
                        _logger.Log(LogLevel.ERROR,
                                    Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                                    "Попытка добавить недостающих пользователей не увенчалась успехом.");
                        continue;
                    }
                }



                int actualNumberOfUsers = withStatistics.StatisticsContainer.GetNumberOfAllUsers();

                if (dbBotUsers.Count > actualNumberOfUsers)
                {
                    _logger.Log(LogLevel.WARNING,
                                Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                                $"Обновление статистики бота. У бота " +
                                $"botUsername {botUsername} botWrapper.BotID={botWrapper.BotId}" +
                                $"старое количество пользователей в БД больше актуального кол-ва " +
                                $"пользователей");
                }

                //Обновление кол-ва пользователей
                var botStat = context.BotForSalesStatistics
                              .Find(botWrapper.BotId);

                botStat.NumberOfUniqueUsers = actualNumberOfUsers;

                //Обновление списка пользователей бота
                List <Record_BotUsername_UserTelegramId> newUsersRecords =
                    new List <Record_BotUsername_UserTelegramId>();

                for (int i = 0; i < newUsersTelegramIds.Count; i++)
                {
                    int newUserTelegramId = newUsersTelegramIds[i];
                    newUsersRecords.Add(new Record_BotUsername_UserTelegramId()
                    {
                        BotUsername       = botUsername,
                        BotUserTelegramId = newUserTelegramId
                    });
                }

                context.BotUsers.AddRange(newUsersRecords);

                _logger.Log(LogLevel.INFO,
                            Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                            $"При обновлении статистики к списку пользователей добавлено " +
                            $"list.Count={newUsersRecords.Count} новых пользователей");

                #endregion
            }


            context.SaveChanges();



            _logger.Log(LogLevel.INFO,
                        Source.FOREST_BOT_STATISTICS_SYNCHRONIZER,
                        "Окончание обновления статистики ботов");
        }
Example #4
0
        public IActionResult CreateNewBotForSales(TokenChange tokenModel, BotType botType)
        {
            int accountId = (int)HttpContext.Items["accountId"];

            try
            {
                string token         = tokenModel?.Token;
                string botUsername   = new TelegramBotClient(token).GetMeAsync().Result.Username;
                string jsonBotMarkup = localizer[botType.ToString()];

                int statusGroupId = contextDb.OrderStatusGroups.First(stat => stat.OwnerId == accountId).Id;



                //нужно установить групппу статусов
                if (jsonBotMarkup.Contains("1000001"))
                {
                    jsonBotMarkup = jsonBotMarkup.Replace("1000001", statusGroupId.ToString());
                }


                BotDB bot = new BotDB
                {
                    OwnerId = accountId,
                    BotType = "BotForSales",
                    Token   = token,
                    BotName = botUsername,
                    Markup  = jsonBotMarkup
                };

                contextDb.Bots.Add(bot);

                //Создание статистики для бота
                BotForSalesStatistics botForSalesStatistics = new BotForSalesStatistics
                {
                    Bot = bot, NumberOfOrders = 0, NumberOfUniqueMessages = 0, NumberOfUniqueUsers = 0
                };

                contextDb.BotForSalesStatistics.Add(botForSalesStatistics);

                try
                {
                    contextDb.SaveChanges();
                }
                catch (Exception exception)
                {
                    throw new TokenMatchException("Возможно в базе уже есть этот бот", exception);
                }

                return(RedirectToAction("SalesTreeEditor", "BotForSalesEditing", new { botId = bot.Id }));
            }
            catch (TokenMatchException ex)
            {
                logger.Log(LogLevel.USER_ERROR, Source.WEBSITE, $"Сайт. Создание нового бота. При " +
                           $"запросе botUsername было выброшено исключение (возможно, введённый" +
                           $"токен был специально испорчен)" + ex.Message, accountId: accountId);

                ModelState.AddModelError("", "Этот бот уже зарегистрирован.");
            }
            catch (Exception ee)
            {
                logger.Log(LogLevel.USER_ERROR, Source.WEBSITE, $"Сайт. Создание нового бота. При " +
                           $"запросе botUsername было выброшено исключение (возможно, введённый" +
                           $"токен был специально испорчен)" + ee.Message, accountId: accountId);

                ModelState.AddModelError("", "Ошибка обработки токена.");
            }


            return(View("BotForSalesTokenEntry"));
        }