Spaces:
Running
Running
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 | |
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') | |
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 | |
async def check(): | |
global processing | |
return 'ng' if processing else 'ok' | |
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ファイルを作成 | |
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に追加 | |
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 | |
}) | |
# 更新されたproject.jsonを書き込む | |
zip_file.writestr('project.json', json.dumps(project).encode('utf-8')) | |
# mmp4.zipの他のファイルもコピー | |
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ファイルのバイナリデータをBase64エンコード | |
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) |