File size: 4,642 Bytes
4f87b7e
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
from flask import Flask, request, send_file, jsonify, make_response
import subprocess, os, shutil, uuid

app = Flask(__name__)

def cors(response):
    response.headers['Access-Control-Allow-Origin'] = '*'
    response.headers['Access-Control-Allow-Methods'] = 'POST, GET, OPTIONS'
    response.headers['Access-Control-Allow-Headers'] = 'Content-Type'
    return response

@app.before_request
def handle_options():
    if request.method == 'OPTIONS':
        return cors(make_response('', 200))

@app.after_request
def after(response):
    return cors(response)

@app.route("/", methods=["GET"])
def index():
    return jsonify({"status": "HtStudio Python Builder 🚀 (APK + EXE)"})

def make_py_html(py_code, app_name):
    escaped = py_code.replace('\\','\\\\').replace('`','\\`').replace('$','\\$')
    return f"""<!DOCTYPE html><html><head><meta charset="UTF-8"><title>{app_name}</title>
<script src="https://skulpt.org/js/skulpt.min.js"></script>
<script src="https://skulpt.org/js/skulpt-stdlib.js"></script>
<style>body{{margin:0;background:#1e1e2e;color:#cdd6f4;font-family:monospace;padding:16px;}}
#output{{white-space:pre-wrap;font-size:14px;line-height:1.6;}}.err{{color:#f38ba8;}}</style>
</head><body><div id="output"></div>
<script>
var code=`{escaped}`;
function outf(t){{document.getElementById('output').innerHTML+=t;}}
function builtinRead(x){{if(Sk.builtinFiles===undefined||Sk.builtinFiles["files"][x]===undefined)throw "File not found: '"+x+"'";return Sk.builtinFiles["files"][x];}}
Sk.configure({{output:outf,read:builtinRead}});
Sk.misceval.asyncToPromise(()=>Sk.importMainWithBody("<stdin>",false,code,true))
.catch(e=>{{var el=document.createElement('div');el.className='err';el.textContent='Hata: '+e.toString();document.getElementById('output').appendChild(el);}});
</script></body></html>"""

@app.route("/build-python", methods=["POST"])
def build_python_apk():
    data = request.get_json(force=True)
    py_code  = data.get("code", "")
    app_name = data.get("name", "HtApp").strip().replace(" ", "_")
    pkg_name = data.get("pkg",  "com.htstudio.app").strip()
    if not py_code.strip():
        return jsonify({"error": "Python kodu boş"}), 400
    job_id = str(uuid.uuid4())[:8]
    work_dir = f"/tmp/build_py_{job_id}"
    os.makedirs(work_dir, exist_ok=True)
    try:
        with open(f"{work_dir}/index.html", "w", encoding="utf-8") as f:
            f.write(make_py_html(py_code, app_name))
        result = subprocess.run(
            ["bash", "/app/build_apk.sh", work_dir, app_name, pkg_name, "/opt/debug.keystore"],
            stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, timeout=120
        )
        if result.returncode != 0:
            return jsonify({"error": "Python APK başarısız", "log": result.stdout[-3000:]}), 500
        apk_path = f"{work_dir}/output.apk"
        if not os.path.exists(apk_path):
            return jsonify({"error": "APK oluşturulamadı", "log": result.stdout[-3000:]}), 500
        return send_file(apk_path, as_attachment=True,
            download_name=f"{app_name}_HtStudio.apk",
            mimetype="application/vnd.android.package-archive")
    finally:
        shutil.rmtree(work_dir, ignore_errors=True)

@app.route("/build-python-exe", methods=["POST"])
def build_python_exe():
    data = request.get_json(force=True)
    py_code  = data.get("code", "")
    app_name = data.get("name", "HtApp").strip().replace(" ", "_")
    pkg_name = data.get("pkg",  "com.htstudio.app").strip()
    if not py_code.strip():
        return jsonify({"error": "Python kodu boş"}), 400
    job_id = str(uuid.uuid4())[:8]
    work_dir = f"/tmp/build_pyexe_{job_id}"
    os.makedirs(work_dir, exist_ok=True)
    try:
        with open(f"{work_dir}/index.html", "w", encoding="utf-8") as f:
            f.write(make_py_html(py_code, app_name))
        result = subprocess.run(
            ["bash", "/app/build_exe.sh", work_dir, app_name, pkg_name],
            stdout=subprocess.PIPE, stderr=subprocess.STDOUT, text=True, timeout=300
        )
        if result.returncode != 0:
            return jsonify({"error": "Python EXE başarısız", "log": result.stdout[-3000:]}), 500
        exe_path = f"{work_dir}/output.exe"
        if not os.path.exists(exe_path):
            return jsonify({"error": "EXE oluşturulamadı", "log": result.stdout[-3000:]}), 500
        return send_file(exe_path, as_attachment=True,
            download_name=f"{app_name}_HtStudio.exe",
            mimetype="application/octet-stream")
    finally:
        shutil.rmtree(work_dir, ignore_errors=True)

if __name__ == "__main__":
    app.run(host="0.0.0.0", port=7860)