using System; using System.Text.Json; using Expedience.Api.Encryption; using Expedience.Infrastructure; using Expedience.Infrastructure.Models; using MassTransit; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; namespace Expedience.Api.Controllers { [Route("api")] [ApiController] public class ExpedienceController : ControllerBase { private readonly ILogger _logger; private readonly IPublishEndpoint _publisher; private readonly IDecryptor _decrypytor; private readonly IServiceScopeFactory _serviceScopeFactory; public ExpedienceController(ILogger logger, IPublishEndpoint publisher, IDecryptor decrypytor, IServiceScopeFactory serviceScopeFactory) { _logger = logger; _publisher = publisher; _decrypytor = decrypytor; _serviceScopeFactory = serviceScopeFactory; } [HttpPost("DutyCompletion")] public async Task PostDutyCompletionResult(List encryptedPayloads) { var utcNow = DateTime.UtcNow; try { foreach (var payload in encryptedPayloads) { var decryptedData = _decrypytor.Decrypt(payload); var completionResult = JsonSerializer.Deserialize(decryptedData)!; completionResult.UploadDateUtc = utcNow; await _publisher.Publish(completionResult); } } catch (Exception ex) { _logger.LogError(ex, "Error publishing completion result: {errorMessage}", ex.Message); } return Ok(); } [HttpGet("UserName/{worldId}/{userHash}")] public async Task GetUserName(int worldId, string userHash, CancellationToken cancellationToken) { try { using var scope = _serviceScopeFactory.CreateScope(); using var dbContext = scope.ServiceProvider.GetRequiredService(); var user = await dbContext.Users.FirstOrDefaultAsync(x => x.UserHash == userHash && x.WorldId == worldId, cancellationToken); if (user != null) return Ok(user.UserName); else return NotFound(); } catch (Exception ex) { _logger.LogError(ex, "Error obtaining user name for World Id {worldId} and hash {userHash}: {errorMessage}", worldId, userHash, ex.Message); } return StatusCode(500); } [HttpGet("DutyCompletionRecords/{expac}")] public async Task GetDutyCompletionRecords(string expac, CancellationToken cancellationToken) { try { using var scope = _serviceScopeFactory.CreateScope(); var repository = scope.ServiceProvider.GetService(); var results = await repository.GetDutyCompletionRecords(expac, cancellationToken); return Ok(results); } catch (Exception ex) { _logger.LogError(ex, "Error getting Duty Completion Records for {expac}: {errorMessage}", expac, ex.Message); } return StatusCode(500); } [HttpGet("DeepDungeonRecords")] public async Task GetDeepDungeonRecords(CancellationToken cancellationToken) { try { using var scope = _serviceScopeFactory.CreateScope(); var repository = scope.ServiceProvider.GetService(); var results = await repository.GetDeepDungeonRecords(cancellationToken); return Ok(results); } catch (Exception ex) { _logger.LogError(ex, "Error getting Deep Dungeon Records: {errorMessage}", ex.Message); } return StatusCode(500); } [HttpGet("TopX/{recordType}/{territoryId}/{limit}")] public async Task GetTopXRecords(int recordType, int territoryId, int limit, CancellationToken cancellationToken) { try { using var scope = _serviceScopeFactory.CreateScope(); var repository = scope.ServiceProvider.GetService(); var records = await repository.GetTopXRecords(recordType, territoryId, limit, cancellationToken); var results = new List(); foreach (var record in records) { var dcr = record.DutyCompletionResult; var territory = record.Territory; var user = record.User; var dutyCompletionResult = new DutyCompletionResult { Id = dcr.Id, UserId = user.UserId, TerritoryId = territory.TerritoryId, IsMinILevel = recordType == 3, HasNpcMembers = recordType == 4, StartTime = dcr.StartTime, EndTime = dcr.EndTime, Hours = dcr.Hours, Minutes = dcr.Minutes, Seconds = dcr.Seconds, Milliseconds = dcr.Milliseconds, GameVersion = dcr.GameVersion, PluginVersion = dcr.PluginVersion, Lang = dcr.Lang, UploadedAt = dcr.UploadedAt, DutyMembers = record.DutyMembers.Select(dm => new DutyMember { ClassJob = dm.ClassJob, IsNpc = dm.IsNpc, IsPlayer = dm.IsPlayer, Level = dm.Level, GroupNumber = dm.GroupNumber, MemberNumber = dm.MemberNumber, }).ToList(), Territory = new Models.Territory { TerritoryId = dcr.TerritoryId, PlaceName = territory.PlaceName, ContentId = String.Empty, ContentName = territory.ContentName, ContentType = territory.ContentType, Expac = territory.Expac, Level = territory.Level, }, User = new User { UserId = user.UserId, UserName = user.UserName, UserHash = String.Empty, WorldId = user.WorldId, }, DataCenter = dcr.DataCenter, }; results.Add(dutyCompletionResult); } return Ok(results); } catch (Exception ex) { _logger.LogError(ex, "Error getting Top X Records: {errorMessage}", ex.Message); } return StatusCode(500); } } }