commit 42f1d1012f556f767375fdb37c7ec9b475a8e662 Author: piecka Date: Fri Mar 21 11:19:20 2025 +0100 batman diff --git a/app/__init__.py b/app/__init__.py new file mode 100644 index 0000000..56c48f2 --- /dev/null +++ b/app/__init__.py @@ -0,0 +1,22 @@ +from flask import Flask +import os +from app.config import Config + +def create_app(config_class=Config): + app = Flask(__name__) + app.config.from_object(config_class) + + # Ensure upload directory exists + os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True) + + # Create empty URI map file if it doesn't exist + uri_map_path = os.path.join(app.config['UPLOAD_FOLDER'], 'uri_map.json') + if not os.path.exists(uri_map_path): + with open(uri_map_path, 'w') as f: + f.write('{}') + + # Register blueprints + from app.routes.main import main_bp + app.register_blueprint(main_bp) + + return app diff --git a/app/__pycache__/__init__.cpython-312.pyc b/app/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..91f9189 Binary files /dev/null and b/app/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/__pycache__/config.cpython-312.pyc b/app/__pycache__/config.cpython-312.pyc new file mode 100644 index 0000000..ab37d0f Binary files /dev/null and b/app/__pycache__/config.cpython-312.pyc differ diff --git a/app/config.py b/app/config.py new file mode 100644 index 0000000..a99b055 --- /dev/null +++ b/app/config.py @@ -0,0 +1,7 @@ +import os + +class Config: + SECRET_KEY = os.environ.get('SECRET_KEY', 'dev-key-please-change') + UPLOAD_FOLDER = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'uploads') + DEBUG = True + MAX_CONTENT_LENGTH = 16 * 1024 * 1024 diff --git a/app/routes/__init__.py b/app/routes/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/routes/__pycache__/__init__.cpython-312.pyc b/app/routes/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..eaef9c7 Binary files /dev/null and b/app/routes/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/routes/__pycache__/main.cpython-312.pyc b/app/routes/__pycache__/main.cpython-312.pyc new file mode 100644 index 0000000..6e44ff9 Binary files /dev/null and b/app/routes/__pycache__/main.cpython-312.pyc differ diff --git a/app/routes/main.py b/app/routes/main.py new file mode 100644 index 0000000..0724820 --- /dev/null +++ b/app/routes/main.py @@ -0,0 +1,47 @@ +from flask import Blueprint, render_template, request, current_app, redirect, url_for, abort, flash +import os +from app.utils.file_handler import save_file, read_markdown_file, get_file_by_uri, load_uri_map + +main_bp = Blueprint('main', __name__) + +@main_bp.route('/', methods=['GET']) +def index(): + # List all available documents + uri_map = load_uri_map() + documents = [{'uri': uri, 'filename': info['filename']} for uri, info in uri_map.items()] + return render_template('index.html', documents=documents) + +@main_bp.route('/upload', methods=['GET', 'POST']) +def upload_file(): + if request.method == 'POST': + if 'file' not in request.files: + flash('No file part') + return redirect(request.url) + + file = request.files['file'] + + if file.filename == '': + flash('No file selected') + return redirect(request.url) + + if file and file.filename.endswith('.md'): + custom_uri = request.form.get('custom_uri', '').strip() + uri, filename = save_file(file, custom_uri if custom_uri else None) + return redirect(url_for('main.view_file', uri=uri)) + else: + flash('Only markdown files are allowed') + + return render_template('upload.html') + +@main_bp.route('/view/') +def view_file(uri): + file_info = get_file_by_uri(uri) + + if not file_info: + abort(404) + + html_content = read_markdown_file(file_info['path']) + return render_template('viewer.html', + filename=file_info['filename'], + content=html_content, + uri=uri) diff --git a/app/templates/index.html b/app/templates/index.html new file mode 100644 index 0000000..804407a --- /dev/null +++ b/app/templates/index.html @@ -0,0 +1,91 @@ + + + + Markdown Viewer + + + + +

Markdown Viewer

+ + + + {% if documents %} +
+

Available Documents

+ + {% for doc in documents %} +
+
+ + {{ doc.filename }} + + URI: {{ doc.uri }} +
+
+ View + +
+
+ {% endfor %} +
+ {% else %} +
+

No documents available

+

Upload a markdown file to get started!

+ Upload Now +
+ {% endif %} + + + + diff --git a/app/templates/upload.html b/app/templates/upload.html new file mode 100644 index 0000000..a7a9266 --- /dev/null +++ b/app/templates/upload.html @@ -0,0 +1,39 @@ + + + + Upload Markdown File + + + +

Upload Markdown File

+ + {% with messages = get_flashed_messages() %} + {% if messages %} +
+ {% for message in messages %} +

{{ message }}

+ {% endfor %} +
+ {% endif %} + {% endwith %} + +
+
+ + +
+ +
+ + + Leave blank for an auto-generated URI +
+ +
+ +
+
+ + Back to Home + + diff --git a/app/templates/viewer.html b/app/templates/viewer.html new file mode 100644 index 0000000..e27ab93 --- /dev/null +++ b/app/templates/viewer.html @@ -0,0 +1,69 @@ + + + + {{ filename }} - Markdown Viewer + + + + + + +
+

{{ filename }}

+

+ Permanent Link: + {{ url_for('main.view_file', uri=uri, _external=True) }} +

