This repository was archived by the owner on Mar 29, 2026. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 143
BREAKING CHANGE: Groups methods overhaul #876
Merged
Merged
Changes from 10 commits
Commits
Show all changes
17 commits
Select commit
Hold shift + click to select a range
c30f6c0
getGroups -> getUserGroups
Regalijan f40a83d
Add multigetPartialGroups
Regalijan 364a853
Update imports for the new things
Regalijan 9d8da1e
Include locked groups
Regalijan 2eac65f
Add tests
Regalijan cf8728b
indent fix
Regalijan 7d867e2
Add getPrimaryGroup
Regalijan 664dab1
Import getPrimaryGroup
Regalijan 48c3074
Return the body, not the whole response
Regalijan 5b9a4e4
Allow fetching multiple groups with getLogo
Regalijan c13fb1b
me when no file extension
Regalijan 2cdc12b
Fix jsdoc
Regalijan 4e45c42
Make sure types match
Regalijan 9cf7f12
Add optional color property to Role interface
Regalijan c6d4e21
Add optional color property to role type jsdoc
Regalijan 0854bb9
Remove isLocked property
Regalijan c04646c
Add PrimaryGroup type
Regalijan File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // Includes | ||
| const http = require('../util/http.js').func | ||
| const RobloxAPIError = require('../util/apiError.js') | ||
|
|
||
| // Args | ||
| exports.required = ['userId'] | ||
| exports.optional = [] | ||
|
|
||
| // Docs | ||
| /** | ||
| * ✅Gets the specified user's primary group. | ||
| * @category User | ||
| * @alias getPrimaryGroup | ||
| * @param {number} userId - The ID of the user. | ||
| * @returns {Promise<Group>} | ||
| * @example const noblox = require("noblox.js") | ||
| * const primaryGroup = await noblox.getPrimaryGroup(1) | ||
| **/ | ||
|
|
||
| // Define | ||
| exports.func = async function (args) { | ||
| const { userId } = args | ||
|
|
||
| const response = await http({ | ||
| url: `https://groups.roblox.com/v1/users/${userId}/groups/primary/role`, | ||
| options: { | ||
| json: true, | ||
| resolveWithFullResponse: true | ||
| } | ||
| }) | ||
|
|
||
| if (response.statusCode !== 200) { | ||
| throw new RobloxAPIError(response) | ||
| } | ||
|
|
||
| return response.body | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| // Includes | ||
| const http = require('../util/http.js').func | ||
| const RobloxAPIError = require('../util/apiError.js') | ||
|
|
||
| // Args | ||
| exports.required = ['userId'] | ||
| exports.optional = [] | ||
|
|
||
| // Docs | ||
| /** | ||
| * ✅ Get the groups of a user. | ||
| * @category User | ||
| * @alias getUserGroups | ||
| * @param {number} userId - The id of the user. | ||
| * @returns {Promise<GroupMemberInfo[]>} | ||
| * @example const noblox = require("noblox.js") | ||
| * let groups = await noblox.getGroups(123456) | ||
|
Regalijan marked this conversation as resolved.
Outdated
|
||
| **/ | ||
|
|
||
| // Define | ||
| exports.func = async function (args) { | ||
| const { userId } = args | ||
|
|
||
| const response = await http({ | ||
| url: `https://groups.roblox.com/v2/users/${userId}/groups/roles?includeLocked=true`, | ||
| options: { | ||
| json: true, | ||
| resolveWithFullResponse: true | ||
| } | ||
| }) | ||
|
|
||
| if (response.statusCode !== 200) { | ||
| throw new RobloxAPIError(response) | ||
| } | ||
|
|
||
| return response.body.data | ||
| } | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,44 @@ | ||
| // Includes | ||
| const http = require('../util/http.js').func | ||
| const RobloxAPIError = require('../util/apiError') | ||
|
|
||
| // Args | ||
| exports.required = ['groupIds'] | ||
| exports.optional = [] | ||
|
|
||
| // Docs | ||
| /** | ||
| * ✅ Gets partial info of multiple groups. | ||
| * @category Group | ||
| * @alias multigetPartialGroups | ||
| * @param {number[]} groupIds - Array of group IDs. | ||
| * @returns {Promise<GroupMultigetPartial[]>} | ||
| * @example const noblox = require("noblox.js") | ||
| * const groupsInfo = await noblox.multigetPartialGroups([1,2,3]) | ||
| **/ | ||
|
|
||
| exports.func = async function (args) { | ||
| const { groupIds } = args | ||
|
|
||
| if (!Array.isArray(groupIds)) throw TypeError('Group IDs must be an array') | ||
|
|
||
| const response = await http({ | ||
| url: `https://groups.roblox.com/v2/groups?groupIds=${groupIds.join(',')}`, | ||
| options: { | ||
| json: true, | ||
| resolveWithFullResponse: true | ||
| } | ||
| }) | ||
|
|
||
| if (response.statusCode !== 200) { | ||
| throw new RobloxAPIError(response) | ||
| } | ||
|
|
||
| const { data } = response.body | ||
|
|
||
| for (let i = 0, len = data.length; i < len; i++) { | ||
| data[i].created = new Date(data[i].created) | ||
| } | ||
|
|
||
| return data | ||
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,56 +1,61 @@ | ||
| // Includes | ||
| const http = require('../util/http.js').func | ||
| const RobloxAPIError = require('../util/apiError.js') | ||
|
|
||
| // Args | ||
| exports.required = ['group'] | ||
| exports.optional = ['size', 'circular', 'format'] | ||
|
|
||
| // Docs | ||
| /** | ||
| * ✅ Get the group's logo. | ||
| * @category Group | ||
| * @alias getLogo | ||
| * @param {number} group - The id of the group. | ||
| * @param {GroupIconSize=} [size=150x150] - The size of the logo. | ||
| * @param {boolean=} [circular=false] - Get the circular version of the logo. | ||
| * @param {GroupIconFormat=} [format=Png] - The file format of the logo. | ||
| * @returns {Promise<string>} | ||
| * @example const noblox = require("noblox.js") | ||
| * const logo = await noblox.getLogo(1) | ||
| **/ | ||
|
|
||
| // Define | ||
| function getLogo (group, size, circular, format) { | ||
| const httpOpt = { | ||
| url: '//thumbnails.roblox.com/v1/groups/icons', | ||
| options: { | ||
| qs: { | ||
| groupIds: group, | ||
| size: size || '150x150', | ||
| format: format || 'Png', | ||
| isCircular: circular | ||
| }, | ||
| json: true, | ||
| resolveWithFullResponse: true | ||
| } | ||
| } | ||
| return http(httpOpt) | ||
| .then(function (res) { | ||
| if (res.statusCode !== 200) { | ||
| throw new RobloxAPIError(res) | ||
| } | ||
|
|
||
| const thumbnailData = res.body.data[0] | ||
|
|
||
| if (thumbnailData.state !== 'Completed') { | ||
| throw new Error('The requested image has not been approved. Status: ' + thumbnailData.state) | ||
| } | ||
|
|
||
| return thumbnailData.imageUrl | ||
| }) | ||
| } | ||
|
|
||
| exports.func = function (args) { | ||
| return getLogo(args.group) | ||
| } | ||
| // Includes | ||
| const http = require('../util/http.js').func | ||
| const RobloxAPIError = require('../util/apiError.js') | ||
|
|
||
| // Args | ||
| exports.required = ['group'] | ||
| exports.optional = ['size', 'circular', 'format'] | ||
|
|
||
| // Docs | ||
| /** | ||
| * ✅ Get the group's logo. | ||
| * @category Group | ||
| * @alias getLogo | ||
| * @param {number || number[]} group - The id(s) of the group. | ||
| * @param {GroupIconSize=} [size=150x150] - The size of the logo. | ||
| * @param {boolean=} [circular=false] - Get the circular version of the logo. | ||
| * @param {GroupIconFormat=} [format=Png] - The file format of the logo. | ||
| * @returns {Promise<string> || Promise<string[]>} | ||
| * @example const noblox = require("noblox.js") | ||
| * const logo = await noblox.getLogo(1) | ||
| **/ | ||
|
|
||
| // Define | ||
| function getLogo (group, size, circular, format) { | ||
| const groupIds = Array.isArray(group) ? group.join(',') : group | ||
| const httpOpt = { | ||
| url: '//thumbnails.roblox.com/v1/groups/icons', | ||
| options: { | ||
| qs: { | ||
| groupIds, | ||
| size: size || '150x150', | ||
| format: format || 'Png', | ||
| isCircular: circular | ||
| }, | ||
| json: true, | ||
| resolveWithFullResponse: true | ||
| } | ||
| } | ||
| return http(httpOpt) | ||
| .then(function (res) { | ||
| if (res.statusCode !== 200) { | ||
| throw new RobloxAPIError(res) | ||
| } | ||
|
|
||
| const urls = [] | ||
|
|
||
| for (const thumb of res.body.data) { | ||
| if (thumb.state !== 'Completed') { | ||
| throw new Error(`The requested image for group ${thumb.targetId} has not been approved. State: ${thumb.state}`) | ||
| } | ||
|
|
||
| urls.push(thumb.imageUrl) | ||
| } | ||
|
|
||
| return urls.length > 1 ? urls : urls.at(0) | ||
| }) | ||
| } | ||
|
|
||
| exports.func = function (args) { | ||
| return getLogo(args.group) | ||
| } |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does it? Or does it return a GroupMemberInfo
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Primary group endpoint returns whole group object.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
https://groups.roblox.com/v1/users/66592931/groups/primary/role
{"group":{"id":3812352,"name":"Polaris Incorporated","description":"Polaris incorporated. The Polaris bot will shut down on the First of March 2022. Thank you all for coming along for the ride. We're proud of what we achieved: From a Project that didn't set out to achieve much at all, except be a hobby of mine.","owner":{"hasVerifiedBadge":false,"userId":66592931,"username":"Neztore","displayName":"Neztore"},"shout":null,"isBuildersClubOnly":false,"publicEntryAllowed":false,"hasVerifiedBadge":false,"hasSocialModules":true},"role":{"id":26008925,"name":"Dev","rank":255,"color":0}}Isn't that a GroupMemberInfo?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I ended up making a new type using the existing Group and Role types, since the primary group returns the full group object (which is not present in the GroupMemberInfo type)