Add webhook
This commit is contained in:
@@ -1163,7 +1163,7 @@ public class TradingBot : Bot, ITradingBot
|
||||
{
|
||||
if (!Config.IsForBacktest)
|
||||
{
|
||||
await MessengerService.SendTradeMessage(message, isBadBehavior);
|
||||
await MessengerService.SendTradeMessage(message, isBadBehavior, Account?.User);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1322,13 +1322,14 @@ public class TradingBot : Bot, ITradingBot
|
||||
var protectedIsForBacktest = Config.IsForBacktest;
|
||||
var protectedName = Config.Name;
|
||||
|
||||
// Log the configuration update
|
||||
await LogInformation($"Updating bot configuration. Previous config: " +
|
||||
$"Balance: {Config.BotTradingBalance}, " +
|
||||
$"MaxTime: {Config.MaxPositionTimeHours?.ToString() ?? "Disabled"}, " +
|
||||
$"FlipOnlyProfit: {Config.FlipOnlyWhenInProfit}, " +
|
||||
$"Cooldown: {Config.CooldownPeriod}, " +
|
||||
$"MaxLoss: {Config.MaxLossStreak}");
|
||||
// Log the configuration update (before changing anything)
|
||||
await LogInformation("⚙️ **Configuration Update**\n" +
|
||||
"📊 **Previous Settings:**\n" +
|
||||
$"💰 Balance: ${Config.BotTradingBalance:F2}\n" +
|
||||
$"⏱️ Max Time: {(Config.MaxPositionTimeHours?.ToString() + "h" ?? "Disabled")}\n" +
|
||||
$"📈 Flip Only in Profit: {(Config.FlipOnlyWhenInProfit ? "✅" : "❌")}\n" +
|
||||
$"⏳ Cooldown: {Config.CooldownPeriod} candles\n" +
|
||||
$"📉 Max Loss Streak: {Config.MaxLossStreak}");
|
||||
|
||||
// Update the configuration
|
||||
Config = newConfig;
|
||||
@@ -1351,12 +1352,13 @@ public class TradingBot : Bot, ITradingBot
|
||||
LoadScenario(Config.ScenarioName);
|
||||
}
|
||||
|
||||
await LogInformation($"Bot configuration updated successfully. New config: " +
|
||||
$"Balance: {Config.BotTradingBalance}, " +
|
||||
$"MaxTime: {Config.MaxPositionTimeHours?.ToString() ?? "Disabled"}, " +
|
||||
$"FlipOnlyProfit: {Config.FlipOnlyWhenInProfit}, " +
|
||||
$"Cooldown: {Config.CooldownPeriod}, " +
|
||||
$"MaxLoss: {Config.MaxLossStreak}");
|
||||
await LogInformation("✅ **Configuration Applied**\n" +
|
||||
"🔧 **New Settings:**\n" +
|
||||
$"💰 Balance: ${Config.BotTradingBalance:F2}\n" +
|
||||
$"⏱️ Max Time: {(Config.MaxPositionTimeHours?.ToString() + "h" ?? "Disabled")}\n" +
|
||||
$"📈 Flip Only in Profit: {(Config.FlipOnlyWhenInProfit ? "✅" : "❌")}\n" +
|
||||
$"⏳ Cooldown: {Config.CooldownPeriod} candles\n" +
|
||||
$"📉 Max Loss Streak: {Config.MaxLossStreak}");
|
||||
|
||||
// Save the updated configuration as backup
|
||||
if (!Config.IsForBacktest)
|
||||
|
||||
@@ -2,16 +2,21 @@
|
||||
using Managing.Common;
|
||||
using Managing.Domain.Statistics;
|
||||
using Managing.Domain.Trades;
|
||||
using Managing.Domain.Users;
|
||||
|
||||
namespace Managing.Application.Shared;
|
||||
|
||||
public class MessengerService : IMessengerService
|
||||
{
|
||||
private readonly IDiscordService _discordService;
|
||||
private readonly IWebhookService _webhookService;
|
||||
private readonly IUserService _userService;
|
||||
|
||||
public MessengerService(IDiscordService discordService)
|
||||
public MessengerService(IDiscordService discordService, IWebhookService webhookService, IUserService userService)
|
||||
{
|
||||
_discordService = discordService;
|
||||
_webhookService = webhookService;
|
||||
_userService = userService;
|
||||
}
|
||||
|
||||
public async Task SendClosedPosition(string address, Trade oldTrade)
|
||||
@@ -50,9 +55,24 @@ public class MessengerService : IMessengerService
|
||||
await _discordService.SendSignal(message, exchange, ticker, direction, timeframe);
|
||||
}
|
||||
|
||||
public async Task SendTradeMessage(string message, bool isBadBehavior = false)
|
||||
public async Task SendTradeMessage(string message, bool isBadBehavior = false, User user = null)
|
||||
{
|
||||
await _discordService.SendTradeMessage(message, isBadBehavior);
|
||||
// Always send to Discord
|
||||
try
|
||||
{
|
||||
await _discordService.SendTradeMessage(message, isBadBehavior);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
|
||||
// If user is provided, also send to webhook
|
||||
if (user != null)
|
||||
{
|
||||
user = _userService.GetUser(user.Name);
|
||||
await _webhookService.SendTradeNotification(user, message, isBadBehavior);
|
||||
}
|
||||
}
|
||||
|
||||
public async Task SendBestTraders(List<Trader> traders)
|
||||
|
||||
62
src/Managing.Application/Shared/WebhookService.cs
Normal file
62
src/Managing.Application/Shared/WebhookService.cs
Normal file
@@ -0,0 +1,62 @@
|
||||
using System.Net.Http.Json;
|
||||
using Managing.Application.Abstractions.Services;
|
||||
using Managing.Domain.Users;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace Managing.Application.Shared;
|
||||
|
||||
public class WebhookService : IWebhookService
|
||||
{
|
||||
private readonly HttpClient _httpClient;
|
||||
private readonly IConfiguration _configuration;
|
||||
private readonly ILogger<WebhookService> _logger;
|
||||
|
||||
public WebhookService(HttpClient httpClient, IConfiguration configuration, ILogger<WebhookService> logger)
|
||||
{
|
||||
_httpClient = httpClient;
|
||||
_configuration = configuration;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public async Task SendTradeNotification(User user, string message, bool isBadBehavior = false)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Get the n8n webhook URL from configuration
|
||||
var webhookUrl = _configuration["N8n:WebhookUrl"];
|
||||
if (string.IsNullOrEmpty(webhookUrl))
|
||||
{
|
||||
_logger.LogWarning("N8n webhook URL not configured, skipping webhook notification");
|
||||
return;
|
||||
}
|
||||
|
||||
// Prepare the payload for n8n webhook
|
||||
var payload = new
|
||||
{
|
||||
message = message,
|
||||
isBadBehavior = isBadBehavior,
|
||||
timestamp = DateTime.UtcNow,
|
||||
type = "trade_notification",
|
||||
telegramChannel = user.TelegramChannel
|
||||
};
|
||||
|
||||
// Send the webhook notification
|
||||
var response = await _httpClient.PostAsJsonAsync(webhookUrl, payload);
|
||||
|
||||
if (response.IsSuccessStatusCode)
|
||||
{
|
||||
_logger.LogInformation($"Successfully sent webhook notification for user {user.Name}");
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.LogWarning($"Failed to send webhook notification. Status: {response.StatusCode}");
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.LogError(ex, $"Error sending webhook notification for user {user.Name}: {ex.Message}");
|
||||
// Don't throw - webhook failures shouldn't break the main flow
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -165,4 +165,21 @@ public class UserService : IUserService
|
||||
await _userRepository.UpdateUser(user);
|
||||
return user;
|
||||
}
|
||||
|
||||
public async Task<User> UpdateTelegramChannel(User user, string telegramChannel)
|
||||
{
|
||||
// Validate Telegram channel format (must start with @ and contain only allowed characters)
|
||||
if (!string.IsNullOrEmpty(telegramChannel))
|
||||
{
|
||||
string pattern = @"^@[a-zA-Z0-9_]{5,32}$";
|
||||
if (!Regex.IsMatch(telegramChannel, pattern))
|
||||
{
|
||||
throw new Exception("Invalid Telegram channel format. Must start with @ and be 5-32 characters long, containing only letters, numbers, and underscores.");
|
||||
}
|
||||
}
|
||||
|
||||
user.TelegramChannel = telegramChannel;
|
||||
await _userRepository.UpdateUser(user);
|
||||
return user;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user