diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..99d756a
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,66 @@
+
+# Created by https://www.toptal.com/developers/gitignore/api/unity
+# Edit at https://www.toptal.com/developers/gitignore?templates=unity
+
+### Unity ###
+# This .gitignore file should be placed at the root of your Unity project directory
+#
+# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
+/Client/[Ll]ibrary/
+/Client/[Tt]emp/
+/Client/[Oo]bj/
+/Client/[Bb]uild/
+/Client/[Ll]ogs/
+/Client/[Uu]ser[Ss]ettings/
+
+# MemoryCaptures can get excessive in size.
+# They also could contain extremely sensitive data
+/Client/[Mm]emoryCaptures/
+
+# Recordings can get excessive in size
+/Client/[Rr]ecordings/
+
+# Autogenerated Jetbrains Rider plugin
+/Client/[Aa]ssets/Plugins/Editor/JetBrains*
+
+# Visual Studio cache directory
+.vs/
+.obj/
+
+# Visual Code directory
+.vscode/
+
+# Gradle cache directory
+.gradle/
+
+# Autogenerated VS/MD/Consulo solution and project files
+ExportedObj/
+.consulo/
+*.csproj
+*.unityproj
+*.sln
+*.suo
+*.tmp
+*.user
+*.userprefs
+*.pidb
+*.booproj
+*.svd
+*.pdb
+*.mdb
+*.opendb
+*.VC.db
+
+# Unity3D generated meta files
+*.pidb.meta
+*.pdb.meta
+*.mdb.meta
+
+# Unity3D generated file on crash reports
+sysinfo.txt
+
+# Builds
+*.apk
+*.aab
+*.unitypackage
+*.app
diff --git a/server/.gitignore b/server/.gitignore
new file mode 100644
index 0000000..7761cae
--- /dev/null
+++ b/server/.gitignore
@@ -0,0 +1,66 @@
+
+# Created by https://www.toptal.com/developers/gitignore/api/unity
+# Edit at https://www.toptal.com/developers/gitignore?templates=unity
+
+### Unity ###
+# This .gitignore file should be placed at the root of your Unity project directory
+#
+# Get latest from https://github.com/github/gitignore/blob/main/Unity.gitignore
+/Server/[Ll]ibrary/
+/Server/[Tt]emp/
+/Server/[Oo]bj/
+/Server/[Bb]uild/
+/Server/[Ll]ogs/
+/Server/[Uu]ser[Ss]ettings/
+
+# MemoryCaptures can get excessive in size.
+# They also could contain extremely sensitive data
+/Server/[Mm]emoryCaptures/
+
+# Recordings can get excessive in size
+/Server/[Rr]ecordings/
+
+# Autogenerated Jetbrains Rider plugin
+/Server/[Aa]ssets/Plugins/Editor/JetBrains*
+
+# Visual Studio cache directory
+.vs/
+.obj/
+
+# Visual Code directory
+.vscode/
+
+# Gradle cache directory
+.gradle/
+
+# Autogenerated VS/MD/Consulo solution and project files
+ExportedObj/
+.consulo/
+*.csproj
+*.unityproj
+*.sln
+*.suo
+*.tmp
+*.user
+*.userprefs
+*.pidb
+*.booproj
+*.svd
+*.pdb
+*.mdb
+*.opendb
+*.VC.db
+
+# Unity3D generated meta files
+*.pidb.meta
+*.pdb.meta
+*.mdb.meta
+
+# Unity3D generated file on crash reports
+sysinfo.txt
+
+# Builds
+*.apk
+*.aab
+*.unitypackage
+*.app
diff --git a/server/Server/Git/AbstractGit.cs b/server/Server/Git/AbstractGit.cs
new file mode 100644
index 0000000..d5b6783
--- /dev/null
+++ b/server/Server/Git/AbstractGit.cs
@@ -0,0 +1,150 @@
+using LibGit2Sharp;
+using NLog;
+using Server.System;
+using System.Diagnostics;
+
+namespace Server.Git
+{
+ public abstract class AbstractGit
+ {
+ private static readonly NLog.ILogger logger = LogManager.GetCurrentClassLogger();
+ public bool isRestart;
+ string _repositoryPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "excel");
+
+ public string excel = "";
+
+ public string repositoryPath { get { return _repositoryPath; } }
+
+ ///
+ /// 가장먼저 시작해야 하는 스크립트
+ ///
+ public void Init()
+ {
+ restart:
+ isRestart = false;
+ Pull();
+ if (isRestart)
+ goto restart;
+ ChangeScript();
+ if (isRestart)
+ goto restart;
+ Push();
+ if (isRestart)
+ goto restart;
+ }
+
+ ///
+ /// 엑셀 불러오기, 저장, 혹은 배포 까지 작업해야하는 함수
+ ///
+ public abstract void ChangeScript();
+
+ private void Pull()
+ {
+ if (!Directory.Exists(_repositoryPath))
+ {
+ Directory.CreateDirectory(_repositoryPath);
+ RepositorySet($"clone {STATICS.remoteUrl} {_repositoryPath}", null);
+
+ //main브렌치로 세팅
+ RepositorySet("branch -m main", _repositoryPath);
+ RepositorySet("branch --set-upstream-to=origin/main main", _repositoryPath);
+ }
+
+ // pull 명령어 실행
+ RepositorySet("pull", _repositoryPath);
+ }
+
+ private static void RepositorySet(string command, string workingDirectory)
+ {
+ ProcessStartInfo psi = new ProcessStartInfo
+ {
+ FileName = "git",
+ Arguments = command,
+ WorkingDirectory = workingDirectory,
+ RedirectStandardOutput = true,
+ RedirectStandardError = true,
+ UseShellExecute = false,
+ CreateNoWindow = true
+ };
+
+ using (Process process = new Process { StartInfo = psi })
+ {
+ process.Start();
+ process.WaitForExit();
+
+ // Git 명령 실행 결과 출력
+ Console.WriteLine(process.StandardOutput.ReadToEnd());
+
+ // 오류 메시지 출력
+ Console.WriteLine(process.StandardError.ReadToEnd());
+ }
+ }
+
+ private void Push()
+ {
+ if(excel == "")
+ {
+ return;
+ }
+
+ //json 저장
+ using (StreamWriter writer = new StreamWriter(repositoryPath + "\\excel.json"))
+ {
+ writer.Write(excel);
+ Console.WriteLine($"파일이 저장되었습니다 : {repositoryPath + "\\excel.json"}");
+ }
+
+
+ // 스테이징
+ RepositorySet("add .", repositoryPath);
+
+ // 커밋
+ RepositorySet($"commit -m \"update excel data\"", repositoryPath);
+
+ // 푸시
+ RepositorySet("push origin main", repositoryPath);
+
+ }
+
+ ///
+ /// 모든 파일리스트 반환
+ ///
+ /// 검색할 폴더 경로
+ /// 확장자
+ ///
+ public List GetFiles(string directoryPath, string extension)
+ {
+ List xlsxFileList = new List();
+
+ try
+ {
+ string[] files = Directory.GetFiles(directoryPath);
+
+ foreach (string file in files)
+ {
+ if (Path.GetExtension(file).Equals(".xlsx", StringComparison.OrdinalIgnoreCase))
+ {
+ xlsxFileList.Add(file);
+ }
+ }
+
+ string[] subdirectories = Directory.GetDirectories(directoryPath);
+ foreach (string subdirectory in subdirectories)
+ {
+ //git시스템 파일은 뛰어넘기
+ if (subdirectory == directoryPath + "\\.git")
+ continue;
+
+ //제귀
+ xlsxFileList.AddRange(GetFiles(subdirectory, extension));
+ }
+ }
+ catch (Exception ex)
+ {
+ logger.Error(ex);
+ }
+
+ return xlsxFileList;
+ }
+ }
+}
diff --git a/server/Server/Git/ExcelManager.cs b/server/Server/Git/ExcelManager.cs
new file mode 100644
index 0000000..a9e5ebb
--- /dev/null
+++ b/server/Server/Git/ExcelManager.cs
@@ -0,0 +1,106 @@
+using Aspose.Cells;
+using Microsoft.AspNetCore.Http;
+using NLog;
+
+namespace Server.Git
+{
+ public class sheet
+ {
+ string _name;
+ public string name { get { return _name; } }
+ List _variable;
+ public List variable { get { return _variable; } }
+ List _type;
+ public List type { get { return _type; } }
+ Dictionary> _dicViewer;
+ public Dictionary> dicViewer { get { return _dicViewer; } }
+
+ public sheet(string name, List variable, List type, Dictionary> dicViewer)
+ {
+ this._name = name;
+ this._variable = variable;
+ this._type = type;
+ this._dicViewer = dicViewer;
+ }
+ }
+ class ExcelManager
+ {
+ private static readonly NLog.ILogger logger = LogManager.GetCurrentClassLogger();
+
+ List _sheets;
+
+ public List sheets { get { return _sheets; } }
+
+ string _pathFile;
+ public ExcelManager(string path, string file = "")
+ {
+ if (file == "")
+ _pathFile = path;
+ else
+ _pathFile = path + "\\" + file;
+ }
+
+ public bool Play()
+ {
+ return ExcelLoad(_pathFile);
+ }
+ public bool ExcelLoad(string path)//엑셀 로드
+ {
+ // 엑셀 파일 불러오기
+ Workbook wb = new Workbook(_pathFile);
+
+ // 모든 워크시트 가져오기
+ WorksheetCollection collection = wb.Worksheets;
+
+ _sheets = new List();
+
+ // 모든 워크시트 반복
+ try
+ {
+ for (int worksheetIndex = 0; worksheetIndex < collection.Count; worksheetIndex++)
+ {
+ //변수이름
+ List variable = new List();
+ //변수 타입
+ List type = new List();
+ Dictionary> dicViewer = new Dictionary>();
+
+ // 인덱스를 사용하여 워크시트 가져오기
+ Worksheet worksheet = collection[worksheetIndex];
+
+ // 행과 열의 수 얻기
+ int vertical = worksheet.Cells.MaxDataRow;
+ int horizontal = worksheet.Cells.MaxDataColumn;
+
+ //변수 이름과 타입 삽입
+ for (int n = 0; n <= horizontal; n++)
+ {
+ variable.Add((string)worksheet.Cells[0, n].Value);
+ type.Add(((string)worksheet.Cells[2, n].Value).ToLower());
+ }
+
+ bool isIndex = variable[0] == "index";
+
+ for (int n = 3; n <= vertical; n++)
+ {
+ Dictionary dataList = new Dictionary();
+ for (int m = 0; m <= horizontal; m++)
+ {
+ dataList.Add(variable[m], worksheet.Cells[n, m].Value);
+ }
+ dicViewer.Add((int)(isIndex ? worksheet.Cells[n, 0].Value : n - 3), dataList);
+ }
+ sheet sheet = new sheet(worksheet.Name, variable, type, dicViewer);
+ _sheets.Add(sheet);
+ }
+ }
+ catch (Exception ex)
+ {
+ logger.Error(ex);
+ return false;
+ }
+
+ return true;
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/Server/Git/ExcelSQL.cs b/server/Server/Git/ExcelSQL.cs
new file mode 100644
index 0000000..1d75ffb
--- /dev/null
+++ b/server/Server/Git/ExcelSQL.cs
@@ -0,0 +1,150 @@
+using Microsoft.AspNetCore.Http;
+using Npgsql;
+using Server.SQL;
+using Server.System;
+using System.Globalization;
+
+namespace Server.Git
+{
+ public class ExcelSQL
+ {
+ List sheets;
+
+ public ExcelSQL(List sheets)
+ {
+ this.sheets = sheets;
+ }
+
+ public void DataUpdate()
+ {
+ using (NpgsqlConnection connection = new NpgsqlConnection(STATICS.EXCEL_SQL_URL))
+ {
+ try
+ {
+ // 데이터베이스 연결 열기
+ connection.Open();
+
+ // 쿼리 작성 및 실행
+ //모든 쿼리 삭제
+ string query;
+ string header1 = "CREATE TABLE IF NOT EXISTS excel.";
+ string header2 = "INSERT INTO excel.";
+ string newTableQuery;
+ string tableDatas;
+ #region 모든 테이블 삭제
+ query = "DROP SCHEMA excel CASCADE;" +
+ "CREATE SCHEMA excel AUTHORIZATION manager;";
+ ExecuteNonQuery(connection, query);
+ #endregion
+ #region 테이블 세팅
+ query = "";
+ for (int n = 0; n < sheets.Count; n++)
+ {
+ //초기화
+ newTableQuery = "";
+ tableDatas = "(";
+
+ #region 신규 테이블 생성
+ newTableQuery += header1;
+ newTableQuery += sheets[n].name + "(";
+ for (int m = 0; m < sheets[n].variable.Count; m++)
+ {
+ if (sheets[n].type[m] == "long" && sheets[n].variable[m] == "index")
+ {
+ newTableQuery += "index SERIAL PRIMARY KEY";
+ tableDatas += "index";
+ continue;
+ }
+ if (m != 0)
+ {
+ newTableQuery += ",\n";
+ tableDatas += ", ";
+ }
+
+ switch (sheets[n].type[m])
+ {
+ case "int":
+ newTableQuery += $"{sheets[n].variable[m]} INT ";
+ break;
+ case "string":
+ newTableQuery += $"{sheets[n].variable[m]} VARCHAR(255) ";
+ break;
+ case "enum":
+ newTableQuery += $"{sheets[n].variable[m]} INT2 ";
+ break;
+ case "text":
+ newTableQuery += $"{sheets[n].variable[m]} TEXT ";
+ break;
+ case "time":
+ newTableQuery += $"{sheets[n].variable[m]} timestamp ";
+ break;
+ }
+ tableDatas += sheets[n].variable[m];
+ }
+ newTableQuery += ");\n";
+ tableDatas += ") VALUES ";
+ bool isStart = true;
+ query += newTableQuery;
+
+ #endregion
+ #region 신규 테이블 데이터 올리기
+
+ query += header2;
+ query += sheets[n].name;
+ query += tableDatas;
+ foreach(KeyValuePair> pair in sheets[n].dicViewer)
+ {
+ if (isStart)
+ {
+ isStart = !isStart;
+ }
+ else
+ {
+ query += ", ";
+ }
+ query += "(";
+ for (int m = 0; m < sheets[n].variable.Count; m++)
+ {
+ switch (sheets[n].type[m])
+ {
+ case "int":
+ case "enum":
+ query += $"{pair.Value[sheets[n].variable[m]]}";
+ break;
+ case "string":
+ case "text":
+ query += $"'{pair.Value[sheets[n].variable[m]]}'";
+ break;
+ case "time":
+ query += $"'{((DateTime)pair.Value[sheets[n].variable[m]]).ToString("yyyy-MM-dd HH:mm:ss")}'";
+ break;
+ }
+ if(m != sheets[n].variable.Count -1)
+ {
+ query += ", ";
+ }
+ }
+ query += ")";
+ }
+ #endregion
+ }
+ ExecuteNonQuery(connection, query);
+
+ #endregion
+ }
+ catch (Exception ex)
+ {
+ Console.WriteLine($"Error: {ex.Message}");
+ }
+ }
+ }
+ private void ExecuteNonQuery(NpgsqlConnection connection, string query)
+ {
+ using (NpgsqlCommand command = new NpgsqlCommand(query, connection))
+ {
+ Console.WriteLine(query);
+ command.ExecuteNonQuery();
+ }
+ }
+ }
+}
diff --git a/server/Server/Git/XlsxToJson.cs b/server/Server/Git/XlsxToJson.cs
new file mode 100644
index 0000000..fce72fe
--- /dev/null
+++ b/server/Server/Git/XlsxToJson.cs
@@ -0,0 +1,48 @@
+using Newtonsoft.Json;
+using System.Collections.Generic;
+using System.IO;
+
+namespace Server.Git
+{
+ public class XlsxToJson : AbstractGit
+ {
+ public override void ChangeScript()
+ {
+ //저장경로 : repositoryPath
+ //작업할것
+ //데이터 db에 업로드
+
+ List fileList = GetFiles(repositoryPath, ".xlsx");
+
+ Dictionary>> sheetList = new Dictionary>>();
+ List sheets = null;
+ for (int n = 0; n < fileList.Count; n++)
+ {
+ ExcelManager em = new ExcelManager(fileList[n]);
+ if (em.Play())
+ {
+ sheets = em.sheets;
+ for (int m = 0; m < sheets.Count; m++)
+ {
+ sheetList.Add(sheets[m].name, sheets[m].dicViewer);
+ }
+ }
+ else
+ {
+ Console.WriteLine("-1 : NotUpdate");
+ return;
+ }
+ }
+
+ excel = JsonConvert.SerializeObject(sheetList);
+ //현재 서버는 PostgreSQL기준으로 쿼리를 생성하는 코드와 패키지가 세팅되어 있습니다 이점 참고바랍니다
+ //추가로 해당 기능을 사용하려면 서버에 excel이라는 스키마가 존재하여야 합니다.
+ if (sheets != null)
+ {
+ ExcelSQL sql = new ExcelSQL(sheets);
+ sql.DataUpdate();
+ }
+
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/Server/NLog.config b/server/Server/NLog.config
new file mode 100644
index 0000000..a758250
--- /dev/null
+++ b/server/Server/NLog.config
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
diff --git a/server/Server/Program.cs b/server/Server/Program.cs
new file mode 100644
index 0000000..293a3d6
--- /dev/null
+++ b/server/Server/Program.cs
@@ -0,0 +1,19 @@
+using Server.System;
+
+var builder = WebApplication.CreateBuilder(args);
+var app = builder.Build();
+
+// ʱȭ
+ProtocolProcessor.Init();
+// ʱȭ
+GItWebhook.Init();
+
+//http
+app.MapPost("/", ProtocolProcessor.Process);
+
+//git ٿ
+app.MapPost("/git", GItWebhook.Process);
+
+//app.MapPost("/update", GItWebhook.Process);
+
+app.Run();
diff --git a/server/Server/Properties/launchSettings.json b/server/Server/Properties/launchSettings.json
new file mode 100644
index 0000000..2da414e
--- /dev/null
+++ b/server/Server/Properties/launchSettings.json
@@ -0,0 +1,28 @@
+{
+ "iisSettings": {
+ "windowsAuthentication": false,
+ "anonymousAuthentication": true,
+ "iisExpress": {
+ "applicationUrl": "https://0.0.0.0:4861",
+ "sslPort": 4862
+ }
+ },
+ "profiles": {
+ "Server": {
+ "commandName": "Project",
+ "launchBrowser": true,
+ "applicationUrl": "https://0.0.0.0:4860",
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ },
+ "dotnetRunMessages": true
+ },
+ "IIS Express": {
+ "commandName": "IISExpress",
+ "launchBrowser": true,
+ "environmentVariables": {
+ "ASPNETCORE_ENVIRONMENT": "Development"
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/Server/SQL/SQL.cs b/server/Server/SQL/SQL.cs
new file mode 100644
index 0000000..0d23eff
--- /dev/null
+++ b/server/Server/SQL/SQL.cs
@@ -0,0 +1,142 @@
+using System.Reflection;
+using System.Text;
+using System.Text.RegularExpressions;
+using Server.System;
+
+namespace Server.SQL
+{
+ public class SQL
+ {
+ string className;
+ Regex regex = new Regex(STATICS.PATTERN);
+
+ public SQL()
+ {
+ className = typeof(T).Name;
+ }
+
+ public string sqlInsert(T instance)
+ {
+ List names = new List();
+ List values = new List();
+ foreach (FieldInfo field in typeof(T).GetFields())
+ {
+ object value = field.GetValue(instance);
+ if (value == null)
+ continue;
+ names.Add(field.Name);
+ values.Add(value.ToString());
+ }
+
+ StringBuilder qurry = new StringBuilder();
+
+ qurry.Append($"INSERT INTO {className} (");
+
+ int n = 0;
+ int count = names.Count;
+
+ for(; n < count; n++)
+ {
+ qurry.Append(names[n]);
+ if(n != count - 1)
+ {
+ qurry.Append(", ");
+ }
+ }
+
+ qurry.Append(") VALUES (");
+ n = 0;
+ for (; n < count; n++)
+ {
+ qurry.Append(values[n]);
+ if (n != count - 1)
+ {
+ qurry.Append(", ");
+ }
+ }
+ qurry.Append(");");
+
+ return qurry.ToString();
+ }
+
+ public string sqlUpdate(string[] names, object[] values, string[] wnames, object[] wvalues)
+ {
+ StringBuilder qurry = new StringBuilder();
+ qurry.Append($"UPDATE {className} SET ");
+ for(int n = 0; n < names.Length; n++)
+ {
+ qurry.Append($"{names[n]} = {values[n]}");
+ if(n < names.Length - 1)
+ {
+ qurry.Append(", ");
+ }
+ }
+ qurry.Append(" WHERE ");
+ for (int n = 0; n < wnames.Length; n++)
+ {
+ qurry.Append($"{wnames[n]} = {wvalues[n]}");
+ if (n < wnames.Length - 1)
+ {
+ qurry.Append(", ");
+ }
+ }
+ return qurry.ToString();
+ }
+
+ public string sqlSelect(string[] names, string[] wnames, object[] wvalues)
+ {
+ StringBuilder qurry = new StringBuilder();
+
+ if(names == null)
+ {
+ qurry.Append($"SELECT * FROM {className} ");
+ }
+ else
+ {
+ qurry.Append("SELECT ");
+ for(int n = 0; n < names.Length; n++)
+ {
+ qurry.Append(names[n]);
+ if (n < names.Length - 1)
+ {
+ qurry.Append(", ");
+ }
+ }
+ qurry.Append($" FROM {className} ");
+ }
+
+ qurry.Append(" WHERE ");
+ for (int n = 0; n < wnames.Length; n++)
+ {
+ qurry.Append($"{wnames[n]} = {wvalues[n]}");
+ if (n < wnames.Length - 1)
+ {
+ qurry.Append(", ");
+ }
+ }
+ return qurry.ToString();
+ }
+
+ public string sqlDelete(string[] wnames, object[] wvalues)
+ {
+ StringBuilder qurry = new StringBuilder();
+ qurry.Append($"DELETE FROM {className}");
+
+ qurry.Append(" WHERE ");
+ for (int n = 0; n < wnames.Length; n++)
+ {
+ qurry.Append($"{wnames[n]} = {wvalues[n]}");
+ if (n < wnames.Length - 1)
+ {
+ qurry.Append(", ");
+ }
+ }
+ return qurry.ToString();
+ }
+ public string Injection(string data)
+ {
+ return regex.Replace(data, "");
+ }
+ }
+}
+
diff --git a/server/Server/SQL/UserSQL.cs b/server/Server/SQL/UserSQL.cs
new file mode 100644
index 0000000..fdcff94
--- /dev/null
+++ b/server/Server/SQL/UserSQL.cs
@@ -0,0 +1,18 @@
+namespace Server.SQL
+{
+ public class User
+ {
+ public int Id { get; set; }
+ public string NickName { get; set; }
+ public string count { get; set; }
+ }
+
+ public class UserSQL : SQL
+ {
+ public void userInsert(User user)
+ {
+ string qurry = sqlInsert(user);
+ }
+ }
+}
+//쿼리 전송
diff --git a/server/Server/Service/AddUser.cs b/server/Server/Service/AddUser.cs
new file mode 100644
index 0000000..00728cf
--- /dev/null
+++ b/server/Server/Service/AddUser.cs
@@ -0,0 +1,44 @@
+using Server.System;
+using Newtonsoft.Json;
+
+namespace Server.Service
+{
+ public class AddUser : AbstractService
+ {
+ private AddUserReq req;
+ public override string Process()
+ {
+ return makeResp();
+ }
+
+ public override Protocol ProtocolValue() => Protocol.AddUser;
+
+ public override Req Requst(string json)
+ {
+ req = JsonConvert.DeserializeObject(json);
+ return req;
+ }
+
+ private string makeResp()
+ {
+ AddUserResp resp = new AddUserResp();
+ resp.status = 200;
+ return resp.ToJson();
+ }
+
+
+ }
+
+ public class AddUserReq : Req
+ {
+ public override bool IsReceivedAllField()
+ {
+ return true;
+ }
+ }
+
+ public class AddUserResp : Resp
+ {
+
+ }
+}
diff --git a/server/Server/Service/Test.cs b/server/Server/Service/Test.cs
new file mode 100644
index 0000000..28befe7
--- /dev/null
+++ b/server/Server/Service/Test.cs
@@ -0,0 +1,44 @@
+using Server.System;
+using Newtonsoft.Json;
+
+namespace Server.Service
+{
+ public class awaketest : AbstractService
+ {
+ private awaketestReq req;
+ public override string Process()
+ {
+ return makeResp();
+ }
+
+ public override Protocol ProtocolValue() => Protocol.Test;
+
+ public override Req Requst(string json)
+ {
+ req = JsonConvert.DeserializeObject(json);
+ return req;
+ }
+
+ private string makeResp()
+ {
+ awaketestResp resp = new awaketestResp();
+ resp.status = 200;
+ return resp.ToJson();
+ }
+
+
+ }
+
+ public class awaketestReq : Req
+ {
+ public override bool IsReceivedAllField()
+ {
+ return true;
+ }
+ }
+
+ public class awaketestResp : Resp
+ {
+
+ }
+}
diff --git a/server/Server/System/Abstract.cs b/server/Server/System/Abstract.cs
new file mode 100644
index 0000000..08a0684
--- /dev/null
+++ b/server/Server/System/Abstract.cs
@@ -0,0 +1,32 @@
+using Newtonsoft.Json;
+
+namespace Server.System
+{
+ public abstract class AbstractService
+ {
+ public abstract Protocol ProtocolValue();
+
+ public abstract string Process();
+
+ public abstract Req Requst(string json);
+ }
+
+ public abstract class Req
+ {
+ public Protocol cmd;
+
+ public virtual bool IsReceivedAllField()
+ {
+ return true;
+ }
+ }
+
+ public abstract class Resp
+ {
+ public int status;
+ public virtual string ToJson()
+ {
+ return JsonConvert.SerializeObject(this);
+ }
+ }
+}
diff --git a/server/Server/System/Enums.cs b/server/Server/System/Enums.cs
new file mode 100644
index 0000000..57cf0c3
--- /dev/null
+++ b/server/Server/System/Enums.cs
@@ -0,0 +1,16 @@
+public enum Protocol
+{
+ Test = 0,
+ AddUser = 1,
+}
+
+public enum Error
+{
+ RuntimeException = -1,//서버 오류
+ None = 0,//사용안함
+ success = 200,//성공
+ notFound = 404,//프로토콜 없음
+ unknown = 500,//파라미터 오류
+ crypto = 800,//암복호화 에러
+ nodata = 900,//데이터가 없음
+}
\ No newline at end of file
diff --git a/server/Server/System/Error.cs b/server/Server/System/Error.cs
new file mode 100644
index 0000000..70078f9
--- /dev/null
+++ b/server/Server/System/Error.cs
@@ -0,0 +1,28 @@
+namespace Server.System
+{
+ public class ErrorResp : Resp
+ {
+ public string message;
+ public ErrorResp(RuntimeException ex)
+ {
+ this.status = (int)ex.status;
+ this.message = ex.Message;
+ }
+ public ErrorResp()
+ {
+ this.status = -1;
+ this.message = "Unknown Error";
+ }
+
+ }
+
+ public class RuntimeException : Exception
+ {
+ public Error status;
+
+ public RuntimeException(string message = "", Error status = Error.RuntimeException) : base(message)
+ {
+ this.status = status;
+ }
+ }
+}
diff --git a/server/Server/System/GItWebhook.cs b/server/Server/System/GItWebhook.cs
new file mode 100644
index 0000000..3c47b91
--- /dev/null
+++ b/server/Server/System/GItWebhook.cs
@@ -0,0 +1,73 @@
+using NLog;
+using Server.Git;
+
+namespace Server.System
+{
+ public class GItWebhook
+ {
+ private static readonly NLog.ILogger logger = LogManager.GetCurrentClassLogger();
+
+ public static Thread thread;
+
+ private static AbstractGit git;
+
+ public static string Process(HttpContext context)
+ {
+ //TODO 아무때나 호출되지 않게 만들기
+ string Response;
+ try
+ {
+ string eaDelivery = context.Request.Headers["X-Gitea-Delivery"];
+ string eaEvent = context.Request.Headers["X-Gitea-Event"];
+ string eaEventType = context.Request.Headers["X-Gitea-Event-Type"];
+ string eaSignature = context.Request.Headers["X-Gitea-Signature"];
+
+ Console.WriteLine($"X-Gitea-Delivery : {eaDelivery}");
+ Console.WriteLine($"X-Gitea-Event : {eaEvent}");
+ Console.WriteLine($"X-Gitea-Event-Type : {eaEventType}");
+ Console.WriteLine($"X-Gitea-Signature : {eaSignature}");
+
+ //task를 쓰면 멈출수가 없기에 thread를 사용
+ if (thread.ThreadState == ThreadState.Unstarted)
+ {
+ thread.Start();
+ }
+ else if (thread.ThreadState == ThreadState.Stopped)
+ {
+ thread = new Thread(git.Init);
+ thread.Start();
+ }
+ else if (thread.ThreadState == ThreadState.WaitSleepJoin || thread.ThreadState == ThreadState.Running)
+ {
+ git.isRestart = true;
+ }
+
+
+ ErrorResp error = new ErrorResp();
+ error.status = 200;
+ error.message = "Success";
+ Response = error.ToJson();
+ }
+ catch (RuntimeException ex)
+ {
+ ErrorResp error = new ErrorResp(ex);
+ Response = error.ToJson();
+ logger.Error("GetErrorResponse : " + Response);
+ }
+ catch (Exception ex)
+ {
+ ErrorResp error = new ErrorResp();
+ Response = error.ToJson();
+ logger.Error("GetErrorResponse : " + ex.ToString());
+ }
+ return Response;
+
+ }
+
+ public static void Init()
+ {
+ git = new XlsxToJson();
+ thread = new Thread(git.Init);
+ }
+ }
+}
diff --git a/server/Server/System/Statics.cs b/server/Server/System/Statics.cs
new file mode 100644
index 0000000..6e6d35e
--- /dev/null
+++ b/server/Server/System/Statics.cs
@@ -0,0 +1,20 @@
+namespace Server.System
+{
+ public static class STATICS
+ {
+ #region Dev
+ #if DEBUG
+ public static readonly string SQL_URL = "Host=myHost;Port=myPort;Username=myUsername;Password=myPassword;Database=myDatabase;";
+ public static readonly string EXCEL_SQL_URL = "Host=myHost;Port=myPort;Username=myUsername;Password=myPassword;Database=myDatabase;";
+ #endif
+ #endregion
+
+ //비공계 프로젝트의 경우 아래와같이 작성해주세요
+ //"https://username:password@www.example.com/";
+ public static readonly string remoteUrl = "https://username:password@www.example.com/";
+
+
+ public static readonly string PATTERN = "[^a-zA-Z0-9가-힣 ]";
+ }
+
+}
diff --git a/server/Server/System/SystemMain.cs b/server/Server/System/SystemMain.cs
new file mode 100644
index 0000000..1e282c1
--- /dev/null
+++ b/server/Server/System/SystemMain.cs
@@ -0,0 +1,78 @@
+using System.Reflection;
+using NLog;
+
+namespace Server.System {
+ public class ProtocolProcessor {
+ private static Dictionary SERVICE_DIC = new Dictionary();
+
+ private static readonly NLog.ILogger logger = LogManager.GetCurrentClassLogger();
+
+
+ public static void addProtocol(AbstractService abstractService) {
+ if (SERVICE_DIC.ContainsKey(abstractService.ProtocolValue())) {
+ logger.Error("중복된 프로토콜 : " + abstractService.ProtocolValue());
+ throw new Exception("중복된 프로토콜 : " + abstractService.ProtocolValue());
+ }
+
+ SERVICE_DIC.Add(abstractService.ProtocolValue(), abstractService);
+ }
+
+ public static void Init() {
+ // 현재 실행 중인 어셈블리를 가져옴
+ var assembly = Assembly.GetExecutingAssembly();
+
+ // 'AbstractService'의 하위 클래스를 모두 찾음
+ var serviceTypes = assembly.GetTypes().Where(t => t.IsSubclassOf(typeof(AbstractService)) && !t.IsAbstract);
+
+ // 각 클래스의 인스턴스를 생성합니다. 생성자에서 자동으로 등록됩니다.
+ foreach (var type in serviceTypes)
+ addProtocol((AbstractService)Activator.CreateInstance(type));
+
+ logger.Info("Server Start");
+ }
+
+ public static string Process(HttpContext context) {
+ AbstractService abstractService;
+
+ string Response = "";
+ try {
+ Protocol cmd = (Protocol)int.Parse(context.Request.Headers["cmd"]);
+ SERVICE_DIC.TryGetValue(cmd, out abstractService);
+ if (abstractService == null)
+ throw new RuntimeException("Not Found", Error.notFound);
+
+ string body = Request(context.Request).GetAwaiter().GetResult();
+
+ logger.Info("GetRequst : " + body);
+
+ Req req = abstractService.Requst(body);
+
+ if (req == null)
+ throw new RuntimeException("", Error.nodata);
+ else if (!req.IsReceivedAllField())
+ throw new RuntimeException("Internal Server Error", Error.unknown);
+
+ Response = abstractService.Process();
+
+ logger.Info("GetResponse : " + Response);
+ }
+ catch (RuntimeException ex) {
+ ErrorResp error = new ErrorResp(ex);
+ Response = error.ToJson();
+ logger.Error("GetErrorResponse : " + Response);
+ }
+ catch (Exception ex) {
+ ErrorResp error = new ErrorResp();
+ Response = error.ToJson();
+ logger.Error("GetErrorResponse : " + ex.ToString());
+ }
+ return Response;
+
+ }
+
+ private static async Task Request(HttpRequest request) {
+ using var reader = new StreamReader(request.Body);
+ return await reader.ReadToEndAsync();
+ }
+ }
+}
\ No newline at end of file
diff --git a/server/Server/appsettings.Development.json b/server/Server/appsettings.Development.json
new file mode 100644
index 0000000..0c208ae
--- /dev/null
+++ b/server/Server/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/server/Server/appsettings.json b/server/Server/appsettings.json
new file mode 100644
index 0000000..50f91df
--- /dev/null
+++ b/server/Server/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Trace",
+ "Microsoft.AspNetCore": "Trace"
+ }
+ },
+ "AllowedHosts": "0.0.0.0;localhost"
+}