diff --git a/Core/Extensions/RepositoryExtension.cs b/Core/Extensions/RepositoryExtension.cs index 98bafd4..3b9c4f7 100644 --- a/Core/Extensions/RepositoryExtension.cs +++ b/Core/Extensions/RepositoryExtension.cs @@ -1,4 +1,6 @@ -using Microsoft.EntityFrameworkCore; +using System.Threading.Tasks; +using Kruzya.TelegramBot.Core.Data; +using Microsoft.EntityFrameworkCore; namespace Kruzya.TelegramBot.Core.Extensions { @@ -43,5 +45,67 @@ namespace Kruzya.TelegramBot.Core.Extensions } #endregion + + #region Core-context repository extensions + + #region BotUserValue + + #region FindOption + + public static async Task FindOption(this DbSet repository, long chatId, + string option) => await repository.FindOption(chatId, 0, option); + + public static async Task FindOption(this DbSet repository, BotUser user, + string option) => await repository.FindOption(user.ChatId, user.UserId, option); + + public static async Task FindOption(this DbSet repository, long chatId, int userId, + string option) => await repository.SingleOrDefaultAsync(e => + e.BotUser.ChatId == chatId && e.BotUser.UserId == userId && e.Name == option); + + #endregion + + #region FindOrCreateOption + + public static async Task FindOrCreateOption(this DbSet repository, long chatId, + string option) => await repository.FindOrCreateOption(chatId, 0, option); + + public static async Task FindOrCreateOption(this DbSet repository, BotUser user, + string option) => await repository.FindOrCreateOption(user.ChatId, user.UserId, option); + + public static async Task FindOrCreateOption(this DbSet repository, long chatId, + int userId, string option) + { + var opt = await repository.FindOption(chatId, userId, option); + if (opt == null) + { + opt = repository.Create(); + } + + return opt; + } + + #endregion + + #region SetOptionValue + + public static async Task SetOptionValue(this DbSet repository, long chatId, string option, + T val) => await repository.SetOptionValue(chatId, 0, option, val); + + public static async Task SetOptionValue(this DbSet repository, BotUser user, string option, + T val) => await repository.SetOptionValue(user.ChatId, user.UserId, option, val); + + public static async Task SetOptionValue(this DbSet repository, long chatId, int userId, + string option, T val) + { + var opt = await repository.FindOrCreateOption(chatId, userId, option); + opt.SetValue(val); + repository.Update(opt); + } + + #endregion + + #endregion + + #endregion } } \ No newline at end of file diff --git a/modules/UrlLimitations/Data/ChatMember.cs b/modules/UrlLimitations/Data/ChatMember.cs deleted file mode 100644 index cc8d906..0000000 --- a/modules/UrlLimitations/Data/ChatMember.cs +++ /dev/null @@ -1,19 +0,0 @@ -using Telegram.Bot.Types; - -namespace Kruzya.TelegramBot.UrlLimitations -{ - public struct ChatMember - { - public long Chat; - public long User; - - public static ChatMember From(long chatId, long userId) - { - return new ChatMember() - { - Chat = chatId, - User = userId - }; - } - } -} \ No newline at end of file diff --git a/modules/UrlLimitations/Data/UrlLimitationsContext.cs b/modules/UrlLimitations/Data/UrlLimitationsContext.cs deleted file mode 100644 index de64347..0000000 --- a/modules/UrlLimitations/Data/UrlLimitationsContext.cs +++ /dev/null @@ -1,7 +0,0 @@ -namespace Kruzya.TelegramBot.UrlLimitations -{ - public class UrlLimitationsContext - { - - } -} \ No newline at end of file diff --git a/modules/UrlLimitations/MessageExtension.cs b/modules/UrlLimitations/MessageExtension.cs new file mode 100644 index 0000000..e2ce906 --- /dev/null +++ b/modules/UrlLimitations/MessageExtension.cs @@ -0,0 +1,64 @@ +using System; +using System.Linq; +using System.Threading.Tasks; +using BotFramework; +using Telegram.Bot; +using Telegram.Bot.Types; +using Telegram.Bot.Types.Enums; + +namespace Kruzya.TelegramBot.UrlLimitations +{ + public static class MessageExtension + { + public static async Task HasUnknownMention(this Message message, ITelegramBotClient bot) + { + foreach (var mention in message.Entities.Where(e => + e.Type == MessageEntityType.Mention || e.Type == MessageEntityType.TextMention)) + { + var userId = 0; + if (mention.Type == MessageEntityType.TextMention) + { + userId = mention.User.Id; + } + else + { + try + { + var chat = await bot.GetChatAsync( + new ChatId(message.Text.Substring(mention.Offset, mention.Length))); + + if (chat != null) + { + if (chat.Type != ChatType.Private) + { + return true; + } + + userId = Convert.ToInt32(chat.Id); + } + } + catch (Exception e) + { + return true; + } + } + + var status = (await bot.GetChatMemberAsync(message.Chat, userId)).Status; + + if ((new ChatMemberStatus[] + { + ChatMemberStatus.Administrator, ChatMemberStatus.Creator, ChatMemberStatus.Member, + ChatMemberStatus.Restricted + + // i'm not sure about "Restricted" + // maybe leaved members with some restrictions also can be "Restricted". + }).Any(e => e == status) == false) + { + return true; + } + } + + return false; + } + } +} \ No newline at end of file diff --git a/modules/UrlLimitations/MessageHandler.cs b/modules/UrlLimitations/MessageHandler.cs index a987b1c..7f18a5f 100644 --- a/modules/UrlLimitations/MessageHandler.cs +++ b/modules/UrlLimitations/MessageHandler.cs @@ -5,6 +5,7 @@ using BotFramework; using BotFramework.Attributes; using BotFramework.Setup; using Kruzya.TelegramBot.Core.Cache; +using Kruzya.TelegramBot.Core.Data; using Kruzya.TelegramBot.Core.Extensions; using Microsoft.Extensions.Logging; using Telegram.Bot.Types; @@ -15,35 +16,34 @@ namespace Kruzya.TelegramBot.UrlLimitations public class MessageHandler : BotEventHandler { protected ILogger Logger; - protected MemoryCache ChatMembersCache; + protected readonly CoreContext dbCtx; - public MessageHandler(ILogger logger, MemoryCache chatMembersCache) + public MessageHandler(ILogger logger, CoreContext coreContext) { Logger = logger; - ChatMembersCache = chatMembersCache; + dbCtx = coreContext; } [TextMessage(InChat.Public)] - public void OnMessageReceived() + public async Task OnMessageReceived() { - UInt16 messageCount; - var chatMember = ChatMember.From(Chat.Id, From.Id); - if (!ChatMembersCache.TryGetValue(chatMember, out messageCount)) + var option = await dbCtx.UserValues.FindOption(Chat.Id, From.Id, "urlLimitations.messagesAfterJoin"); + if (option == null) { return; } + var messageCount = option.GetValue(); if (messageCount > 10) { - ChatMembersCache.SetValue(chatMember, 0, 0); + dbCtx.UserValues.Remove(option); return; } - messageCount++; - ChatMembersCache.SetValue(chatMember, messageCount); + option.SetValue(messageCount + 1); var message = RawUpdate.Message; if (message.Entities.Count(e => e.Type == MessageEntityType.Url || e.Type == MessageEntityType.TextLink) > - 0) + 0 || await message.HasUnknownMention(Bot)) { var targetChat = new ChatId(Chat.Id); Task.WaitAll(new Task[] { diff --git a/modules/UrlLimitations/UrlLimitations.cs b/modules/UrlLimitations/UrlLimitations.cs index e0158da..0ce910f 100644 --- a/modules/UrlLimitations/UrlLimitations.cs +++ b/modules/UrlLimitations/UrlLimitations.cs @@ -1,5 +1,6 @@ using System; using Kruzya.TelegramBot.Core; +using Kruzya.TelegramBot.Core.Data; using Kruzya.TelegramBot.Core.Extensions; using Microsoft.Extensions.DependencyInjection; @@ -10,10 +11,5 @@ namespace Kruzya.TelegramBot.UrlLimitations public UrlLimitations(Core.Core core) : base(core) { } - - public override void ConfigureServices(IServiceCollection services) - { - services.AddMemoryCache(); - } } } \ No newline at end of file diff --git a/modules/UrlLimitations/UserJoinHandler.cs b/modules/UrlLimitations/UserJoinHandler.cs index 98bd0ff..bb293f1 100644 --- a/modules/UrlLimitations/UserJoinHandler.cs +++ b/modules/UrlLimitations/UserJoinHandler.cs @@ -1,25 +1,30 @@ using System; +using System.Threading.Tasks; using BotFramework; using BotFramework.Attributes; using BotFramework.Setup; using Kruzya.TelegramBot.Core.Cache; +using Kruzya.TelegramBot.Core.Data; +using Kruzya.TelegramBot.Core.Extensions; using Telegram.Bot.Types.Enums; namespace Kruzya.TelegramBot.UrlLimitations { public class UserJoinHandler : BotEventHandler { - protected MemoryCache ChatMembersCache; + protected readonly CoreContext dbCtx; - public UserJoinHandler(MemoryCache chatMembersCache) + public UserJoinHandler(CoreContext coreContext) { - ChatMembersCache = chatMembersCache; + dbCtx = coreContext; } [Message(MessageType.ChatMembersAdded, InChat.Public)] - public void OnChatMembersAdded() + public async Task OnChatMembersAdded() { - ChatMembersCache.SetValue(ChatMember.From(Chat.Id, From.Id), 0); + foreach (var member in RawUpdate.Message.NewChatMembers) + await dbCtx.UserValues.SetOptionValue(Chat.Id, member.Id, "urlLimitations.messagesAfterJoin", + 0); } } } \ No newline at end of file