초기커밋
This commit is contained in:
314
GameServer/Global/AIChat/AIChatServerConnector.cs
Normal file
314
GameServer/Global/AIChat/AIChatServerConnector.cs
Normal file
@@ -0,0 +1,314 @@
|
||||
using Org.BouncyCastle.Crypto.Parameters;
|
||||
using Org.BouncyCastle.Crypto.Signers;
|
||||
using ServerCommon;
|
||||
using System.Text;
|
||||
using ServerCore; using ServerBase;
|
||||
using System.Text.Json.Nodes;
|
||||
using Newtonsoft.Json;
|
||||
using MetaAssets;
|
||||
using META_ID = System.UInt32;
|
||||
|
||||
namespace GameServer
|
||||
{
|
||||
static public class AIChatServerConnector
|
||||
{
|
||||
static string server_jwt = string.Empty;
|
||||
static string? jwtAdminJson = null;
|
||||
static string? jwtUserJson = null;
|
||||
|
||||
static public async Task onInit()
|
||||
{
|
||||
var messageBytes = MakeMessage("admin");
|
||||
var signatureBytes = SignMessage(messageBytes);
|
||||
|
||||
AIChatJwt AIChatAdminJwt = new AIChatJwt();
|
||||
AIChatAdminJwt.messageBase64 = Convert.ToBase64String(messageBytes);
|
||||
AIChatAdminJwt.signatureBase64 = Convert.ToBase64String(signatureBytes);
|
||||
|
||||
jwtAdminJson = JsonConvert.SerializeObject(AIChatAdminJwt);
|
||||
|
||||
messageBytes = MakeMessage("user");
|
||||
signatureBytes = SignMessage(messageBytes);
|
||||
|
||||
AIChatJwt AIChatUserJwt = new AIChatJwt();
|
||||
AIChatUserJwt.messageBase64 = Convert.ToBase64String(messageBytes);
|
||||
AIChatUserJwt.signatureBase64 = Convert.ToBase64String(signatureBytes);
|
||||
|
||||
jwtUserJson = JsonConvert.SerializeObject(AIChatUserJwt);
|
||||
|
||||
await serverJwtIssue();
|
||||
|
||||
await RegisterGeneralNPC();
|
||||
}
|
||||
|
||||
static public string getUserJwtJson()
|
||||
{
|
||||
NullReferenceCheckHelper.throwIfNull(jwtUserJson, () => $"jwtUserJson is null !!!");
|
||||
return jwtUserJson;
|
||||
}
|
||||
|
||||
//서버의 JWT를 발행합니다.
|
||||
static private async Task<Result> serverJwtIssue()
|
||||
{
|
||||
(var result, string resMsg) = await sendAIChatServer("POST", $"/api/auth/jwt/issue", null, jwtAdminJson);
|
||||
if (result.isFail()) return result;
|
||||
|
||||
var jwt = JsonNode.Parse(resMsg)?["jwt"]?.ToString();
|
||||
if (jwt != null)
|
||||
{
|
||||
server_jwt = jwt;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
//전체 채팅량 랭킹 (매개변수인 languageType은 res로 받는 캐릭터 이름이나 owner의 이름의 번역 차이임.)
|
||||
static public async Task<(Result, AIChatRanking?)> getAllRanking(LanguageType language, int page, int numPerPage)
|
||||
{
|
||||
(var result, string resMsg) = await sendAIChatServerWithServerJwt("GET", $"/api/ranking/all?lang={language.ToString().ToLower()}&page={page}&numPerPage={numPerPage}", null);
|
||||
if (result.isFail()) return (result, null);
|
||||
|
||||
try
|
||||
{
|
||||
var aichat_ranking = JsonConvert.DeserializeObject<AIChatRanking>(resMsg);
|
||||
return (result, aichat_ranking);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}");
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
//최근 24시간 채팅량 랭킹 (매개변수인 languageType은 res로 받는 캐릭터 이름이나 owner의 이름의 번역 차이임.)
|
||||
static public async Task<(Result, AIChatRanking?)> getTodayRanking(LanguageType language, int page, int numPerPage)
|
||||
{
|
||||
(var result, string resMsg) = await sendAIChatServerWithServerJwt("GET", $"/api/ranking/today?lang={language.ToString().ToLower()}&page={page}&numPerPage={numPerPage}", null);
|
||||
if (result.isFail()) return (result, null);
|
||||
|
||||
try
|
||||
{
|
||||
var aichat_ranking = JsonConvert.DeserializeObject<AIChatRanking>(resMsg);
|
||||
return (result, aichat_ranking);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Log.getLogger().error($"Exception !!!, DeserializeObject : exception:{ex}, resMsg:{resMsg}");
|
||||
return (result, null);
|
||||
}
|
||||
}
|
||||
|
||||
//특정 캐릭터 조회
|
||||
static public async Task<(Result, AIChatCharacter?)> getCharacterByTargetGuid(string target_guid)
|
||||
{
|
||||
(var result, string resMsg) = await sendAIChatServerWithServerJwt("GET", $"/api/character/{target_guid}", null);
|
||||
if (result.isFail()) return (result, null);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
static private byte[] MakeMessage(string role)
|
||||
{
|
||||
var message = "{\"role\":\"" + role + "\"}";
|
||||
var messageBytes = Encoding.UTF8.GetBytes(message);
|
||||
return messageBytes;
|
||||
}
|
||||
|
||||
static private byte[] SignMessage(byte[] messageBytes)
|
||||
{
|
||||
var privateKey = Convert.FromBase64String(GameServerApp.getServerLogic().getServerConfig().AIChatConfig.PrivateKey);
|
||||
var privateKeyParams = new Ed25519PrivateKeyParameters(privateKey, 0);
|
||||
|
||||
// 서명합니다.
|
||||
var signer = new Ed25519Signer();
|
||||
signer.Init(true, privateKeyParams);
|
||||
signer.BlockUpdate(messageBytes, 0, messageBytes.Length);
|
||||
var signature = signer.GenerateSignature();
|
||||
return signature;
|
||||
}
|
||||
|
||||
static public async Task<(Result, string)> sendAIChatServerWithServerJwt(string httpMethod, string url, string? bodyJson)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
if (server_logic.getServerConfig().OfflineMode == true)
|
||||
{
|
||||
result.setFail(ServerErrorCode.AiChatServerInactive);
|
||||
return (result, string.Empty);
|
||||
}
|
||||
|
||||
var fullUrl = makeAiChatServerURL(url);
|
||||
|
||||
(var IsSuccessStatusCode, var readMsg) = await HttpClientHelper.sendHttpRequest( httpMethod
|
||||
, fullUrl, server_jwt, bodyJson
|
||||
, "application/json"
|
||||
, "caliverse", "1.0" );
|
||||
if (IsSuccessStatusCode == false)
|
||||
{
|
||||
Log.getLogger().info($"sendAIChatServer Failed. fullUrl : {fullUrl}, return msg : {readMsg} !!!");
|
||||
|
||||
result = ErrorHelper(readMsg, fullUrl);
|
||||
if (result.ErrorCode == ServerErrorCode.AiChatServerTokenExpired)
|
||||
{
|
||||
result = await serverJwtIssue();
|
||||
if (result.isSuccess())
|
||||
{
|
||||
(IsSuccessStatusCode, readMsg) = await HttpClientHelper.sendHttpRequest( httpMethod
|
||||
, fullUrl, server_jwt, bodyJson
|
||||
, "application/json"
|
||||
, "caliverse", "1.0" );
|
||||
if (IsSuccessStatusCode == false)
|
||||
result.setFail(ServerErrorCode.AiChatServerTokenExpired);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (result, readMsg);
|
||||
}
|
||||
|
||||
static public async Task<(Result, string)> sendAIChatServer(string httpMethod, string url, string? jwt, string? bodyJson)
|
||||
{
|
||||
var result = new Result();
|
||||
|
||||
var server_logic = GameServerApp.getServerLogic();
|
||||
if (server_logic.getServerConfig().OfflineMode == true)
|
||||
{
|
||||
result.setFail(ServerErrorCode.AiChatServerInactive);
|
||||
return (result, string.Empty);
|
||||
}
|
||||
|
||||
var fullUrl = makeAiChatServerURL(url);
|
||||
|
||||
(var IsSuccessStatusCode, var readMsg) = await HttpClientHelper.sendHttpRequest( httpMethod
|
||||
, fullUrl, jwt, bodyJson
|
||||
, "application/json"
|
||||
, "caliverse", "1.0" );
|
||||
if (IsSuccessStatusCode == false)
|
||||
{
|
||||
Log.getLogger().info($"sendAIChatServer Failed. fullUrl : {fullUrl}, return msg : {readMsg} !!!");
|
||||
|
||||
result = ErrorHelper(readMsg, fullUrl);
|
||||
return (result, readMsg);
|
||||
}
|
||||
|
||||
return (result, readMsg);
|
||||
}
|
||||
|
||||
static public string makeAiChatServerURL(string url)
|
||||
{
|
||||
return $"{GameServerApp.getServerLogic().getServerConfig().AIChatConfig.BaseAddress}{url}";
|
||||
}
|
||||
|
||||
static private Result ErrorHelper(string errorMsg, string fullUrl)
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
try
|
||||
{
|
||||
AIChatError? error = JsonConvert.DeserializeObject<AIChatError>(errorMsg);
|
||||
NullReferenceCheckHelper.throwIfNull(error, () => $"error is null !!!");
|
||||
|
||||
switch (error.code)
|
||||
{
|
||||
case 998: result.setFail(ServerErrorCode.AiChatServerBadrequest, err_msg); break;
|
||||
case 999: result.setFail(ServerErrorCode.AiChatServerForbidden, err_msg); break;
|
||||
case 1000: result.setFail(ServerErrorCode.AiChatServerUnauthorized, err_msg); break;
|
||||
case 1001: result.setFail(ServerErrorCode.AiChatServerUserNotFound, err_msg); break;
|
||||
case 1002: result.setFail(ServerErrorCode.AiChatServerCharacterNotFound, err_msg); break;
|
||||
case 1003: result.setFail(ServerErrorCode.AiChatServerReactionNotFound, err_msg); break;
|
||||
case 1004: result.setFail(ServerErrorCode.AiChatServerExampleDialongNotFound, err_msg); break;
|
||||
case 1005: result.setFail(ServerErrorCode.AiChatServerSessionNotFound, err_msg); break;
|
||||
case 1006: result.setFail(ServerErrorCode.AiChatServerModelNotFound, err_msg); break;
|
||||
case 1007: result.setFail(ServerErrorCode.AiChatServerNotEnoughPoint, err_msg); break;
|
||||
case 1008: result.setFail(ServerErrorCode.AiChatServerInvalidParameters, err_msg); break;
|
||||
case 1009: result.setFail(ServerErrorCode.AiChatServerSessionLimitExceeded, err_msg); break;
|
||||
case 1010: result.setFail(ServerErrorCode.AiChatServerInvalidSignature, err_msg); break;
|
||||
case 1011: result.setFail(ServerErrorCode.AiChatServerUserAlreadyExists, err_msg); break;
|
||||
case 1012: result.setFail(ServerErrorCode.AiChatServerRemoveFailed, err_msg); break;
|
||||
case 1013: result.setFail(ServerErrorCode.AiChatServerDuplicateGuid, err_msg); break;
|
||||
case 1014: result.setFail(ServerErrorCode.AiChatServerDuplicateId, err_msg); break;
|
||||
case 1015: result.setFail(ServerErrorCode.AiChatServerChatNotFound, err_msg); break;
|
||||
case 1016: result.setFail(ServerErrorCode.AiChatServerTokenExpired, err_msg); break;
|
||||
case 1017: result.setFail(ServerErrorCode.AiChatServerInternalServer, err_msg); break;
|
||||
case 1018: result.setFail(ServerErrorCode.AiChatServerInvalidMessage, err_msg); break;
|
||||
case 1019: result.setFail(ServerErrorCode.AiChatServerUserOnlyFeature, err_msg); break;
|
||||
case 1020: result.setFail(ServerErrorCode.AiChatServerOwnershipError, err_msg); break;
|
||||
|
||||
case 1024: result.setFail(ServerErrorCode.AiChatServerChargeOrderNotFoundError, err_msg); break;
|
||||
default:
|
||||
{
|
||||
err_msg = $"sendAIChatServer Failed. fullUrl : {fullUrl}, error code : {error.code}, error name : {error.name}, error message : {error.message} !!!";
|
||||
result.setFail(ServerErrorCode.AiChatServerReqFailed, err_msg);
|
||||
Log.getLogger().info(err_msg);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
err_msg = $"AiChat Exception message : {ex.Message}";
|
||||
result.setFail(ServerErrorCode.AiChatServerReqFailed, err_msg);
|
||||
Log.getLogger().info(err_msg);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static private async Task<Result> RegisterGeneralNPC()
|
||||
{
|
||||
var result = new Result();
|
||||
var err_msg = string.Empty;
|
||||
|
||||
List<string> npclist = new();
|
||||
|
||||
var npcGeneralMetaDatas = MetaData.Instance.NpcGeneralMetaData;
|
||||
|
||||
foreach (var generalNpc in npcGeneralMetaDatas)
|
||||
{
|
||||
(result, var ai_chat_character) = await getCharacterByTargetGuid(generalNpc.Value.Npc_id.ToString());
|
||||
if (result.isSuccess())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
EGenderType gender = EGenderType.MALE;
|
||||
if(generalNpc.Value.Gender == EGenderType.ALL)
|
||||
gender = EGenderType.MALE;
|
||||
|
||||
AIChatRegisterCharacter to_register_ai_chat_server = new();
|
||||
to_register_ai_chat_server.guid = generalNpc.Value.Npc_id.ToString();
|
||||
to_register_ai_chat_server.ownerUserGuid = string.Empty;
|
||||
to_register_ai_chat_server.lang = generalNpc.Value.Language.ToString().ToLower();
|
||||
to_register_ai_chat_server.name = generalNpc.Value.Name;
|
||||
to_register_ai_chat_server.persona = UgcNpcHelper.toPersonaWithJsonString(generalNpc.Value.WorldScenario, generalNpc.Value.Description);
|
||||
to_register_ai_chat_server.firstMes = generalNpc.Value.FirstMes;
|
||||
to_register_ai_chat_server.shortDesc = generalNpc.Value.ShortDesc;
|
||||
to_register_ai_chat_server.tags = generalNpc.Value.Tags.Select(x => (META_ID)x).ToList();
|
||||
to_register_ai_chat_server.isOfficial = true;
|
||||
to_register_ai_chat_server.socialActionConfig = UgcNpcHelper.toSocialActionConfigWithAIChatServer((META_ID)generalNpc.Value.SocialAction_default, generalNpc.Value.SocialAction_habit.Select(x => (META_ID)x).ToList());
|
||||
to_register_ai_chat_server.attributes.gender = (int)gender;
|
||||
|
||||
string json = JsonConvert.SerializeObject(to_register_ai_chat_server);
|
||||
var bodyParam = new StringContent(json, Encoding.UTF8, "application/json");
|
||||
|
||||
(result, string resMsg) = await sendAIChatServerWithServerJwt("POST", $"/api/character", json);
|
||||
if (result.isFail())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user