Skip to content
main
Switch branches/tags
Code

Latest commit

 

Git stats

Files

Permalink
Failed to load latest commit information.
Type
Name
Latest commit message
Commit time
 
 
 
 
 
 
 
 
 
 
 
 

YM-API - Unofficial Swift Yandex Music Library

Fully ported Yandex Music API Swift implementation.

Russian Readme (Readme на русском)

Thanks to MarshalX for his Yandex Music API research and the python library.

Content

Introduction

The library provides an interface for interacting with the Yandex Music API.

macOS 10.14+ and iOS 10.0+ are supported by the module.

Yandex personal data access

Constant values CLIENT_ID and CLIENT_SECRET were borrowed from the Yandex Music official application at Microsoft Store. Since the API is private and only used internally, it is impossible to register own application for now on oauth.yandex.ru, and therefore, use your own constant values.

Setup

YM-API is available with CocoaPods. To install a module, just add the module name to the Podfile:

  • iOS
platform :ios, '10.0'
...
pod 'YM-API'
  • macOS
platform :osx, '10.14'
...
pod 'YM-API'

Getting started

You can interact with the API throw YMClient instance.

You can initialize the client in 2 ways:

Basic, at first launch or logout state

import YM_API

let client = YMClient.initialize(device: YMDevice, lang: ApiLanguage)

device parameter - Device info. Essentially needed during working with play queues

let device = YMDevice(os: "iOS", osVer: "14.6", manufacturer: "Apple",
    model: "iPhone8,4", clid: "app-store", 
    deviceId: UUID().uuidString.replacingOccurrences(of: "-", with: "").lowercased(),
    uuid: UUID().uuidString.replacingOccurrences(of: "-", with: "").lowercased())

lang parameter - Yandex Music localization. There are 7 options to choose from:

enum ApiLanguage: String {
    case en//English
    case uz//Uzbek
    case uk//Ukrainian
    case us//English (US)
    case ru//Russian
    case kk//Kazakh
    case hy//Armenian
}

Extended, if there is an active session

import YM_API

let client = YMClient.initialize(device: YMDevice, lang: ApiLanguage, 
    uid: Int, token: String, xToken: String)

uid parameter - Account ID

token parameter - Account token

xToken parameter - Passport Yandex access token

To work with the service in the absence of an active session, you must sign in.

Sign in by login and password (mark as deprecated, but is supported by Yandex for now):

client.authByCredentials(login: String, pass: String, captchaAnswer: nil, 
    captchaKey: nil, captchaCallback: nil) { result in
    //Actions with the result of the query
}

Sign in by login and password with new authorization system (passport.yandex):

Method 1

client.initializeAuthorization(login: login) { result in
    //Get trackID for continue process
    ...
    self.client.authorizeWithPassword(trackId: trackId, pass: pass, 
    captchaAnswer: nil, captchaKey: nil, captchaCallback: nil) { result2 in
        //Get XPassport response object with authorization status 
        //(ok with xToken or error with description)
        //'xToken' may be also saved for user avatar retrieving
        ...
        self.client.generateYMTokenFromXToken(xToken: xRespObj.x_token!) { result3 in
        ///Get generated access token for Yandex Music API service
        }
    }
}

Method 2

client.authByCredentials(login: login, pass: pass, trackId: trackId, captchaAnswer: nil, captchaKey: nil, captchaCallback: nil, xToken: xToken) { result in
    do {
        let dict = try result.get()
        //Fully authorized account (with X Token)
        completion(.success(dict))
    } catch YMError.unfinishedAuthorization(let apiTrackId, let apiXToken, let err) {
        //Error during some authorization step (generating trackId, sending pass and getting XPassport instacne)
        if (retries - 1 >= 0) {
            self.newAuthMethod(login: login, pass: pass, trackId: apiTrackId, xToken: apiXToken, retries: retries - 1, completion: completion)
        } else {
            completion(.failure(YMError.unfinishedAuthorization(trackId: apiTrackId, xToken: apiXToken, innerErr: err)))
        }
    } catch {
        if (retries - 1 >= 0) {
            self.newAuthMethod(login: login, pass: pass, trackId: trackId, xToken: xToken, retries: retries - 1, completion: completion)
        } else {
            completion(.failure(.unfinishedAuthorization(trackId: trackId, xToken: xToken, innerErr: error)))
        }
    }
}

Usage examples

If you have an initialized client with authorized session, you can use all available methods from the API.

Retrieving a list of generated daily playlists in the context of the feed

client.getFeed { result in
    guard let feed = try? result.get() else {return}
    let playlists = feed.generatedPlaylists
}

Retrieving playlist tracks data

Option with calling a function from a playlist track instance

playlist.tracks?[index].fetchTrack(completion: { result in
    //Actions with track data
})

Option with calling a function from a client instance

let trackIds = playlist.tracks?.map{ track in return track.trackId }
client.getTracks(trackIds: trackIds, positions: false) { result in
    //Actions with tracks data
}

Retrieving the track download link

var track: Track!
... acquiring track data...
track.getDownloadLink(codec: .mp3, bitrate: .kbps_192) {result in
    //Actions with download link
}

Application example

An application for iOS (10.0+) was created for this API. It implements a working minimum: playlists generated by Yandex, displaying its content, playing songs including local play queue, the ability to like or dislike them, display the 'my collection' tracks with the ability to listen and search tracks. Also you can use this app on CarPlay through control centre trick. Its source code is publicly available.

Visit this page, to see the example application source.

Setup application ways

This application can be installed on your device for testing in several ways:

Free and simple

You need mac and XCode. Plus you need to have a basic developer account (without paid license) and the Apple device added to it. Update the pod dependencies in the project and just compile the sample application project for your device. The installed application will be available for 7 days due to the limitations of the basic developer account.

Advanced and paid

You need mac and and a developer account with a paid license. On the Apple Developer site you need to prepare the infrastructure for uploading: certificates, application ID (basic capabilities set), provision profiles set. So you can use the application not only on your personal device (App Store Connect public testing throw TestFlight) and not for 7 days. P.S. And if you want to show the whole breadth of your soul and, perhaps, thank the creator, you can upload the application to TestFlight for open testing and share the link, which I will post here =)

Getting help

If you find problems or want to suggest a new feature in the API itself create an issue

I don't plan to add anything cardinal to the application itself - it is an example of using the API

License

You can copy, distribute and modify the software provided that modifications are described and licensed free of charge in accordance with c LGPL-3. Artworks derivatives (including modifications or anything statically linked to the library) may only be distributed in accordance with the LGPL-3, but applications that use a library, optional.