+
+ +
+ {{ content|safe }} +
+ + + + diff --git a/app/utils/__init__.py b/app/utils/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/app/utils/__pycache__/__init__.cpython-312.pyc b/app/utils/__pycache__/__init__.cpython-312.pyc new file mode 100644 index 0000000..2fc94db Binary files /dev/null and b/app/utils/__pycache__/__init__.cpython-312.pyc differ diff --git a/app/utils/__pycache__/file_handler.cpython-312.pyc b/app/utils/__pycache__/file_handler.cpython-312.pyc new file mode 100644 index 0000000..6579894 Binary files /dev/null and b/app/utils/__pycache__/file_handler.cpython-312.pyc differ diff --git a/app/utils/file_handler.py b/app/utils/file_handler.py new file mode 100644 index 0000000..aa0817f --- /dev/null +++ b/app/utils/file_handler.py @@ -0,0 +1,67 @@ +import os +import markdown +import secrets +from flask import current_app +from werkzeug.utils import secure_filename +import json + +def get_uri_map_path(): + """Get the path to the URI mapping file""" + return os.path.join(current_app.config['UPLOAD_FOLDER'], 'uri_map.json') + +def load_uri_map(): + """Load the URI mapping from file""" + map_path = get_uri_map_path() + if os.path.exists(map_path): + with open(map_path, 'r') as f: + return json.load(f) + return {} + +def save_uri_map(uri_map): + """Save the URI mapping to file""" + with open(get_uri_map_path(), 'w') as f: + json.dump(uri_map, f, indent=2) + +def generate_unique_uri(): + """Generate a unique URI for a file""" + uri_map = load_uri_map() + while True: + uri = secrets.token_urlsafe(6) # Generate a short random string + if uri not in uri_map: + return uri + +def save_file(file, custom_uri=None): + """Save the uploaded file to the upload folder and assign a URI""" + # Secure the filename first + filename = secure_filename(file.filename) + + # Generate or use custom URI + uri = custom_uri if custom_uri else generate_unique_uri() + + # Save the file with its original name + filepath = os.path.join(current_app.config['UPLOAD_FOLDER'], filename) + file.save(filepath) + + # Update the URI map + uri_map = load_uri_map() + uri_map[uri] = { + 'filename': filename, + 'path': filepath + } + save_uri_map(uri_map) + + return uri, filename + +def get_file_by_uri(uri): + """Get file info by URI""" + uri_map = load_uri_map() + if uri in uri_map: + return uri_map[uri] + return None + +def read_markdown_file(filepath): + """Read and convert markdown file to HTML""" + with open(filepath, 'r', encoding='utf-8') as f: + md_content = f.read() + html_content = markdown.markdown(md_content, extensions=['tables', 'fenced_code']) + return html_content diff --git a/run.py b/run.py new file mode 100644 index 0000000..d1899a4 --- /dev/null +++ b/run.py @@ -0,0 +1,7 @@ +from app import create_app + +app = create_app() + +if __name__ == '__main__': + app.run(debug=True) + diff --git a/uploads/docker.md b/uploads/docker.md new file mode 100644 index 0000000..27ce45c --- /dev/null +++ b/uploads/docker.md @@ -0,0 +1,44 @@ +# Nice containers for beginners + +#### **Quellen** + +- [selfh.st](https://selfh.st/apps/) <- viele opensource projekte (einige davon dockerized) + +## **Reverseproxies:** + +> Hier wird zumindest einer benötigt, um SSL-Verschlüsselung und HTTPS auf den Websites zu aktivieren +> Caddy ist zwar an sich einfacher, weil es nur eine einzige config datei hat, aber zum lernen würde ich den +> nginxproxymanager empfehlen, da er eine kleine webui hat und man das konzept so gut lernen und verstehen kann + +- [Nginx Reverseproxy-Manager](https://nginxproxymanager.com/guide/) +- [Caddy](https://hub.docker.com/_/caddy/) + +## **Dashboards:** + +> Pick whatever you like. Homepage wird in einer config datei (yml) konfiguriert. Daher würde ich Dashy oder Flame +> eher für den Anfang empfehlen + +- [Dashy](https://github.com/Lissy93/dashy) +- [Flame](https://github.com/pawelmalak/flame) +- [Homepage](https://gethomepage.dev/) + +## **Document-Management:** + +> filebrowser und mydrive sind zwei sehr einfache file share services, die mit einer schönen kleinen weboberfläche kommen +> Nextcloud ist etwas mächtiger, zwar auch deutlich hübscher und mit Android/iOS app etc. Aber eben auch etwas komplexer. Ist aber machbar. +> PaperlessNGX ist ein Dokumentenspeichersystem, hauptsächlich für pdf dateien. Ich lasse mir dort täglich und regelmäßig aus meinen +> Mailpostfächern die .pdf dateien die als Rechnung deklariert sind automatisch in mein system einspielen. Automatisierungstechnisch ein Traum! + +- [filebrowser](https://github.com/hurlenko/filebrowser-docker) +- [my-drive](https://github.com/subnub/myDrive) +- [nextcloud](https://hub.docker.com/_/nextcloud) +- [PaperlessNGX](https://docs.paperless-ngx.com/setup/#docker) +- [Immich](https://immich.app/docs/install/docker-compose) <- google photos clone, für zuhause! (Bessere Suchfunktion, Personenerkennung, Geodaten auf einer Map...) + +## **Sonstige** + +- [Bitwarden](https://github.com/dani-garcia/vaultwarden) <- das ist vaultwarden. Bitwarden + ohne zu Zahlen ^^ + +- [Excalidraw](https://hub.docker.com/r/excalidraw/excalidraw) +- [PDF-Tools](https://github.com/Stirling-Tools/Stirling-PDF) +- [IT-Tools](https://github.com/CorentinTh/it-tools) diff --git a/uploads/uri_map.json b/uploads/uri_map.json new file mode 100644 index 0000000..0283a4c --- /dev/null +++ b/uploads/uri_map.json @@ -0,0 +1,6 @@ +{ + "docker": { + "filename": "docker.md", + "path": "/home/pika/projects/flask/markdownViewer/uploads/docker.md" + } +} \ No newline at end of file