[Enhancement]: implement metadata provider for litres.ru #2485

Open
opened 2026-04-25 00:07:39 +02:00 by adam · 4 comments
Owner

Originally created by @thatguy7 on GitHub (Jan 13, 2025).

Type of Enhancement

Server Backend

Describe the Feature/Enhancement

I would like to implement a metadata provider that draws info from litres.ru. It's an online retailer with primarily Russian catalogue of books/audiobooks but also podcasts.

I had a look at the API and it seems promising, e.g. I could search for a book/audiobook with a call like:

https://api.litres.ru/foundation/api/search?is_for_pda=false&limit=24&offset=0&q=The+Adventure+of+the+Dying+Detective+&show_unavailable=false&types=text_book%2Caudiobook%2Cpodcast%2Cpodcast_episode%2Cwebtoon

An excerpt from the answer looks like:

{
	"type": "audiobook",
	"instance": {
		"id": 64056885,
		"uuid": "7ecfcc26-730b-11eb-aef3-0cc47a5f3f85",
		"cover_url": "/pub/c/cover/64056885.jpg",
		"url": "/audiobook/sir-arthur-conan-doyle-180/the-adventure-of-the-dying-detective-unabridged-64056885/",
		"title": "The Adventure of the Dying Detective (Unabridged)",
		"cover_ratio": 1,
		"is_draft": false,
		"art_type": 1,
		"prices": {
			"final_price": 324.44,
			"inapp_price": null,
			"inapp_base_price": null,
			"full_price": 324.44,
			"discount_price": null,
			"litcoin_count": 0,
			"inapp_name": null,
			"inapp_base_name": null,
			"currency": "RUB",
			"discount_percent": null,
			"cost_with_bonus": 324.44,
			"bonus_money": 0,
			"account_money": 0,
			"can_be_paid_by_account_money": false
		},
		"is_auto_speech_gift": false,
		"subtitle": "",
		"min_age": 0,
		"is_adult_content": false,
		"cover_height": 1448,
		"cover_width": 1448,
		"foreign_publisher_id": 18,
		"language_code": "en",
		"symbols_count": 2133,
		"expected_symbols_count": null,
		"podcast_serial_number": null,
		"last_updated_at": "2025-01-09T17:15:31",
		"last_released_at": "2025-01-09T17:18:00",
		"read_percent": 0,
		"is_finished": false,
		"is_free": false,
		"is_promo": false,
		"is_advertising": false,
		"advertising_marking": null,
		"event_data": null,
		"my_art_status": 0,
		"is_subscription_art": false,
		"is_available_with_subscription": false,
		"is_available_with_litres_subscription": false,
		"availability_with_partner_subscriptions": [],
		"art_subscription_status_for_user": "no_subscription",
		"is_abonement_art": true,
		"is_available_with_abonement": false,
		"can_be_preordered": false,
		"is_preorder_notified_for_user": false,
		"is_exclusive_abonement": false,
		"is_drm": false,
		"in_gifts": 0,
		"is_fourth_art_gift": false,
		"podcast_left_to_buy": null,
		"availability": 1,
		"available_from": null,
		"library_information": null,
		"persons": [
			{
				"id": 18004318,
				"uuid": "c40779b3-2d1b-11e9-96df-0cc47a545a1e",
				"full_name": "Sir Arthur Conan Doyle",
				"full_rodit": "",
				"url": "/author/sir-arthur-conan-doyle-18004318/",
				"role": "author"
			},
			{
				"id": 21320479,
				"uuid": "4ee24809-26aa-11ea-8339-0cc47a5f1565",
				"full_name": "Peter Silverleaf",
				"full_rodit": "Peter Silverleaf",
				"url": "/author/peter-silverleaf/",
				"role": "reader"
			},
			{
				"id": 27611910,
				"uuid": "2a73ac63-704d-11eb-aef3-0cc47a5f3f85",
				"full_name": "Bookstream Audiobooks",
				"full_rodit": "Bookstream Audiobooks",
				"url": "/author/bookstream-audiobooks/",
				"role": "publisher"
			}
		],
		"is_liked": false,
		"rating": {
			"user_rating": null,
			"rated_1_count": 0,
			"rated_2_count": 0,
			"rated_3_count": 0,
			"rated_4_count": 0,
			"rated_5_count": 0,
			"rated_avg": 0,
			"rated_total_count": 0
		},
		"linked_arts": [],
		"series": [],
		"date_written_at": null,
		"release_file_id": 114834523,
		"preview_file_id": 114834508,
		"labels": {
			"is_bestseller": false,
			"is_litres_exclusive": false,
			"is_new": false,
			"is_sales_hit": false
		},
		"in_folders": null,
		"is_archived": false,
		"interacted_at": null,
		"read_at": null,
		"purchased_at": null,
		"is_hidden": false,
		"synchronized_arts": [],
		"synchronizations": [],
		"alternative_version": null,
		"in_user_cart_status": "not_in_cart",
		"is_draft_full_free": false,
		"webtoon_chapters_count": null,
		"webtoon_last_read_chapter_id": null,
		"webtoon_last_read_chapter_number": null
	}
}

