Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
678 changes: 456 additions & 222 deletions package-lock.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
"dependencies": {
"bcrypt": "^5.1.1",
"cloudinary": "^1.41.0",
"cloudinary-build-url": "^0.2.4",
"cookie-parser": "^1.4.6",
"cors": "^2.8.5",
"dotenv": "^16.3.1",
Expand Down
2 changes: 1 addition & 1 deletion src/constants.js
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export const DB_NAME = "videotube"
export const DB_NAME = "axoryn"
162 changes: 152 additions & 10 deletions src/controllers/comment.controller.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,173 @@
import mongoose from "mongoose"
import {Comment} from "../models/comment.model.js"
import {ApiError} from "../utils/ApiError.js"
import {ApiResponse} from "../utils/ApiResponse.js"
import {asyncHandler} from "../utils/asyncHandler.js"
import { Comment } from "../models/comment.model.js"
import { ApiError } from "../utils/ApiError.js"
import { ApiResponse } from "../utils/ApiResponse.js"
import { asyncHandler } from "../utils/asyncHandler.js"
import { Video } from "../models/video.model.js"

const getVideoComments = asyncHandler(async (req, res) => {
//TODO: get all comments for a video
const {videoId} = req.params
const {page = 1, limit = 10} = req.query
const { videoId } = req.params
const { page = 1, limit = 10 } = req.query;

/*
1. Take the Video id and extract the Video Schema.
2. Now Take the Video id and search in the comment schema.
3. Extract all the comments present with the video Id.
4. Take over the username & avatar.
5. Use aggregation pipeline + use pagination.

*/
const options = {
page,
limit
}

if (!videoId) {
throw new ApiError(400, "VideoId is invalid");
}

// const comments = await Comment.find({ video: videoId }).populate("owner", "username avatar");

const myAggregateComments = Comment.aggregate([
{
$match: {
video: new mongoose.Types.ObjectId(videoId)
}
}, {
$lookup: {
from: "users",
localField: "owner",
foreignField: "_id",
as: "commentor"
}
}, {
$unwind: "$commentor" // This ensure, each time seperate commentor object is formed.
}, {
$project: {
_id: 1,
content: 1,
"commentor._id": 1,
"commentor.username": 1,
"commentor.avatar": 1,
"commentor.fullName": 1,
"commentor.createdAt": 1,
}
}
]);

if (!myAggregateComments) {
throw new ApiError(400, "Invalid comment fetching.")
}

Comment.aggregatePaginate(myAggregateComments, options, function (err, results) {
if (err) {
console.error(err);
throw new ApiError(400, "Invalid comment fetching in aggregation pipeline.")
} else {
return res
.status(200)
.json(
new ApiResponse(200, results, "Got Video all comments successfully.")
)
}
})

})

const addComment = asyncHandler(async (req, res) => {
// TODO: add a comment to a video
/*
1. take the content from the user, req.body.
2. Check the existence of it.
3. Then, get the video id from the params.
4. get the user id from the req.user (token)
5. Then, store & save them in the comments db.
*/
const { content } = req.body;
const videoId = req.params.videoId;
const userId = req.user._id;

if (!content) {
throw new ApiError(400, "Content is invalid");
}
if (!videoId) {
throw new ApiError(400, "Video Id doesn't exist")
}

const comment = await Comment.create({
content,
video: videoId,
owner: userId
});
await comment.save();

return res
.status(200)
.json(
new ApiResponse(200, comment, "Comment created successfully")
)
})

const updateComment = asyncHandler(async (req, res) => {
// TODO: update a comment
/*
1. Get the commentId from the params.
2. get and update the comment schema.
3. then, send the response.
*/

const { commentId } = req.params;
const { updatedContent } = req.body;

if (!updatedContent) {
throw new ApiError(400, "Content is invalid")
}

if (!commentId) {
throw new ApiError(400, "Comment Id is invalid.");
}

const updateComment = await Comment.findByIdAndUpdate(
commentId,
{
$set: {
content: updatedContent,
}
},
{
new: true
}
);

return res
.status(200)
.json(
new ApiResponse(200, updateComment, "Comment updated successfully")
)

})

const deleteComment = asyncHandler(async (req, res) => {
// TODO: delete a comment

const { commentId } = req.params;
if (!commentId) {
throw new ApiError(400, "Comment Id is invalid.")
}

const comment = await Comment.findByIdAndDelete(commentId);

return res
.status(200)
.json(
new ApiResponse(200, comment, "Comment deleted successfully.")
)
})

export {
getVideoComments,
addComment,
getVideoComments,
addComment,
updateComment,
deleteComment
}
deleteComment
}
138 changes: 129 additions & 9 deletions src/controllers/dashboard.controller.js
Original file line number Diff line number Diff line change
@@ -1,20 +1,140 @@
import mongoose from "mongoose"
import {Video} from "../models/video.model.js"
import {Subscription} from "../models/subscription.model.js"
import {Like} from "../models/like.model.js"
import {ApiError} from "../utils/ApiError.js"
import {ApiResponse} from "../utils/ApiResponse.js"
import {asyncHandler} from "../utils/asyncHandler.js"
import { Video } from "../models/video.model.js"
import { Subscription } from "../models/subscription.model.js"
import { Like } from "../models/like.model.js"
import { ApiError } from "../utils/ApiError.js"
import { ApiResponse } from "../utils/ApiResponse.js"
import { asyncHandler } from "../utils/asyncHandler.js"
import { User } from "../models/user.model.js"

