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, "Окончание обновления статистики ботов"); }
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")); }