Add public paste CLI and skill
Provide a zero-dependency Python tool that races multiple public paste providers and documents safe AI-tool usage through a project skill.
This commit is contained in:
@@ -0,0 +1,111 @@
|
||||
# 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`.
|
||||
|
||||
## 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 /<id>` 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
|
||||
```
|
||||
Reference in New Issue
Block a user