Version 1.1
Correction de bugs : * Avoir un logo pour les pages d'erreurs #32 * Stocker localement les assets d'un album #37 Co-authored-by: dbroqua <contact@darkou.fr> Reviewed-on: #43
This commit is contained in:
parent
23c58459af
commit
6d0405d129
19 changed files with 1022 additions and 669 deletions
31
README.md
31
README.md
|
@ -62,7 +62,7 @@ Le site est accessible sur [http://localhost:PORT](http://localhost:PORT).
|
||||||
|
|
||||||
#### Standalone
|
#### Standalone
|
||||||
|
|
||||||
Pour la version standalone je vous conseille de faire un script embarquant les variables d'environnement que vous souhaitez modifier :
|
Pour la version standalone je vous conseille de faire un script embarquant les variables d'environnement que vous souhaitez modifier ([voir à la fin pour la liste des variables](#env-file)) :
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
#! /bin/bash
|
#! /bin/bash
|
||||||
|
@ -184,6 +184,26 @@ server {
|
||||||
|
|
||||||
Une fois le vhost activé (lien symbolique dans le dossier site-enable) et nginx rechargé votre site sera alors accessible en https.
|
Une fois le vhost activé (lien symbolique dans le dossier site-enable) et nginx rechargé votre site sera alors accessible en https.
|
||||||
|
|
||||||
|
### Jobs
|
||||||
|
|
||||||
|
Par défaut toute les images des albums sont affichées depuis Discogs. Cependant avec les temps les urls deviennent invalides. Pour éviter cela lors de l'ajout d'un album à votre collection un job est créé. Ce job a pour rôle de stocker les images sur un bucket s3.
|
||||||
|
|
||||||
|
Pour lancer les jobs il faut mettre en place une tâche cron qui sera éxécutée toute les heures (par exemple).
|
||||||
|
|
||||||
|
Exemple de crontab :
|
||||||
|
```crontab
|
||||||
|
0 * * * * curl 'http://localhost:3001/jobs' \
|
||||||
|
-H 'JOBS_HEADER_KEY: JOBS_HEADER_VALUE' \
|
||||||
|
-H 'Accept: application/json'
|
||||||
|
30 * * * * curl 'http://localhost:3001/jobs?state=ERROR' \
|
||||||
|
-H 'JOBS_HEADER_KEY: JOBS_HEADER_VALUE' \
|
||||||
|
-H 'Accept: application/json'
|
||||||
|
```
|
||||||
|
|
||||||
|
N'oubliez pas de remplacer `localhost:30001`, `JOBS_HEADER_KEY` et `JOBS_HEADER_VALUE` par les bonnes valeurs.
|
||||||
|
|
||||||
|
La première ligne permet de parcourir tous les nouveaux jobs alors que la seconde permet de relancer les jobs en erreurs (après 5 tentatives le job est marqué comme définitivement perdu).
|
||||||
|
|
||||||
### Fichier .env {#env-file}
|
### Fichier .env {#env-file}
|
||||||
|
|
||||||
Voici la liste des variables configurables :
|
Voici la liste des variables configurables :
|
||||||
|
@ -198,10 +218,17 @@ FORMSPREE_ID # Id du formulaire formspree pour la page "nous-contacter"
|
||||||
MATOMO_URL # Url vers l'instance matomo (exemple: https://analytics.darkou.fr/)
|
MATOMO_URL # Url vers l'instance matomo (exemple: https://analytics.darkou.fr/)
|
||||||
MATOMO_ID # Id du site sur votre instance matomo (exemple: 1)
|
MATOMO_ID # Id du site sur votre instance matomo (exemple: 1)
|
||||||
SITE_NAME # Nom du site (utilisé dans le titre des pages)
|
SITE_NAME # Nom du site (utilisé dans le titre des pages)
|
||||||
|
AWS_ACCESS_KEY_ID # Clé d'accès AWS
|
||||||
|
AWS_SECRET_ACCESS_KEY # Clé secrète AWS
|
||||||
|
S3_ENDPOINT # Url de l'instance aws (s3.fr-par.scw.cloud pour scaleway france par exemple)
|
||||||
|
S3_SIGNATURE # Version de la signature AWS (s3v4 pour scaleway par exemple)
|
||||||
|
S3_BASEFOLDER # Nom du sous dossier dans lequel seront mis les pochettes des albums
|
||||||
|
S3_BUCKET # Nom du bucket
|
||||||
|
JOBS_HEADER_KEY # Nom du header utilisé pour l'identification des tâches cron (par exemple musictopus)
|
||||||
|
JOBS_HEADER_VALUE # Valeur de la clé
|
||||||
```
|
```
|
||||||
|
|
||||||
## Contributeurs
|
## Contributeurs
|
||||||
|
|
||||||
- Damien Broqua (développeur principal du projet)
|
- Damien Broqua (développeur principal du projet)
|
||||||
- Brunus (Logo et fournisseur d'idées :wink: )
|
- Brunus (Logo et fournisseur d'idées :wink: )
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,14 @@ services:
|
||||||
MATOMO_URL: ${MATOMO_URL}
|
MATOMO_URL: ${MATOMO_URL}
|
||||||
MATOMO_ID: ${MATOMO_ID}
|
MATOMO_ID: ${MATOMO_ID}
|
||||||
SITE_NAME: ${SITE_NAME}
|
SITE_NAME: ${SITE_NAME}
|
||||||
|
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
|
||||||
|
S3_BASEFOLDER: ${S3_BASEFOLDER}
|
||||||
|
S3_BUCKET: ${S3_BUCKET}
|
||||||
|
S3_ENDPOINT: ${S3_ENDPOINT}
|
||||||
|
S3_SIGNATURE: ${S3_SIGNATURE}
|
||||||
|
JOBS_HEADER_KEY: ${JOBS_HEADER_KEY}
|
||||||
|
JOBS_HEADER_VALUE: ${JOBS_HEADER_VALUE}
|
||||||
networks:
|
networks:
|
||||||
- musictopus
|
- musictopus
|
||||||
musictopus-db:
|
musictopus-db:
|
||||||
|
|
|
@ -28,6 +28,14 @@ services:
|
||||||
MATOMO_URL: ${MATOMO_URL}
|
MATOMO_URL: ${MATOMO_URL}
|
||||||
MATOMO_ID: ${MATOMO_ID}
|
MATOMO_ID: ${MATOMO_ID}
|
||||||
SITE_NAME: ${SITE_NAME}
|
SITE_NAME: ${SITE_NAME}
|
||||||
|
AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID}
|
||||||
|
AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY}
|
||||||
|
S3_BASEFOLDER: ${S3_BASEFOLDER}
|
||||||
|
S3_BUCKET: ${S3_BUCKET}
|
||||||
|
S3_ENDPOINT: ${S3_ENDPOINT}
|
||||||
|
S3_SIGNATURE: ${S3_SIGNATURE}
|
||||||
|
JOBS_HEADER_KEY: ${JOBS_HEADER_KEY}
|
||||||
|
JOBS_HEADER_VALUE: ${JOBS_HEADER_VALUE}
|
||||||
networks:
|
networks:
|
||||||
- musictopus
|
- musictopus
|
||||||
musictopus-db:
|
musictopus-db:
|
||||||
|
|
|
@ -41,6 +41,7 @@
|
||||||
"@babel/cli": "^7.17.0",
|
"@babel/cli": "^7.17.0",
|
||||||
"@babel/core": "^7.17.2",
|
"@babel/core": "^7.17.2",
|
||||||
"@babel/preset-env": "^7.16.11",
|
"@babel/preset-env": "^7.16.11",
|
||||||
|
"aws-sdk": "^2.1110.0",
|
||||||
"axios": "^0.26.0",
|
"axios": "^0.26.0",
|
||||||
"connect-ensure-login": "^0.1.1",
|
"connect-ensure-login": "^0.1.1",
|
||||||
"connect-flash": "^0.1.1",
|
"connect-flash": "^0.1.1",
|
||||||
|
@ -60,10 +61,12 @@
|
||||||
"mongoose-unique-validator": "^3.0.0",
|
"mongoose-unique-validator": "^3.0.0",
|
||||||
"npm-run-all": "^4.1.5",
|
"npm-run-all": "^4.1.5",
|
||||||
"passport": "^0.5.2",
|
"passport": "^0.5.2",
|
||||||
|
"passport-custom": "^1.1.1",
|
||||||
"passport-http": "^0.3.0",
|
"passport-http": "^0.3.0",
|
||||||
"passport-local": "^1.0.0",
|
"passport-local": "^1.0.0",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"sass": "^1.49.7",
|
"sass": "^1.49.7",
|
||||||
|
"uuid": "^8.3.2",
|
||||||
"vue": "^3.2.31"
|
"vue": "^3.2.31"
|
||||||
},
|
},
|
||||||
"nodemonConfig": {
|
"nodemonConfig": {
|
||||||
|
|
|
@ -6,50 +6,50 @@
|
||||||
xmlns:svg="http://www.w3.org/2000/svg"
|
xmlns:svg="http://www.w3.org/2000/svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||||
viewBox="0 0 168.85766 133.4734"
|
width="100%"
|
||||||
version="1.1"
|
|
||||||
id="MusicTopus"
|
|
||||||
height="100%"
|
height="100%"
|
||||||
width="100%">
|
id="MusicTopus"
|
||||||
|
version="1.1"
|
||||||
|
viewBox="0 0 168.85766 133.4734">
|
||||||
<defs
|
<defs
|
||||||
id="defs2">
|
id="defs2">
|
||||||
<linearGradient
|
<linearGradient
|
||||||
id="linearGradient3016">
|
id="linearGradient3016">
|
||||||
<stop
|
<stop
|
||||||
offset="0"
|
id="stop3018-4"
|
||||||
stop-color="#949494"
|
stop-color="#949494"
|
||||||
id="stop3018-4" />
|
offset="0" />
|
||||||
<stop
|
<stop
|
||||||
offset="1"
|
id="stop3020-0"
|
||||||
stop-opacity="0"
|
|
||||||
stop-color="#949494"
|
stop-color="#949494"
|
||||||
id="stop3020-0" />
|
stop-opacity="0"
|
||||||
|
offset="1" />
|
||||||
</linearGradient>
|
</linearGradient>
|
||||||
<linearGradient
|
<linearGradient
|
||||||
x1="57.074001"
|
id="linearGradient1417"
|
||||||
y1="27.309999"
|
|
||||||
gradientTransform="translate(-19.041285,-22.505715)"
|
|
||||||
x2="103.29"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
|
||||||
xlink:href="#linearGradient3016"
|
|
||||||
y2="104.59"
|
y2="104.59"
|
||||||
id="linearGradient1417" />
|
xlink:href="#linearGradient3016"
|
||||||
<radialGradient
|
|
||||||
r="7.395"
|
|
||||||
gradientTransform="matrix(2.2777,1.8145,-1.5547,2.3139,262.42,-105.22857)"
|
|
||||||
cx="16.073999"
|
|
||||||
cy="98.385002"
|
|
||||||
gradientUnits="userSpaceOnUse"
|
gradientUnits="userSpaceOnUse"
|
||||||
id="radialGradient10835">
|
x2="103.29"
|
||||||
|
gradientTransform="translate(-19.041285,-22.505715)"
|
||||||
|
y1="27.309999"
|
||||||
|
x1="57.074001" />
|
||||||
|
<radialGradient
|
||||||
|
id="radialGradient10835"
|
||||||
|
gradientUnits="userSpaceOnUse"
|
||||||
|
cy="98.385002"
|
||||||
|
cx="16.073999"
|
||||||
|
gradientTransform="matrix(2.2777,1.8145,-1.5547,2.3139,262.42,-105.22857)"
|
||||||
|
r="7.395">
|
||||||
<stop
|
<stop
|
||||||
offset="0"
|
id="stop10767-64"
|
||||||
stop-color="#989898"
|
stop-color="#989898"
|
||||||
id="stop10767-64" />
|
offset="0" />
|
||||||
<stop
|
<stop
|
||||||
offset="1"
|
id="stop10769-6"
|
||||||
|
stop-color="#989898"
|
||||||
stop-opacity="0"
|
stop-opacity="0"
|
||||||
stop-color="#989898"
|
offset="1" />
|
||||||
id="stop10769-6" />
|
|
||||||
</radialGradient>
|
</radialGradient>
|
||||||
</defs>
|
</defs>
|
||||||
<metadata
|
<metadata
|
||||||
|
@ -65,279 +65,276 @@
|
||||||
</rdf:RDF>
|
</rdf:RDF>
|
||||||
</metadata>
|
</metadata>
|
||||||
<g
|
<g
|
||||||
id="layer1"
|
transform="translate(-4.0461145,-24.740973)"
|
||||||
transform="translate(-4.0461145,-24.740973)">
|
id="layer1">
|
||||||
<g
|
<g
|
||||||
transform="matrix(-1,0,0,1,16.909353,13.841748)"
|
id="g4845"
|
||||||
id="g4845">
|
transform="matrix(-1,0,0,1,16.909353,13.841748)">
|
||||||
<path
|
<path
|
||||||
style="fill:#301818;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4839"
|
||||||
d="m -124.03737,64.054339 c -0.67869,5.653701 -1.79458,14.69263 1.57781,21.418531 0.16987,0.339747 -10.7216,2.427294 -11.91019,-4.293016 -1.11922,-6.328076 -2.52943,-10.954215 -1.33635,-13.964832 3.07095,-7.749247 11.86215,-3.651666 11.66873,-3.160683 z"
|
|
||||||
id="path4839" />
|
|
||||||
<path
|
|
||||||
style="fill:#7b2121;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
d="m -125.27588,63.26029 c 0.41675,0.233807 1.34252,0.316004 1.74941,0.697875 -0.40534,4.680582 -0.98591,7.419536 -0.0655,11.187673 1.56849,6.421216 1.99919,7.121733 2.51886,9.876016 -0.60349,0.201385 -1.88006,0.796452 -2.50566,0.776752 -0.78768,-7.838385 -2.58856,-15.620579 -1.69713,-22.538316 z"
|
|
||||||
id="path4841" />
|
|
||||||
<path
|
|
||||||
style="fill:#f3e8d4;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
|
||||||
d="m -135.88244,67.615699 c 0,0 3.35454,1.181174 3.82701,2.787573 0.47247,1.606399 0.70871,6.000372 0.37798,8.031993 -0.33073,2.031624 -2.74033,2.882069 -2.74033,2.882069 -0.81232,-5.382945 -2.2983,-10.046051 -1.46466,-13.701635 z"
|
|
||||||
id="path4843" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
id="g4837"
|
|
||||||
transform="translate(195.33147,13.841748)">
|
|
||||||
<path
|
|
||||||
id="path4828"
|
|
||||||
d="m -124.03737,64.054339 c -0.67869,5.653701 -1.79458,14.69263 1.57781,21.418531 0.16987,0.339747 -10.7216,2.427294 -11.91019,-4.293016 -1.11922,-6.328076 -2.52943,-10.954215 -1.33635,-13.964832 3.07095,-7.749247 11.86215,-3.651666 11.66873,-3.160683 z"
|
d="m -124.03737,64.054339 c -0.67869,5.653701 -1.79458,14.69263 1.57781,21.418531 0.16987,0.339747 -10.7216,2.427294 -11.91019,-4.293016 -1.11922,-6.328076 -2.52943,-10.954215 -1.33635,-13.964832 3.07095,-7.749247 11.86215,-3.651666 11.66873,-3.160683 z"
|
||||||
style="fill:#301818;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
style="fill:#301818;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
id="path4830"
|
id="path4841"
|
||||||
d="m -125.27588,63.26029 c 0.41675,0.233807 0.84139,0.349413 1.24828,0.731284 -0.40534,4.680582 -0.23721,7.396829 0.16838,11.25449 0.56623,5.385547 0.8967,7.522637 1.41637,10.27692 -0.60349,0.201385 -1.17847,0.395548 -1.80407,0.375848 -0.90324,-7.658049 -3.18063,-15.595778 -1.02896,-22.638542 z"
|
d="m -125.27588,63.26029 c 0.41675,0.233807 1.34252,0.316004 1.74941,0.697875 -0.40534,4.680582 -0.98591,7.419536 -0.0655,11.187673 1.56849,6.421216 1.99919,7.121733 2.51886,9.876016 -0.60349,0.201385 -1.88006,0.796452 -2.50566,0.776752 -0.78768,-7.838385 -2.58856,-15.620579 -1.69713,-22.538316 z"
|
||||||
style="fill:#7b2121;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
style="fill:#7b2121;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
id="path4832"
|
id="path4843"
|
||||||
d="m -135.88244,67.615699 c 0,0 3.35454,1.181174 3.82701,2.787573 0.47247,1.606399 0.70871,6.000372 0.37798,8.031993 -0.33073,2.031624 -2.74033,2.882069 -2.74033,2.882069 -0.81232,-5.382945 -2.2983,-10.046051 -1.46466,-13.701635 z"
|
d="m -135.88244,67.615699 c 0,0 3.35454,1.181174 3.82701,2.787573 0.47247,1.606399 0.70871,6.000372 0.37798,8.031993 -0.33073,2.031624 -2.74033,2.882069 -2.74033,2.882069 -0.81232,-5.382945 -2.2983,-10.046051 -1.46466,-13.701635 z"
|
||||||
style="fill:#f3e8d4;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
style="fill:#f3e8d4;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
</g>
|
</g>
|
||||||
|
<g
|
||||||
|
transform="translate(195.33147,13.841748)"
|
||||||
|
id="g4837">
|
||||||
|
<path
|
||||||
|
style="fill:#301818;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -124.03737,64.054339 c -0.67869,5.653701 -1.79458,14.69263 1.57781,21.418531 0.16987,0.339747 -10.7216,2.427294 -11.91019,-4.293016 -1.11922,-6.328076 -2.52943,-10.954215 -1.33635,-13.964832 3.07095,-7.749247 11.86215,-3.651666 11.66873,-3.160683 z"
|
||||||
|
id="path4828" />
|
||||||
|
<path
|
||||||
|
style="fill:#7b2121;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -125.27588,63.26029 c 0.41675,0.233807 0.84139,0.349413 1.24828,0.731284 -0.40534,4.680582 -0.23721,7.396829 0.16838,11.25449 0.56623,5.385547 0.8967,7.522637 1.41637,10.27692 -0.60349,0.201385 -1.17847,0.395548 -1.80407,0.375848 -0.90324,-7.658049 -3.18063,-15.595778 -1.02896,-22.638542 z"
|
||||||
|
id="path4830" />
|
||||||
|
<path
|
||||||
|
style="fill:#f3e8d4;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m -135.88244,67.615699 c 0,0 3.35454,1.181174 3.82701,2.787573 0.47247,1.606399 0.70871,6.000372 0.37798,8.031993 -0.33073,2.031624 -2.74033,2.882069 -2.74033,2.882069 -0.81232,-5.382945 -2.2983,-10.046051 -1.46466,-13.701635 z"
|
||||||
|
id="path4832" />
|
||||||
|
</g>
|
||||||
<path
|
<path
|
||||||
style="fill:#ec8479;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4668"
|
||||||
d="m 104.6994,52.638393 c -15.180178,-0.07451 -33.140948,8.951637 -33.639877,27.78125 -0.50786,19.166666 9.223449,34.250207 -6.425596,34.301337 -10.643849,0.0348 -6.80357,-16.158483 -6.80357,-16.158483 0.443803,-1.702342 -1.552627,-2.254759 -2.693082,-0.897692 -11.388255,13.593915 3.527003,26.318385 11.722934,37.071045 11.135404,14.60911 24.729611,20.33094 37.083241,-6.31323 16.89051,50.78843 72.75864,-14.34852 42.71131,-27.44716 -0.79429,-0.21911 -2.98222,-0.45948 -1.5119,1.74478 0,0 7.46421,11.18075 -3.02381,13.22916 -7.74851,0.37797 -6.46564,-8.79054 -1.88989,-25.702378 5.34881,-19.769046 -13.75388,-37.501741 -35.52976,-37.608629 z"
|
d="m 104.6994,52.638393 c -15.180178,-0.07451 -33.140948,8.951637 -33.639877,27.78125 -0.50786,19.166666 9.223449,34.250207 -6.425596,34.301337 -10.643849,0.0348 -6.80357,-16.158483 -6.80357,-16.158483 0.443803,-1.702342 -1.552627,-2.254759 -2.693082,-0.897692 -11.388255,13.593915 3.527003,26.318385 11.722934,37.071045 11.135404,14.60911 24.729611,20.33094 37.083241,-6.31323 16.89051,50.78843 72.75864,-14.34852 42.71131,-27.44716 -0.79429,-0.21911 -2.98222,-0.45948 -1.5119,1.74478 0,0 7.46421,11.18075 -3.02381,13.22916 -7.74851,0.37797 -6.46564,-8.79054 -1.88989,-25.702378 5.34881,-19.769046 -13.75388,-37.501741 -35.52976,-37.608629 z"
|
||||||
id="path4668" />
|
style="fill:#ec8479;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#fbb9b8;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4723"
|
||||||
d="m 149.1438,102.30834 c 0,0 -0.30808,0.3199 -0.0742,0.7208 0.23386,0.4009 2.13815,1.20271 1.90429,2.03793 -0.23386,0.83522 -0.23386,1.46998 0.46773,2.03793 0.70158,0.56795 3.00678,1.43657 3.07359,2.23838 0.65095,0.94785 0.11036,4.73821 -1.10248,5.34539 -0.30068,0.83522 -0.26727,1.5368 -0.26727,1.5368 l 2.00452,4.47677 c 2.67736,-5.97229 4.5819,-11.72353 -6.00616,-18.394 z"
|
d="m 149.1438,102.30834 c 0,0 -0.30808,0.3199 -0.0742,0.7208 0.23386,0.4009 2.13815,1.20271 1.90429,2.03793 -0.23386,0.83522 -0.23386,1.46998 0.46773,2.03793 0.70158,0.56795 3.00678,1.43657 3.07359,2.23838 0.65095,0.94785 0.11036,4.73821 -1.10248,5.34539 -0.30068,0.83522 -0.26727,1.5368 -0.26727,1.5368 l 2.00452,4.47677 c 2.67736,-5.97229 4.5819,-11.72353 -6.00616,-18.394 z"
|
||||||
id="path4723" />
|
style="fill:#fbb9b8;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#feb6b7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4689"
|
||||||
d="m 54.790252,98.184879 c 0,0 -8.485807,6.113791 -6.147199,15.134141 2.338609,9.02034 7.015826,10.95805 7.015826,10.95805 -0.248403,-2.16366 -0.08184,-4.23511 0.801809,-6.1472 0,0 -0.200453,-2.07134 -1.336349,-3.00678 -1.135896,-0.93545 -3.073599,-1.67044 -2.672694,-3.07361 0.400905,-1.40316 1.403165,-3.07359 0.935442,-4.14267 -0.467722,-1.06908 -1.069078,-1.73725 -0.801809,-2.87315 0.267272,-1.1359 2.204974,-6.848781 2.204974,-6.848781 z"
|
d="m 54.790252,98.184879 c 0,0 -8.485807,6.113791 -6.147199,15.134141 2.338609,9.02034 7.015826,10.95805 7.015826,10.95805 -0.248403,-2.16366 -0.08184,-4.23511 0.801809,-6.1472 0,0 -0.200453,-2.07134 -1.336349,-3.00678 -1.135896,-0.93545 -3.073599,-1.67044 -2.672694,-3.07361 0.400905,-1.40316 1.403165,-3.07359 0.935442,-4.14267 -0.467722,-1.06908 -1.069078,-1.73725 -0.801809,-2.87315 0.267272,-1.1359 2.204974,-6.848781 2.204974,-6.848781 z"
|
||||||
id="path4689" />
|
style="fill:#feb6b7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<ellipse
|
<path
|
||||||
ry="20.250488"
|
|
||||||
rx="22.683598"
|
|
||||||
cy="99.451027"
|
|
||||||
cx="39.641644"
|
|
||||||
id="circle4790"
|
id="circle4790"
|
||||||
|
d="m 62.325241,99.451027 c 0,11.184033 -10.15579,20.250493 -22.683597,20.250493 -7.402258,0 -0.829184,-8.01428 -4.969517,-12.91144 -0.612097,-0.72399 -1.770309,-5.66385 -3.213537,-6.11122 -5.316459,-1.647971 -14.500545,2.37098 -14.500544,-1.227833 3e-6,-11.184036 6.023828,-20.350467 18.551633,-20.350467 0.220732,3.973948 2.052425,13.960818 7.154907,14.623465 7.156786,-4.199604 19.410793,-0.618035 19.660655,5.727002 z"
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:8.20355606;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:8.20355606;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
<path
|
<path
|
||||||
id="path4"
|
style="fill:#212121;fill-opacity:1;stroke-width:0.205;stroke:none;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none"
|
||||||
transform="translate(4.0461145,24.740973)"
|
|
||||||
d="m 34.146484,51.925781 c -0.314077,0.0092 -0.628478,0.01217 -0.941406,0.02734 -11.059699,0.788242 -20.839327,8.72416 -22.753906,18.482422 -1.0222988,4.666022 -0.263288,9.571297 1.953125,13.871094 l 2.441406,-2.441407 4.525391,2.404297 2.121094,-3.251953 5.230468,1.13086 0.707032,-4.09961 1.414062,4.382813 0.566406,2.402343 -5.65625,-0.564453 -1.414062,4.351719 -4.013672,2.913906 c 0.239784,0.192385 0.473561,0.390466 0.722656,0.574219 7.713021,6.01634 19.591819,7.137217 28.550781,2.716797 C 57.055648,90.480286 62.646095,80.45375 60.816406,71.099609 59.52397,63.325904 53.292903,56.50211 45.197266,53.552734 c 1.309899,2.835554 1.897379,5.928925 2.693359,8.935547 l -10.398437,2 0.90039,3.699219 -3.90039,-4 6.199218,-3.498047 -8.498047,-4.099609 3.998047,-1.900391 z m -9.673828,6.271485 c 0.23821,0.241845 0.400025,0.530577 0.587891,0.802734 -0.185522,2.23358 -3.870804,4.435587 -3.755859,4.089844 -1.319654,1.186159 -2.291211,3.893629 -4.216797,1.74414 1.76144,-2.731738 4.374999,-5.003791 7.384765,-6.636718 z m 2.291016,3.501953 c 0.217609,0.03588 0.400611,0.22504 0.52539,0.664062 1.260066,1.740193 -2.311306,4.335474 -3.519531,4.785157 -0.880279,0.143799 -1.50846,0.89274 -2.666015,-0.138672 0.261264,-1.586273 5.126947,-5.38799 3.720703,-4.21875 0.526069,-0.238877 1.182742,-0.95689 1.710937,-1.080078 0.07923,-0.01848 0.15598,-0.02368 0.228516,-0.01172 z m 2.261719,3.511719 c 0.318835,0.04398 0.591476,0.29958 0.78125,0.880859 0.691211,2.140581 -1.931888,4.415457 -2.626953,4.083984 -1.770649,-0.510364 -3.306383,-1.512291 -1.222657,-2.802734 0.746208,-0.529496 2.111854,-2.294057 3.06836,-2.162109 z m 6.597656,6.009765 c 0.500623,0.0012 1.007104,0.09327 1.488281,0.292969 3.025279,0.986468 3.11205,5.198119 0.179688,6.324219 -2.297247,1.06592 -5.580236,-0.439849 -5.564454,-2.841797 -0.353584,-2.07507 1.72712,-3.780425 3.896485,-3.775391 z m 7.677734,8.976563 c 0.454001,-0.07081 0.897599,0.528293 1.34375,0.736328 1.285766,0.439342 -0.203248,1.889914 -0.646484,2.283203 -1.277789,1.157639 -3.468693,-2.140236 -1.15625,-2.685547 0.154247,-0.211427 0.307651,-0.310382 0.458984,-0.333984 z m 4.345703,2.757812 c 0.225859,0.03343 0.481027,0.198816 0.785157,0.564453 1.747014,0.72605 -1.303778,2.574316 -1.595703,2.697266 -1.103201,1.48933 -3.167305,-1.432728 -1.03125,-1.835938 0.74365,-0.437265 1.164221,-1.526065 1.841796,-1.425781 z m 3.269532,2.306641 c 0.03893,0.0024 0.06028,0.01926 0.0625,0.05078 0.307212,0.15856 0.582857,0.359282 0.86914,0.544922 1.634832,1.36857 -2.961621,4.630292 -3.164062,4.070312 -2.704111,-1.615931 1.64845,-4.702094 2.232422,-4.666015 z"
|
d="m 34.146484,51.925781 c -0.314077,0.0092 -0.628478,0.01217 -0.941406,0.02734 -11.059699,0.788242 -20.839327,8.72416 -22.753906,18.482422 -1.0222988,4.666022 -0.263288,9.571297 1.953125,13.871094 l 2.441406,-2.441407 4.525391,2.404297 2.121094,-3.251953 5.230468,1.13086 0.707032,-4.09961 1.414062,4.382813 0.566406,2.402343 -5.65625,-0.564453 -1.414062,4.351719 -4.013672,2.913906 c 0.239784,0.192385 0.473561,0.390466 0.722656,0.574219 7.713021,6.01634 19.591819,7.137217 28.550781,2.716797 C 57.055648,90.480286 62.646095,80.45375 60.816406,71.099609 59.52397,63.325904 53.292903,56.50211 45.197266,53.552734 c 1.309899,2.835554 1.897379,5.928925 2.693359,8.935547 l -10.398437,2 0.90039,3.699219 -3.90039,-4 6.199218,-3.498047 -8.498047,-4.099609 3.998047,-1.900391 z m -9.673828,6.271485 c 0.23821,0.241845 0.400025,0.530577 0.587891,0.802734 -0.185522,2.23358 -3.870804,4.435587 -3.755859,4.089844 -1.319654,1.186159 -2.291211,3.893629 -4.216797,1.74414 1.76144,-2.731738 4.374999,-5.003791 7.384765,-6.636718 z m 2.291016,3.501953 c 0.217609,0.03588 0.400611,0.22504 0.52539,0.664062 1.260066,1.740193 -2.311306,4.335474 -3.519531,4.785157 -0.880279,0.143799 -1.50846,0.89274 -2.666015,-0.138672 0.261264,-1.586273 5.126947,-5.38799 3.720703,-4.21875 0.526069,-0.238877 1.182742,-0.95689 1.710937,-1.080078 0.07923,-0.01848 0.15598,-0.02368 0.228516,-0.01172 z m 2.261719,3.511719 c 0.318835,0.04398 0.591476,0.29958 0.78125,0.880859 0.691211,2.140581 -1.931888,4.415457 -2.626953,4.083984 -1.770649,-0.510364 -3.306383,-1.512291 -1.222657,-2.802734 0.746208,-0.529496 2.111854,-2.294057 3.06836,-2.162109 z m 6.597656,6.009765 c 0.500623,0.0012 1.007104,0.09327 1.488281,0.292969 3.025279,0.986468 3.11205,5.198119 0.179688,6.324219 -2.297247,1.06592 -5.580236,-0.439849 -5.564454,-2.841797 -0.353584,-2.07507 1.72712,-3.780425 3.896485,-3.775391 z m 7.677734,8.976563 c 0.454001,-0.07081 0.897599,0.528293 1.34375,0.736328 1.285766,0.439342 -0.203248,1.889914 -0.646484,2.283203 -1.277789,1.157639 -3.468693,-2.140236 -1.15625,-2.685547 0.154247,-0.211427 0.307651,-0.310382 0.458984,-0.333984 z m 4.345703,2.757812 c 0.225859,0.03343 0.481027,0.198816 0.785157,0.564453 1.747014,0.72605 -1.303778,2.574316 -1.595703,2.697266 -1.103201,1.48933 -3.167305,-1.432728 -1.03125,-1.835938 0.74365,-0.437265 1.164221,-1.526065 1.841796,-1.425781 z m 3.269532,2.306641 c 0.03893,0.0024 0.06028,0.01926 0.0625,0.05078 0.307212,0.15856 0.582857,0.359282 0.86914,0.544922 1.634832,1.36857 -2.961621,4.630292 -3.164062,4.070312 -2.704111,-1.615931 1.64845,-4.702094 2.232422,-4.666015 z"
|
||||||
style="fill:#212121;fill-opacity:1;stroke-width:0.00521397" />
|
transform="translate(4.0461145,24.740973)"
|
||||||
|
id="path4" />
|
||||||
<ellipse
|
<ellipse
|
||||||
ry="5.6584005"
|
cy="99.451027"
|
||||||
rx="6.7384396"
|
cx="39.641644"
|
||||||
style="opacity:1;fill:#ffaf62;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.41468528;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
|
||||||
id="path4786"
|
id="path4786"
|
||||||
cx="39.641644"
|
style="opacity:1;fill:#ffaf62;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.41468528;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
cy="99.451027" />
|
rx="6.7384396"
|
||||||
|
ry="5.6584005" />
|
||||||
<ellipse
|
<ellipse
|
||||||
ry="0.96285915"
|
cy="99.451027"
|
||||||
rx="1.1466434"
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.41468525;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
|
||||||
id="path4788"
|
|
||||||
cx="39.641644"
|
cx="39.641644"
|
||||||
cy="99.451027" />
|
id="path4788"
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.41468525;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
rx="1.1466434"
|
||||||
|
ry="0.96285915" />
|
||||||
<path
|
<path
|
||||||
style="fill:#feb6b7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4693"
|
||||||
d="m 65.146946,109.76994 c -0.178541,-0.31245 -7.366014,3.88706 -8.686258,8.35993 -2.169132,7.34882 1.269529,10.75759 2.271789,11.89349 1.002261,1.1359 8.753078,5.41221 8.753078,5.41221 0,0 -2.53906,-8.01809 -2.472242,-12.22758 0.06682,-4.2095 1.336347,-12.2944 1.336347,-12.2944 0.214328,-1.45042 -0.351567,-1.51081 -1.202714,-1.14365 z"
|
d="m 65.146946,109.76994 c -0.178541,-0.31245 -7.366014,3.88706 -8.686258,8.35993 -2.169132,7.34882 1.269529,10.75759 2.271789,11.89349 1.002261,1.1359 8.753078,5.41221 8.753078,5.41221 0,0 -2.53906,-8.01809 -2.472242,-12.22758 0.06682,-4.2095 1.336347,-12.2944 1.336347,-12.2944 0.214328,-1.45042 -0.351567,-1.51081 -1.202714,-1.14365 z"
|
||||||
id="path4693" />
|
style="fill:#feb6b7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#ffd7d7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4695"
|
||||||
d="m 62.177083,111.27195 c 0,0 1.370163,-0.28348 1.700892,1.13393 0.330729,1.41741 -1.748139,2.92931 -1.559153,4.86644 0.18899,1.93713 0.944941,3.68527 0.803201,5.00818 -0.141742,1.32292 -1.228423,2.4096 -0.897694,4.15774 0.330729,1.74814 1.370163,3.73252 1.748139,4.96094 0.377979,1.22842 0.472472,2.22061 0.472472,2.22061 l -5.575149,-3.35454 c 0,0 -4.771948,-4.77195 -2.787573,-10.91406 1.984375,-6.14211 6.094865,-8.07924 6.094865,-8.07924 z"
|
d="m 62.177083,111.27195 c 0,0 1.370163,-0.28348 1.700892,1.13393 0.330729,1.41741 -1.748139,2.92931 -1.559153,4.86644 0.18899,1.93713 0.944941,3.68527 0.803201,5.00818 -0.141742,1.32292 -1.228423,2.4096 -0.897694,4.15774 0.330729,1.74814 1.370163,3.73252 1.748139,4.96094 0.377979,1.22842 0.472472,2.22061 0.472472,2.22061 l -5.575149,-3.35454 c 0,0 -4.771948,-4.77195 -2.787573,-10.91406 1.984375,-6.14211 6.094865,-8.07924 6.094865,-8.07924 z"
|
||||||
id="path4695" />
|
style="fill:#ffd7d7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#feb6b9;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4697"
|
||||||
d="m 70.30357,122.75298 c -1.514956,0.94925 -3.443343,1.9309 -5.197172,1.98437 l 0.07087,-2.10249 c 1.584545,0.45556 3.723038,0.23999 5.126302,0.11812 z"
|
d="m 70.30357,122.75298 c -1.514956,0.94925 -3.443343,1.9309 -5.197172,1.98437 l 0.07087,-2.10249 c 1.584545,0.45556 3.723038,0.23999 5.126302,0.11812 z"
|
||||||
id="path4697" />
|
style="fill:#feb6b9;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4699"
|
||||||
d="m 78.146576,107.06696 c 1.636436,10.62428 -0.93564,16.56205 -12.449591,21.04855 l -0.590587,-3.37816 c 7.160654,-1.083 13.649769,-7.8735 13.040178,-17.67039 z"
|
d="m 78.146576,107.06696 c 1.636436,10.62428 -0.93564,16.56205 -12.449591,21.04855 l -0.590587,-3.37816 c 7.160654,-1.083 13.649769,-7.8735 13.040178,-17.67039 z"
|
||||||
id="path4699" />
|
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#feb6b7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4701"
|
||||||
d="m 81.637986,123.01159 c -12.670965,0.95958 -14.152431,12.42398 -10.076572,21.37751 7.724779,4.9815 14.580842,3.99696 17.238885,3.0736 0,0 -9.888972,-5.07812 -9.354434,-11.55941 0.53454,-6.48129 3.741774,-10.89123 3.741774,-10.89123 0.428014,-1.07406 -0.282581,-1.80534 -1.549653,-2.00047 z"
|
d="m 81.637986,123.01159 c -12.670965,0.95958 -14.152431,12.42398 -10.076572,21.37751 7.724779,4.9815 14.580842,3.99696 17.238885,3.0736 0,0 -9.888972,-5.07812 -9.354434,-11.55941 0.53454,-6.48129 3.741774,-10.89123 3.741774,-10.89123 0.428014,-1.07406 -0.282581,-1.80534 -1.549653,-2.00047 z"
|
||||||
id="path4701" />
|
style="fill:#feb6b7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#ffd7d7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4703"
|
||||||
d="m 79.448737,123.30205 c 0.992925,-0.19905 1.78017,0.29602 1.107439,1.0337 0,0 -1.819011,0.56696 -2.031622,2.52772 -0.212614,1.96075 0.354351,2.36235 0,3.47265 -0.354354,1.11031 -2.362353,3.85063 -2.315104,5.14993 0.04725,1.29929 2.244233,3.56715 2.433219,4.70108 0.18899,1.13393 -0.377975,2.81119 0.566965,4.11049 0.944941,1.29929 2.14974,3.73251 2.14974,3.73251 -4.734539,-0.4794 -8.074618,-2.55807 -9.79796,-3.64103 -1.841663,-3.17287 -5.803388,-17.66538 7.887323,-21.08705 z"
|
d="m 79.448737,123.30205 c 0.992925,-0.19905 1.78017,0.29602 1.107439,1.0337 0,0 -1.819011,0.56696 -2.031622,2.52772 -0.212614,1.96075 0.354351,2.36235 0,3.47265 -0.354354,1.11031 -2.362353,3.85063 -2.315104,5.14993 0.04725,1.29929 2.244233,3.56715 2.433219,4.70108 0.18899,1.13393 -0.377975,2.81119 0.566965,4.11049 0.944941,1.29929 2.14974,3.73251 2.14974,3.73251 -4.734539,-0.4794 -8.074618,-2.55807 -9.79796,-3.64103 -1.841663,-3.17287 -5.803388,-17.66538 7.887323,-21.08705 z"
|
||||||
id="path4703" />
|
style="fill:#ffd7d7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4705"
|
||||||
d="m 96.150212,124.61115 c -4.01876,5.52151 -8.794257,9.92116 -16.711757,11.36671 -0.08036,0.88765 0.137909,1.87224 0.41237,2.79858 11.745993,-2.60459 14.877081,-9.93974 16.299387,-14.16529 z"
|
d="m 96.150212,124.61115 c -4.01876,5.52151 -8.794257,9.92116 -16.711757,11.36671 -0.08036,0.88765 0.137909,1.87224 0.41237,2.79858 11.745993,-2.60459 14.877081,-9.93974 16.299387,-14.16529 z"
|
||||||
id="path4705" />
|
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#eea6a7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4707"
|
||||||
d="m 86.603794,146.14025 2.196505,1.32245 c 6.701159,-2.41232 11.511951,-7.21119 15.190401,-13.27595 1.66173,6.03294 8.2499,13.42904 14.22135,13.46541 l 1.87506,-1.76484 c 0,0 0.0148,0.77265 -2.15854,-0.59751 -2.17336,-1.37017 -0.75595,-2.74033 -2.17336,-2.83483 -1.41741,-0.0945 -1.9286,0.12534 -4.20499,-0.7087 -1.44801,-0.53053 -0.75609,-4.10885 -1.74814,-5.05543 -0.99131,-0.94586 -2.3151,-0.56697 -2.92931,-2.5041 -0.61422,-1.93712 0.33073,-2.64583 -0.56697,-3.96875 -0.89178,-1.83082 -2.3092,-2.24423 -2.3092,-2.24423 -0.1266,-0.0643 -1.51607,0.38315 -2.36825,1.96075 -0.37793,0.96857 -0.8032,4.48847 -1.748143,4.77195 -0.944941,0.28348 -1.700892,0.28348 -2.69308,2.03162 -0.992187,1.74814 -0.944941,3.77976 -2.173364,4.25224 -1.228421,0.47247 -2.83482,0.33073 -3.638021,1.46465 -0.803198,1.13393 -4.771948,3.68527 -4.771948,3.68527 z"
|
d="m 86.603794,146.14025 2.196505,1.32245 c 6.701159,-2.41232 11.511951,-7.21119 15.190401,-13.27595 1.66173,6.03294 8.2499,13.42904 14.22135,13.46541 l 1.87506,-1.76484 c 0,0 0.0148,0.77265 -2.15854,-0.59751 -2.17336,-1.37017 -0.75595,-2.74033 -2.17336,-2.83483 -1.41741,-0.0945 -1.9286,0.12534 -4.20499,-0.7087 -1.44801,-0.53053 -0.75609,-4.10885 -1.74814,-5.05543 -0.99131,-0.94586 -2.3151,-0.56697 -2.92931,-2.5041 -0.61422,-1.93712 0.33073,-2.64583 -0.56697,-3.96875 -0.89178,-1.83082 -2.3092,-2.24423 -2.3092,-2.24423 -0.1266,-0.0643 -1.51607,0.38315 -2.36825,1.96075 -0.37793,0.96857 -0.8032,4.48847 -1.748143,4.77195 -0.944941,0.28348 -1.700892,0.28348 -2.69308,2.03162 -0.992187,1.74814 -0.944941,3.77976 -2.173364,4.25224 -1.228421,0.47247 -2.83482,0.33073 -3.638021,1.46465 -0.803198,1.13393 -4.771948,3.68527 -4.771948,3.68527 z"
|
||||||
id="path4707" />
|
style="fill:#eea6a7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#feb6b7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4709"
|
||||||
d="m 123.59821,125.20982 c -1.3987,-1.65054 -0.85807,-3.15445 2.88207,-2.78757 12.13782,1.66374 11.02212,16.63634 10.25261,17.85937 -2.85371,8.22299 -13.58843,8.19381 -18.52084,7.37054 0.96034,-1.98472 15.90292,-9.54748 5.38616,-22.44234 z"
|
d="m 123.59821,125.20982 c -1.3987,-1.65054 -0.85807,-3.15445 2.88207,-2.78757 12.13782,1.66374 11.02212,16.63634 10.25261,17.85937 -2.85371,8.22299 -13.58843,8.19381 -18.52084,7.37054 0.96034,-1.98472 15.90292,-9.54748 5.38616,-22.44234 z"
|
||||||
id="path4709" />
|
style="fill:#feb6b7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#ffd7d7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4711"
|
||||||
d="m 127.42522,122.75298 c 0,0 -1.93712,-0.23624 -1.65364,1.13392 0.28348,1.37017 2.3151,1.46466 2.26785,2.69308 -0.0472,1.22843 -0.51971,4.06325 0.33073,4.63021 0.85045,0.56697 2.55134,2.97656 1.55915,5.71689 -0.99218,2.74033 -1.98437,1.08668 -2.40959,3.54353 -0.42523,2.45684 -0.75596,3.77976 -1.46466,4.53571 -0.70871,0.75595 -1.22842,2.88207 -1.22842,2.88207 0,0 6.75631,0.37798 8.97693,-3.30729 9.56355,-9.24479 -1.05337,-21.95234 -6.37835,-21.82812 z"
|
d="m 127.42522,122.75298 c 0,0 -1.93712,-0.23624 -1.65364,1.13392 0.28348,1.37017 2.3151,1.46466 2.26785,2.69308 -0.0472,1.22843 -0.51971,4.06325 0.33073,4.63021 0.85045,0.56697 2.55134,2.97656 1.55915,5.71689 -0.99218,2.74033 -1.98437,1.08668 -2.40959,3.54353 -0.42523,2.45684 -0.75596,3.77976 -1.46466,4.53571 -0.70871,0.75595 -1.22842,2.88207 -1.22842,2.88207 0,0 6.75631,0.37798 8.97693,-3.30729 9.56355,-9.24479 -1.05337,-21.95234 -6.37835,-21.82812 z"
|
||||||
id="path4711" />
|
style="fill:#ffd7d7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4713"
|
||||||
d="m 115.7277,126.3484 c 2.71026,4.74824 6.41201,7.84401 11.526,8.58604 0.0146,0.75716 -0.10568,1.5973 -0.4009,2.22168 -5.69579,-1.24493 -9.34848,-5.1092 -11.1251,-10.80772 z"
|
d="m 115.7277,126.3484 c 2.71026,4.74824 6.41201,7.84401 11.526,8.58604 0.0146,0.75716 -0.10568,1.5973 -0.4009,2.22168 -5.69579,-1.24493 -9.34848,-5.1092 -11.1251,-10.80772 z"
|
||||||
id="path4713" />
|
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#feb6b7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4715"
|
||||||
d="m 143.05601,138.17508 c 8.45644,-12.2696 1.58622,-19.08645 -2.40542,-26.9274 -1.17246,-1.73452 0.56242,-1.73337 1.26953,-1.5368 4.83863,1.10659 18.77671,5.73353 11.35895,22.98518 -3.1826,2.72671 -6.38288,4.87014 -10.22306,5.47902 z"
|
d="m 143.05601,138.17508 c 8.45644,-12.2696 1.58622,-19.08645 -2.40542,-26.9274 -1.17246,-1.73452 0.56242,-1.73337 1.26953,-1.5368 4.83863,1.10659 18.77671,5.73353 11.35895,22.98518 -3.1826,2.72671 -6.38288,4.87014 -10.22306,5.47902 z"
|
||||||
id="path4715" />
|
style="fill:#feb6b7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#ffd7d7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4717"
|
||||||
d="m 145.33184,110.65773 c -1.44409,-0.17245 -1.87623,0.88971 -1.74814,1.55916 0.12809,0.66945 1.37019,0.51971 1.41742,2.07887 0.0472,1.55916 1.74813,4.91369 2.03162,5.57515 0.28348,0.66145 1.88988,1.65364 2.07887,4.06324 0.18898,2.4096 -0.36512,6.46405 -0.99219,7.46503 -0.73995,1.18117 -0.10965,4.58296 0.33073,4.58296 1.94348,-0.70588 3.22695,-2.18177 4.82892,-3.28608 3.76978,-8.80185 3.25139,-17.5402 -7.94723,-22.03833 z"
|
d="m 145.33184,110.65773 c -1.44409,-0.17245 -1.87623,0.88971 -1.74814,1.55916 0.12809,0.66945 1.37019,0.51971 1.41742,2.07887 0.0472,1.55916 1.74813,4.91369 2.03162,5.57515 0.28348,0.66145 1.88988,1.65364 2.07887,4.06324 0.18898,2.4096 -0.36512,6.46405 -0.99219,7.46503 -0.73995,1.18117 -0.10965,4.58296 0.33073,4.58296 1.94348,-0.70588 3.22695,-2.18177 4.82892,-3.28608 3.76978,-8.80185 3.25139,-17.5402 -7.94723,-22.03833 z"
|
||||||
id="path4717" />
|
style="fill:#ffd7d7;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#feb6b9;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4719"
|
||||||
d="m 145.66189,120.68563 c 0.50608,1.04701 0.81356,2.13795 1.05237,3.27405 0,0 -1.26953,0.21716 -3.54132,0.15034 -2.27179,-0.0668 -5.028,-1.1526 -5.028,-1.1526 0,0 2.12145,0.33409 4.07585,-0.3842 1.95441,-0.71829 3.4411,-1.88759 3.4411,-1.88759 z"
|
d="m 145.66189,120.68563 c 0.50608,1.04701 0.81356,2.13795 1.05237,3.27405 0,0 -1.26953,0.21716 -3.54132,0.15034 -2.27179,-0.0668 -5.028,-1.1526 -5.028,-1.1526 0,0 2.12145,0.33409 4.07585,-0.3842 1.95441,-0.71829 3.4411,-1.88759 3.4411,-1.88759 z"
|
||||||
id="path4719" />
|
style="fill:#feb6b9;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4721"
|
||||||
d="m 131.34627,111.26438 c -0.46387,6.60804 -0.23431,15.14869 15.71879,15.3513 l -0.3508,-2.656 c -5.36818,0.47928 -14.93993,-0.59196 -15.36799,-12.6953 z"
|
d="m 131.34627,111.26438 c -0.46387,6.60804 -0.23431,15.14869 15.71879,15.3513 l -0.3508,-2.656 c -5.36818,0.47928 -14.93993,-0.59196 -15.36799,-12.6953 z"
|
||||||
id="path4721" />
|
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<g
|
<g
|
||||||
id="g4740"
|
transform="rotate(19.617168,87.590538,52.720911)"
|
||||||
transform="rotate(19.617168,87.590538,52.720911)">
|
id="g4740">
|
||||||
<path
|
<path
|
||||||
id="path4725"
|
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.39299998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
d="m 108.72438,96.054369 c -1.67459,2.099573 -6.51237,1.558255 -9.762082,-0.889359 -3.249707,-2.447614 -5.286913,-7.54075 -1.925906,-10.583607 2.406544,-2.178749 7.101418,-0.79705 9.431368,1.36184 2.53306,2.34709 4.6065,7.164892 2.25662,10.111126 z"
|
||||||
|
id="path4725" />
|
||||||
|
<path
|
||||||
|
id="path4730"
|
||||||
|
d="m 108.84598,96.203312 c -1.50822,1.890992 -5.8654,1.403451 -8.79227,-0.801006 -2.926867,-2.204458 -4.761688,-6.79162 -1.734578,-9.532187 2.167468,-1.962302 6.395928,-0.717867 8.494418,1.226549 2.28141,2.11392 4.14887,6.453101 2.03243,9.106644 z"
|
||||||
|
style="opacity:1;fill:#f0f0f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35395768;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.46482563;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="path4732"
|
||||||
|
cx="101.24133"
|
||||||
|
cy="91.80127"
|
||||||
|
r="3.4367433" />
|
||||||
|
<circle
|
||||||
|
r="1.0470117"
|
||||||
|
cy="91.470535"
|
||||||
|
cx="100.24915"
|
||||||
|
id="circle4734"
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:0.94117647;fill-rule:nonzero;stroke:none;stroke-width:0.14161019;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
|
<circle
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:0.94117647;fill-rule:nonzero;stroke:none;stroke-width:0.14161019;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
|
id="circle4657"
|
||||||
|
cx="102.3987"
|
||||||
|
cy="93.070198"
|
||||||
|
r="0.6970861" />
|
||||||
|
</g>
|
||||||
|
<g
|
||||||
|
id="g4750"
|
||||||
|
transform="matrix(-0.84292907,0.5380247,0.5380247,0.84292907,153.98869,-37.720137)">
|
||||||
|
<path
|
||||||
|
id="path4742"
|
||||||
d="m 108.72438,96.054369 c -1.67459,2.099573 -6.51237,1.558255 -9.762082,-0.889359 -3.249707,-2.447614 -5.286913,-7.54075 -1.925906,-10.583607 2.406544,-2.178749 7.101418,-0.79705 9.431368,1.36184 2.53306,2.34709 4.6065,7.164892 2.25662,10.111126 z"
|
d="m 108.72438,96.054369 c -1.67459,2.099573 -6.51237,1.558255 -9.762082,-0.889359 -3.249707,-2.447614 -5.286913,-7.54075 -1.925906,-10.583607 2.406544,-2.178749 7.101418,-0.79705 9.431368,1.36184 2.53306,2.34709 4.6065,7.164892 2.25662,10.111126 z"
|
||||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.39299998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.39299998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
<path
|
<path
|
||||||
style="opacity:1;fill:#f0f0f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35395768;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
style="opacity:1;fill:#f0f0f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35395768;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
d="m 108.84598,96.203312 c -1.50822,1.890992 -5.8654,1.403451 -8.79227,-0.801006 -2.926867,-2.204458 -4.761688,-6.79162 -1.734578,-9.532187 2.167468,-1.962302 6.395928,-0.717867 8.494418,1.226549 2.28141,2.11392 4.14887,6.453101 2.03243,9.106644 z"
|
d="m 108.84598,96.203312 c -1.50822,1.890992 -5.8654,1.403451 -8.79227,-0.801006 -2.926867,-2.204458 -4.761688,-6.79162 -1.734578,-9.532187 2.167468,-1.962302 6.395928,-0.717867 8.494418,1.226549 2.28141,2.11392 4.14887,6.453101 2.03243,9.106644 z"
|
||||||
id="path4730" />
|
id="path4744" />
|
||||||
<circle
|
<circle
|
||||||
r="3.4367433"
|
r="3.4367433"
|
||||||
cy="91.80127"
|
cy="90.845963"
|
||||||
cx="101.24133"
|
cx="105.85611"
|
||||||
id="path4732"
|
id="circle4746"
|
||||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.46482563;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.46482563;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
<circle
|
<circle
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:0.94117647;fill-rule:nonzero;stroke:none;stroke-width:0.14161019;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
style="opacity:1;fill:#ffffff;fill-opacity:0.94117647;fill-rule:nonzero;stroke:none;stroke-width:0.14161019;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
||||||
id="circle4734"
|
id="circle4748"
|
||||||
cx="100.24915"
|
cx="106.96864"
|
||||||
cy="91.470535"
|
cy="89.537895"
|
||||||
r="1.0470117" />
|
r="1.0470117" />
|
||||||
<circle
|
<circle
|
||||||
r="0.6970861"
|
r="0.59710735"
|
||||||
cy="93.070198"
|
|
||||||
cx="102.3987"
|
|
||||||
id="circle4657"
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:0.94117647;fill-rule:nonzero;stroke:none;stroke-width:0.14161019;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
|
||||||
</g>
|
|
||||||
<g
|
|
||||||
transform="matrix(-0.84292907,0.5380247,0.5380247,0.84292907,153.98869,-37.720137)"
|
|
||||||
id="g4750">
|
|
||||||
<path
|
|
||||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:#000000;stroke-width:0.39299998;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
|
||||||
d="m 108.72438,96.054369 c -1.67459,2.099573 -6.51237,1.558255 -9.762082,-0.889359 -3.249707,-2.447614 -5.286913,-7.54075 -1.925906,-10.583607 2.406544,-2.178749 7.101418,-0.79705 9.431368,1.36184 2.53306,2.34709 4.6065,7.164892 2.25662,10.111126 z"
|
|
||||||
id="path4742" />
|
|
||||||
<path
|
|
||||||
id="path4744"
|
|
||||||
d="m 108.84598,96.203312 c -1.50822,1.890992 -5.8654,1.403451 -8.79227,-0.801006 -2.926867,-2.204458 -4.761688,-6.79162 -1.734578,-9.532187 2.167468,-1.962302 6.395928,-0.717867 8.494418,1.226549 2.28141,2.11392 4.14887,6.453101 2.03243,9.106644 z"
|
|
||||||
style="opacity:1;fill:#f0f0f0;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.35395768;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
|
||||||
<circle
|
|
||||||
style="opacity:1;fill:#000000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:0.46482563;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
|
||||||
id="circle4746"
|
|
||||||
cx="105.85611"
|
|
||||||
cy="90.845963"
|
|
||||||
r="3.4367433" />
|
|
||||||
<circle
|
|
||||||
r="1.0470117"
|
|
||||||
cy="89.537895"
|
|
||||||
cx="106.96864"
|
|
||||||
id="circle4748"
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:0.94117647;fill-rule:nonzero;stroke:none;stroke-width:0.14161019;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
|
||||||
<circle
|
|
||||||
style="opacity:1;fill:#ffffff;fill-opacity:0.94117647;fill-rule:nonzero;stroke:none;stroke-width:0.14161019;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke"
|
|
||||||
id="circle4655"
|
|
||||||
cx="105.70718"
|
|
||||||
cy="92.300102"
|
cy="92.300102"
|
||||||
r="0.59710735" />
|
cx="105.70718"
|
||||||
|
id="circle4655"
|
||||||
|
style="opacity:1;fill:#ffffff;fill-opacity:0.94117647;fill-rule:nonzero;stroke:none;stroke-width:0.14161019;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1;paint-order:fill markers stroke" />
|
||||||
</g>
|
</g>
|
||||||
<path
|
<path
|
||||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4752"
|
||||||
d="m 79.440842,83.663452 c 2.401026,-4.843277 7.683432,-2.978854 9.070822,-3.016481 -2.556226,0.763727 -4.708947,2.955988 -6.701589,4.398539 -0.740592,0.536143 -2.442986,-0.394305 -2.369233,-1.382058 z"
|
d="m 79.440842,83.663452 c 2.401026,-4.843277 7.683432,-2.978854 9.070822,-3.016481 -2.556226,0.763727 -4.708947,2.955988 -6.701589,4.398539 -0.740592,0.536143 -2.442986,-0.394305 -2.369233,-1.382058 z"
|
||||||
id="path4752" />
|
|
||||||
<path
|
|
||||||
id="path4754"
|
|
||||||
d="m 125.44005,85.24075 c -2.30199,-5.105822 -7.76722,-3.941999 -8.60332,-4.166742 2.43567,1.088609 4.28608,3.541392 6.07494,5.23005 0.66486,0.627613 2.47348,-0.07434 2.52838,-1.063308 z"
|
|
||||||
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
style="fill:#000000;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
||||||
|
d="m 125.44005,85.24075 c -2.30199,-5.105822 -7.76722,-3.941999 -8.60332,-4.166742 2.43567,1.088609 4.28608,3.541392 6.07494,5.23005 0.66486,0.627613 2.47348,-0.07434 2.52838,-1.063308 z"
|
||||||
|
id="path4754" />
|
||||||
|
<path
|
||||||
|
id="path4756"
|
||||||
d="m 70.96503,82.262275 c 0,0 6.331101,3.071056 7.606771,-0.519718 1.275667,-3.590772 -1.27567,-7.9375 -1.27567,-7.9375 2.892685,-1.049875 3.091067,-3.4469 2.220608,-6.378347 2.152776,-0.348696 4.444174,-0.539426 1.322917,-6.898066 -4.769498,4.415313 -9.420477,9.057506 -9.874626,21.733631 z"
|
d="m 70.96503,82.262275 c 0,0 6.331101,3.071056 7.606771,-0.519718 1.275667,-3.590772 -1.27567,-7.9375 -1.27567,-7.9375 2.892685,-1.049875 3.091067,-3.4469 2.220608,-6.378347 2.152776,-0.348696 4.444174,-0.539426 1.322917,-6.898066 -4.769498,4.415313 -9.420477,9.057506 -9.874626,21.733631 z"
|
||||||
id="path4756" />
|
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4758"
|
||||||
d="m 88.132125,56.156746 c 0,0 3.254408,16.386084 14.566195,13.79779 7.88444,-1.80407 6.28083,-7.617182 6.28083,-7.617182 3.56518,5.081814 12.40153,4.310975 11.29214,-2.539061 2.41655,0.835207 3.97125,0.06982 5.14493,-1.403165 -13.2372,-7.82638 -25.466402,-6.83272 -37.284095,-2.238382 z"
|
d="m 88.132125,56.156746 c 0,0 3.254408,16.386084 14.566195,13.79779 7.88444,-1.80407 6.28083,-7.617182 6.28083,-7.617182 3.56518,5.081814 12.40153,4.310975 11.29214,-2.539061 2.41655,0.835207 3.97125,0.06982 5.14493,-1.403165 -13.2372,-7.82638 -25.466402,-6.83272 -37.284095,-2.238382 z"
|
||||||
id="path4758" />
|
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4760"
|
||||||
d="m 131.36297,62.871892 c -1.12784,1.399585 -4.16412,7.545045 2.00452,7.650591 -0.56702,5.505473 1.00425,9.251589 7.45014,8.986938 -1.43088,-7.033989 -4.7288,-12.453251 -9.45466,-16.637529 z"
|
d="m 131.36297,62.871892 c -1.12784,1.399585 -4.16412,7.545045 2.00452,7.650591 -0.56702,5.505473 1.00425,9.251589 7.45014,8.986938 -1.43088,-7.033989 -4.7288,-12.453251 -9.45466,-16.637529 z"
|
||||||
id="path4760" />
|
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4762"
|
||||||
d="m 140.95127,86.391611 c -1.79338,-0.414357 -3.99759,-0.910879 -6.68174,-1.503391 -2.67445,-0.05943 -3.63783,1.364072 -2.3052,4.777443 2.82115,3.939599 4.73867,3.511676 7.08264,5.144937 0.70035,-2.780098 1.61025,-5.476371 1.9043,-8.418989 z"
|
d="m 140.95127,86.391611 c -1.79338,-0.414357 -3.99759,-0.910879 -6.68174,-1.503391 -2.67445,-0.05943 -3.63783,1.364072 -2.3052,4.777443 2.82115,3.939599 4.73867,3.511676 7.08264,5.144937 0.70035,-2.780098 1.61025,-5.476371 1.9043,-8.418989 z"
|
||||||
id="path4762" />
|
style="fill:#dd6258;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#7f2625;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
|
id="path4764"
|
||||||
d="m 93.342168,119.42814 c 0.529236,-0.73806 0.604365,-0.3573 1.136405,-1.09204 0.364677,-0.50361 0.199924,-1.06153 0.644573,-1.46533 0.309321,-0.28091 0.977351,-0.124 1.362201,-0.31657 0.345479,-0.17287 0.405453,-0.70096 0.732931,-0.84737 0.789296,-0.35288 1.800707,0.26944 2.651021,0.0936 1.078571,-0.22307 2.076941,-1.09961 3.190181,-1.10946 0.97926,-0.009 1.7824,0.64931 2.75826,0.86661 0.76717,0.17085 1.97838,-0.33367 2.73467,-0.0767 0.43365,0.14737 1.07369,-0.0937 1.4783,0.11451 0.30157,0.15517 0.33276,0.75525 0.61169,0.95375 1.72336,1.22644 1.31075,0.33606 2.60238,2.06475 0,0 0.28975,-0.0348 -2.07105,-2.47226 -0.32347,-0.33398 -0.51448,-1.08044 -0.86627,-1.38846 -0.45582,-0.39911 -1.04178,-0.39938 -1.53149,-0.74298 -0.6807,-0.4776 -1.9258,0.26924 -2.60859,-0.0841 -1.25954,-0.65171 -2.00993,-2.31042 -3.18147,-2.02677 -1.01838,0.24657 -2.19748,1.18524 -3.446552,1.56394 -0.794617,0.24091 -1.705404,-0.22114 -2.337848,0.30385 -0.769592,0.63883 -0.5723,0.83835 -1.171115,1.59816 -0.306698,0.38915 -0.985411,0.37691 -1.287999,0.78707 -0.398797,0.54057 -0.388125,1.15748 -0.697902,1.70652 -0.81359,1.44197 -0.702326,1.56918 -0.702326,1.56918 z"
|
d="m 93.342168,119.42814 c 0.529236,-0.73806 0.604365,-0.3573 1.136405,-1.09204 0.364677,-0.50361 0.199924,-1.06153 0.644573,-1.46533 0.309321,-0.28091 0.977351,-0.124 1.362201,-0.31657 0.345479,-0.17287 0.405453,-0.70096 0.732931,-0.84737 0.789296,-0.35288 1.800707,0.26944 2.651021,0.0936 1.078571,-0.22307 2.076941,-1.09961 3.190181,-1.10946 0.97926,-0.009 1.7824,0.64931 2.75826,0.86661 0.76717,0.17085 1.97838,-0.33367 2.73467,-0.0767 0.43365,0.14737 1.07369,-0.0937 1.4783,0.11451 0.30157,0.15517 0.33276,0.75525 0.61169,0.95375 1.72336,1.22644 1.31075,0.33606 2.60238,2.06475 0,0 0.28975,-0.0348 -2.07105,-2.47226 -0.32347,-0.33398 -0.51448,-1.08044 -0.86627,-1.38846 -0.45582,-0.39911 -1.04178,-0.39938 -1.53149,-0.74298 -0.6807,-0.4776 -1.9258,0.26924 -2.60859,-0.0841 -1.25954,-0.65171 -2.00993,-2.31042 -3.18147,-2.02677 -1.01838,0.24657 -2.19748,1.18524 -3.446552,1.56394 -0.794617,0.24091 -1.705404,-0.22114 -2.337848,0.30385 -0.769592,0.63883 -0.5723,0.83835 -1.171115,1.59816 -0.306698,0.38915 -0.985411,0.37691 -1.287999,0.78707 -0.398797,0.54057 -0.388125,1.15748 -0.697902,1.70652 -0.81359,1.44197 -0.702326,1.56918 -0.702326,1.56918 z"
|
||||||
id="path4764" />
|
style="fill:#7f2625;fill-opacity:1;stroke:none;stroke-width:0.26458332px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:none;stroke:#301818;stroke-width:4.46500015;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
id="path4847"
|
||||||
d="m 66.416477,77.838987 c 0,0 2.248303,-29.702875 39.355443,-29.132379 37.10713,0.570497 40.69178,29.399648 40.69178,29.399648"
|
d="m 66.416477,77.838987 c 0,0 2.248303,-29.702875 39.355443,-29.132379 37.10713,0.570497 40.69178,29.399648 40.69178,29.399648"
|
||||||
id="path4847" />
|
style="fill:none;stroke:#301818;stroke-width:4.46500015;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||||
<path
|
|
||||||
id="path4651"
|
|
||||||
d="m 82.283169,89.859621 c 1.901054,-0.826347 5.017206,-1.87303 7.190809,-1.209662 2.299291,0.701728 3.661648,3.157157 5.855653,3.784919 0,0 -0.675634,-7.540694 -7.907825,-7.911193 -3.749793,-0.192098 -5.138637,5.335936 -5.138637,5.335936 z"
|
|
||||||
style="opacity:1;vector-effect:none;fill:#7f2625;fill-opacity:1;stroke:none;stroke-width:1.48535442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
|
||||||
<path
|
<path
|
||||||
style="opacity:1;vector-effect:none;fill:#7f2625;fill-opacity:1;stroke:none;stroke-width:1.48535442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
style="opacity:1;vector-effect:none;fill:#7f2625;fill-opacity:1;stroke:none;stroke-width:1.48535442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
|
d="m 82.283169,89.859621 c 1.901054,-0.826347 5.017206,-1.87303 7.190809,-1.209662 2.299291,0.701728 3.661648,3.157157 5.855653,3.784919 0,0 -0.675634,-7.540694 -7.907825,-7.911193 -3.749793,-0.192098 -5.138637,5.335936 -5.138637,5.335936 z"
|
||||||
|
id="path4651" />
|
||||||
|
<path
|
||||||
|
id="path4653"
|
||||||
d="m 122.49651,94.411543 c -3.78678,-6.81696 -8.0759,-7.480996 -11.84594,-3.933836 0,0 3.20445,-7.27537 10.03419,-4.867774 4.12152,1.452904 1.81175,8.80161 1.81175,8.80161 z"
|
d="m 122.49651,94.411543 c -3.78678,-6.81696 -8.0759,-7.480996 -11.84594,-3.933836 0,0 3.20445,-7.27537 10.03419,-4.867774 4.12152,1.452904 1.81175,8.80161 1.81175,8.80161 z"
|
||||||
id="path4653" />
|
style="opacity:1;vector-effect:none;fill:#7f2625;fill-opacity:1;stroke:none;stroke-width:1.48535442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
<g
|
<g
|
||||||
style="stroke-width:42.36951447"
|
transform="matrix(0.02360188,0,0,0.02360188,113.18825,105.15104)"
|
||||||
id="g6"
|
id="g6"
|
||||||
transform="matrix(0.02360188,0,0,0.02360188,113.18825,105.15104)">
|
style="stroke-width:42.36951447">
|
||||||
<path
|
<path
|
||||||
id="path2"
|
style="fill:#29abe2;stroke-width:42.36951447"
|
||||||
d="m 117.16,11.645 c 0,0 -31.496,38.028 -68.31,85.296 -47.195,60.599 -70.131,146.52 31.843,165.81 113.27,21.429 132.5,-118.17 65.274,-157.01 -49.223,-28.424 -28.81,-94.097 -28.81,-94.095 z"
|
d="m 117.16,11.645 c 0,0 -31.496,38.028 -68.31,85.296 -47.195,60.599 -70.131,146.52 31.843,165.81 113.27,21.429 132.5,-118.17 65.274,-157.01 -49.223,-28.424 -28.81,-94.097 -28.81,-94.095 z"
|
||||||
style="fill:#29abe2;stroke-width:42.36951447" />
|
id="path2" />
|
||||||
<path
|
<path
|
||||||
id="path4-9"
|
style="fill:#ffffff;stroke-width:42.36951447"
|
||||||
d="m 51.844,134.31 c 0,0 -56.287,70.6 25.797,108.12 0,0.01 -44.304,-31.59 -25.797,-108.12 z"
|
d="m 51.844,134.31 c 0,0 -56.287,70.6 25.797,108.12 0,0.01 -44.304,-31.59 -25.797,-108.12 z"
|
||||||
style="fill:#ffffff;stroke-width:42.36951447" />
|
id="path4-9" />
|
||||||
</g>
|
</g>
|
||||||
<g
|
<g
|
||||||
transform="matrix(-0.0125514,0,0,0.0125514,96.697579,101.08859)"
|
style="stroke-width:79.67237854"
|
||||||
id="g4688"
|
id="g4688"
|
||||||
style="stroke-width:79.67237854">
|
transform="matrix(-0.0125514,0,0,0.0125514,96.697579,101.08859)">
|
||||||
<path
|
<path
|
||||||
style="fill:#29abe2;stroke-width:79.67237854"
|
id="path4684"
|
||||||
d="m 117.16,11.645 c 0,0 -31.496,38.028 -68.31,85.296 -47.195,60.599 -70.131,146.52 31.843,165.81 113.27,21.429 132.5,-118.17 65.274,-157.01 -49.223,-28.424 -28.81,-94.097 -28.81,-94.095 z"
|
d="m 117.16,11.645 c 0,0 -31.496,38.028 -68.31,85.296 -47.195,60.599 -70.131,146.52 31.843,165.81 113.27,21.429 132.5,-118.17 65.274,-157.01 -49.223,-28.424 -28.81,-94.097 -28.81,-94.095 z"
|
||||||
id="path4684" />
|
style="fill:#29abe2;stroke-width:79.67237854" />
|
||||||
<path
|
<path
|
||||||
style="fill:#ffffff;stroke-width:79.67237854"
|
id="path4686"
|
||||||
d="m 51.844,134.31 c 0,0 -56.287,70.6 25.797,108.12 0,0.01 -44.304,-31.59 -25.797,-108.12 z"
|
d="m 51.844,134.31 c 0,0 -56.287,70.6 25.797,108.12 0,0.01 -44.304,-31.59 -25.797,-108.12 z"
|
||||||
id="path4686" />
|
style="fill:#ffffff;stroke-width:79.67237854" />
|
||||||
</g>
|
</g>
|
||||||
<path
|
<path
|
||||||
id="path4692"
|
style="opacity:1;vector-effect:none;fill:#29abe2;fill-opacity:1;stroke:none;stroke-width:1.48535442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
||||||
d="m 85.947033,99.042108 0.671609,-0.0707 c 0,0 0.49487,-0.636261 0.777652,-0.353479 0.282783,0.282783 0.424174,0.777652 1.343218,0.565565 0.919043,-0.212086 0.353478,0.212087 1.343217,0.49487 0.989739,0.282783 0.777653,0 1.484609,-0.282783 0.706957,-0.282782 0.212087,-0.777652 1.060435,-0.565565 0.848348,0.212087 0.282782,0.212087 1.272521,-0.212087 0.989739,-0.424174 1.334642,-0.665544 1.334642,-0.665544 0,0 -0.5002,2.353665 -3.049011,3.334305 -4.895674,0.33581 -6.238892,-2.244587 -6.238892,-2.244587 z"
|
d="m 85.947033,99.042108 0.671609,-0.0707 c 0,0 0.49487,-0.636261 0.777652,-0.353479 0.282783,0.282783 0.424174,0.777652 1.343218,0.565565 0.919043,-0.212086 0.353478,0.212087 1.343217,0.49487 0.989739,0.282783 0.777653,0 1.484609,-0.282783 0.706957,-0.282782 0.212087,-0.777652 1.060435,-0.565565 0.848348,0.212087 0.282782,0.212087 1.272521,-0.212087 0.989739,-0.424174 1.334642,-0.665544 1.334642,-0.665544 0,0 -0.5002,2.353665 -3.049011,3.334305 -4.895674,0.33581 -6.238892,-2.244587 -6.238892,-2.244587 z"
|
||||||
|
id="path4692" />
|
||||||
|
<path
|
||||||
|
id="path4694"
|
||||||
|
d="m 90.215634,100.78237 c 0,0 0.47109,0.17648 1.084764,0.10067 0.31585,-0.039 0.649984,-0.31716 1.017863,-0.42775 0.326516,-0.0982 0.666764,-0.12133 0.976323,-0.31443 0.19834,-0.12373 0.30993,-0.330545 0.48732,-0.500317 0.276456,-0.264584 0.578906,-0.54704 0.757961,-0.950004 2.09e-4,-7.1e-5 -0.344817,0.269525 -1.022134,0.718841 -0.188018,0.124727 -0.295615,0.385643 -0.557188,0.510044 -0.286058,0.136046 -0.727267,0.150626 -1.096851,0.284556 -0.199876,0.0724 -0.248589,0.33662 -0.45906,0.42367 -0.308425,0.12756 -0.791836,0.0775 -1.188998,0.15472 z"
|
||||||
|
style="fill:#29ebe2;fill-opacity:1;stroke-width:1.00000024" />
|
||||||
|
<path
|
||||||
|
id="path4698"
|
||||||
|
d="m 119.99047,99.106433 -0.65394,0.265104 c 0,0 -0.42418,-0.459522 -0.70696,-0.17674 -0.28278,0.282783 -0.26511,0.848353 -1.18415,0.636261 -0.91904,-0.212086 -0.35348,0.212092 -1.34322,0.494872 -0.98974,0.28278 -0.77765,0 -1.48461,-0.28278 -0.70695,-0.282787 -0.21208,-0.777657 -1.06043,-0.56557 -0.84835,0.212087 -0.28278,0.212087 -1.27252,-0.212087 -0.98974,-0.424174 -1.51138,-0.479968 -1.51138,-0.479968 0,0 0.9067,2.486225 3.22575,3.148735 2.34542,0.68368 4.48756,-0.65364 5.92076,-2.54505 z"
|
||||||
style="opacity:1;vector-effect:none;fill:#29abe2;fill-opacity:1;stroke:none;stroke-width:1.48535442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
style="opacity:1;vector-effect:none;fill:#29abe2;fill-opacity:1;stroke:none;stroke-width:1.48535442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1" />
|
||||||
<path
|
<path
|
||||||
style="fill:#29ebe2;fill-opacity:1;stroke-width:1.00000024"
|
style="fill:#29ebe2;fill-opacity:1;stroke-width:1.00000024"
|
||||||
d="m 90.215634,100.78237 c 0,0 0.47109,0.17648 1.084764,0.10067 0.31585,-0.039 0.649984,-0.31716 1.017863,-0.42775 0.326516,-0.0982 0.666764,-0.12133 0.976323,-0.31443 0.19834,-0.12373 0.30993,-0.330545 0.48732,-0.500317 0.276456,-0.264584 0.578906,-0.54704 0.757961,-0.950004 2.09e-4,-7.1e-5 -0.344817,0.269525 -1.022134,0.718841 -0.188018,0.124727 -0.295615,0.385643 -0.557188,0.510044 -0.286058,0.136046 -0.727267,0.150626 -1.096851,0.284556 -0.199876,0.0724 -0.248589,0.33662 -0.45906,0.42367 -0.308425,0.12756 -0.791836,0.0775 -1.188998,0.15472 z"
|
|
||||||
id="path4694" />
|
|
||||||
<path
|
|
||||||
style="opacity:1;vector-effect:none;fill:#29abe2;fill-opacity:1;stroke:none;stroke-width:1.48535442;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
|
|
||||||
d="m 119.99047,99.106433 -0.65394,0.265104 c 0,0 -0.42418,-0.459522 -0.70696,-0.17674 -0.28278,0.282783 -0.26511,0.848353 -1.18415,0.636261 -0.91904,-0.212086 -0.35348,0.212092 -1.34322,0.494872 -0.98974,0.28278 -0.77765,0 -1.48461,-0.28278 -0.70695,-0.282787 -0.21208,-0.777657 -1.06043,-0.56557 -0.84835,0.212087 -0.28278,0.212087 -1.27252,-0.212087 -0.98974,-0.424174 -1.51138,-0.479968 -1.51138,-0.479968 0,0 0.9067,2.486225 3.22575,3.148735 2.34542,0.68368 4.48756,-0.65364 5.92076,-2.54505 z"
|
|
||||||
id="path4698" />
|
|
||||||
<path
|
|
||||||
id="path4700"
|
|
||||||
d="m 115.9693,101.42994 c 0,0 -0.47109,0.17648 -1.08477,0.10067 -0.31585,-0.039 -0.64998,-0.31716 -1.01786,-0.42775 -0.32651,-0.0982 -0.66676,-0.12133 -0.97632,-0.31443 -0.19834,-0.12373 -0.30993,-0.33055 -0.48732,-0.50032 -0.27646,-0.26458 -0.57891,-0.547043 -0.75796,-0.950007 -2.1e-4,-7.1e-5 0.34481,0.269525 1.02213,0.718847 0.18802,0.12472 0.29562,0.38564 0.55719,0.51004 0.28606,0.13605 0.72727,0.15063 1.09685,0.28456 0.19988,0.0724 0.24859,0.33662 0.45906,0.42367 0.30843,0.12756 0.79184,0.0775 1.189,0.15472 z"
|
d="m 115.9693,101.42994 c 0,0 -0.47109,0.17648 -1.08477,0.10067 -0.31585,-0.039 -0.64998,-0.31716 -1.01786,-0.42775 -0.32651,-0.0982 -0.66676,-0.12133 -0.97632,-0.31443 -0.19834,-0.12373 -0.30993,-0.33055 -0.48732,-0.50032 -0.27646,-0.26458 -0.57891,-0.547043 -0.75796,-0.950007 -2.1e-4,-7.1e-5 0.34481,0.269525 1.02213,0.718847 0.18802,0.12472 0.29562,0.38564 0.55719,0.51004 0.28606,0.13605 0.72727,0.15063 1.09685,0.28456 0.19988,0.0724 0.24859,0.33662 0.45906,0.42367 0.30843,0.12756 0.79184,0.0775 1.189,0.15472 z"
|
||||||
style="fill:#29ebe2;fill-opacity:1;stroke-width:1.00000024" />
|
id="path4700" />
|
||||||
</g>
|
</g>
|
||||||
</svg>
|
</svg>
|
||||||
|
|
Before Width: | Height: | Size: 32 KiB After Width: | Height: | Size: 32 KiB |
|
@ -105,7 +105,7 @@ function switchTheme(e) {
|
||||||
document.addEventListener('DOMContentLoaded', () => {
|
document.addEventListener('DOMContentLoaded', () => {
|
||||||
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
|
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
|
||||||
if ($navbarBurgers.length > 0) {
|
if ($navbarBurgers.length > 0) {
|
||||||
$navbarBurgers.forEach( el => {
|
$navbarBurgers.forEach( el => {
|
||||||
el.addEventListener('click', () => {
|
el.addEventListener('click', () => {
|
||||||
const target = el.dataset.target;
|
const target = el.dataset.target;
|
||||||
const $target = document.getElementById(target);
|
const $target = document.getElementById(target);
|
||||||
|
|
|
@ -23,6 +23,12 @@
|
||||||
background-color: var(--default-color);
|
background-color: var(--default-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
&:nth-child(4n),
|
||||||
|
&:nth-child(4n-1)
|
||||||
|
{
|
||||||
|
background-color: var(--default-color);
|
||||||
|
}
|
||||||
|
|
||||||
&:first-child,
|
&:first-child,
|
||||||
&:nth-child(2) {
|
&:nth-child(2) {
|
||||||
border-top: 2px solid var(--border-color);
|
border-top: 2px solid var(--border-color);
|
||||||
|
|
15
src/app.js
15
src/app.js
|
@ -7,6 +7,8 @@ import flash from "connect-flash";
|
||||||
import session from "express-session";
|
import session from "express-session";
|
||||||
import MongoStore from "connect-mongo";
|
import MongoStore from "connect-mongo";
|
||||||
|
|
||||||
|
import passportConfig from "./libs/passport";
|
||||||
|
|
||||||
import config, { env, mongoDbUri, secret } from "./config";
|
import config, { env, mongoDbUri, secret } from "./config";
|
||||||
|
|
||||||
import { isXhr } from "./helpers";
|
import { isXhr } from "./helpers";
|
||||||
|
@ -15,15 +17,13 @@ import indexRouter from "./routes";
|
||||||
import maCollectionRouter from "./routes/ma-collection";
|
import maCollectionRouter from "./routes/ma-collection";
|
||||||
import collectionRouter from "./routes/collection";
|
import collectionRouter from "./routes/collection";
|
||||||
|
|
||||||
|
import importJobsRouter from "./routes/jobs";
|
||||||
|
|
||||||
import importAlbumRouterApiV1 from "./routes/api/v1/albums";
|
import importAlbumRouterApiV1 from "./routes/api/v1/albums";
|
||||||
import importSearchRouterApiV1 from "./routes/api/v1/search";
|
import importSearchRouterApiV1 from "./routes/api/v1/search";
|
||||||
import importMeRouterApiV1 from "./routes/api/v1/me";
|
import importMeRouterApiV1 from "./routes/api/v1/me";
|
||||||
|
|
||||||
// Mongoose schema init
|
passportConfig(passport);
|
||||||
require("./models/users");
|
|
||||||
require("./models/albums");
|
|
||||||
|
|
||||||
require("./libs/passport")(passport);
|
|
||||||
|
|
||||||
mongoose
|
mongoose
|
||||||
.connect(mongoDbUri, { useNewUrlParser: true, useUnifiedTopology: true })
|
.connect(mongoDbUri, { useNewUrlParser: true, useUnifiedTopology: true })
|
||||||
|
@ -46,10 +46,10 @@ const sess = {
|
||||||
|
|
||||||
const app = express();
|
const app = express();
|
||||||
|
|
||||||
app.use(express.json());
|
|
||||||
app.use(express.urlencoded({ extended: false }));
|
|
||||||
app.use(cookieParser());
|
app.use(cookieParser());
|
||||||
app.use(flash());
|
app.use(flash());
|
||||||
|
app.use(express.json({ limit: "50mb" }));
|
||||||
|
app.use(express.urlencoded({ extended: false, limit: "50mb" }));
|
||||||
|
|
||||||
app.use(session(sess));
|
app.use(session(sess));
|
||||||
|
|
||||||
|
@ -85,6 +85,7 @@ app.use(
|
||||||
app.use("/", indexRouter);
|
app.use("/", indexRouter);
|
||||||
app.use("/ma-collection", maCollectionRouter);
|
app.use("/ma-collection", maCollectionRouter);
|
||||||
app.use("/collection", collectionRouter);
|
app.use("/collection", collectionRouter);
|
||||||
|
app.use("/jobs", importJobsRouter);
|
||||||
app.use("/api/v1/albums", importAlbumRouterApiV1);
|
app.use("/api/v1/albums", importAlbumRouterApiV1);
|
||||||
app.use("/api/v1/search", importSearchRouterApiV1);
|
app.use("/api/v1/search", importSearchRouterApiV1);
|
||||||
app.use("/api/v1/me", importMeRouterApiV1);
|
app.use("/api/v1/me", importMeRouterApiV1);
|
||||||
|
|
|
@ -8,4 +8,13 @@ module.exports = {
|
||||||
matomoUrl: process.env.MATOMO_URL || "",
|
matomoUrl: process.env.MATOMO_URL || "",
|
||||||
matomoId: process.env.MATOMO_ID || "",
|
matomoId: process.env.MATOMO_ID || "",
|
||||||
siteName: process.env.SITE_NAME || "MusicTopus",
|
siteName: process.env.SITE_NAME || "MusicTopus",
|
||||||
|
awsAccessKeyId: process.env.AWS_ACCESS_KEY_ID,
|
||||||
|
awsSecretAccessKey: process.env.AWS_SECRET_ACCESS_KEY,
|
||||||
|
s3BaseFolder: process.env.S3_BASEFOLDER || "dev",
|
||||||
|
s3Bucket: process.env.S3_BUCKET || "musictopus",
|
||||||
|
s3Endpoint: process.env.S3_ENDPOINT || "s3.fr-par.scw.cloud",
|
||||||
|
s3Signature: process.env.S3_SIGNATURE || "s3v4",
|
||||||
|
jobsHeaderKey: process.env.JOBS_HEADER_KEY || "musictopus",
|
||||||
|
jobsHeaderValue:
|
||||||
|
process.env.JOBS_HEADER_VALUE || "ooYee9xok7eigo2shiePohyoGh1eepew",
|
||||||
};
|
};
|
||||||
|
|
72
src/libs/aws.js
Normal file
72
src/libs/aws.js
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
import AWS from "aws-sdk";
|
||||||
|
import fs from "fs";
|
||||||
|
import path from "path";
|
||||||
|
import axios from "axios";
|
||||||
|
import { v4 as uuid } from "uuid";
|
||||||
|
|
||||||
|
import {
|
||||||
|
awsAccessKeyId,
|
||||||
|
awsSecretAccessKey,
|
||||||
|
s3BaseFolder,
|
||||||
|
s3Endpoint,
|
||||||
|
s3Bucket,
|
||||||
|
s3Signature,
|
||||||
|
} from "../config";
|
||||||
|
|
||||||
|
AWS.config.update({
|
||||||
|
accessKeyId: awsAccessKeyId,
|
||||||
|
secretAccessKey: awsSecretAccessKey,
|
||||||
|
});
|
||||||
|
/**
|
||||||
|
* Fonction permettant de stocker un fichier local sur S3
|
||||||
|
* @param {String} filename
|
||||||
|
* @param {String} file
|
||||||
|
* @param {Boolean} deleteFile
|
||||||
|
*
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
export const uploadFromFile = async (filename, file, deleteFile = false) => {
|
||||||
|
const data = await fs.readFileSync(file);
|
||||||
|
|
||||||
|
const base64data = Buffer.from(data, "binary");
|
||||||
|
const dest = path.join(s3BaseFolder, filename);
|
||||||
|
|
||||||
|
const s3 = new AWS.S3({
|
||||||
|
endpoint: s3Endpoint,
|
||||||
|
signatureVersion: s3Signature,
|
||||||
|
});
|
||||||
|
|
||||||
|
await s3
|
||||||
|
.putObject({
|
||||||
|
Bucket: s3Bucket,
|
||||||
|
Key: dest,
|
||||||
|
Body: base64data,
|
||||||
|
ACL: "public-read",
|
||||||
|
})
|
||||||
|
.promise();
|
||||||
|
|
||||||
|
if (deleteFile) {
|
||||||
|
fs.unlinkSync(file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `https://${s3Bucket}.${s3Endpoint}/${dest}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fonction permettant de stocker un fichier provenant d'une URL sur S3
|
||||||
|
* @param {String} url
|
||||||
|
*
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
export const uploadFromUrl = async (url) => {
|
||||||
|
const filename = `${uuid()}.jpg`;
|
||||||
|
const file = `/tmp/${filename}`;
|
||||||
|
|
||||||
|
const { data } = await axios.get(url, { responseType: "arraybuffer" });
|
||||||
|
|
||||||
|
fs.writeFileSync(file, data);
|
||||||
|
|
||||||
|
return uploadFromFile(filename, file, true);
|
||||||
|
|
||||||
|
// return s3Object;
|
||||||
|
};
|
|
@ -1,11 +1,13 @@
|
||||||
/* eslint-disable func-names */
|
/* eslint-disable func-names */
|
||||||
const mongoose = require("mongoose");
|
import { Strategy as LocalStrategy } from "passport-local";
|
||||||
const LocalStrategy = require("passport-local").Strategy;
|
import { BasicStrategy } from "passport-http";
|
||||||
const { BasicStrategy } = require("passport-http");
|
import { Strategy as CustomStrategy } from "passport-custom";
|
||||||
|
|
||||||
const Users = mongoose.model("Users");
|
import Users from "../models/users";
|
||||||
|
|
||||||
module.exports = function (passport) {
|
import { jobsHeaderKey, jobsHeaderValue } from "../config";
|
||||||
|
|
||||||
|
export default (passport) => {
|
||||||
passport.serializeUser((user, done) => {
|
passport.serializeUser((user, done) => {
|
||||||
done(null, user);
|
done(null, user);
|
||||||
});
|
});
|
||||||
|
@ -55,4 +57,17 @@ module.exports = function (passport) {
|
||||||
.catch(done);
|
.catch(done);
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
passport.use(
|
||||||
|
"jobs",
|
||||||
|
new CustomStrategy((req, next) => {
|
||||||
|
const apiKey = req.headers[jobsHeaderKey];
|
||||||
|
|
||||||
|
if (apiKey === jobsHeaderValue) {
|
||||||
|
return next(null, {
|
||||||
|
username: "jobs",
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return next(null, false, "Oops! Identifiants incorrects");
|
||||||
|
})
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
|
@ -1,468 +1,18 @@
|
||||||
import moment from "moment";
|
import moment from "moment";
|
||||||
import momenttz from "moment-timezone";
|
|
||||||
import xl from "excel4node";
|
|
||||||
|
|
||||||
import Pages from "./Pages";
|
import Pages from "./Pages";
|
||||||
|
import Export from "./Export";
|
||||||
|
|
||||||
import AlbumsModel from "../models/albums";
|
import AlbumsModel from "../models/albums";
|
||||||
|
import JobsModel from "../models/jobs";
|
||||||
import UsersModel from "../models/users";
|
import UsersModel from "../models/users";
|
||||||
import ErrorEvent from "../libs/error";
|
import ErrorEvent from "../libs/error";
|
||||||
|
// import { uploadFromUrl } from "../libs/aws";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Classe permettant la gestion des albums d'un utilisateur
|
* Classe permettant la gestion des albums d'un utilisateur
|
||||||
*/
|
*/
|
||||||
class Albums extends Pages {
|
class Albums extends Pages {
|
||||||
/**
|
|
||||||
* Méthode permettant de remplacer certains cartactères par leur équivalents html
|
|
||||||
* @param {String} str
|
|
||||||
*
|
|
||||||
* @return {String}
|
|
||||||
*/
|
|
||||||
static replaceSpecialChars(str) {
|
|
||||||
if (!str) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
let final = str.toString();
|
|
||||||
const find = ["&", "<", ">"];
|
|
||||||
const replace = ["&", "<", ">"];
|
|
||||||
|
|
||||||
for (let i = 0; i < find.length; i += 1) {
|
|
||||||
final = final.replace(new RegExp(find[i], "g"), replace[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
return final;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Méthode permettant de convertir les rows en csv
|
|
||||||
* @param {Array} rows
|
|
||||||
*
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
static async convertToCsv(rows) {
|
|
||||||
let data =
|
|
||||||
"Artiste;Titre;Genre;Styles;Pays;Année;Date de sortie;Format\n\r";
|
|
||||||
|
|
||||||
for (let i = 0; i < rows.length; i += 1) {
|
|
||||||
const {
|
|
||||||
artists_sort,
|
|
||||||
title,
|
|
||||||
genres,
|
|
||||||
styles,
|
|
||||||
country,
|
|
||||||
year,
|
|
||||||
released,
|
|
||||||
formats,
|
|
||||||
} = rows[i];
|
|
||||||
|
|
||||||
let format = "";
|
|
||||||
for (let j = 0; j < formats.length; j += 1) {
|
|
||||||
format += `${format !== "" ? ", " : ""}${formats[j].name}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
data += `${artists_sort};${title};${genres.join()};${styles.join()};${country};${year};${released};${format}\n\r`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Méthode permettant de convertir les rows en fichier xls
|
|
||||||
* @param {Array} rows
|
|
||||||
*
|
|
||||||
* @return {Object}
|
|
||||||
*/
|
|
||||||
static async convertToXls(rows) {
|
|
||||||
const wb = new xl.Workbook();
|
|
||||||
const ws = wb.addWorksheet("MusicTopus");
|
|
||||||
|
|
||||||
const headerStyle = wb.createStyle({
|
|
||||||
font: {
|
|
||||||
color: "#FFFFFF",
|
|
||||||
size: 11,
|
|
||||||
},
|
|
||||||
fill: {
|
|
||||||
type: "pattern",
|
|
||||||
patternType: "solid",
|
|
||||||
bgColor: "#595959",
|
|
||||||
fgColor: "#595959",
|
|
||||||
},
|
|
||||||
});
|
|
||||||
const style = wb.createStyle({
|
|
||||||
font: {
|
|
||||||
color: "#000000",
|
|
||||||
size: 11,
|
|
||||||
},
|
|
||||||
numberFormat: "0000",
|
|
||||||
});
|
|
||||||
|
|
||||||
const header = [
|
|
||||||
"Artiste",
|
|
||||||
"Titre",
|
|
||||||
"Genre",
|
|
||||||
"Styles",
|
|
||||||
"Pays",
|
|
||||||
"Année",
|
|
||||||
"Date de sortie",
|
|
||||||
"Format",
|
|
||||||
];
|
|
||||||
for (let i = 0; i < header.length; i += 1) {
|
|
||||||
ws.cell(1, i + 1)
|
|
||||||
.string(header[i])
|
|
||||||
.style(headerStyle);
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let i = 0; i < rows.length; i += 1) {
|
|
||||||
const currentRow = i + 2;
|
|
||||||
const {
|
|
||||||
artists_sort,
|
|
||||||
title,
|
|
||||||
genres,
|
|
||||||
styles,
|
|
||||||
country,
|
|
||||||
year,
|
|
||||||
released,
|
|
||||||
formats,
|
|
||||||
} = rows[i];
|
|
||||||
|
|
||||||
let format = "";
|
|
||||||
for (let j = 0; j < formats.length; j += 1) {
|
|
||||||
format += `${format !== "" ? ", " : ""}${formats[j].name}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
ws.cell(currentRow, 1).string(artists_sort).style(style);
|
|
||||||
ws.cell(currentRow, 2).string(title).style(style);
|
|
||||||
ws.cell(currentRow, 3).string(genres.join()).style(style);
|
|
||||||
ws.cell(currentRow, 4).string(styles.join()).style(style);
|
|
||||||
if (country) {
|
|
||||||
ws.cell(currentRow, 5).string(country).style(style);
|
|
||||||
}
|
|
||||||
if (year) {
|
|
||||||
ws.cell(currentRow, 6).number(year).style(style);
|
|
||||||
}
|
|
||||||
if (released) {
|
|
||||||
ws.cell(currentRow, 7)
|
|
||||||
.date(momenttz.tz(released, "Europe/Paris").hour(12))
|
|
||||||
.style({ numberFormat: "dd/mm/yyyy" });
|
|
||||||
}
|
|
||||||
ws.cell(currentRow, 8).string(format).style(style);
|
|
||||||
}
|
|
||||||
|
|
||||||
return wb;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Méthode permettant de convertir les rows en csv pour importer dans MusicTopus
|
|
||||||
* @param {Array} rows
|
|
||||||
*
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
static async convertToXml(rows) {
|
|
||||||
let data = '<?xml version="1.0" encoding="UTF-8"?>\n\r<albums>';
|
|
||||||
|
|
||||||
for (let i = 0; i < rows.length; i += 1) {
|
|
||||||
const {
|
|
||||||
discogsId,
|
|
||||||
year,
|
|
||||||
released,
|
|
||||||
uri,
|
|
||||||
artists,
|
|
||||||
artists_sort,
|
|
||||||
labels,
|
|
||||||
series,
|
|
||||||
companies,
|
|
||||||
formats,
|
|
||||||
title,
|
|
||||||
country,
|
|
||||||
notes,
|
|
||||||
identifiers,
|
|
||||||
videos,
|
|
||||||
genres,
|
|
||||||
styles,
|
|
||||||
tracklist,
|
|
||||||
extraartists,
|
|
||||||
images,
|
|
||||||
thumb,
|
|
||||||
} = rows[i];
|
|
||||||
|
|
||||||
let artistsList = "";
|
|
||||||
let labelList = "";
|
|
||||||
let serieList = "";
|
|
||||||
let companiesList = "";
|
|
||||||
let formatsList = "";
|
|
||||||
let identifiersList = "";
|
|
||||||
let videosList = "";
|
|
||||||
let genresList = "";
|
|
||||||
let stylesList = "";
|
|
||||||
let tracklistList = "";
|
|
||||||
let extraartistsList = "";
|
|
||||||
let imagesList = "";
|
|
||||||
|
|
||||||
for (let j = 0; j < artists.length; j += 1) {
|
|
||||||
artistsList += `<artist>
|
|
||||||
<name>${Albums.replaceSpecialChars(artists[j].name)}</name>
|
|
||||||
<anv>${Albums.replaceSpecialChars(artists[j].anv)}</anv>
|
|
||||||
<join>${Albums.replaceSpecialChars(artists[j].join)}</join>
|
|
||||||
<role>${Albums.replaceSpecialChars(artists[j].role)}</role>
|
|
||||||
<tracks>${Albums.replaceSpecialChars(
|
|
||||||
artists[j].tracks
|
|
||||||
)}</tracks>
|
|
||||||
<id>${Albums.replaceSpecialChars(artists[j].id)}</id>
|
|
||||||
<resource_url>${Albums.replaceSpecialChars(
|
|
||||||
artists[j].resource_url
|
|
||||||
)}</resource_url>
|
|
||||||
<thumbnail_url>${Albums.replaceSpecialChars(
|
|
||||||
artists[j].thumbnail_url
|
|
||||||
)}</thumbnail_url>
|
|
||||||
</artist>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < labels.length; j += 1) {
|
|
||||||
labelList += `<label>
|
|
||||||
<name>${Albums.replaceSpecialChars(labels[j].name)}</name>
|
|
||||||
<catno>${Albums.replaceSpecialChars(labels[j].catno)}</catno>
|
|
||||||
<entity_type>${Albums.replaceSpecialChars(
|
|
||||||
labels[j].entity_type
|
|
||||||
)}</entity_type>
|
|
||||||
<entity_type_name>${Albums.replaceSpecialChars(
|
|
||||||
labels[j].entity_type
|
|
||||||
)}</entity_type_name>
|
|
||||||
<id>${Albums.replaceSpecialChars(labels[j].id)}</id>
|
|
||||||
<resource_url>${Albums.replaceSpecialChars(
|
|
||||||
labels[j].resource_url
|
|
||||||
)}</resource_url>
|
|
||||||
<thumbnail_url>${Albums.replaceSpecialChars(
|
|
||||||
labels[j].thumbnail_url
|
|
||||||
)}</thumbnail_url>
|
|
||||||
</label>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < series.length; j += 1) {
|
|
||||||
serieList += `<serie>
|
|
||||||
<name>${Albums.replaceSpecialChars(series[j].name)}</name>
|
|
||||||
<catno>${Albums.replaceSpecialChars(series[j].catno)}</catno>
|
|
||||||
<entity_type>${Albums.replaceSpecialChars(
|
|
||||||
series[j].entity_type
|
|
||||||
)}</entity_type>
|
|
||||||
<entity_type_name>${Albums.replaceSpecialChars(
|
|
||||||
series[j].entity_type_name
|
|
||||||
)}</entity_type_name>
|
|
||||||
<id>${Albums.replaceSpecialChars(series[j].id)}</id>
|
|
||||||
<resource_url>${Albums.replaceSpecialChars(
|
|
||||||
series[j].resource_url
|
|
||||||
)}</resource_url>
|
|
||||||
<thumbnail_url>${Albums.replaceSpecialChars(
|
|
||||||
series[j].thumbnail_url
|
|
||||||
)}</thumbnail_url>
|
|
||||||
</serie>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < companies.length; j += 1) {
|
|
||||||
companiesList += `<company>
|
|
||||||
<name>${Albums.replaceSpecialChars(companies[j].name)}</name>
|
|
||||||
<catno>${Albums.replaceSpecialChars(companies[j].catno)}</catno>
|
|
||||||
<entity_type>${Albums.replaceSpecialChars(
|
|
||||||
companies[j].entity_type
|
|
||||||
)}</entity_type>
|
|
||||||
<entity_type_name>${Albums.replaceSpecialChars(
|
|
||||||
companies[j].entity_type_name
|
|
||||||
)}</entity_type_name>
|
|
||||||
<id>${Albums.replaceSpecialChars(companies[j].id)}</id>
|
|
||||||
<resource_url>${Albums.replaceSpecialChars(
|
|
||||||
companies[j].resource_url
|
|
||||||
)}</resource_url>
|
|
||||||
<thumbnail_url>${Albums.replaceSpecialChars(
|
|
||||||
companies[j].thumbnail_url
|
|
||||||
)}</thumbnail_url>
|
|
||||||
</company>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < formats.length; j += 1) {
|
|
||||||
let descriptions = "";
|
|
||||||
if (formats[j].descriptions) {
|
|
||||||
for (
|
|
||||||
let k = 0;
|
|
||||||
k < formats[j].descriptions.length;
|
|
||||||
k += 1
|
|
||||||
) {
|
|
||||||
descriptions += `<description>${formats[j].descriptions[k]}</description>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
formatsList += `<format>
|
|
||||||
<name>${Albums.replaceSpecialChars(formats[j].name)}</name>
|
|
||||||
<qte>${Albums.replaceSpecialChars(formats[j].qty)}</qte>
|
|
||||||
<text>${Albums.replaceSpecialChars(formats[j].text)}</text>
|
|
||||||
<descriptions>
|
|
||||||
${descriptions}
|
|
||||||
</descriptions>
|
|
||||||
</format>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < identifiers.length; j += 1) {
|
|
||||||
identifiersList += `<identifier>
|
|
||||||
<type>${Albums.replaceSpecialChars(identifiers[j].type)}</type>
|
|
||||||
<value>${Albums.replaceSpecialChars(
|
|
||||||
identifiers[j].value
|
|
||||||
)}</value>
|
|
||||||
<description>${Albums.replaceSpecialChars(
|
|
||||||
identifiers[j].description
|
|
||||||
)}</description>
|
|
||||||
</identifier>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < videos.length; j += 1) {
|
|
||||||
videosList += `<video embed="${videos[j].embed}">
|
|
||||||
<uri>${Albums.replaceSpecialChars(videos[j].uri)}</uri>
|
|
||||||
<title>${Albums.replaceSpecialChars(videos[j].title)}</title>
|
|
||||||
<description>${Albums.replaceSpecialChars(
|
|
||||||
videos[j].description
|
|
||||||
)}</description>
|
|
||||||
<duration>${Albums.replaceSpecialChars(
|
|
||||||
videos[j].duration
|
|
||||||
)}</duration>
|
|
||||||
</video>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < genres.length; j += 1) {
|
|
||||||
genresList += `<genre>${Albums.replaceSpecialChars(
|
|
||||||
genres[j]
|
|
||||||
)}</genre>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < styles.length; j += 1) {
|
|
||||||
stylesList += `<style>${Albums.replaceSpecialChars(
|
|
||||||
styles[j]
|
|
||||||
)}</style>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < tracklist.length; j += 1) {
|
|
||||||
tracklistList += `<tracklist position="${
|
|
||||||
tracklist[j].position
|
|
||||||
}" type="${tracklist[j].type_}" duration="${
|
|
||||||
tracklist[j].duration
|
|
||||||
}">
|
|
||||||
${Albums.replaceSpecialChars(tracklist[j].title)}
|
|
||||||
</tracklist>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < extraartists.length; j += 1) {
|
|
||||||
extraartistsList += `<extraartist>
|
|
||||||
<name>${Albums.replaceSpecialChars(extraartists[j].name)}</name>
|
|
||||||
<anv>${Albums.replaceSpecialChars(extraartists[j].anv)}</anv>
|
|
||||||
<join>${Albums.replaceSpecialChars(extraartists[j].join)}</join>
|
|
||||||
<role>${Albums.replaceSpecialChars(extraartists[j].role)}</role>
|
|
||||||
<tracks>${Albums.replaceSpecialChars(
|
|
||||||
extraartists[j].tracks
|
|
||||||
)}</tracks>
|
|
||||||
<id>${Albums.replaceSpecialChars(extraartists[j].id)}</id>
|
|
||||||
<resource_url>${Albums.replaceSpecialChars(
|
|
||||||
extraartists[j].resource_url
|
|
||||||
)}</resource_url>
|
|
||||||
<thumbnail_url>${Albums.replaceSpecialChars(
|
|
||||||
extraartists[j].thumbnail_url
|
|
||||||
)}</thumbnail_url>
|
|
||||||
</extraartist>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (let j = 0; j < images.length; j += 1) {
|
|
||||||
imagesList += `<image type="${images[j].type}" width="${
|
|
||||||
images[j].width
|
|
||||||
}" height="${images[j].height}">
|
|
||||||
<uri>${Albums.replaceSpecialChars(images[j].uri)}</uri>
|
|
||||||
<resource_url>${Albums.replaceSpecialChars(
|
|
||||||
images[j].resource_url
|
|
||||||
)}</resource_url>
|
|
||||||
<uri150>${Albums.replaceSpecialChars(
|
|
||||||
images[j].resource_url
|
|
||||||
)}</uri150>
|
|
||||||
</image>
|
|
||||||
`;
|
|
||||||
}
|
|
||||||
|
|
||||||
data += `
|
|
||||||
<album>
|
|
||||||
<discogId>${discogsId}</discogId>
|
|
||||||
<title>${Albums.replaceSpecialChars(title)}</title>
|
|
||||||
<artists_sort>${Albums.replaceSpecialChars(artists_sort)}</artists_sort>
|
|
||||||
<artists>
|
|
||||||
${artistsList}
|
|
||||||
</artists>
|
|
||||||
<year>${year}</year>
|
|
||||||
<country>${Albums.replaceSpecialChars(country)}</country>
|
|
||||||
<released>${released}</released>
|
|
||||||
<uri>${uri}</uri>
|
|
||||||
<thumb>${thumb}</thumb>
|
|
||||||
<labels>
|
|
||||||
${labelList}
|
|
||||||
</labels>
|
|
||||||
<series>
|
|
||||||
${serieList}
|
|
||||||
</series>
|
|
||||||
<companies>
|
|
||||||
${companiesList}
|
|
||||||
</companies>
|
|
||||||
<formats>
|
|
||||||
${formatsList}
|
|
||||||
</formats>
|
|
||||||
<notes>${Albums.replaceSpecialChars(notes)}</notes>
|
|
||||||
<identifiers>
|
|
||||||
${identifiersList}
|
|
||||||
</identifiers>
|
|
||||||
<videos>
|
|
||||||
${videosList}
|
|
||||||
</videos>
|
|
||||||
<genres>
|
|
||||||
${genresList}
|
|
||||||
</genres>
|
|
||||||
<styles>
|
|
||||||
${stylesList}
|
|
||||||
</styles>
|
|
||||||
<tracklist>
|
|
||||||
${tracklistList}
|
|
||||||
</tracklist>
|
|
||||||
<extraartists>
|
|
||||||
${extraartistsList}
|
|
||||||
</extraartists>
|
|
||||||
<images>
|
|
||||||
${imagesList}
|
|
||||||
</images>
|
|
||||||
</album>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return `${data}</albums>`;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Méthode permettant de convertir les rows en csv pour importer dans MusicTopus
|
|
||||||
* @param {Array} rows
|
|
||||||
*
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
static async convertToMusicTopus(rows) {
|
|
||||||
let data = "itemId;createdAt;updatedAt\n\r";
|
|
||||||
|
|
||||||
for (let i = 0; i < rows.length; i += 1) {
|
|
||||||
const { discogsId, createdAt, updatedAt } = rows[i];
|
|
||||||
|
|
||||||
data += `${discogsId};${createdAt};${updatedAt}\n\r`;
|
|
||||||
}
|
|
||||||
|
|
||||||
data += "v1.0";
|
|
||||||
|
|
||||||
return data;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Méthode permettant d'ajouter un album dans une collection
|
* Méthode permettant d'ajouter un album dans une collection
|
||||||
* @param {Object} req
|
* @param {Object} req
|
||||||
|
@ -482,7 +32,18 @@ class Albums extends Pages {
|
||||||
|
|
||||||
const album = new AlbumsModel(data);
|
const album = new AlbumsModel(data);
|
||||||
|
|
||||||
return album.save();
|
await album.save();
|
||||||
|
|
||||||
|
const jobData = {
|
||||||
|
model: "Albums",
|
||||||
|
id: album._id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const job = new JobsModel(jobData);
|
||||||
|
|
||||||
|
job.save();
|
||||||
|
|
||||||
|
return album;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -593,13 +154,13 @@ class Albums extends Pages {
|
||||||
|
|
||||||
switch (exportFormat) {
|
switch (exportFormat) {
|
||||||
case "csv":
|
case "csv":
|
||||||
return Albums.convertToCsv(rows);
|
return Export.convertToCsv(rows);
|
||||||
case "xls":
|
case "xls":
|
||||||
return Albums.convertToXls(rows);
|
return Export.convertToXls(rows);
|
||||||
case "xml":
|
case "xml":
|
||||||
return Albums.convertToXml(rows);
|
return Export.convertToXml(rows);
|
||||||
case "musictopus":
|
case "musictopus":
|
||||||
return Albums.convertToMusicTopus(rows);
|
return Export.convertToMusicTopus(rows);
|
||||||
case "json":
|
case "json":
|
||||||
default:
|
default:
|
||||||
return {
|
return {
|
||||||
|
|
453
src/middleware/Export.js
Normal file
453
src/middleware/Export.js
Normal file
|
@ -0,0 +1,453 @@
|
||||||
|
import momenttz from "moment-timezone";
|
||||||
|
import xl from "excel4node";
|
||||||
|
|
||||||
|
class Export {
|
||||||
|
/**
|
||||||
|
* Méthode permettant de remplacer certains cartactères par leur équivalents html
|
||||||
|
* @param {String} str
|
||||||
|
*
|
||||||
|
* @return {String}
|
||||||
|
*/
|
||||||
|
static replaceSpecialChars(str) {
|
||||||
|
if (!str) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
let final = str.toString();
|
||||||
|
const find = ["&", "<", ">"];
|
||||||
|
const replace = ["&", "<", ">"];
|
||||||
|
|
||||||
|
for (let i = 0; i < find.length; i += 1) {
|
||||||
|
final = final.replace(new RegExp(find[i], "g"), replace[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return final;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de convertir les rows en csv
|
||||||
|
* @param {Array} rows
|
||||||
|
*
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
static async convertToCsv(rows) {
|
||||||
|
let data =
|
||||||
|
"Artiste;Titre;Genre;Styles;Pays;Année;Date de sortie;Format\n\r";
|
||||||
|
|
||||||
|
for (let i = 0; i < rows.length; i += 1) {
|
||||||
|
const {
|
||||||
|
artists_sort,
|
||||||
|
title,
|
||||||
|
genres,
|
||||||
|
styles,
|
||||||
|
country,
|
||||||
|
year,
|
||||||
|
released,
|
||||||
|
formats,
|
||||||
|
} = rows[i];
|
||||||
|
|
||||||
|
let format = "";
|
||||||
|
for (let j = 0; j < formats.length; j += 1) {
|
||||||
|
format += `${format !== "" ? ", " : ""}${formats[j].name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += `${artists_sort};${title};${genres.join()};${styles.join()};${country};${year};${released};${format}\n\r`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de convertir les rows en fichier xls
|
||||||
|
* @param {Array} rows
|
||||||
|
*
|
||||||
|
* @return {Object}
|
||||||
|
*/
|
||||||
|
static async convertToXls(rows) {
|
||||||
|
const wb = new xl.Workbook();
|
||||||
|
const ws = wb.addWorksheet("MusicTopus");
|
||||||
|
|
||||||
|
const headerStyle = wb.createStyle({
|
||||||
|
font: {
|
||||||
|
color: "#FFFFFF",
|
||||||
|
size: 11,
|
||||||
|
},
|
||||||
|
fill: {
|
||||||
|
type: "pattern",
|
||||||
|
patternType: "solid",
|
||||||
|
bgColor: "#595959",
|
||||||
|
fgColor: "#595959",
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const style = wb.createStyle({
|
||||||
|
font: {
|
||||||
|
color: "#000000",
|
||||||
|
size: 11,
|
||||||
|
},
|
||||||
|
numberFormat: "0000",
|
||||||
|
});
|
||||||
|
|
||||||
|
const header = [
|
||||||
|
"Artiste",
|
||||||
|
"Titre",
|
||||||
|
"Genre",
|
||||||
|
"Styles",
|
||||||
|
"Pays",
|
||||||
|
"Année",
|
||||||
|
"Date de sortie",
|
||||||
|
"Format",
|
||||||
|
];
|
||||||
|
for (let i = 0; i < header.length; i += 1) {
|
||||||
|
ws.cell(1, i + 1)
|
||||||
|
.string(header[i])
|
||||||
|
.style(headerStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let i = 0; i < rows.length; i += 1) {
|
||||||
|
const currentRow = i + 2;
|
||||||
|
const {
|
||||||
|
artists_sort,
|
||||||
|
title,
|
||||||
|
genres,
|
||||||
|
styles,
|
||||||
|
country,
|
||||||
|
year,
|
||||||
|
released,
|
||||||
|
formats,
|
||||||
|
} = rows[i];
|
||||||
|
|
||||||
|
let format = "";
|
||||||
|
for (let j = 0; j < formats.length; j += 1) {
|
||||||
|
format += `${format !== "" ? ", " : ""}${formats[j].name}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
ws.cell(currentRow, 1).string(artists_sort).style(style);
|
||||||
|
ws.cell(currentRow, 2).string(title).style(style);
|
||||||
|
ws.cell(currentRow, 3).string(genres.join()).style(style);
|
||||||
|
ws.cell(currentRow, 4).string(styles.join()).style(style);
|
||||||
|
if (country) {
|
||||||
|
ws.cell(currentRow, 5).string(country).style(style);
|
||||||
|
}
|
||||||
|
if (year) {
|
||||||
|
ws.cell(currentRow, 6).number(year).style(style);
|
||||||
|
}
|
||||||
|
if (released) {
|
||||||
|
ws.cell(currentRow, 7)
|
||||||
|
.date(momenttz.tz(released, "Europe/Paris").hour(12))
|
||||||
|
.style({ numberFormat: "dd/mm/yyyy" });
|
||||||
|
}
|
||||||
|
ws.cell(currentRow, 8).string(format).style(style);
|
||||||
|
}
|
||||||
|
|
||||||
|
return wb;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de convertir les rows en csv pour importer dans MusicTopus
|
||||||
|
* @param {Array} rows
|
||||||
|
*
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
static async convertToXml(rows) {
|
||||||
|
let data = '<?xml version="1.0" encoding="UTF-8"?>\n\r<albums>';
|
||||||
|
|
||||||
|
for (let i = 0; i < rows.length; i += 1) {
|
||||||
|
const {
|
||||||
|
discogsId,
|
||||||
|
year,
|
||||||
|
released,
|
||||||
|
uri,
|
||||||
|
artists,
|
||||||
|
artists_sort,
|
||||||
|
labels,
|
||||||
|
series,
|
||||||
|
companies,
|
||||||
|
formats,
|
||||||
|
title,
|
||||||
|
country,
|
||||||
|
notes,
|
||||||
|
identifiers,
|
||||||
|
videos,
|
||||||
|
genres,
|
||||||
|
styles,
|
||||||
|
tracklist,
|
||||||
|
extraartists,
|
||||||
|
images,
|
||||||
|
thumb,
|
||||||
|
} = rows[i];
|
||||||
|
|
||||||
|
let artistsList = "";
|
||||||
|
let labelList = "";
|
||||||
|
let serieList = "";
|
||||||
|
let companiesList = "";
|
||||||
|
let formatsList = "";
|
||||||
|
let identifiersList = "";
|
||||||
|
let videosList = "";
|
||||||
|
let genresList = "";
|
||||||
|
let stylesList = "";
|
||||||
|
let tracklistList = "";
|
||||||
|
let extraartistsList = "";
|
||||||
|
let imagesList = "";
|
||||||
|
|
||||||
|
for (let j = 0; j < artists.length; j += 1) {
|
||||||
|
artistsList += `<artist>
|
||||||
|
<name>${Export.replaceSpecialChars(artists[j].name)}</name>
|
||||||
|
<anv>${Export.replaceSpecialChars(artists[j].anv)}</anv>
|
||||||
|
<join>${Export.replaceSpecialChars(artists[j].join)}</join>
|
||||||
|
<role>${Export.replaceSpecialChars(artists[j].role)}</role>
|
||||||
|
<tracks>${Export.replaceSpecialChars(artists[j].tracks)}</tracks>
|
||||||
|
<id>${Export.replaceSpecialChars(artists[j].id)}</id>
|
||||||
|
<resource_url>${Export.replaceSpecialChars(
|
||||||
|
artists[j].resource_url
|
||||||
|
)}</resource_url>
|
||||||
|
<thumbnail_url>${Export.replaceSpecialChars(
|
||||||
|
artists[j].thumbnail_url
|
||||||
|
)}</thumbnail_url>
|
||||||
|
</artist>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < labels.length; j += 1) {
|
||||||
|
labelList += `<label>
|
||||||
|
<name>${Export.replaceSpecialChars(labels[j].name)}</name>
|
||||||
|
<catno>${Export.replaceSpecialChars(labels[j].catno)}</catno>
|
||||||
|
<entity_type>${Export.replaceSpecialChars(
|
||||||
|
labels[j].entity_type
|
||||||
|
)}</entity_type>
|
||||||
|
<entity_type_name>${Export.replaceSpecialChars(
|
||||||
|
labels[j].entity_type
|
||||||
|
)}</entity_type_name>
|
||||||
|
<id>${Export.replaceSpecialChars(labels[j].id)}</id>
|
||||||
|
<resource_url>${Export.replaceSpecialChars(
|
||||||
|
labels[j].resource_url
|
||||||
|
)}</resource_url>
|
||||||
|
<thumbnail_url>${Export.replaceSpecialChars(
|
||||||
|
labels[j].thumbnail_url
|
||||||
|
)}</thumbnail_url>
|
||||||
|
</label>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < series.length; j += 1) {
|
||||||
|
serieList += `<serie>
|
||||||
|
<name>${Export.replaceSpecialChars(series[j].name)}</name>
|
||||||
|
<catno>${Export.replaceSpecialChars(series[j].catno)}</catno>
|
||||||
|
<entity_type>${Export.replaceSpecialChars(
|
||||||
|
series[j].entity_type
|
||||||
|
)}</entity_type>
|
||||||
|
<entity_type_name>${Export.replaceSpecialChars(
|
||||||
|
series[j].entity_type_name
|
||||||
|
)}</entity_type_name>
|
||||||
|
<id>${Export.replaceSpecialChars(series[j].id)}</id>
|
||||||
|
<resource_url>${Export.replaceSpecialChars(
|
||||||
|
series[j].resource_url
|
||||||
|
)}</resource_url>
|
||||||
|
<thumbnail_url>${Export.replaceSpecialChars(
|
||||||
|
series[j].thumbnail_url
|
||||||
|
)}</thumbnail_url>
|
||||||
|
</serie>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < companies.length; j += 1) {
|
||||||
|
companiesList += `<company>
|
||||||
|
<name>${Export.replaceSpecialChars(companies[j].name)}</name>
|
||||||
|
<catno>${Export.replaceSpecialChars(companies[j].catno)}</catno>
|
||||||
|
<entity_type>${Export.replaceSpecialChars(
|
||||||
|
companies[j].entity_type
|
||||||
|
)}</entity_type>
|
||||||
|
<entity_type_name>${Export.replaceSpecialChars(
|
||||||
|
companies[j].entity_type_name
|
||||||
|
)}</entity_type_name>
|
||||||
|
<id>${Export.replaceSpecialChars(companies[j].id)}</id>
|
||||||
|
<resource_url>${Export.replaceSpecialChars(
|
||||||
|
companies[j].resource_url
|
||||||
|
)}</resource_url>
|
||||||
|
<thumbnail_url>${Export.replaceSpecialChars(
|
||||||
|
companies[j].thumbnail_url
|
||||||
|
)}</thumbnail_url>
|
||||||
|
</company>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < formats.length; j += 1) {
|
||||||
|
let descriptions = "";
|
||||||
|
if (formats[j].descriptions) {
|
||||||
|
for (
|
||||||
|
let k = 0;
|
||||||
|
k < formats[j].descriptions.length;
|
||||||
|
k += 1
|
||||||
|
) {
|
||||||
|
descriptions += `<description>${formats[j].descriptions[k]}</description>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
formatsList += `<format>
|
||||||
|
<name>${Export.replaceSpecialChars(formats[j].name)}</name>
|
||||||
|
<qte>${Export.replaceSpecialChars(formats[j].qty)}</qte>
|
||||||
|
<text>${Export.replaceSpecialChars(formats[j].text)}</text>
|
||||||
|
<descriptions>
|
||||||
|
${descriptions}
|
||||||
|
</descriptions>
|
||||||
|
</format>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < identifiers.length; j += 1) {
|
||||||
|
identifiersList += `<identifier>
|
||||||
|
<type>${Export.replaceSpecialChars(identifiers[j].type)}</type>
|
||||||
|
<value>${Export.replaceSpecialChars(identifiers[j].value)}</value>
|
||||||
|
<description>${Export.replaceSpecialChars(
|
||||||
|
identifiers[j].description
|
||||||
|
)}</description>
|
||||||
|
</identifier>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < videos.length; j += 1) {
|
||||||
|
videosList += `<video embed="${videos[j].embed}">
|
||||||
|
<uri>${Export.replaceSpecialChars(videos[j].uri)}</uri>
|
||||||
|
<title>${Export.replaceSpecialChars(videos[j].title)}</title>
|
||||||
|
<description>${Export.replaceSpecialChars(
|
||||||
|
videos[j].description
|
||||||
|
)}</description>
|
||||||
|
<duration>${Export.replaceSpecialChars(
|
||||||
|
videos[j].duration
|
||||||
|
)}</duration>
|
||||||
|
</video>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < genres.length; j += 1) {
|
||||||
|
genresList += `<genre>${Export.replaceSpecialChars(
|
||||||
|
genres[j]
|
||||||
|
)}</genre>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < styles.length; j += 1) {
|
||||||
|
stylesList += `<style>${Export.replaceSpecialChars(
|
||||||
|
styles[j]
|
||||||
|
)}</style>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < tracklist.length; j += 1) {
|
||||||
|
tracklistList += `<tracklist position="${
|
||||||
|
tracklist[j].position
|
||||||
|
}" type="${tracklist[j].type_}" duration="${
|
||||||
|
tracklist[j].duration
|
||||||
|
}">
|
||||||
|
${Export.replaceSpecialChars(tracklist[j].title)}
|
||||||
|
</tracklist>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < extraartists.length; j += 1) {
|
||||||
|
extraartistsList += `<extraartist>
|
||||||
|
<name>${Export.replaceSpecialChars(extraartists[j].name)}</name>
|
||||||
|
<anv>${Export.replaceSpecialChars(extraartists[j].anv)}</anv>
|
||||||
|
<join>${Export.replaceSpecialChars(extraartists[j].join)}</join>
|
||||||
|
<role>${Export.replaceSpecialChars(extraartists[j].role)}</role>
|
||||||
|
<tracks>${Export.replaceSpecialChars(
|
||||||
|
extraartists[j].tracks
|
||||||
|
)}</tracks>
|
||||||
|
<id>${Export.replaceSpecialChars(extraartists[j].id)}</id>
|
||||||
|
<resource_url>${Export.replaceSpecialChars(
|
||||||
|
extraartists[j].resource_url
|
||||||
|
)}</resource_url>
|
||||||
|
<thumbnail_url>${Export.replaceSpecialChars(
|
||||||
|
extraartists[j].thumbnail_url
|
||||||
|
)}</thumbnail_url>
|
||||||
|
</extraartist>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (let j = 0; j < images.length; j += 1) {
|
||||||
|
imagesList += `<image type="${images[j].type}" width="${
|
||||||
|
images[j].width
|
||||||
|
}" height="${images[j].height}">
|
||||||
|
<uri>${Export.replaceSpecialChars(images[j].uri)}</uri>
|
||||||
|
<resource_url>${Export.replaceSpecialChars(
|
||||||
|
images[j].resource_url
|
||||||
|
)}</resource_url>
|
||||||
|
<uri150>${Export.replaceSpecialChars(
|
||||||
|
images[j].resource_url
|
||||||
|
)}</uri150>
|
||||||
|
</image>
|
||||||
|
`;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += `
|
||||||
|
<album>
|
||||||
|
<discogId>${discogsId}</discogId>
|
||||||
|
<title>${Export.replaceSpecialChars(title)}</title>
|
||||||
|
<artists_sort>${Export.replaceSpecialChars(artists_sort)}</artists_sort>
|
||||||
|
<artists>
|
||||||
|
${artistsList}
|
||||||
|
</artists>
|
||||||
|
<year>${year}</year>
|
||||||
|
<country>${Export.replaceSpecialChars(country)}</country>
|
||||||
|
<released>${released}</released>
|
||||||
|
<uri>${uri}</uri>
|
||||||
|
<thumb>${thumb}</thumb>
|
||||||
|
<labels>
|
||||||
|
${labelList}
|
||||||
|
</labels>
|
||||||
|
<series>
|
||||||
|
${serieList}
|
||||||
|
</series>
|
||||||
|
<companies>
|
||||||
|
${companiesList}
|
||||||
|
</companies>
|
||||||
|
<formats>
|
||||||
|
${formatsList}
|
||||||
|
</formats>
|
||||||
|
<notes>${Export.replaceSpecialChars(notes)}</notes>
|
||||||
|
<identifiers>
|
||||||
|
${identifiersList}
|
||||||
|
</identifiers>
|
||||||
|
<videos>
|
||||||
|
${videosList}
|
||||||
|
</videos>
|
||||||
|
<genres>
|
||||||
|
${genresList}
|
||||||
|
</genres>
|
||||||
|
<styles>
|
||||||
|
${stylesList}
|
||||||
|
</styles>
|
||||||
|
<tracklist>
|
||||||
|
${tracklistList}
|
||||||
|
</tracklist>
|
||||||
|
<extraartists>
|
||||||
|
${extraartistsList}
|
||||||
|
</extraartists>
|
||||||
|
<images>
|
||||||
|
${imagesList}
|
||||||
|
</images>
|
||||||
|
</album>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
return `${data}</albums>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de convertir les rows en csv pour importer dans MusicTopus
|
||||||
|
* @param {Array} rows
|
||||||
|
*
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
static async convertToMusicTopus(rows) {
|
||||||
|
let data = "itemId;createdAt;updatedAt\n\r";
|
||||||
|
|
||||||
|
for (let i = 0; i < rows.length; i += 1) {
|
||||||
|
const { discogsId, createdAt, updatedAt } = rows[i];
|
||||||
|
|
||||||
|
data += `${discogsId};${createdAt};${updatedAt}\n\r`;
|
||||||
|
}
|
||||||
|
|
||||||
|
data += "v1.0";
|
||||||
|
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Export;
|
128
src/middleware/Jobs.js
Normal file
128
src/middleware/Jobs.js
Normal file
|
@ -0,0 +1,128 @@
|
||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
|
import ErrorEvent from "../libs/error";
|
||||||
|
import { uploadFromUrl } from "../libs/aws";
|
||||||
|
import { getAlbumDetails } from "../helpers";
|
||||||
|
|
||||||
|
import JobsModel from "../models/jobs";
|
||||||
|
import AlbumsModel from "../models/albums";
|
||||||
|
|
||||||
|
class Jobs {
|
||||||
|
/**
|
||||||
|
* Méthode permettant de télécharger toute les images d'un album
|
||||||
|
* @param {ObjectId} itemId
|
||||||
|
*/
|
||||||
|
static async importAlbumAssets(itemId) {
|
||||||
|
const album = await AlbumsModel.findById(itemId);
|
||||||
|
|
||||||
|
if (!album) {
|
||||||
|
throw new ErrorEvent(
|
||||||
|
404,
|
||||||
|
"Item non trouvé",
|
||||||
|
`L'album avant l'id ${itemId} n'existe plus dans la collection`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
const item = await getAlbumDetails(album.discogsId);
|
||||||
|
|
||||||
|
if (!item) {
|
||||||
|
throw new ErrorEvent(
|
||||||
|
404,
|
||||||
|
"Erreur de communication",
|
||||||
|
"Erreur lors de la récupération des informations sur Discogs"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.thumb) {
|
||||||
|
album.thumb = await uploadFromUrl(item.thumb);
|
||||||
|
album.thumbType = "local";
|
||||||
|
}
|
||||||
|
const { images } = item;
|
||||||
|
if (images && images.length > 0) {
|
||||||
|
for (let i = 0; i < images.length; i += 1) {
|
||||||
|
images[i].uri150 = await uploadFromUrl(images[i].uri150);
|
||||||
|
images[i].uri = await uploadFromUrl(images[i].uri);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
album.images = images;
|
||||||
|
|
||||||
|
await album.save();
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Point d'entrée
|
||||||
|
* @param {String} state
|
||||||
|
*
|
||||||
|
* @return {Object}
|
||||||
|
*/
|
||||||
|
async run(state = "NEW") {
|
||||||
|
const job = await JobsModel.findOne({
|
||||||
|
state,
|
||||||
|
tries: {
|
||||||
|
$lte: 5,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!job) {
|
||||||
|
return { message: "All jobs done" };
|
||||||
|
}
|
||||||
|
|
||||||
|
job.state = "IN-PROGRESS";
|
||||||
|
|
||||||
|
await job.save();
|
||||||
|
|
||||||
|
try {
|
||||||
|
switch (job.model) {
|
||||||
|
case "Albums":
|
||||||
|
await Jobs.importAlbumAssets(job.id);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw new ErrorEvent(
|
||||||
|
500,
|
||||||
|
"Job inconnu",
|
||||||
|
`Le job avec l'id ${job._id} n'est pas un job valide`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
job.state = "SUCCESS";
|
||||||
|
|
||||||
|
await job.save();
|
||||||
|
|
||||||
|
return this.run(state);
|
||||||
|
} catch (err) {
|
||||||
|
job.state = "ERROR";
|
||||||
|
job.lastTry = new Date();
|
||||||
|
job.lastErrorMessage = err.message;
|
||||||
|
job.tries += 1;
|
||||||
|
|
||||||
|
await job.save();
|
||||||
|
|
||||||
|
throw err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Méthode permettant de créer tous les jobs
|
||||||
|
*
|
||||||
|
* @return {Object}
|
||||||
|
*/
|
||||||
|
static async populate() {
|
||||||
|
const albums = await AlbumsModel.find();
|
||||||
|
|
||||||
|
for (let i = 0; i < albums.length; i += 1) {
|
||||||
|
const jobData = {
|
||||||
|
model: "Albums",
|
||||||
|
id: albums[i]._id,
|
||||||
|
};
|
||||||
|
|
||||||
|
const job = new JobsModel(jobData);
|
||||||
|
await job.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
return { message: `${albums.length} jobs ajouté à la file d'attente` };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default Jobs;
|
|
@ -29,6 +29,7 @@ const AlbumSchema = new mongoose.Schema(
|
||||||
extraartists: Array,
|
extraartists: Array,
|
||||||
images: Array,
|
images: Array,
|
||||||
thumb: String,
|
thumb: String,
|
||||||
|
thumbType: String,
|
||||||
},
|
},
|
||||||
{ timestamps: true }
|
{ timestamps: true }
|
||||||
);
|
);
|
||||||
|
|
24
src/models/jobs.js
Normal file
24
src/models/jobs.js
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import mongoose from "mongoose";
|
||||||
|
|
||||||
|
const { Schema } = mongoose;
|
||||||
|
|
||||||
|
const JobSchema = new mongoose.Schema(
|
||||||
|
{
|
||||||
|
model: String,
|
||||||
|
id: Schema.Types.ObjectId,
|
||||||
|
state: {
|
||||||
|
type: String,
|
||||||
|
enum: ["NEW", "IN-PROGRESS", "ERROR", "SUCCESS"],
|
||||||
|
default: "NEW",
|
||||||
|
},
|
||||||
|
lastTry: Date,
|
||||||
|
lastErrorMessage: String,
|
||||||
|
tries: {
|
||||||
|
type: Number,
|
||||||
|
default: 0,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ timestamps: true }
|
||||||
|
);
|
||||||
|
|
||||||
|
export default mongoose.model("Jobs", JobSchema);
|
40
src/routes/jobs.js
Normal file
40
src/routes/jobs.js
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
import express from "express";
|
||||||
|
import passport from "passport";
|
||||||
|
|
||||||
|
import Jobs from "../middleware/Jobs";
|
||||||
|
|
||||||
|
// eslint-disable-next-line new-cap
|
||||||
|
const router = express.Router();
|
||||||
|
|
||||||
|
router.route("/").get(
|
||||||
|
passport.authenticate(["jobs"], {
|
||||||
|
session: false,
|
||||||
|
}),
|
||||||
|
async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const job = new Jobs();
|
||||||
|
const data = await job.run(req.query.state);
|
||||||
|
|
||||||
|
return res.status(200).json(data).end();
|
||||||
|
} catch (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
router.route("/populate").get(
|
||||||
|
passport.authenticate(["jobs"], {
|
||||||
|
session: false,
|
||||||
|
}),
|
||||||
|
async (req, res, next) => {
|
||||||
|
try {
|
||||||
|
const data = await Jobs.populate();
|
||||||
|
|
||||||
|
return res.status(200).json(data).end();
|
||||||
|
} catch (err) {
|
||||||
|
return next(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export default router;
|
Loading…
Reference in a new issue