| from fastapi.middleware.cors import CORSMiddleware |
| from fastapi.staticfiles import StaticFiles |
| from fastapi import FastAPI, APIRouter |
| import base64, json, zipfile, uvicorn |
| from strgen import StringGenerator |
| from pydantic import BaseModel |
| from pathlib import Path |
| from io import BytesIO |
| from PIL import Image |
|
|
| app = FastAPI() |
|
|
| app.add_middleware( |
| CORSMiddleware, |
| allow_origins=["*"], |
| allow_credentials=True, |
| allow_methods=["*"], |
| allow_headers=["*"], |
| ) |
|
|
| router = APIRouter() |
| processing = False |
|
|
| class TextRequest(BaseModel): text: str |
|
|
| @router.post('/save') |
| async def save(req_data: TextRequest): |
| data = json.loads(req_data.text) |
| zip_buffer = BytesIO() |
| |
| with zipfile.ZipFile(zip_buffer, 'w') as zip_file: |
| zip_file.writestr('data.xml', data[0].encode('utf-8')) |
| zip_file.writestr('data.txt', data[1].encode('utf-8')) |
| |
| for i in range(2, len(data)): |
| file_data = base64.b64decode(data[i].split(',', 1)[1]) |
| file_name = f'{i - 1}.{data[i].split(";")[0].split("/")[1]}' |
| zip_file.writestr(file_name, file_data) |
|
|
| zip_buffer.seek(0) |
| return base64.b64encode(zip_buffer.getvalue()).decode('utf-8') |
|
|
| @router.post('/load') |
| async def load(zip_data: TextRequest): |
| zip_buffer = BytesIO(base64.b64decode(zip_data.text)) |
| data = [] |
| with zipfile.ZipFile(zip_buffer, 'r') as zip_file: |
| data.append(zip_file.open('data.xml').read().decode('utf-8')) |
| data.append(zip_file.open('data.txt').read().decode('utf-8')) |
|
|
| for file_info in zip_file.infolist(): |
| if file_info.filename.startswith('data.'): continue |
| with zip_file.open(file_info) as f: |
| ext = file_info.filename.split('.')[-1] |
| url = base64.b64encode(f.read()).decode('utf-8') |
| data.append(f'data:image/{ext};base64,{url}') |
|
|
| return data |
|
|
| @router.get('/check') |
| async def check(): |
| global processing |
| return 'ng' if processing else 'ok' |
|
|
| @router.post('/sb3') |
| async def sb3(req_data: TextRequest): |
| global processing |
| if processing: return '' |
| processing = True |
| data = json.loads(req_data.text) |
| with zipfile.ZipFile(Path('public').joinpath('mmp4.zip').resolve(), 'r') as template_zip: |
| with template_zip.open('project.json') as f: |
| project = json.loads(f.read().decode('utf-8')) |
|
|
| |
| zip_buffer = BytesIO() |
| with zipfile.ZipFile(zip_buffer, 'w') as zip_file: |
| variables = project['targets'][0]['variables'] |
| tiles = project['targets'].index([v for v in project['targets'] if v['name'] == 'Tiles'][0]) |
| |
| project['targets'][0]['variables'][[v for v in variables if variables[v][0] == 'MODコード'][0]][1] = data[0] |
|
|
| names = StringGenerator('[a-f\\d]{32}').render_list(len(data) - 1, unique=True) |
| for i in range(1, len(data)): |
| name = f'{names[i - 1]}.png' |
| image_data = base64.b64decode(data[i].split(',', 1)[1]) |
| |
| |
| img = Image.open(BytesIO(image_data)) |
| img_resized = img.resize((80, 80)) |
| img_buffer = BytesIO() |
| img_resized.save(img_buffer, format='PNG') |
| img_buffer.seek(0) |
|
|
| |
| zip_file.writestr(name, img_buffer.getvalue()) |
|
|
| project['targets'][tiles]['costumes'].append({ |
| "name": str(i), |
| "bitmapResolution": 2, |
| "dataFormat": "png", |
| "assetId": names[i - 1], |
| "md5ext": f"{names[i - 1]}.png", |
| "rotationCenterX": 40, |
| "rotationCenterY": 40 |
| }) |
|
|
| |
| zip_file.writestr('project.json', json.dumps(project).encode('utf-8')) |
|
|
| |
| with zipfile.ZipFile(Path('public').joinpath('mmp4.zip').resolve(), 'r') as template_zip: |
| for item in template_zip.infolist(): |
| if item.filename != 'project.json': |
| zip_file.writestr(item.filename, template_zip.read(item.filename)) |
|
|
| |
| zip_buffer.seek(0) |
| sb3_base64 = base64.b64encode(zip_buffer.getvalue()).decode('utf-8') |
|
|
| processing = False |
| return sb3_base64 |
|
|
| app.include_router(router, prefix='/api') |
|
|
| if __name__ == '__main__': |
| app.mount('/', StaticFiles(directory=Path('public'), html=True), name='public') |
| uvicorn.run(app, host='0.0.0.0', port=7860) |