Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Получение FLAC'ов #656

Open
ArtemBay opened this issue Aug 23, 2024 · 10 comments
Open

Получение FLAC'ов #656

ArtemBay opened this issue Aug 23, 2024 · 10 comments
Labels
feature Новая функция или улучшение старой

Comments

@ArtemBay
Copy link

Эндпоинт

GET /get-file-info
Authorization: OAuth ...

Параметры

GET-параметры

  • ts - время создания запроса
  • trackId - ID трека
  • quality - качество трека
  • codecs - кодеки которые мы запрашиваем
  • transports - ?
  • sign - подпись

Ответ

Массив из объектов

  • trackId: str
  • quality: str
  • codec: str
  • bitrate: int
  • transport: str
  • size: int
  • gain: bool
  • urls: list
  • url: str
  • realId: str

Пример запроса

Запрос

GET /get-file-info?ts=1724399849&trackId=117708948&quality=lossless&codecs=flac%2Caac%2Che-aac%2Cmp3&transports=raw&sign=VLPICid1TFCXy27MK7jSoQE4BCPN4hCJ0BCvu2FauvU

Ответ

Ответ
{
  "invocationInfo": {
    "req-id": "1724399890495688-5104116694941670615",
    "hostname": "music-stable-back-sas-86.sas.yp-c.yandex.net",
    "exec-duration-millis": 11
  },
  "result" : {
    "downloadInfo": {
      "trackId": "117708948",
      "quality": "lossless",
      "codec": "flac",
      "bitrate": 0,
      "transport": "raw",
      "size": 0,
      "gain": false,
      "urls": [
        "https://strm-mar-126.strm.yandex.net/music-v2/raw/ysign1=0c9d45f401d2ff200b1fd9ce9323fb10a1588de90c1b5f317a4f75cf83945752,ts=66ca8754,secret_version=ver-1,kts=66c7d100,source=mds,pfx,sfx/0/13584909/2d936a4c.173543555.11.117708948/flac",
        "https://media.strm.yandex.net/music-v2/raw/ysign1=0c9d45f401d2ff200b1fd9ce9323fb10a1588de90c1b5f317a4f75cf83945752,ts=66ca8754,secret_version=ver-1,kts=66c7d100,source=mds,pfx,sfx/0/13584909/2d936a4c.173543555.11.117708948/flac"
      ],
      "url": "https://strm-mar-126.strm.yandex.net/music-v2/raw/ysign1=0c9d45f401d2ff200b1fd9ce9323fb10a1588de90c1b5f317a4f75cf83945752,ts=66ca8754,secret_version=ver-1,kts=66c7d100,source=mds,pfx,sfx/0/13584909/2d936a4c.173543555.11.117708948/flac",
      "realId": "117708948"
    }
  }
}
@ArtemBay ArtemBay added the feature Новая функция или улучшение старой label Aug 23, 2024
@ArtemBay
Copy link
Author

ArtemBay commented Aug 23, 2024

Пример запроса на питоне с генерацией подписи

#!/usr/bin/python3
from datetime import datetime

import hmac
import hashlib
import base64

import requests

SECRET = 'kzqU4XhfCaY6B6JTHODeq5'
TRACK_ID = '117708948'
TIMESTAMP = int(datetime.now().timestamp())


hmac_sign = hmac.new(SECRET.encode('utf-8'), f'{TIMESTAMP}{TRACK_ID}losslessflacaache-aacmp3raw'.encode('utf-8'), hashlib.sha256)
sign = base64.b64encode(hmac_sign.digest()).decode('utf-8')[:-1]

print(TIMESTAMP)
print(sign)
print('-' * 15)

p = {'ts': TIMESTAMP, 'trackId': TRACK_ID, 'quality': 'lossless', 'codecs': 'flac,aac,he-aac,mp3', 'transports': 'raw', 'sign': sign}
h = {
    'Authorization': 'TOP SECRET',
    'X-Yandex-Music-Client': 'YandexMusicDesktopAppWindows/5.13.2'

}

resp = requests.get(f'https://api.music.yandex.net/get-file-info', params=p, headers=h)
print(resp.text)

Значение в переменной SECRET статично, но не исключаю факт что оно может со временем измениться. Получалось кровью и потом из десктопного приложения ЯМ

@ArtemBay
Copy link
Author

ArtemBay commented Aug 23, 2024

OAuth в токене обязателен. Если использовать токен который получается этим способом, то хедер авторизации должен выглядеть вот так 'Authorization': 'OAuth AQAAAAAQ###############################'

@direct-dok
Copy link

OAuth в токене обязателен. Если использовать токен который получается этим способом, то хедер авторизации должен выглядеть вот так 'Authorization': 'OAuth AQAAAAAQ###############################'

Привет) а если не секрет, какой прогой трафик слушал?

@ArtemBay
Copy link
Author

OAuth в токене обязателен. Если использовать токен который получается этим способом, то хедер авторизации должен выглядеть вот так 'Authorization': 'OAuth AQAAAAAQ###############################'

Привет) а если не секрет, какой прогой трафик слушал?

mitm proxy, но вообще просто через дев тулсы в десктопной версии яндекс музыки (которая новая на электроне). Оттуда я все штуки и вытянул типа секрета и принципа создания подписи

@Sorrow446
Copy link

Если кто-то готов одолжить мне свой аккаунт Plus, я могу написать инструмент для скачивания музыки с Яндекса с поддержкой lossless. Я не могу получить Plus, потому что британские кредитные карты не принимаются.

