museria 0.2.40 → 0.2.44

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "museria",
3
- "version": "0.2.40",
3
+ "version": "0.2.44",
4
4
  "description": "Decentralized music storage",
5
5
  "main": "./src/index.js",
6
6
  "bin": {
@@ -13,7 +13,7 @@
13
13
  "homepage": "https://github.com/ortexx/museria",
14
14
  "scripts": {
15
15
  "eslint": "eslint src bin test",
16
- "test": "mocha ./test/index.js --timeout=20000",
16
+ "test": "mocha ./test/index.js --timeout=30000",
17
17
  "build-client": "webpack --config=webpack.client.js",
18
18
  "build-client-prod": "cross-env NODE_ENV=production webpack --config=webpack.client.js",
19
19
  "build-face": "webpack --config=webpack.face.js",
@@ -59,7 +59,7 @@
59
59
  "mini-css-extract-plugin": "^1.3.9",
60
60
  "mocha": "^9.1.3",
61
61
  "node-polyfill-webpack-plugin": "^1.0.3",
62
- "resolve-url-loader": "^3.1.2",
62
+ "resolve-url-loader": "^5.0.0",
63
63
  "sass": "^1.43.4",
64
64
  "sass-loader": "^12.3.0",
65
65
  "terser-webpack-plugin": "^5.0.0",
@@ -77,16 +77,16 @@
77
77
  "express": "^4.17.1",
78
78
  "fs-extra": "^9.0.1",
79
79
  "lodash": "^4.17.20",
80
- "metastocle": "^0.2.26",
80
+ "metastocle": "^0.2.29",
81
81
  "music-metadata": "^6.4.0",
82
82
  "node-fetch": "^2.6.1",
83
83
  "node-id3": "^0.2.2",
84
84
  "sanitize-filename": "^1.6.3",
85
85
  "serve-favicon": "^2.5.0",
86
- "sharp": "^0.25.2",
86
+ "sharp": "^0.29.3",
87
87
  "splaytree": "^3.1.0",
88
- "spreadable": "^0.2.22",
89
- "storacle": "^0.2.22",
88
+ "spreadable": "^0.2.25",
89
+ "storacle": "^0.2.25",
90
90
  "transliteration": "^2.2.0"
91
91
  },
92
92
  "repository": {
@@ -49,7 +49,7 @@
49
49
  </if>
50
50
  <header class="header row">
51
51
  <div class="songs-counter-text">
52
- There ${this.songsCount == 1? 'is': 'are'} <b>${ this.songsCount }</b> song${this.songsCount == 1? '': 's'} on the network
52
+ There ${this.songsCount == 1? 'is': 'are'} <b>${ Number(this.songsCount).toLocaleString() }</b> song${this.songsCount == 1? '': 's'} on the network
53
53
  </div>
54
54
  <a state="app" class="logo mx-auto px-4">
55
55
  <div>
@@ -18,7 +18,7 @@ export default class App extends Akili.Component {
18
18
  created() {
19
19
  this.captchaWidth = 240;
20
20
  this.findingSongsLimit = 10;
21
- this.songsCountInterval = 10 * 1000;
21
+ this.songsCountInterval = 15 * 1000;
22
22
  this.songsCountIntervalObj = null;
23
23
  this.scope.songsCount = 0;
24
24
  this.scope.searchInputValue = this.transition.query.f;
package/src/node.js CHANGED
@@ -78,8 +78,7 @@ module.exports = (Parent) => {
78
78
  ]
79
79
  },
80
80
  task: {
81
- cleanUpMusicInterval: '1m',
82
- normalizeSongTitlesInterval: '10m',
81
+ cleanUpMusicInterval: '1m'
83
82
  }
84
83
  }, options);
85
84
 
@@ -120,10 +119,6 @@ module.exports = (Parent) => {
120
119
  if(this.options.task.cleanUpMusicInterval) {
121
120
  await this.task.add('cleanUpMusic', this.options.task.cleanUpMusicInterval, () => this.cleanUpMusic());
122
121
  }
123
-
124
- if(this.options.task.normalizeSongTitlesInterval) {
125
- await this.task.add('normalizeSongTitles', this.options.task.normalizeSongTitlesInterval, () => this.normalizeSongTitles());
126
- }
127
122
  }
128
123
 
129
124
  /**
@@ -133,9 +128,19 @@ module.exports = (Parent) => {
133
128
  */
134
129
  async normalizeSongTitles() {
135
130
  const docs = await this.db.getDocuments('music');
131
+ const titles = {};
132
+
136
133
  for(let i = 0; i < docs.length; i++) {
137
134
  const doc = docs[i];
138
- doc.title = utils.beautifySongTitle(doc.title);
135
+ const title = utils.beautifySongTitle(doc.title);
136
+
137
+ if(titles[title] && titles[title] != doc.$loki) {
138
+ await this.db.deleteDocument(doc);
139
+ continue;
140
+ }
141
+
142
+ doc.title = title;
143
+ titles[title] = doc.$loki;
139
144
  await this.db.updateMusicDocument(doc, { beautify: false });
140
145
  }
141
146
  }
@@ -421,8 +426,7 @@ module.exports = (Parent) => {
421
426
  * @returns {object[]}
422
427
  */
423
428
  async getSongInfo(title, options = {}) {
424
- title = utils.beautifySongTitle(title);
425
- this.songTitleTest(title);
429
+ title = utils.prepareComparisonSongTitle(title);
426
430
  const collection = await this.getCollection('music');
427
431
  const actions = utils.prepareDocumentGettingActions({
428
432
  offset: 0,
@@ -467,7 +471,7 @@ module.exports = (Parent) => {
467
471
  * @returns {object[]}
468
472
  */
469
473
  async findSongs(str, options = {}) {
470
- const title = utils.beautifySongTitle(str);
474
+ const title = utils.prepareComparisonSongTitle(str);
471
475
  str = utils.prepareSongFindingString(str);
472
476
 
473
477
  if(str.length < this.options.music.findingStringMinLength) {
@@ -8,7 +8,7 @@ module.exports.requestSong = node => {
8
8
  return async (req, res, next) => {
9
9
  try {
10
10
  const title = req.query.title;
11
- node.songTitleTest(title);
11
+ node.songTitleTest(title);
12
12
  const link = await node.getSongLink(title, req.query.type);
13
13
 
14
14
  if(!link) {
@@ -66,7 +66,7 @@ midds.fileAccess = node => {
66
66
 
67
67
  if(!doc) {
68
68
  const titleHash = String(req.params.hash).split('.')[0];
69
- const title = utils.decodeSongTitle(titleHash);
69
+ const title = utils.decodeSongTitle(titleHash);
70
70
  doc = await node.db.getMusicByPk(title);
71
71
  }
72
72
 
package/src/utils.js CHANGED
@@ -9,7 +9,7 @@ const mm = require('music-metadata');
9
9
  const base64url = require('base64url');
10
10
 
11
11
  utils.regexSongLinks = /(([a-z]+:\/\/)?[-\p{L}\p{N}]+\.[\p{L}]{2,}|[a-z]+:\/\/(\[:*[\w\d]+:[\w\d:]+\]|\d+\.[\d.]+))\S*/igu;
12
- utils.regexSongFeats = /[([\s]+((ft\.?|feat\.?|featuring)[\s]+((?!(\s+[-([)\]]+))[^)\]])+)\s*[)\]]*([\s]+[-([]+|$)/i;
12
+ utils.regexSongFeats = /[([\s]+((ft\.|feat\.)[\s]+((?!(\s+[-([)\]]+))[^)\]])+)\s*[)\]]*([\s]+[-([]+|$)/iu;
13
13
 
14
14
  utils.heritableSongTags = [
15
15
  'TALB', 'TCOM', 'TCON', 'TCOP', 'TDAT', 'TEXT', 'TIT1', 'TIT3', 'TLAN',
@@ -37,7 +37,7 @@ utils.MusicDocumentsHandler = class extends utils.DocumentsHandler {
37
37
 
38
38
  return this.$ilk(value, filter);
39
39
  }
40
- }
40
+ }
41
41
 
42
42
  /**
43
43
  * @see stUtils.getFileInfo
@@ -125,11 +125,20 @@ utils.beautifySongTitle = function (title) {
125
125
  .replace(/[\sᅠ]+/g, ' ')
126
126
  .replace(/([([])\s+/g, '$1')
127
127
  .replace(/\s+([)\]])/g, '$1')
128
+ .replace(/([([]+)(featuring|feat|ft)(\s)/ig, '$1feat.$3')
129
+ .replace(/([([\s]+)(feat\.|ft\.)(\s)/ig, '$1feat.$3')
128
130
  .toLowerCase();
129
131
 
130
132
  if(!/[^\s]+ - [^\s]+/.test(title)) {
131
133
  return '';
132
134
  }
135
+
136
+ const arr = title.split(/\(?feat\./i);
137
+
138
+ if(arr.length > 2) {
139
+ arr.splice(2, arr.length - 2);
140
+ title = arr.join('(feat.').trim();
141
+ }
133
142
 
134
143
  const sides = this.splitSongTitle(title);
135
144
  let artists = sides[0].split(/,[\s]*/);
@@ -139,26 +148,26 @@ utils.beautifySongTitle = function (title) {
139
148
  if(!mainArtist) {
140
149
  return '';
141
150
  }
142
-
143
- const match = title.match(this.regexSongFeats);
151
+
152
+ const match = sides[1].match(this.regexSongFeats);
144
153
  let feats = (match? match[1]: '').replace(/,([^\s])/, ', $1').trim();
145
154
  title = `${mainArtist} - ${sides[1]}`;
146
- title = title.replace(this.regexSongFeats, '$5');
147
- artists = artists.map(a => a.trim());
148
-
155
+ title = title.replace(this.regexSongFeats, '$5');
156
+ feats && (artists = artists.concat(feats.replace(/feat\./i, '').split(',')));
157
+ artists = [...new Set(artists.map(a => a.trim()).filter(v => v))];
158
+
149
159
  if(artists.length) {
150
- feats = feats? [feats].concat(artists).join(', '): `ft. ${ artists.join(', ') }`;
160
+ feats = `feat. ${ artists.join(', ') }`;
151
161
  }
152
162
 
153
163
  feats && (title += ` (${feats})`);
154
- title = title
155
- .replace(/([([\s]+)(feat\.?|ft\.?|featuring)(\s)/i, '$1feat.$3')
164
+ title = title
156
165
  .replace(/\[\]|\(\)/g, '')
157
166
  .replace(/\s+/g, ' ')
158
167
  .split(' ')
159
168
  .map(p => p? (p[0].toUpperCase() + p.slice(1)): p)
160
169
  .join(' ')
161
- .trim()
170
+ .trim();
162
171
  return title;
163
172
  };
164
173
 
@@ -234,8 +243,8 @@ utils.getSongArtists = function (title, options = {}) {
234
243
  const sides = this.splitSongTitle(title);
235
244
  let artists = sides[0].split(/,/);
236
245
  const match = title.match(this.regexSongFeats);
237
- let feats = (match? match[1]: '').replace(/(feat|ft|featuring)\.?/i, '');
238
- return artists.concat(feats.split(',')).map(v => v.trim()).filter(v => v);
246
+ let feats = (match? match[1]: '').replace(/^feat\./i, '');
247
+ return [...new Set(artists.concat(feats.split(',')).map(v => v.trim()).filter(v => v))];
239
248
  };
240
249
 
241
250
  /**
package/test/node.js CHANGED
@@ -108,17 +108,13 @@ describe('Node', () => {
108
108
  });
109
109
 
110
110
  describe('.getSongInfo()', () => {
111
- it('should throw an error', async () => {
112
- try {
113
- await node.getSongInfo('unexistent song');
114
- throw new Error('Fail');
115
- }
116
- catch (err) {
117
- assert.isOk(err.message.match('Wrong song title'));
118
- }
111
+ it('should return an empty array with a wrong title', async () => {
112
+ const title = 'unexistent';
113
+ const result = await node.getSongInfo(title);
114
+ assert.lengthOf(result, 0);
119
115
  });
120
116
 
121
- it('should return an empty array', async () => {
117
+ it('should return an empty array with a right title', async () => {
122
118
  const title = 'unexistent - unexistent';
123
119
  const result = await node.getSongInfo(title);
124
120
  assert.lengthOf(result, 0);
package/test/utils.js CHANGED
@@ -67,14 +67,13 @@ describe('utils', () => {
67
67
 
68
68
  it('should place feats together', () => {
69
69
  const res = utils.beautifySongTitle('artist1, artist2,artist3 - title (feat. artist4, artist5,artist6)');
70
- assert.equal(res, 'Artist1 - Title (feat. Artist4, Artist5, Artist6, Artist2, Artist3)');
70
+ assert.equal(res, 'Artist1 - Title (feat. Artist2, Artist3, Artist4, Artist5, Artist6)');
71
71
  });
72
72
 
73
73
  it('should bring all feats to a single form', () => {
74
74
  assert.equal(utils.beautifySongTitle('artist - title (ft. Artist)'), 'Artist - Title (feat. Artist)', 'check "ft"');
75
75
  assert.equal(utils.beautifySongTitle('artist - title (feat. Artist)'), 'Artist - Title (feat. Artist)', 'check "feat"');
76
- assert.equal(utils.beautifySongTitle('artist - title (featuring Artist)'), 'Artist - Title (feat. Artist)', 'check "featuring"');
77
- assert.equal(utils.beautifySongTitle('artist - title ft Artist'), 'Artist - Title (feat. Artist)', 'check without brackets');
76
+ assert.equal(utils.beautifySongTitle('artist - title ft. Artist'), 'Artist - Title (feat. Artist)', 'check without brackets');
78
77
  });
79
78
 
80
79
  it('should change the dash type', () => {
@@ -133,8 +132,8 @@ describe('utils', () => {
133
132
  });
134
133
 
135
134
  it('should return the right array', () => {
136
- const artists = utils.getSongArtists('artist,artist2 - title ft. artist3, artist4', { beautify: false });
137
- assert.equal(artists.join(','), 'artist,artist2,artist3,artist4');
135
+ const artists = utils.getSongArtists('artist,artist2 - title ft. artist3, artist4');
136
+ assert.equal(artists.join(','), 'Artist,Artist2,Artist3,Artist4');
138
137
  });
139
138
  });
140
139