It seems to me like most relevant fields are present: title, subtitle, cover, from the persons field one can retrieve author(s), narrator, publisher and translator (which at the moment is not used in ABS). What I am missing is the tags/genres, a description and a release date/year. It is not returned with the search results, but surely could be aquired since the book's page shows the information, though that might require extracting it from HTML.

I use this site to aquire russian books. I am thinking about implementing a metadata provider for the site, so I don't have to copy paste it all the time. Their catalogue is quite large, and apart from exclusives of competing services they have most of the books I look up.

I am not sure about the podcast part, since I am not using that part of ABS at all - but it could work for that as well.

If I were to write a provider, would it be merged?

Why would this be helpful?

An additional provider for metadata for primarily russian books.

Future Implementation (Screenshot)

An additional entry in the provider drop-down field in the match book window and cover lookup window.

Audiobookshelf Server Version

v2.17.7

Current Implementation (Screenshot)

grafik

Originally created by @thatguy7 on GitHub (Jan 13, 2025). ### Type of Enhancement Server Backend ### Describe the Feature/Enhancement I would like to implement a metadata provider that draws info from litres.ru. It's an online retailer with primarily Russian catalogue of books/audiobooks but also podcasts. I had a look at the API and it seems promising, e.g. I could search for a book/audiobook with a call like: ``` https://api.litres.ru/foundation/api/search?is_for_pda=false&limit=24&offset=0&q=The+Adventure+of+the+Dying+Detective+&show_unavailable=false&types=text_book%2Caudiobook%2Cpodcast%2Cpodcast_episode%2Cwebtoon ``` An excerpt from the answer looks like: ```json { "type": "audiobook", "instance": { "id": 64056885, "uuid": "7ecfcc26-730b-11eb-aef3-0cc47a5f3f85", "cover_url": "/pub/c/cover/64056885.jpg", "url": "/audiobook/sir-arthur-conan-doyle-180/the-adventure-of-the-dying-detective-unabridged-64056885/", "title": "The Adventure of the Dying Detective (Unabridged)", "cover_ratio": 1, "is_draft": false, "art_type": 1, "prices": { "final_price": 324.44, "inapp_price": null, "inapp_base_price": null, "full_price": 324.44, "discount_price": null, "litcoin_count": 0, "inapp_name": null, "inapp_base_name": null, "currency": "RUB", "discount_percent": null, "cost_with_bonus": 324.44, "bonus_money": 0, "account_money": 0, "can_be_paid_by_account_money": false }, "is_auto_speech_gift": false, "subtitle": "", "min_age": 0, "is_adult_content": false, "cover_height": 1448, "cover_width": 1448, "foreign_publisher_id": 18, "language_code": "en", "symbols_count": 2133, "expected_symbols_count": null, "podcast_serial_number": null, "last_updated_at": "2025-01-09T17:15:31", "last_released_at": "2025-01-09T17:18:00", "read_percent": 0, "is_finished": false, "is_free": false, "is_promo": false, "is_advertising": false, "advertising_marking": null, "event_data": null, "my_art_status": 0, "is_subscription_art": false, "is_available_with_subscription": false, "is_available_with_litres_subscription": false, "availability_with_partner_subscriptions": [], "art_subscription_status_for_user": "no_subscription", "is_abonement_art": true, "is_available_with_abonement": false, "can_be_preordered": false, "is_preorder_notified_for_user": false, "is_exclusive_abonement": false, "is_drm": false, "in_gifts": 0, "is_fourth_art_gift": false, "podcast_left_to_buy": null, "availability": 1, "available_from": null, "library_information": null, "persons": [ { "id": 18004318, "uuid": "c40779b3-2d1b-11e9-96df-0cc47a545a1e", "full_name": "Sir Arthur Conan Doyle", "full_rodit": "", "url": "/author/sir-arthur-conan-doyle-18004318/", "role": "author" }, { "id": 21320479, "uuid": "4ee24809-26aa-11ea-8339-0cc47a5f1565", "full_name": "Peter Silverleaf", "full_rodit": "Peter Silverleaf", "url": "/author/peter-silverleaf/", "role": "reader" }, { "id": 27611910, "uuid": "2a73ac63-704d-11eb-aef3-0cc47a5f3f85", "full_name": "Bookstream Audiobooks", "full_rodit": "Bookstream Audiobooks", "url": "/author/bookstream-audiobooks/", "role": "publisher" } ], "is_liked": false, "rating": { "user_rating": null, "rated_1_count": 0, "rated_2_count": 0, "rated_3_count": 0, "rated_4_count": 0, "rated_5_count": 0, "rated_avg": 0, "rated_total_count": 0 }, "linked_arts": [], "series": [], "date_written_at": null, "release_file_id": 114834523, "preview_file_id": 114834508, "labels": { "is_bestseller": false, "is_litres_exclusive": false, "is_new": false, "is_sales_hit": false }, "in_folders": null, "is_archived": false, "interacted_at": null, "read_at": null, "purchased_at": null, "is_hidden": false, "synchronized_arts": [], "synchronizations": [], "alternative_version": null, "in_user_cart_status": "not_in_cart", "is_draft_full_free": false, "webtoon_chapters_count": null, "webtoon_last_read_chapter_id": null, "webtoon_last_read_chapter_number": null } } ``` It seems to me like most relevant fields are present: `title`, `subtitle`, `cover`, from the `persons` field one can retrieve `author`(s), `narrator`, `publisher` and `translator` (which at the moment is not used in ABS). What I am missing is the tags/genres, a description and a release date/year. It is not returned with the search results, but surely could be aquired since the book's page shows the information, though that might require extracting it from HTML. I use this site to aquire russian books. I am thinking about implementing a metadata provider for the site, so I don't have to copy paste it all the time. Their catalogue is quite large, and apart from exclusives of competing services they have most of the books I look up. I am not sure about the podcast part, since I am not using that part of ABS at all - but it could work for that as well. If I were to write a provider, would it be merged? ### Why would this be helpful? An additional provider for metadata for primarily russian books. ### Future Implementation (Screenshot) An additional entry in the provider drop-down field in the match book window and cover lookup window. ### Audiobookshelf Server Version v2.17.7 ### Current Implementation (Screenshot) ![grafik](https://github.com/user-attachments/assets/1d1b4eb9-85a7-43cb-9796-25850c384a2f)
adam added the enhancement label 2026-04-25 00:07:39 +02:00
Author
Owner

