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,128 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const settings = require('../../settings.json')
|
|
3
|
+
const getFollowingCount = require('../friends/getFollowingCount.js').func
|
|
4
|
+
const getFollowerCount = require('../friends/getFollowerCount.js').func
|
|
5
|
+
const getFriendCount = require('../friends/getFriendCount.js').func
|
|
6
|
+
const getUserInfo = require('../users/getUserInfo.js').func
|
|
7
|
+
|
|
8
|
+
// Args
|
|
9
|
+
exports.required = ['userId']
|
|
10
|
+
|
|
11
|
+
// Docs
|
|
12
|
+
/**
|
|
13
|
+
* ✅ Get a user's information.
|
|
14
|
+
* @category User
|
|
15
|
+
* @alias getPlayerInfo
|
|
16
|
+
* @param { number } userId - The id of the user.
|
|
17
|
+
* @returns {Promise<PlayerInfo>}
|
|
18
|
+
* @deprecated `getPlayerInfo()` is deprecated; see `getUserInfo()`, `getFollowerCount()`, `getFollowingCount()`, `getFriendCount()`, `getUsernameHistory()`, `getUserFunds()`, `getPlayerThumbnail()` instead - high rate limits on endpoints such as username history and follower count have made this aggregate function not suitable for most users
|
|
19
|
+
* @example const noblox = require("noblox.js")
|
|
20
|
+
* let information = await noblox.getPlayerInfo({userId: 123456})
|
|
21
|
+
**/
|
|
22
|
+
|
|
23
|
+
// Define
|
|
24
|
+
function getPlayerInfo (userId) {
|
|
25
|
+
return new Promise((resolve, reject) => {
|
|
26
|
+
const requests = [
|
|
27
|
+
getUserInfo({ userId }),
|
|
28
|
+
getFriendCount({ userId }),
|
|
29
|
+
|
|
30
|
+
getFollowingCount({ userId }),
|
|
31
|
+
getFollowerCount({ userId })
|
|
32
|
+
].map((promise) =>
|
|
33
|
+
promise.then(
|
|
34
|
+
(val) => ({ status: 'fulfilled', value: val }),
|
|
35
|
+
(rej) => ({ status: 'rejected', reason: rej })
|
|
36
|
+
)
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
Promise.all(requests).then((promiseResponses) => {
|
|
40
|
+
const responses = promiseResponses.map((response) => response.value)
|
|
41
|
+
const userBody = responses[0]
|
|
42
|
+
const failedResponses = promiseResponses.filter(
|
|
43
|
+
(presponse) => presponse.status === 'rejected'
|
|
44
|
+
)
|
|
45
|
+
|
|
46
|
+
if (userBody?.isBanned) {
|
|
47
|
+
const joinDate = new Date(userBody.created)
|
|
48
|
+
const blurb = userBody.description
|
|
49
|
+
const isBanned = userBody.isBanned
|
|
50
|
+
const username = userBody.name
|
|
51
|
+
const displayName = userBody.displayName
|
|
52
|
+
|
|
53
|
+
resolve({
|
|
54
|
+
username,
|
|
55
|
+
joinDate,
|
|
56
|
+
blurb,
|
|
57
|
+
isBanned,
|
|
58
|
+
displayName
|
|
59
|
+
})
|
|
60
|
+
} else if (failedResponses.length) {
|
|
61
|
+
const failureReason = failedResponses
|
|
62
|
+
.map((response) => response.reason)
|
|
63
|
+
.join('\n')
|
|
64
|
+
|
|
65
|
+
if (
|
|
66
|
+
(failureReason.toLowerCase().includes('too many requests') ||
|
|
67
|
+
failureReason.toLowerCase().includes('(429')) &&
|
|
68
|
+
settings.show_deprecation_warnings
|
|
69
|
+
) {
|
|
70
|
+
console.warn()
|
|
71
|
+
console.warn(
|
|
72
|
+
'=============================================================================================================================================================================================='
|
|
73
|
+
)
|
|
74
|
+
console.warn(
|
|
75
|
+
'DEPRECATION WARNING: getPlayerInfo is an aggregate of multiple endpoints, rate limit changes have made this method unsuitable for many people, please use the individualized endpoints instead'
|
|
76
|
+
)
|
|
77
|
+
console.warn(
|
|
78
|
+
' see getUserInfo(), getFollowerCount(), getFollowingCount(), getFriendCount(), getUsernameHistory(), getUserFunds(), getPlayerThumbnail()'
|
|
79
|
+
)
|
|
80
|
+
console.warn()
|
|
81
|
+
console.warn(
|
|
82
|
+
'> Opt out of these warnings using noblox.setOptions({ show_deprecation_warnings: false })'
|
|
83
|
+
)
|
|
84
|
+
console.warn(
|
|
85
|
+
'=============================================================================================================================================================================================='
|
|
86
|
+
)
|
|
87
|
+
console.warn()
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
const error = failedResponses.map((r) => r.reason).join('\n')
|
|
91
|
+
reject(new Error(error))
|
|
92
|
+
} else {
|
|
93
|
+
const responseBodies = responses.map((res) => res.body ?? res)
|
|
94
|
+
const friendCount = responseBodies[1]
|
|
95
|
+
const followerCount = responseBodies[3]
|
|
96
|
+
const followingCount = responseBodies[2]
|
|
97
|
+
const joinDate = new Date(userBody.created)
|
|
98
|
+
const blurb = userBody.description
|
|
99
|
+
const isBanned = userBody.isBanned
|
|
100
|
+
const username = userBody.name
|
|
101
|
+
const displayName = userBody.displayName
|
|
102
|
+
|
|
103
|
+
const currentTime = new Date()
|
|
104
|
+
const age = Math.round(
|
|
105
|
+
Math.abs(
|
|
106
|
+
(joinDate.getTime() - currentTime.getTime()) / (24 * 60 * 60 * 1000)
|
|
107
|
+
)
|
|
108
|
+
)
|
|
109
|
+
|
|
110
|
+
resolve({
|
|
111
|
+
username,
|
|
112
|
+
displayName,
|
|
113
|
+
blurb,
|
|
114
|
+
joinDate,
|
|
115
|
+
age,
|
|
116
|
+
friendCount,
|
|
117
|
+
followerCount,
|
|
118
|
+
followingCount,
|
|
119
|
+
isBanned
|
|
120
|
+
})
|
|
121
|
+
}
|
|
122
|
+
})
|
|
123
|
+
})
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
exports.func = (args) => {
|
|
127
|
+
return getPlayerInfo(args.userId)
|
|
128
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
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
|
+
|
|
8
|
+
// Docs
|
|
9
|
+
/**
|
|
10
|
+
* ✅ Get base-level user profile information
|
|
11
|
+
* @category User
|
|
12
|
+
* @alias getUserInfo
|
|
13
|
+
* @param { number } userId
|
|
14
|
+
* @returns {Promise<UserInfo>}
|
|
15
|
+
**/
|
|
16
|
+
|
|
17
|
+
// Define
|
|
18
|
+
exports.func = function (args) {
|
|
19
|
+
const httpOpt = {
|
|
20
|
+
url: `//users.roblox.com/v1/users/${args.userId}`,
|
|
21
|
+
options: {
|
|
22
|
+
json: true,
|
|
23
|
+
method: 'GET',
|
|
24
|
+
resolveWithFullResponse: true
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
return http(httpOpt).then(function (res) {
|
|
29
|
+
if (res.statusCode !== 200) { throw new RobloxAPIError(res) }
|
|
30
|
+
|
|
31
|
+
res.body.created = new Date(res.body.created)
|
|
32
|
+
|
|
33
|
+
return res.body
|
|
34
|
+
})
|
|
35
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const http = require('../util/http.js').func
|
|
3
|
+
const cache = require('../cache')
|
|
4
|
+
const RobloxAPIError = require('../util/apiError.js')
|
|
5
|
+
|
|
6
|
+
// Args
|
|
7
|
+
exports.required = ['id']
|
|
8
|
+
|
|
9
|
+
// Docs
|
|
10
|
+
/**
|
|
11
|
+
* ✅ Get a user's username from their user id.
|
|
12
|
+
* @category User
|
|
13
|
+
* @alias getUsernameFromId
|
|
14
|
+
* @param {number} id - The id of the user.
|
|
15
|
+
* @returns {Promise<string>}
|
|
16
|
+
* @example const noblox = require("noblox.js")
|
|
17
|
+
* let username = await noblox.getUsernameFromId(123456)
|
|
18
|
+
**/
|
|
19
|
+
|
|
20
|
+
// Define
|
|
21
|
+
function getUsernameFromId (id) {
|
|
22
|
+
const httpOpt = {
|
|
23
|
+
url: `//users.roblox.com/v1/users/${id}`,
|
|
24
|
+
options: {
|
|
25
|
+
resolveWithFullResponse: true,
|
|
26
|
+
method: 'GET'
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return http(httpOpt)
|
|
30
|
+
.then(function (res) {
|
|
31
|
+
if (res.statusCode === 200) {
|
|
32
|
+
const json = JSON.parse(res.body)
|
|
33
|
+
return json.name
|
|
34
|
+
} else {
|
|
35
|
+
throw new RobloxAPIError(res)
|
|
36
|
+
}
|
|
37
|
+
})
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
exports.func = function (args) {
|
|
41
|
+
const id = args.id
|
|
42
|
+
return cache.wrap('NameFromID', id, function () {
|
|
43
|
+
return getUsernameFromId(id)
|
|
44
|
+
})
|
|
45
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const getPageResults = require('../util/getPageResults.js').func
|
|
3
|
+
const cache = require('../cache')
|
|
4
|
+
|
|
5
|
+
// Args
|
|
6
|
+
exports.required = ['userId']
|
|
7
|
+
exports.optional = ['limit', 'sortOrder', 'pageCursor']
|
|
8
|
+
|
|
9
|
+
// Docs
|
|
10
|
+
/**
|
|
11
|
+
* ✅ Get a user's username history.
|
|
12
|
+
* @category User
|
|
13
|
+
* @alias getUsernameHistory
|
|
14
|
+
* @param {number} userId
|
|
15
|
+
* @param {Limit=} [limit=100]
|
|
16
|
+
* @param {SortOrder=} [sortOrder=Asc]
|
|
17
|
+
* @param {string} cursor
|
|
18
|
+
* @returns {Promise<UsernameHistoryEntry[]>}
|
|
19
|
+
* @example const noblox = require("noblox.js")
|
|
20
|
+
* const history = await noblox.getUsernameHistory({ userId: 1, limit: 10, sortOrder: "Asc", cursor: "somecursorstring" })
|
|
21
|
+
**/
|
|
22
|
+
|
|
23
|
+
// Define
|
|
24
|
+
function getUsernameHistory (userId, limit, sortOrder, cursor) {
|
|
25
|
+
return getPageResults({
|
|
26
|
+
url: `//users.roblox.com/v1/users/${userId}/username-history`,
|
|
27
|
+
query: {},
|
|
28
|
+
limit,
|
|
29
|
+
pageCursor: cursor,
|
|
30
|
+
sortOrder
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exports.func = function (args) {
|
|
35
|
+
let { userId, limit, sortOrder, cursor } = args
|
|
36
|
+
limit ||= 100
|
|
37
|
+
sortOrder ||= 'Asc'
|
|
38
|
+
|
|
39
|
+
return cache.wrap('UsernameHistory', `${userId}-${limit}-${sortOrder}-${cursor}`, function () {
|
|
40
|
+
return getUsernameHistory(userId, limit, sortOrder, cursor)
|
|
41
|
+
})
|
|
42
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const shortPoll = require('../util/shortPoll.js').func
|
|
3
|
+
const getBlurb = require('./getBlurb.js').func
|
|
4
|
+
|
|
5
|
+
// Args
|
|
6
|
+
exports.required = ['userId']
|
|
7
|
+
|
|
8
|
+
// Docs
|
|
9
|
+
/**
|
|
10
|
+
* ✅ An event for when a user's blurb changes.
|
|
11
|
+
* @category User
|
|
12
|
+
* @alias onBlurbChange
|
|
13
|
+
* @param {number} userId - The id of the user.
|
|
14
|
+
* @returns An EventEmitter that emits when a user's blurb changes.
|
|
15
|
+
* @example const noblox = require("noblox.js")
|
|
16
|
+
* const blurbEvent = noblox.onBlurbChange(1)
|
|
17
|
+
* blurbEvent.on("data", function(data) {
|
|
18
|
+
* console.log("User's blurb changed!", data)
|
|
19
|
+
* })
|
|
20
|
+
* blurbEvent.on("error", function(err) {
|
|
21
|
+
* console.error("Something went wrong: ", err)
|
|
22
|
+
* // Handle error as needed
|
|
23
|
+
* })
|
|
24
|
+
**/
|
|
25
|
+
|
|
26
|
+
// Define
|
|
27
|
+
exports.func = function (args) {
|
|
28
|
+
return shortPoll({
|
|
29
|
+
getLatest: function (latest) {
|
|
30
|
+
return getBlurb({ userId: args.userId })
|
|
31
|
+
.then(function (blurb) {
|
|
32
|
+
const given = []
|
|
33
|
+
if (blurb !== latest) {
|
|
34
|
+
latest = blurb
|
|
35
|
+
given.push(blurb)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return {
|
|
39
|
+
latest,
|
|
40
|
+
data: given
|
|
41
|
+
}
|
|
42
|
+
})
|
|
43
|
+
},
|
|
44
|
+
delay: 'onBlurbChange'
|
|
45
|
+
})
|
|
46
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const getPageResults = require('../util/getPageResults.js').func
|
|
3
|
+
|
|
4
|
+
// Args
|
|
5
|
+
exports.required = ['keyword']
|
|
6
|
+
exports.optional = ['limit', 'cursor', 'jar']
|
|
7
|
+
|
|
8
|
+
// Docs
|
|
9
|
+
/**
|
|
10
|
+
* ✅ Gets a list of users matching the keyword
|
|
11
|
+
* @category User
|
|
12
|
+
* @alias searchUsers
|
|
13
|
+
* @param {string} keyword - The search term to use
|
|
14
|
+
* @param {10 | 25 | 50 | 100} limit - The maximum number of matching users to return
|
|
15
|
+
* @param {string} cursor - The cursor to use when fetching the next or previous page
|
|
16
|
+
* @returns {Promise<UserSearchResult[]>}
|
|
17
|
+
* @example const noblox = require("noblox.js")
|
|
18
|
+
* noblox.searchUsers("bob", 10, "cursorstring")
|
|
19
|
+
**/
|
|
20
|
+
|
|
21
|
+
// Define
|
|
22
|
+
function searchUsers (jar, keyword, limit, cursor) {
|
|
23
|
+
return getPageResults({
|
|
24
|
+
url: '//users.roblox.com/v1/users/search',
|
|
25
|
+
jar,
|
|
26
|
+
limit,
|
|
27
|
+
pageCursor: cursor,
|
|
28
|
+
query: {
|
|
29
|
+
keyword
|
|
30
|
+
}
|
|
31
|
+
})
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
exports.func = function (args) {
|
|
35
|
+
return searchUsers(
|
|
36
|
+
args.jar,
|
|
37
|
+
args.keyword,
|
|
38
|
+
args.limit ?? 10,
|
|
39
|
+
args.cursor
|
|
40
|
+
)
|
|
41
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
// The data should be a response object
|
|
2
|
+
|
|
3
|
+
class RobloxAPIError extends Error {
|
|
4
|
+
constructor (data) {
|
|
5
|
+
super(getResponseBody(data))
|
|
6
|
+
|
|
7
|
+
this.name = 'RobloxAPIError'
|
|
8
|
+
this.httpStatusCode = data.statusCode
|
|
9
|
+
this.responseBody = getResponseBody(data)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
get error () {
|
|
13
|
+
let obj
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
obj = JSON.parse(this.responseBody)
|
|
17
|
+
} catch {
|
|
18
|
+
return { code: 0, message: this.responseBody.toString() }
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (Object.hasOwn(obj, 'error')) return obj.error // V1 open cloud and some very old BEDEV1 endpoints + some global errors
|
|
22
|
+
|
|
23
|
+
else if (Object.hasOwn(obj, 'errors')) { // Most BEDEV1 endpoints
|
|
24
|
+
return obj.errors.at(0) // In spite of BEDEV1 endpoint errors being nested in an array, they are never seen in groups.
|
|
25
|
+
} else if (Object.hasOwn(obj, 'code') && Object.hasOwn(obj, 'message')) { // V2 open cloud
|
|
26
|
+
return obj
|
|
27
|
+
} else return { code: 0, message: this.responseBody } // Roblox did a funny (i.e. the platform is down)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
get caller () {
|
|
31
|
+
try {
|
|
32
|
+
// https://stackoverflow.com/a/57023880
|
|
33
|
+
return (new Error()).stack?.split('\n')[2]?.trim().split(' ').at(1) ?? null
|
|
34
|
+
} catch {
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getResponseBody (data) {
|
|
41
|
+
if (typeof data.body === 'string') return data.body
|
|
42
|
+
|
|
43
|
+
try {
|
|
44
|
+
return JSON.stringify(data.body)
|
|
45
|
+
} catch {
|
|
46
|
+
throw Error('The passed response body is not a valid object')
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = RobloxAPIError
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const settings = require('../../settings.json')
|
|
3
|
+
|
|
4
|
+
// Args
|
|
5
|
+
exports.required = ['jar']
|
|
6
|
+
|
|
7
|
+
// Docs
|
|
8
|
+
/**
|
|
9
|
+
* 🔐 Remove .ROBLOSECURITY cookie from jar.
|
|
10
|
+
* @category Utility
|
|
11
|
+
* @alias clearSession
|
|
12
|
+
* @param {CookieJar} jar - The CookieJar containing the .ROBLOSECURITY cookie.
|
|
13
|
+
* @returns {Promise<string>}
|
|
14
|
+
* @example const noblox = require("noblox.js")
|
|
15
|
+
* noblox.clearSession()
|
|
16
|
+
**/
|
|
17
|
+
|
|
18
|
+
// Define
|
|
19
|
+
exports.func = function (args) {
|
|
20
|
+
const jar = args.jar
|
|
21
|
+
if (settings.session_only) {
|
|
22
|
+
jar.session = ''
|
|
23
|
+
} else {
|
|
24
|
+
const cookies = jar._jar.store.idx['roblox.com']
|
|
25
|
+
if (cookies) {
|
|
26
|
+
const cookie = cookies['/']
|
|
27
|
+
if (cookie && cookie['.ROBLOSECURITY']) {
|
|
28
|
+
delete cookies['/']['.ROBLOSECURITY']
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const http = require('./http.js').func
|
|
3
|
+
const getVerification = require('./getVerification.js').func
|
|
4
|
+
|
|
5
|
+
// Args
|
|
6
|
+
exports.required = ['url', 'events']
|
|
7
|
+
exports.optional = ['http', 'ignoreCache', 'getBody', 'jar']
|
|
8
|
+
|
|
9
|
+
// Docs
|
|
10
|
+
/**
|
|
11
|
+
* 🔐 Get the verification inputs and send a request.
|
|
12
|
+
* @category Utility
|
|
13
|
+
* @alias generalRequest
|
|
14
|
+
* @param {string} url - The url to post to.
|
|
15
|
+
* @param {object} events - Form data to send with the request.
|
|
16
|
+
* @param {boolean=} [ignoreCache=false] - Whether to ignore the cache or not.
|
|
17
|
+
* @param {boolean=} [getBody=false] - Whether to return the original body before the POST request.
|
|
18
|
+
* @param {CookieJar=} jar - The CookieJar containing the .ROBLOSECURITY cookie.
|
|
19
|
+
* @returns {Promise<Object>}
|
|
20
|
+
* @example const noblox = require("noblox.js")
|
|
21
|
+
* // Login using your cookie.
|
|
22
|
+
* noblox.generalRequest("//www.roblox.com/Groups/Group.aspx?gid=1", { __EVENTTARGET: 'JoinGroupDiv', __EVENTARGUMENT: 'Click' })
|
|
23
|
+
**/
|
|
24
|
+
|
|
25
|
+
// Define
|
|
26
|
+
function general (jar, url, inputs, events, customOpt, body) {
|
|
27
|
+
for (const input in events) {
|
|
28
|
+
inputs[input] = events[input]
|
|
29
|
+
}
|
|
30
|
+
const httpOpt = {
|
|
31
|
+
url,
|
|
32
|
+
options: {
|
|
33
|
+
resolveWithFullResponse: true,
|
|
34
|
+
method: 'POST',
|
|
35
|
+
form: inputs,
|
|
36
|
+
jar
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (customOpt) {
|
|
40
|
+
if (customOpt.url) {
|
|
41
|
+
delete customOpt.url
|
|
42
|
+
}
|
|
43
|
+
Object.assign(httpOpt.options, customOpt)
|
|
44
|
+
}
|
|
45
|
+
return http(httpOpt).then(function (res) {
|
|
46
|
+
return {
|
|
47
|
+
res,
|
|
48
|
+
body
|
|
49
|
+
}
|
|
50
|
+
})
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
exports.func = function (args) {
|
|
54
|
+
const jar = args.jar
|
|
55
|
+
const url = args.url
|
|
56
|
+
const custom = args.http
|
|
57
|
+
return getVerification({ url: custom ? (custom.url || url) : url, jar, ignoreCache: args.ignoreCache, getBody: args.getBody })
|
|
58
|
+
.then(function (response) {
|
|
59
|
+
return general(jar, url, response.inputs, args.events, args.http, response.body)
|
|
60
|
+
})
|
|
61
|
+
}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
// Args
|
|
2
|
+
exports.required = ['row']
|
|
3
|
+
|
|
4
|
+
// Define
|
|
5
|
+
const regex = [
|
|
6
|
+
/rank from (.+) to (.+)\.$/,
|
|
7
|
+
/deleted post "(.+)" by user .+\.$/,
|
|
8
|
+
/changed the group status to: (.*)$/
|
|
9
|
+
]
|
|
10
|
+
// This is no longer used within the library and is maintained only for the purposes of backwards compatibility
|
|
11
|
+
// TODO: Remove this in next Semver major version
|
|
12
|
+
|
|
13
|
+
// Docs
|
|
14
|
+
/**
|
|
15
|
+
* ✅ Get the action row for the audit log text. Supported: change rank, delete post, change group status.
|
|
16
|
+
* @category Utility
|
|
17
|
+
* @alias getAction
|
|
18
|
+
* @deprecated
|
|
19
|
+
* @param {string} row - The audit log action row.
|
|
20
|
+
* @returns {AuditItem}
|
|
21
|
+
**/
|
|
22
|
+
|
|
23
|
+
exports.func = function (args) {
|
|
24
|
+
const row = args.row
|
|
25
|
+
const text = row.text()
|
|
26
|
+
const params = []
|
|
27
|
+
for (let i = 0; i < regex.length; i++) {
|
|
28
|
+
const match = text.match(regex[i])
|
|
29
|
+
if (match) {
|
|
30
|
+
for (let j = 1; j < match.length; j++) {
|
|
31
|
+
params.push(match[j])
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
const target = row.find('a').last().attr('href')
|
|
36
|
+
let found = target.match(/\?ID=(\d+)$/)
|
|
37
|
+
if (!found) {
|
|
38
|
+
found = target.match(/^games\/(\d+)\//)
|
|
39
|
+
}
|
|
40
|
+
found = found && parseInt(found[1], 10)
|
|
41
|
+
return {
|
|
42
|
+
target: found,
|
|
43
|
+
params
|
|
44
|
+
}
|
|
45
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const http = require('./http.js').func
|
|
3
|
+
|
|
4
|
+
// Args
|
|
5
|
+
exports.optional = ['jar']
|
|
6
|
+
|
|
7
|
+
// Docs
|
|
8
|
+
/**
|
|
9
|
+
* 🔐 Get the current authenticated user.
|
|
10
|
+
* @category Utility
|
|
11
|
+
* @alias getAuthenticatedUser
|
|
12
|
+
* @returns {AuthenticatedUserData}
|
|
13
|
+
* @example const noblox = require("noblox.js")
|
|
14
|
+
* // Login using your cookie.
|
|
15
|
+
* const user = await noblox.getAuthenticatedUser()
|
|
16
|
+
**/
|
|
17
|
+
|
|
18
|
+
// Define
|
|
19
|
+
exports.func = async function (args) {
|
|
20
|
+
const jar = args.jar
|
|
21
|
+
const httpOpt = {
|
|
22
|
+
url: '//users.roblox.com/v1/users/authenticated',
|
|
23
|
+
options: {
|
|
24
|
+
method: 'GET',
|
|
25
|
+
followRedirect: false,
|
|
26
|
+
jar,
|
|
27
|
+
json: true,
|
|
28
|
+
resolveWithFullResponse: true
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
const res = await http(httpOpt)
|
|
33
|
+
|
|
34
|
+
if (res.statusCode === 401) {
|
|
35
|
+
throw new Error('You are not logged in.')
|
|
36
|
+
} else if (res.statusCode !== 200) {
|
|
37
|
+
throw new Error(JSON.stringify(res.body))
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
return res.body
|
|
41
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const settings = require('../../settings.json')
|
|
3
|
+
|
|
4
|
+
const noblox = require('../index.js')
|
|
5
|
+
|
|
6
|
+
exports.optional = ['option', 'jar']
|
|
7
|
+
|
|
8
|
+
// Docs
|
|
9
|
+
/**
|
|
10
|
+
* 🔐 Get the current logged in user.
|
|
11
|
+
* @category Utility
|
|
12
|
+
* @alias getCurrentUser
|
|
13
|
+
* @param {string=} option - A specific option to return.
|
|
14
|
+
* @returns {LoggedInUserData}
|
|
15
|
+
* @example const noblox = require("noblox.js")
|
|
16
|
+
* @deprecated getCurrentUser() is deprecated; see getAuthenticatedUser(), getPremium(), getThumbnails(), getUserFunds() instead | August 27, 2024 - https://devforum.roblox.com/t/official-list-of-deprecated-web-endpoints/62889/66
|
|
17
|
+
* // Login using your cookie.
|
|
18
|
+
* const user = await noblox.getCurrentUser()
|
|
19
|
+
**/
|
|
20
|
+
|
|
21
|
+
// Define
|
|
22
|
+
exports.func = async function (args) {
|
|
23
|
+
const jar = args.jar
|
|
24
|
+
const option = args.option
|
|
25
|
+
if (settings.show_deprecation_warnings) {
|
|
26
|
+
console.warn('[DEPRECATED]: getCurrentUser() is deprecated by Roblox; use getAuthenticatedUser(), getPremium(), getThumbnails(), or getUserFunds() instead!')
|
|
27
|
+
console.warn(' > Opt out of these warnings using noblox.setOptions({ show_deprecation_warnings: false })')
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const currentUser = await noblox.getAuthenticatedUser(jar)
|
|
31
|
+
const [premiumStatus, thumbnailResponse, robuxBalance] = await Promise.all(
|
|
32
|
+
[
|
|
33
|
+
noblox.getPremium(currentUser.id, jar),
|
|
34
|
+
noblox.getPlayerThumbnail(currentUser.id, '352x352', 'png', false, 'Body', jar),
|
|
35
|
+
noblox.getUserFunds(currentUser.id, jar)
|
|
36
|
+
]
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
const json = {
|
|
40
|
+
UserID: currentUser.id,
|
|
41
|
+
UserName: currentUser.name,
|
|
42
|
+
RobuxBalance: robuxBalance,
|
|
43
|
+
ThumbnailUrl: thumbnailResponse[0].imageUrl,
|
|
44
|
+
IsAnyBuildersClubMember: false,
|
|
45
|
+
IsPremium: premiumStatus,
|
|
46
|
+
DEPRECATION_WARNING: '[DEPRECATED]: noblox.getCurrentUser() is deprecated; use getAuthenticatedUser(), getPremium(), getThumbnails(), or getUserFunds() instead!'
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
if (!option) {
|
|
50
|
+
return json
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Support queried rgequests `getCurrentUser('UserID') -> only UserID`
|
|
54
|
+
const searchKey = Object.keys(json).filter((key) => {
|
|
55
|
+
return option.toLowerCase() === key.toLowerCase()
|
|
56
|
+
})[0]
|
|
57
|
+
return json[searchKey]
|
|
58
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
// Includes
|
|
2
|
+
const getHash = require('./getHash.js').func
|
|
3
|
+
const http = require('./http.js').func
|
|
4
|
+
const cache = require('../cache')
|
|
5
|
+
const options = require('../options.js')
|
|
6
|
+
|
|
7
|
+
// Args
|
|
8
|
+
exports.optional = ['jar']
|
|
9
|
+
|
|
10
|
+
// Docs
|
|
11
|
+
/**
|
|
12
|
+
* 🔐 Generate an X-CSRF-Token.
|
|
13
|
+
* @category Utility
|
|
14
|
+
* @alias getGeneralToken
|
|
15
|
+
* @param {CookieJar=} jar - The jar containing the .ROBLOSECURITY token.
|
|
16
|
+
* @returns {Promise<string>}
|
|
17
|
+
* @example const noblox = require("noblox.js")
|
|
18
|
+
* // Login using your cookie.
|
|
19
|
+
* const XCSRF = await noblox.getGeneralToken()
|
|
20
|
+
**/
|
|
21
|
+
|
|
22
|
+
// Define
|
|
23
|
+
function getGeneralToken (jar) {
|
|
24
|
+
if (!jar && !options.jar.session) {
|
|
25
|
+
throw new Error('Cannot get CSRF: You are not logged in.')
|
|
26
|
+
}
|
|
27
|
+
const httpOpt = {
|
|
28
|
+
// This will never actually sign you out because an X-CSRF-TOKEN isn't provided, only received
|
|
29
|
+
url: '//auth.roblox.com/v2/logout', // REQUIRES https. Thanks for letting me know, ROBLOX...
|
|
30
|
+
options: {
|
|
31
|
+
resolveWithFullResponse: true,
|
|
32
|
+
method: 'POST',
|
|
33
|
+
jar
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return http(httpOpt)
|
|
37
|
+
.then(function (res) {
|
|
38
|
+
const xcsrf = res.headers['x-csrf-token']
|
|
39
|
+
if (xcsrf) {
|
|
40
|
+
return xcsrf
|
|
41
|
+
} else {
|
|
42
|
+
throw new Error('Did not receive X-CSRF-TOKEN')
|
|
43
|
+
}
|
|
44
|
+
})
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
exports.func = function (args) {
|
|
48
|
+
const jar = args.jar
|
|
49
|
+
return cache.wrap('XCSRF', getHash({ jar }), function () {
|
|
50
|
+
return getGeneralToken(jar)
|
|
51
|
+
})
|
|
52
|
+
}
|