2018-10-05 10:36:57 +00:00
|
|
|
import path from 'path'
|
|
|
|
import sqlite from 'sqlite'
|
|
|
|
import Promise from 'bluebird'
|
|
|
|
import express from 'express'
|
|
|
|
|
|
|
|
require('express-async-errors')
|
|
|
|
|
2018-10-18 15:34:47 +00:00
|
|
|
const values = require(path.join(process.cwd(), 'values.json'))
|
2018-10-05 10:36:57 +00:00
|
|
|
const tracksPerPage = 100
|
|
|
|
|
|
|
|
const dbPromise = Promise.resolve()
|
2018-10-18 15:34:47 +00:00
|
|
|
.then(() => sqlite.open(path.join(process.cwd(), values.database), { Promise, cache: true }))
|
2018-10-05 10:36:57 +00:00
|
|
|
.then(db => db.migrate())
|
|
|
|
|
|
|
|
const app = express()
|
|
|
|
const port = process.env.PORT || 3000
|
|
|
|
|
|
|
|
const router = express.Router()
|
|
|
|
|
2019-01-19 16:27:12 +00:00
|
|
|
const sortfields = ['id', 'track', 'artist', 'title', 'album', 'year']
|
|
|
|
const srchcategories = ['title', 'artist', 'album']
|
|
|
|
|
2018-10-05 10:36:57 +00:00
|
|
|
router.get('/tracks', async (req, res) => {
|
|
|
|
let page = parseInt(req.query.page) || 1
|
|
|
|
if (isNaN(page)) {
|
|
|
|
page = 1
|
|
|
|
}
|
|
|
|
|
2019-01-19 16:27:12 +00:00
|
|
|
let sort = req.query.sort
|
|
|
|
if (!sort || sortfields.indexOf(sort.toLowerCase()) === -1) {
|
|
|
|
sort = 'artist'
|
|
|
|
}
|
|
|
|
|
|
|
|
let sortdir = req.query.sortdir
|
|
|
|
if (!sortdir || (sortdir !== 'desc' && sortdir !== 'asc')) {
|
|
|
|
sortdir = 'asc'
|
|
|
|
}
|
|
|
|
|
2018-10-05 10:36:57 +00:00
|
|
|
let db = await dbPromise
|
|
|
|
let count = (await db.get('SELECT COUNT(*) FROM Track'))['COUNT(*)']
|
|
|
|
|
|
|
|
let pageCount = Math.ceil(count / tracksPerPage)
|
|
|
|
|
|
|
|
if (page > pageCount) page = pageCount
|
|
|
|
|
|
|
|
let offset = (page - 1) * tracksPerPage
|
2019-01-19 16:27:12 +00:00
|
|
|
let tracks = await db.all(`SELECT * FROM Track ORDER BY ${sort} ${sortdir.toUpperCase()} LIMIT ? OFFSET ?`, tracksPerPage, offset)
|
2018-10-05 10:36:57 +00:00
|
|
|
|
|
|
|
for (let i in tracks) {
|
|
|
|
delete tracks[i].file
|
|
|
|
}
|
|
|
|
|
|
|
|
res.jsonp({
|
|
|
|
page, count, pageCount, tracks
|
|
|
|
})
|
|
|
|
})
|
|
|
|
|
|
|
|
router.get('/tracks/search', async (req, res) => {
|
2018-10-09 15:15:26 +00:00
|
|
|
let query = req.query.q
|
2018-10-05 14:10:05 +00:00
|
|
|
let qr = ''
|
|
|
|
let exact = false
|
|
|
|
|
|
|
|
if (query.indexOf(':') !== -1) {
|
|
|
|
let ctr = query.split(':')
|
|
|
|
|
|
|
|
if (srchcategories.indexOf(ctr[0]) !== -1) {
|
|
|
|
qr = `ifnull(${ctr[0]}, '')`
|
|
|
|
query = query.substring(ctr[0].length + 1)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (qr === '') {
|
|
|
|
for (let c in srchcategories) {
|
|
|
|
let cat = srchcategories[c]
|
|
|
|
if (parseInt(c) !== 0) qr += ' || '
|
|
|
|
qr += `ifnull(${cat}, '')`
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (query.indexOf('=') !== -1 && query.indexOf('\\=') === -1) {
|
|
|
|
query = query.replace('=', '')
|
|
|
|
exact = true
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!exact) query = `%${query}%`
|
2018-10-05 10:36:57 +00:00
|
|
|
|
2019-01-19 16:27:12 +00:00
|
|
|
let sort = req.query.sort
|
|
|
|
if (!sort || sortfields.indexOf(sort.toLowerCase()) === -1) {
|
|
|
|
sort = 'artist'
|
|
|
|
}
|
|
|
|
|
|
|
|
let sortdir = req.query.sortdir
|
|
|
|
if (!sortdir || (sortdir !== 'desc' && sortdir !== 'asc')) {
|
|
|
|
sortdir = 'asc'
|
|
|
|
}
|
|
|
|
|
2018-10-09 15:15:26 +00:00
|
|
|
// Paging
|
|
|
|
let page = parseInt(req.query.page) || 1
|
|
|
|
if (isNaN(page)) {
|
|
|
|
page = 1
|
|
|
|
}
|
|
|
|
|
2018-10-05 10:36:57 +00:00
|
|
|
let db = await dbPromise
|
2018-10-09 15:15:26 +00:00
|
|
|
let count = (await db.get(`SELECT COUNT(*) FROM Track WHERE ${qr} LIKE ?`, query))['COUNT(*)']
|
|
|
|
let pageCount = Math.ceil(count / tracksPerPage)
|
|
|
|
|
|
|
|
if (page > pageCount) page = pageCount
|
|
|
|
|
|
|
|
let offset = (page - 1) * tracksPerPage
|
2019-01-19 16:27:12 +00:00
|
|
|
let tracks = await db.all(`SELECT * FROM Track WHERE ${qr} LIKE ? ORDER BY ${sort} ${sortdir.toUpperCase()} LIMIT ? OFFSET ?`,
|
|
|
|
query, tracksPerPage, offset)
|
2018-10-05 10:36:57 +00:00
|
|
|
|
|
|
|
for (let i in tracks) {
|
|
|
|
delete tracks[i].file
|
|
|
|
}
|
|
|
|
|
2018-10-09 15:15:26 +00:00
|
|
|
res.jsonp({
|
|
|
|
page, count, pageCount, tracks
|
|
|
|
})
|
2018-10-05 10:36:57 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
router.get('/track/:id', async (req, res, next) => {
|
|
|
|
let id = req.params.id
|
|
|
|
let db = await dbPromise
|
|
|
|
let track = await db.get('SELECT * FROM Track WHERE id = ?', id)
|
|
|
|
if (!track) return next(new Error('404 file not found'))
|
|
|
|
|
|
|
|
delete track.file
|
|
|
|
|
|
|
|
res.jsonp(track)
|
|
|
|
})
|
|
|
|
|
|
|
|
router.get('/playlists', async (req, res, next) => {
|
|
|
|
let db = await dbPromise
|
|
|
|
let playlists = await db.all('SELECT * FROM Playlist')
|
2018-10-10 10:02:56 +00:00
|
|
|
|
2018-10-05 10:36:57 +00:00
|
|
|
res.jsonp(playlists)
|
|
|
|
})
|
|
|
|
|
|
|
|
router.get('/playlist/:id', async (req, res, next) => {
|
|
|
|
let id = req.params.id
|
|
|
|
let db = await dbPromise
|
|
|
|
let playlist = await db.get('SELECT title FROM Playlist WHERE id = ?', id)
|
|
|
|
|
|
|
|
if (!playlist) return next(new Error('404 file not found'))
|
|
|
|
|
|
|
|
let tracks = await db.all('SELECT trackId FROM PlaylistEntry WHERE playlistId = ?', id)
|
|
|
|
playlist.tracks = tracks
|
2018-10-10 10:02:56 +00:00
|
|
|
|
2018-10-05 10:36:57 +00:00
|
|
|
res.jsonp(playlist)
|
|
|
|
})
|
|
|
|
|
|
|
|
router.get('/serve/by-id/:id', async (req, res, next) => {
|
|
|
|
let id = req.params.id
|
|
|
|
let db = await dbPromise
|
|
|
|
let track = await db.get('SELECT file FROM Track WHERE id = ?', id)
|
|
|
|
if (!track) return next(new Error('404 file not found'))
|
|
|
|
|
2018-10-10 10:02:56 +00:00
|
|
|
let fpath = path.resolve(track.file)
|
|
|
|
|
2018-10-05 10:36:57 +00:00
|
|
|
res.set('Cache-Control', 'public, max-age=31557600')
|
2018-10-10 10:02:56 +00:00
|
|
|
if (req.query.dl && parseInt(req.query.dl) === 1) {
|
|
|
|
return res.download(fpath)
|
|
|
|
}
|
|
|
|
|
2018-10-11 08:41:26 +00:00
|
|
|
res.redirect('/file/track' + fpath.substring(values.directory.length))
|
2018-10-05 10:36:57 +00:00
|
|
|
})
|
|
|
|
|
|
|
|
router.use((err, req, res, next) => {
|
|
|
|
console.error(err)
|
|
|
|
res.status(404).jsonp({error: 404})
|
|
|
|
})
|
|
|
|
|
|
|
|
app.use('/api', router)
|
2018-10-11 08:41:26 +00:00
|
|
|
app.use('/file/track', express.static(path.resolve(values.directory)))
|
2018-10-18 15:34:47 +00:00
|
|
|
app.use('/', express.static(path.join(process.cwd(), 'public')))
|
2018-10-05 10:36:57 +00:00
|
|
|
|
2019-01-15 14:21:33 +00:00
|
|
|
const host = process.env.NODE_ENV === 'development' ? '0.0.0.0' : '127.0.0.1'
|
|
|
|
|
|
|
|
app.listen(port, host, function () {
|
2018-10-05 10:36:57 +00:00
|
|
|
console.log(`app running on port ${port}`)
|
|
|
|
})
|