diff --git a/package-lock.json b/package-lock.json index 62a62b7..556d667 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1032,6 +1032,11 @@ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz", "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==" }, + "pako": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz", + "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==" + }, "parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -1048,6 +1053,11 @@ "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=", "dev": true }, + "pngjs": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-5.0.0.tgz", + "integrity": "sha512-40QW5YalBNfQo5yRYmiw7Yz6TKKVr3h6970B2YE+3fQpsWcrbj1PzJgxeJ19DRQjhMbKPIuMY8rFaXc8moolVw==" + }, "process-nextick-args": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", @@ -1296,6 +1306,14 @@ "safe-buffer": "~5.1.0" } }, + "tga": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/tga/-/tga-1.0.3.tgz", + "integrity": "sha1-fokbRRMIshi0gtvMna5nWWboIrM=", + "requires": { + "debug": "^2.6.1" + } + }, "toidentifier": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz", diff --git a/package.json b/package.json index b209dd5..29541ba 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,9 @@ "morgan": "^1.10.0", "node-rsa": "^1.0.8", "node-snowflake": "0.0.1", + "pako": "^1.0.11", + "pngjs": "^5.0.0", + "tga": "^1.0.3", "xmlbuilder": "^13.0.2", "xmlbuilder2": "0.0.4" }, diff --git a/src/database.js b/src/database.js index 811fc78..efa8da3 100644 --- a/src/database.js +++ b/src/database.js @@ -46,6 +46,11 @@ async function getTopicByCommunityID(communityID) { }); } +async function getCommunities(numberOfPosts) { + verifyConnected(); + return COMMUNITY.find({}).limit(numberOfPosts); +} + async function getCommunityByTitleID(title_id) { verifyConnected(); return COMMUNITY.findOne({ @@ -71,10 +76,9 @@ async function getPostByID(postID) { async function getPostsByCommunity(community, numberOfPosts) { verifyConnected(); - return POST.find({ title_id: community.title_id - }).limit(numberOfPosts.value); + }).limit(numberOfPosts); } async function getPostsByCommunityKey(community, numberOfPosts, search_key) { @@ -109,8 +113,7 @@ async function getServerConfig() { module.exports = { connect, - getTopicByName, - getTopicByCommunityID, + getCommunities, getCommunityByTitleID, getCommunityByID, getDiscoveryHosts, diff --git a/src/models/post.js b/src/models/post.js index c454c3f..e5bb78e 100644 --- a/src/models/post.js +++ b/src/models/post.js @@ -6,6 +6,7 @@ const PostSchema = new Schema({ body: String, app_data: String, painting: String, + painting_uri: String, screenshot: String, url: String, search_key: { diff --git a/src/server.js b/src/server.js index fad87d4..e093a1c 100644 --- a/src/server.js +++ b/src/server.js @@ -10,6 +10,7 @@ const { http: { port } } = config; const app = express(); const miiverse = require('./services/miiverse-api'); +const webApi = require('./services/web-api'); app.set('etag', false); app.disable('x-powered-by'); @@ -26,6 +27,7 @@ app.use(xmlparser); // import the servers into one app.use(miiverse); +app.use(webApi); // 404 handler logger.info('Creating 404 status handler'); diff --git a/src/services/miiverse-api/index.js b/src/services/miiverse-api/index.js index 02fedec..6b14658 100644 --- a/src/services/miiverse-api/index.js +++ b/src/services/miiverse-api/index.js @@ -17,7 +17,7 @@ logger.info('[MIIVERSE] Creating \'discovery\' subdomain'); router.use(subdomain('discovery.olv', discovery)); logger.info('[MIIVERSE] Creating \'api\' subdomain'); router.use(subdomain('api.olv', api)); -router.use(subdomain('4034a63d', discovery)); +router.use(subdomain('d551f9ba', api)); logger.info('[MIIVERSE] Importing middleware'); diff --git a/src/services/miiverse-api/routes/post.js b/src/services/miiverse-api/routes/post.js index f99c01c..ca11e06 100644 --- a/src/services/miiverse-api/routes/post.js +++ b/src/services/miiverse-api/routes/post.js @@ -23,8 +23,10 @@ router.post('/', upload.none(), async function (req, res, next) { appData = req.body.app_data.replace(/\0/g, "").trim(); } let painting = ""; + let painting_uri = ""; if (req.body.painting) { painting = req.body.painting.replace(/\0/g, "").trim(); + painting_uri = util.data.processPainting(painting); } let screenshot = ""; if (req.body.screenshot) { @@ -36,6 +38,7 @@ router.post('/', upload.none(), async function (req, res, next) { body: req.body.body, app_data: appData, painting: painting, + painting_uri: painting_uri, screenshot: screenshot, url: req.body.url, search_key: req.body.search_key, @@ -62,9 +65,6 @@ router.post('/', upload.none(), async function (req, res, next) { catch (e) { console.error(e); - } - finally - { res.set("Content-Type", "application/xml"); res.statusCode = 400; response = { diff --git a/src/services/web-api/index.js b/src/services/web-api/index.js new file mode 100644 index 0000000..bce39dd --- /dev/null +++ b/src/services/web-api/index.js @@ -0,0 +1,23 @@ +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 api = express.Router(); + +// Create subdomains +logger.info('[MIIVERSE] Creating \'web api\' subdomain'); +router.use(subdomain('web.olv', api)); + +// Setup routes +api.use('/', routes.PORTAL); +api.use('/v1/communities/', routes.COMMUNITY); +api.use('/v1/post/', routes.POST); + +module.exports = router; \ No newline at end of file diff --git a/src/services/web-api/routes/communities.js b/src/services/web-api/routes/communities.js new file mode 100644 index 0000000..cab51d3 --- /dev/null +++ b/src/services/web-api/routes/communities.js @@ -0,0 +1,30 @@ +var express = require('express'); +var router = express.Router(); +const database = require('../../../database'); +const comPostGen = require('../../../util/CommunityPostGen'); +const processHeaders = require('../../../util/authentication'); + +/* GET post titles. */ +router.get('/list', function (req, res) { + database.connect().then(async e => { + /* Parse out parameters from URL and headers */ + //const paramPack = processHeaders.data.decodeParamPack(req.headers["x-nintendo-parampack"]); + //"[0:1]=1407375153523200" + let community = await database.getCommunities(5); + console.log(community.length); + let body = '
\n' + + '
'; + body += ''; + res.send('' + + '' + '' + body + ''); + + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/src/services/web-api/routes/index.js b/src/services/web-api/routes/index.js new file mode 100644 index 0000000..3126d7a --- /dev/null +++ b/src/services/web-api/routes/index.js @@ -0,0 +1,6 @@ +module.exports = { + //DISCOVERY: require('./discovery'), + POST: require('./post'), + COMMUNITY: require('./communities'), + PORTAL: require('./portal'), +}; \ No newline at end of file diff --git a/src/services/web-api/routes/portal.js b/src/services/web-api/routes/portal.js new file mode 100644 index 0000000..9a2e246 --- /dev/null +++ b/src/services/web-api/routes/portal.js @@ -0,0 +1,69 @@ +var express = require('express'); +var router = express.Router(); +const database = require('../../../database'); +const comPostGen = require('../../../util/CommunityPostGen'); +const processHeaders = require('../../../util/authentication'); + +/* GET post titles. */ +router.get('/', function (req, res) { + res.send( + '\n' + + '\n' + + '\n' + + '\n' + + '

