commit dcd3c3c44539f2d013f9a489881c4d3e730cb203 Author: CaramelKat <32065563+caramelkat@users.noreply.github.com> Date: Sat Apr 25 00:00:42 2020 -0500 updated portal diff --git a/README.md b/README.md new file mode 100644 index 0000000..9f61fb5 --- /dev/null +++ b/README.md @@ -0,0 +1,12 @@ +# What is this? +This is the Pretendo Network Miiverse API Server, which replaces the former Nintendo Network Miiverse API Server *.olv.nintendo.net +# Install and usage +First install [NodeJS](https://nodejs.org) and [MongoDB](https://mongodb.com). Download/clone this repo and run `npm i` to install all dependencies. Edit `src/config.js` to your liking. Run the server via `npm run start`. +# To-Do +- [x] Discovery Server +- [ ] Posts Server +- [ ] Topic Server +- [ ] Communities Server +- [ ] Integrate with PN account server +# Currently implemented endpoints +- [GET] https://discovery.olv.nintendo.net/v1/endpoint diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..e552e03 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,856 @@ +{ + "name": "pretendoverse", + "version": "1.0.0", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@oozcitak/dom": { + "version": "0.0.11", + "resolved": "https://registry.npmjs.org/@oozcitak/dom/-/dom-0.0.11.tgz", + "integrity": "sha512-BUNzbWpSn0Y7Yo8qgjVCM0axw2A6ncZaY7iC8msZIpuL6vYDP19zRqYI5bYWgBkgDXiap4cFEFsFrauyYAgKnw==", + "requires": { + "@oozcitak/infra": "1.0.4", + "@oozcitak/url": "0.0.8", + "@oozcitak/util": "1.0.2" + }, + "dependencies": { + "@oozcitak/util": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", + "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==" + } + } + }, + "@oozcitak/infra": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.4.tgz", + "integrity": "sha512-PIYPFk/MUzdhdeEBWL8TOEmEHyN60pWDCzXdN6XyNQHwt1i0YNUCOZ434Qa8WNuwJlOCNTrZFK8nlirIOF06Eg==", + "requires": { + "@oozcitak/util": "1.0.2" + }, + "dependencies": { + "@oozcitak/util": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", + "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==" + } + } + }, + "@oozcitak/url": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@oozcitak/url/-/url-0.0.8.tgz", + "integrity": "sha512-PR1ZCwaYvm781f0V14y2Uu8CM94k/znGfNpzJive5XjuDuCtMDFB3MYhSdVNZDG95faupVuFTph2lzn38S0zKg==", + "requires": { + "@oozcitak/infra": "1.0.3", + "@oozcitak/util": "1.0.2", + "@oozcitak/uts46": "0.0.8" + }, + "dependencies": { + "@oozcitak/infra": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@oozcitak/infra/-/infra-1.0.3.tgz", + "integrity": "sha512-9O2wxXGnRzy76O1XUxESxDGsXT5kzETJPvYbreO4mv6bqe1+YSuux2cZTagjJ/T4UfEwFJz5ixanOqB0QgYAag==", + "requires": { + "@oozcitak/util": "1.0.1" + }, + "dependencies": { + "@oozcitak/util": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.1.tgz", + "integrity": "sha512-dFwFqcKrQnJ2SapOmRD1nQWEZUtbtIy9Y6TyJquzsalWNJsKIPxmTI0KG6Ypyl8j7v89L2wixH9fQDNrF78hKg==" + } + } + }, + "@oozcitak/util": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", + "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==" + } + } + }, + "@oozcitak/util": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.3.tgz", + "integrity": "sha512-md38Xc0kBJ8I4aBI13xtX7r4RtSi9HByNVaqcVQeal3PSSbPKmtX1l6+8/YbfaIcP+fyLuwnOxHpYoh/R2DONw==" + }, + "@oozcitak/uts46": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/@oozcitak/uts46/-/uts46-0.0.8.tgz", + "integrity": "sha512-/m/ytADxqWfGiNvenR5wkX7NGBRKQlypufv0w2NRAoWIGDuRLeweClJPRxV41Mln3HNtlF08OKoFFRUG8ztvGQ==", + "requires": { + "@oozcitak/util": "1.0.2", + "punycode": "2.1.1" + }, + "dependencies": { + "@oozcitak/util": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@oozcitak/util/-/util-1.0.2.tgz", + "integrity": "sha512-4n8B1cWlJleSOSba5gxsMcN4tO8KkkcvXhNWW+ADqvq9Xj+Lrl9uCa90GRpjekqQJyt84aUX015DG81LFpZYXA==" + } + } + }, + "accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==", + "requires": { + "mime-types": "~2.1.24", + "negotiator": "0.6.2" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "at-least-node": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", + "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "bl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.0.tgz", + "integrity": "sha512-wbgvOpqopSr7uq6fJrLH8EsvYMJf9gzfo2jCsL2eTy75qXPukA4pCgHamOQkZtY5vmfVtjB+P3LNlMHW5CEZXA==", + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + } + }, + "bluebird": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", + "integrity": "sha512-MKiLiV+I1AA596t9w1sQJ8jkiSr5+ZKi0WKrYGUn6d1Fx+Ij4tIj+m2WMQSGczs5jZVxV339chE8iwk6F64wjA==" + }, + "body-parser": { + "version": "1.19.0", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz", + "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==", + "requires": { + "bytes": "3.1.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "on-finished": "~2.3.0", + "qs": "6.7.0", + "raw-body": "2.4.0", + "type-is": "~1.6.17" + } + }, + "bson": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/bson/-/bson-1.1.3.tgz", + "integrity": "sha512-TdiJxMVnodVS7r0BdL42y/pqC9cL2iKynVwA0Ho3qbsQYr428veL3l7BQyuqiw+Q5SqqoT0m4srSY/BlZ9AxXg==" + }, + "bytes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz", + "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==" + }, + "colors": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.4.0.tgz", + "integrity": "sha512-a+UqTh4kgZg/SlGvfbzDHpgRu7AAQOmmqRHJnxhRZICKFUT91brVhNNt58CMWU9PsBbv3PDCZUHbVxuDiH2mtA==" + }, + "content-disposition": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz", + "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==", + "requires": { + "safe-buffer": "5.1.2" + } + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "cookie": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz", + "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==" + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "dank-each": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dank-each/-/dank-each-1.0.0.tgz", + "integrity": "sha1-qGE0Okso02IgPUBcd4ZNyaZANzA=", + "dev": true + }, + "dank-map": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dank-map/-/dank-map-0.1.0.tgz", + "integrity": "sha1-6Z5384LGjy5asrPzqCuAMZV1Kag=", + "dev": true + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "denque": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.4.1.tgz", + "integrity": "sha512-OfzPuSZKGcgr96rf1oODnfjqBFmr1DVoc/TrItj3Ohe0Ah1C5WX5Baquw/9U9KovnQ88EqmJbD66rKYUQYN1tQ==" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "express": { + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz", + "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==", + "requires": { + "accepts": "~1.3.7", + "array-flatten": "1.1.1", + "body-parser": "1.19.0", + "content-disposition": "0.5.3", + "content-type": "~1.0.4", + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "~1.1.2", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.5", + "qs": "6.7.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.1.2", + "send": "0.17.1", + "serve-static": "1.14.1", + "setprototypeof": "1.1.1", + "statuses": "~1.5.0", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + } + }, + "express-session": { + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/express-session/-/express-session-1.17.0.tgz", + "integrity": "sha512-t4oX2z7uoSqATbMfsxWMbNjAL0T5zpvcJCk3Z9wnPPN7ibddhnmDZXHfEcoBMG2ojKXZoCyPMc5FbtK+G7SoDg==", + "requires": { + "cookie": "0.4.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-headers": "~1.0.2", + "parseurl": "~1.3.3", + "safe-buffer": "5.2.0", + "uid-safe": "~2.1.5" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + }, + "safe-buffer": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.0.tgz", + "integrity": "sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg==" + } + } + }, + "express-subdomain": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/express-subdomain/-/express-subdomain-1.0.5.tgz", + "integrity": "sha1-mQ75eUC39MKCPZWTZIt5voWKY4s=" + }, + "finalhandler": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz", + "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.3", + "statuses": "~1.5.0", + "unpipe": "~1.0.0" + } + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs-extra": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.0.0.tgz", + "integrity": "sha512-pmEYSk3vYsG/bF651KPUXZ+hvjpgWYw/Gc7W9NFUe3ZVLczKKWIij3IKpOrQcdw4TILtibFslZ0UmR8Vvzig4g==", + "requires": { + "at-least-node": "^1.0.0", + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^1.0.0" + } + }, + "graceful-fs": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.3.tgz", + "integrity": "sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ==" + }, + "http-errors": { + "version": "1.7.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz", + "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.1", + "statuses": ">= 1.5.0 < 2", + "toidentifier": "1.0.0" + } + }, + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "jsonfile": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.0.1.tgz", + "integrity": "sha512-jR2b5v7d2vIOust+w3wtFKZIfpC2pnRmFAhAC/BuweZFQR8qZzxH1OyrQ10HmdVYiXWkYUqPVsz91cG7EL2FBg==", + "requires": { + "graceful-fs": "^4.1.6", + "universalify": "^1.0.0" + } + }, + "kareem": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/kareem/-/kareem-2.3.1.tgz", + "integrity": "sha512-l3hLhffs9zqoDe8zjmb/mAN4B8VT3L56EUvKNqLFVs9YlFA+zx7ke1DO8STAdDyYNkeSo1nKmjuvQeI12So8Xw==" + }, + "lodash.foreach": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.foreach/-/lodash.foreach-4.5.0.tgz", + "integrity": "sha1-Gmo16s5AEoDH8G3d7DUWWrJ+PlM=" + }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=" + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==" + }, + "mime-db": { + "version": "1.43.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.43.0.tgz", + "integrity": "sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ==" + }, + "mime-types": { + "version": "2.1.26", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.26.tgz", + "integrity": "sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ==", + "requires": { + "mime-db": "1.43.0" + } + }, + "moment": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.24.0.tgz", + "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==" + }, + "moment-timezone": { + "version": "0.5.28", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.28.tgz", + "integrity": "sha512-TDJkZvAyKIVWg5EtVqRzU97w0Rb0YVbfpqyjgu6GwXCAohVRqwZjf4fOzDE6p1Ch98Sro/8hQQi65WDXW5STPw==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "mongodb": { + "version": "3.5.4", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-3.5.4.tgz", + "integrity": "sha512-xGH41Ig4dkSH5ROGezkgDbsgt/v5zbNUwE3TcFsSbDc6Qn3Qil17dhLsESSDDPTiyFDCPJRpfd4887dtsPgKtA==", + "requires": { + "bl": "^2.2.0", + "bson": "^1.1.1", + "denque": "^1.4.1", + "require_optional": "^1.0.1", + "safe-buffer": "^5.1.2", + "saslprep": "^1.0.0" + } + }, + "mongoose": { + "version": "5.9.4", + "resolved": "https://registry.npmjs.org/mongoose/-/mongoose-5.9.4.tgz", + "integrity": "sha512-aUw4hzvJX9UJVN79JcElCwu/YsW1Sl/IDjErwiIX89xz77kmMjQjCmMsXGE1okUEcJGzGnXPqYl9BggXw8Nlvg==", + "requires": { + "bson": "~1.1.1", + "kareem": "2.3.1", + "mongodb": "3.5.4", + "mongoose-legacy-pluralize": "1.0.2", + "mpath": "0.6.0", + "mquery": "3.2.2", + "ms": "2.1.2", + "regexp-clone": "1.0.0", + "safe-buffer": "5.1.2", + "sift": "7.0.1", + "sliced": "1.0.1" + }, + "dependencies": { + "ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + } + } + }, + "mongoose-legacy-pluralize": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/mongoose-legacy-pluralize/-/mongoose-legacy-pluralize-1.0.2.tgz", + "integrity": "sha512-Yo/7qQU4/EyIS8YDFSeenIvXxZN+ld7YdV9LqFVQJzTLye8unujAWPZ4NWKfFA+RNjh+wvTWKY9Z3E5XM6ZZiQ==" + }, + "mongoose-unique-validator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/mongoose-unique-validator/-/mongoose-unique-validator-2.0.3.tgz", + "integrity": "sha512-3/8pmvAC1acBZS6eWKAWQUiZBlARE1wyWtjga4iQ2wDJeOfRlIKmAvTNHSZXKaAf7RCRUd7wh7as6yWAOrjpQg==", + "requires": { + "lodash.foreach": "^4.1.0", + "lodash.get": "^4.0.2" + } + }, + "morgan": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.0.tgz", + "integrity": "sha512-AbegBVI4sh6El+1gNwvD5YIck7nSA36weD7xvIxG4in80j/UoK8AEGaWnnz8v1GxonMCltmlNs5ZKbGvl9b1XQ==", + "requires": { + "basic-auth": "~2.0.1", + "debug": "2.6.9", + "depd": "~2.0.0", + "on-finished": "~2.3.0", + "on-headers": "~1.0.2" + }, + "dependencies": { + "depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==" + } + } + }, + "mpath": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/mpath/-/mpath-0.6.0.tgz", + "integrity": "sha512-i75qh79MJ5Xo/sbhxrDrPSEG0H/mr1kcZXJ8dH6URU5jD/knFxCVqVC/gVSW7GIXL/9hHWlT9haLbCXWOll3qw==" + }, + "mquery": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/mquery/-/mquery-3.2.2.tgz", + "integrity": "sha512-XB52992COp0KP230I3qloVUbkLUxJIu328HBP2t2EsxSFtf4W1HPSOBWOXf1bqxK4Xbb66lfMJ+Bpfd9/yZE1Q==", + "requires": { + "bluebird": "3.5.1", + "debug": "3.1.0", + "regexp-clone": "^1.0.0", + "safe-buffer": "5.1.2", + "sliced": "1.0.1" + }, + "dependencies": { + "debug": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "negotiator": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz", + "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==" + }, + "object-to-xml": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/object-to-xml/-/object-to-xml-2.0.0.tgz", + "integrity": "sha512-bArXy7WCF1V9R88/zF9adSZSeFQnFmmKhMqNuNLAxqrbkvzcWP8HgnaRCcVJsfvIgvpdHiYd0qzJi7LM7QFfcQ==", + "dev": true, + "requires": { + "dank-each": "^1.0.0", + "dank-map": "~0.1.0", + "sanitizer": "0.1.3" + } + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", + "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" + }, + "parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "proxy-addr": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz", + "integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.9.1" + } + }, + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==" + }, + "qs": { + "version": "6.7.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz", + "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==" + }, + "random-bytes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/random-bytes/-/random-bytes-1.0.0.tgz", + "integrity": "sha1-T2ih3Arli9P7lYSMMDJNt11kNgs=" + }, + "range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==" + }, + "raw-body": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz", + "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==", + "requires": { + "bytes": "3.1.0", + "http-errors": "1.7.2", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + } + }, + "readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "regexp-clone": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/regexp-clone/-/regexp-clone-1.0.0.tgz", + "integrity": "sha512-TuAasHQNamyyJ2hb97IuBEif4qBHGjPHBS64sZwytpLEqtBQ1gPJTnOaQ6qmpET16cK14kkjbazl6+p0RRv0yw==" + }, + "require_optional": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require_optional/-/require_optional-1.0.1.tgz", + "integrity": "sha512-qhM/y57enGWHAe3v/NcwML6a3/vfESLe/sGM2dII+gEO0BpKRUkWZow/tyloNqJyN6kXSl3RyyM8Ll5D/sJP8g==", + "requires": { + "resolve-from": "^2.0.0", + "semver": "^5.1.0" + } + }, + "resolve-from": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-2.0.0.tgz", + "integrity": "sha1-lICrIOlP+h2egKgEx+oUdhGWa1c=" + }, + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sanitizer": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/sanitizer/-/sanitizer-0.1.3.tgz", + "integrity": "sha1-1PCvdHXZp7ryqeWmEXGLqheKOeE=", + "dev": true + }, + "saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "requires": { + "sparse-bitfield": "^3.0.3" + } + }, + "semver": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz", + "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==" + }, + "send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz", + "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.7.2", + "mime": "1.6.0", + "ms": "2.1.1", + "on-finished": "~2.3.0", + "range-parser": "~1.2.1", + "statuses": "~1.5.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "serve-static": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz", + "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.17.1" + } + }, + "setprototypeof": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz", + "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==" + }, + "sift": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/sift/-/sift-7.0.1.tgz", + "integrity": "sha512-oqD7PMJ+uO6jV9EQCl0LrRw1OwsiPsiFQR5AR30heR+4Dl7jBBbDLnNvWiak20tzZlSE1H7RB30SX/1j/YYT7g==" + }, + "sliced": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sliced/-/sliced-1.0.1.tgz", + "integrity": "sha1-CzpmK10Ewxd7GSa+qCsD+Dei70E=" + }, + "sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha1-/0rm5oZWBWuks+eSqzM004JzyhE=", + "optional": true, + "requires": { + "memory-pager": "^1.0.2" + } + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "toidentifier": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", + "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==" + }, + "type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + } + }, + "uid-safe": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/uid-safe/-/uid-safe-2.1.5.tgz", + "integrity": "sha512-KPHm4VL5dDXKz01UuEd88Df+KzynaohSL9fBh096KWAxSKZQDI2uBrVqtvRM4rwrIrRRKsdLNML/lnaaVSRioA==", + "requires": { + "random-bytes": "~1.0.0" + } + }, + "universalify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-1.0.0.tgz", + "integrity": "sha512-rb6X1W158d7pRQBg5gkR8uPaSfiids68LTJQYOtEUhoJUWBdaQHsuT/EUduxXYxcrt4r5PJ4fuHW1MHT6p0qug==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "xmlbuilder": { + "version": "13.0.2", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-13.0.2.tgz", + "integrity": "sha512-Eux0i2QdDYKbdbA6AM6xE4m6ZTZr4G4xF9kahI2ukSEMCzwce2eX9WlTI5J3s+NU7hpasFsr8hWIONae7LluAQ==" + }, + "xmlbuilder2": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/xmlbuilder2/-/xmlbuilder2-0.0.4.tgz", + "integrity": "sha512-4l+sSxet6EkVooCNlNgcImwrUZrk5BMRlJV6xUH9y19rwbwxB+OMfvlWT0hppDcVLjWM0Mu6FnpV/UGB4y/Feg==", + "requires": { + "@oozcitak/dom": "0.0.11", + "@oozcitak/infra": "1.0.4", + "@oozcitak/util": "1.0.3" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..0b1c5bd --- /dev/null +++ b/package.json @@ -0,0 +1,30 @@ +{ + "name": "pretendoverse", + "version": "1.0.0", + "description": "Miiverse API Server", + "main": "./src/server.js", + "scripts": { + "start": "node ./src/server.js", + "test": "echo \"Error: no test specified\" && exit 1" + }, + "keywords": [], + "author": "Jemma", + "license": "ISC", + "dependencies": { + "colors": "^1.4.0", + "express": "^4.17.1", + "express-session": "^1.17.0", + "express-subdomain": "^1.0.5", + "fs-extra": "^9.0.0", + "moment": "^2.24.0", + "moment-timezone": "^0.5.27", + "mongoose": "^5.8.3", + "mongoose-unique-validator": "^2.0.3", + "morgan": "^1.10.0", + "xmlbuilder": "^13.0.2", + "xmlbuilder2": "0.0.4" + }, + "devDependencies": { + "object-to-xml": "^2.0.0" + } +} diff --git a/src/api/index.js b/src/api/index.js new file mode 100644 index 0000000..e69de29 diff --git a/src/config.json b/src/config.json new file mode 100644 index 0000000..0669adf --- /dev/null +++ b/src/config.json @@ -0,0 +1,13 @@ +{ + "http": { + "port": 8080 + }, + "mongoose": { + "uri": "mongodb://localhost:27017", + "database": "Miiverse", + "options": { + "useNewUrlParser": true, + "useUnifiedTopology": true + } + } +} \ No newline at end of file diff --git a/src/database.js b/src/database.js new file mode 100644 index 0000000..b4bb29a --- /dev/null +++ b/src/database.js @@ -0,0 +1,66 @@ +const mongoose = require('mongoose'); +const { mongoose: mongooseConfig } = require('./config.json'); +const { TOPIC } = require('./models/topic'); +const { ENDPOINT } = require('./models/endpoint'); +const { uri, database, options } = mongooseConfig; + +let connection; + +async function connect() { + await mongoose.connect(`${uri}/${database}`, options); + + connection = mongoose.connection; + connection.on('error', console.error.bind(console, 'connection error:')); +} + +function verifyConnected() { + if (!connection) { + throw new Error('Cannot make database requets without being connected'); + } +} + +async function getTopicByName(topicName) { + verifyConnected(); + + if (typeof topicName !== 'string') { + return null; + } + + return TOPIC.findOne({ + name: topicName + }); +} + +async function getTopicByCommunityID(communityID) { + verifyConnected(); + + if (typeof communityID !== 'string') { + return null; + } + + return TOPIC.findOne({ + community_id: communityID + }); +} + +async function getDiscoveryHosts() { + verifyConnected(); + return ENDPOINT.findOne({ + version: 1 + }); +} + +async function getServerConfig() { + verifyConnected(); + return ENDPOINT.findOne({ + type: "config" + }); +} + +module.exports = { + connect, + getTopicByName, + getTopicByCommunityID, + getDiscoveryHosts, + getServerConfig +}; \ No newline at end of file diff --git a/src/logger.js b/src/logger.js new file mode 100644 index 0000000..eda058e --- /dev/null +++ b/src/logger.js @@ -0,0 +1,52 @@ +const fs = require('fs-extra'); +require('colors'); + +const root = __dirname; +fs.ensureDirSync(`${root}/logs`); + +const streams = { + latest: fs.createWriteStream(`${root}/logs/latest.log`), + success: fs.createWriteStream(`${root}/logs/success.log`), + error: fs.createWriteStream(`${root}/logs/error.log`), + warn: fs.createWriteStream(`${root}/logs/warn.log`), + info: fs.createWriteStream(`${root}/logs/info.log`) +}; + +function success(input) { + const time = new Date(); + input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [SUCCESS]: ${input}`; + streams.success.write(`${input}\n`); + + console.log(`${input}`.green.bold); +} + +function error(input) { + const time = new Date(); + input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [ERROR]: ${input}`; + streams.error.write(`${input}\n`); + + console.log(`${input}`.red.bold); +} + +function warn(input) { + const time = new Date(); + input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [WARN]: ${input}`; + streams.warn.write(`${input}\n`); + + console.log(`${input}`.yellow.bold); +} + +function info(input) { + const time = new Date(); + input = `[${time.getHours()}:${time.getMinutes()}:${time.getSeconds()}] [INFO]: ${input}`; + streams.info.write(`${input}\n`); + + console.log(`${input}`.cyan.bold); +} + +module.exports = { + success, + error, + warn, + info +}; \ No newline at end of file diff --git a/src/middleware/client-header.js b/src/middleware/client-header.js new file mode 100644 index 0000000..e722968 --- /dev/null +++ b/src/middleware/client-header.js @@ -0,0 +1,38 @@ +const xmlbuilder = require('xmlbuilder'); + +const VALID_CLIENT_ID_SECRET_PAIRS = { + // 'Key' is the client ID, 'Value' is the client secret + 'a2efa818a34fa16b8afbc8a74eba3eda': 'c91cdb5658bd4954ade78533a339cf9a', // Possibly WiiU exclusive? + 'daf6227853bcbdce3d75baee8332b': '3eff548eac636e2bf45bb7b375e7b6b0', // Possibly 3DS exclusive? + 'ea25c66c26b403376b4c5ed94ab9cdea': 'd137be62cb6a2b831cad8c013b92fb55', // Possibly 3DS exclusive? +}; + + +function nintendoClientHeaderCheck(request, response, next) { + response.set('Content-Type', 'text/xml'); + response.set('Server', 'Nintendo 3DS (http)'); + response.set('X-Nintendo-Date', new Date().getTime()); + + const {headers} = request; + + if ( + !headers['x-nintendo-client-id'] || + !headers['x-nintendo-client-secret'] || + !VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']] || + headers['x-nintendo-client-secret'] !== VALID_CLIENT_ID_SECRET_PAIRS[headers['x-nintendo-client-id']] + ) { + return response.send(xmlbuilder.create({ + errors: { + error: { + cause: 'client_id', + code: '0004', + message: 'API application invalid or incorrect application credentials' + } + } + }).end()); + } + + return next(); +} + +module.exports = nintendoClientHeaderCheck; \ No newline at end of file diff --git a/src/middleware/pnid.js b/src/middleware/pnid.js new file mode 100644 index 0000000..5d47cde --- /dev/null +++ b/src/middleware/pnid.js @@ -0,0 +1,50 @@ +const xmlbuilder = require('xmlbuilder'); +const database = require('../database'); + +async function PNIDMiddleware(request, response, next) { + const { headers } = request; + + if (!headers.authorization || !(headers.authorization.startsWith('Bearer') || headers.authorization.startsWith('Basic'))) { + return next(); + } + + const [type, token] = headers.authorization.split(' '); + let user; + + if (type === 'Basic') { + user = await database.getUserBasic(token); + } else { + user = await database.getUserBearer(token); + } + + if (!user) { + response.status(401); + + if (type === 'Bearer') { + return response.send(xmlbuilder.create({ + errors: { + error: { + cause: 'access_token', + code: '0005', + message: 'Invalid access token' + } + } + }).end()); + } + + return response.send(xmlbuilder.create({ + errors: { + error: { + code: '1105', + message: 'Email address, username, or password, is not valid' + } + } + }).end()); + } + + request.pnid = user; + + return next(); +} + +module.exports = PNIDMiddleware; \ No newline at end of file diff --git a/src/middleware/session.js b/src/middleware/session.js new file mode 100644 index 0000000..e8b663f --- /dev/null +++ b/src/middleware/session.js @@ -0,0 +1,23 @@ +// super basic and there's probably a much better way to do this + +// this will only be used during the registration process, to track the progress of the user +// express-session uses cookies which the WiiU does not support during the registration process + +// temp, in-memory session storage +const sessionStore = {}; + +function sessionMiddlware(request, response, next) { + const ip = request.headers['x-forwarded-for'] || request.connection.remoteAddress; + + if (!sessionStore[ip]) { + sessionStore[ip] = {}; + } + + const session = sessionStore[ip]; + + request.session = session; + + return next(); +} + +module.exports = sessionMiddlware; \ No newline at end of file diff --git a/src/middleware/xml-parser.js b/src/middleware/xml-parser.js new file mode 100644 index 0000000..12fb614 --- /dev/null +++ b/src/middleware/xml-parser.js @@ -0,0 +1,35 @@ +const { document: xmlParser } = require('xmlbuilder2'); + +function XMLMiddleware(request, response, next) { + if (request.method == 'POST' || request.method == 'PUT') { + const headers = request.headers; + let body = ''; + + if ( + !headers['content-type'] || + !headers['content-type'].toLowerCase().includes('xml') + ) { + return next(); + } + + request.setEncoding('utf-8'); + request.on('data', (chunk) => { + body += chunk; + }); + + request.on('end', () => { + try { + request.body = xmlParser(body); + request.body = request.body.toObject(); + } catch (error) { + return next(); + } + + next(); + }); + } else { + next(); + } +} + +module.exports = XMLMiddleware; \ No newline at end of file diff --git a/src/models/endpoint.js b/src/models/endpoint.js new file mode 100644 index 0000000..41c29d8 --- /dev/null +++ b/src/models/endpoint.js @@ -0,0 +1,27 @@ +const { Schema, model } = require('mongoose'); + +const endpointSchema = new Schema({ + has_error: Number, + version: Number, + endpoint: { + host: String, + api_host: String, + portal_host: String, + n3ds_host: String + } +}); + +endpointSchema.methods.updateHosts = async function({host, api_host, portal_host, n3ds_host}) { + this.set('endpoint.host', host); + this.set('endpoint.api_host', api_host); + this.set('endpoint.portal_host', portal_host); + this.set('endpoint.n3ds_host', n3ds_host); + await this.save(); +}; + +const ENDPOINT = model('ENDPOINT', endpointSchema); + +module.exports = { + endpointSchema, + ENDPOINT +}; diff --git a/src/models/post.js b/src/models/post.js new file mode 100644 index 0000000..e69a38d --- /dev/null +++ b/src/models/post.js @@ -0,0 +1,71 @@ +const { Schema, model } = require('mongoose'); +//just testing pull requests +const PostSchema = new Schema({ + body: String, + community_id: String, + country_id: Number, + created_at: String, + feeling_id: Number, + id: Number, + is_autopost: { + type: Number, + default: 0 + }, + is_community_private_autopost: { + type: Number, + default: 0 + }, + is_spoiler: { + type: Number, + default: 0 + }, + is_app_jumpable: { + type: Number, + default: 0 + }, + empathy_count: { + type: Number, + default: 0 + }, + language_id: { + type: Number, + default: 1 + }, + mii: String, + mii_face_url: String, + number: { + type: Number, + default: 1 + }, + pid: Number, + platform_id: Number, + region_id: Number, + reply_count: { + type: Number, + default: 0 + }, + screen_name: String, + title_id: Number, +}); + + +PostSchema.methods.upEmpathy = async function() { + const empathy = this.get('empathy_count'); + this.set('empathy_count', empathy + 1); + + await this.save(); +}; + +PostSchema.methods.downEmpathy = async function() { + const empathy = this.get('empathy_count'); + this.set('empathy_count', empathy - 1); + + await this.save(); +}; + +const MiiversePost = model('MiiversePost', PostSchema); + +module.exports = { + PostSchema, + MiiversePost +}; \ No newline at end of file diff --git a/src/models/topic.js b/src/models/topic.js new file mode 100644 index 0000000..53f53ed --- /dev/null +++ b/src/models/topic.js @@ -0,0 +1,79 @@ +const { Schema, model } = require('mongoose'); +const { PostSchema } = require('./post'); + +const titleIdsSchema = new Schema({ + title_id: String, +}); + +const personSchema = new Schema({ + posts: { + type: [PostSchema], + default: undefined + } +}); + +const TopicSchema = new Schema({ + empathy_count: { + type: Number, + default: 0 + }, + has_shop_page: { + type: Number, + default: 0 + }, + icon: String, + title_ids: { + type: [titleIdsSchema], + default: undefined + }, + title_id: String, + community_id: String, + is_recommended: { + type: Number, + default: 0 + }, + name: String, + people: { + type: [personSchema], + default: undefined + }, +}); + +TopicSchema.methods.upEmpathy = async function() { + const empathy = this.get('empathy_count'); + this.set('empathy_count', empathy + 1); + + await this.save(); +}; + +TopicSchema.methods.downEmpathy = async function() { + const empathy = this.get('empathy_count'); + this.set('empathy_count', empathy - 1); + + await this.save(); +}; + +TopicSchema.pre('save', async function(next) { + if (!this.isModified('password')) { + return next(); + } + + this.set('usernameLower', this.get('username').toLowerCase()); + await this.generatePID(); + await this.generateNEXPassword(); + await this.generateEmailValidationCode(); + await this.generateEmailValidationToken(); + + const primaryHash = util.nintendoPasswordHash(this.get('password'), this.get('pid')); + const hash = bcrypt.hashSync(primaryHash, 10); + + this.set('password', hash); + next(); +}); + +const MiiverseTopic = model('MiiverseTopic', PostSchema); + +module.exports = { + TopicSchema, + MiiverseTopic +}; \ No newline at end of file diff --git a/src/server.js b/src/server.js new file mode 100644 index 0000000..1391f17 --- /dev/null +++ b/src/server.js @@ -0,0 +1,59 @@ +process.title = 'Pretendo - Miiverse'; + +const express = require('express'); +const morgan = require('morgan'); +const xmlparser = require('./middleware/xml-parser'); +const database = require('./database'); +const logger = require('./logger'); +const config = require('./config.json'); + +const { http: { port } } = config; +const app = express(); + +const miiverse = require('./services/miiverse-api'); + +app.set('etag', false); +app.disable('x-powered-by'); + +// Create router +logger.info('Setting up Middleware'); +app.use(morgan('dev')); +app.use(express.json()); +app.use(express.urlencoded({ + extended: true +})); +app.use(xmlparser); + +// import the servers into one +app.use(miiverse); + +// 404 handler +logger.info('Creating 404 status handler'); +app.use((request, response) => { + logger.warn(request.protocol + '://' + request.get('host') + request.originalUrl); + response.status(404); + response.send(); +}); + +// non-404 error handler +logger.info('Creating non-404 status handler'); +app.use((error, request, response) => { + const status = error.status || 500; + + response.status(status); + + response.json({ + app: 'api', + status, + error: error.message + }); +}); + +// Starts the server +logger.info('Starting server'); + +database.connect().then(() => { + app.listen(port, () => { + logger.success(`Server started on port ${port}`); + }); +}); \ No newline at end of file diff --git a/src/services/miiverse-api/index.js b/src/services/miiverse-api/index.js new file mode 100644 index 0000000..f0ba70a --- /dev/null +++ b/src/services/miiverse-api/index.js @@ -0,0 +1,31 @@ +const express = require('express'); +const subdomain = require('express-subdomain'); +const sessionMiddleware = require('../../middleware/session'); +const pnidMiddleware = require('../../middleware/pnid'); +const logger = require('../../logger'); +const routes = require('./routes'); + +// Main router for endpointsindex.js +const router = express.Router(); + +// Router to handle the subdomain restriction +const miiverse = express.Router(); +const portal = express.Router(); + +// Create subdomains +logger.info('[MIIVERSE] Creating \'discovery\' subdomain'); +router.use(subdomain('discovery.olv', miiverse)); + +logger.info('[MIIVERSE] Creating \'portal\' subdomain'); +router.use(subdomain('portal.olv', portal)); +router.use(subdomain('ctr-portal.olv', portal)); + +logger.info('[MIIVERSE] Importing middleware'); +miiverse.use(sessionMiddleware); +miiverse.use(pnidMiddleware); + +// Setup routes +miiverse.use('/v1/endpoint', routes.DISCOVERY); +portal.use('/', routes.PORTAL); + +module.exports = router; \ No newline at end of file diff --git a/src/services/miiverse-api/routes/discovery.js b/src/services/miiverse-api/routes/discovery.js new file mode 100644 index 0000000..9891402 --- /dev/null +++ b/src/services/miiverse-api/routes/discovery.js @@ -0,0 +1,162 @@ +var express = require('express'); +var xml = require('object-to-xml'); +const database = require('../../../database'); +var router = express.Router(); + +/* GET discovery server. */ +router.get('/', function (req, res) { + database.connect().then(async e => { + const discovery = await database.getDiscoveryHosts(); + switch(discovery.has_error) + { + case 0 : + res.set("Content-Type", "application/xml"); + response = { + result: { + has_error: 0, + version: discovery.version, + endpoint: { + host: discovery.endpoint.host, + api_host: discovery.endpoint.api_host, + portal_host: discovery.endpoint.portal_host, + n3ds_host: discovery.endpoint.n3ds_host + } + } + }; + res.send("\n" + xml(response)); + break; + case 1 : + res.set("Content-Type", "application/xml"); + res.statusCode = 400; + response = { + result: { + has_error: 1, + version: 1, + code: 400, + error_code: 1, + message: "SYSTEM_UPDATE_REQUIRED" + } + }; + res.send("\n" + xml(response)); + break; + case 2 : + res.set("Content-Type", "application/xml"); + res.statusCode = 400; + response = { + result: { + has_error: 1, + version: 1, + code: 400, + error_code: 2, + message: "SETUP_NOT_COMPLETE" + } + }; + res.send("\n" + xml(response)); + break; + case 3 : + res.set("Content-Type", "application/xml"); + res.statusCode = 400; + response = { + result: { + has_error: 1, + version: 1, + code: 400, + error_code: 3, + message: "SERVICE_MAINTENANCE" + } + }; + res.send("\n" + xml(response)); + break; + case 4: + res.set("Content-Type", "application/xml"); + res.statusCode = 400; + response = { + result: { + has_error: 1, + version: 1, + code: 400, + error_code: 4, + message: "SERVICE_CLOSED" + } + }; + res.send("\n" + xml(response)); + break; + case 5 : + res.set("Content-Type", "application/xml"); + res.statusCode = 400; + response = { + result: { + has_error: 1, + version: 1, + code: 400, + error_code: 5, + message: "PARENTAL_CONTROLS_ENABLED" + } + }; + res.send("\n" + xml(response)); + break; + case 6 : + res.set("Content-Type", "application/xml"); + res.statusCode = 400; + response = { + result: { + has_error: 1, + version: 1, + code: 400, + error_code: 6, + message: "POSTING_LIMITED_PARENTAL_CONTROLS" + } + }; + res.send("\n" + xml(response)); + break; + case 7 : + res.set("Content-Type", "application/xml"); + res.statusCode = 400; + response = { + result: { + has_error: 1, + version: 1, + code: 400, + error_code: 7, + message: "PNID_BANNED" + } + }; + res.send("\n" + xml(response)); + break; + default : + res.set("Content-Type", "application/xml"); + res.statusCode = 400; + response = { + result: { + has_error: 1, + version: 1, + code: 400, + error_code: 15, + message: "SERVER_ERROR" + } + }; + res.send("\n" + xml(response)); + break; + } + + }).catch(error => { + res.set("Content-Type", "application/xml"); + res.statusCode = 400; + response = { + result: { + has_error: 1, + version: 1, + code: 400, + error_code: 15, + message: "SERVER_ERROR" + } + }; + res.send("\n" + xml(response)); + }); +}); + +router.post('/posts', function (req, res) { + res.sendStatus(200); +}); + +module.exports = router; diff --git a/src/services/miiverse-api/routes/index.js b/src/services/miiverse-api/routes/index.js new file mode 100644 index 0000000..6297d92 --- /dev/null +++ b/src/services/miiverse-api/routes/index.js @@ -0,0 +1,4 @@ +module.exports = { + DISCOVERY: require('./discovery'), + PORTAL: require('./portal'), +}; \ No newline at end of file diff --git a/src/services/miiverse-api/routes/portal.html b/src/services/miiverse-api/routes/portal.html new file mode 100644 index 0000000..e5d8c31 --- /dev/null +++ b/src/services/miiverse-api/routes/portal.html @@ -0,0 +1,17 @@ + + +
+Did I win yet? :p
+ + + \ No newline at end of file diff --git a/src/services/miiverse-api/routes/portal.js b/src/services/miiverse-api/routes/portal.js new file mode 100644 index 0000000..b872790 --- /dev/null +++ b/src/services/miiverse-api/routes/portal.js @@ -0,0 +1,16 @@ +var express = require('express'); +var xml = require('object-to-xml'); +const database = require('../../../database'); +var router = express.Router(); +var path = require("path"); + +/* GET discovery server. */ +router.get('/', function (req, res) { + res.sendFile(path.join(__dirname + '/portal.html')); +}); + +router.post('/posts', function (req, res) { + res.sendStatus(200); +}); + +module.exports = router; diff --git a/src/testingDatabase.js b/src/testingDatabase.js new file mode 100644 index 0000000..31a9a1f --- /dev/null +++ b/src/testingDatabase.js @@ -0,0 +1,23 @@ +const { ENDPOINT } = require('./models/endpoint'); +const database = require('./database'); + + + +const doc = { + has_error: 0, + version: 1, + endpoint: { + host: "host1", + api_host: "host2", + portal_host: "host3", + n3ds_host: "host4" + } +}; +const newEndpoint = new ENDPOINT(doc); +database.connect().then(async yeet => { + const temp = await database.getServerConfig(); + console.log(temp); +}); +//database.getDiscoveryHosts().then(r => console.log(r.endpoint)); + +//newEndpoint.save().catch(error => {console.log(error);}); \ No newline at end of file