Metadata-Version: 2.4
Name: lain-upload
Version: 1.24
Summary: A simple CLI file uploader for multiple file-hosting services, with optional clipboard copy.
Keywords: python,file-upload,file-uploader,uploader,catbox,litterbox,pomf,uguu,fileditch,tempditch,0x0,gofile,pixeldrain,lain-upload,lain,kuroneko
Author: NecRaul
Author-email: NecRaul <necraul@kuroneko.dev>
License-Expression: LGPL-2.1-only
License-File: LICENSE
Classifier: Development Status :: 5 - Production/Stable
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Natural Language :: English
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3 :: Only
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Internet :: WWW/HTTP
Requires-Dist: requests>=2.32.5
Requires-Dist: requests-toolbelt>=1.0.0
Requires-Dist: pyperclip>=1.11.0 ; extra == 'clipboard'
Requires-Python: >=3.10
Project-URL: Homepage, https://github.com/NecRaul/lain-upload
Project-URL: Documentation, https://github.com/NecRaul/lain-upload#readme
Project-URL: Repository, https://github.com/NecRaul/lain-upload.git
Project-URL: Download, https://github.com/NecRaul/lain-upload/releases
Project-URL: Issues, https://github.com/NecRaul/lain-upload/issues
Provides-Extra: clipboard
Description-Content-Type: text/markdown

# lain-upload

A simple CLI file uploader for multiple file-hosting services, with optional clipboard copy.

## Installation

### Via PyPI (Recommended)

You have the option to choose between the standard version (`lain-upload`) or the desktop version (`lain-upload[clipboard]`), which adds clipboard support for auto-copying links.

> [!NOTE]
> For brevity, the examples below use the desktop version.

#### With pip (Basic)

```sh
pip install "lain-upload[clipboard]"
```

#### With pipx (Isolated)

```sh
pipx install "lain-upload[clipboard]"
```

#### With uv (Best)

The most efficient way to install or run `lain-upload`.

```sh
# Permanent isolated installation
uv tool install "lain-upload[clipboard]"

# Run once without installing
uvx --with "lain-upload[clipboard]" lain-upload <file1> <file2> <file3>

# Run in scripts or ad-hoc environments
uv run --with "lain-upload[clipboard]" lain-upload <file1> <file2> <file3>
```

### From Source (Development)

```sh
# Clone the repository and navigate to it
git clone git@github.com:NecRaul/lain-upload.git
cd lain-upload

# Install environment and all development dependencies (mandatory and optional)
uv sync --dev

# Install pre-commit hook
uv run pre-commit install

# Optional: Run all linters and type checkers manually
uv run pre-commit run --all-files

# Run the local version
uv run lain-upload <file1> <file2> <file3>

# Run tests
uv run pytest tests
```

## Usage

Simply provide the path to the file or files you wish to upload.

```sh
# Upload a single file (default host: catbox)
lain-upload kuroneko.png

# Upload multiple files from different directories
lain-upload /path/to/kuroneko.png /path/to/another/directory/shironeko.png yamineko.png ../kamineko.png

# Select a specific host
lain-upload --host uguu kuroneko.png

# Use host authentication when supported
lain-upload --host mixdrop --auth necraul@kuroneko.dev:generated_api_key kuroneko.png

# Set temporary file expiration when supported (e.g. 1h, 12h, 24h, 72h, etc.)
lain-upload --host litterbox --expire-after 24h kuroneko.png

# Enable longer generated filenames when supported
lain-upload --host 0x0 --long-filenames -- kuroneko.png shironeko.png

# Upload to every available non-deprecated host
lain-upload --host all kamineko.png

# Display help and version
lain-upload -h
lain-upload -v
```

### Options

```sh
    --host            HOST                  File hosting service to upload to (default: catbox)
    --auth            AUTH                  Authentication credentials for the host (format varies per host)
    --expire-after    DURATION              How long before the file expires when supported (e.g. 1h, 24h, 72h)
    --long-filenames  -                     Enable longer generated filenames when supported by the host
    --config          PATH                  Path to a custom configuration file
    --init-config     [PATH]                Create a default configuration file at the default or given path
    --show-config     -                     Print the effective configuration after merging defaults and config file
    --no-config       -                     Ignore the configuration file and use only CLI flags
-h, --help            -                     Show help and exit
-v, --version         -                     Show version and exit
```

### Configuration

`lain-upload` supports a JSON configuration file to set a default host and per-host options. You can create a default config, inspect the effective configuration, and override or ignore the config file at runtime.