Miiverse Temp Admin Pannel

\n' + + '\n' + + '
\n' + + '
\n' + + '
\n' + + '
\n' + + '\n' + + '\n' + + '\n' + + '\n' + + '\n' + ) +}); + +module.exports = router; \ No newline at end of file diff --git a/src/services/web-api/routes/post.js b/src/services/web-api/routes/post.js new file mode 100644 index 0000000..89ed8a9 --- /dev/null +++ b/src/services/web-api/routes/post.js @@ -0,0 +1,34 @@ +var express = require('express'); +var router = express.Router(); +const database = require('../../../database'); + +router.get('/', function (req, res) { + database.connect().then(async e => { + /* Parse out parameters from URL and headers */ + //const paramPack = processHeaders.data.decodeParamPack(req.headers["x-nintendo-parampack"]); + //"[0:1]=1407375153523200" + let community = await database.getCommunityByID(req.query.community_id); + console.log(community); + let posts = await database.getPostsByCommunity(community, parseInt(req.query.limit)); + console.log(posts.length); + let body = '' + + '' + + '' + + '' + + '' + + ''; + for(let i = 0; i < posts.length; i++) + { + body += '' + '' + + '' + + '' + + ''; + } + body += '' + '
Screen NameBody TextYeah CountPainting
' + posts[i].screen_name + '' + posts[i].body + '' + posts[i].empathy_count + '
'; + res.send('' + + '' + '' + body + ''); + + }); +}); + +module.exports = router; \ No newline at end of file diff --git a/src/util/authentication.js b/src/util/authentication.js index 4201e22..0dae469 100644 --- a/src/util/authentication.js +++ b/src/util/authentication.js @@ -6,6 +6,9 @@ const xmlParser = require('xml2json'); const request = require("request"); const moment = require('moment'); const { USER } = require('../models/user'); +let TGA = require('tga'); +let pako = require('pako'); +let PNG = require('pngjs').PNG; let methods = { processUser: function(pid) { @@ -44,7 +47,26 @@ let methods = { }); }); }, - + processPainting: function (painting) { + let paintingBuffer = Buffer.from(painting, 'base64'); + let output = ''; + try + { + output = pako.inflate(paintingBuffer); + } + catch (err) + { + console.log(err); + } + let tga = new TGA(Buffer.from(output)); + let png = new PNG({ + width: tga.width, + height: tga.height + }); + png.data = tga.pixels; + let pngBuffer = PNG.sync.write(png); + return `data:image/png;base64,${pngBuffer.toString('base64')}`; + }, decodeParamPack: function (paramPack) { /* Decode base64 */ let dec = Buffer.from(paramPack, "base64").toString("ascii");