Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cubscription controllers #165

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
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
89 changes: 79 additions & 10 deletions src/controllers/comment.controller.js
Original file line number Diff line number Diff line change
@@ -1,31 +1,100 @@
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"

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

if (!mongoose.Types.ObjectId.isValid(videoId)) {
throw new ApiError(400, "Invalid video ID");
}

const comments = await Comment.aggregate([
{ $match: { video: new mongoose.Types.ObjectId(videoId) } },
{ $sort: { createdAt: -1 } },
{
$facet: {
metadata: [{ $count: "total" }, { $addFields: { page: parseInt(page) } }],
data: [{ $skip: (page - 1) * limit }, { $limit: parseInt(limit) }],
},
},
{ $unwind: "$metadata" }
]);

const response = {
comments: comments.length > 0 ? comments[0].data : [],
totalPages: comments.length > 0 ? Math.ceil(comments[0].metadata.total / limit) : 0,
currentPage: parseInt(page)
};

res.status(200).json(new ApiResponse(200, response, "Comments retrieved successfully"));

})

const addComment = asyncHandler(async (req, res) => {
// TODO: add a comment to a video
const { videoId } = req.params;
const { content } = req.body;

if (!mongoose.Types.ObjectId.isValid(videoId)) {
throw new ApiError(400, "Invalid video ID");
}

const newComment = await Comment.create({
content,
video: new mongoose.Types.ObjectId(videoId),
owner: req.user._id
});

res.status(201).json(new ApiResponse(201, newComment, "Comment added successfully"));
})

