Comment j'ai écrit une bibliothèque pour le service Yandex.Music

Présentation


À propos de moi


Bonjour à tous, je suis un étudiant ordinaire dans la spécialité "technicien logiciel". Depuis l'enfance, j'aime les ordinateurs, depuis la 7e année j'ai commencé à apprendre la programmation elle-même. Je suis propriétaire d'un abonnement à Yandex Music depuis plus d'un an et je suis généralement satisfait du service (bien qu'il y ait maintenant des répétitions continues dans la playlist du jour).


Contexte


Je ne me souviens pas exactement pourquoi j'ai décidé de rechercher la documentation officielle de l'API pour ce service, comme un bot que je voulais écrire pour Telegram, mais je suis tombé sur le fait que ce n'était pas le cas ... Après un certain temps, j'ai rencontré un problème dans le référentiel yandex / audio-js . Là, les gars posent exactement la même question que moi: "Où est l'API?" Peu de gens sont impatients d'écouter de la musique via un navigateur, ils veulent une application, mais il n'y a pas non plus d'application Linux! L'intégration à votre joueur préféré est impossible!


Puis j'ai eu l'idée de le faire. Naturellement, je dois en quelque sorte travailler avec le service, faire des béquilles autour d'une application Web n'est pas une option. J'ai compris qu'avoir un tel service, avoir des applications mobiles et Windows (du Microsoft Store), il est tout simplement impossible de ne pas avoir sa propre API interne pour l'interaction. J'avais raison!


Lecture obligatoire devant l'instance principale


Je suis conscient qu'en étudiant leur API non publique, je fouille dans les choses sales des autres. Ci-dessous seront décrites diverses questions controversées, les décisions des développeurs et, en général, comment ils l'ont écrit et comment ils l'utilisent. À certains endroits, j'étais juste choqué , mais je suis sûr que s'ils le faisaient, il y avait des raisons à cela ! N'oublions pas que personne n'aurait dû voir ça. Je tiens également à dire que tout ce qui est écrit ci-dessous est mon opinion . Vous pouvez être d'accord avec lui ou non.


Corps principal


La préparation


API d'application Web


Ci-dessus, j'ai déjà écrit que j'avais trouvé l'API. Ce n'était pas du tout difficile. Tout d'abord, j'ai regardé leur application Web, leur point de terminaison au moment de la rédaction est ici: https://music.yandex.ru/api/v2.1/ . Ils ont des URL suffisamment longues dans lesquelles je participe aux données, et ils envoient également le formulaire. Je vous demande également de faire attention à indiquer la version de l'API , elle l' est .


Vous devez comprendre que ce que j'ai trouvé n'est utilisé par eux que dans une application Web. Il n'y a pas d'OAuth. Plus précisément, il a plus de chances d'exister, mais là, dans les entrailles de notre séance sur le site. En général, la bibliothèque ne convient pas pour les béquilles en autorisation.


API d'application


Je me mis à chercher plus loin. J'étais trop paresseux pour prendre le téléphone, donc j'allais en dernier aux applications mobiles. À cette époque, l'ordinateur exécutait Windows 10 et j'ai activement utilisé l'application officielle Yandex Music du Microsoft Store . En conséquence, j'ai commencé à étudier comment cela fonctionne.


Pour la recherche, j'avais besoin d'un renifleur pour suivre tout le trafic des applications. Vous pouvez utiliser Wireshark , mais je me suis installé sur HTTP Analyzer . Il me semble plus léger et parfaitement adapté à ma tâche.


Allumez le renifleur, accédez à l'application et vous avez terminé. Les demandes sont acheminées par flux. Nous nous asseyons, comprenons, essayons d'appeler chaque gestionnaire qui se trouve dans cette application et découvrons toutes les méthodes existantes, leurs arguments et, bien sûr, les réponses JSON .


Capture d'écran d'une des demandes


De la capture d'écran ci-dessus, vous pouvez immédiatement remarquer une adresse API complètement différente - api.music.yandex.net . De plus, faites attention aux rubriques. En plus des informations sur mon client à partir duquel la demande a été faite, il existe un jeton OAuth - c'est ce dont vous avez besoin!


API d'apprentissage


L'étude a eu lieu en même temps que l'écriture du code. J'ai écrit des classes wrapper pour les objets de service reçus de l'API, implémenté l'envoi de requêtes, trié les paramètres et à certains endroits, j'ai juste deviné ce que ce nom pouvait signifier. À ce stade, j'ai rencontré diverses choses que je ne m'attendais pas à voir ici.


