Skip to content

Commit 4572ea7

Browse files
Update Roblox upload script (currently broken due to Roblox API changes)
1 parent 48fed61 commit 4572ea7

1 file changed

Lines changed: 47 additions & 34 deletions

File tree

bin/publishToRoblox.js

Lines changed: 47 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -28,17 +28,19 @@ if (!process.env.ROBLOX_PUBLISH_KEY)
2828

2929
const publishEndpoint = 'https://apis.roblox.com/assets/v1/assets'
3030
const operationsEndpoint = 'https://apis.roblox.com/assets/v1/operations'
31-
const assetDeliveryEndpoint = 'https://assetdelivery.roblox.com/v1/asset'
31+
const assetDeliveryEndpoint = 'https://apis.roblox.com/asset-delivery-api/v1/assetId' /* 'https://assetdelivery.roblox.com/v1/asset' */
3232

33-
function handleError(error) {
34-
function RobloxError(message) {
35-
console.log(ansiColors.red(`RobloxError: ${message}`))
36-
process.exit(1)
33+
function handleError(err) {
34+
class RobloxError extends Error {
35+
constructor(msg) {
36+
super(ansiColors.red(msg))
37+
this.name = 'RobloxError'
38+
}
3739
}
38-
if (!error.response) throw error
39-
const { code, message, errors } = error.response.data
40-
if (errors) throw new RobloxError(errors[0].message)
41-
throw new RobloxError(`[${code}] ${message}`)
40+
if (!err.response) throw err
41+
let { code, message, errors } = err.response.data
42+
if (errors) ({ code, message } = errors[0])
43+
throw new RobloxError(`[Code ${code}] ${message}`)
4244
}
4345

4446
async function publishAsset(iconName, filename) {
@@ -65,35 +67,45 @@ async function publishAsset(iconName, filename) {
6567
filename: `${filename}.png`,
6668
contentType: 'image/png',
6769
})
68-
const { data } = await axios.post(publishEndpoint, form, {
69-
headers: {
70-
...form.getHeaders(),
71-
'x-api-key': process.env.ROBLOX_PUBLISH_KEY,
72-
},
73-
responseType: 'json',
74-
}).catch(handleError)
70+
const { data } = await axios
71+
.post(publishEndpoint, form, {
72+
headers: {
73+
...form.getHeaders(),
74+
'x-api-key': process.env.ROBLOX_PUBLISH_KEY,
75+
},
76+
responseType: 'json',
77+
})
78+
.catch(handleError)
7579

7680
return data
7781
}
7882

7983
async function getImageId(assetId) {
80-
const { data } = await axios.get(`${assetDeliveryEndpoint}/?id=${assetId}`)
84+
const { data } = await axios
85+
.get(`${assetDeliveryEndpoint}/${assetId}`, {
86+
headers: { 'x-api-key': process.env.ROBLOX_PUBLISH_KEY },
87+
})
8188
.catch(handleError)
8289

83-
const { window: { document: xmlData } } = new JSDOM(data)
84-
const imageId = xmlData.querySelector('.Decal content[name="Texture"] > url')
85-
.textContent.replace(/.*?\?id=/, '')
90+
const {
91+
window: { document: xmlData },
92+
} = new JSDOM(data)
93+
const imageId = xmlData
94+
.querySelector('.Decal content[name="Texture"] > url')
95+
.textContent.match(/\?id=(\d+)/)[1]
8696

8797
return imageId
8898
}
8999

90100
async function getOperation(operationId) {
91-
const { data } = await axios.get(`${operationsEndpoint}/${operationId}`, {
92-
headers: {
93-
'x-api-key': process.env.ROBLOX_PUBLISH_KEY,
94-
},
95-
responseType: 'json',
96-
}).catch(handleError)
101+
const { data } = await axios
102+
.get(`${operationsEndpoint}/${operationId}`, {
103+
headers: {
104+
'x-api-key': process.env.ROBLOX_PUBLISH_KEY,
105+
},
106+
responseType: 'json',
107+
})
108+
.catch(handleError)
97109
return data
98110
}
99111

@@ -120,11 +132,12 @@ writeFileSync(iconAssetsPath, await prettierFormat(assetData))
120132
if (deletedIcons.length > 0)
121133
console.log(
122134
ansiColors.cyan(`Removed ${deletedIcons.length} deleted icons:`),
123-
deletedIcons.join(', '), '\n'
135+
deletedIcons.join(', '),
136+
'\n'
124137
)
125138

126139
// Publish icons
127-
console.log(ansiColors.yellow(`Publishing ${iconsToPublish.length} icons...`));
140+
console.log(ansiColors.yellow(`Publishing ${iconsToPublish.length} icons...`))
128141

129142
const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
130143

@@ -133,25 +146,25 @@ const sleep = ms => new Promise(resolve => setTimeout(resolve, ms));
133146
try {
134147
const { operationId } = await publishAsset(iconName, kebabCase(iconName))
135148

136-
// Waiting is required due to Roblox rate limits
137149
await sleep(4000)
138150

139151
while (!(await getOperation(operationId)).done) {
140-
console.log(
141-
ansiColors.yellow('Waiting for operation to complete...')
142-
)
152+
console.log(ansiColors.yellow('Waiting for operation to complete...'))
143153
await sleep(4000)
144154
}
145155

146-
const { response: { assetId } } = await getOperation(operationId)
156+
const {
157+
response: { assetId },
158+
} = await getOperation(operationId)
147159
const imageId = await getImageId(assetId)
148160
assetData.assetPaths[iconName] = imageId
149161
uploadedIcons.push({ icon: iconName, assetId: assetId, imageId: imageId })
150162
writeFileSync(iconAssetsPath, await prettierFormat(assetData))
151163
writeFileSync(tempFilePath, await prettierFormat(uploadedIcons))
152164

153165
console.log(
154-
ansiColors.green(`Published ${iconName}:`), ansiColors.cyan(imageId)
166+
ansiColors.green(`Published ${iconName}:`),
167+
ansiColors.cyan(imageId)
155168
)
156169
} catch (err) {
157170
console.log(ansiColors.red(`Error publishing ${iconName}:`))

0 commit comments

Comments
 (0)