const updateComment = asyncHandler(async (req, res) => {
// TODO: update a comment
const { commentId } = req.params
const { content } = req.body

if (!mongoose.Types.ObjectId.isValid(commentId)) {
throw new ApiError(400, "Invalid comment ID")
}

const updatedComment = await Comment.findByIdAndUpdate(
commentId,
{ content },
{ new: true }
)

if (!updatedComment) {
throw new ApiError(404, "Comment not found")
}

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 (!mongoose.Types.ObjectId.isValid(commentId)) {
throw new ApiError(400, "Invalid comment ID")
}

const deleteComment = await Comment.findByIdAndDelete(commentId)

if (!deleteComment) {
throw new ApiError(404, "Comment not found")
}

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

export {
getVideoComments,
addComment,
getVideoComments,
addComment,
updateComment,
deleteComment
}
deleteComment
}
146 changes: 139 additions & 7 deletions src/controllers/subscription.controller.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,156 @@
import mongoose, {isValidObjectId} from "mongoose"
import {User} from "../models/user.model.js"
import mongoose, { isValidObjectId } from "mongoose"
import { User } from "../models/user.model.js"
import { Subscription } from "../models/subscription.model.js"
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 toggleSubscription = asyncHandler(async (req, res) => {
const {channelId} = req.params
const { channelId } = req.params
// TODO: toggle subscription
const subscriberId = req.user._id;

// Validate channel ID and subscriber ID
if (!isValidObjectId(channelId) || !isValidObjectId(subscriberId)) {
throw new ApiError(400, "Invalid channel or subscriber ID");
}

// Ensure the user is not subscribing to their own channel
if (subscriberId.toString() === channelId) {
throw new ApiError(400, "You cannot subscribe to your own channel");
}

// Check if the channel exists
const channel = await User.findById(channelId);
if (!channel) {
throw new ApiError(404, "Channel not found");
}

// Check if there is an existing subscription
const existingSubscription = await Subscription.findOne({
subscriber: subscriberId,
channel: channelId,
});

if (existingSubscription) {
// Unsubscribe (remove subscription)
await existingSubscription.remove();
return res.status(200).json(new ApiResponse(200, {}, "Unsubscribed successfully"));
} else {
// Subscribe (create new subscription)
const newSubscription = new Subscription({
subscriber: subscriberId,
channel: channelId,
});

await newSubscription.save();
return res.status(200).json(new ApiResponse(200, newSubscription, "Subscribed successfully"));
}
})

// controller to return subscriber list of a channel
const getUserChannelSubscribers = asyncHandler(async (req, res) => {
const {channelId} = req.params
const { channelId } = req.params

// Validate channel ID
if (!isValidObjectId(channelId)) {
throw new ApiError(400, "Invalid channel ID");
}

// Check if the channel exists
const channel = await User.findById(channelId);
if (!channel) {
throw new ApiError(404, "Channel not found");
}

// Aggregate to find all channels the user has subscribed to and fetch channel details
const subscriptions = await Subscription.aggregate([
{
$match: {
subscriber: new mongoose.Types.ObjectId(channelId),
},
},
{
$lookup: {
from: "users", // The name of the User collection
localField: "channel",
foreignField: "_id",
as: "channelDetails",
},
},
{
$unwind: "$channelDetails",
},
{
$project: {
_id: 0,
channelId: "$channelDetails._id",
channelName: "$channelDetails.username", // Assuming 'username' is the channel name
channelAvatar: "$channelDetails.avatar", // Assuming 'avatar' is the channel's avatar
},
},
]);

if (subscriptions.length === 0) {
return res.status(200).json(new ApiResponse(200, [], "No subscribed channels found"));
}

return res.status(200).json(new ApiResponse(200, subscriptions, "Subscribed channels fetched successfully"));
})

// controller to return channel list to which user has subscribed
const getSubscribedChannels = asyncHandler(async (req, res) => {
const { subscriberId } = req.params

// Validate subscriber ID
if (!isValidObjectId(subscriberId)) {
throw new ApiError(400, "Invalid subscriber ID")
}

// check if the user(channel) exists
const channel = await User.findById(subscriberId)
if (!channel) {
throw new ApiError(404, "Channel not found")
}

// Aggregate to find all subscribers of the given channel and fetch subscriber details
const subscribers = await Subscription.aggregate([
{
$match: {
channel: new mongoose.Types.ObjectId(subscriberId)
}
},
{
$lookup: {
from: "users",
localField: "subscriber",
foreignField: "_id",
as: "subscriberDetails"
}
},
{
$unwind: "$subscriberDetails"
},
{
$project: {
_id: 0,
subscriberId: "$subscriberDetails._id",
subscriberName: "$subscriberDetails.fullname",
subscriberAvatar: "$subscriberDetails.avatar"
}
}
])

if (subscribers.length === 0) {
return res
.status(200)
.json(new ApiResponse(200, {}, "No subscribers found for this channel"))
}

return res
.status(200)
.json(new ApiResponse(200, subscribers, "Subscribers fetched successfully"))
})

export {
Expand Down
104 changes: 99 additions & 5 deletions src/controllers/tweet.controller.js
Original file line number Diff line number Diff line change
@@ -1,24 +1,118 @@
import mongoose, { isValidObjectId } from "mongoose"
import {Tweet} from "../models/tweet.model.js"
import {User} from "../models/user.model.js"
import {ApiError} from "../utils/ApiError.js"
import {ApiResponse} from "../utils/ApiResponse.js"
import {asyncHandler} from "../utils/asyncHandler.js"
import { Tweet } from "../models/tweet.model.js"
import { User } from "../models/user.model.js"
import { ApiError } from "../utils/ApiError.js"
import { ApiResponse } from "../utils/ApiResponse.js"
import { asyncHandler } from "../utils/asyncHandler.js"

const createTweet = asyncHandler(async (req, res) => {
//TODO: create tweet
const { content } = req.body
const userId = req.user._id

if (!content || content.trim().length === 0) {
throw new ApiError(400, "Tweet content cannot be empty")
}

if (!isValidObjectId(userId)) {
throw new ApiError(400, "Invalid user ID");
}

const user = await User.findById(userId);
if (!user) {
throw new ApiError(404, "User not found")
}

const tweet = new Tweet({
owner: user._id,
content: content.trim()
})

await tweet.save()

res
.status(200)
.json(new ApiResponse(201, tweet, "Tweet created successfully"))
})

const getUserTweets = asyncHandler(async (req, res) => {
// TODO: get user tweets
const userId = req.params.userId

if (!isValidObjectId(userId)) {
throw new ApiError(400, "Invalied user ID")
}

const user = await User.findById(userId)
if (!user) {
throw new ApiError(404, "User not found")
}

const tweets = await Tweet.find({ owner: userId }).sort({ createdAt: -1 })

if (tweets.length === 0) {
return res
.status(200)
.json(new ApiResponse(200, {}, "No tweets found"))
}

res
.status(200)
.json(new ApiResponse(200, tweets, "User tweets fetched successfully"))
})

const updateTweet = asyncHandler(async (req, res) => {
//TODO: update tweet
const { tweetId } = req.params;
const { content } = req.body;


if (!isValidObjectId(tweetId)) {
throw new ApiError(400, "Invalid tweet ID");
}

const tweet = await Tweet.findById(tweetId);
if (!tweet) {
throw new ApiError(404, "Tweet not found");
}

if (!content || content.trim().length === 0) {
throw new ApiError(400, "Tweet content cannot be empty");
}

const updatedTweet = await Tweet.findByIdAndUpdate(
tweetId,
{ content },
{ new: true }
)

if (!updatedTweet) {
throw new ApiError(400, "Failed to update tweet")
}

res
.status(200)
.json(new ApiResponse(200, updatedTweet, "Tweet updated successfully"));

})

const deleteTweet = asyncHandler(async (req, res) => {
//TODO: delete tweet
const { tweetId } = req.params

if (!isValidObjectId(tweetId)) {
throw new ApiError(400, "Invalid tweet ID")
}

const deletedTweet = await Tweet.findByIdAndDelete(tweetId)

if (!deletedTweet) {
throw new ApiError(404, "Tweet not found")
}

res
.status(200)
.json(new ApiResponse(200, {}, "Tweet deleted successfully"))
})

export {
Expand Down
Loading