diff --git a/package.json b/package.json index 4ce3720..ff2c155 100644 --- a/package.json +++ b/package.json @@ -19,6 +19,7 @@ "@babel/runtime": "^7.13.17", "@bluelovers/fast-glob": "^3.0.4", "@types/event-stream": "^3.3.34", + "@types/mime-types": "^2.1.0", "@types/react": "^17.0.3", "@types/react-dom": "^17.0.2", "@types/react-redux": "^7.1.16", @@ -38,6 +39,7 @@ "fastest-validator": "^1.11.0", "final-form": "^4.20.2", "fs-extra": "^9.1.0", + "http-response-stream": "^1.0.7", "imghash": "^0.0.8", "jsdoc": "^3.6.7", "opds-extra": "^3.0.9", diff --git a/src/server/index.ts b/src/server/index.ts index 5dcf91b..c082c60 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -1,6 +1,7 @@ import express, { Request, Response, Router, Express } from "express"; import bodyParser from "body-parser"; -import path, { basename, extname } from "path"; +import path, { basename, extname, join} from "path"; +import { isUndefined } from "lodash"; import { buildAsync } from "calibre-opds"; import initMain from "calibre-opds/lib/index"; @@ -8,12 +9,29 @@ import { EnumLinkRel, EnumMIME } from "opds-extra/lib/const"; import { async as FastGlob } from "@bluelovers/fast-glob/bluebird"; import { Entry, Feed } from "opds-extra/lib/v1"; import { Link } from "opds-extra/lib/v1/core"; -import { isUndefined } from "lodash"; + +import { lookup } from 'mime-types'; +import { promises as fs } from 'fs'; +import { responseStream } from 'http-response-stream'; // call express const app: Express = express(); // define our app using express const router = Router(); + + +// configure app to use bodyParser for +// Getting data from body of requests +app.use(bodyParser.json()); + +app.use(bodyParser.urlencoded({ extended: true })); + + +const port: number = Number(process.env.PORT) || 8050; // set our port + +// Send index.html on root request +app.use(express.static("dist")); + export function opdsRouter() { const path_of_books = "/Users/rishi/work/threetwo/src/server/comics"; console.log(path_of_books); @@ -27,23 +45,17 @@ export function opdsRouter() { [ async (feed: Feed) => { feed.books = feed.books || []; - await FastGlob(["*.cbr", "*.cbz"], { + await FastGlob(["*.cbr", "*.cbz", "*.cb7", "*.cba", "*.cbt"], { cwd: path_of_books, }).each((file) => { const ext = extname(file); const title = basename(file, ext); - /** - * make ur download url - */ const href = encodeURI( - `/Users/rishi/work/threetwo/src/server/comics/${file}`, + `/file/${file}`, ); - /** - * mime for file - */ - const type = "application/octet-stream"; + const type = lookup(ext) || "application/octet-stream";; const entry = Entry.deserialize({ title, @@ -71,27 +83,30 @@ export function opdsRouter() { return res.end(feed.toXML()); }); }); + + router.use("/file/*", async (req, res) => { + const file: string = req.params[0]; + const ext = extname(file); + + if ([".cbr", ".cbz", ".cb7", ".cba", ".cbt"].includes(ext)) { + const content = await fs.readFile(join(path_of_books, file)); + const mime = lookup(ext) || "application/octet-stream"; + res.set('Content-Type', mime); + return responseStream(res, content) + } + + res.status(404).end(`'${file}' not exists`) + }) return router; } - -// configure app to use bodyParser for -// Getting data from body of requests -app.use(bodyParser.json()); - -app.use(bodyParser.urlencoded({ extended: true })); -app.use(opdsRouter()); - -const port: number = Number(process.env.PORT) || 8050; // set our port - -// Send index.html on root request -app.use(express.static("dist")); - app.get("/", (req: Request, res: Response) => { console.log("sending index.html"); res.sendFile("/dist/index.html"); }); +app.use(opdsRouter()); + // REGISTER ROUTES // all of the routes will be prefixed with /api diff --git a/yarn.lock b/yarn.lock index a52862d..669ae6e 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1835,6 +1835,11 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.171.tgz#f01b3a5fe3499e34b622c362a46a609fdb23573b" integrity sha512-7eQ2xYLLI/LsicL2nejW9Wyko3lcpN6O/z0ZLHrEQsg280zIdCv1t/0m6UtBjUHokCGBQ3gYTbHzDkZ1xOBwwg== +"@types/mime-types@^2.1.0": + version "2.1.0" + resolved "https://registry.yarnpkg.com/@types/mime-types/-/mime-types-2.1.0.tgz#9ca52cda363f699c69466c2a6ccdaad913ea7a73" + integrity sha1-nKUs2jY/aZxpRmwqbM2q2RPqenM= + "@types/mime@^1": version "1.3.2" resolved "https://registry.yarnpkg.com/@types/mime/-/mime-1.3.2.tgz#93e25bf9ee75fe0fd80b594bc4feb0e862111b5a" @@ -6754,6 +6759,13 @@ http-proxy@^1.17.0: follow-redirects "^1.0.0" requires-port "^1.0.0" +http-response-stream@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/http-response-stream/-/http-response-stream-1.0.7.tgz#07e6104a8431c0788175578b3aebe3f0c7cf9925" + integrity sha512-d6PRAbo67f60BboWpG+RXS1wjPcWcMY6kq4LsACdUYscoh6Kw9HluRegy1/zweetrnatMxtD/dxtn1mO7XVvlQ== + dependencies: + tslib "^2.3.0" + http-signature@~1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1"