diff --git a/SimpleTGBot/DialogData.cs b/SimpleTGBot/DialogData.cs index 9362e68..bb5adb0 100644 --- a/SimpleTGBot/DialogData.cs +++ b/SimpleTGBot/DialogData.cs @@ -6,6 +6,7 @@ internal class DialogData public string? inputPictureFilename; public string? inputTitle; public UserPreset[]? shownPresets; + public UserPreset incompletePreset; } enum DialogState @@ -18,4 +19,8 @@ enum DialogState Settings, ViewingPresets, ChoosingPreset, + CreatingPreset_AwaitingName, + CreatingPreset_AwaitingOutlineColor, + CreatingPreset_AwaitingTitleColor, + CreatingPreset_AwaitingSubtitleColor, } diff --git a/SimpleTGBot/Interactions.cs b/SimpleTGBot/Interactions.cs index 470a9d9..6ca21fb 100644 --- a/SimpleTGBot/Interactions.cs +++ b/SimpleTGBot/Interactions.cs @@ -1,4 +1,5 @@ -using System.Text; +using System.Drawing; +using System.Text; using Telegram.Bot.Types.ReplyMarkups; namespace SimpleTGBot; @@ -17,6 +18,12 @@ internal static class Interactions public const string settingsMessage = "Здесь можно:\n- настроить сохранённые стили"; public const string choosePresetMessage = "Какой пресет сделать активым (цыфра)?"; public const string enterPresetNumberMessage = "Введи номер пресета."; + public const string enterPresetNameMessage = "Назови свой новый пресет."; + public const string enterPresetOutlineColorMessage_head = "Выбери цвет обводки:\n0) оставить без изменений\n"; + public const string enterPresetTitleColorMessage_head = "Выбери цвет заголовка:\n0) оставить без изменений\n"; + public const string enterPresetSubtitleColorMessage_head = "Выбери цвет подзаголовка:\n0) оставить без изменений\n"; + public const string enterPresetColorMessage_tail = "\nИли введи hex-код цвета через #."; + public const string presetCreatedMessage = "Пресет создан!"; static readonly string[] helloWords = ["прив","привет","▶️начать","ку","хай","приветик","превед","привки","хаюхай","здравствуй","здравствуйте","здорово","дарова","дороу","здарова","здорова"]; static readonly string[] cancelWords = ["↩️назад", "назад", "выйти", "отмена", "отменить", "отменяй", "галя", "галина", "стоп"]; @@ -25,13 +32,17 @@ internal static class Interactions public static readonly string backButtonText = "↩️Назад"; public static readonly string gotoPresetsButtonText = "🎨Сохранённые стили"; public static readonly string doneButtonText = "✅Готово"; - public static readonly string choosePresetButtonText = "☑️Выбрать активный"; + public static readonly string choosePresetButtonText = "☑️Выбрать"; + public static readonly string createPresetButtonText = "🔶Создать"; + + public static readonly Color[] quickSelectColors = [Color.FromArgb(255,255,255,255),Color.FromArgb(255,192,192,192),Color.FromArgb(255,15,216,152),Color.FromArgb(255,85,119,252)]; + public static readonly string[] quickSelectColorNames = ["белый", "серый", "зелёный", "голубой"]; public static readonly IReplyMarkup mainReplyMarkup = new ReplyKeyboardMarkup([[new KeyboardButton("▶️Начать")], [new KeyboardButton("⚙️Настройки")]]); public static readonly IReplyMarkup backButtonReplyMarkup = new ReplyKeyboardMarkup(new KeyboardButton("↩️Назад")); public static readonly IReplyMarkup resultActionReplyMarkup = new ReplyKeyboardMarkup([new KeyboardButton(doneButtonText)]); public static readonly IReplyMarkup settingsReplyMarkup = new ReplyKeyboardMarkup([[new KeyboardButton(gotoPresetsButtonText)], [new KeyboardButton(backButtonText)]]); - public static readonly IReplyMarkup presetsReplyMarkup = new ReplyKeyboardMarkup([[new KeyboardButton(choosePresetButtonText)], [new KeyboardButton(backButtonText)]]); + public static readonly IReplyMarkup presetsReplyMarkup = new ReplyKeyboardMarkup([[new KeyboardButton(choosePresetButtonText), new KeyboardButton(createPresetButtonText)], [new KeyboardButton(backButtonText)]]); static readonly string[] digitEmojis = ["0️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣"]; @@ -86,6 +97,42 @@ internal static class Interactions return msg.ToString(); } + public static string MakeColorPickMessage(int type) + { + StringBuilder msg = new StringBuilder(); + msg.Append(type switch + { + 0 => enterPresetOutlineColorMessage_head, + 1 => enterPresetTitleColorMessage_head, + _ => enterPresetSubtitleColorMessage_head + }); + for (int i = 1; i < quickSelectColors.Length; i++) + { + msg.Append($"{i}) {quickSelectColorNames[i - 1]} ({ColorToHex(quickSelectColors[i])})\n"); + } + msg.Append(enterPresetColorMessage_tail); + return msg.ToString(); + } + + public static string ColorToHex(Color color) + { + return "#" + (color.ToArgb() & 0xFFFFFF).ToString("x6"); + } + + public static bool HexToColor(string hex, out Color color) + { + if (uint.TryParse(hex[1..], out uint c)) + { + color = Color.FromArgb((int)(0xFF000000U | c)); + return true; + } + else + { + color = default; + return false; + } + } + public static string DigitsToEmoji(string s) { StringBuilder sb = new StringBuilder(s.Length * 4); diff --git a/SimpleTGBot/TelegramBot.cs b/SimpleTGBot/TelegramBot.cs index e25d181..5423bfc 100644 --- a/SimpleTGBot/TelegramBot.cs +++ b/SimpleTGBot/TelegramBot.cs @@ -244,6 +244,12 @@ internal class TelegramBot dialogData.state = DialogState.ChoosingPreset; await botClient.SendTextMessageAsync(message.Chat.Id, Interactions.choosePresetMessage, replyMarkup: Interactions.backButtonReplyMarkup); } + else if (messageText == Interactions.createPresetButtonText) + { + replied = true; + dialogData.state = DialogState.CreatingPreset_AwaitingName; + await botClient.SendTextMessageAsync(message.Chat.Id, Interactions.enterPresetNameMessage, replyMarkup: Interactions.backButtonReplyMarkup, cancellationToken: cancellationToken); + } } if (!replied) { @@ -280,6 +286,97 @@ internal class TelegramBot } break; } + case DialogState.CreatingPreset_AwaitingName: + case DialogState.CreatingPreset_AwaitingOutlineColor: + case DialogState.CreatingPreset_AwaitingTitleColor: + case DialogState.CreatingPreset_AwaitingSubtitleColor: + { + bool replied = false; + if (message.Text is { } messageText) + { + if (messageText == Interactions.backButtonText) + { + replied = true; + await DialogShowPresets(botClient, user, message.Chat.Id, dialogData); + } + else if (dialogData.state == DialogState.CreatingPreset_AwaitingName) + { + replied = true; + dialogData.incompletePreset.Name = messageText; + dialogData.state = DialogState.CreatingPreset_AwaitingOutlineColor; + await botClient.SendTextMessageAsync(message.Chat.Id, Interactions.MakeColorPickMessage(0), replyMarkup: Interactions.backButtonReplyMarkup, cancellationToken: cancellationToken); + } + else + { + System.Drawing.Color color = default; + bool unchanged = false; + if (messageText.StartsWith('#')) + { + if (Interactions.HexToColor(messageText, out color)) + { + replied = true; + } + } else + { + if (int.TryParse(messageText, out int colorNumber)) + { + if (colorNumber >= 0 && colorNumber <= Interactions.quickSelectColors.Length) + { + if (colorNumber == 0) + { + unchanged = true; + } + else + { + color = Interactions.quickSelectColors[colorNumber - 1]; + } + replied = true; + } + } + } + if (replied) + { + if (dialogData.state == DialogState.CreatingPreset_AwaitingOutlineColor) + { + dialogData.incompletePreset.OutlineColor = unchanged ? System.Drawing.Color.FromArgb(255, 255, 255, 255) : color; + dialogData.state = DialogState.CreatingPreset_AwaitingTitleColor; + await botClient.SendTextMessageAsync(message.Chat.Id, Interactions.MakeColorPickMessage(1), replyMarkup: Interactions.backButtonReplyMarkup, cancellationToken: cancellationToken); + } + else if (dialogData.state == DialogState.CreatingPreset_AwaitingTitleColor) + { + dialogData.incompletePreset.TitleColor = unchanged ? System.Drawing.Color.FromArgb(255, 255, 255, 255) : color; + dialogData.state = DialogState.CreatingPreset_AwaitingSubtitleColor; + await botClient.SendTextMessageAsync(message.Chat.Id, Interactions.MakeColorPickMessage(2), replyMarkup: Interactions.backButtonReplyMarkup, cancellationToken: cancellationToken); + } + else if (dialogData.state == DialogState.CreatingPreset_AwaitingSubtitleColor) + { + dialogData.incompletePreset.SubtitleColor = unchanged ? System.Drawing.Color.FromArgb(255, 255, 255, 255) : color; + dialogData.incompletePreset.OwnerId = user.Id; + long id = await AddPresetToDatabase(dialogData.incompletePreset); + logger.Info($"Создан новый пресет стиля для пользователя {user.Id}: {id}"); + await botClient.SendTextMessageAsync(message.Chat.Id, Interactions.presetCreatedMessage, replyMarkup: Interactions.backButtonReplyMarkup, cancellationToken: cancellationToken); + await DialogShowPresets(botClient, user, message.Chat.Id, dialogData); + } + } + } + } + if (!replied) + { + if (dialogData.state == DialogState.CreatingPreset_AwaitingName) + await botClient.SendTextMessageAsync(message.Chat.Id, Interactions.enterPresetNameMessage, replyMarkup: Interactions.backButtonReplyMarkup, cancellationToken: cancellationToken); + else + { + int t = dialogData.state switch + { + DialogState.CreatingPreset_AwaitingOutlineColor => 0, + DialogState.CreatingPreset_AwaitingTitleColor => 1, + DialogState.CreatingPreset_AwaitingSubtitleColor => 2, + }; + await botClient.SendTextMessageAsync(message.Chat.Id, Interactions.MakeColorPickMessage(t), replyMarkup: Interactions.backButtonReplyMarkup, cancellationToken: cancellationToken); + } + } + break; + } } } @@ -329,10 +426,19 @@ internal class TelegramBot if (subtitle != null) { logger.Info($"Генерирую простой демотиватор: [\"{title}\", \"{subtitle}\"]"); + DemotivatorStyle style = DemotivatorGen.DefaultStyle(); + try + { + ApplyUserPreset(style, await GetActiveUserPreset(message.From!)); + } + catch (Exception) + { + logger.Error("Не удалось применить пользовательский стиль"); + } MemoryStream demotivator = DemotivatorGen.MakePictureDemotivator( dialogData.inputPictureFilename!, [new DemotivatorText() { Title = title, Subtitle = subtitle }], - DemotivatorGen.DefaultStyle()); + style); dialogData.state = DialogState.ShowingResult; await botClient.SendPhotoAsync(message.Chat.Id, new InputFile(demotivator, "dem.png"), caption: Interactions.showingResultMessage, replyMarkup: Interactions.resultActionReplyMarkup, cancellationToken: cancellationToken); demotivator.Dispose(); @@ -351,10 +457,19 @@ internal class TelegramBot string title = dialogData.inputTitle!; logger.Info($"Генерирую простой демотиватор: [\"{title}\", \"{subtitle}\"]"); + DemotivatorStyle style = DemotivatorGen.DefaultStyle(); + try + { + ApplyUserPreset(style, await GetActiveUserPreset(message.From!)); + } + catch (Exception) + { + logger.Error("Не удалось применить пользовательский стиль"); + } MemoryStream demotivator = DemotivatorGen.MakePictureDemotivator( dialogData.inputPictureFilename!, [new DemotivatorText() { Title = title, Subtitle = subtitle }], - DemotivatorGen.DefaultStyle()); + style); dialogData.state = DialogState.ShowingResult; await botClient.SendPhotoAsync(message.Chat.Id, new InputFile(demotivator, "dem.png"), caption: Interactions.showingResultMessage, replyMarkup: Interactions.resultActionReplyMarkup, cancellationToken: cancellationToken); demotivator.Dispose(); @@ -391,6 +506,13 @@ internal class TelegramBot await botClient.SendTextMessageAsync(chatId, Interactions.MakePresetListMessage(presets.Select(preset => preset.Name).ToArray(), activePresetIndex), replyMarkup: Interactions.presetsReplyMarkup); } + void ApplyUserPreset(DemotivatorStyle style, UserPreset preset) + { + style.OutlineColor = preset.OutlineColor; + style.TitleColor = preset.TitleColor; + style.SubtitleColor = preset.SubtitleColor; + } + async Task AddUserToDatabase(User u) { var cmd = database.CreateCommand();