add web
This commit is contained in:
@@ -0,0 +1,522 @@
|
||||
# Commands for flask shell
|
||||
from app.extensions import db, redis_controller
|
||||
from app.models.user import User
|
||||
from app.util import auth
|
||||
from sqlalchemy import func
|
||||
import logging
|
||||
# henlo from china!
|
||||
def lookup_user_id():
|
||||
"""Lookup user by Id"""
|
||||
try:
|
||||
UserId : int = int(input("User Lookup by UserId: "))
|
||||
if UserId < 0:
|
||||
raise Exception("UserId must be a positive integer")
|
||||
except Exception as e:
|
||||
logging.error(f"Unable to parse user input, please enter a valid integer, error: {e}")
|
||||
|
||||
UserObj : User = User.query.filter_by(id=UserId).first()
|
||||
if UserObj is None:
|
||||
logging.error(f"Unable to find user with UserId: {UserId}")
|
||||
else:
|
||||
logging.info(f"""
|
||||
Username : {UserObj.username}
|
||||
UserId : {UserObj.id}
|
||||
CreatedOn : {UserObj.created}
|
||||
LastPing : {UserObj.lastonline}
|
||||
AccountStatus : {UserObj.accountstatus}
|
||||
2FA Enabled : {UserObj.TOTPEnabled}
|
||||
|
||||
-- Description --
|
||||
{UserObj.description}
|
||||
-- End Description --
|
||||
|
||||
""")
|
||||
|
||||
def lookup_user_name():
|
||||
"""Lookup user by Username"""
|
||||
try:
|
||||
Username : str = str(input("User Lookup by Username: "))
|
||||
if len(Username) < 1:
|
||||
raise Exception("Username must be a valid string")
|
||||
except Exception as e:
|
||||
logging.error(f"Unable to parse user input, please enter a valid string, error: {e}")
|
||||
|
||||
UserObj : User = User.query.filter(func.lower(User.username) == func.lower(Username)).first()
|
||||
if UserObj is None:
|
||||
logging.error(f"Unable to find user with Username: {Username}")
|
||||
else:
|
||||
logging.info(f"""
|
||||
Username : {UserObj.username}
|
||||
UserId : {UserObj.id}
|
||||
CreatedOn : {UserObj.created}
|
||||
LastPing : {UserObj.lastonline}
|
||||
AccountStatus : {UserObj.accountstatus}
|
||||
2FA Enabled : {UserObj.TOTPEnabled}
|
||||
|
||||
-- Description --
|
||||
{UserObj.description}
|
||||
-- End Description --
|
||||
|
||||
""")
|
||||
|
||||
def refund_unused_invite_keys():
|
||||
from app.models.invite_key import InviteKey
|
||||
from app.services.economy import IncrementTargetBalance
|
||||
from app.util.transactions import CreateTransaction
|
||||
from app.enums.TransactionType import TransactionType
|
||||
from app.pages.messages.messages import CreateSystemMessage
|
||||
|
||||
allDistinctInviteKeyCreators : list[User] = User.query.join(InviteKey, User.id == InviteKey.created_by).filter(InviteKey.used_by == None).distinct(User.id).all()
|
||||
|
||||
def process_user_invite_keys( userObj : User ):
|
||||
AmountOwed : int = 0
|
||||
InviteKeysDeleted : int = 0
|
||||
|
||||
AllInviteKeys : list[InviteKey] = InviteKey.query.filter_by(created_by=userObj.id, used_by=None).all()
|
||||
for InviteKeyObj in AllInviteKeys:
|
||||
AmountOwed += 20
|
||||
InviteKeysDeleted += 1
|
||||
db.session.delete(InviteKeyObj)
|
||||
db.session.commit()
|
||||
|
||||
if AmountOwed > 0:
|
||||
IncrementTargetBalance(userObj, AmountOwed, 0)
|
||||
CreateTransaction(
|
||||
Reciever = userObj,
|
||||
Sender = None,
|
||||
CurrencyAmount = AmountOwed,
|
||||
CurrencyType = 0,
|
||||
TransactionType = TransactionType.BuildersClubStipend,
|
||||
AssetId = None,
|
||||
CustomText = f"Refunded {InviteKeysDeleted} unused invite keys",
|
||||
)
|
||||
CreateSystemMessage(
|
||||
subject = "Invite Key Refund",
|
||||
message = f"""Hello {userObj.username},
|
||||
This is an automated message to inform you that as invite keys are no longer used on Vortexi, we have refunded you R$ {AmountOwed} for {InviteKeysDeleted} unused invite keys. Please contact us on our Discord Server if you have any questions.
|
||||
|
||||
Sincerely,
|
||||
The Vortexi Team""",
|
||||
userid = userObj.id
|
||||
)
|
||||
|
||||
logging.info(f"Refunded {InviteKeysDeleted} unused invite keys for user {userObj.username}")
|
||||
|
||||
logging.info(f"Found {len(allDistinctInviteKeyCreators)} users with unused invite keys")
|
||||
for UserObj in allDistinctInviteKeyCreators:
|
||||
process_user_invite_keys(UserObj)
|
||||
|
||||
def refund_limiteds():
|
||||
from app.models.userassets import UserAsset
|
||||
from app.models.asset import Asset
|
||||
from app.models.user_trade_items import UserTradeItem
|
||||
from app.services.economy import IncrementTargetBalance, GetAssetRap
|
||||
from app.util.transactions import CreateTransaction
|
||||
from app.enums.TransactionType import TransactionType
|
||||
from app.enums.MembershipType import MembershipType
|
||||
from app.pages.messages.messages import CreateSystemMessage
|
||||
from app.models.user import User
|
||||
from app.util.membership import GetUserMembership
|
||||
import math
|
||||
import logging
|
||||
from app import db
|
||||
|
||||
limitedRAPValueLookup: dict[int, int] = {}
|
||||
refundCapAmount: dict[MembershipType, int] = {
|
||||
MembershipType.NonBuildersClub: 200,
|
||||
MembershipType.BuildersClub: 500,
|
||||
MembershipType.TurboBuildersClub: 750,
|
||||
MembershipType.OutrageousBuildersClub: 1200,
|
||||
}
|
||||
|
||||
def _get_limited_rap_value(assetId: int):
|
||||
if assetId in limitedRAPValueLookup:
|
||||
return limitedRAPValueLookup[assetId]
|
||||
else:
|
||||
rapValue: int = GetAssetRap(assetId)
|
||||
limitedRAPValueLookup[assetId] = rapValue
|
||||
return rapValue
|
||||
|
||||
def refund_user_limiteds(userObj: User):
|
||||
WipedAssets: list = []
|
||||
AllLimitedUserAssets: list[UserAsset] = (
|
||||
UserAsset.query.filter_by(userid=userObj.id)
|
||||
.join(Asset, UserAsset.assetid == Asset.id)
|
||||
.filter(Asset.is_limited == True)
|
||||
.all()
|
||||
)
|
||||
AmountOwed: int = 0
|
||||
|
||||
for UserAssetObj in AllLimitedUserAssets:
|
||||
AssetObj: Asset = UserAssetObj.asset
|
||||
|
||||
LimitedRAPValue: int = _get_limited_rap_value(UserAssetObj.assetid)
|
||||
AssetOriginalPrice: int = (
|
||||
AssetObj.price_robux
|
||||
if AssetObj.price_robux > 0
|
||||
else AssetObj.price_tix
|
||||
)
|
||||
|
||||
if not AssetObj.price_robux > 0 and AssetOriginalPrice > 0:
|
||||
AssetOriginalPrice = math.floor(AssetOriginalPrice / 10)
|
||||
|
||||
RefundedAmount: int = max(
|
||||
AssetOriginalPrice
|
||||
if AssetOriginalPrice > LimitedRAPValue
|
||||
else LimitedRAPValue,
|
||||
50,
|
||||
)
|
||||
AmountOwed += RefundedAmount
|
||||
|
||||
WipedAssets.append(
|
||||
f" - {AssetObj.name} [UAID: {UserAssetObj.id} / Serial: {UserAssetObj.serial}] - R$ {RefundedAmount}"
|
||||
)
|
||||
|
||||
# First delete any trade items that reference this UserAsset
|
||||
UserTradeItem.query.filter_by(user_asset_id=UserAssetObj.id).delete()
|
||||
|
||||
# Then delete the UserAsset itself
|
||||
db.session.delete(UserAssetObj)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
ActualAmountOwed = min(AmountOwed, refundCapAmount[GetUserMembership(userObj)])
|
||||
|
||||
# ===== CHECK FOR ROBUX OVERFLOW =====
|
||||
max_int_32 = 2_147_483_647
|
||||
if userObj.economy.robux + ActualAmountOwed > max_int_32:
|
||||
logging.warning(
|
||||
f"Skipping refund for {userObj.username}: balance would exceed 32-bit integer limit"
|
||||
)
|
||||
return
|
||||
# ====================================
|
||||
|
||||
if ActualAmountOwed > 0:
|
||||
ItemListText: str = "\n".join(WipedAssets)
|
||||
|
||||
IncrementTargetBalance(userObj, ActualAmountOwed, 0)
|
||||
CreateTransaction(
|
||||
Reciever=userObj,
|
||||
Sender=None,
|
||||
CurrencyAmount=ActualAmountOwed,
|
||||
CurrencyType=0,
|
||||
TransactionType=TransactionType.BuildersClubStipend,
|
||||
AssetId=None,
|
||||
CustomText="Limited item refund",
|
||||
)
|
||||
|
||||
CreateSystemMessage(
|
||||
subject="Limited Item Refund",
|
||||
message=f"""Hello {userObj.username},
|
||||
|
||||
This is an automated message to inform you that all limited items are being refunded as we are resetting the economy. We have refunded you R$ {ActualAmountOwed} for the following items:
|
||||
{ItemListText}
|
||||
|
||||
Item Refund Cap: R$ {refundCapAmount[GetUserMembership(userObj)]}
|
||||
Total Value before Cap: R$ {AmountOwed}
|
||||
|
||||
Refunded Amount: R$ {ActualAmountOwed}
|
||||
|
||||
Please contact us on our Discord Server if you have any questions.
|
||||
|
||||
Sincerely,
|
||||
The Vortexi Team""",
|
||||
userid=userObj.id,
|
||||
)
|
||||
|
||||
logging.info(
|
||||
f"Refunded {len(AllLimitedUserAssets)} limited items for user {userObj.username}"
|
||||
)
|
||||
|
||||
AllUsersWithLimiteds: list[User] = (
|
||||
User.query.join(UserAsset, User.id == UserAsset.userid)
|
||||
.join(Asset, UserAsset.assetid == Asset.id)
|
||||
.filter(Asset.is_limited == True)
|
||||
.distinct(User.id)
|
||||
.all()
|
||||
)
|
||||
logging.info(f"Found {len(AllUsersWithLimiteds)} users with limiteds")
|
||||
|
||||
for UserObj in AllUsersWithLimiteds:
|
||||
refund_user_limiteds(UserObj)
|
||||
|
||||
|
||||
def delete_limited_assets():
|
||||
from app.models.asset import Asset
|
||||
from app.models.asset_version import AssetVersion
|
||||
from app.models.asset_thumbnail import AssetThumbnail
|
||||
from app.models.user_avatar_asset import UserAvatarAsset
|
||||
|
||||
# Step 1: Get all limited asset IDs
|
||||
limited_assets = Asset.query.filter_by(is_limited=True).all()
|
||||
limited_asset_ids = [asset.id for asset in limited_assets]
|
||||
|
||||
# Step 2: Delete UserAvatarAssets referencing limited assets
|
||||
UserAvatarAsset.query.filter(UserAvatarAsset.asset_id.in_(limited_asset_ids)).delete(synchronize_session=False)
|
||||
db.session.commit()
|
||||
|
||||
# Step 3: Delete related asset versions
|
||||
AssetVersion.query.filter(AssetVersion.asset_id.in_(limited_asset_ids)).delete(synchronize_session=False)
|
||||
|
||||
# Step 4: Delete related asset thumbnails
|
||||
AssetThumbnail.query.filter(AssetThumbnail.asset_id.in_(limited_asset_ids)).delete(synchronize_session=False)
|
||||
db.session.commit()
|
||||
|
||||
# Step 5: Delete the limited assets themselves
|
||||
Asset.query.filter(Asset.id.in_(limited_asset_ids)).delete(synchronize_session=False)
|
||||
db.session.commit()
|
||||
|
||||
def clear_user_avatar_assets():
|
||||
from app.models.user_avatar_asset import UserAvatarAsset
|
||||
from app.models.asset import Asset
|
||||
from app.routes.thumbnailer import TakeUserThumbnail
|
||||
|
||||
NeedReRender : list[int] = []
|
||||
|
||||
AllUserAvatarAssets : list[UserAvatarAsset] = UserAvatarAsset.query.outerjoin(Asset, UserAvatarAsset.asset_id == Asset.id).filter(Asset.id == None).all()
|
||||
for UserAvatarAssetObj in AllUserAvatarAssets:
|
||||
if UserAvatarAssetObj.user_id not in NeedReRender:
|
||||
NeedReRender.append(UserAvatarAssetObj.user_id)
|
||||
db.session.delete(UserAvatarAssetObj)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
for UserId in NeedReRender:
|
||||
logging.info(f"Re-rendering avatar for user {UserId}")
|
||||
TakeUserThumbnail(UserId)
|
||||
|
||||
def clear_bad_transactions():
|
||||
from app.models.user_transactions import UserTransaction
|
||||
from app.models.asset import Asset
|
||||
|
||||
AllBadTransactions : list[UserTransaction] = UserTransaction.query.outerjoin(Asset, UserTransaction.assetId == Asset.id).filter(Asset.id == None).all()
|
||||
print(f"Found {len(AllBadTransactions)} bad transactions")
|
||||
|
||||
while True:
|
||||
BatchTransactions : list[UserTransaction] = AllBadTransactions[:1000]
|
||||
if len(BatchTransactions) == 0:
|
||||
break
|
||||
for TransactionObj in BatchTransactions:
|
||||
db.session.delete(TransactionObj)
|
||||
db.session.commit()
|
||||
AllBadTransactions = AllBadTransactions[1000:]
|
||||
logging.info(f"Deleted 1000 bad transactions, {len(AllBadTransactions)} remaining")
|
||||
|
||||
def delete_asset( asset_id : int ):
|
||||
from app.models.asset import Asset
|
||||
from app.models.asset_version import AssetVersion
|
||||
from app.models.asset_thumbnail import AssetThumbnail
|
||||
|
||||
AllAssetVersions : list[AssetVersion] = AssetVersion.query.filter_by(asset_id=asset_id).all()
|
||||
AllAssetThumbnails : list[AssetThumbnail] = AssetThumbnail.query.filter_by(asset_id=asset_id).all()
|
||||
|
||||
for AssetVersionObj in AllAssetVersions:
|
||||
print(f"Deleting asset version {AssetVersionObj.id}")
|
||||
db.session.delete(AssetVersionObj)
|
||||
for AssetThumbnailObj in AllAssetThumbnails:
|
||||
print(f"Deleting asset thumbnail {AssetThumbnailObj.id}")
|
||||
db.session.delete(AssetThumbnailObj)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
AssetObj : Asset = Asset.query.filter_by(id=asset_id).first()
|
||||
db.session.delete(AssetObj)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
def create_admin_user():
|
||||
"""
|
||||
! FIRST TIME SETUP ONLY !
|
||||
Creates a user with all admin permissions and a random password
|
||||
|
||||
Note: will raise an exception if User ID 1 already exists
|
||||
"""
|
||||
import datetime
|
||||
import random
|
||||
import string
|
||||
from app.models.user import User
|
||||
from app.models.admin_permissions import AdminPermissions
|
||||
from app.models.usereconomy import UserEconomy
|
||||
from app.models.user_avatar import UserAvatar
|
||||
from app.util.auth import SetPassword
|
||||
from app.pages.admin.permissionsdefinition import PermissionsDefinition
|
||||
|
||||
if User.query.filter_by(id=1).first() is not None:
|
||||
raise Exception("User ID 1 already exists")
|
||||
|
||||
NewUser : User = User(
|
||||
username = "Admin",
|
||||
password = "",
|
||||
created = datetime.datetime.utcnow(),
|
||||
lastonline = datetime.datetime.utcnow()
|
||||
)
|
||||
|
||||
db.session.add(NewUser)
|
||||
db.session.commit()
|
||||
|
||||
NewPassword : str = ''.join(random.choice(string.ascii_uppercase + string.ascii_lowercase + string.digits) for _ in range(24))
|
||||
|
||||
SetPassword(
|
||||
UserObj = NewUser,
|
||||
password = NewPassword
|
||||
)
|
||||
|
||||
UserEconomyObj : UserEconomy = UserEconomy(
|
||||
userid = NewUser.id,
|
||||
robux = 0,
|
||||
tix = 0,
|
||||
)
|
||||
|
||||
db.session.add(UserEconomyObj)
|
||||
|
||||
UserAvatarObj : UserAvatar = UserAvatar(
|
||||
user_id = NewUser.id,
|
||||
)
|
||||
|
||||
db.session.add(UserAvatarObj)
|
||||
|
||||
for permission_name in PermissionsDefinition:
|
||||
permissionObj : AdminPermissions = AdminPermissions(
|
||||
userid = NewUser.id,
|
||||
permission = permission_name
|
||||
)
|
||||
db.session.add(permissionObj)
|
||||
|
||||
db.session.commit()
|
||||
|
||||
print(f"""
|
||||
Successfully created Admin User
|
||||
Username: Admin
|
||||
Password: {NewPassword}""")
|
||||
|
||||
def convert_places_to_universes():
|
||||
from app.models.asset import Asset
|
||||
from app.models.place import Place
|
||||
from app.models.universe import Universe
|
||||
from app.models.place_datastore import PlaceDatastore
|
||||
from app.models.place_ordered_datastore import PlaceOrderedDatastore
|
||||
from app.models.legacy_data_persistence import LegacyDataPersistence
|
||||
from app.models.place_badge import PlaceBadge
|
||||
from app.models.gamepass_link import GamepassLink
|
||||
from app.models.place_developer_product import DeveloperProduct
|
||||
|
||||
AllPlaces : list[Place] = Place.query.filter_by( parent_universe_id = 0 ).order_by(Place.placeid).all()
|
||||
logging.info(f"convert_places_to_universes > Found {len(AllPlaces)} places to convert")
|
||||
for PlaceObj in AllPlaces:
|
||||
PlaceObj : Place
|
||||
try:
|
||||
PlaceAssetObj : Asset = Asset.query.filter_by( id = PlaceObj.placeid ).first()
|
||||
UniverseObj : Universe = Universe(
|
||||
root_place_id = PlaceObj.placeid,
|
||||
creator_id = PlaceAssetObj.creator_id,
|
||||
creator_type = PlaceAssetObj.creator_type,
|
||||
place_rig_choice = PlaceObj.rig_choice,
|
||||
place_year = PlaceObj.placeyear,
|
||||
is_featured = PlaceObj.featured,
|
||||
minimum_account_age = PlaceObj.min_account_age,
|
||||
bc_required = PlaceObj.bc_required,
|
||||
allow_direct_join = False,
|
||||
is_public = PlaceObj.is_public,
|
||||
updated_at = PlaceAssetObj.updated_at,
|
||||
created_at = PlaceAssetObj.created_at
|
||||
)
|
||||
db.session.add(UniverseObj)
|
||||
db.session.commit()
|
||||
|
||||
logging.info(f"convert_places_to_universes > Created universe {UniverseObj.id} from place {PlaceObj.placeid}")
|
||||
PlaceObj.parent_universe_id = UniverseObj.id
|
||||
db.session.commit()
|
||||
|
||||
logging.info(f"convert_places_to_universes > Converting place {PlaceObj.placeid}'s items to universe {UniverseObj.id}")
|
||||
|
||||
db.session.query(PlaceDatastore).filter_by( placeid = PlaceObj.placeid ).update({"universe_id": UniverseObj.id})
|
||||
db.session.query(PlaceOrderedDatastore).filter_by( placeid = PlaceObj.placeid ).update({"universe_id": UniverseObj.id})
|
||||
db.session.query(LegacyDataPersistence).filter_by( placeid = PlaceObj.placeid ).update({"universe_id": UniverseObj.id})
|
||||
db.session.query(PlaceBadge).filter_by( associated_place_id = PlaceObj.placeid ).update({"universe_id": UniverseObj.id})
|
||||
db.session.query(GamepassLink).filter_by( place_id = PlaceObj.placeid ).update({"universe_id": UniverseObj.id})
|
||||
db.session.query(DeveloperProduct).filter_by( placeid = PlaceObj.placeid ).update({"universe_id": UniverseObj.id})
|
||||
|
||||
db.session.commit()
|
||||
|
||||
logging.info(f"convert_places_to_universes > Successfully converted place {PlaceObj.placeid}'s items to universe {UniverseObj.id}")
|
||||
except Exception as e:
|
||||
logging.error(f"convert_places_to_universes > Failed to migrate place {PlaceObj.placeid}, error: {e}")
|
||||
|
||||
def recalculate_universe_visits():
|
||||
from app.models.place import Place
|
||||
from app.models.universe import Universe
|
||||
|
||||
AllUniverses : list[Universe] = Universe.query.all()
|
||||
logging.info(f"recalculate_universe_visits > Found {len(AllUniverses)} universes to recalculate")
|
||||
|
||||
for UniverseObj in AllUniverses:
|
||||
try:
|
||||
UniverseObj : Universe
|
||||
UniverseObj.visit_count = Place.query.filter_by( parent_universe_id = UniverseObj.id ).with_entities(func.sum(Place.visitcount)).scalar()
|
||||
db.session.commit()
|
||||
logging.info(f"recalculate_universe_visits > Successfully recalculated universe {UniverseObj.id}, new visit count: {UniverseObj.visit_count}")
|
||||
|
||||
except Exception as e:
|
||||
logging.error(f"recalculate_universe_visits > Failed to recalculate universe {UniverseObj.id}, error: {e}")
|
||||
|
||||
def reverse_item_transfer():
|
||||
from app.models.limited_item_transfers import LimitedItemTransfer
|
||||
from app.models.asset import Asset
|
||||
from app.models.user import User
|
||||
from app.services.economy import IncrementTargetBalance, DecrementTargetBalance, GetAssetRap
|
||||
from app.models.asset_rap import AssetRap
|
||||
from app.models.userassets import UserAsset
|
||||
import math
|
||||
from datetime import datetime
|
||||
from sqlalchemy import and_
|
||||
from app.pages.messages.messages import CreateSystemMessage
|
||||
|
||||
def reverse_transfer( ItemTransferRecordObj : LimitedItemTransfer ):
|
||||
logging.info(f"reverse_item_transfer > Reversing transfer {ItemTransferRecordObj.id}")
|
||||
RecievingUserObj : User = User.query.filter_by( id = ItemTransferRecordObj.new_owner_id ).first()
|
||||
SendingUserObj : User = User.query.filter_by( id = ItemTransferRecordObj.original_owner_id ).first()
|
||||
UserAssetObj : UserAsset = UserAsset.query.filter_by( id = ItemTransferRecordObj.user_asset_id ).first()
|
||||
|
||||
if RecievingUserObj is None or SendingUserObj is None or UserAssetObj is None:
|
||||
logging.error(f"reverse_item_transfer > Unable to find user or asset for transfer {ItemTransferRecordObj.id}")
|
||||
return
|
||||
|
||||
AssetObj : Asset = Asset.query.filter_by( id = ItemTransferRecordObj.asset_id ).first()
|
||||
AssetRapObj : AssetRap = AssetRap.query.filter_by( assetid = AssetObj.id ).first()
|
||||
CurrentRapValue : int = GetAssetRap( AssetObj )
|
||||
ReversedRapValue : int = math.floor( ( ( CurrentRapValue * 10 ) - ItemTransferRecordObj.purchased_price ) / 9 )
|
||||
|
||||
RobuxGivenToOriginalOwner : int = math.floor( ItemTransferRecordObj.purchased_price * 0.7 )
|
||||
|
||||
UserAssetObj.userid = ItemTransferRecordObj.original_owner_id
|
||||
UserAssetObj.updated = datetime.utcnow()
|
||||
UserAssetObj.is_for_sale = False
|
||||
AssetRapObj.rap = ReversedRapValue
|
||||
db.session.commit()
|
||||
|
||||
IncrementTargetBalance( Target = RecievingUserObj, Amount = ItemTransferRecordObj.purchased_price, CurrencyType = 0 )
|
||||
DecrementTargetBalance( Target = SendingUserObj, Amount = RobuxGivenToOriginalOwner, CurrencyType = 0 )
|
||||
|
||||
CreateSystemMessage( subject = "Item Transfer Reversed", message = f"""Hello {RecievingUserObj.username},
|
||||
This is an automated message to inform you that a recent item transfer has been reversed. You have been refunded R$ {ItemTransferRecordObj.purchased_price} for the item {AssetObj.name} which has been taken from your inventory.
|
||||
Please contact us on our Discord Server if you have any questions.
|
||||
|
||||
Sincerely,
|
||||
The Vortexi Team""", userid = RecievingUserObj.id )
|
||||
|
||||
CreateSystemMessage( subject = "Item Transfer Reversed", message = f"""Hello {SendingUserObj.username},
|
||||
This is an automated message to inform you that a recent item transfer has been reversed. R$ {RobuxGivenToOriginalOwner} has been taken from your account and your item ( {AssetObj.name} ) has been returned to your inventory.
|
||||
Please contact us on our Discord Server if you have any questions.
|
||||
|
||||
Sincerely,
|
||||
The Vortexi Team""", userid = SendingUserObj.id )
|
||||
|
||||
logging.info(f"reverse_item_transfer > Successfully reversed transfer {ItemTransferRecordObj.id} - R$ {ItemTransferRecordObj.purchased_price} given to {RecievingUserObj.username}, R$ {RobuxGivenToOriginalOwner} taken from {SendingUserObj.username}")
|
||||
logging.info(f"reverse_item_transfer > New RAP value for asset {AssetObj.id}: {CurrentRapValue} -> {ReversedRapValue}")
|
||||
|
||||
FradulentTransfers : list[LimitedItemTransfer] = LimitedItemTransfer.query.filter(and_( LimitedItemTransfer.id > 453, LimitedItemTransfer.id < 472 )).order_by(LimitedItemTransfer.id.desc()).all()
|
||||
logging.info(f"reverse_item_transfer > Found {len(FradulentTransfers)} fradulent transfers to reverse")
|
||||
|
||||
for TransferObj in FradulentTransfers:
|
||||
reverse_transfer( TransferObj )
|
||||
|
||||
Reference in New Issue
Block a user