File size: 6,124 Bytes
898ed62
0090d2e
898ed62
 
7ece4a1
898ed62
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
print("=============================================")
print("===   DÉMARRAGE DE MARKITDOWN WEBSERVER   ===")
print("=============================================")
"""
Serveur Flask pour MarkitDowne Local WebApp.

Routes API :
- GET  /          → Page principale
- POST /upload    → Upload et conversion d'un fichier
- GET  /history   → Liste de l'historique
- GET  /download/<id> → Téléchargement du .md
- POST /copy/<id> → Copie dans le presse-papier (retourne le texte)
- POST /clear-history → Vide l'historique
"""

import os
import uuid
import socket
from flask import (
    Flask,
    render_template,
    request,
    jsonify,
    send_file,
    after_this_request,
)

from converter import convert
from history import add_entry, get_all, get_entry, clear

app = Flask(__name__)

# 1 Go max (augmenté pour supporter de gros dossiers)
app.config["MAX_CONTENT_LENGTH"] = 1024 * 1024 * 1024

UPLOAD_FOLDER = os.path.join(os.path.dirname(__file__), "_uploads")
os.makedirs(UPLOAD_FOLDER, exist_ok=True)

# Changement du port pour 5001 afin d'éviter tout conflit avec le calculateur de piscine
PORT = int(os.environ.get("PORT", 5001))


@app.route("/")
def index():
    """Page principale."""
    return render_template("index.html")


@app.route("/upload", methods=["POST"])
def upload():
    """
    Upload et conversion d'un ou plusieurs fichiers (ou dossiers).
    Retourne le Markdown généré pour chaque fichier.
    """
    print("\n--- DEBUG: Received /upload request ---")
    
    files = request.files.getlist("files")
    paths = request.form.getlist("paths")
    
    print(f"DEBUG: Received {len(files)} files.")
    print(f"DEBUG: Received {len(paths)} paths: {paths}")

    if not files or not paths:
        print("DEBUG: No files or paths received. Aborting.")
        return jsonify({"success": False, "error": "Aucun fichier ou chemin reçu."}), 400

    if len(files) != len(paths):
        print("DEBUG: Mismatch between number of files and paths. Aborting.")
        return jsonify({"success": False, "error": "Incohérence entre les fichiers et les chemins."}), 400

    results = []
    errors = []

    for i, file in enumerate(files):
        filename = paths[i]
        print(f"\nDEBUG: Processing file #{i+1}: {filename}")
        
        if not filename:
            print("DEBUG: Skipping file with empty filename.")
            continue
            
        base_name = os.path.basename(filename.replace("\\", "/"))
        temp_filename = f"{uuid.uuid4().hex}_{base_name}"
        temp_path = os.path.join(UPLOAD_FOLDER, temp_filename)
        
        try:
            file.save(temp_path)
            print(f"DEBUG: Saved to temporary file: {temp_path}")

            markdown = convert(temp_path)
            print("DEBUG: Conversion successful.")
            
            entry = add_entry(filename, markdown)
            results.append({
                "id": entry["id"],
                "filename": filename,
                "markdown": markdown,
                "size": entry["size"],
                "date": entry["date"],
            })
        except Exception as e:
            print(f"DEBUG: An error occurred during conversion: {e}")
            errors.append({"filename": filename, "error": str(e)})
        finally:
            if os.path.exists(temp_path):
                try:
                    os.remove(temp_path)
                    print(f"DEBUG: Removed temporary file: {temp_path}")
                except Exception as e:
                    print(f"DEBUG: Failed to remove temporary file: {e}")

    print(f"--- DEBUG: Finished processing. Results: {len(results)}, Errors: {len(errors)} ---")
    return jsonify({
        "success": True,
        "results": results,
        "errors": errors,
    })


@app.route("/history")
def history():
    """Retourne l'historique des conversions."""
    return jsonify({"success": True, "data": get_all()})


@app.route("/download/<entry_id>")
def download(entry_id):
    """Télécharge un fichier .md depuis l'historique."""
    entry = get_entry(entry_id)
    if not entry:
        return jsonify({"success": False, "error": "Entrée introuvable."}), 404

    original_filename = entry["filename"].replace("\\", "/")
    base = os.path.splitext(os.path.basename(original_filename))[0]
    md_filename = f"{base}.md"
    
    temp_md_filename = f"{uuid.uuid4().hex}_{md_filename}"
    md_path = os.path.join(UPLOAD_FOLDER, temp_md_filename)

    with open(md_path, "w", encoding="utf-8") as f:
        f.write(entry["markdown"])

    @after_this_request
    def cleanup(response):
        if os.path.exists(md_path):
            try:
                os.remove(md_path)
            except Exception:
                pass
        return response

    return send_file(
        md_path,
        as_attachment=True,
        download_name=md_filename,
        mimetype="text/markdown",
    )


@app.route("/copy/<entry_id>")
def copy(entry_id):
    """Retourne le contenu Markdown pour copie dans le presse-papier."""
    entry = get_entry(entry_id)
    if not entry:
        return jsonify({"success": False, "error": "Entrée introuvable."}), 404
    return jsonify({"success": True, "markdown": entry["markdown"]})


@app.route("/clear-history", methods=["POST"])
def clear_history():
    """Vide l'historique."""
    clear()
    return jsonify({"success": True})

# Ce bloc n'est exécuté que si on lance le script directement (ex: `python app.py`)
# Il ne sera pas utilisé par Gunicorn sur Hugging Face.
if __name__ == "__main__":
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        if s.connect_ex(('0.0.0.0', PORT)) == 0:
            print(f"ERREUR: Le port {PORT} est déjà utilisé.")
            print("  - Avez-vous une autre application (peut-être un autre projet) qui tourne ?")
            print("  - Essayez de l'arrêter et de relancer.")
            exit(1)

    print(f"\n  MarkitDown WebApp lancée sur http://127.0.0.1:{PORT}\n")
    # On écoute sur 0.0.0.0 pour être compatible avec les conteneurs Docker
    app.run(host="0.0.0.0", port=PORT, debug=False)