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) | 
