Files
caliverse_server/UGQApiServer/Controllers/Common/QuestEditorApi.cs
2025-05-01 07:20:41 +09:00

476 lines
19 KiB
C#
Raw Blame History

using System.Globalization;
using Asp.Versioning;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using MongoDB.Bson.Serialization.Attributes;
using Swashbuckle.AspNetCore.Annotations;
using Swashbuckle.AspNetCore.Filters;
using UGQApiServer.Models;
using UGQDatabase.Models;
using UGQDataAccess.Service;
using UGQApiServer.Converter;
using UGQApiServer.Storage;
using UGQDataAccess.Repository.Models;
using Microsoft.AspNetCore.Authorization;
using UGQDataAccess;
using UGQApiServer.Validation;
using UGQApiServer.UGQData;
using UGQApiServer.Auth;
using JwtRoleAuthentication.Services;
using System.Security.Claims;
using Newtonsoft.Json.Linq;
using ServerCommon;
using ServerBase;
using ServerCommon.UGQ;
using ServerCommon.UGQ.Models;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.IdentityModel.Tokens;
using System.Collections.Generic;
namespace UGQApiServer.Controllers.Common;
public class QuestEditorApi
{
QuestEditorService _questEditorService;
UGQMetaData _ugqMetaData;
DynamoDbClient _dynamoDbClient;
IStorageService _storageService;
public QuestEditorApi(QuestEditorService questEditorService,
UGQMetaData ugqMetaData, DynamoDbClient dynamoDbClient,
IStorageService storageService)
{
_questEditorService = questEditorService;
_ugqMetaData = ugqMetaData;
_dynamoDbClient = dynamoDbClient;
_storageService = storageService;
}
public async Task<IResult> addQuest(string userGuid, UGQSaveQuestModel saveQuestModel, string adminUsername = "")
{
if (string.IsNullOrEmpty(saveQuestModel.UgcBeaconGuid) == false)
{
(Result result, List<UgcNpcAttrib>? ugcNpcs) =
await EntitySearchHelper.findUgcNpcAttribAllByUserGuid(_dynamoDbClient, userGuid, "");
if (result.isFail())
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqGameDbaccessError));
if (ugcNpcs == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqGameDbaccessError));
UgcNpcAttrib? found = ugcNpcs.Where(x => x.UgcNpcMetaGuid == saveQuestModel.UgcBeaconGuid).FirstOrDefault();
if (found == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNotOwnUgcNpc));
saveQuestModel.UgcBeaconNickname = found.Nickname;
}
foreach (var task in saveQuestModel.Tasks)
{
if (string.IsNullOrEmpty(task.UgcActionValueGuid) == false)
{
(Result result, List<UgcNpcAttrib>? ugcNpcs) =
await EntitySearchHelper.findUgcNpcAttribAllByUserGuid(_dynamoDbClient, userGuid, "");
if (result.isFail())
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqGameDbaccessError));
if (ugcNpcs == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqGameDbaccessError));
UgcNpcAttrib? found = ugcNpcs.Where(x => x.UgcNpcMetaGuid == task.UgcActionValueGuid).FirstOrDefault();
if (found == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNotOwnUgcNpc));
task.UgcActionValueName = found.Nickname;
}
}
(ServerErrorCode errorCode, var entity) = await _questEditorService.addQuest(userGuid, saveQuestModel, adminUsername);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (entity == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(entity.ToDTO(langEnum));
}
public async Task<IResult> getQuest(string userGuid, string questContentId)
{
(ServerErrorCode errorCode, var entity) = await _questEditorService.getQuest(userGuid, questContentId);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (entity == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(entity.ToDTO(langEnum));
}
public async Task<IResult> editQuest(string userGuid, string questContentId)
{
(ServerErrorCode errorCode, var entity) = await _questEditorService.editQuest(userGuid, questContentId);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (entity == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(entity.ToDTO(langEnum));
}
public async Task<IResult> saveQuest(string userGuid, string questContentId, UGQSaveQuestModel saveQuestModel)
{
if (string.IsNullOrEmpty(saveQuestModel.UgcBeaconGuid) == false)
{
(Result result, List<UgcNpcAttrib>? ugcNpcs) =
await EntitySearchHelper.findUgcNpcAttribAllByUserGuid(_dynamoDbClient, userGuid, "");
if (result.isFail())
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqGameDbaccessError));
if (ugcNpcs == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqGameDbaccessError));
UgcNpcAttrib? found = ugcNpcs.Where(x => x.UgcNpcMetaGuid == saveQuestModel.UgcBeaconGuid).FirstOrDefault();
if (found == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNotOwnUgcNpc));
saveQuestModel.UgcBeaconNickname = found.Nickname;
}
foreach (var task in saveQuestModel.Tasks)
{
if (string.IsNullOrEmpty(task.UgcActionValueGuid) == false)
{
(Result result, List<UgcNpcAttrib>? ugcNpcs) =
await EntitySearchHelper.findUgcNpcAttribAllByUserGuid(_dynamoDbClient, userGuid, "");
if (result.isFail())
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqGameDbaccessError));
if (ugcNpcs == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqGameDbaccessError));
UgcNpcAttrib? found = ugcNpcs.Where(x => x.UgcNpcMetaGuid == task.UgcActionValueGuid).FirstOrDefault();
if (found == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNotOwnUgcNpc));
task.UgcActionValueName = found.Nickname;
}
}
(ServerErrorCode errorCode, var updated) = await _questEditorService.saveQuest(userGuid, questContentId, saveQuestModel);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (updated == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(updated.ToDTO(langEnum));
}
public async Task<IResult> deleteQuest(string userGuid, string questContentId)
{
var errorCode = await _questEditorService.deleteQuest(userGuid, questContentId);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
return Results.Ok();
}
public async Task<IResult> uploadQuestImage(string userGuid, string questContentId,
int titleImageId, int bannerImageId,
IFormFile? title, IFormFile? banner)
{
(ServerErrorCode errorCode, var entity) = await _questEditorService.editQuest(userGuid, questContentId);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (entity == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
string titleFile = entity.TitleImagePath;
string bannerFile = entity.BannerImagePath;
List<string> deleteFiles = new();
if (titleImageId != 0)
{
var data = _ugqMetaData.getPresetImage(titleImageId);
if (data != null)
titleFile = data.FileName;
}
else
{
if (title != null)
{
FileInfo fileInfo = new FileInfo(title.FileName);
(errorCode, int uploadCounter) = await _questEditorService.incUploadCounter(userGuid, questContentId);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
string filename = $"{questContentId}_title_{uploadCounter}{fileInfo.Extension}";
await _storageService.uploadFile(filename, title);
if (string.IsNullOrEmpty(entity.TitleImagePath) == false &&
entity.TitleImagePath.StartsWith("preset/") == false)
deleteFiles.Add(entity.TitleImagePath);
titleFile = filename;
}
}
if (bannerImageId != 0)
{
var data = _ugqMetaData.getPresetImage(bannerImageId);
if (data != null)
bannerFile = data.FileName;
}
else
{
if (banner != null)
{
FileInfo fileInfo = new FileInfo(banner.FileName);
(errorCode, int uploadCounter) = await _questEditorService.incUploadCounter(userGuid, questContentId);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
string filename = $"{questContentId}_banner_{uploadCounter}{fileInfo.Extension}";
await _storageService.uploadFile(filename, banner);
if (string.IsNullOrEmpty(entity.BannerImagePath) == false &&
entity.BannerImagePath.StartsWith("preset/") == false)
deleteFiles.Add(entity.BannerImagePath);
bannerFile = filename;
}
}
(errorCode, var updated) = await _questEditorService.updateQuestImages(questContentId, titleFile, bannerFile);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (updated == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
foreach (var file in deleteFiles)
await _storageService.deleteFile(file);
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(updated.ToDTO(langEnum));
}
public async Task<IResult> getQuestDialog(string userGuid, string questContentId, string dialogId)
{
(ServerErrorCode errorCode, var entity) = await _questEditorService.getQuestDialog(userGuid, questContentId, dialogId);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (entity == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(entity.ToDTO(langEnum));
}
public async Task<IResult> addQuestDialog(string userGuid, string questContentId, int taskIndex, UGQSaveDialogModel questDialog)
{
var sequences = questDialog.Sequences.Select(x => new DialogSequenceEntity
{
SequenceId = x.SequenceId,
Actions = x.Actions.Select(x => new DialogSequenceActionEntity
{
Talker = x.Talker,
Type = x.Type,
Talk = new TextEntity
{
Kr = x.Talk.Kr,
En = x.Talk.En,
Jp = x.Talk.Jp,
},
NpcAction = x.NpcAction,
Condition = x.Condition,
ConditionValue = x.ConditionValue,
NextSequence = x.NextSequence,
}).ToList(),
}).ToList();
(ServerErrorCode errorCode, var updated, var inserted) = await _questEditorService.addQuestDialog(userGuid, questContentId, taskIndex, sequences);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (updated == null || inserted == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(new UGQAddQuestDialogResponse
{
QuestContent = updated.ToDTO(langEnum),
QuestDialog = inserted.ToDTO(langEnum),
});
}
public async Task<IResult> saveQuestDialog(string userGuid, string questContentId, string dialogId, [FromBody] UGQSaveDialogModel questDialog)
{
var sequences = questDialog.Sequences.Select(x => new DialogSequenceEntity
{
SequenceId = x.SequenceId,
Actions = x.Actions.Select(x => new DialogSequenceActionEntity
{
Talker = x.Talker,
Type = x.Type,
Talk = new TextEntity
{
Kr = x.Talk.Kr,
En = x.Talk.En,
Jp = x.Talk.Jp,
},
NpcAction = x.NpcAction,
Condition = x.Condition,
ConditionValue = x.ConditionValue,
NextSequence = x.NextSequence,
}).ToList(),
}).ToList();
(ServerErrorCode errorCode, var updated) = await _questEditorService.saveQuestDialog(userGuid, questContentId, dialogId, sequences);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (updated == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(updated.ToDTO(langEnum));
}
List<QuestContentState> getAvailablesState(QuestContentState state)
{
List<QuestContentState> availables = [];
switch (state)
{
case QuestContentState.Editable:
availables = [
QuestContentState.Test,
QuestContentState.Standby,
QuestContentState.Shutdown
];
break;
case QuestContentState.Uncomplate:
case QuestContentState.Test:
availables = [
QuestContentState.Editable
];
break;
case QuestContentState.Standby:
availables = [
QuestContentState.Live
];
break;
case QuestContentState.Live:
availables = [
QuestContentState.Standby
];
break;
case QuestContentState.Shutdown:
availables = [];
break;
}
return availables;
}
public async Task<IResult> changeQuestState(string userGuid, string questContentId, QuestContentState state, string adminUsername = "")
{
(ServerErrorCode errorCode, var questContentEntity) = await _questEditorService.getQuest(userGuid, questContentId);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (questContentEntity == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
// admin<69><6E> <20><><EFBFBD><EFBFBD> <20><><EFBFBD>Ѿ<EFBFBD><D1BE><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>ϵ<EFBFBD><CFB5><EFBFBD> ó<><C3B3> - Uncomplate <20><><EFBFBD><EFBFBD><C2B6><EFBFBD> <20><><EFBFBD><EFBFBD> <20>Ұ<EFBFBD><D2B0><EFBFBD>
List<QuestContentState> before = [];
if (string.IsNullOrEmpty(adminUsername) == false)
{
before = [
QuestContentState.Editable,
QuestContentState.Test,
QuestContentState.Standby,
QuestContentState.Live,
QuestContentState.Shutdown,
];
}
else
{
before = getAvailablesState(state);
}
if (before.Any(x => x == questContentEntity.State) == false)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqStateChangeError));
QuestContentEntity? updated = null;
var questDialogIds = questContentEntity.Tasks
.Where(x => string.IsNullOrEmpty(x.DialogId) == false)
.Select(x => x.DialogId!)
.ToList();
var questDialogs = await _questEditorService.getQuestDialogs(questDialogIds);
if (state == QuestContentState.Test)
{
UGQValidator validator = new UGQValidator(_ugqMetaData);
var errors = validator.Validate(questContentEntity, questDialogs);
if (errors.Count > 0)
{
return Results.BadRequest(
ApiResponseFactory.validationError(ServerErrorCode.UgqValidationError,
errors.Select(x => x.ToString()).ToList()));
}
}
(errorCode, updated) = await _questEditorService.changeQuestStateForEditor(userGuid,
questContentEntity, questDialogs, before, state, adminUsername);
if (errorCode != ServerErrorCode.Success)
return Results.BadRequest(ApiResponseFactory.error(errorCode));
if (updated == null)
return Results.BadRequest(ApiResponseFactory.error(ServerErrorCode.UgqNullEntity));
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(updated.ToDTO(langEnum));
}
public async Task<IResult> getCreatorPointHistory(string userGuid, int pageNumber, int pageSize, CreatorPointHistoryKind kind, DateTimeOffset startDate, DateTimeOffset endDate)
{
pageSize = Math.Clamp(pageSize, 1, UGQConstants.MAX_INPUT_PAGE_SIZE);
var result = await _questEditorService.getCreatorPointHistories(
userGuid, pageNumber, pageSize, kind, startDate, endDate);
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(result.ToDTO(langEnum));
}
public async Task<IResult> getQuestProfitStats(string userGuid, int pageNumber, int pageSize)
{
pageSize = Math.Clamp(pageSize, 1, UGQConstants.MAX_INPUT_PAGE_SIZE);
var result = await _questEditorService.getQuestProfitStats(userGuid, pageNumber, pageSize);
LangEnum langEnum = Culture.ToLangEnum(CultureInfo.CurrentCulture.Name);
return Results.Ok(new UGQQuestProfitStatsResult
{
PageNumber = result.PageNumber,
PageSize = result.PageSize,
TotalPages = result.TotalPages,
Items = result.Items.Select(x => x.ToDTO(langEnum)).ToList()
});
}
}