const getChannelStats = asyncHandler(async (req, res) => {
// TODO: Get the channel stats like total video views, total subscribers, total videos, total likes etc.
// TODO: Get the channel stats like total video views, total subscribers, total videos etc.

/*
1. Looking to the User, look out to:
a. videos
b. subscriptions
c. views
*/

const user = await User.aggregate([
{
$match: { _id: new mongoose.Types.ObjectId(req.user._id) }
},
{
$lookup: {
from: "videos",
localField: "_id",
foreignField: "owner",
as: "videosDetails"
}
},
{
$lookup: {
from: "subscriptions",
localField: "_id",
foreignField: "channel",
as: "subscriptionsDetails"
}
},
// join likes by matching video IDs
{
$lookup: {
from: "likes",
let: { userVideos: "$videosDetails._id" },
pipeline: [
{
$match: {
$expr: { $in: ["$video", "$$userVideos"] }
}
}
],
as: "likesDetails"
}
},
{
$addFields: {
totalViews: {
$sum: {
$map: {
input: "$videosDetails",
as: "video",
in: {
$cond: {
if: { $isArray: "$$video.views" },
then: { $size: "$$video.views" },
else: { $ifNull: ["$$video.views", 0] }
}
}
}
}
},
totalLikes: { $size: "$likesDetails" }, // count likes
totalSubscribers: { $size: "$subscriptionsDetails" } // count subscribers
}
},
{
$project: {
username: 1,
totalLikes: 1,
totalSubscribers: 1,
totalViews: 1,
"videosDetails._id": 1,
"videosDetails.isPublished": 1,
"videosDetails.thumbnail": 1,
"videosDetails.title": 1,
"videosDetails.description": 1,
"videosDetails.createdAt": 1
}
}

]);


if (!user) {
throw new ApiError(400, "Error Fetching Stats")
}

return res
.status(200)
.json(
new ApiResponse(200, user, "Fetching Channel Stats Successful")
)
})

const getChannelVideos = asyncHandler(async (req, res) => {
// TODO: Get all the videos uploaded by the channel

const videos = await Video.aggregate([
{
$match: { owner: new mongoose.Types.ObjectId(req.user._id) }
},
{
$addFields: {
views: {
$cond: {
if: { $isArray: "$views" },
then: { $size: "$views" },
else: { $ifNull: ["$views", 0] }
}
}
}
}
]);

if (!videos) {
throw new ApiError(400, "Fetching Channel Videos Failed")
}

return res
.status(200)
.json(
new ApiResponse(200, videos, "Fetching Channel Videos Successful")
)

})

export {
getChannelStats,
getChannelStats,
getChannelVideos
}
}
16 changes: 10 additions & 6 deletions src/controllers/healthcheck.controller.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import {ApiError} from "../utils/ApiError.js"
import {ApiResponse} from "../utils/ApiResponse.js"
import {asyncHandler} from "../utils/asyncHandler.js"

import { ApiError } from "../utils/ApiError.js"
import { ApiResponse } from "../utils/ApiResponse.js"
import { asyncHandler } from "../utils/asyncHandler.js"

const healthcheck = asyncHandler(async (req, res) => {
//TODO: build a healthcheck response that simply returns the OK status as json with a message

return res
.status(200)
.json(
new ApiResponse(200,"OK")
)
})

export {
healthcheck
}

}
Loading