@home-cinema/app 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -0
- package/README.md +52 -0
- package/dist/api/index.js +4 -0
- package/dist/api/routes/config.js +6 -0
- package/dist/api/routes/streamFiles.js +42 -0
- package/dist/api/routes/tv_shows.js +98 -0
- package/dist/client/assets/favicon-RZMYYI_a.svg +1 -0
- package/dist/client/assets/home_img-CbOFmeaT.webp +0 -0
- package/dist/client/assets/index-CeKR2k9Q.js +749 -0
- package/dist/client/assets/index-DWHHH3Bn.css +1 -0
- package/dist/client/index.html +15 -0
- package/dist/client/vite.svg +1 -0
- package/dist/lib/idb.js +44 -0
- package/dist/lib/tmdb_api.js +116 -0
- package/dist/server/entry-server.js +10 -0
- package/dist/server/vite.svg +1 -0
- package/dist/server.js +8 -0
- package/dist/serverBoot.js +77 -0
- package/home_cinema_config.json +6 -0
- package/package.json +63 -0
package/README.md
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
## Home Cinema
|
|
2
|
+
|
|
3
|
+
A website for browsing movie lists and information. it uses [YTS](https://yts.mx/) API and [Torrent Streamer Api](https://github.com/KHLALA-Gh/torrent-streamer-api), built with [Vite](https://vite.dev/) and [React](https://react.dev/)
|
|
4
|
+
|
|
5
|
+

|
|
6
|
+
|
|
7
|
+
### Setup
|
|
8
|
+
|
|
9
|
+
#### Docker (Recommended) :
|
|
10
|
+
|
|
11
|
+
You can use Home Cinema Docker images to run the application with Docker Compose.
|
|
12
|
+
First create `docker-compose.yml` file in the location you want and add the content below.
|
|
13
|
+
|
|
14
|
+
```yml
|
|
15
|
+
services:
|
|
16
|
+
home-cinema-website:
|
|
17
|
+
image: khlala/home-cinema-web:alpha5
|
|
18
|
+
# image: khlala/home-cinema-web:alpha5-arm64 ## use this image if you are running on arm64 arch
|
|
19
|
+
ports:
|
|
20
|
+
- "8000:4173"
|
|
21
|
+
environment:
|
|
22
|
+
- TMDB_KEY=<your_TMDB_api_key> ## Set your TMDB api key here
|
|
23
|
+
restart: always
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
To get TV Shows information you need to get TMDB api key from [TMDB](https://www.themoviedb.org/).
|
|
27
|
+
|
|
28
|
+
> **Note** : Home cinema is still in alpha versions, you may encounter difficulties when installing it.
|
|
29
|
+
|
|
30
|
+
To run the application execute this command :
|
|
31
|
+
|
|
32
|
+
```shell
|
|
33
|
+
docker compose up
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
The website should be accessible from : http://localhost:8000/home_cinema
|
|
37
|
+
|
|
38
|
+
### Configs
|
|
39
|
+
|
|
40
|
+
Create `./config` directory where you created `docker-compose.yml`. Then create your config file `home_cinema_config.json` inside the new directory.
|
|
41
|
+
If you want to know about configurations go [here](./docs/configurations.md).
|
|
42
|
+
|
|
43
|
+
To pass configs through docker compose add your config file in the container volumes.
|
|
44
|
+
|
|
45
|
+
```yml
|
|
46
|
+
volumes:
|
|
47
|
+
- ./config/home_cinema_config.json:/app/dist/home_cinema_config.json
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
### Issues
|
|
51
|
+
|
|
52
|
+
If you encounter any issues using the website don't hesitate to submit an [issue](https://github.com/KHLALA-Gh/HomeCinemaWebsite/issues)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
export const router = Router();
|
|
3
|
+
router.get("/api/playlist", (req, res) => {
|
|
4
|
+
let streams = [];
|
|
5
|
+
if (typeof req.query.streams === "string") {
|
|
6
|
+
streams = [req.query.streams];
|
|
7
|
+
}
|
|
8
|
+
else if (req.query.streams instanceof Array) {
|
|
9
|
+
streams = req.query.streams;
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
res.status(400).json({
|
|
13
|
+
error: "Stream urls are required",
|
|
14
|
+
});
|
|
15
|
+
return;
|
|
16
|
+
}
|
|
17
|
+
let names = [];
|
|
18
|
+
if (typeof req.query.names === "string") {
|
|
19
|
+
names = [req.query.names];
|
|
20
|
+
}
|
|
21
|
+
else if (req.query.names instanceof Array) {
|
|
22
|
+
names = req.query.names;
|
|
23
|
+
}
|
|
24
|
+
else {
|
|
25
|
+
res.status(400).json({
|
|
26
|
+
error: "stream names are required",
|
|
27
|
+
});
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
let fileName = req.query.fileName;
|
|
31
|
+
if (!fileName) {
|
|
32
|
+
fileName = "playlist";
|
|
33
|
+
}
|
|
34
|
+
let playlist = "#EXTM3U\n";
|
|
35
|
+
streams.forEach((url, index) => {
|
|
36
|
+
playlist += `#EXTINF:-1,${names[index]}\n${url}\n`;
|
|
37
|
+
});
|
|
38
|
+
// Set response headers
|
|
39
|
+
res.setHeader("Content-Type", "audio/x-mpegurl");
|
|
40
|
+
res.setHeader("Content-Disposition", `attachment; filename="${fileName}.m3u"`);
|
|
41
|
+
res.send(playlist);
|
|
42
|
+
});
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
import { TMDBApi, TMDBError } from "../../lib/tmdb_api.js";
|
|
3
|
+
export const router = Router();
|
|
4
|
+
function HandlerTMDBApiErr(res, err) {
|
|
5
|
+
console.log(TMDBError.format(err));
|
|
6
|
+
res.status(err.statusCode || 500).json({
|
|
7
|
+
error: err.message,
|
|
8
|
+
});
|
|
9
|
+
return;
|
|
10
|
+
}
|
|
11
|
+
router.get("/api/tv_shows", async (req, res) => {
|
|
12
|
+
try {
|
|
13
|
+
const tmApi = new TMDBApi(process.env.TMDB_KEY);
|
|
14
|
+
let page = req.query.page;
|
|
15
|
+
if (page && isNaN(+page)) {
|
|
16
|
+
page = "1";
|
|
17
|
+
}
|
|
18
|
+
const data = await tmApi.getTVShows(page);
|
|
19
|
+
res.status(200).json(data);
|
|
20
|
+
}
|
|
21
|
+
catch (err) {
|
|
22
|
+
if (err instanceof TMDBError) {
|
|
23
|
+
res.status(err.statusCode || 500).json({
|
|
24
|
+
error: err.message,
|
|
25
|
+
});
|
|
26
|
+
console.log(TMDBError.format(err));
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
res.status(500).json({
|
|
30
|
+
error: "internal server error",
|
|
31
|
+
});
|
|
32
|
+
console.log("error when getting TV SHOWS");
|
|
33
|
+
}
|
|
34
|
+
});
|
|
35
|
+
router.get("/api/tv_shows/search", async (req, res) => {
|
|
36
|
+
try {
|
|
37
|
+
const query = req.query.query;
|
|
38
|
+
let page = +req.query.page;
|
|
39
|
+
if (typeof query !== "string") {
|
|
40
|
+
res.status(400).json({
|
|
41
|
+
error: "search query is required",
|
|
42
|
+
});
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
if (!page) {
|
|
46
|
+
page = 1;
|
|
47
|
+
}
|
|
48
|
+
const api = new TMDBApi(process.env.TMDB_KEY);
|
|
49
|
+
const data = await api.searchTvShows(query, page.toString());
|
|
50
|
+
res.status(200).json(data);
|
|
51
|
+
}
|
|
52
|
+
catch (err) {
|
|
53
|
+
if (err instanceof TMDBError) {
|
|
54
|
+
return HandlerTMDBApiErr(res, err);
|
|
55
|
+
}
|
|
56
|
+
res.status(500).json({
|
|
57
|
+
error: "Internal Server Error",
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
router.get("/api/tv_shows/:id", async (req, res) => {
|
|
62
|
+
try {
|
|
63
|
+
const id = req.params.id;
|
|
64
|
+
const api = new TMDBApi(process.env.TMDB_KEY);
|
|
65
|
+
const data = await api.getTVShowDetails(id);
|
|
66
|
+
res.status(200).json(data);
|
|
67
|
+
}
|
|
68
|
+
catch (err) {
|
|
69
|
+
if (err instanceof TMDBError) {
|
|
70
|
+
console.log(TMDBError.format(err));
|
|
71
|
+
res.status(err.statusCode || 500).json({
|
|
72
|
+
error: err.message,
|
|
73
|
+
});
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
console.log("Internal Server Error !! : ", err);
|
|
77
|
+
res.status(500).json({
|
|
78
|
+
error: "internal server error",
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
router.get("/api/tv_shows/:id/season/:season_number", async (req, res) => {
|
|
83
|
+
try {
|
|
84
|
+
const id = req.params.id;
|
|
85
|
+
const seasonNumber = req.params.season_number;
|
|
86
|
+
const api = new TMDBApi(process.env.TMDB_KEY);
|
|
87
|
+
const data = await api.getSeasonDetails(id, seasonNumber);
|
|
88
|
+
res.status(200).json(data);
|
|
89
|
+
}
|
|
90
|
+
catch (err) {
|
|
91
|
+
if (err instanceof TMDBError) {
|
|
92
|
+
return HandlerTMDBApiErr(res, err);
|
|
93
|
+
}
|
|
94
|
+
res.status(500).json({
|
|
95
|
+
error: "Internal Server Error",
|
|
96
|
+
});
|
|
97
|
+
}
|
|
98
|
+
});
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><!--!Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2025 Fonticons, Inc.--><path d="M0 96C0 60.7 28.7 32 64 32l384 0c35.3 0 64 28.7 64 64l0 320c0 35.3-28.7 64-64 64L64 480c-35.3 0-64-28.7-64-64L0 96zM48 368l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0c-8.8 0-16 7.2-16 16zm368-16c-8.8 0-16 7.2-16 16l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0zM48 240l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0c-8.8 0-16 7.2-16 16zm368-16c-8.8 0-16 7.2-16 16l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0zM48 112l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16L64 96c-8.8 0-16 7.2-16 16zM416 96c-8.8 0-16 7.2-16 16l0 32c0 8.8 7.2 16 16 16l32 0c8.8 0 16-7.2 16-16l0-32c0-8.8-7.2-16-16-16l-32 0zM160 128l0 64c0 17.7 14.3 32 32 32l128 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32L192 96c-17.7 0-32 14.3-32 32zm32 160c-17.7 0-32 14.3-32 32l0 64c0 17.7 14.3 32 32 32l128 0c17.7 0 32-14.3 32-32l0-64c0-17.7-14.3-32-32-32l-128 0z"/></svg>
|
|
Binary file
|