Commit e6250b20 authored by nanahira's avatar nanahira

Merge branch 'master' into tcg_random

parents 0fcaa500 47aa249a
...@@ -5,7 +5,7 @@ RUN npm install -g pm2 ...@@ -5,7 +5,7 @@ RUN npm install -g pm2
# apt # apt
RUN apt update && \ RUN apt update && \
env DEBIAN_FRONTEND=noninteractive apt install -y wget git build-essential libevent-dev libsqlite3-dev mono-complete p7zip-full redis-server && \ env DEBIAN_FRONTEND=noninteractive apt install -y wget git build-essential libevent-dev libsqlite3-dev mono-complete p7zip-full redis-server python3 && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
# srvpro # srvpro
......
...@@ -3,7 +3,7 @@ FROM node:12-buster-slim ...@@ -3,7 +3,7 @@ FROM node:12-buster-slim
# apt # apt
RUN apt update && \ RUN apt update && \
env DEBIAN_FRONTEND=noninteractive apt install -y wget git build-essential libsqlite3-dev libevent-dev p7zip-full && \ env DEBIAN_FRONTEND=noninteractive apt install -y wget git build-essential libsqlite3-dev libevent-dev p7zip-full python3 && \
rm -rf /var/lib/apt/lists/* rm -rf /var/lib/apt/lists/*
# srvpro # srvpro
......
...@@ -28,11 +28,11 @@ ...@@ -28,11 +28,11 @@
"integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q=="
}, },
"ajv": { "ajv": {
"version": "6.10.2", "version": "6.12.0",
"resolved": "https://registry.npmjs.org/ajv/-/ajv-6.10.2.tgz", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.0.tgz",
"integrity": "sha512-TXtUUEYHuaTEbLZWIKUr5pmBuhDLy+8KYtPYdcV8qC+pOZL+NKqYwvWSRrVXHn+ZmRRAu8vJTAznH7Oag6RVRw==", "integrity": "sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw==",
"requires": { "requires": {
"fast-deep-equal": "^2.0.1", "fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0", "fast-json-stable-stringify": "^2.0.0",
"json-schema-traverse": "^0.4.1", "json-schema-traverse": "^0.4.1",
"uri-js": "^4.2.2" "uri-js": "^4.2.2"
...@@ -79,9 +79,9 @@ ...@@ -79,9 +79,9 @@
"integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU="
}, },
"async": { "async": {
"version": "1.3.0", "version": "3.2.0",
"resolved": "https://registry.npmjs.org/async/-/async-1.3.0.tgz", "resolved": "https://registry.npmjs.org/async/-/async-3.2.0.tgz",
"integrity": "sha1-pvFjHopZWmY0ltClWGvRIAfUhx0=" "integrity": "sha512-TR2mEZFVOj2pLStYxLht7TyfuRzaydfpxr3k9RpHIzMgw7A64dzsdqCxH1WJyQdoe8T10nDXd9wnEigmiuHIZw=="
}, },
"asynckit": { "asynckit": {
"version": "0.4.0", "version": "0.4.0",
...@@ -94,9 +94,9 @@ ...@@ -94,9 +94,9 @@
"integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg="
}, },
"aws4": { "aws4": {
"version": "1.9.0", "version": "1.9.1",
"resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.0.tgz", "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.9.1.tgz",
"integrity": "sha512-Uvq6hVe90D0B2WEnUqtdgY1bATGz3mw33nH9Y+dmA+w5DHvUmBgkr5rM/KCHpCsiFNRUfokW/szpPPgMK2hm4A==" "integrity": "sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug=="
}, },
"balanced-match": { "balanced-match": {
"version": "1.0.0", "version": "1.0.0",
...@@ -265,16 +265,16 @@ ...@@ -265,16 +265,16 @@
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
}, },
"denque": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz",
"integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ=="
},
"detect-libc": { "detect-libc": {
"version": "1.0.3", "version": "1.0.3",
"resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
"integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups="
}, },
"double-ended-queue": {
"version": "2.1.0-0",
"resolved": "https://registry.npmjs.org/double-ended-queue/-/double-ended-queue-2.1.0-0.tgz",
"integrity": "sha1-ED01J/0xUo9AGIEwyEHv3XgmTlw="
},
"dtrace-provider": { "dtrace-provider": {
"version": "0.8.8", "version": "0.8.8",
"resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz", "resolved": "https://registry.npmjs.org/dtrace-provider/-/dtrace-provider-0.8.8.tgz",
...@@ -322,14 +322,14 @@ ...@@ -322,14 +322,14 @@
"integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU="
}, },
"fast-deep-equal": { "fast-deep-equal": {
"version": "2.0.1", "version": "3.1.1",
"resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz",
"integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=" "integrity": "sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA=="
}, },
"fast-json-stable-stringify": { "fast-json-stable-stringify": {
"version": "2.0.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
"integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
}, },
"forever-agent": { "forever-agent": {
"version": "0.6.1", "version": "0.6.1",
...@@ -347,9 +347,9 @@ ...@@ -347,9 +347,9 @@
} }
}, },
"formidable": { "formidable": {
"version": "1.2.1", "version": "1.2.2",
"resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.2.tgz",
"integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" "integrity": "sha512-V8gLm+41I/8kguQ4/o1D3RIHRmhYFG4pnNyonvua+40rqcEmT4+V71yaZ3B457xbbgCsCfjSPi65u/W6vK1U5Q=="
}, },
"fs-minipass": { "fs-minipass": {
"version": "1.2.6", "version": "1.2.6",
...@@ -419,6 +419,11 @@ ...@@ -419,6 +419,11 @@
"unzip": "~0.0.4" "unzip": "~0.0.4"
}, },
"dependencies": { "dependencies": {
"async": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/async/-/async-1.3.0.tgz",
"integrity": "sha1-pvFjHopZWmY0ltClWGvRIAfUhx0="
},
"glob": { "glob": {
"version": "3.2.11", "version": "3.2.11",
"resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-3.2.11.tgz",
...@@ -650,16 +655,16 @@ ...@@ -650,16 +655,16 @@
"integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI=" "integrity": "sha1-bUUk6LlV+V1PW1iFHOId1y+06VI="
}, },
"mime-db": { "mime-db": {
"version": "1.42.0", "version": "1.43.0",
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.42.0.tgz", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz",
"integrity": "sha512-UbfJCR4UAVRNgMpfImz05smAXK7+c+ZntjaA26ANtkXLlOe947Aag5zdIcKQULAiF9Cq4WxBi9jUs5zkA84bYQ==" "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ=="
}, },
"mime-types": { "mime-types": {
"version": "2.1.25", "version": "2.1.26",
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.25.tgz", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz",
"integrity": "sha512-5KhStqB5xpTAeGqKBAMgwaYMnQik7teQN4IAzC7npDv6kzeU6prfkR67bc87J1kWMPGkoaZSq1npmexMgkmEVg==", "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==",
"requires": { "requires": {
"mime-db": "1.42.0" "mime-db": "1.43.0"
} }
}, },
"minimatch": { "minimatch": {
...@@ -996,9 +1001,9 @@ ...@@ -996,9 +1001,9 @@
"integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
}, },
"psl": { "psl": {
"version": "1.4.0", "version": "1.8.0",
"resolved": "https://registry.npmjs.org/psl/-/psl-1.4.0.tgz", "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
"integrity": "sha512-HZzqCGPecFLyoRj5HLfuDSKYTJkAfB5thKBIkRHtGjWwY7p1dAyveIbXIq4tO0KYfDF2tHqPUgY9SDnGm00uFw==" "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ=="
}, },
"pullstream": { "pullstream": {
"version": "0.0.4", "version": "0.0.4",
...@@ -1059,13 +1064,14 @@ ...@@ -1059,13 +1064,14 @@
} }
}, },
"redis": { "redis": {
"version": "2.8.0", "version": "3.0.2",
"resolved": "https://registry.npmjs.org/redis/-/redis-2.8.0.tgz", "resolved": "https://registry.npmjs.org/redis/-/redis-3.0.2.tgz",
"integrity": "sha512-M1OkonEQwtRmZv4tEWF2VgpG0JWJ8Fv1PhlgT5+B+uNq2cA3Rt1Yt/ryoR+vQNOQcIEgdCdfH0jr3bDpihAw1A==", "integrity": "sha512-PNhLCrjU6vKVuMOyFu7oSP296mwBkcE6lrAjruBYG5LgdSqtRBoVQIylrMyVZD/lkF24RSNNatzvYag6HRBHjQ==",
"requires": { "requires": {
"double-ended-queue": "^2.1.0-0", "denque": "^1.4.1",
"redis-commands": "^1.2.0", "redis-commands": "^1.5.0",
"redis-parser": "^2.6.0" "redis-errors": "^1.2.0",
"redis-parser": "^3.0.0"
} }
}, },
"redis-commands": { "redis-commands": {
...@@ -1073,15 +1079,23 @@ ...@@ -1073,15 +1079,23 @@
"resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz", "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.5.0.tgz",
"integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg==" "integrity": "sha512-6KxamqpZ468MeQC3bkWmCB1fp56XL64D4Kf0zJSwDZbVLLm7KFkoIcHrgRvQ+sk8dnhySs7+yBg94yIkAK7aJg=="
}, },
"redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
"integrity": "sha1-62LSrbFeTq9GEMBK/hUpOEJQq60="
},
"redis-parser": { "redis-parser": {
"version": "2.6.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-2.6.0.tgz", "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
"integrity": "sha1-Uu0J2srBCPGmMcB+m2mUHnoZUEs=" "integrity": "sha1-tm2CjNyv5rS4pCin3vTGvKwxyLQ=",
"requires": {
"redis-errors": "^1.0.0"
}
}, },
"request": { "request": {
"version": "2.88.0", "version": "2.88.2",
"resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
"integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
"requires": { "requires": {
"aws-sign2": "~0.7.0", "aws-sign2": "~0.7.0",
"aws4": "^1.8.0", "aws4": "^1.8.0",
...@@ -1090,7 +1104,7 @@ ...@@ -1090,7 +1104,7 @@
"extend": "~3.0.2", "extend": "~3.0.2",
"forever-agent": "~0.6.1", "forever-agent": "~0.6.1",
"form-data": "~2.3.2", "form-data": "~2.3.2",
"har-validator": "~5.1.0", "har-validator": "~5.1.3",
"http-signature": "~1.2.0", "http-signature": "~1.2.0",
"is-typedarray": "~1.0.0", "is-typedarray": "~1.0.0",
"isstream": "~0.1.2", "isstream": "~0.1.2",
...@@ -1100,7 +1114,7 @@ ...@@ -1100,7 +1114,7 @@
"performance-now": "^2.1.0", "performance-now": "^2.1.0",
"qs": "~6.5.2", "qs": "~6.5.2",
"safe-buffer": "^5.1.2", "safe-buffer": "^5.1.2",
"tough-cookie": "~2.4.3", "tough-cookie": "~2.5.0",
"tunnel-agent": "^0.6.0", "tunnel-agent": "^0.6.0",
"uuid": "^3.3.2" "uuid": "^3.3.2"
} }
...@@ -1269,19 +1283,12 @@ ...@@ -1269,19 +1283,12 @@
"integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=" "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU="
}, },
"tough-cookie": { "tough-cookie": {
"version": "2.4.3", "version": "2.5.0",
"resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
"integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
"requires": { "requires": {
"psl": "^1.1.24", "psl": "^1.1.28",
"punycode": "^1.4.1" "punycode": "^2.1.1"
},
"dependencies": {
"punycode": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
"integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4="
}
} }
}, },
"traverse": { "traverse": {
...@@ -1313,9 +1320,9 @@ ...@@ -1313,9 +1320,9 @@
"integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po=" "integrity": "sha1-rOEWq1V80Zc4ak6I9GhTeMiy5Po="
}, },
"underscore": { "underscore": {
"version": "1.9.1", "version": "1.10.2",
"resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.10.2.tgz",
"integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" "integrity": "sha512-N4P+Q/BuyuEKFJ43B9gYuOj4TQUHXX+j2FqguVOpjkssLUUrnJofCcBccJSCoeturDoZU6GorDTHSvUDlSQbTg=="
}, },
"underscore.string": { "underscore.string": {
"version": "3.3.5", "version": "3.3.5",
...@@ -1350,9 +1357,9 @@ ...@@ -1350,9 +1357,9 @@
"integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
}, },
"uuid": { "uuid": {
"version": "3.3.3", "version": "3.4.0",
"resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.3.tgz", "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
"integrity": "sha512-pW0No1RGHgzlpHJO1nsVrHKpOEIxkGg1xB+v0ZmdNH5OAeAwzAVrCnI2/6Mtx+Uys6iaylxa+D3g4j63IKKjSQ==" "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A=="
}, },
"verror": { "verror": {
"version": "1.10.0", "version": "1.10.0",
......
...@@ -11,19 +11,20 @@ ...@@ -11,19 +11,20 @@
], ],
"author": "zh99998 <zh99998@gmail.com>, mercury233 <me@mercury233.me>, Nanahira <78877@qq.com>", "author": "zh99998 <zh99998@gmail.com>, mercury233 <me@mercury233.me>, Nanahira <78877@qq.com>",
"dependencies": { "dependencies": {
"async": "^3.2.0",
"bunyan": "latest", "bunyan": "latest",
"challonge": "latest",
"deepmerge": "latest", "deepmerge": "latest",
"formidable": "latest",
"geoip-country-lite": "latest",
"load-json-file": "latest", "load-json-file": "latest",
"moment": "latest", "moment": "latest",
"pg": "^6.4.2",
"redis": "latest", "redis": "latest",
"formidable": "latest",
"request": "latest", "request": "latest",
"sqlite3": "latest",
"underscore": "latest", "underscore": "latest",
"underscore.string": "latest", "underscore.string": "latest",
"sqlite3": "latest",
"geoip-country-lite": "latest",
"challonge": "latest",
"pg": "^6.4.2",
"ws": "^1.1.1" "ws": "^1.1.1"
}, },
"license": "AGPL-3.0", "license": "AGPL-3.0",
......
...@@ -100,7 +100,7 @@ check_permission = (user, permission_required) -> ...@@ -100,7 +100,7 @@ check_permission = (user, permission_required) ->
return false return false
return permission[permission_required] return permission[permission_required]
@auth = (name, pass, permission_required, action = 'unknown') -> @auth = (name, pass, permission_required, action = 'unknown', no_log) ->
reload() reload()
user = users.users[name] user = users.users[name]
if !user if !user
...@@ -115,7 +115,8 @@ check_permission = (user, permission_required) -> ...@@ -115,7 +115,8 @@ check_permission = (user, permission_required) ->
if !check_permission(user, permission_required) if !check_permission(user, permission_required)
add_log("Permission denied. User: "+ name+", Permission needed: "+ permission_required+", Action: " +action) add_log("Permission denied. User: "+ name+", Permission needed: "+ permission_required+", Action: " +action)
return false return false
add_log("Operation success. User: "+ name+", Permission needed: "+ permission_required+", Action: " +action) if !no_log
add_log("Operation success. User: "+ name+", Permission needed: "+ permission_required+", Action: " +action)
return true return true
@add_user = (name, pass, enabled, permissions) -> @add_user = (name, pass, enabled, permissions) ->
......
...@@ -122,7 +122,7 @@ or as follows, to use a specific set of permissions. ...@@ -122,7 +122,7 @@ or as follows, to use a specific set of permissions.
return permission[permission_required]; return permission[permission_required];
}; };
this.auth = function(name, pass, permission_required, action) { this.auth = function(name, pass, permission_required, action, no_log) {
var user; var user;
if (action == null) { if (action == null) {
action = 'unknown'; action = 'unknown';
...@@ -145,7 +145,9 @@ or as follows, to use a specific set of permissions. ...@@ -145,7 +145,9 @@ or as follows, to use a specific set of permissions.
add_log("Permission denied. User: " + name + ", Permission needed: " + permission_required + ", Action: " + action); add_log("Permission denied. User: " + name + ", Permission needed: " + permission_required + ", Action: " + action);
return false; return false;
} }
add_log("Operation success. User: " + name + ", Permission needed: " + permission_required + ", Action: " + action); if (!no_log) {
add_log("Operation success. User: " + name + ", Permission needed: " + permission_required + ", Action: " + action);
}
return true; return true;
}; };
......
...@@ -11,6 +11,7 @@ var http = require('http'); ...@@ -11,6 +11,7 @@ var http = require('http');
var https = require('https'); var https = require('https');
var sqlite3 = require('sqlite3').verbose(); var sqlite3 = require('sqlite3').verbose();
var fs = require('fs'); var fs = require('fs');
var exec = require('child_process').exec;
var execSync = require('child_process').execSync; var execSync = require('child_process').execSync;
var spawn = require('child_process').spawn; var spawn = require('child_process').spawn;
var url = require('url'); var url = require('url');
...@@ -32,6 +33,7 @@ var cardHTMLs=[]; ...@@ -32,6 +33,7 @@ var cardHTMLs=[];
var responder; var responder;
//URL里的更新时间戳 //URL里的更新时间戳
var dataver = moment().format("YYYYMMDDHHmmss"); var dataver = moment().format("YYYYMMDDHHmmss");
const _async = require("async");
//输出反馈信息,如有http长连接则输出到http,否则输出到控制台 //输出反馈信息,如有http长连接则输出到http,否则输出到控制台
var sendResponse = function(text) { var sendResponse = function(text) {
...@@ -46,7 +48,7 @@ var sendResponse = function(text) { ...@@ -46,7 +48,7 @@ var sendResponse = function(text) {
} }
//读取数据库内内容到cardHTMLs,异步 //读取数据库内内容到cardHTMLs,异步
var loadDb = function(db_file) { var loadDb = function(db_file, callback) {
var db = new sqlite3.Database(db_file); var db = new sqlite3.Database(db_file);
db.each("select * from datas,texts where datas.id=texts.id", function (err,result) { db.each("select * from datas,texts where datas.id=texts.id", function (err,result) {
...@@ -196,11 +198,12 @@ var loadDb = function(db_file) { ...@@ -196,11 +198,12 @@ var loadDb = function(db_file) {
dataver = moment().format("YYYYMMDDHHmmss"); dataver = moment().format("YYYYMMDDHHmmss");
sendResponse("已加载数据库"+db_file+",共"+num+"张卡。"); sendResponse("已加载数据库"+db_file+",共"+num+"张卡。");
} }
callback(err, num);
}); });
} }
//将cardHTMLs中内容更新到指定列表页,同步 //将cardHTMLs中内容更新到指定列表页,同步
var writeToFile = function(message) { var writeToFile = function(message, callback) {
var fileContent=fs.readFileSync(config.html_path+config.html_filename, {"encoding":"utf-8"}); var fileContent=fs.readFileSync(config.html_path+config.html_filename, {"encoding":"utf-8"});
var newContent=cardHTMLs.join("\n"); var newContent=cardHTMLs.join("\n");
fileContent=fileContent.replace(/<tbody class="auto-generated">[\w\W]*<\/tbody>/,'<tbody class="auto-generated">\n'+newContent+'\n</tbody>'); fileContent=fileContent.replace(/<tbody class="auto-generated">[\w\W]*<\/tbody>/,'<tbody class="auto-generated">\n'+newContent+'\n</tbody>');
...@@ -210,25 +213,47 @@ var writeToFile = function(message) { ...@@ -210,25 +213,47 @@ var writeToFile = function(message) {
message="<li>"+moment().format('L HH:mm')+"<ul><li>"+message.split("!换行符!").join("</li><li>")+"</li></ul></li>"; message="<li>"+moment().format('L HH:mm')+"<ul><li>"+message.split("!换行符!").join("</li><li>")+"</li></ul></li>";
fileContent=fileContent.replace(/<ul class="auto-generated">/,'<ul class="auto-generated">\n'+message); fileContent=fileContent.replace(/<ul class="auto-generated">/,'<ul class="auto-generated">\n'+message);
} }
fs.writeFileSync(config.html_path+config.html_filename, fileContent); _async.auto({
sendResponse("列表更新完成。"); write: (done) => {
/* fs.writeFile(config.html_path + config.html_filename, fileContent, done)
if (!config.cdn.enabled) { }/*,
copyImages(); copy: ["write", (results, done) => {
} if (!config.cdn.enabled) {
*/ copyImages(done);
} else {
done();
}
}]*/
}, (err) => {
if (!err) {
sendResponse("列表更新完成。");
}
callback(err);
})
} }
//读取指定文件夹里所有数据库,异步 //读取指定文件夹里所有数据库,异步
var loadAllDbs = function() { var loadAllDbs = function(callback) {
cardHTMLs=[]; cardHTMLs=[];
var files = fs.readdirSync(config.db_path+"expansions/"); _async.auto({
for (var i in files) { files: (done) => {
var filename = files[i]; fs.readdir(config.db_path + "expansions/", done);
if (filename.slice(-4) === ".cdb" && (!config.only_show_dbs || config.only_show_dbs.length==0 || config.only_show_dbs[filename])) { },
loadDb(config.db_path+"expansions/"+filename); loadDbs: ["files", (results, done) => {
} _async.each(results.files.filter((filename) => {
} return filename.slice(-4) === ".cdb" && (!config.only_show_dbs || config.only_show_dbs.length == 0 || config.only_show_dbs[filename])
} ).map(filename => config.db_path + "expansions/" + filename), loadDb, done);
}]
}, callback);
}
function execCommands(commands, callback) {
_async.eachSeries(commands, (command, done) => {
exec(command, (err) => {
done(err);
});
}, callback);
} }
//从远程更新数据库,异步 //从远程更新数据库,异步
...@@ -260,18 +285,27 @@ var fetchDatas = function() { ...@@ -260,18 +285,27 @@ var fetchDatas = function() {
} }
//更新本地网页到服务器,异步 //更新本地网页到服务器,异步
var pushDatas = function() { var pushDatas = function(callback) {
if (config.cdn.enabled) { if (config.cdn.enabled) {
uploadCDN(config.cdn.local, config.cdn.remote + "/" + dataver, function () { _async.auto({
uploadCDN(config.db_path + "pics", config.cdn.pics_remote + "pics", function () { local: (done) => {
uploadCDN(config.cdn.local, config.cdn.remote + "/" + dataver, done);
},
pics: (done) => {
uploadCDN(config.db_path + "pics", config.cdn.pics_remote + "pics", done);
},
push: ["local", "pics", (results, done) => {
sendResponse("CDN上传全部完成。"); sendResponse("CDN上传全部完成。");
}); pushHTMLs(done);
}); }]
}, callback);
} else {
pushHTMLs(callback);
} }
pushHTMLs();
} }
var pushHTMLs = function() { var pushHTMLs = function(callback) {
sendResponse("开始上传到网页。"); sendResponse("开始上传到网页。");
try { try {
execSync('git add --all .', { cwd: config.git_html_path, env: process.env }); execSync('git add --all .', { cwd: config.git_html_path, env: process.env });
...@@ -297,6 +331,7 @@ var pushHTMLs = function() { ...@@ -297,6 +331,7 @@ var pushHTMLs = function() {
proc.on('close', (function(git) { proc.on('close', (function(git) {
return function(code) { return function(code) {
sendResponse(git.name + "上传完成。"); sendResponse(git.name + "上传完成。");
callback();
} }
})(git)); })(git));
} }
...@@ -327,39 +362,44 @@ var uploadCDN = function(local, remote, callback) { ...@@ -327,39 +362,44 @@ var uploadCDN = function(local, remote, callback) {
}); });
} }
//将数据库文件夹里卡图复制到列表页对应文件夹里,同步 //将数据库文件夹里卡图复制到列表页对应文件夹里,异步
var copyImages = function() { var copyImages = function (callback) {
execSync('rm -rf "' + config.html_path+config.html_img_rel_path +'"'); const commands = [
execSync('cp -r "' + config.db_path + 'pics' + '" "' + config.html_path + config.html_img_rel_path + '"'); 'rm -rf "' + config.html_path + config.html_img_rel_path + '"',
execSync('rm -rf "' + config.html_path+config.html_img_rel_path +'field"'); 'cp -r "' + config.db_path + 'pics' + '" "' + config.html_path + config.html_img_rel_path + '"',
sendResponse("卡图复制完成。"); 'rm -rf "' + config.html_path+config.html_img_rel_path +'field"',
]
execCommands(commands, (err) => {
if (err) {
sendResponse("卡图复制失败: " + err.toString());
} else {
sendResponse("卡图复制完成。");
}
callback(err);
});
} }
//将数据库文件夹复制到YGOPRO文件夹里,同步 //将数据库文件夹复制到YGOPRO文件夹里,同步
var copyToYGOPRO = function() { var copyToYGOPRO = function(callback) {
execSync('rm -rf ' + config.ygopro_path + 'expansions/*' + ''); const commands = [
execSync('cp -rf "' + config.db_path + 'expansions' + '" "' + config.ygopro_path + '"'); 'rm -rf ' + config.ygopro_path + 'expansions/*' + '',
execSync('cp -rf "' + config.db_path + 'script' + '" "' + config.ygopro_path + 'expansions"'); 'cp -rf "' + config.db_path + 'expansions' + '" "' + config.ygopro_path + '"',
try { 'cp -rf "' + config.db_path + 'script' + '" "' + config.ygopro_path + 'expansions"',
execSync('cp -rf "' + config.db_path + 'lflist.conf' + '" "' + config.ygopro_path + '"'); 'cp -rf "' + config.db_path + 'lflist.conf' + '" "' + config.ygopro_path + '" || true'
} ]
catch (e) {} execCommands(commands, (err) => {
sendResponse("更新完成。"); if (err) {
sendResponse("更新失败: " + err.toString());
} else {
sendResponse("更新完成。");
}
callback(err);
});
} }
//生成更新包,异步 function run7z(params, callback) {
var packDatas = function () { let proc = spawn(settings.modules.tournament_mode.replay_archive_tool, params, { cwd: config.db_path, env: process.env });
file_path = config.html_path;
if (config.cdn.enabled) {
file_path = config.cdn.local;
}
execSync('cp -r "' + config.db_path +'expansions" "'+ config.db_path +'cdb"');
execSync('cp -r "' + config.db_path +'script" "'+ config.db_path +'expansions/script"');
execSync('cp -r "' + config.db_path +'field" "'+ config.db_path +'pics/field"');
execSync('cp -r "' + config.db_path +'pics" "'+ config.db_path +'expansions/pics"');
execSync('cp -r "' + config.db_path +'picn" "'+ config.db_path +'picture/card"');
execSync('cp -r "' + config.db_path +'field" "'+ config.db_path +'picture/field"');
var proc = spawn("7za", ["a", "-x!*.zip", "-x!.git", "-x!LICENSE", "-x!README.md", "-x!mobile.cdb", "-x!cdb", "-x!picn", "-x!field", "-x!script", "-x!pics", "-x!expansions/pics/thumbnail", "-x!picture", "ygosrv233-pre.zip", "*"], { cwd: config.db_path, env: process.env });
proc.stdout.setEncoding('utf8'); proc.stdout.setEncoding('utf8');
proc.stdout.on('data', function(data) { proc.stdout.on('data', function(data) {
//sendResponse("7z: "+data); //sendResponse("7z: "+data);
...@@ -369,41 +409,74 @@ var packDatas = function () { ...@@ -369,41 +409,74 @@ var packDatas = function () {
sendResponse("7z error: "+data); sendResponse("7z error: "+data);
}); });
proc.on('close', function (code) { proc.on('close', function (code) {
execSync('mv -f "' + config.db_path + 'ygosrv233-pre.zip" "' + file_path + '"'); callback(code === 0 ? null : "exit " + code);
execSync('rm -rf "' + config.db_path +'expansions/script"');
execSync('rm -rf "' + config.db_path +'expansions/pics"');
sendResponse("电脑更新包打包完成。");
});
var proc2 = spawn("7za", ["a", "-x!*.zip", "-x!.git", "-x!LICENSE", "-x!README.md", "-x!expansions/pics", "-x!expansions/script", "-x!cdb", "-x!picn", "-x!field", "-x!pics/thumbnail", "-x!picture", "ygosrv233-pre-mobile.zip", "*"], { cwd: config.db_path, env: process.env });
proc2.stdout.setEncoding('utf8');
proc2.stdout.on('data', function(data) {
//sendResponse("7z: "+data);
});
proc2.stderr.setEncoding('utf8');
proc2.stderr.on('data', function(data) {
sendResponse("7z error: "+data);
});
proc2.on('close', function (code) {
execSync('mv -f "' + config.db_path +'ygosrv233-pre-mobile.zip" "'+ file_path +'"');
execSync('rm -rf "' + config.db_path +'pics/field"');
sendResponse("手机更新包打包完成。");
});
var proc3 = spawn("7za", ["a", "-x!*.zip", "-x!.git", "-x!LICENSE", "-x!README.md", "-x!expansions", "-x!pics", "-x!picn", "-x!field", "ygosrv233-pre-2.zip", "*"], { cwd: config.db_path, env: process.env });
proc3.stdout.setEncoding('utf8');
proc3.stdout.on('data', function(data) {
//sendResponse("7z: "+data);
});
proc3.stderr.setEncoding('utf8');
proc3.stderr.on('data', function(data) {
sendResponse("7z error: "+data);
});
proc3.on('close', function (code) {
execSync('mv -f "' + config.db_path + 'ygosrv233-pre-2.zip" "' + file_path + '"');
execSync('rm -rf "' + config.db_path +'cdb"');
execSync('rm -rf "' + config.db_path +'picture/card"');
execSync('rm -rf "' + config.db_path +'picture/field"');
sendResponse("PRO2更新包打包完成。");
}); });
}
//生成更新包,异步
var packDatas = function (callback) {
file_path = config.html_path;
if (config.cdn.enabled) {
file_path = config.cdn.local;
}
_async.auto({
preCommands: (done) => {
execCommands([
'cp -r "' + config.db_path + 'expansions" "' + config.db_path + 'cdb"',
'cp -r "' + config.db_path + 'script" "' + config.db_path + 'expansions/script"',
'cp -r "' + config.db_path + 'field" "' + config.db_path + 'pics/field"',
'cp -r "' + config.db_path + 'pics" "' + config.db_path + 'expansions/pics"',
'cp -r "' + config.db_path + 'picn" "' + config.db_path + 'picture/card"',
'cp -r "' + config.db_path + 'field" "' + config.db_path + 'picture/field"'
], done);
},
run7zPC: ["preCommands", (results, done) => {
run7z(["a", "-x!*.zip", "-x!.git", "-x!LICENSE", "-x!README.md", "-x!mobile.cdb", "-x!cdb", "-x!picn", "-x!field", "-x!script", "-x!pics", "-x!expansions/pics/thumbnail", "-x!picture", "ygosrv233-pre.zip", "*"], done);
}],
run7zMobile: ["preCommands", (results, done) => {
run7z(["a", "-x!*.zip", "-x!.git", "-x!LICENSE", "-x!README.md", "-x!mobile.cdb", "-x!cdb", "-x!picn", "-x!field", "-x!script", "-x!pics", "-x!expansions/pics/thumbnail", "-x!picture", "ygosrv233-pre.zip", "*"], done);
}],
run7zPro2: ["preCommands", (results, done) => {
run7z(["a", "-x!*.zip", "-x!.git", "-x!LICENSE", "-x!README.md", "-x!mobile.cdb", "-x!cdb", "-x!picn", "-x!field", "-x!script", "-x!pics", "-x!expansions/pics/thumbnail", "-x!picture", "ygosrv233-pre.zip", "*"], done);
}],
commandsAfterPC: ["run7zPC", (results, done) => {
execCommands([
'mv -f "' + config.db_path + 'ygosrv233-pre.zip" "' + file_path + '"',
'rm -rf "' + config.db_path +'expansions/script"',
'rm -rf "' + config.db_path +'expansions/pics"'
], (err) => {
if (!err) {
sendResponse("电脑更新包打包完成。");
}
done(err);
});
}],
commandsAfterMobile: ["run7zMobile", (results, done) => {
execCommands([
'mv -f "' + config.db_path +'ygosrv233-pre-mobile.zip" "'+ file_path +'"',
'rm -rf "' + config.db_path +'pics/field"'
], (err) => {
if (!err) {
sendResponse("手机更新包打包完成。");
}
done(err);
});
}],
commandsAfterPro2: ["run7zPro2", (results, done) => {
execCommands([
'mv -f "' + config.db_path + 'ygosrv233-pre-2.zip" "' + file_path + '"',
'rm -rf "' + config.db_path +'cdb"',
'rm -rf "' + config.db_path +'picture/card"',
'rm -rf "' + config.db_path +'picture/field"'
], (err) => {
if (!err) {
sendResponse("Pro2更新包打包完成。");
}
done(err);
});
}]
}, callback);
} }
//建立一个http服务器,接收API操作 //建立一个http服务器,接收API操作
...@@ -435,7 +508,7 @@ function requestListener(req, res) { ...@@ -435,7 +508,7 @@ function requestListener(req, res) {
else if (u.pathname === '/api/load_db') { else if (u.pathname === '/api/load_db') {
res.writeHead(200); res.writeHead(200);
res.end(u.query.callback+'({"message":"开始加载数据库。"});'); res.end(u.query.callback+'({"message":"开始加载数据库。"});');
loadAllDbs(); loadAllDbs(() => { });
} }
else if (u.pathname === '/api/fetch_datas') { else if (u.pathname === '/api/fetch_datas') {
res.writeHead(200); res.writeHead(200);
...@@ -445,22 +518,22 @@ function requestListener(req, res) { ...@@ -445,22 +518,22 @@ function requestListener(req, res) {
else if (u.pathname === '/api/push_datas') { else if (u.pathname === '/api/push_datas') {
res.writeHead(200); res.writeHead(200);
res.end(u.query.callback+'({"message":"开始上传数据。"});'); res.end(u.query.callback+'({"message":"开始上传数据。"});');
pushDatas(); pushDatas(() => { });
} }
else if (u.pathname === '/api/write_to_file') { else if (u.pathname === '/api/write_to_file') {
res.writeHead(200); res.writeHead(200);
res.end(u.query.callback+'({"message":"开始写列表页。"});'); res.end(u.query.callback+'({"message":"开始写列表页。"});');
writeToFile(u.query.message); writeToFile(u.query.message, () => { });
} }
else if (u.pathname === '/api/copy_to_ygopro') { else if (u.pathname === '/api/copy_to_ygopro') {
res.writeHead(200); res.writeHead(200);
res.end(u.query.callback+'({"message":"开始更新到服务器。"});'); res.end(u.query.callback+'({"message":"开始更新到服务器。"});');
copyToYGOPRO(); copyToYGOPRO(() => { });
} }
else if (u.pathname === '/api/pack_data') { else if (u.pathname === '/api/pack_data') {
res.writeHead(200); res.writeHead(200);
res.end(u.query.callback+'({"message":"开始生成更新包。"});'); res.end(u.query.callback+'({"message":"开始生成更新包。"});');
packDatas(); packDatas(() => { });
} }
else { else {
res.writeHead(400); res.writeHead(400);
......
...@@ -10,6 +10,7 @@ exec = require('child_process').exec ...@@ -10,6 +10,7 @@ exec = require('child_process').exec
execFile = require('child_process').execFile execFile = require('child_process').execFile
spawn = require('child_process').spawn spawn = require('child_process').spawn
spawnSync = require('child_process').spawnSync spawnSync = require('child_process').spawnSync
_async = require('async')
# 三方库 # 三方库
_ = global._ = require 'underscore' _ = global._ = require 'underscore'
...@@ -140,11 +141,15 @@ try ...@@ -140,11 +141,15 @@ try
catch e catch e
log.info e unless e.code == 'ENOENT' log.info e unless e.code == 'ENOENT'
setting_save = global.setting_save = (settings) -> setting_save = global.setting_save = (settings, callback) ->
fs.writeFileSync(settings.file, JSON.stringify(settings, null, 2)) if !callback
callback = (err) ->
if(err)
log.warn("setting save fail", err.toString())
fs.writeFile(settings.file, JSON.stringify(settings, null, 2), callback)
return return
setting_change = global.setting_change = (settings, path, val) -> setting_change = global.setting_change = (settings, path, val, callback) ->
# path should be like "modules:welcome" # path should be like "modules:welcome"
log.info("setting changed", path, val) if _.isString(val) log.info("setting changed", path, val) if _.isString(val)
path=path.split(':') path=path.split(':')
...@@ -157,7 +162,7 @@ setting_change = global.setting_change = (settings, path, val) -> ...@@ -157,7 +162,7 @@ setting_change = global.setting_change = (settings, path, val) ->
target=target[key] target=target[key]
key = path.shift() key = path.shift()
target[key] = val target[key] = val
setting_save(settings) setting_save(settings, callback)
return return
VIP_generate_cdkeys = global.VIP_generate_cdkeys = (key_type, count) -> VIP_generate_cdkeys = global.VIP_generate_cdkeys = (key_type, count) ->
...@@ -557,20 +562,27 @@ ROOM_connected_ip = global.ROOM_connected_ip = {} ...@@ -557,20 +562,27 @@ ROOM_connected_ip = global.ROOM_connected_ip = {}
ROOM_bad_ip = global.ROOM_bad_ip = {} ROOM_bad_ip = global.ROOM_bad_ip = {}
# ban a user manually and permanently # ban a user manually and permanently
ban_user = global.ban_user = (name) -> ban_user = global.ban_user = (name, callback) ->
settings.ban.banned_user.push(name) settings.ban.banned_user.push(name)
setting_save(settings) setting_save(settings)
bad_ip=0 bad_ip = []
for room in ROOM_all when room and room.established _async.each(ROOM_all, (room, done)->
for player in room.players if !(room and room.established)
if player and (player.name == name or player.ip == bad_ip) done()
bad_ip = player.ip return
ROOM_bad_ip[bad_ip]=99 _async.each(["players", "watchers"], (player_type, _done)->
settings.ban.banned_ip.push(player.ip) _async.each(room[player_type], (player, __done)->
ygopro.stoc_send_chat_to_room(room, "#{player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED) if player and (player.name == name or bad_ip.indexOf(player.ip) != -1)
CLIENT_send_replays(player, room) bad_ip.push(player.ip)
CLIENT_kick(player) ROOM_bad_ip[bad_ip]=99
continue settings.ban.banned_ip.push(player.ip)
ygopro.stoc_send_chat_to_room(room, "#{player.name} ${kicked_by_system}", ygopro.constants.COLORS.RED)
CLIENT_send_replays(player, room)
CLIENT_kick(player)
__done()
, _done)
, done)
, callback)
return return
# automatically ban user to use random duel # automatically ban user to use random duel
...@@ -591,6 +603,28 @@ ROOM_ban_player = global.ROOM_ban_player = (name, ip, reason, countadd = 1)-> ...@@ -591,6 +603,28 @@ ROOM_ban_player = global.ROOM_ban_player = (name, ip, reason, countadd = 1)->
#log.info("banned", name, ip, reason, bannedplayer.count) #log.info("banned", name, ip, reason, bannedplayer.count)
return return
ROOM_kick = (name, callback)->
found = false
_async.each(ROOM_all, (room, done)->
if !(room and room.established and (name == "all" or name == room.process_pid.toString() or name == room.name))
done()
return
found = true
if room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN
room.scores[room.dueling_players[0].name_vpass] = 0
room.scores[room.dueling_players[1].name_vpass] = 0
room.kicked = true
room.send_replays()
room.process.kill()
room.delete()
done()
return
, (err)->
callback(null, found)
return
)
ROOM_player_win = global.ROOM_player_win = (name)-> ROOM_player_win = global.ROOM_player_win = (name)->
if !ROOM_players_scores[name] if !ROOM_players_scores[name]
ROOM_players_scores[name]={win:0, lose:0, flee:0, combo:0} ROOM_players_scores[name]={win:0, lose:0, flee:0, combo:0}
...@@ -2090,7 +2124,7 @@ ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)-> ...@@ -2090,7 +2124,7 @@ ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)->
checksum += buf.readUInt8(i) checksum += buf.readUInt8(i)
(checksum & 0xFF) == 0 (checksum & 0xFF) == 0
buffer_handle_callback = (buffer, decrypted_buffer, match_permit)-> create_room_with_action = (buffer, decrypted_buffer, match_permit)->
if client.closed if client.closed
return return
action = buffer.readUInt8(1) >> 4 action = buffer.readUInt8(1) >> 4
...@@ -2215,67 +2249,90 @@ ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)-> ...@@ -2215,67 +2249,90 @@ ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)->
room.connect(client) room.connect(client)
return return
match_permit_callback = (buffer, match_permit) -> _async.auto({
if client.closed match_permit: (done) ->
if client.closed
done()
return
if(!settings.modules.arena_mode.check_permit)
done(null, null)
return
request
url: settings.modules.arena_mode.check_permit,
json: true,
qs:
username: client.name,
password: info.pass,
arena: settings.modules.arena_mode.mode
, (error, response, body)->
if client.closed
done(null, null)
return
if !error and body
done(null, body)
else
log.warn("Match permit request error", error)
match_permit_callback(null, null)
return
return return
if id = users_cache[client.name] get_user: (done) ->
secret = id % 65535 + 1 if client.closed
decrypted_buffer = Buffer.allocUnsafe(6) done()
for i in [0, 2, 4] return
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i) if id = users_cache[client.name]
if check_buffer_indentity(decrypted_buffer) secret = id % 65535 + 1
return buffer_handle_callback(decrypted_buffer, decrypted_buffer, match_permit)
#TODO: query database directly, like preload.
request
baseUrl: settings.modules.mycard.auth_base_url,
url: '/users/' + encodeURIComponent(client.name) + '.json',
qs:
api_key: settings.modules.mycard.auth_key,
api_username: client.name,
skip_track_visit: true
json: true
, (error, response, body)->
if !error and body and body.user
users_cache[client.name] = body.user.id
secret = body.user.id % 65535 + 1
decrypted_buffer = Buffer.allocUnsafe(6) decrypted_buffer = Buffer.allocUnsafe(6)
for i in [0, 2, 4] for i in [0, 2, 4]
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i) decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i)
if check_buffer_indentity(decrypted_buffer) if check_buffer_indentity(decrypted_buffer)
buffer = decrypted_buffer done(null, {
else original: decrypted_buffer,
log.warn("READ USER FAIL", error, body) decrypted: decrypted_buffer
ygopro.stoc_die(client, "${create_room_failed}") })
return return
# buffer != decrypted_buffer ==> auth failed #TODO: query database directly, like preload.
request
baseUrl: settings.modules.mycard.auth_base_url,
url: '/users/' + encodeURIComponent(client.name) + '.json',
qs:
api_key: settings.modules.mycard.auth_key,
api_username: client.name,
skip_track_visit: true
json: true
, (error, response, body)->
if !error and body and body.user
users_cache[client.name] = body.user.id
secret = body.user.id % 65535 + 1
decrypted_buffer = Buffer.allocUnsafe(6)
for i in [0, 2, 4]
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i)
if check_buffer_indentity(decrypted_buffer)
buffer = decrypted_buffer
else
log.warn("READ USER FAIL", error, body)
done("${create_room_failed}")
return
if !check_buffer_indentity(buffer) # buffer != decrypted_buffer ==> auth failed
ygopro.stoc_die(client, '${invalid_password_checksum}')
return
return buffer_handle_callback(buffer, decrypted_buffer, match_permit)
return
if settings.modules.arena_mode.check_permit if !check_buffer_indentity(buffer)
request done('${invalid_password_checksum}')
url: settings.modules.arena_mode.check_permit, return
json: true, done(null, {
qs: original: buffer,
username: client.name, decrypted: decrypted_buffer
password: info.pass, })
arena: settings.modules.arena_mode.mode
, (error, response, body)->
if client.closed
return return
if !error and body
match_permit_callback(buffer, body)
else
log.warn("Match permit request error", error)
match_permit_callback(buffer, null)
return return
else }, (err, data) ->
match_permit_callback(buffer, null) if(client.closed)
return
if(err)
ygopro.stoc_die(client, err)
return
create_room_with_action(data.get_user.original, data.get_user.decrypted, data.match_permit)
)
else if settings.modules.challonge.enabled else if settings.modules.challonge.enabled
...@@ -2293,87 +2350,86 @@ ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)-> ...@@ -2293,87 +2350,86 @@ ygopro.ctos_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)->
else else
ygopro.stoc_send_chat(client, '${loading_user_info}', ygopro.constants.COLORS.BABYBLUE) ygopro.stoc_send_chat(client, '${loading_user_info}', ygopro.constants.COLORS.BABYBLUE)
client.setTimeout(300000) #连接后超时5分钟 client.setTimeout(300000) #连接后超时5分钟
challonge.participants._index({ _async.auto({
id: settings.modules.challonge.tournament_id, participant_data: (done) ->
callback: (err, data) -> challonge.participants._index({
if client.closed id: settings.modules.challonge.tournament_id,
return callback: done
if err or !data })
if err return
log.warn("Failed loading Challonge user info", err) ,
ygopro.stoc_die(client, '${challonge_match_load_failed}') match_data: (done) ->
return
found = false
for k,user of data
if user.participant and user.participant.name and deck_name_match(user.participant.name, client.name)
found = user.participant
break
if !found
ygopro.stoc_die(client, '${challonge_user_not_found}')
return
client.challonge_info = found
challonge.matches._index({ challonge.matches._index({
id: settings.modules.challonge.tournament_id, id: settings.modules.challonge.tournament_id,
callback: (err, data) -> callback: done
if client.closed
return
if err or !data
if err
log.warn("Failed loading Challonge match info", err)
ygopro.stoc_die(client, '${challonge_match_load_failed}')
return
found = false
for k,match of data
if match and match.match and !match.match.winnerId and match.match.state != "complete" and match.match.player1Id and match.match.player2Id and (match.match.player1Id == client.challonge_info.id or match.match.player2Id == client.challonge_info.id)
found = match.match
break
if !found
ygopro.stoc_die(client, '${challonge_match_not_found}')
return
#if found.winnerId
# ygopro.stoc_die(client, '${challonge_match_already_finished}')
# return
room = ROOM_find_or_create_by_name('M#' + found.id)
if room
room.challonge_info = found
# room.max_player = 2
room.welcome = "${challonge_match_created}"
if !room
ygopro.stoc_die(client, "${server_full}")
else if room.error
ygopro.stoc_die(client, room.error)
else if room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN
if settings.modules.cloud_replay.enable_halfway_watch and !room.hostinfo.no_watch
#client.setTimeout(300000) #连接后超时5分钟
client.rid = _.indexOf(ROOM_all, room)
client.is_post_watcher = true
if settings.modules.vip.enabled and client.vip and vip_info.players[client.name].words
for line in _.lines vip_info.players[client.name].words
ygopro.stoc_send_chat_to_room(room, line, ygopro.constants.COLORS.PINK)
else if settings.modules.words.enabled and words.words[client.name]
for line in _.lines words.words[client.name][Math.floor(Math.random() * words.words[client.name].length)]
ygopro.stoc_send_chat_to_room(room, line, ygopro.constants.COLORS.PINK)
ygopro.stoc_send_chat_to_room(room, "#{client.name} ${watch_join}")
room.watchers.push client
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE)
for buffer in room.watcher_buffers
client.write buffer
else
ygopro.stoc_die(client, "${watch_denied}")
else if room.hostinfo.no_watch and room.players.length >= (if room.hostinfo.mode == 2 then 4 else 2)
ygopro.stoc_die(client, "${watch_denied_room}")
else
for player in room.get_playing_player() when player and player != client and player.challonge_info.id == client.challonge_info.id
ygopro.stoc_die(client, "${challonge_player_already_in}")
return
#client.room = room
#client.setTimeout(300000) #连接后超时5分钟
client.rid = _.indexOf(ROOM_all, room)
room.connect(client)
return
}) })
return return
}) }, (err, datas) ->
if client.closed
return
if err or !datas.participant_data or !datas.match_data
log.warn("Failed loading Challonge user info", err)
ygopro.stoc_die(client, '${challonge_match_load_failed}')
return
found = false
for k,user of datas.participant_data
if user.participant and user.participant.name and deck_name_match(user.participant.name, client.name)
found = user.participant
break
if !found
ygopro.stoc_die(client, '${challonge_user_not_found}')
return
client.challonge_info = found
found = false
for k,match of datas.match_data
if match and match.match and !match.match.winnerId and match.match.state != "complete" and match.match.player1Id and match.match.player2Id and (match.match.player1Id == client.challonge_info.id or match.match.player2Id == client.challonge_info.id)
found = match.match
break
if !found
ygopro.stoc_die(client, '${challonge_match_not_found}')
return
#if found.winnerId
# ygopro.stoc_die(client, '${challonge_match_already_finished}')
# return
room = ROOM_find_or_create_by_name('M#' + found.id)
if room
room.challonge_info = found
# room.max_player = 2
room.welcome = "${challonge_match_created}"
if !room
ygopro.stoc_die(client, "${server_full}")
else if room.error
ygopro.stoc_die(client, room.error)
else if room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN
if settings.modules.cloud_replay.enable_halfway_watch and !room.hostinfo.no_watch
#client.setTimeout(300000) #连接后超时5分钟
client.rid = _.indexOf(ROOM_all, room)
client.is_post_watcher = true
if settings.modules.vip.enabled and client.vip and vip_info.players[client.name].words
for line in _.lines vip_info.players[client.name].words
ygopro.stoc_send_chat_to_room(room, line, ygopro.constants.COLORS.PINK)
else if settings.modules.words.enabled and words.words[client.name]
for line in _.lines words.words[client.name][Math.floor(Math.random() * words.words[client.name].length)]
ygopro.stoc_send_chat_to_room(room, line, ygopro.constants.COLORS.PINK)
ygopro.stoc_send_chat_to_room(room, "#{client.name} ${watch_join}")
room.watchers.push client
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE)
for buffer in room.watcher_buffers
client.write buffer
else
ygopro.stoc_die(client, "${watch_denied}")
else if room.hostinfo.no_watch and room.players.length >= (if room.hostinfo.mode == 2 then 4 else 2)
ygopro.stoc_die(client, "${watch_denied_room}")
else
for player in room.get_playing_player() when player and player != client and player.challonge_info.id == client.challonge_info.id
ygopro.stoc_die(client, "${challonge_player_already_in}")
return
#client.room = room
#client.setTimeout(300000) #连接后超时5分钟
client.rid = _.indexOf(ROOM_all, room)
room.connect(client)
return
)
else if !client.name or client.name=="" else if !client.name or client.name==""
ygopro.stoc_die(client, "${bad_user_name}") ygopro.stoc_die(client, "${bad_user_name}")
...@@ -2539,7 +2595,7 @@ ygopro.stoc_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)-> ...@@ -2539,7 +2595,7 @@ ygopro.stoc_follow 'JOIN_GAME', false, (buffer, info, client, server, datas)->
return return
# 登场台词 # 登场台词
load_words = global.load_words = () -> load_words = global.load_words = (callback) ->
request request
url: settings.modules.words.get url: settings.modules.words.get
json: true json: true
...@@ -2551,13 +2607,15 @@ load_words = global.load_words = () -> ...@@ -2551,13 +2607,15 @@ load_words = global.load_words = () ->
else else
setting_change(words, "words", body) setting_change(words, "words", body)
log.info "words loaded", _.size words.words log.info "words loaded", _.size words.words
if callback
callback(error, body)
return return
return return
if settings.modules.words.get if settings.modules.words.get
load_words() load_words()
load_dialogues = global.load_dialogues = () -> load_dialogues = global.load_dialogues = (callback) ->
request request
url: settings.modules.dialogues.get url: settings.modules.dialogues.get
json: true json: true
...@@ -2569,10 +2627,12 @@ load_dialogues = global.load_dialogues = () -> ...@@ -2569,10 +2627,12 @@ load_dialogues = global.load_dialogues = () ->
else else
setting_change(dialogues, "dialogues", body) setting_change(dialogues, "dialogues", body)
log.info "dialogues loaded", _.size dialogues.dialogues log.info "dialogues loaded", _.size dialogues.dialogues
if callback
callback(error, body)
return return
return return
load_dialogues_custom = global.load_dialogues_custom = () -> load_dialogues_custom = global.load_dialogues_custom = (callback) ->
request request
url: settings.modules.dialogues.get_custom url: settings.modules.dialogues.get_custom
json: true json: true
...@@ -2584,6 +2644,8 @@ load_dialogues_custom = global.load_dialogues_custom = () -> ...@@ -2584,6 +2644,8 @@ load_dialogues_custom = global.load_dialogues_custom = () ->
else else
setting_change(dialogues, "dialogues_custom", body) setting_change(dialogues, "dialogues_custom", body)
log.info "custom dialogues loaded", _.size dialogues.dialogues_custom log.info "custom dialogues loaded", _.size dialogues.dialogues_custom
if callback
callback(error, body)
return return
return return
...@@ -3045,7 +3107,7 @@ ygopro.stoc_send_random_tip_to_room = (room)-> ...@@ -3045,7 +3107,7 @@ ygopro.stoc_send_random_tip_to_room = (room)->
ygopro.stoc_send_random_tip(player) ygopro.stoc_send_random_tip(player)
return return
load_tips = global.load_tips = ()-> load_tips = global.load_tips = (callback)->
request request
url: settings.modules.tips.get url: settings.modules.tips.get
json: true json: true
...@@ -3057,10 +3119,12 @@ load_tips = global.load_tips = ()-> ...@@ -3057,10 +3119,12 @@ load_tips = global.load_tips = ()->
else else
setting_change(tips, "tips", body) setting_change(tips, "tips", body)
log.info "tips loaded", tips.tips.length log.info "tips loaded", tips.tips.length
if callback
callback(error, body)
return return
return return
load_tips_zh = global.load_tips_zh = ()-> load_tips_zh = global.load_tips_zh = (callback)->
request request
url: settings.modules.tips.get_zh url: settings.modules.tips.get_zh
json: true json: true
...@@ -3072,6 +3136,8 @@ load_tips_zh = global.load_tips_zh = ()-> ...@@ -3072,6 +3136,8 @@ load_tips_zh = global.load_tips_zh = ()->
else else
setting_change(tips, "tips_zh", body) setting_change(tips, "tips_zh", body)
log.info "zh tips loaded", tips.tips_zh.length log.info "zh tips loaded", tips.tips_zh.length
if callback
callback(error, body)
return return
return return
...@@ -3769,7 +3835,10 @@ ygopro.stoc_follow 'REPLAY', true, (buffer, info, client, server, datas)-> ...@@ -3769,7 +3835,10 @@ ygopro.stoc_follow 'REPLAY', true, (buffer, info, client, server, datas)->
if settings.modules.random_duel.enabled if settings.modules.random_duel.enabled
setInterval ()-> setInterval ()->
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.random_type and room.last_active_time and room.waiting_for_player and room.get_disconnected_count() == 0 and (!settings.modules.side_timeout or room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING) _async.each(ROOM_all, (room, done) ->
if !(room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.random_type and room.last_active_time and room.waiting_for_player and room.get_disconnected_count() == 0 and (!settings.modules.side_timeout or room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING))
done()
return
time_passed = Math.floor((moment() - room.last_active_time) / 1000) time_passed = Math.floor((moment() - room.last_active_time) / 1000)
#log.info time_passed #log.info time_passed
if time_passed >= settings.modules.random_duel.hang_timeout if time_passed >= settings.modules.random_duel.hang_timeout
...@@ -3783,12 +3852,18 @@ if settings.modules.random_duel.enabled ...@@ -3783,12 +3852,18 @@ if settings.modules.random_duel.enabled
else if time_passed >= (settings.modules.random_duel.hang_timeout - 20) and not (time_passed % 10) else if time_passed >= (settings.modules.random_duel.hang_timeout - 20) and not (time_passed % 10)
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${afk_warn_part1}#{settings.modules.random_duel.hang_timeout - time_passed}${afk_warn_part2}", ygopro.constants.COLORS.RED) ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${afk_warn_part1}#{settings.modules.random_duel.hang_timeout - time_passed}${afk_warn_part2}", ygopro.constants.COLORS.RED)
ROOM_unwelcome(room, room.waiting_for_player, "${random_ban_reason_AFK}") ROOM_unwelcome(room, room.waiting_for_player, "${random_ban_reason_AFK}")
done()
return
)
return return
, 1000 , 1000
if settings.modules.mycard.enabled if settings.modules.mycard.enabled
setInterval ()-> setInterval ()->
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.arena and room.last_active_time and room.waiting_for_player and room.get_disconnected_count() == 0 and (!settings.modules.side_timeout or room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING) _async.each(ROOM_all, (room, done) ->
if not (room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.arena and room.last_active_time and room.waiting_for_player and room.get_disconnected_count() == 0 and (!settings.modules.side_timeout or room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING))
done()
return
time_passed = Math.floor((moment() - room.last_active_time) / 1000) time_passed = Math.floor((moment() - room.last_active_time) / 1000)
#log.info time_passed #log.info time_passed
if time_passed >= settings.modules.random_duel.hang_timeout if time_passed >= settings.modules.random_duel.hang_timeout
...@@ -3800,8 +3875,15 @@ if settings.modules.mycard.enabled ...@@ -3800,8 +3875,15 @@ if settings.modules.mycard.enabled
CLIENT_kick(room.waiting_for_player) CLIENT_kick(room.waiting_for_player)
else if time_passed >= (settings.modules.random_duel.hang_timeout - 20) and not (time_passed % 10) else if time_passed >= (settings.modules.random_duel.hang_timeout - 20) and not (time_passed % 10)
ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${afk_warn_part1}#{settings.modules.random_duel.hang_timeout - time_passed}${afk_warn_part2}", ygopro.constants.COLORS.RED) ygopro.stoc_send_chat_to_room(room, "#{room.waiting_for_player.name} ${afk_warn_part1}#{settings.modules.random_duel.hang_timeout - time_passed}${afk_warn_part2}", ygopro.constants.COLORS.RED)
done()
return
)
if settings.modules.arena_mode.punish_quit_before_match if settings.modules.arena_mode.punish_quit_before_match
for room in ROOM_all when room and room.arena and room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and room.get_playing_player().length < 2 _async.each(ROOM_all, (room, done) ->
if not (room and room.arena and room.duel_stage == ygopro.constants.DUEL_STAGE.BEGIN and room.get_playing_player().length < 2)
done()
return
player = room.get_playing_player()[0] player = room.get_playing_player()[0]
if player and player.join_time and !player.arena_quit_free if player and player.join_time and !player.arena_quit_free
waited_time = moment() - player.join_time waited_time = moment() - player.join_time
...@@ -3810,22 +3892,33 @@ if settings.modules.mycard.enabled ...@@ -3810,22 +3892,33 @@ if settings.modules.mycard.enabled
player.arena_quit_free = true player.arena_quit_free = true
else if waited_time >= 5000 and waited_time < 6000 else if waited_time >= 5000 and waited_time < 6000
ygopro.stoc_send_chat(player, "${arena_wait_hint}", ygopro.constants.COLORS.BABYBLUE) ygopro.stoc_send_chat(player, "${arena_wait_hint}", ygopro.constants.COLORS.BABYBLUE)
done()
return
)
return return
, 1000 , 1000
if settings.modules.heartbeat_detection.enabled if settings.modules.heartbeat_detection.enabled
setInterval ()-> setInterval ()->
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and (room.hostinfo.time_limit == 0 or room.duel_stage != ygopro.constants.DUEL_STAGE.DUELING) and !room.windbot _async.each ROOM_all, (room, done)->
for player in room.get_playing_player() when player and (room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING or player.selected_preduel) if room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and (room.hostinfo.time_limit == 0 or room.duel_stage != ygopro.constants.DUEL_STAGE.DUELING) and !room.windbot
CLIENT_heartbeat_register(player, true) _async.each(room.get_playing_player(), (player, _done)->
if player and (room.duel_stage != ygopro.constants.DUEL_STAGE.SIDING or player.selected_preduel)
CLIENT_heartbeat_register(player, true)
_done()
, done)
else
done()
return return
, settings.modules.heartbeat_detection.interval , settings.modules.heartbeat_detection.interval
setInterval ()-> setInterval ()->
current_time = moment() current_time = moment()
for room in ROOM_all when room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.hostinfo.auto_death and !room.auto_death_triggered and current_time - moment(room.start_time) > 60000 * room.hostinfo.auto_death _async.each ROOM_all, (room, done)->
room.auto_death_triggered = true if room and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and room.hostinfo.auto_death and !room.auto_death_triggered and current_time - moment(room.start_time) > 60000 * room.hostinfo.auto_death
room.start_death() room.auto_death_triggered = true
room.start_death()
done()
, 1000 , 1000
...@@ -3845,13 +3938,13 @@ spawn_windbot = global.spawn_windbot = () -> ...@@ -3845,13 +3938,13 @@ spawn_windbot = global.spawn_windbot = () ->
windbot_process = spawn windbot_bin, windbot_parameters, {cwd: 'windbot'} windbot_process = spawn windbot_bin, windbot_parameters, {cwd: 'windbot'}
windbot_process.on 'error', (err)-> windbot_process.on 'error', (err)->
log.warn 'WindBot ERROR', err log.warn 'WindBot ERROR', err
if windbot_looplimit < 1000 and !rebooted if windbot_looplimit < 1000 and !global.rebooted
windbot_looplimit++ windbot_looplimit++
spawn_windbot() spawn_windbot()
return return
windbot_process.on 'exit', (code)-> windbot_process.on 'exit', (code)->
log.warn 'WindBot EXIT', code log.warn 'WindBot EXIT', code
if windbot_looplimit < 1000 and !rebooted if windbot_looplimit < 1000 and !global.rebooted
windbot_looplimit++ windbot_looplimit++
spawn_windbot() spawn_windbot()
return return
...@@ -3868,7 +3961,7 @@ spawn_windbot = global.spawn_windbot = () -> ...@@ -3868,7 +3961,7 @@ spawn_windbot = global.spawn_windbot = () ->
if settings.modules.windbot.enabled and settings.modules.windbot.spawn if settings.modules.windbot.enabled and settings.modules.windbot.spawn
spawn_windbot() spawn_windbot()
rebooted = false global.rebooted = false
#http #http
if settings.modules.http if settings.modules.http
...@@ -3883,31 +3976,40 @@ if settings.modules.http ...@@ -3883,31 +3976,40 @@ if settings.modules.http
#console.log(u.query.username, u.query.pass) #console.log(u.query.username, u.query.pass)
if u.pathname == '/api/getrooms' if u.pathname == '/api/getrooms'
pass_validated = auth.auth(u.query.username, u.query.pass, "get_rooms", "get_rooms") pass_validated = auth.auth(u.query.username, u.query.pass, "get_rooms", "get_rooms", true)
if !settings.modules.http.public_roomlist and !pass_validated if !settings.modules.http.public_roomlist and !pass_validated
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, '{"rooms":[{"roomid":"0","roomname":"密码错误","needpass":"true"}]}')) response.end(addCallback(u.query.callback, '{"rooms":[{"roomid":"0","roomname":"密码错误","needpass":"true"}]}'))
else else
response.writeHead(200) roomsjson = [];
roomsjson = JSON.stringify rooms: (for room in ROOM_all when room and room.established _async.each(ROOM_all, (room, done)->
roomid: room.process_pid.toString(), if !(room and room.established)
roomname: if pass_validated then room.name else room.name.split('$', 2)[0], done()
roommode: room.hostinfo.mode, return
needpass: (room.name.indexOf('$') != -1).toString(), roomsjson.push({
users: _.sortBy((for player in room.players when player.pos? roomid: room.process_pid.toString(),
id: (-1).toString(), roomname: if pass_validated then room.name else room.name.split('$', 2)[0],
name: player.name, roommode: room.hostinfo.mode,
ip: if settings.modules.http.show_ip and pass_validated and !player.is_local then player.ip.slice(7) else null, needpass: (room.name.indexOf('$') != -1).toString(),
status: if settings.modules.http.show_info and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and player.pos != 7 then ( users: _.sortBy((for player in room.players when player.pos?
score: room.scores[player.name_vpass], id: (-1).toString(),
lp: if player.lp? then player.lp else room.hostinfo.start_lp, name: player.name,
cards: if room.hostinfo.mode != 2 then (if player.card_count? then player.card_count else room.hostinfo.start_hand) else null ip: if settings.modules.http.show_ip and pass_validated and !player.is_local then player.ip.slice(7) else null,
) else null, status: if settings.modules.http.show_info and room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN and player.pos != 7 then (
pos: player.pos score: room.scores[player.name_vpass],
), "pos"), lp: if player.lp? then player.lp else room.hostinfo.start_lp,
istart: if room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN then (if settings.modules.http.show_info then ("Duel:" + room.duel_count + " " + (if room.duel_stage == ygopro.constants.DUEL_STAGE.SIDING then "Siding" else "Turn:" + (if room.turn? then room.turn else 0) + (if room.death then "/" + (if room.death > 0 then room.death - 1 else "Death") else ""))) else 'start') else 'wait' cards: if room.hostinfo.mode != 2 then (if player.card_count? then player.card_count else room.hostinfo.start_hand) else null
), null, 2 ) else null,
response.end(addCallback(u.query.callback, roomsjson)) pos: player.pos
), "pos"),
istart: if room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN then (if settings.modules.http.show_info then ("Duel:" + room.duel_count + " " + (if room.duel_stage == ygopro.constants.DUEL_STAGE.SIDING then "Siding" else "Turn:" + (if room.turn? then room.turn else 0) + (if room.death then "/" + (if room.death > 0 then room.death - 1 else "Death") else ""))) else 'start') else 'wait'
})
done()
, ()->
response.writeHead(200)
response.end(addCallback(u.query.callback, JSON.stringify({rooms: roomsjson})))
)
else if u.pathname == '/api/duellog' and settings.modules.tournament_mode.enabled else if u.pathname == '/api/duellog' and settings.modules.tournament_mode.enabled
if !auth.auth(u.query.username, u.query.pass, "duel_log", "duel_log") if !auth.auth(u.query.username, u.query.pass, "duel_log", "duel_log")
...@@ -4042,18 +4144,26 @@ if settings.modules.http ...@@ -4042,18 +4144,26 @@ if settings.modules.http
return return
if u.query.stop == 'false' if u.query.stop == 'false'
u.query.stop = false u.query.stop = false
setting_change(settings, 'modules:stop', u.query.stop) setting_change(settings, 'modules:stop', u.query.stop, (err)->
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, "['stop ok', '" + u.query.stop + "']")) if(err)
response.end(addCallback(u.query.callback, "['stop fail', '" + u.query.stop + "']"))
else
response.end(addCallback(u.query.callback, "['stop ok', '" + u.query.stop + "']"))
)
else if u.query.welcome else if u.query.welcome
if !auth.auth(u.query.username, u.query.pass, "change_settings", "change_welcome") if !auth.auth(u.query.username, u.query.pass, "change_settings", "change_welcome")
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, "['密码错误', 0]")) response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return return
setting_change(settings, 'modules:welcome', u.query.welcome) setting_change(settings, 'modules:welcome', (err)->
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, "['welcome ok', '" + u.query.welcome + "']")) if(err)
response.end(addCallback(u.query.callback, "['welcome fail', '" + u.query.welcome + "']"))
else
response.end(addCallback(u.query.callback, "['welcome ok', '" + u.query.welcome + "']"))
)
else if u.query.getwelcome else if u.query.getwelcome
if !auth.auth(u.query.username, u.query.pass, "change_settings", "get_welcome") if !auth.auth(u.query.username, u.query.pass, "change_settings", "get_welcome")
...@@ -4068,57 +4178,65 @@ if settings.modules.http ...@@ -4068,57 +4178,65 @@ if settings.modules.http
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, "['密码错误', 0]")) response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return return
load_tips() tasks = {
tips: load_tips
}
if settings.modules.tips.get_zh if settings.modules.tips.get_zh
load_tips_zh() tasks.tips_zh = load_tips_zh
response.writeHead(200) _async.auto(tasks, (err)->
response.end(addCallback(u.query.callback, "['loading tip', '" + settings.modules.tips.get + (if settings.modules.tips.get_zh then " and " + settings.modules.tips.get_zh else "") + "']")) response.writeHead(200)
if(err)
response.end(addCallback(u.query.callback, "['tip fail', '" + settings.modules.tips.get + "']"))
else
response.end(addCallback(u.query.callback, "['tip ok', '" + settings.modules.tips.get + "']"))
)
else if u.query.loaddialogues else if u.query.loaddialogues
if !auth.auth(u.query.username, u.query.pass, "change_settings", "change_dialogues") if !auth.auth(u.query.username, u.query.pass, "change_settings", "change_dialogues")
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, "['密码错误', 0]")) response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return return
load_dialogues() tasks = {
dialogues: load_dialogues
}
if settings.modules.dialogues.get_custom if settings.modules.dialogues.get_custom
load_dialogues_custom() tasks.dialogues_custom = load_dialogues_custom
response.writeHead(200) _async.auto(tasks, (err)->
response.end(addCallback(u.query.callback, "['loading dialogues', '" + settings.modules.dialogues.get + (if settings.modules.dialogues.get_custom then " and " + settings.modules.dialogues.get_custom else "") + "']")) response.writeHead(200)
if(err)
else if u.query.loadwords response.end(addCallback(u.query.callback, "['dialogues fail', '" + settings.modules.dialogues.get + "']"))
load_words() else
response.writeHead(200) response.end(addCallback(u.query.callback, "['dialogues ok', '" +settings.modules.dialogues.get + "']"))
response.end(addCallback(u.query.callback, "['loading words', '" + settings.modules.words.get + "']")) )
else if u.query.ban else if u.query.ban
if !auth.auth(u.query.username, u.query.pass, "ban_user", "ban_user") if !auth.auth(u.query.username, u.query.pass, "ban_user", "ban_user")
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, "['密码错误', 0]")) response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return return
ban_user(u.query.ban) ban_user(u.query.ban, (err)->
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']")) if(err)
response.end(addCallback(u.query.callback, "['ban fail', '" + u.query.ban + "']"))
else
response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']"))
)
else if u.query.kick else if u.query.kick
if !auth.auth(u.query.username, u.query.pass, "kick_user", "kick_user") if !auth.auth(u.query.username, u.query.pass, "kick_user", "kick_user")
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, "['密码错误', 0]")) response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return return
kick_room_found = false ROOM_kick(u.query.kick, (err, found)->
for room in ROOM_all when room and room.established and (u.query.kick == "all" or u.query.kick == room.process_pid.toString() or u.query.kick == room.name) response.writeHead(200)
kick_room_found = true if err
if room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN response.end(addCallback(u.query.callback, "['kick fail', '" + u.query.kick + "']"))
room.scores[room.dueling_players[0].name_vpass] = 0 else if found
room.scores[room.dueling_players[1].name_vpass] = 0 response.end(addCallback(u.query.callback, "['kick ok', '" + u.query.kick + "']"))
room.kicked = true else
room.send_replays() response.end(addCallback(u.query.callback, "['room not found', '" + u.query.kick + "']"))
room.process.kill() )
room.delete()
response.writeHead(200)
if kick_room_found
response.end(addCallback(u.query.callback, "['kick ok', '" + u.query.kick + "']"))
else
response.end(addCallback(u.query.callback, "['room not found', '" + u.query.kick + "']"))
else if u.query.death else if u.query.death
if !auth.auth(u.query.username, u.query.pass, "start_death", "start_death") if !auth.auth(u.query.username, u.query.pass, "start_death", "start_death")
...@@ -4126,14 +4244,21 @@ if settings.modules.http ...@@ -4126,14 +4244,21 @@ if settings.modules.http
response.end(addCallback(u.query.callback, "['密码错误', 0]")) response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return return
death_room_found = false death_room_found = false
for room in ROOM_all when room and (u.query.death == "all" or u.query.death == room.process_pid.toString() or u.query.death == room.name) _async.each(ROOM_all, (room, done)->
if !(room and (u.query.death == "all" or u.query.death == room.process_pid.toString() or u.query.death == room.name))
done()
return
if room.start_death() if room.start_death()
death_room_found = true death_room_found = true
response.writeHead(200) done()
if death_room_found return
response.end(addCallback(u.query.callback, "['death ok', '" + u.query.death + "']")) , () ->
else response.writeHead(200)
response.end(addCallback(u.query.callback, "['room not found', '" + u.query.death + "']")) if death_room_found
response.end(addCallback(u.query.callback, "['death ok', '" + u.query.death + "']"))
else
response.end(addCallback(u.query.callback, "['room not found', '" + u.query.death + "']"))
)
else if u.query.deathcancel else if u.query.deathcancel
if !auth.auth(u.query.username, u.query.pass, "start_death", "cancel_death") if !auth.auth(u.query.username, u.query.pass, "start_death", "cancel_death")
...@@ -4141,34 +4266,35 @@ if settings.modules.http ...@@ -4141,34 +4266,35 @@ if settings.modules.http
response.end(addCallback(u.query.callback, "['密码错误', 0]")) response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return return
death_room_found = false death_room_found = false
for room in ROOM_all when room and (u.query.deathcancel == "all" or u.query.deathcancel == room.process_pid.toString() or u.query.deathcancel == room.name) _async.each(rooms, (room, done)->
if !(room and (u.query.deathcancel == "all" or u.query.deathcancel == room.process_pid.toString() or u.query.deathcancel == room.name))
done()
return
if room.cancel_death() if room.cancel_death()
death_room_found = true death_room_found = true
response.writeHead(200) done()
if death_room_found , () ->
response.end(addCallback(u.query.callback, "['death cancel ok', '" + u.query.deathcancel + "']")) response.writeHead(200)
else if death_room_found
response.end(addCallback(u.query.callback, "['room not found', '" + u.query.deathcancel + "']")) response.end(addCallback(u.query.callback, "['death cancel ok', '" + u.query.deathcancel + "']"))
else
response.end(addCallback(u.query.callback, "['room not found', '" + u.query.deathcancel + "']"))
)
else if u.query.reboot else if u.query.reboot
if !auth.auth(u.query.username, u.query.pass, "stop", "reboot") if !auth.auth(u.query.username, u.query.pass, "stop", "reboot")
response.writeHead(200) response.writeHead(200)
response.end(addCallback(u.query.callback, "['密码错误', 0]")) response.end(addCallback(u.query.callback, "['密码错误', 0]"))
return return
for room in ROOM_all when room ROOM_kick("all", (err, found)->
if room.duel_stage != ygopro.constants.DUEL_STAGE.BEGIN global.rebooted = true
room.scores[room.dueling_players[0].name_vpass] = 0 if windbot_process
room.scores[room.dueling_players[1].name_vpass] = 0 windbot_process.kill()
room.kicked = true response.writeHead(200)
room.send_replays() response.end(addCallback(u.query.callback, "['reboot ok', '" + u.query.reboot + "']"))
room.process.kill() process.exit()
room.delete() )
rebooted = true
if windbot_process
windbot_process.kill()
response.writeHead(200)
response.end(addCallback(u.query.callback, "['reboot ok', '" + u.query.reboot + "']"))
throw "rebooted"
else if u.query.generatekey and settings.modules.vip.enabled else if u.query.generatekey and settings.modules.vip.enabled
if !auth.auth(u.query.username, u.query.pass, "vip", "generate_keys") if !auth.auth(u.query.username, u.query.pass, "vip", "generate_keys")
......
// Generated by CoffeeScript 1.12.7 // Generated by CoffeeScript 1.12.7
(function() { (function() {
var CLIENT_check_vip, CLIENT_get_absolute_pos, CLIENT_get_authorize_key, CLIENT_get_kick_reconnect_target, CLIENT_get_partner, CLIENT_heartbeat_register, CLIENT_heartbeat_unregister, CLIENT_import_data, CLIENT_is_able_to_kick_reconnect, CLIENT_is_able_to_reconnect, CLIENT_is_banned_by_mc, CLIENT_is_player, CLIENT_kick, CLIENT_kick_reconnect, CLIENT_pre_reconnect, CLIENT_reconnect, CLIENT_reconnect_register, CLIENT_reconnect_unregister, CLIENT_send_pre_reconnect_info, CLIENT_send_reconnect_info, CLIENT_send_replays, CLIENT_send_vip_status, CLIENT_use_cdkey, Cloud_replay_ids, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_clear_disconnect, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_pid, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_player_flee, ROOM_player_get_score, ROOM_player_lose, ROOM_player_win, ROOM_players_banned, ROOM_players_oppentlist, ROOM_players_scores, ROOM_unwelcome, ROOM_validate, Room, SERVER_clear_disconnect, SERVER_kick, SOCKET_flush_data, VIP_generate_cdkeys, _, addCallback, auth, badwords, ban_user, bunyan, challonge, challonge_cache, challonge_module_name, challonge_queue_callbacks, chat_color, concat_name, config, cppversion, crypto, date, deck_name_match, default_config, default_data, dialogues, disconnect_list, dns, duel_log, e, exec, execFile, fs, geoip, get_callback, get_memory_usage, http, http_server, https, https_server, import_datas, imported, is_requesting, j, k, l, len, len1, len2, lflists, list, loadJSON, load_dialogues, load_dialogues_custom, load_tips, load_tips_zh, load_words, log, long_resolve_cards, m, memory_usage, merge, moment, net, oldbadwords, oldconfig, olddialogues, oldduellog, oldtips, oldwords, options, os, path, pgClient, pg_client, pg_query, plugin_filename, plugin_list, plugin_path, real_windbot_server_ip, rebooted, redis, redisdb, ref, ref1, ref2, refresh_challonge_cache, release_disconnect, report_to_big_brother, request, requestListener, roomlist, setting_change, setting_save, settings, spawn, spawnSync, spawn_windbot, tips, url, users_cache, v, vip_info, wait_room_start, wait_room_start_arena, windbot_looplimit, windbot_process, windbots, words, ygopro, zlib; var CLIENT_check_vip, CLIENT_get_absolute_pos, CLIENT_get_authorize_key, CLIENT_get_kick_reconnect_target, CLIENT_get_partner, CLIENT_heartbeat_register, CLIENT_heartbeat_unregister, CLIENT_import_data, CLIENT_is_able_to_kick_reconnect, CLIENT_is_able_to_reconnect, CLIENT_is_banned_by_mc, CLIENT_is_player, CLIENT_kick, CLIENT_kick_reconnect, CLIENT_pre_reconnect, CLIENT_reconnect, CLIENT_reconnect_register, CLIENT_reconnect_unregister, CLIENT_send_pre_reconnect_info, CLIENT_send_reconnect_info, CLIENT_send_replays, CLIENT_send_vip_status, CLIENT_use_cdkey, Cloud_replay_ids, ROOM_all, ROOM_bad_ip, ROOM_ban_player, ROOM_clear_disconnect, ROOM_connected_ip, ROOM_find_by_name, ROOM_find_by_pid, ROOM_find_by_port, ROOM_find_by_title, ROOM_find_or_create_ai, ROOM_find_or_create_by_name, ROOM_find_or_create_random, ROOM_kick, ROOM_player_flee, ROOM_player_get_score, ROOM_player_lose, ROOM_player_win, ROOM_players_banned, ROOM_players_oppentlist, ROOM_players_scores, ROOM_unwelcome, ROOM_validate, Room, SERVER_clear_disconnect, SERVER_kick, SOCKET_flush_data, VIP_generate_cdkeys, _, _async, addCallback, auth, badwords, ban_user, bunyan, challonge, challonge_cache, challonge_module_name, challonge_queue_callbacks, chat_color, concat_name, config, cppversion, crypto, date, deck_name_match, default_config, default_data, dialogues, disconnect_list, dns, duel_log, e, exec, execFile, fs, geoip, get_callback, get_memory_usage, http, http_server, https, https_server, import_datas, imported, is_requesting, j, k, l, len, len1, len2, lflists, list, loadJSON, load_dialogues, load_dialogues_custom, load_tips, load_tips_zh, load_words, log, long_resolve_cards, m, memory_usage, merge, moment, net, oldbadwords, oldconfig, olddialogues, oldduellog, oldtips, oldwords, options, os, path, pgClient, pg_client, pg_query, plugin_filename, plugin_list, plugin_path, real_windbot_server_ip, redis, redisdb, ref, ref1, ref2, refresh_challonge_cache, release_disconnect, report_to_big_brother, request, requestListener, roomlist, setting_change, setting_save, settings, spawn, spawnSync, spawn_windbot, tips, url, users_cache, v, vip_info, wait_room_start, wait_room_start_arena, windbot_looplimit, windbot_process, windbots, words, ygopro, zlib;
net = require('net'); net = require('net');
...@@ -24,6 +24,8 @@ ...@@ -24,6 +24,8 @@
spawnSync = require('child_process').spawnSync; spawnSync = require('child_process').spawnSync;
_async = require('async');
_ = global._ = require('underscore'); _ = global._ = require('underscore');
_.str = require('underscore.string'); _.str = require('underscore.string');
...@@ -137,11 +139,18 @@ ...@@ -137,11 +139,18 @@
} }
} }
setting_save = global.setting_save = function(settings) { setting_save = global.setting_save = function(settings, callback) {
fs.writeFileSync(settings.file, JSON.stringify(settings, null, 2)); if (!callback) {
callback = function(err) {
if (err) {
return log.warn("setting save fail", err.toString());
}
};
}
fs.writeFile(settings.file, JSON.stringify(settings, null, 2), callback);
}; };
setting_change = global.setting_change = function(settings, path, val) { setting_change = global.setting_change = function(settings, path, val, callback) {
var key, target; var key, target;
if (_.isString(val)) { if (_.isString(val)) {
log.info("setting changed", path, val); log.info("setting changed", path, val);
...@@ -158,7 +167,7 @@ ...@@ -158,7 +167,7 @@
key = path.shift(); key = path.shift();
target[key] = val; target[key] = val;
} }
setting_save(settings); setting_save(settings, callback);
}; };
VIP_generate_cdkeys = global.VIP_generate_cdkeys = function(key_type, count) { VIP_generate_cdkeys = global.VIP_generate_cdkeys = function(key_type, count) {
...@@ -683,29 +692,30 @@ ...@@ -683,29 +692,30 @@
ROOM_bad_ip = global.ROOM_bad_ip = {}; ROOM_bad_ip = global.ROOM_bad_ip = {};
ban_user = global.ban_user = function(name) { ban_user = global.ban_user = function(name, callback) {
var bad_ip, len2, len3, m, n, player, ref3, room; var bad_ip;
settings.ban.banned_user.push(name); settings.ban.banned_user.push(name);
setting_save(settings); setting_save(settings);
bad_ip = 0; bad_ip = [];
for (m = 0, len2 = ROOM_all.length; m < len2; m++) { _async.each(ROOM_all, function(room, done) {
room = ROOM_all[m]; if (!(room && room.established)) {
if (room && room.established) { done();
ref3 = room.players; return;
for (n = 0, len3 = ref3.length; n < len3; n++) { }
player = ref3[n]; return _async.each(["players", "watchers"], function(player_type, _done) {
if (player && (player.name === name || player.ip === bad_ip)) { return _async.each(room[player_type], function(player, __done) {
bad_ip = player.ip; if (player && (player.name === name || bad_ip.indexOf(player.ip) !== -1)) {
bad_ip.push(player.ip);
ROOM_bad_ip[bad_ip] = 99; ROOM_bad_ip[bad_ip] = 99;
settings.ban.banned_ip.push(player.ip); settings.ban.banned_ip.push(player.ip);
ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED); ygopro.stoc_send_chat_to_room(room, player.name + " ${kicked_by_system}", ygopro.constants.COLORS.RED);
CLIENT_send_replays(player, room); CLIENT_send_replays(player, room);
CLIENT_kick(player); CLIENT_kick(player);
continue;
} }
} return __done();
} }, _done);
} }, done);
}, callback);
}; };
ROOM_ban_player = global.ROOM_ban_player = function(name, ip, reason, countadd) { ROOM_ban_player = global.ROOM_ban_player = function(name, ip, reason, countadd) {
...@@ -741,6 +751,29 @@ ...@@ -741,6 +751,29 @@
} }
}; };
ROOM_kick = function(name, callback) {
var found;
found = false;
return _async.each(ROOM_all, function(room, done) {
if (!(room && room.established && (name === "all" || name === room.process_pid.toString() || name === room.name))) {
done();
return;
}
found = true;
if (room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN) {
room.scores[room.dueling_players[0].name_vpass] = 0;
room.scores[room.dueling_players[1].name_vpass] = 0;
}
room.kicked = true;
room.send_replays();
room.process.kill();
room["delete"]();
done();
}, function(err) {
callback(null, found);
});
};
ROOM_player_win = global.ROOM_player_win = function(name) { ROOM_player_win = global.ROOM_player_win = function(name) {
if (!ROOM_players_scores[name]) { if (!ROOM_players_scores[name]) {
ROOM_players_scores[name] = { ROOM_players_scores[name] = {
...@@ -2581,7 +2614,7 @@ ...@@ -2581,7 +2614,7 @@
}); });
ygopro.ctos_follow('JOIN_GAME', false, function(buffer, info, client, server, datas) { ygopro.ctos_follow('JOIN_GAME', false, function(buffer, info, client, server, datas) {
var buffer_handle_callback, check_buffer_indentity, len2, len3, len4, len5, line, m, match_permit_callback, n, name, o, p, pre_room, ref3, ref4, ref5, ref6, replay_id, room; var check_buffer_indentity, create_room_with_action, len2, len3, len4, len5, line, m, n, name, o, p, pre_room, ref3, ref4, ref5, ref6, replay_id, room;
info.pass = info.pass.trim(); info.pass = info.pass.trim();
client.pass = info.pass; client.pass = info.pass;
if (CLIENT_is_able_to_reconnect(client) || CLIENT_is_able_to_kick_reconnect(client)) { if (CLIENT_is_able_to_reconnect(client) || CLIENT_is_able_to_kick_reconnect(client)) {
...@@ -2662,7 +2695,7 @@ ...@@ -2662,7 +2695,7 @@
} }
return (checksum & 0xFF) === 0; return (checksum & 0xFF) === 0;
}; };
buffer_handle_callback = function(buffer, decrypted_buffer, match_permit) { create_room_with_action = function(buffer, decrypted_buffer, match_permit) {
var action, len2, len3, len4, len5, line, m, n, name, o, opt1, opt2, opt3, options, p, player, ref3, ref4, ref5, ref6, room, room_title, title; var action, len2, len3, len4, len5, line, m, n, name, o, opt1, opt2, opt3, options, p, player, ref3, ref4, ref5, ref6, room, room_title, title;
if (client.closed) { if (client.closed) {
return; return;
...@@ -2817,81 +2850,107 @@ ...@@ -2817,81 +2850,107 @@
room.connect(client); room.connect(client);
} }
}; };
match_permit_callback = function(buffer, match_permit) { _async.auto({
var decrypted_buffer, i, id, len2, m, ref3, secret; match_permit: function(done) {
if (client.closed) { if (client.closed) {
return; done();
}
if (id = users_cache[client.name]) {
secret = id % 65535 + 1;
decrypted_buffer = Buffer.allocUnsafe(6);
ref3 = [0, 2, 4];
for (m = 0, len2 = ref3.length; m < len2; m++) {
i = ref3[m];
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
}
if (check_buffer_indentity(decrypted_buffer)) {
return buffer_handle_callback(decrypted_buffer, decrypted_buffer, match_permit);
}
}
request({
baseUrl: settings.modules.mycard.auth_base_url,
url: '/users/' + encodeURIComponent(client.name) + '.json',
qs: {
api_key: settings.modules.mycard.auth_key,
api_username: client.name,
skip_track_visit: true
},
json: true
}, function(error, response, body) {
var len3, n, ref4;
if (!error && body && body.user) {
users_cache[client.name] = body.user.id;
secret = body.user.id % 65535 + 1;
decrypted_buffer = Buffer.allocUnsafe(6);
ref4 = [0, 2, 4];
for (n = 0, len3 = ref4.length; n < len3; n++) {
i = ref4[n];
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
}
if (check_buffer_indentity(decrypted_buffer)) {
buffer = decrypted_buffer;
}
} else {
log.warn("READ USER FAIL", error, body);
ygopro.stoc_die(client, "${create_room_failed}");
return; return;
} }
if (!check_buffer_indentity(buffer)) { if (!settings.modules.arena_mode.check_permit) {
ygopro.stoc_die(client, '${invalid_password_checksum}'); done(null, null);
return; return;
} }
return buffer_handle_callback(buffer, decrypted_buffer, match_permit); request({
}); url: settings.modules.arena_mode.check_permit,
}; json: true,
if (settings.modules.arena_mode.check_permit) { qs: {
request({ username: client.name,
url: settings.modules.arena_mode.check_permit, password: info.pass,
json: true, arena: settings.modules.arena_mode.mode
qs: { }
username: client.name, }, function(error, response, body) {
password: info.pass, if (client.closed) {
arena: settings.modules.arena_mode.mode done(null, null);
} return;
}, function(error, response, body) { }
if (!error && body) {
done(null, body);
} else {
log.warn("Match permit request error", error);
match_permit_callback(null, null);
}
});
},
get_user: function(done) {
var decrypted_buffer, i, id, len2, m, ref3, secret;
if (client.closed) { if (client.closed) {
done();
return; return;
} }
if (!error && body) { if (id = users_cache[client.name]) {
match_permit_callback(buffer, body); secret = id % 65535 + 1;
} else { decrypted_buffer = Buffer.allocUnsafe(6);
log.warn("Match permit request error", error); ref3 = [0, 2, 4];
match_permit_callback(buffer, null); for (m = 0, len2 = ref3.length; m < len2; m++) {
i = ref3[m];
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
}
if (check_buffer_indentity(decrypted_buffer)) {
done(null, {
original: decrypted_buffer,
decrypted: decrypted_buffer
});
return;
}
} }
}); request({
} else { baseUrl: settings.modules.mycard.auth_base_url,
match_permit_callback(buffer, null); url: '/users/' + encodeURIComponent(client.name) + '.json',
} qs: {
api_key: settings.modules.mycard.auth_key,
api_username: client.name,
skip_track_visit: true
},
json: true
}, function(error, response, body) {
var len3, n, ref4;
if (!error && body && body.user) {
users_cache[client.name] = body.user.id;
secret = body.user.id % 65535 + 1;
decrypted_buffer = Buffer.allocUnsafe(6);
ref4 = [0, 2, 4];
for (n = 0, len3 = ref4.length; n < len3; n++) {
i = ref4[n];
decrypted_buffer.writeUInt16LE(buffer.readUInt16LE(i) ^ secret, i);
}
if (check_buffer_indentity(decrypted_buffer)) {
buffer = decrypted_buffer;
}
} else {
log.warn("READ USER FAIL", error, body);
done("${create_room_failed}");
return;
}
if (!check_buffer_indentity(buffer)) {
done('${invalid_password_checksum}');
return;
}
done(null, {
original: buffer,
decrypted: decrypted_buffer
});
});
}
}, function(err, data) {
if (client.closed) {
return;
}
if (err) {
ygopro.stoc_die(client, err);
return;
}
return create_room_with_action(data.get_user.original, data.get_user.decrypted, data.match_permit);
});
} else if (settings.modules.challonge.enabled) { } else if (settings.modules.challonge.enabled) {
pre_room = ROOM_find_by_name(info.pass); pre_room = ROOM_find_by_name(info.pass);
if (pre_room && pre_room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && settings.modules.cloud_replay.enable_halfway_watch && !pre_room.hostinfo.no_watch) { if (pre_room && pre_room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && settings.modules.cloud_replay.enable_halfway_watch && !pre_room.hostinfo.no_watch) {
...@@ -2910,113 +2969,107 @@ ...@@ -2910,113 +2969,107 @@
} else { } else {
ygopro.stoc_send_chat(client, '${loading_user_info}', ygopro.constants.COLORS.BABYBLUE); ygopro.stoc_send_chat(client, '${loading_user_info}', ygopro.constants.COLORS.BABYBLUE);
client.setTimeout(300000); client.setTimeout(300000);
challonge.participants._index({ _async.auto({
id: settings.modules.challonge.tournament_id, participant_data: function(done) {
callback: function(err, data) { challonge.participants._index({
var found, user; id: settings.modules.challonge.tournament_id,
if (client.closed) { callback: done
return; });
},
match_data: function(done) {
challonge.matches._index({
id: settings.modules.challonge.tournament_id,
callback: done
});
}
}, function(err, datas) {
var found, len3, len4, len5, len6, line, match, n, o, p, player, q, ref4, ref5, ref6, ref7, ref8, ref9, user;
if (client.closed) {
return;
}
if (err || !datas.participant_data || !datas.match_data) {
log.warn("Failed loading Challonge user info", err);
ygopro.stoc_die(client, '${challonge_match_load_failed}');
return;
}
found = false;
ref4 = datas.participant_data;
for (k in ref4) {
user = ref4[k];
if (user.participant && user.participant.name && deck_name_match(user.participant.name, client.name)) {
found = user.participant;
break;
} }
if (err || !data) { }
if (err) { if (!found) {
log.warn("Failed loading Challonge user info", err); ygopro.stoc_die(client, '${challonge_user_not_found}');
} return;
ygopro.stoc_die(client, '${challonge_match_load_failed}'); }
return; client.challonge_info = found;
found = false;
ref5 = datas.match_data;
for (k in ref5) {
match = ref5[k];
if (match && match.match && !match.match.winnerId && match.match.state !== "complete" && match.match.player1Id && match.match.player2Id && (match.match.player1Id === client.challonge_info.id || match.match.player2Id === client.challonge_info.id)) {
found = match.match;
break;
} }
found = false; }
for (k in data) { if (!found) {
user = data[k]; ygopro.stoc_die(client, '${challonge_match_not_found}');
if (user.participant && user.participant.name && deck_name_match(user.participant.name, client.name)) { return;
found = user.participant; }
break; room = ROOM_find_or_create_by_name('M#' + found.id);
if (room) {
room.challonge_info = found;
room.welcome = "${challonge_match_created}";
}
if (!room) {
ygopro.stoc_die(client, "${server_full}");
} else if (room.error) {
ygopro.stoc_die(client, room.error);
} else if (room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN) {
if (settings.modules.cloud_replay.enable_halfway_watch && !room.hostinfo.no_watch) {
client.rid = _.indexOf(ROOM_all, room);
client.is_post_watcher = true;
if (settings.modules.vip.enabled && client.vip && vip_info.players[client.name].words) {
ref6 = _.lines(vip_info.players[client.name].words);
for (n = 0, len3 = ref6.length; n < len3; n++) {
line = ref6[n];
ygopro.stoc_send_chat_to_room(room, line, ygopro.constants.COLORS.PINK);
}
} else if (settings.modules.words.enabled && words.words[client.name]) {
ref7 = _.lines(words.words[client.name][Math.floor(Math.random() * words.words[client.name].length)]);
for (o = 0, len4 = ref7.length; o < len4; o++) {
line = ref7[o];
ygopro.stoc_send_chat_to_room(room, line, ygopro.constants.COLORS.PINK);
}
} }
ygopro.stoc_send_chat_to_room(room, client.name + " ${watch_join}");
room.watchers.push(client);
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
ref8 = room.watcher_buffers;
for (p = 0, len5 = ref8.length; p < len5; p++) {
buffer = ref8[p];
client.write(buffer);
}
} else {
ygopro.stoc_die(client, "${watch_denied}");
} }
if (!found) { } else if (room.hostinfo.no_watch && room.players.length >= (room.hostinfo.mode === 2 ? 4 : 2)) {
ygopro.stoc_die(client, '${challonge_user_not_found}'); ygopro.stoc_die(client, "${watch_denied_room}");
} else {
ref9 = room.get_playing_player();
for (q = 0, len6 = ref9.length; q < len6; q++) {
player = ref9[q];
if (!(player && player !== client && player.challonge_info.id === client.challonge_info.id)) {
continue;
}
ygopro.stoc_die(client, "${challonge_player_already_in}");
return; return;
} }
client.challonge_info = found; client.rid = _.indexOf(ROOM_all, room);
challonge.matches._index({ room.connect(client);
id: settings.modules.challonge.tournament_id,
callback: function(err, data) {
var len3, len4, len5, len6, line, match, n, o, p, player, q, ref4, ref5, ref6, ref7;
if (client.closed) {
return;
}
if (err || !data) {
if (err) {
log.warn("Failed loading Challonge match info", err);
}
ygopro.stoc_die(client, '${challonge_match_load_failed}');
return;
}
found = false;
for (k in data) {
match = data[k];
if (match && match.match && !match.match.winnerId && match.match.state !== "complete" && match.match.player1Id && match.match.player2Id && (match.match.player1Id === client.challonge_info.id || match.match.player2Id === client.challonge_info.id)) {
found = match.match;
break;
}
}
if (!found) {
ygopro.stoc_die(client, '${challonge_match_not_found}');
return;
}
room = ROOM_find_or_create_by_name('M#' + found.id);
if (room) {
room.challonge_info = found;
room.welcome = "${challonge_match_created}";
}
if (!room) {
ygopro.stoc_die(client, "${server_full}");
} else if (room.error) {
ygopro.stoc_die(client, room.error);
} else if (room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN) {
if (settings.modules.cloud_replay.enable_halfway_watch && !room.hostinfo.no_watch) {
client.rid = _.indexOf(ROOM_all, room);
client.is_post_watcher = true;
if (settings.modules.vip.enabled && client.vip && vip_info.players[client.name].words) {
ref4 = _.lines(vip_info.players[client.name].words);
for (n = 0, len3 = ref4.length; n < len3; n++) {
line = ref4[n];
ygopro.stoc_send_chat_to_room(room, line, ygopro.constants.COLORS.PINK);
}
} else if (settings.modules.words.enabled && words.words[client.name]) {
ref5 = _.lines(words.words[client.name][Math.floor(Math.random() * words.words[client.name].length)]);
for (o = 0, len4 = ref5.length; o < len4; o++) {
line = ref5[o];
ygopro.stoc_send_chat_to_room(room, line, ygopro.constants.COLORS.PINK);
}
}
ygopro.stoc_send_chat_to_room(room, client.name + " ${watch_join}");
room.watchers.push(client);
ygopro.stoc_send_chat(client, "${watch_watching}", ygopro.constants.COLORS.BABYBLUE);
ref6 = room.watcher_buffers;
for (p = 0, len5 = ref6.length; p < len5; p++) {
buffer = ref6[p];
client.write(buffer);
}
} else {
ygopro.stoc_die(client, "${watch_denied}");
}
} else if (room.hostinfo.no_watch && room.players.length >= (room.hostinfo.mode === 2 ? 4 : 2)) {
ygopro.stoc_die(client, "${watch_denied_room}");
} else {
ref7 = room.get_playing_player();
for (q = 0, len6 = ref7.length; q < len6; q++) {
player = ref7[q];
if (!(player && player !== client && player.challonge_info.id === client.challonge_info.id)) {
continue;
}
ygopro.stoc_die(client, "${challonge_player_already_in}");
return;
}
client.rid = _.indexOf(ROOM_all, room);
room.connect(client);
}
}
});
} }
}); });
} }
...@@ -3205,7 +3258,7 @@ ...@@ -3205,7 +3258,7 @@
} }
}); });
load_words = global.load_words = function() { load_words = global.load_words = function(callback) {
request({ request({
url: settings.modules.words.get, url: settings.modules.words.get,
json: true json: true
...@@ -3218,6 +3271,9 @@ ...@@ -3218,6 +3271,9 @@
setting_change(words, "words", body); setting_change(words, "words", body);
log.info("words loaded", _.size(words.words)); log.info("words loaded", _.size(words.words));
} }
if (callback) {
callback(error, body);
}
}); });
}; };
...@@ -3225,7 +3281,7 @@ ...@@ -3225,7 +3281,7 @@
load_words(); load_words();
} }
load_dialogues = global.load_dialogues = function() { load_dialogues = global.load_dialogues = function(callback) {
request({ request({
url: settings.modules.dialogues.get, url: settings.modules.dialogues.get,
json: true json: true
...@@ -3238,10 +3294,13 @@ ...@@ -3238,10 +3294,13 @@
setting_change(dialogues, "dialogues", body); setting_change(dialogues, "dialogues", body);
log.info("dialogues loaded", _.size(dialogues.dialogues)); log.info("dialogues loaded", _.size(dialogues.dialogues));
} }
if (callback) {
callback(error, body);
}
}); });
}; };
load_dialogues_custom = global.load_dialogues_custom = function() { load_dialogues_custom = global.load_dialogues_custom = function(callback) {
request({ request({
url: settings.modules.dialogues.get_custom, url: settings.modules.dialogues.get_custom,
json: true json: true
...@@ -3254,6 +3313,9 @@ ...@@ -3254,6 +3313,9 @@
setting_change(dialogues, "dialogues_custom", body); setting_change(dialogues, "dialogues_custom", body);
log.info("custom dialogues loaded", _.size(dialogues.dialogues_custom)); log.info("custom dialogues loaded", _.size(dialogues.dialogues_custom));
} }
if (callback) {
callback(error, body);
}
}); });
}; };
...@@ -3914,7 +3976,7 @@ ...@@ -3914,7 +3976,7 @@
} }
}; };
load_tips = global.load_tips = function() { load_tips = global.load_tips = function(callback) {
request({ request({
url: settings.modules.tips.get, url: settings.modules.tips.get,
json: true json: true
...@@ -3927,10 +3989,13 @@ ...@@ -3927,10 +3989,13 @@
setting_change(tips, "tips", body); setting_change(tips, "tips", body);
log.info("tips loaded", tips.tips.length); log.info("tips loaded", tips.tips.length);
} }
if (callback) {
callback(error, body);
}
}); });
}; };
load_tips_zh = global.load_tips_zh = function() { load_tips_zh = global.load_tips_zh = function(callback) {
request({ request({
url: settings.modules.tips.get_zh, url: settings.modules.tips.get_zh,
json: true json: true
...@@ -3943,6 +4008,9 @@ ...@@ -3943,6 +4008,9 @@
setting_change(tips, "tips_zh", body); setting_change(tips, "tips_zh", body);
log.info("zh tips loaded", tips.tips_zh.length); log.info("zh tips loaded", tips.tips_zh.length);
} }
if (callback) {
callback(error, body);
}
}); });
}; };
...@@ -4908,11 +4976,11 @@ ...@@ -4908,11 +4976,11 @@
if (settings.modules.random_duel.enabled) { if (settings.modules.random_duel.enabled) {
setInterval(function() { setInterval(function() {
var len2, m, room, time_passed; _async.each(ROOM_all, function(room, done) {
for (m = 0, len2 = ROOM_all.length; m < len2; m++) { var time_passed;
room = ROOM_all[m];
if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.random_type && room.last_active_time && room.waiting_for_player && room.get_disconnected_count() === 0 && (!settings.modules.side_timeout || room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING))) { if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.random_type && room.last_active_time && room.waiting_for_player && room.get_disconnected_count() === 0 && (!settings.modules.side_timeout || room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING))) {
continue; done();
return;
} }
time_passed = Math.floor((moment() - room.last_active_time) / 1000); time_passed = Math.floor((moment() - room.last_active_time) / 1000);
if (time_passed >= settings.modules.random_duel.hang_timeout) { if (time_passed >= settings.modules.random_duel.hang_timeout) {
...@@ -4926,17 +4994,18 @@ ...@@ -4926,17 +4994,18 @@
ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${afk_warn_part1}" + (settings.modules.random_duel.hang_timeout - time_passed) + "${afk_warn_part2}", ygopro.constants.COLORS.RED); ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${afk_warn_part1}" + (settings.modules.random_duel.hang_timeout - time_passed) + "${afk_warn_part2}", ygopro.constants.COLORS.RED);
ROOM_unwelcome(room, room.waiting_for_player, "${random_ban_reason_AFK}"); ROOM_unwelcome(room, room.waiting_for_player, "${random_ban_reason_AFK}");
} }
} done();
});
}, 1000); }, 1000);
} }
if (settings.modules.mycard.enabled) { if (settings.modules.mycard.enabled) {
setInterval(function() { setInterval(function() {
var len2, len3, m, n, player, room, time_passed, waited_time; _async.each(ROOM_all, function(room, done) {
for (m = 0, len2 = ROOM_all.length; m < len2; m++) { var time_passed;
room = ROOM_all[m];
if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.arena && room.last_active_time && room.waiting_for_player && room.get_disconnected_count() === 0 && (!settings.modules.side_timeout || room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING))) { if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.arena && room.last_active_time && room.waiting_for_player && room.get_disconnected_count() === 0 && (!settings.modules.side_timeout || room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING))) {
continue; done();
return;
} }
time_passed = Math.floor((moment() - room.last_active_time) / 1000); time_passed = Math.floor((moment() - room.last_active_time) / 1000);
if (time_passed >= settings.modules.random_duel.hang_timeout) { if (time_passed >= settings.modules.random_duel.hang_timeout) {
...@@ -4948,12 +5017,14 @@ ...@@ -4948,12 +5017,14 @@
} else if (time_passed >= (settings.modules.random_duel.hang_timeout - 20) && !(time_passed % 10)) { } else if (time_passed >= (settings.modules.random_duel.hang_timeout - 20) && !(time_passed % 10)) {
ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${afk_warn_part1}" + (settings.modules.random_duel.hang_timeout - time_passed) + "${afk_warn_part2}", ygopro.constants.COLORS.RED); ygopro.stoc_send_chat_to_room(room, room.waiting_for_player.name + " ${afk_warn_part1}" + (settings.modules.random_duel.hang_timeout - time_passed) + "${afk_warn_part2}", ygopro.constants.COLORS.RED);
} }
} done();
});
if (settings.modules.arena_mode.punish_quit_before_match) { if (settings.modules.arena_mode.punish_quit_before_match) {
for (n = 0, len3 = ROOM_all.length; n < len3; n++) { _async.each(ROOM_all, function(room, done) {
room = ROOM_all[n]; var player, waited_time;
if (!(room && room.arena && room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && room.get_playing_player().length < 2)) { if (!(room && room.arena && room.duel_stage === ygopro.constants.DUEL_STAGE.BEGIN && room.get_playing_player().length < 2)) {
continue; done();
return;
} }
player = room.get_playing_player()[0]; player = room.get_playing_player()[0];
if (player && player.join_time && !player.arena_quit_free) { if (player && player.join_time && !player.arena_quit_free) {
...@@ -4965,42 +5036,39 @@ ...@@ -4965,42 +5036,39 @@
ygopro.stoc_send_chat(player, "${arena_wait_hint}", ygopro.constants.COLORS.BABYBLUE); ygopro.stoc_send_chat(player, "${arena_wait_hint}", ygopro.constants.COLORS.BABYBLUE);
} }
} }
} done();
});
} }
}, 1000); }, 1000);
} }
if (settings.modules.heartbeat_detection.enabled) { if (settings.modules.heartbeat_detection.enabled) {
setInterval(function() { setInterval(function() {
var len2, len3, m, n, player, ref3, room; _async.each(ROOM_all, function(room, done) {
for (m = 0, len2 = ROOM_all.length; m < len2; m++) {
room = ROOM_all[m];
if (room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && (room.hostinfo.time_limit === 0 || room.duel_stage !== ygopro.constants.DUEL_STAGE.DUELING) && !room.windbot) { if (room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && (room.hostinfo.time_limit === 0 || room.duel_stage !== ygopro.constants.DUEL_STAGE.DUELING) && !room.windbot) {
ref3 = room.get_playing_player(); return _async.each(room.get_playing_player(), function(player, _done) {
for (n = 0, len3 = ref3.length; n < len3; n++) {
player = ref3[n];
if (player && (room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING || player.selected_preduel)) { if (player && (room.duel_stage !== ygopro.constants.DUEL_STAGE.SIDING || player.selected_preduel)) {
CLIENT_heartbeat_register(player, true); CLIENT_heartbeat_register(player, true);
} }
} return _done();
}, done);
} else {
return done();
} }
} });
}, settings.modules.heartbeat_detection.interval); }, settings.modules.heartbeat_detection.interval);
} }
setInterval(function() { setInterval(function() {
var current_time, len2, m, results, room; var current_time;
current_time = moment(); current_time = moment();
results = []; return _async.each(ROOM_all, function(room, done) {
for (m = 0, len2 = ROOM_all.length; m < len2; m++) { if (room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.hostinfo.auto_death && !room.auto_death_triggered && current_time - moment(room.start_time) > 60000 * room.hostinfo.auto_death) {
room = ROOM_all[m]; room.auto_death_triggered = true;
if (!(room && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && room.hostinfo.auto_death && !room.auto_death_triggered && current_time - moment(room.start_time) > 60000 * room.hostinfo.auto_death)) { room.start_death();
continue;
} }
room.auto_death_triggered = true; return done();
results.push(room.start_death()); });
}
return results;
}, 1000); }, 1000);
windbot_looplimit = 0; windbot_looplimit = 0;
...@@ -5023,14 +5091,14 @@ ...@@ -5023,14 +5091,14 @@
}); });
windbot_process.on('error', function(err) { windbot_process.on('error', function(err) {
log.warn('WindBot ERROR', err); log.warn('WindBot ERROR', err);
if (windbot_looplimit < 1000 && !rebooted) { if (windbot_looplimit < 1000 && !global.rebooted) {
windbot_looplimit++; windbot_looplimit++;
spawn_windbot(); spawn_windbot();
} }
}); });
windbot_process.on('exit', function(code) { windbot_process.on('exit', function(code) {
log.warn('WindBot EXIT', code); log.warn('WindBot EXIT', code);
if (windbot_looplimit < 1000 && !rebooted) { if (windbot_looplimit < 1000 && !global.rebooted) {
windbot_looplimit++; windbot_looplimit++;
spawn_windbot(); spawn_windbot();
} }
...@@ -5049,7 +5117,7 @@ ...@@ -5049,7 +5117,7 @@
spawn_windbot(); spawn_windbot();
} }
rebooted = false; global.rebooted = false;
if (settings.modules.http) { if (settings.modules.http) {
addCallback = function(callback, text) { addCallback = function(callback, text) {
...@@ -5059,58 +5127,58 @@ ...@@ -5059,58 +5127,58 @@
return callback + "( " + text + " );"; return callback + "( " + text + " );";
}; };
requestListener = function(request, response) { requestListener = function(request, response) {
var archive_args, archive_name, archive_process, check, death_room_found, duellog, error, filename, getpath, key, kick_room_found, len2, len3, len4, len5, len6, len7, len8, m, n, o, p, parseQueryString, pass_validated, player, q, r, ref3, ref4, replay, ret_keys, room, roomsjson, s, u; var archive_args, archive_name, archive_process, check, death_room_found, duellog, error, filename, getpath, key, len2, len3, len4, m, n, o, parseQueryString, pass_validated, ref3, ref4, replay, ret_keys, room, roomsjson, tasks, u;
parseQueryString = true; parseQueryString = true;
u = url.parse(request.url, parseQueryString); u = url.parse(request.url, parseQueryString);
if (u.pathname === '/api/getrooms') { if (u.pathname === '/api/getrooms') {
pass_validated = auth.auth(u.query.username, u.query.pass, "get_rooms", "get_rooms"); pass_validated = auth.auth(u.query.username, u.query.pass, "get_rooms", "get_rooms", true);
if (!settings.modules.http.public_roomlist && !pass_validated) { if (!settings.modules.http.public_roomlist && !pass_validated) {
response.writeHead(200); response.writeHead(200);
response.end(addCallback(u.query.callback, '{"rooms":[{"roomid":"0","roomname":"密码错误","needpass":"true"}]}')); response.end(addCallback(u.query.callback, '{"rooms":[{"roomid":"0","roomname":"密码错误","needpass":"true"}]}'));
} else { } else {
response.writeHead(200); roomsjson = [];
roomsjson = JSON.stringify({ _async.each(ROOM_all, function(room, done) {
rooms: (function() { var player;
var len2, m, results; if (!(room && room.established)) {
results = []; done();
for (m = 0, len2 = ROOM_all.length; m < len2; m++) { return;
room = ROOM_all[m]; }
if (room && room.established) { roomsjson.push({
results.push({ roomid: room.process_pid.toString(),
roomid: room.process_pid.toString(), roomname: pass_validated ? room.name : room.name.split('$', 2)[0],
roomname: pass_validated ? room.name : room.name.split('$', 2)[0], roommode: room.hostinfo.mode,
roommode: room.hostinfo.mode, needpass: (room.name.indexOf('$') !== -1).toString(),
needpass: (room.name.indexOf('$') !== -1).toString(), users: _.sortBy((function() {
users: _.sortBy((function() { var len2, m, ref3, results;
var len3, n, ref3, results1; ref3 = room.players;
ref3 = room.players; results = [];
results1 = []; for (m = 0, len2 = ref3.length; m < len2; m++) {
for (n = 0, len3 = ref3.length; n < len3; n++) { player = ref3[m];
player = ref3[n]; if (player.pos != null) {
if (player.pos != null) { results.push({
results1.push({ id: (-1).toString(),
id: (-1).toString(), name: player.name,
name: player.name, ip: settings.modules.http.show_ip && pass_validated && !player.is_local ? player.ip.slice(7) : null,
ip: settings.modules.http.show_ip && pass_validated && !player.is_local ? player.ip.slice(7) : null, status: settings.modules.http.show_info && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && player.pos !== 7 ? {
status: settings.modules.http.show_info && room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN && player.pos !== 7 ? { score: room.scores[player.name_vpass],
score: room.scores[player.name_vpass], lp: player.lp != null ? player.lp : room.hostinfo.start_lp,
lp: player.lp != null ? player.lp : room.hostinfo.start_lp, cards: room.hostinfo.mode !== 2 ? (player.card_count != null ? player.card_count : room.hostinfo.start_hand) : null
cards: room.hostinfo.mode !== 2 ? (player.card_count != null ? player.card_count : room.hostinfo.start_hand) : null } : null,
} : null, pos: player.pos
pos: player.pos });
}); }
}
}
return results1;
})(), "pos"),
istart: room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN ? (settings.modules.http.show_info ? "Duel:" + room.duel_count + " " + (room.duel_stage === ygopro.constants.DUEL_STAGE.SIDING ? "Siding" : "Turn:" + (room.turn != null ? room.turn : 0) + (room.death ? "/" + (room.death > 0 ? room.death - 1 : "Death") : "")) : 'start') : 'wait'
});
} }
} return results;
return results; })(), "pos"),
})() istart: room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN ? (settings.modules.http.show_info ? "Duel:" + room.duel_count + " " + (room.duel_stage === ygopro.constants.DUEL_STAGE.SIDING ? "Siding" : "Turn:" + (room.turn != null ? room.turn : 0) + (room.death ? "/" + (room.death > 0 ? room.death - 1 : "Death") : "")) : 'start') : 'wait'
}, null, 2); });
response.end(addCallback(u.query.callback, roomsjson)); return done();
}, function() {
response.writeHead(200);
return response.end(addCallback(u.query.callback, JSON.stringify({
rooms: roomsjson
})));
});
} }
} else if (u.pathname === '/api/duellog' && settings.modules.tournament_mode.enabled) { } else if (u.pathname === '/api/duellog' && settings.modules.tournament_mode.enabled) {
if (!auth.auth(u.query.username, u.query.pass, "duel_log", "duel_log")) { if (!auth.auth(u.query.username, u.query.pass, "duel_log", "duel_log")) {
...@@ -5276,18 +5344,28 @@ ...@@ -5276,18 +5344,28 @@
if (u.query.stop === 'false') { if (u.query.stop === 'false') {
u.query.stop = false; u.query.stop = false;
} }
setting_change(settings, 'modules:stop', u.query.stop); setting_change(settings, 'modules:stop', u.query.stop, function(err) {
response.writeHead(200); response.writeHead(200);
response.end(addCallback(u.query.callback, "['stop ok', '" + u.query.stop + "']")); if (err) {
return response.end(addCallback(u.query.callback, "['stop fail', '" + u.query.stop + "']"));
} else {
return response.end(addCallback(u.query.callback, "['stop ok', '" + u.query.stop + "']"));
}
});
} else if (u.query.welcome) { } else if (u.query.welcome) {
if (!auth.auth(u.query.username, u.query.pass, "change_settings", "change_welcome")) { if (!auth.auth(u.query.username, u.query.pass, "change_settings", "change_welcome")) {
response.writeHead(200); response.writeHead(200);
response.end(addCallback(u.query.callback, "['密码错误', 0]")); response.end(addCallback(u.query.callback, "['密码错误', 0]"));
return; return;
} }
setting_change(settings, 'modules:welcome', u.query.welcome); setting_change(settings, 'modules:welcome', function(err) {
response.writeHead(200); response.writeHead(200);
response.end(addCallback(u.query.callback, "['welcome ok', '" + u.query.welcome + "']")); if (err) {
return response.end(addCallback(u.query.callback, "['welcome fail', '" + u.query.welcome + "']"));
} else {
return response.end(addCallback(u.query.callback, "['welcome ok', '" + u.query.welcome + "']"));
}
});
} else if (u.query.getwelcome) { } else if (u.query.getwelcome) {
if (!auth.auth(u.query.username, u.query.pass, "change_settings", "get_welcome")) { if (!auth.auth(u.query.username, u.query.pass, "change_settings", "get_welcome")) {
response.writeHead(200); response.writeHead(200);
...@@ -5302,65 +5380,70 @@ ...@@ -5302,65 +5380,70 @@
response.end(addCallback(u.query.callback, "['密码错误', 0]")); response.end(addCallback(u.query.callback, "['密码错误', 0]"));
return; return;
} }
load_tips(); tasks = {
tips: load_tips
};
if (settings.modules.tips.get_zh) { if (settings.modules.tips.get_zh) {
load_tips_zh(); tasks.tips_zh = load_tips_zh;
} }
response.writeHead(200); _async.auto(tasks, function(err) {
response.end(addCallback(u.query.callback, "['loading tip', '" + settings.modules.tips.get + (settings.modules.tips.get_zh ? " and " + settings.modules.tips.get_zh : "") + "']")); response.writeHead(200);
if (err) {
return response.end(addCallback(u.query.callback, "['tip fail', '" + settings.modules.tips.get + "']"));
} else {
return response.end(addCallback(u.query.callback, "['tip ok', '" + settings.modules.tips.get + "']"));
}
});
} else if (u.query.loaddialogues) { } else if (u.query.loaddialogues) {
if (!auth.auth(u.query.username, u.query.pass, "change_settings", "change_dialogues")) { if (!auth.auth(u.query.username, u.query.pass, "change_settings", "change_dialogues")) {
response.writeHead(200); response.writeHead(200);
response.end(addCallback(u.query.callback, "['密码错误', 0]")); response.end(addCallback(u.query.callback, "['密码错误', 0]"));
return; return;
} }
load_dialogues(); tasks = {
dialogues: load_dialogues
};
if (settings.modules.dialogues.get_custom) { if (settings.modules.dialogues.get_custom) {
load_dialogues_custom(); tasks.dialogues_custom = load_dialogues_custom;
} }
response.writeHead(200); _async.auto(tasks, function(err) {
response.end(addCallback(u.query.callback, "['loading dialogues', '" + settings.modules.dialogues.get + (settings.modules.dialogues.get_custom ? " and " + settings.modules.dialogues.get_custom : "") + "']")); response.writeHead(200);
} else if (u.query.loadwords) { if (err) {
load_words(); return response.end(addCallback(u.query.callback, "['dialogues fail', '" + settings.modules.dialogues.get + "']"));
response.writeHead(200); } else {
response.end(addCallback(u.query.callback, "['loading words', '" + settings.modules.words.get + "']")); return response.end(addCallback(u.query.callback, "['dialogues ok', '" + settings.modules.dialogues.get + "']"));
}
});
} else if (u.query.ban) { } else if (u.query.ban) {
if (!auth.auth(u.query.username, u.query.pass, "ban_user", "ban_user")) { if (!auth.auth(u.query.username, u.query.pass, "ban_user", "ban_user")) {
response.writeHead(200); response.writeHead(200);
response.end(addCallback(u.query.callback, "['密码错误', 0]")); response.end(addCallback(u.query.callback, "['密码错误', 0]"));
return; return;
} }
ban_user(u.query.ban); ban_user(u.query.ban, function(err) {
response.writeHead(200); response.writeHead(200);
response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']")); if (err) {
return response.end(addCallback(u.query.callback, "['ban fail', '" + u.query.ban + "']"));
} else {
return response.end(addCallback(u.query.callback, "['ban ok', '" + u.query.ban + "']"));
}
});
} else if (u.query.kick) { } else if (u.query.kick) {
if (!auth.auth(u.query.username, u.query.pass, "kick_user", "kick_user")) { if (!auth.auth(u.query.username, u.query.pass, "kick_user", "kick_user")) {
response.writeHead(200); response.writeHead(200);
response.end(addCallback(u.query.callback, "['密码错误', 0]")); response.end(addCallback(u.query.callback, "['密码错误', 0]"));
return; return;
} }
kick_room_found = false; ROOM_kick(u.query.kick, function(err, found) {
for (p = 0, len5 = ROOM_all.length; p < len5; p++) { response.writeHead(200);
room = ROOM_all[p]; if (err) {
if (!(room && room.established && (u.query.kick === "all" || u.query.kick === room.process_pid.toString() || u.query.kick === room.name))) { return response.end(addCallback(u.query.callback, "['kick fail', '" + u.query.kick + "']"));
continue; } else if (found) {
} return response.end(addCallback(u.query.callback, "['kick ok', '" + u.query.kick + "']"));
kick_room_found = true; } else {
if (room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN) { return response.end(addCallback(u.query.callback, "['room not found', '" + u.query.kick + "']"));
room.scores[room.dueling_players[0].name_vpass] = 0;
room.scores[room.dueling_players[1].name_vpass] = 0;
} }
room.kicked = true; });
room.send_replays();
room.process.kill();
room["delete"]();
}
response.writeHead(200);
if (kick_room_found) {
response.end(addCallback(u.query.callback, "['kick ok', '" + u.query.kick + "']"));
} else {
response.end(addCallback(u.query.callback, "['room not found', '" + u.query.kick + "']"));
}
} else if (u.query.death) { } else if (u.query.death) {
if (!auth.auth(u.query.username, u.query.pass, "start_death", "start_death")) { if (!auth.auth(u.query.username, u.query.pass, "start_death", "start_death")) {
response.writeHead(200); response.writeHead(200);
...@@ -5368,20 +5451,23 @@ ...@@ -5368,20 +5451,23 @@
return; return;
} }
death_room_found = false; death_room_found = false;
for (q = 0, len6 = ROOM_all.length; q < len6; q++) { _async.each(ROOM_all, function(room, done) {
room = ROOM_all[q]; if (!(room && (u.query.death === "all" || u.query.death === room.process_pid.toString() || u.query.death === room.name))) {
if (room && (u.query.death === "all" || u.query.death === room.process_pid.toString() || u.query.death === room.name)) { done();
if (room.start_death()) { return;
death_room_found = true;
}
} }
} if (room.start_death()) {
response.writeHead(200); death_room_found = true;
if (death_room_found) { }
response.end(addCallback(u.query.callback, "['death ok', '" + u.query.death + "']")); done();
} else { }, function() {
response.end(addCallback(u.query.callback, "['room not found', '" + u.query.death + "']")); response.writeHead(200);
} if (death_room_found) {
return response.end(addCallback(u.query.callback, "['death ok', '" + u.query.death + "']"));
} else {
return response.end(addCallback(u.query.callback, "['room not found', '" + u.query.death + "']"));
}
});
} else if (u.query.deathcancel) { } else if (u.query.deathcancel) {
if (!auth.auth(u.query.username, u.query.pass, "start_death", "cancel_death")) { if (!auth.auth(u.query.username, u.query.pass, "start_death", "cancel_death")) {
response.writeHead(200); response.writeHead(200);
...@@ -5389,47 +5475,38 @@ ...@@ -5389,47 +5475,38 @@
return; return;
} }
death_room_found = false; death_room_found = false;
for (r = 0, len7 = ROOM_all.length; r < len7; r++) { _async.each(rooms, function(room, done) {
room = ROOM_all[r]; if (!(room && (u.query.deathcancel === "all" || u.query.deathcancel === room.process_pid.toString() || u.query.deathcancel === room.name))) {
if (room && (u.query.deathcancel === "all" || u.query.deathcancel === room.process_pid.toString() || u.query.deathcancel === room.name)) { done();
if (room.cancel_death()) { return;
death_room_found = true;
}
} }
} if (room.cancel_death()) {
response.writeHead(200); death_room_found = true;
if (death_room_found) { }
response.end(addCallback(u.query.callback, "['death cancel ok', '" + u.query.deathcancel + "']")); return done();
} else { }, function() {
response.end(addCallback(u.query.callback, "['room not found', '" + u.query.deathcancel + "']")); response.writeHead(200);
} if (death_room_found) {
return response.end(addCallback(u.query.callback, "['death cancel ok', '" + u.query.deathcancel + "']"));
} else {
return response.end(addCallback(u.query.callback, "['room not found', '" + u.query.deathcancel + "']"));
}
});
} else if (u.query.reboot) { } else if (u.query.reboot) {
if (!auth.auth(u.query.username, u.query.pass, "stop", "reboot")) { if (!auth.auth(u.query.username, u.query.pass, "stop", "reboot")) {
response.writeHead(200); response.writeHead(200);
response.end(addCallback(u.query.callback, "['密码错误', 0]")); response.end(addCallback(u.query.callback, "['密码错误', 0]"));
return; return;
} }
for (s = 0, len8 = ROOM_all.length; s < len8; s++) { ROOM_kick("all", function(err, found) {
room = ROOM_all[s]; global.rebooted = true;
if (!(room)) { if (windbot_process) {
continue; windbot_process.kill();
}
if (room.duel_stage !== ygopro.constants.DUEL_STAGE.BEGIN) {
room.scores[room.dueling_players[0].name_vpass] = 0;
room.scores[room.dueling_players[1].name_vpass] = 0;
} }
room.kicked = true; response.writeHead(200);
room.send_replays(); response.end(addCallback(u.query.callback, "['reboot ok', '" + u.query.reboot + "']"));
room.process.kill(); return process.exit();
room["delete"](); });
}
rebooted = true;
if (windbot_process) {
windbot_process.kill();
}
response.writeHead(200);
response.end(addCallback(u.query.callback, "['reboot ok', '" + u.query.reboot + "']"));
throw "rebooted";
} else if (u.query.generatekey && settings.modules.vip.enabled) { } else if (u.query.generatekey && settings.modules.vip.enabled) {
if (!auth.auth(u.query.username, u.query.pass, "vip", "generate_keys")) { if (!auth.auth(u.query.username, u.query.pass, "vip", "generate_keys")) {
response.writeHead(200); response.writeHead(200);
......
...@@ -28,6 +28,9 @@ var challonge; ...@@ -28,6 +28,9 @@ var challonge;
if (challonge_config.enabled) { if (challonge_config.enabled) {
challonge = require('challonge').createClient(challonge_config.options); challonge = require('challonge').createClient(challonge_config.options);
} }
let _async = require("async");
const os = require("os");
const PROCESS_COUNT = os.cpus().length;
//http长连接 //http长连接
var responder; var responder;
...@@ -95,7 +98,7 @@ var readDeck = function(deck_name, deck_full_path) { ...@@ -95,7 +98,7 @@ var readDeck = function(deck_name, deck_full_path) {
} }
//读取指定文件夹中所有卡组 //读取指定文件夹中所有卡组
var getDecks = function() { var getDecks = function(callback) {
var decks=[]; var decks=[];
var decks_list = fs.readdirSync(config.deck_path); var decks_list = fs.readdirSync(config.deck_path);
for (var k in decks_list) { for (var k in decks_list) {
...@@ -105,34 +108,43 @@ var getDecks = function() { ...@@ -105,34 +108,43 @@ var getDecks = function() {
decks.push(deck); decks.push(deck);
} }
} }
return decks; _async.auto({
readDir: (done) => {
fs.readdir(config.deck_path, done);
},
handleDecks: ["readDir", (results, done) => {
const decks_list = results.readDir;
_async.each(decks_list, (deck_name, _done) => {
if (_.endsWith(deck_name, ".ydk")) {
var deck = readDeck(deck_name, config.deck_path + deck_name);
decks.push(deck);
}
}, done)
}]
}, callback);
} }
var delDeck = function(deck_name) { var delDeck = function (deck_name, callback) {
var result=0; if (deck_name.startsWith("../") || deck_name.contains("/../")) { //security issue
try { callback("Invalid deck");
fs.unlinkSync(config.deck_path+deck_name);
result="已删除"+deck_name+"";
}
catch(e) {
result=e.toString();
}
finally {
return result;
} }
fs.unlink(config.deck_path + deck_name, callback);
} }
var clearDecks = function() { var clearDecks = function (callback) {
var decks_list = fs.readdirSync(config.deck_path); _async.auto({
for (var k in decks_list) { deckList: (done) => {
var deck_name = decks_list[k]; fs.readdir(config.deck_path, done);
if (_.endsWith(deck_name, ".ydk")) { },
delDeck(deck_name); removeAll: ["deckList", (results, done) => {
} const decks_list = results.deckList;
} _async.each(decks_list, delDeck, done);
}]
}, callback);
} }
var UploadToChallonge = function() { var UploadToChallonge = function () {
if (!challonge) { if (!challonge) {
sendResponse("未开启Challonge模式。"); sendResponse("未开启Challonge模式。");
return false; return false;
...@@ -150,47 +162,41 @@ var UploadToChallonge = function() { ...@@ -150,47 +162,41 @@ var UploadToChallonge = function() {
sendResponse("玩家列表为空。"); sendResponse("玩家列表为空。");
return false; return false;
} }
sendResponse("读取玩家列表完毕,共有"+player_list.length+"名玩家。"); sendResponse("读取玩家列表完毕,共有" + player_list.length + "名玩家。");
sendResponse("开始上传玩家列表至Challonge。"); sendResponse("开始上传玩家列表至Challonge。");
var success_count = [0]; _async.each(player_list, (player_name, done) => {
for (var k in player_list) { sendResponse("正在上传玩家 " + player_name + " 至Challonge。");
var player_name = player_list[k];
sendResponse("正在上传玩家 "+player_name+" 至Challonge。");
challonge.participants.create({ challonge.participants.create({
id: challonge_config.tournament_id, id: challonge_config.tournament_id,
participant: { participant: {
name: player_name name: player_name
}, },
callback: (function(player_name, success_count) { callback: (err, data) => {
return function(err, data) { if (err) {
if (err) { sendResponse("玩家 "+player_name+" 上传失败:"+err.text);
sendResponse("玩家 "+player_name+" 上传失败:"+err.text); } else {
if (data.participant) {
sendResponse("玩家 "+player_name+" 上传完毕,其Challonge ID是 "+data.participant.id+"");
} else { } else {
if (data.participant) { sendResponse("玩家 "+player_name+" 上传完毕。");
sendResponse("玩家 "+player_name+" 上传完毕,其Challonge ID是 "+data.participant.id+"");
} else {
sendResponse("玩家 "+player_name+" 上传完毕。");
}
++success_count[0];
if (success_count[0] >= player_list.length) {
sendResponse("玩家列表上传完成。");
}
} }
}; }
})(player_name, success_count) done();
}
}); });
} }, (err) => {
sendResponse("玩家列表上传完成。");
});
return true; return true;
} }
var receiveDecks = function(files) { var receiveDecks = function(files, callback) {
var result=[]; var result = [];
for (var i in files) { _async.each(files, (file, done) => {
var file=files[i];
if (_.endsWith(file.name, ".ydk")) { if (_.endsWith(file.name, ".ydk")) {
var deck=readDeck(file.name, file.path); var deck = readDeck(file.name, file.path);
if (deck.main.length>=40) { if (deck.main.length >= 40) {
fs.createReadStream(file.path).pipe(fs.createWriteStream(config.deck_path+file.name)); fs.createReadStream(file.path).pipe(fs.createWriteStream(config.deck_path + file.name));
result.push({ result.push({
file: file.name, file: file.name,
status: "OK" status: "OK"
...@@ -209,8 +215,8 @@ var receiveDecks = function(files) { ...@@ -209,8 +215,8 @@ var receiveDecks = function(files) {
status: "不是卡组文件" status: "不是卡组文件"
}); });
} }
} done();
return result; }, callback);
} }
//建立一个http服务器,接收API操作 //建立一个http服务器,接收API操作
...@@ -231,13 +237,20 @@ function requestListener(req, res) { ...@@ -231,13 +237,20 @@ function requestListener(req, res) {
} }
var form = new formidable.IncomingForm(); var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) { form.parse(req, function(err, fields, files) {
res.writeHead(200, { receiveDecks(files, (err, result) => {
"Access-Control-Allow-origin": "*", if (err) {
'content-type': 'text/plain' res.writeHead(200, {
"Access-Control-Allow-origin": "*",
'content-type': 'text/plain'
});
res.end(err.toString());
}
res.writeHead(200, {
"Access-Control-Allow-origin": "*",
'content-type': 'text/plain'
});
res.end(JSON.stringify(result));
}); });
var result=receiveDecks(files);
//console.log(files);
res.end(JSON.stringify(result));
}); });
} }
else if (u.pathname === '/api/msg') { else if (u.pathname === '/api/msg') {
...@@ -276,9 +289,15 @@ function requestListener(req, res) { ...@@ -276,9 +289,15 @@ function requestListener(req, res) {
res.end("Auth Failed."); res.end("Auth Failed.");
return; return;
} }
res.writeHead(200); getDecks((err, decks) => {
var decklist=getDecks(); if (err) {
res.end(u.query.callback+'('+JSON.stringify(decklist)+');'); res.writeHead(500);
res.end(u.query.callback + '(' + err.toString() +');');
} else {
res.writeHead(200);
res.end(u.query.callback+'('+JSON.stringify(decks)+');');
}
})
} }
else if (u.pathname === '/api/del_deck') { else if (u.pathname === '/api/del_deck') {
if (!auth.auth(u.query.username, u.query.password, "deck_dashboard_write", "delete_deck")) { if (!auth.auth(u.query.username, u.query.password, "deck_dashboard_write", "delete_deck")) {
...@@ -287,8 +306,16 @@ function requestListener(req, res) { ...@@ -287,8 +306,16 @@ function requestListener(req, res) {
return; return;
} }
res.writeHead(200); res.writeHead(200);
var result=delDeck(u.query.msg); delDeck(u.query.msg, (err) => {
res.end(u.query.callback+'("'+result+'");'); let result;
if (err) {
result = "删除卡组 " + u.query.msg + "失败: " + err.toString();
} else {
result = "删除卡组 " + u.query.msg + "成功。";
}
res.writeHead(200);
res.end(u.query.callback+'("'+result+'");');
});
} }
else if (u.pathname === '/api/clear_decks') { else if (u.pathname === '/api/clear_decks') {
if (!auth.auth(u.query.username, u.query.password, "deck_dashboard_write", "clear_decks")) { if (!auth.auth(u.query.username, u.query.password, "deck_dashboard_write", "clear_decks")) {
...@@ -296,8 +323,17 @@ function requestListener(req, res) { ...@@ -296,8 +323,17 @@ function requestListener(req, res) {
res.end("Auth Failed."); res.end("Auth Failed.");
return; return;
} }
clearDecks((err) => {
let result;
if (err) {
result = "删除全部卡组失败。" + err.toString();
} else {
result = "删除全部卡组成功。";
}
res.writeHead(200);
res.end(u.query.callback+'("'+result+'");');
});
res.writeHead(200); res.writeHead(200);
clearDecks();
res.end(u.query.callback+'("已删除全部卡组。");'); res.end(u.query.callback+'("已删除全部卡组。");');
} }
else if (u.pathname === '/api/upload_to_challonge') { else if (u.pathname === '/api/upload_to_challonge') {
......
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