heavily modified database interaction
This commit is contained in:
parent
038603314a
commit
f9eede4fea
13 changed files with 291 additions and 127 deletions
|
@ -43,7 +43,7 @@ class Database {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
const model = require(modelFile);
|
const model = require(modelFile);
|
||||||
if (model.createTable === undefined) {
|
if (model.prototype?.createTable === undefined || model.name === 'Base') {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
modelFile = path.basename(modelFile);
|
modelFile = path.basename(modelFile);
|
||||||
|
@ -62,10 +62,10 @@ class Database {
|
||||||
const model = models[index];
|
const model = models[index];
|
||||||
try {
|
try {
|
||||||
const timestamp = new Date().getTime();
|
const timestamp = new Date().getTime();
|
||||||
await model.createTable();
|
await model.prototype.createTable();
|
||||||
logger.debug('creation/alteration of table \'' + model.tableName + '\' finished after ' + (new Date().getTime() - timestamp) + 'ms');
|
logger.debug('creation/alteration of table \'' + model.name + '\' finished after ' + (new Date().getTime() - timestamp) + 'ms');
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
logger.error('an error occured creating table \'' + model.tableName + '\' > ' + err);
|
logger.error('an error occured creating table \'' + model.name + '\' > ' + err);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
const metadata = require('../libs/metadata.js');
|
const metadata = require('../libs/metadata.js');
|
||||||
const { extname } = require('path');
|
const { extname } = require('path');
|
||||||
|
|
||||||
|
const Artist = require('../models/Artist.js');
|
||||||
|
|
||||||
class Queue {
|
class Queue {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -111,18 +113,9 @@ class Queue {
|
||||||
artists.push(artist);
|
artists.push(artist);
|
||||||
}
|
}
|
||||||
for (let index = 0; index < artists.length; index++) {
|
for (let index = 0; index < artists.length; index++) {
|
||||||
artist = artists[index].trim();
|
artist = new Artist(artists[index]);
|
||||||
try {
|
artist = await artist.save();
|
||||||
const [element, created] = await database.models.Artist.findOrCreate({
|
return artist;
|
||||||
where: { name: artist }
|
|
||||||
});
|
|
||||||
if (created) {
|
|
||||||
logger.debug('created artist: ' + JSON.stringify(element));
|
|
||||||
}
|
|
||||||
return element;
|
|
||||||
} catch (err) {
|
|
||||||
logger.error('error finding or creating artist \'' + JSON.stringify(tags) + '\' > ' + err);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -2,6 +2,8 @@ const path = require('path');
|
||||||
const chokidar = require('chokidar');
|
const chokidar = require('chokidar');
|
||||||
const { open, writeFile } = require('fs/promises');
|
const { open, writeFile } = require('fs/promises');
|
||||||
|
|
||||||
|
const Environment = require('../models/Environment.js');
|
||||||
|
|
||||||
class Watcher {
|
class Watcher {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
@ -23,6 +25,12 @@ class Watcher {
|
||||||
const directory = path.resolve(config.library.sources[index]);
|
const directory = path.resolve(config.library.sources[index]);
|
||||||
let ignoreInitial = !initialScan;
|
let ignoreInitial = !initialScan;
|
||||||
if (ignoreInitial === false) {
|
if (ignoreInitial === false) {
|
||||||
|
let env = new Environment(constants.ENVIRONMENT_LASTSCAN);
|
||||||
|
await env.find('key');
|
||||||
|
if (env === undefined) {
|
||||||
|
env = new Environment(constants.ENVIRONMENT_LASTSCAN, new Date().getTime().toString());
|
||||||
|
env.save();
|
||||||
|
}
|
||||||
ignoreInitial = (new Date().getTime() - await this.#checkHiddenFile(directory)) < (config?.library?.initialscan?.maxage || 86400000);
|
ignoreInitial = (new Date().getTime() - await this.#checkHiddenFile(directory)) < (config?.library?.initialscan?.maxage || 86400000);
|
||||||
}
|
}
|
||||||
logger.debug('watching directory \'' + directory + '\'...');
|
logger.debug('watching directory \'' + directory + '\'...');
|
||||||
|
@ -55,7 +63,7 @@ class Watcher {
|
||||||
let filehandle;
|
let filehandle;
|
||||||
try {
|
try {
|
||||||
filehandle = await open(hiddenFile);
|
filehandle = await open(hiddenFile);
|
||||||
return (await filehandle.readFile()).toString();
|
return (await filehandle.readFile()).toString();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
if (error.code === 'ENOENT') {
|
if (error.code === 'ENOENT') {
|
||||||
return await this.#createHiddenFile(hiddenFile);
|
return await this.#createHiddenFile(hiddenFile);
|
||||||
|
|
|
@ -17,14 +17,14 @@
|
||||||
"library": {
|
"library": {
|
||||||
"enabled": true,
|
"enabled": true,
|
||||||
"sources": [
|
"sources": [
|
||||||
"/home/velvettear/mounts/samsung/music"
|
"/home/velvettear/downloads"
|
||||||
],
|
],
|
||||||
"formats": [
|
"formats": [
|
||||||
"mp3",
|
"mp3",
|
||||||
"flac"
|
"flac"
|
||||||
],
|
],
|
||||||
"initialscan": {
|
"initialscan": {
|
||||||
"enabled": false,
|
"enabled": true,
|
||||||
"maxage": 3600000
|
"maxage": 3600000
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -41,6 +41,6 @@
|
||||||
"listen": "0.0.0.0",
|
"listen": "0.0.0.0",
|
||||||
"port": 3001,
|
"port": 3001,
|
||||||
"nodelay": false,
|
"nodelay": false,
|
||||||
"threshold": 8
|
"threshold": 10
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -19,5 +19,7 @@ module.exports = {
|
||||||
API_PLAY: '/play',
|
API_PLAY: '/play',
|
||||||
API_PAUSE: '/pause',
|
API_PAUSE: '/pause',
|
||||||
API_RESUME: '/resume',
|
API_RESUME: '/resume',
|
||||||
API_STOP: '/stop'
|
API_STOP: '/stop',
|
||||||
|
|
||||||
|
ENVIRONMENT_LASTSCAN:'lastscan'
|
||||||
}
|
}
|
|
@ -1,23 +1,28 @@
|
||||||
|
const path = require('path');
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
|
||||||
const tableName = 'album';
|
const Base = require('./Base.js');
|
||||||
|
|
||||||
class Album {
|
const tableName = path.basename(__filename, '.js').toLowerCase();
|
||||||
|
|
||||||
constructor() {
|
class Album extends Base {
|
||||||
|
|
||||||
|
constructor(name) {
|
||||||
|
super();
|
||||||
|
this.tableName = tableName;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return this.name !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getModel() {
|
||||||
|
return database.connection.define(tableName, {
|
||||||
|
name: DataTypes.TEXT
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTable() {
|
module.exports = Album;
|
||||||
(await getModel()).sync({ alter: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getModel() {
|
|
||||||
return database.connection.define(tableName, {
|
|
||||||
name: DataTypes.TEXT
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { Album, createTable, tableName };
|
|
|
@ -1,28 +1,34 @@
|
||||||
|
const path = require('path');
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
|
||||||
const tableName = 'albumtoartist';
|
const Base = require('./Base.js');
|
||||||
|
|
||||||
class AlbumToArtist {
|
const tableName = path.basename(__filename, '.js').toLowerCase();
|
||||||
|
|
||||||
constructor() {
|
class AlbumToArtist extends Base {
|
||||||
|
|
||||||
|
constructor(album, artist) {
|
||||||
|
super();
|
||||||
|
this.tableName = tableName;
|
||||||
|
this.album = album;
|
||||||
|
this.artist = artist;
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return this.album !== undefined || this.artist !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getModel() {
|
||||||
|
return database.connection.define(tableName, {
|
||||||
|
album: DataTypes.INTEGER,
|
||||||
|
artist: DataTypes.INTEGER
|
||||||
|
},
|
||||||
|
{
|
||||||
|
freezeTableName: true
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTable() {
|
module.exports = AlbumToArtist;
|
||||||
(await getModel()).sync({ alter: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getModel() {
|
|
||||||
return database.connection.define(tableName, {
|
|
||||||
album: DataTypes.INTEGER,
|
|
||||||
artist: DataTypes.INTEGER
|
|
||||||
},
|
|
||||||
{
|
|
||||||
freezeTableName: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { AlbumToArtist, createTable, tableName };
|
|
|
@ -1,23 +1,26 @@
|
||||||
|
const path = require('path');
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
|
||||||
const tableName = 'artist';
|
const Base = require('./Base.js');
|
||||||
|
|
||||||
class Artist {
|
const tableName = path.basename(__filename, '.js').toLowerCase();
|
||||||
|
|
||||||
constructor() {
|
class Artist extends Base {
|
||||||
|
|
||||||
|
constructor(name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return this.name !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getModel() {
|
||||||
|
return database.connection.define(tableName, {
|
||||||
|
name: DataTypes.TEXT
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTable() {
|
module.exports = Artist;
|
||||||
(await getModel()).sync({ alter: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getModel() {
|
|
||||||
return database.connection.define(tableName, {
|
|
||||||
name: DataTypes.TEXT
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { Artist, createTable, tableName };
|
|
98
models/Base.js
Normal file
98
models/Base.js
Normal file
|
@ -0,0 +1,98 @@
|
||||||
|
class Base {
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
async save() {
|
||||||
|
if (!this.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const [element, created] = await (await this.getModel()).findOrCreate({
|
||||||
|
where: await this.#createWhereClause()
|
||||||
|
});
|
||||||
|
if (created) {
|
||||||
|
logger.debug('created \'' + this.tableName + '\' entry: ' + JSON.stringify(element));
|
||||||
|
}
|
||||||
|
if (element?.id === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
return element;
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('error finding or creating \'' + this.tableName + '\' entry: \'' + JSON.stringify(this) + '\' > ' + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async find() {
|
||||||
|
if (!this.isValid()) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
const element = await (await this.getModel()).findOne({
|
||||||
|
where: await this.#createWhereClause()
|
||||||
|
});
|
||||||
|
if (element?.id === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
this.#fillThis(element);
|
||||||
|
} catch (error) {
|
||||||
|
logger.error('error finding \'' + this.tableName + '\' entry: \'' + JSON.stringify(this) + '\' > ' + error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async createTable() {
|
||||||
|
return await createTable();
|
||||||
|
}
|
||||||
|
|
||||||
|
async createTable() {
|
||||||
|
const model = await this.getModel();
|
||||||
|
if (model === undefined) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
await model.sync({ alter: true });
|
||||||
|
}
|
||||||
|
|
||||||
|
async getModel() {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
#fillThis(data) {
|
||||||
|
if (data === undefined || data.dataValues === undefined || data.dataValues.id === undefined || data.dataValues.id < 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
for (const key in data.dataValues) {
|
||||||
|
this[key] = data.dataValues[key];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async #createWhereClause(fields) {
|
||||||
|
const model = await this.getModel();
|
||||||
|
if (model === undefined || model.tableAttributes === undefined) {
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
const where = {};
|
||||||
|
for (const key in model.tableAttributes) {
|
||||||
|
if (key === 'id' || key === 'createdAt' || key === 'updatedAt' || fields !== undefined && (key !== fields || !fields.includes(key))) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
const value = this[key];
|
||||||
|
if (value === undefined) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
where[key] = value;
|
||||||
|
}
|
||||||
|
return where;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = Base;
|
37
models/Environment.js
Normal file
37
models/Environment.js
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
const path = require('path');
|
||||||
|
const { DataTypes } = require('sequelize');
|
||||||
|
|
||||||
|
const Base = require('./Base.js');
|
||||||
|
|
||||||
|
const tableName = path.basename(__filename, '.js').toLowerCase();
|
||||||
|
|
||||||
|
class Environment extends Base {
|
||||||
|
|
||||||
|
constructor(key, value) {
|
||||||
|
super();
|
||||||
|
this.tableName = tableName;
|
||||||
|
this.key = key;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return this.key !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getModel() {
|
||||||
|
if (this.model === undefined) {
|
||||||
|
this.model = await database.connection.define(tableName, {
|
||||||
|
key: DataTypes.TEXT,
|
||||||
|
value: DataTypes.TEXT
|
||||||
|
},
|
||||||
|
{
|
||||||
|
freezeTableName: true
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return this.model;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = Environment;
|
|
@ -1,31 +1,35 @@
|
||||||
|
const path = require('path');
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
|
||||||
const tableName = 'track';
|
const Base = require('./Base.js');
|
||||||
|
|
||||||
class Track {
|
const tableName = path.basename(__filename, '.js').toLowerCase();
|
||||||
|
|
||||||
|
class Track extends Base {
|
||||||
|
|
||||||
constructor() {
|
constructor() {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return this.title !== undefined &&
|
||||||
|
this.file !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getModel() {
|
||||||
|
return database.connection.define(tableName, {
|
||||||
|
title: DataTypes.TEXT,
|
||||||
|
year: DataTypes.INTEGER,
|
||||||
|
duration: DataTypes.FLOAT,
|
||||||
|
comment: DataTypes.TEXT,
|
||||||
|
diskno: DataTypes.INTEGER,
|
||||||
|
diskof: DataTypes.INTEGER,
|
||||||
|
trackno: DataTypes.INTEGER,
|
||||||
|
trackof: DataTypes.INTEGER,
|
||||||
|
file: DataTypes.TEXT
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTable() {
|
module.exports = Track;
|
||||||
(await getModel()).sync({ alter: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getModel() {
|
|
||||||
return database.connection.define(tableName, {
|
|
||||||
title: DataTypes.TEXT,
|
|
||||||
year: DataTypes.INTEGER,
|
|
||||||
duration: DataTypes.FLOAT,
|
|
||||||
comment: DataTypes.TEXT,
|
|
||||||
diskno: DataTypes.INTEGER,
|
|
||||||
diskof: DataTypes.INTEGER,
|
|
||||||
trackno: DataTypes.INTEGER,
|
|
||||||
trackof: DataTypes.INTEGER,
|
|
||||||
file: DataTypes.TEXT
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { Track, createTable, tableName };
|
|
|
@ -1,28 +1,32 @@
|
||||||
|
const path = require('path');
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
|
||||||
const tableName = 'tracktoalbum';
|
const Base = require('./Base.js');
|
||||||
|
|
||||||
|
const tableName = path.basename(__filename, '.js').toLowerCase();
|
||||||
|
|
||||||
class TrackToAlbum {
|
class TrackToAlbum {
|
||||||
|
|
||||||
constructor() {
|
constructor(track, album) {
|
||||||
|
this.track = track;
|
||||||
|
this.album = album;
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return this.track !== undefined || this.album !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getModel() {
|
||||||
|
return database.connection.define(tableName, {
|
||||||
|
track: DataTypes.INTEGER,
|
||||||
|
album: DataTypes.INTEGER
|
||||||
|
},
|
||||||
|
{
|
||||||
|
freezeTableName: true
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTable() {
|
module.exports = TrackToAlbum;
|
||||||
(await getModel()).sync({ alter: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getModel() {
|
|
||||||
return database.connection.define(tableName, {
|
|
||||||
track: DataTypes.INTEGER,
|
|
||||||
album: DataTypes.INTEGER
|
|
||||||
},
|
|
||||||
{
|
|
||||||
freezeTableName: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { TrackToAlbum, createTable, tableName };
|
|
|
@ -1,28 +1,32 @@
|
||||||
|
const path = require('path');
|
||||||
const { DataTypes } = require('sequelize');
|
const { DataTypes } = require('sequelize');
|
||||||
|
|
||||||
const tableName = 'tracktoartist'
|
const Base = require('./Base.js');
|
||||||
|
|
||||||
|
const tableName = path.basename(__filename, '.js').toLowerCase();
|
||||||
|
|
||||||
class TrackToArtist {
|
class TrackToArtist {
|
||||||
|
|
||||||
constructor() {
|
constructor(track, artist) {
|
||||||
|
this.track = track;
|
||||||
|
this.artist = artist;
|
||||||
|
}
|
||||||
|
|
||||||
|
isValid() {
|
||||||
|
return this.track !== undefined || this.artist !== undefined;
|
||||||
|
}
|
||||||
|
|
||||||
|
async getModel() {
|
||||||
|
return database.connection.define(tableName, {
|
||||||
|
track: DataTypes.INTEGER,
|
||||||
|
artist: DataTypes.INTEGER
|
||||||
|
},
|
||||||
|
{
|
||||||
|
freezeTableName: true
|
||||||
|
}
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async function createTable() {
|
module.exports = TrackToArtist;
|
||||||
(await getModel()).sync({ alter: true });
|
|
||||||
}
|
|
||||||
|
|
||||||
async function getModel() {
|
|
||||||
return database.connection.define(tableName, {
|
|
||||||
track: DataTypes.INTEGER,
|
|
||||||
artist: DataTypes.INTEGER
|
|
||||||
},
|
|
||||||
{
|
|
||||||
freezeTableName: true
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = { TrackToArtist, createTable, tableName };
|
|
Loading…
Reference in a new issue