Spaces:
Running
Running
from fastapi.middleware.cors import CORSMiddleware | |
from fastapi.staticfiles import StaticFiles | |
from fastapi import APIRouter, FastAPI | |
import base64, json, zipfile, uvicorn | |
from strgen import StringGenerator | |
from pathlib import Path | |
from io import BytesIO | |
from PIL import Image | |
app = FastAPI() | |
app.add_middleware( | |
CORSMiddleware, | |
allow_origins=[ | |
"http://localhost:3000", | |
"http://localhost:8000", | |
"http://127.0.0.1:3000", | |
"http://127.0.0.1:8000", | |
], | |
allow_credentials=True, | |
allow_methods=["*"], | |
allow_headers=["*"], | |
) | |
router = APIRouter() | |
def save(data): | |
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') | |
def load(zip_data): | |
zip_buffer = BytesIO(base64.b64decode(zip_data)) | |
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 | |
def sb3(data): | |
# まず、mmp4.zipからproject.jsonを読み込む | |
with zipfile.ZipFile('mmp4.zip', '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((40, 40)) | |
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('mmp4.zip', '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') | |
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=8000) |