318 lines
22 KiB
Python
318 lines
22 KiB
Python
# avatar.roblox.com
|
|
import logging
|
|
from flask import Blueprint, render_template, request, redirect, url_for, flash, session, abort, jsonify, make_response
|
|
from app.util import auth
|
|
from app.extensions import db, csrf, limiter, user_limiter
|
|
from flask_wtf.csrf import CSRFError, generate_csrf
|
|
|
|
from app.routes.thumbnailer import TakeUserThumbnail
|
|
|
|
from app.models.user_avatar import UserAvatar
|
|
from app.models.user_avatar_asset import UserAvatarAsset
|
|
from app.models.user import User
|
|
from app.models.asset import Asset
|
|
from app.models.userassets import UserAsset
|
|
|
|
from app.enums.AssetType import AssetType
|
|
|
|
AvatarAPIRoute = Blueprint('avatarapi', __name__, url_prefix='/')
|
|
|
|
csrf.exempt(AvatarAPIRoute)
|
|
@AvatarAPIRoute.errorhandler(CSRFError)
|
|
def handle_csrf_error(e):
|
|
ErrorResponse = make_response(jsonify({
|
|
"errors": [
|
|
{
|
|
"code": 0,
|
|
"message": "Token Validation Failed"
|
|
}
|
|
]
|
|
}))
|
|
|
|
ErrorResponse.status_code = 403
|
|
ErrorResponse.headers["x-csrf-token"] = generate_csrf()
|
|
return ErrorResponse
|
|
|
|
@AvatarAPIRoute.errorhandler(429)
|
|
def handle_ratelimit_reached(e):
|
|
return jsonify({
|
|
"errors": [
|
|
{
|
|
"code": 9,
|
|
"message": "The flood limit has been exceeded."
|
|
}
|
|
]
|
|
}), 429
|
|
|
|
@AvatarAPIRoute.before_request
|
|
def before_request():
|
|
if "Roblox/" not in request.user_agent.string:
|
|
csrf.protect()
|
|
|
|
@AvatarAPIRoute.route("/v1/avatar", methods=["GET"])
|
|
@auth.authenticated_required_api
|
|
@limiter.limit("60/minute")
|
|
def get_authenticated_user_avatar():
|
|
AuthenticatedUser : User = auth.GetCurrentUser()
|
|
|
|
UserAvatarObject : UserAvatar = UserAvatar.query.filter_by(user_id = AuthenticatedUser.id).first()
|
|
if UserAvatarObject is None:
|
|
UserAvatarObject = UserAvatar(AuthenticatedUser.id)
|
|
db.session.add(UserAvatarObject)
|
|
db.session.commit()
|
|
|
|
UserAvatarAssetObject : list[UserAvatarAsset] = UserAvatarAsset.query.filter_by(user_id = AuthenticatedUser.id).all()
|
|
WearingAssets : list[dict] = []
|
|
|
|
for AvatarAsset in UserAvatarAssetObject:
|
|
AssetObject : Asset = AvatarAsset.asset
|
|
WearingAssets.append({
|
|
"id": AvatarAsset.asset_id,
|
|
"name": AssetObject.name,
|
|
"assetType": {
|
|
"id": AssetObject.asset_type.value,
|
|
"name": AssetObject.asset_type.name
|
|
},
|
|
"currentVersionId": AssetObject.id
|
|
})
|
|
|
|
return jsonify({
|
|
"scales": {
|
|
"height": UserAvatarObject.height_scale,
|
|
"width": UserAvatarObject.width_scale,
|
|
"head": UserAvatarObject.head_scale,
|
|
"depth": 1,
|
|
"proportion": UserAvatarObject.proportion_scale,
|
|
"bodyType": UserAvatarObject.body_type_scale
|
|
},
|
|
"playerAvatarType": "R6" if not UserAvatarObject.r15 else "R15",
|
|
"bodyColors": {
|
|
"headColorId": UserAvatarObject.head_color_id,
|
|
"torsoColorId": UserAvatarObject.torso_color_id,
|
|
"rightArmColorId": UserAvatarObject.right_arm_color_id,
|
|
"leftArmColorId": UserAvatarObject.left_arm_color_id,
|
|
"rightLegColorId": UserAvatarObject.right_leg_color_id,
|
|
"leftLegColorId": UserAvatarObject.left_leg_color_id
|
|
},
|
|
"assets": WearingAssets,
|
|
"defaultShirtApplied": False,
|
|
"defaultPantsApplied": False,
|
|
"emotes": []
|
|
})
|
|
|
|
@AvatarAPIRoute.route("/v1/avatar/metadata", methods=["GET"])
|
|
@auth.authenticated_required_api
|
|
@limiter.limit("60/minute")
|
|
def get_avatar_editor_metadata():
|
|
return jsonify({
|
|
"enableDefaultClothingMessage": False,
|
|
"isAvatarScaleEmbeddedInTab": True,
|
|
"isBodyTypeScaleOutOfTab": True,
|
|
"scaleHeightIncrement": 0.05,
|
|
"scaleWidthIncrement": 0.05,
|
|
"scaleHeadIncrement": 0.05,
|
|
"scaleProportionIncrement": 0.05,
|
|
"scaleBodyTypeIncrement": 0.05,
|
|
"supportProportionAndBodyType": True,
|
|
"showDefaultClothingMessageOnPageLoad": False,
|
|
"areThreeDeeThumbsEnabled": False,
|
|
"isAvatarWearingApiCallsLockingOnFrontendEnabled": True,
|
|
"isOutfitHandlingOnFrontendEnabled": True,
|
|
"isJustinUiChangesEnabled": True,
|
|
"isCategoryReorgEnabled": True,
|
|
"LCEnabledInEditorAndCatalog": True,
|
|
"isLCCompletelyEnabled": True
|
|
})
|
|
|
|
@AvatarAPIRoute.route("/v1/avatar-rules", methods=["GET"])
|
|
@auth.authenticated_required_api
|
|
@limiter.limit("60/minute")
|
|
def get_avatar_editor_rules():
|
|
return jsonify({"playerAvatarTypes":["R6","R15"],"scales":{"height":{"min":0.9,"max":1.05,"increment":0.01},"width":{"min":0.7,"max":1,"increment":0.01},"head":{"min":0.95,"max":1,"increment":0.01},"proportion":{"min":0,"max":1,"increment":0.01},"bodyType":{"min":0,"max":1,"increment":0.01}},"wearableAssetTypes":[{"maxNumber":1,"id":18,"name":"Face"},{"maxNumber":1,"id":19,"name":"Gear"},{"maxNumber":1,"id":17,"name":"Head"},{"maxNumber":1,"id":29,"name":"Left Arm"},{"maxNumber":1,"id":30,"name":"Left Leg"},{"maxNumber":1,"id":12,"name":"Pants"},{"maxNumber":1,"id":28,"name":"Right Arm"},{"maxNumber":1,"id":31,"name":"Right Leg"},{"maxNumber":1,"id":11,"name":"Shirt"},{"maxNumber":1,"id":2,"name":"T-Shirt"},{"maxNumber":1,"id":27,"name":"Torso"},{"maxNumber":1,"id":48,"name":"Climb Animation"},{"maxNumber":1,"id":49,"name":"Death Animation"},{"maxNumber":1,"id":50,"name":"Fall Animation"},{"maxNumber":1,"id":51,"name":"Idle Animation"},{"maxNumber":1,"id":52,"name":"Jump Animation"},{"maxNumber":1,"id":53,"name":"Run Animation"},{"maxNumber":1,"id":54,"name":"Swim Animation"},{"maxNumber":1,"id":55,"name":"Walk Animation"},{"maxNumber":1,"id":56,"name":"Pose Animation"},{"maxNumber":0,"id":61,"name":"Emote Animation"},{"maxNumber":3,"id":8,"name":"Hat"},{"maxNumber":5,"id":41,"name":"Hair Accessory"},{"maxNumber":5,"id":42,"name":"Face Accessory"},{"maxNumber":1,"id":43,"name":"Neck Accessory"},{"maxNumber":1,"id":44,"name":"Shoulder Accessory"},{"maxNumber":1,"id":45,"name":"Front Accessory"},{"maxNumber":1,"id":46,"name":"Back Accessory"},{"maxNumber":1,"id":47,"name":"Waist Accessory"},{"maxNumber":1,"id":72,"name":"Dress Skirt Accessory"},{"maxNumber":1,"id":67,"name":"Jacket Accessory"},{"maxNumber":1,"id":70,"name":"Left Shoe Accessory"},{"maxNumber":1,"id":71,"name":"Right Shoe Accessory"},{"maxNumber":1,"id":66,"name":"Pants Accessory"},{"maxNumber":1,"id":65,"name":"Shirt Accessory"},{"maxNumber":1,"id":69,"name":"Shorts Accessory"},{"maxNumber":1,"id":68,"name":"Sweater Accessory"},{"maxNumber":1,"id":64,"name":"T-Shirt Accessory"},{"maxNumber":1,"id":76,"name":"Eyebrow Accessory"},{"maxNumber":1,"id":77,"name":"Eyelash Accessory"},{"maxNumber":1,"id":78,"name":"Mood Animation"},{"maxNumber":1,"id":79,"name":"Dynamic Head"}],"bodyColorsPalette":[{"brickColorId":361,"hexColor":"#564236","name":"Dirt brown"},{"brickColorId":192,"hexColor":"#694028","name":"Reddish brown"},{"brickColorId":217,"hexColor":"#7C5C46","name":"Brown"},{"brickColorId":153,"hexColor":"#957977","name":"Sand red"},{"brickColorId":359,"hexColor":"#AF9483","name":"Linen"},{"brickColorId":352,"hexColor":"#C7AC78","name":"Burlap"},{"brickColorId":5,"hexColor":"#D7C59A","name":"Brick yellow"},{"brickColorId":101,"hexColor":"#DA867A","name":"Medium red"},{"brickColorId":1007,"hexColor":"#A34B4B","name":"Dusty Rose"},{"brickColorId":1014,"hexColor":"#AA5500","name":"CGA brown"},{"brickColorId":38,"hexColor":"#A05F35","name":"Dark orange"},{"brickColorId":18,"hexColor":"#CC8E69","name":"Nougat"},{"brickColorId":125,"hexColor":"#EAB892","name":"Light orange"},{"brickColorId":1030,"hexColor":"#FFCC99","name":"Pastel brown"},{"brickColorId":133,"hexColor":"#D5733D","name":"Neon orange"},{"brickColorId":106,"hexColor":"#DA8541","name":"Bright orange"},{"brickColorId":105,"hexColor":"#E29B40","name":"Br. yellowish orange"},{"brickColorId":1017,"hexColor":"#FFAF00","name":"Deep orange"},{"brickColorId":24,"hexColor":"#F5CD30","name":"Bright yellow"},{"brickColorId":334,"hexColor":"#F8D96D","name":"Daisy orange"},{"brickColorId":226,"hexColor":"#FDEA8D","name":"Cool yellow"},{"brickColorId":141,"hexColor":"#27462D","name":"Earth green"},{"brickColorId":1021,"hexColor":"#3A7D15","name":"Camo"},{"brickColorId":28,"hexColor":"#287F47","name":"Dark green"},{"brickColorId":37,"hexColor":"#4B974B","name":"Bright green"},{"brickColorId":310,"hexColor":"#5B9A4C","name":"Shamrock"},{"brickColorId":317,"hexColor":"#7C9C6B","name":"Moss"},{"brickColorId":119,"hexColor":"#A4BD47","name":"Br. yellowish green"},{"brickColorId":1011,"hexColor":"#002060","name":"Navy blue"},{"brickColorId":1012,"hexColor":"#2154B9","name":"Deep blue"},{"brickColorId":1010,"hexColor":"#0000FF","name":"Really blue"},{"brickColorId":23,"hexColor":"#0D69AC","name":"Bright blue"},{"brickColorId":305,"hexColor":"#527CAE","name":"Steel blue"},{"brickColorId":102,"hexColor":"#6E99CA","name":"Medium blue"},{"brickColorId":45,"hexColor":"#B4D2E4","name":"Light blue"},{"brickColorId":107,"hexColor":"#008F9C","name":"Bright bluish green"},{"brickColorId":1018,"hexColor":"#12EED4","name":"Teal"},{"brickColorId":1027,"hexColor":"#9FF3E9","name":"Pastel blue-green"},{"brickColorId":1019,"hexColor":"#00FFFF","name":"Toothpaste"},{"brickColorId":1013,"hexColor":"#04AFEC","name":"Cyan"},{"brickColorId":11,"hexColor":"#80BBDC","name":"Pastel Blue"},{"brickColorId":1024,"hexColor":"#AFDDFF","name":"Pastel light blue"},{"brickColorId":104,"hexColor":"#6B327C","name":"Bright violet"},{"brickColorId":1023,"hexColor":"#8C5B9F","name":"Lavender"},{"brickColorId":321,"hexColor":"#A75E9B","name":"Lilac"},{"brickColorId":1015,"hexColor":"#AA00AA","name":"Magenta"},{"brickColorId":1031,"hexColor":"#6225D1","name":"Royal purple"},{"brickColorId":1006,"hexColor":"#B480FF","name":"Alder"},{"brickColorId":1026,"hexColor":"#B1A7FF","name":"Pastel violet"},{"brickColorId":21,"hexColor":"#C4281C","name":"Bright red"},{"brickColorId":1004,"hexColor":"#FF0000","name":"Really red"},{"brickColorId":1032,"hexColor":"#FF00BF","name":"Hot pink"},{"brickColorId":1016,"hexColor":"#FF66CC","name":"Pink"},{"brickColorId":330,"hexColor":"#FF98DC","name":"Carnation pink"},{"brickColorId":9,"hexColor":"#E8BAC8","name":"Light reddish violet"},{"brickColorId":1025,"hexColor":"#FFC9C9","name":"Pastel orange"},{"brickColorId":364,"hexColor":"#5A4C42","name":"Dark taupe"},{"brickColorId":351,"hexColor":"#BC9B5D","name":"Cork"},{"brickColorId":1008,"hexColor":"#C1BE42","name":"Olive"},{"brickColorId":29,"hexColor":"#A1C48C","name":"Medium green"},{"brickColorId":1022,"hexColor":"#7F8E64","name":"Grime"},{"brickColorId":151,"hexColor":"#789082","name":"Sand green"},{"brickColorId":135,"hexColor":"#74869D","name":"Sand blue"},{"brickColorId":1020,"hexColor":"#00FF00","name":"Lime green"},{"brickColorId":1028,"hexColor":"#CCFFCC","name":"Pastel green"},{"brickColorId":1009,"hexColor":"#FFFF00","name":"New Yeller"},{"brickColorId":1029,"hexColor":"#FFFFCC","name":"Pastel yellow"},{"brickColorId":1003,"hexColor":"#111111","name":"Really black"},{"brickColorId":26,"hexColor":"#1B2A35","name":"Black"},{"brickColorId":199,"hexColor":"#635F62","name":"Dark stone grey"},{"brickColorId":194,"hexColor":"#A3A2A5","name":"Medium stone grey"},{"brickColorId":1002,"hexColor":"#CDCDCD","name":"Mid gray"},{"brickColorId":208,"hexColor":"#E5E4DF","name":"Light stone grey"},{"brickColorId":1,"hexColor":"#F2F3F3","name":"White"},{"brickColorId":1001,"hexColor":"#F8F8F8","name":"Institutional white"}],"basicBodyColorsPalette":[{"brickColorId":364,"hexColor":"#5A4C42","name":"Dark taupe"},{"brickColorId":217,"hexColor":"#7C5C46","name":"Brown"},{"brickColorId":359,"hexColor":"#AF9483","name":"Linen"},{"brickColorId":18,"hexColor":"#CC8E69","name":"Nougat"},{"brickColorId":125,"hexColor":"#EAB892","name":"Light orange"},{"brickColorId":361,"hexColor":"#564236","name":"Dirt brown"},{"brickColorId":192,"hexColor":"#694028","name":"Reddish brown"},{"brickColorId":351,"hexColor":"#BC9B5D","name":"Cork"},{"brickColorId":352,"hexColor":"#C7AC78","name":"Burlap"},{"brickColorId":5,"hexColor":"#D7C59A","name":"Brick yellow"},{"brickColorId":153,"hexColor":"#957977","name":"Sand red"},{"brickColorId":1007,"hexColor":"#A34B4B","name":"Dusty Rose"},{"brickColorId":101,"hexColor":"#DA867A","name":"Medium red"},{"brickColorId":1025,"hexColor":"#FFC9C9","name":"Pastel orange"},{"brickColorId":330,"hexColor":"#FF98DC","name":"Carnation pink"},{"brickColorId":135,"hexColor":"#74869D","name":"Sand blue"},{"brickColorId":305,"hexColor":"#527CAE","name":"Steel blue"},{"brickColorId":11,"hexColor":"#80BBDC","name":"Pastel Blue"},{"brickColorId":1026,"hexColor":"#B1A7FF","name":"Pastel violet"},{"brickColorId":321,"hexColor":"#A75E9B","name":"Lilac"},{"brickColorId":107,"hexColor":"#008F9C","name":"Bright bluish green"},{"brickColorId":310,"hexColor":"#5B9A4C","name":"Shamrock"},{"brickColorId":317,"hexColor":"#7C9C6B","name":"Moss"},{"brickColorId":29,"hexColor":"#A1C48C","name":"Medium green"},{"brickColorId":105,"hexColor":"#E29B40","name":"Br. yellowish orange"},{"brickColorId":24,"hexColor":"#F5CD30","name":"Bright yellow"},{"brickColorId":334,"hexColor":"#F8D96D","name":"Daisy orange"},{"brickColorId":199,"hexColor":"#635F62","name":"Dark stone grey"},{"brickColorId":1002,"hexColor":"#CDCDCD","name":"Mid gray"},{"brickColorId":1001,"hexColor":"#F8F8F8","name":"Institutional white"}],"minimumDeltaEBodyColorDifference":11.4,"proportionsAndBodyTypeEnabledForUser":True,"defaultClothingAssetLists":{"defaultShirtAssetIds":[855776103,855760101,855766176,855777286,855768342,855779323,855773575,855778084],"defaultPantAssetIds":[855783877,855780360,855781078,855782781,855781508,855785499,855782253,855784936]},"bundlesEnabledForUser":False,"emotesEnabledForUser":False})
|
|
|
|
@AvatarAPIRoute.route("/v1/avatar/set-player-avatar-type", methods=["POST"])
|
|
@auth.authenticated_required_api
|
|
@limiter.limit("30/minute")
|
|
@user_limiter.limit("30/minute")
|
|
def set_player_avatar_type():
|
|
AuthenticatedUser : User = auth.GetCurrentUser()
|
|
|
|
if not request.is_json:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
if "playerAvatarType" not in request.json:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
if request.json["playerAvatarType"] not in ["R6", "R15"]:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
UserAvatarObject : UserAvatar = UserAvatar.query.filter_by(user_id = AuthenticatedUser.id).first()
|
|
if UserAvatarObject is None:
|
|
UserAvatarObject = UserAvatar(AuthenticatedUser.id)
|
|
db.session.add(UserAvatarObject)
|
|
db.session.commit()
|
|
|
|
UserAvatarObject.r15 = True if request.json["playerAvatarType"] == "R15" else False
|
|
db.session.commit()
|
|
|
|
TakeUserThumbnail(AuthenticatedUser.id)
|
|
|
|
return jsonify({
|
|
"success": True
|
|
})
|
|
|
|
@AvatarAPIRoute.route("/v1/avatar/set-scales", methods=["POST"])
|
|
@auth.authenticated_required_api
|
|
@limiter.limit("30/minute")
|
|
@user_limiter.limit("30/minute")
|
|
def set_player_avatar_scale():
|
|
AuthenticatedUser : User = auth.GetCurrentUser()
|
|
|
|
if not request.is_json:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
if "height" not in request.json or "width" not in request.json or "head" not in request.json or "proportion" not in request.json or "bodyType" not in request.json:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
AvatarScales = {}
|
|
|
|
try:
|
|
AvatarScales["height"] = float(request.json["height"])
|
|
AvatarScales["width"] = float(request.json["width"])
|
|
AvatarScales["head"] = float(request.json["head"])
|
|
AvatarScales["proportion"] = float(request.json["proportion"])
|
|
AvatarScales["bodyType"] = float(request.json["bodyType"])
|
|
except ValueError:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
if AvatarScales["height"] < 0.9 or AvatarScales["height"] > 1.05 or AvatarScales["width"] < 0.7 or AvatarScales["width"] > 1 or AvatarScales["head"] < 0.95 or AvatarScales["head"] > 1 or AvatarScales["proportion"] < 0 or AvatarScales["proportion"] > 1 or AvatarScales["bodyType"] < 0 or AvatarScales["bodyType"] > 1:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
UserAvatarObject : UserAvatar = UserAvatar.query.filter_by(user_id = AuthenticatedUser.id).first()
|
|
if UserAvatarObject is None:
|
|
UserAvatarObject = UserAvatar(AuthenticatedUser.id)
|
|
db.session.add(UserAvatarObject)
|
|
db.session.commit()
|
|
|
|
UserAvatarObject.height_scale = AvatarScales["height"]
|
|
UserAvatarObject.width_scale = AvatarScales["width"]
|
|
UserAvatarObject.head_scale = AvatarScales["head"]
|
|
UserAvatarObject.proportion_scale = AvatarScales["proportion"]
|
|
UserAvatarObject.body_type_scale = AvatarScales["bodyType"]
|
|
db.session.commit()
|
|
|
|
TakeUserThumbnail(AuthenticatedUser.id)
|
|
return jsonify({
|
|
"success": True
|
|
})
|
|
|
|
AllowedBodyColors = [361, 192, 217, 153, 359, 352, 5, 101, 1007, 1014, 38, 18, 125, 1030, 133, 106, 105, 1017, 24, 334, 226, 141, 1021, 28, 37, 310, 317, 119, 1011, 1012, 1010, 23, 305, 102, 45, 107, 1018, 1027, 1019, 1013, 11, 1024, 104, 1023, 321, 1015, 1031, 1006, 1026, 21, 1004, 1032, 1016, 330, 9, 1025, 364, 351, 1008, 29, 1022, 151, 135, 1020, 1028, 1009, 1029, 1003, 26, 199, 194, 1002, 208, 1, 1001]
|
|
|
|
@AvatarAPIRoute.route("/v1/avatar/set-body-colors", methods=["POST"])
|
|
@auth.authenticated_required_api
|
|
@limiter.limit("30/minute")
|
|
@user_limiter.limit("30/minute")
|
|
def set_player_avatar_body_colors():
|
|
AuthenticatedUser : User = auth.GetCurrentUser()
|
|
|
|
if not request.is_json:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
if "headColorId" not in request.json or "torsoColorId" not in request.json or "rightArmColorId" not in request.json or "leftArmColorId" not in request.json or "rightLegColorId" not in request.json or "leftLegColorId" not in request.json:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
if not isinstance(request.json["headColorId"], int) or not isinstance(request.json["torsoColorId"], int) or not isinstance(request.json["rightArmColorId"], int) or not isinstance(request.json["leftArmColorId"], int) or not isinstance(request.json["rightLegColorId"], int) or not isinstance(request.json["leftLegColorId"], int):
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
if request.json["headColorId"] not in AllowedBodyColors or request.json["torsoColorId"] not in AllowedBodyColors or request.json["rightArmColorId"] not in AllowedBodyColors or request.json["leftArmColorId"] not in AllowedBodyColors or request.json["rightLegColorId"] not in AllowedBodyColors or request.json["leftLegColorId"] not in AllowedBodyColors:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
UserAvatarObject : UserAvatar = UserAvatar.query.filter_by(user_id = AuthenticatedUser.id).first()
|
|
if UserAvatarObject is None:
|
|
UserAvatarObject = UserAvatar(AuthenticatedUser.id)
|
|
db.session.add(UserAvatarObject)
|
|
db.session.commit()
|
|
|
|
UserAvatarObject.head_color_id = request.json["headColorId"]
|
|
UserAvatarObject.torso_color_id = request.json["torsoColorId"]
|
|
UserAvatarObject.right_arm_color_id = request.json["rightArmColorId"]
|
|
UserAvatarObject.left_arm_color_id = request.json["leftArmColorId"]
|
|
UserAvatarObject.right_leg_color_id = request.json["rightLegColorId"]
|
|
UserAvatarObject.left_leg_color_id = request.json["leftLegColorId"]
|
|
|
|
db.session.commit()
|
|
TakeUserThumbnail(AuthenticatedUser.id)
|
|
|
|
return jsonify({
|
|
"success": True
|
|
})
|
|
|
|
@AvatarAPIRoute.route("/v1/avatar/set-wearing-assets", methods=["POST"])
|
|
@auth.authenticated_required_api
|
|
@limiter.limit("30/minute")
|
|
@user_limiter.limit("30/minute")
|
|
def set_player_avatar_wearing_assets():
|
|
AuthenticatedUser : User = auth.GetCurrentUser()
|
|
|
|
if not request.is_json:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
if "assetIds" not in request.json:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
if not isinstance(request.json["assetIds"], list):
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
InvalidAssetIds : list[int] = []
|
|
AssetTypeCounter : dict[int, int] = {}
|
|
AllowedAssetIds : list[int] = []
|
|
|
|
for AssetId in request.json["assetIds"]:
|
|
try:
|
|
AssetId = int(AssetId)
|
|
except ValueError:
|
|
return jsonify({"errors": [{"code": 0, "message": "Invalid JSON"}]}), 400
|
|
|
|
if AssetId in InvalidAssetIds or AssetId in AllowedAssetIds:
|
|
continue
|
|
UserAssetObj : UserAsset = UserAsset.query.filter_by(userid = AuthenticatedUser.id, assetid = AssetId).first()
|
|
|
|
if UserAssetObj is None:
|
|
InvalidAssetIds.append(AssetId)
|
|
continue
|
|
|
|
AssetObj : Asset = UserAssetObj.asset
|
|
|
|
if AssetObj.moderation_status != 0:
|
|
InvalidAssetIds.append(AssetId)
|
|
continue
|
|
if AssetObj.asset_type.value not in [2,8,11,12,17,18,19,27,28,29,30,31,32,41,42,43,44,45,46,47,57,58]:
|
|
return jsonify({"errors": [{"code": 3, "message": "Invalid AssetId"}]}), 400
|
|
|
|
if AssetObj.asset_type.value not in AssetTypeCounter:
|
|
AssetTypeCounter[AssetObj.asset_type.value] = 0
|
|
|
|
if AssetTypeCounter[AssetObj.asset_type.value] >= 1 and AssetObj.asset_type != AssetType.Hat:
|
|
return jsonify({"errors": [{"code": 3, "message": "Invalid AssetId"}]}), 400
|
|
if AssetTypeCounter[AssetObj.asset_type.value] >= 3 and AssetObj.asset_type == AssetType.Hat:
|
|
return jsonify({"errors": [{"code": 3, "message": "Invalid AssetId"}]}), 400
|
|
|
|
AssetTypeCounter[AssetObj.asset_type.value] += 1
|
|
AllowedAssetIds.append(AssetId)
|
|
|
|
UserAvatarAsset.query.filter_by(user_id = AuthenticatedUser.id).delete()
|
|
db.session.commit()
|
|
|
|
for AssetId in AllowedAssetIds:
|
|
NewAvatarAssetObj : UserAvatarAsset = UserAvatarAsset( user_id = AuthenticatedUser.id, asset_id = AssetId )
|
|
db.session.add(NewAvatarAssetObj)
|
|
|
|
db.session.commit()
|
|
TakeUserThumbnail(AuthenticatedUser.id)
|
|
|
|
return jsonify({
|
|
"invalidAssetIds": InvalidAssetIds,
|
|
"success": True
|
|
})
|
|
|