using System.Collections.Concurrent; using Managing.Application.Abstractions; using Managing.Application.Abstractions.Services; using Managing.Application.Bots; using Managing.Common; using Managing.Core; using Managing.Domain.Bots; using Managing.Domain.MoneyManagements; using Managing.Domain.Workflows; using Microsoft.Extensions.Logging; using Newtonsoft.Json; namespace Managing.Application.ManageBot { public class BotService : IBotService { private readonly IBotRepository _botRepository; private readonly IExchangeService _exchangeService; private readonly IMessengerService _messengerService; private readonly IAccountService _accountService; private readonly ILogger _tradingBotLogger; private readonly ITradingService _tradingService; private ConcurrentDictionary _botTasks = new ConcurrentDictionary(); public BotService(IBotRepository botRepository, IExchangeService exchangeService, IMessengerService messengerService, IAccountService accountService, ILogger tradingBotLogger, ITradingService tradingService) { _botRepository = botRepository; _exchangeService = exchangeService; _messengerService = messengerService; _accountService = accountService; _tradingBotLogger = tradingBotLogger; _tradingService = tradingService; } public async void SaveBotBackup(BotBackup botBackup) { await _botRepository.InsertBotAsync(botBackup); } public BotBackup GetBotBackup(string name) { return _botRepository.GetBots().FirstOrDefault(b => b.Name == name); } public void SaveBotBackup(string name, Enums.BotType botType, string data) { var backup = GetBotBackup(name); if (backup != null) { backup.Data = data; _botRepository.UpdateBackupBot(backup); return; } var botBackup = new BotBackup { Name = name, BotType = botType, Data = data }; _botRepository.InsertBotAsync(botBackup); } public class BotTaskWrapper { public Task Task { get; private set; } public Type BotType { get; private set; } public object BotInstance { get; private set; } // Add this line public BotTaskWrapper(Task task, Type botType, object botInstance) // Update constructor { Task = task; BotType = botType; BotInstance = botInstance; // Set the bot instance } } public void AddSimpleBotToCache(IBot bot) { var botTask = new BotTaskWrapper(Task.Run(() => bot.Start()), bot.GetType(), bot); // Pass bot as the instance _botTasks.AddOrUpdate(bot.GetName(), botTask, (key, existingVal) => botTask); } public void AddTradingBotToCache(ITradingBot bot) { var botTask = new BotTaskWrapper(Task.Run(() => bot.Start()), bot.GetType(), bot); _botTasks.AddOrUpdate(bot.GetName(), botTask, (key, existingVal) => botTask); } public List GetActiveBots() { return _botTasks.Values .Where(wrapper => typeof(ITradingBot).IsAssignableFrom(wrapper.BotType)) .Select(wrapper => wrapper.BotInstance as ITradingBot) .Where(bot => bot != null) .ToList(); } public IEnumerable GetSavedBots() { return _botRepository.GetBots(); } public void StartBotFromBackup(BotBackup backupBot) { object bot = null; Task botTask = null; switch (backupBot.BotType) { case Enums.BotType.SimpleBot: bot = CreateSimpleBot(backupBot.Name, null); // Assuming null is an acceptable parameter for workflow botTask = Task.Run(() => ((IBot)bot).Start()); break; case Enums.BotType.ScalpingBot: var scalpingBotData = JsonConvert.DeserializeObject(backupBot.Data); bot = CreateScalpingBot( scalpingBotData.AccountName, scalpingBotData.MoneyManagement, backupBot.Name, scalpingBotData.Ticker, scalpingBotData.Scenario, scalpingBotData.Timeframe, scalpingBotData.IsForWatchingOnly); botTask = Task.Run(() => ((ITradingBot)bot).Start()); break; case Enums.BotType.FlippingBot: var flippingBotData = JsonConvert.DeserializeObject(backupBot.Data); bot = CreateFlippingBot( flippingBotData.AccountName, flippingBotData.MoneyManagement, backupBot.Name, flippingBotData.Ticker, flippingBotData.Scenario, flippingBotData.Timeframe, flippingBotData.IsForWatchingOnly); botTask = Task.Run(() => ((ITradingBot)bot).Start()); break; } if (bot != null && botTask != null) { var botWrapper = new BotTaskWrapper(botTask, bot.GetType(), bot); _botTasks.AddOrUpdate(backupBot.Name, botWrapper, (key, existingVal) => botWrapper); } } public IBot CreateSimpleBot(string botName, Workflow workflow) { return new SimpleBot(botName, _tradingBotLogger, workflow, this); } public ITradingBot CreateScalpingBot(string accountName, MoneyManagement moneyManagement, string name, Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly) { return new ScalpingBot( accountName, moneyManagement, name, scenario, _exchangeService, ticker, _tradingService, _tradingBotLogger, interval, _accountService, _messengerService, this, isForWatchingOnly: isForWatchingOnly); } public ITradingBot CreateBacktestScalpingBot(string accountName, MoneyManagement moneyManagement, Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly) { return new ScalpingBot( accountName, moneyManagement, "BacktestBot", scenario, _exchangeService, ticker, _tradingService, _tradingBotLogger, interval, _accountService, _messengerService, this, true, isForWatchingOnly); } public ITradingBot CreateFlippingBot(string accountName, MoneyManagement moneyManagement, string name, Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly) { return new FlippingBot( accountName, moneyManagement, name, scenario, _exchangeService, ticker, _tradingService, _tradingBotLogger, interval, _accountService, _messengerService, this, isForWatchingOnly: isForWatchingOnly); } public ITradingBot CreateBacktestFlippingBot(string accountName, MoneyManagement moneyManagement, Enums.Ticker ticker, string scenario, Enums.Timeframe interval, bool isForWatchingOnly) { return new FlippingBot( accountName, moneyManagement, "BacktestBot", scenario, _exchangeService, ticker, _tradingService, _tradingBotLogger, interval, _accountService, _messengerService, this, true, isForWatchingOnly); } } }