476 lines
19 KiB
C#
476 lines
19 KiB
C#
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()
|
||
});
|
||
}
|
||
}
|
||
|
||
|