init
This commit is contained in:
commit
ef757eb224
26
.dockerignore
Normal file
26
.dockerignore
Normal file
@ -0,0 +1,26 @@
|
||||
__pycache__
|
||||
*.pyc
|
||||
*.pyo
|
||||
*.pyd
|
||||
.Python
|
||||
env/
|
||||
venv/
|
||||
.env
|
||||
.venv
|
||||
pip-log.txt
|
||||
pip-delete-this-directory.txt
|
||||
.tox/
|
||||
.coverage
|
||||
.coverage.*
|
||||
.cache
|
||||
nosetests.xml
|
||||
coverage.xml
|
||||
*.cover
|
||||
*.log
|
||||
.pytest_cache/
|
||||
.git
|
||||
.gitignore
|
||||
README.md
|
||||
Dockerfile
|
||||
docker-compose.yml
|
||||
test.py
|
44
.gitignore
vendored
Normal file
44
.gitignore
vendored
Normal file
@ -0,0 +1,44 @@
|
||||
# Python
|
||||
__pycache__/
|
||||
*.py[cod]
|
||||
*$py.class
|
||||
*.so
|
||||
.Python
|
||||
env/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
downloads/
|
||||
eggs/
|
||||
.eggs/
|
||||
lib/
|
||||
lib64/
|
||||
parts/
|
||||
sdist/
|
||||
var/
|
||||
wheels/
|
||||
*.egg-info/
|
||||
.installed.cfg
|
||||
*.egg
|
||||
test.py
|
||||
# Virtual Environment
|
||||
venv/
|
||||
ENV/
|
||||
.env
|
||||
.venv
|
||||
|
||||
# IDE
|
||||
.idea/
|
||||
.vscode/
|
||||
*.swp
|
||||
*.swo
|
||||
|
||||
# Docker
|
||||
.docker/
|
||||
|
||||
# Logs
|
||||
*.log
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
16
Dockerfile
Normal file
16
Dockerfile
Normal file
@ -0,0 +1,16 @@
|
||||
FROM python:3.11-slim
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY requirements.txt .
|
||||
RUN pip install --no-cache-dir -r requirements.txt
|
||||
|
||||
COPY . .
|
||||
|
||||
EXPOSE 5000
|
||||
|
||||
ENV FLASK_APP=app.py
|
||||
ENV FLASK_ENV=production
|
||||
ENV HOST=0.0.0.0
|
||||
|
||||
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app", "--workers", "4"]
|
234
app.py
Normal file
234
app.py
Normal file
@ -0,0 +1,234 @@
|
||||
import datetime
|
||||
from flask import Flask, jsonify
|
||||
from flask_cors import CORS
|
||||
import resend
|
||||
from flask import request
|
||||
|
||||
|
||||
app = Flask(__name__)
|
||||
CORS(app, resources={
|
||||
r"/*": {
|
||||
"origins": ["*"],
|
||||
"methods": ["GET", "POST", "OPTIONS"],
|
||||
"allow_headers": ["Content-Type"]
|
||||
}
|
||||
})
|
||||
|
||||
# from supabase import create_client, Client
|
||||
# SUPABASE_URL = "https://supabase-core.dev3vds1.link/"
|
||||
# SUPABASE_KEY = "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJpc3MiOiJzdXBhYmFzZSIsImlhdCI6MTc0NTk0MzYwMCwiZXhwIjo0OTAxNjE3MjAwLCJyb2xlIjoiYW5vbiJ9.28hFArcAFQ3mYTYL2n7nno4nHu5ZszkOO0dkAURR6Yg"
|
||||
# supabase: Client = create_client(SUPABASE_URL, SUPABASE_KEY)
|
||||
|
||||
resend.api_key = "re_XvLrRZMH_3mumWA531UugMk1X7A67fhH7"
|
||||
|
||||
|
||||
@app.route('/send_email', methods=['POST'])
|
||||
def send_email():
|
||||
try:
|
||||
data = request.get_json()
|
||||
email = data.get('email', 'with.reihan@gmail.com')
|
||||
if not email:
|
||||
return jsonify({'status': 'error', 'message': 'Email is required'}), 400
|
||||
# Check if the email is valid
|
||||
if not isinstance(email, str) or '@' not in email:
|
||||
return jsonify({'status': 'error', 'message': 'Invalid email format'}), 400
|
||||
|
||||
username = email.split('@')[0]
|
||||
date = str(datetime.datetime.now().date())
|
||||
product = data.get('product', 'NVIDIA-686')
|
||||
price_hour = data.get('price_hour', '2.00')
|
||||
price = data.get('price', '147.00')
|
||||
|
||||
html = f"""
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
||||
<title>VertexGPU Invoice</title>
|
||||
</head>
|
||||
<body
|
||||
style="
|
||||
margin: 0;
|
||||
padding: 20px;
|
||||
background-color: #0a0a0a;
|
||||
color: #ffffff;
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
line-height: 1.6;
|
||||
"
|
||||
>
|
||||
<div
|
||||
style="
|
||||
max-width: 800px;
|
||||
margin: 20px auto;
|
||||
background-color: rgba(10, 10, 10, 0.95);
|
||||
border: 1px solid rgba(12, 232, 126, 0.2);
|
||||
border-radius: 8px;
|
||||
padding: 25px;
|
||||
"
|
||||
>
|
||||
<!-- Header -->
|
||||
<header
|
||||
style="
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding-bottom: 20px;
|
||||
border-bottom: 2px solid rgba(12, 232, 126, 0.3);
|
||||
margin-bottom: 20px;
|
||||
"
|
||||
>
|
||||
<div style="font-size: 24px; font-weight: bold">Vertex<span style="color: #0ce87e">GPU</span></div>
|
||||
</header>
|
||||
|
||||
<!-- Invoice Details -->
|
||||
<div
|
||||
style="
|
||||
background-color: rgba(12, 232, 126, 0.05);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(12, 232, 126, 0.2);
|
||||
margin-bottom: 20px;
|
||||
"
|
||||
>
|
||||
<table style="width: 100%; border-collapse: collapse">
|
||||
<tr>
|
||||
<td style="padding: 8px 0"><span style="color: #808080">Date Issued:</span> {date}</td>
|
||||
<td style="padding: 8px 0">
|
||||
<span style="color: #808080">Client ID:</span>
|
||||
<span style="color: #0ce87e">VX-CLIENT-686</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 8px 0"><span style="color: #808080">User:</span> {username}</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- Invoice Items -->
|
||||
<table style="width: 100%; border-collapse: collapse; margin-bottom: 20px">
|
||||
<thead>
|
||||
<tr style="border-bottom: 1px solid rgba(12, 232, 126, 0.2)">
|
||||
<th style="text-align: left; padding: 12px 8px; color: #808080; font-weight: normal">
|
||||
Description
|
||||
</th>
|
||||
<th style="text-align: left; padding: 12px 8px; color: #808080; font-weight: normal">
|
||||
Duration
|
||||
</th>
|
||||
<th style="text-align: left; padding: 12px 8px; color: #808080; font-weight: normal">Rate</th>
|
||||
<th style="text-align: left; padding: 12px 8px; color: #808080; font-weight: normal">Amount</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr style="border-bottom: 1px solid rgba(12, 232, 126, 0.1)">
|
||||
<td style="padding: 12px 8px">{product}</td>
|
||||
<td style="padding: 12px 8px">30 Days</td>
|
||||
<td style="padding: 12px 8px">${price_hour}/hour</td>
|
||||
<td style="padding: 12px 8px; color: #0ce87e">${price}</td>
|
||||
</tr>
|
||||
<tr style="border-bottom: 1px solid rgba(12, 232, 126, 0.1)">
|
||||
<td style="padding: 12px 8px">Priority Support Package</td>
|
||||
<td style="padding: 12px 8px">1 Month</td>
|
||||
<td style="padding: 12px 8px">$00.00</td>
|
||||
<td style="padding: 12px 8px; color: #0ce87e">$00.00</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<!-- Totals -->
|
||||
<div
|
||||
style="
|
||||
background-color: rgba(12, 232, 126, 0.05);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(12, 232, 126, 0.2);
|
||||
margin-bottom: 20px;
|
||||
"
|
||||
>
|
||||
<table style="width: 100%; border-collapse: collapse">
|
||||
<tr>
|
||||
<td style="padding: 8px 0; color: #808080">Subtotal:</td>
|
||||
<td style="padding: 8px 0; text-align: right; color: #0ce87e">${price}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td style="padding: 8px 0; color: #808080">Network Fee:</td>
|
||||
<td style="padding: 8px 0; text-align: right">$0.00</td>
|
||||
</tr>
|
||||
<tr style="border-top: 1px solid rgba(12, 232, 126, 0.2)">
|
||||
<td style="padding: 8px 0; color: #808080; font-size: 18px">Total Due:</td>
|
||||
<td
|
||||
style="
|
||||
padding: 8px 0;
|
||||
text-align: right;
|
||||
color: #0ce87e;
|
||||
font-size: 18px;
|
||||
font-weight: bold;
|
||||
"
|
||||
>
|
||||
${price}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
<!-- GPU Status -->
|
||||
<div
|
||||
style="
|
||||
background-color: rgba(12, 232, 126, 0.05);
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
border: 1px solid rgba(12, 232, 126, 0.2);
|
||||
margin-bottom: 20px;
|
||||
"
|
||||
>
|
||||
<p style="color: #0ce87e; margin: 0 0 12px 0; font-weight: bold">GPU Status Update</p>
|
||||
<p style="margin: 0 0 12px 0">
|
||||
Your GPU instance is being initialized and will be ready for access within the next 2 hours. Once
|
||||
configuration is complete, we'll send your authentication credentials to your registered email
|
||||
address.
|
||||
</p>
|
||||
<p style="color: #808080; margin: 0">
|
||||
For any assistance, our support team is available 24/7. Thank you for choosing our service.
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<footer style="text-align: center; color: #808080; font-size: 14px">
|
||||
<p style="margin: 0 0 8px 0">
|
||||
Thank you for choosing VertexGPU for your high-performance computing needs!
|
||||
</p>
|
||||
<p style="margin: 0 0 8px 0">
|
||||
Visit us at
|
||||
<a href="https://vertexgpu.com" style="color: #0ce87e; text-decoration: none">vertexgpu.com</a>
|
||||
</p>
|
||||
<p style="margin: 0">
|
||||
Questions? Contact us at
|
||||
<a style="color: #0ce87e; text-decoration: none" href="mailto:support@vertexgpu.com"
|
||||
>support@vertexgpu.com</a
|
||||
>
|
||||
</p>
|
||||
</footer>
|
||||
</div>
|
||||
</body>
|
||||
</html>"""
|
||||
|
||||
# Send email using Resend
|
||||
params: resend.Emails.SendParams = {
|
||||
"from": "Vertex (no-reply) <purchase@vertexgpu.com>",
|
||||
"to": [email],
|
||||
"subject": "Thanks for purchasing our product!",
|
||||
"html": html,
|
||||
}
|
||||
|
||||
email = resend.Emails.send(params)
|
||||
print(email)
|
||||
return jsonify({'status': 'success', 'message': 'email sent'})
|
||||
except:
|
||||
return jsonify({'status': 'error', 'message': 'Failed to send email'}), 500
|
||||
|
||||
@app.route('/health')
|
||||
def health():
|
||||
return jsonify({'status': 'success', 'message': 'ok'})
|
||||
|
||||
if __name__ == '__main__':
|
||||
app.run(host='0.0.0.0', port=5000)
|
13
docker-compose.yml
Normal file
13
docker-compose.yml
Normal file
@ -0,0 +1,13 @@
|
||||
version: "3.8"
|
||||
|
||||
services:
|
||||
web:
|
||||
build: .
|
||||
ports:
|
||||
- "5001:5000"
|
||||
environment:
|
||||
- FLASK_APP=app.py
|
||||
- FLASK_ENV=development
|
||||
volumes:
|
||||
- .:/app
|
||||
restart: unless-stopped
|
BIN
requirements.txt
Normal file
BIN
requirements.txt
Normal file
Binary file not shown.
Loading…
x
Reference in New Issue
Block a user