difference.py 3.6 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. from enum import Enum
  2. from typing import List, Union
  3. ujson = False
  4. try:
  5. import ujson as json
  6. ujson = True
  7. except ImportError:
  8. import json
  9. class Operation(Enum):
  10. """Класс перечисления типов операций для изменения плейлиста.
  11. Note:
  12. Существует две операции: вставка, удаление.
  13. """
  14. INSERT = 'insert'
  15. DELETE = 'delete'
  16. class Difference:
  17. """Класс, представляющий обёртку над созданием данных для запроса изменения плейлиста.
  18. Note:
  19. Результатом является перечень (массив) операций, которые будут применены к плейлисту.
  20. Конечной разницей (набором операций) является JSON, который будет отправлен в теле запроса.
  21. Attributes:
  22. operations (:obj:`list` из :obj:`dict`): Перечень операция для изменения плейлиста.
  23. """
  24. def __init__(self) -> None:
  25. self.operations = []
  26. def to_json(self) -> str:
  27. """Сериализация всех операций над плейлистом.
  28. Returns:
  29. :obj:`str`: Сформированное тело для запроса.
  30. """
  31. return json.dumps(self.operations, ensure_ascii=not ujson)
  32. def add_delete(self, from_: int, to: int) -> 'Difference':
  33. """Добавление операции удаления.
  34. Note:
  35. Передаётся диапазон для удаления треков.
  36. Args:
  37. from_ (:obj:`int`): С какого индекса.
  38. to (:obj:`int`): По какой индекс.
  39. Returns:
  40. :obj:`yandex_music.utils.difference.Difference`: Набор операций над плейлистом.
  41. """
  42. operation = {'op': Operation.DELETE.value, 'from': from_, 'to': to}
  43. self.operations.append(operation)
  44. return self
  45. def add_insert(self, at: int, tracks: Union[dict, List[dict]]) -> 'Difference':
  46. """Добавление операции вставки.
  47. Note:
  48. В `tracks` передаётся словарь с двумя ключами: `id`, `album_id`. Это нужно для формирования операции.
  49. Args:
  50. at (:obj:`int`): Индекс для вставки.
  51. tracks (:obj:`dict` | :obj:`list: из :obj:`dict`): Словарь уникальными идентификаторами треков.
  52. Returns:
  53. :obj:`yandex_music.utils.difference.Difference`: Набор операций над плейлистом.
  54. """
  55. # TODO (MarshalX) принимать TrackId, а так же строку и сплитить её по ":".
  56. # При отсутствии album_id кидать исключение.
  57. # https://github.com/MarshalX/yandex-music-api/issues/558
  58. if not isinstance(tracks, list):
  59. tracks = [tracks]
  60. operation = {'op': Operation.INSERT.value, 'at': at, 'tracks': []}
  61. for track in tracks:
  62. # TODO (MarshalX) replace to normal TrackId object
  63. # https://github.com/MarshalX/yandex-music-api/issues/558
  64. track = type('TrackId', (), track)
  65. operation['tracks'].append({'id': track.id, 'albumId': track.album_id})
  66. self.operations.append(operation)
  67. return self