diff --git a/Database/BaseDBMigration.cs b/Database/BaseDBMigration.cs index 88cf9cd..74ebfeb 100644 --- a/Database/BaseDBMigration.cs +++ b/Database/BaseDBMigration.cs @@ -34,7 +34,8 @@ private void CreateCommonTables() .WithColumn("TelegramID").AsInt64().NotNullable() .WithColumn("Name").AsString(255).NotNullable() .WithColumn("Link").AsString(255).NotNullable() - .WithColumn("Status").AsString(255).Nullable(); + .WithColumn("Status").AsString(255).Nullable() + .WithColumn("SettingsJson").AsString(int.MaxValue).NotNullable().WithDefaultValue("{}"); } // Contacts diff --git a/Database/DBInit.cs b/Database/DBInit.cs index c2babb9..b7b6de2 100644 --- a/Database/DBInit.cs +++ b/Database/DBInit.cs @@ -63,6 +63,8 @@ public static WebApplicationBuilder CreateBuilderByDBType(string[] args) new SqliteUserRepository(Config.sqlConnectionString!)); builder.Services.AddSingleton(_ => new SqliteUserGetter(Config.sqlConnectionString!)); + builder.Services.AddSingleton(_ => + new SqliteUserSettingsRepository(Config.sqlConnectionString!)); builder.Services.AddSingleton(_ => new SqliteContactGroupRepository(Config.sqlConnectionString!)); diff --git a/Database/Interfaces/IUserSettingsRepository.cs b/Database/Interfaces/IUserSettingsRepository.cs new file mode 100644 index 0000000..379189e --- /dev/null +++ b/Database/Interfaces/IUserSettingsRepository.cs @@ -0,0 +1,20 @@ +// Copyright (C) 2024-2025 ZenonEl +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Эта программа является свободным программным обеспечением: вы можете распространять и/или изменять +// её на условиях Стандартной общественной лицензии GNU Affero, опубликованной +// Фондом свободного программного обеспечения, либо версии 3 лицензии, либо +// (по вашему выбору) любой более поздней версии. + +using TelegramMediaRelayBot.Domain.Models; + +namespace TelegramMediaRelayBot.Database.Interfaces; + +public interface IUserSettingsRepository +{ + Task GetSettingsAsync(int userId); + Task SaveSettingsAsync(int userId, UserSettings settings); +} diff --git a/Database/Migrations/AddSettingsJsonColumn.cs b/Database/Migrations/AddSettingsJsonColumn.cs new file mode 100644 index 0000000..abc7371 --- /dev/null +++ b/Database/Migrations/AddSettingsJsonColumn.cs @@ -0,0 +1,32 @@ +// Copyright (C) 2024-2025 ZenonEl +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Эта программа является свободным программным обеспечением: вы можете распространять и/или изменять +// её на условиях Стандартной общественной лицензии GNU Affero, опубликованной +// Фондом свободного программного обеспечения, либо версии 3 лицензии, либо +// (по вашему выбору) любой более поздней версии. + +using FluentMigrator; + +namespace TelegramMediaRelayBot.Database.Migrations; + +[Migration(20260328)] +public class AddSettingsJsonColumn : Migration +{ + public override void Up() + { + if (!Schema.Table("Users").Column("SettingsJson").Exists()) + { + Alter.Table("Users") + .AddColumn("SettingsJson").AsString(int.MaxValue).NotNullable().WithDefaultValue("{}"); + } + } + + public override void Down() + { + Delete.Column("SettingsJson").FromTable("Users"); + } +} diff --git a/Database/Repositories/SqLite/UserSettingsRepository.cs b/Database/Repositories/SqLite/UserSettingsRepository.cs new file mode 100644 index 0000000..ad17aa4 --- /dev/null +++ b/Database/Repositories/SqLite/UserSettingsRepository.cs @@ -0,0 +1,57 @@ +// Copyright (C) 2024-2025 ZenonEl +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Эта программа является свободным программным обеспечением: вы можете распространять и/или изменять +// её на условиях Стандартной общественной лицензии GNU Affero, опубликованной +// Фондом свободного программного обеспечения, либо версии 3 лицензии, либо +// (по вашему выбору) любой более поздней версии. + +using Dapper; +using Microsoft.Data.Sqlite; +using TelegramMediaRelayBot.Database.Interfaces; +using TelegramMediaRelayBot.Domain.Models; + +namespace TelegramMediaRelayBot.Database.Repositories.Sqlite; + +public class SqliteUserSettingsRepository(string connectionString) : IUserSettingsRepository +{ + private readonly string _connectionString = connectionString; + + public async Task GetSettingsAsync(int userId) + { + const string query = "SELECT SettingsJson FROM Users WHERE ID = @userId"; + + try + { + using var connection = new SqliteConnection(_connectionString); + var json = await connection.ExecuteScalarAsync(query, new { userId }); + return UserSettings.FromJson(json ?? "{}"); + } + catch (Exception ex) + { + Log.Error(ex, "Failed to get settings for user {UserId}", userId); + return new UserSettings(); + } + } + + public async Task SaveSettingsAsync(int userId, UserSettings settings) + { + const string query = "UPDATE Users SET SettingsJson = @json WHERE ID = @userId"; + + try + { + var json = settings.ToJson(); + using var connection = new SqliteConnection(_connectionString); + var affected = await connection.ExecuteAsync(query, new { json, userId }); + return affected > 0; + } + catch (Exception ex) + { + Log.Error(ex, "Failed to save settings for user {UserId}", userId); + return false; + } + } +} diff --git a/Domain/Models/UserSettings.cs b/Domain/Models/UserSettings.cs new file mode 100644 index 0000000..a06d444 --- /dev/null +++ b/Domain/Models/UserSettings.cs @@ -0,0 +1,60 @@ +// Copyright (C) 2024-2025 ZenonEl +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU Affero General Public License as published +// by the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. + +// Эта программа является свободным программным обеспечением: вы можете распространять и/или изменять +// её на условиях Стандартной общественной лицензии GNU Affero, опубликованной +// Фондом свободного программного обеспечения, либо версии 3 лицензии, либо +// (по вашему выбору) любой более поздней версии. + +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace TelegramMediaRelayBot.Domain.Models; + +public sealed class UserSettings +{ + public DistributionSettings Distribution { get; set; } = new(); + public PrivacyUserSettings Privacy { get; set; } = new(); + + private static readonly JsonSerializerOptions JsonOptions = new() + { + PropertyNamingPolicy = JsonNamingPolicy.CamelCase, + DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingDefault + }; + + public string ToJson() => JsonSerializer.Serialize(this, JsonOptions); + + public static UserSettings FromJson(string json) + { + if (string.IsNullOrWhiteSpace(json)) return new(); + try { return JsonSerializer.Deserialize(json, JsonOptions) ?? new(); } + catch { return new(); } + } +} + +public sealed class DistributionSettings +{ + public string DefaultAction { get; set; } = "send_only_to_me"; + public string DefaultActionCondition { get; set; } = ""; + public int AutoSendDelaySeconds { get; set; } = 30; + public List TargetGroupIds { get; set; } = []; + public List TargetContactIds { get; set; } = []; +} + +public sealed class PrivacyUserSettings +{ + public bool InboxEnabled { get; set; } = false; + public bool AllowContentForwarding { get; set; } = true; + public string WhoCanFindMe { get; set; } = "everyone"; + public SiteFilterSettings SiteFilter { get; set; } = new(); +} + +public sealed class SiteFilterSettings +{ + public bool Enabled { get; set; } = false; + public string FilterType { get; set; } = "none"; + public List BlockedDomains { get; set; } = []; +}