museria 0.2.38 → 0.2.42
Sign up to get free protection for your applications and to get access to all the features.
- package/README.md +0 -2
- package/dist/client/museria.client.js +3 -3
- package/dist/face/museria.face.js +8 -8
- package/dist/face/style.css +2 -2
- package/package.json +6 -7
- package/src/browser/face/controllers/app/app.html +9 -7
- package/src/browser/face/controllers/app/app.js +2 -4
- package/src/browser/face/controllers/app/app.scss +21 -4
- package/src/client.js +1 -1
- package/src/db/transports/loki/index.js +5 -6
- package/src/node.js +17 -14
- package/src/server/transports/express/client/controllers.js +2 -2
- package/src/server/transports/express/client/routes.js +1 -1
- package/src/server/transports/express/index.js +7 -6
- package/src/server/transports/express/midds.js +1 -1
- package/src/utils.js +21 -12
- package/test/client.js +1 -1
- package/test/group.js +1 -1
- package/test/node.js +5 -9
- package/test/routes.js +1 -1
- package/test/utils.js +4 -5
package/dist/face/style.css
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
/*!
|
2
2
|
* museria face
|
3
|
-
* @version 0.2.
|
3
|
+
* @version 0.2.42
|
4
4
|
* {@link https://github.com/ortexx/museria}
|
5
5
|
*/
|
6
6
|
/*!
|
@@ -17,4 +17,4 @@
|
|
17
17
|
*/@font-face{font-display:block;font-family:Font Awesome\ 5 Free;font-style:normal;font-weight:900;src:url(fa-solid-900.eot);src:url(fa-solid-900.eot) format("embedded-opentype"),url(fa-solid-900.woff2) format("woff2"),url(fa-solid-900.woff) format("woff"),url(fa-solid-900.ttf) format("truetype"),url(fa-solid-900.svg) format("svg")}.fa,.fas{font-family:Font Awesome\ 5 Free;font-weight:900}/*!
|
18
18
|
* Font Awesome Free 5.15.4 by @fontawesome - https://fontawesome.com
|
19
19
|
* License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License)
|
20
|
-
*/@font-face{font-display:block;font-family:Font Awesome\ 5 Brands;font-style:normal;font-weight:400;src:url(fa-brands-400.eot);src:url(fa-brands-400.eot) format("embedded-opentype"),url(fa-brands-400.woff2) format("woff2"),url(fa-brands-400.woff) format("woff"),url(fa-brands-400.ttf) format("truetype"),url(fa-brands-400.svg) format("svg")}.fab{font-family:Font Awesome\ 5 Brands;font-weight:400}@font-face{font-family:ProximaNova;src:url(proxima-nova.ttf)}@font-face{font-family:OpenSans;src:url(open-sans.ttf)}*{margin:0;padding:0}body{background:#353535;color:#ccc;font-family:OpenSans;height:100%;overflow-y:scroll}.custom-file input{cursor:pointer;text-indent:-1000px}.custom-control-label{cursor:pointer;opacity:.8}.custom-control-label:hover{opacity:1}.btn{font-weight:700;padding:0;text-transform:uppercase}.btn:active,.btn:focus{box-shadow:none!important;outline:none!important}.btn[disabled]{cursor:not-allowed}a{color:#ccc;text-decoration:underline}a:hover{color:#ccc;text-decoration:none}.input-group-lg input[type=text]{height:auto;padding:.42rem 1rem .45rem}.alert-success{background-color:#25301f;border-color:#28a745;color:#aed3b7}.alert-danger{background-color:#301f1f;border-color:#c00;color:#d3aeae}.alert-info{background-color:#1f2730;border-color:#0af;color:#aec7d3}.invalid-feedback{color:#f39595}.close-fa{color:#666;cursor:pointer;opacity:.7;position:absolute;right:.9em;top:50%;transform:translateY(-50%);z-index:2}.close-fa:hover{opacity:1}.app{display:flex;flex-direction:column;height:100vh}.app .wmodal-overlay{align-items:center;background:rgba(34,34,34,.8);cursor:pointer;display:flex;height:100vh;justify-content:center;left:0;position:fixed;top:0;width:100%;z-index:11000}.app .wmodal-close{color:#666;cursor:pointer;font-size:1.8em;opacity:.4;position:absolute;right:.55em;top:.5em}.app .wmodal-close:hover{opacity:1}.app .wmodal-body{background:#000;box-shadow:0 0 4px 2px hsla(0,0%,40%,.6);box-sizing:border-box;cursor:default;padding:3.5em 2.5em;position:relative}.app .upload-events .wmodal-close{font-size:2em;right:1em;top:50%;transform:translateY(-50%)}.app .upload-events .wmodal-body{padding:2em 5em 2em 2em;word-break:break-all}.app .upload-events .wmodal-body.danger{box-shadow:0 0 4px 2px rgba(204,0,0,.6)}.app .upload-events .wmodal-body.success{box-shadow:0 0 4px 2px rgba(40,167,69,.6)}.app .finding-list>*{display:block}.app .finding-list>:not(:first-child){margin-top:.5em}.app .captcha input{background:#151515;border-color:#292929;width:240px}.app .captcha input:focus{background:#151515;border-color:#666}.app .captcha-preloader{color:#666;font-size:1.7em;text-align:center}.app .header{background:#333;background:radial-gradient(#666,#464646,#333);padding:8.2em 0 6.6em;text-shadow:0 0 .8em #333}.app .header .logo{display:flex;font-family:ProximaNova;font-weight:700;text-decoration:none;text-transform:uppercase}.app .header .logo-img{display:inline-block;vertical-align:middle;width:3em}.app .header .logo-title{color:#fff;display:inline-block;font-size:3em;letter-spacing:.05em;margin-left:.1em;vertical-align:middle}.app .header .logo-description-start{color:#d7cf9b;font-size:2em;letter-spacing:.07em;margin-left:.1em;margin-top:-.3em}.app .header .logo-description-end{color:#d7cf9b;font-size:7.2em;letter-spacing:.03em;margin-left:.2em;margin-top:-.21em}.app .header .logo-description-end-lg{color:#d7cf9b;font-size:3.6em;letter-spacing:.06em;margin-top:-.2em}.app .content{flex:1}.app .footer{background:#333;background:radial-gradient(#555,#424242,#333);color:#ccc;padding:1.5em 0 3em}.app .footer h5{color:#d7cf9b;font-weight:700;margin-bottom:.6em;opacity:.7;text-shadow:0 0 1em #000;text-transform:uppercase}.app .footer a{color:#ccc;text-decoration:none}.app .footer a:hover{text-decoration:underline}.app .footer ul.nav>li{font-size:.9em;line-height:1.8em;word-break:break-all}.app .song-search .alert.alert-success a{color:#aed3b7;text-decoration:none}.app .song-search .alert.alert-success a:hover{color:#28a745}.app .song-search-input{position:relative}.app .song-search-input>i{color:#888;left:.7em;position:absolute;top:50%;transform:translateY(-50%);z-index:1}.app .song-search-input>i.song-search-loading{margin-top:-.37em}.app .song-search-input>i.song-search-close{cursor:pointer;left:unset;opacity:.6;right:.7em}.app .song-search-input>i.song-search-close:hover{opacity:1}.app .song-search-input>input{padding-left:2.5em}.app .song-search-input>input:focus{z-index:0}.app .cover-img{height:2.22em;left:2px;object-fit:cover;pointer-events:none;position:absolute;top:1px;width:2.22em;z-index:2}.app .cover-remove{right:4.5em}.app .cover-label.with-img{padding-left:3em}.app .upload-preloader-btn i{color:#ccc;font-size:1.4em;margin-left:.3em;margin-top:-.1em;vertical-align:middle}.app .song-priority{font-size:.9em}.app .image-link{align-items:center;color:#fff;display:inline-flex;flex-direction:row;opacity:.7;text-decoration:none}.app .image-link:hover{opacity:1}.app .image-link-pic{font-size:3em}.app .image-link-title{font-size:3em;margin-left:.5em;text-transform:uppercase}.app #audio-file{left:-10000px}.app .questions{display:inline-block;list-style:none;margin:0;text-align:left}.app .questions>li{opacity:.9}.app .questions>li:not(:last-child){margin-bottom:2em}.app .questions>li>:first-child{color:#fff;font-size:1.5em;font-weight:700;text-transform:uppercase}.app .questions>li>:last-child{color:#ccc;font-size:1.4em}.app .questions>li>:last-child:before{color:#86e29b;content:"↵";display:inline-block;font-weight:700;margin:0 .4em 0 0;transform:scaleX(-1)}
|
20
|
+
*/@font-face{font-display:block;font-family:Font Awesome\ 5 Brands;font-style:normal;font-weight:400;src:url(fa-brands-400.eot);src:url(fa-brands-400.eot) format("embedded-opentype"),url(fa-brands-400.woff2) format("woff2"),url(fa-brands-400.woff) format("woff"),url(fa-brands-400.ttf) format("truetype"),url(fa-brands-400.svg) format("svg")}.fab{font-family:Font Awesome\ 5 Brands;font-weight:400}@font-face{font-family:ProximaNova;src:url(proxima-nova.ttf)}@font-face{font-family:OpenSans;src:url(open-sans.ttf)}*{margin:0;padding:0}body{background:#353535;color:#ccc;font-family:OpenSans;height:100%;overflow-y:scroll}.custom-file input{cursor:pointer;text-indent:-1000px}.custom-control-label{cursor:pointer;opacity:.8}.custom-control-label:hover{opacity:1}.btn{font-weight:700;padding:0;text-transform:uppercase}.btn:active,.btn:focus{box-shadow:none!important;outline:none!important}.btn[disabled]{cursor:not-allowed}a{color:#ccc;text-decoration:underline}a:hover{color:#ccc;text-decoration:none}.input-group-lg input[type=text]{height:auto;padding:.42rem 1rem .45rem}.alert-success{background-color:#25301f;border-color:#28a745;color:#aed3b7}.alert-danger{background-color:#301f1f;border-color:#c00;color:#d3aeae}.alert-info{background-color:#1f2730;border-color:#0af;color:#aec7d3}.invalid-feedback{color:#f39595}.close-fa{color:#666;cursor:pointer;opacity:.7;position:absolute;right:.9em;top:50%;transform:translateY(-50%);z-index:2}.close-fa:hover{opacity:1}.app{display:flex;flex-direction:column;height:100vh}.app .wmodal-overlay{align-items:center;background:rgba(34,34,34,.8);cursor:pointer;display:flex;height:100vh;justify-content:center;left:0;position:fixed;top:0;width:100%;z-index:11000}.app .wmodal-close{color:#666;cursor:pointer;font-size:1.8em;opacity:.4;position:absolute;right:.55em;top:.5em}.app .wmodal-close:hover{opacity:1}.app .wmodal-body{background:#000;box-shadow:0 0 4px 2px hsla(0,0%,40%,.6);box-sizing:border-box;cursor:default;padding:3.5em 2.5em;position:relative}.app .upload-events .wmodal-close{font-size:2em;right:1em;top:50%;transform:translateY(-50%)}.app .upload-events .wmodal-body{padding:2em 5em 2em 2em;word-break:break-all}.app .upload-events .wmodal-body.danger{box-shadow:0 0 4px 2px rgba(204,0,0,.6)}.app .upload-events .wmodal-body.success{box-shadow:0 0 4px 2px rgba(40,167,69,.6)}.app .finding-list>*{display:block}.app .finding-list>:not(:first-child){margin-top:.5em}.app .captcha input{background:#151515;border-color:#292929;width:240px}.app .captcha input:focus{background:#151515;border-color:#666}.app .captcha-preloader{color:#666;font-size:1.7em;text-align:center}.app .header{background:#333;background:radial-gradient(#666,#464646,#333);padding:8.2em 0 6.6em;position:relative;text-shadow:0 0 .8em #333}.app .header .songs-counter-text{bottom:1.5em;color:#666;font-weight:700;left:50%;position:absolute;text-align:center;text-transform:uppercase;transform:translateX(-50%)}.app .header .songs-counter-text b{color:#888}.app .header .logo{display:flex;font-family:ProximaNova;font-weight:700;text-decoration:none;text-transform:uppercase}.app .header .logo-img{display:inline-block;vertical-align:middle;width:3em}.app .header .logo-title{color:#fff;display:inline-block;font-size:3em;letter-spacing:.05em;margin-left:.1em;vertical-align:middle}.app .header .logo-description-start{color:#d7cf9b;font-size:2em;letter-spacing:.07em;margin-left:.1em;margin-top:-.3em}.app .header .logo-description-end{color:#d7cf9b;font-size:7.2em;letter-spacing:.03em;margin-left:.2em;margin-top:-.21em}.app .header .logo-description-end-lg{color:#d7cf9b;font-size:3.6em;letter-spacing:.06em;margin-top:-.2em}.app .content{flex:1}.app .footer{background:#333;background:radial-gradient(#555,#424242,#333);color:#ccc;padding:1.5em 0 3em}.app .footer h5{color:#d7cf9b;font-weight:700;margin-bottom:.6em;opacity:.7;text-shadow:0 0 1em #000;text-transform:uppercase}.app .footer a{color:#ccc;text-decoration:none}.app .footer a:hover{text-decoration:underline}.app .footer ul.nav>li{font-size:.9em;line-height:1.8em;word-break:break-all}.app .song-search .alert.alert-success a{color:#aed3b7;text-decoration:none}.app .song-search .alert.alert-success a:hover{color:#28a745}.app .song-search-input{position:relative}.app .song-search-input>i{color:#888;left:.7em;position:absolute;top:50%;transform:translateY(-50%);z-index:1}.app .song-search-input>i.song-search-loading{margin-top:-.37em}.app .song-search-input>i.song-search-close{cursor:pointer;left:unset;opacity:.6;right:.7em}.app .song-search-input>i.song-search-close:hover{opacity:1}.app .song-search-input>input{padding-left:2.5em;padding-right:2em}.app .song-search-input>input:focus{z-index:0}.app .cover-img{height:2.22em;left:2px;object-fit:cover;pointer-events:none;position:absolute;top:1px;width:2.22em;z-index:2}.app .cover-remove{right:4.5em}.app .cover-label.with-img{padding-left:3em}.app .upload-preloader-btn i{color:#ccc;font-size:1.4em;margin-left:.3em;margin-top:-.1em;vertical-align:middle}.app .song-priority{font-size:.9em}.app .image-link{align-items:center;color:#fff;display:inline-flex;flex-direction:row;opacity:.7;text-decoration:none}.app .image-link:hover{opacity:1}.app .image-link-pic{font-size:3em}.app .image-link-title{font-size:3em;margin-left:.5em;text-transform:uppercase}.app #audio-file{left:-10000px}.app .questions{display:inline-block;list-style:none;margin:0;text-align:left}.app .questions>li{opacity:.9}.app .questions>li:not(:last-child){margin-bottom:2em}.app .questions>li>:first-child{color:#fff;font-size:1.5em;font-weight:700;text-transform:uppercase}.app .questions>li>:last-child{color:#ccc;font-size:1.4em}.app .questions>li>:last-child:before{color:#86e29b;content:"↵";display:inline-block;font-weight:700;margin:0 .4em 0 0;transform:scaleX(-1)}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "museria",
|
3
|
-
"version": "0.2.
|
3
|
+
"version": "0.2.42",
|
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=
|
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",
|
@@ -69,8 +69,7 @@
|
|
69
69
|
},
|
70
70
|
"dependencies": {
|
71
71
|
"@fortawesome/fontawesome-free": "^5.15.0",
|
72
|
-
"akili": "^1.2.
|
73
|
-
"array-chunk-reader": "^0.1.15",
|
72
|
+
"akili": "^1.2.19",
|
74
73
|
"base64url": "^3.0.1",
|
75
74
|
"bootstrap": "^4.5.3",
|
76
75
|
"chalk": "^4.1.2",
|
@@ -78,7 +77,7 @@
|
|
78
77
|
"express": "^4.17.1",
|
79
78
|
"fs-extra": "^9.0.1",
|
80
79
|
"lodash": "^4.17.20",
|
81
|
-
"metastocle": "^0.2.
|
80
|
+
"metastocle": "^0.2.26",
|
82
81
|
"music-metadata": "^6.4.0",
|
83
82
|
"node-fetch": "^2.6.1",
|
84
83
|
"node-id3": "^0.2.2",
|
@@ -86,8 +85,8 @@
|
|
86
85
|
"serve-favicon": "^2.5.0",
|
87
86
|
"sharp": "^0.25.2",
|
88
87
|
"splaytree": "^3.1.0",
|
89
|
-
"spreadable": "^0.2.
|
90
|
-
"storacle": "^0.2.
|
88
|
+
"spreadable": "^0.2.22",
|
89
|
+
"storacle": "^0.2.22",
|
91
90
|
"transliteration": "^2.2.0"
|
92
91
|
},
|
93
92
|
"repository": {
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div class="app container-fluid">
|
1
|
+
<div class="app container-fluid">
|
2
2
|
<if recreate is="${ this.showCaptcha }" class="captcha wmodal">
|
3
3
|
<div
|
4
4
|
class="wmodal-overlay"
|
@@ -48,6 +48,9 @@
|
|
48
48
|
</div>
|
49
49
|
</if>
|
50
50
|
<header class="header row">
|
51
|
+
<div class="songs-counter-text">
|
52
|
+
There ${this.songsCount == 1? 'is': 'are'} <b>${ Number(this.songsCount).toLocaleString() }</b> song${this.songsCount == 1? '': 's'} on the network
|
53
|
+
</div>
|
51
54
|
<a state="app" class="logo mx-auto px-4">
|
52
55
|
<div>
|
53
56
|
<img src="./img/logo.svg" class="logo-img">
|
@@ -55,12 +58,12 @@
|
|
55
58
|
<div class="logo-description-start">decentralized</div>
|
56
59
|
<div class="logo-description-end-lg d-lg-none">storage</div>
|
57
60
|
</div>
|
58
|
-
<div class="logo-description-end d-none d-lg-block">storage</div>
|
61
|
+
<div class="logo-description-end d-none d-lg-block">storage</div>
|
59
62
|
</a>
|
60
63
|
</header>
|
61
|
-
<div class="content">
|
64
|
+
<div class="content">
|
62
65
|
<div class="row pt-5 pb-3">
|
63
|
-
<div class="song-search col-lg-6 col-12 pl-5 pr-5 pr-lg-4 pt-4">
|
66
|
+
<div class="song-search col-lg-6 col-12 pl-5 pr-5 pr-lg-4 pt-4">
|
64
67
|
<div class="song-search-input input-group input-group-lg">
|
65
68
|
<i hidden="${ this.isFinding }" class="fas fa-search fa-lg"></i>
|
66
69
|
<i hidden="${ !this.isFinding }" class="fas fa-circle-notch fa-spin song-search-loading fa-lg"></i>
|
@@ -240,10 +243,9 @@
|
|
240
243
|
</div>
|
241
244
|
</li>
|
242
245
|
<li>
|
243
|
-
<div>
|
246
|
+
<div>Where can I get the node status?</div>
|
244
247
|
<div>
|
245
|
-
There
|
246
|
-
<a href="/status?pretty" target="_blank">here</a>.
|
248
|
+
There is a special route <a href="/status?pretty" target="_blank">here</a>.
|
247
249
|
</div>
|
248
250
|
</li>
|
249
251
|
<li>
|
@@ -1,7 +1,6 @@
|
|
1
1
|
import './app.scss';
|
2
2
|
import Akili from 'akili';
|
3
3
|
import router from 'akili/src/services/router';
|
4
|
-
import request from 'akili/src/services/request';
|
5
4
|
import client from '../../client';
|
6
5
|
|
7
6
|
export default class App extends Akili.Component {
|
@@ -19,7 +18,7 @@ export default class App extends Akili.Component {
|
|
19
18
|
created() {
|
20
19
|
this.captchaWidth = 240;
|
21
20
|
this.findingSongsLimit = 10;
|
22
|
-
this.songsCountInterval =
|
21
|
+
this.songsCountInterval = 15 * 1000;
|
23
22
|
this.songsCountIntervalObj = null;
|
24
23
|
this.scope.songsCount = 0;
|
25
24
|
this.scope.searchInputValue = this.transition.query.f;
|
@@ -83,8 +82,7 @@ export default class App extends Akili.Component {
|
|
83
82
|
}
|
84
83
|
|
85
84
|
async setSongsCount() {
|
86
|
-
|
87
|
-
this.scope.songsCount = data.filesCount;
|
85
|
+
this.scope.songsCount = await client.getNetworkFilesCount();
|
88
86
|
}
|
89
87
|
|
90
88
|
setFindingValue(val) {
|
@@ -3,7 +3,7 @@
|
|
3
3
|
.app {
|
4
4
|
display: flex;
|
5
5
|
height: 100vh;
|
6
|
-
flex-direction: column;
|
6
|
+
flex-direction: column;
|
7
7
|
|
8
8
|
.wmodal {
|
9
9
|
&-overlay {
|
@@ -96,11 +96,27 @@
|
|
96
96
|
}
|
97
97
|
|
98
98
|
& .header {
|
99
|
+
position: relative;
|
99
100
|
background: #333;
|
100
101
|
background: radial-gradient(#666,#464646, #333);
|
101
102
|
padding: 8.2em 0 6.6em 0;
|
102
103
|
text-shadow: 0px 0px 0.8em #333;
|
103
104
|
|
105
|
+
& .songs-counter-text {
|
106
|
+
position: absolute;
|
107
|
+
left: 50%;
|
108
|
+
transform: translateX(-50%);
|
109
|
+
bottom: 1.5em;
|
110
|
+
color: $gray;
|
111
|
+
text-transform: uppercase;
|
112
|
+
font-weight: bold;
|
113
|
+
text-align: center;
|
114
|
+
|
115
|
+
& b {
|
116
|
+
color: $light;
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
104
120
|
& .logo {
|
105
121
|
display: flex;
|
106
122
|
font-family: ProximaNova;
|
@@ -197,7 +213,7 @@
|
|
197
213
|
}
|
198
214
|
|
199
215
|
&-input {
|
200
|
-
position: relative;
|
216
|
+
position: relative;
|
201
217
|
|
202
218
|
& > i {
|
203
219
|
position: absolute;
|
@@ -224,8 +240,9 @@
|
|
224
240
|
}
|
225
241
|
|
226
242
|
& > input {
|
227
|
-
padding-left: 2.5em;
|
228
|
-
|
243
|
+
padding-left: 2.5em;
|
244
|
+
padding-right: 2em;
|
245
|
+
|
229
246
|
&:focus {
|
230
247
|
z-index: 0;
|
231
248
|
}
|
package/src/client.js
CHANGED
@@ -2,7 +2,6 @@ const DatabaseMuseria = require('../database')();
|
|
2
2
|
const DatabaseLoki = require('spreadable/src/db/transports/loki')(DatabaseMuseria);
|
3
3
|
const DatabaseLokiMetastocle = require('metastocle/src/db/transports/loki')(DatabaseLoki);
|
4
4
|
const DatabaseLokiStoracle = require('storacle/src/db/transports/loki')(DatabaseLokiMetastocle);
|
5
|
-
const ArrayChunkReader = require('array-chunk-reader');
|
6
5
|
const utils = require('../../../utils');
|
7
6
|
|
8
7
|
module.exports = (Parent) => {
|
@@ -20,10 +19,10 @@ module.exports = (Parent) => {
|
|
20
19
|
}, options);
|
21
20
|
const fullName = this.createCollectionName('music');
|
22
21
|
const documents = this.col[fullName].find();
|
23
|
-
const reader = new ArrayChunkReader(documents, { limit: 1000, log: false });
|
24
22
|
let max = null;
|
25
23
|
|
26
|
-
|
24
|
+
for(let i = 0; i < documents.length; i++) {
|
25
|
+
const doc = documents[i];
|
27
26
|
let score = doc.compTitle === title? 1: 0;
|
28
27
|
|
29
28
|
if(!score) {
|
@@ -35,18 +34,18 @@ module.exports = (Parent) => {
|
|
35
34
|
|
36
35
|
if(score === 1) {
|
37
36
|
max = { score, doc };
|
38
|
-
|
37
|
+
break;
|
39
38
|
}
|
40
39
|
|
41
40
|
if(!max || score > max.score) {
|
42
41
|
max = { score, doc };
|
43
|
-
|
42
|
+
continue;
|
44
43
|
}
|
45
44
|
|
46
45
|
if(score == max.score && Math.random() > 0.5) {
|
47
46
|
max = { score, doc };
|
48
47
|
}
|
49
|
-
}
|
48
|
+
}
|
50
49
|
|
51
50
|
if(max && max.score >= options.similarity) {
|
52
51
|
return this.prepareDocumentToGet(max.doc);
|
package/src/node.js
CHANGED
@@ -5,7 +5,6 @@ const sharp = require('sharp');
|
|
5
5
|
const fse = require('fs-extra');
|
6
6
|
const qs = require('querystring');
|
7
7
|
const SplayTree = require('splaytree');
|
8
|
-
const ArrayChunkReader = require('array-chunk-reader');
|
9
8
|
const DatabaseLokiMuseria = require('./db/transports/loki')();
|
10
9
|
const ServerExpressMuseria = require('./server/transports/express')();
|
11
10
|
const MusicCollection = require('./collection/transports/music')();
|
@@ -79,8 +78,7 @@ module.exports = (Parent) => {
|
|
79
78
|
]
|
80
79
|
},
|
81
80
|
task: {
|
82
|
-
cleanUpMusicInterval: '1m'
|
83
|
-
normalizeSongTitlesInterval: '10m',
|
81
|
+
cleanUpMusicInterval: '1m'
|
84
82
|
}
|
85
83
|
}, options);
|
86
84
|
|
@@ -121,10 +119,6 @@ module.exports = (Parent) => {
|
|
121
119
|
if(this.options.task.cleanUpMusicInterval) {
|
122
120
|
await this.task.add('cleanUpMusic', this.options.task.cleanUpMusicInterval, () => this.cleanUpMusic());
|
123
121
|
}
|
124
|
-
|
125
|
-
if(this.options.task.normalizeSongTitlesInterval) {
|
126
|
-
await this.task.add('normalizeSongTitles', this.options.task.normalizeSongTitlesInterval, () => this.normalizeSongTitles());
|
127
|
-
}
|
128
122
|
}
|
129
123
|
|
130
124
|
/**
|
@@ -134,11 +128,21 @@ module.exports = (Parent) => {
|
|
134
128
|
*/
|
135
129
|
async normalizeSongTitles() {
|
136
130
|
const docs = await this.db.getDocuments('music');
|
137
|
-
const
|
138
|
-
|
139
|
-
|
131
|
+
const titles = {};
|
132
|
+
|
133
|
+
for(let i = 0; i < docs.length; i++) {
|
134
|
+
const doc = docs[i];
|
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;
|
140
144
|
await this.db.updateMusicDocument(doc, { beautify: false });
|
141
|
-
}
|
145
|
+
}
|
142
146
|
}
|
143
147
|
|
144
148
|
/**
|
@@ -422,8 +426,7 @@ module.exports = (Parent) => {
|
|
422
426
|
* @returns {object[]}
|
423
427
|
*/
|
424
428
|
async getSongInfo(title, options = {}) {
|
425
|
-
title = utils.
|
426
|
-
this.songTitleTest(title);
|
429
|
+
title = utils.prepareComparisonSongTitle(title);
|
427
430
|
const collection = await this.getCollection('music');
|
428
431
|
const actions = utils.prepareDocumentGettingActions({
|
429
432
|
offset: 0,
|
@@ -468,7 +471,7 @@ module.exports = (Parent) => {
|
|
468
471
|
* @returns {object[]}
|
469
472
|
*/
|
470
473
|
async findSongs(str, options = {}) {
|
471
|
-
const title = utils.
|
474
|
+
const title = utils.prepareComparisonSongTitle(str);
|
472
475
|
str = utils.prepareSongFindingString(str);
|
473
476
|
|
474
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) {
|
@@ -131,4 +131,4 @@ module.exports.removeSong = node => {
|
|
131
131
|
next(err);
|
132
132
|
}
|
133
133
|
}
|
134
|
-
};
|
134
|
+
};
|
@@ -1,4 +1,5 @@
|
|
1
|
-
const
|
1
|
+
const ServerExpressStoracle = require('storacle/src/server/transports/express')();
|
2
|
+
const ServerExpressMetastocle = require('metastocle/src/server/transports/express')(ServerExpressStoracle);
|
2
3
|
const routes = require('./routes');
|
3
4
|
const routesClient = require('./client/routes');
|
4
5
|
const routesApi = require('./api/routes');
|
@@ -29,7 +30,7 @@ module.exports = (Parent) => {
|
|
29
30
|
const remove = [
|
30
31
|
'addDocument', 'updateDocuments',
|
31
32
|
'deleteDocuments', 'getDocumentsCount',
|
32
|
-
'getDocumentByPk', 'getDocuments'
|
33
|
+
'getDocumentByPk', 'getDocuments', 'removeFile'
|
33
34
|
];
|
34
35
|
return super.getClientRoutes().filter(r => !remove.includes(r.name)).concat(routesClient);
|
35
36
|
}
|
@@ -45,7 +46,7 @@ module.exports = (Parent) => {
|
|
45
46
|
* @see ServerExpressMetastocle.prototype.getApiMasterRoutes
|
46
47
|
*/
|
47
48
|
getApiMasterRoutes() {
|
48
|
-
const remove = ['updateDocuments', 'deleteDocuments'];
|
49
|
+
const remove = ['updateDocuments', 'deleteDocuments', 'removeFile'];
|
49
50
|
return super.getApiMasterRoutes().filter(r => !remove.includes(r.name)).concat(routesApiMaster);
|
50
51
|
}
|
51
52
|
|
@@ -53,7 +54,7 @@ module.exports = (Parent) => {
|
|
53
54
|
* @see ServerExpressMetastocle.prototype.getApiButlerRoutes
|
54
55
|
*/
|
55
56
|
getApiButlerRoutes() {
|
56
|
-
const remove = ['updateDocuments', 'deleteDocuments'];
|
57
|
+
const remove = ['updateDocuments', 'deleteDocuments', 'removeFile'];
|
57
58
|
return super.getApiButlerRoutes().filter(r => !remove.includes(r.name)).concat(routesApiButler);
|
58
59
|
}
|
59
60
|
|
@@ -61,7 +62,7 @@ module.exports = (Parent) => {
|
|
61
62
|
* @see ServerExpressMetastocle.prototype.getApiSlaveRoutes
|
62
63
|
*/
|
63
64
|
getApiSlaveRoutes() {
|
64
|
-
const remove = ['updateDocuments', 'deleteDocuments'];
|
65
|
+
const remove = ['updateDocuments', 'deleteDocuments', 'removeFile'];
|
65
66
|
return super.getApiSlaveRoutes().filter(r => !remove.includes(r.name)).concat(routesApiSlave);
|
66
67
|
}
|
67
68
|
|
@@ -69,7 +70,7 @@ module.exports = (Parent) => {
|
|
69
70
|
* @see ServerExpressMetastocle.prototype.getApiNodeRoutes
|
70
71
|
*/
|
71
72
|
getApiNodeRoutes() {
|
72
|
-
const remove = ['addDocument'];
|
73
|
+
const remove = ['addDocument', 'storFile'];
|
73
74
|
return super.getApiNodeRoutes().filter(r => !remove.includes(r.name)).concat(routesApiNode);
|
74
75
|
}
|
75
76
|
}
|
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
|
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',
|
@@ -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 =
|
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.
|
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 =
|
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(
|
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/client.js
CHANGED
@@ -336,7 +336,7 @@ describe('Client', () => {
|
|
336
336
|
assert.isNull(await node.db.getMusicByPk(title), 'check the database');
|
337
337
|
assert.isFalse(await node.hasFile(doc.fileHash), 'check the file');
|
338
338
|
});
|
339
|
-
});
|
339
|
+
});
|
340
340
|
|
341
341
|
describe('.createRequestedSongAudioLink()', () => {
|
342
342
|
it('should return the right link', async () => {
|
package/test/group.js
CHANGED
package/test/node.js
CHANGED
@@ -108,17 +108,13 @@ describe('Node', () => {
|
|
108
108
|
});
|
109
109
|
|
110
110
|
describe('.getSongInfo()', () => {
|
111
|
-
it('should
|
112
|
-
|
113
|
-
|
114
|
-
|
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/routes.js
CHANGED
@@ -361,7 +361,7 @@ describe('routes', () => {
|
|
361
361
|
assert.isNull(await node.db.getMusicByPk(title), 'check the database');
|
362
362
|
assert.isFalse(await node.hasFile(doc.fileHash), 'check the file');
|
363
363
|
});
|
364
|
-
});
|
364
|
+
});
|
365
365
|
|
366
366
|
describe('/api/master/remove-song/', function () {
|
367
367
|
it('should return an auth error', async function () {
|
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.
|
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
|
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'
|
137
|
-
assert.equal(artists.join(','), '
|
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
|
|