{ "info": { "author": "mkb79", "author_email": "mkb79@hackitall.de", "bugtrack_url": null, "classifiers": [ "Development Status :: 4 - Beta", "Intended Audience :: Developers", "License :: OSI Approved :: GNU Affero General Public License v3", "Programming Language :: Python :: 3.6", "Programming Language :: Python :: 3.7", "Programming Language :: Python :: 3.8" ], "description": "# Audible\n\n[![image](https://img.shields.io/pypi/v/audible.svg)](https://pypi.org/project/audible/)\n[![image](https://img.shields.io/pypi/l/audible.svg)](https://pypi.org/project/audible/)\n[![image](https://img.shields.io/pypi/pyversions/audible.svg)](https://pypi.org/project/audible/)\n[![image](https://img.shields.io/pypi/status/audible.svg)](https://pypi.org/project/audible/)\n[![image](https://img.shields.io/pypi/wheel/audible.svg)](https://pypi.org/project/audible/)\n[![Travis](https://img.shields.io/travis/mkb79/audible/master.svg?logo=travis)](https://travis-ci.org/mkb79/audible)\n[![image](https://img.shields.io/pypi/implementation/audible.svg)](https://pypi.org/project/audible/)\n[![image](https://img.shields.io/pypi/dm/audible.svg)](https://pypi.org/project/audible/)\n\n**Sync/Async Interface for internal Audible API written in pure Python.**\n\nCode and README are forked from omarroth\u2018s fantastic [audible.cr](https://github.com/omarroth/audible.cr) API written in crystal.\nThe whole code is written with Pythonista for iOS.\n\n## Requirements\n\n- Python >= 3.6\n- depends on following packages:\n\t- aiohttp\n\t- beautifulsoup4\n\t- pbkdf2\n\t- Pillow\n\t- pyaes\n\t- requests\n\t- rsa \n\n## Installation\n\n`pip install audible`\n\n## Usage\n\n### Basis Examples\n\n- Retrieving API credentials\n\n```python\nimport audible\n\n# example for US accounts\nauth = audible.LoginAuthenticator(\n \"EMAIL\",\n \"PASSWORD\",\n locale=\"us\"\n)\n```\n\n- Instantiate API with Authenticator\n\n*Hint: the Authenticator will be stored as `auth` attribute, you can access them with `client.auth`*\n\n```python\nclient = audible.AudibleAPI(auth)\n```\n\n- Save credentials\n\n*Hint: locale (country) code are stored in file*\n\n```python\nauth.to_file(\"FILENAME\", encryption=False)\n```\n\n- Load credentials from file\n\n*Hint: uses saved locale code*\n\n```python\nauth = audible.FileAuthenticator(\"FILENAME\")\n\n# to specify another locale code at restore\nauth = audible.FileAuthenticator(\n \"FILENAME\",\n locale=\"some other locale\"\n)\n```\n\n- retrieving library from API\n\n*Hint: with any request you get a list with response text and the raw response object*\n\n*Hint: audibles current API version is 1.0, the Client use this version on default*\n\n```python\nlibrary, _ = client.get(\n path=\"library\",\n params={\n \"num_results\": 999,\n \"response_groups\": \"media, sample\"\n }\n)\n\n# to specify another API version\nlibrary, _ = client.get(\n path=\"library/books\",\n api_version=\"0.0\",\n params={\n \"purchaseAfterDate\": \"01/01/1970\",\n \"sortInAscendingOrder\": \"true\"\n }\n)\n```\n\n### Localizations\n\nCurrently this Client have localizations for 5 countries built-in.\n\n- USA (locale=\"us\")\n- Germany (locale=\"de\")\n- United Kingdom (locale=\"uk\")\n- France (locale=\"fr\")\n- Canada (locale=\"ca\")\n\nYou can provide custom locales with this code:\n\n```python\nimport audible\n\n# example for uk\ncustom_locale = audible.Locale(\n countryCode=\"uk\",\n domain=\"co.uk\",\n marketPlaceId=\"A2I9A3Q2GNFNGQ\",\n)\n\nauth = audible.LoginAuthenticator(..., locale=custom_locale)\nclient = audible.AudibleAPI(auth)\n```\n\nYou can try to autodetect locales like so:\n\n```python\nimport audible\n\n# needs the Top Level Domain for the audible page in your country\n# example for uk\ncustom_locale = autodetect_locale(\"co.uk\")\n\n# look if everything is fine\nprint(custom_locale)\n\n# create Authenticator\ncustom_locale = audible.Locale(**custom_locale)\nauth = audible.LoginAuthenticator(..., locale=custom_locale)\n```\n\n\n### Load and Save Credentials\n\n#### Saved data\n\nIf you save a session following data will be stored in file:\n\n- login_cookies\n- access_token\n- refresh_token\n- adp_token\n- device_private_key\n- locale_code\n- store_authentication_cookie (*new*)\n- device_info (*new*)\n- customer_info (*new*)\n- expires\n\n#### Unencrypted Load/Save\n\nCredentials can be saved any time to file like so:\n\n```python\nimport audible\n\nauth = audible.LoginAuthenticator(...)\nauth.to_file(\"FILENAME\", encryption=False)\n\n# Sometime later...\nauth = audible.FileAuthenticator(\"FILENAME\")\n```\n\nAuthenticator sets the filename as the default value when loading from or save to file simply run to overwrite old file\n`auth.to_file()`. No filename is needed.\n\n#### Encrypted Load/Save\n\nThis Client supports file encryption now. The encryption\nalgorithm used is symmetric AES in cipher-block chaining (CBC) mode. Currently json and bytes style output are supported.\nCredentials can be saved any time to encrypted file like so:\n\n```python\nimport audible\n\nauth = audible.LoginAuthenticator(...)\n\n# save credentials in json style\nauth.to_file(\n \"FILENAME\",\n \"PASSWORD\",\n encryption=\"json\"\n)\n\n# in bytes style\nauth.to_file(\n \"FILENAME\",\n \"PASSWORD\",\n encryption=\"bytes\"\n)\n\n# Sometime later...\n# load credentials\n# encryption style are autodetected\nauth = audible.FileAuthenticator(\n \"FILENAME\",\n \"PASSWORD\"\n)\n```\n\nAuthenticator sets the filename, password and encryption style as the default values when loading from or save to file simply run to overwrite old file with same password and encryption style\n`auth.to_file()`. No filename is needed.\n\n##### Advanced use of encryption/decryption:\n\n`auth.to_file(..., **kwargs)`\n\n`auth = audible.FileAuthenticator(..., **kwargs)`\n\nFollowing arguments are possible:\n\n- key_size (default = 32)\n- salt_marker (default = b\"$\")\n- kdf_iterations (default = 1000)\n- hashmod (default = Crypto.Hash.SHA256)\n\n`key_size` may be 16, 24 or 32. The key is derived via the PBKDF2 key derivation function (KDF) from the password and a random salt of 16 bytes (the AES block size) minus the length of the salt header (see below).\nThe hash function used by PBKDF2 is SHA256 per default. You can pass a different hash function module via the `hashmod` argument. The module must adhere to the Python API for Cryptographic Hash Functions (PEP 247).\nPBKDF2 uses a number of iterations of the hash function to derive the key, which can be set via the `kdf_iterations` keyword argumeent. The default number is 1000 and the maximum 65535.\nThe header and the salt are written to the first block of the encrypted output (bytes mode) or written as key/value pairs (dict mode). The header consist of the number of KDF iterations encoded as a big-endian word bytes wrapped by `salt_marker` on both sides. With the default value of `salt_marker = b'$'`, the header size is thus 4 and the salt 12 bytes.\nThe salt marker must be a byte string of 1-6 bytes length.\nThe last block of the encrypted output is padded with up to 16 bytes, all having the value of the length of the padding.\nIn json style all values are written as base64 encoded string.\n\n#### Remove encryption\n\nTo remove encryption from file (or save as new file):\n\n```python\nfrom audible.aescipher import remove_file_encryption\n\nencrypted_file = \"FILENAME\"\ndecrypted_file = \"FILENAME\"\npassword = \"PASSWORD\"\n\nremove_file_encryption(\n encrypted_file,\n decrypted_file,\n password\n)\n```\n\n### CAPTCHA\n\nLogging in currently requires answering a CAPTCHA. By default Pillow is used to show captcha and user prompt will be provided using `input`, which looks like:\n\n```\nAnswer for CAPTCHA:\n```\n\nIf Pillow can't display the captcha, the captcha url will be printed.\n\nA custom callback can be provided (for example submitting the CAPTCHA to an external service), like so:\n\n```\ndef custom_captcha_callback(captcha_url):\n\n # Do some things with the captcha_url ... \n # maybe you can call webbrowser.open(captcha_url)\n\n return \"My answer for CAPTCHA\"\n\nauth = audible.LoginAuthenticator(\n \"EMAIL\",\n \"PASSWORD\",\n locale=\"us\",\n captcha_callback=custom_captcha_callback\n)\n```\n\n### 2FA\n\nIf 2-factor-authentication by default is activated a user prompt will be provided using `input`, which looks like:\n\n```\n\"OTP Code: \"\n```\n\nA custom callback can be provided, like so:\n\n```\ndef custom_otp_callback():\n\n # Do some things to insert otp code\n\n return \"My answer for otp code\"\n\nauth = audible.LoginAuthenticator(\n \"EMAIL\",\n \"PASSWORD\",\n locale=\"us\",\n otp_callback=custom_otp_callback\n)\n```\n\n\n### Logging\n\nIn preparation of adding logging in near future I add following functions:\n\n```python\nimport audible\n\n# console logging\naudible.set_console_logger(\"level\")\n\n# file logging\naudible.set_file_logger(\"filename\", \"level\")\n\n```\n\nFollowing levels will be accepted:\n\n- debug\n- info\n- warn (or warning)\n- error\n- critical\n\nYou can use numeric levels too:\n\n- 10 (debug)\n- 20 (info)\n- 30 (warn)\n- 40 (error)\n- 50 (critical)\n\n### Asynchron requests\n\nBy default the AudibleAPI client requests are synchron using the requests module.\n\nThe client supports now asynchronous request using the aiohttp module. You can instantiate a async client with `client = audible.AudibleAPI(..., is_async=True)`. Example to use async client can be found in [example folder](https://github.com/mkb79/Audible/tree/developing/examples) on github repo.\n\n## Authentication\n\n### Informations\n\nClients are authenticated using OpenID. Once a client has successfully authenticated with Amazon, they are given an access token for authenticating with Audible.\n\n### Register device\n\nClients authenticate with Audible using cookies from Amazon and the given access token to `/auth/register`. Clients are given an refresh token, RSA private key and adp_token.\n\nFor requests to the Audible API, requests need to be signed using the provided RSA private key and adp_token. Request signing is fairly straight-forward and uses a signed SHA256 digest. Headers look like:\n\n```\nx-adp-alg: SHA256withRSA:1.0\nx-adp-signature: AAAAAAAA...:2019-02-16T00:00:01.000000000Z,\nx-adp-token: {enc:...}\n```\n\nAs reference for other implementations, a client **must** store a working `access_token` from a successful Amazon login in order to renew `refresh_token`, `adp_token`, etc from `/auth/register`.\n\n### Refresh access token\n\nAn `access_token` can be renewed by making a request to `/auth/token`. `access_token`s are valid for 1 hour.\nTo renew access_token with client call:\n\n```python\n# refresh access_token if token already expired\n# if token is valid nothing will be refreshed.\nauth.refresh_token()\n\n# to force renew of access_token if token is valid\nauth.refresh_token(force=true)\n```\n\n*Hint: If you saved your session before don't forget to save again.*\n\n### Deregister device\n\nRefresh token, RSA private key and adp_token are valid until deregister.\n\nTo deregister a device with client call `auth.deregister_device()`\n\nTo deregister all devices with client call `auth.deregister_device(deregister_all=True)`.\nThis function is necessary to prevent hanging slots if you registered a device earlier but don\u2018t store the given credentials.\nThis also deregister all other devices such as a audible app on mobile devices.\n\n## Documentation:\n\nThere is currently no publicly available documentation about the Audible API. There is a node client ([audible-api](https://github.com/willthefirst/audible/tree/master/node_modules/audible-api)) that has some endpoints documented, but does not provide information on authentication.\n\nLuckily the Audible API is partially self-documenting, however the parameter names need to be known. Error responses will look like:\n\n```json\n{\n \"message\": \"1 validation error detected: Value 'some_random_string123' at 'numResults' failed to satisfy constraint: Member must satisfy regular expression pattern: ^\\\\d+$\"\n}\n```\n\nFew endpoints have been fully documented, as a large amount of functionality is not testable from the app or functionality is unknown. Most calls need to be authenticated.\n\nFor `%s` substitutions the value is unknown or can be inferred from the endpoint. `/1.0/catalog/products/%s` for example requires an `asin`, as in `/1.0/catalog/products/B002V02KPU`.\n\nEach bullet below refers to a parameter for the request with the specified method and URL.\n\nResponses will often provide very little info without `response_groups` specified. Multiple response groups can be specified, for example: `/1.0/catalog/products/B002V02KPU?response_groups=product_plan_details,media,review_attrs`. When providing an invalid response group, the server will return an error response but will not provide information on available response groups.\n\n### GET /0.0/library/books\n\n#### Deprecated: Use `/1.0/library`\n\nparams:\n\n- purchaseAfterDate: mm/dd/yyyy\n- sortByColumn: [SHORT_TITLE, strTitle, DOWNLOAD_STATUS, RUNNING_TIME, sortPublishDate, SHORT_AUTHOR, sortPurchDate, DATE_AVAILABLE]\n- sortInAscendingOrder: [true, false]\n\n### GET /1.0/library\n\nparams:\n\n- num_results: \\\\d+ (max: 1000)\n- page: \\\\d+\n- purchased_after: [RFC3339](https://tools.ietf.org/html/rfc3339) (e.g. `2000-01-01T00:00:00Z`)\n- response_groups: [contributors, media, price, product_attrs, product_desc, product_extended_attrs, product_plan_details, product_plans, rating, sample, sku, series, reviews, ws4v, origin, relationships, review_attrs, categories, badge_types, category_ladders, claim_code_url, is_downloaded, is_finished, is_returnable, origin_asin, pdf_url, percent_complete, provided_review]\n- sort_by: [-Author, -Length, -Narrator, -PurchaseDate, -Title, Author, Length, Narrator, PurchaseDate, Title]\n\n### GET /1.0/library/%{asin}\n\nparams:\n\n- response_groups: [contributors, media, price, product_attrs, product_desc, product_extended_attrs, product_plan_details, product_plans, rating, sample, sku, series, reviews, ws4v, origin, relationships, review_attrs, categories, badge_types, category_ladders, claim_code_url, is_downloaded, is_finished, is_returnable, origin_asin, pdf_url, percent_complete, provided_review]\n\n### POST(?) /1.0/library/item\n\n- asin:\n\n### POST(?) /1.0/library/item/%s/%s\n\n### GET /1.0/wishlist\n\nparams:\n\n- num_results: \\\\d+ (max: 50)\n- page: \\\\d+\n- response_groups: [contributors, media, price, product_attrs, product_desc, product_extended_attrs, product_plan_details, product_plans, rating, sample, sku]\n- sort_by: [-Author, -DateAdded, -Price, -Rating, -Title, Author, DateAdded, Price, Rating, Title]\n\n### POST /1.0/wishlist\n\nbody:\n\n- asin : String\n\nExample request body:\n\n```json\n{\n \"asin\": \"B002V02KPU\"\n}\n```\n\nReturns 201 and a `Location` to the resource.\n\n### DELETE /1.0/wishlist/%{asin}\n\nReturns 204 and removes the item from the wishlist using the given `asin`.\n\n### GET /1.0/badges/progress\n\nparams:\n\n- locale: en_US\n- response_groups: brag_message\n- store: Audible\n\n### GET /1.0/badges/metadata\n\nparams:\n\n- locale: en_US\n- response_groups: all_levels_metadata\n\n### GET /1.0/account/information\n\nparams:\n\n- response_groups: [delinquency_status, customer_benefits, subscription_details_payment_instrument, plan_summary, subscription_details]\n- source: [Enterprise, RodizioFreeBasic, AyceRomance, AllYouCanEat, AmazonEnglish, ComplimentaryOriginalMemberBenefit, Radio, SpecialBenefit, Rodizio]\n\n### POST(?) /1.0/library/collections/%s/channels/%s\n\n- customer_id:\n- marketplace:\n\n### POST(?) /1.0/library/collections/%s/products/%s\n\n- channel_id:\n\n### GET /1.0/catalog/categories\n\n- categories_num_levels: \\\\d+ (greater than or equal to 1)\n- ids: \\\\d+(,\\\\d+)\\*\n- root: [InstitutionsHpMarketing, ChannelsConfigurator, AEReadster, ShortsPrime, ExploreBy, RodizioBuckets, EditorsPicks, ClientContent, RodizioGenres, AmazonEnglishProducts, ShortsSandbox, Genres, Curated, ShortsIntroOutroRemoval, Shorts, RodizioEpisodesAndSeries, ShortsCurated]\n\n### GET /1.0/catalog/categories/%{category_id}\n\n- image_dpi: \\\\d+\n- image_sizes:\n- image_variants:\n- products_in_plan_timestamp:\n- products_not_in_plan_timestamp:\n- products_num_results: \\\\d+\n- products_plan: [Enterprise, RodizioFreeBasic, AyceRomance, AllYouCanEat, AmazonEnglish, ComplimentaryOriginalMemberBenefit, Radio, SpecialBenefit, Rodizio]\n- products_sort_by: [-ReleaseDate, ContentLevel, -Title, AmazonEnglish, AvgRating, BestSellers, -RuntimeLength, ReleaseDate, ProductSiteLaunchDate, -ContentLevel, Title, Relevance, RuntimeLength]\n- reviews_num_results: \\\\d+\n- reviews_sort_by: [MostHelpful, MostRecent]\n\n### POST /1.0/content/%{asin}/licenserequest\n\n- B consumption_type: [Streaming, Offline, Download]\n- B drm_type: [Hls, PlayReady, Hds, Adrm]\n- B quality: [High, Normal, Extreme, Low]\n- B num_active_offline_licenses: \\\\d+ (max: 10)\n\nExample request body:\n\n```json\n{\n \"drm_type\": \"Adrm\",\n \"consumption_type\": \"Download\",\n \"quality\": \"Extreme\"\n}\n```\n\nFor a succesful request, returns JSON body with `content_url`.\n\n### GET /1.0/annotations/lastpositions\n\n- asins: asin (comma-separated), e.g. ?asins=B01LWUJKQ7,B01LWUJKQ7,B01LWUJKQ7\n\n### GET /1.0/content/%{asin}/metadata\n\n- response_groups: [chapter_info]\n- acr:\n\n### GET /1.0/customer/information\n\n- response_groups: [migration_details, subscription_details_rodizio, subscription_details_premium, customer_segment, subscription_details_channels]\n\n### GET /1.0/customer/status\n\n- response_groups: [benefits_status, member_giving_status, prime_benefits_status, prospect_benefits_status]\n\n### GET /1.0/customer/freetrial/eligibility\n\n### GET /1.0/library/collections\n\n- customer_id:\n- marketplace:\n\n### POST(?) /1.0/library/collections\n\n- collection_type:\n\n### GET /1.0/library/collections/%s\n\n- customer_id:\n- marketplace:\n- page_size:\n- continuation_token:\n\n### GET /1.0/library/collections/%s/products\n\n- customer_id:\n- marketplace:\n- page_size:\n- continuation_token:\n- image_sizes:\n\n### GET /1.0/stats/aggregates\n\n- daily_listening_interval_duration: ([012]?[0-9])|(30) (0 to 30, inclusive)\n- daily_listening_interval_start_date: YYYY-MM-DD (e.g. `2019-06-16`)\n- locale: en_US\n- monthly_listening_interval_duration: 0?[0-9]|1[012] (0 to 12, inclusive)\n- monthly_listening_interval_start_date: YYYY-MM (e.g. `2019-02`)\n- response_groups: [total_listening_stats]\n- store: [AudibleForInstitutions, Audible, AmazonEnglish, Rodizio]\n\n### GET /1.0/stats/status/finished\n\n- asin: asin\n\n### POST(?) /1.0/stats/status/finished\n\n- start_date:\n- status:\n- continuation_token:\n\n### GET /1.0/pages/%s\n\n%s: ios-app-home\n\n- locale: en-US\n- reviews_num_results:\n- reviews_sort_by:\n- response_groups: [media, product_plans, view, product_attrs, contributors, product_desc, sample]\n\n### GET /1.0/catalog/products/%{asin}\n\n- image_dpi:\n- image_sizes:\n- response_groups: [contributors, media, product_attrs, product_desc, product_extended_attrs, product_plan_details, product_plans, rating, review_attrs, reviews, sample, sku]\n- reviews_num_results: \\\\d+ (max: 10)\n- reviews_sort_by: [MostHelpful, MostRecent]\n\n### GET /1.0/catalog/products/%{asin}/reviews\n\n- sort_by: [MostHelpful, MostRecent]\n- num_results: \\\\d+ (max: 50)\n- page: \\\\d+\n\n### GET /1.0/catalog/products\n\n- author:\n- browse_type:\n- category_id: \\\\d+(,\\\\d+)\\*\n- disjunctive_category_ids:\n- image_dpi: \\\\d+\n- image_sizes:\n- in_plan_timestamp:\n- keywords:\n- narrator:\n- not_in_plan_timestamp:\n- num_most_recent:\n- num_results: \\\\d+ (max: 50)\n- page: \\\\d+\n- plan: [Enterprise, RodizioFreeBasic, AyceRomance, AllYouCanEat, AmazonEnglish, ComplimentaryOriginalMemberBenefit, Radio, SpecialBenefit, Rodizio]\n- products_since_timestamp:\n- products_sort_by: [-ReleaseDate, ContentLevel, -Title, AmazonEnglish, AvgRating, BestSellers, -RuntimeLength, ReleaseDate, ProductSiteLaunchDate, -ContentLevel, Title, Relevance, RuntimeLength]\n- publisher:\n- response_groups: [contributors, media, price, product_attrs, product_desc, product_extended_attrs, product_plan_detail, product_plans, rating, review_attrs, reviews, sample, sku]\n- reviews_num_results: \\\\d+ (max: 10)\n- reviews_sort_by: [MostHelpful, MostRecent]\n- title:\n\n### GET /1.0/recommendations\n\n- category_image_variants:\n- image_dpi:\n- image_sizes:\n- in_plan_timestamp:\n- language:\n- not_in_plan_timestamp:\n- num_results: \\\\d+ (max: 50)\n- plan: [Enterprise, RodizioFreeBasic, AyceRomance, AllYouCanEat, AmazonEnglish, ComplimentaryOriginalMemberBenefit, Radio, SpecialBenefit, Rodizio]\n- response_groups: [contributors, media, price, product_attrs, product_desc, product_extended_attrs, product_plan_details, product_plans, rating, sample, sku]\n- reviews_num_results: \\\\d+ (max: 10)\n- reviews_sort_by: [MostHelpful, MostRecent]\n\n### GET /1.0/catalog/products/%{asin}/sims\n\n- category_image_variants:\n- image_dpi:\n- image_sizes:\n- in_plan_timestamp:\n- language:\n- not_in_plan_timestamp:\n- num_results: \\\\d+ (max: 50)\n- plan: [Enterprise, RodizioFreeBasic, AyceRomance, AllYouCanEat, AmazonEnglish, ComplimentaryOriginalMemberBenefit, Radio, SpecialBenefit, Rodizio]\n- response_groups: [contributors, media, price, product_attrs, product_desc, product_extended_attrs, product_plans, rating, review_attrs, reviews, sample, sku]\n- reviews_num_results: \\\\d+ (max: 10)\n- reviews_sort_by: [MostHelpful, MostRecent]\n- similarity_type: [InTheSameSeries, ByTheSameNarrator, RawSimilarities, ByTheSameAuthor, NextInSameSeries]\n\n## Downloading\n\nFor multipart books, it's necessary to use the `child_asin` provided with `response_groups=relationships` in order to download each part.\n\n```python\nimport audible\n\nclient = audible.Client(\"EMAIL\", \"PASSWORD\", local=\"us\")\nlicense = client.post(\n \"content/{asin}/licenserequest\",\n body={\n \"drm_type\": \"Adrm\",\n \"consumption_type\": \"Download\",\n \"quality\":\"Extreme\"\n }\n)\ncontent_url = license['content_license']['content_metadata']['content_url']['offline_url']\n\n# `content_url` can then be downloaded using any tool\n\n```\n\nAssuming you have your activation bytes, you can convert .aax into another format with the following:\n\n```\n$ ffmpeg -activation_bytes 1CEB00DA -i test.aax -vn -c:a copy output.mp4\n```\n\n\n", "description_content_type": "text/markdown", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/mkb79/audible", "keywords": "Audible,API,async", "license": "AGPL", "maintainer": "", "maintainer_email": "", "name": "audible", "package_url": "https://pypi.org/project/audible/", "platform": "", "project_url": "https://pypi.org/project/audible/", "project_urls": { "Homepage": "https://github.com/mkb79/audible" }, "release_url": "https://pypi.org/project/audible/0.2.1/", "requires_dist": [ "aiohttp", "beautifulsoup4", "pbkdf2", "Pillow", "pyaes", "requests", "rsa" ], "requires_python": ">=3.6", "summary": "A(Sync) Interface for internal Audible API written in pure Python.", "version": "0.2.1" }, "last_serial": 5868724, "releases": { "0.1.1": [ { "comment_text": "", "digests": { "md5": "1342a68ef70ccb2cdcc13c0cf8f6a232", "sha256": "18653b6bff269dbd1528462a00d75e31f756172b41f46ae86a43e43e1f03fd75" }, "downloads": -1, "filename": "audible-0.1.1-py3-none-any.whl", "has_sig": false, "md5_digest": "1342a68ef70ccb2cdcc13c0cf8f6a232", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6.0", "size": 25165, "upload_time": "2019-06-20T21:45:43", "url": "https://files.pythonhosted.org/packages/59/3f/01523a06a783d1ed50e842b3c855d31d5e4517e2d7874c2666fcc7e27b87/audible-0.1.1-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "1e2ec7c3acb1416c802776df33922efe", "sha256": "4b993d29e8159d9e1dbc2610ea0aa3e1c2c3406f75999fc793bfc3a9830f475c" }, "downloads": -1, "filename": "audible-0.1.1.tar.gz", "has_sig": false, "md5_digest": "1e2ec7c3acb1416c802776df33922efe", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 30275, "upload_time": "2019-06-20T21:45:46", "url": "https://files.pythonhosted.org/packages/80/a3/1996c6c2a11f1471e65dd098429afd5873f2b4940c94f4b09359cb247028/audible-0.1.1.tar.gz" } ], "0.1.2": [ { "comment_text": "", "digests": { "md5": "eb3c6cbe13cb51277212a5645c027d2b", "sha256": "2c066e7bf7523ea1ee1164beae445149d000af69cb5ca530ba6d89661dcb80f9" }, "downloads": -1, "filename": "audible-0.1.2-py3-none-any.whl", "has_sig": false, "md5_digest": "eb3c6cbe13cb51277212a5645c027d2b", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6.0", "size": 25248, "upload_time": "2019-06-21T11:24:01", "url": "https://files.pythonhosted.org/packages/71/e5/beebaadf82896b2489701a59fac55c7db5cce8c0cd4e657cf772204d9bf3/audible-0.1.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "a9acb902ee4ead337213474dda606db2", "sha256": "29ad5e28d52f0d4ca378202ef0342f213eb3a2edd30e8a602cbf9d655ac92c3d" }, "downloads": -1, "filename": "audible-0.1.2.tar.gz", "has_sig": false, "md5_digest": "a9acb902ee4ead337213474dda606db2", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6.0", "size": 30508, "upload_time": "2019-06-21T07:01:25", "url": "https://files.pythonhosted.org/packages/5b/c7/0776997eb74a207c19cc490cd4d2601e24efda905193b9bff1c854cc609a/audible-0.1.2.tar.gz" } ], "0.1.3": [ { "comment_text": "", "digests": { "md5": "1abfe2880e51d98b89e545fed7f96e8a", "sha256": "4ff0b98739288b23d802eb8f853aab4206a476b16bdcba5b2471507c748af411" }, "downloads": -1, "filename": "audible-0.1.3-py3-none-any.whl", "has_sig": false, "md5_digest": "1abfe2880e51d98b89e545fed7f96e8a", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 25305, "upload_time": "2019-06-22T07:14:05", "url": "https://files.pythonhosted.org/packages/23/ca/0c3822c159ed9f0b1e2900fe27a6d368f1dd4904aa1a7db6743e726357a2/audible-0.1.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "5cf4c4f83b72ac731af4c84486b1c927", "sha256": "b0dd6f14adb1d19f12ca19ba44e00c86cb2011184a6f9f5c152c92ba71919e69" }, "downloads": -1, "filename": "audible-0.1.3.tar.gz", "has_sig": false, "md5_digest": "5cf4c4f83b72ac731af4c84486b1c927", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 28453, "upload_time": "2019-06-22T07:12:00", "url": "https://files.pythonhosted.org/packages/be/39/b875a8571f8e32e898285ab9bfd351abf2cc7b4049a50aa8c6af6a6e7f76/audible-0.1.3.tar.gz" } ], "0.1.4": [ { "comment_text": "", "digests": { "md5": "6a9c333fd2921ca0b024936f0606700d", "sha256": "569d16fc08e2cca996b4180bf883c37f2b5db516106891e5e2b621f1370074ab" }, "downloads": -1, "filename": "audible-0.1.4-py3-none-any.whl", "has_sig": false, "md5_digest": "6a9c333fd2921ca0b024936f0606700d", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": ">=3.6", "size": 25947, "upload_time": "2019-06-22T21:15:30", "url": "https://files.pythonhosted.org/packages/e5/01/f8281867d6900463c0370a42b3bbf75aef212463941a0c806bd94b23d328/audible-0.1.4-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "f1e2ddd03b24e019ef4b52cbad1a9b46", "sha256": "7fb9ce8151ab19d73aaa4ba4d9fa6d9809cd677eb15c6b0fed4e613aeeca5c5c" }, "downloads": -1, "filename": "audible-0.1.4.tar.gz", "has_sig": false, "md5_digest": "f1e2ddd03b24e019ef4b52cbad1a9b46", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 29544, "upload_time": "2019-06-22T21:11:41", "url": "https://files.pythonhosted.org/packages/f9/05/3fc41311ea5eccf5792a4fddd0e22b806f504694c208fcaa0d6093ac9e4b/audible-0.1.4.tar.gz" } ], "0.1.5": [ { "comment_text": "", "digests": { "md5": "c64fecb305bc4cd260b523aa1182fce4", "sha256": "b54bba58b532de403ab3be5948f4ee7a5d9459c56a8a4060e637ae606fc1d107" }, "downloads": -1, "filename": "audible-0.1.5-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "c64fecb305bc4cd260b523aa1182fce4", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 26519, "upload_time": "2019-06-23T11:57:37", "url": "https://files.pythonhosted.org/packages/75/e0/fe37991068a3384e1c2c24fc834ad1ad29e4e8abe88fd1418e1353bb6701/audible-0.1.5-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "c52f2ce60cb60c79b78bbb3c27acda3f", "sha256": "d306f3363055e1261126550617a26ee3a3bf8b1a6dff140bb8d8cf7d346e2fc9" }, "downloads": -1, "filename": "audible-0.1.5.tar.gz", "has_sig": false, "md5_digest": "c52f2ce60cb60c79b78bbb3c27acda3f", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 30342, "upload_time": "2019-06-23T11:54:41", "url": "https://files.pythonhosted.org/packages/5a/93/92176e7c99f89edb289e9990aab173e69bbd667238d58d1b25645fa5db7a/audible-0.1.5.tar.gz" } ], "0.1.6": [ { "comment_text": "", "digests": { "md5": "f6972b91949e648a2cd87a684d25d0c5", "sha256": "6538d8a11553fbfe1f88c2bcc69a974ea1f82f9ac4cec0de3c7a7368eb4b9366" }, "downloads": -1, "filename": "audible-0.1.6-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "f6972b91949e648a2cd87a684d25d0c5", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 26640, "upload_time": "2019-07-19T08:43:59", "url": "https://files.pythonhosted.org/packages/b4/56/f2d2f9b689ee1057c765d754b5524c58ce546d340e160afdde5bf033ddca/audible-0.1.6-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "044aae3f7135c4bdc6dda9354162057b", "sha256": "d95d5f51bc4a41cd39c2e570272013e10c1de2e4fc184d7c535368b5be4da028" }, "downloads": -1, "filename": "audible-0.1.6.tar.gz", "has_sig": false, "md5_digest": "044aae3f7135c4bdc6dda9354162057b", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 30527, "upload_time": "2019-07-19T08:33:00", "url": "https://files.pythonhosted.org/packages/bc/a0/79ac18f5bbfe8858de4515f975b73f8bfb6b5728ae62f3e05885f900f4b2/audible-0.1.6.tar.gz" } ], "0.2.0": [ { "comment_text": "", "digests": { "md5": "34d2be7ec9941fba014833a2b7249dcf", "sha256": "fdcd4adb5ce3c7e6334f1d9969905da0edb6b51f79088d454d2415dc14e55515" }, "downloads": -1, "filename": "audible-0.2.0-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "34d2be7ec9941fba014833a2b7249dcf", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 39252, "upload_time": "2019-07-27T20:29:23", "url": "https://files.pythonhosted.org/packages/81/e8/1c79f3515f92343eaf7e4bbfd8d1778eb3e4c074fd1a25c58261e47f2641/audible-0.2.0-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "b903a8e601feb1c84a9e7e13dedef672", "sha256": "2c1dbbf2485c93074bffd90460aed30960775e13d5f7cbfb29fbee2e0ddc3b4f" }, "downloads": -1, "filename": "audible-0.2.0-py3.7.egg", "has_sig": false, "md5_digest": "b903a8e601feb1c84a9e7e13dedef672", "packagetype": "bdist_egg", "python_version": "3.7", "requires_python": ">=3.6", "size": 58313, "upload_time": "2019-09-22T11:01:07", "url": "https://files.pythonhosted.org/packages/f7/4d/87f3ac08221bee0b0dc927976e436631a68bcde7a9a39c44392b4a6a06ac/audible-0.2.0-py3.7.egg" }, { "comment_text": "", "digests": { "md5": "5350b0a86f479a868e58998109414683", "sha256": "af8960411f0f8ecf33bb5d5117eccedf3eafba05f893b8f2f90b567a3e0c85ef" }, "downloads": -1, "filename": "audible-0.2.0.tar.gz", "has_sig": false, "md5_digest": "5350b0a86f479a868e58998109414683", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 44582, "upload_time": "2019-07-27T20:29:25", "url": "https://files.pythonhosted.org/packages/4f/1a/95434ac7faabfad1482d5efad9a1ec38322d5aefe8fc3161bb2d277cb76d/audible-0.2.0.tar.gz" } ], "0.2.1": [ { "comment_text": "", "digests": { "md5": "dc3da05ca612c50900976e899e740be9", "sha256": "b0133a704a0fd7900369b1221ef908fcb057f9b7cd42521ed20ab831503eff57" }, "downloads": -1, "filename": "audible-0.2.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "dc3da05ca612c50900976e899e740be9", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 43333, "upload_time": "2019-09-22T11:01:05", "url": "https://files.pythonhosted.org/packages/14/d5/8c4302fa47eebb341ebd3ca2a637a7920a2d8b9c2fd8ebb27c3978b942fe/audible-0.2.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "bfa19e2c82d02356bd5e12fc20617fb5", "sha256": "b96794b37b0440bb5f0e4e8a627c86e8ab1a36fb380980971526e0efca8d94ba" }, "downloads": -1, "filename": "audible-0.2.1.tar.gz", "has_sig": false, "md5_digest": "bfa19e2c82d02356bd5e12fc20617fb5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 42650, "upload_time": "2019-09-22T11:01:10", "url": "https://files.pythonhosted.org/packages/6b/a3/0a2050a1c79655afd06e86a00b4a394e8ae8c01065edd02cbb6aee39d4d6/audible-0.2.1.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "dc3da05ca612c50900976e899e740be9", "sha256": "b0133a704a0fd7900369b1221ef908fcb057f9b7cd42521ed20ab831503eff57" }, "downloads": -1, "filename": "audible-0.2.1-py2.py3-none-any.whl", "has_sig": false, "md5_digest": "dc3da05ca612c50900976e899e740be9", "packagetype": "bdist_wheel", "python_version": "py2.py3", "requires_python": ">=3.6", "size": 43333, "upload_time": "2019-09-22T11:01:05", "url": "https://files.pythonhosted.org/packages/14/d5/8c4302fa47eebb341ebd3ca2a637a7920a2d8b9c2fd8ebb27c3978b942fe/audible-0.2.1-py2.py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "bfa19e2c82d02356bd5e12fc20617fb5", "sha256": "b96794b37b0440bb5f0e4e8a627c86e8ab1a36fb380980971526e0efca8d94ba" }, "downloads": -1, "filename": "audible-0.2.1.tar.gz", "has_sig": false, "md5_digest": "bfa19e2c82d02356bd5e12fc20617fb5", "packagetype": "sdist", "python_version": "source", "requires_python": ">=3.6", "size": 42650, "upload_time": "2019-09-22T11:01:10", "url": "https://files.pythonhosted.org/packages/6b/a3/0a2050a1c79655afd06e86a00b4a394e8ae8c01065edd02cbb6aee39d4d6/audible-0.2.1.tar.gz" } ] }