Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement meeting service #7

Open
wants to merge 7 commits into
base: stage
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions src/Api/Apis/Meetings/Contracts/CreateMeetingContract.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
namespace Api.Apis.Meetings.Contracts;

public record CreateMeetingContract
{
public required string Name { get; set; }
public required string Agenda { get; set; }
public required DateTime Date { get; set; }
}
29 changes: 29 additions & 0 deletions src/Api/Apis/Meetings/CreateMeeting.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using Api.Abstractions;
using Api.Apis.Meetings.Contracts;
using Api.Extensions;
using Domain.Entities.Meeting;
using Domain.Primitives;
using UseCases.Features.Meetings.Create;
using UseCases.Features.Meetings.Get.ByUser;
namespace Api.Apis.Meetings;

public class CreateMeetingEndpoint : IEndpoint
{
public void MapEndpoint(IEndpointRouteBuilder app)
{
app.MapPost($"{Constants.MeetingsApi}/", CreateMeeting)
.MapToApiVersion(1)
.WithTags(nameof(Constants.MeetingsApi))
.Produces<PagedList<Meeting>>()
.ProduceProblems(StatusCodes.Status400BadRequest,
StatusCodes.Status401Unauthorized,
StatusCodes.Status404NotFound);
}

private static async Task<IResult> CreateMeeting(CreateMeetingContract contract, [AsParameters] MeetingServices services)
{
var userId = services.HttpContextAccessor.GetUserId();
await services.Mediator.Send(new CreateMeetingCommand(contract.Name, userId , contract.Agenda, contract.Date));
return Results.Ok();
}
}
4 changes: 2 additions & 2 deletions src/Api/Apis/Meetings/GetMeetingsByUser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ public class GetMeetingsByUserEndpoint : IEndpoint
{
public void MapEndpoint(IEndpointRouteBuilder app)
{
app.MapGet($"{Constants.MeetingApi}/", GetCurrentUser)
app.MapGet($"{Constants.MeetingsApi}/", GetCurrentUser)
.MapToApiVersion(1)
.WithTags(nameof(Constants.MeetingApi))
.WithTags(nameof(Constants.MeetingsApi))
.Produces<PagedList<Meeting>>()
.ProduceProblems(StatusCodes.Status400BadRequest,
StatusCodes.Status401Unauthorized,
Expand Down
3 changes: 1 addition & 2 deletions src/Api/Apis/Messengers/Telegram/TelegramServices.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using Infrastructure.Messengers.Telegram.Bot;
using Infrastructure.Messengers.Telegram.UpdateListener;
using Infrastructure.Messengers.Telegram.UpdateListener;
using MediatR;
using Telegram.Bot;
namespace Api.Apis.Messengers.Telegram;
Expand Down
2 changes: 1 addition & 1 deletion src/Api/Configurations/EndpointConstants.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,6 @@ public static class EndpointConstants
{
public const string TelegramApi = "messengers/telegram";
public const string UserApi = "users";
public const string MeetingApi = "meetings";
public const string MeetingsApi = "meetings";
public const string InvitationApi = "invitations";
}
2 changes: 2 additions & 0 deletions src/Domain/Entities/Meeting/Meeting.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ public class Meeting : Entity
public UserId CreatorId { get; set; }
public User.User? Creator { get; set; }
public required string Name { get; set; }
public required long ZoomMeetingId { get; set; }
public required string Agenda { get; set; }
public required DateTime Scheduled { get; set; }
public required string Url { get; set; }
public MeetingStatus Status { get; set; } = MeetingStatus.Scheduled;
Expand Down
25 changes: 15 additions & 10 deletions src/Infrastructure/HostBuilderExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
using Infrastructure.Database.Abstractions;
using Infrastructure.Database.Options;
using Infrastructure.Database.Repositories;
using Infrastructure.MeetingService.Options;
using Infrastructure.Messengers.Options;
using Infrastructure.Messengers.Telegram.Bot;
using Infrastructure.Messengers.Telegram.ChatDistributor;
using Infrastructure.Messengers.Telegram.Service;
using Infrastructure.Messengers.Telegram.UpdateListener;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Telegram.Bot;
using ZoomNet;

namespace Infrastructure;

Expand All @@ -26,8 +26,8 @@ public static void ConfigureInfrastructureLayer(this IHostApplicationBuilder hos
hostBuilder.ConfigureMessengers();
hostBuilder.ConfigureDatabase();
hostBuilder.ConfigureMessengers();
hostBuilder.ConfigureZoom();
hostBuilder.RegisterRepositories();
hostBuilder.RegisterServices();
}

private static void ConfigureMessengers(this IHostApplicationBuilder hostBuilder)
Expand All @@ -36,6 +36,17 @@ private static void ConfigureMessengers(this IHostApplicationBuilder hostBuilder
var options = hostBuilder.Services.BuildServiceProvider().GetRequiredService<IOptions<MessengerOptions>>().Value;
hostBuilder.ConfigureTelegram(options);
}

private static void ConfigureZoom(this IHostApplicationBuilder hostBuilder)
{
var options = hostBuilder.Services.BuildServiceProvider().GetRequiredService<IOptions<MeetingServiceOptions>>().Value;

hostBuilder.Services.AddSingleton<IZoomClient, ZoomClient>(sp =>
{ var connectionInfo = new JwtConnectionInfo(options.ZoomApiKey, options.ZoomApiSecret);
var zoomClient = new ZoomClient(connectionInfo);
return zoomClient;
});
}

private static void ConfigureTelegram(this IHostApplicationBuilder hostBuilder, MessengerOptions options)
{
Expand All @@ -45,8 +56,7 @@ private static void ConfigureTelegram(this IHostApplicationBuilder hostBuilder,
return telegramBotClient;
});
hostBuilder.Services.ConfigureTelegramBot<Microsoft.AspNetCore.Mvc.JsonOptions>(opt => opt.JsonSerializerOptions);

hostBuilder.Services.AddSingleton<ITelegramBot, TelegramBot>();

hostBuilder.Services.AddSingleton<ITelegramUpdateListener, TelegramUpdateListener>();
hostBuilder.Services.AddScoped<ITelegramChatDistributor, TelegramTelegramChatDistributor>();
}
Expand All @@ -73,9 +83,4 @@ private static void RegisterRepositories(this IHostApplicationBuilder builder)
builder.Services.AddScoped<IInvitationRepository, InvitationRepository>();
builder.Services.AddScoped<IMeetingRepository, MeetingRepository>();
}

private static void RegisterServices(this IHostApplicationBuilder builder)
{
builder.Services.AddSingleton<ITelegramService, TelegramService>();
}
}
5 changes: 5 additions & 0 deletions src/Infrastructure/Infrastructure.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -27,12 +27,17 @@
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="9.0.0-preview.7.24405.7" />
<PackageReference Include="Npgsql.EntityFrameworkCore.PostgreSQL" Version="9.0.0-preview.7" />
<PackageReference Include="Serilog" Version="4.0.1" />
<PackageReference Include="ZoomNet" Version="0.80.0" />
<ProjectReference Include="..\Domain\Domain.csproj" />
<ProjectReference Include="..\Telegram.Bot\Telegram.Bot.csproj" />
</ItemGroup>

