Skip to content

Commit

Permalink
Have added simple telegram api
Browse files Browse the repository at this point in the history
  • Loading branch information
shishnk committed Apr 13, 2024
1 parent ab52bda commit a832a8a
Show file tree
Hide file tree
Showing 75 changed files with 1,173 additions and 253 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ public class RegisterMapper : IRegister
public void Register(TypeAdapterConfig config)
{
config.NewConfig<UserWeatherSubscription, UserWeatherSubscriptionDto>()
.Map(dest => dest.Location, src => src.Location.Value);
.Map(dest => dest.Location, src => src.Location.Value)
.Map(dest => dest.ResendInterval, src => src.ResendInterval)
.Map(dest => dest.UserTelegramId, src => src.User.TelegramId);
config.NewConfig<User, UserDto>()
.Map(dest => dest.TelegramId, src => src.TelegramId)
.Map(dest => dest.MobileNumber, src => src.Metadata.MobileNumber)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace DatabaseApp.Application.UserWeatherSubscriptions.Commands.CreateUserWe

public class CreateUserWeatherSubscriptionCommand : IRequest<Result>
{
public int TelegramUserId { get; set; }
public required string Location { get; set; }
public TimeSpan ResendInterval { get; set; }
public long TelegramUserId { get; init; }
public required string Location { get; init; }
public TimeSpan ResendInterval { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,6 @@ namespace DatabaseApp.Application.UserWeatherSubscriptions.Commands.DeleteUserWe

public class DeleteUserWeatherSubscriptionCommand : IRequest<Result>
{
public int UserTelegramId { get; init; }
public long UserTelegramId { get; init; }
public required string Location { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ namespace DatabaseApp.Application.UserWeatherSubscriptions.Commands.UpdateUserWe

public class UpdateUserWeatherSubscriptionCommand : IRequest<Result>
{
public int UserTelegramId { get; init; }
public long UserTelegramId { get; init; }
public required string Location { get; init; }
public TimeSpan ResendInterval { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,5 +4,5 @@ namespace DatabaseApp.Application.UserWeatherSubscriptions.Queries.GetWeatherSub

public class GetUserWeatherSubscriptionsQuery : IRequest<List<UserWeatherSubscriptionDto>>
{
public int UserTelegramId { get; init; }
public long UserTelegramId { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,6 @@ public class UserWeatherSubscriptionDto
{
// ReSharper disable once UnusedAutoPropertyAccessor.Global
public required string Location { get; set; }
public int UserTelegramId { get; set; }
public TimeSpan ResendInterval { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@

namespace DatabaseApp.Application.Users.Commands.CreateUser;

public class CreateUserCommand : IRequest<Result<int>>
public class CreateUserCommand : IRequest<Result<long>>
{
public required int TelegramId { get; init; }
public required long TelegramId { get; init; }
public required string Username { get; init; }
public required string MobileNumber { get; init; }
public required DateTime RegisteredAt { get; init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,15 @@
namespace DatabaseApp.Application.Users.Commands.CreateUser;

// ReSharper disable once UnusedType.Global
public class CreateUserCommandHandler(IUserRepository repository) : IRequestHandler<CreateUserCommand, Result<int>>
public class CreateUserCommandHandler(IUserRepository repository) : IRequestHandler<CreateUserCommand, Result<long>>
{
public async Task<Result<int>> Handle(CreateUserCommand request, CancellationToken cancellationToken)
public async Task<Result<long>> Handle(CreateUserCommand request, CancellationToken cancellationToken)
{
var existingUser = await repository.GetByTelegramIdAsync(request.TelegramId, cancellationToken);

if (existingUser != null)
{
return Result.Fail<int>("User already exists");
return Result.Fail("User already exists");
}

var userMetadata = UserMetadata.Create(request.Username, request.MobileNumber);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
// ReSharper disable once ClassNeverInstantiated.Global
public class UserDto
{
public required int TelegramId { get; set; }
public required long TelegramId { get; set; }
public required string Username { get; set; }
public required string MobileNumber { get; set; }
public DateTime RegisteredAt { get; set; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
public class User : IEntity
{
public int Id { get; init; }
public int TelegramId { get; init; }
public long TelegramId { get; init; }
public required UserMetadata Metadata { get; init; }
public DateTime RegisteredAt { get; init; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,16 @@ public interface IRepository

public interface IUserRepository : IRepository
{
Task<User?> GetByTelegramIdAsync(int telegramId, CancellationToken cancellationToken);
Task<User?> GetByTelegramIdAsync(long telegramId, CancellationToken cancellationToken);
Task AddAsync(User user, CancellationToken cancellationToken);
Task<List<User>> GetAllAsync(CancellationToken cancellationToken);
}

public interface IWeatherSubscriptionRepository : IRepository
{
Task<List<UserWeatherSubscription>> GetAllByUserTelegramId(int userTelegramId, CancellationToken cancellationToken);
Task<List<UserWeatherSubscription>> GetAllByUserTelegramId(long userTelegramId, CancellationToken cancellationToken);

Task<UserWeatherSubscription?> GetByUserTelegramIdAndLocationAsync(int userTelegramId, Location location,
Task<UserWeatherSubscription?> GetByUserTelegramIdAndLocationAsync(long userTelegramId, Location location,
CancellationToken cancellationToken);

Task AddAsync(UserWeatherSubscription weatherSubscription, CancellationToken cancellationToken);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
using DatabaseApp.IntegrationEvents.IntegrationEventHandlers;
using DatabaseApp.IntegrationEvents.IntegrationEventHandlers.UserIntegrationEventHandlers;
using DatabaseApp.IntegrationEvents.IntegrationEventHandlers.UserSubscriptionEventHandlers;
using Microsoft.AspNetCore.Builder;
using Microsoft.Extensions.DependencyInjection;
using TelegramBotApp.Messaging;
using TelegramBotApp.Messaging.IntegrationContext.UserIntegrationEvents;
using TelegramBotApp.Messaging.IntegrationContext.UserSubscriptionEvents;

namespace DatabaseApp.IntegrationEvents;

Expand All @@ -12,8 +15,13 @@ public static class EventBusExtensions
public static IApplicationBuilder SubscribeToEvents(this IApplicationBuilder app)
{
var eventBus = app.ApplicationServices.GetRequiredService<IEventBus>();

eventBus.Subscribe<GetAllUsersRequestIntegrationEvent, GetAllUsersRequestIntegrationEventHandler>();

eventBus.Subscribe<CacheRequestUsersIntegrationEvent, CacheRequestUsersIntegrationEventHandler>();
eventBus.Subscribe<CacheRequestUserSubscriptionsIntegrationEvent, CacheRequestUserSubscriptionsIntegrationEventHandler>();
eventBus.Subscribe<CreatedUserIntegrationEvent, CreatedUserIntegrationEventHandler>();
eventBus.Subscribe<CreatedUserSubscriptionIntegrationEvent, CreatedUserSubscriptionIntegrationEventHandler>();
eventBus.Subscribe<UpdatedUserSubscriptionIntegrationEvent, UpdatedUserSubscriptionIntegrationEventHandler>();
eventBus.Subscribe<DeletedUserSubscriptionIntegrationEvent, DeletedUserSubscriptionIntegrationEventHandler>();

return app;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
using DatabaseApp.Application.Users.Commands.CreateUser;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using TelegramBotApp.Caching.Caching;
using TelegramBotApp.Messaging.IntegrationContext;
using TelegramBotApp.Messaging.IntegrationContext.UserIntegrationEvents;
using TelegramBotApp.Messaging.IntegrationResponseContext.IntegrationResponses;

namespace DatabaseApp.IntegrationEvents.IntegrationEventHandlers.UserIntegrationEventHandlers;

public class CreatedUserIntegrationEventHandler(IServiceScopeFactory factory, ICacheService cacheService)
: IIntegrationEventHandler<CreatedUserIntegrationEvent>
{
public async Task<IResponseMessage> Handle(CreatedUserIntegrationEvent @event)
{
using var scope = factory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
var result = await mediator.Send(new CreateUserCommand
{
TelegramId = @event.UserTelegramId, // TODO
Username = @event.Username,
MobileNumber = @event.MobileNumber,
RegisteredAt = @event.RegisteredAt
});

if (!result.IsSuccess) return UniversalResponse.Empty;

var allUsers = await cacheService.GetAsync<List<long>>("allUsers");
await cacheService.RemoveAsync("allUsers");

allUsers ??= [];
allUsers.Add(@event.UserTelegramId);

await cacheService.SetAsync("allUsers", allUsers);

return UniversalResponse.Empty;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
using DatabaseApp.Application.Users.Queries.GetAllUsers;
using DatabaseApp.Application.UserWeatherSubscriptions.Queries.GetWeatherSubscriptions;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using TelegramBotApp.Caching.Caching;
using TelegramBotApp.Messaging.Common;
using TelegramBotApp.Messaging.IntegrationContext;
using TelegramBotApp.Messaging.IntegrationContext.UserIntegrationEvents;
using TelegramBotApp.Messaging.IntegrationResponseContext.IntegrationResponses;

namespace DatabaseApp.IntegrationEvents.IntegrationEventHandlers.UserSubscriptionEventHandlers;

public class CacheRequestUserSubscriptionsIntegrationEventHandler(
IServiceScopeFactory factory,
ICacheService cacheService)
: IIntegrationEventHandler<CacheRequestUserSubscriptionsIntegrationEvent>
{
public async Task<IResponseMessage> Handle(CacheRequestUserSubscriptionsIntegrationEvent @event)
{
using var scope = factory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();
List<UserSubscriptionInfo> subscriptionInfos = [];
var userTelegramIds = await cacheService.GetAsync<List<long>>("allUsers");

if (userTelegramIds is null)
{
var userDtos = await mediator.Send(new GetAllUsersQuery());
userTelegramIds = userDtos.Select(dto => dto.TelegramId).ToList();
await cacheService.SetAsync("allUsers", userTelegramIds);
}

foreach (var telegramId in userTelegramIds)
{
var userSubscription = await mediator.Send(new GetUserWeatherSubscriptionsQuery
{
UserTelegramId = telegramId
});

if (userSubscription.Count == 0) continue;

subscriptionInfos.AddRange(userSubscription.Select(subscriptionDto => new UserSubscriptionInfo
{
TelegramId = subscriptionDto.UserTelegramId,
ResendInterval = subscriptionDto.ResendInterval,
Location = subscriptionDto.Location
}));
}

await cacheService.RemoveAsync("allSubscriptions");
await cacheService.SetAsync("allSubscriptions", subscriptionInfos);

return UniversalResponse.Empty;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
using DatabaseApp.Application.UserWeatherSubscriptions.Commands.CreateUserWeatherSubscription;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using TelegramBotApp.Caching.Caching;
using TelegramBotApp.Messaging.Common;
using TelegramBotApp.Messaging.IntegrationContext;
using TelegramBotApp.Messaging.IntegrationContext.UserSubscriptionEvents;
using TelegramBotApp.Messaging.IntegrationResponseContext.IntegrationResponses;

namespace DatabaseApp.IntegrationEvents.IntegrationEventHandlers.UserSubscriptionEventHandlers;

public class CreatedUserSubscriptionIntegrationEventHandler(IServiceScopeFactory factory, ICacheService cacheService)
: IIntegrationEventHandler<CreatedUserSubscriptionIntegrationEvent>
{
public async Task<IResponseMessage> Handle(CreatedUserSubscriptionIntegrationEvent @event)
{
using var scope = factory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();

var result = await mediator.Send(new CreateUserWeatherSubscriptionCommand
{
Location = @event.City,
ResendInterval = @event.ResendInterval,
TelegramUserId = @event.TelegramId
});

if (result.IsFailed) return new UniversalResponse(result.Errors.First().Message);

var allSubscriptions = await cacheService.GetAsync<List<UserSubscriptionInfo>>("allSubscriptions");
await cacheService.RemoveAsync("allSubscriptions");

allSubscriptions ??= [];

allSubscriptions.Add(new()
{
ResendInterval = @event.ResendInterval,
Location = @event.City,
TelegramId = @event.TelegramId
});
await cacheService.SetAsync("allSubscriptions", allSubscriptions);

return new UniversalResponse("Subscription created successfully");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
using DatabaseApp.Application.UserWeatherSubscriptions.Commands.DeleteUserWeatherSubscription;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using TelegramBotApp.Caching.Caching;
using TelegramBotApp.Messaging.Common;
using TelegramBotApp.Messaging.IntegrationContext;
using TelegramBotApp.Messaging.IntegrationContext.UserSubscriptionEvents;
using TelegramBotApp.Messaging.IntegrationResponseContext.IntegrationResponses;

namespace DatabaseApp.IntegrationEvents.IntegrationEventHandlers.UserSubscriptionEventHandlers;

public class DeletedUserSubscriptionIntegrationEventHandler(IServiceScopeFactory factory, ICacheService cacheService)
: IIntegrationEventHandler<DeletedUserSubscriptionIntegrationEvent>
{
public async Task<IResponseMessage> Handle(DeletedUserSubscriptionIntegrationEvent @event)
{
using var scope = factory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();

var result = await mediator.Send(new DeleteUserWeatherSubscriptionCommand
{
UserTelegramId = @event.TelegramUserId,
Location = @event.Location
});

if (result.IsFailed) return new UniversalResponse(result.Errors.First().Message);

var allSubscriptions = await cacheService.GetAsync<List<UserSubscriptionInfo>>("allSubscriptions");
await cacheService.RemoveAsync("allSubscriptions");

allSubscriptions ??= [];

allSubscriptions.RemoveAll(x =>
x.TelegramId == @event.TelegramUserId && x.Location == @event.Location);

await cacheService.SetAsync("allSubscriptions", allSubscriptions);

return new UniversalResponse("Subscription deleted successfully");
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using DatabaseApp.Application.UserWeatherSubscriptions.Commands.UpdateUserWeatherSubscription;
using MediatR;
using Microsoft.Extensions.DependencyInjection;
using TelegramBotApp.Caching.Caching;
using TelegramBotApp.Messaging.Common;
using TelegramBotApp.Messaging.IntegrationContext;
using TelegramBotApp.Messaging.IntegrationContext.UserSubscriptionEvents;
using TelegramBotApp.Messaging.IntegrationResponseContext.IntegrationResponses;

namespace DatabaseApp.IntegrationEvents.IntegrationEventHandlers.UserSubscriptionEventHandlers;

public class UpdatedUserSubscriptionIntegrationEventHandler(IServiceScopeFactory factory, ICacheService cacheService)
: IIntegrationEventHandler<UpdatedUserSubscriptionIntegrationEvent>
{
public async Task<IResponseMessage> Handle(UpdatedUserSubscriptionIntegrationEvent @event)
{
using var scope = factory.CreateScope();
var mediator = scope.ServiceProvider.GetRequiredService<IMediator>();

var result = await mediator.Send(new UpdateUserWeatherSubscriptionCommand
{
Location = @event.Location,
ResendInterval = @event.ResendInterval,
UserTelegramId = @event.TelegramUserId
});

if (result.IsFailed) return new UniversalResponse(result.Errors.First().Message);

var allSubscriptions = await cacheService.GetAsync<List<UserSubscriptionInfo>>("allSubscriptions");
await cacheService.RemoveAsync("allSubscriptions");

allSubscriptions ??= [];

allSubscriptions.RemoveAll(x =>
x.TelegramId == @event.TelegramUserId && x.Location == @event.Location);

allSubscriptions.Add(new()
{
ResendInterval = @event.ResendInterval,
Location = @event.Location,
TelegramId = @event.TelegramUserId
});
await cacheService.SetAsync("allSubscriptions", allSubscriptions);

return new UniversalResponse("Subscription updated successfully");
}
}
Loading

0 comments on commit a832a8a

Please sign in to comment.