MarshalX / yandex-music-api

Неофициальная Python библиотека для работы с API сервиса Яндекс.Музыка
https://yandex-music.rtfd.io
GNU Lesser General Public License v3.0
930 stars 81 forks source link

Новый эндпоинт download-info #566

Open glebliutsko opened 1 year ago

glebliutsko commented 1 year ago

Эндпоинт

GET /tracks/{trackId}/download-info
Authorization: OAuth ...

Параметры

URL-параметры:

GET-параметры

Ответ

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

Пример запроса-ответа

Запрос

GET /tracks/565378/download-info?can_use_streaming=true&ts=1668329810&sign=5j8wlO7h6lcauv86ieL5JRkprxDjXe82YlYrGU1XY80%3D

Ответ

Ответ ```json { "invocationInfo": { "req-id": "1668329810397732-17408067972088390176", "hostname": "music-stable-back-vla-18.vla.yp-c.yandex.net", "exec-duration-millis": 1 }, "result": [{ "codec": "mp3", "gain": false, "preview": false, "downloadInfoUrl": "https://strm.yandex.ru/music/music-strm-jsons/565378.d445daf9/kaltura/760339.10.2/1668329930/1668332853/3892efdee525f66a1f4b8f8b417cf5393d96ec2e610ffa245648f0143f045768/master.m3u8?abc_id=94&from=ya-music", "direct": true, "container": "hls", "bitrateInKbps": 192 }, { "codec": "mp3", "gain": false, "preview": false, "downloadInfoUrl": "https://strm.yandex.ru/music/music-strm-jsons/565378.d445daf9/kaltura/760339.12.320/1668329930/1668332853/d4cbee26024962dd1ab601270183534bc1d255dbc72a423a6e99157e980ef089/master.m3u8?abc_id=94&from=ya-music", "direct": true, "container": "hls", "bitrateInKbps": 320 }, { "codec": "aac", "gain": true, "preview": false, "downloadInfoUrl": "https://strm.yandex.ru/music/music-strm-jsons/565378.d445daf9/kaltura/760339.9.g128/1668329930/1668332853/121a1f6e674d1bbf6b7d145dcc7cd74e64fbf47b6b3b0f29a653b3164e0b3992/master.m3u8?abc_id=94&from=ya-music", "direct": true, "container": "hls", "bitrateInKbps": 128 }] } ```
MarshalX commented 1 year ago

@glebliutsko А какой старый эндпоинт был на download info?

glebliutsko commented 1 year ago

@glebliutsko А какой старый эндпоинт был на download info?

Тот же самый кстати.

Щас потестил. Если can_use_streaming=false или его нету, то все работает как раньше, но если can_use_streaming=true, то просит подпись.

Причем приложение не использует can_use_streaming=false вообще, даже при скачивании.

MarshalX commented 1 year ago

@glebliutsko Которое приложение кстати смотришь? Чтобы я потом глянул как они подпись строят. Ведро или винда?

glebliutsko commented 1 year ago

@glebliutsko Которое приложение кстати смотришь? Чтобы я потом глянул как они подпись строят. Ведро или винда?

Ведро

MarshalX commented 1 year ago
  1. Надо посмотреть что с подписью
  2. Надо подумать стоит ли переезжать на их новый вариант загрузки всего или можно сидеть на старом пока они поддерживают это легаси
glebliutsko commented 1 year ago
  1. Надо подумать стоит ли переезжать на их новый вариант загрузки всего или можно сидеть на старом пока они поддерживают это легаси

Мне кажется можно оставть два. Кому-то и hls может пригодится. Тем более отличаются только параметрами

glebliutsko commented 1 year ago

Отреверсил подпись. Объяснять лень, поэтому вот код

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

import hmac
import hashlib
import base64

import requests

SECRET = 'p93jhgh689SBReK6ghtw62'
TRACK_ID = '108235280'
TIMESTAMP = int(datetime.now().timestamp())

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

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

p = {'can_use_streaming': 'true', 'ts': TIMESTAMP, 'sign': sign}
h = {
    'Authorization': 'TOP SECRET',
    'X-Yandex-Music-Client': 'YandexMusicAndroid/24022571'

}
resp = requests.get(f'https://api.music.yandex.net/tracks/{TRACK_ID}/download-info', params=p, headers=h)
print(resp.text)
Ktilis commented 1 year ago
SECRET = 'p93jhgh689SBReK6ghtw62'

Вопрос: переменная SECRET как-то изменяется, или она постоянная?

MarshalX commented 1 year ago

@Ktilis Всегда была постоянной если говорить про текущую реализацию

MarshalX commented 1 year ago

@glebliutsko Супер, спасибо! Полезная информация

glebliutsko commented 1 year ago

@Ktilis постоянная, она захардкоженна.

Ну точнее как захардкожена. Там такой метод.

public static String m13133if() {
    return kx5.m15650goto() ? "OsXPlRyQHP39vlrJjTDYd6" : kx5.m15653this() ? "Me0wlJDNpnE0joknU0YLUF" : "p93jhgh689SBReK6ghtw62";
}

Не знаю что делают kx5.m15650goto() и kx5.m15653this(), но у меня оно всегда возвращяло p93jhgh689SBReK6ghtw62

glebliutsko commented 1 year ago

Потыкал я в дебагере. Результаты такие

Вот эти два метода

public static String f17354if;

public static final boolean m27504goto() {
    String str = f17354if;
    if (str != null) {
        return ln7.m7493do(str, "yauto");
    }
    ln7.m28062final("platformFlavor");
    throw null;
}

public static final boolean m27506this() {
    String str = f17354if;
    if (str != null) {
        return ln7.m7493do(str, "yango");
    }
    ln7.m28062final("platformFlavor");
    throw null;
}

ln7.m7493do(a, b) -- сравнивает два объекта как-то по умному

public static boolean m7493do(Object obj, Object obj2) {
    return obj == null ? obj2 == null : obj.equals(obj2);
}

Свойство f17354if у меня ставится из класса YMApplication в gplay.

kx5.f17353do = "prod";
kx5.f17354if = "gplay";
kx5.f61253for = "release";

Видимо у них разные ключи в зависимости от сборки

Думаю если всегда использовать в заголовках X-Yandex-Music-Client: YandexMusicAndroid/24022571 проблем быть не должно