Python Library Media
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

CDDB.py 4.7KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. import urllib
  2. import socket
  3. import os
  4. import urllib.parse
  5. import urllib.request
  6. import subprocess
  7. import logging
  8. from .common import KEY_ALBUM, KEY_ARTIST, KEY_GENRE, KEY_TITLE, KEY_TRACK, KEY_YEAR
  9. try:
  10. from config import APP_NAME as ROOT_LOGGER_NAME
  11. except ImportError:
  12. ROOT_LOGGER_NAME = 'root'
  13. logger = logging.getLogger(ROOT_LOGGER_NAME).getChild(__name__)
  14. version = 2.0
  15. if 'EMAIL' in os.environ:
  16. (default_user, hostname) = os.environ['EMAIL'].split('@')
  17. else:
  18. default_user = os.environ.get('USER') or os.geteuid() or 'user'
  19. hostname = socket.gethostname() or 'host'
  20. proto = 6
  21. default_server = 'http://gnudb.gnudb.org/~cddb/cddb.cgi'
  22. def my_disc_metadata(**kwargs):
  23. """Generate my disc metadata
  24. kwargs needs to include the following data:
  25. * KEY_ARTIST (str)
  26. * KEY_ALBUM (str)
  27. * KEY_YEAR (int) - will be converted here
  28. * KEY_GENRE (str)
  29. * "track_xx" (str) - where xx is the track number which will be converted to int here
  30. """
  31. main_dict = {}
  32. for key in [KEY_ARTIST, KEY_ALBUM, KEY_YEAR, KEY_GENRE]:
  33. try:
  34. value = kwargs.pop(key)
  35. except KeyError:
  36. logger.error("Information is missing in kwargs - key=%s", key)
  37. return None
  38. if key in [KEY_YEAR]:
  39. try:
  40. main_dict[key] = int(value)
  41. except ValueError:
  42. logger.error("Can't convert %s (key=%s) to integer value", value, key)
  43. return None
  44. else:
  45. main_dict[key] = value
  46. rv = dict(main_dict)
  47. rv["tracks"] = []
  48. for key in list(kwargs):
  49. value = kwargs.pop(key)
  50. if key.startswith("track_"):
  51. track = dict(main_dict)
  52. try:
  53. track[KEY_TRACK] = int(key[6:])
  54. except ValueError:
  55. logger.warning("Useless information kwargs - kwargs[%s] = %s", key, repr(value))
  56. track[KEY_TITLE] = value
  57. rv["tracks"].append(track)
  58. else:
  59. logger.warning("Useless information kwargs - key=%s", key)
  60. return rv
  61. def query(data_str, server_url=default_server, user=default_user, host=hostname, client_name=ROOT_LOGGER_NAME, client_version=version):
  62. url = f"{server_url}?cmd=cddb+query+{data_str}&hello={user}+{host}+{client_name}+{client_version}&proto={proto}"
  63. response = urllib.request.urlopen(url)
  64. header = response.readline().decode("utf-8").rstrip().split(" ", 3)
  65. header[0] = int(header[0])
  66. if header[0] not in (210, ):
  67. logger.error("Error while querying cddb entry: \"%d - %s\"", header[0], header[3])
  68. return None
  69. rv = {}
  70. for line in response.readlines():
  71. line = line.decode("utf-8").rstrip()
  72. if line == '.': # end of matches
  73. break
  74. dummy, did, txt = line.split(" ", 2)
  75. rv[did] = txt
  76. return rv
  77. def cddb(disc_id, server_url=default_server, user=default_user, host=hostname, client_name=ROOT_LOGGER_NAME, client_version=version):
  78. KEY_TRANSLATOR = {
  79. "DGENRE": KEY_GENRE,
  80. "DYEAR": KEY_YEAR
  81. }
  82. #
  83. url = f"{server_url}?cmd=cddb+read+data+{disc_id}&hello={default_server}+{hostname}+{client_name}+{client_version}&proto={proto}"
  84. response = urllib.request.urlopen(url)
  85. header = response.readline().decode("utf-8").rstrip().split(" ", 3)
  86. header[0] = int(header[0])
  87. if header[0] not in (210, ):
  88. logger.error("Error while reading cddb entry: \"%d - %s\"", header[1], header[3])
  89. return None
  90. data = {}
  91. for line in response.readlines():
  92. line = line.decode("utf-8").rstrip()
  93. if line == '.': # end of matches
  94. break
  95. if not line.startswith("#"):
  96. match = line.split('=', 2)
  97. key = KEY_TRANSLATOR.get(match[0])
  98. value = match[1].strip()
  99. if key:
  100. if key == KEY_YEAR:
  101. value = int(value)
  102. data[key] = value
  103. elif match[0] == "DTITLE":
  104. art_tit = value.split("/", 2)
  105. data[KEY_ARTIST] = art_tit[0].strip()
  106. data[KEY_ALBUM] = art_tit[1].strip()
  107. elif match[0].startswith("TTITLE"):
  108. data["track_%02d" % (int(match[0][6:]) + 1)] = value
  109. else:
  110. logger.debug("cddb line ignored: \"%s\"", line)
  111. return my_disc_metadata(**data)
  112. def discid():
  113. discid_cmd = subprocess.getoutput("which cd-discid")
  114. if not discid_cmd:
  115. logger.error("cd-discid is required for encoding. You need to install it to your system.")
  116. return None
  117. else:
  118. try:
  119. return subprocess.check_output(discid_cmd).decode("utf-8").strip().replace(" ", "+")
  120. except subprocess.CalledProcessError as e:
  121. return None