Nico Pr
Coming soon (?)
Download & share high quality music and more from any device or browser.
Flaque is a simple media downloader. Run your own instance at home, make it accessible from outside, share content with friends and family.
- Download lossless files from Qobuz and Tidal
- Unlock links and fast download via AllDebrid
- Orders queue, no hurry, processed one by one
- Email download link after order is processed
- Delete email address once order is completed
Drop the links#
No ads, no download manager, command lines, torrents, transfer, drive, etc...
One click drop, wait for delivery, play and share from any device.
Flaque web page#
Go to Flaque page, paste link and email.
Flaque bookmark#
Click.
Flaque to go#
Share everywhere
Features#
Web player#
- Play & share music from any browser
- One "music box" per email (hashed)
- Background audio
- Native media controls
- MP3@320 playback
- Original file download
- Offline playback [SOON]
- Playlists [SOON]
Delivery#
- Allow direct open files (flac, pdf, mp4, ...)
- Or compress all orders and force download
- Qobuz & Tidal albums zipped with cover & emailed
- Single tracks are added to web player if enabled
Metadata#
- Extract covers from audio files
- Extract first page from PDF files (CBR & CBZ [SOON])
- Parse MKV files and fetch posters from TMDB
- Attach images to emails
- Opengraph message previews

Alldebrid download relay#
- {FLAQUE_URL}/dbrd?url={LINK}
- Waiting line page [SOON]
- Start download
Privacy#
- No account
- No cookies
- No analytics
- No centralized database
- Not storing email addresses in database
- Just keeping a hash for download limits
- Also used by web player to store tracks
- Collecting IP addresses but also hashed
Security#
Not really... just sharing ¯\(ツ)/¯
Flaque setup#
🧪 FIRST RELEASE
🚀 NODEJS NO LTS
💥 UNSTABLE TEST
🪲 BUGS INCOMING
☣️ This version is running a Node.js 23.10 EXPERIMENTAL UNSAFE web server with no dependencies (built-in modules only), coded by a machine (and fixed by a human).
Flaque code was typed on a real keyboard, and needs a few npm packages to run smoothly.
- archiver : create ZIP archives
- music-metadata : extract metadata & cover art
- pdfjs-dist : open PDF files
- @napi-rs/canvas : PDF page to JPG
- nodemailer : send emails
Underlying server can be easily replaced.
This project was intended for personal use, tested with friends for almost a year now.
Running on a 2016 Intel NUC + Ubuntu server + 1Gbps internet access, uptime and performances are satisfying.
Downloaders get stuck from time to time, error handling is not fully implemented.
Flaque sources#
Download repository from Github
Required software#
- Node.js 23.10
- Python 3.12
- qobuz-dl (working on a Node.js port)
- tidal-dl-ng
- FFmpeg
Docker#
Flaque image is based on node:23.10-alpine.
Two volumes must be mounted to preserve data :
/app/prod : Flaque config files and drops directory
/root/.config : Qobuz & Tidal config files
Open terminal in Flaque directory
Create image
docker compose --file ops/docker/docker-compose.yml build --force-rm --no-cacheCreate container
docker compose // volumes // portsConnect Qobuz account (enter credentials, ignore all settings)
docker exec -it {container_name} qobuz-dlConnect Tidal account (enter credentials, follow instructions)
docker exec -it {container_name} tidal-dl-ng login
Autoinstall#
⚠️ experimental
Following scripts will automatically download and install all required dependencies.
Windows
Self-contained portable installation Tested on Windows 11 Pro 24H2
- Open terminal in Flaque directory
- Run autoinstall script
ops\scripts\install_win.bat - Connect Qobuz account (enter credentials, ignore all settings)
run.bat qobuz-dl - Connect Tidal account (enter credentials, follow instructions)
run.bat tidal-dl-ng login - Edit
prod/server.conf.jsandprod/flaque.conf.js - Start server
run.bat npm start - Go to Flaque page
{FLAQUE_URL}/flaque - If running locally : http://localhost:8080/flaque
Ubuntu
Tested on Ubuntu 24 desktop fresh install and Ubuntu 24 WSL2
- Open terminal in Flaque directory
- Make script executable
chmod +x ./ops/scripts/install_ubuntu.sh - Run autoinstall script
./ops/scripts/install_ubuntu.sh - Open a new terminal
- Connect Qobuz account (enter credentials, ignore all settings)
qobuz-dl - Connect Tidal account (enter credentials, follow instructions)
tidal-dl-ng login - Edit
prod/server.conf.jsandprod/flaque.conf.js - Start server
npm start
HTTPS#
- docker reverse
- let's encrypt
- win acme
Settings#
⚠️ Flaque is open by default. Accepts drops from any email address !
opts: { // global options
url: "https://localhost", // flaque public url
storage: "prod/drops",
fastdrop: true,
keeptime: 7200, // delete downloaded zip files after x seconds
linked: [ // no zip, direct link delivery
".flac",
".pdf",
".mkv",
".mp4"
],
keepdata: true // keep history > 24h
},
bin: { // binaries
"qobuz-dl": "qobuz-dl",
"tidal-dl-ng": "tidal-dl-ng",
"ffmpeg": "ffmpeg"
},
mail: { // mail conf
smtp: "domain.tld", // smtp server
port: 465, // smtp port
from: "\"flaque\" <flaque@domain.tld>", // mail from
user: "flaque@domain.tld", // mail account
pass: "p4ssw0rd", // password
msgsize: 512 // max mail message length
},
play: { // web player
enabled: true, // enable web player
tracks: 30, // max tracks per email address
upload: false, // allow tracks upload
upmail: [ // allow tracks upload mails
]
},
tmdb: { // movie posters
token: "TMDB_TOKEN"
},
limit: { // download restrictions
skip: { // VIP bypass all limits
mail: [ // email exact match
"flaque@domain.tld"
],
ip: [ // ip exact matches
]
},
main: { // global limits
day: 100, // max downloads / day
hour: 10 // max downloads / hour
},
ip: { // ip limits
day: 100, // max downloads / day
hour: 20, // max downloads / hour
list: [ // ban IP address or IP ranges
]
},
mail: { // email limits
day: 100, // max downloads / day
hour: 20, // max downloads / hour
list: [ // ban emails or domains
"privaterelay.appleid.com",
]
}
},
www: { // downloaders
qobuz: { // qobuz conf
enabled: true, // enable downloader
quality: 6,
mail: { // email custom quality
"flaque@domain.tld": 27
},
day: 100, // max downloads / day
hour: 10, // max downloads / hour
type: {
track: { // download tracks
enabled: true
},
album: { // download albums
enabled: true
}
}
},
tidal: { // tidal conf
enabled: true, // enable downloader
quality: "LOSSLESS",
mail: { // email custom quality
"flaque@domain.tld": "HI_RES_LOSSLESS"
},
delay: false, // random delay before download
day: 100, // max downloads / day
hour: 10, // max downloads / hour
type: {
track: { // download tracks
enabled: true
},
album: { // download albums
enabled: true
}
}
},
alldebrid: { // alldebrid conf
enabled: true, // enable downloader
relay: false, // enable alldebrid direct download relay, no mail required, ip check only
app: "ALLDEBRID_APP_NAME",
key: "ALLDEBRID_API_KEY",
day: 100, // max downloads / day
hour: 10, // max downloads / hour
size: 5000, // max ddl file size MB
speed: 5, // download speed limit MB/s
type: { // hosts conf
"1fichier": {
enabled: true, // enable 1fichier
day: 100, // max downloads / day
hour: 10, // max downloads / hour
size: 2000 // max file size MB
},
"isra": { enabled: false },
"katfile": {
enabled: true, // enable katfile
day: 100, // max downloads / day
hour: 10, // max downloads / hour
size: 75 // max file size MB
},
"mega": {enabled: true},
"rapidgator": {enabled: true},
"scribd": {enabled: true},
"turbobit": {
enabled: true, // enable turbobit
day: 100, // max downloads / day
hour: 10, // max downloads / hour
size: 1000 // max file size MB
},
},
p2p: { // magnet & torrents
day: 100, // max downloads / day
hour: 10, // max downloads / hour
size: 75 // max file size MB
},
exts: [ // allowed file extensions
]
}
}Configuration#
Web drop#
- Go to Flaque page
- Paste link
- Type email
- Drop
Browser will keep email address in LocalStorage, next pasted links will be submitted automatically.
Bookmark drop#
- Generate bookmarklet code below
- Data not transfered to server
- Right click bookmarks bar, Add page ...
- Choose a fancy name, paste code in URL field
- Go to Qobuz or Tidal track / album page
- Click the button
One bookmark = one email address
<form>
<input type="text" name="flaque" placeholder="Flaque URL" required/>
<input type="email" name="email" placeholder="Email address" required/>
<input type="text" name="msg" placeholder="Message (optional)"/>
<input type="submit" value="Generate bookmark">
</form>:root {
--font: 'Courier New', Courier, monospace;
--back: #FFFFFF;
--btnback: #cacaca;
--col: #333333;
}
@media (prefers-color-scheme: dark) {
:root {
--back: #0d1117;
--btnback: #939393;
--col: #c9d1d9;
}
}
html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
input[type=submit],
input[type=text],
input[type=email] {
box-sizing: border-box;
-webkit-appearance: none;
outline: none;
background-color: var(--back);
color: var(--col);
border: solid 1px transparent;
border-radius: 0;
padding: 0;
width: 100%;
max-width: 380px;
font-size: 1.2em;
line-height: 1.2em;
font-family: var(--font);
}
input[type=submit] {
cursor: pointer;
font-weight: normal;
}
input[type=text],
input[type=email] {
border-bottom: solid 1px var(--btnback);
}
form {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
}const cliqueFlaque = () => {
const popMsg = (txt, col, out = 2500) => {
console.log(txt);
let wrap = document
.createElement("div");
wrap
.setAttribute(
"style",
[
"position:fixed",
"top:20px",
"width:100%",
"z-index:5000",
"text-align:center"
]
.join(";") + ";"
);
let ack = document
.createElement("span");
ack
.setAttribute(
"style",
[
"box-sizing:border-box",
"font-size:1.3em",
"border-radius:6px",
"padding:0.33em 0.66em",
"color:#FFFFFF",
"background-color:" +
[
"rgba(228,45,68,0.7)",
"rgba(105,216,91,0.7)",
"rgba(232,174,11,0.7)"
][col]
]
.join(";") + ";"
);
ack.innerHTML = txt;
wrap
.appendChild(ack);
document.body
.appendChild(wrap);
setTimeout(
() =>
wrap
.remove(),
out
);
};
let box = "{box}" || prompt("email"),
msg = "{msg}",
drop = "{flaque}/drop?" +
"lnk=" + location.href +
"&box=" + box +
(
msg
? "&msg=" + encodeURI(msg)
: ""
);
if(!box)
return popMsg(
"mail please",
2
);
fetch(drop)
.then(
res =>
res.ok
&& res
.json()
|| null
)
.then(
dropped => {
if(dropped) {
if(dropped.box) {
popMsg(
"<a style=\"color:#FFFFFF;text-decoration:none;\" href=\"" + dropped.box + "\" target=\"_blank\">▶ click to open player</a>",
+dropped.ok,
5000
);
}
else
popMsg(
dropped.msg,
+dropped.ok
);
}
else {
popMsg(
"maybe",
2
);
}
}
);
};
const plouf = (flaque, box, msg) =>
"javascript:(function(){" +
[
["{flaque}", flaque],
["{box}", box],
["{msg}", msg],
[/\s+/g, " "],
[/\/\*[\s\S]*?\*\/|([^\\:]|^)\/\/.*|^\s*\n$/gm, "$1"],
[/\s*([{}[\]()=+\-/*:,;<>!|&?])\s*/g, "$1"],
[/\s*\.\s*/g, "."]
]
.reduce(
(clique, claque) =>
clique
.replace(...claque),
cliqueFlaque
.toString()
)
.trim()
+ "})()";
window.addEventListener(
"load",
() =>
document.querySelector("form")
.addEventListener(
"submit",
evt => {
evt.preventDefault();
const dat = Object.fromEntries(new FormData(evt.target));
console.log(plouf(dat["flaque"], dat["email"], dat["msg"]));
return false;
}
)
);Mobile drop#
Qobuz & Tidal
- Install apps
- Create free accounts
- Choose track or album
- Tap dots ⋮menu···
- Share -> More
- Run shortcut
Alldebrid
- Open browser
- Go to supported host link
- Open share sheet
- Run shortcut
Shortcuts can be duplicated, renamed, and edited
iOs#
- Install Shortcuts
- Get shortcut below
- Run configuration
- Set Flaque URL and email address
const iOsShortcutData = "data:application/octet-stream;base64,QUVBMQAAAACdCAAAYnBsaXN0MDDRAQJfEBdTaWduaW5nQ2VydGlmaWNhdGVDaGFpbqMDBAVPEQMLMIIDBzCCAqygAwIBAgIIJ22PNA5arMIwCgYIKoZIzj0EAwIwcjEmMCQGA1UEAwwdQXBwbGUgU3lzdGVtIEludGVncmF0aW9uIENBIDQxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzAeFw0yNTAzMjAxNjUwMzNaFw0yNjA0MTYxODIxMjFaME0xKTAnBgNVBAMMIDdiYjdmYTNkNGNhNDQ0ZWJhMmM4MDk2MTVlODE4ZTNmMRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzBZMBMGByqGSM49AgEGCCqGSM49AwEHA0IABIsdfPbolstAhLEQKKGNPs6L7rDgsk87/5nlynltl0u+Yc2nCQgi1usB2NbH5NlXPVNdWwQzbg9Tbmi6lPxJQJ+jggFPMIIBSzAMBgNVHRMBAf8EAjAAMB8GA1UdIwQYMBaAFHpHujiKFSRIIkbNvo8aJHs0AyppMEEGCCsGAQUFBwEBBDUwMzAxBggrBgEFBQcwAYYlaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwMy1hc2ljYTQwNDCBlgYDVR0gBIGOMIGLMIGIBgkqhkiG92NkBQEwezB5BggrBgEFBQcCAjBtDGtUaGlzIGNlcnRpZmljYXRlIGlzIHRvIGJlIHVzZWQgZXhjbHVzaXZlbHkgZm9yIGZ1bmN0aW9ucyBpbnRlcm5hbCB0byBBcHBsZSBQcm9kdWN0cyBhbmQvb3IgQXBwbGUgcHJvY2Vzc2VzLjAdBgNVHQ4EFgQUV/ZMwtR6SrSY2DO5i9jEsqM0zxEwDgYDVR0PAQH/BAQDAgeAMA8GCSqGSIb3Y2QSAQQCBQAwCgYIKoZIzj0EAwIDSQAwRgIhAK2tDnA422NXaRlZdcKLPUmNWbaUF3/g8Q9nK29UuOOGAiEA1K9lDIeAe/V67h22KTcIg4/m+k4Rxl4RbrYMIJKO5+RPEQLqMIIC5jCCAm2gAwIBAgIIMw3u+L9MaC4wCgYIKoZIzj0EAwMwZzEbMBkGA1UEAwwSQXBwbGUgUm9vdCBDQSAtIEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwHhcNMTcwMjIyMjIyMzIyWhcNMzIwMjE4MDAwMDAwWjByMSYwJAYDVQQDDB1BcHBsZSBTeXN0ZW0gSW50ZWdyYXRpb24gQ0EgNDEmMCQGA1UECwwdQXBwbGUgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkxEzARBgNVBAoMCkFwcGxlIEluYy4xCzAJBgNVBAYTAlVTMFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEBmukVm99nyfRzjaOkhtWzVQ2ZErJlGiZ+skgfuL1WA/c4mrrGUcvLu87pAG0ARNEfFomraCcKSWK5eYGb098WqOB9zCB9DAPBgNVHRMBAf8EBTADAQH/MB8GA1UdIwQYMBaAFLuw3qFYM4iapIqZ3r6966/ayySrMEYGCCsGAQUFBwEBBDowODA2BggrBgEFBQcwAYYqaHR0cDovL29jc3AuYXBwbGUuY29tL29jc3AwMy1hcHBsZXJvb3RjYWczMDcGA1UdHwQwMC4wLKAqoCiGJmh0dHA6Ly9jcmwuYXBwbGUuY29tL2FwcGxlcm9vdGNhZzMuY3JsMB0GA1UdDgQWBBR6R7o4ihUkSCJGzb6PGiR7NAMqaTAOBgNVHQ8BAf8EBAMCAQYwEAYKKoZIhvdjZAYCEQQCBQAwCgYIKoZIzj0EAwMDZwAwZAIwFQypjsavlmlrp5/dXNQDWWyuUtRgxot24LfFovEJfOCa42ux43wxxCd6p46J/at3AjBhMyDxKf/5hzKuKchkPXZ7UaTSAi92vmAikfHVOnXctOLGKpb+xgncSk/VJPD8yrJPEQJHMIICQzCCAcmgAwIBAgIILcX8iNLFS5UwCgYIKoZIzj0EAwMwZzEbMBkGA1UEAwwSQXBwbGUgUm9vdCBDQSAtIEczMSYwJAYDVQQLDB1BcHBsZSBDZXJ0aWZpY2F0aW9uIEF1dGhvcml0eTETMBEGA1UECgwKQXBwbGUgSW5jLjELMAkGA1UEBhMCVVMwHhcNMTQwNDMwMTgxOTA2WhcNMzkwNDMwMTgxOTA2WjBnMRswGQYDVQQDDBJBcHBsZSBSb290IENBIC0gRzMxJjAkBgNVBAsMHUFwcGxlIENlcnRpZmljYXRpb24gQXV0aG9yaXR5MRMwEQYDVQQKDApBcHBsZSBJbmMuMQswCQYDVQQGEwJVUzB2MBAGByqGSM49AgEGBSuBBAAiA2IABJjpLz1AcqTtkyJygRMc3RCV8cWjTnHcFBbZDuWmBSp3ZHtfTjjTuxxEtX/1H7YyYl3J6YRbTzBPEVoA/VhYDKX1DyxNB0cTddqXl5dvMVztK517IDvYuVTZXpmkOlEKMaNCMEAwHQYDVR0OBBYEFLuw3qFYM4iapIqZ3r6966/ayySrMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgEGMAoGCCqGSM49BAMDA2gAMGUCMQCD6cHEFl4aXTQY2e3v9GwOAEZLuN+yRhHFD/3meoyhpmvOwgPUnPWTxnS4at+qIxUCMG1mihDK1A3UT82NQz60imOlM27jbdoXt2QfyFMm+YhidDkLF1vLUagM6BgD56KyKAAIAAsAJQApAzgGJgAAAAAAAAIBAAAAAAAAAAYAAAAAAAAAAAAAAAAAAAhxMEUCIQDjL6bmebGGWLDLcQuPiyL+GXXWTZRi6tTmYbdWRb82pQIgVMEApOvQ9C65TDuAaofyn6k8vS1lUe/ijbbgbNs+XBEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADcn/LQ1ZO0rm6OoKsdkWWZnv5qA8FZ5NVt6Fzq22uFNbX8W42JXe0vYvRbWw9lWnTFvqUlGedM323k8bp1iCb0NzY7pqJuny1R6SelHe3tfSOXNA4wUjcf9tsOIh4rrVkOFQAAAAAAAM1eAAAAAAAAAAAQAAABAABlAgAAAAAAAAAAAAAAAAAAAAAAAAAAAABkQFj9eSWrM530xl87GZ3ryXwBHHaSzLjJJTc/u4Ea2Q4VAADUDAAAliDPU/p7eIkn8Cl7n2iVkJ5vdNwrMxE8N8ygktONkKUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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";<div>Get iOs shortcut</div>html, body {
margin: 0;
padding: 0;
width: 100%;
height: 100%;
}
body {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
justify-content: space-evenly;
align-items: center;
background-color: #FFFFFF;
color: #333333;
font-family: 'Courier New', Courier, monospace;
}
@media (prefers-color-scheme: dark) {
body {
background-color: #0d1117;
color: #c9d1d9;
}
}
div {
font-size: 1.5em;
cursor: pointer;
}document.querySelector("div")
.addEventListener(
"click",
() =>
forceDL(
"FLAQUE_DROP.shortcut",
iOsShortcutData
)
);const forceDL = (nnm, dat) => {
let a = document.createElement("a");
document.body.appendChild(a);
a.style.display = "none";
a.href = dat;
a.download = nnm;
a.click();
a.remove();
};Android#
- Install HTTP Shortcuts
- Fill form below (not sent to server ;)
- Set Flaque URL and email address
- Download shortcut
- Import in HTTP Shortcuts
<form>
<input type="text" name="flaque" placeholder="Flaque URL" required/>
<input type="email" name="email" placeholder="Email address" required/>
<input type="submit" value="Generate shortcut"/>
</form>input[type=submit] {
font-size: 1.5em;
}const gen = () =>
"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx"
.replace(
/[xy]/g,
c => {
const r = Math.random() * 16 | 0;
return (c === "x" ? r : (r & 0x3 | 0x8)).toString(16);
}
);
const plouf = (flaque, box) => {
const categoryId = gen();
const shortcutId = gen();
const variableId = gen();
const shortcutJSON = JSON.stringify({
categories: [
{
id: categoryId,
name: "Shortcuts",
shortcuts: [
{
categoryId: categoryId,
codeOnFailure: "const fail \u003d JSON.parse(response.body);\nif(fail.msg) showToast(fail.msg);",
codeOnSuccess: "const drop \u003d JSON.parse(response.body);\nif(drop.msg) showToast(drop.msg);\nif(drop.box) { if(confirm(\"open flaque player ?\")) { openUrl(drop.box); } }",
description: "Good vibes",
iconName: "flat_color_brightness",
id: shortcutId,
launcherShortcut: false,
name: "FLAQUE DROP",
responseHandling: {
successOutput: "none"
},
url: flaque + "/drop?lnk\u003d{{" + variableId + "}}\u0026box\u003d" + box
}
]
}
],
compatibilityVersion: 78,
variables: [
{
flags: 1,
id: variableId,
key: "flaque_drop",
urlEncode: true
}
],
version: 1
}, null, "\t");
forceDL("FLAQUE_DROP.json", "data:application/json;base64," + btoa(shortcutJSON));
};
window.addEventListener(
"load",
() =>
document.querySelector("form")
.addEventListener(
"submit",
evt => {
evt.preventDefault();
const dat = Object.fromEntries(new FormData(evt.target));
plouf(dat["flaque"], dat["email"]);
return false;
}
)
);URL drop#
Simple HTTP GET request{FLAQUE_URL}/drop?lnk={MEDIA_LINK}&box={EMAIL_ADDRESS}
Optional email custom message&msg=enjoy the silence when the music's over
Guides [SOON]#
- Self hosting
- Port redirect
- Static IP
- Domain name
- Dynamic DNS
- Let's Encrypt
- Self-signed
- Py managed env
- pipx
- Docker
- Raspberry
- ...
How it works#
- Wait for order (link + email address)
- Validate link, email, status, limits
- Queue order, processed one by one
- Download file
- Process order
- Parse metadata
- Extract or fetch image
- Create archive if needed
- Move file to user directory
- Email download link
- Next order
Database#
flaque_drops : orders tracking
- hash : drop hash
- date : timestamp
- www : portal, Qobuz / Tidal / Alldebrid
- typ : media type, album / track / host
- uid : keep download links, optional, can be disabled
- stt : drop state (wait it, load it, parse it, zip it, send it, mail, delete it)
- box : email address hash
- ip : ip address hash
flaque_tracks : web player tracks
- hash : drop hash
- box : owner email hash
- file : file name
- artist : track artist
- album : track album
- title : track title
- dur : track duration
- ext : file type
- size : file size
- samp : sample rate
- bits : bit depth
- rate : bitrate
- tags : custom tags [SOON]
flaque_files : downloaded files
- hash : drop hash
- box : owner email hash
- date: timestamp
- file : file name
- ext : file type
- size : file size
Storage#
Flaque drops directory structure
tmp : temporary storage
{email_hash} : user directory
live : user music library
{drop_hash}
lossless flac
320kbps mp3
cover jpg
file : user downloads
{drop_hash}
file || archiveCompile#
- Open terminal in Flaque directory
- Install necessary packages
npm install google-closure-compiler sass - Optional : obfuscate JS code
npm install javascript-obfuscator - Run compilation script
npm run compile
Credits#
nodejs, nodemailer, archiver, python, qobuz-dl, tidal-dl-ng, alldebrid, music-metadata, tmdb, pdf.js, skr canvas, ffmpeg, fontawesome, closure compiler, sass, javascript-obfuscator
Disclaimer#
⚠️ No liability for any damages or issues
🚫 No responsibility for how this software is used
🎶 Good vibes
〜ヽ(⌐■_■)ノ♪♬