Files
2025-05-01 07:20:41 +09:00

564 lines
23 KiB
C#

using Newtonsoft.Json;
using ServerCore; using ServerBase;
using ServerCommon;
using static ServerCommon.MetaHelper;
using META_ID = System.UInt32;
using Amazon.S3.Model;
namespace GameServer
{
public class AIChatAction : EntityActionBase
{
private string user_jwt = string.Empty;
public AIChatAction(Player owner)
: base(owner)
{
}
public override Task<Result> onInit()
{
var result = new Result();
return Task.FromResult(result);
}
public override void onClear()
{
user_jwt = string.Empty;
}
//-------------인증 JWT 관련 API-------------
//특정 유저의 JWT를 검증합니다.
public async Task<(Result, AIChatJwtInfo?)> jwtverify(string user_jwt)
{
var result = new Result();
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var server_logic = GameServerApp.getServerLogic();
if (server_logic.getServerConfig().OfflineMode == true)
{
result.setFail(ServerErrorCode.AiChatServerInactive);
return (result, null);
}
var url = $"/api/auth/jwt/verify";
(result, string resMsg) = await AIChatServerConnector.sendAIChatServer("GET", url, user_jwt, null);
if (result.isFail())
{
Log.getLogger().error($"Failed ai chat server action : jwtverify, msg : {resMsg}");
return (result, null);
}
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatJwtVerify);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
try
{
var aichat_jwt_info = JsonConvert.DeserializeObject<AIChatJwtInfo>(resMsg);
return (result, aichat_jwt_info);
}
catch(Exception ex)
{
Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}");
return (result, null);
}
}
//특정 유저의 JWT를 발행합니다.
public async Task<(Result, string?)> jwtIssue(string user_guid)
{
var result = new Result();
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var server_logic = GameServerApp.getServerLogic();
if (server_logic.getServerConfig().OfflineMode == true)
{
result.setFail(ServerErrorCode.AiChatServerInactive);
return (result, string.Empty);
}
var url = $"/api/auth/jwt/issue/{user_guid}";
var body = AIChatServerConnector.getUserJwtJson();
(result, string resMsg) = await AIChatServerConnector.sendAIChatServer("POST", url, null, body);
if (result.isFail())
{
Log.getLogger().error($"Failed ai chat server action : jwtIssue, msg : {resMsg}");
return (result, string.Empty);
}
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatJwtIssue);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
try
{
var ai_chat_issue_jwt = JsonConvert.DeserializeObject<AIChatIssueJwt>(resMsg);
NullReferenceCheckHelper.throwIfNull(ai_chat_issue_jwt, () => $"ai_chat_issue_jwt is null !!! - {toBasicString()}");
user_jwt = ai_chat_issue_jwt.jwt == null ? string.Empty : ai_chat_issue_jwt.jwt;
return (result, user_jwt);
}
catch (Exception ex)
{
Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}");
return (result, null);
}
}
//포인트 충전
public async Task<Result> pointCharge(AIChatPointCharge aIChatPointCharge)
{
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var url = $"/api/point/charge";
var body = JsonConvert.SerializeObject(aIChatPointCharge);
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("PUT", url, body);
if (result.isFail())
{
if (result.ErrorCode == ServerErrorCode.AiChatServerInactive)
return result;
result.setFail(ServerErrorCode.AiChatServerRetryChargePoint);
Log.getLogger().error($"Failed ai chat server action : pointCharge, msg : {resMsg}");
return result;
}
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatPointCharge);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
return result;
}
//포인트 충전 확인
public async Task<Result> pointChargeCheckByOrderGuid(string order_guid)
{
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var aIPointVerify = new AIChatPointVerify() { orderGuid = order_guid };
var url = $"/api/point/charge";
var body = JsonConvert.SerializeObject(aIPointVerify);
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("GET", url, body);
if (result.isFail()) return result;
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatPointChargeVerify);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
return result;
}
//어제까지의 벌어들인 미청구 포인트 조회
public async Task<(Result, AIChatPointClaimables?)> pointClaimables(int page, int num_per_page, string user_guid)
{
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var url = $"/api/point/claimables/{user_guid}?page={page}&numPerPage={num_per_page}";
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("GET", url, null);
if (result.isFail())
{
if (result.ErrorCode == ServerErrorCode.AiChatServerUserNotFound)
{
result = await registerUser(player.getUserGuid(), player.getUserNickname());
if (result.isFail())
{
return (result, null);
}
(result, resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("GET", url, null);
if (result.isFail())
{
return (result, null);
}
}
}
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatIncentiveSearch);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
try
{
var aichat_point_claim_ables = JsonConvert.DeserializeObject<AIChatPointClaimables>(resMsg);
return (result, aichat_point_claim_ables);
}
catch (Exception ex)
{
Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}");
return (result, null);
}
}
//인센티브 수령 완료 표시
public async Task<Result> pointMarkClaimed(string user_guid, int marking_day)
{
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"server_logic is null !!!");
var url = $"/api/point/mark-as-claimed/{user_guid}?aggregationEndTime={marking_day}";
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("POST", url, null);
if (result.isFail())
{
Log.getLogger().error($"Failed ai chat server action : pointMarkClaimed, msg : {resMsg}");
return result;
}
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatIncentiveMarking);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
return result;
}
//신규 유저 등록
public async Task<Result> registerUser(string user_guid, string name)
{
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var url = $"/api/user/{user_guid}";
var aIRegisterUser = new AIChatRegisterUser() { nick = name };
var body = JsonConvert.SerializeObject(aIRegisterUser);
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("POST", url, body);
if (result.isFail())
{
Log.getLogger().error($"Failed ai chat server action : registerUser, user_guid : {user_guid}, name : {name}, msg : {resMsg}");
return result;
}
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatRegisterUser);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
return result;
}
//유저 등록 제거
public async Task<Result> deleteUser(string user_guid)
{
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var url = $"/api/user/{user_guid}";
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("DELETE", url, null);
if (result.isFail()) return result;
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatDeleteUser);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
return result;
}
//특정 캐릭터 조회
public async Task<(Result, AIChatCharacter?)> getCharacterByTargetGuid(string target_guid)
{
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var url = $"/api/character/{target_guid}";
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("GET", url, null);
if (result.isFail()) return (result, null);
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatGetCharacter);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
try
{
var aichat_character = JsonConvert.DeserializeObject<AIChatCharacter>(resMsg);
return (result, aichat_character);
}
catch (Exception ex)
{
Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}");
return (result, null);
}
}
//-------------유저 권한 API-------------
//신규 캐릭터 등록
public async Task<Result> registerCharacter(AIChatRegisterCharacter aIChatRegisterCharacter)
{
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var url = $"/api/character";
var body = JsonConvert.SerializeObject(aIChatRegisterCharacter);
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("POST", url, body);
if (result.isFail())
{
Log.getLogger().error($"Failed ai chat server action : registerCharacter, msg : {resMsg}");
return result;
}
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatRegisterCharacter);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
return result;
}
//캐릭터 수정
public async Task<Result> updateCharacter(AIChatRegisterCharacter aIChatRegisterCharacter)
{
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var url = $"/api/character/locale/{aIChatRegisterCharacter.guid}";
var body = JsonConvert.SerializeObject(aIChatRegisterCharacter);
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("PUT", url, body);
if (result.isFail()) return result;
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatUpdateCharacter);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, body);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
return result;
}
//캐릭터 등록 제거
public async Task<Result> deleteCharacter(string character_guid)
{
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var url = $"/api/character/{character_guid}";
(var result, string resMsg) = await AIChatServerConnector.sendAIChatServerWithServerJwt("DELETE", url, null);
if (result.isFail()) return result;
var invokers = new List<ILogInvoker>();
var log_action = new LogActionEx(LogActionType.AIChatDeleteCharacter);
var task_log_data = AIChatBusinessLogHelper.toLogInfo(url, string.Empty);
invokers.Add(new AIChatBusinessLog(task_log_data));
BusinessLogger.collectLogs(log_action, player, invokers);
return result;
}
/// <summary>
/// 데이터 수집 기간 : 월요일 00:00:00 ~ 일요일 23:59:59(KST 기준 - UTC+9)
/// 인센티브 보상 지급 날짜 및 시각 : 매주 월요일 05:00 (KST 기준 - UTC+9)
/// </summary>
public async Task<Result> updateTickOfIncentivePoint()
{
var result = new Result();
var err_msg = string.Empty;
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var current_time = DateTimeHelper.Current;
var incentive_collect_time = current_time.AddDays(Convert.ToInt32(DayOfWeek.Monday) - Convert.ToInt32(current_time.DayOfWeek)).Date;
var incentive_provide_time = incentive_collect_time.AddHours(5);
var ai_chat_attribute = player.getEntityAttribute<AiChatAttribute>();
NullReferenceCheckHelper.throwIfNull(ai_chat_attribute, () => $"ai_chat_attribute is null !!! - {player.toBasicString()}");
var last_incentive_provide_time = ai_chat_attribute.LastIncentiveProvideTime;
if (last_incentive_provide_time != default ||
last_incentive_provide_time == incentive_provide_time ||
incentive_provide_time > current_time)
{
return result;
}
result = await TakeIncentivePoint(incentive_provide_time);
if(result.isFail()) return result;
return result;
}
public async Task<Result> TakeIncentivePoint(DateTime new_incentive_provide_time)
{
var result = new Result();
var err_msg = string.Empty;
var player = getOwner() as Player;
NullReferenceCheckHelper.throwIfNull(player, () => $"player is null !!!");
var server_logic = GameServerApp.getServerLogic();
var dynamo_db_client = server_logic.getDynamoDbClient();
var mail_action = player.getEntityAction<MailAction>();
NullReferenceCheckHelper.throwIfNull(mail_action, () => $"mail_action is null !!!");
var ai_chat_attribute = player.getEntityAttribute<AiChatAttribute>();
NullReferenceCheckHelper.throwIfNull(ai_chat_attribute, () => $"ai_chat_attribute is null !!! - {player.toBasicString()}");
if (MetaData.Instance._CurrencyMetaTableByCurrencyType.TryGetValue(CurrencyType.Beam, out var currencyMetaData) == false)
{
result.setFail(ServerErrorCode.CurrencyNotFoundData, err_msg);
return result;
}
(result, var pointClaim) = await pointClaimables(0, 100, player.getUserGuid());
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(pointClaim, () => $"pointClaim is null !!! - {toBasicString()}");
if (pointClaim.items.Count == 0)
{
ai_chat_attribute.LastIncentiveProvideTime = new_incentive_provide_time;
ai_chat_attribute.modifiedEntityAttribute();
(result, var ai_chat_doc) = await ai_chat_attribute.toDocBase();
if (result.isFail()) return result;
NullReferenceCheckHelper.throwIfNull(ai_chat_doc, () => $"ai_chat_doc is null !!! - {player.toBasicString()}");
result = await dynamo_db_client.simpleUpdateDocumentWithDocType(ai_chat_doc);
if (result.isFail())
{
err_msg = $"Failed to simpleUpdateDocumentWithDocType ai_chat_doc !!! - {player.toBasicString()}";
Log.getLogger().error(err_msg);
return result;
}
return result;
}
var IncentivePointList = new List<int>();
int maxPoint = GameConfigMeta.AiChatInsentiveMax;
int last_incentive_period = 0;
foreach (var pointInfo in pointClaim.items)
{
int amount = pointInfo.amount;
if(maxPoint < amount)
{
amount = maxPoint;
}
IncentivePointList.Add(amount);
if(last_incentive_period < pointInfo.end_time)
{
last_incentive_period = pointInfo.end_time;
}
}
var fn_send_system_mail = async delegate ()
{
var result = new Result();
var err_msg = string.Empty;
var receivedMailDocs = new List<DynamoDbDocBase>();
foreach (var amount in IncentivePointList)
{
var mail_items = new List<ServerCommon.MailItem>() { new ServerCommon.MailItem() { ItemId = (META_ID)currencyMetaData.ItemId, Count = amount } };
(result, var receivedMailDoc) = await mail_action.tryMakeNewSystemMail(mail_items, ServerCommon.Constant.NPC_INSENTIVE_META_KEY, GameConfigMeta.AiChatInsentivePeriod, string.Empty);
if (result.isFail())
{
return result;
}
NullReferenceCheckHelper.throwIfNull(receivedMailDoc, () => $"receivedMailDoc is null !!! - {toBasicString()}");
receivedMailDocs.Add(receivedMailDoc);
}
ai_chat_attribute.LastIncentiveProvideTime = new_incentive_provide_time;
var batch = new QueryBatchEx<QueryRunnerWithDocument>(player, LogActionType.MailAiChatIncentivePoint
, dynamo_db_client);
{
batch.addQuery(new DBQEntityWrite(receivedMailDocs));
batch.addQuery(new DBQWriteToAttributeAllWithTransactionRunner());
}
result = await QueryHelper.sendQueryAndBusinessLog(batch);
if (result.isFail())
{
return result;
}
result = await pointMarkClaimed(player.getUserGuid(), last_incentive_period);
if (result.isFail())
{
return result;
}
mail_action.NewReceivedMail();
return result;
};
var transaction_name = "provideIncentivePoint";
result = await player.runTransactionRunnerSafelyWithTransGuid(player.getUserGuid()
, TransactionIdType.PrivateContents, transaction_name
, fn_send_system_mail);
if (result.isFail())
{
err_msg = $"Failed to runTransactionRunnerSafelyWithTransGuid() !!! : {result.toBasicString()} - transactionName:{transaction_name}, {player.toBasicString()}";
Log.getLogger().error(err_msg);
}
return result;
}
}
}