diff --git a/SimpleTGBot/Config.cs b/SimpleTGBot/Config.cs
index 64f6758..812949a 100644
--- a/SimpleTGBot/Config.cs
+++ b/SimpleTGBot/Config.cs
@@ -5,7 +5,8 @@ namespace SimpleTGBot;
internal class Config
{
public const string DEFAULT_BOT_TOKEN_FILENAME = "telegram_token.txt";
-
+ public const string DEFAULT_DATABASE_FILENAME = "demotivatorbot.db";
+
public static string? TryReadBotTokenFile()
{
try
diff --git a/SimpleTGBot/Interactions.cs b/SimpleTGBot/Interactions.cs
index a643120..b440179 100644
--- a/SimpleTGBot/Interactions.cs
+++ b/SimpleTGBot/Interactions.cs
@@ -1,4 +1,5 @@
-using Telegram.Bot.Types.ReplyMarkups;
+using System.Text;
+using Telegram.Bot.Types.ReplyMarkups;
namespace SimpleTGBot;
@@ -28,6 +29,8 @@ internal static class Interactions
public static readonly IReplyMarkup resultActionReplyMarkup = new ReplyKeyboardMarkup([new KeyboardButton(doneButtonText)]);
public static readonly IReplyMarkup settingsReplyMarkup = new ReplyKeyboardMarkup([[new KeyboardButton(gotoPresetsButtonText)], [new KeyboardButton(backButtonText)]]);
+ static readonly string[] digitEmojis = ["0️⃣", "1️⃣", "2️⃣", "3️⃣", "4️⃣", "5️⃣", "6️⃣", "7️⃣", "8️⃣", "9️⃣"];
+
public static bool IsStartCommand(string message)
{
return message.Split(' ').FirstOrDefault() == "/start";
@@ -55,4 +58,33 @@ internal static class Interactions
{
return message == backButtonText;
}
+
+ public static string MakePresetListMessage(string[] presetNames)
+ {
+ StringBuilder msg = new StringBuilder();
+ msg.Append("Твои сохранённые стили:\n");
+ for (int i = 0; i < presetNames.Length; i++)
+ {
+ msg.Append(DigitsToEmoji((i + 1).ToString()));
+ msg.Append(' ');
+ msg.Append(presetNames[i]);
+ msg.Append('\n');
+ }
+ if (presetNames.Length == 0)
+ {
+ msg.Append("<пусто>");
+ }
+ msg.Append("\n");
+ return msg.ToString();
+ }
+
+ public static string DigitsToEmoji(string s)
+ {
+ StringBuilder sb = new StringBuilder(s.Length * 4);
+ foreach (char digit in s)
+ {
+ sb.Append(digitEmojis[digit - '0']);
+ }
+ return sb.ToString();
+ }
}
diff --git a/SimpleTGBot/MemeGen/Types.cs b/SimpleTGBot/MemeGen/Types.cs
index 5cf6e27..afb0421 100644
--- a/SimpleTGBot/MemeGen/Types.cs
+++ b/SimpleTGBot/MemeGen/Types.cs
@@ -13,7 +13,7 @@ public record DemotivatorStyle
public float Padding { get; set; }
public float OuterMargin { get; set; }
public float CaptionSpacing { get; set; }
- public float Wtf1 { get; set; }
+ public float AdditionalTextWidth { get; set; }
public Color OutlineColor { get; set; }
public Color TitleColor { get; set; }
public Color SubtitleColor { get; set; }
diff --git a/SimpleTGBot/Program.cs b/SimpleTGBot/Program.cs
index 02c40f7..71c6b3f 100644
--- a/SimpleTGBot/Program.cs
+++ b/SimpleTGBot/Program.cs
@@ -1,4 +1,5 @@
using System.Text;
+using Microsoft.Data.Sqlite;
using SimpleTGBot.Logging;
namespace SimpleTGBot;
@@ -16,6 +17,11 @@ public static class Program
// Православная кодировка
Console.OutputEncoding = Encoding.UTF8;
+ using SqliteConnection db = new("Data Source=" + Config.DEFAULT_DATABASE_FILENAME);
+ db.Open();
+
+ PrepareDatabaseTables(db);
+
string? botToken = Config.TryReadBotTokenFile();
if (botToken == null)
@@ -33,10 +39,29 @@ public static class Program
using (Logger logger = new Logger())
{
logger.Sinks.Add(new StdoutSink());
- TelegramBot telegramBot = new TelegramBot(botToken, logger);
+ TelegramBot telegramBot = new TelegramBot(botToken, logger, db);
await telegramBot.Run();
}
+ db.Close();
+
return 0;
}
+
+ static void PrepareDatabaseTables(SqliteConnection db)
+ {
+ var cmd = db.CreateCommand();
+ cmd.CommandText = "CREATE TABLE IF NOT EXISTS users (id INTEGER PRIMARY KEY, selected_preset INTEGER)";
+ cmd.ExecuteNonQuery();
+
+ cmd = db.CreateCommand();
+ cmd.CommandText = @"CREATE TABLE IF NOT EXISTS user_presets (
+ id INTEGER PRIMARY KEY AUTOINCREMENT,
+ user_id INTEGER,
+ name TEXT,
+ outline_color INTEGER,
+ title_color INTEGER,
+ subtitle_color INTEGER)";
+ cmd.ExecuteNonQuery();
+ }
}
diff --git a/SimpleTGBot/SimpleTGBot.csproj b/SimpleTGBot/SimpleTGBot.csproj
index ed4a1e7..6f82ec6 100644
--- a/SimpleTGBot/SimpleTGBot.csproj
+++ b/SimpleTGBot/SimpleTGBot.csproj
@@ -8,6 +8,7 @@
+
diff --git a/SimpleTGBot/TelegramBot.cs b/SimpleTGBot/TelegramBot.cs
index 196f25e..7f2fd96 100644
--- a/SimpleTGBot/TelegramBot.cs
+++ b/SimpleTGBot/TelegramBot.cs
@@ -1,4 +1,6 @@
-using SimpleTGBot.Logging;
+using System.Drawing;
+using Microsoft.Data.Sqlite;
+using SimpleTGBot.Logging;
using SimpleTGBot.MemeGen;
using Telegram.Bot;
using Telegram.Bot.Exceptions;
@@ -12,17 +14,19 @@ internal class TelegramBot
{
private string token;
private Logger logger;
+ private SqliteConnection database;
private Dictionary dialogs;
private TempStorage temp;
private HttpClient httpClient;
- public TelegramBot(string token, Logger logger)
+ public TelegramBot(string token, Logger logger, SqliteConnection db)
{
this.token = token;
this.logger = logger;
dialogs = new Dictionary();
temp = new TempStorage();
httpClient = new HttpClient();
+ database = db;
}
///
@@ -72,12 +76,17 @@ internal class TelegramBot
{
if (update.Message is not { } message) return;
if (message.Chat.Type != ChatType.Private) return;
+ if (message.From is not { } user) return;
DialogData dialogData;
if (!dialogs.ContainsKey(message.Chat.Id))
{
dialogData = new DialogData() { state = DialogState.Initial };
dialogs[message.Chat.Id] = dialogData;
+ if (!await IsUserInDatabase(user))
+ {
+ await AddUserToDatabase(user);
+ }
} else
{
dialogData = dialogs[message.Chat.Id];
@@ -203,7 +212,7 @@ internal class TelegramBot
{
replied = true;
dialogData.state = DialogState.ViewingPresets;
- await botClient.SendTextMessageAsync(message.Chat.Id, "<заглушка>", replyMarkup: Interactions.backButtonReplyMarkup);
+ await botClient.SendTextMessageAsync(message.Chat.Id, Interactions.MakePresetListMessage((await GetUserPresets(user)).Select(preset => preset.Name).ToArray()), replyMarkup: Interactions.backButtonReplyMarkup);
}
else if (messageText == Interactions.backButtonText)
{
@@ -330,6 +339,135 @@ internal class TelegramBot
temp.deleteTemporaryFile(dialogData.inputPictureFilename);
}
+ async Task AddUserToDatabase(User u)
+ {
+ var cmd = database.CreateCommand();
+ cmd.CommandText = "INSERT INTO users (id) VALUES ($1)";
+ cmd.Parameters.AddWithValue("$1", u.Id);
+ await cmd.ExecuteNonQueryAsync();
+
+ cmd = database.CreateCommand();
+ UserPreset defaultPreset = UserPreset.Default();
+ defaultPreset.OwnerId = u.Id;
+ await AddPresetToDatabase(defaultPreset);
+ }
+
+ async Task AddPresetToDatabase(UserPreset p)
+ {
+ var cmd = database.CreateCommand();
+ cmd.CommandText = "INSERT INTO user_presets (user_id, name, outline_color, title_color, subtitle_color) VALUES ($1, $2, $3, $4, $5)";
+ cmd.Parameters.AddWithValue("$1", p.OwnerId);
+ cmd.Parameters.AddWithValue("$2", p.Name);
+ cmd.Parameters.AddWithValue("$3", (long)p.OutlineColor.ToArgb() & 0xFFFFFFL);
+ cmd.Parameters.AddWithValue("$4", (long)p.TitleColor.ToArgb() & 0xFFFFFFL);
+ cmd.Parameters.AddWithValue("$5", (long)p.SubtitleColor.ToArgb() & 0xFFFFFFL);
+ await cmd.ExecuteNonQueryAsync();
+ }
+
+ async Task IsUserInDatabase(User u)
+ {
+ var cmd = database.CreateCommand();
+ cmd.CommandText = "SELECT id FROM users WHERE id = $1";
+ cmd.Parameters.AddWithValue("$1", u.Id);
+ using var reader = await cmd.ExecuteReaderAsync();
+ return await reader.ReadAsync();
+ }
+
+ async Task GetUserPresets(User u)
+ {
+ var cmd = database.CreateCommand();
+ cmd.CommandText = "SELECT id, user_id, name, outline_color, title_color, subtitle_color FROM user_presets WHERE id = $1";
+ cmd.Parameters.AddWithValue("$1", u.Id);
+ using var reader = await cmd.ExecuteReaderAsync();
+ List result = new List();
+ while (reader.Read())
+ {
+ result.Add(new UserPreset()
+ {
+ Id = reader.GetInt64(0),
+ OwnerId = reader.GetInt64(1),
+ Name = reader.GetString(2),
+ OutlineColor = System.Drawing.Color.FromArgb((int)(0xff000000L | reader.GetInt64(3))),
+ TitleColor = System.Drawing.Color.FromArgb((int)(0xff000000L | reader.GetInt64(4))),
+ SubtitleColor = System.Drawing.Color.FromArgb((int)(0xff000000L | reader.GetInt64(5))),
+ });
+ }
+ return result.ToArray();
+ }
+
+ async Task GetUserPresetByName(User u, string name)
+ {
+ var cmd = database.CreateCommand();
+ cmd.CommandText = "SELECT id, outline_color, title_color, subtitle_color FROM user_presets WHERE name = $1";
+ cmd.Parameters.AddWithValue("$1", name);
+ using (var reader = await cmd.ExecuteReaderAsync())
+ {
+ if (reader.Read())
+ {
+ return new UserPreset()
+ {
+ Id = reader.GetInt64(0),
+ OwnerId = u.Id,
+ Name = name,
+ OutlineColor = System.Drawing.Color.FromArgb((int)(0xff000000L | reader.GetInt64(1))),
+ TitleColor = System.Drawing.Color.FromArgb((int)(0xff000000L | reader.GetInt64(2))),
+ SubtitleColor = System.Drawing.Color.FromArgb((int)(0xff000000L | reader.GetInt64(3))),
+ };
+ }
+ else
+ {
+ return null;
+ }
+ }
+ }
+
+ async Task DeleteUserPreset(long id)
+ {
+ var cmd = database.CreateCommand();
+ cmd.CommandText = "DELETE FROM user_presets WHERE id = $1";
+ cmd.Parameters.AddWithValue("$1", id);
+ cmd.ExecuteNonQuery();
+ }
+
+ async Task GetActiveUserPreset(User u)
+ {
+ var cmd = database.CreateCommand();
+ cmd.CommandText = "SELECT selected_preset FROM users WHERE id = $1";
+ cmd.Parameters.AddWithValue("$1", u.Id);
+ int activePreset = -1;
+ using (var reader = await cmd.ExecuteReaderAsync()) {
+ if (reader.Read())
+ {
+ activePreset = reader.GetInt32(0);
+ } else
+ {
+ throw new Exception("пользователь не найден");
+ }
+ }
+
+ cmd = database.CreateCommand();
+ cmd.CommandText = "SELECT name, outline_color, title_color, subtitle_color FROM user_presets WHERE id = $1";
+ cmd.Parameters.AddWithValue("$1", activePreset);
+ using (var reader = await cmd.ExecuteReaderAsync())
+ {
+ if (reader.Read())
+ {
+ return new UserPreset()
+ {
+ Id = activePreset,
+ OwnerId = u.Id,
+ Name = reader.GetString(0),
+ OutlineColor = System.Drawing.Color.FromArgb((int)(0xff000000L | reader.GetInt64(1))),
+ TitleColor = System.Drawing.Color.FromArgb((int)(0xff000000L | reader.GetInt64(2))),
+ SubtitleColor = System.Drawing.Color.FromArgb((int)(0xff000000L | reader.GetInt64(3))),
+ };
+ } else
+ {
+ throw new Exception("выбранный пресет пользователя " + u.Id + " не найден");
+ }
+ }
+ }
+
///
/// Обработчик исключений, возникших при работе бота
///
diff --git a/SimpleTGBot/UserPreset.cs b/SimpleTGBot/UserPreset.cs
new file mode 100644
index 0000000..1926eb2
--- /dev/null
+++ b/SimpleTGBot/UserPreset.cs
@@ -0,0 +1,23 @@
+using System.Drawing;
+
+namespace SimpleTGBot;
+
+internal struct UserPreset
+{
+ public long Id;
+ public long OwnerId;
+ public string Name;
+ public Color OutlineColor;
+ public Color TitleColor;
+ public Color SubtitleColor;
+
+ public static UserPreset Default() => new UserPreset()
+ {
+ Id = 0,
+ OwnerId = 0,
+ Name = "По умолчанию",
+ OutlineColor = Color.FromArgb(255, 255, 255, 255),
+ TitleColor = Color.FromArgb(255, 255, 255, 255),
+ SubtitleColor = Color.FromArgb(255, 255, 255, 255),
+ };
+}