From 57a6ae20e295a6427892f306656e7dfc4c70843f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Jun 2025 12:54:10 +0000 Subject: [PATCH 1/5] Initial plan for issue From a4b6397cf0db0e37aa1407b7c61b42f52d4ab47a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Jun 2025 13:00:51 +0000 Subject: [PATCH 2/5] Add GitHub profile endpoints with DTOs and controller Co-authored-by: maximgorbatyuk <13348685+maximgorbatyuk@users.noreply.github.com> --- .../Github/Dtos/GithubProfileBotChatDto.cs | 36 +++++++ .../Features/Github/Dtos/GithubProfileDto.cs | 33 +++++++ .../Dtos/GithubProfileProcessingJobDto.cs | 24 +++++ .../Features/Github/GithubController.cs | 98 +++++++++++++++++++ 4 files changed, 191 insertions(+) create mode 100644 src/Web.Api/Features/Github/Dtos/GithubProfileBotChatDto.cs create mode 100644 src/Web.Api/Features/Github/Dtos/GithubProfileDto.cs create mode 100644 src/Web.Api/Features/Github/Dtos/GithubProfileProcessingJobDto.cs create mode 100644 src/Web.Api/Features/Github/GithubController.cs diff --git a/src/Web.Api/Features/Github/Dtos/GithubProfileBotChatDto.cs b/src/Web.Api/Features/Github/Dtos/GithubProfileBotChatDto.cs new file mode 100644 index 00000000..9fba782e --- /dev/null +++ b/src/Web.Api/Features/Github/Dtos/GithubProfileBotChatDto.cs @@ -0,0 +1,36 @@ +using System; +using Domain.Entities.Github; + +namespace Web.Api.Features.Github.Dtos; + +public record GithubProfileBotChatDto +{ + public Guid Id { get; init; } + + public long ChatId { get; init; } + + public string Username { get; init; } + + public bool IsAdmin { get; init; } + + public int MessagesCount { get; init; } + + public DateTimeOffset CreatedAt { get; init; } + + public DateTimeOffset UpdatedAt { get; init; } + + public GithubProfileBotChatDto() + { + } + + public GithubProfileBotChatDto(GithubProfileBotChat chat) + { + Id = chat.Id; + ChatId = chat.ChatId; + Username = chat.Username; + IsAdmin = chat.IsAdmin; + MessagesCount = chat.MessagesCount; + CreatedAt = chat.CreatedAt; + UpdatedAt = chat.UpdatedAt; + } +} \ No newline at end of file diff --git a/src/Web.Api/Features/Github/Dtos/GithubProfileDto.cs b/src/Web.Api/Features/Github/Dtos/GithubProfileDto.cs new file mode 100644 index 00000000..42fb5995 --- /dev/null +++ b/src/Web.Api/Features/Github/Dtos/GithubProfileDto.cs @@ -0,0 +1,33 @@ +using System; +using Domain.Entities.Github; + +namespace Web.Api.Features.Github.Dtos; + +public record GithubProfileDto +{ + public string Username { get; init; } + + public int Version { get; init; } + + public int RequestsCount { get; init; } + + public DateTime DataSyncedAt { get; init; } + + public DateTimeOffset CreatedAt { get; init; } + + public DateTimeOffset UpdatedAt { get; init; } + + public GithubProfileDto() + { + } + + public GithubProfileDto(GithubProfile profile) + { + Username = profile.Username; + Version = profile.Version; + RequestsCount = profile.RequestsCount; + DataSyncedAt = profile.DataSyncedAt; + CreatedAt = profile.CreatedAt; + UpdatedAt = profile.UpdatedAt; + } +} \ No newline at end of file diff --git a/src/Web.Api/Features/Github/Dtos/GithubProfileProcessingJobDto.cs b/src/Web.Api/Features/Github/Dtos/GithubProfileProcessingJobDto.cs new file mode 100644 index 00000000..a4af20cc --- /dev/null +++ b/src/Web.Api/Features/Github/Dtos/GithubProfileProcessingJobDto.cs @@ -0,0 +1,24 @@ +using System; +using Domain.Entities.Github; + +namespace Web.Api.Features.Github.Dtos; + +public record GithubProfileProcessingJobDto +{ + public string Username { get; init; } + + public DateTimeOffset CreatedAt { get; init; } + + public DateTimeOffset UpdatedAt { get; init; } + + public GithubProfileProcessingJobDto() + { + } + + public GithubProfileProcessingJobDto(GithubProfileProcessingJob job) + { + Username = job.Username; + CreatedAt = job.CreatedAt; + UpdatedAt = job.UpdatedAt; + } +} \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GithubController.cs b/src/Web.Api/Features/Github/GithubController.cs new file mode 100644 index 00000000..b3225c06 --- /dev/null +++ b/src/Web.Api/Features/Github/GithubController.cs @@ -0,0 +1,98 @@ +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Domain.Entities.Github; +using Domain.Enums; +using Domain.ValueObjects.Pagination; +using Infrastructure.Database; +using Microsoft.AspNetCore.Mvc; +using Microsoft.EntityFrameworkCore; +using Web.Api.Features.Github.Dtos; +using Web.Api.Setup.Attributes; + +namespace Web.Api.Features.Github; + +[ApiController] +[Route("api/github")] +[HasAnyRole(Role.Admin)] +public class GithubController : ControllerBase +{ + private readonly DatabaseContext _context; + + public GithubController(DatabaseContext context) + { + _context = context; + } + + [HttpGet("profiles")] + public async Task GetGithubProfiles( + [FromQuery] PageModel queryParams, + CancellationToken cancellationToken) + { + var profiles = await _context.GithubProfiles + .OrderByDescending(x => x.CreatedAt) + .AsPaginatedAsync( + queryParams, + cancellationToken); + + return Ok(new Pageable( + profiles.CurrentPage, + profiles.PageSize, + profiles.TotalItems, + profiles.Results + .Select(x => new GithubProfileDto(x)) + .ToList())); + } + + [HttpGet("chats")] + public async Task GetGithubProfileChats( + [FromQuery] PageModel queryParams, + CancellationToken cancellationToken) + { + var chats = await _context.GithubProfileBotChats + .OrderByDescending(x => x.MessagesCount) + .ThenByDescending(x => x.CreatedAt) + .AsPaginatedAsync( + queryParams, + cancellationToken); + + return Ok(new Pageable( + chats.CurrentPage, + chats.PageSize, + chats.TotalItems, + chats.Results + .Select(x => new GithubProfileBotChatDto(x)) + .ToList())); + } + + [HttpGet("processing-jobs")] + public async Task GetGithubProcessingJobs( + CancellationToken cancellationToken) + { + var jobs = await _context.GithubProfileProcessingJobs + .OrderByDescending(x => x.CreatedAt) + .AllAsync(cancellationToken); + + return Ok(jobs.Select(x => new GithubProfileProcessingJobDto(x)).ToList()); + } + + [HttpDelete("processing-jobs/{username}")] + public async Task DeleteGithubProcessingJob( + string username, + CancellationToken cancellationToken) + { + var job = await _context.GithubProfileProcessingJobs + .FirstOrDefaultAsync(x => x.Username == username, cancellationToken); + + if (job == null) + { + return NotFound($"Github processing job with username '{username}' not found"); + } + + _context.GithubProfileProcessingJobs.Remove(job); + await _context.TrySaveChangesAsync(cancellationToken); + + return Ok(); + } +} \ No newline at end of file From ee35bc5ef829e5ed88c8eb3810cd971232eab5f5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 20 Jun 2025 13:21:05 +0000 Subject: [PATCH 3/5] Refactor GitHub endpoints to use Handler pattern with QueryParams classes Co-authored-by: maximgorbatyuk <13348685+maximgorbatyuk@users.noreply.github.com> --- .../DeleteGithubProcessingJobCommand.cs | 3 + .../DeleteGithubProcessingJobHandler.cs | 36 ++++++++ .../GetGithubProcessingJobsHandler.cs | 31 +++++++ .../GetGithubProcessingJobsResponse.cs | 7 ++ .../GetGithubProfileChatsHandler.cs | 39 +++++++++ .../GetGithubProfileChatsQueryParams.cs | 7 ++ .../GetGithubProfileChatsResponse.cs | 11 +++ .../GetGithubProfilesHandler.cs | 38 +++++++++ .../GetGithubProfilesQueryParams.cs | 7 ++ .../GetGithubProfilesResponse.cs | 11 +++ .../Features/Github/GithubController.cs | 83 +++++++------------ 11 files changed, 220 insertions(+), 53 deletions(-) create mode 100644 src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobCommand.cs create mode 100644 src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobHandler.cs create mode 100644 src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsHandler.cs create mode 100644 src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsResponse.cs create mode 100644 src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsHandler.cs create mode 100644 src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsQueryParams.cs create mode 100644 src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsResponse.cs create mode 100644 src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesHandler.cs create mode 100644 src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesQueryParams.cs create mode 100644 src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesResponse.cs diff --git a/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobCommand.cs b/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobCommand.cs new file mode 100644 index 00000000..71ef0a57 --- /dev/null +++ b/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobCommand.cs @@ -0,0 +1,3 @@ +namespace Web.Api.Features.Github.DeleteGithubProcessingJob; + +public record DeleteGithubProcessingJobCommand(string Username); \ No newline at end of file diff --git a/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobHandler.cs b/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobHandler.cs new file mode 100644 index 00000000..c1a3fd6a --- /dev/null +++ b/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobHandler.cs @@ -0,0 +1,36 @@ +using System.Threading; +using System.Threading.Tasks; +using Infrastructure.Database; +using Infrastructure.Services.Mediator; +using Microsoft.AspNetCore.Http; +using Microsoft.EntityFrameworkCore; + +namespace Web.Api.Features.Github.DeleteGithubProcessingJob; + +public class DeleteGithubProcessingJobHandler : IRequestHandler +{ + private readonly DatabaseContext _context; + + public DeleteGithubProcessingJobHandler(DatabaseContext context) + { + _context = context; + } + + public async Task Handle( + DeleteGithubProcessingJobCommand request, + CancellationToken cancellationToken) + { + var job = await _context.GithubProfileProcessingJobs + .FirstOrDefaultAsync(x => x.Username == request.Username, cancellationToken); + + if (job == null) + { + throw new BadHttpRequestException($"Github processing job with username '{request.Username}' not found"); + } + + _context.GithubProfileProcessingJobs.Remove(job); + await _context.TrySaveChangesAsync(cancellationToken); + + return Nothing.Value; + } +} \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsHandler.cs b/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsHandler.cs new file mode 100644 index 00000000..0bf11e2a --- /dev/null +++ b/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsHandler.cs @@ -0,0 +1,31 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Infrastructure.Database; +using Infrastructure.Services.Mediator; +using Microsoft.EntityFrameworkCore; +using Web.Api.Features.Github.Dtos; + +namespace Web.Api.Features.Github.GetGithubProcessingJobs; + +public class GetGithubProcessingJobsHandler : IRequestHandler +{ + private readonly DatabaseContext _context; + + public GetGithubProcessingJobsHandler(DatabaseContext context) + { + _context = context; + } + + public async Task Handle( + Nothing request, + CancellationToken cancellationToken) + { + var jobs = await _context.GithubProfileProcessingJobs + .OrderByDescending(x => x.CreatedAt) + .ToListAsync(cancellationToken); + + return new GetGithubProcessingJobsResponse( + jobs.Select(x => new GithubProfileProcessingJobDto(x)).ToList()); + } +} \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsResponse.cs b/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsResponse.cs new file mode 100644 index 00000000..1d36cb44 --- /dev/null +++ b/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsResponse.cs @@ -0,0 +1,7 @@ +using System.Collections.Generic; +using Web.Api.Features.Github.Dtos; + +namespace Web.Api.Features.Github.GetGithubProcessingJobs; + +public record GetGithubProcessingJobsResponse( + IReadOnlyCollection Results); \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsHandler.cs b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsHandler.cs new file mode 100644 index 00000000..b76f7adc --- /dev/null +++ b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsHandler.cs @@ -0,0 +1,39 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Infrastructure.Database; +using Infrastructure.Services.Mediator; +using Microsoft.EntityFrameworkCore; +using Web.Api.Features.Github.Dtos; + +namespace Web.Api.Features.Github.GetGithubProfileChats; + +public class GetGithubProfileChatsHandler : IRequestHandler +{ + private readonly DatabaseContext _context; + + public GetGithubProfileChatsHandler(DatabaseContext context) + { + _context = context; + } + + public async Task Handle( + GetGithubProfileChatsQueryParams request, + CancellationToken cancellationToken) + { + var chats = await _context.GithubProfileBotChats + .OrderByDescending(x => x.MessagesCount) + .ThenByDescending(x => x.CreatedAt) + .AsPaginatedAsync( + request, + cancellationToken); + + return new GetGithubProfileChatsResponse( + chats.CurrentPage, + chats.PageSize, + chats.TotalItems, + chats.Results + .Select(x => new GithubProfileBotChatDto(x)) + .ToList()); + } +} \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsQueryParams.cs b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsQueryParams.cs new file mode 100644 index 00000000..4b0a94e2 --- /dev/null +++ b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsQueryParams.cs @@ -0,0 +1,7 @@ +using Domain.ValueObjects.Pagination; + +namespace Web.Api.Features.Github.GetGithubProfileChats; + +public record GetGithubProfileChatsQueryParams : PageModel +{ +} \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsResponse.cs b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsResponse.cs new file mode 100644 index 00000000..da7a9f7a --- /dev/null +++ b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsResponse.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Domain.ValueObjects.Pagination; +using Web.Api.Features.Github.Dtos; + +namespace Web.Api.Features.Github.GetGithubProfileChats; + +public record GetGithubProfileChatsResponse( + int CurrentPage, + int PageSize, + int TotalItems, + IReadOnlyCollection Results) : Pageable(CurrentPage, PageSize, TotalItems, Results); \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesHandler.cs b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesHandler.cs new file mode 100644 index 00000000..1e9cac85 --- /dev/null +++ b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesHandler.cs @@ -0,0 +1,38 @@ +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Infrastructure.Database; +using Infrastructure.Services.Mediator; +using Microsoft.EntityFrameworkCore; +using Web.Api.Features.Github.Dtos; + +namespace Web.Api.Features.Github.GetGithubProfiles; + +public class GetGithubProfilesHandler : IRequestHandler +{ + private readonly DatabaseContext _context; + + public GetGithubProfilesHandler(DatabaseContext context) + { + _context = context; + } + + public async Task Handle( + GetGithubProfilesQueryParams request, + CancellationToken cancellationToken) + { + var profiles = await _context.GithubProfiles + .OrderByDescending(x => x.CreatedAt) + .AsPaginatedAsync( + request, + cancellationToken); + + return new GetGithubProfilesResponse( + profiles.CurrentPage, + profiles.PageSize, + profiles.TotalItems, + profiles.Results + .Select(x => new GithubProfileDto(x)) + .ToList()); + } +} \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesQueryParams.cs b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesQueryParams.cs new file mode 100644 index 00000000..ad29f480 --- /dev/null +++ b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesQueryParams.cs @@ -0,0 +1,7 @@ +using Domain.ValueObjects.Pagination; + +namespace Web.Api.Features.Github.GetGithubProfiles; + +public record GetGithubProfilesQueryParams : PageModel +{ +} \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesResponse.cs b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesResponse.cs new file mode 100644 index 00000000..b1d7bf7e --- /dev/null +++ b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesResponse.cs @@ -0,0 +1,11 @@ +using System.Collections.Generic; +using Domain.ValueObjects.Pagination; +using Web.Api.Features.Github.Dtos; + +namespace Web.Api.Features.Github.GetGithubProfiles; + +public record GetGithubProfilesResponse( + int CurrentPage, + int PageSize, + int TotalItems, + IReadOnlyCollection Results) : Pageable(CurrentPage, PageSize, TotalItems, Results); \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GithubController.cs b/src/Web.Api/Features/Github/GithubController.cs index b3225c06..90f61b52 100644 --- a/src/Web.Api/Features/Github/GithubController.cs +++ b/src/Web.Api/Features/Github/GithubController.cs @@ -1,14 +1,15 @@ -using System.Collections.Generic; -using System.Linq; +using System; using System.Threading; using System.Threading.Tasks; -using Domain.Entities.Github; using Domain.Enums; -using Domain.ValueObjects.Pagination; -using Infrastructure.Database; +using Infrastructure.Services.Mediator; +using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; -using Microsoft.EntityFrameworkCore; -using Web.Api.Features.Github.Dtos; +using Microsoft.Extensions.DependencyInjection; +using Web.Api.Features.Github.DeleteGithubProcessingJob; +using Web.Api.Features.Github.GetGithubProfileChats; +using Web.Api.Features.Github.GetGithubProfiles; +using Web.Api.Features.Github.GetGithubProcessingJobs; using Web.Api.Setup.Attributes; namespace Web.Api.Features.Github; @@ -18,63 +19,40 @@ namespace Web.Api.Features.Github; [HasAnyRole(Role.Admin)] public class GithubController : ControllerBase { - private readonly DatabaseContext _context; + private readonly IServiceProvider _serviceProvider; - public GithubController(DatabaseContext context) + public GithubController(IServiceProvider serviceProvider) { - _context = context; + _serviceProvider = serviceProvider; } [HttpGet("profiles")] public async Task GetGithubProfiles( - [FromQuery] PageModel queryParams, + [FromQuery] GetGithubProfilesQueryParams queryParams, CancellationToken cancellationToken) { - var profiles = await _context.GithubProfiles - .OrderByDescending(x => x.CreatedAt) - .AsPaginatedAsync( - queryParams, - cancellationToken); - - return Ok(new Pageable( - profiles.CurrentPage, - profiles.PageSize, - profiles.TotalItems, - profiles.Results - .Select(x => new GithubProfileDto(x)) - .ToList())); + return Ok( + await _serviceProvider.GetRequiredService() + .Handle(queryParams, cancellationToken)); } [HttpGet("chats")] public async Task GetGithubProfileChats( - [FromQuery] PageModel queryParams, + [FromQuery] GetGithubProfileChatsQueryParams queryParams, CancellationToken cancellationToken) { - var chats = await _context.GithubProfileBotChats - .OrderByDescending(x => x.MessagesCount) - .ThenByDescending(x => x.CreatedAt) - .AsPaginatedAsync( - queryParams, - cancellationToken); - - return Ok(new Pageable( - chats.CurrentPage, - chats.PageSize, - chats.TotalItems, - chats.Results - .Select(x => new GithubProfileBotChatDto(x)) - .ToList())); + return Ok( + await _serviceProvider.GetRequiredService() + .Handle(queryParams, cancellationToken)); } [HttpGet("processing-jobs")] public async Task GetGithubProcessingJobs( CancellationToken cancellationToken) { - var jobs = await _context.GithubProfileProcessingJobs - .OrderByDescending(x => x.CreatedAt) - .AllAsync(cancellationToken); - - return Ok(jobs.Select(x => new GithubProfileProcessingJobDto(x)).ToList()); + return Ok( + await _serviceProvider.GetRequiredService() + .Handle(Nothing.Value, cancellationToken)); } [HttpDelete("processing-jobs/{username}")] @@ -82,17 +60,16 @@ public async Task DeleteGithubProcessingJob( string username, CancellationToken cancellationToken) { - var job = await _context.GithubProfileProcessingJobs - .FirstOrDefaultAsync(x => x.Username == username, cancellationToken); + try + { + await _serviceProvider.GetRequiredService() + .Handle(new DeleteGithubProcessingJobCommand(username), cancellationToken); - if (job == null) + return Ok(); + } + catch (BadHttpRequestException ex) { - return NotFound($"Github processing job with username '{username}' not found"); + return NotFound(ex.Message); } - - _context.GithubProfileProcessingJobs.Remove(job); - await _context.TrySaveChangesAsync(cancellationToken); - - return Ok(); } } \ No newline at end of file From 6ae765ebf42914dcee377c7a87d1b6b7197738a2 Mon Sep 17 00:00:00 2001 From: "maxim.gorbatyuk" Date: Sat, 21 Jun 2025 07:26:06 +0500 Subject: [PATCH 4/5] Fixes --- .../DeleteGithubProcessingJobCommand.cs | 6 ++++-- .../DeleteGithubProcessingJobHandler.cs | 2 +- .../Github/Dtos/GithubProfileBotChatDto.cs | 17 +++++++++-------- .../Features/Github/Dtos/GithubProfileDto.cs | 15 ++++++++------- .../Dtos/GithubProfileProcessingJobDto.cs | 6 +++--- .../GetGithubProcessingJobsHandler.cs | 2 +- .../GetGithubProcessingJobsResponse.cs | 3 ++- .../GetGithubProfileChatsHandler.cs | 5 +++-- .../GetGithubProfileChatsQueryParams.cs | 2 +- .../GetGithubProfileChatsResponse.cs | 6 ++++-- .../GetGithubProfilesHandler.cs | 2 +- .../GetGithubProfilesQueryParams.cs | 2 +- .../GetGithubProfilesResponse.cs | 6 ++++-- src/Web.Api/Features/Github/GithubController.cs | 4 ++-- 14 files changed, 44 insertions(+), 34 deletions(-) diff --git a/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobCommand.cs b/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobCommand.cs index 71ef0a57..b75fedf3 100644 --- a/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobCommand.cs +++ b/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobCommand.cs @@ -1,3 +1,5 @@ -namespace Web.Api.Features.Github.DeleteGithubProcessingJob; +namespace Web.Api.Features.Github.DeleteGithubProcessingJob; -public record DeleteGithubProcessingJobCommand(string Username); \ No newline at end of file +#pragma warning disable SA1313 +public record DeleteGithubProcessingJobCommand( + string Username); \ No newline at end of file diff --git a/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobHandler.cs b/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobHandler.cs index c1a3fd6a..33e479b8 100644 --- a/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobHandler.cs +++ b/src/Web.Api/Features/Github/DeleteGithubProcessingJob/DeleteGithubProcessingJobHandler.cs @@ -1,4 +1,4 @@ -using System.Threading; +using System.Threading; using System.Threading.Tasks; using Infrastructure.Database; using Infrastructure.Services.Mediator; diff --git a/src/Web.Api/Features/Github/Dtos/GithubProfileBotChatDto.cs b/src/Web.Api/Features/Github/Dtos/GithubProfileBotChatDto.cs index 9fba782e..89fbe5f9 100644 --- a/src/Web.Api/Features/Github/Dtos/GithubProfileBotChatDto.cs +++ b/src/Web.Api/Features/Github/Dtos/GithubProfileBotChatDto.cs @@ -1,4 +1,4 @@ -using System; +using System; using Domain.Entities.Github; namespace Web.Api.Features.Github.Dtos; @@ -6,24 +6,25 @@ namespace Web.Api.Features.Github.Dtos; public record GithubProfileBotChatDto { public Guid Id { get; init; } - + public long ChatId { get; init; } - + public string Username { get; init; } - + public bool IsAdmin { get; init; } - + public int MessagesCount { get; init; } - + public DateTimeOffset CreatedAt { get; init; } - + public DateTimeOffset UpdatedAt { get; init; } public GithubProfileBotChatDto() { } - public GithubProfileBotChatDto(GithubProfileBotChat chat) + public GithubProfileBotChatDto( + GithubProfileBotChat chat) { Id = chat.Id; ChatId = chat.ChatId; diff --git a/src/Web.Api/Features/Github/Dtos/GithubProfileDto.cs b/src/Web.Api/Features/Github/Dtos/GithubProfileDto.cs index 42fb5995..7dce8296 100644 --- a/src/Web.Api/Features/Github/Dtos/GithubProfileDto.cs +++ b/src/Web.Api/Features/Github/Dtos/GithubProfileDto.cs @@ -1,4 +1,4 @@ -using System; +using System; using Domain.Entities.Github; namespace Web.Api.Features.Github.Dtos; @@ -6,22 +6,23 @@ namespace Web.Api.Features.Github.Dtos; public record GithubProfileDto { public string Username { get; init; } - + public int Version { get; init; } - + public int RequestsCount { get; init; } - + public DateTime DataSyncedAt { get; init; } - + public DateTimeOffset CreatedAt { get; init; } - + public DateTimeOffset UpdatedAt { get; init; } public GithubProfileDto() { } - public GithubProfileDto(GithubProfile profile) + public GithubProfileDto( + GithubProfile profile) { Username = profile.Username; Version = profile.Version; diff --git a/src/Web.Api/Features/Github/Dtos/GithubProfileProcessingJobDto.cs b/src/Web.Api/Features/Github/Dtos/GithubProfileProcessingJobDto.cs index a4af20cc..01394443 100644 --- a/src/Web.Api/Features/Github/Dtos/GithubProfileProcessingJobDto.cs +++ b/src/Web.Api/Features/Github/Dtos/GithubProfileProcessingJobDto.cs @@ -1,4 +1,4 @@ -using System; +using System; using Domain.Entities.Github; namespace Web.Api.Features.Github.Dtos; @@ -6,9 +6,9 @@ namespace Web.Api.Features.Github.Dtos; public record GithubProfileProcessingJobDto { public string Username { get; init; } - + public DateTimeOffset CreatedAt { get; init; } - + public DateTimeOffset UpdatedAt { get; init; } public GithubProfileProcessingJobDto() diff --git a/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsHandler.cs b/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsHandler.cs index 0bf11e2a..18474569 100644 --- a/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsHandler.cs +++ b/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsHandler.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Infrastructure.Database; diff --git a/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsResponse.cs b/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsResponse.cs index 1d36cb44..55bb5f5f 100644 --- a/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsResponse.cs +++ b/src/Web.Api/Features/Github/GetGithubProcessingJobs/GetGithubProcessingJobsResponse.cs @@ -1,7 +1,8 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Web.Api.Features.Github.Dtos; namespace Web.Api.Features.Github.GetGithubProcessingJobs; +#pragma warning disable SA1313 public record GetGithubProcessingJobsResponse( IReadOnlyCollection Results); \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsHandler.cs b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsHandler.cs index b76f7adc..2b7efa5a 100644 --- a/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsHandler.cs +++ b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsHandler.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Infrastructure.Database; @@ -8,7 +8,8 @@ namespace Web.Api.Features.Github.GetGithubProfileChats; -public class GetGithubProfileChatsHandler : IRequestHandler +public class GetGithubProfileChatsHandler + : IRequestHandler { private readonly DatabaseContext _context; diff --git a/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsQueryParams.cs b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsQueryParams.cs index 4b0a94e2..8b226319 100644 --- a/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsQueryParams.cs +++ b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsQueryParams.cs @@ -1,4 +1,4 @@ -using Domain.ValueObjects.Pagination; +using Domain.ValueObjects.Pagination; namespace Web.Api.Features.Github.GetGithubProfileChats; diff --git a/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsResponse.cs b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsResponse.cs index da7a9f7a..b299a5e9 100644 --- a/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsResponse.cs +++ b/src/Web.Api/Features/Github/GetGithubProfileChats/GetGithubProfileChatsResponse.cs @@ -1,11 +1,13 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Domain.ValueObjects.Pagination; using Web.Api.Features.Github.Dtos; namespace Web.Api.Features.Github.GetGithubProfileChats; +#pragma warning disable SA1313 public record GetGithubProfileChatsResponse( int CurrentPage, int PageSize, int TotalItems, - IReadOnlyCollection Results) : Pageable(CurrentPage, PageSize, TotalItems, Results); \ No newline at end of file + IReadOnlyCollection Results) + : Pageable(CurrentPage, PageSize, TotalItems, Results); \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesHandler.cs b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesHandler.cs index 1e9cac85..30bfa060 100644 --- a/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesHandler.cs +++ b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesHandler.cs @@ -1,4 +1,4 @@ -using System.Linq; +using System.Linq; using System.Threading; using System.Threading.Tasks; using Infrastructure.Database; diff --git a/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesQueryParams.cs b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesQueryParams.cs index ad29f480..b7ecf685 100644 --- a/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesQueryParams.cs +++ b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesQueryParams.cs @@ -1,4 +1,4 @@ -using Domain.ValueObjects.Pagination; +using Domain.ValueObjects.Pagination; namespace Web.Api.Features.Github.GetGithubProfiles; diff --git a/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesResponse.cs b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesResponse.cs index b1d7bf7e..725e7ef8 100644 --- a/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesResponse.cs +++ b/src/Web.Api/Features/Github/GetGithubProfiles/GetGithubProfilesResponse.cs @@ -1,11 +1,13 @@ -using System.Collections.Generic; +using System.Collections.Generic; using Domain.ValueObjects.Pagination; using Web.Api.Features.Github.Dtos; namespace Web.Api.Features.Github.GetGithubProfiles; +#pragma warning disable SA1313 public record GetGithubProfilesResponse( int CurrentPage, int PageSize, int TotalItems, - IReadOnlyCollection Results) : Pageable(CurrentPage, PageSize, TotalItems, Results); \ No newline at end of file + IReadOnlyCollection Results) + : Pageable(CurrentPage, PageSize, TotalItems, Results); \ No newline at end of file diff --git a/src/Web.Api/Features/Github/GithubController.cs b/src/Web.Api/Features/Github/GithubController.cs index 90f61b52..7a74eab6 100644 --- a/src/Web.Api/Features/Github/GithubController.cs +++ b/src/Web.Api/Features/Github/GithubController.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Threading; using System.Threading.Tasks; using Domain.Enums; @@ -7,9 +7,9 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using Web.Api.Features.Github.DeleteGithubProcessingJob; +using Web.Api.Features.Github.GetGithubProcessingJobs; using Web.Api.Features.Github.GetGithubProfileChats; using Web.Api.Features.Github.GetGithubProfiles; -using Web.Api.Features.Github.GetGithubProcessingJobs; using Web.Api.Setup.Attributes; namespace Web.Api.Features.Github; From 65d7d49e8470a275f96018d8e07b12fee0164320 Mon Sep 17 00:00:00 2001 From: "maxim.gorbatyuk" Date: Sat, 21 Jun 2025 12:21:12 +0500 Subject: [PATCH 5/5] Fixes --- src/Domain/Entities/Github/GithubProfileData.cs | 3 +++ .../Services/Github/GithubGraphQLService.cs | 8 +++++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/Domain/Entities/Github/GithubProfileData.cs b/src/Domain/Entities/Github/GithubProfileData.cs index 8ec69599..60cbda3c 100644 --- a/src/Domain/Entities/Github/GithubProfileData.cs +++ b/src/Domain/Entities/Github/GithubProfileData.cs @@ -46,6 +46,8 @@ public record GithubProfileData public int MonthsToFetchCommits { get; init; } + public DateTime UserCreatedAt { get; init; } + public DateTime CreatedAt { get; init; } public GithubProfileData() @@ -105,6 +107,7 @@ public string GetTelegramFormattedText() var result = $"Github stats for {Username}\n" + $"Name: {Name}\n" + + $"Profile created: {UserCreatedAt:yyyy-MM-dd}\n" + $"Profile URL\n\n" + $"🌟 Social stats:\n" + $"- Followers: {Followers:N0}\n" + diff --git a/src/Infrastructure/Services/Github/GithubGraphQLService.cs b/src/Infrastructure/Services/Github/GithubGraphQLService.cs index 6703a8f8..4cb598d3 100644 --- a/src/Infrastructure/Services/Github/GithubGraphQLService.cs +++ b/src/Infrastructure/Services/Github/GithubGraphQLService.cs @@ -366,7 +366,8 @@ private GithubProfileData MapToGithubProfileData( user.ContributionsCollection?.CommitContributionsByRepository, topLanguagesCount), MonthsToFetchCommits = monthsToFetchCommits, - CreatedAt = user.CreatedAt + UserCreatedAt = user.CreatedAt, + CreatedAt = DateTime.UtcNow, }; } @@ -487,10 +488,15 @@ public record UserProfile public string Id { get; set; } public string Name { get; set; } public string Login { get; set; } + public string Url { get; set; } + public CountInfo Followers { get; set; } + public CountInfo Following { get; set; } + public CountInfo Repositories { get; set; } + public CountInfo StarredRepositories { get; set; } public CountInfo Issues { get; set; } public CountInfo PullRequests { get; set; }