From 1c8895483d1539814f8fbe49671daa2df1b33a06 Mon Sep 17 00:00:00 2001 From: ZenonEl <165126589+ZenonEl@users.noreply.github.com> Date: Mon, 30 Mar 2026 06:40:58 +0400 Subject: [PATCH] fix(settings): add settings state display and enable/disable toggle closes #34 - Show current action, delay, and enabled/disabled status in settings menus - Add Enable/Disable toggle buttons for default action (previously only Off existed) - Show confirmation with current state after every settings change - UPSERT queries now properly set IsActive=1 when configuring actions - Add GetDefaultActionSettings and SetDefaultActionIsActive to IDefaultAction interfaces - Add missing resource strings for both EN and RU locales --- Database/Interfaces/IDefaultAction.cs | 2 + Database/Repositories/SqLite/DefaultAction.cs | 52 +++++++-- Resources/texts.resx | 39 +++++++ Resources/texts.ru-RU.resx | 33 ++++++ .../IParameterizedCallBackQuery.cs | 54 ++++++++- .../ICallBackQuery/ISettingsCallbackQuery.cs | 39 ++++++- TelegramBot/Menu/Users.cs | 107 +++++++++++++++++- TelegramBot/Utils/Keyboard/Users.cs | 1 + 8 files changed, 304 insertions(+), 23 deletions(-) diff --git a/Database/Interfaces/IDefaultAction.cs b/Database/Interfaces/IDefaultAction.cs index 19cf9d0..c4c9015 100644 --- a/Database/Interfaces/IDefaultAction.cs +++ b/Database/Interfaces/IDefaultAction.cs @@ -25,6 +25,7 @@ public interface IDefaultActionSetter public bool SetAutoSendVideoActionToUser(int userId, string action, string type); + public bool SetDefaultActionIsActive(int userId, string type, bool isActive); } public interface IDefaultActionGetter @@ -33,4 +34,5 @@ public interface IDefaultActionGetter public int GetDefaultActionId(int userId, string type); public string GetDefaultActionByUserIDAndType(int userID, string type); + public (string Action, string ActionCondition, bool IsActive) GetDefaultActionSettings(int userId, string type); } \ No newline at end of file diff --git a/Database/Repositories/SqLite/DefaultAction.cs b/Database/Repositories/SqLite/DefaultAction.cs index b000f54..74cb4ae 100644 --- a/Database/Repositories/SqLite/DefaultAction.cs +++ b/Database/Repositories/SqLite/DefaultAction.cs @@ -58,9 +58,9 @@ public SqliteDefaultActionSetter(string connectionString) public bool SetAutoSendVideoConditionToUser(int userId, string actionCondition, string type) { const string query = @" - INSERT INTO DefaultUsersActions (UserId, Type, ActionCondition) - VALUES (@userId, @type, @actionCondition) - ON CONFLICT(UserId, Type) + INSERT INTO DefaultUsersActions (UserId, Type, ActionCondition, IsActive) + VALUES (@userId, @type, @actionCondition, 1) + ON CONFLICT(UserId, Type) DO UPDATE SET ActionCondition = @actionCondition"; using var connection = new SqliteConnection(_connectionString); @@ -70,14 +70,25 @@ ON CONFLICT(UserId, Type) public bool SetAutoSendVideoActionToUser(int userId, string action, string type) { const string query = @" - INSERT INTO DefaultUsersActions (UserId, Type, Action) - VALUES (@userId, @type, @action) - ON CONFLICT(UserId, Type) - DO UPDATE SET Action = @action"; + INSERT INTO DefaultUsersActions (UserId, Type, Action, IsActive) + VALUES (@userId, @type, @action, 1) + ON CONFLICT(UserId, Type) + DO UPDATE SET Action = @action, IsActive = 1"; using var connection = new SqliteConnection(_connectionString); return connection.Execute(query, new {userId, type, action}) > 0; } + + public bool SetDefaultActionIsActive(int userId, string type, bool isActive) + { + const string query = @" + UPDATE DefaultUsersActions + SET IsActive = @isActive + WHERE UserId = @userId AND Type = @type"; + + using var connection = new SqliteConnection(_connectionString); + return connection.Execute(query, new {userId, type, isActive}) > 0; + } } public class SqliteDefaultActionGetter : IDefaultActionGetter @@ -129,7 +140,7 @@ public string GetDefaultActionByUserIDAndType(int userID, string type) try { using var connection = new SqliteConnection(_connectionString); - + var result = connection.QueryFirstOrDefault<(string Action, string ActionCondition)>( @"SELECT Action, ActionCondition FROM DefaultUsersActions @@ -138,8 +149,8 @@ FROM DefaultUsersActions AND IsActive = 1", new { userID, type }); - return result != default - ? $"{result.Action};{result.ActionCondition}" + return result != default + ? $"{result.Action};{result.ActionCondition}" : UsersAction.NO_VALUE; } catch (Exception ex) @@ -148,4 +159,25 @@ FROM DefaultUsersActions return ""; } } + + public (string Action, string ActionCondition, bool IsActive) GetDefaultActionSettings(int userId, string type) + { + try + { + using var connection = new SqliteConnection(_connectionString); + + var result = connection.QueryFirstOrDefault<(string Action, string ActionCondition, bool IsActive)>( + @"SELECT Action, ActionCondition, IsActive + FROM DefaultUsersActions + WHERE UserId = @userId AND Type = @type", + new { userId, type }); + + return result; + } + catch (Exception ex) + { + Log.Error(ex, "An error occurred in the method {MethodName}", nameof(GetDefaultActionSettings)); + return (string.Empty, string.Empty, false); + } + } } \ No newline at end of file diff --git a/Resources/texts.resx b/Resources/texts.resx index b744dc5..60c6c5a 100644 --- a/Resources/texts.resx +++ b/Resources/texts.resx @@ -326,9 +326,42 @@ Are you sure you want to unmute them? If not, type /start Default action successfully changed. + + Default action has been disabled. + Default action not changed. + + Current settings: + + + Action + + + Delay + + + Status + + + not configured + + + enabled + + + disabled + + + sec. + + + Enable Auto-Send + + + Please specify the IDs of groups or users: + ⏳ Time is up, the default action will be performed... @@ -379,6 +412,12 @@ Are you sure you want to unmute them? If not, type /start Only Me + + Enable + + + Disable + Disable Auto-Send diff --git a/Resources/texts.ru-RU.resx b/Resources/texts.ru-RU.resx index e130a92..b2749b0 100644 --- a/Resources/texts.ru-RU.resx +++ b/Resources/texts.ru-RU.resx @@ -331,9 +331,42 @@ ID: {0} Действие по умолчанию успешно изменено. + + Действие по умолчанию отключено. + Действие по умолчанию не изменено. + + Текущие настройки: + + + Действие + + + Задержка + + + Статус + + + не настроено + + + включено + + + отключено + + + сек. + + + Включить авто-рассылку + + + Укажите ID групп или пользователей: + ⏳ Время вышло, будет выполнено действие по умолчанию... diff --git a/TelegramBot/Handlers/ICallBackQuery/IParameterizedCallBackQuery.cs b/TelegramBot/Handlers/ICallBackQuery/IParameterizedCallBackQuery.cs index 393b527..d21d4af 100644 --- a/TelegramBot/Handlers/ICallBackQuery/IParameterizedCallBackQuery.cs +++ b/TelegramBot/Handlers/ICallBackQuery/IParameterizedCallBackQuery.cs @@ -49,25 +49,31 @@ public class SetAutoSendTimeCommand : IBotCallbackQueryHandlers public string Name => "user_set_auto_send_video_time_to:"; private readonly IDefaultActionSetter _defaultActionSetter; + private readonly IDefaultActionGetter _defaultActionGetter; private readonly IUserGetter _userGetter; public SetAutoSendTimeCommand( IUserGetter userGetter, - IDefaultActionSetter defaultActionSetter) + IDefaultActionSetter defaultActionSetter, + IDefaultActionGetter defaultActionGetter) { _userGetter = userGetter; _defaultActionSetter = defaultActionSetter; + _defaultActionGetter = defaultActionGetter; } public async Task ExecuteAsync(Update update, ITelegramBotClient botClient, CancellationToken ct) { string callbackQueryData = update.CallbackQuery!.Data!.Split(':')[1]; var chatId = update.CallbackQuery!.Message!.Chat.Id; + int userId = _userGetter.GetUserIDbyTelegramID(chatId); bool result = Users.SetAutoSendVideoTimeToUser(chatId, callbackQueryData, _defaultActionSetter, _userGetter); - var message = result - ? Config.GetResourceString("AutoSendTimeChangedMessage") + callbackQueryData + string statusText = Users.FormatSettingsStatus(_defaultActionGetter, userId); + var message = result + ? Config.GetResourceString("AutoSendTimeChangedMessage") + callbackQueryData + " " + Config.GetResourceString("SettingsSecondsLabel") : Config.GetResourceString("AutoSendTimeNotChangedMessage"); + message += "\n\n" + statusText; await CommonUtilities.SendMessage( botClient, @@ -112,6 +118,45 @@ public async Task ExecuteAsync(Update update, ITelegramBotClient botClient, Canc { string action = update.CallbackQuery!.Data!.Split(':')[1]; long chatId = update.CallbackQuery!.Message!.Chat.Id; + int userId = _userGetter.GetUserIDbyTelegramID(chatId); + + // Handle "enable" action: re-enable existing settings without changing them + if (action == "enable") + { + bool enableResult = _defaultActionSetter.SetDefaultActionIsActive(userId, UsersActionTypes.DEFAULT_MEDIA_DISTRIBUTION, true); + string enableMessage = enableResult + ? Config.GetResourceString("DefaultActionChangedMessage") + : Config.GetResourceString("DefaultActionNotChangedMessage"); + + string statusText = Users.FormatSettingsStatus(_defaultActionGetter, userId); + await CommonUtilities.SendMessage( + botClient, + update, + KeyboardUtils.GetReturnButtonMarkup("user_set_video_send_users"), + cancellationToken, + enableMessage + "\n\n" + statusText + ); + return; + } + + // Handle "off" action: disable the default action + if (action == UsersAction.OFF) + { + bool disableResult = _defaultActionSetter.SetDefaultActionIsActive(userId, UsersActionTypes.DEFAULT_MEDIA_DISTRIBUTION, false); + string disableMessage = disableResult + ? Config.GetResourceString("DefaultActionDisabledMessage") + : Config.GetResourceString("DefaultActionNotChangedMessage"); + + string statusText = Users.FormatSettingsStatus(_defaultActionGetter, userId); + await CommonUtilities.SendMessage( + botClient, + update, + KeyboardUtils.GetReturnButtonMarkup("user_set_video_send_users"), + cancellationToken, + disableMessage + "\n\n" + statusText + ); + return; + } List extendActions = new List { @@ -148,12 +193,13 @@ await CommonUtilities.SendMessage( if (result) { + string confirmStatusText = Users.FormatSettingsStatus(_defaultActionGetter, userId); await CommonUtilities.SendMessage( botClient, update, KeyboardUtils.GetReturnButtonMarkup("user_set_video_send_users"), cancellationToken, - Config.GetResourceString("DefaultActionChangedMessage") + Config.GetResourceString("DefaultActionChangedMessage") + "\n\n" + confirmStatusText ); return; } diff --git a/TelegramBot/Handlers/ICallBackQuery/ISettingsCallbackQuery.cs b/TelegramBot/Handlers/ICallBackQuery/ISettingsCallbackQuery.cs index f6eb7a0..c4bd509 100644 --- a/TelegramBot/Handlers/ICallBackQuery/ISettingsCallbackQuery.cs +++ b/TelegramBot/Handlers/ICallBackQuery/ISettingsCallbackQuery.cs @@ -45,31 +45,64 @@ public async Task ExecuteAsync(Update update, ITelegramBotClient botClient, Canc public class VideoDefaultActionsMenuCommand : IBotCallbackQueryHandlers { + private readonly IDefaultActionGetter _defaultActionGetter; + private readonly IUserGetter _userGetter; + + public VideoDefaultActionsMenuCommand( + IDefaultActionGetter defaultActionGetter, + IUserGetter userGetter) + { + _defaultActionGetter = defaultActionGetter; + _userGetter = userGetter; + } + public string Name => "video_default_actions_menu"; public async Task ExecuteAsync(Update update, ITelegramBotClient botClient, CancellationToken ct) { - await Users.ViewVideoDefaultActionsMenu(botClient, update); + await Users.ViewVideoDefaultActionsMenu(botClient, update, _defaultActionGetter, _userGetter); } } public class UserSetAutoSendVideoTimeCommand : IBotCallbackQueryHandlers { + private readonly IDefaultActionGetter _defaultActionGetter; + private readonly IUserGetter _userGetter; + + public UserSetAutoSendVideoTimeCommand( + IDefaultActionGetter defaultActionGetter, + IUserGetter userGetter) + { + _defaultActionGetter = defaultActionGetter; + _userGetter = userGetter; + } + public string Name => "user_set_auto_send_video_time"; public async Task ExecuteAsync(Update update, ITelegramBotClient botClient, CancellationToken ct) { - await Users.ViewAutoSendVideoTimeMenu(botClient, update); + await Users.ViewAutoSendVideoTimeMenu(botClient, update, _defaultActionGetter, _userGetter); } } public class UserSetVideoSendUsersCommand : IBotCallbackQueryHandlers { + private readonly IDefaultActionGetter _defaultActionGetter; + private readonly IUserGetter _userGetter; + + public UserSetVideoSendUsersCommand( + IDefaultActionGetter defaultActionGetter, + IUserGetter userGetter) + { + _defaultActionGetter = defaultActionGetter; + _userGetter = userGetter; + } + public string Name => "user_set_video_send_users"; public async Task ExecuteAsync(Update update, ITelegramBotClient botClient, CancellationToken ct) { - await Users.ViewUsersVideoSentUsersActionsMenu(botClient, update); + await Users.ViewUsersVideoSentUsersActionsMenu(botClient, update, _defaultActionGetter, _userGetter); } } diff --git a/TelegramBot/Menu/Users.cs b/TelegramBot/Menu/Users.cs index 425d385..9f44893 100644 --- a/TelegramBot/Menu/Users.cs +++ b/TelegramBot/Menu/Users.cs @@ -10,6 +10,7 @@ // (по вашему выбору) любой более поздней версии. +using System.Text; using TelegramMediaRelayBot.Database; using TelegramMediaRelayBot.Database.Interfaces; using TelegramMediaRelayBot.TelegramBot.Utils; @@ -98,39 +99,133 @@ await CommonUtilities.SendMessage( ); } - public static async Task ViewVideoDefaultActionsMenu(ITelegramBotClient botClient, Update update) + public static async Task ViewVideoDefaultActionsMenu(ITelegramBotClient botClient, Update update, + IDefaultActionGetter? defaultActionGetter = null, IUserGetter? userGetter = null) { + string statusText = ""; + if (defaultActionGetter != null && userGetter != null) + { + long chatId = CommonUtilities.GetIDfromUpdate(update); + int userId = userGetter.GetUserIDbyTelegramID(chatId); + statusText = FormatSettingsStatus(defaultActionGetter, userId); + } + + string message = Config.GetResourceString("VideoDefaultActionsMenuText"); + if (!string.IsNullOrEmpty(statusText)) + message += "\n\n" + statusText; + await CommonUtilities.SendMessage( botClient, update, UsersDefaultActionsMenuKB.GetDefaultVideoDistributionKeyboardMarkup(), cancellationToken, - Config.GetResourceString("VideoDefaultActionsMenuText") + message ); } - public static async Task ViewUsersVideoSentUsersActionsMenu(ITelegramBotClient botClient, Update update) + public static async Task ViewUsersVideoSentUsersActionsMenu(ITelegramBotClient botClient, Update update, + IDefaultActionGetter? defaultActionGetter = null, IUserGetter? userGetter = null) { + string statusText = ""; + if (defaultActionGetter != null && userGetter != null) + { + long chatId = CommonUtilities.GetIDfromUpdate(update); + int userId = userGetter.GetUserIDbyTelegramID(chatId); + var settings = defaultActionGetter.GetDefaultActionSettings(userId, UsersActionTypes.DEFAULT_MEDIA_DISTRIBUTION); + if (!string.IsNullOrEmpty(settings.Action)) + { + string actionName = GetActionDisplayName(settings.Action); + string activeIndicator = settings.IsActive ? "✅" : "❌"; + statusText = $"{activeIndicator} {Config.GetResourceString("SettingsActionLabel")}: {actionName}"; + } + } + + string message = Config.GetResourceString("UsersVideoSentUsersMenuText"); + if (!string.IsNullOrEmpty(statusText)) + message += "\n\n" + statusText; + await CommonUtilities.SendMessage( botClient, update, UsersDefaultActionsMenuKB.GetUsersVideoSentUsersKeyboardMarkup(), cancellationToken, - Config.GetResourceString("UsersVideoSentUsersMenuText") + message ); } - public static async Task ViewAutoSendVideoTimeMenu(ITelegramBotClient botClient, Update update) + public static async Task ViewAutoSendVideoTimeMenu(ITelegramBotClient botClient, Update update, + IDefaultActionGetter? defaultActionGetter = null, IUserGetter? userGetter = null) { + string statusText = ""; + if (defaultActionGetter != null && userGetter != null) + { + long chatId = CommonUtilities.GetIDfromUpdate(update); + int userId = userGetter.GetUserIDbyTelegramID(chatId); + var settings = defaultActionGetter.GetDefaultActionSettings(userId, UsersActionTypes.DEFAULT_MEDIA_DISTRIBUTION); + if (!string.IsNullOrEmpty(settings.ActionCondition)) + { + string activeIndicator = settings.IsActive ? "✅" : "❌"; + statusText = $"{activeIndicator} {Config.GetResourceString("SettingsDelayLabel")}: {settings.ActionCondition} {Config.GetResourceString("SettingsSecondsLabel")}"; + } + } + + string message = Config.GetResourceString("AutoSendVideoTimeMenuText"); + if (!string.IsNullOrEmpty(statusText)) + message += "\n\n" + statusText; + await CommonUtilities.SendMessage( botClient, update, UsersDefaultActionsMenuKB.GetUsersAutoSendVideoTimeKeyboardMarkup(), cancellationToken, - Config.GetResourceString("AutoSendVideoTimeMenuText") + message ); } + public static string FormatSettingsStatus(IDefaultActionGetter defaultActionGetter, int userId) + { + var settings = defaultActionGetter.GetDefaultActionSettings(userId, UsersActionTypes.DEFAULT_MEDIA_DISTRIBUTION); + + if (string.IsNullOrEmpty(settings.Action) && string.IsNullOrEmpty(settings.ActionCondition)) + return $"📋 {Config.GetResourceString("SettingsCurrentStateText")} {Config.GetResourceString("SettingsNotConfigured")}"; + + var sb = new StringBuilder(); + sb.AppendLine($"📋 {Config.GetResourceString("SettingsCurrentStateText")}"); + + string statusIndicator = settings.IsActive ? "✅" : "❌"; + string statusText = settings.IsActive + ? Config.GetResourceString("SettingsEnabled") + : Config.GetResourceString("SettingsDisabled"); + sb.AppendLine($" {Config.GetResourceString("SettingsStatusLabel")}: {statusIndicator} {statusText}"); + + if (!string.IsNullOrEmpty(settings.Action)) + { + string actionName = GetActionDisplayName(settings.Action); + sb.AppendLine($" {Config.GetResourceString("SettingsActionLabel")}: {actionName}"); + } + + if (!string.IsNullOrEmpty(settings.ActionCondition)) + { + sb.AppendLine($" {Config.GetResourceString("SettingsDelayLabel")}: {settings.ActionCondition} {Config.GetResourceString("SettingsSecondsLabel")}"); + } + + return sb.ToString().TrimEnd(); + } + + private static string GetActionDisplayName(string action) + { + return action switch + { + UsersAction.SEND_MEDIA_TO_ALL_CONTACTS => Config.GetResourceString("AllContactsButtonText"), + UsersAction.SEND_MEDIA_TO_DEFAULT_GROUPS => Config.GetResourceString("DefaultGroupsButtonText"), + UsersAction.SEND_MEDIA_TO_SPECIFIED_USERS => Config.GetResourceString("SpecifiedContactsButtonText"), + UsersAction.SEND_MEDIA_TO_SPECIFIED_GROUPS => Config.GetResourceString("SpecifiedGroupsButtonText"), + UsersAction.SEND_MEDIA_ONLY_TO_ME => Config.GetResourceString("OnlyMeButtonText"), + UsersAction.OFF => Config.GetResourceString("DisableAutoSendButtonText"), + _ => action + }; + } + public static bool SetAutoSendVideoTimeToUser(long chatId, string time, IDefaultActionSetter defaultActionSetter, IUserGetter userGetter) { int userId = userGetter.GetUserIDbyTelegramID(chatId); diff --git a/TelegramBot/Utils/Keyboard/Users.cs b/TelegramBot/Utils/Keyboard/Users.cs index 9e8ec9d..967a273 100644 --- a/TelegramBot/Utils/Keyboard/Users.cs +++ b/TelegramBot/Utils/Keyboard/Users.cs @@ -271,6 +271,7 @@ public static InlineKeyboardMarkup GetUsersVideoSentUsersKeyboardMarkup() }, new[] { + InlineKeyboardButton.WithCallbackData(Config.GetResourceString("EnableAutoSendButtonText"), "user_set_video_send_users:enable"), InlineKeyboardButton.WithCallbackData(Config.GetResourceString("DisableAutoSendButtonText"), $"user_set_video_send_users:{UsersAction.OFF}"), }, new[]