# publicpaste `publicpaste` is a tiny Python package and CLI that posts text to multiple public paste providers concurrently and returns the first successful direct URL. - Python 3 standard library first - zero runtime dependencies - CLI and Python API - concurrent provider fan-out with first-success return - optional verification of the returned URL > Only paste text that is safe to publish. Returned links are public, and third-party services have their own retention and acceptable-use policies. ## Install From this repository: ```sh python -m pip install . ``` ## CLI ```sh publicpaste "hello from publicpaste" echo "hello from stdin" | publicpaste publicpaste --file a.txt ``` By default stdout contains only the URL, making the command easy to pipe: ```sh url=$(publicpaste --file notes.txt) ``` JSON output includes the provider name: ```sh publicpaste --json "hello" # {"url":"https://...","provider":"paste.rs"} ``` Useful options: - `--timeout SECONDS`: per-provider timeout, default `8.0` - `--overall-timeout SECONDS`: total wait budget, default `12.0` - `--json`: print `url` and `provider` as JSON - `--verbose`: print provider diagnostics on failure - `--verify`: GET the returned URL and confirm a 2xx response containing a text fragment - `--list-providers`: list provider names - `--provider NAME`: use only a provider; repeat to select several - `--disable-provider NAME`: disable a provider; repeatable Failures print a concise error to stderr and exit with status `1`. ## Web service `publicpaste` also includes a zero-dependency web UI and JSON API: ```sh python -m publicpaste.web # or, after installation: publicpaste-web ``` Open `http://127.0.0.1:12072`, enter text, and click “完成”. The page calls `POST /api/paste`, shows the returned URL/provider, and copies the URL to the clipboard. Useful environment variables: - `PUBLICPASTE_HOST`: bind host, default `0.0.0.0` - `PUBLICPASTE_PORT`: bind port, default `12072` - `PUBLICPASTE_DATA_DIR`: data/log directory, default `/data` - `PUBLICPASTE_TIMEOUT`: per-provider timeout, default `8.0` - `PUBLICPASTE_OVERALL_TIMEOUT`: total wait budget, default `12.0` - `PUBLICPASTE_VERIFY`: verify returned URL when true, default false Health check: ```sh curl http://127.0.0.1:12072/health ``` ## Docker Build and run with Compose: ```sh docker compose up -d --build ``` The included `compose.yml` uses image/container name `publicpaste`, maps `12072:12072`, and stores logs/data in `/vol1/1000/docker/publicpaste/data` mounted at `/data`. ## Python API ```python from publicpaste import paste_text result = paste_text("hello", timeout=8.0, overall_timeout=12.0) print(result.url) print(result.provider) ``` Signature: ```python paste_text( text, timeout=8.0, overall_timeout=12.0, providers=None, disabled_providers=None, verify=False, ) ``` `providers` may be a sequence of provider names or provider instances. `disabled_providers` removes providers by name. The function returns a `PasteResult` dataclass with at least `url` and `provider`. If every provider fails, it raises `PasteError` with aggregated per-provider errors. ## Providers Default enabled providers: - `paste.rs` — `POST https://paste.rs/`, raw UTF-8 body; `GET /` returns plain text. - `dpaste.org` — `POST https://dpaste.org/api/`, form fields `content`, `lexer=plain`, `format=url`, `expires_on=2592000`. - `0x0.st` — multipart field `file`, filename `paste.txt`, `text/plain`; this is a public file host, so use only non-sensitive text. - `snippet.host` — form fields `content`, `visibility=2`, `expires=1month`, `language=plain text`; parses `Location` or HTML URL. - `paste.centos.org` — `POST https://paste.centos.org/`, form fields `code`, `lang=text`, `expire=1440`; parses the final redirected view URL. Its documented `/api/create` endpoint currently requires an API key, so the browser-compatible form endpoint is used. - `termbin.com` — TCP port `9999`; low priority but enabled by default. Each provider has a response parsing method so parsing can be unit tested without network access. ## Validation and verification Provider responses are accepted only when the URL uses `http` or `https` and matches the expected provider host and path shape. By default `publicpaste` does not fetch the returned URL after creation, keeping the fastest provider path quick. When `verify=True` or `--verify` is used, `publicpaste` performs a GET against the returned direct URL and checks that the response is 2xx and contains a fragment of the original text. HTML escaping is tolerated. ## Why not PrivateBin, privydrop, clipboard-style services, or similar? This project intentionally targets simple public paste endpoints with stable, scriptable APIs. It does not include PrivateBin, privydrop, clipboard-style services, or similar tools when they require browser JavaScript, P2P flows, access codes, encrypted URL fragments, unstable/undocumented APIs, or interaction patterns that do not reliably return a direct public URL from a simple request. The initially reviewed services that are not enabled by default for those reasons include `clipboard.im`, `clipboard.run`, `clipboardify.com`, `clipboardonline.com`, `privydrop.app`, `privatebin.net`, `paste.drhack.net`, `pasteme.cn`, `paste.sdjz.wiki`, and `myonlineclipboard.com`. ## Tests Tests are unit-only and do not access the public internet: ```sh python -m pytest ```