TelegramBot: add method to work with the database
This commit is contained in:
parent
330abb90ff
commit
a457ea1a19
@ -5,7 +5,8 @@ namespace SimpleTGBot;
|
|||||||
internal class Config
|
internal class Config
|
||||||
{
|
{
|
||||||
public const string DEFAULT_BOT_TOKEN_FILENAME = "telegram_token.txt";
|
public const string DEFAULT_BOT_TOKEN_FILENAME = "telegram_token.txt";
|
||||||
|
public const string DEFAULT_DATABASE_FILENAME = "demotivatorbot.db";
|
||||||
|
|
||||||
public static string? TryReadBotTokenFile()
|
public static string? TryReadBotTokenFile()
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using Telegram.Bot.Types.ReplyMarkups;
|
using System.Text;
|
||||||
|
using Telegram.Bot.Types.ReplyMarkups;
|
||||||
|
|
||||||
namespace SimpleTGBot;
|
namespace SimpleTGBot;
|
||||||
|
|
||||||
@ -28,6 +29,8 @@ internal static class Interactions
|
|||||||
public static readonly IReplyMarkup resultActionReplyMarkup = new ReplyKeyboardMarkup([new KeyboardButton(doneButtonText)]);
|
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 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)
|
public static bool IsStartCommand(string message)
|
||||||
{
|
{
|
||||||
return message.Split(' ').FirstOrDefault() == "/start";
|
return message.Split(' ').FirstOrDefault() == "/start";
|
||||||
@ -55,4 +58,33 @@ internal static class Interactions
|
|||||||
{
|
{
|
||||||
return message == backButtonText;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -13,7 +13,7 @@ public record DemotivatorStyle
|
|||||||
public float Padding { get; set; }
|
public float Padding { get; set; }
|
||||||
public float OuterMargin { get; set; }
|
public float OuterMargin { get; set; }
|
||||||
public float CaptionSpacing { get; set; }
|
public float CaptionSpacing { get; set; }
|
||||||
public float Wtf1 { get; set; }
|
public float AdditionalTextWidth { get; set; }
|
||||||
public Color OutlineColor { get; set; }
|
public Color OutlineColor { get; set; }
|
||||||
public Color TitleColor { get; set; }
|
public Color TitleColor { get; set; }
|
||||||
public Color SubtitleColor { get; set; }
|
public Color SubtitleColor { get; set; }
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
using SimpleTGBot.Logging;
|
using SimpleTGBot.Logging;
|
||||||
|
|
||||||
namespace SimpleTGBot;
|
namespace SimpleTGBot;
|
||||||
@ -16,6 +17,11 @@ public static class Program
|
|||||||
// Православная кодировка
|
// Православная кодировка
|
||||||
Console.OutputEncoding = Encoding.UTF8;
|
Console.OutputEncoding = Encoding.UTF8;
|
||||||
|
|
||||||
|
using SqliteConnection db = new("Data Source=" + Config.DEFAULT_DATABASE_FILENAME);
|
||||||
|
db.Open();
|
||||||
|
|
||||||
|
PrepareDatabaseTables(db);
|
||||||
|
|
||||||
string? botToken = Config.TryReadBotTokenFile();
|
string? botToken = Config.TryReadBotTokenFile();
|
||||||
|
|
||||||
if (botToken == null)
|
if (botToken == null)
|
||||||
@ -33,10 +39,29 @@ public static class Program
|
|||||||
using (Logger logger = new Logger())
|
using (Logger logger = new Logger())
|
||||||
{
|
{
|
||||||
logger.Sinks.Add(new StdoutSink());
|
logger.Sinks.Add(new StdoutSink());
|
||||||
TelegramBot telegramBot = new TelegramBot(botToken, logger);
|
TelegramBot telegramBot = new TelegramBot(botToken, logger, db);
|
||||||
await telegramBot.Run();
|
await telegramBot.Run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
db.Close();
|
||||||
|
|
||||||
return 0;
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -8,6 +8,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.4" />
|
||||||
<PackageReference Include="System.Drawing.Common" Version="9.0.4" />
|
<PackageReference Include="System.Drawing.Common" Version="9.0.4" />
|
||||||
<PackageReference Include="Telegram.Bot" Version="19.0.0-preview.2" />
|
<PackageReference Include="Telegram.Bot" Version="19.0.0-preview.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
@ -1,4 +1,6 @@
|
|||||||
using SimpleTGBot.Logging;
|
using System.Drawing;
|
||||||
|
using Microsoft.Data.Sqlite;
|
||||||
|
using SimpleTGBot.Logging;
|
||||||
using SimpleTGBot.MemeGen;
|
using SimpleTGBot.MemeGen;
|
||||||
using Telegram.Bot;
|
using Telegram.Bot;
|
||||||
using Telegram.Bot.Exceptions;
|
using Telegram.Bot.Exceptions;
|
||||||
@ -12,17 +14,19 @@ internal class TelegramBot
|
|||||||
{
|
{
|
||||||
private string token;
|
private string token;
|
||||||
private Logger logger;
|
private Logger logger;
|
||||||
|
private SqliteConnection database;
|
||||||
private Dictionary<long, DialogData> dialogs;
|
private Dictionary<long, DialogData> dialogs;
|
||||||
private TempStorage temp;
|
private TempStorage temp;
|
||||||
private HttpClient httpClient;
|
private HttpClient httpClient;
|
||||||
|
|
||||||
public TelegramBot(string token, Logger logger)
|
public TelegramBot(string token, Logger logger, SqliteConnection db)
|
||||||
{
|
{
|
||||||
this.token = token;
|
this.token = token;
|
||||||
this.logger = logger;
|
this.logger = logger;
|
||||||
dialogs = new Dictionary<long, DialogData>();
|
dialogs = new Dictionary<long, DialogData>();
|
||||||
temp = new TempStorage();
|
temp = new TempStorage();
|
||||||
httpClient = new HttpClient();
|
httpClient = new HttpClient();
|
||||||
|
database = db;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@ -72,12 +76,17 @@ internal class TelegramBot
|
|||||||
{
|
{
|
||||||
if (update.Message is not { } message) return;
|
if (update.Message is not { } message) return;
|
||||||
if (message.Chat.Type != ChatType.Private) return;
|
if (message.Chat.Type != ChatType.Private) return;
|
||||||
|
if (message.From is not { } user) return;
|
||||||
|
|
||||||
DialogData dialogData;
|
DialogData dialogData;
|
||||||
if (!dialogs.ContainsKey(message.Chat.Id))
|
if (!dialogs.ContainsKey(message.Chat.Id))
|
||||||
{
|
{
|
||||||
dialogData = new DialogData() { state = DialogState.Initial };
|
dialogData = new DialogData() { state = DialogState.Initial };
|
||||||
dialogs[message.Chat.Id] = dialogData;
|
dialogs[message.Chat.Id] = dialogData;
|
||||||
|
if (!await IsUserInDatabase(user))
|
||||||
|
{
|
||||||
|
await AddUserToDatabase(user);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
{
|
{
|
||||||
dialogData = dialogs[message.Chat.Id];
|
dialogData = dialogs[message.Chat.Id];
|
||||||
@ -203,7 +212,7 @@ internal class TelegramBot
|
|||||||
{
|
{
|
||||||
replied = true;
|
replied = true;
|
||||||
dialogData.state = DialogState.ViewingPresets;
|
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)
|
else if (messageText == Interactions.backButtonText)
|
||||||
{
|
{
|
||||||
@ -330,6 +339,135 @@ internal class TelegramBot
|
|||||||
temp.deleteTemporaryFile(dialogData.inputPictureFilename);
|
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<bool> 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<UserPreset[]> 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<UserPreset> result = new List<UserPreset>();
|
||||||
|
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<UserPreset?> 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<UserPreset> 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 + " не найден");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Обработчик исключений, возникших при работе бота
|
/// Обработчик исключений, возникших при работе бота
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
23
SimpleTGBot/UserPreset.cs
Normal file
23
SimpleTGBot/UserPreset.cs
Normal file
@ -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),
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user