import path from 'path' import sqlite from 'sqlite' import Promise from 'bluebird' import express from 'express' require('express-async-errors') const values = require(path.join(process.cwd(), 'values.json')) const tracksPerPage = 100 const dbPromise = Promise.resolve() .then(() => sqlite.open(path.join(process.cwd(), values.database), { Promise, cache: true })) .then(db => db.migrate()) const app = express() const port = process.env.PORT || 3000 const router = express.Router() router.get('/tracks', async (req, res) => { let page = parseInt(req.query.page) || 1 if (isNaN(page)) { page = 1 } 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 let tracks = await db.all('SELECT * FROM Track LIMIT ? OFFSET ?', tracksPerPage, offset) for (let i in tracks) { delete tracks[i].file } res.jsonp({ page, count, pageCount, tracks }) }) let srchcategories = ['title', 'artist', 'album'] router.get('/tracks/search', async (req, res) => { let query = req.query.q 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}%` // Paging let page = parseInt(req.query.page) || 1 if (isNaN(page)) { page = 1 } let db = await dbPromise 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 let tracks = await db.all(`SELECT * FROM Track WHERE ${qr} LIKE ? LIMIT ? OFFSET ?`, query, tracksPerPage, offset) for (let i in tracks) { delete tracks[i].file } res.jsonp({ page, count, pageCount, tracks }) }) 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') 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 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')) let fpath = path.resolve(track.file) res.set('Cache-Control', 'public, max-age=31557600') if (req.query.dl && parseInt(req.query.dl) === 1) { return res.download(fpath) } res.redirect('/file/track' + fpath.substring(values.directory.length)) }) router.use((err, req, res, next) => { console.error(err) res.status(404).jsonp({error: 404}) }) app.use('/api', router) app.use('/file/track', express.static(path.resolve(values.directory))) app.use('/', express.static(path.join(process.cwd(), 'public'))) const host = process.env.NODE_ENV === 'development' ? '0.0.0.0' : '127.0.0.1' app.listen(port, host, function () { console.log(`app running on port ${port}`) })