diff --git a/backend/DramaLing.Api/Controllers/AIController.cs b/backend/DramaLing.Api/Controllers/AIController.cs
index f5870dd..b39d99b 100644
--- a/backend/DramaLing.Api/Controllers/AIController.cs
+++ b/backend/DramaLing.Api/Controllers/AIController.cs
@@ -7,6 +7,7 @@ using System.Diagnostics;
namespace DramaLing.Api.Controllers;
[Route("api/ai")]
+[AllowAnonymous]
public class AIController : BaseController
{
private readonly IAnalysisService _analysisService;
@@ -24,7 +25,6 @@ public class AIController : BaseController
/// 分析請求
/// 分析結果
[HttpPost("analyze-sentence")]
- [AllowAnonymous]
public async Task AnalyzeSentence(
[FromBody] SentenceAnalysisRequest request)
{
@@ -33,11 +33,7 @@ public class AIController : BaseController
try
{
- // For testing without auth - use dummy user ID
- var userId = "test-user-id";
-
- _logger.LogInformation("Processing sentence analysis request {RequestId} for user {UserId}",
- requestId, userId);
+ _logger.LogInformation("Processing sentence analysis request {RequestId}", requestId);
// Input validation
if (!ModelState.IsValid)
@@ -86,7 +82,6 @@ public class AIController : BaseController
/// 健康檢查端點
///
[HttpGet("health")]
- [AllowAnonymous]
public IActionResult GetHealth()
{
var healthData = new
@@ -104,7 +99,6 @@ public class AIController : BaseController
/// 取得分析統計資訊
///
[HttpGet("stats")]
- [AllowAnonymous]
public async Task GetAnalysisStats()
{
try
diff --git a/backend/DramaLing.Api/Controllers/AnalysisController.cs b/backend/DramaLing.Api/Controllers/AnalysisController.cs
deleted file mode 100644
index e8d7b4f..0000000
--- a/backend/DramaLing.Api/Controllers/AnalysisController.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Authorization;
-using DramaLing.Api.Models.DTOs;
-using DramaLing.Api.Services;
-using System.Diagnostics;
-
-namespace DramaLing.Api.Controllers;
-
-[Route("api/analysis")]
-[AllowAnonymous]
-public class AnalysisController : BaseController
-{
- private readonly IAnalysisService _analysisService;
-
- public AnalysisController(
- IAnalysisService analysisService,
- ILogger logger) : base(logger)
- {
- _analysisService = analysisService;
- }
-
- ///
- /// 智能分析英文句子
- ///
- /// 分析請求
- /// 分析結果
- [HttpPost("analyze")]
- public async Task AnalyzeSentence([FromBody] SentenceAnalysisRequest request)
- {
- var requestId = Guid.NewGuid().ToString();
- var stopwatch = Stopwatch.StartNew();
-
- try
- {
- // Input validation
- if (!ModelState.IsValid)
- {
- return HandleModelStateErrors();
- }
-
- _logger.LogInformation("Processing sentence analysis request {RequestId}", requestId);
-
- // 使用帶快取的分析服務
- var options = request.Options ?? new AnalysisOptions();
- var analysisData = await _analysisService.AnalyzeSentenceAsync(
- request.InputText, options);
-
- stopwatch.Stop();
- analysisData.Metadata.ProcessingDate = DateTime.UtcNow;
-
- _logger.LogInformation("Sentence analysis completed for request {RequestId} in {ElapsedMs}ms",
- requestId, stopwatch.ElapsedMilliseconds);
-
- var response = new SentenceAnalysisResponse
- {
- Success = true,
- ProcessingTime = stopwatch.Elapsed.TotalSeconds,
- Data = analysisData
- };
-
- return SuccessResponse(response);
- }
- catch (ArgumentException ex)
- {
- _logger.LogWarning(ex, "Invalid input for request {RequestId}", requestId);
- return ErrorResponse("INVALID_INPUT", ex.Message, null, 400);
- }
- catch (InvalidOperationException ex)
- {
- _logger.LogError(ex, "AI service error for request {RequestId}", requestId);
- return ErrorResponse("AI_SERVICE_ERROR", "AI服務暫時不可用", null, 500);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Unexpected error processing request {RequestId}", requestId);
- return ErrorResponse("INTERNAL_ERROR", "伺服器內部錯誤", null, 500);
- }
- }
-
- ///
- /// 健康檢查端點
- ///
- [HttpGet("health")]
- public IActionResult GetHealth()
- {
- var healthData = new
- {
- Status = "Healthy",
- Service = "Analysis Service",
- Timestamp = DateTime.UtcNow,
- Version = "1.0"
- };
-
- return SuccessResponse(healthData);
- }
-
- ///
- /// 取得分析統計資訊
- ///
- [HttpGet("stats")]
- public async Task GetAnalysisStats()
- {
- try
- {
- var stats = await _analysisService.GetAnalysisStatsAsync();
- var statsData = new
- {
- TotalAnalyses = stats.TotalAnalyses,
- CachedAnalyses = stats.CachedAnalyses,
- CacheHitRate = stats.CacheHitRate,
- AverageResponseTimeMs = stats.AverageResponseTimeMs,
- LastAnalysisAt = stats.LastAnalysisAt,
- ProviderUsage = stats.ProviderUsageStats
- };
-
- return SuccessResponse(statsData);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error getting analysis stats");
- return ErrorResponse("INTERNAL_ERROR", "無法取得統計資訊");
- }
- }
-}
\ No newline at end of file
diff --git a/backend/DramaLing.Api/Controllers/AudioController.cs b/backend/DramaLing.Api/Controllers/AudioController.cs
deleted file mode 100644
index 132733e..0000000
--- a/backend/DramaLing.Api/Controllers/AudioController.cs
+++ /dev/null
@@ -1,218 +0,0 @@
-using Microsoft.AspNetCore.Mvc;
-using Microsoft.AspNetCore.Authorization;
-using DramaLing.Api.Models.Dtos;
-using DramaLing.Api.Services;
-
-namespace DramaLing.Api.Controllers;
-
-[Route("api/[controller]")]
-[Authorize]
-public class AudioController : BaseController
-{
- private readonly IAudioCacheService _audioCacheService;
- private readonly IAzureSpeechService _speechService;
-
- public AudioController(
- IAudioCacheService audioCacheService,
- IAzureSpeechService speechService,
- ILogger logger) : base(logger)
- {
- _audioCacheService = audioCacheService;
- _speechService = speechService;
- }
-
- ///
- /// Generate audio from text using TTS
- ///
- /// TTS request parameters
- /// Audio URL and metadata
- [HttpPost("tts")]
- public async Task GenerateAudio([FromBody] TTSRequest request)
- {
- try
- {
- if (string.IsNullOrWhiteSpace(request.Text))
- {
- return BadRequest(new TTSResponse
- {
- Error = "Text is required"
- });
- }
-
- if (request.Text.Length > 1000)
- {
- return BadRequest(new TTSResponse
- {
- Error = "Text is too long (max 1000 characters)"
- });
- }
-
- if (!IsValidAccent(request.Accent))
- {
- return BadRequest(new TTSResponse
- {
- Error = "Invalid accent. Use 'us' or 'uk'"
- });
- }
-
- if (request.Speed < 0.5f || request.Speed > 2.0f)
- {
- return BadRequest(new TTSResponse
- {
- Error = "Speed must be between 0.5 and 2.0"
- });
- }
-
- var response = await _audioCacheService.GetOrCreateAudioAsync(request);
-
- if (!string.IsNullOrEmpty(response.Error))
- {
- return ErrorResponse("TTS_ERROR", response.Error, null, 500);
- }
-
- return SuccessResponse(response);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error generating audio for text: {Text}", request.Text);
- return StatusCode(500, new TTSResponse
- {
- Error = "Internal server error"
- });
- }
- }
-
- ///
- /// Get cached audio by hash
- ///
- /// Audio cache hash
- /// Cached audio URL
- [HttpGet("tts/cache/{hash}")]
- public async Task> GetCachedAudio(string hash)
- {
- try
- {
- // 實現快取查詢邏輯
- // 這裡應該從資料庫查詢快取的音頻
- return NotFound(new TTSResponse
- {
- Error = "Audio not found in cache"
- });
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error retrieving cached audio: {Hash}", hash);
- return StatusCode(500, new TTSResponse
- {
- Error = "Internal server error"
- });
- }
- }
-
- ///
- /// Evaluate pronunciation from uploaded audio
- ///
- /// Audio file
- /// Target text for pronunciation
- /// User's CEFR level
- /// Pronunciation assessment results
- [HttpPost("pronunciation/evaluate")]
- public async Task> EvaluatePronunciation(
- IFormFile audioFile,
- [FromForm] string targetText,
- [FromForm] string userLevel = "B1")
- {
- try
- {
- if (audioFile == null || audioFile.Length == 0)
- {
- return BadRequest(new PronunciationResponse
- {
- Error = "Audio file is required"
- });
- }
-
- if (string.IsNullOrWhiteSpace(targetText))
- {
- return BadRequest(new PronunciationResponse
- {
- Error = "Target text is required"
- });
- }
-
- // 檢查檔案大小 (最大 10MB)
- if (audioFile.Length > 10 * 1024 * 1024)
- {
- return BadRequest(new PronunciationResponse
- {
- Error = "Audio file is too large (max 10MB)"
- });
- }
-
- // 檢查檔案類型
- var allowedTypes = new[] { "audio/wav", "audio/mp3", "audio/mpeg", "audio/ogg" };
- if (!allowedTypes.Contains(audioFile.ContentType))
- {
- return BadRequest(new PronunciationResponse
- {
- Error = "Invalid audio format. Use WAV, MP3, or OGG"
- });
- }
-
- using var audioStream = audioFile.OpenReadStream();
- var request = new PronunciationRequest
- {
- TargetText = targetText,
- UserLevel = userLevel
- };
-
- var response = await _speechService.EvaluatePronunciationAsync(audioStream, request);
-
- if (!string.IsNullOrEmpty(response.Error))
- {
- return StatusCode(500, response);
- }
-
- return Ok(response);
- }
- catch (Exception ex)
- {
- _logger.LogError(ex, "Error evaluating pronunciation for text: {Text}", targetText);
- return StatusCode(500, new PronunciationResponse
- {
- Error = "Internal server error"
- });
- }
- }
-
- ///
- /// Get supported voices for TTS
- ///
- /// List of available voices
- [HttpGet("voices")]
- public ActionResult