Update bot messages

This commit is contained in:
2025-07-05 15:35:07 +07:00
parent daef7ddcfc
commit b7f608c8ba
6 changed files with 204 additions and 11 deletions

View File

@@ -17,6 +17,7 @@ public class UserController : BaseController
{
private IConfiguration _config;
private readonly IJwtUtils _jwtUtils;
private readonly IWebhookService _webhookService;
/// <summary>
/// Initializes a new instance of the <see cref="UserController"/> class.
@@ -24,11 +25,13 @@ public class UserController : BaseController
/// <param name="config">Configuration settings.</param>
/// <param name="userService">Service for user-related operations.</param>
/// <param name="jwtUtils">Utility for JWT token operations.</param>
public UserController(IConfiguration config, IUserService userService, IJwtUtils jwtUtils)
/// <param name="webhookService">Service for webhook operations.</param>
public UserController(IConfiguration config, IUserService userService, IJwtUtils jwtUtils, IWebhookService webhookService)
: base(userService)
{
_config = config;
_jwtUtils = jwtUtils;
_webhookService = webhookService;
}
/// <summary>
@@ -98,7 +101,74 @@ public class UserController : BaseController
{
var user = await GetUser();
var updatedUser = await _userService.UpdateTelegramChannel(user, telegramChannel);
// Send welcome message to the newly configured telegram channel
if (!string.IsNullOrEmpty(telegramChannel))
{
try
{
var welcomeMessage = $"🎉 **Trading Bot - Welcome!**\n\n" +
$"┌─────────────────────────────┐\n" +
$"│ CHANNEL CONFIGURED ✅ │\n" +
$"└─────────────────────────────┘\n\n" +
$"🎯 **Agent:** {user.Name}\n" +
$"📡 **Channel ID:** {telegramChannel}\n" +
$"⏰ **Setup Time:** {DateTime.UtcNow:MMM dd, yyyy • HH:mm:ss} UTC\n\n" +
$"🔔 **Notification Types:**\n" +
$"• 📈 Position Opens & Closes\n" +
$"• 🤖 Bot configuration changes\n\n" +
$"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +
$"🚀 **Welcome aboard!** Your trading notifications are now live.";
await _webhookService.SendMessage(welcomeMessage, telegramChannel);
}
catch (Exception ex)
{
// Log the error but don't fail the update operation
Console.WriteLine($"Failed to send welcome message to telegram channel {telegramChannel}: {ex.Message}");
}
}
return Ok(updatedUser);
}
/// <summary>
/// Tests the Telegram channel configuration by sending a test message.
/// </summary>
/// <returns>A message indicating the test result.</returns>
[HttpPost("telegram-channel/test")]
public async Task<ActionResult<string>> TestTelegramChannel()
{
var user = await GetUser();
if (string.IsNullOrEmpty(user.TelegramChannel))
{
return BadRequest("No Telegram channel configured for this user. Please set a Telegram channel first.");
}
try
{
var testMessage = $"🚀 **Trading Bot - Channel Test**\n\n" +
$"┌─────────────────────────────┐\n" +
$"│ CONNECTION SUCCESSFUL ✅ │\n" +
$"└─────────────────────────────┘\n\n" +
$"🎯 **Agent:** {user.Name}\n" +
$"📡 **Channel ID:** {user.TelegramChannel}\n" +
$"⏰ **Test Time:** {DateTime.UtcNow:MMM dd, yyyy • HH:mm:ss} UTC\n\n" +
$"🔔 **You will receive notifications for:**\n" +
$"• 📈 Position Opens & Closes\n" +
$"• 🤖 Bot configuration changes\n\n" +
$"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +
$"🎉 **Ready to trade!** Your notifications are now active.";
await _webhookService.SendMessage(testMessage, user.TelegramChannel);
return Ok($"Test message sent successfully to Telegram channel {user.TelegramChannel}. Please check your Telegram to verify delivery.");
}
catch (Exception ex)
{
return StatusCode(500, $"Failed to send test message: {ex.Message}");
}
}
}

View File

