This commit is contained in:
25
services/database/CONNECTOR.js
Normal file
25
services/database/CONNECTOR.js
Normal file
@@ -0,0 +1,25 @@
|
||||
const { MongoClient } = require('mongodb');
|
||||
const server = require("../../server");
|
||||
const config = server.config;
|
||||
|
||||
var dbo;
|
||||
const url = "mongodb://" + config.database.host + ":" + config.database.port + "/";
|
||||
const database = config.database.name;
|
||||
|
||||
exports.connect = async function () {
|
||||
if (dbo) {
|
||||
console.log("DB CONNECTED")
|
||||
return dbo;
|
||||
}
|
||||
else {
|
||||
try {
|
||||
console.log("DB CONNECTING:" + config.database.host + ":" + config.database.port)
|
||||
const client = await MongoClient.connect(url);
|
||||
dbo = client.db(database);
|
||||
return dbo;
|
||||
} catch (error) {
|
||||
console.error(`MongoDB connection failed with > ${error}`);
|
||||
throw error;
|
||||
}
|
||||
}
|
||||
}
|
||||
302
services/database/albums.js
Normal file
302
services/database/albums.js
Normal file
@@ -0,0 +1,302 @@
|
||||
const redis = require("../redis")
|
||||
|
||||
const { ObjectId } = require('mongodb');
|
||||
const connector = require("./CONNECTOR");
|
||||
var dbo;
|
||||
connector.connect().then((ret) => {
|
||||
dbo = ret;
|
||||
dbo.collection("albums").createIndex({ artist_name: 1, year: 1, title: 1 });
|
||||
// TEMPORARY
|
||||
dbo.collection("albums").updateMany({}, { $unset: { cover32: 1, cover64: 1, cover128: 1, cover256: 1, cover512: 1 } });
|
||||
updateArtistName();
|
||||
});
|
||||
|
||||
function updateArtistName() {
|
||||
dbo.collection("albums")
|
||||
.find({ artist_name: undefined })
|
||||
.toArray((err, result) => {
|
||||
result.forEach(item => {
|
||||
dbo.collection("artists")
|
||||
.findOne({ _id: item.artist_id })
|
||||
.then(artist => {
|
||||
if (artist) {
|
||||
dbo.collection("albums")
|
||||
.updateOne(
|
||||
{ _id: item._id },
|
||||
{ $set: { artist_id: artist._id, artist_name: artist.name } },
|
||||
{ upsert: false });
|
||||
}
|
||||
});
|
||||
})
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
exports.collection = function (page, filter, callback) {
|
||||
process.stdout.write("services/db_manager ALBUMS Collection: " + page + "\n");
|
||||
let redis_key = "albumsCollection_" + (filter || '') + '_' + page;
|
||||
|
||||
redis.get(redis_key, (value) => {
|
||||
if (value) {
|
||||
process.stdout.write("services/db_manager ALBUMS Collection REDIS: " + page + "\n");
|
||||
callback(value);
|
||||
} else {
|
||||
let aggregate = [
|
||||
{ $project: { "covers.cover256": false, "covers.cover64": false, "covers.cover32": false } },
|
||||
{ $match: { visibility: { $not: { $eq: 'hidden' } } } },
|
||||
{ $sort: { artist_name: 1, year: 1, title: 1 } },
|
||||
];
|
||||
|
||||
if (filter) {
|
||||
aggregate.push({
|
||||
$match: { visibility: { $in: filter } }
|
||||
});
|
||||
}
|
||||
|
||||
if (page > -1) {
|
||||
let pageSize = 12;
|
||||
let skip = (page - 1) * pageSize;
|
||||
aggregate.push(
|
||||
{ $skip: skip },
|
||||
{ $limit: pageSize });
|
||||
}
|
||||
dbo
|
||||
.collection("albums")
|
||||
.aggregate(aggregate, { allowDiskUse: true })
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
result.forEach(album => {
|
||||
album.type = "album";
|
||||
album.tracks = [];
|
||||
});
|
||||
}
|
||||
process.stdout.write("services/db_manager ALBUMS Collection MONGO: " + page + "\n");
|
||||
callback(result);
|
||||
redis.set(redis_key, result);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.favourites = function (id, callback) {
|
||||
dbo.collection("favourites")
|
||||
.find({ userId: id, type: "album" })
|
||||
.toArray((err, favourites) => {
|
||||
if (err) throw err;
|
||||
let aggregate = [
|
||||
{ $match: { _id: { $in: favourites.map(m => m.itemId) } } },
|
||||
{ $project: { "covers.cover256": false, "covers.cover64": false, "covers.cover32": false } },
|
||||
]
|
||||
dbo.collection("albums")
|
||||
.aggregate(aggregate)
|
||||
.toArray((err, result) => {
|
||||
result.forEach(album => {
|
||||
album.type = "album";
|
||||
album.tracks = [];
|
||||
});
|
||||
callback(result);
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
exports.newest = function (count, filter, callback) {
|
||||
let aggregate = [
|
||||
{ $project: { "covers.cover256": false, "covers.cover128": false, "covers.cover32": false } },
|
||||
{ $match: { visibility: { $not: { $eq: 'hidden' } } } },
|
||||
{ $sort: { _id: -1 } },
|
||||
];
|
||||
|
||||
if (filter) {
|
||||
aggregate.push({
|
||||
$match: { visibility: { $in: filter } }
|
||||
});
|
||||
}
|
||||
aggregate.push({ $limit: count })
|
||||
|
||||
dbo
|
||||
.collection("albums")
|
||||
.aggregate(aggregate, {
|
||||
allowDiskUse: true
|
||||
})
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
result.forEach(album => {
|
||||
album.type = "album";
|
||||
album.tracks = [];
|
||||
});
|
||||
}
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.byId = function (id, filter, callback) {
|
||||
process.stdout.write("services/db_manager ALBUM by id: " + id + "\n");
|
||||
let redis_key = "albumId_" + (filter || '') + '_' + id;
|
||||
|
||||
redis.get(redis_key, (value) => {
|
||||
if (value) {
|
||||
process.stdout.write("services/db_manager ALBUM by id REDIS: " + id + "\n");
|
||||
callback(value);
|
||||
} else {
|
||||
let aggregate = [
|
||||
{
|
||||
$lookup: {
|
||||
from: "tracks",
|
||||
localField: "_id",
|
||||
foreignField: "album_id",
|
||||
as: "tracks"
|
||||
}
|
||||
},
|
||||
{ $match: { _id: ObjectId(id) } }
|
||||
]
|
||||
|
||||
if (filter) {
|
||||
aggregate.push({
|
||||
$match: { visibility: { $in: filter } }
|
||||
});
|
||||
}
|
||||
|
||||
dbo
|
||||
.collection("albums")
|
||||
.aggregate(aggregate)
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
result.forEach(album => {
|
||||
album.type = "album";
|
||||
});
|
||||
}
|
||||
process.stdout.write("services/db_manager ALBUM by id MONGO: " + id + "\n");
|
||||
callback(result[0]);
|
||||
redis.set(redis_key, result[0]);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.filter = function (term, callback) {
|
||||
let aggregate = [
|
||||
{ $project: { 'parent.covers': false, 'covers.cover32': false, 'covers.cover256': false } },
|
||||
{ $match: { title: { $regex: term, $options: "i" } }, },
|
||||
{ $limit: 6 }
|
||||
]
|
||||
dbo
|
||||
.collection("albums")
|
||||
.aggregate(aggregate)
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.tracks = function (id, callback) {
|
||||
process.stdout.write("services/db_manager TRACKS by id: " + id + "\n");
|
||||
|
||||
let request = [
|
||||
{
|
||||
$lookup: {
|
||||
from: "tracks",
|
||||
localField: "_id",
|
||||
foreignField: "album_id",
|
||||
as: "tracks"
|
||||
}
|
||||
},
|
||||
{ $match: { _id: ObjectId(id) } }
|
||||
];
|
||||
|
||||
dbo
|
||||
.collection("albums")
|
||||
.aggregate(request)
|
||||
.toArray((err, result) => {
|
||||
if (result) {
|
||||
callback(result[0]);
|
||||
} else {
|
||||
if (err) {
|
||||
process.stderr("services/db_manager ALBUM by id ERROR: " + err.message);
|
||||
}
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.delete = function (album, callback) {
|
||||
dbo.collection("albums")
|
||||
.deleteOne({ _id: ObjectId(album._id) }, err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.update = function (album, callback) {
|
||||
dbo.collection("albums")
|
||||
.updateOne(
|
||||
{ _id: ObjectId(album._id) },
|
||||
{
|
||||
$set: {
|
||||
visibility: album.visibility
|
||||
}
|
||||
},
|
||||
{ upsert: false },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
exports.updateCovers = function (album, covers, callback) {
|
||||
dbo.collection("albums")
|
||||
.updateOne(
|
||||
{ _id: ObjectId(album._id) },
|
||||
{ $set: { covers: covers } },
|
||||
{ upsert: false },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
exports.moveTo = function (album, callback) {
|
||||
process.stdout.write("services/db_manager ALBUM '" + album._id + "' move to '" + album.artist_id + "'\n");
|
||||
|
||||
dbo
|
||||
.collection("albums")
|
||||
.updateOne(
|
||||
{ _id: ObjectId(album._id) },
|
||||
{ $set: { artist_id: ObjectId(album.artist_id), artist_name: album.artist_name } },
|
||||
{ upsert: false },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.empty = function (callback) {
|
||||
dbo
|
||||
.collection("albums")
|
||||
.aggregate([
|
||||
{
|
||||
$lookup: {
|
||||
from: "tracks",
|
||||
localField: "_id",
|
||||
foreignField: "album_id",
|
||||
as: "tracks"
|
||||
}
|
||||
}
|
||||
])
|
||||
.toArray((err, result) => {
|
||||
callback(result.filter(f => !f.tracks || f.tracks.length == 0));
|
||||
});
|
||||
};
|
||||
264
services/database/artists.js
Normal file
264
services/database/artists.js
Normal file
@@ -0,0 +1,264 @@
|
||||
const redis = require("../redis")
|
||||
const { ObjectId } = require('mongodb');
|
||||
const connector = require("./CONNECTOR");
|
||||
var dbo;
|
||||
connector.connect().then((ret) => {
|
||||
dbo = ret;
|
||||
dbo.collection("artists").createIndex({ name: 1 });
|
||||
// TEMPORARY
|
||||
dbo.collection("artists").updateMany({}, { $unset: { cover32: 1, cover64: 1, cover128: 1, cover256: 1, cover512: 1 } })
|
||||
});
|
||||
|
||||
let artist_lookup_album = {
|
||||
$lookup: {
|
||||
from: "albums",
|
||||
localField: "_id",
|
||||
foreignField: "artist_id",
|
||||
as: "albums"
|
||||
}
|
||||
}
|
||||
let artist_lookup_tracks = {
|
||||
$lookup: {
|
||||
from: "tracks",
|
||||
localField: "albums._id",
|
||||
foreignField: "album_id",
|
||||
as: "albums.tracks"
|
||||
}
|
||||
}
|
||||
let artists_project = {
|
||||
$project: {
|
||||
"covers.cover64": false,
|
||||
"covers.cover128": false,
|
||||
"covers.cover512": false,
|
||||
"covers.cover1024": false,
|
||||
}
|
||||
}
|
||||
let artist_project = {
|
||||
$project: {
|
||||
"albums.tracks.path": false,
|
||||
"albums.tracks.bitrate": false,
|
||||
"albums.tracks.album_id": false,
|
||||
"albums.tracks.mime": false,
|
||||
"albums.artist_id": false,
|
||||
"albums.covers.cover256": false,
|
||||
"albums.covers.cover512": false
|
||||
}
|
||||
}
|
||||
exports.collection = function (page, filter, callback) {
|
||||
process.stdout.write("services/db_manager ARTISTS Collection: " + page + "\n");
|
||||
let redis_key = "artistsCollection_" + (filter || '') + '_' + page;
|
||||
|
||||
redis.get(redis_key, (value) => {
|
||||
if (value) {
|
||||
process.stdout.write("services/db_manager ARTISTS Collection REDIS: " + page + "\n");
|
||||
callback(value);
|
||||
} else {
|
||||
|
||||
let aggregate = []
|
||||
if (filter) {
|
||||
aggregate.push(
|
||||
artist_lookup_album, {
|
||||
$match: { "albums.visibility": { $in: filter } }
|
||||
});
|
||||
}
|
||||
aggregate.push(
|
||||
artists_project,
|
||||
{ $sort: { name: 1 } }
|
||||
)
|
||||
if (page > -1) {
|
||||
let pageSize = 12;
|
||||
let skip = (page - 1) * pageSize;
|
||||
aggregate.push(
|
||||
{ $skip: skip },
|
||||
{ $limit: pageSize });
|
||||
}
|
||||
|
||||
dbo
|
||||
.collection("artists")
|
||||
.aggregate(aggregate, { allowDiskUse: true })
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
result.forEach(item => {
|
||||
item.type = "artist";
|
||||
item.albums = [];
|
||||
item.tracks = [];
|
||||
});
|
||||
}
|
||||
process.stdout.write("services/db_manager ARTISTS Collection MONGO: " + page + "\n");
|
||||
callback(result);
|
||||
redis.set(redis_key, result);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.favourites = function (id, callback) {
|
||||
dbo.collection("favourites")
|
||||
.find({ userId: id, type: "artist" })
|
||||
.toArray((err, favourites) => {
|
||||
if (err) throw err;
|
||||
let aggregate = [
|
||||
{ $match: { _id: { $in: favourites.map(m => m.itemId) } } },
|
||||
artists_project,
|
||||
]
|
||||
dbo.collection("artists")
|
||||
.aggregate(aggregate)
|
||||
.toArray((err, result) => {
|
||||
result.forEach(item => {
|
||||
item.type = "artist";
|
||||
item.albums = [];
|
||||
item.tracks = [];
|
||||
});
|
||||
callback(result);
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
exports.byId = function (id, filter, callback) {
|
||||
process.stdout.write("services/db_manager ARTIST by id: " + id + "\n");
|
||||
let redis_key = "artistId_" + (filter || '') + '_' + id;
|
||||
|
||||
redis.get(redis_key, (value) => {
|
||||
if (value) {
|
||||
process.stdout.write("services/db_manager ARTIST by id REDIS: " + id + "\n");
|
||||
callback(value);
|
||||
} else {
|
||||
|
||||
let aggregate = [
|
||||
artist_lookup_album,
|
||||
{
|
||||
$unwind: { path: "$albums" }
|
||||
},
|
||||
artist_lookup_tracks,
|
||||
artist_project,
|
||||
{
|
||||
$group: {
|
||||
_id: "$_id",
|
||||
name: { $first: "$name" },
|
||||
covers: { $first: "$covers" },
|
||||
albums: { $push: "$albums" }
|
||||
}
|
||||
},
|
||||
{ $match: { _id: ObjectId(id) } },
|
||||
];
|
||||
dbo
|
||||
.collection("artists")
|
||||
.aggregate(aggregate)
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
result.forEach(item => {
|
||||
item.type = "artist";
|
||||
item.tracks = [];
|
||||
if (filter) {
|
||||
item.albums = item.albums.filter(album => { return filter.indexOf(album.visibility) > -1 });
|
||||
}
|
||||
});
|
||||
}
|
||||
process.stdout.write("services/db_manager ARTIST by id MONGO: " + id + "\n");
|
||||
callback(result[0]);
|
||||
redis.set(redis_key, result[0]);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.filter = function (term, callback) {
|
||||
let aggregate = [
|
||||
{ $project: { 'covers.cover64': false, 'covers.cover512': false } },
|
||||
{ $match: { name: { $regex: term, $options: "i" } }, },
|
||||
{ $limit: 6 }
|
||||
]
|
||||
dbo
|
||||
.collection("artists")
|
||||
.aggregate(aggregate)
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.tracks = function (id, showPath, callback) {
|
||||
let request = [
|
||||
artist_lookup_album,
|
||||
{
|
||||
$unwind: { path: "$albums" }
|
||||
},
|
||||
artist_lookup_tracks,
|
||||
{ $match: { _id: ObjectId(id) } },
|
||||
{
|
||||
$group: {
|
||||
_id: "$_id",
|
||||
name: { $first: "$name" },
|
||||
albums: { $push: "$albums" }
|
||||
}
|
||||
}
|
||||
];
|
||||
|
||||
if (!showPath) {
|
||||
request.push({
|
||||
$project: {
|
||||
"albums.tracks.path": false,
|
||||
"albums.tracks.bitrate": false,
|
||||
"albums.tracks.album_id": false,
|
||||
"albums.tracks.mime": false,
|
||||
"albums.artist_id": false,
|
||||
"albums.covers": false,
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dbo
|
||||
.collection("artists")
|
||||
.aggregate(request)
|
||||
.toArray((err, result) => {
|
||||
if (result) {
|
||||
callback(result[0]);
|
||||
} else {
|
||||
callback(null);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.delete = function (artist, callback) {
|
||||
dbo.collection("artists")
|
||||
.deleteOne({ _id: ObjectId(artist._id) }, err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.updateCovers = function (artist, covers, callback) {
|
||||
dbo.collection("artists").updateOne(
|
||||
{ _id: ObjectId(artist._id) },
|
||||
{ $set: { covers: covers } },
|
||||
{ upsert: false },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
exports.empty = function (callback) {
|
||||
dbo
|
||||
.collection("artists")
|
||||
.aggregate([
|
||||
{
|
||||
$lookup: {
|
||||
from: "albums",
|
||||
localField: "_id",
|
||||
foreignField: "artist_id",
|
||||
as: "albums"
|
||||
}
|
||||
}
|
||||
])
|
||||
.toArray((err, result) => {
|
||||
callback(result.filter(f => !f.albums || f.albums.length == 0));
|
||||
});
|
||||
};
|
||||
273
services/database/boxes.js
Normal file
273
services/database/boxes.js
Normal file
@@ -0,0 +1,273 @@
|
||||
const redis = require("../redis")
|
||||
const { ObjectId } = require('mongodb');
|
||||
const connector = require("./CONNECTOR");
|
||||
var dbo;
|
||||
connector.connect().then((ret) => {
|
||||
dbo = ret;
|
||||
dbo.collection("boxes").createIndex({ title: 1 });
|
||||
// TEMPORARY
|
||||
dbo.collection("boxes").updateMany({}, { $unset: { cover32: 1, cover64: 1, cover128: 1, cover256: 1, cover512: 1 } })
|
||||
});
|
||||
|
||||
let box_project = {
|
||||
$project: {
|
||||
"videos.path": false,
|
||||
"videos.box_id": false,
|
||||
"videos.mime": false,
|
||||
path: false,
|
||||
"covers.cover32": false,
|
||||
}
|
||||
}
|
||||
let boxes_project = {
|
||||
$project: {
|
||||
path: false,
|
||||
"covers.cover32": false,
|
||||
"covers.cover64": false,
|
||||
"covers.cover256": false
|
||||
}
|
||||
}
|
||||
let box_lookup_videos = {
|
||||
$lookup: {
|
||||
from: "videos",
|
||||
localField: "_id",
|
||||
foreignField: "box_id",
|
||||
as: "videos"
|
||||
}
|
||||
}
|
||||
|
||||
exports.collection = function (page, filter, callback) {
|
||||
process.stdout.write("services/db_manager BOXES Collection: " + page + "\n");
|
||||
let redis_key = "boxesCollection_" + (filter || '') + '_' + page;
|
||||
|
||||
redis.get(redis_key, (value) => {
|
||||
if (value) {
|
||||
process.stdout.write("services/db_manager BOXES Collection REDIS: " + page + "\n");
|
||||
callback(value);
|
||||
} else {
|
||||
|
||||
let aggregate = [
|
||||
boxes_project,
|
||||
{ $match: { visibility: { $not: { $eq: 'hidden' } } } },
|
||||
{ $sort: { title: 1 } },
|
||||
];
|
||||
if (filter) {
|
||||
aggregate.push({
|
||||
$match: { visibility: { $in: filter } }
|
||||
});
|
||||
}
|
||||
if (page > -1) {
|
||||
let pageSize = 12;
|
||||
let skip = (page - 1) * pageSize;
|
||||
aggregate.push(
|
||||
{ $skip: skip },
|
||||
{ $limit: pageSize });
|
||||
}
|
||||
dbo
|
||||
.collection("boxes")
|
||||
.aggregate(aggregate, {
|
||||
allowDiskUse: true
|
||||
})
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
result.forEach(item => {
|
||||
item.type = "box";
|
||||
item.videos = [];
|
||||
});
|
||||
}
|
||||
process.stdout.write("services/db_manager BOXES Collection MONGO: " + page + "\n");
|
||||
callback(result);
|
||||
redis.set(redis_key, result);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.favourites = function (id, callback) {
|
||||
dbo.collection("favourites")
|
||||
.find({ userId: id, type: "box" })
|
||||
.toArray((err, favourites) => {
|
||||
if (err) throw err;
|
||||
let aggregate = [
|
||||
{ $match: { _id: { $in: favourites.map(m => m.itemId) } } },
|
||||
boxes_project,
|
||||
]
|
||||
dbo.collection("boxes")
|
||||
.aggregate(aggregate)
|
||||
.toArray((err, result) => {
|
||||
result.forEach(item => {
|
||||
item.type = "box";
|
||||
item.videos = [];
|
||||
});
|
||||
callback(result);
|
||||
});
|
||||
})
|
||||
};
|
||||
|
||||
|
||||
exports.newest = function (count, filter, callback) {
|
||||
let aggregate = [
|
||||
boxes_project,
|
||||
{ $sort: { _id: -1 } },
|
||||
{ $match: { visibility: { $not: { $eq: 'hidden' } } } }
|
||||
];
|
||||
if (filter) {
|
||||
aggregate.push({
|
||||
$match: { visibility: { $in: filter } }
|
||||
});
|
||||
}
|
||||
aggregate.push({ $limit: count })
|
||||
|
||||
dbo
|
||||
.collection("boxes")
|
||||
.aggregate(aggregate, {
|
||||
allowDiskUse: true
|
||||
})
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
result.forEach(item => {
|
||||
item.type = "box";
|
||||
item.videos = [];
|
||||
});
|
||||
}
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
exports.byId = function (id, filter, callback) {
|
||||
process.stdout.write("services/db_manager BOX by id: " + id + "\n");
|
||||
let redis_key = "boxId_" + (filter || '') + '_' + id;
|
||||
|
||||
redis.get(redis_key, (value) => {
|
||||
if (value) {
|
||||
process.stdout.write("services/db_manager BOX by id REDIS: " + id + "\n");
|
||||
callback(value);
|
||||
} else {
|
||||
let aggregate = [
|
||||
box_lookup_videos,
|
||||
box_project,
|
||||
{ $match: { _id: ObjectId(id) } }
|
||||
];
|
||||
if (filter) {
|
||||
aggregate.push({
|
||||
$match: { visibility: { $in: filter } }
|
||||
});
|
||||
}
|
||||
|
||||
dbo
|
||||
.collection("boxes")
|
||||
.aggregate(aggregate)
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
result.forEach(item => {
|
||||
item.type = "box";
|
||||
});
|
||||
}
|
||||
process.stdout.write("services/db_manager BOX by id MONGO: " + id + "\n");
|
||||
callback(result[0]);
|
||||
redis.set(redis_key, result[0]);
|
||||
});
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.filter = function (term, callback) {
|
||||
let aggregate = [
|
||||
{ $project: { 'covers.cover256': false } },
|
||||
{ $match: { title: { $regex: term, $options: "i" } }, },
|
||||
{ $limit: 6 }
|
||||
]
|
||||
dbo
|
||||
.collection("boxes")
|
||||
.aggregate(aggregate)
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.empty = function (callback) {
|
||||
dbo
|
||||
.collection("boxes")
|
||||
.aggregate([box_lookup_videos])
|
||||
.toArray((err, result) => {
|
||||
callback(result.filter(f => !f.videos || f.videos.length == 0));
|
||||
});
|
||||
};
|
||||
|
||||
exports.videos = function (id, showPath, callback) {
|
||||
let request = [
|
||||
{
|
||||
$lookup: {
|
||||
from: "videos",
|
||||
localField: "_id",
|
||||
foreignField: "box_id",
|
||||
as: "videos"
|
||||
}
|
||||
},
|
||||
{ $match: { _id: ObjectId(id) } }
|
||||
];
|
||||
|
||||
if (!showPath) {
|
||||
request.push({
|
||||
$project: {
|
||||
"videos.mime": false,
|
||||
"videos.path": false,
|
||||
"videos.box_id": false,
|
||||
path: false,
|
||||
"covers.cover32": false,
|
||||
"covers.cover64": false,
|
||||
"covers.cover128": false
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
dbo
|
||||
.collection("boxes")
|
||||
.aggregate(request)
|
||||
.toArray((err, result) => {
|
||||
callback(result[0]);
|
||||
});
|
||||
};
|
||||
|
||||
exports.delete = function (box, callback) {
|
||||
dbo.collection("boxes").deleteOne({ _id: box._id }, err => {
|
||||
if (err) throw err;
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
exports.update = function (box, callback) {
|
||||
dbo.collection("boxes").updateOne(
|
||||
{ _id: ObjectId(box._id) },
|
||||
{
|
||||
$set: {
|
||||
visibility: box.visibility
|
||||
}
|
||||
},
|
||||
{ upsert: false },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
exports.updateCovers = function (box, covers, callback) {
|
||||
dbo.collection("boxes").updateOne(
|
||||
{ _id: ObjectId(box._id) },
|
||||
{ $set: { covers: covers } },
|
||||
{ upsert: false },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
734
services/database/index.js
Normal file
734
services/database/index.js
Normal file
@@ -0,0 +1,734 @@
|
||||
const { ObjectId } = require('mongodb');
|
||||
const bcrypt = require("bcryptjs");
|
||||
const ffmpeg = require("fluent-ffmpeg");
|
||||
const fs = require("fs");
|
||||
|
||||
const notifier = require("../notifier");
|
||||
|
||||
const server = require("../../server");
|
||||
const config = server.config;
|
||||
|
||||
const connector = require("./CONNECTOR");
|
||||
var dbo;
|
||||
connector.connect().then((ret) => {
|
||||
dbo = ret;
|
||||
});
|
||||
|
||||
notifier.on("metadata_excluded", item => {
|
||||
insert_artist_if_not_exists(item, artist => {
|
||||
insert_album_if_not_exists(item, artist, album => {
|
||||
insert_track_if_not_exists(item, album);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
notifier.on("pathdata_excluded", item => {
|
||||
insert_box_if_not_exists(item, box => {
|
||||
insert_video_if_not_exists(item, box);
|
||||
});
|
||||
});
|
||||
|
||||
notifier.on("check_video_details", item => {
|
||||
if (!item.tracks) {
|
||||
get_video_tracks(item, tracks => {
|
||||
item.tracks = tracks;
|
||||
update_video(item);
|
||||
});
|
||||
}
|
||||
if (!item.thumbnail) {
|
||||
get_video_thumbnail(item, thumbnail => {
|
||||
item.thumbnail = thumbnail;
|
||||
update_video(item);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
/*
|
||||
MODULES
|
||||
*/
|
||||
|
||||
const albums = require("./albums");
|
||||
exports.albums = albums;
|
||||
|
||||
const radios = require("./radios");
|
||||
exports.radios = radios;
|
||||
|
||||
const tracks = require("./tracks");
|
||||
exports.tracks = tracks;
|
||||
|
||||
const artists = require("./artists");
|
||||
exports.artists = artists;
|
||||
|
||||
const boxes = require("./boxes");
|
||||
exports.boxes = boxes;
|
||||
|
||||
const videos = require("./videos");
|
||||
exports.videos = videos;
|
||||
|
||||
const users = require("./users");
|
||||
exports.users = users;
|
||||
|
||||
const system = require("./system");
|
||||
exports.system = system;
|
||||
|
||||
|
||||
exports.artist_count = function (callback) {
|
||||
return dbo.collection("artists").countDocuments(callback);
|
||||
};
|
||||
|
||||
exports.album_count = function (callback) {
|
||||
return dbo.collection("albums").countDocuments(callback);
|
||||
};
|
||||
|
||||
exports.track_count = function (callback) {
|
||||
return dbo.collection("tracks").countDocuments(callback);
|
||||
};
|
||||
|
||||
exports.box_count = function (callback) {
|
||||
return dbo.collection("boxes").countDocuments(callback);
|
||||
};
|
||||
|
||||
exports.video_count = function (callback) {
|
||||
return dbo.collection("videos").countDocuments(callback);
|
||||
};
|
||||
|
||||
exports.users_count = function (callback) {
|
||||
return dbo.collection("users").countDocuments(callback);
|
||||
};
|
||||
|
||||
/*
|
||||
USER
|
||||
*/
|
||||
|
||||
exports.addUser = function (user, callback) {
|
||||
bcrypt.genSalt(10, function (err, salt) {
|
||||
bcrypt.hash(user.password, salt, function (err, hash) {
|
||||
user.password = hash;
|
||||
if (!user.roles) {
|
||||
user.roles = ["user"];
|
||||
}
|
||||
user.name = user.name.toLowerCase();
|
||||
user.player = {};
|
||||
user.fullname = user.name;
|
||||
dbo.collection("users").insertOne(user, err => {
|
||||
if (err) throw err;
|
||||
dbo.collection("users").findOne({ name: user.name }, (err, result) => {
|
||||
if (err) throw err;
|
||||
delete result.password;
|
||||
callback(result);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.deleteUser = function (id, callback) {
|
||||
dbo
|
||||
.collection("users")
|
||||
.deleteOne({ _id: ObjectId(id) }, (err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.updateUserRole = function (user, callback) {
|
||||
dbo
|
||||
.collection("users")
|
||||
.updateOne({ name: user.name }, { $set: { roles: user.roles } }, err => {
|
||||
if (err) throw err;
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
exports.updateUserAccess = function (name) {
|
||||
dbo
|
||||
.collection("users")
|
||||
.updateOne(
|
||||
{ name: name },
|
||||
{ $set: { last_access: new Date().toLocaleString() } }
|
||||
);
|
||||
};
|
||||
|
||||
exports.updateUserPassword = function (user, newPassowrd) {
|
||||
bcrypt.genSalt(10, function (err, salt) {
|
||||
bcrypt.hash(newPassowrd, salt, function (err, hash) {
|
||||
dbo
|
||||
.collection("users")
|
||||
.updateOne({ name: user }, { $set: { password: hash } },
|
||||
err => { if (err) throw err; });
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
exports.updateUserConfig = function (user, body, callback) {
|
||||
dbo.collection("users").updateOne(
|
||||
{ name: user.name },
|
||||
{
|
||||
$set: {
|
||||
mobile_bpm: body.mobile_bpm,
|
||||
desktop_bpm: body.desktop_bpm,
|
||||
video_lang: body.video_lang,
|
||||
video_quality: body.video_quality,
|
||||
fullname: body.fullname
|
||||
}
|
||||
},
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
exports.updateUserSettings = function (user, callback) {
|
||||
dbo
|
||||
.collection("users")
|
||||
.updateOne(
|
||||
{ _id: user._id },
|
||||
{ $set: { player: user.player } },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
exports.userByName = function (name, callback) {
|
||||
dbo.collection("users").findOne({ name: name.toLowerCase() }, (err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.userById = function (id, callback) {
|
||||
dbo
|
||||
.collection("users")
|
||||
.findOne({ _id: ObjectId(id) }, (err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
HISTORY
|
||||
*/
|
||||
exports.historyList = function (id, callback) {
|
||||
dbo
|
||||
.collection("history")
|
||||
.find(
|
||||
{ userId: id, type: { $in: ['album', 'artist', 'box', 'radio'] } },
|
||||
{ projection: { _id: false, userId: false } }
|
||||
)
|
||||
.sort({ _id: -1 })
|
||||
.limit(12)
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.clearHistory = function (id, callback) {
|
||||
dbo
|
||||
.collection("history")
|
||||
.deleteMany({ userId: id }, (err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.updateHistory = function (item, callback) {
|
||||
dbo
|
||||
.collection("history")
|
||||
.deleteMany({ userId: item.userId, id: item.id, type: { $in: ['album', 'artist', 'box', 'radio'] } }, err => {
|
||||
if (err) throw err;
|
||||
dbo
|
||||
.collection("history")
|
||||
.insertOne(item, err => {
|
||||
if (err) throw err;
|
||||
callback();
|
||||
}
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
exports.search = function (term, callback) {
|
||||
let r = [];
|
||||
dbo
|
||||
.collection("artists")
|
||||
.find(
|
||||
{ name: { $regex: term, $options: "i" } },
|
||||
{ projection: { _id: true, name: true, "covers.cover256": true } }
|
||||
)
|
||||
.toArray((err, result) => {
|
||||
if (result && result.length > 0) {
|
||||
result.forEach(item => {
|
||||
item.type = "artist";
|
||||
item.search_rank = item.name.toLowerCase().indexOf(term);
|
||||
});
|
||||
r = r.concat(result);
|
||||
}
|
||||
dbo
|
||||
.collection("albums")
|
||||
.find(
|
||||
{ title: { $regex: term, $options: "i" } },
|
||||
{ projection: { _id: true, title: true, "covers.cover128": true } }
|
||||
)
|
||||
.toArray((err, result) => {
|
||||
|
||||
if (result && result.length > 0) {
|
||||
result.forEach(item => {
|
||||
item.type = "album";
|
||||
item.parent = {};
|
||||
item.search_rank = item.title.toLowerCase().indexOf(term);
|
||||
});
|
||||
r = r.concat(result);
|
||||
}
|
||||
dbo
|
||||
.collection("tracks")
|
||||
.aggregate([
|
||||
{
|
||||
$lookup: {
|
||||
from: "albums",
|
||||
localField: "album_id",
|
||||
foreignField: "_id",
|
||||
as: "parent"
|
||||
}
|
||||
}, {
|
||||
$unwind: "$parent"
|
||||
}, {
|
||||
$project: {
|
||||
album_id: false,
|
||||
bitrate: false,
|
||||
disk: false,
|
||||
duration: false,
|
||||
mime: false,
|
||||
path: false,
|
||||
genre: false,
|
||||
track: false,
|
||||
"parent.artist_id": false,
|
||||
"parent.year": false,
|
||||
"parent.covers.cover32": false,
|
||||
"parent.covers.cover128": false,
|
||||
"parent.covers.cover256": false,
|
||||
"parent.covers.cover512": false
|
||||
}
|
||||
}, {
|
||||
$match: { title: { $regex: term, $options: "i" } }
|
||||
}])
|
||||
.toArray((err, result) => {
|
||||
if (result && result.length > 0) {
|
||||
result.forEach(item => {
|
||||
item.type = "track";
|
||||
item.search_rank = item.title.toLowerCase().indexOf(term);
|
||||
});
|
||||
r = r.concat(result);
|
||||
}
|
||||
dbo
|
||||
.collection("boxes")
|
||||
.find(
|
||||
{ title: { $regex: term, $options: "i" } },
|
||||
{ projection: { _id: true, title: true, "covers.cover128": true } }
|
||||
)
|
||||
.toArray((err, result) => {
|
||||
if (result && result.length > 0) {
|
||||
result.forEach(item => {
|
||||
item.type = "box";
|
||||
item.search_rank = item.title.toLowerCase().indexOf(term);
|
||||
});
|
||||
r = r.concat(result);
|
||||
}
|
||||
|
||||
dbo
|
||||
.collection("videos")
|
||||
.aggregate([
|
||||
{
|
||||
$lookup: {
|
||||
from: "boxes",
|
||||
localField: "box_id",
|
||||
foreignField: "_id",
|
||||
as: "parent"
|
||||
}
|
||||
}, {
|
||||
$unwind: "$parent"
|
||||
}, {
|
||||
$project: {
|
||||
path: false,
|
||||
mime: false,
|
||||
tracks: false,
|
||||
box_id: false,
|
||||
"parent.box_id": false,
|
||||
"parent.year": false,
|
||||
"parent.path": false,
|
||||
"parent.title": false,
|
||||
"parent.covers.cover32": false,
|
||||
"parent.covers.cover64": false,
|
||||
"parent.covers.cover128": false,
|
||||
"parent.covers.cover256": false,
|
||||
"parent.covers.cover512": false
|
||||
}
|
||||
}, {
|
||||
$match: { title: { $regex: term, $options: "i" } }
|
||||
}]
|
||||
)
|
||||
.toArray((err, result) => {
|
||||
if (result && result.length > 0) {
|
||||
result.forEach(item => {
|
||||
item.type = "video";
|
||||
item.search_rank = item.title
|
||||
.toLowerCase()
|
||||
.indexOf(term);
|
||||
});
|
||||
r = r.concat(result);
|
||||
}
|
||||
dbo
|
||||
.collection("radios")
|
||||
.find(
|
||||
{ name: { $regex: term, $options: "i" } },
|
||||
{ projection: { _id: true, name: true } }
|
||||
)
|
||||
.toArray((err, result) => {
|
||||
if (result && result.length > 0) {
|
||||
result.forEach(item => {
|
||||
item.type = "radio";
|
||||
item.search_rank = item.name
|
||||
.toLowerCase()
|
||||
.indexOf(term);
|
||||
});
|
||||
r = r.concat(result);
|
||||
}
|
||||
callback(
|
||||
r
|
||||
.sort((a, b) => {
|
||||
return a.search_rank - b.search_rank;
|
||||
})
|
||||
.splice(0, 50)
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
CHAT
|
||||
*/
|
||||
exports.messageList = function (callback) {
|
||||
dbo
|
||||
.collection("chat")
|
||||
.aggregate([
|
||||
{
|
||||
$lookup: {
|
||||
from: "users",
|
||||
localField: "user_id",
|
||||
foreignField: "_id",
|
||||
as: "user"
|
||||
}
|
||||
},
|
||||
{
|
||||
$project: {
|
||||
"user.password": false,
|
||||
"user.player": false
|
||||
}
|
||||
},
|
||||
{ $unwind: "$user" },
|
||||
{ $sort: { _id: 1 } }
|
||||
])
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result.splice(0, 100));
|
||||
});
|
||||
};
|
||||
|
||||
exports.writeMessage = function (user, message, callback) {
|
||||
dbo
|
||||
.collection("chat")
|
||||
.insertOne(
|
||||
{ user_id: user._id, message: message, timestamp: Date.now() },
|
||||
(err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result.ops);
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
exports.deleteMessage = function (id, user, callback) {
|
||||
dbo.collection("chat").deleteOne({ _id: ObjectId(id), user_id: user._id }, err => {
|
||||
if (err) throw err;
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
/*
|
||||
FUNCTIONS
|
||||
*/
|
||||
function insert_artist_if_not_exists(item, callback) {
|
||||
dbo.collection("artists").findOne({ name: item.artist }, (err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
callback(result);
|
||||
} else {
|
||||
let artist = {
|
||||
name: item.artist,
|
||||
insert_on: Date.now()
|
||||
}
|
||||
if (item.owner) {
|
||||
artist.owner_id = item.owner._id;
|
||||
}
|
||||
dbo
|
||||
.collection("artists")
|
||||
.updateOne(
|
||||
{ name: item.artist },
|
||||
{ $set: artist },
|
||||
{ upsert: true },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
insert_artist_if_not_exists(item, callback);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function insert_album_if_not_exists(item, artist, callback) {
|
||||
dbo
|
||||
.collection("albums")
|
||||
.findOne({ artist_id: artist._id, title: item.album }, (err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
callback(result);
|
||||
} else {
|
||||
let album = {
|
||||
artist_id: artist._id,
|
||||
artist_name: artist.name,
|
||||
title: item.album.trim(),
|
||||
year: item.year,
|
||||
insert_on: Date.now()
|
||||
}
|
||||
if (item.covers) {
|
||||
album.cover32 = item.covers.cover32;
|
||||
album.cover64 = item.covers.cover64;
|
||||
album.cover128 = item.covers.cover128;
|
||||
album.cover256 = item.covers.cover256;
|
||||
}
|
||||
if (item.owner) {
|
||||
album.owner_id = item.owner._id;
|
||||
}
|
||||
dbo.collection("albums").updateOne(
|
||||
{ artist_id: artist._id, title: item.album },
|
||||
{ $set: album },
|
||||
{ upsert: true },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
insert_album_if_not_exists(item, artist, callback);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function insert_track_if_not_exists(item, album, callback) {
|
||||
let short_path = ""
|
||||
if (item.path.indexOf(config.upload_folder) == 0) {
|
||||
short_path = item.path.replace(config.upload_folder, "");
|
||||
} else {
|
||||
short_path = item.path.replace(config.music_folder, "");
|
||||
}
|
||||
|
||||
dbo.collection("tracks").updateOne(
|
||||
{ path: short_path },
|
||||
{
|
||||
$set: {
|
||||
title: item.title,
|
||||
path: short_path,
|
||||
album_id: album._id,
|
||||
duration: item.duration,
|
||||
bitrate: item.bitrate,
|
||||
mime: item.mime,
|
||||
disk: item.disk,
|
||||
track: item.track,
|
||||
genre: item.genre,
|
||||
insert_on: Date.now()
|
||||
}
|
||||
},
|
||||
{ upsert: true },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
dbo.collection("tracks").findOne({ path: short_path }, (err, result) => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function insert_box_if_not_exists(item, callback) {
|
||||
let short_path = item.box_path.replace(config.video_folder, "");
|
||||
dbo
|
||||
.collection("boxes")
|
||||
.findOne({ title: item.box, year: item.year }, (err, result) => {
|
||||
if (err) throw err;
|
||||
if (result) {
|
||||
callback(result);
|
||||
} else {
|
||||
let box = {
|
||||
title: item.box,
|
||||
path: short_path,
|
||||
year: item.year,
|
||||
cover64: item.cover64,
|
||||
cover128: item.cover128,
|
||||
cover256: item.cover256,
|
||||
cover512: item.cover512,
|
||||
insert_on: Date.now()
|
||||
}
|
||||
if (item.owner) {
|
||||
box.owner_id = item.owner._id;
|
||||
}
|
||||
dbo
|
||||
.collection("boxes")
|
||||
.updateOne(
|
||||
{ title: item.box },
|
||||
{ $set: box },
|
||||
{ upsert: true },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
insert_box_if_not_exists(item, callback);
|
||||
}
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function insert_video_if_not_exists(item, box, callback) {
|
||||
item.path = item.path.replace(config.video_folder, "");
|
||||
dbo.collection("videos").updateOne(
|
||||
{ path: item.path },
|
||||
{
|
||||
$set: {
|
||||
title: item.title,
|
||||
path: item.path,
|
||||
box_id: box._id,
|
||||
mime: item.mime,
|
||||
insert_on: Date.now()
|
||||
}
|
||||
},
|
||||
{ upsert: true },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
dbo.collection("videos").findOne({ path: item.path }, (err, result) => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback(result);
|
||||
}
|
||||
if (!result.tracks) {
|
||||
get_video_tracks(item, tracks => {
|
||||
result.tracks = tracks;
|
||||
update_video(result);
|
||||
});
|
||||
}
|
||||
if (!result.thumbnail) {
|
||||
get_video_thumbnail(result, thumbnail => {
|
||||
result.thumbnail = thumbnail;
|
||||
update_video(result);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function update_video(video, callback) {
|
||||
process.stdout.write("updating video: " + video.title + "\n");
|
||||
let val = {};
|
||||
if (video.tracks) {
|
||||
val.tracks = video.tracks;
|
||||
}
|
||||
if (video.thumbnail) {
|
||||
val.thumbnail = video.thumbnail;
|
||||
}
|
||||
|
||||
if (!val) {
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
dbo
|
||||
.collection("videos")
|
||||
.updateOne({ _id: video._id }, { $set: val }, { upsert: false }, err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function get_video_thumbnail(video, callback) {
|
||||
let path = config.video_folder + video.path;
|
||||
if (!fs.existsSync(path)) {
|
||||
path = config.upload_folder + video.path;
|
||||
}
|
||||
ffmpeg(path)
|
||||
.on("end", () => {
|
||||
process.stdout.write("Thumbnail for '" + video.title + "' created\n");
|
||||
let thumbnail =
|
||||
config.cache_folder + "/video_covers/" + video._id.toString() + ".png";
|
||||
if (!fs.existsSync(thumbnail)) {
|
||||
callback(null);
|
||||
return;
|
||||
}
|
||||
let bitmap = fs.readFileSync(thumbnail);
|
||||
callback("data:image/png;base64, " + bitmap.toString("base64"));
|
||||
fs.unlinkSync(thumbnail);
|
||||
})
|
||||
.on("error", err => {
|
||||
process.stdout.write(
|
||||
"Thumbnail error for " + video.title + ": " + err.message + "\n"
|
||||
);
|
||||
callback(null);
|
||||
})
|
||||
.screenshot({
|
||||
timestamps: ["20%"],
|
||||
filename: video._id.toString(),
|
||||
folder: config.cache_folder + "/video_covers",
|
||||
size: "346x180"
|
||||
});
|
||||
}
|
||||
|
||||
function get_video_tracks(video, callback) {
|
||||
let path = config.video_folder + video.path;
|
||||
if (!fs.existsSync(path)) {
|
||||
path = config.upload_folder + video.path;
|
||||
}
|
||||
ffmpeg(path).ffprobe((err, data) => {
|
||||
if (!data) {
|
||||
return callback([]);
|
||||
}
|
||||
let audio_streams = data.streams.filter(f => f.codec_type == "audio");
|
||||
let return_value = audio_streams.map(m => {
|
||||
return {
|
||||
index: m.index,
|
||||
lang: (m.tags && m.tags.language
|
||||
? m.tags.language
|
||||
: m.index
|
||||
? m.index
|
||||
: ""
|
||||
).toString(),
|
||||
title: (m.tags && m.tags.title
|
||||
? m.tags.title
|
||||
: m.index
|
||||
? m.index
|
||||
: ""
|
||||
).toString()
|
||||
};
|
||||
});
|
||||
callback(return_value);
|
||||
});
|
||||
}
|
||||
79
services/database/radios.js
Normal file
79
services/database/radios.js
Normal file
@@ -0,0 +1,79 @@
|
||||
const { ObjectId } = require('mongodb');
|
||||
const connector = require("./CONNECTOR");
|
||||
var dbo;
|
||||
connector.connect().then((ret) => {
|
||||
dbo = ret;
|
||||
});
|
||||
|
||||
exports.collection = function (callback) {
|
||||
dbo
|
||||
.collection("radios")
|
||||
.find({})
|
||||
.sort({ name: 1 })
|
||||
.toArray((err, result) => {
|
||||
result.forEach(item => {
|
||||
item.type = "radio";
|
||||
});
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.byId = function (id, callback) {
|
||||
dbo
|
||||
.collection("radios")
|
||||
.findOne({ _id: ObjectId(id) }, (err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.add = function (radio, callback) {
|
||||
dbo.collection("radios").updateOne(
|
||||
{ url: radio.url },
|
||||
{
|
||||
$set: {
|
||||
name: radio.name,
|
||||
url: radio.url
|
||||
}
|
||||
},
|
||||
{ upsert: true },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
dbo.collection("radios").findOne({ url: radio.url }, (err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
}
|
||||
);
|
||||
};
|
||||
|
||||
exports.delete = function (id, callback) {
|
||||
dbo
|
||||
.collection("radios")
|
||||
.deleteOne({ _id: ObjectId(id) }, (err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.update = function (radio, callback) {
|
||||
dbo.collection("radios").updateOne(
|
||||
{ _id: radio._id },
|
||||
{
|
||||
$set: {
|
||||
name: radio.name,
|
||||
url: radio.url,
|
||||
cover32: radio.cover32,
|
||||
cover64: radio.cover64,
|
||||
cover128: radio.cover128
|
||||
}
|
||||
},
|
||||
{ upsert: false },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
);
|
||||
};
|
||||
59
services/database/system.js
Normal file
59
services/database/system.js
Normal file
@@ -0,0 +1,59 @@
|
||||
const connector = require("./CONNECTOR");
|
||||
var dbo;
|
||||
connector.connect().then((ret) => {
|
||||
dbo = ret;
|
||||
});
|
||||
|
||||
exports.domains = function (callback) {
|
||||
dbo
|
||||
.collection("system")
|
||||
.findOne({ key: 'domains' })
|
||||
.then(result => {
|
||||
if (result) {
|
||||
callback(result.value);
|
||||
} else {
|
||||
callback([]);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.allows = function (callback) {
|
||||
dbo.collection("system")
|
||||
.findOne({ key: 'allows' })
|
||||
.then(allows => {
|
||||
if (!allows) {
|
||||
callback({
|
||||
"guests": false,
|
||||
"register": false,
|
||||
});
|
||||
} else {
|
||||
callback(allows.value);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
exports.setAllows = function (allows, callback) {
|
||||
dbo.collection("system")
|
||||
.updateOne(
|
||||
{ key: "allows" },
|
||||
{ $set: { value: allows } },
|
||||
{ upsert: true }, err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exports.setDomains = function (domains, callback) {
|
||||
dbo.collection("system")
|
||||
.updateOne(
|
||||
{ key: "domains" },
|
||||
{ $set: { value: domains } },
|
||||
{ upsert: true }, err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
113
services/database/tracks.js
Normal file
113
services/database/tracks.js
Normal file
@@ -0,0 +1,113 @@
|
||||
const { ObjectId } = require('mongodb');
|
||||
const connector = require("./CONNECTOR");
|
||||
var dbo;
|
||||
connector.connect().then((ret) => {
|
||||
dbo = ret;
|
||||
dbo.collection("tracks").createIndex({ path: 1, album_id: 1, "disk.no": 1, "track.no": 1 });
|
||||
});
|
||||
|
||||
const server = require("../../server");
|
||||
const config = server.config;
|
||||
|
||||
exports.collection = function (callback) {
|
||||
dbo
|
||||
.collection("tracks")
|
||||
.find()
|
||||
.toArray((err, result) => {
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.byId = function (id, callback) {
|
||||
dbo
|
||||
.collection("tracks")
|
||||
.findOne({ _id: ObjectId(id) }, (err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.delete = function (track, callback) {
|
||||
dbo.collection("tracks").deleteOne(track, err => {
|
||||
if (err) throw err;
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
exports.exists = function (path, callback) {
|
||||
dbo
|
||||
.collection("tracks")
|
||||
.find({ path: path.replace(config.music_folder, "") })
|
||||
.limit(1)
|
||||
.toArray((err, result) => {
|
||||
callback(result.length > 0);
|
||||
});
|
||||
};
|
||||
|
||||
exports.moveTo = function (track, callback) {
|
||||
dbo
|
||||
.collection("tracks")
|
||||
.updateOne(
|
||||
{ _id: ObjectId(track._id) },
|
||||
{ $set: { album_id: ObjectId(track.album_id) } },
|
||||
{ upsert: false },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.mostListened = function (filter, callback) {
|
||||
let aggregate = [{
|
||||
$group: {
|
||||
_id: "$id",
|
||||
title: { $last: "$title" },
|
||||
covers: { $last: "$covers" },
|
||||
parent: { $last: "$parent" },
|
||||
counter: { $sum: 1 },
|
||||
album: { $last: "$album" }
|
||||
},
|
||||
}]
|
||||
if (filter) {
|
||||
aggregate
|
||||
.unshift({
|
||||
$lookup: {
|
||||
from: "albums",
|
||||
let: { album_id: "$parent._id" },
|
||||
pipeline: [{
|
||||
$match: {
|
||||
$expr: {
|
||||
$eq: ["$_id", { $toObjectId: "$$album_id" }]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
as: "album"
|
||||
}
|
||||
}, { $unwind: "$album" })
|
||||
aggregate
|
||||
.push({
|
||||
$project: {
|
||||
"album.cover256": false,
|
||||
"album.cover128": false,
|
||||
"album.cover64": false,
|
||||
"album.cover32": false
|
||||
}
|
||||
}, { $match: { "album.visibility": { $in: filter } } });
|
||||
} else {
|
||||
aggregate.unshift({ $match: { type: 'track' } });
|
||||
}
|
||||
aggregate.push({ $sort: { counter: -1, _id: -1 } }, { $limit: 6 })
|
||||
|
||||
dbo
|
||||
.collection("history")
|
||||
.aggregate(aggregate, {
|
||||
allowDiskUse: true
|
||||
})
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
49
services/database/users.js
Normal file
49
services/database/users.js
Normal file
@@ -0,0 +1,49 @@
|
||||
const { ObjectId } = require('mongodb');
|
||||
const connector = require("./CONNECTOR");
|
||||
var dbo;
|
||||
connector.connect().then((ret) => {
|
||||
dbo = ret;
|
||||
dbo.collection("favourites").createIndex({ userId: 1 });
|
||||
});
|
||||
|
||||
exports.collection = function (callback) {
|
||||
dbo
|
||||
.collection("users")
|
||||
.find({}, { password: false })
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.favourites = function (id, callback) {
|
||||
dbo.collection("favourites")
|
||||
.find({ userId: id })
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
}
|
||||
|
||||
exports.insertFavourite = function (item, callback) {
|
||||
item.itemId = ObjectId(item.itemId);
|
||||
dbo
|
||||
.collection("favourites")
|
||||
.insertOne(item, err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
exports.deleteFavourite = function (item, callback) {
|
||||
dbo
|
||||
.collection("favourites")
|
||||
.deleteMany({ userId: item.userId, itemId: ObjectId(item.itemId) }, (err) => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
}
|
||||
118
services/database/videos.js
Normal file
118
services/database/videos.js
Normal file
@@ -0,0 +1,118 @@
|
||||
const { ObjectId } = require('mongodb');
|
||||
var connector = require("./CONNECTOR");
|
||||
var dbo;
|
||||
connector.connect().then((ret) => {
|
||||
dbo = ret;
|
||||
dbo.collection("videos").createIndex({ box_id: 1, title: 1 });
|
||||
});
|
||||
|
||||
var server = require("../../server");
|
||||
var config = server.config;
|
||||
|
||||
exports.exists = function (path, callback) {
|
||||
let short_path = path.replace(config.video_folder, "");
|
||||
dbo.collection("videos").findOne({ path: short_path }, (err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.collection = function (callback) {
|
||||
dbo
|
||||
.collection("videos")
|
||||
.find()
|
||||
.toArray((err, result) => {
|
||||
result.forEach(item => {
|
||||
item.thumbnail = "";
|
||||
});
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.byId = function (id, callback) {
|
||||
dbo
|
||||
.collection("videos")
|
||||
.findOne({ _id: ObjectId(id) }, (err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
|
||||
exports.delete = function (video, callback) {
|
||||
dbo.collection("videos")
|
||||
.deleteOne({ _id: ObjectId(video._id) }, err => {
|
||||
if (err) throw err;
|
||||
callback();
|
||||
});
|
||||
};
|
||||
|
||||
exports.moveTo = function (video, callback) {
|
||||
dbo
|
||||
.collection("videos")
|
||||
.updateOne(
|
||||
{ _id: ObjectId(video._id) },
|
||||
{ $set: { box_id: ObjectId(video.box_id) } },
|
||||
{ upsert: false },
|
||||
err => {
|
||||
if (err) throw err;
|
||||
if (callback) {
|
||||
callback();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
exports.mostViewed = function (filter, callback) {
|
||||
let aggregate = [{
|
||||
$group: {
|
||||
_id: "$id",
|
||||
title: { $last: "$title" },
|
||||
thumbnail: { $last: "$thumbnail" },
|
||||
parent: { $last: "$parent" },
|
||||
counter: { $sum: 1 },
|
||||
box: { $last: "$box" }
|
||||
},
|
||||
}]
|
||||
if (filter) {
|
||||
aggregate
|
||||
.unshift({
|
||||
$lookup: {
|
||||
from: "boxes",
|
||||
let: { box_id: "$parent._id" },
|
||||
pipeline: [{
|
||||
$match: {
|
||||
$expr: {
|
||||
$eq: ["$_id", { $toObjectId: "$$box_id" }]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
as: "box"
|
||||
}
|
||||
}, { $unwind: "$box" })
|
||||
aggregate.push({
|
||||
$project: {
|
||||
"box.cover256": false,
|
||||
"box.cover128": false,
|
||||
"box.cover64": false,
|
||||
"box.cover32": false,
|
||||
"box.path": false
|
||||
}
|
||||
}, { $match: { "box.visibility": { $in: filter } } });
|
||||
}
|
||||
else {
|
||||
aggregate.unshift({ $match: { type: 'video' } });
|
||||
}
|
||||
aggregate.push(
|
||||
{ $sort: { counter: -1, _id: -1 } },
|
||||
{ $limit: 12 });
|
||||
|
||||
dbo
|
||||
.collection("history")
|
||||
.aggregate(aggregate, {
|
||||
allowDiskUse: true
|
||||
})
|
||||
.toArray((err, result) => {
|
||||
if (err) throw err;
|
||||
callback(result);
|
||||
});
|
||||
};
|
||||
Reference in New Issue
Block a user