Commit c8d7c8b4 authored by insun park's avatar insun park
Browse files
parents 4c627a3d 17618ca9
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
\ No newline at end of file
-----BEGIN CERTIFICATE-----
MIIFBTCCAu2gAwIBAgIQS6hSk/eaL6JzBkuoBI110DANBgkqhkiG9w0BAQsFADBP
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
Fw0yNzAzMTIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
bmNyeXB0MQwwCgYDVQQDEwNSMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQDPV+XmxFQS7bRH/sknWHZGUCiMHT6I3wWd1bUYKb3dtVq/+vbOo76vACFL
YlpaPAEvxVgD9on/jhFD68G14BQHlo9vH9fnuoE5CXVlt8KvGFs3Jijno/QHK20a
/6tYvJWuQP/py1fEtVt/eA0YYbwX51TGu0mRzW4Y0YCF7qZlNrx06rxQTOr8IfM4
FpOUurDTazgGzRYSespSdcitdrLCnF2YRVxvYXvGLe48E1KGAdlX5jgc3421H5KR
mudKHMxFqHJV8LDmowfs/acbZp4/SItxhHFYyTr6717yW0QrPHTnj7JHwQdqzZq3
DZb3EoEmUVQK7GH29/Xi8orIlQ2NAgMBAAGjgfgwgfUwDgYDVR0PAQH/BAQDAgGG
MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/
AgEAMB0GA1UdDgQWBBS7vMNHpeS8qcbDpHIMEI2iNeHI6DAfBgNVHSMEGDAWgBR5
tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKG
Fmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0gBAwwCjAIBgZngQwBAgEwJwYD
VR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0B
AQsFAAOCAgEAkrHnQTfreZ2B5s3iJeE6IOmQRJWjgVzPw139vaBw1bGWKCIL0vIo
zwzn1OZDjCQiHcFCktEJr59L9MhwTyAWsVrdAfYf+B9haxQnsHKNY67u4s5Lzzfd
u6PUzeetUK29v+PsPmI2cJkxp+iN3epi4hKu9ZzUPSwMqtCceb7qPVxEbpYxY1p9
1n5PJKBLBX9eb9LU6l8zSxPWV7bK3lG4XaMJgnT9x3ies7msFtpKK5bDtotij/l0
GaKeA97pb5uwD9KgWvaFXMIEt8jVTjLEvwRdvCn294GPDF08U8lAkIv7tghluaQh
1QnlE4SEN4LOECj8dsIGJXpGUk3aU3KkJz9icKy+aUgA+2cP21uh6NcDIS3XyfaZ
QjmDQ993ChII8SXWupQZVBiIpcWO4RqZk3lr7Bz5MUCwzDIA359e57SSq5CCkY0N
4B6Vulk7LktfwrdGNVI5BsC9qqxSwSKgRJeZ9wygIaehbHFHFhcBaMDKpiZlBHyz
rsnnlFXCb5s8HKn5LsUgGvB24L7sGNZP2CX7dhHov+YhD+jozLW2p9W4959Bz2Ei
RmqDtmiXLnzqTpXbI+suyCsohKRg6Un0RC47+cpiVwHiXZAW+cn8eiNIjqbVgXLx
KPpdzvvtTnOPlC7SQZSYmdunr3Bf9b77AiC/ZidstK36dRILKz7OA54=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
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
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFBTCCAu2gAwIBAgIQS6hSk/eaL6JzBkuoBI110DANBgkqhkiG9w0BAQsFADBP
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
Fw0yNzAzMTIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
bmNyeXB0MQwwCgYDVQQDEwNSMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQDPV+XmxFQS7bRH/sknWHZGUCiMHT6I3wWd1bUYKb3dtVq/+vbOo76vACFL
YlpaPAEvxVgD9on/jhFD68G14BQHlo9vH9fnuoE5CXVlt8KvGFs3Jijno/QHK20a
/6tYvJWuQP/py1fEtVt/eA0YYbwX51TGu0mRzW4Y0YCF7qZlNrx06rxQTOr8IfM4
FpOUurDTazgGzRYSespSdcitdrLCnF2YRVxvYXvGLe48E1KGAdlX5jgc3421H5KR
mudKHMxFqHJV8LDmowfs/acbZp4/SItxhHFYyTr6717yW0QrPHTnj7JHwQdqzZq3
DZb3EoEmUVQK7GH29/Xi8orIlQ2NAgMBAAGjgfgwgfUwDgYDVR0PAQH/BAQDAgGG
MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/
AgEAMB0GA1UdDgQWBBS7vMNHpeS8qcbDpHIMEI2iNeHI6DAfBgNVHSMEGDAWgBR5
tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKG
Fmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0gBAwwCjAIBgZngQwBAgEwJwYD
VR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0B
AQsFAAOCAgEAkrHnQTfreZ2B5s3iJeE6IOmQRJWjgVzPw139vaBw1bGWKCIL0vIo
zwzn1OZDjCQiHcFCktEJr59L9MhwTyAWsVrdAfYf+B9haxQnsHKNY67u4s5Lzzfd
u6PUzeetUK29v+PsPmI2cJkxp+iN3epi4hKu9ZzUPSwMqtCceb7qPVxEbpYxY1p9
1n5PJKBLBX9eb9LU6l8zSxPWV7bK3lG4XaMJgnT9x3ies7msFtpKK5bDtotij/l0
GaKeA97pb5uwD9KgWvaFXMIEt8jVTjLEvwRdvCn294GPDF08U8lAkIv7tghluaQh
1QnlE4SEN4LOECj8dsIGJXpGUk3aU3KkJz9icKy+aUgA+2cP21uh6NcDIS3XyfaZ
QjmDQ993ChII8SXWupQZVBiIpcWO4RqZk3lr7Bz5MUCwzDIA359e57SSq5CCkY0N
4B6Vulk7LktfwrdGNVI5BsC9qqxSwSKgRJeZ9wygIaehbHFHFhcBaMDKpiZlBHyz
rsnnlFXCb5s8HKn5LsUgGvB24L7sGNZP2CX7dhHov+YhD+jozLW2p9W4959Bz2Ei
RmqDtmiXLnzqTpXbI+suyCsohKRg6Un0RC47+cpiVwHiXZAW+cn8eiNIjqbVgXLx
KPpdzvvtTnOPlC7SQZSYmdunr3Bf9b77AiC/ZidstK36dRILKz7OA54=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE REQUEST-----
MIIE3DCCAsQCAQAwUjEYMBYGA1UEAwwPbWFpbC5nZXVtZG8ubmV0MRcwFQYDVQQI
DA5DemVjaCBSZXB1YmxpYzELMAkGA1UEBhMCQ1oxEDAOBgNVBAoMB1Vua25vd24w
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQCzpAtFlq/z5lXAlTYKScZr
T4X9WxxlmqUYLgXrSEHnlKWbSsdWdafUpAo6qRBKKpZt/ETfaPyn48gx4MYJyqY7
3XJsdTlTSSVsNNajUfcYbGpKw9chhGzqWHDyNVbIKVfZQ6LmZxGXPqLClF+U4+Sc
nPc3oVgEW2AE+jy0VuZVNBFCukR98JqM0r90qBGZXsX27s3zepADUC/sHB1n2BuX
Oc+pMWJUFjLvI+Z50nyOQAsF6oIe3CHcTL4cuIzra4TWbiF4dLaA5pDy4MXmiLhM
7rAOZAxqjcD3+vpETeiY7BnWZCb/B8rEWwnwnzjf/Z+pwp7YnQyG+xkTTHgrlHXo
GHbyoLP2JoVRJWObOaAvDRk6CkylwP3YpFdV8vjIMAFDe1boY4GzWx3IW+QuIcT0
TYYIqwE+LEExRblAMq14qkdxumWYx8t0u96C13y1MKUHJajhd0Ft2t2IQFXmaClF
SLO8zuHaQZQRr6wB7bPMWjRgE+i2KpmB2ODsVtgXvgAeRgwlTjnp5nsW/sg8DlGA
tDWEMl671T1KztpZq+yv2bafCSkNX5i/Z1PB54PaJX07KVWZGCrxf1qP1epv8ZPr
XK4PfQyAxXu4A9VKFM7Pf57OWvh8kObjQLsb7qaUKluwYTRMH+gxynT8NUgTpdhJ
a8gHtKnen9uJSwP/xc6wywIDAQABoEUwQwYJKoZIhvcNAQkOMTYwNDAJBgNVHRME
AjAAMBoGA1UdEQQTMBGCD21haWwuZ2V1bWRvLm5ldDALBgNVHQ8EBAMCBeAwDQYJ
KoZIhvcNAQELBQADggIBAEXxtZCp//zYdi4Sm+Mg/g8oELDKt96nh/F31PE7+GuN
6gntRV7E556rdHznN63juX0pHRv/vvA+HsjoC6UehBIAouV/OvcFgb8JMiYQ33Ot
GSyRBSiVwZblDZu/Qs0qq/TXTaX5zjE4SWIEIqt9wlDBnHliBXmMQgD5lJGVJm9l
PrN/5QiiHizP0lQkLW7LpyxRF0hF9uGwDQ/Yjx2wwGkeo/GihK/e2U6mVhYbmBY6
fzt1t2Rqgv8f3mmwJlPznHEeLgOHiU6UTShmo+nayZ5NxtcSoK0rVhMmjU0vI+40
U0zi8q9b3g/r67ZtcIcnfGCheRnlVxaOfNeDvrDCdM3z4THj6mLdLioH3p5LipJt
mbof5rY9QSv7I2xS84T2SAw+QOsjPxv+OtJWZNsGMPTcfgYUMzP3TEzYKmNWxzmP
AWVP+FxX6DofZ+CnqoIXWV24MBJaWXzjbkGRtaxBh47w1IX6Y6EYtWmyx06rXID0
V3P34R4hokqmASA0VFYkf3V2fsooMw5+SLj7Gycf5JtkK2ooRbq1kj/O/GwLP+28
bI8rzMhGk53SEsWHnHouvlwUl3PpDOQ4gAjBG4IQ1+m4p94a5j18viN9Qw/yK+pg
aWuzO3zNPnNsYtn4mepJSqdVEhdDudso8vqj/dyHgtpC2omKcZT/wy0NLggDx2px
-----END CERTIFICATE REQUEST-----
-----BEGIN PRIVATE KEY-----
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
xmq2F2+l3MuWBv8K5+MIxZuqaAqO
-----END PRIVATE KEY-----
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAs6QLRZav8+ZVwJU2CknG
a0+F/VscZZqlGC4F60hB55Slm0rHVnWn1KQKOqkQSiqWbfxE32j8p+PIMeDGCcqm
O91ybHU5U0klbDTWo1H3GGxqSsPXIYRs6lhw8jVWyClX2UOi5mcRlz6iwpRflOPk
nJz3N6FYBFtgBPo8tFbmVTQRQrpEffCajNK/dKgRmV7F9u7N83qQA1Av7BwdZ9gb
lznPqTFiVBYy7yPmedJ8jkALBeqCHtwh3Ey+HLiM62uE1m4heHS2gOaQ8uDF5oi4
TO6wDmQMao3A9/r6RE3omOwZ1mQm/wfKxFsJ8J843/2fqcKe2J0MhvsZE0x4K5R1
6Bh28qCz9iaFUSVjmzmgLw0ZOgpMpcD92KRXVfL4yDABQ3tW6GOBs1sdyFvkLiHE
9E2GCKsBPixBMUW5QDKteKpHcbplmMfLdLvegtd8tTClByWo4XdBbdrdiEBV5mgp
RUizvM7h2kGUEa+sAe2zzFo0YBPotiqZgdjg7FbYF74AHkYMJU456eZ7Fv7IPA5R
gLQ1hDJeu9U9Ss7aWavsr9m2nwkpDV+Yv2dTweeD2iV9OylVmRgq8X9aj9Xqb/GT
61yuD30MgMV7uAPVShTOz3+ezlr4fJDm40C7G+6mlCpbsGE0TB/oMcp0/DVIE6XY
SWvIB7Sp3p/biUsD/8XOsMsCAwEAAQ==
-----END PUBLIC KEY-----
-----BEGIN PRIVATE KEY-----
MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQDt9I7q7STbVQO6
BlKBmtDnX8E6k1nYbEiPD3FFyV/zjSRs24WKmVgI1aV8driPX3hQfUHl67j1WoUx
yvvFPG8asHwRZctWlwwjnqjRenk62rXffMVTqqniSBd5jxtfQqrsmmhLFEp1LCCl
aCvRphCpufMEIxSRpPwcnnDlP2UJ4I8WjfbhGNOMxyYPGcaoTXbBTKkG6ahUS3dC
qLsHJ1gIoAFYwiMU1OQnazXjYkBVp8cQDVToKcwajlPs9sfWn0SkLRW7ht1LdnRN
KODgJl1jLjzXejk+wp8pkPSvi7Jh89CM2WAkJ4167fAI2If5xIjt+Tp35ccKczi2
TrR64UWpAgMBAAECggEASX/XwULcto7M5uHbDENYsY8HLWOkRdA0nVPExiyMYbs/
/AvWdNgmtBvh0M8O9OIlVJ9MAovMBqUeLSIooGSpYNIQkIMjyqw/SKVSOdodpgs2
UEDG5q/5Z3ajIZ4Nc2AxUYHkIwSydvzZXJ4PouMrlHFmWenICbCvWtupvXXWbLUC
jG5uN0nCKIpba1kdViOugRw6ugzI4Hr19Kt7hTGxDBrxPcSghUk/HQwtjO92dcad
NHZ5nT/r7h1LtmlOq75UCN6VHExgsryU2+JVOkm5PgMU1VNjuIqhKhG268QUfGHg
tYnwx3kvq3rAaEcBjNix9adV3YZAJ1OJiBcjj+e+sQKBgQD/ossVdJj5ZFlaPQOL
QL0iHH0BaTdyA/3yqLb153iCKiz9tvA8zTF3l0uDeCHZzBsQ62WoaNWSrIibiaUT
gcvUna4WnGqdiT1DDnVtiBqIJC2VHSZ65b0j1ZRPYHDBJv5JD2EId+8FHAApK1c6
H6T3DWLbJYHMC+H+oXLZjDASDQKBgQDuS1GJKyS3ioUkT5UarC7BhNG7FnzR+WYv
e8PCnHlzv54bylCwKs7CD6vS1IHG8zV9aSOU7ZXx88Et442IgtiTJ4h+hbd1LOeK
PniOG7/CLcLxZnqhZrAL99jejY2KUjYMvUm5WQ8Tf1yCeTOh5sq3Hcq/OIo6IVx+
UC/eiToHDQKBgQCL6HD1gSbn9z/f31y9LeVVcfoId6lcwUqPMD9SPij6NFMDWMgK
vtK//RHbFjiQluCJVgwBK78X003AsoiiMHt6FgJdZaYEKkRZGuSx2beLoyE/ZwDU
akAmCJJvDv0m+UxaeAxHMjyiszxzS8ElkoQaojzka5aqMiax0XKmFc+JUQKBgClC
+Xda9Ryi67MB5LudnOr9aKOQnURufvcx4w/LsGwOff4p5hbbErofpIz5Jw+gBV8V
2YdsLE6c+pJLmLJOldnFOqlN1hqAEAesEYvp2iZxbhQGvq077rfjzrWapSuSWLGU
BTQG68lggFBHVF1wbSGQEw9RZv3x0OY+VEugT1/xAoGARGLes+9pKiNsYR0U+OCJ
p9Vj7s/4bRqiWVEYyD69Npia/JCrUJDCn7dU8XBxHm1GOJKcDrMu9TW1lYkDIrtj
IhhKlOudYkgwpYvpxYS7NUG4FN2Ij+psUG+HCKUopH9adQQdzY7rvPvoREWLOgTu
nuZ4IybUag/ro8UWwgPoh8g=
-----END PRIVATE KEY-----
-----BEGIN CERTIFICATE-----
MIIF+jCCBOKgAwIBAgISBW2Z3jYPZ7lzrV34q14gP+7SMA0GCSqGSIb3DQEBCwUA
MDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBFbmNyeXB0MQwwCgYDVQQD
EwNSMTAwHhcNMjUwNjE3MjAyNjM4WhcNMjUwOTE1MjAyNjM3WjAaMRgwFgYDVQQD
Ew9tYWlsLmdldW1kby5uZXQwggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoIC
AQCzpAtFlq/z5lXAlTYKScZrT4X9WxxlmqUYLgXrSEHnlKWbSsdWdafUpAo6qRBK
KpZt/ETfaPyn48gx4MYJyqY73XJsdTlTSSVsNNajUfcYbGpKw9chhGzqWHDyNVbI
KVfZQ6LmZxGXPqLClF+U4+ScnPc3oVgEW2AE+jy0VuZVNBFCukR98JqM0r90qBGZ
XsX27s3zepADUC/sHB1n2BuXOc+pMWJUFjLvI+Z50nyOQAsF6oIe3CHcTL4cuIzr
a4TWbiF4dLaA5pDy4MXmiLhM7rAOZAxqjcD3+vpETeiY7BnWZCb/B8rEWwnwnzjf
/Z+pwp7YnQyG+xkTTHgrlHXoGHbyoLP2JoVRJWObOaAvDRk6CkylwP3YpFdV8vjI
MAFDe1boY4GzWx3IW+QuIcT0TYYIqwE+LEExRblAMq14qkdxumWYx8t0u96C13y1
MKUHJajhd0Ft2t2IQFXmaClFSLO8zuHaQZQRr6wB7bPMWjRgE+i2KpmB2ODsVtgX
vgAeRgwlTjnp5nsW/sg8DlGAtDWEMl671T1KztpZq+yv2bafCSkNX5i/Z1PB54Pa
JX07KVWZGCrxf1qP1epv8ZPrXK4PfQyAxXu4A9VKFM7Pf57OWvh8kObjQLsb7qaU
KluwYTRMH+gxynT8NUgTpdhJa8gHtKnen9uJSwP/xc6wywIDAQABo4ICHzCCAhsw
DgYDVR0PAQH/BAQDAgWgMB0GA1UdJQQWMBQGCCsGAQUFBwMBBggrBgEFBQcDAjAM
BgNVHRMBAf8EAjAAMB0GA1UdDgQWBBQS6kQXO/TUMRJSXZo8wuRdFU7vCzAfBgNV
HSMEGDAWgBS7vMNHpeS8qcbDpHIMEI2iNeHI6DAzBggrBgEFBQcBAQQnMCUwIwYI
KwYBBQUHMAKGF2h0dHA6Ly9yMTAuaS5sZW5jci5vcmcvMBoGA1UdEQQTMBGCD21h
aWwuZ2V1bWRvLm5ldDATBgNVHSAEDDAKMAgGBmeBDAECATAuBgNVHR8EJzAlMCOg
IaAfhh1odHRwOi8vcjEwLmMubGVuY3Iub3JnLzgzLmNybDCCAQQGCisGAQQB1nkC
BAIEgfUEgfIA8AB2AMz7D2qFcQll/pWbU87psnwi6YVcDZeNtql+VMD+TA2wAAAB
l3/IFlYAAAQDAEcwRQIhAMGJG+8pZNiNNFtyDyQfT7xiddPZHnakhA35jftHAWWK
AiBS+rZRV07VME4THIzd7+Bu3Zk+xQwKkwKeYTFdAIGEaQB2ABLxTjS9U3JMhAYZ
w48/ehP457Vih4icbTAFhOvlhiY6AAABl3/IFkcAAAQDAEcwRQIhAOmX9ha/eJR3
BFGZOZ8zgoP1MLj+QUQetC5oW318aODUAiBya+30cVbxeDv1nMbExA8IeGChuISs
r/IXps3ng+vE/TANBgkqhkiG9w0BAQsFAAOCAQEAPN519JygtLqHuZ5tD6BDHrXC
FE5nKf0VcqZO8p5GtuZlfKlLAy0ucFSoF6sU8UPe2xk0Z18VbmHujytpRQHTRs9m
okvAi1rKvZ4YTHBfHNGoZEXX3QUHdbZ4Siktg71Y9wywc4CDnf0BWjo/3JlxkUhb
32hQ/EphnxYjS3eIJnfSIzJ7Ba80jGMHCq46Xtgboj9xgAYL61zO1B4YaygjZEAd
XMVkiKjXsupu9OQ5+wzkQFH/opKlma9c8e3W0LtNzS98w9y0fjNQNCCq8Op1vsJC
DRn5fI2B7mcvCNwABjo/x2LqNLcRO4zKkZ7XD3hlSLCH+G3tM/GWEks4KX5LjA==
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIFBTCCAu2gAwIBAgIQS6hSk/eaL6JzBkuoBI110DANBgkqhkiG9w0BAQsFADBP
MQswCQYDVQQGEwJVUzEpMCcGA1UEChMgSW50ZXJuZXQgU2VjdXJpdHkgUmVzZWFy
Y2ggR3JvdXAxFTATBgNVBAMTDElTUkcgUm9vdCBYMTAeFw0yNDAzMTMwMDAwMDBa
Fw0yNzAzMTIyMzU5NTlaMDMxCzAJBgNVBAYTAlVTMRYwFAYDVQQKEw1MZXQncyBF
bmNyeXB0MQwwCgYDVQQDEwNSMTAwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK
AoIBAQDPV+XmxFQS7bRH/sknWHZGUCiMHT6I3wWd1bUYKb3dtVq/+vbOo76vACFL
YlpaPAEvxVgD9on/jhFD68G14BQHlo9vH9fnuoE5CXVlt8KvGFs3Jijno/QHK20a
/6tYvJWuQP/py1fEtVt/eA0YYbwX51TGu0mRzW4Y0YCF7qZlNrx06rxQTOr8IfM4
FpOUurDTazgGzRYSespSdcitdrLCnF2YRVxvYXvGLe48E1KGAdlX5jgc3421H5KR
mudKHMxFqHJV8LDmowfs/acbZp4/SItxhHFYyTr6717yW0QrPHTnj7JHwQdqzZq3
DZb3EoEmUVQK7GH29/Xi8orIlQ2NAgMBAAGjgfgwgfUwDgYDVR0PAQH/BAQDAgGG
MB0GA1UdJQQWMBQGCCsGAQUFBwMCBggrBgEFBQcDATASBgNVHRMBAf8ECDAGAQH/
AgEAMB0GA1UdDgQWBBS7vMNHpeS8qcbDpHIMEI2iNeHI6DAfBgNVHSMEGDAWgBR5
tFnme7bl5AFzgAiIyBpY9umbbjAyBggrBgEFBQcBAQQmMCQwIgYIKwYBBQUHMAKG
Fmh0dHA6Ly94MS5pLmxlbmNyLm9yZy8wEwYDVR0gBAwwCjAIBgZngQwBAgEwJwYD
VR0fBCAwHjAcoBqgGIYWaHR0cDovL3gxLmMubGVuY3Iub3JnLzANBgkqhkiG9w0B
AQsFAAOCAgEAkrHnQTfreZ2B5s3iJeE6IOmQRJWjgVzPw139vaBw1bGWKCIL0vIo
zwzn1OZDjCQiHcFCktEJr59L9MhwTyAWsVrdAfYf+B9haxQnsHKNY67u4s5Lzzfd
u6PUzeetUK29v+PsPmI2cJkxp+iN3epi4hKu9ZzUPSwMqtCceb7qPVxEbpYxY1p9
1n5PJKBLBX9eb9LU6l8zSxPWV7bK3lG4XaMJgnT9x3ies7msFtpKK5bDtotij/l0
GaKeA97pb5uwD9KgWvaFXMIEt8jVTjLEvwRdvCn294GPDF08U8lAkIv7tghluaQh
1QnlE4SEN4LOECj8dsIGJXpGUk3aU3KkJz9icKy+aUgA+2cP21uh6NcDIS3XyfaZ
QjmDQ993ChII8SXWupQZVBiIpcWO4RqZk3lr7Bz5MUCwzDIA359e57SSq5CCkY0N
4B6Vulk7LktfwrdGNVI5BsC9qqxSwSKgRJeZ9wygIaehbHFHFhcBaMDKpiZlBHyz
rsnnlFXCb5s8HKn5LsUgGvB24L7sGNZP2CX7dhHov+YhD+jozLW2p9W4959Bz2Ei
RmqDtmiXLnzqTpXbI+suyCsohKRg6Un0RC47+cpiVwHiXZAW+cn8eiNIjqbVgXLx
KPpdzvvtTnOPlC7SQZSYmdunr3Bf9b77AiC/ZidstK36dRILKz7OA54=
-----END CERTIFICATE-----
-----BEGIN PRIVATE KEY-----
MIIJQQIBADANBgkqhkiG9w0BAQEFAASCCSswggknAgEAAoICAQCzpAtFlq/z5lXA
lTYKScZrT4X9WxxlmqUYLgXrSEHnlKWbSsdWdafUpAo6qRBKKpZt/ETfaPyn48gx
4MYJyqY73XJsdTlTSSVsNNajUfcYbGpKw9chhGzqWHDyNVbIKVfZQ6LmZxGXPqLC
lF+U4+ScnPc3oVgEW2AE+jy0VuZVNBFCukR98JqM0r90qBGZXsX27s3zepADUC/s
HB1n2BuXOc+pMWJUFjLvI+Z50nyOQAsF6oIe3CHcTL4cuIzra4TWbiF4dLaA5pDy
4MXmiLhM7rAOZAxqjcD3+vpETeiY7BnWZCb/B8rEWwnwnzjf/Z+pwp7YnQyG+xkT
THgrlHXoGHbyoLP2JoVRJWObOaAvDRk6CkylwP3YpFdV8vjIMAFDe1boY4GzWx3I
W+QuIcT0TYYIqwE+LEExRblAMq14qkdxumWYx8t0u96C13y1MKUHJajhd0Ft2t2I
QFXmaClFSLO8zuHaQZQRr6wB7bPMWjRgE+i2KpmB2ODsVtgXvgAeRgwlTjnp5nsW
/sg8DlGAtDWEMl671T1KztpZq+yv2bafCSkNX5i/Z1PB54PaJX07KVWZGCrxf1qP
1epv8ZPrXK4PfQyAxXu4A9VKFM7Pf57OWvh8kObjQLsb7qaUKluwYTRMH+gxynT8
NUgTpdhJa8gHtKnen9uJSwP/xc6wywIDAQABAoICAFY7IZoG6nFWmMU4Gte3cEKk
yrnCWZBAOo2v0fGOHuyuQwyXSbasBaMiFzLvYr1nUgx7swfXGqjww3GF5ypeF4vX
Eg0T/C+Jhig5+Oou90DHEgLPnV4edjXLvHPXvM+aYOwO9oxI333NeE2U8YjEGEJB
ar5OebSltCLPiAI9UJWHx91TEnut2lJM+9BguQn5H2gYW85LgAPHIyngmRD3AM+H
1bHu3bdlbI+0mPbTXizeeywc1NdBbhOU1xFsWWDMnNhdxz1OMSkRBHVCBl1SNb3g
Oay+w+MGJqIi3K2bBFMbyo9KRhnXwLKezNevZprG4TSZEq0CPjgxImlMJMcunaW8
6hmxWZ0WsonCyrNes1p5+whqRqLaRp89OsrAO4Ttu4S/ElZmS92+BcgXV8pq9mcZ
S5304ARUvFjhS4VomNdrYVhBaUzqOhnywHwsYyW8PHFm1J/XezzaEffXNvNjtAQL
jXOibqpW1vganzRYnoHuoWARU/kRDVkaCqkNJ/XCQHvoAB8dFE2Apkv7+RqYMjcV
0vRHPs7Au6G2hZJPy8eG2WXFcrCbJ7AKGpuJtBAgWhUyXUDpPkTpn3U22Uj/nDin
eBaIRjGfW5szfxgWVAHD6eZkVtvyqlBJOd1MNgIZgBgnx/2ahBfNmDFLxBprnXa7
29gxB6oOSCUnV/t8zC3RAoIBAQDZYYLQ2MFzWHfRdoiKE5gyjy14Fjsr73X4udl6
TzSkIXWhwDepqpT20AWAd6gNf2TsNEnfoIz9YhDkmFp+O2nS9a/y5JQdvwDIgvJw
brIvZoUIpHv+6G/K0uJIeeIcQv96u5hXWTl3DqytsUYGth2RF7oVEcj/A+thkEjc
mA3UZhx66g/7d4aSIYMAbiyFKdBPffEkgpyJRtIRhdhSRVim6vM0MFDO3z6sNOQa
scVVaEB2qBoqRd0bXXIWkAoHjL+zUcRRqbTeTl9ZeTUi5gtLUyQacJoPSHJf5MyJ
91kZh0r/IPsekF3eZee4mradaC3nr3dVgdu0Zn+iIbL+/md5AoIBAQDTjhyw6irT
lQGU7N5EsmlJ5diLjCcdRGgXWSnNL2nrrrK00oe9bUPLAxC/vahGeVCHKU7AlmYA
hcduM8uO0Lr7R/6svjwLV2P0DdF605ERSj7eziEplVibYf1ZFsHMjSCo+Mq8HWBv
XpyATf1jBmsDxe/Wlz0Sqefxx4Des0aPZQOKBBqBWgj+oVzVunIWZoZteQlMtKWa
X5KsOxGNnpcQrOPNrTYX2L/ja7RN1kYGh11e3XsZvyxuCzQju/Pd7Pck6ESfuRJp
H80GGa694HcgNOTEdpkmYuxQEYXj2RA/8+pouQCiaZ9CHSJvZs0MikqW2S4SII6D
HZRkrHihvdVjAoIBAAQtDmFKuLSpj2uztj3I0JSwEXSMIMjgScjkcRwbZ2x7xBG+
apNU1pXDO0fThKP1vY+YFY85O1wmxSJPFvXz2D2YQLAO2hWUNMSlV1j3l263rniT
CFrGRleEI5q21LQsSVInRm7vJN53prOTgz/fwcOmzAlZlR3pCl2Ocwfh1+orqAJo
erQfALPP9v9MHojUW88bIUXNSIqOlLyHcLdr458ZRmDLSNIgkcinH3av0ZWpcguV
gSMswmmjKuzqCXdJqekc+gODmhjnMoe6f13TQ4ZH65qibSM8Bg53i8JewRRvd+5c
yNY2eccq9/+g4T824CLiSQ2YeAsIKQ2JTjH92ykCggEADzXgijfL7HqCKpr9QCMz
vsRv1Vi2Vzxb35Hhl4cZLoDZCHc6mzwH68jEo4SXXLnMOGuX5fDqVI9Jz3qZ4CLR
zs9WWEU1O/uEjD+SGCqt+3hDHPHlIIBEZqec95LTTEm5V2zL5sqV7Gv5BKCW30/O
0e6hV+R316evrYqSkXCCWj0BDCNPZI18qBIiApvtJ/8nGyfgq0sxvO+yM//rOytz
4RcNKfSSNxS2dzt/Mzl8v2tsIy35c9hy8VaM4STaW9J10omApZtA354Rt6aREcXZ
ys8Cw71jNYdXRkp8Pe2VZYO8Dtt+WC8P7Ej7+NaDV6t5wW7MCTGeDX9K9BISek6T
0QKCAQAxV1pTX7LnZZxLkOl6jTRBwOZ3PadMndklsodiUQDLWAMp9Ih0C40HlDKS
GSMscJy3ydPfZCDL+FeX5MpW14O5dlzBMMR8OMd/pPVpYmzgXKt7OxX0sngEEgQt
dPXtqjYRf3kbjJaC0es5FvyiBdi8aCEevWX4p8eSfjYhDy6/5Jzn477gKNh/4NmE
ArcyMKYg19Qrg90H7nj3LFyjjWomp2jf1s6Y3rS2A9CTgkwFTT292UkBQUKN9JKx
xmhc8Y0r9r3HYL+5fdNDXTErciuMoAL+vqG/zH5Wcjhy0mVxas7fkxe5GzVBjrPA
xmq2F2+l3MuWBv8K5+MIxZuqaAqO
-----END PRIVATE KEY-----
version: '3'
volumes:
mailserver_posteio:
services:
mailserver:
image: analogic/poste.io
container_name: poste-io
restart: always
ports:
- "25:25"
- "8800:80"
- "4433:443"
- "110:110"
- "143:143"
- "465:465"
- "587:587"
- "993:993"
- "995:995"
- "4190:4190"
environment:
- VIRTUAL_HOST=mail.geumdo.net
- LETSENCRYPT_HOST=mail.geumdo.net
- LETSENCRYPT_EMAIL=admin@mail.geumdo.net
volumes:
- /etc/localtime:/etc/localtime:ro
- mailserver_posteio:/data
- ./certs:/data/ssl
#!/bin/sh
create_volume() {
docker volume inspect $1 > /dev/null 2>&1
if [ $? -eq 0 ]; then
echo "Volume '$1' already exists."
else
docker volume create --name=$1
echo "Volume '$1' created."
fi
}
create_volume mailserver_posteio
docker build -t mailserver_posteio
docker-compose up -d --build
# os with ssh
# images
FROM ubuntu:22.04
ENV DEBIAN_FRONTEND=noninteractive
# package procedure(update&upgrade&install)
RUN apt-get update && \
apt-get upgrade -y && \
apt-get install -y vim net-tools zip unzip apt-utils iputils-ping wget tar curl language-pack-ko openssh-server git telnet nmap && \
apt-get install -y mysql-server mysql-client nginx sudo
# install php7.2
RUN apt-get install -y software-properties-common && \
add-apt-repository ppa:ondrej/php && \
apt-get update -y && \
apt-get install -y php7.2 php7.2-fpm libapache2-mod-php7.2 php7.2-mysql php7.2-mbstring php7.2-xml php7.2-gd php7.2-curl
# Set up configuration for SSH
RUN mkdir /var/run/sshd
RUN echo 'root:!@#gds$%^' | chpasswd
RUN sed -ri 's/^#?PermitRootLogin\s+.*/PermitRootLogin yes/' /etc/ssh/sshd_config
RUN echo " StrictHostKeyChecking no" >> /etc/ssh/ssh_config
# Add 'gds' user and set password
RUN useradd -m -s /bin/bash gds
RUN echo 'gds:gds12!@' | chpasswd
# Add 'gds' user to sudoers (Remove NOPASSWD to require password for sudo)
RUN usermod -aG sudo gds
# Disable 'su' command for 'gds' user by restricting access to 'root'
RUN dpkg-reconfigure -plow libpam-runtime
RUN echo "gds ALL=(ALL) ALL" >> /etc/sudoers # Allow sudo, with password
RUN chmod 750 /bin/su # Restrict access to 'su' for non-root users
# Set SSH to allow gds login and permit root login
RUN echo "AllowUsers gds" >> /etc/ssh/sshd_config
# SSH login fix. Otherwise, user is kicked off after login
RUN sed 's@session\s*required\s*pam_loginuid.so@session optional pam_loginuid.so@g' -i /etc/pam.d/sshd
# Install Node.js (16.20.0) and NPM (8.19.4)
RUN curl -fsSL https://deb.nodesource.com/setup_16.x | bash - \
&& apt-get install -y nodejs \
&& npm install -g npm@8.19.4
# MySQL 8 install and setting
RUN sed -ri 's/^#?bind-address\s+.*/bind-address = 0.0.0.0/' /etc/mysql/mysql.conf.d/mysqld.cnf
RUN sed -ri 's/^#?\s*port\s*=\s*[0-9]+/port = 53306/' /etc/mysql/mysql.conf.d/mysqld.cnf
RUN sed -ri 's/^#?max_allowed_packet\s+.*/max_allowed_packet = 16M/' /etc/mysql/mysql.conf.d/mysqld.cnf
RUN echo "default-time-zone='+09:00'" >> /etc/mysql/mysql.conf.d/mysqld.cnf
RUN echo "character-set-server=utf8mb4" >> /etc/mysql/mysql.conf.d/mysqld.cnf
#run script folder and copy script
RUN mkdir /service_script
COPY start_service.sh /service_script
COPY nodam.sql /service_script
RUN chmod +x /service_script/start_service.sh
#package clean unused
RUN apt-get clean && \
rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
# Expose port(SSH,NGINX,NODEJS,MYSQL)
EXPOSE 22 52530 52532 52533 53306
# Run SSH,NGINX,NODEJS,MYSQL
CMD ["/service_script/start_service.sh"]
# PHP & Node.js 하이브리드 애플리케이션 서버 (노담)
본 프로젝트는 Docker를 사용하여 '노담(Nodam)'으로 추정되는 PHP 및 Node.js 기반의 복합 웹 애플리케이션 서버 환경 전체를 패키징한 것입니다. 기존 서버의 파일 구조, 데이터베이스, 실행 환경을 그대로 Docker 컨테이너로 마이그레이션하여, `docker-compose up` 명령어 하나로 전체 시스템을 구동할 수 있도록 설계되었습니다.
## 기술 아키텍처
시스템은 Nginx, PHP-FPM, Node.js, MySQL 등 모든 구성요소가 단일 Docker 컨테이너에서 동작하는 올인원(All-in-one) 방식으로 구축되었습니다.
- **`Dockerfile`**: `ubuntu:22.04`를 기반으로, 애플리케이션 실행에 필요한 모든 서버 소프트웨어를 설치합니다.
- **웹/애플리케이션 서버**: Nginx, PHP 7.2-FPM, Node.js 16.x
- **데이터베이스 서버**: MySQL Server (컨테이너 내부 설치)
- **기타**: OpenSSH Server, 각종 빌드 도구 및 유틸리티
- **MySQL 설정**: `my.cnf` 파일을 직접 수정하여 외부 접속 허용, 포트 변경(53306), 타임존 및 캐릭터셋(utf8mb4) 설정을 적용합니다.
- **`docker-compose.yml`**:
- **단일 서비스 `os`**: 모든 컴포넌트가 설치된 `Dockerfile`을 빌드하여 `docker_nodam`이라는 이름의 컨테이너를 생성합니다.
- **포트 매핑**:
- `52530`: 관리자 ERP (PHP)
- `52532`: HTTP 서버 (Node.js)
- `52533`: TCP/IP 소켓 서버 (Node.js)
- `53306`: MySQL 데이터베이스
- `2236`: SSH
- **소스코드 및 설정 마운트**:
- `./home/ubuntu/node`: Node.js 소스코드
- `./var/www/html`: PHP 소스코드 (웹 루트)
- `./etc/nginx/sites-available/default`: Nginx 사이트 설정
- 이러한 구조는 호스트에서 소스코드와 설정을 직접 수정하고 관리할 수 있게 합니다.
- **데이터 영속성**: `nodam_dbconfig`, `nodam_dbdata`라는 외부 볼륨을 사용하여 MySQL의 설정과 데이터를 컨테이너가 삭제되어도 안전하게 보존합니다.
### 시스템 구동 워크플로우 (`start_service.sh`)
1. **서버 데몬 실행**: SSH, PHP-FPM, Nginx, MySQL 서비스를 순차적으로 시작합니다.
2. **데이터베이스 초기화**:
- MySQL 서버가 완전히 구동될 때까지 대기합니다.
- MySQL `root` 계정의 비밀번호를 스크립트 내에서 설정합니다.
- `nodam.sql` 파일을 `mysql` 클라이언트로 실행하여, 사전에 정의된 데이터베이스 스키마와 데이터를 모두 임포트합니다. 이를 통해 컨테이너는 항상 동일한 데이터 상태에서 시작합니다.
3. **Node.js 애플리케이션 실행**:
- `npm install` 명령어로 의존성 모듈을 설치합니다.
- `node index.js &`: 메인 HTTP 서버를 백그라운드로 실행합니다.
- `node socket.js &`: 실시간 통신을 위한 소켓 서버를 백그라운드로 실행합니다.
## 기술 스택
- **오케스트레이션**: Docker, Docker Compose
- **백엔드**: Node.js, PHP 7.2
- **웹 서버**: Nginx
- **데이터베이스**: MySQL
- **주요 언어**: JavaScript (Node.js), PHP
## 실행 방법
### 사전 요구사항
- Docker 및 Docker Compose
- `nodam_dbconfig`, `nodam_dbdata` 라는 이름의 Docker 외부 볼륨이 사전에 생성되어 있어야 합니다.
```bash
docker volume create nodam_dbconfig
docker volume create nodam_dbdata
```
### 실행
1. **Docker 이미지 빌드 및 컨테이너 실행**:
```bash
# (선택) 재빌드 및 실행 스크립트
./rebuild_docker.sh
# 또는 docker-compose 직접 실행
docker-compose up --build -d
```
최초 실행 시 `nodam.sql` 파일을 통해 데이터베이스를 구축하므로 다소 시간이 걸릴 수 있습니다.
2. **애플리케이션 접근**:
- **관리자 ERP**: `http://<서버_IP>:52530`
- **메인 서비스 (HTTP)**: `http://<서버_IP>:52532`
- 기타 서비스는 `docker-compose.yml`의 포트 매핑을 참고하여 접근합니다.
### 중지
```bash
docker-compose down
```
\ No newline at end of file
version: '3'
services:
os:
build:
context: .
dockerfile: Dockerfile
container_name: docker_nodam
ports:
- "2236:22" # SSH
- "52530:52530" # 관리자 erp
- "52532:52532" # http 서버
- "52533:52533" # TCP/IP 서버
- "53306:53306" # MYSQL
network_mode: bridge
restart: always
volumes:
- ./home/ubuntu/node:/home/ubuntu/node
- ./var/www/html:/var/www/html
- ./etc/nginx/sites-available/default:/etc/nginx/sites-available/default
- nodam_dbconfig:/etc/mysql
- nodam_dbdata:/var/lib/mysql
volumes:
nodam_dbconfig:
external: true
nodam_dbdata:
external: true
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##
# Default server configuration
#
server {
listen 52530 default_server;
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
#listen [::]:52530 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /var/www/html;
# Add index.php to the list if you are using PHP
index index.php index.html index.htm index.nginx-debian.html;
server_name _;
location /nodam/ {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
#try_files $uri $uri/ =404;
#proxy_buffers 8 1024k;
#proxy_buffer_size 1024k;
#proxy_buffering off;
#proxy_pass http://121.150.20.121:52530; #//port give by your need
#proxy_no_cache 1;
#proxy_cache_bypass 1;
#proxy_redirect off;
#proxy_set_header Host $host;
#proxy_set_header X-Real-IP $remote_addr;
#proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
#proxy_set_header Connection keep-alive;
try_files $uri $uri/ /nodam/index.php;
}
location /policy {
return 301 /policy/;
}
location /policy/ {
alias /var/www/html/nodamLand/resource/page/;
try_files $uri $uri/ index.html;
}
location /policy/css/ {
alias /var/www/html/nodamLand/resource/css/;
}
location /policy/images/ {
alias /var/www/html/nodamLand/resource/images/;
}
location ~ \.php$ {
#try_files $uri /index.php = 404;
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php7.2-fpm.sock;
#fastcgi_pass 127.0.0.1:52531;
#fastcgi_index index.php;
#fastcgi_buffers 16 16k;
#fastcgi_buffer_size 32k;
#fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
#fastcgi_read_timeout 600;
#include fastcgi_params;
}
location ~ /\.ht {
deny all;
}
location ~ ^/(application|system)/ {
return 403;
}
# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/run/php/php7.4-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}
var port = 52532;
import Filter from 'badwords-ko';
var filter = new Filter();
import {faker} from '@faker-js/faker';
import * as _ from 'underscore';
import multer from 'multer';
import path from 'path';
import mysql, {} from 'mysql2';
var conn = mysql.createConnection({
host: '127.0.0.1',
user: 'web',
password: '1q2w3e4r5t',
database: 'test_nodam',
port: 53306,
multipleStatements: true,
});
conn.addListener('error', function (err){
console.log(err);
});
conn.query(`select word from fword where is_active = 1`, function (err_00, res_00){
var arr_fword = [];
_.each(res_00, function (v, i){
arr_fword.push(v.word);
});
filter.addWords(...arr_fword);
//console.log(filter.options.list.length);
});
import express from 'express';
var app = express();
app.use(express.json({limit: '2mb'}));
app.use(express.urlencoded({limit: '2mb', extended: false}));
/*
app.get('/', function (req, res, next){
conn.query('select * from fword where is_active = 1 limit 10;', function (err_00, res_00){
console.log(res_00);
res.json(res_00);
});
});
*/
/* DESC: 입력받은 텍스트에서 비속어를 선별하고 * 처리하고 반환
* URL: http://121.150.20.121:52532/test_filter
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |chat |string |채팅내용
* OUTPUT: |code |int |0: 성공, 이외 실패
* |data |string |필터링된 채팅
* |message |string |실패 사유 같은 것들
*/
app.post('/test_filter', function (req, res, next){
console.log('/test_filter');
console.log(req.body);
var res_json = {code: 0, data: '', message: ''};
try{
var res_filt = filter.clean(req.body.chat);
res_json.data = res_filt;
res.send(res_json);
return;
}catch(err){
res_json.code = 1;
res.send(res_json);
return;
}
});
/* DESC: 회원 가입
* URL: http://121.150.20.121:52532/user_sign
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |id |string |아이디, 8자 이상 16자 이하
* |pw |string |비밀번호, 8자 이상 16자 이하
* |name |string |이름
* |sex |string |성별, 0: 여자, 1: 남자
* OUTPUT: |code |int |0: 성공, 1: 실패 - 아이디 중복, 2: 실패 - insert failed, 99: 실패 - invalid param
* |data |int |db에 저장된 index, 실패시 없음
* |message |string |실패 사유 같은 것들
*/
app.post('/user_sign', function (req, res, next){
console.log('/user_sign');
console.log(req.body);
var id = req.body.id;
var pw = req.body.pw;
var name = (req.body.name).trim();
name = name.replace(/\+s/g, '');
var sex = req.body.sex;
var res_json = {code: 0, data: '', message: ''};
if(!id || !pw || !name || (pw.length < 8 && pw.length > 16) || (id.length < 8 && pw.length > 16) || ((filter.clean(id)).indexOf('*') > -1) || ((filter.clean(name)).indexOf('*') > -1) || (id.indexOf(' ') > -1)){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select *
from user
where id = ${conn.escape(id)}`, function (err_00, res_00){
if(err_00 || (res_00.length > 0)){
console.log(err_00);
res_json.code = 1;
res.send(res_json);
return;
}
var query_insert = `insert into user(uid, id, pw, name, sex) values("${faker.string.uuid()}", ${conn.escape(id)}, ${conn.escape(pw)}, ${conn.escape(name)}, ${conn.escape(sex)})`;
conn.query(query_insert, function (err_01, res_01){
console.log(err_01);
console.log(res_01);
if(err_01){
res_json.code = 2;
res.send(res_json);
return;
}
res_json.data = res_01.insertId;
console.log(res_json);
res.send(res_json);
return;
});
});
});
/* DESC: 회원 탈퇴
* URL: http://121.150.20.121:52532/user_resign
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |id |string |아이디, 8자 이상 16자 이하
* |pw |string |비밀번호, 8자 이상 16자 이하
* OUTPUT: |code |int |0: 성공, 1: 실패 - 계정 없음, 2: 실패 - 탈퇴 실패, 99: 실패 - invalid param
* |data |int |db에 저장된 index, 실패시 없음
* |message |string |실패 사유 같은 것들
*/
app.post('/user_resign', function (req, res, next){
console.log('/user_resign');
console.log(req.body);
var id = req.body.id;
var pw = req.body.pw;
var res_json = {code: 0, data: '', message: ''};
if(!id || !pw){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select *
from user
where id = ${conn.escape(id)}
and pw = ${conn.escape(pw)}`, function (err_00, res_00){
if(err_00 || (res_00.length == 0)){
console.log(err_00);
res_json.code = 1;
res.send(res_json);
return;
}
console.log(res_00);
var uid_u = res_00[0].uid;
var query_update = `update user set is_active = 0 where uid = ${conn.escape(uid_u)}`;
conn.query(query_update, function (err_01, res_01){
if(err_01 || res_01.affectedRows == 0){
console.log(err_01);
res_json.code = 2;
res.send(res_json);
return;
}
res_json.data = res_01.affectedRows;
console.log(res_json);
res.send(res_json);
return;
});
});
});
/* DESC: 로그인
* URL: http://121.150.20.121:52532/user_login
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |id |string |아이디
* |pw |string |비밀번호
* OUTPUT: |code |int |0: 성공, 1: 실패 - 아이디 존재 X 혹은 비번, 2: 미션 혹은 간판 오류, 3: 실패 - 회원 탈퇴됨
* |data |array |
* |-user |json |
* |--uid |string |이용자 고유값
* |--id |string |아이디
* |--name |string |이름
* |--sex |int |0: 여자, 1: 남자
* |--costume |int |의상 기본값: 0(다 벗고 있는걸로 대충 적당히)
* |--head |int |모자 기본값: 0(안쓴것?)
* |--hair |int |머리카락 기본값: 0(대머리?)
* |--face |int |얼굴 기본값: 0(기본얼굴?)
* |--inventory |json |인벤토리 기본값: {"inven0":"0","inven1":"0","inven2":"0","inven3":"0"}
* |---inven0~3 |int |아이템
* |-user_level |json |진행정도 기본값: {level: -1, level: 1, point: 0, process: 0}
* |--uid |string |단계 고유값
* |--level |int |진행 단계
* |--point |int |획득 점수
* |--process |int |해당 단계 진행도
* |-user_sign |json |만든 간판 기본값: {uid: -1, data: -1, comment: ''}
* |--uid |string |간판 고유값
* |--data |int |표지판 그림
* |--comment |string |표지판 표제어
* |message |string |실패 사유 같은 것들
*/
app.post('/user_login', function (req, res, next){
console.log('/user_login');
console.log(req.body);
var id = req.body.id;
var pw = req.body.pw;
var res_json = {code: 0, data: '', message: ''};
if(!id || !pw){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select uid, id, name, sex, costume, head, hair, face, inventory, is_active
from user
where id = "${req.body.id}"
and pw = "${req.body.pw}"`, function (err_00, res_00){
if(err_00 || !res_00.length){
res_json.code = 1;
res.send(res_json);
return;
}
if(res_00[0].is_active == 0){
res_json.code = 3;
res.send(res_json);
return;
}
conn.query(`select uid, level, point, process
from user_level
where is_active = 1
and uid_u = "${res_00[0].uid}"
order by user_level.level desc;
select uid, data, comment
from user_sign
where is_active = 1
and uid_u = "${res_00[0].uid}";`, function (err_01, res_01){
if(err_01){
res_json.code = 2;
res.send(res_json);
return;
}
res_00[0].inventory = JSON.parse(res_00[0].inventory);
res_json.data = {
user: (res_00[0]),
user_level: res_01[0][0] || {level: 1, point: 0, process: 0},
user_sign: res_01[1][0] || {uid: -1, data: -1, comment: ''},
};
console.log(res_json);
res.send(res_json);
return;
});
});
});
/* DESC: 영상, 사운드, 그림 등 모든 미디어 데이터 호출
* URL: http://121.150.20.121:52532/get_media
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값(무작위 접근 차단 용도)
* OUTPUT: |code |int |0: 성공, 1: 실패 - 계정 존재 X, 2: 실패 - 미디어 없음 or select failed, 99: 실패 - invalid param
* |data |array json |
* |-type |int |0: 영상, 1: 소리, 2: 그림
* |-level |int |에셋이 사용되는 레벨(쓸데 있으면 사용)
* |-path |string |데이터의 경로, 대체로 링크 형태가 될 것
* |message |string |실패 사유 같은 것들
*/
app.post('/get_media', function (req, res, next){
console.log('/get_media');
console.log(req.body);
var uid_u = req.body.uid_u;
var res_json = {code: 0, data: '', message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select *
from user
where uid = "${uid_u}"`, function (err_00, res_00){
if(err_00 || !res_00.length){
res_json.code = 1;
res.send(res_json);
return;
}
conn.query(`select media.type, media.level, media.path
from media
where is_active = 1
order by media.level, media.type`, function (err_01, res_01){
if(err_01 || !res_01.length){
res_json.code = 2;
res.send(res_json);
return;
}
res_json.data = res_01;
res.send(res_json);
return;
});
});
});
/* DESC: 이용자의 현재 진행 레벨과 누적 경험치(점수) 등을 획득
* URL: http://121.150.20.121:52532/get_user_level
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값(무작위 접근 차단 용도)
* OUTPUT: |code |int |0: 성공, 1: 실패 - 계정 존재 X or select failed
* |data |array json |기본값: {uid: -1, level: 0, point: 0, process: 0}
* |-uid |string |레벨 고유값
* |-level |int |현재 진행중인 레벨
* |-process |int |현재 진행중인 레벨의 진행 정도(의미 없을 수 있음)
* |-point |int |지금까지 획득한 누적 경험치
* |message |string |실패 사유 같은 것들
*/
app.post('/get_user_level', function (req, res, next){
console.log('/get_user_level');
console.log(req.body);
var uid_u = req.body.uid_u;
var res_json = {code: 0, data: '', message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select *
from user
where uid = "${uid_u}";
select level, point, process
from user_level
where is_active = 1
and uid_u = "${uid_u}"
order by user_level.level desc`, function (err_00, res_00){
if(err_00 || !res_00[0].length){
res_json.code = 1;
res.send(res_json);
return;
}
res_json.data = res_00[1] || [{uid: -1, level: 0, point: 0, process: 0}];
res.send(res_json);
return;
});
});
/* DESC: 이용자의 레벨 진행 정보 등록 혹은 갱신
* URL: http://121.150.20.121:52532/update_user_level
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값(무작위 접근 차단 용도)
* |point |int |획득한 점수
* |process |int |진행도
* OUTPUT: |code |int |0: 성공, 1: 실패 - 계정 존재 X or select failed, 2: 실패 - insert or update failed
* |data |int |0: 갱신 혹은 등록 실패, 1: 갱신 혹은 등록 성공
* |message |string |실패 사유 같은 것들
*/
app.post('/update_user_level', function (req, res, next){
console.log('/update_user_level');
console.log(req.body);
var uid_u = req.body.uid_u;
var level = req.body.level || 1;
var point = req.body.point || 0;
var process = req.body.process || 0;
var res_json = {code: 0, data: '', message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select *
from user
where uid = "${uid_u}";
select *
from user_level
where is_active = 1
and uid_u = "${uid_u}"`, function (err_00, res_00){
if(err_00 || !res_00[0].length){
res_json.code = 1;
res.send(res_json);
return;
}
var query_str = `insert into user_level(uid, uid_u, level, point, process)
values("${faker.string.uuid()}", "${uid_u}", "${level}", "${point}", "${process}")`;
if(res_00[1].length){
query_str = `update user_level
set level = "${level}", point = "${point}", process = "${process}"
where uid_u = "${uid_u}"`;
}
conn.query(query_str, function (err_01, res_01){
if(err_01){
res_json.code = 2;
res.send(res_json);
return;
}
res_json.data = res_01.affectedRows;
res.send(res_json);
return;
});
});
});
/* DESC: 이용자의 레벨 진행 정보 초기화
* URL: http://121.150.20.121:52532/reset_user_level
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* OUTPUT: |code |int |0: 성공, 1: 실패 - 계정 없음 or 레벨 없음, 2: 실패 - update failed
* |data |int |0: 갱신 실패, >= 1: 갱신 성공
* |message |string |실패 사유 같은 것들
*/
app.post('/reset_user_level', function (req, res, next){
console.log('/del_user_level');
console.log(req.body);
var uid_u = req.body.uid_u;
var res_json = {code: 0, data: '', message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select *
from user
where uid = "${uid_u}";
select *
from user_level
where uid_u = "${uid_u}";
update user_level
set is_active = 0
where uid_u = "${uid_u}"`, function (err_00, res_00){
console.log(res_00);
if(err_00 || !res_00[0].length || !res_00[1].length){
res_json.code = 1;
res.send(res_json);
return;
}
res_json.data = res_00[2].affectedRows;
res.send(res_json);
return;
});
});
/* DESC: 이용자의 코스튬 정보 갱신
* 이름이 빈칸이면 오류 반환
* URL: http://121.150.20.121:52532/update_user_costume
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* |head |int |대갈통
* |hair |int |머리스타일
* |face |int |와꾸
* |costume |int |의상
* |sex |int |성별
* |name |string |이름
* OUTPUT: |code |int |0: 성공, 1: 실패 - 계정 없음, 2: 실패 - update failed
* |data |int |0: 갱신 실패, >= 1: 갱신 성공
* |message |string |실패 사유 같은 것들
*/
app.post('/update_user_costume', function (req, res, next){
console.log('/update_user_costume');
console.log(req.body);
var uid_u = req.body.uid_u;
var head = req.body.head;
var hair = req.body.hair;
var face = req.body.face;
var costume = req.body.costume;
var sex = req.body.sex;
var name = req.body.name;
var res_json = {code: 0, data: '', message: ''};
if(!uid_u || (name.length < 0) || ((filter.clean(name)).indexOf('\*') > 0)){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select *
from user
where uid = "${uid_u}";`, function (err_00, res_00){
if(err_00 || !res_00.length){
res_json.code = 1;
res.send(res_json);
return;
}
conn.query(`update user
set head = "${head}", hair = "${hair}", face = "${face}", costume = "${costume}", sex = "${sex}", name = ${conn.escape(name)}
where uid = ${conn.escape(uid_u)}`, function (err_01, res_01){
if(err_01){
res_json.code = 2;
res.send(res_json);
return;
}
res_json.data = res_01.affectedRows;
res.send(res_json);
return;
});
});
});
/* DESC: 이용자 정보 획득
* URL: http://121.150.20.121:52532/get_user
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* OUTPUT: |code |int |0: 성공, 1: 실패 - 계정 없음, 2: 실패 - update failed
* |data | |
* |-user |json |
* |--uid |string |이용자 고유값
* |--id |string |아이디
* |--name |string |이름
* |--sex |int |0: 여자, 1: 남자
* |--costume |int |의상 기본값: 0(다 벗고 있는걸로 대충 적당히)
* |--head |int |모자 기본값: 0(안쓴것?)
* |--hair |int |머리카락 기본값: 0(대머리?)
* |--face |int |얼굴 기본값: 0(기본얼굴?)
* |--inventory |json |인벤토리 기본값: {"inven0":"0","inven1":"0","inven2":"0","inven3":"0"}
* |---inven0~3 |int |아이템
* |-user_level |json |진행정도 기본값: {level: -1, level: 1, point: 0, process: 0}
* |--uid |string |단계 고유값
* |--level |int |진행 단계
* |--point |int |획득 점수
* |--process |int |해당 단계 진행도
* |-user_sign |json |만든 간판 기본값: {uid: -1, data: -1, comment: ''}
* |--uid |string |표지판 고유값
* |--data |int |표지판 그림
* |--comment |string |표지판 표제어
* |message |string |실패 사유 같은 것들
*/
app.post('/get_user', function (req, res, next){
console.log('/get_user_by_uid');
console.log(req.body);
var uid_u = req.body.uid_u;
var res_json = {code: 0, data: '', message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select uid, id, name, sex, costume, head, hair, face, inventory
from user
where uid = "${uid_u}"`, function (err_00, res_00){
if(err_00 || !res_00.length){
res_json.code = 1;
res.send(res_json);
return;
}
conn.query(`select uid, level, point, process
from user_level
where uid_u = "${res_00[0].uid}";
select uid, data, comment
from user_sign
where uid_u = "${res_00[0].uid}";`, function (err_01, res_01){
if(err_01){
res_json.code = 2;
res.send(res_json);
return;
}
res_00[0].inventory = JSON.parse(res_00[0].inventory);
res_json.data = {
user: (res_00[0]),
user_level: res_01[0][0] || {level: 1, point: 0, process: 0},
user_sign: res_01[1][0] || {uid: -1, data: -1, comment: ''},
};
console.log(res_json);
res.send(res_json);
return;
});
});
});
/* DESC: 이용자의 인벤토리 내용물 변경
* item = 0 일 때, 아이템 없음으로 취급
* URL: http://121.150.20.121:52532/set_inventory
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* |slot |int |인벤토리칸, 0~3
* |item |int |아이템 종류, 0~4(임시)
* OUTPUT: |code |int |0: 성공, 1: 실패 - 계정 없음, 2: 실패 - update failed
* |data |int |0: 갱신 실패, >= 1: 갱신 성공
* |message |string |실패 사유 같은 것들
*/
app.post('/set_inventory', function (req, res, next){
console.log('/set_inventory');
console.log(req.body);
var uid_u = req.body.uid_u;
var slot = req.body.slot | 0;
var item = req.body.item | 0;
var res_json = {code: 0, data: '', message: ''};
if(!uid_u || !(0 <= slot && slot < 4) || !(0 <= item && item < 5)){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select inventory
from user
where uid = ${conn.escape(uid_u)}`, function (err_00, res_00){
if(err_00 || !res_00.length){
res_json.code = 1;
res.send(res_json);
return;
}
var json_inven = JSON.parse(res_00[0].inventory);
if(slot == 0) json_inven.inven0 = item;
if(slot == 1) json_inven.inven1 = item;
if(slot == 2) json_inven.inven2 = item;
if(slot == 3) json_inven.inven3 = item;
var string_inven = JSON.stringify(json_inven);
conn.query(`update user
set inventory = ${conn.escape(string_inven)}
where uid = ${conn.escape(uid_u)}`, function (err_01, res_01){
if(err_01){
res_json.code = 2;
res.send(res_json);
return;
}
res_json.data = res_01.affectedRows;
res.send(res_json);
return;
});
});
});
/* DESC: 이용자의 인벤토리 초기화
* 초기값은 {"inven0":0,"inven1":0,"inven2":0,"inven3":0}
* URL: http://121.150.20.121:52532/reset_inventory
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* OUTPUT: |code |int |0: 성공, 1: 실패 - update failed
* |data |int |0: 갱신 실패, >= 1: 갱신 성공
* |message |string |실패 사유 같은 것들
*/
app.post('/reset_inventory', function (req, res, next){
console.log('/reset_inventory');
console.log(req.body);
var uid_u = req.body.uid_u;
var res_json = {code: 0, data: '', message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`update user
set inventory = '{"inven0":0,"inven1":0,"inven2":0,"inven3":0}'
where uid = ${conn.escape(uid_u)}`, function (err_00, res_00){
if(err_00){
console.log(err_00);
res_json.code = 1;
res.send(res_json);
return;
}
res_json.data = res_00.affectedRows;
res.send(res_json);
return;
});
});
/* DESC: 이용자의 인벤토리 정보 획득
* URL: http://121.150.20.121:52532/get_inventory
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* OUTPUT: |code |int |0: 성공, 1: 실패 - 계정 없음
* |data |json |
* ||inven0 |int |아이템 종류 0~4
* ||inven1 |int |아이템 종류 0~4
* ||inven2 |int |아이템 종류 0~4
* ||inven3 |int |아이템 종류 0~4
* |message |string |실패 사유 같은 것들
*/
app.post('/get_inventory', function (req, res, next){
console.log('/get_inventory');
console.log(req.body);
var uid_u = req.body.uid_u;
var res_json = {code: 0, data: '', message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select inventory
from user
where uid = ${conn.escape(uid_u)}`, function (err_00, res_00){
if(err_00 || !res_00.length){
res_json.code = 1;
res.send(res_json);
return;
}
res_json.data = JSON.parse(res_00[0].inventory);
res.send(res_json);
return;
});
});
/* DESC: 이용자가 미션을 시작했다고 알림
* 반환되는 uid_m을 통해 이용자의 미션 고유값 판단
* URL: http://121.150.20.121:52532/set_mission
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* |level |string |이용자 고유값
* OUTPUT: |code |int |0: 성공, 1: insert failed
* |data |json |
* ||uid_m |string |미션 고유값
* |message |string |실패 사유 같은 것들
*/
app.post('/set_mission', function (req, res, next){
console.log('/set_mission');
console.log(req.body);
var res_json = {code: 0, data: {}, message: ''};
var uid_u = req.body.uid_u;
var level = req.body.level;
var uid_m = faker.string.uuid();
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`update user_level
set is_active = 0
where uid_u = ${conn.escape(uid_u)}
and level = ${conn.escape(level)};
insert into user_level(uid, uid_u, level)
values("${uid_m}", ${conn.escape(uid_u)}, ${conn.escape(level)});`, function (err_00, res_00){
if(err_00){
console.log(err_00);
res_json.code = 1;
res.send(res_json);
return;
}
res_json.data = {
uid_m: uid_m
};
res.send(res_json);
return;
});
});
/* DESC: 미션 고유값을 기반으로 미션 정보 갱신
* 점수는 현재까지 누적된 값을 전송해주면 됨
* URL: http://121.150.20.121:52532/update_mission
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_m |string |미션 고유값
* |point |int |누적 획득 점수
* |process |int |진행률, 현재는 쓸 일 없음, 기본값 0
* OUTPUT: |code |int |0: 성공, 1: update failed
* |data |json |
* |message |string |실패 사유 같은 것들
*/
app.post('/update_mission', function (req, res, next){
console.log('/update_mission');
console.log(req.body);
var res_json = {code: 0, data: {}, message: ''};
var uid_m = req.body.uid_m;
var point = req.body.point;
var process = req.body.process || '0';
if(!uid_m){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`update user_level
set point = ${conn.escape(point)},
process = ${conn.escape(process)}
where uid = ${conn.escape(uid_m)}`, function (err_00, res_00){
if(err_00){
console.log(err_00);
res_json.code = 1;
res.send(res_json);
return;
}
res.send(res_json);
return;
});
});
/* DESC: 이용자 고유값을 통해 모든 미션을 초기화
* URL: http://121.150.20.121:52532/reset_mission
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* OUTPUT: |code |int |0: 성공, 1: update failed
* |data |json |-
* |message |string |실패 사유 같은 것들
*/
app.post('/reset_mission', function (req, res, next){
console.log('/reset_mission');
console.log(req.body);
var uid_u = req.body.uid_u;
var res_json = {code: 0, data: {}, message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`update user_level
set is_active = 0
where uid_u = ${conn.escape(uid_u)}`, function (err_00, res_00){
if(err_00){
res_json.code = 1;
res.send(res_json);
return;
}
res.send(res_json);
return;
});
});
/* DESC: 각 미션에 해당하는 질문/답변/해설 등을 받아 옴
* URL: http://121.150.20.121:52532/get_question
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* OUTPUT: |code |int |0: 성공, 1: select failed
* |data |json |
* |-level |int |미션 넘버
* |-type |int |0: 시험 문제, 이것만 보냄
* |-question |string |시험 문제
* |-answers |array json |
* ||-a |string |답변
* ||-c |int |if type == 0, 0: 오답, 1: 정답
* || | |else, 점수(설문)
* |-explain |string |해설
* |message |string |실패 사유 같은 것들
*/
app.post('/get_question', function (req, res, next){
console.log('/get_question');
console.log(req.body);
var uid_u = req.body.uid_u;
var res_json = {code: 0, data: '', message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select q.level, q.type, q.question, q.answers, q.explain
from question as q
where q.is_active = 1
and q.type = 0`, function (err_00, res_00){
//console.log(res_00);
if(err_00 ||(res_00.length == 0)){
res_json.code = 1;
res.send(res_json);
return;
}
for(var i = 0; i < res_00.length; i++){
res_00[i].answers = JSON.parse(res_00[i].answers);
}
res_json.data = res_00;
console.log(res_json);
res.send(res_json);
return;
});
;})
/*
간판 점유 기능
간판 점유 여부 확인 기능
- 간판 점유 남은 시간 반환 기능
스크린샷 저장 기능 -> 서버에 png 파일을 저장하는 방법에 대해
설문조사 불러오기
설문조사 결과 저장
- json 형태로 저장하되 문제의 개수 및 선택한 답변의 점수 표시
- 총점 저장
이용약관
http://121.150.20.121:52530/terms_of_service.html
개인정보보호정책
http://121.150.20.121:52530/privacy_policy.html
*/
var upload = multer({
storage: multer.diskStorage({
destination: function (req, file, done){
done(null, 'uploads/');
},
filename: function (req, file, done){
var ext = path.extname(file.originalname);
var filename = path.basename(file.originalname, ext) + ext;
done(null, filename);
}
}),
limits: {
fileSize: 2 * 1024 * 1024,
}
});
//app.get('/test_upload', function (req, res, next){
// res.sendFile('C:/jamong/240722_server_test/test_upload.html');
//});
app.get('/get_image', function (req, res, next){
res.sendFile(`/home/ubuntu/node/uploads/${req.query.uid_u}.png`);
});
/* DESC: 스크린샷을 서버에 저장하고 서버상 경로, 파일 크기 및 db상 인덱스 반환
* 파일의 필드네임은 file_image
* 파일 이름은 uid_u(이용자 고유값을 사용할 것을 권장)
* 파일의 확장자는 반드시 png로 설정할 것
* URL: http://121.150.20.121:52532/set_image
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |file_image |file |{이용자 고유값}.png
* OUTPUT: |code |int |0: 성공, 1: update or insert failed
* |data |json |
* |-insert_id |int |db상 인덱스, 0 초과시 정상
* |-path |string |서버상 데이터 저장 경로
* |-size |int |파일 크기
* |message |string |실패 사유 같은 것들
*/
app.post('/set_image', upload.single('file_image'), function (req, res, next){
console.log('/set_image');
console.log(req.file);
var path = req.file.path;
var size = req.file.size;
var filename = req.file.filename;
var uid_u = filename.split('.')[0];
var res_json = {code: 0, data: {
insert_id: 0,
path: path,
size: size,
}, message: ''};
conn.query(`update user_screenshot set is_active = 0 where uid_u = ${conn.escape(uid_u)};
insert into user_screenshot(uid_u) values(${conn.escape(uid_u)});`, function (err_00, res_00){
if(err_00){
console.log(err_00);
res_json.code = 1;
res.send(res_json);
return;
}
res_json.data.insert_id = res_00[1].insertId;
res.send(res_json);
return;
});
});
/* DESC: 새로운 설문조사 결과를 저장
* URL: http://121.150.20.121:52532/set_user_survey
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* |a0 |int |첫번째 답변 점수
* |a1 |int |두번째 답변 점수
* |a2 |int |세번째 답변 점수
* |amount |int |모든 답변 점수 총합
* OUTPUT: |code |int |0: 성공, 1: update or insert failed
* |data |json |
* |-uid_us |string |표지판 고유값
* |message |string |실패 사유 같은 것들
*/
app.post('/set_user_survey', function (req, res, next){
console.log('/set_user_survey');
console.log(req.body);
var uid_u = req.body.uid_u;
var a0 = req.body.a0;
var a1 = req.body.a1;
var a2 = req.body.a2;
var amount = req.body.amount;
var res_json = {code: 0, data: {}, message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
var answers = {
a0: a0,
a1: a1,
a2: a2,
};
conn.query(`update user_survey
set is_active = 0
where uid_u = ${conn.escape(uid_u)};
insert into user_survey(uid_u, answers, amount)
values(${conn.escape(uid_u)}, ${conn.escape(JSON.stringify(answers))}, ${amount});`, function (err_00, res_00){
if(err_00){
console.log(err_00);
res_json.code = 1;
res.send(res_json);
return;
}
res_json.data = res_00[1].insertId;
res.send(res_json);
return;
});
});
/* DESC: 설문조사 질문지들을 모두 받아옴
* 답변 텍스트 및 점수는 모두 통일할 예정
* 퀴즈와는 달리 정답이 존재하는게 아니라, 누적시킬 점수만 존재함
* URL: http://121.150.20.121:52532/get_survey
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* OUTPUT: |code |int |0: 성공, 1: select failed
* |data |json |
* |-question |string |표지판 고유값
* |-answers |array json |
* |--a |string |답변 텍스트
* |--c |string |좋지 않다: 0, 보통이다: 1, 좋다: 2
* |message |string |실패 사유 같은 것들
*/
app.post('/get_survey', function (req, res, next){
console.log('/get_survey');
console.log(req.body);
var uid_u = req.body.uid_u;
var res_json = {code: 0, data: {}, message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select question, answers from question where type = 1 and is_active = 1`, function (err_00, res_00){
if(err_00 || (res_00.length == 0)){
console.log(err_00);
res_json.code = 1;
res.send(res_json);
return;
}
res_json.data = res_00;
for(var i = 0; i < (res_json.data).length; i++){
res_json.data[i].answers = JSON.parse(res_json.data[i].answers);
}
res.send(res_json);
return;
});
});
/* DESC: 새로운 표지판을 저장하고 해당하는 고유값을 반환
* URL: http://121.150.20.121:52532/set_user_sign
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* |data |int |클라이언트상 표지판의 번호
* |comment |string |표지판 표제어
* OUTPUT: |code |int |0: 성공, 1: update or insert failed, 2: 표제어 필터링됨
* |data |json |
* |-uid_us |string |표지판 고유값
* |message |string |실패 사유 같은 것들
*/
app.post('/set_user_sign', function (req, res, next){
console.log('/set_user_sign');
console.log(req.body);
var uid_u = req.body.uid_u;
var data = req.body.data;
var comment = req.body.comment;
var res_json = {code: 0, data: {}, message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
if(((filter.clean(comment)).indexOf('*') > -1)){
res_json.code = 2;
res.send(res_json);
return;
}
var uid = faker.string.uuid();
conn.query(`update user_sign
set is_active = 0
where uid_u = ${conn.escape(uid_u)};
insert into user_sign(uid, uid_u, data, comment)
values(${conn.escape(uid)}, ${conn.escape(uid_u)}, ${conn.escape(data)}, ${conn.escape(comment)});`, function (err_00, res_00){
if(err_00){
console.log(err_00);
res_json.code = 1;
res.send(res_json);
return;
}
res_json.data = {
uid_us: uid
};
res.send(res_json);
return;
});
});
/* DESC: 이용자의 간판을 불러옴
* URL: http://121.150.20.121:52532/get_user_sign
* METHOD: POST
* |NAME |TYPE |DESC
* INPUT: |uid_u |string |이용자 고유값
* OUTPUT: |code |int |0: 성공, 1: select failed
* |data |json |
* |-uid |string |표지판 고유값
* |-data |int |표지판 그림
* |-comment |string |표지판 표제어
* |message |string |실패 사유 같은 것들
*/
app.post('/get_user_sign', function (req, res, next){
console.log('/get_user_sign');
console.log(req.body);
var uid_u = req.body.uid_u;
var res_json = {code: 0, data: {}, message: ''};
if(!uid_u){
res_json.code = 99;
res.send(res_json);
return;
}
conn.query(`select uid, data, comment from user_sign where uid_u = ${conn.escape(uid_u)} and is_active = 1`, function (err_00, res_00){
if(err_00 || (res_00.length == 0)){
res_json.code = 1;
res.send(res_json);
return;
}
res_json.data = res_00[0];
res.send(res_json);
return;
});
});
app.get('/get_test', function (req, res, next){
conn.query('select * from user where id="safaquiel"', function (err_00, res_00){
if(err_00){
res.send(err_00);
}
res.send(res_00);
});
});
app.get('/test_chat', function (req, res, next){
console.log('/test_chat');
console.log(req.query);
res.sendFile('C:/jamong/240722_server_test/test_socket_chat.html');
});
// 쓰레기 자동 삭제 및 생성
setInterval(function (){
conn.query('select 1');
console.log('database handshake');
}, 180000);
app.listen(port, function (){
console.log(port);
});
/*
import {WebSocketServer} from 'ws';
const sockserver = new WebSocketServer({ port: 52534 })
sockserver.on('connection', ws => {
console.log('New client connected!')
ws.send('connection established')
ws.on('close', () => console.log('Client has disconnected!'))
ws.on('message', data => {
sockserver.clients.forEach(client => {
console.log(`distributing message: ${data}`)
client.send(`${data}`)
})
})
ws.onerror = function () {
console.log('websocket error')
}
ws.on('jump', function (data){
console.log(data);
client.send('jump', data);
});
});
*/
import Filter from 'badword-filter-ko';
var filter = new Filter();
console.log('안녕 시발아');
console.log(filter.clean('안녕 시발아'));
/*
export function get_filtered(str){
return filter.clean(str);
}
*/
\ No newline at end of file
var port = 52533;
import Filter from 'badwords-ko';
var filter = new Filter();
import mysql, {} from 'mysql2';
var conn = mysql.createConnection({
host: '127.0.0.1',
user: 'web',
password: '1q2w3e4r5t',
database: 'test_nodam',
port: 53306,
multipleStatements: true,
});
conn.addListener('error', function (err){
console.log(err);
});
conn.query(`select word from fword where is_active = 1`, function (err_00, res_00){
var arr_fword = [];
_.each(res_00, function (v, i){
arr_fword.push(v.word);
});
filter.addWords(...arr_fword);
});
import {createServer} from 'http';
import express from 'express';
import {Server} from 'socket.io';
var app = express();
var server = createServer(app);
var io = new Server(server, {
cors: {
origin: '*',
methods: ['GET', 'POST'],
},
allowEIO3: true
});
import moment from 'moment';
server.listen(port, function (){
console.log(port);
});
io.engine.on('connection_error', function (err){
console.log(err);
});
import {faker} from '@faker-js/faker';
import * as _ from 'underscore';
var arr_trash = [];
var arr_trash_exclude = [
// 나무
{x: 4, y: 4},
{x: 4, y: 14},
{x: 14, y: 4},
{x: 14, y: 14},
// 호수
{x: 9, y: 6},
{x: 9, y: 7},
{x: 6, y: 9},
{x: 7, y: 9},
{x: 11, y: 9},
{x: 12, y: 9},
{x: 9, y: 11},
{x: 9, y: 12},
{x: 8, y: 8},
{x: 9, y: 8},
{x: 10, y: 8},
{x: 8, y: 9},
{x: 9, y: 9},
{x: 10, y: 9},
{x: 8, y: 10},
{x: 9, y: 10},
{x: 10, y: 10},
];
var arr_sign = [
{uid_us: -1, data: -1, comment: '', set_at: parseInt(moment.now() / 1000) - 300},
{uid_us: -1, data: -1, comment: '', set_at: parseInt(moment.now() / 1000) - 300},
{uid_us: -1, data: -1, comment: '', set_at: parseInt(moment.now() / 1000) - 300},
{uid_us: -1, data: -1, comment: '', set_at: parseInt(moment.now() / 1000) - 300},
];
console.log(arr_sign);
function set_arr_trash(){
do{
if(arr_trash.length >= 50){
break;
}
while(true){
var trash = {
x: faker.number.int({min: 1, max: 17}),
y: faker.number.int({min: 1, max: 17}),
//type: 1
type: faker.number.int({min: 1, max: 4})
};
// 이미 쓰레기가 있는 곳들은 제외
var is_in = _.find(arr_trash, function (v){
return ((v.x == trash.x) && (v.y == trash.y));
});
// 사물이나 호수 등이 있는 곳들은 제외
var is_exclude = _.find(arr_trash_exclude, function (v){
return ((v.x == trash.x) && (v.y == trash.y));
});
// 둘 모두 해당사항이 없어야 쓰레기가 생성됨
if((is_in == undefined) && (is_exclude == undefined)){
arr_trash.push(trash);
break;
}
}
}while(true);
console.log(`set_arr_trash\t${new Date()}`);
/*
var arr_trash_visual = [
['■','■','■','■','■','■','■','■','■','■','■','■','■','■','■','■','■','■','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ','■',' ',' ',' ',' ',' ',' ',' ',' ',' ','■',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ','■',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ','■',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ','■','■','■',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ','■','■','■','■','■','■','■',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ','■','■','■',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ','■',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ','■',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ','■',' ',' ',' ',' ',' ',' ',' ',' ',' ','■',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ',' ','■'],
['■','■','■','■','■','■','■','■','■','■','■','■','■','■','■','■','■','■','■'],
];
for(var i = 0; i < arr_trash.length; i++){
if(arr_trash[i].type > 0){
var x = arr_trash[i].x;
var y = arr_trash[i].y;
arr_trash_visual[x][y] = '★';
}
}
for(var i = 0; i < arr_trash_visual.length; i++){
console.log(arr_trash_visual[i].join(' '));
}
*/
}
set_arr_trash()
// 쓰레기 자동 삭제 및 생성
setInterval(function (){
arr_trash.shift();
set_arr_trash();
}, 10000);
// 쓰레기 자동 삭제 및 생성
setInterval(function (){
conn.query('select 1');
console.log('database handshake');
}, 1800000);
var json_user = {};
io.on('connect', function (socket){
console.log(`connect\t${socket.id}\t${socket.client.conn.server.clientsCount}`);
console.log(`count\t${socket.client.conn.server.clientsCount}`);
json_user[`${socket.id}`] = {
socket_id: socket.id,
uid_u: '',
name: '',
costume: 0,
head: 0,
hair: 0,
face: 0,
tong: 0,
glove: 0,
name: 0,
pos_x: 0,
pos_y: 0,
pos_z: 0,
rot_y: 0,
level: 0,
point: 0,
process: 0,
};
socket.on('get_users', function (){
console.log(`get_users\t${socket.id}`);
var arr_user = [];
for(var i in json_user){
arr_user.push(json_user[i]);
}
io.to(socket.id).emit('get_users', arr_user);
});
/* DESC: 현재 필드에 존재하는 표지판 상태를 모두 불러옴
* 접속할 때 get_users와 동일한 타이밍에 호출하면 됨
* 요청한 사람한테만 데이터 전송
* URL: http://121.150.20.121:52533
* NAME: get_signs
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |12
* |id |string |보낸 사람 소켓 id
* OUTPUT: |code |int |12
* |id |string |보낸 사람 소켓 id
* |data |array json |현재 표지판 배열
* |-uid_us |string |표지판 고유값
* |-data |int |표지판 그림
* |-comment |string |표지판 표제어
* |-set_at |int |표지판이 갱신된 timestamp(second)
*/
socket.on('get_signs', function (){
console.log(`get_signs\t${socket.id}`);
var res_json = {code: 12, id: socket.id, data: arr_sign, err: 0};
io.to(socket.id).emit('get_signs', res_json);
});
/* DESC: 공원에 있는 표지판에 직접 만든 표지판을 설치
* 단, 누군가가 이미 설치한지 30초가 지나지 않았다면 설치 불가
* URL: http://121.150.20.121:52533
* NAME: set_sign
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |11
* |data |json |
* |-index_sign |int |0~3, 대응하는 표지판 인덱스
* |-uid_us |string |표지판 고유값
* |-data |int |표지판 그림
* |-comment |string |표지판 표제어
* OUTPUT: |code |int |11
* |id |string |보낸 사람 소켓 id
* |data |array json |현재 표지판 배열
* |-uid_us |string |표지판 고유값
* |-data |int |표지판 그림
* |-comment |string |표지판 표제어
* |-set_at |int |표지판이 갱신된 timestamp(second)
* |err |int |0: 정상, 1~29: 숫자에 해당하는 초만큼 시간 남음
*/
socket.on('set_sign', function (data){
console.log(`set_sign\t${socket.id}\t${JSON.stringify(data)}`);
var res_json = {code: 11, id: socket.id, data: '', err: 0};
var index_sign = data.data.index_sign;
var uid_us = data.data.uid_us;
var paint = data.data.data;
var comment = data.data.comment;
var ts_now = parseInt(moment.now() / 1000);
var ts_remain = (ts_now - arr_sign[index_sign].set_at);
if(ts_remain >= 30){
arr_sign[index_sign].set_at = ts_now;
arr_sign[index_sign].uid_us = uid_us;
arr_sign[index_sign].data = paint;
arr_sign[index_sign].comment = comment;
res_json.data = arr_sign;
console.log(res_json);
io.emit('set_sign', res_json);
return;
}else{
console.log('set sign failed');
res_json.err = 1;
console.log(res_json);
io.to(socket.io).emit('set_sign', res_json);
return;
}
});
/* DESC: 입력받은 텍스트에서 비속어를 선별하고 * 처리하고 반환
* URL: http://121.150.20.121:52533
* NAME: chat
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |0
* |id |string |보낸 사람 소켓 id
* |name |string |보낸 사람 닉네임
* |data |string |채팅 내용
* OUTPUT: |code |int |0
* |id |string |보낸 사람 소켓 id
* |name |string |보낸 사람 닉네임
* |data |string |필터링된 채팅 내용
*/
socket.on('chat', function (data){
console.log(`chat\t${socket.id}\t${JSON.stringify(data)}`);
console.log(filter.clean(data.data));
data.data = filter.clean(data.data);
if(data){
io.emit('chat', data);
}
});
/* DESC:
* URL: http://121.150.20.121:52533
* NAME: move
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |1
* |id |string |보낸 사람 소켓 id
* |pos |json |
* |-x |int |x 좌표
* |-y |int |y 좌표
* |-z |int |z 좌표
* OUTPUT: |code |int |1
* |id |string |보낸 사람 소켓 id
* |data |json |
* |-x |int |x 좌표
* |-y |int |y 좌표
* |-z |int |z 좌표
*/
socket.on('move', function (data){
//socket.broadcast.emit('move', data);
console.log(`move\t${socket.id}\t${JSON.stringify(data)}`);
if(data){
json_user[socket.id].pos_x = data.pos.x;
json_user[socket.id].pos_y = data.pos.y;
json_user[socket.id].pos_z = data.pos.z;
socket.broadcast.emit('move', data);
}
});
/* DESC:
* URL: http://121.150.20.121:52533
* NAME: rotate
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |6
* |id |string |보낸 사람 소켓 id
* |data |int |회전축 값, unity에서라면 기본적으로 y
* OUTPUT: |code |int |6
* |id |string |보낸 사람 소켓 id
* |data |int |회전축 값, unity에서라면 기본적으로 y
*/
socket.on('rotate', function (data){
console.log(`rotate\t${socket.id}\t${JSON.stringify(data)}`);
if(data){
json_user[socket.id].rot_y = data.data;
socket.broadcast.emit('rotate', data);
}
});
/* DESC:
* URL: http://121.150.20.121:52533
* NAME: jump
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |2
* |id |string |보낸 사람 소켓 id
* OUTPUT: |code |int |2
* |id |string |보낸 사람 소켓 id
*/
socket.on('jump', function (data){
//socket.broadcast.emit('jump', data);
console.log(`jump\t${socket.id}\t${JSON.stringify(data)}`);
if(data){
socket.broadcast.emit('jump', data);
}
});
/* DESC: 요청한 사람에게만, 쓰레기 현황을 보냄(접속 직후라던지...)
* URL: http://121.150.20.121:52533
* NAME: get_trash
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |3
* |id |string |보낸 사람 소켓 id
* OUTPUT: |code |int |3
* |id |string |보낸 사람 소켓 id
* |data |array json |
* |-x |int |x축 좌표
* |-y |int |y축 좌표
* |-type |int |쓰레기 종류, 0: 없음(오류), 1: 담배, 2 ...
*/
socket.on('get_trash', function (data){
console.log(`get_trash\t${data}\t${JSON.stringify(data)}`);
if(data){
io.to(data.id).emit('get_trash', {code: 3, id: data.id, data: arr_trash});
}
});
/* DESC: 5초마다 자동으로 모든 클라이언트에게 쓰레기 현황을 뿌림
* URL: http://121.150.20.121:52533
* NAME: sync_trash
* METHOD: SOCKET EMIT
* |NAME |TYPE |DESC
* OUTPUT: |code |int |4
* |data |array json |
* |-x |int |x축 좌표
* |-y |int |y축 좌표
* |-type |int |쓰레기 종류, 0: 없음(오류), 1: 담배, 2 ...
*/
var sync_trash = setInterval(function (){
//io.to(users).emit('sync_trash', {code: 4, data: arr_trash});
io.to(socket.id).emit('sync_trash', {code: 4, data: arr_trash});
}, 5000);
/* DESC: 쓰레기를 주웠다면 해당 쓰레기는 삭제하고 새 쓰레기 생성
* URL: http://121.150.20.121:52533
* NAME: del_trash
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |5
* |x |int |x축 좌표
* |y |int |y축 좌표
* |type |int |쓰레기 종류, 0: 없음(오류), 1: 담배, 2 ...
* OUTPUT: |code |int |5
* |data |array json |
* |-x |int |x축 좌표
* |-y |int |y축 좌표
* |-type |int |쓰레기 종류, 0: 없음(오류), 1: 담배, 2 ...
*/
socket.on('del_trash', function (data){
console.log(`del_trash\t${socket.id}\t${JSON.stringify(data)}`);
arr_trash = _.without(arr_trash, _.findWhere(arr_trash, {
x: data.x,
y: data.y,
type: data.type
}));
set_arr_trash();
io.emit('del_trash', {code: 5, id: data.id, data: arr_trash});
});
/* DESC: 새로 접속한 유저의 소켓 정보를 생성
* connect 이후에 한번만 불러주면 됨
* 이후, 다른 이용자를 포함하는 이용자 정보 배열을 반환
* 나를 포함한 모든 사람에게 데이터가 전달됨
* URL: http://121.150.20.121:52533
* NAME: add_user
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |6
* |data |json |
* |-uid_u |string |이용자 고유값
* OUTPUT: |code |int |6
* |id |string |보낸 사람 소켓 id
* |data |array json |현재 이용자 배열
* |-socket_id |string |socket_id
* |-uid_u |string |이용자 고유값
* |-name |string |이름
* |-costume |int |몸통 파트
* |-head |int |머리 파트
* |-hair |int |머리카락 파트
* |-face |int |얼굴 파트
* |-sex |int |성별
* |-pos_x |float |위치 x축
* |-pos_y |float |위치 y축
* |-pos_z |float |위치 z축
* |-rot_y |float |회전 y축
* |-level |int |현재 진행 중인 미션
* |-point |int |경험치
* |-process |int |진행도
* |err |int |0: 정상, 1: 소켓 정보 갱신 실패, 2: select failed
*/
socket.on('add_user', function (data){
console.log(`add_user\t${socket.id}\t${JSON.stringify(data)}`);
var res_json = {code: 6, id: socket.id, data: '', err: 0};
if(json_user.hasOwnProperty(socket.id)){
conn.query(`select * from user where uid = ${conn.escape(data.data.uid_u)};
select * from user_level where uid_u = ${conn.escape(data.data.uid_u)} and is_active = 1 limit 1;`, function (err_00, res_00){
console.log(err_00);
if(err_00 || (res_00[0].length == 0)){
res_json.err = 2;
io.to(socket.io).emit('add_user', res_json);
console.log(res_json);
return;
}
json_user[socket.id].socket_id = socket.id;
json_user[socket.id].uid_u = res_00[0][0].uid;
json_user[socket.id].costume = res_00[0][0].costume;
json_user[socket.id].head = res_00[0][0].head;
json_user[socket.id].hair = res_00[0][0].hair;
json_user[socket.id].face = res_00[0][0].face;
json_user[socket.id].sex = res_00[0][0].sex;
json_user[socket.id].tong = 0;
json_user[socket.id].glove = 0;
json_user[socket.id].name = res_00[0][0].name;
json_user[socket.id].pos_x = 0;
json_user[socket.id].pos_y = 0;
json_user[socket.id].pos_z = 0;
json_user[socket.id].rot_y = 0;
json_user[socket.id].level = 0;
json_user[socket.id].point = 0;
json_user[socket.id].process = 0;
if(res_00[1].length > 0){
json_user[socket.id].level = res_00[1][0].level;
json_user[socket.id].point = res_00[1][0].point;
json_user[socket.id].process = res_00[1][0].progress;
}
var arr_user = [];
for(var i in json_user){
arr_user.push(json_user[i]);
}
res_json.data = arr_user;
console.log(res_json);
io.emit('add_user', res_json);
return;
});
}else{
console.log('add user failed');
res_json.err = 1;
console.log(res_json);
io.to(socket.io).emit('add_user', res_json);
return;
}
});
/* DESC: 이미 접속해 있던 사람의 정보를 갱신
* 장갑, 집게 등을 갱신할 때 불러주면 됨
* 그리고 http 통신의 update_user_costume 뒤에 불러주면 됨
* 이후, 다른 이용자를 포함하는 이용자 정보 배열을 반환
* 나를 포함한 모든 사람에게 데이터가 전달됨
* URL: http://121.150.20.121:52533
* NAME: upd_user
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |7
* |id |string |보낸 사람 소켓 id
* |data |json |
* |-uid_u |string |이용자 고유값
* |-glove |int |장갑, 착용시 1, 안보내면 이전값 그대로 씀
* |-tong |int |집게, 착용시 1, 안보내면 이전값 그대로 씀
* OUTPUT: |code |int |7
* |id |string |보낸 사람 소켓 id
* |data |array json |현재 이용자 배열
* |-socket_id |string |socket_id
* |-uid_u |string |이용자 고유값
* |-name |string |이름
* |-costume |int |몸통 파트
* |-head |int |머리 파트
* |-hair |int |머리카락 파트
* |-face |int |얼굴 파트
* |-glove |int |장갑
* |-tong |int |집게
* |-pos_x |float |위치 x축
* |-pos_y |float |위치 y축
* |-pos_z |float |위치 z축
* |-rot_y |float |회전 y축
* |-level |int |현재 진행 중인 미션
* |-point |int |경험치
* |-process |int |진행도
* |err |int |0: 정상, 1: 소켓 생성 실패, 2: select failed
*/
socket.on('upd_user', function (data){
console.log(`upd_user\t${socket.id}\t${JSON.stringify(data)}`);
var res_json = {code: 7, id: socket.id, data: '', err: 0};
if(json_user.hasOwnProperty(socket.id)){
conn.query(`select * from user where uid = ${conn.escape(data.data.uid_u)};
select * from user_level where uid_u = ${conn.escape(data.data.uid_u)} and is_active = 1 limit 1;`, function (err_00, res_00){
if(err_00 || (res_00.length == 0)){
res_json.err = 2;
io.to(socket.io).emit('upd_user', res_json);
return;
}
json_user[socket.id].costume = res_00[0][0].costume;
json_user[socket.id].head = res_00[0][0].head;
json_user[socket.id].hair = res_00[0][0].hair;
json_user[socket.id].face = res_00[0][0].face;
json_user[socket.id].tong = data.data.tong || json_user[socket.id].tong;
json_user[socket.id].glove = data.data.glove || json_user[socket.id].glove;
json_user[socket.id].name = res_00[0][0].name;
if(res_00[1].length > 0){
json_user[socket.id].level = res_00[1][0].level;
json_user[socket.id].point = res_00[1][0].point;
json_user[socket.id].process = res_00[1][0].progress;
}
var arr_user = [];
for(var i in json_user){
arr_user.push(json_user[i]);
}
res_json.data = arr_user;
io.emit('upd_user', res_json);
return;
});
}else{
res_json.err = 1;
io.to(socket.id).emit('upd_user', res_json);
return;
}
});
/* DESC: 새로운 미션을 시작할 때 보내주면 됨
* DB에 새 미션 정보를 저장, 저장된 정보는 다음 로그인할 때 받아옴
* 나를 포함한 모든 사람에게 데이터가 전달됨
* URL: http://121.150.20.121:52533
* NAME: add_level
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |9
* |id |string |보낸 사람 소켓 id
* |data |json |
* |-uid_u |string |이용자 고유값
* |-level |string |시작한 미션 넘버(각 미션 1~8, 올 클리어시 0)
* OUTPUT: |code |int |9
* |id |string |보낸 사람 소켓 id
* |data |array json |현재 이용자 배열
* |-socket_id |string |socket_id
* |-uid_u |string |이용자 고유값
* |-name |string |이름
* |-costume |int |몸통 파트
* |-head |int |머리 파트
* |-hair |int |머리카락 파트
* |-face |int |얼굴 파트
* |-glove |int |장갑
* |-tong |int |집게
* |-pos_x |float |위치 x축
* |-pos_y |float |위치 y축
* |-pos_z |float |위치 z축
* |-rot_y |float |회전 y축
* |-level |int |현재 진행 중인 미션
* |-point |int |현재 진행 중 미션 점수, 기본값 0
* |-process |int |진행도, 기본값 0
* |err |int |0: 정상, 1: 소켓 생성 실패, 2: insert failed
*/
socket.on('add_level', function (data){
console.log(`add_level\t${socket.id}\t${JSON.stringify(data)}`);
var res_json = {code: 9, id: socket.id, data: '', err: 0};
if(json_user.hasOwnProperty(socket.id)){
json_user[socket.id].level = data.data.level;
conn.query(`insert into user_level(uid, uid_u, level)
values("${faker.string.uuid()}", ${conn.escape(data.data.uid_u)}), ${conn.escape(data.data.level)}`, function (err_00, res_00){
if(err_00){
res_json.err = 2;
io.to(socket.io).emit('add_level', res_json);
return;
}
var arr_user = [];
for(var i in json_user){
arr_user.push(json_user[i]);
}
io.emit('add_level', res_json);
return;
});
}else{
res_json.err = 1;
io.to(socket.io).emit('add_level', res_json);
return;
}
});
/* DESC: 미션이 종료될 때만 보내주면 됨
* DB에 갱신 미션 정보를 저장, 다음 로그인할 때 받아옴
* 나를 포함한 모든 사람에게 데이터가 전달됨
* URL: http://121.150.20.121:52533
* NAME: upd_level
* METHOD: SOCKET ON & EMIT
* |NAME |TYPE |DESC
* INPUT: |code |int |10
* |id |string |보낸 사람 소켓 id
* |data |json |
* |-uid_u |string |이용자 고유값
* |-level |int |미션 넘버(각 미션 1~8, 올 클리어시 0)
* |-point |int |해당 미션에서 획득한 누적 점수
* OUTPUT: |code |int |10
* |id |string |보낸 사람 소켓 id
* |data |array json |현재 이용자 배열
* |-socket_id |string |socket_id
* |-uid_u |string |이용자 고유값
* |-name |string |이름
* |-costume |int |몸통 파트
* |-head |int |머리 파트
* |-hair |int |머리카락 파트
* |-face |int |얼굴 파트
* |-glove |int |장갑
* |-tong |int |집게
* |-pos_x |float |위치 x축
* |-pos_y |float |위치 y축
* |-pos_z |float |위치 z축
* |-rot_y |float |회전 y축
* |-level |int |현재 진행 중인 미션
* |-point |int |해당 미션에서 획득한 점수
* |-process |int |진행도, 기본값 0
* |err |int |0: 정상, 1: 소켓 생성 실패, 2: update failed
*/
socket.on('upd_level', function (data){
console.log(`upd_level\t${socket.id}\t${JSON.stringify(data)}`);
var res_json = {code: 10, id: socket.id, data: '', err: 0};
if(json_user.hasOwnProperty(socket.id)){
json_user[socket.id].level = data.data.level || json_user[socket.id].level;
json_user[socket.id].point = data.data.point || json_user[socket.id].point;
json_user[socket.id].process = data.data.process || json_user[socket.id].process;
conn.query(`update user_level
set level = ${conn.escape(data.data.level)},
point = ${conn.escape(data.data.point)},
process = ${conn.escape(data.data.process)}
where uid_u = ${conn.escape(data.data.uid_u)}
and level = ${conn.escape(data.data.level)}
and is_active = 1`, function (err_00, res_00){
if(err_00){
res_json.err = 2;
io.to(socket.id).emit('upd_level', res_json);
return;
}else{
var arr_user = [];
for(var i in json_user){
arr_user.push(json_user[i]);
}
res_json.data = arr_user;
io.emit('upd_level', res_json);
return;
}
});
}else{
res_json.err = 1;
io.to(socket.io).emit('upd_level', res_json);
return;
}
});
socket.on('pick_trash', function (data){
console.log(`pick_trash\t${socket.id}\t${socket.client.conn.server.clientsCount}`);
var res_json = {code: 11, id: socket.id, data: '', err: 0};
conn.query(`select inventory
from user
where uid = ${conn.escape(data.data.uid_u)}`, function (err_00, res_00){
if(err_00 || res_00.length == 0){
res_json.err = 1;
io.to(socket.id).emit('pick_trash', res_json);
return;
}else{
var inven = JSON.parse(res_00[0].inventory);
console.log(inven);
if(inven.inven0 == 0){
inven.inven0 = data.type;
}else if(inven.inven1 == 0){
inven.inven1 = data.type;
}else if(inven.inven2 == 0){
inven.inven2 = data.type;
}else if(inven.inven3 == 0){
inven.inven3 = data.type;
}else{
res_json.err = 2;
io.to(socket.id).emit('pick_trash', res_json);
return;
}
conn.query(`update user
set inventory = ${conn.escape(JSON.stringify(inven))}
where uid = ${conn.escape(data.data.uid_u)}`, function (err_01, res_01){
if(err_01){
res_json.err = 3;
io.to(socket.id).emit('pick_trash', res_json);
return;
}
arr_trash = _.without(arr_trash, _.findWhere(arr_trash, {
x: data.data.x,
y: data.data.y,
type: data.data.type
}));
set_arr_trash();
res_json.data = {
id: socket.id,
inven: inven,
};
io.to(socket.id).emit('pick_trash', res_json);
io.emit('sync_trash', {code: 4, data: arr_trash});
return;
});
}
});
});
/* DESC: 누군가가 접속을 끊을 때 호출
* 이후, 다른 이용자의 socket id 반환, 해당 id로 캐릭터 삭제
* 나를 포함한 모든 사람에게 데이터가 전달됨
* URL: http://121.150.20.121:52533
* NAME: disconnected
* METHOD: SOCKET EMIT
* |NAME |TYPE |DESC
* OUTPUT: |code |int |8
* |id |string |나간 사람 소켓 id
* |data |string |-
*/
socket.on('disconnect', function (){
console.log(`disconnect\t${socket.id}\t${socket.client.conn.server.clientsCount}`);
//console.log(socket.client.conn.server.clientsCount);
var res_json = {code: 8, id: socket.id, data: ''};
clearInterval(sync_trash);
json_user = _.omit(json_user, function (v, i){
return i == socket.id;
});
var arr_user = [];
for(var i in json_user){
arr_user.push(json_user[i]);
}
res_json.data = socket.id;
console.log(res_json);
io.emit('disconnected', res_json);
});
});
<!DOCTYPE html>
<html>
<head>
<title>Socket.IO Example</title>
</head>
<body>
<h1>Real-time Chat</h1>
<ul id="messages"></ul>
<form id="chat-form">
<input type="text" id="message-input" autocomplete="off" />
<button>Send</button>
</form>
<!--<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.js"></script>-->
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('connect', function (){
console.log('connected to server');
});
socket.on('disconnect', function (){
console.log('disconnected from server');
});
// 서버에서 전달된 메시지 수신
socket.on('chat', (msg) => {
const messages = document.getElementById('messages');
const li = document.createElement('li');
li.textContent = msg;
messages.appendChild(li);
});
// 메시지 전송
const form = document.getElementById('chat-form');
form.addEventListener('submit', (e) => {
e.preventDefault();
const input = document.getElementById('message-input');
const msg = input.value;
socket.emit('chat', msg);
input.value = '';
});
</script>
</body>
</html>
\ No newline at end of file
<!DOCTYPE html>
<html>
<head>
<title>Socket.IO Example</title>
</head>
<body>
<h1>Real-time Chat</h1>
<ul id="messages"></ul>
<form id="chat-form">
<input type="text" id="message-input" autocomplete="off" />
<button>Send</button>
</form>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.2.0/socket.io.js"></script>
<script>
var socket = io.connect('http://121.150.20.121:52533');
socket.on('connect', function (){
console.log('connected to server');
//console.log(socket);
console.log(socket.id);
});
socket.emit('add_user', {
code: 6,
data: {
uid_u: 'b00965d8-69b6-47cf-9b1d-015d9873700a'
}
});
socket.on('add_user', function (data){
console.log(data);
});
socket.on('disconnected', function (data){
console.log(data);
});
socket.on('disconnect', function (){
console.log('disconnected from server');
console.log(socket.id);
});
// 서버에서 전달된 메시지 수신
socket.on('chat', function (data){
console.log(data);
const messages = document.getElementById('messages');
const li = document.createElement('li');
li.textContent = data.data;
messages.appendChild(li);
});
// 메시지 전송
const form = document.getElementById('chat-form');
form.addEventListener('submit', (e) => {
e.preventDefault();
const input = document.getElementById('message-input');
var data = {code: 0, id: socket.id, data: input.value}
socket.emit('chat', data);
input.value = '';
});
(function() {
var mousePos = {x: 0, y:0, z: 0};
document.onmousemove = handleMouseMove;
setInterval(getMousePosition, 100);
function handleMouseMove(event) {
var dot, eventDoc, doc, body, pageX, pageY;
event = event || window.event;
if (event.pageX == null && event.clientX != null) {
eventDoc = (event.target && event.target.ownerDocument) || document;
doc = eventDoc.documentElement;
body = eventDoc.body;
event.pageX = event.clientX +
(doc && doc.scrollLeft || body && body.scrollLeft || 0) -
(doc && doc.clientLeft || body && body.clientLeft || 0);
event.pageY = event.clientY +
(doc && doc.scrollTop || body && body.scrollTop || 0) -
(doc && doc.clientTop || body && body.clientTop || 0 );
}
mousePos = {
x: parseInt(event.pageX),
y: 0,
z: parseInt(event.pageY),
};
//console.log(mousePos);
}
function getMousePosition() {
var data = {code: 1, id: socket.id, pos: mousePos};
data.pos.x = parseInt((data.pos.x / window.innerWidth) * 28.5);
data.pos.z = parseInt((data.pos.z / window.innerHeight) * 28.5);
if (!data) {
// We haven't seen any movement yet
}
else {
socket.emit('move', data);
}
}
})();
socket.on('move', function (data){
console.log(data);
});
document.addEventListener('keydown', function (e){
if(e.code == 'Space'){
/*
console.log('fdsafdsa');
socket.emit('jump', {code: 2, id: socket.id});
*/
/*
socket.emit('upd_user', {
uid_u: '39192510-63e1-4850-9e53-98ff93f5843f',
costume: 4,
head: 3,
hair: 2,
face: 1,
name: 'asdfasdf'
});
*/
socket.emit('pick_trash', {
uid_u: '39192510-63e1-4850-9e53-98ff93f5843f',
type: 1,
x: 5,
y: 5,
});
}
});
socket.on('pick_trash', function (data){
console.log(data);
});
socket.on('upd_user', function (data){
console.log(data);
});
socket.on('jump', function (data){
console.log(data);
});
socket.on('sync_trash', function (data){
console.log(data);
});
</script>
</html>
\ No newline at end of file
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment