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.
Files changed (272) hide show
  1. package/.github/ISSUE_TEMPLATE/bug_report.md +29 -0
  2. package/.github/ISSUE_TEMPLATE/feature_request.md +22 -0
  3. package/.github/workflows/doc-publish.yml +33 -0
  4. package/.github/workflows/npmpublish.yml +72 -0
  5. package/.github/workflows/run-tests.yml +49 -0
  6. package/CODE_OF_CONDUCT.md +76 -0
  7. package/LICENSE +21 -0
  8. package/README.md +182 -0
  9. package/eslint.config.mjs +34 -0
  10. package/examples/cleanPlayers.js +130 -0
  11. package/examples/cleanWall.js +110 -0
  12. package/examples/revertRanks.js +100 -0
  13. package/examples/savePlayers.js +119 -0
  14. package/examples/saveWall.js +96 -0
  15. package/img/moderatedThumbnails/moderatedThumbnail_100x100.png +0 -0
  16. package/img/moderatedThumbnails/moderatedThumbnail_110x110.png +0 -0
  17. package/img/moderatedThumbnails/moderatedThumbnail_140x140.png +0 -0
  18. package/img/moderatedThumbnails/moderatedThumbnail_150x150.png +0 -0
  19. package/img/moderatedThumbnails/moderatedThumbnail_150x200.png +0 -0
  20. package/img/moderatedThumbnails/moderatedThumbnail_180x180.png +0 -0
  21. package/img/moderatedThumbnails/moderatedThumbnail_250x250.png +0 -0
  22. package/img/moderatedThumbnails/moderatedThumbnail_30x30.png +0 -0
  23. package/img/moderatedThumbnails/moderatedThumbnail_352x352.png +0 -0
  24. package/img/moderatedThumbnails/moderatedThumbnail_420x420.png +0 -0
  25. package/img/moderatedThumbnails/moderatedThumbnail_48x48.png +0 -0
  26. package/img/moderatedThumbnails/moderatedThumbnail_50x50.png +0 -0
  27. package/img/moderatedThumbnails/moderatedThumbnail_60x60.png +0 -0
  28. package/img/moderatedThumbnails/moderatedThumbnail_720x720.png +0 -0
  29. package/img/moderatedThumbnails/moderatedThumbnail_75x75.png +0 -0
  30. package/img/noblox-js-small.png +0 -0
  31. package/img/noblox-js.png +0 -0
  32. package/img/thumbnailSizes.png +0 -0
  33. package/jsDocsConfig.json +55 -0
  34. package/lib/accountinformation/getUserSocialLinks.js +40 -0
  35. package/lib/accountsettings/block.js +53 -0
  36. package/lib/accountsettings/unblock.js +53 -0
  37. package/lib/asset/deleteFromInventory.js +56 -0
  38. package/lib/asset/getGamePassProductInfo.js +50 -0
  39. package/lib/asset/getProductInfo.js +46 -0
  40. package/lib/asset/uploadAnimation.js +103 -0
  41. package/lib/asset/uploadItem.js +83 -0
  42. package/lib/asset/uploadModel.js +90 -0
  43. package/lib/avatar/avatarRules.js +39 -0
  44. package/lib/avatar/currentlyWearing.js +33 -0
  45. package/lib/avatar/getAvatar.js +36 -0
  46. package/lib/avatar/getCurrentAvatar.js +38 -0
  47. package/lib/avatar/getRecentItems.js +36 -0
  48. package/lib/avatar/outfitDetails.js +33 -0
  49. package/lib/avatar/outfits.js +38 -0
  50. package/lib/avatar/redrawAvatar.js +47 -0
  51. package/lib/avatar/removeAssetId.js +51 -0
  52. package/lib/avatar/setAvatarBodyColors.js +61 -0
  53. package/lib/avatar/setAvatarScales.js +61 -0
  54. package/lib/avatar/setPlayerAvatarType.js +51 -0
  55. package/lib/avatar/setWearingAssets.js +51 -0
  56. package/lib/avatar/wearAssetId.js +51 -0
  57. package/lib/badges/getAwardedTimestamps.js +49 -0
  58. package/lib/badges/getBadgeInfo.js +44 -0
  59. package/lib/badges/getGameBadges.js +63 -0
  60. package/lib/badges/getPlayerBadges.js +28 -0
  61. package/lib/badges/updateBadgeInfo.js +75 -0
  62. package/lib/cache/add.js +14 -0
  63. package/lib/cache/addIf.js +26 -0
  64. package/lib/cache/clear.js +8 -0
  65. package/lib/cache/get.js +28 -0
  66. package/lib/cache/index.js +17 -0
  67. package/lib/cache/new.js +12 -0
  68. package/lib/cache/wrap.js +25 -0
  69. package/lib/chat/addUsersToConversation.js +58 -0
  70. package/lib/chat/chatSettings.js +34 -0
  71. package/lib/chat/getChatMessages.js +41 -0
  72. package/lib/chat/getConversations.js +44 -0
  73. package/lib/chat/getRolloutSettings.js +36 -0
  74. package/lib/chat/getUnreadConversationCount.js +34 -0
  75. package/lib/chat/getUnreadMessages.js +39 -0
  76. package/lib/chat/getUserConversations.js +38 -0
  77. package/lib/chat/markChatAsRead.js +53 -0
  78. package/lib/chat/markChatAsSeen.js +51 -0
  79. package/lib/chat/multiGetLatestMessages.js +38 -0
  80. package/lib/chat/onNewConversation.js +50 -0
  81. package/lib/chat/onNewMessage.js +53 -0
  82. package/lib/chat/onNewMessageBySelf.js +50 -0
  83. package/lib/chat/onUserOnline.js +50 -0
  84. package/lib/chat/onUserTyping.js +54 -0
  85. package/lib/chat/removeFromGroupConversation.js +59 -0
  86. package/lib/chat/renameGroupConversation.js +58 -0
  87. package/lib/chat/sendChatMessage.js +58 -0
  88. package/lib/chat/setChatUserTyping.js +58 -0
  89. package/lib/chat/start121Conversation.js +51 -0
  90. package/lib/chat/startCloudEditConversation.js +51 -0
  91. package/lib/chat/startGroupConversation.js +59 -0
  92. package/lib/client/onNotification.js +86 -0
  93. package/lib/client/setAPIKey.js +18 -0
  94. package/lib/client/setCookie.js +38 -0
  95. package/lib/datastores/deleteDatastoreEntry.js +56 -0
  96. package/lib/datastores/getDatastoreEntry.js +88 -0
  97. package/lib/datastores/getDatastoreEntryVersions.js +73 -0
  98. package/lib/datastores/getDatastoreKeys.js +63 -0
  99. package/lib/datastores/getDatastores.js +62 -0
  100. package/lib/datastores/incrementDatastoreEntry.js +83 -0
  101. package/lib/datastores/setDatastoreEntry.js +80 -0
  102. package/lib/develop/canManage.js +42 -0
  103. package/lib/develop/configureItem.js +210 -0
  104. package/lib/develop/updateUniverse.js +52 -0
  105. package/lib/develop/updateUniverseAccess.js +54 -0
  106. package/lib/economy/getGroupFunds.js +42 -0
  107. package/lib/economy/getGroupPayoutEligibility.js +55 -0
  108. package/lib/economy/getGroupRevenueSummary.js +42 -0
  109. package/lib/economy/getGroupTransactions.js +32 -0
  110. package/lib/economy/getResaleData.js +48 -0
  111. package/lib/economy/getResellers.js +35 -0
  112. package/lib/economy/getUserFunds.js +43 -0
  113. package/lib/economy/getUserTransactions.js +34 -0
  114. package/lib/economy/onGroupTransaction.js +74 -0
  115. package/lib/friends/acceptFriendRequest.js +54 -0
  116. package/lib/friends/declineAllFriendRequests.js +52 -0
  117. package/lib/friends/declineFriendRequest.js +54 -0
  118. package/lib/friends/getFollowerCount.js +35 -0
  119. package/lib/friends/getFollowers.js +56 -0
  120. package/lib/friends/getFollowingCount.js +35 -0
  121. package/lib/friends/getFollowings.js +56 -0
  122. package/lib/friends/getFriendCount.js +35 -0
  123. package/lib/friends/getFriendRequests.js +51 -0
  124. package/lib/friends/getFriends.js +48 -0
  125. package/lib/friends/onFriendRequest.js +58 -0
  126. package/lib/friends/removeFriend.js +53 -0
  127. package/lib/friends/sendFriendRequest.js +54 -0
  128. package/lib/friends/unfollow.js +53 -0
  129. package/lib/games/addDeveloperProduct.js +53 -0
  130. package/lib/games/configureGamePass.js +126 -0
  131. package/lib/games/getDeveloperProducts.js +44 -0
  132. package/lib/games/getGameInstances.js +31 -0
  133. package/lib/games/getGamePasses.js +39 -0
  134. package/lib/games/getGameRevenue.js +48 -0
  135. package/lib/games/getGameSocialLinks.js +42 -0
  136. package/lib/games/getGroupGames.js +30 -0
  137. package/lib/games/getPlaceInfo.js +47 -0
  138. package/lib/games/getUniverseInfo.js +50 -0
  139. package/lib/games/publishToTopic.js +52 -0
  140. package/lib/games/sendUserNotification.js +65 -0
  141. package/lib/games/updateDeveloperProduct.js +56 -0
  142. package/lib/groups/banFromGroup.js +47 -0
  143. package/lib/groups/changeRank.js +59 -0
  144. package/lib/groups/deleteWallPost.js +59 -0
  145. package/lib/groups/deleteWallPostsByUser.js +55 -0
  146. package/lib/groups/demote.js +25 -0
  147. package/lib/groups/exile.js +55 -0
  148. package/lib/groups/getAuditLog.js +64 -0
  149. package/lib/groups/getGroup.js +50 -0
  150. package/lib/groups/getGroupBans.js +37 -0
  151. package/lib/groups/getGroupSocialLinks.js +41 -0
  152. package/lib/groups/getGroups.js +82 -0
  153. package/lib/groups/getJoinRequest.js +47 -0
  154. package/lib/groups/getJoinRequests.js +53 -0
  155. package/lib/groups/getPlayers.js +103 -0
  156. package/lib/groups/getRankInGroup.js +45 -0
  157. package/lib/groups/getRankNameInGroup.js +44 -0
  158. package/lib/groups/getRole.js +64 -0
  159. package/lib/groups/getRolePermissions.js +48 -0
  160. package/lib/groups/getRoles.js +53 -0
  161. package/lib/groups/getShout.js +47 -0
  162. package/lib/groups/getWall.js +56 -0
  163. package/lib/groups/groupPayout.js +103 -0
  164. package/lib/groups/handleJoinRequest.js +57 -0
  165. package/lib/groups/handleJoinRequests.js +61 -0
  166. package/lib/groups/leaveGroup.js +56 -0
  167. package/lib/groups/onAuditLog.js +62 -0
  168. package/lib/groups/onJoinRequest.js +63 -0
  169. package/lib/groups/onJoinRequestHandle.js +105 -0
  170. package/lib/groups/onShout.js +57 -0
  171. package/lib/groups/onWallPost.js +58 -0
  172. package/lib/groups/promote.js +25 -0
  173. package/lib/groups/searchGroups.js +32 -0
  174. package/lib/groups/setGroupDescription.js +58 -0
  175. package/lib/groups/setGroupName.js +59 -0
  176. package/lib/groups/setRank.js +74 -0
  177. package/lib/groups/setRoleInfo.js +84 -0
  178. package/lib/groups/shout.js +58 -0
  179. package/lib/groups/unbanFromGroup.js +41 -0
  180. package/lib/index.js +212 -0
  181. package/lib/internal/levelOneCopy.js +16 -0
  182. package/lib/internal/queue.js +61 -0
  183. package/lib/internal/timeout.js +30 -0
  184. package/lib/internal/wrap.js +78 -0
  185. package/lib/inventory/getCollectibles.js +31 -0
  186. package/lib/inventory/getInventory.js +32 -0
  187. package/lib/inventory/getInventoryById.js +31 -0
  188. package/lib/inventory/getOwnership.js +47 -0
  189. package/lib/inventory/getUAIDs.js +47 -0
  190. package/lib/itemconfiguration/getGroupAssets.js +32 -0
  191. package/lib/options.js +26 -0
  192. package/lib/party/onPartyDeleted.js +53 -0
  193. package/lib/party/onPartyInvite.js +53 -0
  194. package/lib/party/onPartyJoinedGame.js +53 -0
  195. package/lib/party/onPartyLeftGame.js +53 -0
  196. package/lib/party/onPartySelfJoined.js +53 -0
  197. package/lib/party/onPartySelfLeft.js +53 -0
  198. package/lib/party/onPartyUserJoined.js +53 -0
  199. package/lib/party/onPartyUserLeft.js +53 -0
  200. package/lib/premiumfeatures/getPremium.js +46 -0
  201. package/lib/presence/getPresences.js +60 -0
  202. package/lib/privatemessages/getMessages.js +55 -0
  203. package/lib/privatemessages/message.js +75 -0
  204. package/lib/privatemessages/onMessage.js +89 -0
  205. package/lib/thumbnails/getLogo.js +56 -0
  206. package/lib/thumbnails/getPlayerThumbnail.js +120 -0
  207. package/lib/thumbnails/getThumbnails.js +92 -0
  208. package/lib/trades/acceptTrade.js +52 -0
  209. package/lib/trades/canTradeWith.js +43 -0
  210. package/lib/trades/counterTrade.js +78 -0
  211. package/lib/trades/declineTrade.js +52 -0
  212. package/lib/trades/getTradeInfo.js +47 -0
  213. package/lib/trades/getTrades.js +37 -0
  214. package/lib/trades/sendTrade.js +76 -0
  215. package/lib/users/getBlurb.js +37 -0
  216. package/lib/users/getIdFromUsername.js +56 -0
  217. package/lib/users/getPlayerInfo.js +128 -0
  218. package/lib/users/getUserInfo.js +35 -0
  219. package/lib/users/getUsernameFromId.js +45 -0
  220. package/lib/users/getUsernameHistory.js +42 -0
  221. package/lib/users/onBlurbChange.js +46 -0
  222. package/lib/users/searchUsers.js +41 -0
  223. package/lib/util/apiError.js +50 -0
  224. package/lib/util/clearSession.js +32 -0
  225. package/lib/util/generalRequest.js +61 -0
  226. package/lib/util/getAction.js +45 -0
  227. package/lib/util/getAuthenticatedUser.js +41 -0
  228. package/lib/util/getCurrentUser.js +58 -0
  229. package/lib/util/getGeneralToken.js +52 -0
  230. package/lib/util/getHash.js +29 -0
  231. package/lib/util/getInputs.js +37 -0
  232. package/lib/util/getPageResults.js +86 -0
  233. package/lib/util/getSenderUserId.js +30 -0
  234. package/lib/util/getSession.js +38 -0
  235. package/lib/util/getVerification.js +60 -0
  236. package/lib/util/getVerificationInputs.js +31 -0
  237. package/lib/util/http.js +138 -0
  238. package/lib/util/jar.js +25 -0
  239. package/lib/util/refreshCookie.js +52 -0
  240. package/lib/util/relog.js +81 -0
  241. package/lib/util/setOptions.js +54 -0
  242. package/lib/util/shortPoll.js +102 -0
  243. package/package.json +76 -0
  244. package/postinstall.mjs +1 -0
  245. package/settings.json +115 -0
  246. package/test/accountinformation.test.js +27 -0
  247. package/test/accountsettings.test.js +27 -0
  248. package/test/asset.test.js +81 -0
  249. package/test/assets/Great-White-Shark-Fin.rbxm +0 -0
  250. package/test/assets/KeyframeSequence.rbxm +0 -0
  251. package/test/avatar.test.js +164 -0
  252. package/test/badges.test.js +96 -0
  253. package/test/chat.test.js +104 -0
  254. package/test/datastore.test.js +105 -0
  255. package/test/develop.test.js +53 -0
  256. package/test/economy.test.js +143 -0
  257. package/test/friends.test.js +146 -0
  258. package/test/games.test.js +229 -0
  259. package/test/groups.test.js +405 -0
  260. package/test/inventory.test.js +98 -0
  261. package/test/itemconfiguration.test.js +24 -0
  262. package/test/premiumfeatures.test.js +17 -0
  263. package/test/presence.test.js +25 -0
  264. package/test/privatemessages.test.js +33 -0
  265. package/test/thumbnails.test.js +53 -0
  266. package/test/users.test.js +110 -0
  267. package/tutorials/Authentication.md +75 -0
  268. package/tutorials/Event Emitters.md +26 -0
  269. package/tutorials/Promises.md +86 -0
  270. package/tutorials/VPS Authentication.md +72 -0
  271. package/typings/index.d.ts +2639 -0
  272. package/typings/jsDocs.ts +1987 -0
@@ -0,0 +1,29 @@
1
+ // Dependencies
2
+ const crypto = require('crypto')
3
+
4
+ // Includes
5
+ const getSession = require('./getSession.js').func
6
+
7
+ // Args
8
+ exports.optional = ['jar']
9
+
10
+ // Docs
11
+ /**
12
+ * 🔐 Get a unique hash for the given jar. Used to cache items that depend on session.
13
+ * @category Utility
14
+ * @alias getHash
15
+ * @param {CookieJar} jar - The audit log action row.
16
+ * @returns {string}
17
+ * @example const noblox = require("noblox.js")
18
+ * // Login using your cookie.
19
+ * const hash = noblox.getHash()
20
+ **/
21
+
22
+ // Define
23
+ exports.func = function ({ jar }) {
24
+ if (typeof jar === 'string') {
25
+ jar = { session: jar }
26
+ }
27
+ const session = getSession({ jar })
28
+ return crypto.createHash('md5').update(session).digest('hex')
29
+ }
@@ -0,0 +1,37 @@
1
+ // Dependencies
2
+ const parser = require('cheerio')
3
+
4
+ // Args
5
+ exports.required = ['html']
6
+ exports.optional = ['find']
7
+
8
+ // Docs
9
+ /**
10
+ * ✅ Get verification inputs on a page.
11
+ * @category Utility
12
+ * @alias getInputs
13
+ * @param {string} html - The html to get the inputs from.
14
+ * @param {Array<string>=} find - The inputs to find on the page
15
+ * @returns {Inputs}
16
+ * @example const noblox = require("noblox.js")
17
+ * const inputs = noblox.getInputs("htmlhere")
18
+ **/
19
+
20
+ // Define
21
+ exports.func = function (args) {
22
+ const $ = parser.load(args.html)
23
+ const inputs = {}
24
+ const find = args.find
25
+ if (find) {
26
+ for (let i = 0; i < find.length; i++) {
27
+ const get = find[i]
28
+ inputs[get] = $('input[name=' + get + ']').val()
29
+ }
30
+ } else {
31
+ $('input[name]').each(function (index, element) {
32
+ const here = $(this)
33
+ inputs[here.attr('name')] = here.val()
34
+ })
35
+ }
36
+ return inputs
37
+ }
@@ -0,0 +1,86 @@
1
+ // Includes
2
+ const http = require('./http.js').func
3
+ const RobloxAPIError = require('./apiError.js')
4
+
5
+ // Args
6
+ exports.required = ['url', 'query', 'limit']
7
+ exports.optional = ['jar', 'sortOrder']
8
+
9
+ // Docs
10
+ /**
11
+ * ✅ Handle pagination returned by Roblox.
12
+ * @category Utility
13
+ * @alias getPageResults
14
+ * @param {string} url - The url to retrieve the page results from.
15
+ * @param {string} query - Any query parameters to add to the url.
16
+ * @param {SortOrder=} sortOrder - The order to sort the results by.
17
+ * @param {Limit=} limit - The maximum number of results to return. Following 'pages' of results will be requested until
18
+ * this limit of results is reached.
19
+ * @param {string=} pageCursor - Current page index
20
+ * @returns {Promise<Array>}
21
+ * @example const noblox = require("noblox.js")
22
+ * const inventory = await noblox.getPageResults("//inventory.roblox.com/v2/users/1/inventory", "Shirt", "Asc", 100)
23
+ **/
24
+
25
+ // Define
26
+ function getPageResults (jar, url, query, sortOrder, limit, pageCursor, results) {
27
+ return new Promise((resolve, reject) => {
28
+ const allowedLimits = [10, 25, 50, 100]
29
+
30
+ const httpOpt = {
31
+ url,
32
+ options: {
33
+ qs: {
34
+ limit: limit <= 100 ? allowedLimits.reduce((prev, curr) => Math.abs(curr - limit) < Math.abs(prev - limit) ? curr : prev) : 100, // Get the most fit page limit within the boundries.
35
+ cursor: pageCursor || '', // Add page cursor.
36
+ ...query // Add asset types.
37
+ },
38
+ method: 'GET',
39
+ resolveWithFullResponse: true,
40
+ jar,
41
+ json: true
42
+ }
43
+ }
44
+ return http(httpOpt).then((res) => {
45
+ let body = res.body
46
+ if (typeof (body) === 'string') body = JSON.parse(body.trim())
47
+
48
+ const data = body.data
49
+
50
+ if (res.statusCode !== 200) {
51
+ return reject(new RobloxAPIError(res))
52
+ }
53
+
54
+ results = results ? results.concat(data) : data
55
+
56
+ if (results.length > limit) {
57
+ results = results.slice(0, limit)
58
+ }
59
+
60
+ if (results.length >= limit || data.length === 0 || !body.nextPageCursor) {
61
+ return resolve(results)
62
+ }
63
+
64
+ resolve(getPageResults(jar, url, query, sortOrder, limit, body.nextPageCursor, results))
65
+ })
66
+ .catch(error => reject(error))
67
+ })
68
+ }
69
+
70
+ function parseDates (results) {
71
+ return new Promise((resolve, reject) => {
72
+ if (!results) return resolve([])
73
+
74
+ resolve(results.map(result => {
75
+ if (result.created) result.created = new Date(result.created)
76
+ if (result.updated) result.updated = new Date(result.updated)
77
+ return result
78
+ }))
79
+ })
80
+ }
81
+
82
+ exports.func = function (args) {
83
+ return getPageResults(args.jar, args.url, args.query, args.sortOrder, args.limit).then(results => {
84
+ return parseDates(results)
85
+ })
86
+ }
@@ -0,0 +1,30 @@
1
+ // Includes
2
+ const getCurrentUser = require('./getCurrentUser.js').func
3
+ const getHash = require('./getHash.js').func
4
+ const cache = require('../cache')
5
+
6
+ // Args
7
+ exports.optional = ['jar']
8
+
9
+ // Docs
10
+ /**
11
+ * 🔐 Get the userId of the current user and cache it.
12
+ * @category Utility
13
+ * @alias getSenderUserId
14
+ * @param {CookieJar=} jar - The CookieJar containing the .ROBLOSECURITY cookie.
15
+ * @returns {Promise<number>}
16
+ * @example const noblox = require("noblox.js")
17
+ * // Login using your cookie.
18
+ * const userId = await noblox.getSenderUserId()
19
+ **/
20
+
21
+ // Define
22
+ exports.func = function (args) {
23
+ const jar = args.jar
24
+ return cache.wrap('SenderID', getHash({ jar }), function () {
25
+ return getCurrentUser({ jar })
26
+ .then(function (info) {
27
+ return info.UserID
28
+ })
29
+ })
30
+ }
@@ -0,0 +1,38 @@
1
+ // Includes
2
+ const settings = require('../../settings.json')
3
+ const options = require('../options.js')
4
+
5
+ // Args
6
+ exports.optional = ['jar']
7
+
8
+ // Docs
9
+ /**
10
+ * 🔐 Get the .ROBLOSECURITY cookie from the jar.
11
+ * @category Utility
12
+ * @alias getSession
13
+ * @param {CookieJar=} jar - The cookie jar containing the .ROBLOSECURITY cookie.
14
+ * @returns {string}
15
+ * @example const noblox = require("noblox.js")
16
+ * // Login using your cookie.
17
+ * const cookie = await noblox.getSession()
18
+ **/
19
+
20
+ // Define
21
+ exports.func = function (args) {
22
+ const jar = args.jar || options.jar
23
+ if (settings.session_only) {
24
+ if (typeof jar === 'string') {
25
+ return jar
26
+ }
27
+ return jar.session
28
+ } else {
29
+ const cookies = jar.getCookies('https://roblox.com')
30
+ for (let i = 0; i < cookies.length; i++) {
31
+ const element = cookies[i]
32
+ if (element.key === '.ROBLOSECURITY') {
33
+ return element.value
34
+ }
35
+ }
36
+ return ''
37
+ }
38
+ }
@@ -0,0 +1,60 @@
1
+ // Includes
2
+ const http = require('./http.js').func
3
+ const getHash = require('./getHash.js').func
4
+ const getVerificationInputs = require('./getVerificationInputs.js').func
5
+ const cache = require('../cache')
6
+ const URL = require('url').URL
7
+
8
+ // Args
9
+ exports.required = ['url']
10
+ exports.optional = ['ignoreCache', 'getBody', 'jar']
11
+
12
+ // Docs
13
+ /**
14
+ * 🔐 Get the RequestVerificationToken from a url.
15
+ * @category Utility
16
+ * @alias getVerification
17
+ * @param {string} url - The url to get the token from.
18
+ * @param {boolean=} [ignoreCache=false] - Determines whether the cache be ignored or not.
19
+ * @param {boolean=} [getBody=false] - If the body and inputs should be returned in an object
20
+ * @param {CookieJar=} jar - The CookieJar containing the .ROBLOSECURITY cookie.
21
+ * @returns {Promise<GetVerificationResponse>}
22
+ * @example const noblox = require("noblox.js")
23
+ * // Login using your cookie.
24
+ * const verificationTokenInfo = await noblox.getVerification()
25
+ **/
26
+
27
+ // Define
28
+ function getVerification (jar, url, getBody) {
29
+ const httpOpt = {
30
+ url,
31
+ options: {
32
+ resolveWithFullResponse: true,
33
+ jar
34
+ }
35
+ }
36
+ return http(httpOpt)
37
+ .then(function (res) {
38
+ const inputs = getVerificationInputs({ html: res.body })
39
+ let match
40
+ if (res.headers && res.headers['set-cookie']) {
41
+ match = res.headers['set-cookie'].toString().match(/__RequestVerificationToken=(.*?);/)
42
+ }
43
+ return {
44
+ body: (getBody ? res.body : null),
45
+ inputs,
46
+ header: match && match[1]
47
+ }
48
+ })
49
+ }
50
+
51
+ exports.func = function (args) {
52
+ const jar = args.jar
53
+ if (args.ignoreCache) {
54
+ return getVerification(jar, args.url, args.getBody)
55
+ } else {
56
+ return cache.wrap('Verify', new URL(args.url).pathname + getHash({ jar }), function () {
57
+ return getVerification(jar, args.url, args.getBody)
58
+ })
59
+ }
60
+ }
@@ -0,0 +1,31 @@
1
+ // Dependencies
2
+ const parser = require('cheerio')
3
+
4
+ // Args
5
+ exports.required = [['html', 'selector']]
6
+
7
+ // Docs
8
+ /**
9
+ * ✅ Get the verification inputs from the html.
10
+ * @category Utility
11
+ * @alias getVerificationInputs
12
+ * @param {string | function} html | selector - The html to search or the cheerio selector to use.
13
+ * @returns {Inputs}
14
+ * @example const noblox = require("noblox.js")
15
+ * const inputs = noblox.getVerificationInputs("htmlstuff")
16
+ **/
17
+
18
+ // Define
19
+ exports.func = function (args) {
20
+ let $ = args.selector
21
+ if (!$) {
22
+ $ = parser.load(args.html)
23
+ }
24
+ const inputs = {}
25
+ const find = ['__VIEWSTATE', '__VIEWSTATEGENERATOR', '__EVENTVALIDATION', '__RequestVerificationToken']
26
+ for (let i = 0; i < find.length; i++) {
27
+ const get = find[i]
28
+ inputs[get] = $('input[name=' + get + ']').val()
29
+ }
30
+ return inputs
31
+ }
@@ -0,0 +1,138 @@
1
+ // Dependencies
2
+ const util = require('util')
3
+ let request = util.promisify(require('postman-request'))
4
+
5
+ // Includes
6
+ const options = require('../options.js')
7
+ const settings = require('../../settings.json')
8
+ const cache = require('../cache')
9
+ const getHash = require('./getHash.js').func
10
+ const { version } = require('../../package.json')
11
+
12
+ // Args
13
+ exports.required = ['url']
14
+ exports.optional = ['options', 'ignoreLoginError']
15
+
16
+ // Define
17
+ request = request.defaults({
18
+ forever: true,
19
+ agentOptions: {
20
+ maxSockets: Infinity
21
+ },
22
+ simple: false,
23
+ gzip: true,
24
+ timeout: settings.timeout,
25
+ headers: settings.use_noblox_ua
26
+ ? {
27
+ 'user-agent': `noblox-${version}`
28
+ }
29
+ : undefined
30
+ })
31
+
32
+ // Docs
33
+ /**
34
+ * ✅ Send an http request to url with options.
35
+ * @category Utility
36
+ * @alias http
37
+ * @param {string} url - The url to request to.
38
+ * @param {object} options - The options to send with the request.
39
+ * @param {boolean} ignoreLoginError - If any login errors should be ignored.
40
+ * @returns {Promise<string>}
41
+ * @example const noblox = require("noblox.js")
42
+ * const body = await noblox.http("https://roblox.com/login", { method: "GET" })
43
+ **/
44
+
45
+ function http (url, opt) {
46
+ if (opt?.headers) {
47
+ opt.headers = Object.fromEntries(
48
+ Object.entries(opt.headers).map(([k, v]) => [k.toLowerCase(), v])
49
+ )
50
+ }
51
+ if (opt && !opt.jar && Object.keys(opt).indexOf('jar') > -1) {
52
+ opt.jar = options.jar
53
+ }
54
+ if (settings.session_only && opt && opt.jar) {
55
+ if (!opt.headers) {
56
+ opt.headers = {}
57
+ }
58
+ opt.headers.cookie = '.ROBLOSECURITY=' + opt.jar.session + ';'
59
+ opt.headers['x-api-key'] = opt.jar.apiKey
60
+ opt.jar = null
61
+ }
62
+ if (opt && opt.verification) {
63
+ if (!opt.headers) {
64
+ opt.headers = {}
65
+ }
66
+ const verify = '__RequestVerificationToken=' + opt.verification + ';'
67
+ if (opt.headers.cookie) {
68
+ opt.headers.cookie += verify
69
+ } else {
70
+ opt.headers.cookie = verify
71
+ }
72
+ }
73
+ if (url.indexOf('http') !== 0) {
74
+ url = 'https:' + url
75
+ }
76
+
77
+ /*
78
+ In CI, actions does not allow us to use a static ip address (nor guarantees any particular location)
79
+ This is a problem as Roblox locks sessions to a particular region
80
+ Therefore, we intercept the request during testing and send it to the forwarder (which has a static ip address), the Roblox hostname is set as the Destination-Host header
81
+ The ID token is for Google Cloud and allows authenticating with the Cloud Run service that acts as our forwarder
82
+ Requests without auth headers do not go through the forwarder as they are unauthenticated and do not need forwarding
83
+ */
84
+ if (process?.env.CI && process.env.FORWARDER_HOSTNAME && (opt.headers.cookie || opt.headers['x-api-key'])) {
85
+ const urlObj = new URL(url)
86
+ const { hostname } = urlObj
87
+
88
+ opt.headers['Destination-Host'] = hostname
89
+ opt.headers['x-serverless-authorization'] = `Bearer ${process.env.ID_TOKEN}`
90
+ urlObj.hostname = process.env.FORWARDER_HOSTNAME
91
+ url = urlObj.href
92
+ }
93
+ return request(url, opt)
94
+ }
95
+
96
+ exports.func = function (args) {
97
+ const opt = args.options || {}
98
+ if (typeof opt.jar === 'string') {
99
+ opt.jar = { session: opt.jar }
100
+ }
101
+ const jar = opt.jar
102
+ const depth = args.depth || 0
103
+ const full = opt.resolveWithFullResponse || false
104
+ opt.resolveWithFullResponse = true
105
+ const follow = opt.followRedirect === undefined || opt.followRedirect
106
+ opt.followRedirect = function (res) {
107
+ if (!args.ignoreLoginError && res.headers.location && (res.headers.location.startsWith('https://www.roblox.com/newlogin') || res.headers.location.startsWith('/Login/Default.aspx'))) {
108
+ return false
109
+ }
110
+ return follow
111
+ }
112
+ return http(args.url, opt).then(function (res) {
113
+ if (res.statusCode === 403 && res.headers['x-csrf-token'] && Object.hasOwn(opt.headers ?? {}, 'x-csrf-token')) {
114
+ if (depth >= 2) {
115
+ throw new Error('Tried ' + (depth + 1) + ' times and could not refresh XCSRF token successfully')
116
+ }
117
+
118
+ const token = res.headers['x-csrf-token']
119
+
120
+ if (token) {
121
+ opt.headers['x-csrf-token'] = token
122
+ opt.jar = jar
123
+ args.depth = depth + 1
124
+ return exports.func(args)
125
+ } else {
126
+ throw new Error('Could not refresh X-CSRF-TOKEN')
127
+ }
128
+ } else {
129
+ if (depth > 0) {
130
+ cache.add(options.cache, 'XCSRF', getHash({ jar }), opt.headers['x-csrf-token'])
131
+ }
132
+ }
133
+ if (res.statusCode === 302 && !args.ignoreLoginError && res.headers.location && (res.headers.location.startsWith('https://www.roblox.com/newlogin') || res.headers.location.startsWith('/Login/Default.aspx'))) {
134
+ throw new Error('You are not logged in')
135
+ }
136
+ return full ? res : res.body
137
+ })
138
+ }
@@ -0,0 +1,25 @@
1
+ // Dependencies
2
+ const util = require('util')
3
+ const request = util.promisify(require('postman-request'))
4
+
5
+ // Includes
6
+ const settings = require('../../settings.json')
7
+
8
+ // Docs
9
+ /**
10
+ * ✅ Create a jar file based on sessionOnly.
11
+ * @category Utility
12
+ * @alias jar
13
+ * @param {boolean=} sessionOnly - The session to use to create the jar file.
14
+ * @returns {CookieJar}
15
+ * @example const noblox = require("noblox.js")
16
+ * const jar = noblox.jar()
17
+ **/
18
+
19
+ // Define
20
+ exports.func = function (sessionOnly) {
21
+ if (!sessionOnly) {
22
+ sessionOnly = settings.session_only
23
+ }
24
+ return (sessionOnly ? { session: '' } : request.jar())
25
+ }
@@ -0,0 +1,52 @@
1
+ // Includes
2
+ const options = require('../options.js')
3
+ const getGeneralToken = require('./getGeneralToken.js').func
4
+ const http = require('./http.js').func
5
+ // Args
6
+ exports.required = []
7
+ exports.optional = ['cookie']
8
+
9
+ // Docs
10
+ /**
11
+ * 🔐 Refreshes the stored cookie, stores it, and returns it.
12
+ * @category Utility
13
+ * @deprecated [Retrieving your .ROBLOSECURITY cookie in incognito mode should make a cookie that does not expire.]{@link https://noblox.js.org/tutorial-Authentication.html}
14
+ * @alias refreshCookie
15
+ * @param {string=} cookie - The cookie to refresh.
16
+ * @returns {Promise<string>}
17
+ * @example const noblox = require("noblox.js")
18
+ * const newCookie = await noblox.refreshCookie("COOKIEHERE")
19
+ **/
20
+
21
+ // Refreshes the internally stored cookie, or the cookie provided
22
+ // Stores the new cookie & returns it
23
+ function refreshCookie (cookie) {
24
+ if (cookie) {
25
+ options.jar.session = cookie
26
+ }
27
+
28
+ return getGeneralToken({}).then((token) => {
29
+ return http({
30
+ url: 'https://www.roblox.com/authentication/signoutfromallsessionsandreauthenticate',
31
+ options: {
32
+ method: 'POST',
33
+ resolveWithFullResponse: true,
34
+ jar: null,
35
+ headers: {
36
+ 'X-CSRF-TOKEN': token
37
+ }
38
+ }
39
+ }).then((res) => {
40
+ const cookies = res.headers['set-cookie']
41
+ if (cookies) {
42
+ const cookie = cookies.toString().match(/\.ROBLOSECURITY=(.*?);/)[1]
43
+ options.jar.session = cookie
44
+ return cookie
45
+ } else {
46
+ throw new Error('Failed to refresh cookie: None returned.')
47
+ }
48
+ })
49
+ })
50
+ }
51
+
52
+ module.exports = refreshCookie
@@ -0,0 +1,81 @@
1
+ // Includes
2
+ const options = require('../options.js')
3
+ const getGeneralToken = require('./getGeneralToken.js').func
4
+ const getVerification = require('./getVerification.js').func
5
+ const getCurrentUser = require('./getCurrentUser.js').func
6
+ const http = require('./http.js').func
7
+ const cookieFile = './cookie'
8
+ const fs = require('fs')
9
+ // Args
10
+ exports.required = ['cookie']
11
+ exports.optional = []
12
+
13
+ const day = 86400000
14
+
15
+ // Define
16
+ const relog = (cookie) => {
17
+ if (!cookie) throw new Error('no cookie supplied?')
18
+ options.jar.session = cookie
19
+ return getVerification({ url: 'https://www.roblox.com/my/account#!/security' })
20
+ .then((ver) => {
21
+ if (!ver.header) console.log('Bad cookie.')
22
+ return getGeneralToken({}).then((token) => {
23
+ return http({
24
+ url: 'https://www.roblox.com/authentication/signoutfromallsessionsandreauthenticate',
25
+ options: {
26
+ method: 'POST',
27
+ resolveWithFullResponse: true,
28
+ verification: ver.header,
29
+ jar: null,
30
+ headers: {
31
+ 'X-CSRF-TOKEN': token
32
+ },
33
+ form: {
34
+ __RequestVerificationToken: ver.inputs.__RequestVerificationToken
35
+ }
36
+ }
37
+ }).then((res) => {
38
+ const cookies = res.headers['set-cookie']
39
+ if (cookies) {
40
+ options.jar.session = cookies.toString().match(/\.ROBLOSECURITY=(.*?);/)[1]
41
+
42
+ fs.writeFile(cookieFile, JSON.stringify({ cookie: options.jar.session, time: Date.now() }), (err) => {
43
+ if (err) {
44
+ console.error('Failed to write cookie')
45
+ }
46
+ return true
47
+ })
48
+ }
49
+ })
50
+ })
51
+ })
52
+ }
53
+ module.exports = c
54
+
55
+ async function c (cookie) {
56
+ // Check for file
57
+ if (fs.existsSync(cookieFile)) {
58
+ const json = JSON.parse(fs.readFileSync(cookieFile))
59
+
60
+ // Check its new enough
61
+ if (json.time + day > Date.now()) {
62
+ // Its recent enough. Try it.
63
+ try {
64
+ await relog(json.cookie)
65
+ return getCurrentUser({})
66
+ } catch (e) {
67
+ console.log('Stored relog failed. Trying with given.')
68
+ }
69
+ }
70
+ }
71
+ if (cookie) {
72
+ // Try the user's cookie
73
+ try {
74
+ await relog(cookie)
75
+ return getCurrentUser({})
76
+ } catch (e) {
77
+ console.error(e)
78
+ }
79
+ }
80
+ throw new Error('No cookie supplied and no cookie file available.')
81
+ }
@@ -0,0 +1,54 @@
1
+ const settings = require('../../settings.json')
2
+
3
+ // Docs
4
+ /**
5
+ * ✅ Updates library options. This allows you to modify settings such as time-out, or number of event retries without
6
+ * altering the settings.json file. Objects passed to this function should match the format of the settings.json file.
7
+ * Unknown keys, or malformed options will be rejected with an error.
8
+ * @category Utility
9
+ * @param {Partial<NobloxOptions>} newOptions - The new options to set, structured as per [settings.json](https://github.com/noblox/noblox.js/blob/master/settings.json)
10
+ * @returns void
11
+ * @see [settings.json](https://github.com/noblox/noblox.js/blob/master/settings.json) - default package settings
12
+ * @example const noblox = require("noblox.js")
13
+ * // This example overrides getPlayerThumbnail()'s response URL when a thumbnail is moderated.
14
+ * // You usually want to run this before logging in with your cookie.
15
+ * noblox.setOptions({
16
+ * thumbnail: {
17
+ * failedUrl: {
18
+ * blocked: "https://raw.githubusercontent.com/noblox/noblox.js/master/img/noblox-js.png"
19
+ * }
20
+ * }
21
+ * })
22
+ */
23
+ function setOptions (newOptions) {
24
+ return setOptionsLevel(settings, newOptions)
25
+ }
26
+
27
+ // This function allows key validation to be performed at different "levels" of nesting.
28
+ // Ensures the provided keys already exist, and discards invalid keys.
29
+ function setOptionsLevel (settingsLevel, inputObj) {
30
+ const keys = Object.keys(inputObj)
31
+
32
+ for (const key of keys) {
33
+ const newValue = inputObj[key]
34
+ const currentValue = settingsLevel[key]
35
+
36
+ if (currentValue !== undefined) {
37
+ if (typeof currentValue === 'object') {
38
+ if (typeof inputObj[key] !== 'object') {
39
+ throw new Error(`Tried to set options key ${key}, an object, to a non-object value: ${newValue}`)
40
+ }
41
+
42
+ setOptionsLevel(currentValue, newValue)
43
+ } else {
44
+ // it's not undefined, and it's not a nested object - set the value.
45
+ settingsLevel[key] = newValue
46
+ }
47
+ } else {
48
+ // The key doesn't exist
49
+ throw new Error(`Tried to set option "${key}". This option does not exist, or has been nested incorrectly.`)
50
+ }
51
+ }
52
+ }
53
+
54
+ exports.func = setOptions