uvero 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- uvero-0.1.0/LICENSE +21 -0
- uvero-0.1.0/PKG-INFO +95 -0
- uvero-0.1.0/README.md +63 -0
- uvero-0.1.0/pyproject.toml +49 -0
- uvero-0.1.0/setup.cfg +4 -0
- uvero-0.1.0/uvero/__init__.py +3 -0
- uvero-0.1.0/uvero/api.py +84 -0
- uvero-0.1.0/uvero/boards.py +84 -0
- uvero-0.1.0/uvero/cli.py +147 -0
- uvero-0.1.0/uvero/clipboard.py +13 -0
- uvero-0.1.0/uvero/utils.py +36 -0
- uvero-0.1.0/uvero.egg-info/PKG-INFO +95 -0
- uvero-0.1.0/uvero.egg-info/SOURCES.txt +15 -0
- uvero-0.1.0/uvero.egg-info/dependency_links.txt +1 -0
- uvero-0.1.0/uvero.egg-info/entry_points.txt +2 -0
- uvero-0.1.0/uvero.egg-info/requires.txt +4 -0
- uvero-0.1.0/uvero.egg-info/top_level.txt +1 -0
uvero-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Uvero
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
uvero-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: uvero
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Uvero CLI – online clipboard from your terminal
|
|
5
|
+
Author-email: Uvero <support@uvero.app>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://uvero.app
|
|
8
|
+
Project-URL: Repository, https://github.com/sakethdevx/uvero-cli
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/sakethdevx/uvero-cli/issues
|
|
10
|
+
Keywords: clipboard,cli,terminal,online clipboard,paste,share
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Utilities
|
|
23
|
+
Classifier: Topic :: Internet
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: typer>=0.9.0
|
|
28
|
+
Requires-Dist: requests>=2.28.0
|
|
29
|
+
Requires-Dist: pyperclip>=1.8.0
|
|
30
|
+
Requires-Dist: rich>=13.0.0
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# uvero-cli
|
|
34
|
+
|
|
35
|
+
**Uvero** is an online clipboard service. This CLI lets you interact with it directly from your terminal.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install uvero
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
### Send content
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Interactive paste mode (CTRL+D to finish)
|
|
49
|
+
uvero send
|
|
50
|
+
|
|
51
|
+
# Send a file
|
|
52
|
+
uvero send notes.txt
|
|
53
|
+
|
|
54
|
+
# Send system clipboard contents
|
|
55
|
+
uvero send -
|
|
56
|
+
|
|
57
|
+
# Pipe data
|
|
58
|
+
cat log.txt | uvero send
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Retrieve content
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Save to uvero_4832.txt
|
|
65
|
+
uvero get 4832
|
|
66
|
+
|
|
67
|
+
# Save to a specific file
|
|
68
|
+
uvero get 4832 notes.txt
|
|
69
|
+
|
|
70
|
+
# Copy directly to system clipboard
|
|
71
|
+
uvero get 4832 -c
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Boards (private shared clipboards)
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Create a board
|
|
78
|
+
uvero board create
|
|
79
|
+
|
|
80
|
+
# Send to a board
|
|
81
|
+
uvero board send abcd-def notes.txt
|
|
82
|
+
uvero board send abcd-def # interactive paste mode
|
|
83
|
+
|
|
84
|
+
# Get board content
|
|
85
|
+
uvero board get abcd-def
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Help
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
uvero --help
|
|
92
|
+
uvero send --help
|
|
93
|
+
uvero get --help
|
|
94
|
+
uvero board --help
|
|
95
|
+
```
|
uvero-0.1.0/README.md
ADDED
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
# uvero-cli
|
|
2
|
+
|
|
3
|
+
**Uvero** is an online clipboard service. This CLI lets you interact with it directly from your terminal.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install uvero
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Send content
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
# Interactive paste mode (CTRL+D to finish)
|
|
17
|
+
uvero send
|
|
18
|
+
|
|
19
|
+
# Send a file
|
|
20
|
+
uvero send notes.txt
|
|
21
|
+
|
|
22
|
+
# Send system clipboard contents
|
|
23
|
+
uvero send -
|
|
24
|
+
|
|
25
|
+
# Pipe data
|
|
26
|
+
cat log.txt | uvero send
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Retrieve content
|
|
30
|
+
|
|
31
|
+
```bash
|
|
32
|
+
# Save to uvero_4832.txt
|
|
33
|
+
uvero get 4832
|
|
34
|
+
|
|
35
|
+
# Save to a specific file
|
|
36
|
+
uvero get 4832 notes.txt
|
|
37
|
+
|
|
38
|
+
# Copy directly to system clipboard
|
|
39
|
+
uvero get 4832 -c
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### Boards (private shared clipboards)
|
|
43
|
+
|
|
44
|
+
```bash
|
|
45
|
+
# Create a board
|
|
46
|
+
uvero board create
|
|
47
|
+
|
|
48
|
+
# Send to a board
|
|
49
|
+
uvero board send abcd-def notes.txt
|
|
50
|
+
uvero board send abcd-def # interactive paste mode
|
|
51
|
+
|
|
52
|
+
# Get board content
|
|
53
|
+
uvero board get abcd-def
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## Help
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
uvero --help
|
|
60
|
+
uvero send --help
|
|
61
|
+
uvero get --help
|
|
62
|
+
uvero board --help
|
|
63
|
+
```
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=77.0"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "uvero"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Uvero CLI – online clipboard from your terminal"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
license = "MIT"
|
|
12
|
+
license-files = ["LICENSE"]
|
|
13
|
+
authors = [
|
|
14
|
+
{ name = "Uvero", email = "support@uvero.app" },
|
|
15
|
+
]
|
|
16
|
+
keywords = ["clipboard", "cli", "terminal", "online clipboard", "paste", "share"]
|
|
17
|
+
classifiers = [
|
|
18
|
+
"Development Status :: 4 - Beta",
|
|
19
|
+
"Environment :: Console",
|
|
20
|
+
"Intended Audience :: Developers",
|
|
21
|
+
"Intended Audience :: End Users/Desktop",
|
|
22
|
+
"Operating System :: OS Independent",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.8",
|
|
25
|
+
"Programming Language :: Python :: 3.9",
|
|
26
|
+
"Programming Language :: Python :: 3.10",
|
|
27
|
+
"Programming Language :: Python :: 3.11",
|
|
28
|
+
"Programming Language :: Python :: 3.12",
|
|
29
|
+
"Topic :: Utilities",
|
|
30
|
+
"Topic :: Internet",
|
|
31
|
+
]
|
|
32
|
+
dependencies = [
|
|
33
|
+
"typer>=0.9.0",
|
|
34
|
+
"requests>=2.28.0",
|
|
35
|
+
"pyperclip>=1.8.0",
|
|
36
|
+
"rich>=13.0.0",
|
|
37
|
+
]
|
|
38
|
+
|
|
39
|
+
[project.urls]
|
|
40
|
+
Homepage = "https://uvero.app"
|
|
41
|
+
Repository = "https://github.com/sakethdevx/uvero-cli"
|
|
42
|
+
"Bug Tracker" = "https://github.com/sakethdevx/uvero-cli/issues"
|
|
43
|
+
|
|
44
|
+
[project.scripts]
|
|
45
|
+
uvero = "uvero.cli:app"
|
|
46
|
+
|
|
47
|
+
[tool.setuptools.packages.find]
|
|
48
|
+
where = ["."]
|
|
49
|
+
include = ["uvero*"]
|
uvero-0.1.0/setup.cfg
ADDED
uvero-0.1.0/uvero/api.py
ADDED
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""API layer – all communication with the Uvero backend."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import requests
|
|
6
|
+
|
|
7
|
+
BASE_URL = "https://uvero.app"
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def _url(path: str) -> str:
|
|
11
|
+
return f"{BASE_URL}{path}"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def send_clipboard(content: str) -> dict:
|
|
15
|
+
"""Upload *content* to the clipboard service and return the JSON response."""
|
|
16
|
+
response = requests.post(
|
|
17
|
+
_url("/api/clipboard/send"),
|
|
18
|
+
json={"content": content},
|
|
19
|
+
timeout=15,
|
|
20
|
+
)
|
|
21
|
+
response.raise_for_status()
|
|
22
|
+
return response.json()
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def get_clipboard(code: str) -> dict:
|
|
26
|
+
"""Fetch clipboard entry identified by *code* and return the JSON response."""
|
|
27
|
+
response = requests.get(
|
|
28
|
+
_url(f"/api/clipboard/get/{code}"),
|
|
29
|
+
timeout=15,
|
|
30
|
+
)
|
|
31
|
+
response.raise_for_status()
|
|
32
|
+
return response.json()
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
def create_board(password: str | None = None) -> dict:
|
|
36
|
+
"""Create a new private board and return the JSON response."""
|
|
37
|
+
payload: dict = {}
|
|
38
|
+
if password:
|
|
39
|
+
payload["password"] = password
|
|
40
|
+
response = requests.post(
|
|
41
|
+
_url("/api/clipboard/board/create"),
|
|
42
|
+
json=payload,
|
|
43
|
+
timeout=15,
|
|
44
|
+
)
|
|
45
|
+
response.raise_for_status()
|
|
46
|
+
return response.json()
|
|
47
|
+
|
|
48
|
+
|
|
49
|
+
def send_board(board: str, content: str, password: str | None = None) -> dict:
|
|
50
|
+
"""Send *content* to *board* and return the JSON response."""
|
|
51
|
+
payload: dict = {"board": board, "content": content}
|
|
52
|
+
if password:
|
|
53
|
+
payload["password"] = password
|
|
54
|
+
response = requests.post(
|
|
55
|
+
_url("/api/clipboard/board/send"),
|
|
56
|
+
json=payload,
|
|
57
|
+
timeout=15,
|
|
58
|
+
)
|
|
59
|
+
response.raise_for_status()
|
|
60
|
+
return response.json()
|
|
61
|
+
|
|
62
|
+
|
|
63
|
+
def get_board(board: str, password: str | None = None) -> dict:
|
|
64
|
+
"""Retrieve content from *board* and return the JSON response."""
|
|
65
|
+
params: dict = {}
|
|
66
|
+
if password:
|
|
67
|
+
params["password"] = password
|
|
68
|
+
response = requests.get(
|
|
69
|
+
_url(f"/api/clipboard/board/get/{board}"),
|
|
70
|
+
params=params,
|
|
71
|
+
timeout=15,
|
|
72
|
+
)
|
|
73
|
+
response.raise_for_status()
|
|
74
|
+
return response.json()
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def health_check() -> dict:
|
|
78
|
+
"""Call the CLI health endpoint and return the JSON response."""
|
|
79
|
+
response = requests.get(
|
|
80
|
+
_url("/api/clipboard/cli-health"),
|
|
81
|
+
timeout=10,
|
|
82
|
+
)
|
|
83
|
+
response.raise_for_status()
|
|
84
|
+
return response.json()
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
"""Board-related CLI commands (create / send / get)."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import getpass
|
|
6
|
+
import sys
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
import typer
|
|
10
|
+
|
|
11
|
+
from uvero import api
|
|
12
|
+
from uvero.utils import console, handle_api_error, is_piped, read_file, read_stdin
|
|
13
|
+
|
|
14
|
+
board_app = typer.Typer(help="Manage private boards.")
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
@board_app.command("create")
|
|
18
|
+
def board_create():
|
|
19
|
+
"""Create a new private board."""
|
|
20
|
+
try:
|
|
21
|
+
result = api.create_board()
|
|
22
|
+
except Exception as exc:
|
|
23
|
+
console.print(f"[bold red]❌ Error:[/bold red] {exc}")
|
|
24
|
+
raise typer.Exit(1)
|
|
25
|
+
|
|
26
|
+
handle_api_error(result)
|
|
27
|
+
board_id = result.get("data", {}).get("board") or result.get("data", {}).get("id", "")
|
|
28
|
+
console.print(f"[bold green]Board created:[/bold green] {board_id}")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
@board_app.command("send")
|
|
32
|
+
def board_send(
|
|
33
|
+
board: str = typer.Argument(..., help="Board identifier"),
|
|
34
|
+
file: Optional[str] = typer.Argument(None, help="File to upload (omit for paste mode)"),
|
|
35
|
+
):
|
|
36
|
+
"""Send content to a board."""
|
|
37
|
+
if file:
|
|
38
|
+
try:
|
|
39
|
+
content = read_file(file)
|
|
40
|
+
except OSError as exc:
|
|
41
|
+
console.print(f"[bold red]❌ Error:[/bold red] {exc}")
|
|
42
|
+
raise typer.Exit(1)
|
|
43
|
+
elif is_piped():
|
|
44
|
+
content = read_stdin()
|
|
45
|
+
else:
|
|
46
|
+
console.print("[dim]Paste your text below. Press CTRL+D when done.[/dim]")
|
|
47
|
+
try:
|
|
48
|
+
content = sys.stdin.read()
|
|
49
|
+
except EOFError:
|
|
50
|
+
content = ""
|
|
51
|
+
|
|
52
|
+
try:
|
|
53
|
+
result = api.send_board(board, content)
|
|
54
|
+
except Exception as exc:
|
|
55
|
+
console.print(f"[bold red]❌ Error:[/bold red] {exc}")
|
|
56
|
+
raise typer.Exit(1)
|
|
57
|
+
|
|
58
|
+
handle_api_error(result)
|
|
59
|
+
console.print(f"[bold green]✔ Sent to board:[/bold green] {board}")
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
@board_app.command("get")
|
|
63
|
+
def board_get(
|
|
64
|
+
board: str = typer.Argument(..., help="Board identifier"),
|
|
65
|
+
):
|
|
66
|
+
"""Retrieve content from a board."""
|
|
67
|
+
try:
|
|
68
|
+
result = api.get_board(board)
|
|
69
|
+
except Exception as exc:
|
|
70
|
+
console.print(f"[bold red]❌ Error:[/bold red] {exc}")
|
|
71
|
+
raise typer.Exit(1)
|
|
72
|
+
|
|
73
|
+
# Handle password-protected boards
|
|
74
|
+
if result.get("requiresPassword"):
|
|
75
|
+
password = getpass.getpass("Board password: ")
|
|
76
|
+
try:
|
|
77
|
+
result = api.get_board(board, password=password)
|
|
78
|
+
except Exception as exc:
|
|
79
|
+
console.print(f"[bold red]❌ Error:[/bold red] {exc}")
|
|
80
|
+
raise typer.Exit(1)
|
|
81
|
+
|
|
82
|
+
handle_api_error(result)
|
|
83
|
+
content = result.get("data", {}).get("content", "")
|
|
84
|
+
console.print(content)
|
uvero-0.1.0/uvero/cli.py
ADDED
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
"""Main CLI entry point – exposes the `uv` command."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
from typing import Optional
|
|
8
|
+
|
|
9
|
+
import typer
|
|
10
|
+
from rich.console import Console
|
|
11
|
+
|
|
12
|
+
from uvero import api
|
|
13
|
+
from uvero.boards import board_app
|
|
14
|
+
from uvero.clipboard import read_clipboard, write_clipboard
|
|
15
|
+
from uvero.utils import handle_api_error, is_piped, read_file, read_stdin, write_file
|
|
16
|
+
|
|
17
|
+
console = Console()
|
|
18
|
+
|
|
19
|
+
app = typer.Typer(
|
|
20
|
+
name="uvero",
|
|
21
|
+
help="Uvero – online clipboard from your terminal.",
|
|
22
|
+
no_args_is_help=True,
|
|
23
|
+
)
|
|
24
|
+
|
|
25
|
+
app.add_typer(board_app, name="board")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
def _check_health() -> None:
|
|
29
|
+
"""Silently verify that the Uvero service is reachable."""
|
|
30
|
+
try:
|
|
31
|
+
api.health_check()
|
|
32
|
+
except Exception:
|
|
33
|
+
console.print("[bold yellow]⚠ Uvero service unavailable.[/bold yellow]")
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
@app.command()
|
|
37
|
+
def send(
|
|
38
|
+
file: Optional[str] = typer.Argument(
|
|
39
|
+
None,
|
|
40
|
+
help="File to send. Use '-' to send the system clipboard.",
|
|
41
|
+
),
|
|
42
|
+
):
|
|
43
|
+
"""Send content to the Uvero clipboard.
|
|
44
|
+
|
|
45
|
+
\b
|
|
46
|
+
uv send – interactive paste mode (or piped stdin)
|
|
47
|
+
uv send file.txt – send a file
|
|
48
|
+
uv send - – send system clipboard contents
|
|
49
|
+
"""
|
|
50
|
+
_check_health()
|
|
51
|
+
|
|
52
|
+
if file == "-":
|
|
53
|
+
# Read from system clipboard
|
|
54
|
+
try:
|
|
55
|
+
content = read_clipboard()
|
|
56
|
+
except Exception as exc:
|
|
57
|
+
console.print(f"[bold red]❌ Error reading clipboard:[/bold red] {exc}")
|
|
58
|
+
raise typer.Exit(1)
|
|
59
|
+
elif file:
|
|
60
|
+
# Read from the given file path
|
|
61
|
+
try:
|
|
62
|
+
content = read_file(file)
|
|
63
|
+
except OSError as exc:
|
|
64
|
+
console.print(f"[bold red]❌ Error:[/bold red] {exc}")
|
|
65
|
+
raise typer.Exit(1)
|
|
66
|
+
elif is_piped():
|
|
67
|
+
# Data piped via stdin
|
|
68
|
+
content = read_stdin()
|
|
69
|
+
else:
|
|
70
|
+
# Interactive paste mode
|
|
71
|
+
console.print("[dim]Paste your text below. Press CTRL+D (Linux/Mac) or CTRL+Z (Windows) when done.[/dim]")
|
|
72
|
+
try:
|
|
73
|
+
content = sys.stdin.read()
|
|
74
|
+
except EOFError:
|
|
75
|
+
content = ""
|
|
76
|
+
|
|
77
|
+
if not content:
|
|
78
|
+
console.print("[bold red]❌ Error:[/bold red] Nothing to send.")
|
|
79
|
+
raise typer.Exit(1)
|
|
80
|
+
|
|
81
|
+
try:
|
|
82
|
+
result = api.send_clipboard(content)
|
|
83
|
+
except Exception as exc:
|
|
84
|
+
console.print(f"[bold red]❌ Error:[/bold red] {exc}")
|
|
85
|
+
raise typer.Exit(1)
|
|
86
|
+
|
|
87
|
+
handle_api_error(result)
|
|
88
|
+
|
|
89
|
+
code = result.get("data", {}).get("code", "")
|
|
90
|
+
console.print(f"\n📋 [bold]Clipboard Code:[/bold] {code}")
|
|
91
|
+
console.print(f"🔗 [link]https://uvero.app/{code}[/link]")
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
@app.command()
|
|
95
|
+
def get(
|
|
96
|
+
code: str = typer.Argument(..., help="Clipboard code to retrieve"),
|
|
97
|
+
output: Optional[str] = typer.Argument(
|
|
98
|
+
None,
|
|
99
|
+
help="File path to write content to. Omit to auto-generate (uvero_CODE.txt).",
|
|
100
|
+
),
|
|
101
|
+
copy: bool = typer.Option(
|
|
102
|
+
False,
|
|
103
|
+
"-c",
|
|
104
|
+
help="Copy retrieved content to system clipboard.",
|
|
105
|
+
),
|
|
106
|
+
):
|
|
107
|
+
"""Retrieve content from the Uvero clipboard.
|
|
108
|
+
|
|
109
|
+
\b
|
|
110
|
+
uv get 4832 – save to uvero_4832.txt
|
|
111
|
+
uv get 4832 notes.txt – save to notes.txt
|
|
112
|
+
uv get 4832 -c – copy to system clipboard
|
|
113
|
+
"""
|
|
114
|
+
_check_health()
|
|
115
|
+
|
|
116
|
+
try:
|
|
117
|
+
result = api.get_clipboard(code)
|
|
118
|
+
except Exception as exc:
|
|
119
|
+
console.print(f"[bold red]❌ Error:[/bold red] {exc}")
|
|
120
|
+
raise typer.Exit(1)
|
|
121
|
+
|
|
122
|
+
handle_api_error(result)
|
|
123
|
+
|
|
124
|
+
content = result.get("data", {}).get("content", "")
|
|
125
|
+
|
|
126
|
+
if copy:
|
|
127
|
+
try:
|
|
128
|
+
write_clipboard(content)
|
|
129
|
+
except Exception as exc:
|
|
130
|
+
console.print(f"[bold red]❌ Error copying to clipboard:[/bold red] {exc}")
|
|
131
|
+
raise typer.Exit(1)
|
|
132
|
+
console.print("[bold green]✔ Copied to clipboard[/bold green]")
|
|
133
|
+
return
|
|
134
|
+
|
|
135
|
+
# Determine output file path
|
|
136
|
+
dest = output if output else f"uvero_{code}.txt"
|
|
137
|
+
try:
|
|
138
|
+
write_file(dest, content)
|
|
139
|
+
except OSError as exc:
|
|
140
|
+
console.print(f"[bold red]❌ Error:[/bold red] {exc}")
|
|
141
|
+
raise typer.Exit(1)
|
|
142
|
+
|
|
143
|
+
console.print(f"[bold green]✔ Saved to:[/bold green] {dest}")
|
|
144
|
+
|
|
145
|
+
|
|
146
|
+
if __name__ == "__main__":
|
|
147
|
+
app()
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
"""System clipboard helpers (read / write) using pyperclip."""
|
|
2
|
+
|
|
3
|
+
import pyperclip
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def read_clipboard() -> str:
|
|
7
|
+
"""Return the current system clipboard content."""
|
|
8
|
+
return pyperclip.paste()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def write_clipboard(text: str) -> None:
|
|
12
|
+
"""Write *text* to the system clipboard."""
|
|
13
|
+
pyperclip.copy(text)
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
"""Shared utilities used across CLI commands."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
from pathlib import Path
|
|
5
|
+
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
|
|
8
|
+
console = Console()
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def read_stdin() -> str:
|
|
12
|
+
"""Read all text from standard input (piped or interactive paste mode)."""
|
|
13
|
+
return sys.stdin.read()
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
def is_piped() -> bool:
|
|
17
|
+
"""Return True when data is being piped into the process via stdin."""
|
|
18
|
+
return not sys.stdin.isatty()
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def read_file(path: str) -> str:
|
|
22
|
+
"""Read and return the contents of the file at *path*."""
|
|
23
|
+
return Path(path).read_text(encoding="utf-8")
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def write_file(path: str, content: str) -> None:
|
|
27
|
+
"""Write *content* to the file at *path*."""
|
|
28
|
+
Path(path).write_text(content, encoding="utf-8")
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
def handle_api_error(response: dict) -> None:
|
|
32
|
+
"""Print a rich error message and raise SystemExit if the API returned an error."""
|
|
33
|
+
if not response.get("success", True):
|
|
34
|
+
error_msg = response.get("error", "Unknown error")
|
|
35
|
+
console.print(f"[bold red]❌ Error:[/bold red] {error_msg}")
|
|
36
|
+
raise SystemExit(1)
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: uvero
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Uvero CLI – online clipboard from your terminal
|
|
5
|
+
Author-email: Uvero <support@uvero.app>
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Project-URL: Homepage, https://uvero.app
|
|
8
|
+
Project-URL: Repository, https://github.com/sakethdevx/uvero-cli
|
|
9
|
+
Project-URL: Bug Tracker, https://github.com/sakethdevx/uvero-cli/issues
|
|
10
|
+
Keywords: clipboard,cli,terminal,online clipboard,paste,share
|
|
11
|
+
Classifier: Development Status :: 4 - Beta
|
|
12
|
+
Classifier: Environment :: Console
|
|
13
|
+
Classifier: Intended Audience :: Developers
|
|
14
|
+
Classifier: Intended Audience :: End Users/Desktop
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Topic :: Utilities
|
|
23
|
+
Classifier: Topic :: Internet
|
|
24
|
+
Requires-Python: >=3.8
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
License-File: LICENSE
|
|
27
|
+
Requires-Dist: typer>=0.9.0
|
|
28
|
+
Requires-Dist: requests>=2.28.0
|
|
29
|
+
Requires-Dist: pyperclip>=1.8.0
|
|
30
|
+
Requires-Dist: rich>=13.0.0
|
|
31
|
+
Dynamic: license-file
|
|
32
|
+
|
|
33
|
+
# uvero-cli
|
|
34
|
+
|
|
35
|
+
**Uvero** is an online clipboard service. This CLI lets you interact with it directly from your terminal.
|
|
36
|
+
|
|
37
|
+
## Installation
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
pip install uvero
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Usage
|
|
44
|
+
|
|
45
|
+
### Send content
|
|
46
|
+
|
|
47
|
+
```bash
|
|
48
|
+
# Interactive paste mode (CTRL+D to finish)
|
|
49
|
+
uvero send
|
|
50
|
+
|
|
51
|
+
# Send a file
|
|
52
|
+
uvero send notes.txt
|
|
53
|
+
|
|
54
|
+
# Send system clipboard contents
|
|
55
|
+
uvero send -
|
|
56
|
+
|
|
57
|
+
# Pipe data
|
|
58
|
+
cat log.txt | uvero send
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
### Retrieve content
|
|
62
|
+
|
|
63
|
+
```bash
|
|
64
|
+
# Save to uvero_4832.txt
|
|
65
|
+
uvero get 4832
|
|
66
|
+
|
|
67
|
+
# Save to a specific file
|
|
68
|
+
uvero get 4832 notes.txt
|
|
69
|
+
|
|
70
|
+
# Copy directly to system clipboard
|
|
71
|
+
uvero get 4832 -c
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Boards (private shared clipboards)
|
|
75
|
+
|
|
76
|
+
```bash
|
|
77
|
+
# Create a board
|
|
78
|
+
uvero board create
|
|
79
|
+
|
|
80
|
+
# Send to a board
|
|
81
|
+
uvero board send abcd-def notes.txt
|
|
82
|
+
uvero board send abcd-def # interactive paste mode
|
|
83
|
+
|
|
84
|
+
# Get board content
|
|
85
|
+
uvero board get abcd-def
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Help
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
uvero --help
|
|
92
|
+
uvero send --help
|
|
93
|
+
uvero get --help
|
|
94
|
+
uvero board --help
|
|
95
|
+
```
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
uvero/__init__.py
|
|
5
|
+
uvero/api.py
|
|
6
|
+
uvero/boards.py
|
|
7
|
+
uvero/cli.py
|
|
8
|
+
uvero/clipboard.py
|
|
9
|
+
uvero/utils.py
|
|
10
|
+
uvero.egg-info/PKG-INFO
|
|
11
|
+
uvero.egg-info/SOURCES.txt
|
|
12
|
+
uvero.egg-info/dependency_links.txt
|
|
13
|
+
uvero.egg-info/entry_points.txt
|
|
14
|
+
uvero.egg-info/requires.txt
|
|
15
|
+
uvero.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
uvero
|