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;
|
||||
}
|
||||
const model = require(modelFile);
|
||||
if (model.createTable === undefined) {
|
||||
if (model.prototype?.createTable === undefined || model.name === 'Base') {
|
||||
continue;
|
||||
}
|
||||
modelFile = path.basename(modelFile);
|
||||
|
@ -62,10 +62,10 @@ class Database {
|
|||
const model = models[index];
|
||||
try {
|
||||
const timestamp = new Date().getTime();
|
||||
await model.createTable();
|
||||
logger.debug('creation/alteration of table \'' + model.tableName + '\' finished after ' + (new Date().getTime() - timestamp) + 'ms');
|
||||
await model.prototype.createTable();
|
||||
logger.debug('creation/alteration of table \'' + model.name + '\' finished after ' + (new Date().getTime() - timestamp) + 'ms');
|
||||
} 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 { extname } = require('path');
|
||||
|
||||
const Artist = require('../models/Artist.js');
|
||||
|
||||
class Queue {
|
||||
|
||||
constructor() {
|
||||
|
@ -111,18 +113,9 @@ class Queue {
|
|||
artists.push(artist);
|
||||
}
|
||||
for (let index = 0; index < artists.length; index++) {
|
||||
artist = artists[index].trim();
|
||||
try {
|
||||
const [element, created] = await database.models.Artist.findOrCreate({
|
||||
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);
|
||||
}
|
||||
artist = new Artist(artists[index]);
|
||||
artist = await artist.save();
|
||||
return artist;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -2,6 +2,8 @@ const path = require('path');
|
|||
const chokidar = require('chokidar');
|
||||
const { open, writeFile } = require('fs/promises');
|
||||
|
||||
const Environment = require('../models/Environment.js');
|
||||
|
||||
class Watcher {
|
||||
|
||||
constructor() {
|
||||
|
@ -23,6 +25,12 @@ class Watcher {
|
|||
const directory = path.resolve(config.library.sources[index]);
|
||||
let ignoreInitial = !initialScan;
|
||||
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);
|
||||
}
|
||||
logger.debug('watching directory \'' + directory + '\'...');
|
||||
|
@ -55,7 +63,7 @@ class Watcher {
|
|||
let filehandle;
|
||||
try {
|
||||
filehandle = await open(hiddenFile);
|
||||
return (await filehandle.readFile()).toString();
|
||||
return (await filehandle.readFile()).toString();
|
||||
} catch (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
return await this.#createHiddenFile(hiddenFile);
|
||||
|
|
|
@ -17,14 +17,14 @@
|
|||
"library": {
|
||||
"enabled": true,
|
||||
"sources": [
|
||||
"/home/velvettear/mounts/samsung/music"
|
||||
"/home/velvettear/downloads"
|
||||
],
|
||||
"formats": [
|
||||
"mp3",
|
||||
"flac"
|
||||
],
|
||||
"initialscan": {
|
||||
"enabled": false,
|
||||
"enabled": true,
|
||||
"maxage": 3600000
|
||||
}
|
||||
},
|
||||
|
@ -41,6 +41,6 @@
|
|||
"listen": "0.0.0.0",
|
||||
"port": 3001,
|
||||
"nodelay": false,
|
||||
"threshold": 8
|
||||
"threshold": 10
|
||||
}
|
||||
}
|
|
@ -19,5 +19,7 @@ module.exports = {
|
|||
API_PLAY: '/play',
|
||||
API_PAUSE: '/pause',
|
||||
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 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() {
|
||||
(await getModel()).sync({ alter: true });
|
||||
}
|
||||
|
||||
async function getModel() {
|
||||
return database.connection.define(tableName, {
|
||||
name: DataTypes.TEXT
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { Album, createTable, tableName };
|
||||
module.exports = Album;
|
|
@ -1,28 +1,34 @@
|
|||
const path = require('path');
|
||||
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() {
|
||||
(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 };
|
||||
module.exports = AlbumToArtist;
|
|
@ -1,23 +1,26 @@
|
|||
const path = require('path');
|
||||
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() {
|
||||
(await getModel()).sync({ alter: true });
|
||||
}
|
||||
|
||||
async function getModel() {
|
||||
return database.connection.define(tableName, {
|
||||
name: DataTypes.TEXT
|
||||
});
|
||||
}
|
||||
|
||||
module.exports = { Artist, createTable, tableName };
|
||||
module.exports = Artist;
|
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 tableName = 'track';
|
||||
const Base = require('./Base.js');
|
||||
|
||||
class Track {
|
||||
const tableName = path.basename(__filename, '.js').toLowerCase();
|
||||
|
||||
class Track extends Base {
|
||||
|
||||
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() {
|
||||
(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 };
|
||||
module.exports = Track;
|
|
@ -1,28 +1,32 @@
|
|||
const path = require('path');
|
||||
const { DataTypes } = require('sequelize');
|
||||
|
||||
const tableName = 'tracktoalbum';
|
||||
const Base = require('./Base.js');
|
||||
|
||||
const tableName = path.basename(__filename, '.js').toLowerCase();
|
||||
|
||||
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() {
|
||||
(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 };
|
||||
module.exports = TrackToAlbum;
|
|
@ -1,28 +1,32 @@
|
|||
const path = require('path');
|
||||
const { DataTypes } = require('sequelize');
|
||||
|
||||
const tableName = 'tracktoartist'
|
||||
const Base = require('./Base.js');
|
||||
|
||||
const tableName = path.basename(__filename, '.js').toLowerCase();
|
||||
|
||||
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() {
|
||||
(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 };
|
||||
module.exports = TrackToArtist;
|
Loading…
Reference in a new issue