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
|
||||
{
|
||||
public const string DEFAULT_BOT_TOKEN_FILENAME = "telegram_token.txt";
|
||||
|
||||
public const string DEFAULT_DATABASE_FILENAME = "demotivatorbot.db";
|
||||
|
||||
public static string? TryReadBotTokenFile()
|
||||
{
|
||||
try
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -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; }
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
@ -8,6 +8,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Data.Sqlite" Version="9.0.4" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="9.0.4" />
|
||||
<PackageReference Include="Telegram.Bot" Version="19.0.0-preview.2" />
|
||||
</ItemGroup>
|
||||
|
@ -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<long, DialogData> 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<long, DialogData>();
|
||||
temp = new TempStorage();
|
||||
httpClient = new HttpClient();
|
||||
database = db;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@ -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<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>
|
||||
|
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