mkb79 / audible Goto Github PK
View Code? Open in Web Editor NEWA(Sync) Interface for internal Audible API written in pure Python.
Home Page: https://audible.readthedocs.io
License: GNU Affero General Public License v3.0
A(Sync) Interface for internal Audible API written in pure Python.
Home Page: https://audible.readthedocs.io
License: GNU Affero General Public License v3.0
pip install audible
created a test.py file.
import audible
# for US accounts
client = audible.Client("myemail", "mypassword", local="us")
# specify a api_version on request
# default is api_version="1.0"
# get deprecated version of library
library = client.get("library/books", api_version="0.0", purchaseAfterDate="01/01/1970", sortInAscendingOrder="true")
print(library)
executed that file. with python3.6
python3.6 test.py
the results I got back are.
Answer for CAPTCHA: audible-api: unable to open X server `' @ error/display.c/DisplayImageCommand/410.
I realize I need to register, however I have no idea how to go about doing that. Is there any sample code on how to go about doing that?
Having a hard time understanding how does the BestSellers option in products_sort_by parameter works, for instance in /1.0/catalog/products endpoint. I'm trying to make API calls about the products on audible and sort them by best sellers, yet I'm getting random items in response that are definitely not sorted by best sellers:
client.get("/1.0/catalog/products", num_results=50, page=0, response_groups=['product_attrs'], products_sort_by=['BestSellers'])
Am I doing this wrong or is audible just ignoring the parameter?
Is your feature request related to a problem? Please describe.
Audible.es | Spain is a new Audible Marketplace. See Audible Help
It is yet not included in the localization.
Describe the solution you'd like
Add
"spain": { "country_code": "es", "domain": "es", "market_place_id": "" },
using:
audible 0.6.0
Python 3.10
When trying to login using captcha method, login fails due to an exception 'KeyError'.
I am using a captcha call back but the guess
seems to be coming back correctly on ln 376.
In line 388 of login.py ( last line in the section below ) it calls the 'get_next_action_from_soup'
while check_for_captcha(login_soup):
...
inputs = get_inputs_from_soup(login_soup)
inputs["guess"] = guess
inputs["use_image_captcha"] = "true"
inputs["use_audio_captcha"] = "false"
inputs["showPasswordChecked"] = "false"
inputs["email"] = username
inputs["password"] = password
method, url = get_next_action_from_soup(login_soup)
inside that method it gets an exception on line 126
method = form["method"]
KeyError: method
The form variable contains the following
(<)form action="get" name="ue_backdetect"(>)<input name="ue_back" type="hidden" value="1"/></form>
Replace (<) with < above
I have used the captcha on many occasions in the past with success until now.
I know you can do this via search the market place but was hoping there was a tag for it so I could see it for books in my library
hi, do you have scraped some info about the api endpoint for searching the marketplace?
I'm not getting the audible app to work with mitmproxy.
Describe the bug
Using the https://cde-ta-g7g.amazon.com/FionaCDEServiceEngine/sidecar
worked previously with audible.Client
and returned the correct response. Now it returns None. In client.py Client._request()
the resp
object contains the correct response however the response_callback()
function returns None with the resp
object, hence this endpoint is unusable.
This is because
in default_response_callback
resp.next_request
returns None for this endpoint
To Reproduce
auth = audible.Authenticator.from_file("credentials.json")
def get_bookmarks(url, **kwargs):
with audible.Client(auth=auth) as client:
library = client.get(
url,
**kwargs
)
return library
Expected behavior
Returns the clips, notes and bookmarks of a book
Desktop (please complete the following information):
audible==0.8.2
Python 3.10.1
Need help from users for another method to register a new Audible dummy device!
Please tell me if the code below let you register a new device or if you get any error message!
Great project! Thanks so much for all the hard work. :)
I recently ran into the issue of approval alerting (that amazon recently added) and it was already fixed! Wow.
I wanted to see if you could expose the alert callback similar to OTP, CVF, etc.? That would be much appreciated, thanks!
Hello there,
I started working with this repo a few hours ago because I do like the idea of archiving audiobooks.
This is a plus catalog audiobook so anyone with the subscription can help me with it.
ASIN - 1665074620
Title - What Addicts Know
I am using Google Colab for this as I like to try new things there and then implement the rest on my server.
I have a few questions about the usage but before that, I want to know how to download the audiobooks. I don't care about the format (.aax or .aacx) because I can decode either. Which link do I download?
The following is my code to get the download URL:
body = {
"supported_drm_types" : [
"Mpeg",
"Adrm"
],
"quality" : "High",
"consumption_type" : "Download"
}
token = client.post("1.0/content/1665074620/licenserequest", body)
print(json.dumps(token, indent=3, sort_keys=True))
{
"content_license": {
"access_expiry_date": "2024-12-31T12:00:00Z",
"acr": "CXXXXXX",
"allowed_users": [
"amzn1.account.XXXXXXXXXXXXXXXXXXXXXXXXX"
],
"asin": "1665074620",
"content_metadata": {
"content_url": {
"offline_url": "https://dze5l2jxnquy5.cloudfront.net/bk_blak_016548it/28335321/aax/XXXX....XXXX"
}
},
"drm_type": "Adrm",
"license_id": "XXXXXXXXXXXXXXXXXXXXXXXX",
"license_response": "y/XXXXXX.....XXXXX",
"message": "Customer [XXXXXXXXXXXXXXX] has rights to asin [1665074620] for AYCL",
"refresh_date": "2022-03-18T06:28:07Z",
"removal_date": "2022-04-27T06:28:07Z",
"request_id": "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX",
"requires_ad_supported_playback": false,
"status_code": "Granted",
"voucher_id": "cdn:XXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
},
"response_groups": [
"always-returned"
]
}
### When I click the offline_url, I get this following error:
##
At first I thought that my macBook and the Colab instance have different IP Addresses and thats why I can't download it. Then I tried downloading it directly on the colab instance but it still wouldn't download.
I don't understand what I am doing wrong here. I read the closed thread for downloading files but the first post is from back in 2019 and it doesn't work.
The other question I have is about only getting the Audible Plus Catalog. I see the plan for it is named "Audible-AYCL" which is not included in plans[]. I created a function for this and I got around it but it would be nice if it was updated.
### My whole code:
!mkdir /content/audible
import audible, urllib, cv2, json
from google.colab.patches import cv2_imshow (I am running this in google colab)
DIR_PATH = "/content/audible"
email = "xx"
pasword = "xx"
country = "xx"
def cb(captcha_url):
urllib.request.urlretrieve(captcha_url, "/content/audible/captcha.jpg")
image = cv2.imread('/content/audible/captcha.jpg')
cv2_imshow(image)
print(captcha_url)
answer = input("Answer for CAPTCHA: ")
answer = str(answer).strip().lower()
return answer
!rm /content/captcha.jpg
auth = audible.Authenticator.from_login(
email,
pasword,
locale = country,
with_username=False,
captcha_callback=cb
)
auth.to_file(DIR_PATH+country)
auth = audible.Authenticator.from_file(DIR_PATH+country)
client = audible.Client(auth)
body = {
"supported_drm_types" : [
"Mpeg",
"Adrm"
],
"quality" : "High",
"consumption_type" : "Download"
}
token = client.post("1.0/content/1665074620/licenserequest", body)
print(json.dumps(token, indent=3, sort_keys=True))
Looking forward to solving this problem. Will update if I find something new.
Not really an issue but more like a question.
One of the fields returned when querying my book library is the "content_type".
I would like to find out what are all the potential values associated with that field.
Based on the content of my own library I see these:
Episode 1
Lecture 15
Newspaper / Magazine 2
Performance 12
Product 601
Radio/TV Program 5
Show 1
Speech 6
Do you have such a list or a way to find such a list?
Thanks!
I am building an endpoint that will just return the login URL returned from build_oauth_url
Heres the code:
def get_auth_link():
code_verifier = audible.login.create_code_verifier()
oauth_url = audible.login.build_oauth_url(
country_code=COUNTRY_CODE,
domain=DOMAIN,
market_place_id=MARKETPLACE_ID,
code_verifier=code_verifier,
with_username=False
)
return oauth_url
When I use the link, sign in and get the address bar URL to use from_login_external
I get this as a return exception:
Exception: {'response': {'error': {'code': 'InvalidValue', 'index': 'tGP0Ha5AGkt8rT5f6GvjpwAAAAAAAAABCoOqqcjUmA7AKfxjSct01Cg_pilnvd6EEVWx2HFy9kOVWSGENsmEtLsb4T6TZHp8zL_c87GaD91q9qFKypHaaxu34HHfFjfv5gRHpfla80sRtMspddIA8e63XKV7tPaiRy3JG-wkH8mu1UgOHYwpgnWjmeKY-gSC9oVhl0e86leJkMF25Lluxz-fBorjbap52nclsr9Ml6FmSkUKVLWdbQ==', 'message': 'One or more provided values are invalid.'}}, 'request_id': 'fcd9fbe1-2432-4af5-bfc1-6cf3d1e42ebb'}
I am using the callback on from_login_external
to pass in the URL from my custom endpoint like so:
def audible_login():
#{ id: str, url: str }
params = request.json
print(params['url'])
def auth_link_url_callback(login_url: str):
print(login_url)
return params['url']
auth = audible.Authenticator.from_login_external(COUNTRY_CODE, login_url_callback=auth_link_url_callback)
auth.to_file(params['id'])
I am posting the URL and via a CURL command for testing:
curl -X POST -H "Content-Type: application/json" -d '{
"url": "https://www.amazon.com.au/ap/maplanding?openid.assoc_handle=amzn_audible_ios_au&openid.claimed_id=https%3A%2F%2Fwww.amazon.com.au%2Fap%2Fid%2Famzn1.account.AHDJ2REEGR72DEJEMJDUBHMW4PUA&openid.identity=https%3A%2F%2Fwww.amazon.com.au%2Fap%2Fid%2Famzn1.account.AHDJ2REEGR72DEJEMJDUBHMW4PUA&openid.mode=id_res&openid.ns=http%3A%2F%2Fspecs.openid.net%2Fauth%2F2.0&openid.op_endpoint=https%3A%2F%2Fwww.amazon.com.au%2Fap%2Fsignin&openid.response_nonce=2022-01-05T07%3A35%3A16Z-1504074421391324938&openid.return_to=https%3A%2F%2Fwww.amazon.com.au%2Fap%2Fmaplanding&openid.signed=assoc_handle%2Cclaimed_id%2Cidentity%2Cmode%2Cns%2Cop_endpoint%2Cresponse_nonce%2Creturn_to%2Cns.pape%2Cpape.auth_policies%2Cpape.auth_time%2Coa2.authorization_code%2Ccaptcha_verified%2Csigned&openid.ns.pape=http%3A%2F%2Fspecs.openid.net%2Fextensions%2Fpape%2F1.0&openid.pape.auth_policies=http%3A%2F%2Fschemas.openid.net%2Fpape%2Fpolicies%2F2007%2F06%2Fnone&openid.pape.auth_time=2022-01-05T07%3A35%3A16Z&openid.sig=kHOEjSvIPKmMI6r1FfL2SjC6fKeRFFkbwFbXkO6t1zs%3D&serial=&openid.oa2.authorization_code=SRCSCKBUVJDQKPfDDWMZAUSg&openid.ns.oa2=http%3A%2F%2Fwww.amazon.com%2Fap%2Fext%2Foauth%2F2&captcha_verified=1&",
"id": "1"
}' http://localhost:5000/login_with_url
Am I building up the URL wrong? Any advice would be appreciated.
Hey mkb79,
I wanted to thank you for this library... and I would like to get involved and contributing to this library. Lets chat when you get a chance...
Thanks
I'm working on my new project MyAudible. I have no experience with Django. Everyone is welcome to help me building a good Django app!
I found out today, that Amazon changed the "openid.oa2.response_type" from "token to "code". In result of this, a successfully authorization gives a "authorization_code" instead of a "access_token". In exchange for the authorization code a access token can be requested. But this requires a device registration.
Amazon still accepts "token" request for now. Maybe this can change in the future.
Hi!
I was looking to use this package but when I tried to install it Windows throws an ugly error message caused by the pycrypto setup.py
. Looking up how to resolve this issue wasn't very helpful as it seems that pycrypto is dead.
I'm sure I can find a workaround but I thought it might be worth making an issue as it's probably not great to be using a corpse of a library as a dependency. If there's not interest in it then fair enough and the issue can just be closed.
Thanks!
Hi mkb79,
Thanks for the Python library!
I was able to use an older version back in July but it started failing when I tried to use it again today.
So, I downloaded the new version (0.2.1 v 0.1.5), made the necessary code changes and I'm still getting the same error.
Here's an abbreviated version of the body of my request:
{'requested_token_type': ['bearer', 'mac_dms', 'website_cookies', 'store_authentication_cookie'], 'cookies': {'website_cookies': [], 'domain': '.amazon.com'}, 'registration_data': {'domain': 'Device', 'app_version': '3.7', 'device_serial': 'Y9UGDIF8OUUKCUF1CHV8M8YZDREDDFM0WOHGDRQV', 'device_type': 'A2CZJZGLK2JJVM', 'device_name': '%FIRST_NAME%%FIRST_NAME_POSSESSIVE_STRING%%DUPE_STRATEGY_1ST%Audible for iPhone', 'os_version': '12.3.1', 'device_model': 'iPhone', 'app_name': 'Audible'}, 'auth_data': {'access_token': 'Atna|EwICID7AOCk...'}, 'requested_extensions': ['device_info', 'customer_info']}
And the return json associated with the 500 HTTP error:
{'request_id': '1fbad2a3-978b-4319-8497-7099f6bc17b3', 'response': {'error': {'code': 'ServerError', 'index': 'xYLIwBnwW...==', 'message': 'The server has encountered a runtime error.'}}}
What am I doing wrong?
Is it a temporary server outage?
Thanks.
I‘ve created a new branch. It doesn’t show up a captcha request for 5 logins. But for now captchas seems to be appearing. Maybe I tried to often in very short time.
Can someone test the new branch and try to login (hopefully without a captcha)?!
New login page requires this parameter, it gets encrypted using aes128 gcm with jwk rsa. I didn't get the exact code to mimic the process. Can anybody help me to get the encryption part?
Describe the bug
When i try to download high quality books it fails with:
error: Bad Request (400): 1 validation error detected: Value 'Extreme' at 'quality' failed to satisfy constraint: Member must satisfy enum value set: [High, Normal]
if i set the quality to normal
it works. Further, the --ignore-errors
is ignored
To Reproduce
Steps to reproduce the behavior:
run audible download --all --aaxc --cover --cover-size 1215 --chapter -y -q high --ignore-errors
Expected behavior
Download the audiobooks
Desktop (please complete the following information):
Describe the bug
If your email address has “-”,It will not be allowed to pass the is_valid_email inspection!
For example:[email protected] it no work!
login.py 222 line
def is_valid_email(obj: str) -> bool:
valid_mail = r"^[a-z0-9]+[._]?[a-z0-9]+[@]\w+[.]\w+$"
if re.match(valid_mail, obj):
return True
return False
It should be changed to:^\w+([-+.]\w+)@\w+([-.]\w+).\w+([-.]\w+)*$
I'm trying to use the pdf_url value from the GET /1.0/library/%{asin}
endpoint. It worked before, but currently the value is a cloudfront.net URL. However, the URL is missing the Key-Pair-Id and Policy query parameters, so using the URL results in an error message. Do you know how to get a working URL with these parameters?
I can not install this program as it relies on pycrypto, which is bugged the hell out when ever I try to install it. The issue with pycrypto is well know, and, aparrently, pycrypto has been depricated.
Hi!
Thanks a lot for the hard work on this!
I also am a big fan of Audible and Kindle.
I tend to buy the Kindle and Audible versions of the same book.
Although, whispersync for voice is not available in my country.
However, the books I buy definitely support Whispersync for voice.
I'm looking for a homemade way to synchronize my Kindle and Audible books.
Would your API be of any help to achieve my goal?
Thanks for your help!
Hi mkb79,
When I use the call/endpoint https://github.com/mkb79/Audible#get-10library the doc indicates that I should get the category/genre associated with each book but it doesn't seem to be the case.
I see "category_ladders" but it's always null for me.
What am I missing?
Thanks!
I am trying to get the "finished" status of all titles in my library. I'm able to log in successfully and retrieve the titles, but the "is_finished" attribute is always set to None. Here is the code snippet I'm using:
auth = audible.FileAuthenticator("audible.save")
print(auth.adp_token)
client = audible.AudibleAPI(auth)
library, _ = client.get("library")
for book in library["items"]:
print(book['is_finished'])
I'm guessing this is more a problem with the API returning that value but the mobile app must be retrieving it somehow.
Intead of a typical CAPTCHA image that looks like this:
I'm now getting a partial image like this:
I haven't change anything to my code. The only difference is that I've upgraded to a Mac Mini M1 (vs an old Mac Mini 2012) which came with Bigsur (vs Catalina).
My old Mac is no longer available for me to test. :-(
Hi
I can't seem to get the "product_page_url" out of the request?
I am not sure witch response_group I need to use for this but I am using the following request and not getting anything but "None"
with audible.Client(auth=auth_US) as client:
library = client.get(
"1.0/library",
num_results=1000,
response_groups="contributors, media, product_attrs, product_desc, product_extended_attrs, product_plan_details, product_plans, rating, series, origin, relationships, categories, badge_types, category_ladders, is_downloaded, is_finished, is_removable, is_returnable, is_visible, order_details, pdf_url, percent_complete",
#"contributors,product_desc, product_attrs, media, is_finished, product_extended_attrs, is_playable, is_removable, is_returnable, pdf_url, percent_complete",
sort_by="-PurchaseDate"
)
Any help would be amazing thanks.
When using the example code to download an AAXC from my library I am now receiving 403 Forbidden response codes. This worked fine before, but has just started this month. I'm able to authenticate, and pull down a fresh library list.
To Reproduce
Steps to reproduce the behavior:
with httpx.stream("GET", url) as r:
Relevant Dependencies:
httpx v0.16.1
audible v0.5.4 (this library)
I have made no changes in the last few months, and it has worked fine until now. Last known working was late April 2021. But after trying it in the last couple days (with no changes) I now get a 403 forbidden. Can't seem to figure out what is different or the reason for the 403. Audible API change?
However, if I take the URL that it's attempting to use it will work just fine in the browser (not logged in and all history/cache/cookies cleared). However it seems to download an aax file not an aaxc file. But nonetheless a file is downloaded- no 403. I've never tried to put the URL in the browser before now so I'm not sure what the expected behavior is.
Just started using this API and wondered if there is a way to download the cover art for books too?
There is a value 'image_url' but it seems to be None for every book.
Any help would be awesome thanks.
Describe the bug
Unable to log in to au store using the library
Maybe there was a change in the audible API?
To Reproduce
Steps to reproduce the behavior:
import audible
from getpass import getpass
import logging
logging.basicConfig(stream=sys.stderr, level=logging.INFO)
user = input('Username (email): ')
passwd = getpass()
auth = audible.Authenticator.from_login(
user,
passwd,
locale="AU",
with_username=False,
captcha_callback=captcha,
)
auth.to_file(auth_file)
client = audible.Client(auth=auth)
library = client.get(
'library',
num_results=1000,
response_groups=','.join([
'series',
'product_desc',
'product_attrs',
]),
sort_by='Author',
)
Expected behavior
It should return the library of the logged in user
Logs
INFO:audible.login:Login with Amazon Account.
ERROR:audible.login:Error message: Important Message! To better protect your account, please re-enter your password and then enter the characters as they are shown in the image below.
ERROR:audible.login:Error message: We're sorry. The Web address you entered is not a functioning page on our site
INFO:audible.auth:logged in to Audible as [omitted]
INFO:audible.auth:saved data to file .audible_auth
INFO:audible.auth:set filename .audible_auth as default
INFO:__main__:retrieving library
INFO:audible.auth:bearer auth flow applied to request
Traceback (most recent call last):
File "/home/$USER/.local/share/virtualenvs/audible-release-tracker-uvQ44N2A/lib/python3.9/site-packages/audible/client.py", line 143, in _request
resp.raise_for_status()
File "/home/$USER/.local/share/virtualenvs/audible-release-tracker-uvQ44N2A/lib/python3.9/site-packages/httpx/_models.py", line 1402, in raise_for_status
raise HTTPStatusError(message, request=request, response=self)
httpx.HTTPStatusError: 400 Client Error: Bad Request for url: https://api.audible.com.au/1.0/library?num_results=1000&response_groups=series%2Cproduct_desc%2Cproduct_attrs&sort_by=Author
For more information check: https://httpstatuses.com/400
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/$USER/Projects/audible-release-tracker/script.py", line 184, in <module>
asyncio.run(main())
File "/usr/lib/python3.9/asyncio/runners.py", line 44, in run
return loop.run_until_complete(main)
File "/usr/lib/python3.9/asyncio/base_events.py", line 642, in run_until_complete
return future.result()
File "/home/$USER/Projects/audible-release-tracker/script.py", line 166, in main
for title,owned in get_owned_series(client).items()
File "/home/$USER/Projects/audible-release-tracker/script.py", line 64, in get_owned_series
library = client.get(
File "/home/$USER/.local/share/virtualenvs/audible-release-tracker-uvQ44N2A/lib/python3.9/site-packages/audible/client.py", line 217, in get
return self._request("GET", path, params=params, **kwargs)
File "/home/$USER/.local/share/virtualenvs/audible-release-tracker-uvQ44N2A/lib/python3.9/site-packages/audible/client.py", line 157, in _request
self._raise_for_status_error(exc.response)
File "/home/$USER/.local/share/virtualenvs/audible-release-tracker-uvQ44N2A/lib/python3.9/site-packages/audible/client.py", line 104, in _raise_for_status_error
raise BadRequest(resp, data)
audible.exceptions.BadRequest: Bad Request (400): The specified authorization token does not correspond to a supported domain
Desktop (please complete the following information):
Additional context
It was definitely working last month
Describe the bug
When I attempt to authenticate, I get constant Captchas. I input the captcha details, but it will not continue
To Reproduce
Steps to reproduce the behavior: Simply running the code below
import audible
auth = audible.Authenticator.from_login(
"email",
"pass",
locale='us'
)
with audible.Client(auth=auth) as client:
library = client.get(
"1.0/library",
num_results=1000,
response_groups="product_desc, product_attrs",
sort_by="-PurchaseDate"
)
for book in library["items"]:
print(book)
Desktop (please complete the following information):
It seems that Amazon has recently changed its Login Security such that the CVF code usually supplied via email to verify a new login has been replaced with a system that lets the user click a link and either allow or deny the login attempt.
This has broken the CVF flow in the Audible API:
Lines 110 to 112 in a1a7041
Describe the bug
When fetching the library (calling aget_from_api in models.py::Library), if the library is very large (or transfer is slow), the underlying httpx call can timeout,
Workaround
Replace: resp = await api_client.get("library", params=request_params)
With: resp = await api_client.get("library", params=request_params, timeout=None)
Suggested Solution
Expose a timeout parameter in aget_from_api.
This makes the problem the consumer of the library and avoids the infinite timeout employed by the workaround.
I'm trying to follow the different examples provided to get a book download URL.
I'm successfully authenticating and fetching my library. However, I'm getting a 500 error when trying to get the book download URL as follow:
license = client.post(
f"content/{child_asin}/licenserequest",
body={
"drm_type": "Adrm",
"consumption_type": "Download",
"quality": "Extreme"
}
)
content_url = license['content_license']['content_metadata']['content_url']['offline_url']
The error obtained is as follow:
audible.exceptions.UnexpectedError: Internal Server Error (500): Unexpected error while servicing request for ASIN: B07231CR59 and ACR: null.
I tried using the book asin directly and using its child asin. Can you point me in the correct direction?
I'm using this code
auth = audible.LoginAuthenticator( username, password, locale=custom_locale, captcha_callback=custom_captcha_callback, )
to login, but it always asks for "Code: " after solving the captcha. What code ist requested here, where can I find it and is there a way to automatically fill it in or prevent asking for it as I want to use it in an automated script (captcha solver service is working already)? I don't have 2FA set up in amazon and I'm using version 0.2.1 installed via pip
I have this java script which encrypts a strigified JSON object.
Amazon apps using this string as the "frc" cookie. My app creates the frc cookie from custom bytes. Amazon still accepts this frc cookie. But I will be prepared for the future and build the frc cookie the same way as Amazon does.
I've tried to rebuild the java script to python
import base64
import hmac
import hashlib
import json
import gzip
from Crypto.Cipher import AES
from Crypto.Util.py3compat import bchr
def check_sig(pw, iv, data, sig):
key = get_key_from_password(pw, b'HmacSHA256')
new_sig = hmac.new(key, iv + data, hashlib.sha256).digest()
new_sig = new_sig[:len(sig)]
assert sig == new_sig, 'Signature check failed'
def decrypt_frc(pw, iv, data):
key = get_key_from_password(pw, b"AES/CBC/PKCS7Padding")
crypter = AES.new(key, AES.MODE_CBC, iv)
decrypted_data = crypter.decrypt(data)
return decrypted_data
def split_frc(frc):
frc += (len(frc) % 4) * '='
frc = base64.b64decode(frc)
sig = frc[1:9]
iv = frc[9:25]
data = frc[25:]
return sig, iv, data
def get_key_from_password(pw, salt):
return hashlib.pbkdf2_hmac('sha1', pw, salt, 1000, 16)
def pkcs7unpad(msg, blocklen):
assert len(msg) % blocklen == 0
paddinglen = msg[-1]
assert paddinglen > 0 and paddinglen <= blocklen, "Incorrect padding - Wrong key"
assert msg[-paddinglen:] == bchr(paddinglen) * paddinglen, "Incorrect padding - Wrong key"
return msg[:-paddinglen]
if __name__ == '__main__':
frc_cookie = ''
device_serial = ''
device_serial = device_serial.encode()
sig, iv, data = split_frc(frc_cookie)
check_sig(device_serial, iv, data, sig)
decrypted = decrypt_frc(device_serial, iv, data)
decrypted = pkcs7unpad(decrypted, 16)
decompressed = gzip.decompress(decrypted)
decrypted_data = json.loads(decompressed)
Can someone with JAVA and Python knowledge take a look on my code if I have take a misstake?
A library response returns a 13-digit numeric state-token
in the response headers.
Using this state token in the url query on the next request like /1.0/library?state_token=1234567654321
will return only changes since the state take was given.
If there are no new content, the json response body items
list is empty, the total-count
header entry is 0 and the state token is in the header is unchanged. If there are changes in the library, a new state token is obtained, which should be used next time.
Could you please add Australian and Italian marketplaces:
"australia": { "countryCode": "au", "domain": "com.au", "marketPlaceId": "AN7EY7DTAW63G" }, "italy": { "countryCode": "it", "domain": "it", "marketPlaceId": "A2N7FU2W2BU2ZC" },
Thanks!
I will add support using username to login to Audible. Can someone with username test this?
I've just used my python shell to successfully authenticate myself.
audible.LoginAuthenticator("[email protected]", "pw", locale="uk")
After the captcha it returned a LoginAuthenticator object.
I did not save the returned object to a variable, so I'm unable to save it to a file.
Now when I try to authenticate again (so that this time I can then save the auth to a file) it prompts me for a "code", which I think is a 2FA code right?
I have checked my emails, and I've logged into my audible account and I can't seem to find any 2FA notifications, nor options to disable 2FA.
I've got the string repr of the LoginAuthenticator object that was printed out to my console.
Is there any way I can turn this string into the right format and save that to a file, which I can then use to authenticate myself again?
Thanks and nice one for writing this package :)
Describe the bug
The subject says it all
To Reproduce
Executing download_books_aaxc.py with a valid German account and a book you own.
Result is
Error: Internal Server Error (500): There was an internal error processing the request
in get_license_response
I have no experience with http via python so at the moment I do not know how to narrow it down but I am willing to help if somebody can point me in the right direction
Expected behavior
Eventually a downloaded book but at the moment I am more interested in the voucher file
Screenshots
If applicable, add screenshots to help explain your problem.
Desktop (please complete the following information):
我在对接注册设备的时候提示{"response":{"error":{"code":"InvalidValue","index":"RYuYsd_4VoiVF34wpxzEJAAAAAAAAAABv_ARlqvxrJ-jPM4mLFcoeH3O84pv6xnbo-wcRzJIxyyhPjBCuewweBAyzdvpHH8pNWKTMsS-INu_7O68uG5-zO2zLPuh4pw3hCpbGWbU0U2E69sXj2DW1Wg23I_GGku1y0pmefIWzfmLwdMkXSDjzkO7OzK3JzmjmcegCPIihpnSNbodgAtiE06b6cfjDnEcaPoTICxuYcXvy1zOOuXsSAYHULgBTO_XXnJHGw==","message":"One or more provided values are invalid."}},"request_id":"67dde610-45d1-4cef-9c3f-fd4f2f58ddf3"},
请问怎么处理
Thanks for creating this package. I'm trying to login over JupyterLab and, although I do get the OTP via text message, the cell throws a "Login failed. Please check the log" error message. That is, the "OTP Code: " prompt does not show up for me in JupyterLab. Is there a workaround or something else I could do instead? Thanks.
Books downloaded with
license, _ = client.post(
"content/{asin}/licenserequest",
body={
"drm_type": "Adrm",
"consumption_type": "Download",
"quality":"Extreme"
}
)
content_url = license['content_license']['content_metadata']['content_url']['offline_url']
can’t converted with ffmpeg -activation_bytes ...
at this moment.
Read here
https://www.epubor.com/how-to-convert-audible-aaxc-to-mp3.html
https://www.reddit.com/r/audible/comments/c1zk2c/axxc_format_drm_and_audible_escape/
Audible uses a new aaxc format when downloading via audible app on android/iOS or the api. But with this client you can get the response of a licenserequest. Example shorten on many places with ... :
{
"content_license": {
"acr": "CR!...",
"asin": "B07DDKJH33",
"content_metadata": {
"content_url": {
"offline_url": "https://dyrrggeck87jc.cloudfront.net/.../bk_adko_003749ade_lc_128_44100_2.aax?voucherId=cdn:...&Policy=...&Signature=...&Key-Pair-Id=..."
}
},
"drm_type": "Adrm",
"license_response": "...==",
"message": "Eligibility details:[GrantRightsReason [reasonCode=MEMBERSHIP, reason=No need to verify active offline license when request is not for offline consumption. OWNERSHIP-user does not have expected ownership rights over the parent title asin. OWNERSHIP-title does not qualify for long title child part ownership or customer does not own child part. OWNERSHIP-user has ownership rights. GEO_RIGHTS-user has geo-rights[DE] over the title[B07DDKJH33] in marketplaceId[AN7V1F1VY261K]. TITLE_ATTRIBUTES-title does not have rodizio plan association. GEO_RIGHTS-user has geo-rights[DE] over the title[B07DDKJH33] in marketplaceId[AN7V1F1VY261K]. No need to verify active offline license when request is not for offline consumption. BENEFIT-user has valid Radio benefit associated[RadioStub]. TITLE_ATTRIBUTES-title does not have radio plan association. Client Asin Mapping validation skipped since client id is null. AAA Client with id: ApolloEnv:AudibleApiExternalRouterService/EU/Prod, does not have access to asin: B07DDKJH33. Client does not have plans that support asin benefits.]]. Licensing details:[ADRM license granted]",
"request_id": "...",
"status_code": "Granted",
"voucher_id": "cdn:..."
},
"response_groups": [
"always-returned"
]
}
Maybe someone has the know-how to use this informations to decode the new aaxc format.
Meanwhile you can grab the audible web page for the download urls. You can use cookies to authenticate like so:
import audible
import requests
auth = audible.FileAuthenticator(...)
cookies = auth.login_cookies
r = requests.get("https://www.audible.com/...", cookies=cookies)
Edit 2022-01-11:
Since ffmpeg 4.4 decryption of aaxc files should be build in. You have to use ffmpeg with the --audible_iv
and --audible_key
options and the correct iv/key pair from the decrypted licenserequest response!
I tried to authenticate in the following:
import audible
auth = audible.Authenticator.from_login(
USERNAME,
PASSWORD,
locale='fr',
with_username=False
)
After entering the captcha, validating 2SV, I press enter and get:
Answer for CAPTCHA: pr3ybz
Approval alert detected! Amazon sends you a mail.
Please press ENTER when you approve the notification.
---------------------------------------------------------------------------
IndexError Traceback (most recent call last)
<ipython-input-10-c44ab5a00348> in <module>
5 PASSWORD,
6 locale=COUNTRY_CODE,
----> 7 with_username=False
8 )
~/anaconda3/lib/python3.7/site-packages/audible/auth.py in from_login(cls, username, password, locale, serial, with_username, register, captcha_callback, otp_callback, cvf_callback, approval_callback)
363 otp_callback=otp_callback,
364 cvf_callback=cvf_callback,
--> 365 approval_callback=approval_callback)
366
367 logger.info(f"logged in to Audible as {username}")
~/anaconda3/lib/python3.7/site-packages/audible/auth.py in re_login(self, username, password, serial, with_username, captcha_callback, otp_callback, cvf_callback, approval_callback)
592 otp_callback=otp_callback,
593 cvf_callback=cvf_callback,
--> 594 approval_callback=approval_callback)
595
596 serial = login_device.pop("serial")
~/anaconda3/lib/python3.7/site-packages/audible/login.py in login(username, password, country_code, domain, market_place_id, serial, with_username, captcha_callback, otp_callback, cvf_callback, approval_callback)
403 default_approval_alert_callback()
404
--> 405 url = login_soup.find_all("a", class_="a-link-normal")[1]["href"]
406
407 login_resp = session.get(url)
IndexError: list index out of range
Heads up: a user of Libation got a CVF approval page without div id resend-approval-alert. Look for one of these also:
form id="resend-approval-form" method="post" action="/ap/cvf/approval/resend"
a id="resend-approval-link" class="a-link-normal" href="#"
Describe the bug
When downloading from the JP marketplace, only ascii characters in the title of the book are used in the filename.
For example, this results in a title named "ぼぎわんが、来る"
to be empty, named only as "-AAX_22_64.aaxc"
This makes it difficult to use the --all option, as all the files are named the same.
audible library list
however, displays the book titles properly.
To Reproduce
audible download --all
or
audible download -a ASIN
Where does the file get stored? Is there a way I can use to_file
and from_file
with a different storage container?
I'm having problems getting this to work in the Australia Marketpace. Not sure if its just me or everyone.
I am able to log in, but authorizing a new device returns an error. Other regions are working fine.
resp = httpx.post(f"https://api.amazon.{domain}/auth/register", json=body)
Get error 400 BAD REQUEST from:
Exception: {'response': {'error': {'code': 'InvalidToken', 'index': 'cXZ_xxxx_z95BIfA==', 'message': 'One or more tokens are invalid.'}}, 'request_id': '81d134e1-c0f9-4a83-8dce-xxxx'}
I verified that a device isn't created at:
https://www.amazon.com.au/hz/mycd/digital-console/devicedetails?deviceFamily=AUDIBLE_APP
But able to log in and register a device from the android app.
Trying to figure out a way to debug.. Was wondering if there is another Amazon API call that we can call to check that the session was established? Anyway, happy to provide more details or help debug if I can.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.