1
+ import json
1
2
import pathlib
2
- import shutil
3
3
4
4
import audible
5
5
import httpx
6
+ from audible .aescipher import decrypt_voucher_from_licenserequest
6
7
7
8
8
- # files downloaded via this script can't be converted at this moment
9
+ # files downloaded via this script can be converted
9
10
# audible uses a new format (aaxc instead of aax)
10
11
# more informations and workaround here:
11
12
# https://github.com/mkb79/Audible/issues/3
13
+ # especially: https://github.com/mkb79/Audible/issues/3#issuecomment-705262614
12
14
13
15
14
- # get download link(s) for book
15
- def _get_download_link ( asin , quality ):
16
+ # get license response for book
17
+ def get_license_response ( client , asin , quality ):
16
18
try :
17
19
response = client .post (
18
20
f"content/{ asin } /licenserequest" ,
@@ -22,16 +24,21 @@ def _get_download_link(asin, quality):
22
24
"quality" : quality
23
25
}
24
26
)
25
- return response [ 'content_license' ][ 'content_metadata' ][ 'content_url' ][ 'offline_url' ]
27
+ return response
26
28
except Exception as e :
27
29
print (f"Error: { e } " )
28
30
return
29
31
30
32
33
+ def get_download_link (license_response ):
34
+ return license_response ["content_license" ]["content_metadata" ]["content_url" ]["offline_url" ]
35
+
36
+
31
37
def download_file (url , filename ):
32
- r = httpx .get (url )
33
- with open (filename , 'wb' ) as f :
34
- shutil .copyfileobj (r .iter_raw , f )
38
+ with httpx .stream ("GET" , url ) as r :
39
+ with open (filename , 'wb' ) as f :
40
+ for chunck in r .iter_bytes ():
41
+ f .write (chunck )
35
42
return filename
36
43
37
44
@@ -40,24 +47,33 @@ def download_file(url, filename):
40
47
41
48
auth = audible .FileAuthenticator (
42
49
filename = "FILENAME" ,
43
- encryption = "json" ,
44
50
password = password
45
51
)
46
- client = audible .AudibleAPI (auth )
52
+ client = audible .Client (auth )
47
53
48
54
books = client .get (
49
- path = "0.0/ library/books " ,
55
+ path = "library" ,
50
56
params = {
51
- "purchaseAfterDate" : "01/01/1970"
52
- }
53
- )["books" ]["book" ]
54
-
55
- for book in books :
56
- asin = book ['asin' ]
57
- title = book ['title' ] + f"( { asin } ).aaxc"
58
- dl_link = _get_download_link (asin , quality = "Extreme" )
59
- if dl_link :
57
+ "response_groups" : "product_attrs" ,
58
+ "num_results" : "999"
59
+ }
60
+ )
61
+
62
+ for book in books ["items" ]:
63
+ asin = book ["asin" ]
64
+ title = book ["title" ] + f"( { asin } ).aaxc"
65
+ lr = get_license_response (client , asin , quality = "Extreme" )
66
+
67
+ if lr :
68
+ # download book
69
+ dl_link = get_download_link (lr )
60
70
filename = pathlib .Path .cwd () / "audiobooks" / title
61
71
print (f"download link now: { dl_link } " )
62
72
status = download_file (dl_link , filename )
63
- print (f"downloaded file: { status } " )
73
+ print (f"downloaded file: { status } to { filename } " )
74
+
75
+ # save voucher
76
+ voucher_file = filename .with_suffix (".json" )
77
+ decrypted_voucher = decrypt_voucher_from_licenserequest (auth , lr )
78
+ voucher_file .write_text (json .dumps (decrypted_voucher , indent = 4 ))
79
+ print (f"saved voucher to: { voucher_file } " )
0 commit comments