noblox-asset.js 7.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
- package/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
- package/.github/workflows/doc-publish.yml +33 -0
- package/.github/workflows/npmpublish.yml +72 -0
- package/.github/workflows/run-tests.yml +49 -0
- package/CODE_OF_CONDUCT.md +76 -0
- package/LICENSE +21 -0
- package/README.md +182 -0
- package/eslint.config.mjs +34 -0
- package/examples/cleanPlayers.js +130 -0
- package/examples/cleanWall.js +110 -0
- package/examples/revertRanks.js +100 -0
- package/examples/savePlayers.js +119 -0
- package/examples/saveWall.js +96 -0
- package/img/moderatedThumbnails/moderatedThumbnail_100x100.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_110x110.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_140x140.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_150x150.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_150x200.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_180x180.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_250x250.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_30x30.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_352x352.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_420x420.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_48x48.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_50x50.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_60x60.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_720x720.png +0 -0
- package/img/moderatedThumbnails/moderatedThumbnail_75x75.png +0 -0
- package/img/noblox-js-small.png +0 -0
- package/img/noblox-js.png +0 -0
- package/img/thumbnailSizes.png +0 -0
- package/jsDocsConfig.json +55 -0
- package/lib/accountinformation/getUserSocialLinks.js +40 -0
- package/lib/accountsettings/block.js +53 -0
- package/lib/accountsettings/unblock.js +53 -0
- package/lib/asset/deleteFromInventory.js +56 -0
- package/lib/asset/getGamePassProductInfo.js +50 -0
- package/lib/asset/getProductInfo.js +46 -0
- package/lib/asset/uploadAnimation.js +103 -0
- package/lib/asset/uploadItem.js +83 -0
- package/lib/asset/uploadModel.js +90 -0
- package/lib/avatar/avatarRules.js +39 -0
- package/lib/avatar/currentlyWearing.js +33 -0
- package/lib/avatar/getAvatar.js +36 -0
- package/lib/avatar/getCurrentAvatar.js +38 -0
- package/lib/avatar/getRecentItems.js +36 -0
- package/lib/avatar/outfitDetails.js +33 -0
- package/lib/avatar/outfits.js +38 -0
- package/lib/avatar/redrawAvatar.js +47 -0
- package/lib/avatar/removeAssetId.js +51 -0
- package/lib/avatar/setAvatarBodyColors.js +61 -0
- package/lib/avatar/setAvatarScales.js +61 -0
- package/lib/avatar/setPlayerAvatarType.js +51 -0
- package/lib/avatar/setWearingAssets.js +51 -0
- package/lib/avatar/wearAssetId.js +51 -0
- package/lib/badges/getAwardedTimestamps.js +49 -0
- package/lib/badges/getBadgeInfo.js +44 -0
- package/lib/badges/getGameBadges.js +63 -0
- package/lib/badges/getPlayerBadges.js +28 -0
- package/lib/badges/updateBadgeInfo.js +75 -0
- package/lib/cache/add.js +14 -0
- package/lib/cache/addIf.js +26 -0
- package/lib/cache/clear.js +8 -0
- package/lib/cache/get.js +28 -0
- package/lib/cache/index.js +17 -0
- package/lib/cache/new.js +12 -0
- package/lib/cache/wrap.js +25 -0
- package/lib/chat/addUsersToConversation.js +58 -0
- package/lib/chat/chatSettings.js +34 -0
- package/lib/chat/getChatMessages.js +41 -0
- package/lib/chat/getConversations.js +44 -0
- package/lib/chat/getRolloutSettings.js +36 -0
- package/lib/chat/getUnreadConversationCount.js +34 -0
- package/lib/chat/getUnreadMessages.js +39 -0
- package/lib/chat/getUserConversations.js +38 -0
- package/lib/chat/markChatAsRead.js +53 -0
- package/lib/chat/markChatAsSeen.js +51 -0
- package/lib/chat/multiGetLatestMessages.js +38 -0
- package/lib/chat/onNewConversation.js +50 -0
- package/lib/chat/onNewMessage.js +53 -0
- package/lib/chat/onNewMessageBySelf.js +50 -0
- package/lib/chat/onUserOnline.js +50 -0
- package/lib/chat/onUserTyping.js +54 -0
- package/lib/chat/removeFromGroupConversation.js +59 -0
- package/lib/chat/renameGroupConversation.js +58 -0
- package/lib/chat/sendChatMessage.js +58 -0
- package/lib/chat/setChatUserTyping.js +58 -0
- package/lib/chat/start121Conversation.js +51 -0
- package/lib/chat/startCloudEditConversation.js +51 -0
- package/lib/chat/startGroupConversation.js +59 -0
- package/lib/client/onNotification.js +86 -0
- package/lib/client/setAPIKey.js +18 -0
- package/lib/client/setCookie.js +38 -0
- package/lib/datastores/deleteDatastoreEntry.js +56 -0
- package/lib/datastores/getDatastoreEntry.js +88 -0
- package/lib/datastores/getDatastoreEntryVersions.js +73 -0
- package/lib/datastores/getDatastoreKeys.js +63 -0
- package/lib/datastores/getDatastores.js +62 -0
- package/lib/datastores/incrementDatastoreEntry.js +83 -0
- package/lib/datastores/setDatastoreEntry.js +80 -0
- package/lib/develop/canManage.js +42 -0
- package/lib/develop/configureItem.js +210 -0
- package/lib/develop/updateUniverse.js +52 -0
- package/lib/develop/updateUniverseAccess.js +54 -0
- package/lib/economy/getGroupFunds.js +42 -0
- package/lib/economy/getGroupPayoutEligibility.js +55 -0
- package/lib/economy/getGroupRevenueSummary.js +42 -0
- package/lib/economy/getGroupTransactions.js +32 -0
- package/lib/economy/getResaleData.js +48 -0
- package/lib/economy/getResellers.js +35 -0
- package/lib/economy/getUserFunds.js +43 -0
- package/lib/economy/getUserTransactions.js +34 -0
- package/lib/economy/onGroupTransaction.js +74 -0
- package/lib/friends/acceptFriendRequest.js +54 -0
- package/lib/friends/declineAllFriendRequests.js +52 -0
- package/lib/friends/declineFriendRequest.js +54 -0
- package/lib/friends/getFollowerCount.js +35 -0
- package/lib/friends/getFollowers.js +56 -0
- package/lib/friends/getFollowingCount.js +35 -0
- package/lib/friends/getFollowings.js +56 -0
- package/lib/friends/getFriendCount.js +35 -0
- package/lib/friends/getFriendRequests.js +51 -0
- package/lib/friends/getFriends.js +48 -0
- package/lib/friends/onFriendRequest.js +58 -0
- package/lib/friends/removeFriend.js +53 -0
- package/lib/friends/sendFriendRequest.js +54 -0
- package/lib/friends/unfollow.js +53 -0
- package/lib/games/addDeveloperProduct.js +53 -0
- package/lib/games/configureGamePass.js +126 -0
- package/lib/games/getDeveloperProducts.js +44 -0
- package/lib/games/getGameInstances.js +31 -0
- package/lib/games/getGamePasses.js +39 -0
- package/lib/games/getGameRevenue.js +48 -0
- package/lib/games/getGameSocialLinks.js +42 -0
- package/lib/games/getGroupGames.js +30 -0
- package/lib/games/getPlaceInfo.js +47 -0
- package/lib/games/getUniverseInfo.js +50 -0
- package/lib/games/publishToTopic.js +52 -0
- package/lib/games/sendUserNotification.js +65 -0
- package/lib/games/updateDeveloperProduct.js +56 -0
- package/lib/groups/banFromGroup.js +47 -0
- package/lib/groups/changeRank.js +59 -0
- package/lib/groups/deleteWallPost.js +59 -0
- package/lib/groups/deleteWallPostsByUser.js +55 -0
- package/lib/groups/demote.js +25 -0
- package/lib/groups/exile.js +55 -0
- package/lib/groups/getAuditLog.js +64 -0
- package/lib/groups/getGroup.js +50 -0
- package/lib/groups/getGroupBans.js +37 -0
- package/lib/groups/getGroupSocialLinks.js +41 -0
- package/lib/groups/getGroups.js +82 -0
- package/lib/groups/getJoinRequest.js +47 -0
- package/lib/groups/getJoinRequests.js +53 -0
- package/lib/groups/getPlayers.js +103 -0
- package/lib/groups/getRankInGroup.js +45 -0
- package/lib/groups/getRankNameInGroup.js +44 -0
- package/lib/groups/getRole.js +64 -0
- package/lib/groups/getRolePermissions.js +48 -0
- package/lib/groups/getRoles.js +53 -0
- package/lib/groups/getShout.js +47 -0
- package/lib/groups/getWall.js +56 -0
- package/lib/groups/groupPayout.js +103 -0
- package/lib/groups/handleJoinRequest.js +57 -0
- package/lib/groups/handleJoinRequests.js +61 -0
- package/lib/groups/leaveGroup.js +56 -0
- package/lib/groups/onAuditLog.js +62 -0
- package/lib/groups/onJoinRequest.js +63 -0
- package/lib/groups/onJoinRequestHandle.js +105 -0
- package/lib/groups/onShout.js +57 -0
- package/lib/groups/onWallPost.js +58 -0
- package/lib/groups/promote.js +25 -0
- package/lib/groups/searchGroups.js +32 -0
- package/lib/groups/setGroupDescription.js +58 -0
- package/lib/groups/setGroupName.js +59 -0
- package/lib/groups/setRank.js +74 -0
- package/lib/groups/setRoleInfo.js +84 -0
- package/lib/groups/shout.js +58 -0
- package/lib/groups/unbanFromGroup.js +41 -0
- package/lib/index.js +212 -0
- package/lib/internal/levelOneCopy.js +16 -0
- package/lib/internal/queue.js +61 -0
- package/lib/internal/timeout.js +30 -0
- package/lib/internal/wrap.js +78 -0
- package/lib/inventory/getCollectibles.js +31 -0
- package/lib/inventory/getInventory.js +32 -0
- package/lib/inventory/getInventoryById.js +31 -0
- package/lib/inventory/getOwnership.js +47 -0
- package/lib/inventory/getUAIDs.js +47 -0
- package/lib/itemconfiguration/getGroupAssets.js +32 -0
- package/lib/options.js +26 -0
- package/lib/party/onPartyDeleted.js +53 -0
- package/lib/party/onPartyInvite.js +53 -0
- package/lib/party/onPartyJoinedGame.js +53 -0
- package/lib/party/onPartyLeftGame.js +53 -0
- package/lib/party/onPartySelfJoined.js +53 -0
- package/lib/party/onPartySelfLeft.js +53 -0
- package/lib/party/onPartyUserJoined.js +53 -0
- package/lib/party/onPartyUserLeft.js +53 -0
- package/lib/premiumfeatures/getPremium.js +46 -0
- package/lib/presence/getPresences.js +60 -0
- package/lib/privatemessages/getMessages.js +55 -0
- package/lib/privatemessages/message.js +75 -0
- package/lib/privatemessages/onMessage.js +89 -0
- package/lib/thumbnails/getLogo.js +56 -0
- package/lib/thumbnails/getPlayerThumbnail.js +120 -0
- package/lib/thumbnails/getThumbnails.js +92 -0
- package/lib/trades/acceptTrade.js +52 -0
- package/lib/trades/canTradeWith.js +43 -0
- package/lib/trades/counterTrade.js +78 -0
- package/lib/trades/declineTrade.js +52 -0
- package/lib/trades/getTradeInfo.js +47 -0
- package/lib/trades/getTrades.js +37 -0
- package/lib/trades/sendTrade.js +76 -0
- package/lib/users/getBlurb.js +37 -0
- package/lib/users/getIdFromUsername.js +56 -0
- package/lib/users/getPlayerInfo.js +128 -0
- package/lib/users/getUserInfo.js +35 -0
- package/lib/users/getUsernameFromId.js +45 -0
- package/lib/users/getUsernameHistory.js +42 -0
- package/lib/users/onBlurbChange.js +46 -0
- package/lib/users/searchUsers.js +41 -0
- package/lib/util/apiError.js +50 -0
- package/lib/util/clearSession.js +32 -0
- package/lib/util/generalRequest.js +61 -0
- package/lib/util/getAction.js +45 -0
- package/lib/util/getAuthenticatedUser.js +41 -0
- package/lib/util/getCurrentUser.js +58 -0
- package/lib/util/getGeneralToken.js +52 -0
- package/lib/util/getHash.js +29 -0
- package/lib/util/getInputs.js +37 -0
- package/lib/util/getPageResults.js +86 -0
- package/lib/util/getSenderUserId.js +30 -0
- package/lib/util/getSession.js +38 -0
- package/lib/util/getVerification.js +60 -0
- package/lib/util/getVerificationInputs.js +31 -0
- package/lib/util/http.js +138 -0
- package/lib/util/jar.js +25 -0
- package/lib/util/refreshCookie.js +52 -0
- package/lib/util/relog.js +81 -0
- package/lib/util/setOptions.js +54 -0
- package/lib/util/shortPoll.js +102 -0
- package/package.json +76 -0
- package/postinstall.mjs +1 -0
- package/settings.json +115 -0
- package/test/accountinformation.test.js +27 -0
- package/test/accountsettings.test.js +27 -0
- package/test/asset.test.js +81 -0
- package/test/assets/Great-White-Shark-Fin.rbxm +0 -0
- package/test/assets/KeyframeSequence.rbxm +0 -0
- package/test/avatar.test.js +164 -0
- package/test/badges.test.js +96 -0
- package/test/chat.test.js +104 -0
- package/test/datastore.test.js +105 -0
- package/test/develop.test.js +53 -0
- package/test/economy.test.js +143 -0
- package/test/friends.test.js +146 -0
- package/test/games.test.js +229 -0
- package/test/groups.test.js +405 -0
- package/test/inventory.test.js +98 -0
- package/test/itemconfiguration.test.js +24 -0
- package/test/premiumfeatures.test.js +17 -0
- package/test/presence.test.js +25 -0
- package/test/privatemessages.test.js +33 -0
- package/test/thumbnails.test.js +53 -0
- package/test/users.test.js +110 -0
- package/tutorials/Authentication.md +75 -0
- package/tutorials/Event Emitters.md +26 -0
- package/tutorials/Promises.md +86 -0
- package/tutorials/VPS Authentication.md +72 -0
- package/typings/index.d.ts +2639 -0
- package/typings/jsDocs.ts +1987 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const events = require('events')
|
|
2
|
+
|
|
3
|
+
const onNotification = require('../client/onNotification.js').func
|
|
4
|
+
|
|
5
|
+
exports.optional = ['jar']
|
|
6
|
+
|
|
7
|
+
// Docs
|
|
8
|
+
/**
|
|
9
|
+
* 🔐 An event for when someone joins a party.
|
|
10
|
+
* @category Party
|
|
11
|
+
* @alias onPartyUserJoined
|
|
12
|
+
* @returns An EventEmitter that emits when someone joins a party.
|
|
13
|
+
* @example const noblox = require("noblox.js")
|
|
14
|
+
* // Login using your cookie
|
|
15
|
+
* const partyJoined = noblox.onPartyUserJoined()
|
|
16
|
+
* partyJoined.on("data", function(data) {
|
|
17
|
+
* console.log("Someone joined a party! ", data)
|
|
18
|
+
* })
|
|
19
|
+
* partyJoined.on("error", function(err) {
|
|
20
|
+
* console.error("Something went wrong: ", err)
|
|
21
|
+
* // Handle error as needed
|
|
22
|
+
* })
|
|
23
|
+
**/
|
|
24
|
+
|
|
25
|
+
exports.func = (args) => {
|
|
26
|
+
const jar = args.jar
|
|
27
|
+
const newEvent = new events.EventEmitter()
|
|
28
|
+
const notifications = onNotification({ jar })
|
|
29
|
+
|
|
30
|
+
notifications.on('data', (name, message) => {
|
|
31
|
+
if (name === 'PartyNotifications' && message.Type === 'PartyUserJoined') {
|
|
32
|
+
newEvent.emit('data', {
|
|
33
|
+
PartyId: message.PartyId,
|
|
34
|
+
PartyType: message.PartyType
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
notifications.on('error', (err) => {
|
|
40
|
+
newEvent.emit('error', err)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
notifications.on('connect', () => {
|
|
44
|
+
newEvent.emit('connect')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
notifications.on('close', (internal) => {
|
|
48
|
+
if (internal) return
|
|
49
|
+
notifications.emit('close', true)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return newEvent
|
|
53
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
const events = require('events')
|
|
2
|
+
|
|
3
|
+
const onNotification = require('../client/onNotification.js').func
|
|
4
|
+
|
|
5
|
+
exports.optional = ['jar']
|
|
6
|
+
|
|
7
|
+
// Docs
|
|
8
|
+
/**
|
|
9
|
+
* 🔐 An event for when someone leaves a party.
|
|
10
|
+
* @category Party
|
|
11
|
+
* @alias onPartyUserLeft
|
|
12
|
+
* @returns An EventEmitter that emits when someone leaves a party.
|
|
13
|
+
* @example const noblox = require("noblox.js")
|
|
14
|
+
* // Login using your cookie
|
|
15
|
+
* const partyLeft = noblox.onPartyUserLeft()
|
|
16
|
+
* partyLeft.on("data", function(data) {
|
|
17
|
+
* console.log("Someone left party! ", data)
|
|
18
|
+
* })
|
|
19
|
+
* partyLeft.on("error", function(err) {
|
|
20
|
+
* console.error("Something went wrong: ", err)
|
|
21
|
+
* // Handle error as needed
|
|
22
|
+
* })
|
|
23
|
+
**/
|
|
24
|
+
|
|
25
|
+
exports.func = (args) => {
|
|
26
|
+
const jar = args.jar
|
|
27
|
+
const newEvent = new events.EventEmitter()
|
|
28
|
+
const notifications = onNotification({ jar })
|
|
29
|
+
|
|
30
|
+
notifications.on('data', (name, message) => {
|
|
31
|
+
if (name === 'PartyNotifications' && message.Type === 'PartyUserLeft') {
|
|
32
|
+
newEvent.emit('data', {
|
|
33
|
+
PartyId: message.PartyId,
|
|
34
|
+
PartyType: message.PartyType
|
|
35
|
+
})
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
notifications.on('error', (err) => {
|
|
40
|
+
newEvent.emit('error', err)
|
|
41
|
+
})
|
|
42
|
+
|
|
43
|
+
notifications.on('connect', () => {
|
|
44
|
+
newEvent.emit('connect')
|
|
45
|
+
})
|
|
46
|
+
|
|
47
|
+
notifications.on('close', (internal) => {
|
|
48
|
+
if (internal) return
|
|
49
|
+
notifications.emit('close', true)
|
|
50
|
+
})
|
|
51
|
+
|
|
52
|
+
return newEvent
|
|
53
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const http = require('../util/http.js').func
|
|
3
|
+
const RobloxAPIError = require('../util/apiError.js')
|
|
4
|
+
|
|
5
|
+
// Args
|
|
6
|
+
exports.required = ['userId']
|
|
7
|
+
exports.optional = ['jar']
|
|
8
|
+
|
|
9
|
+
// Docs
|
|
10
|
+
/**
|
|
11
|
+
* 🔐 Gets whether or not a user has premium.
|
|
12
|
+
* @category User
|
|
13
|
+
* @alias getPremium
|
|
14
|
+
* @param {number} userId - The id of the user.
|
|
15
|
+
* @returns {Promise<boolean>}
|
|
16
|
+
* @example const noblox = require("noblox.js")
|
|
17
|
+
* // Login using your cookie
|
|
18
|
+
* const hasPremium = await noblox.getPremium(123456)
|
|
19
|
+
**/
|
|
20
|
+
|
|
21
|
+
// Define
|
|
22
|
+
function getPremium (jar, userId) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const httpOpt = {
|
|
25
|
+
url: `https://premiumfeatures.roblox.com/v1/users/${userId}/validate-membership`,
|
|
26
|
+
options: {
|
|
27
|
+
method: 'GET',
|
|
28
|
+
jar,
|
|
29
|
+
resolveWithFullResponse: true
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return http(httpOpt)
|
|
33
|
+
.then(function (res) {
|
|
34
|
+
if (res.statusCode === 200) {
|
|
35
|
+
resolve(res.body === 'true')
|
|
36
|
+
} else {
|
|
37
|
+
reject(new RobloxAPIError(res))
|
|
38
|
+
}
|
|
39
|
+
})
|
|
40
|
+
})
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
exports.func = function (args) {
|
|
44
|
+
const jar = args.jar
|
|
45
|
+
return getPremium(jar, args.userId)
|
|
46
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const http = require('../util/http.js').func
|
|
3
|
+
const getGeneralToken = require('../util/getGeneralToken.js').func
|
|
4
|
+
const RobloxAPIError = require('../util/apiError.js')
|
|
5
|
+
|
|
6
|
+
// Args
|
|
7
|
+
exports.required = ['userIds']
|
|
8
|
+
exports.optional = []
|
|
9
|
+
|
|
10
|
+
// Docs
|
|
11
|
+
/**
|
|
12
|
+
* 🔐 Get the presence status of users.
|
|
13
|
+
* @category Presence
|
|
14
|
+
* @alias getPresences
|
|
15
|
+
* @param {Array<number>} userIds - An array of userIds.
|
|
16
|
+
* @returns {Promise<Presences>}
|
|
17
|
+
* @example const noblox = require("noblox.js")
|
|
18
|
+
* // Login using your cookie
|
|
19
|
+
* const presences = await noblox.getPresences([1, 2, 3])
|
|
20
|
+
**/
|
|
21
|
+
|
|
22
|
+
// Define
|
|
23
|
+
function getPresences (userIds, jar, xcsrf) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const httpOpt = {
|
|
26
|
+
url: '//presence.roblox.com/v1/presence/users',
|
|
27
|
+
options: {
|
|
28
|
+
method: 'POST',
|
|
29
|
+
resolveWithFullResponse: true,
|
|
30
|
+
jar,
|
|
31
|
+
headers: {
|
|
32
|
+
'X-CSRF-TOKEN': xcsrf,
|
|
33
|
+
'Content-Type': 'application/json'
|
|
34
|
+
},
|
|
35
|
+
body: JSON.stringify({
|
|
36
|
+
userIds
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
return http(httpOpt)
|
|
42
|
+
.then(function (res) {
|
|
43
|
+
const responseData = JSON.parse(res.body)
|
|
44
|
+
if (res.statusCode !== 200) {
|
|
45
|
+
reject(new RobloxAPIError(res))
|
|
46
|
+
} else {
|
|
47
|
+
resolve(responseData)
|
|
48
|
+
}
|
|
49
|
+
})
|
|
50
|
+
.catch(error => reject(error))
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exports.func = function (args) {
|
|
55
|
+
const jar = args.jar
|
|
56
|
+
return getGeneralToken({ jar })
|
|
57
|
+
.then(function (xcsrf) {
|
|
58
|
+
return getPresences(args.userIds, args.jar, xcsrf)
|
|
59
|
+
})
|
|
60
|
+
}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const http = require('../util/http.js').func
|
|
3
|
+
const RobloxAPIError = require('../util/apiError.js')
|
|
4
|
+
// Args
|
|
5
|
+
exports.required = []
|
|
6
|
+
exports.optional = ['pageNumber', 'pageSize', 'messageTab', 'jar']
|
|
7
|
+
|
|
8
|
+
// Docs
|
|
9
|
+
/**
|
|
10
|
+
* 🔐 Get the messages of the authenticated user.
|
|
11
|
+
* @category User
|
|
12
|
+
* @alias getMessages
|
|
13
|
+
* @param {number=} [pageNumber=0] - The number of the current page.
|
|
14
|
+
* @param {number=} [pageSize=25] - The size of the current page.
|
|
15
|
+
* @param {("Inbox" | "Sent" | "Archive")=} [messageTab=Inbox] - The tab of the messages being fetched (Inbox, Sent, Archive)
|
|
16
|
+
* @returns {Promise<PrivateMessagesPage>}
|
|
17
|
+
* @example const noblox = require("noblox.js")
|
|
18
|
+
* // Login using your cookie
|
|
19
|
+
* let messages = await noblox.getMessages(1, 10, "Inbox"))
|
|
20
|
+
**/
|
|
21
|
+
|
|
22
|
+
// Define
|
|
23
|
+
function getMessages (jar, pageNumber, pageSize, messageTab) {
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
const httpOpt = {
|
|
26
|
+
url: `//privatemessages.roblox.com/v1/messages?pageNumber=${pageNumber}&pageSize=${pageSize}&messageTab=${messageTab}`,
|
|
27
|
+
options: {
|
|
28
|
+
method: 'GET',
|
|
29
|
+
jar,
|
|
30
|
+
resolveWithFullResponse: true
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
return http(httpOpt)
|
|
34
|
+
.then(function (res) {
|
|
35
|
+
if (res.statusCode === 200) {
|
|
36
|
+
resolve(JSON.parse(res.body))
|
|
37
|
+
} else {
|
|
38
|
+
reject(new RobloxAPIError(res))
|
|
39
|
+
}
|
|
40
|
+
})
|
|
41
|
+
})
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
exports.func = function (args) {
|
|
45
|
+
const jar = args.jar
|
|
46
|
+
const pageNumber = (args.pageNumber && args.pageNumber.toString()) || '0'
|
|
47
|
+
const pageSize = (args.pageSize && args.pageSize.toString()) || '25'
|
|
48
|
+
const messageTab = args.messageTab || 'Inbox'
|
|
49
|
+
if (!['Inbox', 'Sent', 'Archive'].includes(messageTab)) {
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
reject(new Error('messageTab must be Inbox, Sent, or Archive'))
|
|
52
|
+
})
|
|
53
|
+
}
|
|
54
|
+
return getMessages(jar, pageNumber, pageSize, messageTab)
|
|
55
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const http = require('../util/http.js').func
|
|
3
|
+
const queue = require('../internal/queue.js')
|
|
4
|
+
const getGeneralToken = require('../util/getGeneralToken.js').func
|
|
5
|
+
const getHash = require('../util/getHash.js').func
|
|
6
|
+
const getSenderId = require('../util/getSenderUserId.js').func
|
|
7
|
+
const RobloxAPIError = require('../util/apiError.js')
|
|
8
|
+
|
|
9
|
+
// Args
|
|
10
|
+
exports.required = ['recipient', 'subject', 'body']
|
|
11
|
+
exports.optional = ['replyMessageId', 'includePreviousMessage', 'jar']
|
|
12
|
+
|
|
13
|
+
// Docs
|
|
14
|
+
/**
|
|
15
|
+
* 🔐 Send a message. NOTE: Roblox blocks web servers and proxies from sending messages.
|
|
16
|
+
* @category User
|
|
17
|
+
* @alias message
|
|
18
|
+
* @param {number} recipient - The id of the user.
|
|
19
|
+
* @param {string} subject - The subject of the message.
|
|
20
|
+
* @param {string} body - The body of the message.
|
|
21
|
+
* @param {number=} replyMessageId - The messageId to reply to.
|
|
22
|
+
* @param {boolean=} [includePreviousMessage=false] - The previous or next page cursor.
|
|
23
|
+
* @returns {Promise<void>}
|
|
24
|
+
* @example const noblox = require("noblox.js")
|
|
25
|
+
* // Login using your cookie
|
|
26
|
+
* noblox.message(1, "A subject", "A body", 1234, true)
|
|
27
|
+
**/
|
|
28
|
+
|
|
29
|
+
// Define
|
|
30
|
+
function message (jar, token, senderId, recipient, subject, body, replyMessageId, includePreviousMessage) {
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const httpOpt = {
|
|
33
|
+
url: '//privatemessages.roblox.com/v1/messages/send',
|
|
34
|
+
options: {
|
|
35
|
+
method: 'POST',
|
|
36
|
+
jar,
|
|
37
|
+
headers: {
|
|
38
|
+
'X-CSRF-TOKEN': token,
|
|
39
|
+
'Content-Type': 'application/json'
|
|
40
|
+
},
|
|
41
|
+
body: JSON.stringify({
|
|
42
|
+
userId: senderId,
|
|
43
|
+
recipientId: recipient,
|
|
44
|
+
subject,
|
|
45
|
+
body,
|
|
46
|
+
replyMessageId,
|
|
47
|
+
includePreviousMessage
|
|
48
|
+
}),
|
|
49
|
+
resolveWithFullResponse: true
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return http(httpOpt)
|
|
53
|
+
.then(function (res) {
|
|
54
|
+
if (res.statusCode === 200) {
|
|
55
|
+
resolve(JSON.parse(res.body))
|
|
56
|
+
} else {
|
|
57
|
+
reject(new RobloxAPIError(res))
|
|
58
|
+
}
|
|
59
|
+
})
|
|
60
|
+
})
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
exports.func = function (args) {
|
|
64
|
+
const jar = args.jar
|
|
65
|
+
return queue('Message', getHash({ jar }), function () {
|
|
66
|
+
return getGeneralToken({ jar })
|
|
67
|
+
.then(function (xcsrf) {
|
|
68
|
+
return getSenderId({ jar }).then((senderId) => {
|
|
69
|
+
return message(jar, xcsrf, senderId, args.recipient, args.subject, args.body, args.replyMessageId, args.includePreviousMessage)
|
|
70
|
+
})
|
|
71
|
+
})
|
|
72
|
+
}, function () {
|
|
73
|
+
return true
|
|
74
|
+
})
|
|
75
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
// Dependencies
|
|
2
|
+
const events = require('events')
|
|
3
|
+
|
|
4
|
+
// Includes
|
|
5
|
+
const onNotification = require('../client/onNotification.js').func
|
|
6
|
+
const getMessages = require('./getMessages.js').func
|
|
7
|
+
|
|
8
|
+
// Args
|
|
9
|
+
exports.optional = ['jar']
|
|
10
|
+
|
|
11
|
+
// Docs
|
|
12
|
+
/**
|
|
13
|
+
* 🔐 An event for when a user sends you a message via. the older 'email-like' message system. To receive chat messages,
|
|
14
|
+
* see the `onNewMessage` method.
|
|
15
|
+
* @see [onNewMessage()](global.html#onNewMessage).
|
|
16
|
+
* @category User
|
|
17
|
+
* @alias onMessage
|
|
18
|
+
* @returns An EventEmitter that emits when a user sends you a message.
|
|
19
|
+
* @example const noblox = require("noblox.js")
|
|
20
|
+
* // Login using your cookie
|
|
21
|
+
* const messageEvent = noblox.onMessage()
|
|
22
|
+
* messageEvent.on("data", function(data) {
|
|
23
|
+
* console.log("New message! ", data)
|
|
24
|
+
* })
|
|
25
|
+
* messageEvent.on("error", function(err) {
|
|
26
|
+
* console.error("Something went wrong: ", err)
|
|
27
|
+
* // Handle error as needed
|
|
28
|
+
* })
|
|
29
|
+
**/
|
|
30
|
+
|
|
31
|
+
// Define
|
|
32
|
+
exports.func = function (args) {
|
|
33
|
+
const jar = args.jar
|
|
34
|
+
const onMessage = new events.EventEmitter()
|
|
35
|
+
let waitingForRequest = false
|
|
36
|
+
let latest
|
|
37
|
+
getMessages({ jar, messageTab: 'Inbox', pageNumber: 0, pageSize: 1 })
|
|
38
|
+
.then(function (initial) {
|
|
39
|
+
latest = initial.collection[0] ? initial.collection[0].id : 0
|
|
40
|
+
const notifications = onNotification({ jar })
|
|
41
|
+
notifications.on('data', function (name, message) {
|
|
42
|
+
if (name === 'MessageNotification' && message.Type === 'Created') {
|
|
43
|
+
if (waitingForRequest) {
|
|
44
|
+
waitingForRequest = false
|
|
45
|
+
} else {
|
|
46
|
+
getMessages({
|
|
47
|
+
jar,
|
|
48
|
+
messageTab: 'Inbox',
|
|
49
|
+
pageNumber: 0,
|
|
50
|
+
pageSize: 1
|
|
51
|
+
})
|
|
52
|
+
.then(function (inbox) {
|
|
53
|
+
const messages = inbox.collection
|
|
54
|
+
for (let i = messages.length - 1; i >= 0; i--) {
|
|
55
|
+
const message = messages[i]
|
|
56
|
+
const id = message.id
|
|
57
|
+
if (id > latest) {
|
|
58
|
+
latest = id
|
|
59
|
+
onMessage.emit('data', message)
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
})
|
|
63
|
+
}
|
|
64
|
+
} else if (name === 'FriendshipNotifications' && message.Type === 'FriendshipRequested') {
|
|
65
|
+
waitingForRequest = true
|
|
66
|
+
}
|
|
67
|
+
})
|
|
68
|
+
notifications.on('error', function (err) {
|
|
69
|
+
onMessage.emit('error', err)
|
|
70
|
+
})
|
|
71
|
+
notifications.on('connect', function () {
|
|
72
|
+
onMessage.emit('connect')
|
|
73
|
+
})
|
|
74
|
+
notifications.on('close', function (internal) {
|
|
75
|
+
if (internal) {
|
|
76
|
+
return
|
|
77
|
+
}
|
|
78
|
+
onMessage.emit('close', true)
|
|
79
|
+
})
|
|
80
|
+
onMessage.on('close', function (internal) {
|
|
81
|
+
if (internal) {
|
|
82
|
+
return
|
|
83
|
+
}
|
|
84
|
+
notifications.emit('close', true)
|
|
85
|
+
})
|
|
86
|
+
})
|
|
87
|
+
|
|
88
|
+
return onMessage
|
|
89
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const http = require('../util/http.js').func
|
|
3
|
+
const RobloxAPIError = require('../util/apiError.js')
|
|
4
|
+
|
|
5
|
+
// Args
|
|
6
|
+
exports.required = ['group']
|
|
7
|
+
exports.optional = ['size', 'circular', 'format']
|
|
8
|
+
|
|
9
|
+
// Docs
|
|
10
|
+
/**
|
|
11
|
+
* ✅ Get the group's logo.
|
|
12
|
+
* @category Group
|
|
13
|
+
* @alias getLogo
|
|
14
|
+
* @param {number} group - The id of the group.
|
|
15
|
+
* @param {GroupIconSize=} [size=150x150] - The size of the logo.
|
|
16
|
+
* @param {boolean=} [circular=false] - Get the circular version of the logo.
|
|
17
|
+
* @param {GroupIconFormat=} [format=Png] - The file format of the logo.
|
|
18
|
+
* @returns {Promise<string>}
|
|
19
|
+
* @example const noblox = require("noblox.js")
|
|
20
|
+
* const logo = await noblox.getLogo(1)
|
|
21
|
+
**/
|
|
22
|
+
|
|
23
|
+
// Define
|
|
24
|
+
function getLogo (group, size, circular, format) {
|
|
25
|
+
const httpOpt = {
|
|
26
|
+
url: '//thumbnails.roblox.com/v1/groups/icons',
|
|
27
|
+
options: {
|
|
28
|
+
qs: {
|
|
29
|
+
groupIds: group,
|
|
30
|
+
size: size || '150x150',
|
|
31
|
+
format: format || 'Png',
|
|
32
|
+
isCircular: circular
|
|
33
|
+
},
|
|
34
|
+
json: true,
|
|
35
|
+
resolveWithFullResponse: true
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return http(httpOpt)
|
|
39
|
+
.then(function (res) {
|
|
40
|
+
if (res.statusCode !== 200) {
|
|
41
|
+
throw new RobloxAPIError(res)
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const thumbnailData = res.body.data[0]
|
|
45
|
+
|
|
46
|
+
if (thumbnailData.state !== 'Completed') {
|
|
47
|
+
throw new Error('The requested image has not been approved. Status: ' + thumbnailData.state)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
return thumbnailData.imageUrl
|
|
51
|
+
})
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
exports.func = function (args) {
|
|
55
|
+
return getLogo(args.group)
|
|
56
|
+
}
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const http = require('../util/http.js').func
|
|
3
|
+
const { thumbnail: settings } = require('../../settings.json')
|
|
4
|
+
const RobloxAPIError = require('../util/apiError.js')
|
|
5
|
+
|
|
6
|
+
// Args
|
|
7
|
+
exports.required = ['userIds']
|
|
8
|
+
exports.optional = ['size', 'format', 'isCircular', 'cropType', 'retryCount']
|
|
9
|
+
|
|
10
|
+
// Variables
|
|
11
|
+
const eligibleSizes = {
|
|
12
|
+
body: {
|
|
13
|
+
sizes: ['30x30', '48x48', '60x60', '75x75', '100x100', '110x110', '140x140', '150x150', '150x200', '180x180', '250x250', '352x352', '420x420', '720x720'],
|
|
14
|
+
endpoint: 'avatar'
|
|
15
|
+
},
|
|
16
|
+
bust: {
|
|
17
|
+
sizes: ['48x48', '50x50', '60x60', '75x75', '100x100', '150x150', '180x180', '352x352', '420x420'],
|
|
18
|
+
endpoint: 'avatar-bust'
|
|
19
|
+
},
|
|
20
|
+
headshot: {
|
|
21
|
+
sizes: ['48x48', '50x50', '60x60', '75x75', '100x100', '110x110', '150x150', '180x180', '352x352', '420x420', '720x720'],
|
|
22
|
+
endpoint: 'avatar-headshot'
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
// Docs
|
|
27
|
+
/**
|
|
28
|
+
* ✅ Get a user's thumbnail.
|
|
29
|
+
* @category User
|
|
30
|
+
* @alias getPlayerThumbnail
|
|
31
|
+
* @param {number | Array<number>} userIds - The id or an array ids of thumbnails to be retrieved; 100
|
|
32
|
+
* @param {number | string=} [size=720x720] - The [size of the image to be returned]{@link https://noblox.js.org/thumbnailSizes.png}; defaults highest resolution
|
|
33
|
+
* @param {'png' | 'jpeg'=} [format=png] - The file format of the returned thumbnails
|
|
34
|
+
* @param {boolean=} [isCircular=false] - Return the circular version of the thumbnails
|
|
35
|
+
* @param {'Body' | 'Bust' | 'Headshot'=} [cropType=Body] - The style of thumbnail that will be returned
|
|
36
|
+
* @returns {Promise<PlayerThumbnailData[]>}
|
|
37
|
+
* @example const noblox = require("noblox.js")
|
|
38
|
+
* let thumbnail_default = await noblox.getPlayerThumbnail(2416399685)
|
|
39
|
+
* let thumbnail_circHeadshot = await noblox.getPlayerThumbnail(2416399685, 420, "png", true, "Headshot")
|
|
40
|
+
* let thumbnails_body = await noblox.getPlayerThumbnail([2416399685, 234567, 345678], "150x200", "jpeg", false, "Body")
|
|
41
|
+
**/
|
|
42
|
+
|
|
43
|
+
// Define
|
|
44
|
+
function getPlayerThumbnail (userIds, size, format = 'png', isCircular = false, cropType = 'body', retryCount = settings.maxRetries) {
|
|
45
|
+
// Validate userIds
|
|
46
|
+
if (Array.isArray(userIds)) {
|
|
47
|
+
if (userIds.some(isNaN)) {
|
|
48
|
+
throw new Error('userIds must be a number or an array of numbers')
|
|
49
|
+
}
|
|
50
|
+
userIds = [...new Set(userIds)] // get rid of duplicates, endpoint response does this anyway
|
|
51
|
+
if (userIds.length > 100) {
|
|
52
|
+
throw new Error(`too many userIds provided (${userIds.length}); maximum 100`)
|
|
53
|
+
}
|
|
54
|
+
} else {
|
|
55
|
+
if (isNaN(userIds)) {
|
|
56
|
+
throw new Error('userId is not a number')
|
|
57
|
+
}
|
|
58
|
+
userIds = [userIds]
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Validate cropType
|
|
62
|
+
cropType = cropType.toLowerCase()
|
|
63
|
+
if (!Object.keys(eligibleSizes).includes(cropType)) {
|
|
64
|
+
throw new Error(`Invalid cropping type provided: ${cropType} | Use: ${Object.keys(eligibleSizes).join(', ')}`)
|
|
65
|
+
}
|
|
66
|
+
const { sizes, endpoint } = eligibleSizes[cropType]
|
|
67
|
+
|
|
68
|
+
// Validate size
|
|
69
|
+
size = size || sizes[sizes.length - 1]
|
|
70
|
+
if (typeof size === 'number') {
|
|
71
|
+
size = `${size}x${size}`
|
|
72
|
+
}
|
|
73
|
+
if (!sizes.includes(size)) {
|
|
74
|
+
throw new Error(`Invalid size parameter provided: ${size} | [${cropType.toUpperCase()}] Use: ${sizes.join(', ')}`)
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
// Validate format
|
|
78
|
+
if (format.toLowerCase() !== 'png' && format.toLowerCase() !== 'jpeg') {
|
|
79
|
+
throw new Error(`Invalid image type provided: ${format} | Use: png, jpeg`)
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
return http({
|
|
83
|
+
url: `https://thumbnails.roblox.com/v1/users/${endpoint}?userIds=${userIds.join(',')}&size=${size}&format=${format}&isCircular=${!!isCircular}`,
|
|
84
|
+
options: {
|
|
85
|
+
resolveWithFullResponse: true,
|
|
86
|
+
followRedirect: true
|
|
87
|
+
}
|
|
88
|
+
})
|
|
89
|
+
.then(async (res) => {
|
|
90
|
+
let { data } = JSON.parse(res.body)
|
|
91
|
+
if (res.statusCode === 200) {
|
|
92
|
+
if (retryCount > 0) {
|
|
93
|
+
const pendingThumbnails = data.filter(obj => { return obj.state === 'Pending' }).map(obj => obj.targetId) // Get 'Pending' thumbnails as array of userIds
|
|
94
|
+
if (pendingThumbnails.length > 0) {
|
|
95
|
+
await timeout(settings.retryDelay) // small delay helps cache populate on Roblox's end; default 500ms
|
|
96
|
+
const updatedPending = await getPlayerThumbnail(pendingThumbnails, size, format, isCircular, cropType, --retryCount) // Recursively retry for # of maxRetries attempts; default 2
|
|
97
|
+
data = data.map(obj => updatedPending.find(o => o.targetId === obj.targetId) || obj) // Update primary array's values
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
data = data.map(obj => {
|
|
101
|
+
if (obj.state !== 'Completed') {
|
|
102
|
+
const settingsUrl = settings.failedUrl[obj.state.toLowerCase()] // user defined settings.json default image URL for blocked or pending thumbnails; default ""
|
|
103
|
+
obj.imageUrl = settingsUrl || `https://noblox.js.org/moderatedThumbnails/moderatedThumbnail_${size}.png`
|
|
104
|
+
}
|
|
105
|
+
return obj
|
|
106
|
+
})
|
|
107
|
+
return data
|
|
108
|
+
} else {
|
|
109
|
+
throw new RobloxAPIError(res)
|
|
110
|
+
}
|
|
111
|
+
})
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
function timeout (ms) {
|
|
115
|
+
return new Promise(resolve => { setTimeout(resolve, ms) })
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
exports.func = function ({ userIds, size, format, isCircular, cropType, retryCount }) {
|
|
119
|
+
return getPlayerThumbnail(userIds, size, format, isCircular, cropType, retryCount)
|
|
120
|
+
}
|