Initial commit

This commit is contained in:
retoor 2024-11-26 04:34:46 +01:00
commit 3e72ecab20
18 changed files with 295 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
.history
.venv
src/upload/__pycache__

12
Makefile Normal file
View File

@ -0,0 +1,12 @@
all: ensure_env build serve
ensure_env:
-@python3 -m venv .venv
build:
./.venv/bin/python -m pip install build
./.venv/bin/python -m build .
./.venv/bin/python -m pip install -e .
serve:
./.venv/bin/rupload.serve

17
README.md Normal file
View File

@ -0,0 +1,17 @@
# RUpload
## About
Easiest way to upload files to a server.
Since it doesn't have captcha or whatsoever, it's only usable with people you trust on a not listed domain. It's destined for public use, as long the domain isn't listed in a search engine. It has a limitation for file size, so it would never go terribly wrong.
## Installation
```
python3 -m venv .venv
./venv/bin/python -m pip install .
```
## Usage
```
rupload.serve [host(127.0.0.1)] [port] [destination path for uploads] [max file size in bytes]
```

3
pyproject.toml Normal file
View File

@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools", "wheel"]
build-backend = "setuptools.build_meta"

25
setup.cfg Normal file
View File

@ -0,0 +1,25 @@
[metadata]
name = rupload
version = 1.3.37
description = upload tool
author = Retoor
author_email = retoor@molodetz.nl
license = MIT
long_description = file: README.md
long_description_content_type = text/markdown
[options]
packages = find:
package_dir =
= src
python_requires = >=3.7
install_requires =
aiohttp==3.10.10
dataset==1.6.2
[options.packages.find]
where = src
[options.entry_points]
console_scripts =
rupload.serve = rupload.cli:main

View File

@ -0,0 +1,29 @@
Metadata-Version: 2.1
Name: rupload
Version: 1.3.37
Summary: upload tool
Author: Retoor
Author-email: retoor@molodetz.nl
License: MIT
Requires-Python: >=3.7
Description-Content-Type: text/markdown
Requires-Dist: aiohttp==3.10.10
Requires-Dist: dataset==1.6.2
# RUpload
## About
Easiest way to upload files to a server.
Since it doesn't have captcha or whatsoever, it's only usable with people you trust on a not listed domain. It's destined for public use, as long the domain isn't listed in a search engine. It has a limitation for file size, so it would never go terribly wrong.
## Installation
```
python3 -m venv .venv
./venv/bin/python -m pip install .
```
## Usage
```
rupload.serve [host(127.0.0.1)] [port] [destination path for uploads] [max file size in bytes]
```

View File

@ -0,0 +1,13 @@
README.md
pyproject.toml
setup.cfg
src/rupload/__init__.py
src/rupload/__main__.py
src/rupload/app.py
src/rupload/cli.py
src/rupload.egg-info/PKG-INFO
src/rupload.egg-info/SOURCES.txt
src/rupload.egg-info/dependency_links.txt
src/rupload.egg-info/entry_points.txt
src/rupload.egg-info/requires.txt
src/rupload.egg-info/top_level.txt

View File

@ -0,0 +1 @@

View File

@ -0,0 +1,2 @@
[console_scripts]
rupload.serve = rupload.cli:main

View File

@ -0,0 +1,2 @@
aiohttp==3.10.10
dataset==1.6.2

View File

@ -0,0 +1 @@
rupload

0
src/rupload/__init__.py Normal file
View File

0
src/rupload/__main__.py Normal file
View File

Binary file not shown.

Binary file not shown.

Binary file not shown.

151
src/rupload/app.py Normal file
View File

@ -0,0 +1,151 @@
import aiohttp
from aiohttp import web
import asyncio
import pathlib
class Rupload(web.Application):
def __init__(self, upload_path, max_file_size):
self.upload_path = upload_path
self.max_file_size = max_file_size
super().__init__()
UPLOAD_FOLDER = "uploads"
pathlib.Path(UPLOAD_FOLDER).mkdir(parents=True, exist_ok=True)
UPLOAD_PAGE = """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>File Upload</title>
<style>
body {
font-family: Arial, sans-serif;
background-color: #f4f4f9;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
margin: 0;
}
.container {
background-color: #fff;
border-radius: 8px;
box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
padding: 20px;
text-align: center;
width: 100%;
max-width: 500px;
}
h1 {
font-size: 24px;
margin-bottom: 20px;
color: #333;
}
form {
display: flex;
flex-direction: column;
gap: 15px;
}
input[type="file"] {
padding: 10px;
border: 2px solid #ccc;
border-radius: 5px;
font-size: 16px;
}
button {
padding: 10px 20px;
background-color: #007bff;
color: white;
border: none;
border-radius: 5px;
font-size: 16px;
cursor: pointer;
transition: background-color 0.3s;
}
button:hover {
background-color: #0056b3;
}
.message {
margin-top: 20px;
font-size: 18px;
color: #333;
}
.footer {
margin-top: 30px;
font-size: 14px;
color: #777;
}
</style>
</head>
<body>
<div class="container">
<h1>Upload Your File</h1>
<form action="/upload" method="POST" enctype="multipart/form-data">
<label for="file">Choose a file to upload:</label>
<input type="file" name="file" id="file" required>
<button type="submit">Upload</button>
</form>
</div>
</body>
</html>
"""
async def handle_upload(request):
reader = await request.multipart()
field = await reader.next()
if field.name == "file":
filename = field.filename
print(filename)
if ".." or "/" in filename:
return web.Response(status=400, text="Invalid filename.")
filepath = pathlib.Path(UPLOAD_FOLDER).joinpath(filename)
if filepath.exists():
return web.Response(status=400, text="File already exists.")
with filepath.open("wb") as f:
file_size = 0
while True:
chunk = await field.read_chunk()
if not chunk:
break
file_size += len(chunk)
if file_size > max_file_size:
f.close()
f.unlink()
return web.Response(
status=413,
text="File is too large. Maximum file size is {} bytes.".format(
max_file_size
),
)
f.write(chunk)
return web.Response(text=f"File {filename} uploaded successfully!")
return web.Response(status=400, text="No file uploaded.")
async def handle_index(request):
return web.Response(text=UPLOAD_PAGE, content_type="text/html")
def create_app(upload_path="upload", max_file_size=1024 * 1024 * 50):
app = Rupload(upload_path=upload_path, max_file_size=max_file_size)
app.add_routes([web.get("/", handle_index), web.post("/upload", handle_upload)])
return app

36
src/rupload/cli.py Normal file
View File

@ -0,0 +1,36 @@
import argparse
from aiohttp import web
from rupload.app import create_app
def parse_args():
parser = argparse.ArgumentParser(description="Start the file upload server.")
parser.add_argument(
"--hostname", type=str, default="127.0.0.1", help="The hostname for the server."
)
parser.add_argument(
"--port", type=int, default=8081, help="The port to bind the server to."
)
parser.add_argument(
"--upload_folder",
type=str,
default="uploads",
help="Directory to store uploaded files.",
)
parser.add_argument(
"--max_file_size",
type=int,
default=50 * 1024 * 1024,
help="Maximum file size in bytes (default is 50MB).",
)
return parser.parse_args()
def main():
args = parse_args()
app = create_app(upload_path=args.upload_folder, max_file_size=args.max_file_size)
web.run_app(app, host=args.hostname, port=args.port)
if __name__ == "__main__":
main()