{"id":21006224,"url":"https://github.com/derlin/goodreads-metadata-fetcher","last_synced_at":"2025-03-13T14:43:38.744Z","repository":{"id":151664221,"uuid":"390821920","full_name":"derlin/goodreads-metadata-fetcher","owner":"derlin","description":"Kotlin library to fetch metadata from GoodReads","archived":false,"fork":false,"pushed_at":"2023-05-01T07:06:49.000Z","size":720,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":3,"default_branch":"main","last_synced_at":"2025-01-20T10:30:56.817Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://derlin.github.io/goodreads-metadata-fetcher/","language":"Kotlin","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/derlin.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-07-29T18:52:36.000Z","updated_at":"2024-09-13T15:37:06.000Z","dependencies_parsed_at":null,"dependency_job_id":"d0790700-624d-4dc7-93e4-02267ca39368","html_url":"https://github.com/derlin/goodreads-metadata-fetcher","commit_stats":null,"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derlin%2Fgoodreads-metadata-fetcher","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derlin%2Fgoodreads-metadata-fetcher/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derlin%2Fgoodreads-metadata-fetcher/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/derlin%2Fgoodreads-metadata-fetcher/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/derlin","download_url":"https://codeload.github.com/derlin/goodreads-metadata-fetcher/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243428421,"owners_count":20289315,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-19T08:49:59.492Z","updated_at":"2025-03-13T14:43:38.724Z","avatar_url":"https://github.com/derlin.png","language":"Kotlin","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Module GoodReads Metadata Fetcher\n\n\u003e **Warning**\n\u003e\n\u003e This repository is currently **on hold**, due to too many changes and restrictions with the new GoodReads interface and the lack of an official API.\n\n| [![Code](https://img.shields.io/badge/code-github.com-informational.svg)](https://github.com/derlin/goodreads-metadata-fetcher) | [![Documentation](https://img.shields.io/badge/documentation-derlin.io-informational.svg)](https://derlin.github.io/goodreads-metadata-fetcher/) | ![main workflow](https://github.com/derlin/goodreads-metadata-fetcher/actions/workflows/main.yaml/badge.svg) \n| :-----------: | :---------: | :---------:\n\nThis Kotlin Library implements a basic metadata lookup for [GoodReads](https://www.goodreads.com/).\nIt is compatible with Android.\n\n## Installation\n\nThis library is published on GitHub Packages. To learn how to use GitHub Packages, see:\n* for Gradle projects: [Working with the Gradle registry](\n   https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-gradle-registry)\n* for Maven projects: [Working with the Apache Maven registry](\n  https://docs.github.com/en/packages/working-with-a-github-packages-registry/working-with-the-apache-maven-registry)\n\nYou can also build the library (keep reading) and then run `./gradlew publishToMavenLocal` to make it available on your machine.\n\n### Build the library\n\nAfter cloning the repo, run the following to install the package on your local maven repo:\n\n```shell\n./gradlew publishToMavenLocal\n```\n\n### Import the library\n\nGiven projects on the same computer.\n\n**Gradle Project** open you module `build.gradle` and add:\n\n```groovy\nrepositories {\n    // ...\n    mavenLocal() // \u003c- use maven locally\n}\n\ndependencies {\n    // ...\n    implementation 'ch.derlin:goodreads-metadata-fetcher:1.0.0-SNAPSHOT'\n}\n```\n\n**Maven** open your `pom.xml` and add:\n\n```xml\n\u003cdependency\u003e\n    \u003cgroupId\u003ech.derlin\u003c/groupId\u003e\n    \u003cartifactId\u003egoodreads-metadata-fetcher\u003c/artifactId\u003e\n    \u003cversion\u003e1.0.0-SNAPHOST\u003c/version\u003e\n\u003c/dependency\u003e\n```\n\n## Usage\n\n*NOTE*: this library might sometimes seem slow, but this is mostly due to GoodReads itself being slow ;).\n\n### Search GoodReads and get Books metadata (interactively)\n\nYou will usually first do a search on GoodReads, then select a book in the list based oh on some criteria (or user input), \nand finally get the selected book's metadata.\n\nThis library allows you to do so easily, using the `GoodReadsLookup` class:\n\n1. create a `GoodReadsLookup` by providing some title and optionally an author;\n2. call `getMatches()`, which returns **the first 20 results** from GoodReads as a list of `GoodReadsSearchResult`;\n3. select one or more results that interest you based on some criteria (or user input);\n4. call `getMetadata()` from any `GoodReadsSearchResult` that interests you.\n\nHere is an example:\n```kotlin\n// [1] create a lookup, here on a partial title\nval lookup = GoodReadsLookup(title = \"Billy Milligan\")\n// [2] fetch the 20 best results\nval results = lookup.getMatches()\n// [3] select some results, here based on a partial Author name\nval myBook = results.firstOrNull { match -\u003e\n    match.authors.any { it.contains(\"Keyes\") }\n}\n// [4] actually fetch the metadata on the result (if any)\nval meta = myBook?.getMetadata()\nmeta?.let { println(it.toCompilableString()) } // use a prettier toString for console logging\n```\n\nThe result of the above snippet is:\n```\nGoodReadsMetadata(\n  title=\"The Minds of Billy Milligan\",\n  authors=listOf(\"Daniel Keyes\"),\n  url=\"https://www.goodreads.com/book/show/1391817.The_Minds_of_Billy_Milligan\",\n  id=\"1391817\",\n  isbn=\"9780394519432\",\n  pages=374,\n  pubDate=LocalDate.parse(\"1981-10-01\"),\n)\n```\n\nBy default, `getMatches()` will search in all fields if an author is provided, and in title only if the author is null. \nIt is possible to change this behavior by setting `includeAuthorInSearch = true`.\nSee also [better searches](#better-searches-title-only).\n\n### Get metadata automatically\n\n`GoodReadsLookup` also provides a convenient method to try to find the right book automatically in the list of results:\n```kotlin\nGoodReadsLookup(title=\"je pense trop\").findBestMatch().getMetadata()\n//GoodReadsMetadata(\n//    title=\"Je pense trop : comment canaliser ce mental envahissant\",\n//    authors=listOf(\"Christel Petitcollin\"),\n//    url=\"https://www.goodreads.com/book/show/10605863-je-pense-trop\",\n//    id=\"10605863\",\n//    isbn=\"9782813201966\",\n//    pages=252,\n//    pubDate=LocalDate.parse(\"2010-11-22\"),\n//)\n\n```\nOr more directly using `GoodReadsMetadata.lookup` (exact same):\n```kotlin\nGoodReadsMetadata.lookup(title=\"Freakonomics\", author=\"Steven Levitt, Stephen Dubner\")\n//GoodReadsMetadata(\n//    title=\"Freakonomics: A Rogue Economist Explores the Hidden Side of Everything\",\n//    authors=listOf(\"Steven D. Levitt\", \"Stephen J. Dubner\"),\n//    url=\"https://www.goodreads.com/book/show/1202.Freakonomics\",\n//    id=\"1202\",\n//    isbn=\"9780061234002\",\n//    pages=268,\n//    pubDate=LocalDate.parse(\"2005-04-12\"),\n//)\n```\n\nThe library will first do a search (see `GoodReadsLookup.getMatches()`), \nthen try to find a match in the list of results, throwing a `GrNotFoundException` if none. \n\n**IMPORTANT** for a result to be a match, the following conditions must apply:\n\n- the title must match exactly (*),\n- the author(s) must all be present in the list of authors, in the correct order (initials ignored)\n\n(*) All comparisons are diacritics, symbols, space and casing insensitive.\n\nNote that in case titles contain subtitles (\"Some Title**:** some subtitle\"), there will be a match either if the given title contains\nthe full title+subtitle, or only the title.\n\nSee also [better searches](#better-searches-title-only).\n\n### Get all results (not only the first page)\n\nSometimes, you want to see more than the first 20 results of a GoodReads search.\n`GoodReadsPaginatedSearchResult` is here for that.\nEither instantiate it directly from a GoodReads search page URL (see also `GoodReadsUrl`), or use `GoodReadsLookup.getAllMatchesPaginated`.\n\nOnce instantiated, you can use `hasNext()` and `next()` in order to fetch more pages.\nYou can get the full list of already fetched search results using `allResults()`,\nThe total number of results and pages, as well as the last page fetched are available through\n`totalResults`, `totalPages` and `currentPage` (the latter starting at `1`).\nIf no result is found, they will be set to `0`.\n\n*NOTE*: `GoodReadsPaginatedSearchResult` does network calls inside the constructor, so ensure you instantiate\nit in a background task on Android.\n\nExample:\n```kotlin\nval paginatedResults: GoodReadsPaginatedSearchResults = GoodReadsLookup(\"how time war\").getMatchesPaginated()\nprintln(\"Total pages available: ${paginatedResults.totalPages}\")\n\nwhile(paginatedResults.hasNext()) {\n    val nextResults = paginatedResults.next()\n    // do something with the newest results, e.g. add them to an adapter on Android\n}\n\npaginatedResults.allResults() // here we have the complete list of results\n```\n\n### Other\n\nThe class `GoodReadsUrl` offers convenient static methods to construct the search query URL from title and/or author,\nget the URL of a book given its GoodReads ID, etc. Check it out !\n\n## Tips and tricks\n\n### Better searches: title only\n\nIn general, GoodReads results are usually better when searching in title only.\nHence, we highly recommend to use title only in `GoodReadsLookup` if your title is specific enough,\nand to only include author in search in cases where the title very short / generic.\n\nIf you are using `GoodReadsMetadata.lookup()` or `GoodReadsLookup.findBestMatch()`,\nwe recommend you pass the author (if known) since it is used for matching, but to disable author in search\nby passing `includeAuthorInSearch = false` as argument.\n\n### Retry on server fault\n\nGoodReads tends to be a bit unstable, and may raise HTTP 5XX once in a while.\nTo avoid your code crashing on such cases, The `Retry` class is here to help.\nSimply instantiate a `Retry` with the `RetryConfiguration` you need, and wrap\nyour calls to GoodReads into a `retrier.run { }` block.\n\nSee the samples below for examples. \n\n@sample samples.findBookInteractively\n@sample samples.findBookAutomatically\n@sample samples.lookupWithRetry\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fderlin%2Fgoodreads-metadata-fetcher","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fderlin%2Fgoodreads-metadata-fetcher","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fderlin%2Fgoodreads-metadata-fetcher/lists"}