Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 94e457f240 | |||
| 83fbf9a91e | |||
| 698f4b10aa | |||
| 3230afae61 |
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
[project]
|
[project]
|
||||||
name = "rbx-upload"
|
name = "rbx-upload"
|
||||||
version = "0.2.6"
|
version = "0.2.10"
|
||||||
description = "Roblox asset upload client"
|
description = "Roblox asset upload client"
|
||||||
requires-python = ">=3.13"
|
requires-python = ">=3.13"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
|
|||||||
@@ -253,6 +253,60 @@ class RobloxClient:
|
|||||||
await asyncio.gather(*[_upload_one(item) for item in items])
|
await asyncio.gather(*[_upload_one(item) for item in items])
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
async def publish_collectible(
|
||||||
|
self,
|
||||||
|
asset_id: int,
|
||||||
|
group_id: int,
|
||||||
|
name: str,
|
||||||
|
description: str,
|
||||||
|
price: int = 5,
|
||||||
|
) -> str:
|
||||||
|
"""Publish an asset as a Limited collectible. Returns the collectibleItemId."""
|
||||||
|
csrf = await self._get_csrf_token()
|
||||||
|
response = await self._http.post(
|
||||||
|
"https://itemconfiguration.roblox.com/v1/collectibles",
|
||||||
|
json={
|
||||||
|
"isRentalOptIn": False,
|
||||||
|
"idempotencyToken": str(uuid.uuid4()),
|
||||||
|
"targetId": asset_id,
|
||||||
|
"targetType": 0,
|
||||||
|
"publishingType": 2,
|
||||||
|
"agreedPublishingFee": 10,
|
||||||
|
"creatorGroupId": group_id,
|
||||||
|
"publisherUserId": self._publisher_user_id,
|
||||||
|
"quantity": 0,
|
||||||
|
"quantityLimitPerUser": 0,
|
||||||
|
"resaleRestriction": 2,
|
||||||
|
"priceInRobux": price,
|
||||||
|
"priceOffset": 0,
|
||||||
|
"optOutFromRegionalPricing": False,
|
||||||
|
"isFree": False,
|
||||||
|
"saleLocationConfiguration": {"saleLocationType": 1, "places": []},
|
||||||
|
"name": name,
|
||||||
|
"description": description,
|
||||||
|
},
|
||||||
|
headers={
|
||||||
|
"X-CSRF-TOKEN": csrf,
|
||||||
|
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:145.0) Gecko/20100101 Firefox/145.0",
|
||||||
|
"Referer": "https://create.roblox.com/",
|
||||||
|
"Origin": "https://create.roblox.com",
|
||||||
|
},
|
||||||
|
cookies=self._csrf_cookies,
|
||||||
|
)
|
||||||
|
|
||||||
|
if response.status_code == 429:
|
||||||
|
raise RateLimitError("Rate limit hit during collectible publish.")
|
||||||
|
if response.status_code in (401, 403):
|
||||||
|
raise AuthError(f"Not authorized to publish this collectible ({response.status_code}): {response.text}")
|
||||||
|
|
||||||
|
response.raise_for_status()
|
||||||
|
data = response.json()
|
||||||
|
collectible_item_id = data.get("collectibleItemId")
|
||||||
|
if not collectible_item_id:
|
||||||
|
# status=0 means already published — look up the ID
|
||||||
|
collectible_item_id = await self.get_collectible_item_id(asset_id)
|
||||||
|
return collectible_item_id
|
||||||
|
|
||||||
async def onsale_asset(
|
async def onsale_asset(
|
||||||
self,
|
self,
|
||||||
collectible_item_id: str,
|
collectible_item_id: str,
|
||||||
@@ -293,11 +347,11 @@ class RobloxClient:
|
|||||||
"""Look up the collectible item ID (UUID) for a given asset ID, retrying until available."""
|
"""Look up the collectible item ID (UUID) for a given asset ID, retrying until available."""
|
||||||
for _ in range(max_attempts):
|
for _ in range(max_attempts):
|
||||||
response = await self._http.get(
|
response = await self._http.get(
|
||||||
self._proxy_url(f"https://economy.roblox.com/v2/assets/{asset_id}/details"),
|
f"https://itemconfiguration.roblox.com/v1/collectibles/0/{asset_id}",
|
||||||
cookies=self._csrf_cookies,
|
cookies=self._csrf_cookies,
|
||||||
)
|
)
|
||||||
response.raise_for_status()
|
response.raise_for_status()
|
||||||
collectible_item_id = response.json().get("CollectibleItemId")
|
collectible_item_id = response.json().get("collectibleItemId")
|
||||||
if collectible_item_id:
|
if collectible_item_id:
|
||||||
return collectible_item_id
|
return collectible_item_id
|
||||||
await asyncio.sleep(poll_interval)
|
await asyncio.sleep(poll_interval)
|
||||||
|
|||||||
Reference in New Issue
Block a user