- Default path
  - Linux/BSD: `$XDG_CONFIG_HOME/necraul/lain-upload.json` or `~/.config/necraul/lain-upload.json`
  - MacOS: `~/Library/Application Support/necraul/lain-upload.json`
  - Windows: `%APPDATA%/necraul/lain-upload.json`
- Basic structure
  - `default_host`: host used when `--host` flag is omitted (default: `"catbox"`).
  - `hosts`: per-host configuration (`auth`, `expire_after`, `long_filenames`, etc.), keyed by host name.

```json
{
  "default_host": "catbox",
  "hosts": {
    "catbox": {
      "auth": null
    },
    "litterbox": {
      "expire_after": "72h",
      "long_filenames": false
    },
    "gofile": {
      "auth": null
    }
  }
}
```

```sh
# Create a default configuration file at the default path
lain-upload --init-config

# Create a default configuration file at a custom path
lain-upload --init-config config.json

# Show the effective configuration (defaults merged with the default config file)
lain-upload --show-config

# Create a default configuration file at the default path and print it
lain-upload --init-config --show-config

# Create a default configuration file at a custom path and print it
lain-upload --init-config /path/to/config.json --show-config

# Show the effective configuration (defaults merged with the custom config file)
lain-upload --config config.json --show-config

# Upload using the config file's default_host (no --host needed)
lain-upload kuroneko.png

# Override the config file's default_host
lain-upload --host uguu shironeko.png

# Use a custom configuration file
lain-upload --config /path/to/config.json kamineko.png

# Ignore the configuration file and use only CLI flags
lain-upload --no-config kuroneko.png

# Override config's host and expiration (CLI flag overrides config)
lain-upload --host litterbox --expire-after 24h kuroneko.png
```

## Supported Hosts

- [catbox](https://catbox.moe/) - Support for user authentication with userhashes.
- [litterbox](https://litterbox.catbox.moe/) - Support for custom expiration time and longer upload filenames.
- [pomf](https://pomf.lain.la/) - No extra options (_deprecated_).
- [uguu](https://uguu.se/) - No extra options.
- [fileditch](https://new.fileditch.com/) - No extra options.
- [tempditch](https://temp.fileditch.com/) - No extra options.
- [0x0](https://0x0.st/) - Support for custom expiration time and longer upload filenames.
- [x0](https://x0.at/) - Support for longer upload filenames.
- [gofile](https://gofile.io/) - Support for user authentication with bearer API tokens.
- [pixeldrain](https://pixeldrain.com/) - Support for user authentication with API keys (**Required**).
- [buzzheavier](https://buzzheavier.com/) - No extra options.
- [mixdrop](https://mixdrop.ag/) - Support for user authentication with mail and API keys (**Required**).
- [sharey](https://sharey.org/) - Support for custom expiration time.

## Dependencies

- [requests](https://github.com/psf/requests): send the API request for uploading.
- [requests-toolbelt](https://github.com/requests/toolbelt): enable memory-efficient streaming and progress tracking for large uploads.

### Optional

- [pyperclip](https://github.com/asweigart/pyperclip): copy the uploaded files' URLs to the clipboard.

## How it works

Supported services provide upload endpoints that accept multipart `HTTP` requests.

This tool automates uploads and adds safety checks and quality-of-life features.

### The Manual Way

```sh
curl -F "file=@kuroneko.png" https://example-upload-service.tld/upload-endpoint
```

### The lain-upload way

- Batch Processing: Upload multiple files in a single command, iterating through each one and reporting results as they complete rather than waiting for the entire batch to finish.
- Validation: Enforces service-specific constraints before sending anything. File size limits, allowed extensions, and authentication requirements are all checked upfront to avoid partial uploads or silent failures.
- API Request: Sends multipart `POST` requests via `requests` and `requests-toolbelt`. The toolbelt layer wraps the file in a streaming encoder so large files are read and sent in chunks rather than loaded fully into memory.
- Normalization: Parses each service's unique response format and extracts a clean, shareable URL regardless of how the host structures its JSON or plain-text reply.
- Clipboard (Optional): If `pyperclip` is installed, each resulting URL is copied to the clipboard immediately after upload so it is ready to paste without any extra steps.

## Special thanks

- To **7666** of <https://lain.la/> for running the [pomf](https://pomf.lain.la/) service that inspired this project.
- To **r/a/dio anons** for feedback and suggestions.