@advplyr commented on GitHub (Jan 13, 2025):

Do you know if they do strict throttling of requests?
Since this isn't a public API they might block our user-agent once it starts getting used by Abs.

We can try it out if you can do some testing on it to make sure it isn't going to result in a bunch of user bug reports

@advplyr commented on GitHub (Jan 13, 2025): Do you know if they do strict throttling of requests? Since this isn't a public API they might block our user-agent once it starts getting used by Abs. We can try it out if you can do some testing on it to make sure it isn't going to result in a bunch of user bug reports
Author
Owner

@thatguy7 commented on GitHub (Jan 13, 2025):

Do you know if they do strict throttling of requests?

I do not.

But if you are not against another provider in general, I will write something up in the coming weeks and test it.

Are there some specific minimal requirements like number of lookups per hour/minute/second, that must be satisfied?

I must admid that I have not considered such a limitation at all. I usually add books as I buy them, one at a time. But ABS users might match their whole library which would fire a lot of API calls.

@thatguy7 commented on GitHub (Jan 13, 2025): > Do you know if they do strict throttling of requests? I do not. But if you are not against another provider in general, I will write something up in the coming weeks and test it. Are there some specific minimal requirements like number of lookups per hour/minute/second, that must be satisfied? I must admid that I have not considered such a limitation at all. I usually add books as I buy them, one at a time. But ABS users might match their whole library which would fire a lot of API calls.
Author
Owner

@advplyr commented on GitHub (Jan 13, 2025):

There is no standard set for number of requests. Right now we are only throttling requests made when matching authors using the p-throttle library. Afaik we only had rate limit issues for users matching authors that had a lot of authors.
The providers should be refactored to be more standardized in general. I'm hoping to eventually have a plugin system that supports provider plugins, so that will need to get done for that.
For now we should just make sure it works when matching a full library and we can implement the p-throttle like done in the Audnexus.js file.

@advplyr commented on GitHub (Jan 13, 2025): There is no standard set for number of requests. Right now we are only throttling requests made when matching authors using the [p-throttle](https://github.com/sindresorhus/p-throttle) library. Afaik we only had rate limit issues for users matching authors that had a lot of authors. The providers should be refactored to be more standardized in general. I'm hoping to eventually have a plugin system that supports provider plugins, so that will need to get done for that. For now we should just make sure it works when matching a full library and we can implement the p-throttle like done in the `Audnexus.js` file.
Author
Owner

@thatguy7 commented on GitHub (Jan 15, 2025):

I had a further look at the API and figured out how to get all the attributes without any parsing.

https://api.litres.ru/foundation/api/arts/64056885

@thatguy7 commented on GitHub (Jan 15, 2025): I had a further look at the API and figured out how to get all the attributes without any parsing. ```https://api.litres.ru/foundation/api/arts/64056885```
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/audiobookshelf#2485