< Summary

Information
Class: Chronicis.Api.Controllers.ExternalLinksController
Assembly: Chronicis.Api
File(s): /home/runner/work/chronicis/chronicis/src/Chronicis.Api/Controllers/ExternalLinksController.cs
Line coverage
0%
Covered lines: 0
Uncovered lines: 45
Coverable lines: 45
Total lines: 104
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 10
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)100%210%
GetSuggestions()0%2040%
GetContent()0%4260%

File(s)

/home/runner/work/chronicis/chronicis/src/Chronicis.Api/Controllers/ExternalLinksController.cs

#LineLine coverage
 1using Chronicis.Api.Services.ExternalLinks;
 2using Chronicis.Shared.DTOs;
 3using Chronicis.Shared.Extensions;
 4using Microsoft.AspNetCore.Mvc;
 5
 6namespace Chronicis.Api.Controllers;
 7
 8/// <summary>
 9/// API endpoints for External Link operations (SRD content, etc.)
 10/// </summary>
 11[ApiController]
 12[Route("external-links")]
 13// [Authorize] // Temporarily disabled for testing
 14public class ExternalLinksController : ControllerBase
 15{
 16    private readonly IExternalLinkService _externalLinkService;
 17    private readonly ILogger<ExternalLinksController> _logger;
 18
 019    public ExternalLinksController(
 020        IExternalLinkService externalLinkService,
 021        ILogger<ExternalLinksController> logger)
 22    {
 023        _externalLinkService = externalLinkService;
 024        _logger = logger;
 025    }
 26
 27    /// <summary>
 28    /// GET /api/external-links/suggestions?worldId={worldId}&amp;source={source}&amp;query={query}
 29    /// Get external link suggestions for autocomplete.
 30    /// Filters to only include providers enabled for the specified world.
 31    /// </summary>
 32    [HttpGet("suggestions")]
 33    public async Task<ActionResult<List<ExternalLinkSuggestionDto>>> GetSuggestions(
 34        [FromQuery] Guid? worldId,
 35        [FromQuery] string? source,
 36        [FromQuery] string? query,
 37        CancellationToken ct)
 38    {
 039        if (string.IsNullOrWhiteSpace(source))
 40        {
 041            return Ok(new List<ExternalLinkSuggestionDto>());
 42        }
 43
 044        _logger.LogDebugSanitized(
 045            "Getting external link suggestions for world {WorldId}, source '{Source}' with query '{Query}'",
 046            worldId, source, query);
 47
 048        var suggestions = await _externalLinkService.GetSuggestionsAsync(worldId, source, query ?? "", ct);
 49
 050        var dtos = suggestions.Select(s => new ExternalLinkSuggestionDto
 051        {
 052            Source = s.Source,
 053            Id = s.Id,
 054            Title = s.Title,
 055            Subtitle = s.Subtitle,
 056            Category = s.Category,
 057            Icon = s.Icon,
 058            Href = s.Href
 059        }).ToList();
 60
 061        return Ok(dtos);
 062    }
 63
 64    /// <summary>
 65    /// GET /api/external-links/content?source={source}&amp;id={id}
 66    /// Get external link content for display.
 67    /// </summary>
 68    [HttpGet("content")]
 69    public async Task<ActionResult<ExternalLinkContentDto>> GetContent(
 70        [FromQuery] string? source,
 71        [FromQuery] string? id,
 72        CancellationToken ct)
 73    {
 074        if (string.IsNullOrWhiteSpace(source) || string.IsNullOrWhiteSpace(id))
 75        {
 076            return BadRequest(new ExternalLinkErrorDto { Message = "Source and id are required" });
 77        }
 78
 079        _logger.LogDebugSanitized(
 080            "Getting external link content for source '{Source}' with id '{Id}'",
 081            source, id);
 82
 083        var content = await _externalLinkService.GetContentAsync(source, id, ct);
 84
 085        if (content == null)
 86        {
 087            return NotFound(new ExternalLinkErrorDto { Message = "Content not found" });
 88        }
 89
 090        var dto = new ExternalLinkContentDto
 091        {
 092            Source = content.Source,
 093            Id = content.Id,
 094            Title = content.Title,
 095            Kind = content.Kind,
 096            Markdown = content.Markdown,
 097            Attribution = content.Attribution,
 098            ExternalUrl = content.ExternalUrl,
 099            JsonData = content.JsonData
 0100        };
 101
 0102        return Ok(dto);
 0103    }
 104}