diff --git a/backend/models/movie.js b/backend/models/movie.js new file mode 100644 index 0000000000000000000000000000000000000000..6f93e0b6e226257056b7bb291c48a9a749e04b94 --- /dev/null +++ b/backend/models/movie.js @@ -0,0 +1,27 @@ +const mongoose = require("mongoose"); +const { Schema } = mongoose; + +const MovieSchema = new mongoose.Schema({ + adult: { type: Boolean }, + backdrop_path: { type: String }, + genre_ids: [Number], + id: { type: Number, required: true, unique: true }, + original_language: { type: String }, + original_title: { type: String }, + overview: { type: String }, + popularity: { type: String }, + poster_path: { type: String }, + release_date: { type: String }, + title: { type: String }, + video: { type: Boolean }, + vote_average: { type: String }, + vote_count: { type: Number }, +}); + +const MovieModel = mongoose.model( + "MovieModel", + MovieSchema, + "movies_populated" +); + +module.exports = MovieModel; diff --git a/backend/models/movies.js b/backend/models/movies.js deleted file mode 100644 index c17caa43d52d7b45d552816c0fc44c41f153f9f6..0000000000000000000000000000000000000000 --- a/backend/models/movies.js +++ /dev/null @@ -1,14 +0,0 @@ -const mongoose = require("mongoose"); -const { Schema } = mongoose; - -const MovieSchema = new mongoose.Schema({ - publisher: { type: String, required: true }, - title: { type: String, required: true, unique: true }, - date: { type: String }, - imageURL: { type: String }, - viewers: [{ type: Schema.Types.ObjectId, ref: "UserModel" }], -}); - -const MovieModel = mongoose.model("MovieModel", MovieSchema, "movies"); - -module.exports = MovieModel; diff --git a/backend/models/user.js b/backend/models/user.js index 1f70ae7101b636b12a6ede29a240dc691013d9ec..f8b0dc63548530921acde194ac2a3aaa84ce904b 100644 --- a/backend/models/user.js +++ b/backend/models/user.js @@ -1,9 +1,21 @@ const mongoose = require("mongoose"); -const UserSchema = new mongoose.Schema({ - email: { type: String, required: true, unique: true }, - firstName: { type: String }, - lastName: { type: String }, +const UserSchema = new mongoose.Schema( + { + email: { type: String, required: true, unique: true }, + firstName: { type: String }, + lastName: { type: String }, + }, + { + toJSON: { virtuals: true }, // So `res.json()` and other `JSON.stringify()` functions include virtuals + toObject: { virtuals: true }, // So `console.log()` and other functions that use `toObject()` include virtuals + } +); + +UserSchema.virtual("watchedMovies", { + ref: "MovieModel", + localField: "_id", // The user _id should match the viewers field in movies + foreignField: "viewers", }); const UserModel = mongoose.model("UserModel", UserSchema, "users"); diff --git a/backend/package-lock.json b/backend/package-lock.json index c917d224f909fb6973f67829e475a47c150a3528..c7e77f9130c8d15c9f3941d5f8c6e7d193d82c9f 100644 --- a/backend/package-lock.json +++ b/backend/package-lock.json @@ -8,6 +8,7 @@ "name": "centrale-ei-web-backend", "version": "0.1.0", "dependencies": { + "axios": "^0.27.2", "cors": "^2.8.5", "dotenv-cli": "^5.1.0", "express": "^4.18.1", @@ -214,6 +215,20 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "dependencies": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -561,6 +576,17 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -699,6 +725,14 @@ "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", "dev": true }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.0" + } + }, "node_modules/denque": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", @@ -1187,6 +1221,38 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "node_modules/follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -3197,6 +3263,20 @@ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "axios": { + "version": "0.27.2", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz", + "integrity": "sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ==", + "requires": { + "follow-redirects": "^1.14.9", + "form-data": "^4.0.0" + } + }, "balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -3446,6 +3526,14 @@ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "dev": true }, + "combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, "concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -3549,6 +3637,11 @@ "integrity": "sha512-0ISdNousHvZT2EiFlZeZAHBUvSxmKswVCEf8hW7KWgG4a8MVEu/3Vb6uWYozkjylyCxe0JBIiRB1jV45S70WVQ==", "dev": true }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==" + }, "denque": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/denque/-/denque-2.0.1.tgz", @@ -3929,6 +4022,21 @@ "integrity": "sha512-WIWGi2L3DyTUvUrwRKgGi9TwxQMUEqPOPQBVi71R96jZXJdFskXEmf54BoZaS1kknGODoIGASGEzBUYdyMCBJg==", "dev": true }, + "follow-redirects": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.1.tgz", + "integrity": "sha512-yLAMQs+k0b2m7cVxpS1VKJVvoz7SS9Td1zss3XRwXj+ZDH00RJgnuLx7E44wx02kQLrdM3aOOy+FpzS7+8OizA==" + }, + "form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + } + }, "forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", diff --git a/backend/package.json b/backend/package.json index a067f27c606d6a1da1b0f7d8fbb7567eb29a9b33..8c560d3fec00daac452efa7a2380ee108cd4d81c 100644 --- a/backend/package.json +++ b/backend/package.json @@ -9,6 +9,7 @@ "format": "eslint . --fix" }, "dependencies": { + "axios": "^0.27.2", "cors": "^2.8.5", "dotenv-cli": "^5.1.0", "express": "^4.18.1", diff --git a/backend/populate.js b/backend/populate.js new file mode 100644 index 0000000000000000000000000000000000000000..bd0564d853f7003994a4e89e37983630cadfd78c --- /dev/null +++ b/backend/populate.js @@ -0,0 +1,85 @@ +const mongoose = require("mongoose"); +const MovieModel = require("./models/movie"); +const axios = require("axios"); + +async function fetchMoviesFromTheMovieDatabase(n) { + // TODO: fetch movies from the The Movie Database API + try { + // Do something if call succeeded + const movieFetch = await axios.get( + `https://api.themoviedb.org/3/movie/popular?api_key=522d421671cf75c2cba341597d86403a&page=` + + n + ); + // console.log(movieFetch.data.results); + return movieFetch.data.results; + } catch (error) { + // Do something if call failed + console.error(error); + } +} + +async function populateMovies(movies) { + // TODO: populate movies into the database + try { + await movies.forEach(async (movie) => { + const newMovie = await new MovieModel({ + // Movie attributes + adult: movie.adult, + backdrop_path: movie.backdrop_path, + genre_ids: movie.genre_ids, + id: movie.id, + original_language: movie.original_language, + original_title: movie.original_title, + overview: movie.overview, + popularity: movie.popularity, + poster_path: movie.poster_path, + release_date: movie.release_date, + title: movie.title, + video: movie.video, + vote_average: movie.vote_average, + vote_count: movie.vote_count, + }); + + // Create a new movie instance + const createdMovie = await newMovie.save(); + + // What to do after movie has been saved ! + console.log("Movie Saved !"); + console.log(createdMovie.title); + }); + } catch (error) { + console.log(error); + } +} + +async function dropDataBase() { + // TODO: Drop the collections + try { + await MovieModel.deleteMany({}); + } catch (error) { + console.log(error); + } +} + +async function populate() { + // Connect mongoose client + const client = await mongoose.connect(process.env.MONGO_DB_URL); + await dropDataBase(); + + for (let n = 1; n < 300; n++) { + const movies = await fetchMoviesFromTheMovieDatabase(n); + await populateMovies(movies); + console.log(n); + } + + // disconnect mongoose client + // await client.disconnect(); +} + +populate(2) + .then(() => { + console.log("All done !"); + }) + .catch((error) => { + console.error(error); + }); diff --git a/backend/routes/movies.js b/backend/routes/movies.js index a41712ef93d00251ae66cbf7c5a8dc26e8e9ebb2..867ce0f6a45870cb77980ca98702f3fb7306eabf 100644 --- a/backend/routes/movies.js +++ b/backend/routes/movies.js @@ -1,5 +1,5 @@ const express = require("express"); -const MovieModel = require("../models/movies"); +const MovieModel = require("../models/movie"); const router = express.Router(); module.exports = router; diff --git a/backend/routes/users.js b/backend/routes/users.js index 1d698d1810c8257e4c090288b24fe05e43376da3..0f46e78327ea9ca9123076fb90199c6a851a7745 100644 --- a/backend/routes/users.js +++ b/backend/routes/users.js @@ -8,6 +8,17 @@ router.get("/", function (req, res) { }); }); +router.get("/:id/movies", async function (req, res) { + try { + const user = await UserModel.findById(req.params["id"]).populate( + "watchedMovies" + ); + res.send(user); + } catch (error) { + console.log(error); + } +}); + router.post("/new", function (req, res) { const newUser = new UserModel({ email: req.body.email,