Проверьте мои репозитории, если у вас есть подозрения, у меня большой опыт написания музыкальных инструментов и реинжиниринга музыкальных стриминговых сервисов. Если вы готовы, напишите мне в Telegram. Спасибо. Извините за плохой русский, я использовал сервис перевода.

@ArtemBay
Copy link
Author

Если кто-то готов одолжить мне свой аккаунт Plus, я могу написать инструмент для скачивания музыки с Яндекса с поддержкой lossless. Я не могу получить Plus, потому что британские кредитные карты не принимаются.

Проверьте мои репозитории, если у вас есть подозрения, у меня большой опыт написания музыкальных инструментов и реинжиниринга музыкальных стриминговых сервисов. Если вы готовы, напишите мне в Telegram. Спасибо. Извините за плохой русский, я использовал сервис перевода.

Я уже сделал для себя, можешь исправить/дописать некоторые моменты (Как посмотрел, стоит только переписать получение плейлистов и исправить говнокод с кучей условий. Я тогда не особо разбирался с тем как оно работает, просто взял ссылку которую мне выдал яндекс в приложении)
yam.txt

@Sorrow446
Copy link

Я пишу свой инструмент на языке Rust. Да, я планирую реализовать поддержку плейлистов. Моя проблема в том, что единственный способ получить токен - это перехватить приложение для Android и Windows. Я хочу автоматизировать получение токена. Куки здесь не разрешают lossless: https://yandex-music.readthedocs.io/en/main/token.html

@Sorrow446
Copy link

Sorrow446 commented Sep 29, 2024

Мне больше не нужна учетная запись Plus, чтобы я мог пронюхать о приложениях Windows. Я публично поделюсь своим инструментом, когда он будет готов.

@llistochek
Copy link

Может кому пригодится.
Функция получения информации для скачивания с использованием дефолтной подписи (на основе скрипта от @ArtemBay):

import base64
import hashlib
import hmac
import typing
from dataclasses import dataclass
from datetime import datetime

from yandex_music import Track
from yandex_music.utils.sign_request import DEFAULT_SIGN_KEY


@dataclass
class LosslessDownloadInfo:
    quality: str
    codec: str
    urls: list[str]
    bitrate: int


def get_lossless_info(track: Track) -> LosslessDownloadInfo:
    client = track.client
    assert client
    timestamp = int(datetime.now().timestamp())
    params = {
        "ts": timestamp,
        "trackId": track.id,
        "quality": "lossless",
        "codecs": "flac,aac,he-aac,mp3",
        "transports": "raw",
    }
    res = "".join(str(e) for e in params.values()).replace(",", "")
    hmac_sign = hmac.new(
        DEFAULT_SIGN_KEY.encode(),
        res.encode(),
        hashlib.sha256,
    )
    sign = base64.b64encode(hmac_sign.digest()).decode()[:-1]
    params["sign"] = sign

    resp = client.request.get(
        "https://api.music.yandex.net/get-file-info", params=params
    )
    resp = typing.cast(dict, resp)
    e = resp["download_info"]
    return LosslessDownloadInfo(
        quality=e["quality"], codec=e["codec"], urls=e["urls"], bitrate=e["bitrate"]
    )

@vectorserver
Copy link

vectorserver commented Dec 17, 2024

OAuth в токене обязателен. Если использовать токен который получается этим способом, то хедер авторизации должен выглядеть вот так 'Authorization': 'OAuth AQAAAAAQ###############################'

Привет) а если не секрет, какой прогой трафик слушал?

mitm proxy, но вообще просто через дев тулсы в десктопной версии яндекс музыки (которая новая на электроне). Оттуда я все штуки и вытянул типа секрета и принципа создания подписи

Метод генерации подписи я тоже нашел, а вто как получить secretKey я, так и не допер)

...
generateSign: async function (secretKey, data) {
        const encoder = new TextEncoder();
        const keyData = encoder.encode(secretKey);
        const cryptoKey = await crypto.subtle.importKey(
            'raw',
            keyData,
            {name: 'HMAC', hash: {name: 'SHA-256'}},
            false,
            ['sign']
        );

        const dataEncoded = encoder.encode(data);
        const signature = await crypto.subtle.sign(
            'HMAC',
            cryptoKey,
            dataEncoded
        );

        return btoa(String.fromCharCode(...new Uint8Array(signature))).slice(0, -1);
    },
    fetchFileInfo: async function (trackId) {
        const secretKey = 'kzqU4XhfCaY6B6JTHODeq5';
        const timestamp = Math.floor(Date.now() / 1000);
        const dataToSign = `${timestamp}${trackId}losslessflacaache-aacmp3raw`;
        const sign = await appYa.generateSign(secretKey, dataToSign);

        console.log(timestamp);
        console.log(sign);
        console.log('-'.repeat(15));

        const params = new URLSearchParams({
            ts: timestamp,
            trackId: trackId,
            quality: 'lossless',
            codecs: 'flac,aac,he-aac,mp3',
            transports: 'raw',
            sign: sign
        });

        const headers = new Headers({
            'Authorization': 'TOP SECRET',
            'X-Yandex-Music-Client': 'YandexMusicDesktopAppWindows/5.13.2'
        });

        const url = `https://api.music.yandex.net/get-file-info?${params.toString()}`;

        try {
            const response = await fetch(url, {headers});
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            const data = await response.text();
            console.log(data);
            return data;
        } catch (error) {
            console.error('Error fetching file info:', error);
        }
    },

...```

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Новая функция или улучшение старой
Projects
None yet
Development

No branches or pull requests

5 participants