tempspace-cli 1.0.0__py3-none-any.whl

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.
cli/__init__.py ADDED
@@ -0,0 +1 @@
1
+ __version__ = "1.0.0"
cli/tempspace.py ADDED
@@ -0,0 +1,137 @@
1
+ import argparse
2
+ import requests
3
+ import os
4
+ import sys
5
+ import hashlib
6
+ import multiprocessing
7
+ from tqdm import tqdm
8
+ from requests_toolbelt.multipart.encoder import MultipartEncoder, MultipartEncoderMonitor
9
+ from rich.console import Console
10
+ from rich.panel import Panel
11
+
12
+ # Default configuration
13
+ DEFAULT_SERVER_URL = "https://tempspace.fly.dev/"
14
+ CHUNK_SIZE = 1024 * 1024 # 1MB
15
+
16
+ def parse_time(time_str: str) -> int:
17
+ """
18
+ Parse a time string (e.g., '7d', '24h', '360') into an integer number of hours.
19
+ Returns the number of hours as an integer, or None if parsing fails.
20
+ """
21
+ time_str = time_str.lower().strip()
22
+ if time_str.endswith('d'):
23
+ try:
24
+ days = int(time_str[:-1])
25
+ return days * 24
26
+ except ValueError:
27
+ return None
28
+ elif time_str.endswith('h'):
29
+ try:
30
+ return int(time_str[:-1])
31
+ except ValueError:
32
+ return None
33
+ else:
34
+ try:
35
+ return int(time_str)
36
+ except ValueError:
37
+ return None
38
+
39
+ def calculate_file_hash(filepath: str) -> str:
40
+ """Calculate the SHA256 hash of a file in chunks."""
41
+ sha256_hash = hashlib.sha256()
42
+ try:
43
+ with open(filepath, "rb") as f:
44
+ for byte_block in iter(lambda: f.read(CHUNK_SIZE), b""):
45
+ sha256_hash.update(byte_block)
46
+ return sha256_hash.hexdigest()
47
+ except IOError as e:
48
+ print(f"Error reading file for hashing: {e}", file=sys.stderr)
49
+ sys.exit(1)
50
+
51
+ def main():
52
+ """Main function to handle argument parsing and file upload."""
53
+ console = Console()
54
+
55
+ parser = argparse.ArgumentParser(
56
+ description="Upload a file to Tempspace.",
57
+ formatter_class=argparse.RawTextHelpFormatter
58
+ )
59
+
60
+ parser.add_argument("filepath", help="The path to the file you want to upload.")
61
+ parser.add_argument("-t", "--time", type=str, default='24', help="Set the file's expiration time. Examples: '24h', '7d', '360' (hours).\nDefault: '24' (24 hours).")
62
+ parser.add_argument("-p", "--password", type=str, help="Protect the file with a password.")
63
+ parser.add_argument("--one-time", action="store_true", help="The file will be deleted after the first download.")
64
+ parser.add_argument("--url", type=str, default=os.environ.get("TEMPSPACE_URL", DEFAULT_SERVER_URL), help=f"The URL of the Tempspace server.\nCan also be set with the TEMPSPACE_URL environment variable.\nDefault: {DEFAULT_SERVER_URL}")
65
+
66
+ args = parser.parse_args()
67
+
68
+ # --- Validate Inputs ---
69
+ if not os.path.isfile(args.filepath):
70
+ console.print(f"[bold red]Error:[/] File not found at '{args.filepath}'")
71
+ sys.exit(1)
72
+
73
+ hours = parse_time(args.time)
74
+ if hours is None:
75
+ console.print(f"[bold red]Error:[/] Invalid time format '{args.time}'. Use formats like '24h', '7d', or '360'.")
76
+ sys.exit(1)
77
+
78
+ # --- Hashing ---
79
+ console.print("[cyan]Calculating file hash...[/]")
80
+ client_hash = calculate_file_hash(args.filepath)
81
+ console.print(f" [cyan]- Hash:[/] {client_hash}")
82
+
83
+ # --- Prepare Upload ---
84
+ upload_url = f"{args.url.rstrip('/')}/upload"
85
+ filename = os.path.basename(args.filepath)
86
+ file_size = os.path.getsize(args.filepath)
87
+
88
+ fields = {
89
+ 'hours': str(hours),
90
+ 'one_time': str(args.one_time).lower(),
91
+ 'client_hash': client_hash,
92
+ 'file': (filename, open(args.filepath, 'rb'), 'application/octet-stream')
93
+ }
94
+ if args.password:
95
+ fields['password'] = args.password
96
+
97
+ encoder = MultipartEncoder(fields=fields)
98
+ response = None
99
+
100
+ try:
101
+ bar_format = "{desc}: {percentage:3.0f}%|{bar}| {n_fmt}/{total_fmt} [Speed: {rate_fmt}, ETA: {remaining}]"
102
+ with tqdm(total=encoder.len, unit='B', unit_scale=True, desc=f"Uploading {filename}", bar_format=bar_format) as pbar:
103
+ monitor = MultipartEncoderMonitor(encoder, lambda m: pbar.update(m.bytes_read - pbar.n))
104
+ response = requests.post(upload_url, data=monitor, headers={'Content-Type': monitor.content_type})
105
+
106
+ except FileNotFoundError:
107
+ console.print(f"[bold red]Error:[/] The file '{args.filepath}' was not found.")
108
+ sys.exit(1)
109
+ except requests.exceptions.RequestException as e:
110
+ console.print("\n[bold red]An error occurred while connecting to the server:[/]")
111
+ console.print(e)
112
+ sys.exit(1)
113
+ except Exception as e:
114
+ console.print(f"\n[bold red]An unexpected error occurred:[/] {e}")
115
+ sys.exit(1)
116
+ finally:
117
+ # Ensure the file handle is closed
118
+ if 'file' in fields and not fields['file'][1].closed:
119
+ fields['file'][1].close()
120
+
121
+ # --- Handle Response ---
122
+ if response is not None:
123
+ if response.status_code == 200:
124
+ console.print("\n[bold green]Upload successful![/]")
125
+ console.print(Panel(response.text.strip(), title="[bold cyan]Download Link[/]", border_style="green"))
126
+ else:
127
+ console.print(f"\n[bold red]Error:[/] Upload failed with status code {response.status_code}")
128
+ try:
129
+ error_details = response.json()
130
+ console.print(f"[red]Server message:[/] {error_details.get('detail', 'No details provided.')}")
131
+ except requests.exceptions.JSONDecodeError:
132
+ console.print(f"[red]Server response:\n[/]{response.text}")
133
+ sys.exit(1)
134
+
135
+ if __name__ == "__main__":
136
+ multiprocessing.freeze_support()
137
+ main()
@@ -0,0 +1,152 @@
1
+ Metadata-Version: 2.4
2
+ Name: tempspace-cli
3
+ Version: 1.0.0
4
+ Summary: A command-line tool for uploading files to Tempspace.
5
+ Author-email: Tempspace <tempspace@example.com>
6
+ License: MIT License
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Requires-Python: >=3.7
10
+ Description-Content-Type: text/markdown
11
+ Requires-Dist: requests==2.31.0
12
+ Requires-Dist: tqdm==4.66.1
13
+ Requires-Dist: requests-toolbelt==1.0.0
14
+ Requires-Dist: rich==13.7.1
15
+
16
+ # 🚀 FileShare - Enhanced Terminal File Upload Service
17
+
18
+ A modern, terminal-style file sharing service with password protection, rate limiting, and QR code generation.
19
+
20
+ ## 📦 Installation
21
+
22
+ ### Server
23
+
24
+ To run the web server, you can clone the repository and run it locally.
25
+
26
+ ```bash
27
+ # Clone the repository
28
+ git clone <your-repo>
29
+ cd fileshare
30
+
31
+ # Install dependencies
32
+ pip install -r requirements.txt
33
+
34
+ # Copy environment template
35
+ cp .env.example .env
36
+
37
+ # Edit .env and change admin credentials!
38
+ nano .env
39
+
40
+ # Run the server
41
+ python main.py
42
+ ```
43
+
44
+ ### Command-Line Tool (CLI)
45
+
46
+ To use the command-line tool, you can install it directly from PyPI.
47
+
48
+ ```bash
49
+ pip install tempspace-cli
50
+ ```
51
+
52
+ ## ✨ Features
53
+
54
+ ### 🔒 Security
55
+ - **Rate Limiting**: 10 uploads/hour, 100 downloads/hour per IP
56
+ - **Password Protection**: Optional password-protected uploads
57
+ - **Secure Admin Panel**: HTTP Basic Auth for debug endpoints
58
+ - **File Deduplication**: Automatic duplicate detection (SHA256)
59
+ - **One-Time Downloads**: Self-destructing links after first download
60
+
61
+ ### 🎨 UI/UX
62
+ - **Modern Terminal Design**: Green-on-black terminal aesthetic
63
+ - **Drag & Drop**: Intuitive file upload interface
64
+ - **QR Code Generation**: Instant QR codes for mobile sharing
65
+ - **Upload History**: Local storage of recent uploads (browser)
66
+ - **Toast Notifications**: Non-intrusive feedback system
67
+ - **Real-time Progress**: Upload progress with speed indicators
68
+ - **Countdown Timer**: Shows time remaining until expiry
69
+ - **Responsive Design**: Works on mobile, tablet, and desktop
70
+
71
+ ### 📦 File Management
72
+ - **Large File Support**: Up to 4GB per file
73
+ - **Image Previews**: Automatic preview for images
74
+ - **Multiple Expiry Options**: 1, 3, 6, 12, or 24 hours
75
+ - **Chunked Uploads**: Efficient streaming for large files
76
+ - **Automatic Cleanup**: Background task removes expired files
77
+
78
+ ## 📖 Usage
79
+
80
+ ### Web Interface
81
+
82
+ 1. **Open** `http://localhost:8000` in your browser
83
+ 2. **Drag & drop** a file or click to browse
84
+ 3. **Configure** expiry time and optional password
85
+ 4. **Upload** and share the generated link
86
+ 5. **Scan QR code** for mobile access
87
+
88
+ ### CLI Usage
89
+
90
+ Once installed, you can use the `tempspace` command.
91
+
92
+ #### Basic Upload
93
+ ```bash
94
+ tempspace /path/to/document.pdf -t 6h
95
+ ```
96
+
97
+ #### Password Protected Upload
98
+ ```bash
99
+ tempspace /path/to/secret.txt -t 12h -p "mypassword"
100
+ ```
101
+
102
+ #### One-Time Download
103
+ ```bash
104
+ tempspace /path/to/report.pdf --one-time
105
+ ```
106
+
107
+ ## 🔧 Configuration
108
+
109
+ ### Environment Variables
110
+
111
+ Create a `.env` file for the server:
112
+
113
+ ```bash
114
+ # Admin credentials (CHANGE THESE!)
115
+ ADMIN_USER=admin
116
+ ADMIN_PASS=your-secure-password-here
117
+
118
+ # Optional: Custom limits
119
+ RATE_LIMIT_UPLOADS=10
120
+ RATE_LIMIT_DOWNLOADS=100
121
+ ```
122
+
123
+ ## 🛡️ Admin Endpoints
124
+
125
+ Protected by HTTP Basic Auth (use credentials from `.env`).
126
+
127
+ ### View Statistics
128
+ ```bash
129
+ curl -u admin:password http://localhost:8000/debug/stats
130
+ ```
131
+
132
+ ### Wipe All Files
133
+ ```bash
134
+ curl -X POST -u admin:password http://localhost:8000/debug/wipe
135
+ ```
136
+
137
+ ⚠️ **Warning**: This deletes ALL uploaded files permanently!
138
+
139
+ ## 📝 License
140
+
141
+ MIT License - Feel free to use and modify!
142
+
143
+ ## 🤝 Contributing
144
+
145
+ Contributions welcome! Please:
146
+ 1. Fork the repository
147
+ 2. Create a feature branch
148
+ 3. Submit a pull request
149
+
150
+ ## 📧 Support
151
+
152
+ For issues and questions, please open a GitHub issue.
@@ -0,0 +1,7 @@
1
+ cli/__init__.py,sha256=J-j-u0itpEFT6irdmWmixQqYMadNl1X91TxUmoiLHMI,22
2
+ cli/tempspace.py,sha256=3pu-xLDhzWoYxxrthzUM5lyCnTES0V7wzveVZY6gNow,5443
3
+ tempspace_cli-1.0.0.dist-info/METADATA,sha256=IZ-40lW57UaEJw9N71K9DWaU65WXMYRq8WNbYrmJyD4,3754
4
+ tempspace_cli-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
5
+ tempspace_cli-1.0.0.dist-info/entry_points.txt,sha256=DBBYsRS-fK4MSA3-4lrSPyi6oyHxoJLCII7c793nPtw,49
6
+ tempspace_cli-1.0.0.dist-info/top_level.txt,sha256=2ImG917oaVHlm0nP9oJE-Qrgs-fq_fGWgba2H1f8fpE,4
7
+ tempspace_cli-1.0.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (80.9.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ tempspace = cli.tempspace:main
@@ -0,0 +1 @@
1
+ cli