181 lines
6.4 KiB
C#
181 lines
6.4 KiB
C#
using DramaLing.Api.Models.DTOs;
|
||
using DramaLing.Api.Services;
|
||
using Microsoft.AspNetCore.Authorization;
|
||
using Microsoft.AspNetCore.Mvc;
|
||
using System.Security.Claims;
|
||
|
||
namespace DramaLing.Api.Controllers;
|
||
|
||
[Route("api/[controller]")]
|
||
[ApiController]
|
||
[AllowAnonymous] // 暫時移除認證要求,與 FlashcardsController 保持一致
|
||
public class ImageGenerationController : ControllerBase
|
||
{
|
||
private readonly IImageGenerationOrchestrator _orchestrator;
|
||
private readonly ILogger<ImageGenerationController> _logger;
|
||
|
||
public ImageGenerationController(
|
||
IImageGenerationOrchestrator orchestrator,
|
||
ILogger<ImageGenerationController> logger)
|
||
{
|
||
_orchestrator = orchestrator ?? throw new ArgumentNullException(nameof(orchestrator));
|
||
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
|
||
}
|
||
|
||
/// <summary>
|
||
/// 為指定詞卡生成例句圖片
|
||
/// </summary>
|
||
/// <param name="flashcardId">詞卡 ID</param>
|
||
/// <param name="request">生成請求參數</param>
|
||
/// <returns>生成請求結果</returns>
|
||
[HttpPost("flashcards/{flashcardId}/generate")]
|
||
public async Task<IActionResult> GenerateImage(
|
||
Guid flashcardId,
|
||
[FromBody] GenerationRequest request)
|
||
{
|
||
try
|
||
{
|
||
var userId = GetCurrentUserId();
|
||
request.UserId = userId;
|
||
|
||
_logger.LogInformation("Starting image generation for flashcard {FlashcardId} by user {UserId}",
|
||
flashcardId, userId);
|
||
|
||
var result = await _orchestrator.StartGenerationAsync(flashcardId, request);
|
||
|
||
return Ok(new { success = true, data = result });
|
||
}
|
||
catch (ArgumentException ex)
|
||
{
|
||
_logger.LogWarning(ex, "Invalid request for flashcard {FlashcardId}", flashcardId);
|
||
return BadRequest(new { success = false, error = ex.Message });
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "Failed to start image generation for flashcard {FlashcardId}", flashcardId);
|
||
return StatusCode(500, new { success = false, error = "Failed to start generation" });
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 獲取圖片生成狀態
|
||
/// </summary>
|
||
/// <param name="requestId">生成請求 ID</param>
|
||
/// <returns>生成狀態詳情</returns>
|
||
[HttpGet("requests/{requestId}/status")]
|
||
public async Task<IActionResult> GetGenerationStatus(Guid requestId)
|
||
{
|
||
try
|
||
{
|
||
var userId = GetCurrentUserId();
|
||
_logger.LogInformation("Getting generation status for request {RequestId} by user {UserId}",
|
||
requestId, userId);
|
||
|
||
var status = await _orchestrator.GetGenerationStatusAsync(requestId);
|
||
|
||
return Ok(new { success = true, data = status });
|
||
}
|
||
catch (ArgumentException ex)
|
||
{
|
||
_logger.LogWarning(ex, "Generation request {RequestId} not found", requestId);
|
||
return NotFound(new { success = false, error = ex.Message });
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "Failed to get status for request {RequestId}", requestId);
|
||
return StatusCode(500, new { success = false, error = "Failed to get status" });
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 取消圖片生成請求
|
||
/// </summary>
|
||
/// <param name="requestId">生成請求 ID</param>
|
||
/// <returns>取消結果</returns>
|
||
[HttpPost("requests/{requestId}/cancel")]
|
||
public async Task<IActionResult> CancelGeneration(Guid requestId)
|
||
{
|
||
try
|
||
{
|
||
var userId = GetCurrentUserId();
|
||
_logger.LogInformation("Cancelling generation request {RequestId} by user {UserId}",
|
||
requestId, userId);
|
||
|
||
var cancelled = await _orchestrator.CancelGenerationAsync(requestId);
|
||
|
||
if (cancelled)
|
||
{
|
||
return Ok(new { success = true, message = "Generation cancelled successfully" });
|
||
}
|
||
else
|
||
{
|
||
return BadRequest(new { success = false, error = "Cannot cancel this request" });
|
||
}
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "Failed to cancel generation request {RequestId}", requestId);
|
||
return StatusCode(500, new { success = false, error = "Failed to cancel generation" });
|
||
}
|
||
}
|
||
|
||
/// <summary>
|
||
/// 獲取用戶的圖片生成歷史
|
||
/// </summary>
|
||
/// <param name="page">頁碼</param>
|
||
/// <param name="pageSize">每頁數量</param>
|
||
/// <returns>生成歷史列表</returns>
|
||
[HttpGet("history")]
|
||
public async Task<IActionResult> GetGenerationHistory(
|
||
[FromQuery] int page = 1,
|
||
[FromQuery] int pageSize = 20)
|
||
{
|
||
try
|
||
{
|
||
var userId = GetCurrentUserId();
|
||
|
||
// TODO: 實現分頁查詢邏輯
|
||
// 暫時返回空列表
|
||
var history = new
|
||
{
|
||
requests = new List<object>(),
|
||
pagination = new
|
||
{
|
||
currentPage = page,
|
||
pageSize = pageSize,
|
||
totalCount = 0,
|
||
totalPages = 0
|
||
}
|
||
};
|
||
|
||
return Ok(new { success = true, data = history });
|
||
}
|
||
catch (Exception ex)
|
||
{
|
||
_logger.LogError(ex, "Failed to get generation history for user");
|
||
return StatusCode(500, new { success = false, error = "Failed to get history" });
|
||
}
|
||
}
|
||
|
||
private Guid GetCurrentUserId()
|
||
{
|
||
// 暫時使用固定測試用戶 ID,與 FlashcardsController 保持一致
|
||
return Guid.Parse("E0A7DFA1-6B8A-4BD8-812C-54D7CBFAA394");
|
||
|
||
// TODO: 恢復真實認證後改回 JWT Token 解析
|
||
// var userIdClaim = User.FindFirst(ClaimTypes.NameIdentifier)?.Value
|
||
// ?? User.FindFirst("sub")?.Value;
|
||
//
|
||
// if (string.IsNullOrEmpty(userIdClaim))
|
||
// {
|
||
// throw new UnauthorizedAccessException("User ID not found in token");
|
||
// }
|
||
//
|
||
// if (!Guid.TryParse(userIdClaim, out var userId))
|
||
// {
|
||
// throw new UnauthorizedAccessException("Invalid user ID format in token");
|
||
// }
|
||
//
|
||
// return userId;
|
||
}
|
||
} |