Au moment de la rédaction, la bibliothèque contient 83 classes, et seules certaines d'entre elles sont auxiliaires. Les autres sont des cours de musique Yandex, qui indiquent l'ampleur de ce service et le niveau d'abstractions.


L'envoi de 47 méthodes a été implémenté. Et ce n'est pas tout ce qui se trouve dans l'API (plus d'informations ci-dessous).


La douleur


Au début, j'ai essayé de ne pas faire attention, j'ai été simplement surpris, car c'est Yandex , comment cela peut-il être. Mais ensuite, à un moment précis, tout a explosé. Je vais peut-être commencer par lui.


  1. Deux objets avec différents niveaux d'attachement au champ


    Nouvelle version de l'objet


    L'objet lui-même n'est qu'une «référence» à lui-même. Pour sa version complète. Lorsque nous demandons une liste de pistes, nous recevons leur identifiant, grâce auquel nous pouvons obtenir des informations plus détaillées. De bonnes pratiques, beaucoup le font, mais elles ne sont pas toujours respectées (paragraphe 9).


    Ancienne version de l'objet


    Ayant implémenté la classe pour cet objet au tout début, j'ai pensé que je l'utiliserais partout, mais peu importe comment! Il me semble que les commentaires sont superflus et tout peut être vu dans les captures d'écran.


    Je n'ai pas réparé ce type de montants dans ma bibliothèque, donc avoir la classe TrackShortOld a maintenant TrackShortOld .


    Soit dit en passant, ces deux objets vivent dans la même méthode, dans la méthode d' atterrissage .


  2. Versions, méthodes d'API


    Je ne vous ai pas simplement demandé de prêter attention à la façon dont la version est spécifiée dans l'API de l'application Web. Généralement, comment indique-t-on habituellement une version? Probablement de l'une des manières suivantes:


    • faire la version sur un sous-domaine séparé;
    • mettre la version dans la partie demande;
    • passez la version souhaitée du paramètre API à la demande.

    Yandex a décidé dans ce cas de faire autrement. Nous avons une méthode landing3 - sa version actuelle au moment de la rédaction. Mais personne n'interdit d' envoyer une demande d' atterrissage2 - une structure complètement différente, d'autres objets.


    J'ai découvert cela tout à fait par accident, oubliant simplement d'ajouter un nombre à la fin du nom de la méthode et interceptant un tas d'exceptions.


  3. Travailler avec le nouveau, ne pas abandonner l'ancien


    Je l'ai vu quand j'ai écrit des méthodes d'envoi "Like" pour tous les objets qui le sont. Il n'y en a pas beaucoup (playlist, artiste, piste, album). Quelle a été ma surprise quand j'ai vu différentes approches de la même action.


    Nous aimons les artistes comme celui-ci: https://api.music.yandex.net/users/<USER_ID>/likes/artists/add et transférer l' artist-id dans le formulaire.


    Nous aimons les pistes comme celle-ci: https://api.music.yandex.net/users/<USER_ID>/likes/tracks/add-multiple et sous la forme de track-ids .


    Si vous ne l'avez pas remarqué, alors quand vous aimez la piste, la méthode add-multiple est utilisée, pas add . Cette méthode n'est utilisée avec aucun autre type, mais elles existent toutes (cela valait la peine d'essayer d'envoyer une demande)! Et je les ai implémentés dans ma bibliothèque au lieu d'en ajouter . Après tout, cette méthode est universelle. Vous pouvez ajouter une ou plusieurs pistes.


  4. Qu'est-ce qu'un identifiant de piste unique


    Beaucoup de temps s'est écoulé, mais je ne comprends toujours pas quand envoyer uniquement l' id la piste, et quand l'identifiant et l'album_id sont concaténés via deux points ( id:album_id ). Parfois une piste est dans plusieurs albums, parfois il n'y a pas d'album. Cas trop obscurs en regardant de côté, je ne sais pas comment ils gèrent cela (ou je ne peux pas le faire, bagus 2).


  5. Nombreux champs facultatifs


    J'ai eu quelques problèmes. S'il y a un problème, il est lié au champ requis. Je ne cesse d'être surpris de voir comment, à mon avis, les champs obligatoires ne renvoient tout simplement pas l'API.


    • album_id de la classe TrackID et TrackShort;
    • order_id de la classe AutoRenewable (abonnement);
    • next_revision dans Feed;
    • cover_uri dans Track;
    • anniversaire dans le compte;
    • balises dans la liste de lecture.

    La liste est longue, mais tout est dans l'histoire des commits. Peut-être que cet article est aspiré du doigt.


  6. Méthodes de similitude à l'exception de certains champs de la réponse


    Réponse sur l'état du compte ( api.music.yandex.net/account/status ):


    Réponse sur l'état du compte


    État du compte radio de réponse ( https://api.music.yandex.net/rotor/account/status ):


    Réponse radio de l'état du compte


    Je comprends que les droits sont différents, les champs sont maintenant avec une limite non pas sur le nombre de pistes dans le cache, mais sur le nombre de sauts par heure, mais cela ressemble plus à une sorte de duplication.


    Je ne sais pas comment dans Yandex, mais je l'ai fusionné en une seule classe.


  7. Donc un ou plusieurs?


    J'ai toujours pensé que si une méthode renvoie une liste, même si le résultat est un élément, la liste contenant cet élément sera renvoyée et rien d'autre, mais ici et là, et plus encore.


    fonctionnalité et fonctionnalités


    Cette fonctionnalité reviendra, puis les fonctionnalités , puis la fonctionnalité et les fonctionnalités .


  8. Utilisation abusive des méthodes


    Ci-dessus, j'ai écrit qu'ils utilisent l'une ou l'autre méthode pour effectuer une action. Ils sont allés plus loin.


    Envoi de morceaux supprimés lorsque le dos en est bien conscient


    En plus de l' ID de la liste de lecture et des images avec et par quelle piste supprimer, pour une raison quelconque, ils transfèrent les pistes à supprimer à la méthode de suppression des pistes de la liste de lecture. Il est possible que je n'aie pas compris cela, comme tout le reste, mais la méthode fonctionne sans trop d'informations. Et quelles pistes ont été supprimées, il vaut mieux le savoir au dos, que de passer par paramètre.


  9. Demandes très lourdes


    J'ai écrit ci-dessus que donner une liste avec les ID de piste est une bonne pratique, vous obtenez des informations détaillées sur une piste uniquement lorsque vous en avez vraiment besoin. Ce n'est pas toujours utilisé ici.


    Jetez un œil à la façon dont ils donnent sans pitié des informations détaillées sur tous mes morceaux de la liste de lecture "J'aime" en une seule demande:


    Demande lourde


    Il a donné les 396 pistes ! Octets reçus: 3,75 M , et ceci est un autre téléchargement de couverture!



Baguettes


  1. Téléchargez toutes les pistes dans le cache à partir de "J'aime"


    Lorsque la limite a été atteinte, un ajout a été fait à la fin et supprimé depuis le début. Merci pour la visualisation de la file d'attente, mais j'ai pensé que je ne ferais que télécharger les 100 derniers morceaux de la playlist. Cela s'est produit dans le client mobile pour Android ( regarder la vidéo ).


  2. On dirait que je ne suis pas confus quand je dois envoyer un identifiant, mais quand id: album_id


    Pistes en double



Remarques


Le nombre de tentatives d'activation du code cadeau est de 10. Prochaine interdiction pour 24 heures.


Selon l'application à partir de laquelle vous êtes assis, différentes offres vous sont proposées pour souscrire un abonnement.


La limite du nombre de pistes dans le cache est une illusion, c'est juste un nombre, et l'application ne vous permet pas de charger plus (bagus 2).


Toutes ces listes de lecture intelligentes, suggestions, couleurs de texte et de bouton proviennent de l'API - le voici, un vrai RESTFull.


L'heure de début de l'annonce et l'annonce elle-même sont renvoyées même si vous avez un abonnement.


Un lien vers XML contenant des données sur l'emplacement du fichier à télécharger dure 1 minute, puis une erreur 410.


Conclusion


Je n'ai écrit que ce dont je me souvenais. Après tout, j'ai rencontré tout cela pendant plusieurs mois. Toutes mes notes sont des messages dans un télégramme, parce que quand je suis tombé sur quelque chose comme ça, j'ai partagé avec des amis. J'ai essayé de restaurer les points clés.


Je ne voulais en aucun cas dire à quel point tout était mauvais, en quelque sorte pour mettre les jambages sur le public spécialement. Ce n'est peut-être pas du tout un montant, mais tout ce que j'ai écrit ci-dessus me semble personnellement étrange.


Il a partagé avec vous comment il a écrit la bibliothèque de l'API de service privée Yandex.Music et quelles choses il a rencontrées pendant le développement.


Vous savez maintenant comment et sur quoi fonctionne leur application Windows, et donc ma bibliothèque.


Au fait, maintenant j'essaie de tout documenter, lors de la documentation de ma bibliothèque, je documente automatiquement leur API. C'est serré, et j'ai encore besoin de temps pour trouver une entreprise pour passer par la pratique technologique industrielle.


Merci d'avoir lu jusqu'ici!

Source: https://habr.com/ru/post/fr462607/


All Articles