997 lines
28 KiB
JavaScript
997 lines
28 KiB
JavaScript
var express = require('express');
|
|
var router = express.Router();
|
|
|
|
const DB = require("./../mongoDB.js");
|
|
const Post = require("./../def/post.js");
|
|
const Notifications = require("./../notifications.js");
|
|
|
|
DB.getDB.then((DB) => {
|
|
|
|
const getProfileId = (req) => {
|
|
const rawProfileId = req.cookies.profile_id || req.query.profile_id || req.body.profile_id || req.profileInfo?._id;
|
|
if (!rawProfileId) return null;
|
|
if (!DB.ObjectID.isValid(rawProfileId)) return null;
|
|
return DB.ObjectID(rawProfileId);
|
|
};
|
|
|
|
const postBelongToProfile = (post, profileid) => {
|
|
if (!post) return false;
|
|
return post.profileid == profileid;
|
|
};
|
|
|
|
const generateNonOrganicPosts = async (req, profileid) => {
|
|
let posts = [];
|
|
// News Posts
|
|
const newsPosts = await DB.getNews();
|
|
posts.push(...newsPosts);
|
|
|
|
// Popular Profiles
|
|
const popularProfiles = await DB.getPopularProfiles(5);
|
|
content = "Active users to follow:\n";
|
|
popularProfiles.forEach((p) => {
|
|
content += "@p:" + p._id + "\n";
|
|
});
|
|
let popularProfilesPost = new Post({ profileid: 1, content, nonOrganicType: "PopularUsers" });
|
|
posts.push(popularProfilesPost);
|
|
|
|
// Popular Groups
|
|
const popularGroups = await DB.getPopularGroups(5);
|
|
content = "Popular groups to follow:\n";
|
|
popularGroups.forEach((p) => {
|
|
content += "@p:" + p._id + "\n";
|
|
});
|
|
let popularGroupsPost = new Post({ profileid: 1, content, nonOrganicType: "PopularGroups" });
|
|
posts.push(popularGroupsPost);
|
|
|
|
const yourFollowsInterests = await DB.getFriendsFriends(profileid);
|
|
content = "People your follow has these interests:\n";
|
|
yourFollowsInterests.forEach((p) => {
|
|
content += "@p:" + p + "\n";
|
|
});
|
|
let yourFollowsInterestsPost = new Post({ profileid: 1, content, nonOrganicType: "PopularUsers" });
|
|
posts.push(yourFollowsInterestsPost);
|
|
|
|
return posts;
|
|
};
|
|
|
|
const mergePosts = (organic, nonOrganic) => {
|
|
if (!organic || organic.length < 5) return nonOrganic;
|
|
//organic.push(...nonOrganic);
|
|
let mergedPosts = [];
|
|
while (organic.length + nonOrganic.length) {
|
|
if (organic.length == 0) {
|
|
mergedPosts.push(nonOrganic.shift());
|
|
continue;
|
|
}
|
|
if (nonOrganic.length == 0) {
|
|
mergedPosts.push(organic.shift());
|
|
continue;
|
|
}
|
|
if (nonOrganic[0].nonOrganicType == 'News') {
|
|
mergedPosts.push(nonOrganic.shift());
|
|
continue;
|
|
}
|
|
if (Math.random() < 0.2) {
|
|
mergedPosts.push(nonOrganic.shift());
|
|
} else {
|
|
mergedPosts.push(organic.shift());
|
|
}
|
|
}
|
|
return mergedPosts;
|
|
};
|
|
|
|
/**
|
|
* @swagger
|
|
* tags:
|
|
* name: Posts
|
|
* description: Post management
|
|
*/
|
|
|
|
/**
|
|
* @swagger
|
|
* components:
|
|
* schemas:
|
|
* Post:
|
|
* type: object
|
|
* properties:
|
|
* profileid:
|
|
* type: string
|
|
* description: The ID of the profile that created the post.
|
|
* content:
|
|
* type: string
|
|
* description: The content of the post.
|
|
* createdAt:
|
|
* type: string
|
|
* format: date-time
|
|
* description: The timestamp when the post was created.
|
|
* reactions:
|
|
* type: object
|
|
* description: An object containing reactions to the post, keyed by profile ID.
|
|
* comments:
|
|
* type: array
|
|
* items:
|
|
* type: object
|
|
* description: An array of comments on the post.
|
|
* bookmarks:
|
|
* type: array
|
|
* items:
|
|
* type: string
|
|
* description: An array of profile IDs that bookmarked the post.
|
|
* nonOrganicType:
|
|
* type: string
|
|
* description: Type of non-organic content (e.g., "News", "PopularUsers", "PopularGroups").
|
|
* contentHistory:
|
|
* type: array
|
|
* items:
|
|
* type: string
|
|
* description: A history of content edits.
|
|
* toProfile:
|
|
* type: string
|
|
* description: The ID of the profile this post is directed to (e.g., a group).
|
|
* lastUpdated:
|
|
* type: string
|
|
* format: date-time
|
|
* description: The timestamp when the post was last updated.
|
|
* tags:
|
|
* type: array
|
|
* items:
|
|
* type: string
|
|
* description: An array of tags associated with the post.
|
|
* chatSenderId:
|
|
* type: string
|
|
* description: The ID of the chat sender, if applicable.
|
|
*
|
|
* /post/organic:
|
|
* get:
|
|
* summary: Get the organic feed for the current user
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Post'
|
|
*/
|
|
router.get("/organic", async (req, res) => {
|
|
try {
|
|
const profileid = getProfileId(req);
|
|
if (!profileid) return res.status(400).json([]);
|
|
let organicPosts = await DB.getFeed(profileid);
|
|
const nonOrganicPosts = await generateNonOrganicPosts(req, profileid);
|
|
const posts = mergePosts(organicPosts || [], nonOrganicPosts || []);
|
|
return res.json(posts);
|
|
} catch (error) {
|
|
console.error("Error loading organic feed", error);
|
|
return res.status(500).json([]);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post:
|
|
* get:
|
|
* summary: Get the feed with promotional content
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Post'
|
|
*/
|
|
router.get("/", async (req, res) => {
|
|
try {
|
|
const profileid = getProfileId(req);
|
|
if (!profileid) return res.status(400).json([]);
|
|
const nonOrganicPosts = await generateNonOrganicPosts(req, profileid);
|
|
let promotionalPosts = await DB.getPromotionalPosts(profileid);
|
|
const posts = mergePosts(promotionalPosts || [], nonOrganicPosts || []);
|
|
return res.json(posts);
|
|
} catch (error) {
|
|
console.error("Error loading feed", error);
|
|
return res.status(500).json([]);
|
|
}
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/tag/{tag}:
|
|
* get:
|
|
* summary: Get posts with a specific tag
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: tag
|
|
* required: true
|
|
* schema:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Post'
|
|
* 400:
|
|
* description: Tag is required
|
|
*/
|
|
router.get("/tag/:tag", async (req, res) => {
|
|
const profileid = getProfileId(req);
|
|
const tag = req.query.tag || req.params.tag;
|
|
if(!tag) {
|
|
console.log("Tag query empty: ", tag);
|
|
return res.json({
|
|
status: "Tag is required",
|
|
});
|
|
}
|
|
console.log("Tag query: ", tag);
|
|
let posts = await DB.getPostsByTag('#' + tag, profileid);
|
|
return res.json(posts);
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/usr/{id}:
|
|
* get:
|
|
* summary: Get posts from a specific user
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* required: true
|
|
* schema:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Post'
|
|
*/
|
|
router.get("/usr/:id", async (req, res) => {
|
|
const profileId = req.params.id;
|
|
const viewerProdileId = getProfileId(req);
|
|
const profile = await DB.getProfileCache(profileId);
|
|
const posts = await DB.getPosts(profileId, viewerProdileId);
|
|
if (profile.isCourse) {
|
|
//check for subscription
|
|
//const viewerProdile = await DB.getProfileCache(viewerProdileId);
|
|
//if (!viewerProdile.subscription || viewerProdile.subscription < (new Date()-1)) {
|
|
// return res.json([posts[posts.length - 1]]);
|
|
//}
|
|
}
|
|
return res.json(posts);
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/usr/{id}/images:
|
|
* get:
|
|
* summary: Get all image posts from a user
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* required: true
|
|
* schema:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: string
|
|
* posts:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Post'
|
|
*/
|
|
router.get("/usr/:id/images", async (req, res) => {
|
|
const profileid = req.params.id;
|
|
const viewerProfileId = getProfileId(req);
|
|
const posts = await DB.getMediaTagPostOfUser(profileid, viewerProfileId);
|
|
return res.json({
|
|
status: "ok",
|
|
posts
|
|
});
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/usr/{id}/embedded:
|
|
* get:
|
|
* summary: Get all embedded posts from a user
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* required: true
|
|
* schema:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: string
|
|
* posts:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Post'
|
|
*/
|
|
router.get("/usr/:id/embedded", async (req, res) => {
|
|
const profileid = req.params.id;
|
|
const viewerProfileId = getProfileId(req);
|
|
const posts = await DB.getMediaTagPostOfUser(profileid, viewerProfileId, "@iframe:");
|
|
return res.json({
|
|
status: "ok",
|
|
posts
|
|
});
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/usr/{id}/media:
|
|
* get:
|
|
* summary: Get all media posts from a user
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* required: true
|
|
* schema:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: string
|
|
* posts:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Post'
|
|
*/
|
|
router.get("/usr/:id/media", async (req, res) => {
|
|
const profileid = req.params.id;
|
|
const viewerProfileId = getProfileId(req);
|
|
const posts = await DB.getMediaTagPostOfUser(profileid, viewerProfileId, "@youtube:|@vimeo:|@hls:");
|
|
return res.json({
|
|
status: "ok",
|
|
posts
|
|
});
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/video/{id}:
|
|
* get:
|
|
* summary: Get video details by ID
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* required: true
|
|
* schema:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
*/
|
|
router.get("/video/:id", async (req, res) => {
|
|
videoId = req.params.id;
|
|
return res.json([]);
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post:
|
|
* post:
|
|
* summary: Create a new post
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* 403:
|
|
* description: Not authorized to post to this group
|
|
*/
|
|
router.post("/", async (req, res) => {
|
|
let post = {
|
|
profileid: getProfileId(req),
|
|
...req.body
|
|
}
|
|
const isGroupPrivate = await DB.isGroupPrivate(post.toProfile);
|
|
const isGroupNewsOnly = await DB.isGroupNewsOnly(post.toProfile);
|
|
if (post.toProfile && isGroupPrivate) {
|
|
let requestProfile = getProfileId(req) + "";
|
|
let group = await DB.getProfileCache(post.toProfile);
|
|
if (!group.subscribed[requestProfile] && group._id != requestProfile) {
|
|
return res.json({
|
|
status: "You are not part of this private group",
|
|
});
|
|
}
|
|
}
|
|
if (post.toProfile && isGroupNewsOnly) {
|
|
return res.json({
|
|
status: "This is a news only group, only the admin can post",
|
|
});
|
|
}
|
|
post.toProfile = post.toProfile ? DB.ObjectID(post.toProfile) : undefined;
|
|
let postObj = new Post(post);
|
|
let dbr = await DB.newPost(postObj);
|
|
post = postObj.toObj();
|
|
post._id = dbr.insertedId;
|
|
if ((post.toProfile && post.toProfile != post.profileid) || post.nonOrganicType == 'News') {
|
|
await Notifications.youGotANewPost(post);
|
|
}
|
|
await Notifications.yourGroupMakeANewPost(post);
|
|
if(!isGroupPrivate){
|
|
await Notifications.yourSubscriptionProfileHasNewPost(post);
|
|
}
|
|
return res.json({
|
|
status: "ok",
|
|
...post
|
|
})
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/react:
|
|
* post:
|
|
* summary: React to a post
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* postid:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
*/
|
|
router.post("/react", async (req, res) => {
|
|
let profileid = getProfileId(req);
|
|
let postid = req.body.postid;
|
|
let reaction = {
|
|
type: "like",
|
|
createdAt: new Date()
|
|
};
|
|
r = await DB.newReaction(postid, profileid, reaction);
|
|
Notifications.youGotANewReaction(postid, profileid, 'like');
|
|
return res.json({
|
|
status: "ok"
|
|
});
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/unreact:
|
|
* post:
|
|
* summary: Remove a reaction from a post
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* postid:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
*/
|
|
router.post("/unreact", async (req, res) => {
|
|
let profileid = getProfileId(req);
|
|
let postid = req.body.postid;
|
|
r = await DB.removeReaction(postid, profileid);
|
|
return res.json({
|
|
status: "ok"
|
|
})
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/bookmark:
|
|
* post:
|
|
* summary: Bookmark a post
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* postid:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
*/
|
|
router.post("/bookmark", async (req, res) => {
|
|
let profileid = getProfileId(req);
|
|
let postid = req.body.postid;
|
|
r = await DB.bookmarkPost(postid, profileid);
|
|
return res.json({
|
|
status: "ok"
|
|
});
|
|
})
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/unbookmark:
|
|
* post:
|
|
* summary: Remove a bookmark from a post
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* postid:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
*/
|
|
router.post("/unbookmark", async (req, res) => {
|
|
let profileid = getProfileId(req);
|
|
let postid = req.body.postid;
|
|
r = await DB.unbookmarkPost(postid, profileid);
|
|
return res.json({
|
|
status: "ok"
|
|
})
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/comment:
|
|
* post:
|
|
* summary: Add a comment to a post
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* postid:
|
|
* type: string
|
|
* content:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
*/
|
|
router.post("/comment/", async (req, res) => {
|
|
let profileid = getProfileId(req);
|
|
let postid = req.body.postid;
|
|
let content = req.body.content;
|
|
let comment = {
|
|
profileid: profileid,
|
|
content: content,
|
|
createdAt: new Date(),
|
|
lastUpdated: new Date(),
|
|
reactions: {}
|
|
}
|
|
Notifications.youGotANewPostComment(postid, profileid, content)
|
|
r = await DB.newComment(postid, comment);
|
|
return res.json({
|
|
status: "ok",
|
|
...comment
|
|
})
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/comment/react:
|
|
* post:
|
|
* summary: React to a comment
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* postid:
|
|
* type: string
|
|
* commentDate:
|
|
* type: string
|
|
* format: date-time
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
*/
|
|
router.post("/comment/react", async (req, res) => {
|
|
let userid = getProfileId(req);
|
|
let postid = req.body.postid;
|
|
let commentDate = new Date(req.body.commentDate);
|
|
let reaction = {
|
|
type: "like",
|
|
createdAt: new Date()
|
|
};
|
|
r = await DB.newCommentReaction(postid, commentDate, userid, reaction);
|
|
return res.json({
|
|
status: "ok"
|
|
})
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/comment/unreact:
|
|
* post:
|
|
* summary: Remove a reaction from a comment
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* requestBody:
|
|
* required: true
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* postid:
|
|
* type: string
|
|
* commentDate:
|
|
* type: string
|
|
* format: date-time
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
*/
|
|
router.post("/comment/unreact", async (req, res) => {
|
|
let profileid = getProfileId(req);
|
|
let postid = req.body.postid;
|
|
let commentDate = new Date(req.body.commentDate);
|
|
r = await DB.removeCommentReaction(postid, commentDate, profileid);
|
|
return res.json({
|
|
status: "ok"
|
|
})
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/images:
|
|
* get:
|
|
* summary: Get all image posts for the current user
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: string
|
|
* posts:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Post'
|
|
*/
|
|
router.get("/images", async (req, res) => {
|
|
const profileid = getProfileId(req);
|
|
const posts = await DB.getMediaTagPostOfUser(profileid, profileid);
|
|
return res.json({
|
|
status: "ok",
|
|
posts
|
|
});
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/embedded:
|
|
* get:
|
|
* summary: Get all embedded posts for the current user
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: string
|
|
* posts:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Post'
|
|
*/
|
|
router.get("/embedded", async (req, res) => {
|
|
const profileid = getProfileId(req);
|
|
const posts = await DB.getMediaTagPostOfUser(profileid, profileid, "@iframe:");
|
|
return res.json({
|
|
status: "ok",
|
|
posts
|
|
});
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/media:
|
|
* get:
|
|
* summary: Get all media posts for the current user
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: string
|
|
* posts:
|
|
* type: array
|
|
* items:
|
|
* $ref: '#/components/schemas/Post'
|
|
*/
|
|
router.get("/media", async (req, res) => {
|
|
const profileid = getProfileId(req);
|
|
const posts = await DB.getMediaTagPostOfUser(profileid, profileid, "@youtube:|@vimeo:|@hls:");
|
|
return res.json({
|
|
status: "ok",
|
|
posts
|
|
});
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/course/recent:
|
|
* get:
|
|
* summary: Get recently watched media from courses
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* type: object
|
|
* properties:
|
|
* status:
|
|
* type: string
|
|
* recentMedia:
|
|
* type: object
|
|
* additionalProperties:
|
|
* type: array
|
|
* items:
|
|
* type: object
|
|
* properties:
|
|
* watchRecord:
|
|
* type: object
|
|
* _id:
|
|
* type: string
|
|
* profileid:
|
|
* type: string
|
|
* content:
|
|
* type: string
|
|
* createdAt:
|
|
* type: string
|
|
* format: date-time
|
|
* reactions:
|
|
* type: object
|
|
* comments:
|
|
* type: array
|
|
* items:
|
|
* type: object
|
|
* bookmarks:
|
|
* type: array
|
|
* items:
|
|
* type: string
|
|
* nonOrganicType:
|
|
* type: string
|
|
* contentHistory:
|
|
* type: array
|
|
* items:
|
|
* type: string
|
|
* toProfile:
|
|
* type: string
|
|
* lastUpdated:
|
|
* type: string
|
|
* format: date-time
|
|
* tags:
|
|
* type: array
|
|
* items:
|
|
* type: string
|
|
* chatSenderId:
|
|
* type: string
|
|
* mediaProfileMap:
|
|
* type: object
|
|
* additionalProperties:
|
|
* type: object
|
|
*/
|
|
router.get("/course/recent", async (req, res) => {
|
|
const profileid = getProfileId(req);
|
|
const profile = await DB.getProfileCache(profileid);
|
|
const mediaPostsId = []
|
|
const recentMedia = {};
|
|
const mediaProfileP = []
|
|
let postPromises = [];
|
|
// Get watch information from profile data
|
|
Object.keys(profile.data).forEach(key => {
|
|
// So far we only use watch info using postid keys
|
|
if(DB.ObjectID.isValid(key)){
|
|
mediaPostsId.push(profile.data[key]);
|
|
postPromises.push(DB.getPostCached(profile.data[key].postId));
|
|
if(!recentMedia[profile.data[key].profileId]){
|
|
recentMedia[profile.data[key].profileId] = [];
|
|
mediaProfileP.push(DB.getProfileCache(profile.data[key].profileId));
|
|
}
|
|
}
|
|
});
|
|
recentMediaArray = mediaPostsId.sort((a,b)=>{
|
|
return b.ts - a.ts;
|
|
});
|
|
const postObjs = await Promise.all(postPromises);
|
|
const postObjsMap = postObjs.reduce((map, item)=>{
|
|
map[item._id] = item;
|
|
return map
|
|
}, {});
|
|
recentMediaArray.forEach(record => {
|
|
const postAndRecord = {
|
|
watchRecord: record,
|
|
... postObjsMap[record.postId]
|
|
}
|
|
recentMedia[record.profileId].push(postAndRecord);
|
|
});
|
|
// Transform profiles array to dict
|
|
let mediaProfile = await Promise.all(mediaProfileP);
|
|
let mediaProfileMap = mediaProfile.reduce((dict, item) => {
|
|
dict[item._id] = item;
|
|
return dict;
|
|
}, {});
|
|
return res.json({
|
|
status: "ok",
|
|
recentMedia,
|
|
mediaProfileMap,
|
|
});
|
|
});
|
|
|
|
/**
|
|
* @swagger
|
|
* /post/{id}:
|
|
* get:
|
|
* summary: Get a specific post by ID
|
|
* tags: [Posts]
|
|
* security:
|
|
* - cookieAuth: []
|
|
* parameters:
|
|
* - in: path
|
|
* name: id
|
|
* required: true
|
|
* schema:
|
|
* type: string
|
|
* responses:
|
|
* 200:
|
|
* description: OK
|
|
* content:
|
|
* application/json:
|
|
* schema:
|
|
* $ref: '#/components/schemas/Post'
|
|
*/
|
|
router.get("/:id", async (req, res) => {
|
|
const postId = req.params.id;
|
|
const post = await DB.getPost(postId);
|
|
return res.json({
|
|
status: "ok",
|
|
...post
|
|
});
|
|
});
|
|
|
|
router.delete("/:id", async (req, res) => {
|
|
const profileid = getProfileId(req) + '';
|
|
const postId = req.params.id;
|
|
const post = await DB.getPost(postId);
|
|
if (!postBelongToProfile(post, profileid))
|
|
return res.json({
|
|
status: "This post is not yours."
|
|
});
|
|
await DB.removePost(postId);
|
|
return res.json({
|
|
status: "ok"
|
|
});
|
|
});
|
|
|
|
router.post("/:id", async (req, res) => {
|
|
const profileid = getProfileId(req) + '';
|
|
const postId = req.params.id;
|
|
const post = await DB.getPost(postId);
|
|
const newContent = req.body.content;
|
|
if (!postBelongToProfile(post, profileid))
|
|
return res.json({
|
|
status: "This post is not yours."
|
|
});
|
|
await DB.updatePost(postId, newContent, post.content);
|
|
return res.json({
|
|
status: "ok"
|
|
});
|
|
});
|
|
|
|
});
|
|
|
|
module.exports = router
|