1.1.24 - FLAC for HiFi users
This commit is contained in:
parent
6302f54fbd
commit
53f6b760fe
|
@ -148,12 +148,12 @@
|
|||
"Save": "Zapisz",
|
||||
"Edit": "Edytuj",
|
||||
"Importer": "Importer",
|
||||
"Enter URL": "Enter URL",
|
||||
"Currently only Spotify is supported and limited to 100 tracks.": "Currently only Spotify is supported and limited to 100 tracks.",
|
||||
"Import into playlist": "Import into playlist",
|
||||
"Keep sidebar open": "Keep sidebar open",
|
||||
"WARNING: Might require reload to work properly!": "WARNING: Might require reload to work properly!",
|
||||
"An error occured, URL might be invalid or unsupported.": "An error occured, URL might be invalid or unsupported.",
|
||||
"Enter URL": "Wprowadź adres URL",
|
||||
"Currently only Spotify is supported and limited to 100 tracks.": "Obecnie obsługuje tylko Spotify i maksymalnie 100 utworów.",
|
||||
"Import into playlist": "Importuj na playlistę",
|
||||
"Keep sidebar open": "Panel boczny zawsze otwarty",
|
||||
"WARNING: Might require reload to work properly!": "UWAGA: Może wymagać ponownego uruchomienia, by działać poprawnie!",
|
||||
"An error occured, URL might be invalid or unsupported.": "Wystąpił błąd, adres URL może być nieprawidłowy lub nieobsługiwany.",
|
||||
"Top tracks": "Najpopularniejsze utwory",
|
||||
"Show all top tracks": "Pokaż wszystkie najpopularniejsze utwory",
|
||||
"Singles": "Single",
|
||||
|
@ -163,9 +163,9 @@
|
|||
"No": "Nie",
|
||||
"Download Filename": "Nazwa pobieranego pliku",
|
||||
"Language": "Język",
|
||||
"Background Image": "Background Image",
|
||||
"Enter URL or absolute path. WARNING: Requires reload!": "Enter URL or absolute path. WARNING: Requires reload!",
|
||||
"LGBT Mode": "LGBT Mode",
|
||||
"Native top bar": "Native top bar",
|
||||
"Requires restart of Freezer!": "Requires restart of Freezer!"
|
||||
"Background Image": "Obraz w tle",
|
||||
"Enter URL or absolute path. WARNING: Requires reload!": "Wprowadź adres URL lub całą ścieżkę pliku. UWAGA: Wymaga ponownego uruchomienia!",
|
||||
"LGBT Mode": "Tryb LGBT",
|
||||
"Native top bar": "Natywny górny pasek",
|
||||
"Requires restart of Freezer!": "Wymaga ponownego uruchomiania Freezera!"
|
||||
}
|
|
@ -236,7 +236,11 @@ new Vue({
|
|||
this.playbackInfo = playbackInfo;
|
||||
|
||||
//Stream URL
|
||||
let url = `${process.env.NODE_ENV === 'development' ? "http://localhost:10069" : window.location.origin}${this.playbackInfo.url}`;
|
||||
let url;
|
||||
if (this.playbackInfo.encrypted)
|
||||
url = `${process.env.NODE_ENV === 'development' ? "http://localhost:10069" : window.location.origin}${this.playbackInfo.url}`;
|
||||
else
|
||||
url = this.playbackInfo.direct;
|
||||
//Cancel loading
|
||||
this.loaders--;
|
||||
if (this.loaders > 0) {
|
||||
|
@ -424,7 +428,10 @@ new Vue({
|
|||
if (this.gapless.promise) resolve();
|
||||
}
|
||||
this.gapless.info = info
|
||||
if (info.encrypted)
|
||||
this.gapless.audio = new Audio(`${process.env.NODE_ENV === 'development' ? "http://localhost:10069" : window.location.origin}${info.url}`);
|
||||
else
|
||||
this.gapless.audio = new Audio(info.direct);
|
||||
this.gapless.audio.volume = 0.00;
|
||||
this.gapless.audio.preload = 'auto';
|
||||
this.gapless.crossfade = false;
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "freezer",
|
||||
"version": "1.1.20",
|
||||
"version": "1.1.23",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "freezer",
|
||||
"version": "1.1.20",
|
||||
"version": "1.1.23",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"arg": "^5.0.0",
|
||||
|
@ -18,6 +18,7 @@
|
|||
"cors": "^2.8.5",
|
||||
"discord-rpc": "^3.2.0",
|
||||
"express": "^4.17.1",
|
||||
"form-data": "^2.3.3",
|
||||
"lastfmapi": "^0.1.1",
|
||||
"metaflac-js2": "^1.0.7",
|
||||
"nedb": "^1.8.0",
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "freezer",
|
||||
"private": true,
|
||||
"version": "1.1.23",
|
||||
"version": "1.1.24",
|
||||
"description": "",
|
||||
"main": "background.js",
|
||||
"scripts": {
|
||||
|
|
|
@ -140,11 +140,37 @@ class DeezerAPI {
|
|||
this.token = data.results.checkForm;
|
||||
this.userId = data.results.USER.USER_ID;
|
||||
this.favoritesPlaylist = data.results.USER.LOVEDTRACKS_ID.toString();
|
||||
try {
|
||||
await this.authorizeAtv();
|
||||
} catch (e) {
|
||||
logger.warn(`Couldnt authorize ATV: ${e}`);
|
||||
}
|
||||
|
||||
if (!this.userId || this.userId == 0 || !this.token) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
//Authorize Android TV
|
||||
async authorizeAtv() {
|
||||
let res = await axios.post(
|
||||
"https://distribution-api.deezer.com/device/token",
|
||||
{"brand_name":"Hisense","device_id":"7239e4071d8992c955ad","model_name":"HE50A6109FUWTS","country_code":"FRA"}
|
||||
);
|
||||
let deviceToken = res.data.device_token;
|
||||
// Get unauthorized token
|
||||
res = await axios.get('https://connect.deezer.com/oauth/access_token.php?grant_type=client_credentials&client_id=447462&client_secret=a83bf7f38ad2f137e444727cfc3775cf&output=json');
|
||||
let accessToken = res.data.access_token;
|
||||
// Get smart login code
|
||||
res = await axios.post(`https://connect.deezer.com/2.0/smartlogin/device?access_token=${accessToken}&device_token=${deviceToken}`);
|
||||
let smartLoginCode = res.data.data.smartLoginCode;
|
||||
// Associate
|
||||
await this.callApi('deezer.associateSmartLoginCodeWithUser', {'SMARTLOGIN_CODE': smartLoginCode});
|
||||
// Get authorized token
|
||||
res = await axios.get(`https://connect.deezer.com/2.0/smartlogin/${smartLoginCode}?access_token=${accessToken}`);
|
||||
accessToken = res.data.data.accessToken;
|
||||
this.accessToken = accessToken;
|
||||
}
|
||||
|
||||
//Wrapper because electron is piece of shit
|
||||
async callPublicApi(path, params) {
|
||||
if (this.electron) return await this._callPublicApiElectron(path, params);
|
||||
|
@ -223,6 +249,30 @@ class DeezerAPI {
|
|||
return `https://e-cdns-proxy-${md5origin.substring(0, 1)}.dzcdn.net/mobile/1/${step3}`;
|
||||
}
|
||||
|
||||
//Generate url with android tv support
|
||||
async generateUrl(trackId, md5origin, mediaVersion, quality = 3) {
|
||||
if (quality == 9 && this.accessToken) {
|
||||
try {
|
||||
let res = await axios({
|
||||
method: 'GET',
|
||||
url: `https://api.deezer.com/platform/gcast/track/${trackId}/streamUrls`,
|
||||
headers: {
|
||||
"Authorization": "Bearer " + this.accessToken
|
||||
},
|
||||
responseType: 'json'
|
||||
});
|
||||
if (res.data.data.attributes.url_flac)
|
||||
return {encrypted: false, url: res.data.data.attributes.url_flac};
|
||||
} catch (e) {
|
||||
console.warn(`Failed getting ATV URL! Using normal: ${e}`)
|
||||
}
|
||||
}
|
||||
return {
|
||||
encrypted: true,
|
||||
url: DeezerAPI.getUrl(trackId, md5origin, mediaVersion, quality)
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
async fallback(info, quality = 3) {
|
||||
let qualityInfo = Track.getUrlInfo(info);
|
||||
|
@ -266,11 +316,15 @@ class DeezerAPI {
|
|||
//Fallback thru available qualities, -1 if none work
|
||||
async qualityFallback(info, quality = 3) {
|
||||
try {
|
||||
let res = await axios.head(DeezerAPI.getUrl(info.trackId, info.md5origin, info.mediaVersion, quality));
|
||||
let urlGen = await this.generateUrl(info.trackId, info.md5origin, info.mediaVersion, quality);
|
||||
let res = await axios.head(urlGen.url);
|
||||
if (res.status > 400) throw new Error(`Status code: ${res.status}`);
|
||||
//Make sure it's an int
|
||||
info.quality = parseInt(quality.toString(), 10);
|
||||
info.size = parseInt(res.headers['content-length'], 10);
|
||||
info.encrypted = urlGen.encrypted;
|
||||
if (!info.encrypted)
|
||||
info.direct = urlGen.url;
|
||||
return info;
|
||||
} catch (e) {
|
||||
logger.warn('Quality fallback: ' + e);
|
||||
|
|
|
@ -206,6 +206,7 @@ class DownloadThread {
|
|||
this.stopped = true;
|
||||
this.isUserUploaded = download.track.id.toString().startsWith('-');
|
||||
this.coverPath = null;
|
||||
this.encrypted = false;
|
||||
}
|
||||
|
||||
//Callback wrapper
|
||||
|
@ -262,9 +263,11 @@ class DownloadThread {
|
|||
this.download.downloaded = start;
|
||||
|
||||
//Download
|
||||
let url = DeezerAPI.getUrl(this.qualityInfo.trackId, this.qualityInfo.md5origin, this.qualityInfo.mediaVersion, this.qualityInfo.quality);
|
||||
let urlGen = await deezer.generateUrl(this.qualityInfo.trackId, this.qualityInfo.md5origin, this.qualityInfo.mediaVersion, this.qualityInfo.quality);
|
||||
this.encrypted = urlGen.encrypted;
|
||||
|
||||
if (this.stopped) return;
|
||||
this._request = https.get(url, {headers: {'Range': `bytes=${start}-`}}, (r) => {
|
||||
this._request = https.get(urlGen.url, {headers: {'Range': `bytes=${start}-`}}, (r) => {
|
||||
this._response = r;
|
||||
let outFile = fs.createWriteStream(tmp, {flags: 'a'});
|
||||
|
||||
|
@ -321,13 +324,18 @@ class DownloadThread {
|
|||
this.download.state = 2;
|
||||
|
||||
//Decrypt
|
||||
decryptor.decryptFile(decryptor.getKey(this.qualityInfo.trackId), tmp, `${tmp}.DEC`);
|
||||
let outPath = this.generatePath(this.qualityInfo.quality);
|
||||
await fs.promises.mkdir(path.dirname(outPath), {recursive: true});
|
||||
if (this.encrypted) {
|
||||
decryptor.decryptFile(decryptor.getKey(this.qualityInfo.trackId), tmp, `${tmp}.DEC`);
|
||||
await fs.promises.copyFile(`${tmp}.DEC`, outPath);
|
||||
await fs.promises.unlink(`${tmp}.DEC`);
|
||||
} else {
|
||||
await fs.promises.copyFile(tmp, outPath);
|
||||
}
|
||||
await fs.promises.unlink(tmp);
|
||||
|
||||
|
||||
let cover = null;
|
||||
|
||||
if (!this.isUserUploaded) {
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{
|
||||
"name": "freezer",
|
||||
"private": true,
|
||||
"version": "1.1.23",
|
||||
"version": "1.1.24",
|
||||
"description": "Freezer PC",
|
||||
"scripts": {
|
||||
"pack": "electron-builder --dir",
|
||||
|
|
Loading…
Reference in New Issue