1
0
forked from spitkov/sxbin

added download all to folder view which zips then downloads refactored the whole sotring mechanisms now it stores it in a db NOT IN A FUCKING HTML FILE THATS LIKE SO OPTIMAL also you can add /raw to any text and get it raw uwu :3 major refactor :333

This commit is contained in:
spitkov 2024-09-09 21:23:37 +02:00
parent 25c0f89486
commit c1201dd7a6
6 changed files with 207 additions and 70 deletions

BIN
.DS_Store vendored Normal file

Binary file not shown.

191
app.py
View File

@ -4,15 +4,73 @@ import shortuuid
import os import os
from datetime import datetime from datetime import datetime
import zipfile import zipfile
import sqlite3
import threading
import time
import shutil
from datetime import timedelta
app = Flask(__name__) app = Flask(__name__)
UPLOAD_FOLDER = './uploads' UPLOAD_FOLDER = './uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
DATABASE = 'data.db'
if not os.path.exists(UPLOAD_FOLDER): if not os.path.exists(UPLOAD_FOLDER):
os.makedirs(UPLOAD_FOLDER) os.makedirs(UPLOAD_FOLDER)
data_store = {} # Database setup and helper functions
def get_db():
db = getattr(threading.current_thread(), '_database', None)
if db is None:
db = threading.current_thread()._database = sqlite3.connect(DATABASE)
return db
def init_db():
with app.app_context():
db = get_db()
with app.open_resource('schema.sql', mode='r') as f:
db.cursor().executescript(f.read())
db.commit()
@app.teardown_appcontext
def close_connection(exception):
db = getattr(threading.current_thread(), '_database', None)
if db is not None:
db.close()
# Initialize database
init_db()
# Add this function to delete old files
def delete_old_files():
while True:
db = get_db()
cursor = db.cursor()
# Delete files older than 30 days
thirty_days_ago = datetime.now() - timedelta(days=30)
cursor.execute("SELECT vanity, type, data FROM content WHERE created_at < ?", (thirty_days_ago,))
old_files = cursor.fetchall()
for vanity, content_type, data in old_files:
if content_type == 'file':
file_path = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}_{data}')
if os.path.exists(file_path):
os.remove(file_path)
elif content_type == 'folder':
folder_path = os.path.join(app.config['UPLOAD_FOLDER'], vanity)
if os.path.exists(folder_path):
shutil.rmtree(folder_path)
cursor.execute("DELETE FROM content WHERE created_at < ?", (thirty_days_ago,))
db.commit()
time.sleep(86400) # Sleep for 24 hours
# Start the cleanup thread
cleanup_thread = threading.Thread(target=delete_old_files)
cleanup_thread.daemon = True
cleanup_thread.start()
@app.route('/') @app.route('/')
def index(): def index():
@ -20,28 +78,36 @@ def index():
@app.route('/content/<vanity>') @app.route('/content/<vanity>')
def content(vanity): def content(vanity):
target = data_store.get(vanity) db = get_db()
cursor = db.cursor()
cursor.execute("SELECT * FROM content WHERE vanity = ?", (vanity,))
target = cursor.fetchone()
if target: if target:
if target['type'] == 'pastebin': content_type, content_data = target[1], target[2]
return render_template('content.html', content=target['content'], created_at=target['created_at']) if content_type == 'pastebin':
elif target['type'] == 'file': return render_template('content.html', content=content_data, created_at=target[3])
file_path = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}_{target["filename"]}') elif content_type == 'file':
file_path = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}_{content_data}')
file_info = { file_info = {
'name': target['filename'], 'name': content_data,
'size': os.path.getsize(file_path), 'size': os.path.getsize(file_path),
'modified_at': datetime.fromtimestamp(os.path.getmtime(file_path)).strftime('%Y-%m-%d %H:%M:%S'), 'modified_at': datetime.fromtimestamp(os.path.getmtime(file_path)).strftime('%Y-%m-%d %H:%M:%S'),
'url': url_for('download_file', vanity=vanity) 'url': url_for('download_file', vanity=vanity)
} }
return render_template('file.html', **file_info) return render_template('file.html', **file_info)
elif target['type'] == 'url': elif content_type == 'url':
return render_template('content.html', url=target['url']) return render_template('content.html', url=content_data)
return 'Not Found', 404 return 'Not Found', 404
@app.route('/download/<vanity>', methods=['GET']) @app.route('/download/<vanity>', methods=['GET'])
def download_file(vanity): def download_file(vanity):
target = data_store.get(vanity) db = get_db()
if target and target['type'] == 'file': cursor = db.cursor()
filename = f'{vanity}_{target["filename"]}' cursor.execute("SELECT * FROM content WHERE vanity = ? AND type = 'file'", (vanity,))
target = cursor.fetchone()
if target:
filename = f'{vanity}_{target[2]}'
return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True) return send_from_directory(app.config['UPLOAD_FOLDER'], filename, as_attachment=True)
return 'Not Found', 404 return 'Not Found', 404
@ -50,12 +116,12 @@ def upload_pastebin():
content = request.form['content'] content = request.form['content']
vanity = shortuuid.uuid()[:6] vanity = shortuuid.uuid()[:6]
created_at = datetime.now().strftime('%Y-%m-%d %H:%M:%S') created_at = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
data_store[vanity] = {'type': 'pastebin', 'content': content, 'created_at': created_at}
html_content = render_template('content.html', content=content, created_at=created_at) db = get_db()
html_file_path = os.path.join('templates', f'{vanity}.html') cursor = db.cursor()
with open(html_file_path, 'w') as f: cursor.execute("INSERT INTO content (vanity, type, data, created_at) VALUES (?, ?, ?, ?)",
f.write(html_content) (vanity, 'pastebin', content, created_at))
db.commit()
return jsonify({'vanity': vanity}) return jsonify({'vanity': vanity})
@ -71,18 +137,12 @@ def upload_file():
filename = secure_filename(file.filename) filename = secure_filename(file.filename)
filepath = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}_{filename}') filepath = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}_{filename}')
file.save(filepath) file.save(filepath)
data_store[vanity] = {'type': 'file', 'filename': filename}
file_info = { db = get_db()
'name': filename, cursor = db.cursor()
'size': os.path.getsize(filepath), cursor.execute("INSERT INTO content (vanity, type, data) VALUES (?, ?, ?)",
'modified_at': datetime.fromtimestamp(os.path.getmtime(filepath)).strftime('%Y-%m-%d %H:%M:%S'), (vanity, 'file', filename))
'url': url_for('download_file', vanity=vanity) db.commit()
}
html_content = render_template('file.html', **file_info)
html_file_path = os.path.join('templates', f'{vanity}.html')
with open(html_file_path, 'w') as f:
f.write(html_content)
return jsonify({'vanity': vanity}) return jsonify({'vanity': vanity})
@ -115,7 +175,11 @@ def upload_folder():
handle_uploaded_folder(files, folder_path) handle_uploaded_folder(files, folder_path)
data_store[vanity] = {'type': 'folder', 'files': [file.filename for file in files]} db = get_db()
cursor = db.cursor()
cursor.execute("INSERT INTO content (vanity, type, data) VALUES (?, ?, ?)",
(vanity, 'folder', ','.join([file.filename for file in files])))
db.commit()
return jsonify({'vanity': vanity}) return jsonify({'vanity': vanity})
@ -123,51 +187,59 @@ def upload_folder():
def shorten_url(): def shorten_url():
original_url = request.form['url'] original_url = request.form['url']
vanity = shortuuid.uuid()[:6] vanity = shortuuid.uuid()[:6]
data_store[vanity] = {'type': 'url', 'url': original_url}
html_content = f'<html><body><script>window.location.href="{original_url}";</script></body></html>' db = get_db()
html_file_path = os.path.join('templates', f'{vanity}.html') cursor = db.cursor()
with open(html_file_path, 'w') as f: cursor.execute("INSERT INTO content (vanity, type, data) VALUES (?, ?, ?)",
f.write(html_content) (vanity, 'url', original_url))
db.commit()
return jsonify({'vanity': vanity}) return jsonify({'vanity': vanity})
@app.route('/<vanity>', methods=['GET']) @app.route('/<vanity>', methods=['GET'])
def redirect_vanity(vanity): def redirect_vanity(vanity):
target = data_store.get(vanity) db = get_db()
cursor = db.cursor()
cursor.execute("SELECT * FROM content WHERE vanity = ?", (vanity,))
target = cursor.fetchone()
if target: if target:
if target['type'] == 'pastebin': content_type, content_data = target[1], target[2]
return render_template(f'{vanity}.html') if content_type == 'pastebin':
elif target['type'] == 'file': return render_template('content.html', content=content_data, created_at=target[3])
file_path = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}_{target["filename"]}') elif content_type == 'file':
file_path = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}_{content_data}')
file_info = { file_info = {
'name': target['filename'], 'name': content_data,
'size': os.path.getsize(file_path), 'size': os.path.getsize(file_path),
'modified_at': datetime.fromtimestamp(os.path.getmtime(file_path)).strftime('%Y-%m-%d %H:%M:%S'), 'modified_at': datetime.fromtimestamp(os.path.getmtime(file_path)).strftime('%Y-%m-%d %H:%M:%S'),
'url': url_for('download_file', vanity=vanity) 'url': url_for('download_file', vanity=vanity)
} }
return render_template('file.html', **file_info) return render_template('file.html', **file_info)
elif target['type'] == 'folder': elif content_type == 'folder':
return redirect(url_for('folder_content', vanity=vanity)) return redirect(url_for('folder_content', vanity=vanity))
elif target['type'] == 'url': elif content_type == 'url':
return render_template('content.html', url=target['url']) return render_template('content.html', url=content_data)
return render_template('404.html'), 404 return render_template('404.html'), 404
@app.route('/<vanity>/raw', methods=['GET']) @app.route('/<vanity>/raw', methods=['GET'])
def raw_vanity(vanity): def raw_vanity(vanity):
target = data_store.get(vanity) db = get_db()
cursor = db.cursor()
cursor.execute("SELECT * FROM content WHERE vanity = ? AND type = 'pastebin'", (vanity,))
target = cursor.fetchone()
if target: if target:
if target['type'] == 'pastebin': return target[2], 200, {'Content-Type': 'text/plain; charset=utf-8'}
return render_template(f'{vanity}raw.html') return 'Not Found', 404
return render_template('404.html'), 404
@app.route('/folder/<vanity>', methods=['GET']) @app.route('/folder/<vanity>', methods=['GET'])
def folder_content(vanity): def folder_content(vanity):
target = data_store.get(vanity) db = get_db()
if target and target['type'] == 'folder': cursor = db.cursor()
cursor.execute("SELECT * FROM content WHERE vanity = ? AND type = 'folder'", (vanity,))
target = cursor.fetchone()
if target:
folder_path = os.path.join(app.config['UPLOAD_FOLDER'], vanity) folder_path = os.path.join(app.config['UPLOAD_FOLDER'], vanity)
files = [] files = []
for root, _, filenames in os.walk(folder_path): for root, _, filenames in os.walk(folder_path):
@ -188,14 +260,27 @@ def folder_content(vanity):
prev_url = url_for('folder_content', vanity=vanity, page=page-1) if page > 1 else None prev_url = url_for('folder_content', vanity=vanity, page=page-1) if page > 1 else None
next_url = url_for('folder_content', vanity=vanity, page=page+1) if end < total_files else None next_url = url_for('folder_content', vanity=vanity, page=page+1) if end < total_files else None
return render_template('folder.html', files=files, prev_url=prev_url, next_url=next_url) download_all_url = url_for('download_folder_as_zip', vanity=vanity)
# Get the current folder name
current_folder = os.path.basename(folder_path)
return render_template('folder.html',
files=files,
prev_url=prev_url,
next_url=next_url,
download_all_url=download_all_url,
current_folder=current_folder)
return 'Not Found', 404 return 'Not Found', 404
@app.route('/folder/<vanity>/download', methods=['GET']) @app.route('/folder/<vanity>/download', methods=['GET'])
def download_folder_as_zip(vanity): def download_folder_as_zip(vanity):
target = data_store.get(vanity) db = get_db()
if target and target['type'] == 'folder': cursor = db.cursor()
cursor.execute("SELECT * FROM content WHERE vanity = ? AND type = 'folder'", (vanity,))
target = cursor.fetchone()
if target:
folder_path = os.path.join(app.config['UPLOAD_FOLDER'], vanity) folder_path = os.path.join(app.config['UPLOAD_FOLDER'], vanity)
zip_path = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}.zip') zip_path = os.path.join(app.config['UPLOAD_FOLDER'], f'{vanity}.zip')

