using Backend.DatabaseHandler; using Backend.Interface; using Backend.ServiceHandler; using Microsoft.AspNetCore.Mvc; namespace Backend.Controllers { [ApiController] [Route("api/news-sentiment")] public sealed class NewsSentimentController : ControllerBase { private static DateTime _lastRefresh = DateTime.MinValue; private static readonly Lock _refreshLock = new(); private readonly NewsSentimentService _service; private readonly IUserInterestStore _interests; private readonly INewsSentimentStore _store; public NewsSentimentController( NewsSentimentService service, IUserInterestStore interests, INewsSentimentStore store) { _service = service; _interests = interests; _store = store; } [HttpGet] public async Task Analyze( [FromQuery] string keyword, CancellationToken cancellationToken) { var results = await _service.AnalyzeAsync(keyword, cancellationToken); return Ok(results); } [HttpGet("feed")] public async Task Feed( [FromQuery] string user, [FromQuery] string? keyword = null, [FromQuery(Name = "request-amount")] int requestAmount = 20, CancellationToken cancellationToken = default) { if (string.IsNullOrWhiteSpace(user)) return BadRequest("User cannot be empty."); if (requestAmount < 1) requestAmount = 1; List keywords; if (!string.IsNullOrWhiteSpace(keyword)) { keywords = [keyword.Trim()]; } else { var symbols = await _interests.FetchAllAsync(user, "symbol"); var topics = await _interests.FetchAllAsync(user, "topic"); keywords = symbols.Concat(topics).Distinct().ToList(); } if (keywords.Count == 0) return Ok(Array.Empty()); var results = await _store.GetFeedAsync(keywords, requestAmount, cancellationToken); return Ok(results.Select(NewsFeedItem.From)); } [HttpGet("refresh")] public async Task> Refresh( [FromQuery] string user, CancellationToken cancellationToken = default) { try { if (string.IsNullOrWhiteSpace(user)) return BadRequest("User cannot be empty."); lock (_refreshLock) { if ((DateTime.UtcNow - _lastRefresh).TotalSeconds < 5) return Ok(new BoolResponse { Success = false }); _lastRefresh = DateTime.UtcNow; } var symbols = await _interests.FetchAllAsync(user, "symbol"); var topics = await _interests.FetchAllAsync(user, "topic"); var kws = symbols.Concat(topics).Distinct().ToList(); foreach (var kw in kws) { await _service.AnalyzeAsync(kw, cancellationToken); } return Ok(new BoolResponse { Success = true }); } catch (Exception) { return Ok(new BoolResponse { Success = false }); } } } }