using DysonNetwork.Shared.Models; using DysonNetwork.Shared.Proto; using Grpc.Core; using Microsoft.EntityFrameworkCore; namespace DysonNetwork.Insight.Reader; public class WebArticleGrpcService(AppDatabase db) : WebArticleService.WebArticleServiceBase { public override async Task GetWebArticle( GetWebArticleRequest request, ServerCallContext context ) { if (!Guid.TryParse(request.Id, out var id)) throw new RpcException(new Status(StatusCode.InvalidArgument, "invalid id")); var article = await db.WebArticles .Include(a => a.Feed) .FirstOrDefaultAsync(a => a.Id == id); return article == null ? throw new RpcException(new Status(StatusCode.NotFound, "article not found")) : new GetWebArticleResponse { Article = article.ToProtoValue() }; } public override async Task GetWebArticleBatch( GetWebArticleBatchRequest request, ServerCallContext context ) { var ids = request.Ids .Where(s => !string.IsNullOrWhiteSpace(s) && Guid.TryParse(s, out _)) .Select(Guid.Parse) .ToList(); if (ids.Count == 0) return new GetWebArticleBatchResponse(); var articles = await db.WebArticles .Include(a => a.Feed) .Where(a => ids.Contains(a.Id)) .ToListAsync(); var response = new GetWebArticleBatchResponse(); response.Articles.AddRange(articles.Select(a => a.ToProtoValue())); return response; } public override async Task ListWebArticles( ListWebArticlesRequest request, ServerCallContext context ) { if (!Guid.TryParse(request.FeedId, out var feedId)) throw new RpcException(new Status(StatusCode.InvalidArgument, "invalid feed_id")); var query = db.WebArticles .Include(a => a.Feed) .Where(a => a.FeedId == feedId); var articles = await query.ToListAsync(); var response = new ListWebArticlesResponse { TotalSize = articles.Count }; response.Articles.AddRange(articles.Select(a => a.ToProtoValue())); return response; } public override async Task GetRecentArticles( GetRecentArticlesRequest request, ServerCallContext context ) { var limit = request.Limit > 0 ? request.Limit : 20; var articles = await db.WebArticles .Include(a => a.Feed) .OrderByDescending(a => a.PublishedAt ?? DateTime.MinValue) .ThenByDescending(a => a.CreatedAt) .Take(limit) .ToListAsync(); var response = new GetRecentArticlesResponse(); response.Articles.AddRange(articles.Select(a => a.ToProtoValue())); return response; } }