It’ll come from the previous request, if there are pages which can still be retrieved afterwards.
I’ve updated the function to also request subsequent pages. If you get rate limited, you’ll need to yield in between requests. I haven’t tested this code, so lmk if u get errors.
async function getUserMembershipId(targetUserId) {
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
console.log(response.status!==200?String(response.Status) + response.statusText:"Request ok. Code 200.");
let data = await response.json();
if (response.status !== 200) {
console.log(data.message);
};
let pageToken = data.nextPageToken;
let currentPage = data.groupMemberships;
while (pageToken) {
for (let membership of currentPage) {
//check to see if it's the UserId of the user we want
let splitted = membership.user.split("/");
let userId = splitted[splitted.length - 1];
if (userId == targetUserId) {
//the UserIds match! Now, return the membership ID
let membershipId = membership.path.split("/")[3];
return membershipId;
}
}
//membership not found on this page, let's advance to the next one
let newResponse = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50&pageToken=${pageToken}`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
if (!newResponse.ok) { //if it failed for whatever reason
warn("Failed to retrieve subsequent pages. Error code:", newResponse.status);
break;
};
let newData = await newResponse.json();
pageToken, currentPage = newData.nextPageToken, newData.groupMemberships;
}
};
I got an error saying ReferenceError: pageToken is not defined
at getUserMembershipId (C:\Users\jenkins\Videos\fuelsystem\index.js:47:12)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async updateRoleProcess (C:\Users\jenkins\Videos\fuelsystem\index.js:101:24)
I got another error saying Request ok. Code 200.
TypeError: Cannot read properties of undefined (reading ‘split’)
at getUserMembershipId (C:\Users\jenkins\Videos\fuelsystem\index.js:50:44)
at process.processTicksAndRejections (node:internal/process/task_queues:105:5)
at async updateRoleProcess (C:\Users\jenkins\Videos\fuelsystem\index.js:102:24)
It’s my first time working with paginated data in this context, so you’ll need to bare with.
I’ve tested this and it should work.
async function getUserMembershipId(targetUserId) {
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
console.log(response.status!==200?String(response.Status) + response.statusText:"Request ok. Code 200.");
let data = await response.json();
if (response.status !== 200) {
console.log(data.message);
};
let pageToken = data.nextPageToken;
let currentPage = data.groupMemberships;
while (pageToken) {
for (let membership of currentPage) {
if (!membership.user || !membership.path) {continue;};
//check to see if it's the UserId of the user we want
let splitted = membership.user.split("/");
let userId = splitted[splitted.length - 1];
if (userId == targetUserId) {
//the UserIds match! Now, return the membership ID
let membershipId = membership.path.split("/")[3];
return membershipId;
}
}
//membership not found on this page, let's advance to the next one
let newResponse = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50&pageToken=${pageToken}`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
if (!newResponse.ok) { //if it failed for whatever reason
warn("Failed to retrieve subsequent pages. Error code:", newResponse.status);
break;
};
let newData = await newResponse.json();
pageToken = newData.nextPageToken;
currentPage = newData.groupMemberships;
}
};
it prints out false false
false false
false false
false false
false false
false false
Failed to parse resource path and its identifiers - groups/7045894/memberships/undefined.
That means it’s checked all the pages of users of that group and not found the user. Or, there are no more pages to check, so the iteration never starts and no users are checked.
Could you answer my earlier question of how many people are at that rank in the group? It can affect the code’s result.
In the meantime, here’s something to account for the group not having enough people for multiple pages:
async function getUserMembershipId(targetUserId) {
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
console.log(response.status!==200?String(response.Status) + response.statusText:"Request ok. Code 200.");
let data = await response.json();
if (response.status !== 200) {
console.log(data.message);
};
let pageToken = data.nextPageToken || 1;
let currentPage = data.groupMemberships;
while (pageToken) {
for (let membership of currentPage) {
if (!membership.user || !membership.path) {continue;};
//check to see if it's the UserId of the user we want
let splitted = membership.user.split("/");
let userId = splitted[splitted.length - 1];
if (userId == targetUserId) {
//the UserIds match! Now, return the membership ID
let splitted = membership.path.split("/");
let membershipId = splitted[splitted.length - 1];
return membershipId;
}
}
if (pageToken === 1) {
pageToken = 0;
continue;
};
//membership not found on this page, let's advance to the next one
let newResponse = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50&pageToken=${pageToken}`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
if (!newResponse.ok) { //if it failed for whatever reason
warn("Failed to retrieve subsequent pages. Error code:", newResponse.status);
break;
};
let newData = await newResponse.json();
pageToken = newData.nextPageToken;
currentPage = newData.groupMemberships;
}
};
The only thing that could be causing the issue now is incorrect data.
Here’s the full code snippet:
const apiKey = "";
const groupId = 0;
const targetRole = "Rank name";
const targetUserId = 0;
async function getGroupRoleId(targetRole) {
//send the GET request
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/roles?maxPageSize=20`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
let data = await response.json()
if (response.status !== 200) {
console.log(data.message);
}
for (let role of data.groupRoles) {
if (role.displayName === targetRole) {
return Number(role.id);
}
}
};
async function getUserMembershipId(targetUserId) {
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
console.log(response.status!==200?String(response.Status) + response.statusText:"Request ok. Code 200.");
let data = await response.json();
if (response.status !== 200) {
console.log(data.message);
};
let pageToken = data.nextPageToken || 1;
let currentPage = data.groupMemberships;
while (pageToken) {
for (let membership of currentPage) {
if (!membership.user || !membership.path) {continue;};
//check to see if it's the UserId of the user we want
let splitted = membership.user.split("/");
let userId = splitted[splitted.length - 1];
if (userId == targetUserId) {
//the UserIds match! Now, return the membership ID
let splitted = membership.path.split("/");
let membershipId = splitted[splitted.length - 1];
return membershipId;
}
}
if (pageToken === 1) {
pageToken = 0;
continue;
};
//membership not found on this page, let's advance to the next one
let newResponse = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50&pageToken=${pageToken}`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
if (!newResponse.ok) { //if it failed for whatever reason
warn("Failed to retrieve subsequent pages. Error code:", newResponse.status);
break;
};
let newData = await newResponse.json();
pageToken = newData.nextPageToken;
currentPage = newData.groupMemberships;
}
};
async function updateUserRole(targetRoleId, targetMembershipId) {
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships/${targetMembershipId}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"x-api-key": apiKey
},
body: JSON.stringify({
"role": `groups/${groupId}/roles/${targetRoleId}`
})
});
let data = await response.json();
if (response.status !== 200) {
console.log(data.message);
} else {
console.log("Request ok. Code 200.")
};
};
async function updateRoleProcess(userId, roleName) {
let roleId = await getGroupRoleId(roleName);
let membershipId = await getUserMembershipId(userId);
await updateUserRole(roleId, membershipId);
};
updateRoleProcess(targetUserId, targetRole).catch(error => console.log(error));
Even though you have previously said they are correct, please copy and paste the things exactly into the corresponding constants:
API key, as a string
Group ID
Target UserId
Target role name, as a string
The code itself is fine, it accounts for groups with enough members for multiple pages as well as groups with not enough members for more than one page. I have tested with both types.
If you get an error, could you also send the code around the line the error came from?
That looks like an internal Node.js error, unless you input one of the constants which are substituted into the URL wrong. Check your constants and try again.
const groupId = 7045894;
const targetRole = "Suspended";
const targetUserId = 7030584619;
async function getGroupRoleId(targetRole) {
//send the GET request
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/roles?maxPageSize=20`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
let data = await response.json()
if (response.status !== 200) {
console.log(data.message);
}
for (let role of data.groupRoles) {
if (role.displayName === targetRole) {
return Number(role.id);
}
}
};
async function getUserMembershipId(targetUserId) {
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
console.log(response.status!==200?String(response.Status) + response.statusText:"Request ok. Code 200.");
let data = await response.json();
if (response.status !== 200) {
console.log(data.message);
};
let pageToken = data.nextPageToken || 1;
let currentPage = data.groupMemberships;
while (pageToken) {
for (let membership of currentPage) {
if (!membership.user || !membership.path) {continue;};
//check to see if it's the UserId of the user we want
let splitted = membership.user.split("/");
let userId = splitted[splitted.length - 1];
if (userId == targetUserId) {
//the UserIds match! Now, return the membership ID
let splitted = membership.path.split("/");
let membershipId = splitted[splitted.length - 1];
return membershipId;
}
}
if (pageToken === 1) {
pageToken = 0;
continue;
};
//membership not found on this page, let's advance to the next one
let newResponse = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50&pageToken=${pageToken}`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
if (!newResponse.ok) { //if it failed for whatever reason
warn("Failed to retrieve subsequent pages. Error code:", newResponse.status);
break;
};
let newData = await newResponse.json();
pageToken = newData.nextPageToken;
currentPage = newData.groupMemberships;
}
};
async function updateUserRole(targetRoleId, targetMembershipId) {
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships/${targetMembershipId}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"x-api-key": apiKey
},
body: JSON.stringify({
"role": `groups/${groupId}/roles/${targetRoleId}`
})
});
let data = await response.json();
if (response.status !== 200) {
console.log(data.message);
} else {
console.log("Request ok. Code 200.")
};
};
async function updateRoleProcess(userId, roleName) {
let roleId = await getGroupRoleId(roleName);
let membershipId = await getUserMembershipId(userId);
await updateUserRole(roleId, membershipId);
};
updateRoleProcess(targetUserId, targetRole).catch(error => console.log(error));
const groupId = 7045894;
const targetRole = "Suspended";
const targetUserId = 7030584619;
async function getGroupRoleId(targetRole) {
//send the GET request
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/roles?maxPageSize=20`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
let data = await response.json()
if (response.status !== 200) {
console.log(data.message);
}
for (let role of data.groupRoles) {
if (role.displayName === targetRole) {
return Number(role.id);
}
}
};
async function getUserMembershipId(targetUserId) {
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
console.log(response.status!==200?String(response.Status) + response.statusText:"Request ok. Code 200.");
let data = await response.json();
if (response.status !== 200) {
console.log(data.message);
};
let pageToken = data.nextPageToken || 1;
let currentPage = data.groupMemberships;
while (pageToken) {
for (let membership of currentPage) {
if (!membership.user || !membership.path) {continue;};
//check to see if it's the UserId of the user we want
let splitted = membership.user.split("/");
let userId = splitted[splitted.length - 1];
if (userId == targetUserId) {
//the UserIds match! Now, return the membership ID
let splitted = membership.path.split("/");
let membershipId = splitted[splitted.length - 1];
return membershipId;
}
}
if (pageToken === 1) {
pageToken = 0;
continue;
};
//membership not found on this page, let's advance to the next one
let newResponse = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships?maxPageSize=50&pageToken=${pageToken}`, {
method: "GET",
headers: {
"x-api-key": apiKey
}
});
if (!newResponse.ok) { //if it failed for whatever reason
warn("Failed to retrieve subsequent pages. Error code:", newResponse.status);
break;
};
let newData = await newResponse.json();
pageToken = newData.nextPageToken || 1;
currentPage = newData.groupMemberships;
}
};
async function updateUserRole(targetRoleId, targetMembershipId) {
let response = await fetch(`https://apis.roblox.com/cloud/v2/groups/${groupId}/memberships/${targetMembershipId}`, {
method: "PATCH",
headers: {
"Content-Type": "application/json",
"x-api-key": apiKey
},
body: JSON.stringify({
"role": `groups/${groupId}/roles/${targetRoleId}`
})
});
let data = await response.json();
if (response.status !== 200) {
console.log(data.message);
} else {
console.log("Request ok. Code 200.")
};
};
async function updateRoleProcess(userId, roleName) {
let roleId = await getGroupRoleId(roleName);
let membershipId = await getUserMembershipId(userId);
await updateUserRole(roleId, membershipId);
};
updateRoleProcess(targetUserId, targetRole).catch(error => console.log(error));