diff --git a/Core/Extensions/UserExtension.cs b/Core/Extensions/UserExtension.cs index 11f578c..2455952 100644 --- a/Core/Extensions/UserExtension.cs +++ b/Core/Extensions/UserExtension.cs @@ -5,17 +5,20 @@ namespace Kruzya.TelegramBot.Core.Extensions { public static class UserExtension { - public static string ToHtml(this User user) + public static string ToHtml(this User user, bool byUsername = true) { var text = new StringBuilder(); text.Append($""); - if (!string.IsNullOrWhiteSpace(user.Username)) + + if (byUsername && !string.IsNullOrWhiteSpace(user.Username)) + { text.Append(user.Username); + } else + { text.Append($"{user.FirstName} {user.LastName}".Trim().HtmlEncode()); - text.Append(""); - - return text.ToString(); + } + return text.Append("").ToString(); } } } \ No newline at end of file diff --git a/Core/appsettings.Development.json b/Core/appsettings.Development.json deleted file mode 100644 index 45f769a..0000000 --- a/Core/appsettings.Development.json +++ /dev/null @@ -1,23 +0,0 @@ -{ - "Logging": { - "LogLevel": { - "Default": "Information", - "Microsoft": "Warning", - "Microsoft.Hosting.Lifetime": "Information" - } - }, - - "BotConfig": { - "token": "5093569980:AAEnrlpg2VYD0CyQYIZtWpUuRrlpkDG8NaI" - }, - - "ModuleDirectories": [ - "C:\\Users\\Andriy\\RiderProjects\\telegram-bot\\modules\\Destiny2.WhereIsXur\\bin\\Debug\\net5.0", - "C:\\Users\\Andriy\\RiderProjects\\telegram-bot\\modules\\RichSiteSummary\\bin\\Debug\\net5.0" - ], - - "ConnectionStrings": { - "DefaultConnection": "server=127.0.0.1;UserId=root;Password=;database=kruzyatgbot-core;port=3306", - "RichSiteSummary": "server=127.0.0.1;UserId=root;Password=;database=kruzyatgbot-rss;port=3306" - } -} diff --git a/Kruzya.TelegramBot.sln b/Kruzya.TelegramBot.sln index a5069e8..80208c2 100644 --- a/Kruzya.TelegramBot.sln +++ b/Kruzya.TelegramBot.sln @@ -15,6 +15,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UrlLimitations", "modules\U EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Destiny2.WhereIsXur", "modules\Destiny2.WhereIsXur\Destiny2.WhereIsXur.csproj", "{AE782132-BED8-4D1E-98FA-CB768171D332}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ChatManagement", "modules\ChatManagement\ChatManagement.csproj", "{55ACF7F7-409A-45EE-A41D-D8417DE7EAA7}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -45,11 +47,16 @@ Global {AE782132-BED8-4D1E-98FA-CB768171D332}.Debug|Any CPU.Build.0 = Debug|Any CPU {AE782132-BED8-4D1E-98FA-CB768171D332}.Release|Any CPU.ActiveCfg = Release|Any CPU {AE782132-BED8-4D1E-98FA-CB768171D332}.Release|Any CPU.Build.0 = Release|Any CPU + {55ACF7F7-409A-45EE-A41D-D8417DE7EAA7}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55ACF7F7-409A-45EE-A41D-D8417DE7EAA7}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55ACF7F7-409A-45EE-A41D-D8417DE7EAA7}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55ACF7F7-409A-45EE-A41D-D8417DE7EAA7}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution {F1E1FBB7-ABA4-4304-9A42-D4975822B002} = {C7821F15-DEDD-474F-A575-A296D4B58F10} {C50D64C3-204B-4B58-927B-C8D759787252} = {C7821F15-DEDD-474F-A575-A296D4B58F10} {B82E3339-3B34-4600-8C59-C5A3640B1982} = {C7821F15-DEDD-474F-A575-A296D4B58F10} {AE782132-BED8-4D1E-98FA-CB768171D332} = {C7821F15-DEDD-474F-A575-A296D4B58F10} + {55ACF7F7-409A-45EE-A41D-D8417DE7EAA7} = {C7821F15-DEDD-474F-A575-A296D4B58F10} EndGlobalSection EndGlobal diff --git a/modules/ChatManagement/ChatManagement.cs b/modules/ChatManagement/ChatManagement.cs new file mode 100644 index 0000000..782feb6 --- /dev/null +++ b/modules/ChatManagement/ChatManagement.cs @@ -0,0 +1,11 @@ +using Kruzya.TelegramBot.Core; + +namespace West.TelegramBot.ChatManagement +{ + public class ChatManagement : Module + { + public ChatManagement(Core core) : base(core) + { + } + } +} \ No newline at end of file diff --git a/modules/ChatManagement/ChatManagement.csproj b/modules/ChatManagement/ChatManagement.csproj new file mode 100644 index 0000000..86601c4 --- /dev/null +++ b/modules/ChatManagement/ChatManagement.csproj @@ -0,0 +1,13 @@ + + + + net5.0 + TelegramBot.ChatManagement + West.TelegramBot.ChatManagement + + + + + + + diff --git a/modules/ChatManagement/Extensions/BotExtension.cs b/modules/ChatManagement/Extensions/BotExtension.cs new file mode 100644 index 0000000..123d715 --- /dev/null +++ b/modules/ChatManagement/Extensions/BotExtension.cs @@ -0,0 +1,28 @@ +using System.Threading.Tasks; +using Telegram.Bot; +using Telegram.Bot.Types; + +namespace West.TelegramBot.ChatManagement.Extensions +{ + public static class BotExtension + { + public static async Task CanPunishMember(this ITelegramBotClient bot, Chat chat, User user, User victim = null) + { + var callerMember = await bot.GetChatMemberAsync(chat, user.Id); + var canUse = callerMember is ChatMemberOwner; + + if (callerMember is ChatMemberAdministrator callerAdmin) + { + canUse = callerAdmin.CanRestrictMembers; + } + + if (victim != null && canUse) + { + var victimMember = await bot.GetChatMemberAsync(chat, victim.Id); + canUse = victimMember is not ChatMemberOwner && victimMember is not ChatMemberAdministrator; + } + + return canUse; + } + } +} \ No newline at end of file diff --git a/modules/ChatManagement/Handler/Ban.cs b/modules/ChatManagement/Handler/Ban.cs new file mode 100644 index 0000000..071f7cb --- /dev/null +++ b/modules/ChatManagement/Handler/Ban.cs @@ -0,0 +1,38 @@ +using System.Threading.Tasks; +using BotFramework.Attributes; +using BotFramework.Enums; +using Telegram.Bot; +using Telegram.Bot.Types; + +namespace West.TelegramBot.ChatManagement.Handler +{ + public class Ban : ManagementHandler + { + [Command("ban", CommandParseMode.Both)] + public async Task HandleBan() + { + if (!await CanPunish()) return; + + await BanMember(GetVictim()); + } + + [Command("unban", CommandParseMode.Both)] + public async Task HandleUnban() + { + if (!await CanPunish()) return; + + await Bot.RestrictChatMemberAsync(Chat.Id, GetVictim().Id, + new ChatPermissions + { + CanSendMessages = true, + CanChangeInfo = true, + CanInviteUsers = true, + CanPinMessages = true, + CanSendPolls = true, + CanSendMediaMessages = true, + CanSendOtherMessages = true, + CanAddWebPagePreviews = true + }); + } + } +} \ No newline at end of file diff --git a/modules/ChatManagement/Handler/ManagementHandler.cs b/modules/ChatManagement/Handler/ManagementHandler.cs new file mode 100644 index 0000000..2254a61 --- /dev/null +++ b/modules/ChatManagement/Handler/ManagementHandler.cs @@ -0,0 +1,50 @@ +using System; +using System.Threading.Tasks; +using BotFramework; +using Kruzya.TelegramBot.Core.Extensions; +using Telegram.Bot; +using Telegram.Bot.Types; +using Telegram.Bot.Types.Enums; +using West.TelegramBot.ChatManagement.Extensions; + +namespace West.TelegramBot.ChatManagement.Handler +{ + public class ManagementHandler : BotEventHandler + { + protected User GetVictim() + { + return RawUpdate.Message?.ReplyToMessage?.From; + } + + protected async Task CanPunish() + { + return GetVictim() != null && await Bot.CanPunishMember(Chat, From, GetVictim()); + } + + protected async Task BanMember(User user, DateTime? banEnd = null, bool sendMessage = true) + { + await BanMember(user.Id, banEnd, sendMessage); + + if (sendMessage) + { + await Bot.SendTextMessageAsync( + Chat.Id, + $"{From.ToHtml(false)} заблокировал {user.ToHtml(false)} на 7 дней", + disableNotification: true, parseMode: ParseMode.Html); + } + } + + protected async Task BanMember(long userId, DateTime? banEnd = null, bool sendMessage = true) + { + await Bot.RestrictChatMemberAsync( + Chat.Id, + userId, + new ChatPermissions + { + CanSendMessages = false + }, + banEnd ?? DateTime.Now.AddDays(7) + ); + } + } +} \ No newline at end of file diff --git a/modules/ChatManagement/Handler/Warn.cs b/modules/ChatManagement/Handler/Warn.cs new file mode 100644 index 0000000..e71887e --- /dev/null +++ b/modules/ChatManagement/Handler/Warn.cs @@ -0,0 +1,66 @@ +using System; +using System.Threading.Tasks; +using BotFramework.Attributes; +using BotFramework.Enums; +using Kruzya.TelegramBot.Core.Data; +using Kruzya.TelegramBot.Core.Extensions; +using Telegram.Bot; +using Telegram.Bot.Types.Enums; + +namespace West.TelegramBot.ChatManagement.Handler +{ + public class Command : ManagementHandler + { + private readonly CoreContext _db; + + public Command(CoreContext db) + { + _db = db; + } + + [Command("warn", CommandParseMode.Both)] + public async Task HandleWarn() + { + if (!await CanPunish()) return; + + var warnUser = GetVictim(); + var warnOption = await GetWarnOption(); + var warnCount = warnOption.GetValue() + 1; + warnOption.SetValue(warnCount); + _db.MarkAsModified(warnOption); + + await Bot.SendTextMessageAsync(Chat.Id, $"{warnUser.ToHtml(false)}, Вам выдано предупреждение! " + + $"Текущее кол-во: {warnCount}/3", + disableNotification: true, + parseMode: ParseMode.Html); + + if (warnCount == 3) + { + await BanMember(warnUser); + warnOption.SetValue(0); + } + } + + [Command("unwarn", CommandParseMode.Both)] + public async Task HandleUnwarn() + { + if (!await CanPunish()) return; + + var warnOption = await GetWarnOption(); + var warnCount = Math.Max(warnOption.GetValue() - 1, 0); + warnOption.SetValue(warnCount); + _db.MarkAsModified(warnOption); + + await Bot.SendTextMessageAsync(Chat.Id, + $"{GetVictim().ToHtml(false)}, с Вас снято предупреждение! " + + $"Текущее кол-во: {warnCount}/3", + disableNotification: true, + parseMode: ParseMode.Html); + } + + private async Task GetWarnOption() + { + return await _db.UserValues.FindOrCreateOption(Chat.Id, GetVictim().Id, "warnCount"); + } + } +} \ No newline at end of file