spotifywebapiPython 1.0.45__py3-none-any.whl → 1.0.47__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of spotifywebapiPython might be problematic. Click here for more details.
- {spotifywebapiPython-1.0.45.dist-info → spotifywebapiPython-1.0.47.dist-info}/METADATA +6 -6
- {spotifywebapiPython-1.0.45.dist-info → spotifywebapiPython-1.0.47.dist-info}/RECORD +34 -28
- spotifywebapipython/const.py +1 -1
- spotifywebapipython/docs/__init__.html +21 -3
- spotifywebapipython/docs/index.html +20 -2
- spotifywebapipython/docs/search.js +1 -1
- spotifywebapipython/docs/spotifywebapiPython/const.html +3 -3
- spotifywebapipython/docs/spotifywebapiPython/saappmessages.html +22 -2
- spotifywebapipython/docs/spotifywebapiPython/sautils.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifyapierror.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifyapimessage.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifyauthtoken.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifyclient.html +2 -200
- spotifywebapipython/docs/spotifywebapiPython/spotifydiscovery.html +2 -28
- spotifywebapipython/docs/spotifywebapiPython/spotifywebapiauthenticationerror.html +2 -2
- spotifywebapipython/docs/spotifywebapiPython/spotifywebapierror.html +2 -2
- spotifywebapipython/models/__init__.py +0 -10
- spotifywebapipython/saappmessages.py +7 -1
- spotifywebapipython/spotifyclient.py +0 -249
- spotifywebapipython/spotifydiscovery.py +0 -46
- spotifywebapipython/zeroconfapi/__init__.py +21 -0
- spotifywebapipython/{models/zeroconfblobbuilder.py → zeroconfapi/blobbuilder.py} +10 -58
- spotifywebapipython/zeroconfapi/credentials.py +18 -0
- spotifywebapipython/zeroconfapi/cryptodiffiehellman.py +24 -0
- spotifywebapipython/zeroconfapi/helpers.py +30 -0
- spotifywebapipython/zeroconfapi/spotifyzeroconfapierror.py +108 -0
- spotifywebapipython/zeroconfapi/zeroconfconnect.py +562 -0
- spotifywebapipython/{models → zeroconfapi}/zeroconfgetinfo.py +21 -7
- spotifywebapipython/{models → zeroconfapi}/zeroconfgetinfoalias.py +1 -1
- spotifywebapipython/{models → zeroconfapi}/zeroconfgetinfodrmmediaformat.py +1 -1
- spotifywebapipython/{models → zeroconfapi}/zeroconfresponse.py +3 -3
- {spotifywebapiPython-1.0.45.dist-info → spotifywebapiPython-1.0.47.dist-info}/LICENSE +0 -0
- {spotifywebapiPython-1.0.45.dist-info → spotifywebapiPython-1.0.47.dist-info}/WHEEL +0 -0
- {spotifywebapiPython-1.0.45.dist-info → spotifywebapiPython-1.0.47.dist-info}/top_level.txt +0 -0
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</title>
|
|
10
10
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20role%3D%22img%22%20aria-label%3D%22pdoc%20logo%22%20width%3D%22300%22%20height%3D%22150%22%20viewBox%3D%22-1%200%2060%2030%22%3E%3Ctitle%3Epdoc%3C/title%3E%3Cpath%20d%3D%22M29.621%2021.293c-.011-.273-.214-.475-.511-.481a.5.5%200%200%200-.489.503l-.044%201.393c-.097.551-.695%201.215-1.566%201.704-.577.428-1.306.486-2.193.182-1.426-.617-2.467-1.654-3.304-2.487l-.173-.172a3.43%203.43%200%200%200-.365-.306.49.49%200%200%200-.286-.196c-1.718-1.06-4.931-1.47-7.353.191l-.219.15c-1.707%201.187-3.413%202.131-4.328%201.03-.02-.027-.49-.685-.141-1.763.233-.721.546-2.408.772-4.076.042-.09.067-.187.046-.288.166-1.347.277-2.625.241-3.351%201.378-1.008%202.271-2.586%202.271-4.362%200-.976-.272-1.935-.788-2.774-.057-.094-.122-.18-.184-.268.033-.167.052-.339.052-.516%200-1.477-1.202-2.679-2.679-2.679-.791%200-1.496.352-1.987.9a6.3%206.3%200%200%200-1.001.029c-.492-.564-1.207-.929-2.012-.929-1.477%200-2.679%201.202-2.679%202.679A2.65%202.65%200%200%200%20.97%206.554c-.383.747-.595%201.572-.595%202.41%200%202.311%201.507%204.29%203.635%205.107-.037.699-.147%202.27-.423%203.294l-.137.461c-.622%202.042-2.515%208.257%201.727%2010.643%201.614.908%203.06%201.248%204.317%201.248%202.665%200%204.492-1.524%205.322-2.401%201.476-1.559%202.886-1.854%206.491.82%201.877%201.393%203.514%201.753%204.861%201.068%202.223-1.713%202.811-3.867%203.399-6.374.077-.846.056-1.469.054-1.537zm-4.835%204.313c-.054.305-.156.586-.242.629-.034-.007-.131-.022-.307-.157-.145-.111-.314-.478-.456-.908.221.121.432.25.675.355.115.039.219.051.33.081zm-2.251-1.238c-.05.33-.158.648-.252.694-.022.001-.125-.018-.307-.157-.217-.166-.488-.906-.639-1.573.358.344.754.693%201.198%201.036zm-3.887-2.337c-.006-.116-.018-.231-.041-.342.635.145%201.189.368%201.599.625.097.231.166.481.174.642-.03.049-.055.101-.067.158-.046.013-.128.026-.298.004-.278-.037-.901-.57-1.367-1.087zm-1.127-.497c.116.306.176.625.12.71-.019.014-.117.045-.345.016-.206-.027-.604-.332-.986-.695.41-.051.816-.056%201.211-.031zm-4.535%201.535c.209.22.379.47.358.598-.006.041-.088.138-.351.234-.144.055-.539-.063-.979-.259a11.66%2011.66%200%200%200%20.972-.573zm.983-.664c.359-.237.738-.418%201.126-.554.25.237.479.548.457.694-.006.042-.087.138-.351.235-.174.064-.694-.105-1.232-.375zm-3.381%201.794c-.022.145-.061.29-.149.401-.133.166-.358.248-.69.251h-.002c-.133%200-.306-.26-.45-.621.417.091.854.07%201.291-.031zm-2.066-8.077a4.78%204.78%200%200%201-.775-.584c.172-.115.505-.254.88-.378l-.105.962zm-.331%202.302a10.32%2010.32%200%200%201-.828-.502c.202-.143.576-.328.984-.49l-.156.992zm-.45%202.157l-.701-.403c.214-.115.536-.249.891-.376a11.57%2011.57%200%200%201-.19.779zm-.181%201.716c.064.398.194.702.298.893-.194-.051-.435-.162-.736-.398.061-.119.224-.3.438-.495zM8.87%204.141c0%20.152-.123.276-.276.276s-.275-.124-.275-.276.123-.276.276-.276.275.124.275.276zm-.735-.389a1.15%201.15%200%200%200-.314.783%201.16%201.16%200%200%200%201.162%201.162c.457%200%20.842-.27%201.032-.653.026.117.042.238.042.362a1.68%201.68%200%200%201-1.679%201.679%201.68%201.68%200%200%201-1.679-1.679c0-.843.626-1.535%201.436-1.654zM5.059%205.406A1.68%201.68%200%200%201%203.38%207.085a1.68%201.68%200%200%201-1.679-1.679c0-.037.009-.072.011-.109.21.3.541.508.935.508a1.16%201.16%200%200%200%201.162-1.162%201.14%201.14%200%200%200-.474-.912c.015%200%20.03-.005.045-.005.926.001%201.679.754%201.679%201.68zM3.198%204.141c0%20.152-.123.276-.276.276s-.275-.124-.275-.276.123-.276.276-.276.275.124.275.276zM1.375%208.964c0-.52.103-1.035.288-1.52.466.394%201.06.64%201.717.64%201.144%200%202.116-.725%202.499-1.738.383%201.012%201.355%201.738%202.499%201.738.867%200%201.631-.421%202.121-1.062.307.605.478%201.267.478%201.942%200%202.486-2.153%204.51-4.801%204.51s-4.801-2.023-4.801-4.51zm24.342%2019.349c-.985.498-2.267.168-3.813-.979-3.073-2.281-5.453-3.199-7.813-.705-1.315%201.391-4.163%203.365-8.423.97-3.174-1.786-2.239-6.266-1.261-9.479l.146-.492c.276-1.02.395-2.457.444-3.268a6.11%206.11%200%200%200%201.18.115%206.01%206.01%200%200%200%202.536-.562l-.006.175c-.802.215-1.848.612-2.021%201.25-.079.295.021.601.274.837.219.203.415.364.598.501-.667.304-1.243.698-1.311%201.179-.02.144-.022.507.393.787.213.144.395.26.564.365-1.285.521-1.361.96-1.381%201.126-.018.142-.011.496.427.746l.854.489c-.473.389-.971.914-.999%201.429-.018.278.095.532.316.713.675.556%201.231.721%201.653.721.059%200%20.104-.014.158-.02.207.707.641%201.64%201.513%201.64h.013c.8-.008%201.236-.345%201.462-.626.173-.216.268-.457.325-.692.424.195.93.374%201.372.374.151%200%20.294-.021.423-.068.732-.27.944-.704.993-1.021.009-.061.003-.119.002-.179.266.086.538.147.789.147.15%200%20.294-.021.423-.069.542-.2.797-.489.914-.754.237.147.478.258.704.288.106.014.205.021.296.021.356%200%20.595-.101.767-.229.438.435%201.094.992%201.656%201.067.106.014.205.021.296.021a1.56%201.56%200%200%200%20.323-.035c.17.575.453%201.289.866%201.605.358.273.665.362.914.362a.99.99%200%200%200%20.421-.093%201.03%201.03%200%200%200%20.245-.164c.168.428.39.846.68%201.068.358.273.665.362.913.362a.99.99%200%200%200%20.421-.093c.317-.148.512-.448.639-.762.251.157.495.257.726.257.127%200%20.25-.024.37-.071.427-.17.706-.617.841-1.314.022-.015.047-.022.068-.038.067-.051.133-.104.196-.159-.443%201.486-1.107%202.761-2.086%203.257zM8.66%209.925a.5.5%200%201%200-1%200c0%20.653-.818%201.205-1.787%201.205s-1.787-.552-1.787-1.205a.5.5%200%201%200-1%200c0%201.216%201.25%202.205%202.787%202.205s2.787-.989%202.787-2.205zm4.4%2015.965l-.208.097c-2.661%201.258-4.708%201.436-6.086.527-1.542-1.017-1.88-3.19-1.844-4.198a.4.4%200%200%200-.385-.414c-.242-.029-.406.164-.414.385-.046%201.249.367%203.686%202.202%204.896.708.467%201.547.7%202.51.7%201.248%200%202.706-.392%204.362-1.174l.185-.086a.4.4%200%200%200%20.205-.527c-.089-.204-.326-.291-.527-.206zM9.547%202.292c.093.077.205.114.317.114a.5.5%200%200%200%20.318-.886L8.817.397a.5.5%200%200%200-.703.068.5.5%200%200%200%20.069.703l1.364%201.124zm-7.661-.065c.086%200%20.173-.022.253-.068l1.523-.893a.5.5%200%200%200-.506-.863l-1.523.892a.5.5%200%200%200-.179.685c.094.158.261.247.432.247z%22%20transform%3D%22matrix%28-1%200%200%201%2058%200%29%22%20fill%3D%22%233bb300%22/%3E%3Cpath%20d%3D%22M.3%2021.86V10.18q0-.46.02-.68.04-.22.18-.5.28-.54%201.34-.54%201.06%200%201.42.28.38.26.44.78.76-1.04%202.38-1.04%201.64%200%203.1%201.54%201.46%201.54%201.46%203.58%200%202.04-1.46%203.58-1.44%201.54-3.08%201.54-1.64%200-2.38-.92v4.04q0%20.46-.04.68-.02.22-.18.5-.14.3-.5.42-.36.12-.98.12-.62%200-1-.12-.36-.12-.52-.4-.14-.28-.18-.5-.02-.22-.02-.68zm3.96-9.42q-.46.54-.46%201.18%200%20.64.46%201.18.48.52%201.2.52.74%200%201.24-.52.52-.52.52-1.18%200-.66-.48-1.18-.48-.54-1.26-.54-.76%200-1.22.54zm14.741-8.36q.16-.3.54-.42.38-.12%201-.12.64%200%201.02.12.38.12.52.42.16.3.18.54.04.22.04.68v11.94q0%20.46-.04.7-.02.22-.18.5-.3.54-1.7.54-1.38%200-1.54-.98-.84.96-2.34.96-1.8%200-3.28-1.56-1.48-1.58-1.48-3.66%200-2.1%201.48-3.68%201.5-1.58%203.28-1.58%201.48%200%202.3%201v-4.2q0-.46.02-.68.04-.24.18-.52zm-3.24%2010.86q.52.54%201.26.54.74%200%201.22-.54.5-.54.5-1.18%200-.66-.48-1.22-.46-.56-1.26-.56-.8%200-1.28.56-.48.54-.48%201.2%200%20.66.52%201.2zm7.833-1.2q0-2.4%201.68-3.96%201.68-1.56%203.84-1.56%202.16%200%203.82%201.56%201.66%201.54%201.66%203.94%200%201.66-.86%202.96-.86%201.28-2.1%201.9-1.22.6-2.54.6-1.32%200-2.56-.64-1.24-.66-2.1-1.92-.84-1.28-.84-2.88zm4.18%201.44q.64.48%201.3.48.66%200%201.32-.5.66-.5.66-1.48%200-.98-.62-1.46-.62-.48-1.34-.48-.72%200-1.34.5-.62.5-.62%201.48%200%20.96.64%201.46zm11.412-1.44q0%20.84.56%201.32.56.46%201.18.46.64%200%201.18-.36.56-.38.9-.38.6%200%201.46%201.06.46.58.46%201.04%200%20.76-1.1%201.42-1.14.8-2.8.8-1.86%200-3.58-1.34-.82-.64-1.34-1.7-.52-1.08-.52-2.36%200-1.3.52-2.34.52-1.06%201.34-1.7%201.66-1.32%203.54-1.32.76%200%201.48.22.72.2%201.06.4l.32.2q.36.24.56.38.52.4.52.92%200%20.5-.42%201.14-.72%201.1-1.38%201.1-.38%200-1.08-.44-.36-.34-1.04-.34-.66%200-1.24.48-.58.48-.58%201.34z%22%20fill%3D%22green%22/%3E%3C/svg%3E"/>
|
|
11
11
|
<!-- build env - Package Name = "spotifywebapiPython" -->
|
|
12
|
-
<!-- build env - Package Version = "1.0.
|
|
12
|
+
<!-- build env - Package Version = "1.0.47" -->
|
|
13
13
|
<!-- pdoc module.modulename = "spotifywebapipython.spotifywebapiauthenticationerror" -->
|
|
14
14
|
<!-- pdoc module.is_package = "False" -->
|
|
15
15
|
<!-- pdoc root_module_name = "None" -->
|
|
@@ -74,7 +74,7 @@
|
|
|
74
74
|
|
|
75
75
|
<footer class="footertext">
|
|
76
76
|
spotifywebapiPython</br>
|
|
77
|
-
Version 1.0.
|
|
77
|
+
Version 1.0.47</br>
|
|
78
78
|
<a href="https://developer.spotify.com/documentation/web-api" target="_blank">
|
|
79
79
|
<img src="../spotifywebapipython.ico" alt="brand icon" style="width:32px; height:32px; padding:4px;"/>
|
|
80
80
|
A Spotify Web Api Client
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
</title>
|
|
10
10
|
<link rel="icon" type="image/svg+xml" href="data:image/svg+xml,%3Csvg%20xmlns%3D%22http%3A//www.w3.org/2000/svg%22%20role%3D%22img%22%20aria-label%3D%22pdoc%20logo%22%20width%3D%22300%22%20height%3D%22150%22%20viewBox%3D%22-1%200%2060%2030%22%3E%3Ctitle%3Epdoc%3C/title%3E%3Cpath%20d%3D%22M29.621%2021.293c-.011-.273-.214-.475-.511-.481a.5.5%200%200%200-.489.503l-.044%201.393c-.097.551-.695%201.215-1.566%201.704-.577.428-1.306.486-2.193.182-1.426-.617-2.467-1.654-3.304-2.487l-.173-.172a3.43%203.43%200%200%200-.365-.306.49.49%200%200%200-.286-.196c-1.718-1.06-4.931-1.47-7.353.191l-.219.15c-1.707%201.187-3.413%202.131-4.328%201.03-.02-.027-.49-.685-.141-1.763.233-.721.546-2.408.772-4.076.042-.09.067-.187.046-.288.166-1.347.277-2.625.241-3.351%201.378-1.008%202.271-2.586%202.271-4.362%200-.976-.272-1.935-.788-2.774-.057-.094-.122-.18-.184-.268.033-.167.052-.339.052-.516%200-1.477-1.202-2.679-2.679-2.679-.791%200-1.496.352-1.987.9a6.3%206.3%200%200%200-1.001.029c-.492-.564-1.207-.929-2.012-.929-1.477%200-2.679%201.202-2.679%202.679A2.65%202.65%200%200%200%20.97%206.554c-.383.747-.595%201.572-.595%202.41%200%202.311%201.507%204.29%203.635%205.107-.037.699-.147%202.27-.423%203.294l-.137.461c-.622%202.042-2.515%208.257%201.727%2010.643%201.614.908%203.06%201.248%204.317%201.248%202.665%200%204.492-1.524%205.322-2.401%201.476-1.559%202.886-1.854%206.491.82%201.877%201.393%203.514%201.753%204.861%201.068%202.223-1.713%202.811-3.867%203.399-6.374.077-.846.056-1.469.054-1.537zm-4.835%204.313c-.054.305-.156.586-.242.629-.034-.007-.131-.022-.307-.157-.145-.111-.314-.478-.456-.908.221.121.432.25.675.355.115.039.219.051.33.081zm-2.251-1.238c-.05.33-.158.648-.252.694-.022.001-.125-.018-.307-.157-.217-.166-.488-.906-.639-1.573.358.344.754.693%201.198%201.036zm-3.887-2.337c-.006-.116-.018-.231-.041-.342.635.145%201.189.368%201.599.625.097.231.166.481.174.642-.03.049-.055.101-.067.158-.046.013-.128.026-.298.004-.278-.037-.901-.57-1.367-1.087zm-1.127-.497c.116.306.176.625.12.71-.019.014-.117.045-.345.016-.206-.027-.604-.332-.986-.695.41-.051.816-.056%201.211-.031zm-4.535%201.535c.209.22.379.47.358.598-.006.041-.088.138-.351.234-.144.055-.539-.063-.979-.259a11.66%2011.66%200%200%200%20.972-.573zm.983-.664c.359-.237.738-.418%201.126-.554.25.237.479.548.457.694-.006.042-.087.138-.351.235-.174.064-.694-.105-1.232-.375zm-3.381%201.794c-.022.145-.061.29-.149.401-.133.166-.358.248-.69.251h-.002c-.133%200-.306-.26-.45-.621.417.091.854.07%201.291-.031zm-2.066-8.077a4.78%204.78%200%200%201-.775-.584c.172-.115.505-.254.88-.378l-.105.962zm-.331%202.302a10.32%2010.32%200%200%201-.828-.502c.202-.143.576-.328.984-.49l-.156.992zm-.45%202.157l-.701-.403c.214-.115.536-.249.891-.376a11.57%2011.57%200%200%201-.19.779zm-.181%201.716c.064.398.194.702.298.893-.194-.051-.435-.162-.736-.398.061-.119.224-.3.438-.495zM8.87%204.141c0%20.152-.123.276-.276.276s-.275-.124-.275-.276.123-.276.276-.276.275.124.275.276zm-.735-.389a1.15%201.15%200%200%200-.314.783%201.16%201.16%200%200%200%201.162%201.162c.457%200%20.842-.27%201.032-.653.026.117.042.238.042.362a1.68%201.68%200%200%201-1.679%201.679%201.68%201.68%200%200%201-1.679-1.679c0-.843.626-1.535%201.436-1.654zM5.059%205.406A1.68%201.68%200%200%201%203.38%207.085a1.68%201.68%200%200%201-1.679-1.679c0-.037.009-.072.011-.109.21.3.541.508.935.508a1.16%201.16%200%200%200%201.162-1.162%201.14%201.14%200%200%200-.474-.912c.015%200%20.03-.005.045-.005.926.001%201.679.754%201.679%201.68zM3.198%204.141c0%20.152-.123.276-.276.276s-.275-.124-.275-.276.123-.276.276-.276.275.124.275.276zM1.375%208.964c0-.52.103-1.035.288-1.52.466.394%201.06.64%201.717.64%201.144%200%202.116-.725%202.499-1.738.383%201.012%201.355%201.738%202.499%201.738.867%200%201.631-.421%202.121-1.062.307.605.478%201.267.478%201.942%200%202.486-2.153%204.51-4.801%204.51s-4.801-2.023-4.801-4.51zm24.342%2019.349c-.985.498-2.267.168-3.813-.979-3.073-2.281-5.453-3.199-7.813-.705-1.315%201.391-4.163%203.365-8.423.97-3.174-1.786-2.239-6.266-1.261-9.479l.146-.492c.276-1.02.395-2.457.444-3.268a6.11%206.11%200%200%200%201.18.115%206.01%206.01%200%200%200%202.536-.562l-.006.175c-.802.215-1.848.612-2.021%201.25-.079.295.021.601.274.837.219.203.415.364.598.501-.667.304-1.243.698-1.311%201.179-.02.144-.022.507.393.787.213.144.395.26.564.365-1.285.521-1.361.96-1.381%201.126-.018.142-.011.496.427.746l.854.489c-.473.389-.971.914-.999%201.429-.018.278.095.532.316.713.675.556%201.231.721%201.653.721.059%200%20.104-.014.158-.02.207.707.641%201.64%201.513%201.64h.013c.8-.008%201.236-.345%201.462-.626.173-.216.268-.457.325-.692.424.195.93.374%201.372.374.151%200%20.294-.021.423-.068.732-.27.944-.704.993-1.021.009-.061.003-.119.002-.179.266.086.538.147.789.147.15%200%20.294-.021.423-.069.542-.2.797-.489.914-.754.237.147.478.258.704.288.106.014.205.021.296.021.356%200%20.595-.101.767-.229.438.435%201.094.992%201.656%201.067.106.014.205.021.296.021a1.56%201.56%200%200%200%20.323-.035c.17.575.453%201.289.866%201.605.358.273.665.362.914.362a.99.99%200%200%200%20.421-.093%201.03%201.03%200%200%200%20.245-.164c.168.428.39.846.68%201.068.358.273.665.362.913.362a.99.99%200%200%200%20.421-.093c.317-.148.512-.448.639-.762.251.157.495.257.726.257.127%200%20.25-.024.37-.071.427-.17.706-.617.841-1.314.022-.015.047-.022.068-.038.067-.051.133-.104.196-.159-.443%201.486-1.107%202.761-2.086%203.257zM8.66%209.925a.5.5%200%201%200-1%200c0%20.653-.818%201.205-1.787%201.205s-1.787-.552-1.787-1.205a.5.5%200%201%200-1%200c0%201.216%201.25%202.205%202.787%202.205s2.787-.989%202.787-2.205zm4.4%2015.965l-.208.097c-2.661%201.258-4.708%201.436-6.086.527-1.542-1.017-1.88-3.19-1.844-4.198a.4.4%200%200%200-.385-.414c-.242-.029-.406.164-.414.385-.046%201.249.367%203.686%202.202%204.896.708.467%201.547.7%202.51.7%201.248%200%202.706-.392%204.362-1.174l.185-.086a.4.4%200%200%200%20.205-.527c-.089-.204-.326-.291-.527-.206zM9.547%202.292c.093.077.205.114.317.114a.5.5%200%200%200%20.318-.886L8.817.397a.5.5%200%200%200-.703.068.5.5%200%200%200%20.069.703l1.364%201.124zm-7.661-.065c.086%200%20.173-.022.253-.068l1.523-.893a.5.5%200%200%200-.506-.863l-1.523.892a.5.5%200%200%200-.179.685c.094.158.261.247.432.247z%22%20transform%3D%22matrix%28-1%200%200%201%2058%200%29%22%20fill%3D%22%233bb300%22/%3E%3Cpath%20d%3D%22M.3%2021.86V10.18q0-.46.02-.68.04-.22.18-.5.28-.54%201.34-.54%201.06%200%201.42.28.38.26.44.78.76-1.04%202.38-1.04%201.64%200%203.1%201.54%201.46%201.54%201.46%203.58%200%202.04-1.46%203.58-1.44%201.54-3.08%201.54-1.64%200-2.38-.92v4.04q0%20.46-.04.68-.02.22-.18.5-.14.3-.5.42-.36.12-.98.12-.62%200-1-.12-.36-.12-.52-.4-.14-.28-.18-.5-.02-.22-.02-.68zm3.96-9.42q-.46.54-.46%201.18%200%20.64.46%201.18.48.52%201.2.52.74%200%201.24-.52.52-.52.52-1.18%200-.66-.48-1.18-.48-.54-1.26-.54-.76%200-1.22.54zm14.741-8.36q.16-.3.54-.42.38-.12%201-.12.64%200%201.02.12.38.12.52.42.16.3.18.54.04.22.04.68v11.94q0%20.46-.04.7-.02.22-.18.5-.3.54-1.7.54-1.38%200-1.54-.98-.84.96-2.34.96-1.8%200-3.28-1.56-1.48-1.58-1.48-3.66%200-2.1%201.48-3.68%201.5-1.58%203.28-1.58%201.48%200%202.3%201v-4.2q0-.46.02-.68.04-.24.18-.52zm-3.24%2010.86q.52.54%201.26.54.74%200%201.22-.54.5-.54.5-1.18%200-.66-.48-1.22-.46-.56-1.26-.56-.8%200-1.28.56-.48.54-.48%201.2%200%20.66.52%201.2zm7.833-1.2q0-2.4%201.68-3.96%201.68-1.56%203.84-1.56%202.16%200%203.82%201.56%201.66%201.54%201.66%203.94%200%201.66-.86%202.96-.86%201.28-2.1%201.9-1.22.6-2.54.6-1.32%200-2.56-.64-1.24-.66-2.1-1.92-.84-1.28-.84-2.88zm4.18%201.44q.64.48%201.3.48.66%200%201.32-.5.66-.5.66-1.48%200-.98-.62-1.46-.62-.48-1.34-.48-.72%200-1.34.5-.62.5-.62%201.48%200%20.96.64%201.46zm11.412-1.44q0%20.84.56%201.32.56.46%201.18.46.64%200%201.18-.36.56-.38.9-.38.6%200%201.46%201.06.46.58.46%201.04%200%20.76-1.1%201.42-1.14.8-2.8.8-1.86%200-3.58-1.34-.82-.64-1.34-1.7-.52-1.08-.52-2.36%200-1.3.52-2.34.52-1.06%201.34-1.7%201.66-1.32%203.54-1.32.76%200%201.48.22.72.2%201.06.4l.32.2q.36.24.56.38.52.4.52.92%200%20.5-.42%201.14-.72%201.1-1.38%201.1-.38%200-1.08-.44-.36-.34-1.04-.34-.66%200-1.24.48-.58.48-.58%201.34z%22%20fill%3D%22green%22/%3E%3C/svg%3E"/>
|
|
11
11
|
<!-- build env - Package Name = "spotifywebapiPython" -->
|
|
12
|
-
<!-- build env - Package Version = "1.0.
|
|
12
|
+
<!-- build env - Package Version = "1.0.47" -->
|
|
13
13
|
<!-- pdoc module.modulename = "spotifywebapipython.spotifywebapierror" -->
|
|
14
14
|
<!-- pdoc module.is_package = "False" -->
|
|
15
15
|
<!-- pdoc root_module_name = "None" -->
|
|
@@ -71,7 +71,7 @@
|
|
|
71
71
|
|
|
72
72
|
<footer class="footertext">
|
|
73
73
|
spotifywebapiPython</br>
|
|
74
|
-
Version 1.0.
|
|
74
|
+
Version 1.0.47</br>
|
|
75
75
|
<a href="https://developer.spotify.com/documentation/web-api" target="_blank">
|
|
76
76
|
<img src="../spotifywebapipython.ico" alt="brand icon" style="width:32px; height:32px; padding:4px;"/>
|
|
77
77
|
A Spotify Web Api Client
|
|
@@ -50,13 +50,8 @@ from .trackpagesaved import TrackPageSaved, TrackSaved
|
|
|
50
50
|
from .trackpagesimplified import TrackPageSimplified
|
|
51
51
|
from .trackrecommendations import TrackRecommendations
|
|
52
52
|
from .userprofile import UserProfile, UserProfileSimplified
|
|
53
|
-
from .zeroconfblobbuilder import ZeroconfBlobBuilder, ZeroconfCredentials
|
|
54
53
|
from .zeroconfdiscoveryresult import ZeroconfDiscoveryResult
|
|
55
|
-
from .zeroconfgetinfoalias import ZeroconfGetInfoAlias
|
|
56
|
-
from .zeroconfgetinfodrmmediaformat import ZeroconfGetInfoDrmMediaFormat
|
|
57
|
-
from .zeroconfgetinfo import ZeroconfGetInfo
|
|
58
54
|
from .zeroconfproperty import ZeroconfProperty
|
|
59
|
-
from .zeroconfresponse import ZeroconfResponse
|
|
60
55
|
|
|
61
56
|
# all classes to import when "import *" is specified.
|
|
62
57
|
__all__ = [
|
|
@@ -111,11 +106,6 @@ __all__ = [
|
|
|
111
106
|
'TrackPageSimplified',
|
|
112
107
|
'TrackRecommendations',
|
|
113
108
|
'UserProfile','UserProfileSimplified',
|
|
114
|
-
'ZeroconfBlobBuilder', 'ZeroconfCredentials',
|
|
115
109
|
'ZeroconfDiscoveryResult',
|
|
116
|
-
'ZeroconfGetInfo',
|
|
117
|
-
'ZeroconfGetInfoAlias',
|
|
118
|
-
'ZeroconfGetInfoDrmMediaFormat',
|
|
119
110
|
'ZeroconfProperty',
|
|
120
|
-
'ZeroconfResponse',
|
|
121
111
|
]
|
|
@@ -38,4 +38,10 @@ class SAAppMessages:
|
|
|
38
38
|
MSG_SPOTIFY_WEB_API_AUTH_ERROR:str = "SAM1002E - Spotify Web API returned an authorization error status while processing the \"{methodname}\" method.\nHTTP Status: {httpstatus} - {httpreason}\nError: {error}\nError Description: \"{errordescription}\""
|
|
39
39
|
"""
|
|
40
40
|
SAM1002E - Spotify Web API returned an authorization error status while processing the \"{methodname}\" method.\nHTTP Status: {httpstatus} - {httpreason}\nError: {error}\nError Description: \"{errordescription}\"
|
|
41
|
-
"""
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
MSG_SPOTIFY_ZEROCONF_API_ERROR:str = "SAM1003E - Spotify ZeroConf API returned an error status while processing the \"{methodname}\" method.\nStatus: {status} - {httpreason}\nMessage: \"{message}\""
|
|
44
|
+
"""
|
|
45
|
+
SAM1001E - Spotify ZeroConf API returned an error status while processing the \"{methodname}\" method.\nStatus: {status} - {httpreason}\nMessage: \"{message}\"
|
|
46
|
+
"""
|
|
47
|
+
|
|
@@ -14,7 +14,6 @@ from lxml.etree import fromstring, Element
|
|
|
14
14
|
from .oauthcli import AuthClient
|
|
15
15
|
from .models import *
|
|
16
16
|
from .models import UserProfile as UserProfileCurrentUser
|
|
17
|
-
from .models.zeroconfblobbuilder import int_to_b64str
|
|
18
17
|
from .sautils import export, GetUnixTimestampMSFromUtcNow, _xmlGetInnerText
|
|
19
18
|
from .saappmessages import SAAppMessages
|
|
20
19
|
from .spotifyapierror import SpotifyApiError
|
|
@@ -13819,251 +13818,3 @@ class SpotifyClient:
|
|
|
13819
13818
|
|
|
13820
13819
|
# trace.
|
|
13821
13820
|
_logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|
|
13822
|
-
|
|
13823
|
-
|
|
13824
|
-
|
|
13825
|
-
def ZeroconfGetInformation(self,
|
|
13826
|
-
actionUrl:str,
|
|
13827
|
-
) -> ZeroconfGetInfo:
|
|
13828
|
-
"""
|
|
13829
|
-
Retrieve Spotify Connect device information from the Spotify Zeroconf API `getInfo` endpoint.
|
|
13830
|
-
|
|
13831
|
-
Args:
|
|
13832
|
-
actionUrl (str):
|
|
13833
|
-
The Zeroconf action url to issue the request to.
|
|
13834
|
-
Example: `http://192.168.1.80:8200/zc?action=getInfo`
|
|
13835
|
-
|
|
13836
|
-
Returns:
|
|
13837
|
-
An `ZeroconfGetInfo` object that contains the response.
|
|
13838
|
-
|
|
13839
|
-
Raises:
|
|
13840
|
-
SpotifyWebApiError:
|
|
13841
|
-
If the Spotify Web API request was for a non-authorization service
|
|
13842
|
-
and the response contains error information.
|
|
13843
|
-
SpotifApiError:
|
|
13844
|
-
If the method fails for any other reason.
|
|
13845
|
-
|
|
13846
|
-
<details>
|
|
13847
|
-
<summary>Sample Code</summary>
|
|
13848
|
-
```python
|
|
13849
|
-
.. include:: ../docs/include/samplecode/SpotifyClient/ZeroconfGetInformation.py
|
|
13850
|
-
```
|
|
13851
|
-
</details>
|
|
13852
|
-
"""
|
|
13853
|
-
apiMethodName:str = 'ZeroconfGetInformation'
|
|
13854
|
-
apiMethodParms:SIMethodParmListContext = None
|
|
13855
|
-
result:ZeroconfGetInfo = None
|
|
13856
|
-
|
|
13857
|
-
try:
|
|
13858
|
-
|
|
13859
|
-
# trace.
|
|
13860
|
-
apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
|
|
13861
|
-
apiMethodParms.AppendKeyValue("actionUrl", actionUrl)
|
|
13862
|
-
_logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify Zeroconf getInfo response", apiMethodParms)
|
|
13863
|
-
|
|
13864
|
-
# execute spotify zeroconf api request.
|
|
13865
|
-
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, actionUrl)
|
|
13866
|
-
self.MakeRequest('GET', msg)
|
|
13867
|
-
|
|
13868
|
-
# process results.
|
|
13869
|
-
result = ZeroconfGetInfo(root=msg.ResponseData)
|
|
13870
|
-
|
|
13871
|
-
# trace.
|
|
13872
|
-
_logsi.LogObject(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
|
|
13873
|
-
return result
|
|
13874
|
-
|
|
13875
|
-
except SpotifyWebApiError: raise # pass handled exceptions on thru
|
|
13876
|
-
except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
|
|
13877
|
-
except Exception as ex:
|
|
13878
|
-
|
|
13879
|
-
# format unhandled exception.
|
|
13880
|
-
raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
|
|
13881
|
-
|
|
13882
|
-
finally:
|
|
13883
|
-
|
|
13884
|
-
# trace.
|
|
13885
|
-
_logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|
|
13886
|
-
|
|
13887
|
-
|
|
13888
|
-
def ZeroconfResetUsers(self,
|
|
13889
|
-
actionUrl:str,
|
|
13890
|
-
) -> ZeroconfResponse:
|
|
13891
|
-
"""
|
|
13892
|
-
Reset users for a Spotify Connect device by calling the Spotify Zeroconf API `resetUsers` endpoint.
|
|
13893
|
-
|
|
13894
|
-
Args:
|
|
13895
|
-
actionUrl (str):
|
|
13896
|
-
The Zeroconf action url to issue the request to.
|
|
13897
|
-
Example: `http://192.168.1.80:8200/zc?action=resetUsers`
|
|
13898
|
-
|
|
13899
|
-
Returns:
|
|
13900
|
-
An `ZeroconfResponse` object that contains the response.
|
|
13901
|
-
|
|
13902
|
-
Raises:
|
|
13903
|
-
SpotifyWebApiError:
|
|
13904
|
-
If the Spotify Web API request was for a non-authorization service
|
|
13905
|
-
and the response contains error information.
|
|
13906
|
-
SpotifApiError:
|
|
13907
|
-
If the method fails for any other reason.
|
|
13908
|
-
|
|
13909
|
-
<details>
|
|
13910
|
-
<summary>Sample Code</summary>
|
|
13911
|
-
```python
|
|
13912
|
-
.. include:: ../docs/include/samplecode/SpotifyClient/ZeroconfResetUsers.py
|
|
13913
|
-
```
|
|
13914
|
-
</details>
|
|
13915
|
-
"""
|
|
13916
|
-
apiMethodName:str = 'ZeroconfResetUsers'
|
|
13917
|
-
apiMethodParms:SIMethodParmListContext = None
|
|
13918
|
-
result:ZeroconfResponse = None
|
|
13919
|
-
|
|
13920
|
-
try:
|
|
13921
|
-
|
|
13922
|
-
# trace.
|
|
13923
|
-
apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
|
|
13924
|
-
apiMethodParms.AppendKeyValue("actionUrl", actionUrl)
|
|
13925
|
-
_logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify Zeroconf ResetUsers response", apiMethodParms)
|
|
13926
|
-
|
|
13927
|
-
# execute spotify zeroconf api request.
|
|
13928
|
-
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, actionUrl)
|
|
13929
|
-
self.MakeRequest('GET', msg)
|
|
13930
|
-
|
|
13931
|
-
# process results.
|
|
13932
|
-
result = ZeroconfResponse(root=msg.ResponseData)
|
|
13933
|
-
|
|
13934
|
-
# trace.
|
|
13935
|
-
_logsi.LogObject(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
|
|
13936
|
-
return result
|
|
13937
|
-
|
|
13938
|
-
except SpotifyWebApiError: raise # pass handled exceptions on thru
|
|
13939
|
-
except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
|
|
13940
|
-
except Exception as ex:
|
|
13941
|
-
|
|
13942
|
-
# format unhandled exception.
|
|
13943
|
-
raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
|
|
13944
|
-
|
|
13945
|
-
finally:
|
|
13946
|
-
|
|
13947
|
-
# trace.
|
|
13948
|
-
_logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|
|
13949
|
-
|
|
13950
|
-
|
|
13951
|
-
def ZeroconfAddUser(self,
|
|
13952
|
-
actionUrl:str,
|
|
13953
|
-
getInfoResponse:ZeroconfGetInfo,
|
|
13954
|
-
username:str,
|
|
13955
|
-
password:str,
|
|
13956
|
-
) -> ZeroconfResponse:
|
|
13957
|
-
"""
|
|
13958
|
-
Add a user to a Spotify Connect device by calling the Spotify Zeroconf API `addUser` endpoint.
|
|
13959
|
-
|
|
13960
|
-
Args:
|
|
13961
|
-
actionUrl (str):
|
|
13962
|
-
The Zeroconf action url to issue the request to.
|
|
13963
|
-
Example: `http://192.168.1.80:8200/zc?action=addUser&version=1.0`
|
|
13964
|
-
|
|
13965
|
-
Returns:
|
|
13966
|
-
An `ZeroconfResponse` object that contains the response.
|
|
13967
|
-
|
|
13968
|
-
Raises:
|
|
13969
|
-
SpotifyWebApiError:
|
|
13970
|
-
If the Spotify Web API request was for a non-authorization service
|
|
13971
|
-
and the response contains error information.
|
|
13972
|
-
SpotifApiError:
|
|
13973
|
-
If the method fails for any other reason.
|
|
13974
|
-
|
|
13975
|
-
<details>
|
|
13976
|
-
<summary>Sample Code</summary>
|
|
13977
|
-
```python
|
|
13978
|
-
.. include:: ../docs/include/samplecode/SpotifyClient/ZeroconfGetInformation.py
|
|
13979
|
-
```
|
|
13980
|
-
</details>
|
|
13981
|
-
"""
|
|
13982
|
-
apiMethodName:str = 'ZeroconfAddUser'
|
|
13983
|
-
apiMethodParms:SIMethodParmListContext = None
|
|
13984
|
-
result:ZeroconfResponse = None
|
|
13985
|
-
|
|
13986
|
-
try:
|
|
13987
|
-
|
|
13988
|
-
# trace.
|
|
13989
|
-
apiMethodParms = _logsi.EnterMethodParmList(SILevel.Debug, apiMethodName)
|
|
13990
|
-
apiMethodParms.AppendKeyValue("actionUrl", actionUrl)
|
|
13991
|
-
apiMethodParms.AppendKeyValue("getInfoResponse", getInfoResponse)
|
|
13992
|
-
apiMethodParms.AppendKeyValue("username", username)
|
|
13993
|
-
apiMethodParms.AppendKeyValue("password", password)
|
|
13994
|
-
_logsi.LogMethodParmList(SILevel.Verbose, "Get Spotify Zeroconf addUser response", apiMethodParms)
|
|
13995
|
-
|
|
13996
|
-
raise NotImplemented()
|
|
13997
|
-
|
|
13998
|
-
# build credentials object.
|
|
13999
|
-
self.credentials = ZeroconfCredentials(username, password)
|
|
14000
|
-
|
|
14001
|
-
# build authentication blob.
|
|
14002
|
-
builder = ZeroconfBlobBuilder(self.credentials, getInfoResponse.DeviceId, getInfoResponse.PublicKey)
|
|
14003
|
-
blob = builder.build()
|
|
14004
|
-
|
|
14005
|
-
# # call zeroconf to add the user to the device.
|
|
14006
|
-
# r = self._add_user(
|
|
14007
|
-
# self.credentials.username.decode('ascii'),
|
|
14008
|
-
# int_to_b64str(builder.dh_keys.public_key),
|
|
14009
|
-
# blob)
|
|
14010
|
-
|
|
14011
|
-
# def _add_user(self, username: str, client_key: str, blob: str): # -> bool
|
|
14012
|
-
# respone = requests.post(
|
|
14013
|
-
# self.uri,
|
|
14014
|
-
# headers={
|
|
14015
|
-
# 'Content-Type': 'application/x-www-form-urlencoded'
|
|
14016
|
-
# },
|
|
14017
|
-
# params={
|
|
14018
|
-
# 'action': 'addUser',
|
|
14019
|
-
# 'userName': username,
|
|
14020
|
-
# 'clientKey': client_key,
|
|
14021
|
-
# 'blob': blob
|
|
14022
|
-
# }
|
|
14023
|
-
# )
|
|
14024
|
-
# return respone
|
|
14025
|
-
|
|
14026
|
-
# build spotify zeroconf addUser parameters.
|
|
14027
|
-
urlParms:dict = \
|
|
14028
|
-
{
|
|
14029
|
-
'userName': self.credentials.username.decode('ascii'),
|
|
14030
|
-
'clientKey': int_to_b64str(builder.dh_keys.public_key),
|
|
14031
|
-
'blob': blob,
|
|
14032
|
-
'deviceId': getInfoResponse.DeviceId,
|
|
14033
|
-
'deviceName': getInfoResponse.RemoteName,
|
|
14034
|
-
'loginId': 'xxxxxxxxxxx',
|
|
14035
|
-
}
|
|
14036
|
-
|
|
14037
|
-
# let params = [
|
|
14038
|
-
# 3 ("action", "addUser"),
|
|
14039
|
-
# 3 ("userName", username),
|
|
14040
|
-
# 3 ("blob", blob),
|
|
14041
|
-
# 3 ("clientKey", my_public_key),
|
|
14042
|
-
# ("deviceId", &device_id),
|
|
14043
|
-
# ("deviceName", "spotify-connect"),
|
|
14044
|
-
# ("loginId", &login_id),
|
|
14045
|
-
|
|
14046
|
-
|
|
14047
|
-
# execute spotify zeroconf api request.
|
|
14048
|
-
msg:SpotifyApiMessage = SpotifyApiMessage(apiMethodName, actionUrl)
|
|
14049
|
-
msg.UrlParameters = urlParms
|
|
14050
|
-
self.MakeRequest('POST', msg)
|
|
14051
|
-
|
|
14052
|
-
# process results.
|
|
14053
|
-
result = ZeroconfResponse(root=msg.ResponseData)
|
|
14054
|
-
|
|
14055
|
-
# trace.
|
|
14056
|
-
_logsi.LogObject(SILevel.Verbose, TRACE_METHOD_RESULT_TYPE % (apiMethodName, type(result).__name__), result, excludeNonPublic=True)
|
|
14057
|
-
return result
|
|
14058
|
-
|
|
14059
|
-
except SpotifyWebApiError: raise # pass handled exceptions on thru
|
|
14060
|
-
except SpotifyWebApiAuthenticationError: raise # pass handled exceptions on thru
|
|
14061
|
-
except Exception as ex:
|
|
14062
|
-
|
|
14063
|
-
# format unhandled exception.
|
|
14064
|
-
raise SpotifyApiError(SAAppMessages.UNHANDLED_EXCEPTION.format(apiMethodName, str(ex)), ex, logsi=_logsi)
|
|
14065
|
-
|
|
14066
|
-
finally:
|
|
14067
|
-
|
|
14068
|
-
# trace.
|
|
14069
|
-
_logsi.LeaveMethod(SILevel.Debug, apiMethodName)
|
|
@@ -300,52 +300,6 @@ class SpotifyDiscovery:
|
|
|
300
300
|
return self._DiscoveredDeviceNames
|
|
301
301
|
|
|
302
302
|
|
|
303
|
-
def BroadcastService(self, serviceInfo:ServiceInfo, port:int=5353) -> None:
|
|
304
|
-
"""
|
|
305
|
-
Generate a Zeroconf / mDNS broadcast to announce a service, and sends the broadcast out.
|
|
306
|
-
|
|
307
|
-
Args:
|
|
308
|
-
serviceInfo (ServiceInfo):
|
|
309
|
-
Service information to broadcast.
|
|
310
|
-
port (int):
|
|
311
|
-
mDNS port number to send the broadcast on.
|
|
312
|
-
Default is 5353.
|
|
313
|
-
"""
|
|
314
|
-
try:
|
|
315
|
-
|
|
316
|
-
# create the zeroconf service.
|
|
317
|
-
zeroconf:Zeroconf = Zeroconf(ip_version=IPVersion.V4Only)
|
|
318
|
-
|
|
319
|
-
# # TEST TODO - hardcoded serviceinfo properties for testing.
|
|
320
|
-
# serviceType:str = '_spotify-connect._tcp.local.'
|
|
321
|
-
# serviceName:str = 'Bose-ST10-95._spotify-connect._tcp.local.'
|
|
322
|
-
# parsedAddresses:list[str] = ['192.168.1.82']
|
|
323
|
-
# port:int = 8200
|
|
324
|
-
# hostTTL:int = 120
|
|
325
|
-
# priority:int = 0
|
|
326
|
-
# otherTTL:int = 4500
|
|
327
|
-
# server:str = 'Bose-SM2-987bf3244-95.local.'
|
|
328
|
-
# weight:int = 0
|
|
329
|
-
# properties:dict = {b'CPath': b'/zc', b'VERSION': b'1.0'}
|
|
330
|
-
|
|
331
|
-
# # create the zeroconf serviceinfo object.
|
|
332
|
-
# zcfServiceInfo:ServiceInfo = ServiceInfo(serviceType, serviceName, port, weight, priority, properties, server, hostTTL, otherTTL, parsed_addresses=parsedAddresses)
|
|
333
|
-
|
|
334
|
-
# generate a broadcast packet to announce the service.
|
|
335
|
-
_logsi.LogVerbose("Generating Zeroconf Service Broadcast for service: '%s'" % serviceInfo.name)
|
|
336
|
-
dnsOutgoing = zeroconf.generate_service_broadcast(serviceInfo, serviceInfo.host_ttl, True)
|
|
337
|
-
|
|
338
|
-
# send the broadcast packet.
|
|
339
|
-
_logsi.LogVerbose("Sending Zeroconf Service Broadcast for service: '%s'" % serviceInfo.name)
|
|
340
|
-
zeroconf.send(dnsOutgoing, addr=None, port=port)
|
|
341
|
-
|
|
342
|
-
except Exception as ex:
|
|
343
|
-
|
|
344
|
-
# this is not really an exception, but more of an indicator that
|
|
345
|
-
# the timeout has been reached.
|
|
346
|
-
_logsi.LogException("Zeroconf Broadcast Service exception: %s" % str(ex), ex, logToSystemLogger=False)
|
|
347
|
-
|
|
348
|
-
|
|
349
303
|
def ToString(self, includeItems:bool=False) -> str:
|
|
350
304
|
"""
|
|
351
305
|
Returns a displayable string representation of the class.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# import all classes from the namespace.
|
|
2
|
+
from .blobbuilder import BlobBuilder
|
|
3
|
+
from .credentials import Credentials
|
|
4
|
+
from .spotifyzeroconfapierror import SpotifyZeroconfApiError
|
|
5
|
+
from .zeroconfconnect import ZeroconfConnect
|
|
6
|
+
from .zeroconfresponse import ZeroconfResponse
|
|
7
|
+
from .zeroconfgetinfo import ZeroconfGetInfo
|
|
8
|
+
from .zeroconfgetinfoalias import ZeroconfGetInfoAlias
|
|
9
|
+
from .zeroconfgetinfodrmmediaformat import ZeroconfGetInfoDrmMediaFormat
|
|
10
|
+
|
|
11
|
+
# all classes to import when "import *" is specified.
|
|
12
|
+
__all__ = [
|
|
13
|
+
'BlobBuilder',
|
|
14
|
+
'Credentials',
|
|
15
|
+
'SpotifyZeroconfApiError',
|
|
16
|
+
'ZeroconfConnect',
|
|
17
|
+
'ZeroconfGetInfo',
|
|
18
|
+
'ZeroconfGetInfoAlias',
|
|
19
|
+
'ZeroconfGetInfoDrmMediaFormat',
|
|
20
|
+
'ZeroconfResponse',
|
|
21
|
+
]
|
|
@@ -5,35 +5,29 @@ from Crypto.Util import Counter
|
|
|
5
5
|
from Crypto.Protocol.KDF import PBKDF2
|
|
6
6
|
from Crypto.Hash import SHA1
|
|
7
7
|
from base64 import b64decode, b64encode
|
|
8
|
-
import secrets
|
|
9
8
|
|
|
10
|
-
|
|
11
|
-
|
|
9
|
+
from .credentials import Credentials
|
|
10
|
+
from .cryptodiffiehellman import CryptoDiffieHellman
|
|
11
|
+
from .helpers import write_bytes, write_int, byte_list_to_int, b64_to_int, int_to_bytes
|
|
12
12
|
|
|
13
|
-
# copied from https://github.com/maraid/zerospot
|
|
14
13
|
|
|
15
|
-
class
|
|
16
|
-
def __init__(self, username: str, password: str):
|
|
17
|
-
self.username: bytes = bytes(username, 'ascii')
|
|
18
|
-
self.password: bytes = bytes(password, 'ascii')
|
|
19
|
-
self.auth_type: int = 0x00
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class ZeroconfBlobBuilder:
|
|
14
|
+
class BlobBuilder:
|
|
23
15
|
|
|
24
|
-
def __init__(self, credentials:
|
|
25
|
-
self.credentials:
|
|
16
|
+
def __init__(self, credentials: Credentials, device_id: str, remote_pubkey: str):
|
|
17
|
+
self.credentials: Credentials = credentials
|
|
26
18
|
self.device_id: bytes = bytes(device_id, 'ascii')
|
|
27
19
|
self.remote_pubkey: str = remote_pubkey
|
|
28
|
-
self.dh_keys =
|
|
20
|
+
self.dh_keys = CryptoDiffieHellman()
|
|
29
21
|
self._blob = b''
|
|
30
22
|
self._encrypted_blob = b''
|
|
31
23
|
|
|
24
|
+
|
|
32
25
|
def build(self):
|
|
33
26
|
self._build()
|
|
34
27
|
self._encrypt()
|
|
35
28
|
return self._encrypted_blob.decode("ascii")
|
|
36
29
|
|
|
30
|
+
|
|
37
31
|
def _build(self): # -> bytes
|
|
38
32
|
blob = bytearray()
|
|
39
33
|
# 'I'
|
|
@@ -75,6 +69,7 @@ class ZeroconfBlobBuilder:
|
|
|
75
69
|
|
|
76
70
|
self._blob = b64encode(encrypted_blob)
|
|
77
71
|
|
|
72
|
+
|
|
78
73
|
def _encrypt(self):
|
|
79
74
|
remote_device_key = b64_to_int(self.remote_pubkey)
|
|
80
75
|
shared_key = self.dh_keys.shared_secret(remote_device_key)
|
|
@@ -98,47 +93,4 @@ class ZeroconfBlobBuilder:
|
|
|
98
93
|
|
|
99
94
|
self._encrypted_blob = b64encode(encrypted_signed_blob)
|
|
100
95
|
|
|
101
|
-
|
|
102
|
-
def write_int(i: int, out: bytearray):
|
|
103
|
-
if i < 0x80:
|
|
104
|
-
out.append(i)
|
|
105
|
-
else:
|
|
106
|
-
out.append(0x80 | (i & 0x7f))
|
|
107
|
-
out.append((i >> 7))
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
def write_bytes(b: bytes, out: bytearray):
|
|
111
|
-
write_int(len(b), out)
|
|
112
|
-
out.extend(b)
|
|
113
|
-
|
|
114
|
-
def byte_list_to_int(byte_list):
|
|
115
|
-
return int.from_bytes(bytes(byte_list), 'big')
|
|
116
|
-
|
|
117
|
-
def int_to_bytes(i: int):
|
|
118
|
-
return i.to_bytes((i.bit_length() + 7) // 8, byteorder='big')
|
|
119
|
-
|
|
120
|
-
def int_to_b64str(i: int):
|
|
121
|
-
return b64encode(int_to_bytes(i)).decode('ascii')
|
|
122
|
-
|
|
123
|
-
def b64_to_int(b64: str):
|
|
124
|
-
return int.from_bytes(b64decode(b64), 'big')
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
class DiffieHellman:
|
|
128
|
-
DH_GENERATOR = 2
|
|
129
|
-
DH_PRIME = byte_list_to_int([
|
|
130
|
-
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2,
|
|
131
|
-
0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67,
|
|
132
|
-
0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e,
|
|
133
|
-
0x34, 0x04, 0xdd, 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
|
|
134
|
-
0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45, 0xe4, 0x85, 0xb5,
|
|
135
|
-
0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20, 0xff, 0xff,
|
|
136
|
-
0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
|
137
|
-
|
|
138
|
-
def __init__(self):
|
|
139
|
-
self._private_key = secrets.randbits(95 * 8)
|
|
140
|
-
self.public_key = pow(DiffieHellman.DH_GENERATOR, self._private_key, DiffieHellman.DH_PRIME)
|
|
141
|
-
|
|
142
|
-
def shared_secret(self, remote_key):
|
|
143
|
-
return pow(remote_key, self._private_key, DiffieHellman.DH_PRIME)
|
|
144
96
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
class Credentials:
|
|
2
|
+
"""
|
|
3
|
+
Credentials used by the Spotify SpConnectionLoginBlob method.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
def __init__(self, username: str, password: str):
|
|
7
|
+
"""
|
|
8
|
+
Initializes a new instance of the class.
|
|
9
|
+
|
|
10
|
+
Args:
|
|
11
|
+
username (str):
|
|
12
|
+
Spotify Connect user name to login with.
|
|
13
|
+
password (str):
|
|
14
|
+
Spotify Connect user password to login with.
|
|
15
|
+
"""
|
|
16
|
+
self.username: bytes = bytes(username, 'ascii')
|
|
17
|
+
self.password: bytes = bytes(password, 'ascii')
|
|
18
|
+
self.auth_type: int = 0x00
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import secrets
|
|
2
|
+
|
|
3
|
+
from .helpers import byte_list_to_int
|
|
4
|
+
|
|
5
|
+
class CryptoDiffieHellman:
|
|
6
|
+
|
|
7
|
+
DH_GENERATOR = 2
|
|
8
|
+
DH_PRIME = byte_list_to_int([
|
|
9
|
+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xc9, 0x0f, 0xda, 0xa2, 0x21, 0x68, 0xc2,
|
|
10
|
+
0x34, 0xc4, 0xc6, 0x62, 0x8b, 0x80, 0xdc, 0x1c, 0xd1, 0x29, 0x02, 0x4e, 0x08, 0x8a, 0x67,
|
|
11
|
+
0xcc, 0x74, 0x02, 0x0b, 0xbe, 0xa6, 0x3b, 0x13, 0x9b, 0x22, 0x51, 0x4a, 0x08, 0x79, 0x8e,
|
|
12
|
+
0x34, 0x04, 0xdd, 0xef, 0x95, 0x19, 0xb3, 0xcd, 0x3a, 0x43, 0x1b, 0x30, 0x2b, 0x0a, 0x6d,
|
|
13
|
+
0xf2, 0x5f, 0x14, 0x37, 0x4f, 0xe1, 0x35, 0x6d, 0x6d, 0x51, 0xc2, 0x45, 0xe4, 0x85, 0xb5,
|
|
14
|
+
0x76, 0x62, 0x5e, 0x7e, 0xc6, 0xf4, 0x4c, 0x42, 0xe9, 0xa6, 0x3a, 0x36, 0x20, 0xff, 0xff,
|
|
15
|
+
0xff, 0xff, 0xff, 0xff, 0xff, 0xff])
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def __init__(self):
|
|
19
|
+
self._private_key = secrets.randbits(95 * 8)
|
|
20
|
+
self.public_key = pow(CryptoDiffieHellman.DH_GENERATOR, self._private_key, CryptoDiffieHellman.DH_PRIME)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def shared_secret(self, remote_key):
|
|
24
|
+
return pow(remote_key, self._private_key, CryptoDiffieHellman.DH_PRIME)
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from base64 import b64decode, b64encode
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
def write_int(i: int, out: bytearray):
|
|
5
|
+
if i < 0x80:
|
|
6
|
+
out.append(i)
|
|
7
|
+
else:
|
|
8
|
+
out.append(0x80 | (i & 0x7f))
|
|
9
|
+
out.append((i >> 7))
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
def write_bytes(b: bytes, out: bytearray):
|
|
13
|
+
write_int(len(b), out)
|
|
14
|
+
out.extend(b)
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def byte_list_to_int(byte_list):
|
|
18
|
+
return int.from_bytes(bytes(byte_list), 'big')
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def int_to_bytes(i: int):
|
|
22
|
+
return i.to_bytes((i.bit_length() + 7) // 8, byteorder='big')
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def int_to_b64str(i: int):
|
|
26
|
+
return b64encode(int_to_bytes(i)).decode('ascii')
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def b64_to_int(b64: str):
|
|
30
|
+
return int.from_bytes(b64decode(b64), 'big')
|