Update sync contracts
This commit is contained in:
parent
6fd1ae7c80
commit
367b13e175
@ -6,12 +6,12 @@ public sealed class TextMatchData
|
||||
|
||||
public long UserId { get; set; }
|
||||
|
||||
public long? ChatId { get; set; }
|
||||
|
||||
public string ChatUsername { get; set; }
|
||||
|
||||
public string Template { get; set; }
|
||||
|
||||
public bool Active { get; set; }
|
||||
|
||||
public TextMatchRule Rule { get; set; }
|
||||
|
||||
public DateTimeOffset CreatedDateTime { get; set; }
|
||||
|
||||
@ -10,6 +10,18 @@ public interface ITextMatchesController
|
||||
[Post]
|
||||
Task<long> Create([Body] CreateTextMatchRequest request, CancellationToken cancellationToken = default);
|
||||
|
||||
[Get(WebRoutes.TextMatches.ById)]
|
||||
Task<TextMatchData> GetById([Path] long id, CancellationToken cancellationToken = default);
|
||||
|
||||
[Get(WebRoutes.TextMatches.ByUserId)]
|
||||
Task<TextMatchData[]> GetByUserId([Path] long userId, CancellationToken cancellationToken = default);
|
||||
|
||||
[Delete(WebRoutes.TextMatches.ById)]
|
||||
public Task Delete([Path] long id, CancellationToken cancellationToken = default);
|
||||
|
||||
[Patch(WebRoutes.TextMatches.Activate)]
|
||||
Task Activate([Path] long id, CancellationToken cancellationToken = default);
|
||||
|
||||
[Patch(WebRoutes.TextMatches.Disable)]
|
||||
Task Disable([Path] long id, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@ -4,8 +4,6 @@ public class CreateTextMatchRequest
|
||||
{
|
||||
public long UserId { get; set; }
|
||||
|
||||
public long? ChatId { get; set; }
|
||||
|
||||
public string ChatUsername { get; set; }
|
||||
|
||||
public string Template { get; set; }
|
||||
|
||||
@ -9,5 +9,11 @@ public static class WebRoutes
|
||||
public const string Path = BasePath + "/" + "text-matches";
|
||||
|
||||
public const string ByUserId = "by-user-id/{userId}";
|
||||
|
||||
public const string Activate = ById + "/" + "activate";
|
||||
|
||||
public const string Disable = ById + "/" + "disable";
|
||||
|
||||
public const string ById = "{id}";
|
||||
}
|
||||
}
|
||||
@ -1,6 +1,6 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Nocr.TelegramListener.Async.Api.Contracts.Events;
|
||||
using Nocr.TextMatcher.AppServices.TextMatches.Services;
|
||||
using Nocr.TextMatcher.AppServices.TextMatches.Repositories;
|
||||
using Nocr.TextMatcher.Async.Api.Contracts;
|
||||
using Nocr.TextMatcher.Core.Dates;
|
||||
using Rebus.Bus;
|
||||
@ -12,17 +12,17 @@ public sealed class MessageReceivedHandler : IHandleMessages<MessageReceived>
|
||||
{
|
||||
private readonly ILogger<MessageReceivedHandler> _logger;
|
||||
private readonly IBus _bus;
|
||||
private readonly ITextMatchService _textMatchService;
|
||||
private readonly ITextMatchRepository _textMatchService;
|
||||
private readonly ICurrentDateProvider _dateProvider;
|
||||
|
||||
public MessageReceivedHandler(ILogger<MessageReceivedHandler> logger,
|
||||
IBus bus,
|
||||
ITextMatchService textMatchService,
|
||||
ITextMatchRepository textMatchRepository,
|
||||
ICurrentDateProvider dateProvider)
|
||||
{
|
||||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||||
_bus = bus ?? throw new ArgumentNullException(nameof(bus));
|
||||
_textMatchService = textMatchService ?? throw new ArgumentNullException(nameof(textMatchService));
|
||||
_textMatchService = textMatchRepository ?? throw new ArgumentNullException(nameof(textMatchRepository));
|
||||
_dateProvider = dateProvider ?? throw new ArgumentNullException(nameof(dateProvider));
|
||||
}
|
||||
|
||||
@ -32,17 +32,15 @@ public sealed class MessageReceivedHandler : IHandleMessages<MessageReceived>
|
||||
|
||||
var matches = await _textMatchService.Get();
|
||||
|
||||
foreach (var match in matches)
|
||||
foreach (var match in matches.Where(x => x.Active))
|
||||
{
|
||||
if (match.IsMatches(message.ChatId, message.ChatUsername, message.Text))
|
||||
if (match.IsMatches(message.ChatUsername, message.Text))
|
||||
{
|
||||
_logger.LogInformation("Message {@Message} matched {@Match}", message, match);
|
||||
var @event = new TextMatchMatched
|
||||
{
|
||||
ChatId = message.ChatId,
|
||||
ChatUsername = message.ChatUsername,
|
||||
Text = message.Text,
|
||||
UserId = message.From,
|
||||
MatchId = match.Id,
|
||||
MatchUserId = match.UserId,
|
||||
OccuredDateTime = message.OccuredDateTime,
|
||||
PublishedDateTime = _dateProvider.UtcNow
|
||||
};
|
||||
|
||||
@ -9,4 +9,8 @@ public interface ITextMatchRepository
|
||||
Task<IReadOnlyCollection<TextMatch>> Get(CancellationToken cancellationToken = default);
|
||||
|
||||
Task<IReadOnlyCollection<TextMatch>> GetByUserId(long userId, CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TextMatch?> GetById(long id, CancellationToken cancellationToken = default);
|
||||
|
||||
Task Update(TextMatch textMatch, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@ -1,5 +1,4 @@
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches;
|
||||
using Nocr.TextMatcher.Api.Contracts.TextMatches.Dto;
|
||||
|
||||
namespace Nocr.TextMatcher.AppServices.TextMatches.Repositories;
|
||||
|
||||
@ -49,4 +48,14 @@ public sealed class InMemoryTextMatchRepository : ITextMatchRepository
|
||||
{
|
||||
return Task.FromResult<IReadOnlyCollection<TextMatch>>(_textMatches.Where(x => x.UserId == userId).ToArray());
|
||||
}
|
||||
|
||||
public Task<TextMatch?> GetById(long id, CancellationToken cancellationToken)
|
||||
{
|
||||
return Task.FromResult(_textMatches.FirstOrDefault(x => x.Id == id));
|
||||
}
|
||||
|
||||
public Task Update(TextMatch textMatch, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
@ -5,12 +5,18 @@ namespace Nocr.TextMatcher.AppServices.TextMatches.Services;
|
||||
|
||||
public interface ITextMatchService
|
||||
{
|
||||
Task<long> Create(long userId, string chatUsername, string template, TextMatchRule rule, long? chatId = null,
|
||||
Task<long> Create(long userId, string chatUsername, string template, TextMatchRule rule,
|
||||
CancellationToken cancellationToken = default);
|
||||
|
||||
Task<TextMatchData?> GetById(long id, CancellationToken cancellationToken = default);
|
||||
|
||||
Task Delete(long id, CancellationToken cancellationToken = default);
|
||||
|
||||
Task<IReadOnlyCollection<TextMatch>> Get(CancellationToken cancellationToken = default);
|
||||
|
||||
Task<IReadOnlyCollection<TextMatchData>> GetByUserId(long userId, CancellationToken cancellationToken);
|
||||
Task Activate(long id, CancellationToken cancellationToken = default);
|
||||
|
||||
Task Disable(long id, CancellationToken cancellationToken = default);
|
||||
|
||||
Task<IReadOnlyCollection<TextMatchData>> Get(CancellationToken cancellationToken = default);
|
||||
|
||||
Task<IReadOnlyCollection<TextMatchData>> GetByUserId(long userId, CancellationToken cancellationToken = default);
|
||||
}
|
||||
@ -21,10 +21,10 @@ public sealed class TextMatchService : ITextMatchService
|
||||
_dateProvider = dateProvider ?? throw new ArgumentNullException(nameof(dateProvider));
|
||||
}
|
||||
|
||||
public async Task<long> Create(long userId, string chatUsername, string template, TextMatchRule rule, long? chatId = null,
|
||||
public async Task<long> Create(long userId, string chatUsername, string template, TextMatchRule rule,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var textMatch = TextMatch.Initialize(userId, chatUsername, template, rule, _dateProvider.UtcNow, chatId);
|
||||
var textMatch = TextMatch.Initialize(userId, chatUsername, template, rule, _dateProvider.UtcNow);
|
||||
await _repository.Create(textMatch, cancellationToken);
|
||||
|
||||
var @event = new TextMatchCreated
|
||||
@ -38,28 +38,71 @@ public sealed class TextMatchService : ITextMatchService
|
||||
return textMatch.Id;
|
||||
}
|
||||
|
||||
public async Task<TextMatchData?> GetById(long id, CancellationToken cancellationToken)
|
||||
{
|
||||
var textMatch = await _repository.GetById(id, cancellationToken);
|
||||
if (textMatch == null)
|
||||
return null;
|
||||
|
||||
return MapToTextMatchData(textMatch);
|
||||
}
|
||||
|
||||
public Task Delete(long id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _repository.Delete(id, cancellationToken);
|
||||
}
|
||||
|
||||
public Task<IReadOnlyCollection<TextMatch>> Get(CancellationToken cancellationToken = default)
|
||||
public async Task Activate(long id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _repository.Get(cancellationToken);
|
||||
var textMatch = await _repository.GetById(id, cancellationToken);
|
||||
if (textMatch == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Match with id {id} not found");
|
||||
}
|
||||
|
||||
textMatch.Activate();
|
||||
|
||||
await _repository.Update(textMatch, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyCollection<TextMatchData>> GetByUserId(long userId, CancellationToken cancellationToken = default)
|
||||
public async Task Disable(long id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
var textMatch = await _repository.GetById(id, cancellationToken);
|
||||
if (textMatch == null)
|
||||
{
|
||||
throw new InvalidOperationException($"Match with id {id} not found");
|
||||
}
|
||||
|
||||
textMatch.Disable();
|
||||
|
||||
await _repository.Update(textMatch, cancellationToken);
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyCollection<TextMatchData>> Get(CancellationToken cancellationToken = default)
|
||||
{
|
||||
var matches = await _repository.Get(cancellationToken);
|
||||
|
||||
return matches.Select(MapToTextMatchData).ToArray();
|
||||
}
|
||||
|
||||
public async Task<IReadOnlyCollection<TextMatchData>> GetByUserId(long userId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
var matches = await _repository.GetByUserId(userId, cancellationToken);
|
||||
return matches.Select(x => new TextMatchData
|
||||
return matches.Select(MapToTextMatchData).ToArray();
|
||||
}
|
||||
|
||||
private TextMatchData MapToTextMatchData(TextMatch textMatch)
|
||||
{
|
||||
return new TextMatchData
|
||||
{
|
||||
Id = x.Id,
|
||||
ChatId = x.ChatId,
|
||||
ChatUsername = x.ChatUsername,
|
||||
Template = x.Template,
|
||||
UserId = x.UserId,
|
||||
Rule = x.Rule,
|
||||
CreatedDateTime = x.CreatedDateTime
|
||||
}).ToArray();
|
||||
Id = textMatch.Id,
|
||||
ChatUsername = textMatch.ChatUsername,
|
||||
Active = textMatch.Active,
|
||||
Template = textMatch.Template,
|
||||
UserId = textMatch.UserId,
|
||||
Rule = textMatch.Rule,
|
||||
CreatedDateTime = textMatch.CreatedDateTime
|
||||
};
|
||||
}
|
||||
}
|
||||
@ -9,14 +9,14 @@ public sealed class TextMatch
|
||||
|
||||
public long UserId { get; private set; }
|
||||
|
||||
public long? ChatId { get; private set; }
|
||||
|
||||
public string ChatUsername { get; private set; }
|
||||
|
||||
public string Template { get; private set; }
|
||||
|
||||
public TextMatchRule Rule { get; private set; }
|
||||
|
||||
public bool Active { get; private set; }
|
||||
|
||||
public DateTimeOffset CreatedDateTime { get; private set; }
|
||||
|
||||
private TextMatch(long userId,
|
||||
@ -24,41 +24,60 @@ public sealed class TextMatch
|
||||
string template,
|
||||
TextMatchRule rule,
|
||||
DateTimeOffset createdDateTime,
|
||||
long? chatId)
|
||||
bool active)
|
||||
{
|
||||
UserId = userId;
|
||||
ChatUsername = chatUsername;
|
||||
Template = template;
|
||||
Rule = rule;
|
||||
CreatedDateTime = createdDateTime;
|
||||
ChatId = chatId;
|
||||
Active = active;
|
||||
}
|
||||
|
||||
public static TextMatch Initialize(long userId,
|
||||
string chatUsername,
|
||||
string template,
|
||||
TextMatchRule rule,
|
||||
DateTimeOffset createdDateTime,
|
||||
long? chatId = null)
|
||||
DateTimeOffset createdDateTime)
|
||||
{
|
||||
if (userId <= 0)
|
||||
throw new ArgumentException("User id should be greater tha 0", nameof(userId));
|
||||
|
||||
if (chatId is <= 0)
|
||||
throw new ArgumentException("Chat id should be greater tha 0", nameof(chatId));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(template))
|
||||
throw new ArgumentException("Template should not be empty", nameof(template));
|
||||
|
||||
if (string.IsNullOrWhiteSpace(chatUsername))
|
||||
throw new ArgumentException("Chat username should not be empty", nameof(chatUsername));
|
||||
|
||||
return new TextMatch(userId, chatUsername, template, rule, createdDateTime,chatId);
|
||||
if (chatUsername.StartsWith("@"))
|
||||
throw new ArgumentException("Chat username should be without @", nameof(chatUsername));
|
||||
|
||||
return new TextMatch(userId, chatUsername, template, rule, createdDateTime, true);
|
||||
}
|
||||
|
||||
public bool IsMatches(long chatId, string chatUsername, string text)
|
||||
public void Disable()
|
||||
{
|
||||
if (ChatId.HasValue && ChatId != chatId && !string.Equals(ChatUsername, chatUsername, StringComparison.OrdinalIgnoreCase))
|
||||
if (Active == false)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to disable inactive match");
|
||||
}
|
||||
|
||||
Active = false;
|
||||
}
|
||||
|
||||
public void Activate()
|
||||
{
|
||||
if (Active == true)
|
||||
{
|
||||
throw new InvalidOperationException("Failed to activate inactive match");
|
||||
}
|
||||
|
||||
Active = true;
|
||||
}
|
||||
|
||||
public bool IsMatches(string chatUsername, string text)
|
||||
{
|
||||
if (!string.Equals(ChatUsername, chatUsername, StringComparison.OrdinalIgnoreCase))
|
||||
return false;
|
||||
|
||||
switch (Rule)
|
||||
|
||||
@ -4,13 +4,9 @@ public class TextMatchMatched : IEvent
|
||||
{
|
||||
public Guid Id => Guid.NewGuid();
|
||||
|
||||
public long UserId { get; set; }
|
||||
public long MatchId { get; set; }
|
||||
|
||||
public long? ChatId { get; set; }
|
||||
|
||||
public string ChatUsername { get; set; } = null!;
|
||||
|
||||
public string Text { get; set; }
|
||||
public long MatchUserId { get; set; }
|
||||
|
||||
public DateTimeOffset OccuredDateTime { get; set; }
|
||||
|
||||
|
||||
@ -20,13 +20,38 @@ public class TextMatchController : ControllerBase
|
||||
[HttpPost]
|
||||
public Task<long> Create([FromBody] CreateTextMatchRequest request, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _textMatchService.Create(request.UserId, request.ChatUsername, request.Template, request.Rule,
|
||||
request.ChatId, cancellationToken);
|
||||
return _textMatchService.Create(request.UserId, request.ChatUsername, request.Template, request.Rule, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet(WebRoutes.TextMatches.ById)]
|
||||
public Task<TextMatchData?> GetById([FromRoute] long id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _textMatchService.GetById(id, cancellationToken);
|
||||
}
|
||||
|
||||
|
||||
[HttpDelete(WebRoutes.TextMatches.ById)]
|
||||
public Task Delete([FromRoute] long id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _textMatchService.Delete(id, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpGet(WebRoutes.TextMatches.ByUserId)]
|
||||
public Task<IReadOnlyCollection<TextMatchData>> GetByUserId([FromRoute] long userId, CancellationToken cancellationToken = default)
|
||||
public Task<IReadOnlyCollection<TextMatchData>> GetByUserId([FromRoute] long userId,
|
||||
CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _textMatchService.GetByUserId(userId, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPatch(WebRoutes.TextMatches.Activate)]
|
||||
public Task Activate([FromRoute] long id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _textMatchService.Activate(id, cancellationToken);
|
||||
}
|
||||
|
||||
[HttpPatch(WebRoutes.TextMatches.Disable)]
|
||||
public Task Disable([FromRoute] long id, CancellationToken cancellationToken = default)
|
||||
{
|
||||
return _textMatchService.Disable(id, cancellationToken);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user