-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathindex.js
127 lines (111 loc) · 3.99 KB
/
index.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
const fs = require('fs');
const stream = require('stream');
const cors = require('cors');
const glob = require('glob');
const path = require('path');
const express = require('express');
const morgan = require('morgan');
const app = express();
const port = process.env.PORT || 3000;
const basePath = process.env.BASE_PATH;
app.use(morgan('short'));
const whitelist = ['https://dailypage.org', 'http://localhost:3000'];
const corsOptions = {
origin: (origin, callback) => {
if (whitelist.indexOf(origin) !== -1 || !origin) {
callback(null, true);
} else {
callback(new Error('Not allowed by CORS'));
}
},
};
app.use(cors(corsOptions));
app.options('*', cors(corsOptions));
app.get('/meta/music/artists', async (_, res) => {
res.send(fs.readdirSync(`${basePath}/meta/Artists`, { withFileTypes: true })
.filter(dirent => dirent.isDirectory())
.map(dirent => dirent.name))
});
function globAlbums(artist) {
return Object.keys(glob.GlobSync(`${basePath}/meta/Artists/${artist || '**'}/*`, {nodir: true}).matches[0]).map(match => {
const dirName = path.dirname(match).split('/');
const artist = dirName[dirName.length - 1];
return {artist: artist, name: path.basename(match)}
}).sort((a, b) => a.name.toLowerCase().localeCompare(b.name.toLowerCase()));
}
app.get('/meta/music/albums', async (_, res) => {
res.send(globAlbums());
});
function getTracks(artist) {
let allTracks = [];
globAlbums(artist).forEach((album) => {
const trackData = JSON.parse(fs.readFileSync(`${basePath}/meta/Artists/${album.artist}/${album.name}`).toString()).tracks
trackData.forEach((track) => {
allTracks.push({
id: track.id, title: track.name, album, artist: (track.artist ? track.artist : album.artist),
});
});
});
allTracks = allTracks.sort((a, b) => {
if (a.title > b.title) { return 1; }
if (b.title > a.title) { return -1; }
return 0;
});
return allTracks;
}
app.get('/meta/music/songs', async (req, res) => {
res.send(getTracks());
});
app.get('/meta/music/artist/:artistID/songs', async (req, res) => {
res.send(getTracks(req.params.artistID));
});
app.get('/meta/music/artist/:artistID/albums', async (req, res) => {
res.send(Object.keys(glob.GlobSync(`${basePath}/meta/Artists/${req.params.artistID}/*`, {nodir: true}).matches[0]).map(match => {
return path.basename(match);
}));
});
app.get('/meta/music/artist/:artistID/:albumID', async (req, res) => {
const albumFile = JSON.parse(fs.readFileSync(`${basePath}/meta/Artists/${req.params.artistID}/${req.params.albumID}`).toString());
res.send(albumFile)
});
app.use('/meta', express.static(`${basePath}/meta`));
app.get('/audio/:fileID/:albumID*?', async (req, res) => {
let readStream;
const filePath = `${basePath}/Albums/${req.params.albumID}/${req.params.fileID}.mp3`;
if (!fs.existsSync(filePath)) {
res.status(404).send('<h1>404, not found</h1>');
return;
}
let buffer = fs.readFileSync(filePath);
const total = buffer.byteLength;
if (req.headers.range) {
const { range } = req.headers;
const parts = range.replace(/bytes=/, '').split('-');
const partialStart = parts[0];
const partialEnd = parts[1];
const start = parseInt(partialStart, 10);
let end;
if (partialEnd) {
end = parseInt(partialEnd, 10);
buffer = Buffer.from(buffer.slice(start, end));
}
readStream = new stream.PassThrough();
readStream.end(buffer);
res.writeHead(206, {
Range: `bytes ${start}-${end}/${total}`,
'Content-Range': `bytes ${start}-${end}/${total}`,
'Content-Length': buffer.byteLength,
'Accept-Ranges': 'bytes',
'Content-Type': 'audio/mpeg',
});
readStream.pipe(res);
} else {
readStream = new stream.PassThrough();
readStream.end(buffer);
res.writeHead(200, { 'Content-Length': total, 'Content-Type': 'audio/mpeg' });
readStream.pipe(res);
}
});
app.listen(port, () => {
console.log(`Listening on ${port}`); // eslint-disable-line no-console
});