Metadata-Version: 2.4
Name: librofm
Version: 1.1.0
Summary: A Python client library for downloading audiobooks from Libro.fm
License: MIT
License-File: LICENSE
Keywords: audiobook,libro.fm,download,cli
Author: Bryan L. Fordham
Author-email: bryan@nativesavannah.com
Requires-Python: >=3.10
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: End Users/Desktop
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Multimedia :: Sound/Audio
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Dist: pydantic (>=2.13.5,<3.0.0)
Requires-Dist: pydantic-settings (>=2.9.1,<3.0.0)
Requires-Dist: python-dotenv (>=1.2.3,<2.0.0)
Requires-Dist: requests (>=2.32.4,<3.0.0)
Project-URL: Bug Reports, https://codeberg.org/bfordham/librofm/issues
Project-URL: Homepage, https://codeberge.org/bfordham/librofm
Project-URL: Source, https://codeberg.org/bfordham/librofm
Description-Content-Type: text/markdown

# librofm

A Python client library for syncing your audiobooks from [Libro.fm](https://libro.fm).

## Features

- Download audiobooks from your Libro.fm library
- Support for both MP3 and M4B formats (M4B preferred when available)
- Automatic, configurable file organization
- Command-line interface for syncing your audiobooks locally
- Python API for programmatic access

## Installation

```bash
pip install librofm
```

## Configuration

In order for this to work at all, you have to set your Libro.fm credentials as environment variables:

```bash
export LIBROFM_USERNAME="your_username"
export LIBROFM_PASSWORD="your_password"
```

Alternatively, create an environment file. It will search in the following order:
- `./.librofm`
- `./.env`
- `~/.librofm`

If running from the commandline, you can specify a specific file to use with `--config <file>`.

The two other configuration options are:
- `LIBROFM_OUTPUT_DIR`: The base directory in which to store you downloads. Defaults to `~/Audiobooks`
- `LIBROFM_DESTINATION_PATTERN`: How you want your files organized. Defaults to `< authors >/< title >`

*Note:* It's `authors`, plural. You can use any field in the Audiobook model, as well as any other text.

## Usage

### Command Line

Download all audiobooks to the default directory (`~/Audiobooks`):

```bash
librofm-sync
```

Download to a custom directory, overriding `.env`:

```bash
librofm-sync --base-path /path/to/audiobooks
```

By default, it won't download books it has previously retrieved. You can force it to redownload:

```bash
librofm-sync --force
```

You probably want to include `--overyouwrite` with `--force`. They are separate because, since you can configure the destination however you want, there's extra safety so you don't accidentally overwrite a book if you, for example, dump everything into a single folder.

If you've previously downloaded books, you can have `librofm-sync` try to match them with the books in your LibroFM library. You may want to adjust `destination_pattern` setting to match how you've organized things (The default is `<authors>/<title>`).

```bash
librofm-sync --create-index
```

Show help:

```bash
librofm-sync --help
```

### Python API

```python
from librofm.client import LibroFMClient

# Create client (uses environment variables)
client = LibroFMClient.get_client()

# Or create with explicit settings
client = LibroFMClient("username", "password", "~/Audiobooks", "< authors >/< title>")

# Get your library
audiobooks = client.get_library()
print(f"Found {len(audiobooks)} audiobooks")

# Download a specific audiobook
audiobook = audiobooks[0]
success = client.download(audiobook)

# Get download manifest for MP3 files
manifest = client.get_download_manifest(audiobook)
print(f"Audiobook has {len(manifest.parts)} parts")

# Get M4B package info
m4b_info = client.get_packaged_m4b_info(audiobook)
if m4b_info:
    print(f"M4B available at: {m4b_info.m4b_url}")
```

## File Organization

By default, downloaded audiobooks are organized as:
```
base_path/
    Author Name/
        Book Title/
            part1.mp3
            part2.mp3
            ...
    Another Author/
        Another Book/
            book.m4b
```

This default configuration looks like: `< authors >/< title >`. If you want to put all books by an author into the same folder, you would use `<authors>`.

You can add anything that is in the `Audiobook` model. I don't know why you'd want to, but you can do strange things like `< authors >/< isbn >/banana`.

## Duplicate Detection

When a book is downlaoded, `librofm-sync` creates a file in the directory that contains LibroFM ID of that book. When you perform another sync, it will find all the index files in the output directory and (unless you use `--force`) it will skip books previously downloaded. Using the index files instead of, for example, the destination directory, means you can move and rename files as you wish. As long as you leave the index file in place, it will be detected and future syncs will not duplicate the work.

I did not come up with this idea. It's similar to the pattern used in [BandcampSync](https://github.com/meeb/bandcampsync/tree/main) and I adapted it here.It's much better than what I had originally intended.

## Requirements

- Python 3.10+
- Active Libro.fm account with audiobooks in your library

## License

MIT License

## Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

## Disclaimer

This tool is not associated with LibroFM in any way. 

This tool is for personal use only. Please respect Libro.fm's terms of service and only download audiobooks you have legally purchased.