@@ -188,6 +188,18 @@ namespace Managing.Application.ManageBot
{
await Task.Run(() =>
bot.Stop()); // Assuming Stop is an asynchronous process wrapped in Task.Run for synchronous methods
var stopMessage = $"🛑 **Bot Stopped**\n\n" +
$"┌─────────────────────────────┐\n" +
$"│ BOT STOPPED 🔴 │\n" +
$"└─────────────────────────────┘\n\n" +
$"🎯 **Agent:** {bot.User.AgentName}\n" +
$"🤖 **Bot Name:** {bot.Name}\n" +
$"⏰ **Stopped At:** {DateTime.UtcNow:MMM dd, yyyy • HH:mm:ss} UTC\n\n" +
$"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +
$"✅ **Bot has been safely stopped and is no longer active.**";
await _messengerService.SendTradeMessage(stopMessage, false, bot.User);
return bot.GetStatus();
}
}
@@ -205,6 +217,18 @@ namespace Managing.Application.ManageBot
{
await Task.Run(() =>
bot.Stop()); // Assuming Stop is an asynchronous process wrapped in Task.Run for synchronous methods
var deleteMessage = $"🗑️ **Bot Deleted**\n\n" +
$"┌─────────────────────────────┐\n" +
$"│ BOT DELETED ❌ │\n" +
$"└─────────────────────────────┘\n\n" +
$"🎯 **Agent:** {bot.User.AgentName}\n" +
$"🤖 **Bot Name:** {bot.Name}\n" +
$"⏰ **Deleted At:** {DateTime.UtcNow:MMM dd, yyyy • HH:mm:ss} UTC\n\n" +
$"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +
$"⚠️ **Bot has been permanently deleted and all data removed.**";
await _messengerService.SendTradeMessage(deleteMessage, false, bot.User);
}
await _botRepository.DeleteBotBackup(identifier);
@@ -220,18 +244,30 @@ namespace Managing.Application.ManageBot
return false;
}
public Task<string> RestartBot(string identifier)
public async Task<string> RestartBot(string identifier)
{
if (_botTasks.TryGetValue(identifier, out var botWrapper))
{
if (botWrapper.BotInstance is IBot bot)
{
bot.Restart();
return Task.FromResult(bot.GetStatus());
var restartMessage = $"🔄 **Bot Restarted**\n\n" +
$"┌─────────────────────────────┐\n" +
$"│ BOT RESTARTED 🟢 │\n" +
$"└─────────────────────────────┘\n\n" +
$"🎯 **Agent:** {bot.User.AgentName}\n" +
$"🤖 **Bot Name:** {bot.Name}\n" +
$"⏰ **Restarted At:** {DateTime.UtcNow:MMM dd, yyyy • HH:mm:ss} UTC\n\n" +
$"━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +
$"🚀 **Bot has been successfully restarted and is now active.**";
await _messengerService.SendTradeMessage(restartMessage, false, bot.User);
return bot.GetStatus();
}
}
return Task.FromResult(BotStatus.Down.ToString());
return BotStatus.Down.ToString();
}
public void ToggleIsForWatchingOnly(string identifier)

View File

@@ -68,6 +68,11 @@ public class MessengerService : IMessengerService
}
}
public async Task SendMessage(string message, string telegramChannel)
{
await _webhookService.SendMessage(message, telegramChannel);
}
private string BuildPositionMessage(Position position)
{
var direction = position.OriginDirection.ToString();

View File

@@ -77,7 +77,7 @@ public class WebhookService : IWebhookService
message = message,
timestamp = DateTime.UtcNow,
type = "general_message",
telegramChannel = telegramChannel
telegramChannel = FormatTelegramChannel(telegramChannel)
};
// Send the webhook notification
@@ -97,4 +97,23 @@ public class WebhookService : IWebhookService
_logger.LogError(ex, "Error sending webhook message");
}
}
private string FormatTelegramChannel(string? telegramChannel)
{
if (string.IsNullOrEmpty(telegramChannel))
{
return string.Empty;
}
if (telegramChannel.StartsWith("100"))
{
return telegramChannel.Substring(3);
}
else if (telegramChannel.StartsWith("-100"))
{
return telegramChannel.Substring(4);
}
return telegramChannel;
}
}

View File

@@ -2598,6 +2598,41 @@ export class UserClient extends AuthorizedApiBase {
}
return Promise.resolve<User>(null as any);
}
user_TestTelegramChannel(): Promise<string> {
let url_ = this.baseUrl + "/User/telegram-channel/test";
url_ = url_.replace(/[?&]$/, "");
let options_: RequestInit = {
method: "POST",
headers: {
"Accept": "application/json"
}
};
return this.transformOptions(options_).then(transformedOptions_ => {
return this.http.fetch(url_, transformedOptions_);
}).then((_response: Response) => {
return this.processUser_TestTelegramChannel(_response);
});
}
protected processUser_TestTelegramChannel(response: Response): Promise<string> {
const status = response.status;
let _headers: any = {}; if (response.headers && response.headers.forEach) { response.headers.forEach((v: any, k: any) => _headers[k] = v); };
if (status === 200) {
return response.text().then((_responseText) => {
let result200: any = null;
result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver) as string;
return result200;
});
} else if (status !== 200 && status !== 204) {
return response.text().then((_responseText) => {
return throwException("An unexpected server error occurred.", status, _responseText, _headers);
});
}
return Promise.resolve<string>(null as any);
}
}
export class WorkflowClient extends AuthorizedApiBase {

View File

@@ -88,6 +88,24 @@ function UserInfoSettings() {
}
}
const testTelegramChannel = async () => {
if (!user?.telegramChannel) {
const toast = new Toast('No telegram channel configured')
toast.update('error', 'Please configure a telegram channel first')
return
}
const toast = new Toast('Testing telegram channel...')
try {
const response = await api.user_TestTelegramChannel()
toast.update('success', 'Test message sent! Check your Telegram.')
} catch (error: any) {
console.error('Error testing telegram channel:', error)
const errorMessage = error.response?.data || error.message || 'Failed to send test message'
toast.update('error', errorMessage)
}
}
return (
<div className="container mx-auto p-4">
<div className="bg-base-200 rounded-lg p-6 shadow-lg">
@@ -136,12 +154,22 @@ function UserInfoSettings() {
<div>
<label className="font-semibold">Telegram Channel:</label>
<p>{user?.telegramChannel || 'Not set'}</p>
<div className="flex gap-2 mt-2">
<button
className="btn btn-primary mt-2"
className="btn btn-primary"
onClick={() => setShowTelegramModal(true)}
>
Update Telegram Channel
</button>
{user?.telegramChannel && (
<button
className="btn btn-secondary"
onClick={testTelegramChannel}
>
Test Channel
</button>
)}
</div>
</div>
</div>
</div>