초기커밋

This commit is contained in:
2025-05-01 07:20:41 +09:00
commit 98bb2e3c5c
2747 changed files with 646947 additions and 0 deletions

View File

@@ -0,0 +1,508 @@
using System.Net;
using System.Net.Http.Json;
using System.Security.Cryptography;
using System.Text;
using System.Xml.Linq;
using Amazon.Runtime.Internal.Endpoints.StandardLibrary;
using Google.Protobuf.WellKnownTypes;
using Microsoft.AspNetCore.Mvc.Formatters;
using Microsoft.Extensions.Hosting;
using Newtonsoft.Json;
using Org.BouncyCastle.Asn1.Ocsp;
using ServerCore; using ServerBase;
using ServerCommon;
using ServerCommon.UGQ.Models;
using UGQDatabase.Models;
namespace GameServer
{
public class UgqApiManager
{
HttpClient http_client = new();
string url_prefix = string.Empty;
private static readonly object lock_object = new object();
private static bool is_task_running = false;
private static Task? inspection_check_task = null;
private static Int32 api_server_check_state = 0; //0이면 서버 정상 상태, -1이면 서버 죽거나 ip주소 바뀌어서 접속 안되는 상태
private const Int32 inspection_state = -1;
private const Int32 active_state = 0;
private const string connection_test_str = "connection-test";
public async Task onInit()
{
await Task.CompletedTask;
http_client.BaseAddress = new Uri(GameServerApp.getServerLogic().getServerConfig().UgqApiServerConfig.ApiServerAddress);
url_prefix = GameServerApp.getServerLogic().getServerConfig().UgqApiServerConfig.UrlInGamePrefix;
}
public async Task<Result> checkConnection()
{
(var result, var ret) = await sendUgqRequestToApiServer<UgqBoardSearchResult>(http_client, HttpMethod.Get, connection_test_str, new(), string.Empty);
return (result);
}
public async Task<(Result, UgqBoardSearchResult?)> getPagedGradeUgqFromBoard(Dictionary<string, string> dictionaries, LanguageType langType)
{
string url_str = $"quest-board?";
var url_builder_str = makeGetParamString(url_str, dictionaries);
var headers = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(langType);
(var result, var ret) = await sendUgqRequestToApiServer<UgqBoardSearchResult>(http_client, HttpMethod.Get, url_builder_str, headers, string.Empty);
return (result, ret);
}
public async Task<(Result, UgqBoardItemDetail?)> getUgqDetailFromBoard(Dictionary<string, string> dictionaries, string userGuid, LanguageType langType)
{
string url_str = $"quest-board-detail/{userGuid}?";
var url_builder_str = makeGetParamString(url_str, dictionaries);
var headers = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(langType);
(var result, var ret) = await sendUgqRequestToApiServer<UgqBoardItemDetail>(http_client, HttpMethod.Get, url_builder_str, headers, string.Empty);
return (result, ret);
}
public async Task<(Result, UgqBoardSportlightResult?)> getPagedSpotLightUgqFromBoard(Dictionary<string, string> dictionaries)
{
(var result, var ret) = await sendUgqRequestToApiServer<UgqBoardSportlightResult>(http_client, HttpMethod.Get, "quest-board-spotlight", dictionaries, string.Empty);
return (result, ret);
}
public async Task<(Result, UgqBoardSearchResult?)> getPagedBookmarkUgqFromBoard(Dictionary<string, string> dictionaries, string userGuid)
{
string url_str = $"bookmark-quest-board/{userGuid}?";
var url_builder_str = makeGetParamString(url_str, dictionaries);
(var result, var ret) = await sendUgqRequestToApiServer<UgqBoardSearchResult>(http_client, HttpMethod.Get, url_builder_str, dictionaries, string.Empty);
return (result, ret);
}
public async Task<Result> ugqRegisterBookmark(Dictionary<string, string> dict, UInt32 questId, string userGuid)
{
UgqBookmarkRequest request = new();
request.QuestId = questId;
request.UserGuid = userGuid;
(var result, var _) = await sendUgqRequestToApiServer<object>(http_client, HttpMethod.Post, $"bookmark", dict, JsonConvert.SerializeObject(request));
return result;
}
public async Task<Result> ugqDeRegisterBookmark(Dictionary<string, string> dict, UInt32 questId, string userGuid)
{
UgqUnbookmarkRequest request = new();
request.QuestId = questId;
request.UserGuid = userGuid;
(var result, var _) = await sendUgqRequestToApiServer<object>(http_client, HttpMethod.Post, $"unbookmark", dict, JsonConvert.SerializeObject(request));
return result;
}
public async Task<Result> ugqRegisterLike(Dictionary<string, string> dict, UInt32 questId, UInt32 questRevision, string userGuid)
{
UgqLikeRequest request = new();
request.QuestId = questId;
request.Revision = questRevision;
request.UserGuid = userGuid;
(var result, var _) = await sendUgqRequestToApiServer<object>(http_client, HttpMethod.Post, $"like", dict, JsonConvert.SerializeObject(request));
return result;
}
public async Task<Result> setUgqQuestAccepted(string userGuid, UInt32 questId, UInt32 QuestRevision, LanguageType langType)
{
var dict = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(langType);
UgqQuestAcceptedRequest request = new();
request.QuestId = questId;
request.Revision = QuestRevision;
request.Reason = UGQAcceptReason.Player;
string url_str = $"set-quest-accepted/{userGuid}";
(var result, var _) = await sendUgqRequestToApiServer<object>(http_client, HttpMethod.Post, url_str, dict, JsonConvert.SerializeObject(request));
return result;
}
public async Task<Result> setTestUgqQuestCompleted(string userGuid, UInt32 questId, UInt32 QuestRevision, LanguageType langType)
{
var dict = UgqApiHelper.makeDictionaryForUgqQuestId(questId, QuestRevision);
string url_str = $"set-test-completed/{userGuid}?";
var url_builder_str = makeGetParamString(url_str, dict);
var headers = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(langType);
(var result, var _) = await sendUgqRequestToApiServer<UgqBoardItemDetail>(http_client, HttpMethod.Post, url_builder_str, headers, string.Empty);
return result;
}
public async Task<Result> setTestUgqQuestAborted(string userGuid, UInt32 questId, UInt32 QuestRevision, LanguageType langType)
{
var dict = UgqApiHelper.makeDictionaryForUgqQuestId(questId, QuestRevision);
string url_str = $"set-test-aborted/{userGuid}?";
var url_builder_str = makeGetParamString(url_str, dict);
var headers = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(langType);
(var result, var _) = await sendUgqRequestToApiServer<UgqBoardItemDetail>(http_client, HttpMethod.Post, url_builder_str, headers, string.Empty);
return result;
}
public async Task<Result> setUgqQuestCompleted(string userGuid, UInt32 questId, UInt32 QuestRevision, Int32 amount, LanguageType langType)
{
var dict = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(langType);
UgqQuestCompletedRequest request = new();
request.QuestId = questId;
request.Revision = QuestRevision;
request.Amount = amount;
string url_str = $"set-quest-completed/{userGuid}";
(var result, var _) = await sendUgqRequestToApiServer<object>(http_client, HttpMethod.Post, url_str, dict, JsonConvert.SerializeObject(request));
return result;
}
public async Task<Result> setUgqQuestAborted(string userGuid, UInt32 questId, UInt32 QuestRevision, UGQAbortReason reason, LanguageType langType)
{
var dict = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(langType);
UgqQuestAbortedRequest request = new();
request.QuestId = questId;
request.Revision = QuestRevision;
request.Reason = reason;
string url_str = $"set-quest-aborted/{userGuid}";
(var result, var _) = await sendUgqRequestToApiServer<object>(http_client, HttpMethod.Post, url_str, dict, JsonConvert.SerializeObject(request));
return result;
}
public async Task<Result> ugqDeregisterLike(Dictionary<string, string> dict, UInt32 questId, UInt32 questRevision, string userGuid)
{
UgqUnlikeRequest request = new();
request.QuestId = questId;
request.Revision = questRevision;
request.UserGuid = userGuid;
var req_param = JsonContent.Create(new { questId = questId, revision = questRevision, userGuid = userGuid });
(var result, var _) = await sendUgqRequestToApiServer<object>(http_client, HttpMethod.Post, $"unlike", dict, JsonConvert.SerializeObject(request));
return result;
}
public async Task<Result> ugqReport(Dictionary<string, string> dict, UInt32 questId, UInt32 questRevision, string userGuid, string reportText)
{
UgqReportRequest request = new();
request.QuestId = questId;
request.Revision = questRevision;
request.UserGuid = userGuid;
request.Contents = reportText;
var req_param = JsonContent.Create(new { questId = questId, revision = questRevision, userGuid = userGuid, contents = reportText });
(var result, var _) = await sendUgqRequestToApiServer<object>(http_client, HttpMethod.Post, $"report", dict, JsonConvert.SerializeObject(request));
return result;
}
public async Task<(Result, GameQuestDataEntity?)> getUgqQuestData(string userGuid, UInt32 questId, UInt32 questRevision, LanguageType langType)
{
var dictionaries = UgqApiHelper.makeDictionaryForUgqQuestId(questId, questRevision);
string url_str = $"game-quest-data?";
var url_builder_str = makeGetParamString(url_str, dictionaries);
var headers = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(langType);
(var result, var ret) = await sendUgqRequestToApiServer<GameQuestDataEntity>(http_client, HttpMethod.Get, url_builder_str, headers, string.Empty);
return (result, ret);
}
public async Task<(Result, List<UgqQuestInTestState>?)> getTestUgqIds(string userGuid, LanguageType languageType)
{
string url_str = $"user-quests-in-test-state/{userGuid}";
var dictionaries = UgqApiHelper.makeDictionaryFromLanguageType(languageType);
(var result, var ret) = await sendUgqRequestToApiServer<List<UgqQuestInTestState>>(http_client, HttpMethod.Get, url_str, dictionaries, string.Empty);
return (result, ret);
}
public async Task<(Result, GameQuestDataEntity?)> getUgqTestQuestData(string userGuid, UInt32 questId, UInt32 questRevision, LanguageType langType)
{
var dictionaries = UgqApiHelper.makeDictionaryForUgqQuestId(questId, questRevision);
string url_str = $"test-game-quest-data/{userGuid}?";
var url_builder_str = makeGetParamString(url_str, dictionaries);
var headers = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(langType);
(var result, var ret) = await sendUgqRequestToApiServer<GameQuestDataEntity>(http_client, HttpMethod.Get, url_builder_str, headers, string.Empty);
return (result, ret);
}
public async Task<(Result, GameQuestDataEntity?)> getUgqLatestQuestData(UInt32 questId, LanguageType langType)
{
var dictionaries = UgqApiHelper.makeDictionaryForQuestId(questId, langType);
string url_str = $"latest-revision-game-quest-data?";
var url_builder_str = makeGetParamString(url_str, dictionaries);
var headers = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(langType);
(var result, var ret) = await sendUgqRequestToApiServer<GameQuestDataEntity>(http_client, HttpMethod.Get, url_builder_str, headers, string.Empty);
return (result, ret);
}
public async Task<(Result, GameQuestDataSimple?)> getUgqQuestSimpleInfo(UInt32 questId, UInt32 questRevision, QuestContentState state)
{
var dictionaries = UgqApiHelper.makeDictionaryForUgqByState(questId, questRevision, state);
string url_str = $"game-quest-data-simple?";
var url_builder_str = makeGetParamString(url_str, dictionaries);
(var result, var ret) = await sendUgqRequestToApiServer<GameQuestDataSimple>(http_client, HttpMethod.Get, url_builder_str, new(), string.Empty);
return (result, ret);
}
public async Task<(Result, GameQuestDataEntity?)> requestBeginCreatorPoint(string userGuid, Int32 cost, Int32 questId, Int32 questRevision, LanguageType languageType)
{
var result = new Result();
if (cost == 0)
{
return (result, new());
}
var dictionaries = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(languageType);
string url_str = $"begin-creator-point";
BeginCreatorPointRequest request = new();
request.UserGuid = userGuid;
request.Point = cost;
//여기 제네릭 나중에 영수증 response로 처리 해야된다.
(result, var ret) = await sendUgqRequestToApiServer<GameQuestDataEntity>(http_client, HttpMethod.Post, url_str, dictionaries, JsonConvert.SerializeObject(request));
return (result, ret);
}
public async Task<(Result, GameQuestDataEntity?)> requestCommitCreatorPoint(string userGuid, string receipt, LanguageType languageType)
{
var dictionaries = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(languageType);
string url_str = $"commit-creator-point";
CommitCreatorPointRequest request = new();
request.UserGuid = userGuid;
request.ReceiptId = receipt;
(var result, var ret) = await sendUgqRequestToApiServer<GameQuestDataEntity>(http_client, HttpMethod.Post, url_str, dictionaries, JsonConvert.SerializeObject(request));
return (result, ret);
}
public async Task<(Result, GameQuestDataEntity?)> requestCancelCreatorPoint(string userGuid, string receipt, string reason, LanguageType languageType)
{
var dictionaries = UgqApiHelper.makeDictionaryFromLanguageTypeWithMediaType(languageType);
string url_str = $"cancel-creator-point";
CancelCreatorPointRequest request = new();
request.UserGuid = userGuid;
request.ReceiptId = receipt;
request.CancelReason = reason;
(var result, GameQuestDataEntity? ret) = await sendUgqRequestToApiServer<GameQuestDataEntity>(http_client, HttpMethod.Post, url_str, dictionaries, JsonConvert.SerializeObject(request));
return (result, ret);
}
private async Task<(Result, T?)> sendUgqRequestToApiServer<T>(HttpClient httpClient, HttpMethod method, string url, Dictionary<string, string> headers, string reqBodyString)
where T : class
{
var result = new Result();
var err_msg = string.Empty;
//점검 상태면 여기서 리턴
if (api_server_check_state == inspection_state && !url.Equals(connection_test_str))
{
err_msg = $"UgqApiServer Inspection State. Exception !!!";
result.setFail(ServerErrorCode.UgqApiServerHttpRequestException, err_msg);
Log.getLogger().error(result.toBasicString());
return (result, null);
}
HttpRequestMessage requestMessage = new HttpRequestMessage(method, $"{url_prefix}/{url}");
foreach (var header in headers)
{
requestMessage.Headers.Add(header.Key, header.Value);
}
if (reqBodyString != string.Empty)
{
var stringContent = new StringContent(reqBodyString, UnicodeEncoding.UTF8, "application/json");
requestMessage.Content = stringContent;
}
var content_string = string.Empty;
try
{
var resMsg = await httpClient.SendAsync(requestMessage);
if (resMsg.IsSuccessStatusCode == false)
{
if (resMsg.StatusCode == HttpStatusCode.BadRequest)
{
content_string = await resMsg.Content.ReadAsStringAsync();
if (string.IsNullOrWhiteSpace(content_string))
{
err_msg =
$"UgqApiServerRequestFailed Failed. content_string : resMsg.StatusCode : {resMsg.StatusCode}, reason : {resMsg.ReasonPhrase} !!!, url : {url}";
result.setFail(ServerErrorCode.UgqApiServerRequestFailed, err_msg);
Log.getLogger().info(err_msg);
}
else
{
result = makeErrorResult(content_string);
}
return (result, null);
}
err_msg =
$"UgqApiServerRequestFailed Failed. resMsg.StatusCode : content_string : {content_string}, {resMsg.StatusCode}, reason : {resMsg.ReasonPhrase} !!!, url : {url}";
result.setFail(ServerErrorCode.UgqApiServerRequestFailed, err_msg);
Log.getLogger().info(err_msg);
return (result, null);
}
content_string = await resMsg.Content.ReadAsStringAsync();
if (string.IsNullOrWhiteSpace(content_string))
{
return (result, null);
}
}
catch (Exception e)
{
err_msg = $"UgqApiServerRequestFailed Failed. Exception !!!, {e.Message}";
result.setFail(ServerErrorCode.UgqApiServerHttpRequestException, err_msg);
Log.getLogger().error(result.toBasicString());
//서버죽었으므로 여기서 점검 상태로 변경
StartChangeInspectStateTask();
//await changeInspectState();
return (result, null);
}
var contect_template = JsonConvert.DeserializeObject<T>(content_string);
if (null == contect_template)
{
err_msg = $"UgqApiServerRequest Serialize Failed. content_string : {content_string} !!!, url : {url}";
result.setFail(ServerErrorCode.UgqApiServerConvertToObjectFailed, err_msg);
Log.getLogger().info(err_msg);
return (result, null);
}
return (result, contect_template);
}
private void StartChangeInspectStateTask()
{
lock (lock_object)
{
if (is_task_running)
return; // 이미 실행 중인 작업이 있으면 아무것도 하지 않음
is_task_running = true;
inspection_check_task = Task.Run(async () =>
{
try
{
await changeInspectState();
}
finally
{
is_task_running = false; // 작업이 완료된 후 상태 업데이트
}
});
}
}
private async Task changeInspectState()
{
api_server_check_state = inspection_state;
while (true)
{
// 1분 대기
await Task.Delay(TimeSpan.FromMinutes(1));
var result = new Result();
result = await checkConnection();
if (result.isFail() && result.getErrorCode() == ServerErrorCode.UgqApiServerHttpRequestException)
{
Log.getLogger().error($"ugq api server inpection recheck still error changed");
}
else
{
//그렇지 않으면 정상 이니까 상태 변경
api_server_check_state = active_state;
Log.getLogger().error($"ugq api server inpection request success !! api_server_check_state : {api_server_check_state}");
break;
}
}
}
private Result makeErrorResult(string content_string)
{
var result = new Result();
try
{
var response_result = JsonConvert.DeserializeObject<ApiErrorResponse>(content_string);
NullReferenceCheckHelper.throwIfNull(response_result, () => $"response_result is null !!!");
result.setFail((ServerErrorCode)response_result.ErrorCode, response_result.ErrorMessage);
}
catch (Exception e)
{
var err_msg = $"UgqApiServerRequest Serialize Failed. content_string : {e}, {content_string} !!!";
result.setFail(ServerErrorCode.UgqApiServerConvertToObjectFailed, err_msg);
Log.getLogger().info(err_msg);
return result;
}
return result;
}
private string makeGetParamString(string prefixUrl, Dictionary<string, string> dictionaries)
{
StringBuilder url_builder = new StringBuilder(prefixUrl);
int count = dictionaries.Count;
int index = 0;
foreach (var dict in dictionaries)
{
url_builder.Append($"{dict.Key}={dict.Value}");
if (index < count - 1)
{
url_builder.Append("&");
}
index++;
}
return url_builder.ToString();
}
}
}