6
schema.sql Normal file
View File

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS content (
vanity TEXT PRIMARY KEY,
type TEXT NOT NULL,
data TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);

View File

@ -3,37 +3,43 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Folder</title> <title>Folder Contents</title>
<style> <style>
body { body {
font-family: Arial, sans-serif; font-family: Arial, sans-serif;
background-color: #121212; background-color: #121212;
color: #e0e0e0; color: #e0e0e0;
margin: 0; margin: 0;
padding: 0; padding: 20px;
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
} }
.container { .container {
background: #1e1e1e; background: #1e1e1e;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3); box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
padding: 20px; padding: 20px;
width: 400px; max-width: 800px;
text-align: center; margin: 0 auto;
} }
h1 { h1 {
margin-bottom: 20px; margin-bottom: 20px;
color: #f5f5f5; color: #f5f5f5;
text-align: center;
} }
ul { .folder-structure {
background: #2a2a2a;
border-radius: 4px;
padding: 10px;
margin-bottom: 20px;
}
.file-list {
list-style-type: none; list-style-type: none;
padding: 0; padding: 0;
} }
li { .file-list li {
margin: 10px 0; margin: 10px 0;
padding: 5px;
background: #333;
border-radius: 4px;
} }
a { a {
color: #61afef; color: #61afef;
@ -42,16 +48,56 @@
a:hover { a:hover {
text-decoration: underline; text-decoration: underline;
} }
.download-all-btn {
display: block;
width: 200px;
margin: 20px auto;
padding: 10px;
background-color: #4CAF50;
color: white;
text-align: center;
text-decoration: none;
border-radius: 5px;
font-weight: bold;
}
.download-all-btn:hover {
background-color: #45a049;
}
.pagination {
text-align: center;
margin-top: 20px;
}
.pagination a {
margin: 0 10px;
}
</style> </style>
</head> </head>
<body> <body>
<div class="container"> <div class="container">
<h1>Folder</h1> <h1>Folder Contents</h1>
<ul>
<div class="folder-structure">
<!-- You can add a tree-like structure here if needed -->
<p>Current folder: /{{ current_folder }}</p>
</div>
<ul class="file-list">
{% for file in files %} {% for file in files %}
<li><a href="{{ file.url }}">{{ file.name }}</a></li> <li><a href="{{ file.url }}">{{ file.name }}</a></li>
{% endfor %} {% endfor %}
</ul> </ul>
<a href="{{ download_all_url }}" class="download-all-btn">Download All</a>
<div class="pagination">
{% if prev_url %}
<a href="{{ prev_url }}">Previous</a>
{% endif %}
{% if next_url %}
<a href="{{ next_url }}">Next</a>
{% endif %}
</div>
</div> </div>
</body> </body>
</html> </html>

BIN
uploads/.DS_Store vendored Normal file

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB