mai2: fix ghost saving, add memorial photo upload
This commit is contained in:
parent
c6e7100f51
commit
d0e43140ba
@ -1,6 +1,8 @@
|
||||
from datetime import datetime, date, timedelta
|
||||
from datetime import datetime
|
||||
from typing import Any, Dict, List
|
||||
import logging
|
||||
from base64 import b64decode
|
||||
from os import path, stat
|
||||
|
||||
from core.config import CoreConfig
|
||||
from titles.mai2.const import Mai2Constants
|
||||
@ -773,4 +775,64 @@ class Mai2Base:
|
||||
self.logger.debug(data)
|
||||
|
||||
def handle_upload_user_photo_api_request(self, data: Dict) -> Dict:
|
||||
self.logger.debug(data)
|
||||
if not self.game_config.uploads.photos or not self.game_config.uploads.photos_dir:
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
photo = data.get("userPhoto", {})
|
||||
|
||||
if photo is None or not photo:
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
order_id = int(photo.get("orderId", -1))
|
||||
user_id = int(photo.get("userId", -1))
|
||||
div_num = int(photo.get("divNumber", -1))
|
||||
div_len = int(photo.get("divLength", -1))
|
||||
div_data = photo.get("divData", "")
|
||||
playlog_id = int(photo.get("playlogId", -1))
|
||||
track_num = int(photo.get("trackNo", -1))
|
||||
upload_date = photo.get("uploadDate", "")
|
||||
|
||||
if order_id < 0 or user_id <= 0 or div_num < 0 or div_len <= 0 or not div_data or playlog_id < 0 or track_num <= 0 or not upload_date:
|
||||
self.logger.warn(f"Malformed photo upload request")
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
if order_id == 0 and div_num > 0:
|
||||
self.logger.warn(f"Failed to set orderId properly (still 0 after first chunk)")
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
if div_num == 0 and order_id > 0:
|
||||
self.logger.warn(f"First chuck re-send, Ignore")
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
if div_num >= div_len:
|
||||
self.logger.warn(f"Sent extra chunks ({div_num} >= {div_len})")
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
if div_len >= 100:
|
||||
self.logger.warn(f"Photo too large ({div_len} * 10240 = {div_len * 10240} bytes)")
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
photo_chunk = b64decode(div_data)
|
||||
|
||||
if len(photo_chunk) > 10240 or (len(photo_chunk) < 10240 and div_num + 1 != div_len):
|
||||
self.logger.warn(f"Incorrect data size after decoding (Expected 10240, got {len(photo_chunk)})")
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
if not path.exists(f"{self.game_config.uploads.photos_dir}/{user_id}_{playlog_id}_{track_num}.jpeg") and div_num != 0:
|
||||
self.logger.warn(f"Out of order photo upload (div_num {div_num})")
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
if path.exists(f"{self.game_config.uploads.photos_dir}/{user_id}_{playlog_id}_{track_num}.jpeg") and div_num == 0:
|
||||
self.logger.warn(f"Duplicate file upload")
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
elif path.exists(f"{self.game_config.uploads.photos_dir}/{user_id}_{playlog_id}_{track_num}.jpeg"):
|
||||
fstats = stat(f"{self.game_config.uploads.photos_dir}/{user_id}_{playlog_id}_{track_num}.jpeg")
|
||||
if fstats.st_size != 10240 * div_num:
|
||||
self.logger.warn(f"Out of order photo upload (trying to upload div {div_num}, expected div {fstats.st_size / 10240} for file sized {fstats.st_size} bytes)")
|
||||
return {'returnCode': 0, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
||||
with open(f"{self.game_config.uploads.photos_dir}/{user_id}_{playlog_id}_{track_num}.jpeg", "ab") as f:
|
||||
f.write(photo_chunk)
|
||||
|
||||
return {'returnCode': order_id + 1, 'apiName': 'UploadUserPhotoApi'}
|
||||
|
@ -117,7 +117,7 @@ class Mai2DX(Mai2Base):
|
||||
|
||||
if "userGhost" in upsert:
|
||||
for ghost in upsert["userGhost"]:
|
||||
self.data.profile.put_profile_extend(user_id, self.version, ghost)
|
||||
self.data.profile.put_profile_ghost(user_id, self.version, ghost)
|
||||
|
||||
if "userOption" in upsert and len(upsert["userOption"]) > 0:
|
||||
self.data.profile.put_profile_option(
|
||||
@ -217,9 +217,6 @@ class Mai2DX(Mai2Base):
|
||||
|
||||
return {"returnCode": 1, "apiName": "UpsertUserAllApi"}
|
||||
|
||||
def handle_user_logout_api_request(self, data: Dict) -> Dict:
|
||||
return {"returnCode": 1}
|
||||
|
||||
def handle_get_user_data_api_request(self, data: Dict) -> Dict:
|
||||
profile = self.data.profile.get_profile_detail(data["userId"], self.version)
|
||||
if profile is None:
|
||||
@ -568,3 +565,10 @@ class Mai2DX(Mai2Base):
|
||||
"nextIndex": next_index,
|
||||
"userMusicList": [{"userMusicDetailList": music_detail_list}],
|
||||
}
|
||||
|
||||
def handle_user_login_api_request(self, data: Dict) -> Dict:
|
||||
ret = super().handle_user_login_api_request(data)
|
||||
if ret is None or not ret:
|
||||
return ret
|
||||
ret['loginId'] = ret.get('loginCount', 0)
|
||||
return ret
|
||||
|
@ -7,7 +7,7 @@ import string
|
||||
import logging, coloredlogs
|
||||
import zlib
|
||||
from logging.handlers import TimedRotatingFileHandler
|
||||
from os import path
|
||||
from os import path, mkdir
|
||||
from typing import Tuple
|
||||
|
||||
from core.config import CoreConfig
|
||||
@ -109,6 +109,19 @@ class Mai2Servlet:
|
||||
f"{core_cfg.title.hostname}",
|
||||
)
|
||||
|
||||
def setup(self):
|
||||
if self.game_cfg.uploads.photos and self.game_cfg.uploads.photos_dir and not path.exists(self.game_cfg.uploads.photos_dir):
|
||||
try:
|
||||
mkdir(self.game_cfg.uploads.photos_dir)
|
||||
except:
|
||||
self.logger.error(f"Failed to make photo upload directory at {self.game_cfg.uploads.photos_dir}")
|
||||
|
||||
if self.game_cfg.uploads.movies and self.game_cfg.uploads.movies_dir and not path.exists(self.game_cfg.uploads.movies_dir):
|
||||
try:
|
||||
mkdir(self.game_cfg.uploads.movies_dir)
|
||||
except:
|
||||
self.logger.error(f"Failed to make movie upload directory at {self.game_cfg.uploads.movies_dir}")
|
||||
|
||||
def render_POST(self, request: Request, version: int, url_path: str) -> bytes:
|
||||
if url_path.lower() == "ping":
|
||||
return zlib.compress(b'{"returnCode": "1"}')
|
||||
|
Loading…
Reference in New Issue
Block a user