diff --git a/Kruzya.TelegramBot.sln b/Kruzya.TelegramBot.sln index 54db1d5..3e4043c 100644 --- a/Kruzya.TelegramBot.sln +++ b/Kruzya.TelegramBot.sln @@ -2,6 +2,10 @@ Microsoft Visual Studio Solution File, Format Version 12.00 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "Core\Core.csproj", "{B41CB31A-641E-4079-87ED-5CE310B2D8C1}" EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Modules", "Modules", "{C7821F15-DEDD-474F-A575-A296D4B58F10}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CombotAntiSpam", "modules\CombotAntiSpam\CombotAntiSpam.csproj", "{F1E1FBB7-ABA4-4304-9A42-D4975822B002}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -12,7 +16,12 @@ Global {B41CB31A-641E-4079-87ED-5CE310B2D8C1}.Debug|Any CPU.Build.0 = Debug|Any CPU {B41CB31A-641E-4079-87ED-5CE310B2D8C1}.Release|Any CPU.ActiveCfg = Release|Any CPU {B41CB31A-641E-4079-87ED-5CE310B2D8C1}.Release|Any CPU.Build.0 = Release|Any CPU + {F1E1FBB7-ABA4-4304-9A42-D4975822B002}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {F1E1FBB7-ABA4-4304-9A42-D4975822B002}.Debug|Any CPU.Build.0 = Debug|Any CPU + {F1E1FBB7-ABA4-4304-9A42-D4975822B002}.Release|Any CPU.ActiveCfg = Release|Any CPU + {F1E1FBB7-ABA4-4304-9A42-D4975822B002}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(NestedProjects) = preSolution + {F1E1FBB7-ABA4-4304-9A42-D4975822B002} = {C7821F15-DEDD-474F-A575-A296D4B58F10} EndGlobalSection EndGlobal diff --git a/modules/CombotAntiSpam/Combot/CombotApiResponse.cs b/modules/CombotAntiSpam/Combot/CombotApiResponse.cs new file mode 100644 index 0000000..60f5a91 --- /dev/null +++ b/modules/CombotAntiSpam/Combot/CombotApiResponse.cs @@ -0,0 +1,31 @@ +using System; +using Newtonsoft.Json; + +namespace Kruzya.TelegramBot.CombotAntiSpam.Combot +{ + internal class CombotApiResponse + { + public class ApiResult + { + [JsonProperty("messages")] + public string[] Messages { get; set; } + + [JsonProperty("time_added")] + public int TimeAdded { get; set; } + + [JsonProperty("offenses")] + public int Offenses { get; set; } + + public DateTime AddedAt => DateTimeOffset.FromUnixTimeSeconds(TimeAdded).DateTime; + } + + [JsonProperty("ok")] + public bool IsSpammer { get; set; } + + [JsonProperty("description")] + public string Description { get; set; } + + [JsonProperty("result")] + public ApiResult Result { get; set; } + } +} \ No newline at end of file diff --git a/modules/CombotAntiSpam/Combot/CombotClient.cs b/modules/CombotAntiSpam/Combot/CombotClient.cs new file mode 100644 index 0000000..a685fff --- /dev/null +++ b/modules/CombotAntiSpam/Combot/CombotClient.cs @@ -0,0 +1,30 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Kruzya.TelegramBot.Core.Extensions; +using Telegram.Bot.Types; + +namespace Kruzya.TelegramBot.CombotAntiSpam.Combot +{ + public class CombotClient : ICombotClient + { + public HttpClient _HttpClient; + + public CombotClient() + { + _HttpClient = new HttpClient(); + _HttpClient.BaseAddress = new Uri("https://api.cas.chat/check"); + } + + public bool IsSpammer(User user) + { + return IsSpammerAsync(user).GetAwaiter().GetResult(); + } + + public async Task IsSpammerAsync(User user) + { + var result = await _HttpClient.GetJsonAsync($"?user_id={user.Id}"); + return result.IsSpammer; + } + } +} \ No newline at end of file diff --git a/modules/CombotAntiSpam/Combot/ICombotClient.cs b/modules/CombotAntiSpam/Combot/ICombotClient.cs new file mode 100644 index 0000000..94e8bd6 --- /dev/null +++ b/modules/CombotAntiSpam/Combot/ICombotClient.cs @@ -0,0 +1,11 @@ +using System.Threading.Tasks; +using Telegram.Bot.Types; + +namespace Kruzya.TelegramBot.CombotAntiSpam.Combot +{ + public interface ICombotClient + { + public bool IsSpammer(User user); + public Task IsSpammerAsync(User user); + } +} \ No newline at end of file diff --git a/modules/CombotAntiSpam/CombotAntiSpam.csproj b/modules/CombotAntiSpam/CombotAntiSpam.csproj new file mode 100644 index 0000000..463ac4f --- /dev/null +++ b/modules/CombotAntiSpam/CombotAntiSpam.csproj @@ -0,0 +1,13 @@ + + + + netcoreapp3.1 + TelegramBot.CombotAntiSpam + Kruzya.TelegramBot.CombotAntiSpam + + + + + + + diff --git a/modules/CombotAntiSpam/Startup.cs b/modules/CombotAntiSpam/Startup.cs new file mode 100644 index 0000000..9879731 --- /dev/null +++ b/modules/CombotAntiSpam/Startup.cs @@ -0,0 +1,18 @@ +using Kruzya.TelegramBot.CombotAntiSpam.Combot; +using Kruzya.TelegramBot.Core; +using Microsoft.Extensions.DependencyInjection; + +namespace Kruzya.TelegramBot.CombotAntiSpam +{ + public class Startup : Module + { + public Startup(Core.Core core) : base(core) + { + } + + public override void ConfigureServices(IServiceCollection services) + { + services.AddSingleton(); + } + } +} diff --git a/modules/CombotAntiSpam/UserJoinHandler.cs b/modules/CombotAntiSpam/UserJoinHandler.cs new file mode 100644 index 0000000..e085e1e --- /dev/null +++ b/modules/CombotAntiSpam/UserJoinHandler.cs @@ -0,0 +1,50 @@ +using System.Text; +using System.Threading.Tasks; +using BotFramework; +using BotFramework.Attributes; +using BotFramework.Setup; +using Kruzya.TelegramBot.CombotAntiSpam.Combot; +using Kruzya.TelegramBot.Core.Extensions; +using Microsoft.Extensions.Logging; +using Telegram.Bot.Types.Enums; + +namespace Kruzya.TelegramBot.CombotAntiSpam +{ + public class UserJoinHandler : BotEventHandler + { + protected ICombotClient _combotClient; + protected ILogger _logger; + + public UserJoinHandler(ICombotClient combotClient) + { + _combotClient = combotClient; + } + + [Message(MessageType.ChatMembersAdded, InChat.Public)] + public async Task OnUserJoined() + { + var canKickMembers = ((await Bot.GetChatMemberAsync(Chat, (await Bot.GetMeAsync()).Id)).CanRestrictMembers == true); + + foreach (var member in RawUpdate.Message.NewChatMembers) + { + if (!(await _combotClient.IsSpammerAsync(member))) + { + continue; + } + + var messageText = new StringBuilder(); + messageText.Append($"⚠️ Combot Anti-Spam\n\n"); + messageText.Append($"User {member.ToHtml()} is spammer.\n"); + messageText.Append( + $"More details you can find on CAS site."); + + await Bot.SendTextMessageAsync(Chat, messageText.ToString(), ParseMode.Html); + + if (canKickMembers) + { + await Bot.KickChatMemberAsync(Chat, member.Id); + } + } + } + } +} \ No newline at end of file