<ItemGroup>
<Folder Include="Database\Migrations\" />
<Folder Include="MeetingService\Zoom\" />
<PackageReference Include="ZoomNet" Version="0.80.0" />
<ProjectReference Include="..\Telegram.Bot\Telegram.Bot.csproj" />
<Folder Include="MeetingService\Zoom\" />
</ItemGroup>

</Project>
7 changes: 7 additions & 0 deletions src/Infrastructure/MeetingService/IMeetingService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
using Meeting = ZoomNet.Models.Meeting;
namespace Infrastructure.MeetingService;

public interface IMeetingService
{
Task<Meeting?> CreateMeeting(string name, string stringUserId);
}
15 changes: 15 additions & 0 deletions src/Infrastructure/MeetingService/MeetingService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using Infrastructure.Messengers.Telegram.UpdateListener.Commands;
using Telegram.Bot;
using Telegram.Bot.Types;
using ZoomNet;
using ZoomNet.Models;
namespace Infrastructure.MeetingService;

public class MeetingService(IZoomClient zoomClient) : IMeetingService
{
public async Task<Meeting?> CreateMeeting(string name, string stringUserId)
{
return await zoomClient.Meetings.CreateInstantMeetingAsync(stringUserId, name, "agenda");
}
}

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace Infrastructure.MeetingService.Options;

public sealed record MeetingServiceOptions
{
public required string ZoomApiKey { get; set; }
public required string ZoomApiSecret { get; set; }
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Options;
namespace Infrastructure.MeetingService.Options;

public class MeetingServiceOptionsSetup(IConfiguration configuration) : IConfigureOptions<MeetingServiceOptions>
{
private const string SectionName = "MeetingService";

public void Configure(MeetingServiceOptions serviceOptions) => configuration.GetSection(SectionName).Bind(serviceOptions);
}
6 changes: 0 additions & 6 deletions src/Infrastructure/Messengers/Telegram/Bot/ITelegramBot.cs

This file was deleted.

5 changes: 0 additions & 5 deletions src/Infrastructure/Messengers/Telegram/Bot/TelegramBot.cs

This file was deleted.

This file was deleted.

This file was deleted.

4 changes: 4 additions & 0 deletions src/UseCases/Features/Meetings/Create/CreateMeetingCommand.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
using UseCases.Abstractions.Messaging;
namespace UseCases.Features.Meetings.Create;

public record CreateMeetingCommand(string Name, string UserId, string Agenda, DateTime Date) : ICommand;
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
using Domain.Entities.Meeting;
using Domain.Entities.User;
using Infrastructure.MeetingService;
using UseCases.Abstractions.Messaging;
namespace UseCases.Features.Meetings.Create;

public class CreateMeetingCommandHandler(IMeetingRepository meetingRepository, IMeetingService meetingService) : ICommandHandler<CreateMeetingCommand>
{
public async Task Handle(CreateMeetingCommand request, CancellationToken cancellationToken)
{
var creatorId = new UserId(Ulid.Parse(request.UserId));

var meeting = await meetingService.CreateMeeting(request.Name, request.UserId);

if (meeting is null)
{
throw new ApplicationException($"Error creating meeting: {request.UserId}");
}

var dbMeeting = new Meeting
{
Id = new MeetingId(),
ZoomMeetingId = meeting.Id,
Agenda = request.Agenda,
Name = request.Name,
Url = meeting.JoinUrl,
Created = DateTime.Now,
Scheduled = request.Date,
CreatorId = creatorId
};

await meetingRepository.CreateAsync(dbMeeting, cancellationToken);
}
}