Commit 542ddefd authored by nanahira's avatar nanahira

migrate to template service and add account bind

parent ad70bfea
...@@ -13,3 +13,5 @@ CDB_REPO: 'https://code.mycard.moe/mycard/ygopro-database.git' ...@@ -13,3 +13,5 @@ CDB_REPO: 'https://code.mycard.moe/mycard/ygopro-database.git'
CDB_BRANCH: 'master' CDB_BRANCH: 'master'
FEEDBACK_NOTIFY_URL: '' # 反馈推送消息。使用 koishi-plugin-apisend 搭建 FEEDBACK_NOTIFY_URL: '' # 反馈推送消息。使用 koishi-plugin-apisend 搭建
FEEDBACK_NOTIFY_TOKEN: 'default' FEEDBACK_NOTIFY_TOKEN: 'default'
REDIS_URL: 'redis://localhost:6379'
ROOT_URL: 'https://jdaw.moecube.com'
\ No newline at end of file
...@@ -18,14 +18,19 @@ ...@@ -18,14 +18,19 @@
"@nestjs/schedule": "^2.1.0", "@nestjs/schedule": "^2.1.0",
"@nestjs/swagger": "^6.1.4", "@nestjs/swagger": "^6.1.4",
"@nestjs/typeorm": "^9.0.1", "@nestjs/typeorm": "^9.0.1",
"aragami": "^1.1.2",
"class-transformer": "^0.5.1", "class-transformer": "^0.5.1",
"class-validator": "^0.13.2", "class-validator": "^0.13.2",
"koishi": "^4.11.1", "crypto-random-string": "3.3.1",
"koishi": "^4.11.2",
"koishi-nestjs": "^6.0.16", "koishi-nestjs": "^6.0.16",
"koishi-plugin-adapter-wechat-official": "^1.0.2", "koishi-plugin-adapter-wechat-official": "^1.0.2",
"koishi-plugin-puppeteer": "^3.3.2", "koishi-plugin-puppeteer": "^3.3.2",
"koishi-plugin-ygocard": "^10.4.9", "koishi-plugin-ygocard": "^10.4.9",
"nicot": "^1.0.17", "mustache": "^4.2.0",
"nestjs-aragami": "^1.0.0",
"nestjs-mycard": "^3.0.2",
"nicot": "^1.0.26",
"pg": "^8.8.0", "pg": "^8.8.0",
"pg-native": "^3.0.1", "pg-native": "^3.0.1",
"reflect-metadata": "^0.1.13", "reflect-metadata": "^0.1.13",
...@@ -41,6 +46,7 @@ ...@@ -41,6 +46,7 @@
"@nestjs/testing": "^9.0.0", "@nestjs/testing": "^9.0.0",
"@types/express": "^4.17.15", "@types/express": "^4.17.15",
"@types/jest": "28.1.8", "@types/jest": "28.1.8",
"@types/mustache": "^4.2.2",
"@types/node": "^16.0.0", "@types/node": "^16.0.0",
"@types/supertest": "^2.0.11", "@types/supertest": "^2.0.11",
"@typescript-eslint/eslint-plugin": "^5.0.0", "@typescript-eslint/eslint-plugin": "^5.0.0",
...@@ -901,6 +907,11 @@ ...@@ -901,6 +907,11 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
"dev": true "dev": true
}, },
"node_modules/@ioredis/commands": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
},
"node_modules/@istanbuljs/load-nyc-config": { "node_modules/@istanbuljs/load-nyc-config": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
...@@ -1491,9 +1502,9 @@ ...@@ -1491,9 +1502,9 @@
} }
}, },
"node_modules/@koishijs/core": { "node_modules/@koishijs/core": {
"version": "4.11.1", "version": "4.11.2",
"resolved": "https://registry.npmjs.org/@koishijs/core/-/core-4.11.1.tgz", "resolved": "https://registry.npmjs.org/@koishijs/core/-/core-4.11.2.tgz",
"integrity": "sha512-HrzgBnimg/fgIzxTyH8BJb7nZpgt912i4zcfvRN9kNcPwbdOpjGllCVRuhRxSEBR21OJvCYTmT0dzf1qNPd3Vg==", "integrity": "sha512-9Smg9FV+X7qi9AANI9cKXC4hjZ3s1ayJHCnzzP//dQM3EIOX++DqQ4rYz7AYg2BeX9gbP07Zy9TZc28duDuPDA==",
"dependencies": { "dependencies": {
"@koishijs/utils": "^6.4.0", "@koishijs/utils": "^6.4.0",
"@minatojs/core": "^2.1.1", "@minatojs/core": "^2.1.1",
...@@ -1504,16 +1515,16 @@ ...@@ -1504,16 +1515,16 @@
} }
}, },
"node_modules/@koishijs/loader": { "node_modules/@koishijs/loader": {
"version": "2.5.1", "version": "2.5.2",
"resolved": "https://registry.npmjs.org/@koishijs/loader/-/loader-2.5.1.tgz", "resolved": "https://registry.npmjs.org/@koishijs/loader/-/loader-2.5.2.tgz",
"integrity": "sha512-ZNyzmL/sCTENPegZBx5rPs1mb+7YOxCb9Il0vyul9zuGzSJoJklSAIoTpBRt1v6BH/eUHEwY6ngcomkxQlf6xQ==", "integrity": "sha512-6tnd1PPrOT1Dpsg9d5LWjDiOb5nxD+bP5IByzkdXzXvhIzwbiv5T8bFJNJBtrh0wnqMArHtb2TWWxIK+Xax59Q==",
"dependencies": { "dependencies": {
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"ns-require": "^1.1.4" "ns-require": "^1.1.4"
}, },
"peerDependencies": { "peerDependencies": {
"@koishijs/core": "^4.11.1" "@koishijs/core": "^4.11.2"
} }
}, },
"node_modules/@koishijs/loader/node_modules/dotenv": { "node_modules/@koishijs/loader/node_modules/dotenv": {
...@@ -1564,6 +1575,17 @@ ...@@ -1564,6 +1575,17 @@
"cosmokit": "^1.4.0" "cosmokit": "^1.4.0"
} }
}, },
"node_modules/@nanahira/redlock": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@nanahira/redlock/-/redlock-1.0.0.tgz",
"integrity": "sha512-kf48X8tSbZm1DQT3Aj3B/Fza+L9toi5+j47BX9WJ9hIqyuCDRWMC2wQOJB1XAcOFZ+FGrfAjTa21bdTEuVlYeQ==",
"dependencies": {
"node-abort-controller": "^3.0.1"
},
"engines": {
"node": ">=12"
}
},
"node_modules/@nestjs/axios": { "node_modules/@nestjs/axios": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-1.0.1.tgz", "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-1.0.1.tgz",
...@@ -2379,6 +2401,12 @@ ...@@ -2379,6 +2401,12 @@
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
}, },
"node_modules/@types/mustache": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@types/mustache/-/mustache-4.2.2.tgz",
"integrity": "sha512-MUSpfpW0yZbTgjekDbH0shMYBUD+X/uJJJMm9LXN1d5yjl5lCY1vN/eWKD6D1tOtjA6206K0zcIPnUaFMurdNA==",
"dev": true
},
"node_modules/@types/node": { "node_modules/@types/node": {
"version": "16.18.11", "version": "16.18.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz",
...@@ -3006,6 +3034,29 @@ ...@@ -3006,6 +3034,29 @@
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
}, },
"node_modules/aragami": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/aragami/-/aragami-1.1.2.tgz",
"integrity": "sha512-asrmtKkLOgtXMYt3TeM/lWsmbKdJwjUPDV9yb+h62FBBMFx0h+lrEQN1XL6ZIkfyggtyC0G5gv0f9G+Ul0cTUg==",
"dependencies": {
"@nanahira/redlock": "^1.0.0",
"better-lock": "^2.0.3",
"class-transformer": "^0.5.1",
"encoded-buffer": "^0.2.6",
"ioredis": "^5.2.3",
"lodash": "^4.17.21",
"lru-cache": "^7.13.1",
"typed-reflector": "^1.0.11"
}
},
"node_modules/aragami/node_modules/lru-cache": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
"integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA==",
"engines": {
"node": ">=12"
}
},
"node_modules/arg": { "node_modules/arg": {
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
...@@ -3183,6 +3234,11 @@ ...@@ -3183,6 +3234,11 @@
} }
] ]
}, },
"node_modules/better-lock": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/better-lock/-/better-lock-2.0.3.tgz",
"integrity": "sha512-3bCaToLrmEXZcIOOVWgi1STvp3/6EpoZAmlWBeuX2MvDB0Ql2ctl/vQ0CbhQIJYQiptdGypllP3ez+TeEmdnKQ=="
},
"node_modules/binary-extensions": { "node_modules/binary-extensions": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
...@@ -3699,6 +3755,14 @@ ...@@ -3699,6 +3755,14 @@
"node": ">=0.8" "node": ">=0.8"
} }
}, },
"node_modules/cluster-key-slot": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA==",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/co": { "node_modules/co": {
"version": "4.6.0", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
...@@ -3982,6 +4046,25 @@ ...@@ -3982,6 +4046,25 @@
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==", "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==",
"deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in." "deprecated": "This package is no longer supported. It's now a built-in Node module. If you've depended on crypto, you should switch to the one that's built-in."
}, },
"node_modules/crypto-random-string": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-3.3.1.tgz",
"integrity": "sha512-5j88ECEn6h17UePrLi6pn1JcLtAiANa3KExyr9y9Z5vo2mv56Gh3I4Aja/B9P9uyMwyxNHAHWv+nE72f30T5Dg==",
"dependencies": {
"type-fest": "^0.8.1"
},
"engines": {
"node": ">=8"
}
},
"node_modules/crypto-random-string/node_modules/type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"engines": {
"node": ">=8"
}
},
"node_modules/date-fns": { "node_modules/date-fns": {
"version": "2.29.3", "version": "2.29.3",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
...@@ -4061,6 +4144,14 @@ ...@@ -4061,6 +4144,14 @@
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
}, },
"node_modules/denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==",
"engines": {
"node": ">=0.10"
}
},
"node_modules/depd": { "node_modules/depd": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
...@@ -4188,6 +4279,21 @@ ...@@ -4188,6 +4279,21 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
}, },
"node_modules/encoded-buffer": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/encoded-buffer/-/encoded-buffer-0.2.6.tgz",
"integrity": "sha512-zEskqXs0FbF9HcwZkumyAoiB3NN23yAoJvPmLP0NuWQLXTeCDMeVRYK1kjIsZPkoXE2cIBS0iht95pqf8UKyog==",
"dependencies": {
"lodash": "^4.17.10",
"to-buffer": "^1.1.1",
"tslib": "^1.9.3"
}
},
"node_modules/encoded-buffer/node_modules/tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
},
"node_modules/encodeurl": { "node_modules/encodeurl": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
...@@ -5596,6 +5702,29 @@ ...@@ -5596,6 +5702,29 @@
"node": ">= 0.10" "node": ">= 0.10"
} }
}, },
"node_modules/ioredis": {
"version": "5.2.5",
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.2.5.tgz",
"integrity": "sha512-7HKo/ClM2DGLRXdFq8ruS3Uuadensz4A76wPOU0adqlOqd1qkhoLPDaBhmVhUhNGpB+J65/bhLmNB8DDY99HJQ==",
"dependencies": {
"@ioredis/commands": "^1.1.1",
"cluster-key-slot": "^1.1.0",
"debug": "^4.3.4",
"denque": "^2.0.1",
"lodash.defaults": "^4.2.0",
"lodash.isarguments": "^3.1.0",
"redis-errors": "^1.2.0",
"redis-parser": "^3.0.0",
"standard-as-callback": "^2.1.0"
},
"engines": {
"node": ">=12.22.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/ioredis"
}
},
"node_modules/ip": { "node_modules/ip": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
...@@ -6851,12 +6980,12 @@ ...@@ -6851,12 +6980,12 @@
} }
}, },
"node_modules/koishi": { "node_modules/koishi": {
"version": "4.11.1", "version": "4.11.2",
"resolved": "https://registry.npmjs.org/koishi/-/koishi-4.11.1.tgz", "resolved": "https://registry.npmjs.org/koishi/-/koishi-4.11.2.tgz",
"integrity": "sha512-sHMa8okx+kl5jHBwzT2gb4qGeOJRKG8AfLt4w5BLJwOPpvdo6cW9RiRy1uBwkXM7zf4yOvtr0+6WEu+AuD6bXQ==", "integrity": "sha512-7VL8BvL16l6S6hTWov1wX86Uw7xEYIyQso68Q/SMdN4YFE5CpLAUEsT8uTaSFpX/kscIk9x84tLq2+H6N2xYog==",
"dependencies": { "dependencies": {
"@koishijs/core": "4.11.1", "@koishijs/core": "4.11.2",
"@koishijs/loader": "^2.5.1", "@koishijs/loader": "^2.5.2",
"@koishijs/utils": "^6.4.0", "@koishijs/utils": "^6.4.0",
"@satorijs/satori": "^2.0.1", "@satorijs/satori": "^2.0.1",
"cac": "^6.7.14", "cac": "^6.7.14",
...@@ -7048,6 +7177,16 @@ ...@@ -7048,6 +7177,16 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}, },
"node_modules/lodash.defaults": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
},
"node_modules/lodash.isarguments": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
},
"node_modules/lodash.memoize": { "node_modules/lodash.memoize": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
...@@ -7398,12 +7537,57 @@ ...@@ -7398,12 +7537,57 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true "dev": true
}, },
"node_modules/nestjs-aragami": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/nestjs-aragami/-/nestjs-aragami-1.0.0.tgz",
"integrity": "sha512-McYZ+5weJocxKU0C09YFl1k1Gf8T0yqTSrM3dzq3zDreubgTKT9RmhVTLtoBQU0Ka49EaX1xMidoJYx9aI53Ew==",
"peerDependencies": {
"@nestjs/common": "^9.1.2",
"aragami": "^1.1.2"
}
},
"node_modules/nestjs-mycard": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/nestjs-mycard/-/nestjs-mycard-3.0.2.tgz",
"integrity": "sha512-a2bp0IKoxgxdVRadGEpDzJaRx230P9sDAourkT6fcF6PGeJHUSx0nEvt/sULFRWQiPT+spD1hqgEw2S+wSaSmQ==",
"dependencies": {
"@nestjs/axios": "^0.1.0"
},
"peerDependencies": {
"@nestjs/common": "^9.1.2",
"rxjs": "^7.5.7"
}
},
"node_modules/nestjs-mycard/node_modules/@nestjs/axios": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.1.1.tgz",
"integrity": "sha512-rLEq6yfho2CZyOcxP+P4Q3FjkNuiiHDyzj3Cr9i4Kdn3Ng09ygtOB4++jjXPREc6650pOFfzNtw18QH7bfLnQA==",
"dependencies": {
"axios": "1.2.1"
},
"peerDependencies": {
"@nestjs/common": "^7.0.0 || ^8.0.0 || ^9.0.0",
"reflect-metadata": "^0.1.12",
"rxjs": "^6.0.0 || ^7.0.0"
}
},
"node_modules/nestjs-mycard/node_modules/axios": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz",
"integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==",
"dependencies": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
},
"node_modules/nicot": { "node_modules/nicot": {
"version": "1.0.17", "version": "1.0.26",
"resolved": "https://registry.npmjs.org/nicot/-/nicot-1.0.17.tgz", "resolved": "https://registry.npmjs.org/nicot/-/nicot-1.0.26.tgz",
"integrity": "sha512-SnohOuhceU1FJVXppU/pdpbmelqg/OMq4G8FNwjhWQSVZnxNHl90PCkvjVApvEhHXfOts+ToeZ0GCweVgDhBGQ==", "integrity": "sha512-gjFRsor4/074rOLwV4LaEpqoqKyAYFvNyYC2LDQKrlK3lLICCp6pSV/QtB2b680NWhzhyJ9y/4QjRxsC1FRCvQ==",
"dependencies": { "dependencies": {
"lodash": "^4.17.21" "lodash": "^4.17.21",
"typed-reflector": "^1.0.11"
}, },
"peerDependencies": { "peerDependencies": {
"@nestjs/common": "^9.0.3", "@nestjs/common": "^9.0.3",
...@@ -7416,8 +7600,7 @@ ...@@ -7416,8 +7600,7 @@
"node_modules/node-abort-controller": { "node_modules/node-abort-controller": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz",
"integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==", "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw=="
"dev": true
}, },
"node_modules/node-emoji": { "node_modules/node-emoji": {
"version": "1.11.0", "version": "1.11.0",
...@@ -8352,6 +8535,25 @@ ...@@ -8352,6 +8535,25 @@
"node": ">= 0.10" "node": ">= 0.10"
} }
}, },
"node_modules/redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==",
"engines": {
"node": ">=4"
}
},
"node_modules/redis-parser": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
"dependencies": {
"redis-errors": "^1.0.0"
},
"engines": {
"node": ">=4"
}
},
"node_modules/reflect-metadata": { "node_modules/reflect-metadata": {
"version": "0.1.13", "version": "0.1.13",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
...@@ -8951,6 +9153,11 @@ ...@@ -8951,6 +9153,11 @@
"node": ">=8" "node": ">=8"
} }
}, },
"node_modules/standard-as-callback": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
},
"node_modules/statuses": { "node_modules/statuses": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
...@@ -9380,6 +9587,11 @@ ...@@ -9380,6 +9587,11 @@
"integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
"dev": true "dev": true
}, },
"node_modules/to-buffer": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
"integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
},
"node_modules/to-fast-properties": { "node_modules/to-fast-properties": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
...@@ -11017,6 +11229,11 @@ ...@@ -11017,6 +11229,11 @@
"integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==",
"dev": true "dev": true
}, },
"@ioredis/commands": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@ioredis/commands/-/commands-1.2.0.tgz",
"integrity": "sha512-Sx1pU8EM64o2BrqNpEO1CNLtKQwyhuXuqyfH7oGKCk+1a33d2r5saW8zNwm3j6BTExtjrv2BxTgzzkMwts6vGg=="
},
"@istanbuljs/load-nyc-config": { "@istanbuljs/load-nyc-config": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
...@@ -11484,9 +11701,9 @@ ...@@ -11484,9 +11701,9 @@
} }
}, },
"@koishijs/core": { "@koishijs/core": {
"version": "4.11.1", "version": "4.11.2",
"resolved": "https://registry.npmjs.org/@koishijs/core/-/core-4.11.1.tgz", "resolved": "https://registry.npmjs.org/@koishijs/core/-/core-4.11.2.tgz",
"integrity": "sha512-HrzgBnimg/fgIzxTyH8BJb7nZpgt912i4zcfvRN9kNcPwbdOpjGllCVRuhRxSEBR21OJvCYTmT0dzf1qNPd3Vg==", "integrity": "sha512-9Smg9FV+X7qi9AANI9cKXC4hjZ3s1ayJHCnzzP//dQM3EIOX++DqQ4rYz7AYg2BeX9gbP07Zy9TZc28duDuPDA==",
"requires": { "requires": {
"@koishijs/utils": "^6.4.0", "@koishijs/utils": "^6.4.0",
"@minatojs/core": "^2.1.1", "@minatojs/core": "^2.1.1",
...@@ -11497,9 +11714,9 @@ ...@@ -11497,9 +11714,9 @@
} }
}, },
"@koishijs/loader": { "@koishijs/loader": {
"version": "2.5.1", "version": "2.5.2",
"resolved": "https://registry.npmjs.org/@koishijs/loader/-/loader-2.5.1.tgz", "resolved": "https://registry.npmjs.org/@koishijs/loader/-/loader-2.5.2.tgz",
"integrity": "sha512-ZNyzmL/sCTENPegZBx5rPs1mb+7YOxCb9Il0vyul9zuGzSJoJklSAIoTpBRt1v6BH/eUHEwY6ngcomkxQlf6xQ==", "integrity": "sha512-6tnd1PPrOT1Dpsg9d5LWjDiOb5nxD+bP5IByzkdXzXvhIzwbiv5T8bFJNJBtrh0wnqMArHtb2TWWxIK+Xax59Q==",
"requires": { "requires": {
"dotenv": "^16.0.3", "dotenv": "^16.0.3",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
...@@ -11551,6 +11768,14 @@ ...@@ -11551,6 +11768,14 @@
"cosmokit": "^1.4.0" "cosmokit": "^1.4.0"
} }
}, },
"@nanahira/redlock": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/@nanahira/redlock/-/redlock-1.0.0.tgz",
"integrity": "sha512-kf48X8tSbZm1DQT3Aj3B/Fza+L9toi5+j47BX9WJ9hIqyuCDRWMC2wQOJB1XAcOFZ+FGrfAjTa21bdTEuVlYeQ==",
"requires": {
"node-abort-controller": "^3.0.1"
}
},
"@nestjs/axios": { "@nestjs/axios": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-1.0.1.tgz", "resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-1.0.1.tgz",
...@@ -12169,6 +12394,12 @@ ...@@ -12169,6 +12394,12 @@
"resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-3.0.1.tgz",
"integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA==" "integrity": "sha512-Y4XFY5VJAuw0FgAqPNd6NNoV44jbq9Bz2L7Rh/J6jLTiHBSBJa9fxqQIvkIld4GsoDOcCbvzOUAbLPsSKKg+uA=="
}, },
"@types/mustache": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@types/mustache/-/mustache-4.2.2.tgz",
"integrity": "sha512-MUSpfpW0yZbTgjekDbH0shMYBUD+X/uJJJMm9LXN1d5yjl5lCY1vN/eWKD6D1tOtjA6206K0zcIPnUaFMurdNA==",
"dev": true
},
"@types/node": { "@types/node": {
"version": "16.18.11", "version": "16.18.11",
"resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz", "resolved": "https://registry.npmjs.org/@types/node/-/node-16.18.11.tgz",
...@@ -12648,6 +12879,28 @@ ...@@ -12648,6 +12879,28 @@
"resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
"integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw=="
}, },
"aragami": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/aragami/-/aragami-1.1.2.tgz",
"integrity": "sha512-asrmtKkLOgtXMYt3TeM/lWsmbKdJwjUPDV9yb+h62FBBMFx0h+lrEQN1XL6ZIkfyggtyC0G5gv0f9G+Ul0cTUg==",
"requires": {
"@nanahira/redlock": "^1.0.0",
"better-lock": "^2.0.3",
"class-transformer": "^0.5.1",
"encoded-buffer": "^0.2.6",
"ioredis": "^5.2.3",
"lodash": "^4.17.21",
"lru-cache": "^7.13.1",
"typed-reflector": "^1.0.11"
},
"dependencies": {
"lru-cache": {
"version": "7.14.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.14.1.tgz",
"integrity": "sha512-ysxwsnTKdAx96aTRdhDOCQfDgbHnt8SK0KY8SEjO0wHinhWOFTESbjVCMPbU1uGXg/ch4lifqx0wfjOawU2+WA=="
}
}
},
"arg": { "arg": {
"version": "4.1.3", "version": "4.1.3",
"resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
...@@ -12783,6 +13036,11 @@ ...@@ -12783,6 +13036,11 @@
"resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==" "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA=="
}, },
"better-lock": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/better-lock/-/better-lock-2.0.3.tgz",
"integrity": "sha512-3bCaToLrmEXZcIOOVWgi1STvp3/6EpoZAmlWBeuX2MvDB0Ql2ctl/vQ0CbhQIJYQiptdGypllP3ez+TeEmdnKQ=="
},
"binary-extensions": { "binary-extensions": {
"version": "2.2.0", "version": "2.2.0",
"resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
...@@ -13151,6 +13409,11 @@ ...@@ -13151,6 +13409,11 @@
"integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
"dev": true "dev": true
}, },
"cluster-key-slot": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.2.tgz",
"integrity": "sha512-RMr0FhtfXemyinomL4hrWcYJxmX6deFdCxpJzhDttxgO1+bcCnkk+9drydLVDmAMG7NE6aN/fl4F7ucU/90gAA=="
},
"co": { "co": {
"version": "4.6.0", "version": "4.6.0",
"resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
...@@ -13385,6 +13648,21 @@ ...@@ -13385,6 +13648,21 @@
"resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz", "resolved": "https://registry.npmjs.org/crypto/-/crypto-1.0.1.tgz",
"integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig==" "integrity": "sha512-VxBKmeNcqQdiUQUW2Tzq0t377b54N2bMtXO/qiLa+6eRRmmC4qT3D4OnTGoT/U6O9aklQ/jTwbOtRMTTY8G0Ig=="
}, },
"crypto-random-string": {
"version": "3.3.1",
"resolved": "https://registry.npmjs.org/crypto-random-string/-/crypto-random-string-3.3.1.tgz",
"integrity": "sha512-5j88ECEn6h17UePrLi6pn1JcLtAiANa3KExyr9y9Z5vo2mv56Gh3I4Aja/B9P9uyMwyxNHAHWv+nE72f30T5Dg==",
"requires": {
"type-fest": "^0.8.1"
},
"dependencies": {
"type-fest": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
"integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA=="
}
}
},
"date-fns": { "date-fns": {
"version": "2.29.3", "version": "2.29.3",
"resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz", "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.29.3.tgz",
...@@ -13440,6 +13718,11 @@ ...@@ -13440,6 +13718,11 @@
"resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
"integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==" "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ=="
}, },
"denque": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz",
"integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw=="
},
"depd": { "depd": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
...@@ -13533,6 +13816,23 @@ ...@@ -13533,6 +13816,23 @@
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
"integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A=="
}, },
"encoded-buffer": {
"version": "0.2.6",
"resolved": "https://registry.npmjs.org/encoded-buffer/-/encoded-buffer-0.2.6.tgz",
"integrity": "sha512-zEskqXs0FbF9HcwZkumyAoiB3NN23yAoJvPmLP0NuWQLXTeCDMeVRYK1kjIsZPkoXE2cIBS0iht95pqf8UKyog==",
"requires": {
"lodash": "^4.17.10",
"to-buffer": "^1.1.1",
"tslib": "^1.9.3"
},
"dependencies": {
"tslib": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
"integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg=="
}
}
},
"encodeurl": { "encodeurl": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
...@@ -14575,6 +14875,22 @@ ...@@ -14575,6 +14875,22 @@
"integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==",
"dev": true "dev": true
}, },
"ioredis": {
"version": "5.2.5",
"resolved": "https://registry.npmjs.org/ioredis/-/ioredis-5.2.5.tgz",
"integrity": "sha512-7HKo/ClM2DGLRXdFq8ruS3Uuadensz4A76wPOU0adqlOqd1qkhoLPDaBhmVhUhNGpB+J65/bhLmNB8DDY99HJQ==",
"requires": {
"@ioredis/commands": "^1.1.1",
"cluster-key-slot": "^1.1.0",
"debug": "^4.3.4",
"denque": "^2.0.1",
"lodash.defaults": "^4.2.0",
"lodash.isarguments": "^3.1.0",
"redis-errors": "^1.2.0",
"redis-parser": "^3.0.0",
"standard-as-callback": "^2.1.0"
}
},
"ip": { "ip": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz",
...@@ -15537,12 +15853,12 @@ ...@@ -15537,12 +15853,12 @@
} }
}, },
"koishi": { "koishi": {
"version": "4.11.1", "version": "4.11.2",
"resolved": "https://registry.npmjs.org/koishi/-/koishi-4.11.1.tgz", "resolved": "https://registry.npmjs.org/koishi/-/koishi-4.11.2.tgz",
"integrity": "sha512-sHMa8okx+kl5jHBwzT2gb4qGeOJRKG8AfLt4w5BLJwOPpvdo6cW9RiRy1uBwkXM7zf4yOvtr0+6WEu+AuD6bXQ==", "integrity": "sha512-7VL8BvL16l6S6hTWov1wX86Uw7xEYIyQso68Q/SMdN4YFE5CpLAUEsT8uTaSFpX/kscIk9x84tLq2+H6N2xYog==",
"requires": { "requires": {
"@koishijs/core": "4.11.1", "@koishijs/core": "4.11.2",
"@koishijs/loader": "^2.5.1", "@koishijs/loader": "^2.5.2",
"@koishijs/utils": "^6.4.0", "@koishijs/utils": "^6.4.0",
"@satorijs/satori": "^2.0.1", "@satorijs/satori": "^2.0.1",
"cac": "^6.7.14", "cac": "^6.7.14",
...@@ -15689,6 +16005,16 @@ ...@@ -15689,6 +16005,16 @@
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
}, },
"lodash.defaults": {
"version": "4.2.0",
"resolved": "https://registry.npmjs.org/lodash.defaults/-/lodash.defaults-4.2.0.tgz",
"integrity": "sha512-qjxPLHd3r5DnsdGacqOMU6pb/avJzdh9tFX2ymgoZE27BmjXrNy/y4LoaiTeAb+O3gL8AfpJGtqfX/ae2leYYQ=="
},
"lodash.isarguments": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/lodash.isarguments/-/lodash.isarguments-3.1.0.tgz",
"integrity": "sha512-chi4NHZlZqZD18a0imDHnZPrDeBbTtVN7GXMwuGdRH9qotxAjYs3aVLKc7zNOG9eddR5Ksd8rvFEBc9SsggPpg=="
},
"lodash.memoize": { "lodash.memoize": {
"version": "4.1.2", "version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
...@@ -15962,19 +16288,53 @@ ...@@ -15962,19 +16288,53 @@
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
"dev": true "dev": true
}, },
"nestjs-aragami": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/nestjs-aragami/-/nestjs-aragami-1.0.0.tgz",
"integrity": "sha512-McYZ+5weJocxKU0C09YFl1k1Gf8T0yqTSrM3dzq3zDreubgTKT9RmhVTLtoBQU0Ka49EaX1xMidoJYx9aI53Ew==",
"requires": {}
},
"nestjs-mycard": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/nestjs-mycard/-/nestjs-mycard-3.0.2.tgz",
"integrity": "sha512-a2bp0IKoxgxdVRadGEpDzJaRx230P9sDAourkT6fcF6PGeJHUSx0nEvt/sULFRWQiPT+spD1hqgEw2S+wSaSmQ==",
"requires": {
"@nestjs/axios": "^0.1.0"
},
"dependencies": {
"@nestjs/axios": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@nestjs/axios/-/axios-0.1.1.tgz",
"integrity": "sha512-rLEq6yfho2CZyOcxP+P4Q3FjkNuiiHDyzj3Cr9i4Kdn3Ng09ygtOB4++jjXPREc6650pOFfzNtw18QH7bfLnQA==",
"requires": {
"axios": "1.2.1"
}
},
"axios": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/axios/-/axios-1.2.1.tgz",
"integrity": "sha512-I88cFiGu9ryt/tfVEi4kX2SITsvDddTajXTOFmt2uK1ZVA8LytjtdeyefdQWEf5PU8w+4SSJDoYnggflB5tW4A==",
"requires": {
"follow-redirects": "^1.15.0",
"form-data": "^4.0.0",
"proxy-from-env": "^1.1.0"
}
}
}
},
"nicot": { "nicot": {
"version": "1.0.17", "version": "1.0.26",
"resolved": "https://registry.npmjs.org/nicot/-/nicot-1.0.17.tgz", "resolved": "https://registry.npmjs.org/nicot/-/nicot-1.0.26.tgz",
"integrity": "sha512-SnohOuhceU1FJVXppU/pdpbmelqg/OMq4G8FNwjhWQSVZnxNHl90PCkvjVApvEhHXfOts+ToeZ0GCweVgDhBGQ==", "integrity": "sha512-gjFRsor4/074rOLwV4LaEpqoqKyAYFvNyYC2LDQKrlK3lLICCp6pSV/QtB2b680NWhzhyJ9y/4QjRxsC1FRCvQ==",
"requires": { "requires": {
"lodash": "^4.17.21" "lodash": "^4.17.21",
"typed-reflector": "^1.0.11"
} }
}, },
"node-abort-controller": { "node-abort-controller": {
"version": "3.0.1", "version": "3.0.1",
"resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz", "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.0.1.tgz",
"integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw==", "integrity": "sha512-/ujIVxthRs+7q6hsdjHMaj8hRG9NuWmwrz+JdRwZ14jdFoKSkm+vDsCbF9PLpnSqjaWQJuTmVtcWHNLr+vrOFw=="
"dev": true
}, },
"node-emoji": { "node-emoji": {
"version": "1.11.0", "version": "1.11.0",
...@@ -16664,6 +17024,19 @@ ...@@ -16664,6 +17024,19 @@
"resolve": "^1.1.6" "resolve": "^1.1.6"
} }
}, },
"redis-errors": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz",
"integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w=="
},
"redis-parser": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz",
"integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==",
"requires": {
"redis-errors": "^1.0.0"
}
},
"reflect-metadata": { "reflect-metadata": {
"version": "0.1.13", "version": "0.1.13",
"resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.13.tgz",
...@@ -17116,6 +17489,11 @@ ...@@ -17116,6 +17489,11 @@
} }
} }
}, },
"standard-as-callback": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/standard-as-callback/-/standard-as-callback-2.1.0.tgz",
"integrity": "sha512-qoRRSyROncaz1z0mvYqIE4lCd9p2R90i6GxW3uZv5ucSu8tU7B5HXUP1gG8pVZsYNVaXjk8ClXHPttLyxAL48A=="
},
"statuses": { "statuses": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
...@@ -17431,6 +17809,11 @@ ...@@ -17431,6 +17809,11 @@
"integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
"dev": true "dev": true
}, },
"to-buffer": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz",
"integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg=="
},
"to-fast-properties": { "to-fast-properties": {
"version": "2.0.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
......
...@@ -16,6 +16,13 @@ import { HttpModule } from '@nestjs/axios'; ...@@ -16,6 +16,13 @@ import { HttpModule } from '@nestjs/axios';
import { Feedback } from './feedback/entities/feedback.entity'; import { Feedback } from './feedback/entities/feedback.entity';
import { OnSubscribeService } from './on-subscribe/on-subscribe.service'; import { OnSubscribeService } from './on-subscribe/on-subscribe.service';
import { BotService } from './bot/bot.service'; import { BotService } from './bot/bot.service';
import { MycardAuthModule } from 'nestjs-mycard';
import { MycardAccountService } from './mycard-account/mycard-account.service';
import { AragamiModule } from 'nestjs-aragami';
import { User } from './mycard-account/entities/user.entity';
import { MycardAccountController } from './mycard-account/mycard-account.controller';
import { TemplateService } from './template/template.service';
import { ArenaScoreService } from './arena-score/arena-score.service';
@Module({ @Module({
imports: [ imports: [
...@@ -41,9 +48,16 @@ import { BotService } from './bot/bot.service'; ...@@ -41,9 +48,16 @@ import { BotService } from './bot/bot.service';
bigNumberStrings: false, bigNumberStrings: false,
}), }),
}), }),
TypeOrmModule.forFeature([CommandCount, Feedback]), TypeOrmModule.forFeature([CommandCount, Feedback, User]),
ScheduleModule.forRoot(), ScheduleModule.forRoot(),
HttpModule, HttpModule,
MycardAuthModule.register(),
AragamiModule.registerAsync({
inject: [ConfigService],
useFactory: async (config: ConfigService) => ({
redis: { uri: config.get('REDIS_URL') },
}),
}),
KoishiModule.registerAsync({ KoishiModule.registerAsync({
inject: [ConfigService], inject: [ConfigService],
useWs: true, useWs: true,
...@@ -155,6 +169,10 @@ import { BotService } from './bot/bot.service'; ...@@ -155,6 +169,10 @@ import { BotService } from './bot/bot.service';
FeedbackService, FeedbackService,
OnSubscribeService, OnSubscribeService,
BotService, BotService,
MycardAccountService,
TemplateService,
ArenaScoreService,
], ],
controllers: [MycardAccountController],
}) })
export class AppModule {} export class AppModule {}
import { Test, TestingModule } from '@nestjs/testing';
import { ArenaScoreService } from './arena-score.service';
describe('ArenaScoreService', () => {
let service: ArenaScoreService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [ArenaScoreService],
}).compile();
service = module.get<ArenaScoreService>(ArenaScoreService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
import { Injectable } from '@nestjs/common';
@Injectable()
export class ArenaScoreService {}
...@@ -13,6 +13,7 @@ import { HttpService } from '@nestjs/axios'; ...@@ -13,6 +13,7 @@ import { HttpService } from '@nestjs/axios';
import { lastValueFrom } from 'rxjs'; import { lastValueFrom } from 'rxjs';
import { PutSession, UseCommand } from 'koishi-nestjs'; import { PutSession, UseCommand } from 'koishi-nestjs';
import { BotService } from '../bot/bot.service'; import { BotService } from '../bot/bot.service';
import { TemplateService } from '../template/template.service';
@Injectable() @Injectable()
export class FeedbackService extends CrudService(Feedback) { export class FeedbackService extends CrudService(Feedback) {
...@@ -24,6 +25,7 @@ export class FeedbackService extends CrudService(Feedback) { ...@@ -24,6 +25,7 @@ export class FeedbackService extends CrudService(Feedback) {
private config: ConfigService, private config: ConfigService,
private http: HttpService, private http: HttpService,
private botService: BotService, private botService: BotService,
private template: TemplateService,
) { ) {
super(repo); super(repo);
} }
...@@ -75,18 +77,12 @@ export class FeedbackService extends CrudService(Feedback) { ...@@ -75,18 +77,12 @@ export class FeedbackService extends CrudService(Feedback) {
@UseCommand('investigate', '调研') @UseCommand('investigate', '调研')
private async investigateCommand() { private async investigateCommand() {
return '欢迎访问MC有奖调研功能。目前暂时无进行中的调研。我们一般每1-2个月都会公布有奖调研,欢迎下次再查询。'; return this.template.render('investigate-not-available');
} }
@UseCommand('feedback', '发送反馈。') @UseCommand('feedback', '发送反馈。')
private async feedbackCommand(@PutSession() session: Session) { private async feedbackCommand(@PutSession() session: Session) {
await session.send( await session.send(this.template.render('feedback-menu'));
'您的反馈种类是?(输入数字回复)\n' +
'1. BUG或举报玩家不当行为\n' +
'2. 游戏功能/改善 \n' +
'3. 游戏体验出问题(例如卡、掉线)\n' +
'4. 其他反馈',
);
let choice = 0; let choice = 0;
while (true) { while (true) {
const input = await session.prompt(); const input = await session.prompt();
...@@ -103,31 +99,21 @@ export class FeedbackService extends CrudService(Feedback) { ...@@ -103,31 +99,21 @@ export class FeedbackService extends CrudService(Feedback) {
await session.send('请选择一个正确的选项(数字1~4)'); await session.send('请选择一个正确的选项(数字1~4)');
} }
if (choice == 1) { if (choice == 1) {
return ( return this.template.render('feedback-menu');
'举报BUG需要提交对战录像或截图。\n' +
'举报玩家需提供充足的证据,例如骂人截图。\n' +
'因此请到 ygobbs.com 发帖举报。 感谢!'
);
} }
const category = ['游戏功能/改善', '游戏体验问题', '其他'][choice - 2]; const category = ['游戏功能/改善', '游戏体验问题', '其他'][choice - 2];
await session.send('您启动了反馈系统!您的下一段文字会作为反馈发给我们!'); await session.send(this.template.render('feedback-prompt'));
const content = await session.prompt(); const content = await session.prompt();
if (this.botService.isBuiltinCommand(content)) { if (this.botService.isBuiltinCommand(content)) {
return session.execute(content); return session.execute(content);
} }
const count = await this.createFeedback(session, { category, content }); const count = await this.createFeedback(session, { category, content });
return `反馈成功!谢谢您的意见! return this.template.render('feedback-success', { count });
这是我们在决斗暗网服务号收到的第 ${count} 个反馈!`;
} }
@UseCommand('feedback.shop', '发送周边反馈。') @UseCommand('feedback.shop', '发送周边反馈。')
private async shopFeedbackCommand(@PutSession() session: Session) { private async shopFeedbackCommand(@PutSession() session: Session) {
await session.send( await session.send(this.template.render('feedback-shop'));
'感谢进入周边反馈功能!周边对MC来说至关重要,MC需要周边来支持服务器维持。\n' +
'如果您有任何对MCPro游戏周边的反馈,请留言于此,感谢!\n' +
'我们会非常关心您对我们周边的意见和看法!\n' +
'为此,希望您可以尽可能清晰表达您的意见,以便我们更好理解您的需求。',
);
const content = await session.prompt(); const content = await session.prompt();
if (this.botService.isBuiltinCommand(content)) { if (this.botService.isBuiltinCommand(content)) {
return session.execute(content); return session.execute(content);
...@@ -136,7 +122,6 @@ export class FeedbackService extends CrudService(Feedback) { ...@@ -136,7 +122,6 @@ export class FeedbackService extends CrudService(Feedback) {
category: '周边', category: '周边',
content, content,
}); });
return `我们收到了您的周边反馈。 return this.template.render('feedback-shop-success', { count });
这是我们在决斗暗网服务号收到的第 ${count} 个周边反馈!`;
} }
} }
...@@ -4,17 +4,22 @@ import { NestExpressApplication } from '@nestjs/platform-express'; ...@@ -4,17 +4,22 @@ import { NestExpressApplication } from '@nestjs/platform-express';
import { AppModule } from './app.module'; import { AppModule } from './app.module';
import { ConfigService } from '@nestjs/config'; import { ConfigService } from '@nestjs/config';
import { KoishiWsAdapter } from 'koishi-nestjs'; import { KoishiWsAdapter } from 'koishi-nestjs';
import PackageJson from '../package.json';
async function bootstrap() { async function bootstrap() {
const app = await NestFactory.create<NestExpressApplication>(AppModule); const app = await NestFactory.create<NestExpressApplication>(AppModule);
app.setGlobalPrefix('api');
app.useWebSocketAdapter(new KoishiWsAdapter(app)); app.useWebSocketAdapter(new KoishiWsAdapter(app));
app.enableCors(); app.enableCors();
if (process.env.NODE_ENV !== 'production') {
app.enableCors();
}
app.set('trust proxy', ['172.16.0.0/12', 'loopback']); app.set('trust proxy', ['172.16.0.0/12', 'loopback']);
const documentConfig = new DocumentBuilder() const documentConfig = new DocumentBuilder()
.setTitle('app') .setTitle(PackageJson.name)
.setDescription('The app') .setDescription(PackageJson.description)
.setVersion('1.0') .setVersion(PackageJson.version)
.build(); .build();
const document = SwaggerModule.createDocument(app, documentConfig); const document = SwaggerModule.createDocument(app, documentConfig);
......
import { IsBase64, IsString, MaxLength, MinLength } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
export class BindQueryDto {
@IsBase64()
@IsString()
@ApiProperty({ description: 'MyCard SSO' })
sso: string;
@IsString()
@MaxLength(64)
@MinLength(64)
@ApiProperty({ description: 'session ID' })
session: string;
decodeToken() {
const decoded = Buffer.from(this.sso, 'base64').toString();
const params = new URLSearchParams(decoded);
return params.get('token');
}
}
import { IntColumn, StringIdBase } from 'nicot';
import { Entity, Index } from 'typeorm';
@Entity()
export class User extends StringIdBase({ length: 50 }) {
@Index()
@IntColumn('int', {
unsigned: true,
description: 'MyCard ID',
required: false,
})
mycardId: number;
}
import { Test, TestingModule } from '@nestjs/testing';
import { MycardAccountController } from './mycard-account.controller';
describe('MycardAccountController', () => {
let controller: MycardAccountController;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
controllers: [MycardAccountController],
}).compile();
controller = module.get<MycardAccountController>(MycardAccountController);
});
it('should be defined', () => {
expect(controller).toBeDefined();
});
});
import {
Controller,
Get,
Header,
Query,
Render,
ValidationPipe,
} from '@nestjs/common';
import { MycardAccountService } from './mycard-account.service';
import { ApiOperation, ApiProduces } from '@nestjs/swagger';
import { BindQueryDto } from './dto/bind-query.dto';
import { TemplateService } from '../template/template.service';
@Controller('mycard-account')
export class MycardAccountController {
constructor(
private mycardAccountService: MycardAccountService,
private template: TemplateService,
) {}
@Get('bind')
@ApiOperation({
summary: '绑定帐号回调。',
})
@ApiProduces('text/html')
@Header('content-type', 'text/html')
@Header('cache-control', 'no-cache')
async bind(
@Query(
new ValidationPipe({
transform: true,
transformOptions: { enableImplicitConversion: true },
}),
)
dto: BindQueryDto,
) {
const view = await this.mycardAccountService.bindCallback(dto);
return this.template.render('bind-result.html', view, true);
}
}
import { Test, TestingModule } from '@nestjs/testing';
import { MycardAccountService } from './mycard-account.service';
describe('MycardAccountService', () => {
let service: MycardAccountService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [MycardAccountService],
}).compile();
service = module.get<MycardAccountService>(MycardAccountService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
import { Injectable } from '@nestjs/common';
import { CrudService } from 'nicot';
import { User } from './entities/user.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { PutUserId, UseCommand } from 'koishi-nestjs';
import { Aragami, CacheKey, CacheTTL } from 'aragami';
import { InjectAragami } from 'nestjs-aragami';
import cryptoRandomString from 'crypto-random-string';
import { MycardAuthService, MycardUser } from 'nestjs-mycard';
import { ConfigService } from '@nestjs/config';
import { BindQueryDto } from './dto/bind-query.dto';
@CacheTTL(1800)
class BindSession {
@CacheKey()
sessionId: string;
userId: string;
static create(userId: string) {
const s = new BindSession();
s.sessionId = cryptoRandomString({ length: 64, type: 'url-safe' });
s.userId = userId;
return s;
}
}
function loginUrl(callbackUrl: string) {
let params = new URLSearchParams();
params.set('return_sso_url', callbackUrl);
const payload = Buffer.from(params.toString()).toString('base64');
const url = new URL('https://accounts.moecube.com/signin');
params = url['searchParams'];
params.set('sso', payload);
return url.toString();
}
@Injectable()
export class MycardAccountService extends CrudService(User) {
private rootUrl = this.config.get<string>('ROOT_URL');
constructor(
@InjectRepository(User) repo,
@InjectAragami() private aragami: Aragami,
private mycard: MycardAuthService,
private config: ConfigService,
) {
super(repo);
}
async findOrCreateUser(id: string) {
let user = await this.repo.findOne({ where: { id } });
if (user) {
return user;
}
user = new User();
user.id = id;
return this.repo.save(user);
}
@UseCommand('unbind', '解绑 MyCard 帐号')
async unbind(@PutUserId() id: string) {
const user = await this.findOrCreateUser(id);
if (!user.mycardId) {
return '您还未绑定 MyCard 帐号。';
}
await this.repo.update({ id }, { mycardId: null });
return '解绑成功。';
}
@UseCommand('bind', '绑定 MyCard 帐号')
async bind(@PutUserId() id: string) {
const session = BindSession.create(id);
await this.aragami.set(session);
const url = loginUrl(
`${this.rootUrl}/api/mycard-account/bind?session=${session.sessionId}`,
);
return `请点击下面的链接完成 MyCard 帐号绑定:\n${url}`;
}
async bindCallback(
dto: BindQueryDto,
): Promise<{ error?: string; user?: MycardUser }> {
const session = await this.aragami.get(BindSession, dto.session);
if (!session) {
return { error: '会话不存在。' };
}
try {
const mycardUser = await this.mycard.getUserFromToken(dto.decodeToken());
await this.findOrCreateUser(session.userId);
await this.repo.update(
{ id: session.userId },
{ mycardId: mycardUser.id },
);
return { user: mycardUser };
} catch (e) {
return { error: e.message };
} finally {
await this.aragami.del(BindSession, dto.session);
}
}
}
import { ConsoleLogger, Injectable } from '@nestjs/common'; import { ConsoleLogger, Injectable } from '@nestjs/common';
import { UseEvent } from 'koishi-nestjs'; import { UseEvent } from 'koishi-nestjs';
import { Session } from 'koishi'; import { Session } from 'koishi';
import { TemplateService } from '../template/template.service';
@Injectable() @Injectable()
export class OnSubscribeService extends ConsoleLogger { export class OnSubscribeService extends ConsoleLogger {
constructor() { constructor(private template: TemplateService) {
super('OnSubscribeService'); super('OnSubscribeService');
} }
@UseEvent('wechat:subscribe') @UseEvent('wechat:subscribe')
async onSubscribe(session: Session) { async onSubscribe(session: Session) {
this.log(`User ${session.userId} subscribed.`); this.log(`User ${session.userId} subscribed.`);
await session.send( await session.send(this.template.render('on-subscribe'));
'欢迎关注决斗暗网!\n' +
'\n' +
'我们的菜单包含了各种功能,其中有游戏下载方式,玩家社区,举报反馈渠道等。',
);
} }
@UseEvent('wechat:unsubscribe') @UseEvent('wechat:unsubscribe')
......
import { Injectable, OnModuleInit } from '@nestjs/common'; import { Injectable, OnApplicationBootstrap } from '@nestjs/common';
import { InjectContext } from 'koishi-nestjs'; import { InjectContext } from 'koishi-nestjs';
import { Context } from 'koishi'; import { Context } from 'koishi';
import { TemplateService } from '../template/template.service';
@Injectable() @Injectable()
export class ReplyService implements OnModuleInit { export class ReplyService implements OnApplicationBootstrap {
replies: { key: string; content: string }[] = [ constructor(
{ @InjectContext() private ctx: Context,
key: 'download', private template: TemplateService,
content: ) {}
'下列都为游戏王YGOPro在各平台的软件,名字不同,但本质一样。MyCard平台会提供YGOPro和YGOPro2的下载与对战。\n' + onApplicationBootstrap() {
'安卓端YGOMobile下载:https://ygomobile.top\n' +
'苹果端KoishiPro iOS下载:https://koishi.pro/download/\n' +
'电脑端(包含Win和Mac)MyCard萌卡平台下载:https://mycard.moe',
},
{
key: 'servers',
content:
'1. MyCard服。电脑用户请使用MyCard客户端,安卓端用户点击【萌卡平台】,IOS端用户点击【MyCard】\n' +
'2. 233服。主机信息:s1.ygo233.com 端口:233。端口改为23333为先行卡服。\n' +
'3. Koishi服。主机信息:koishi.momobako.com 端口:7210。该服拥有断线重连。\n' +
'4. 轮抽2pick服。轮抽娱乐模式的服务器。 详情 https://ygobbs.com/t/87931\n' +
'5. 分级服。靠特殊卡表限制主流进场的服务器。详情 https://ygobbs.com/t/364147\n' +
'6. 游戏王Rush Duel服。遵循游戏王Rush Duel规则的服务器。详情 https://ygobbs.com/t/200563\n' +
'7. 高速决斗服。人物技能+游戏王5DS高速决斗模式。 详情 https://ygobbs.com/t/166971\n' +
'8. 诡异空间服。平衡的独立卡池,特殊规则服。详情 https://ygobbs.com/t/303983',
},
{
key: 'update',
content:
'安卓端YGOMobile:登录后会提示更新,手动更新请访问https://ygomobile.top\n' +
'苹果端KoishiPro2 iOS:用电脑使用爱思助手自签更新,教程请见 https://koishi.pro/download/\n' +
'电脑端MyCard会自动更新。若自动更新没触发,请在游戏大厅下方点击【校验完整性】更新。',
},
{
key: 'faq',
content:
'如果遇到了游戏安装、出BUG、下载等问题,请访问 https://ygobbs.com/t/108594\n' +
'如果遇到了游戏处理,规则类问题,请查看游戏王OCG规则修订书 https://ocg-rule.readthedocs.io/zh_CN/latest/ \n' +
'\n' +
'其他寻求帮助的方式:\n' +
'1. 在 ygobbs.com 搜索符合您问题描述的帖子,95%以上问题都有其他用户发帖询问过。\n' +
'2. 若没有,您可以在MC玩家社区 ygobbs.com 带上恰当的描述发帖寻求帮助,管理员会在36小时内回帖。\n' +
'3. 若问题很复杂,请加萌卡测试与 bug 反馈QQ群 553241437 询问。',
},
{
key: 'novelai',
content:
'由于AI绘图的普及,MC与各爱好贡献者们合作成立了YGOPro卡图娘化项目。\n' +
'现在为广大玩家们提供娘化补丁下载。\n' +
'详情与下载方式:https://ygobbs.com/t/396440',
},
];
constructor(@InjectContext() private ctx: Context) {}
onModuleInit() {
const base = this.ctx.command('reply', '默认回复。'); const base = this.ctx.command('reply', '默认回复。');
for (const reply of this.replies) { for (const templateName of this.template
base.subcommand(`.${reply.key}`).action(() => reply.content); .getTemplateList()
.filter((t) => t.startsWith('reply-'))) {
const commandName = templateName.slice(6);
base.subcommand(`.${commandName}`).action(() => {
return this.template.render(templateName, {});
});
} }
} }
} }
import { Test, TestingModule } from '@nestjs/testing';
import { TemplateService } from './template.service';
describe('TemplateService', () => {
let service: TemplateService;
beforeEach(async () => {
const module: TestingModule = await Test.createTestingModule({
providers: [TemplateService],
}).compile();
service = module.get<TemplateService>(TemplateService);
});
it('should be defined', () => {
expect(service).toBeDefined();
});
});
import { ConsoleLogger, Injectable, OnModuleInit } from '@nestjs/common';
import fs from 'fs';
import path from 'path';
import Mustache from 'mustache';
@Injectable()
export class TemplateService extends ConsoleLogger implements OnModuleInit {
private templates = new Map<string, string>();
constructor() {
super('TemplateService');
}
async onModuleInit() {
const fileList = await fs.promises.readdir('views');
for (const file of fileList) {
if (!file.endsWith('.mustache')) {
continue;
}
const template = file.slice(0, file.length - 9);
this.templates.set(
template,
await fs.promises.readFile(path.join('views', file), 'utf-8'),
);
this.log(`Loaded template ${template}`);
}
}
render(template: string, view: any = {}, htmlSafe = false) {
const text = this.templates.get(template);
if (!text) {
this.warn(`Template ${template} not found.`);
return template;
}
let result: string;
if (htmlSafe) {
result = Mustache.render(text, view);
} else {
result = Mustache.render(text, view, undefined, { escape: (v) => v });
}
return result.trim();
}
getTemplateList() {
return [...this.templates.keys()];
}
}
import yaml from 'yaml'; import yaml from 'yaml';
import * as fs from 'fs'; import * as fs from 'fs';
import * as process from 'process';
const defaultConfig = { const defaultConfig = {
host: '::', host: '::',
...@@ -17,6 +18,11 @@ const defaultConfig = { ...@@ -17,6 +18,11 @@ const defaultConfig = {
CDB_BRANCH: 'master', CDB_BRANCH: 'master',
FEEDBACK_NOTIFY_URL: '', FEEDBACK_NOTIFY_URL: '',
FEEDBACK_NOTIFY_TOKEN: 'default', FEEDBACK_NOTIFY_TOKEN: 'default',
REDIS_URL: 'redis://localhost:6379',
ROOT_URL:
process.env.NODE_ENV === 'production'
? 'https://jdaw.moecube.com'
: 'http://localhost:3000',
}; };
export type Config = typeof defaultConfig; export type Config = typeof defaultConfig;
......
...@@ -12,7 +12,8 @@ ...@@ -12,7 +12,8 @@
"baseUrl": "./", "baseUrl": "./",
"incremental": true, "incremental": true,
"esModuleInterop": true, "esModuleInterop": true,
"skipLibCheck": true "skipLibCheck": true,
"resolveJsonModule": true
}, },
"compileOnSave": true, "compileOnSave": true,
"allowJs": true "allowJs": true
......
{{#error}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>错误</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
min-height: 100vh;
flex-direction: column;
transform: translate(0, -10rem);
}
svg {
width: 400px;
height: 400px;
}
h2 {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 36px;
margin-top: 40px;
color: #333;
opacity: 1;
}
/*h2 {*/
/* animation: 0s title ease-in-out;*/
/* animation-delay: 0s;*/
/* animation-fill-mode: forwards;*/
/*}*/
.btn {
width: 60%;
padding: 1rem 3rem;
/*border: 1px solid green;*/
border-radius: 1rem;
color: white;
background-color: #8ae155;
}
.circle {
stroke-dasharray: 1194;
stroke-dashoffset: 1194;
}
.img1 {
translate: 0 -4em;
transform: scale(2);
width: 100px;
height: 100px;
background-color: red;
border-radius: 50px;
}
.img2 {
text-align: center;
transform: scale(1.5);
height: 100px;
line-height: 100px;
display: block;
color: #FFF;
/*text-align: center;*/
font-size: 60px
}
@keyframes circle {
from {
stroke-dashoffset: 1194;
}
to {
stroke-dashoffset: 2388;
}
}
/*控制外圈动画*/
/* svg .circle {*/
/* animation: circle 0.8s ease-in-out;*/
/* animation-fill-mode: forwards;*/
/* }*/
.tick {
stroke-dasharray: 350;
stroke-dashoffset: 350;
}
/*svg .tick {*/
/* animation: tick 0.8s ease-in-out;*/
/* animation-fill-mode: forwards;*/
/* animation-delay: .95s;*/
/*}*/
@keyframes title {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>
</head>
<body>
<div class="img1">
<span class="img2">!</span>
</div>
<br>
<h2>绑定错误: {{.}}</h2>
<h2 class="btn" id="btn-confirm">确定</h2>
<script type="text/javascript">
const closeButton = document.getElementById('btn-confirm');
closeButton.addEventListener('click', () => {
if(WeixinJSBridge) {
WeixinJSBridge.call('closeWindow');
} else {
window.close();
}
})
</script>
</body>
</html>
{{/error}}
{{^error}}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>提示</title>
<style>
body {
display: flex;
justify-content: center;
align-items: center;
text-align: center;
min-height: 100vh;
flex-direction: column;
transform: translate(0, -10rem);
}
svg {
width: 400px;
height: 400px;
}
h2 {
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, 'Open Sans', 'Helvetica Neue', sans-serif;
font-size: 36px;
margin-top: 40px;
color: #333;
opacity: 0;
}
h2 {
animation: .6s title ease-in-out;
animation-delay: 1.2s;
animation-fill-mode: forwards;
}
.btn {
width: 60%;
padding: 1rem 3rem;
/*border: 1px solid green;*/
border-radius: 1rem;
color: white;
background-color:#8ae155;
}
.circle {
stroke-dasharray: 1194;
stroke-dashoffset: 1194;
}
@keyframes circle {
from {
stroke-dashoffset: 1194;
}
to {
stroke-dashoffset: 2388;
}
}
/*控制外圈动画*/
svg .circle {
animation: circle 0.8s ease-in-out;
animation-fill-mode: forwards;
}
.tick {
stroke-dasharray: 350;
stroke-dashoffset: 350;
}
@keyframes tick {
from {
stroke-dashoffset: 350;
}
to {
stroke-dashoffset: 0;
}
}
svg .tick {
animation: tick 0.8s ease-in-out;
animation-fill-mode: forwards;
animation-delay: .95s;
}
@keyframes title {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
</style>
</head>
<body>
<svg>
<circle class="circle" fill="#8ae155" stroke="#8ae155" stroke-width="20" cx="200" cy="200" r="190"
stroke-linecap="round" transform="rotate(-90,200,200)"/>
<polyline class="tick" fill="none" stroke="white" stroke-width="24" points="88,214 173,284 304,138"
stroke-linecap="round" stroke-linejoin="round"/>
</svg>
<h2>MyCard 帐号 {{user.username}} 绑定成功</h2>
<h2 class="btn" id="btn-confirm">确定</h2>
<script type="text/javascript">
const closeButton = document.getElementById('btn-confirm');
closeButton.addEventListener('click', () => {
if(WeixinJSBridge) {
WeixinJSBridge.call('closeWindow');
} else {
window.close();
}
})
</script>
</body>
</html>
{{/error}}
\ No newline at end of file
举报BUG需要提交对战录像或截图。
举报玩家需提供充足的证据,例如骂人截图。
因此请到 ygobbs.com 发帖举报。感谢!
\ No newline at end of file
您的反馈种类是?(输入数字回复)
1. BUG或举报玩家不当行为
2. 游戏功能/改善
3. 游戏体验出问题(例如卡、掉线)
4. 其他反馈
\ No newline at end of file
您启动了反馈系统!您的下一段文字会作为反馈发给我们!
\ No newline at end of file
我们收到了您的周边反馈。
这是我们在决斗暗网服务号收到的第 {{count}} 个周边反馈!
\ No newline at end of file
感谢进入周边反馈功能!周边对 MC 来说至关重要,MC 需要周边来支持服务器维持。
如果您有任何对 MCPro 游戏周边的反馈,请留言于此,感谢!
我们会非常关心您对我们周边的意见和看法!
为此,希望您可以尽可能清晰表达您的意见,以便我们更好理解您的需求。
\ No newline at end of file
反馈成功!谢谢您的意见!
这是我们在决斗暗网服务号收到的第 {{count}} 个反馈!
\ No newline at end of file
欢迎访问 MC 有奖调研功能。目前暂时无进行中的调研。我们一般每 1-2 个月都会公布有奖调研,欢迎下次再查询。
\ No newline at end of file
欢迎关注决斗暗网!
我们的菜单包含了各种功能,其中有游戏下载方式,玩家社区,举报反馈渠道等。
\ No newline at end of file
下列都为游戏王 YGOPro 在各平台的软件,名字不同,但本质一样。MyCard平台会提供YGOPro和YGOPro2的下载与对战。
安卓端 YGOMobile 下载:https://ygomobile.top
苹果端 KoishiPro2 iOS 下载:https://koishi.pro/download/
电脑端(包含 Win 和 Mac)MyCard 萌卡平台下载:https://mycard.moe
\ No newline at end of file
如果遇到了游戏安装、出BUG、下载等问题,请访问 https://ygobbs.com/t/108594\n' +
如果遇到了游戏处理,规则类问题,请查看游戏王OCG规则修订书 https://ocg-rule.readthedocs.io/zh_CN/latest/
其他寻求帮助的方式:\n' +
1. 在 ygobbs.com 搜索符合您问题描述的帖子,95%以上问题都有其他用户发帖询问过。\n' +
2. 若没有,您可以在MC玩家社区 ygobbs.com 带上恰当的描述发帖寻求帮助,管理员会在36小时内回帖。\n' +
3. 若问题很复杂,请加萌卡测试与 bug 反馈QQ群 553241437 询问。',
\ No newline at end of file
由于 AI 绘图的普及,MC 与各爱好贡献者们合作成立了 YGOPro 卡图娘化项目。
现在为广大玩家们提供娘化补丁下载。
详情与下载方式:https://ygobbs.com/t/396440
\ No newline at end of file
1. MyCard服。电脑用户请使用MyCard客户端,安卓端用户点击【萌卡平台】,IOS端用户点击【MyCard】
2. 233服。主机信息:s1.ygo233.com 端口:233。端口改为23333为先行卡服。
3. Koishi服。主机信息:koishi.momobako.com 端口:7210。该服拥有断线重连。
4. 轮抽2pick服。轮抽娱乐模式的服务器。 详情 https://ygobbs.com/t/87931
5. 分级服。靠特殊卡表限制主流进场的服务器。详情 https://ygobbs.com/t/364147
6. 游戏王Rush Duel服。遵循游戏王Rush Duel规则的服务器。详情 https://ygobbs.com/t/200563
7. 高速决斗服。人物技能+游戏王5DS高速决斗模式。 详情 https://ygobbs.com/t/166971
8. 诡异空间服。平衡的独立卡池,特殊规则服。详情 https://ygobbs.com/t/303983
\ No newline at end of file
安卓端 YGOMobile:登录后会提示更新,手动更新请访问https://ygomobile.top
苹果端 KoishiPro2 iOS:用电脑使用爱思助手自签更新,教程请见 https://koishi.pro/download/
电脑端 MyCard 会自动更新。若自动更新没触发,请在游戏大厅下方点击【校验完整性】更新。
\ No newline at end of file
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment