add web
This commit is contained in:
@@ -0,0 +1,270 @@
|
||||
from app.extensions import redis_controller, db
|
||||
from app.util import redislock
|
||||
|
||||
from app.models.usereconomy import UserEconomy
|
||||
from app.models.user import User
|
||||
from app.models.userassets import UserAsset
|
||||
from app.models.groups import Group, GroupEconomy
|
||||
from app.models.asset import Asset
|
||||
from app.models.asset_rap import AssetRap
|
||||
from app.services.groups import GetGroupFromId, GetUserFromId
|
||||
|
||||
import redis_lock
|
||||
import math
|
||||
|
||||
class InvalidCurrencyTypeException(Exception):
|
||||
pass
|
||||
class EconomyLockAcquireException(Exception):
|
||||
pass
|
||||
class InsufficientFundsException(Exception):
|
||||
pass
|
||||
class AssetNotLimitedException(Exception):
|
||||
pass
|
||||
class AssetDoesNotExistException(Exception):
|
||||
pass
|
||||
|
||||
def TaxCurrencyAmount( Amount : int ) -> int:
|
||||
return math.floor( Amount * 0.7 )
|
||||
|
||||
def GetAssetFromId( assetid : int | Asset ) -> Asset | None:
|
||||
"""
|
||||
Returns the Asset object for the given assetid
|
||||
"""
|
||||
if isinstance(assetid, Asset):
|
||||
return assetid
|
||||
AssetObj : Asset = Asset.query.filter_by(id=assetid).first()
|
||||
if AssetObj is None:
|
||||
raise AssetDoesNotExistException("Asset does not exist")
|
||||
return AssetObj
|
||||
|
||||
def GetUserEconomyObj( TargetUser : User ) -> UserEconomy | None:
|
||||
"""
|
||||
Returns the UserEconomy object for the given user
|
||||
"""
|
||||
return UserEconomy.query.filter_by( userid=TargetUser.id ).first()
|
||||
|
||||
def GetGroupEconomyObj( TargetGroup : Group ) -> GroupEconomy | None:
|
||||
"""
|
||||
Returns the GroupEconomy object for the given group
|
||||
"""
|
||||
return GroupEconomy.query.filter_by( group_id=TargetGroup.id ).first()
|
||||
|
||||
def GetUserBalance( TargetUser : User ) -> tuple[int, int]:
|
||||
"""
|
||||
Returns the User's Robux and Tickets balance
|
||||
"""
|
||||
EconomyObj : UserEconomy = GetUserEconomyObj( TargetUser )
|
||||
return EconomyObj.robux, EconomyObj.tix
|
||||
|
||||
def GetGroupBalance( TargetGroup : Group ) -> tuple[int, int]:
|
||||
"""
|
||||
Returns the Group's Robux and Tickets balance
|
||||
"""
|
||||
EconomyObj : GroupEconomy = GetGroupEconomyObj( TargetGroup )
|
||||
return EconomyObj.robux_balance, EconomyObj.tix_balance
|
||||
|
||||
def UnsafeIncrementTargetBalance( Target : User | Group, Amount : int, CurrencyType : int ): # CurrencyType is 0 for Robux, 1 for Tickets
|
||||
"""
|
||||
Increments the Target Balance ( Not Recommended for normal use please instead use IncrementTargetBalance)
|
||||
"""
|
||||
if isinstance(Target, User):
|
||||
TargetEconomyObj : UserEconomy = GetUserEconomyObj( Target )
|
||||
if CurrencyType == 0:
|
||||
TargetEconomyObj.robux += Amount
|
||||
elif CurrencyType == 1:
|
||||
TargetEconomyObj.tix += Amount
|
||||
else:
|
||||
raise InvalidCurrencyTypeException("Invalid Currency Type")
|
||||
db.session.commit()
|
||||
elif isinstance(Target, Group):
|
||||
TargetEconomyObj : GroupEconomy = GetGroupEconomyObj( Target )
|
||||
if CurrencyType == 0:
|
||||
TargetEconomyObj.robux_balance += Amount
|
||||
elif CurrencyType == 1:
|
||||
TargetEconomyObj.tix_balance += Amount
|
||||
else:
|
||||
raise InvalidCurrencyTypeException("Invalid Currency Type")
|
||||
db.session.commit()
|
||||
else:
|
||||
raise TypeError("Invalid Target Type")
|
||||
|
||||
def UnsafeDecrementTargetBalance( Target : User | Group, Amount : int, CurrencyType : int ): # CurrencyType is 0 for Robux, 1 for Tickets
|
||||
"""
|
||||
Decrements the Target Balance ( Not Recommended for normal use please instead use DecrementTargetBalance)
|
||||
"""
|
||||
if isinstance(Target, User):
|
||||
TargetEconomyObj : UserEconomy = GetUserEconomyObj( Target )
|
||||
if CurrencyType == 0:
|
||||
TargetEconomyObj.robux -= Amount
|
||||
elif CurrencyType == 1:
|
||||
TargetEconomyObj.tix -= Amount
|
||||
else:
|
||||
raise InvalidCurrencyTypeException("Invalid Currency Type")
|
||||
db.session.commit()
|
||||
elif isinstance(Target, Group):
|
||||
TargetEconomyObj : GroupEconomy = GetGroupEconomyObj( Target )
|
||||
if CurrencyType == 0:
|
||||
TargetEconomyObj.robux_balance -= Amount
|
||||
elif CurrencyType == 1:
|
||||
TargetEconomyObj.tix_balance -= Amount
|
||||
else:
|
||||
raise InvalidCurrencyTypeException("Invalid Currency Type")
|
||||
db.session.commit()
|
||||
else:
|
||||
raise TypeError("Invalid Target Type")
|
||||
|
||||
def IncrementTargetBalance( Target : User | Group, Amount : int, CurrencyType : int ): # CurrencyType is 0 for Robux, 1 for Tickets
|
||||
"""
|
||||
Increments the Target Balance
|
||||
"""
|
||||
if Amount < 0:
|
||||
raise ValueError("Amount must be positive")
|
||||
if isinstance(Target, User):
|
||||
with redis_lock.Lock( redis_client = redis_controller, name = f"economy:{Target.id}", expire = 1, auto_renewal = True ):
|
||||
UnsafeIncrementTargetBalance( Target, Amount, CurrencyType )
|
||||
return
|
||||
elif isinstance(Target, Group):
|
||||
with redis_lock.Lock( redis_client = redis_controller, name = f"economy_group:{Target.id}", expire = 1, auto_renewal = True ):
|
||||
UnsafeIncrementTargetBalance( Target, Amount, CurrencyType )
|
||||
return
|
||||
else:
|
||||
raise TypeError("Invalid Target Type")
|
||||
|
||||
def DecrementTargetBalance( Target : User | Group, Amount : int, CurrencyType : int ): # CurrencyType is 0 for Robux, 1 for Tickets
|
||||
"""
|
||||
Decrements the Target Balance
|
||||
"""
|
||||
if Amount < 0:
|
||||
raise ValueError("Amount must be positive")
|
||||
if isinstance(Target, User):
|
||||
with redis_lock.Lock( redis_client = redis_controller, name = f"economy:{Target.id}", expire = 1, auto_renewal = True ):
|
||||
TargetEconomyObj : UserEconomy = GetUserEconomyObj( Target )
|
||||
if CurrencyType == 0:
|
||||
if TargetEconomyObj.robux < Amount:
|
||||
raise InsufficientFundsException("Insufficient Funds")
|
||||
elif CurrencyType == 1:
|
||||
if TargetEconomyObj.tix < Amount:
|
||||
raise InsufficientFundsException("Insufficient Funds")
|
||||
UnsafeDecrementTargetBalance( Target, Amount, CurrencyType )
|
||||
return
|
||||
elif isinstance(Target, Group):
|
||||
with redis_lock.Lock( redis_client = redis_controller, name = f"economy_group:{Target.id}", expire = 1, auto_renewal = True ):
|
||||
TargetEconomyObj : GroupEconomy = GroupEconomy.query.filter_by( group_id=Target.id ).first()
|
||||
if CurrencyType == 0:
|
||||
if TargetEconomyObj.robux_balance < Amount:
|
||||
raise InsufficientFundsException("Insufficient Funds")
|
||||
elif CurrencyType == 1:
|
||||
if TargetEconomyObj.tix_balance < Amount:
|
||||
raise InsufficientFundsException("Insufficient Funds")
|
||||
UnsafeDecrementTargetBalance( Target, Amount, CurrencyType )
|
||||
return
|
||||
else:
|
||||
raise TypeError("Invalid Target Type")
|
||||
|
||||
def TransferFunds( Source : User | Group, Target : User | Group, Amount : int, CurrencyType : int, ApplyTax : bool = False): # CurrencyType is 0 for Robux, 1 for Tickets
|
||||
"""
|
||||
Transfers funds from the source to the target
|
||||
"""
|
||||
|
||||
if Amount < 0:
|
||||
raise ValueError("Amount must be positive")
|
||||
if Source == Target:
|
||||
raise ValueError("Source and Target must be different")
|
||||
if CurrencyType not in [0,1]:
|
||||
raise InvalidCurrencyTypeException("Invalid Currency Type")
|
||||
if isinstance(Source, User):
|
||||
SourceEconomyObj : UserEconomy = GetUserEconomyObj( Source )
|
||||
if CurrencyType == 0:
|
||||
if SourceEconomyObj.robux < Amount:
|
||||
raise InsufficientFundsException("Insufficient Funds")
|
||||
elif CurrencyType == 1:
|
||||
if SourceEconomyObj.tix < Amount:
|
||||
raise InsufficientFundsException("Insufficient Funds")
|
||||
elif isinstance(Source, Group):
|
||||
SourceEconomyObj : GroupEconomy = GroupEconomy.query.filter_by( group_id=Source.id ).first()
|
||||
if CurrencyType == 0:
|
||||
if SourceEconomyObj.robux_balance < Amount:
|
||||
raise InsufficientFundsException("Insufficient Funds")
|
||||
elif CurrencyType == 1:
|
||||
if SourceEconomyObj.tix_balance < Amount:
|
||||
raise InsufficientFundsException("Insufficient Funds")
|
||||
else:
|
||||
raise TypeError("Invalid Source Type")
|
||||
|
||||
TakenAmount : int = Amount
|
||||
GivenAmount : int = Amount
|
||||
if ApplyTax:
|
||||
GivenAmount = TaxCurrencyAmount( Amount )
|
||||
try:
|
||||
DecrementTargetBalance( Source, TakenAmount, CurrencyType )
|
||||
except InsufficientFundsException:
|
||||
raise InsufficientFundsException("Insufficient Funds")
|
||||
IncrementTargetBalance( Target, GivenAmount, CurrencyType )
|
||||
|
||||
return
|
||||
|
||||
def AdjustAssetRap(AssetObj : Asset | int, robux : int):
|
||||
""" Adjusts the RAP of an asset
|
||||
https://roblox.fandom.com/wiki/Recent_Average_Price
|
||||
This will only work with assets that are limited
|
||||
"""
|
||||
AssetObj : Asset = GetAssetFromId(AssetObj)
|
||||
|
||||
AssetRapObject : AssetRap = AssetRap.query.filter_by(assetid=AssetObj.id).first()
|
||||
if AssetRapObject is None:
|
||||
if not AssetObj.is_limited:
|
||||
raise AssetNotLimitedException("Asset is not limited")
|
||||
AssetRapObject = AssetRap(assetid=AssetObj.id, rap=robux)
|
||||
db.session.add(AssetRapObject)
|
||||
db.session.commit()
|
||||
return True
|
||||
if AssetRapObject.rap <= 0:
|
||||
AssetRapObject.rap = robux
|
||||
CurrentRAP = AssetRapObject.rap
|
||||
AssetRapObject.rap = math.floor(CurrentRAP - ( CurrentRAP - robux ) / 10)
|
||||
db.session.commit()
|
||||
return True
|
||||
|
||||
def GetAssetRap(AssetObj : Asset | int ) -> int:
|
||||
"""
|
||||
Returns the RAP of an asset
|
||||
"""
|
||||
AssetObj : Asset = GetAssetFromId(AssetObj)
|
||||
if not AssetObj.is_limited:
|
||||
raise AssetNotLimitedException("Asset is not limited")
|
||||
|
||||
AssetRapObject : AssetRap = AssetRap.query.filter_by(assetid=AssetObj.id).first()
|
||||
if AssetRapObject is None:
|
||||
AssetRapObject = AssetRap(assetid=AssetObj.id, rap=0)
|
||||
db.session.add(AssetRapObject)
|
||||
db.session.commit()
|
||||
return AssetRapObject.rap
|
||||
|
||||
def GetCreatorOfAsset( AssetObj : Asset | int ) -> User | Group | None:
|
||||
"""
|
||||
Returns the creator of an asset
|
||||
"""
|
||||
AssetObj : Asset = GetAssetFromId(AssetObj)
|
||||
if AssetObj.creator_type == 1:
|
||||
return GetGroupFromId(AssetObj.creator_id)
|
||||
elif AssetObj.creator_type == 0:
|
||||
return GetUserFromId(AssetObj.creator_id)
|
||||
else:
|
||||
return None
|
||||
|
||||
def CalculateUserRAP( UserObj : User | int, skipCache : bool = False ) -> int:
|
||||
"""
|
||||
Calculates the RAP of a user
|
||||
"""
|
||||
if redis_controller.exists(f"rap_calculation:{UserObj.id}") and not skipCache:
|
||||
return int(redis_controller.get(f"rap_calculation:{UserObj.id}"))
|
||||
|
||||
UserObj : User = GetUserFromId(UserObj)
|
||||
UserRAP : int = 0
|
||||
UserLimitedAssets : list[UserAsset] = UserAsset.query.filter_by(userid=UserObj.id).outerjoin( Asset, Asset.id == UserAsset.assetid ).filter( Asset.is_limited == True ).all()
|
||||
|
||||
for UserLimitedAsset in UserLimitedAssets:
|
||||
UserRAP += GetAssetRap(UserLimitedAsset.assetid)
|
||||
|
||||
redis_controller.set(f"rap_calculation:{UserObj.id}", UserRAP, ex = 60)
|
||||
return UserRAP
|
||||
Reference in New Issue
Block a user