diff --git a/.gitignore b/.gitignore index 30bc162..6ffb8b6 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,3 @@ -/node_modules \ No newline at end of file +/node_modules + +Procfile \ No newline at end of file diff --git a/api/all_novels.js b/api/all_novels.js deleted file mode 100644 index a0d44e7..0000000 --- a/api/all_novels.js +++ /dev/null @@ -1,37 +0,0 @@ -const express = require("express"); -const cheerio = require("cheerio"); -const request = require("request"); - -const router = express.Router(); - -const baseUrl = "https://boxnovel.com/novel/"; - -router.get("/novels/:pageNo/", (req, res) => { - orderBy = req.query.o; - pageNo = req.params.pageNo; - let novels = []; - - url = `${baseUrl}/page/${pageNo}/?m_orderby=${orderBy}`; - - request(url, (err, response, body) => { - if (err) throw err; - - $ = cheerio.load(body); - - $(".page-item-detail").each(function (result) { - novelName = $(this).find("h5 > a").text(); - novelCover = $(this).find("img").attr("src"); - novelUrl = $(this).find("h5 > a").attr("href").replace(baseUrl, ""); - novel = { - novelName: novelName, - novelCover: novelCover, - novelUrl: novelUrl, - }; - - novels.push(novel); - }); - res.json(novels); - }); -}); - -module.exports = router; diff --git a/api/chapter.js b/api/chapter.js deleted file mode 100644 index 7b5b072..0000000 --- a/api/chapter.js +++ /dev/null @@ -1,56 +0,0 @@ -const express = require("express"); -const cheerio = require("cheerio"); -const request = require("request"); - -const router = express.Router(); - -const baseUrl = "https://boxnovel.com/"; - -router.get("/novel/:novelUrl/:chapterUrl", (req, res) => { - url = - baseUrl + "novel/" + req.params.novelUrl + "/" + req.params.chapterUrl; - - request(url, (err, response, body) => { - if (err) throw err; - - $ = cheerio.load(body); - - chapterNameLower = req.params.chapterUrl.replace("-", " "); - - chapterName = - chapterNameLower.charAt(0).toUpperCase() + - chapterNameLower.slice(1); - - chapterText = $(".reading-content").text(); - - let nextChapter = null; - - if ($(".nav-next").length) { - nextChapter = $(".nav-next") - .find("a") - .attr("href") - .replace(baseUrl, ""); - } - - let prevChapter = null; - - if ($(".nav-previous").length) { - prevChapter = $(".nav-previous") - .find("a") - .attr("href") - .replace(baseUrl, ""); - } - - chapter = { - chapterUrl: url, - chapterName, - chapterText, - nextChapter, - prevChapter, - }; - - res.json(chapter); - }); -}); - -module.exports = router; diff --git a/api/latest.js b/api/latest.js deleted file mode 100644 index f464c50..0000000 --- a/api/latest.js +++ /dev/null @@ -1,37 +0,0 @@ -const express = require("express"); -const cheerio = require("cheerio"); -const request = require("request"); - -const router = express.Router(); - -const baseUrl = "https://boxnovel.com/"; - -router.get("/latest", (req, res) => { - let novels = []; - - request(baseUrl, (err, response, body) => { - if (err) throw err; - - $ = cheerio.load(body); - - $(".page-item-detail").each(function (result) { - novelName = $(this).find("h5 > a").text(); - novelCover = $(this).find("img").attr("src"); - novelUrl = $(this) - .find("h5 > a") - .attr("href") - .replace(baseUrl + "novel/", ""); - novel = { - novelName: novelName, - novelCover: novelCover, - novelUrl: novelUrl, - }; - - novels.push(novel); - }); - - res.json(novels); - }); -}); - -module.exports = router; diff --git a/api/novel.js b/api/novel.js deleted file mode 100644 index bd5f6f3..0000000 --- a/api/novel.js +++ /dev/null @@ -1,79 +0,0 @@ -const express = require("express"); -const cheerio = require("cheerio"); -const request = require("request"); - -const router = express.Router(); - -const baseUrl = "https://boxnovel.com/"; - -router.get("/novel/:novelUrl", (req, res) => { - novelUrl = req.params.novelUrl; - url = baseUrl + "novel/" + novelUrl; - - request(url, (err, response, body) => { - if (err) throw err; - - $ = cheerio.load(body); - - $(".post-title > h3 > span").remove(); - - novelName = $(".post-title > h3") - .text() - .replace(/[\t\n]/g, "") - .trim(); - - novelCover = $(".summary_image > a > img").attr("src"); - - let novelDetails = {}; - - $(".post-content_item").each(function (result) { - detailName = $(this) - .find(".summary-heading > h5") - .text() - .replace(/[\t\n]/g, "") - .trim(); - detail = $(this) - .find(".summary-content") - .text() - .replace(/[\t\n]/g, "") - .trim(); - - novelDetails[detailName] = detail; - }); - - novelSummary = $(".c_000").text(); - - let novelChapters = []; - - $(".wp-manga-chapter").each(function (result) { - chapterName = $(this) - .find("a") - .text() - .replace(/[\t\n]/g, "") - .trim(); - - releaseDate = $(this) - .find("span") - .text() - .replace(/[\t\n]/g, "") - .trim(); - - chapterUrl = $(this).find("a").attr("href").replace(baseUrl, ""); - - novelChapters.push({ chapterName, releaseDate, chapterUrl }); - }); - - novel = { - novelName, - novelUrl, - novelCover, - novelSummary, - novelDetails, - novelChapters, - }; - - res.json(novel); - }); -}); - -module.exports = router; diff --git a/api/search.js b/api/search.js deleted file mode 100644 index 395263c..0000000 --- a/api/search.js +++ /dev/null @@ -1,62 +0,0 @@ -const express = require("express"); -const cheerio = require("cheerio"); -const request = require("request"); - -const router = express.Router(); - -const baseUrl = "https://boxnovel.com/"; - -router.get("/search/", (req, res) => { - searchTerm = req.query.s; - orderBy = req.query.o; - - url = - baseUrl + - "?s=" + - searchTerm + - "&post_type=wp-manga&m_orderby=" + - orderBy; - request(url, (err, response, body) => { - if (err) throw err; - - $ = cheerio.load(body); - - let novels = []; - - $(".c-tabs-item__content").each(function (result) { - novelName = $(this).find("h4 > a").text(); - - let novelDetails = {}; - - $(this) - .find(".post-content_item") - .each(function (result) { - detailName = $(this) - .find(".summary-heading > h5") - .text() - .replace(/[\t\n]/g, "") - .trim(); - detail = $(this) - .find(".summary-content") - .text() - .replace(/[\t\n]/g, "") - .trim(); - - novelDetails[detailName] = detail; - }); - - novelCover = $(this).find("img").attr("src"); - - novelUrl = $(this) - .find("h4 > a") - .attr("href") - .replace(baseUrl + "novel/", ""); - - novels.push({ novelName, novelCover, novelUrl, novelDetails }); - }); - - res.json(novels); - }); -}); - -module.exports = router; diff --git a/package.json b/package.json index 745c718..49487c8 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,8 @@ "description": "Backend for LNReader", "main": "server.js", "scripts": { - "start": "nodemon server" + "start": "node server", + "server": "nodemon server" }, "author": "", "license": "ISC", diff --git a/server.js b/server.js index 2eeabed..f9ef507 100644 --- a/server.js +++ b/server.js @@ -10,17 +10,17 @@ app.use( app.get("/", (req, res) => res.json({ - Author: "Rajarshee Chatterjee", + Author: "@rajarsheechatterjee", Version: "1.0.0", - Github: "https://github.com/rajarsheechatterjee/LNReader-backend", + Github: "https://github.com/rajarsheechatterjee/lnreader-extensions", }) ); -app.use("/api/", require("./api/latest")); -app.use("/api/", require("./api/novel")); -app.use("/api/", require("./api/search")); -app.use("/api/", require("./api/chapter")); -app.use("/api/", require("./api/all_novels")); +// Box Novel +app.use("/api/1/", require("./src/en/boxnovel/boxnovel")); + +// ReadLightNovel +app.use("/api/2/", require("./src/en/readlightnovel/readlightnovel")); const PORT = process.env.PORT || 5000; diff --git a/src/en/boxnovel/boxnovel.js b/src/en/boxnovel/boxnovel.js new file mode 100644 index 0000000..a7c6ca4 --- /dev/null +++ b/src/en/boxnovel/boxnovel.js @@ -0,0 +1,223 @@ +const express = require("express"); +const cheerio = require("cheerio"); +const request = require("request"); + +const router = express.Router(); + +const baseUrl = "https://boxnovel.com/novel"; + +const searchUrl = "https://boxnovel.com/"; + +// Top novels + +router.get("/novels/:pageNo/", (req, res) => { + orderBy = req.query.o; + pageNo = req.params.pageNo; + + url = `${baseUrl}/page/${pageNo}/?m_orderby=${orderBy}`; + + request(url, (err, response, body) => { + if (err) throw err; + + let novels = []; + + $ = cheerio.load(body); + + $(".page-item-detail").each(function (result) { + novelName = $(this).find("h5 > a").text(); + novelCover = $(this).find("img").attr("src"); + novelUrl = $(this) + .find("h5 > a") + .attr("href") + .replace(`${baseUrl}/`, ""); + novel = { + extensionId: 1, + novelName: novelName, + novelCover: novelCover, + novelUrl: novelUrl, + }; + + novels.push(novel); + }); + res.json(novels); + }); +}); + +// Novel + +router.get("/novel/:novelUrl", (req, res) => { + novelUrl = req.params.novelUrl; + url = `${baseUrl}/${novelUrl}/`; + + request(url, (err, response, body) => { + if (err) throw err; + + $ = cheerio.load(body); + + let novel = {}; + + $(".post-title > h3 > span").remove(); + + novel.extensionId = 1; + + novel.sourceUrl = url; + + novel.novelUrl = `${novelUrl}/`; + + novel.novelName = $(".post-title > h3") + .text() + .replace(/[\t\n]/g, "") + .trim(); + + novel.novelCover = $(".summary_image > a > img").attr("src"); + + $(".post-content_item").each(function (result) { + detailName = $(this) + .find(".summary-heading > h5") + .text() + .replace(/[\t\n]/g, "") + .trim(); + detail = $(this) + .find(".summary-content") + .text() + .replace(/[\t\n]/g, "") + .trim(); + + novel[detailName] = detail; + }); + + novel.novelSummary = $(".c_000").text(); + + let novelChapters = []; + + $(".wp-manga-chapter").each(function (result) { + chapterName = $(this) + .find("a") + .text() + .replace(/[\t\n]/g, "") + .trim(); + + releaseDate = $(this) + .find("span") + .text() + .replace(/[\t\n]/g, "") + .trim(); + + chapterUrl = $(this).find("a").attr("href").replace(url, ""); + + novelChapters.push({ chapterName, releaseDate, chapterUrl }); + }); + + novel.novelChapters = novelChapters.reverse(); + + res.json(novel); + }); +}); + +// Chapter + +router.get("/novel/:novelUrl/:chapterUrl", (req, res) => { + url = `${baseUrl}/${req.params.novelUrl}/${req.params.chapterUrl}`; + + request(url, (err, response, body) => { + if (err) throw err; + + $ = cheerio.load(body); + + chapterNameLower = req.params.chapterUrl.replace("-", " "); + + chapterName = + chapterNameLower.charAt(0).toUpperCase() + + chapterNameLower.slice(1); + + chapterText = $(".reading-content").text(); + + let nextChapter = null; + + if ($(".nav-next").length) { + nextChapter = $(".nav-next") + .find("a") + .attr("href") + .replace(baseUrl, ""); + } + + let prevChapter = null; + + if ($(".nav-previous").length) { + prevChapter = $(".nav-previous") + .find("a") + .attr("href") + .replace(baseUrl, ""); + } + + chapter = { + extensionId: 1, + novelUrl: `${req.params.novelUrl}/`, + chapterUrl: `${req.params.chapterUrl}/`, + chapterName, + chapterText, + nextChapter, + prevChapter, + }; + + res.json(chapter); + }); +}); + +// Search + +router.get("/search/", (req, res) => { + searchTerm = req.query.s; + orderBy = req.query.o; + + url = `${searchUrl}?s=${searchTerm}&post_type=wp-manga&m_orderby=${orderBy}`; + + request(url, (err, response, body) => { + if (err) throw err; + + $ = cheerio.load(body); + + let novels = []; + + $(".c-tabs-item__content").each(function (result) { + novelName = $(this).find("h4 > a").text(); + + // let novelDetails = {}; + + // $(this) + // .find(".post-content_item") + // .each(function (result) { + // detailName = $(this) + // .find(".summary-heading > h5") + // .text() + // .replace(/[\t\n]/g, "") + // .trim(); + // detail = $(this) + // .find(".summary-content") + // .text() + // .replace(/[\t\n]/g, "") + // .trim(); + + // novelDetails[detailName] = detail; + // }); + + novelCover = $(this).find("img").attr("src"); + + novelUrl = $(this) + .find("h4 > a") + .attr("href") + .replace(`${baseUrl}`, ""); + + novels.push({ + extensionId: 1, + novelName, + novelCover, + novelUrl, + }); + }); + + res.json(novels); + }); +}); + +module.exports = router; diff --git a/src/en/readlightnovel/readlightnovel.js b/src/en/readlightnovel/readlightnovel.js new file mode 100644 index 0000000..c6bb705 --- /dev/null +++ b/src/en/readlightnovel/readlightnovel.js @@ -0,0 +1,215 @@ +const express = require("express"); +const cheerio = require("cheerio"); +const request = require("request"); + +const router = express.Router(); + +const baseUrl = "https://www.readlightnovel.org"; + +const searchUrl = "https://www.readlightnovel.org/detailed-search"; + +// Top Novels + +router.get("/novels/", (req, res) => { + // orderBy = req.query.o; + let novels = []; + + url = `${baseUrl}/top-novel?change_type=top_rated`; + + request(url, (err, response, body) => { + if (err) throw err; + + $ = cheerio.load(body); + + $(".top-novel-block").each(function (result) { + novelName = $(this).find(".top-novel-header > h2 > a").text(); + novelCover = $(this).find("img").attr("src"); + novelUrl = $(this) + .find(".top-novel-header > h2 > a") + .attr("href") + .replace(`${baseUrl}/`, ""); + novel = { + extensionId: 2, + novelName: novelName, + novelCover: novelCover, + novelUrl: `${novelUrl}/`, + }; + + novels.push(novel); + }); + + res.json(novels); + }); +}); + +// Novel + +router.get("/novel/:novelUrl", (req, res) => { + novelUrl = req.params.novelUrl; + url = `${baseUrl}/${novelUrl}`; + + request(url, (err, response, body) => { + if (err) throw err; + + $ = cheerio.load(body); + + let novel = {}; + + novel.extensionId = 2; + + novel.sourceUrl = url; + + novel.novelUrl = `${novelUrl}/`; + + novel.novelName = $(".block-title > h1").text(); + + novel.novelCover = $(".novel-cover > a > img").attr("src"); + + $(".novel-detail-item").each(function (result) { + detailName = $(this) + .find(".novel-detail-header > h6") + .text() + .replace(/[\t\n]/g, "") + .trim(); + detail = $(this) + .find(".novel-detail-body") + .text() + // .replace(/[\t\n]/g, " ") + .trim(); + + novel[detailName] = detail; + }); + + novel.Alternative = novel["Alternative Names"]; + novel.novelSummary = novel.Description; + novel["Genre(s)"] = novel.Genre.replace(/[\t\n]/g, ", "); + novel.Release = novel.Year; + + delete novel["Alternative Names"]; + delete novel.Description; + delete novel.Genre; + delete novel.Year; + + let novelChapters = []; + + $(".tab-content") + .find("li") + .each(function (result) { + chapterName = $(this) + .find("a") + .text() + .replace(/[\t\n]/g, "") + .trim(); + + releaseDate = null; + // $(this) + // .find("span") + // .text() + // .replace(/[\t\n]/g, "") + // .trim(); + + chapterUrl = $(this) + .find("a") + .attr("href") + .replace(baseUrl, ""); + + novelChapters.push({ + chapterName, + releaseDate, + chapterUrl: chapterUrl.replace(`/${novelUrl}/`, ""), + }); + }); + + novel.novelChapters = novelChapters; + + res.json(novel); + }); +}); + +// Chapter + +router.get("/novel/:novelUrl/:chapterUrl/:volumeUrl?", (req, res) => { + req.params.volumeUrl + ? (optionalUrl = req.params.volumeUrl) + : (optionalUrl = ""); + + url = `${baseUrl}/${req.params.novelUrl}/${req.params.chapterUrl}/${optionalUrl}`; + + request(url, (err, response, body) => { + if (err) throw err; + + $ = cheerio.load(body); + + $(".block-title > h1").find("a").remove(); + + chapterName = $(".block-title > h1").text().replace(" - ", ""); + + // $(".desc").find(".trinity-player-iframe-wrapper").remove(); + + chapterText = $(".desc").text(); + + let nextChapter = null; + + if ($("a.next.next-link").length) { + nextChapter = $("a.next.next-link") + .attr("href") + .replace(`${baseUrl}/${req.params.novelUrl}/`, ""); + } + + let prevChapter = null; + + if ($("a.prev.prev-link").length) { + prevChapter = $("a.prev.prev-link") + .attr("href") + .replace(`${baseUrl}/${req.params.novelUrl}/`, ""); + } + + chapter = { + extensionId: 2, + novelUrl: req.params.novelUrl, + chapterUrl: `${req.params.chapterUrl}/${optionalUrl}`, + chapterName, + chapterText, + nextChapter, + prevChapter, + }; + + res.json(chapter); + }); +}); + +router.get("/search/", (req, res) => { + searchTerm = req.query.s; + + request.post( + { url: searchUrl, form: { keyword: searchTerm, search: 1 } }, + (err, response, body) => { + if (err) throw err; + + $ = cheerio.load(body); + + let novels = []; + + $(".top-novel-block").each(function (result) { + novelName = $(this).find(".top-novel-header > h2 > a").text(); + novelCover = $(this).find("img").attr("src"); + novelUrl = $(this) + .find(".top-novel-header > h2 > a") + .attr("href") + .replace(`${baseUrl}/`, ""); + novel = { + extensionId: 2, + novelName: novelName, + novelCover: novelCover, + novelUrl: `${novelUrl}/`, + }; + + novels.push(novel); + }); + + res.json(novels); + } + ); +}); + +module.exports = router;