diff --git a/src/models/post.js b/src/models/post.js index 510d430..9fc2fbb 100644 --- a/src/models/post.js +++ b/src/models/post.js @@ -43,6 +43,10 @@ const PostSchema = new Schema({ type: Number, default: 0 }, + country_id: { + type: Number, + default: 49 + }, language_id: { type: Number, default: 1 diff --git a/src/services/miiverse-api/routes/communities.js b/src/services/miiverse-api/routes/communities.js index 9764bf5..d5ec646 100644 --- a/src/services/miiverse-api/routes/communities.js +++ b/src/services/miiverse-api/routes/communities.js @@ -36,27 +36,6 @@ router.get('/new', async function (req, res) { } else res.sendStatus(404); }); -router.get('/0/posts', async function (req, res) { - const paramPack = processHeaders.data.decodeParamPack(req.headers["x-nintendo-parampack"]); - let community = await database.getCommunityByTitleID(paramPack.title_id); - if(community != null) - { - let posts; - if(req.query.search_key) - posts = await database.getPostsByCommunityKey(community, parseInt(req.query.limit), req.query.search_key); - else - posts = await database.getPostsByCommunity(community, parseInt(req.query.limit)); - /* Build formatted response and send it off. */ - let options = { - name: 'posts', - with_mii: req.query.with_mii === 1 - } - res.contentType("application/xml"); - res.send(await comPostGen.PostsResponse(posts, community, options)); - } - else res.sendStatus(404); -}); - router.get('/:appID/posts', async function (req, res) { const paramPack = processHeaders.data.decodeParamPack(req.headers["x-nintendo-parampack"]); let community = await COMMUNITY.findOne({ app_id: req.params.appID }); @@ -67,20 +46,35 @@ router.get('/:appID/posts', async function (req, res) { let query = { community_id: community.app_id ? community.app_id : community.community_id, removed: false, - app_data: { $ne: null } + app_data: { $ne: null }, + message_to_pid: { $eq: null } } if(req.query.search_key) - query.search_key = search_key; + query.search_key = req.query.search_key; if(!req.query.allow_spoiler) query.is_spoiler = 0; + if(req.query.by === 'followings') { + let userContent = await database.getUserContent(req.pid); + query.pid = userContent.following_users; + } - let posts = await POST.find(query).sort({ created_at: -1}).limit(parseInt(req.query.limit)); + let posts; + if(req.query.distinct_pid === '1') + posts = await POST.aggregate([ + { $match: query }, // filter based on input query + { $sort: { created_at: -1 } }, // sort by 'created_at' in descending order + { $group: { _id: '$pid', doc: { $first: '$$ROOT' } } }, // remove any duplicate 'pid' elements + { $replaceRoot: { newRoot: '$doc' } }, // replace the root with the 'doc' field + { $limit: (req.query.limit ? Number(req.query.limit) : 10) } // only return the top 8 results + ]); + else + posts = await POST.find(query).sort({ created_at: -1}).limit(parseInt(req.query.limit)); /* Build formatted response and send it off. */ let options = { name: 'posts', - with_mii: req.query.with_mii === 1 + with_mii: req.query.with_mii === '1' } res.contentType("application/xml"); res.send(await comPostGen.PostsResponse(posts, community, options)); diff --git a/src/services/miiverse-api/routes/people.js b/src/services/miiverse-api/routes/people.js index 94fbd8d..0054dac 100644 --- a/src/services/miiverse-api/routes/people.js +++ b/src/services/miiverse-api/routes/people.js @@ -2,31 +2,51 @@ const express = require('express'); const router = express.Router(); const database = require('../../../database'); const xmlGenerator = require('../../../util/xmlResponseGenerator'); +const processHeaders = require("../../../util/util"); +const {COMMUNITY} = require("../../../models/communities"); +const {POST} = require("../../../models/post"); +const comPostGen = require("../../../util/xmlResponseGenerator"); /* GET post titles. */ router.get('/', async function (req, res) { - let community = await database.getCommunityByTitleID(1407375153321472); - if(community != null) - { - let posts; - if(req.query.search_key) - posts = await database.getPostsByCommunityKey(community, parseInt(req.query.limit), req.query.search_key); - else - posts = await database.getPostsByCommunity(community, parseInt(req.query.limit)); + let userContent = await database.getUserContent(req.pid); - /* Build formatted response and send it off. */ - let options = { - name: 'people', - with_mii: req.query.with_mii === 1 - } - res.contentType("application/xml"); - res.send(await xmlGenerator.PostsResponse(posts, community, options)); + let query = { + removed: false, + app_data: { $eq: null }, + message_to_pid: { $eq: null } } + + if(req.query.relation === 'friend') { + query.pid = { $in: userContent.following_users.map(i=>Number(i)) }; + } + else if(req.query.relation === 'following') { + query.pid = { $in: userContent.followed_users.map(i=>Number(i)) }; + } + else if(req.query.pid) { + query.pid = { $in: req.query.pid.map(i=>Number(i)) } + } + let posts; + if(req.query.distinct_pid === '1') + posts = await POST.aggregate([ + { $match: query }, // filter based on input query + { $sort: { created_at: -1 } }, // sort by 'created_at' in descending order + { $group: { _id: '$pid', doc: { $first: '$$ROOT' } } }, // remove any duplicate 'pid' elements + { $replaceRoot: { newRoot: '$doc' } }, // replace the root with the 'doc' field + { $limit: (req.query.limit ? Number(req.query.limit) : 10) } // only return the top 8 results + ]); + else if(req.query.is_hot === '1') + posts = await POST.find(query).sort({ empathy_count: -1}).limit(parseInt(req.query.limit)); else - { - res.status(404); - res.send(); + posts = await POST.find(query).sort({ created_at: -1}).limit(parseInt(req.query.limit)); + + /* Build formatted response and send it off. */ + let options = { + name: 'posts', + with_mii: req.query.with_mii === '1' } + res.contentType("application/xml"); + res.send(await comPostGen.People(posts, options)); }); router.get('/:pid/following', async function (req, res) { @@ -34,7 +54,7 @@ router.get('/:pid/following', async function (req, res) { if(!user) res.sendStatus(404); let people = await database.getFollowedUsers(user); if(!people) res.sendStatus(404); - res.send(await xmlGenerator.People(people)); + res.send(await xmlGenerator.Following(people)); }); module.exports = router; diff --git a/src/services/miiverse-api/routes/post.js b/src/services/miiverse-api/routes/post.js index 281ea4c..217d68f 100644 --- a/src/services/miiverse-api/routes/post.js +++ b/src/services/miiverse-api/routes/post.js @@ -35,15 +35,38 @@ router.post('/:post_id/empathies', upload.none(), async function (req, res) { res.sendStatus(403); return; } - let user = await database.getUserContent(pid); - if(user.likes.indexOf(post.id) === -1 && user.id !== post.pid) + let userContent = await database.getUserContent(req.pid); + if(userContent.likes.indexOf(post.id) === -1 && userContent.pid !== post.pid) { - post.upEmpathy(); - user.addToLikes(post.id) - res.sendStatus(200); + if(post.empathy_count < 0) { + await POST.updateOne( + { id: post.id }, + { $set: { empathy_count: 1 } } + ); + } + else { + await POST.updateOne( + { id: post.id }, + { $inc: { empathy_count: 1 } } + ); + } + userContent.addToLikes(post.id); + } else if(userContent.likes.indexOf(post.id) !== -1 && userContent.pid !== post.pid) { + if(post.empathy_count < 0) { + await POST.updateOne( + { id: post.id }, + { $set: { empathy_count: 0 } } + ); + } + else { + await POST.updateOne( + { id: post.id }, + { $inc: { empathy_count: -1 } } + ); + } + userContent.removeFromLike(post.id); } - else - res.sendStatus(200); + res.sendStatus(200); }); router.get('/:post_id/replies', async function (req, res) { diff --git a/src/util/xmlResponseGenerator.js b/src/util/xmlResponseGenerator.js index 80e25ed..db49b1c 100644 --- a/src/util/xmlResponseGenerator.js +++ b/src/util/xmlResponseGenerator.js @@ -163,12 +163,12 @@ class XmlResponseGenerator { } /** - * Generate response to /v1/people + * Generate response to /v1/users/:pid/following * @param people * @returns xml * @constructor */ - static async People(people) { + static async Following(people) { let xml = xmlbuilder.create("result", { encoding: 'UTF-8' }) .e("has_error", "0").up() .e("version", "1").up() @@ -182,6 +182,31 @@ class XmlResponseGenerator { } return xml.up().end({ pretty: true, allowEmpty: true}); } + + /** + * Generate response to /v1/people + * @param posts + * @param options + * @returns xml + * @constructor + */ + static async People(posts, options) { + const expirationDate = moment().add(1, 'days'); + let xml = xmlbuilder.create("result", { encoding: 'UTF-8' }) + .e("has_error", "0").up() + .e("version", "1").up() + .e("expire", expirationDate.format('YYYY-MM-DD HH:MM:SS')).up() + .e("request_name", options.name).up() + .e("people"); + for (const post of posts) { + xml = xml.e("person") + .e("posts") + postObj(xml, post, options); + xml = xml.up().up(); + } + xml = xml.up(); + return xml.end({ pretty: true, allowEmpty: true }); + } } /** @@ -197,8 +222,8 @@ function postObj(xml, post, options) { } xml.e("body", post.body ? post.body.replace(/[^A-Za-z\d\s-_!@#$%^&*(){}+=,.<>/?;:'"\[\]]/g, "") : "").up() .e("community_id", post.community_id).up() - .e("country_id", post.country_id).up() - .e("created_at", post.created_at).up() + .e("country_id", post.country_id ? post.country_id : 254).up() + .e("created_at", new moment(post.created_at).format('YYYY-MM-DD HH:MM:SS')).up() .e("feeling_id", post.feeling_id).up() .e("id", post.id).up() .e("is_autopost", post.is_autopost).up() @@ -207,7 +232,7 @@ function postObj(xml, post, options) { .e("is_app_jumpable", post.is_app_jumpable).up() .e("empathy_count", post.empathy_count).up() .e("language_id", post.language_id).up(); - if(post.mii && options.with_mii) { + if(options.with_mii) { xml.e("mii", post.mii.replace(/[^A-Za-z0-9+/=]/g, "").replace(/[\n\r]+/gm, '').trim()).up() .e("mii_face_url", post.mii_face_url).up() } @@ -215,7 +240,7 @@ function postObj(xml, post, options) { if (post.painting) { xml.e("painting") .e("format", "tga").up() - .e("content", post.painting.replace(/\r?\n|\r/g, "").trim()).up() + .e("content", post.painting.replace(/[\n\r]+/gm, '').trim()).up() .e("size", post.painting.length).up() .e("url", `https://pretendo-cdn.b-cdn.net/paintings/${post.pid}/${post.id}.png`).up() .up();