Skip to content

Commit

Permalink
Migrate setCookie from /mobileapi/userinfo to `/v1/users/authenti…
Browse files Browse the repository at this point in the history
…cated`; add `getUserFunds` method (#824)

* feat(breaking)!: add getUserFunds(); migrate setCookie() from getCurrentUser() to getAuthenticatedUser(); polyfill and deprecate getCurrentUser() + add console warnings for getCurrentUser usage

BREAKING CHANGE: getCurrentUser's /mobileinfo api endpoint is being deprecated by Roblox on August 27th (https://devforum.roblox.com/t/official-list-of-deprecated-web-endpoints/62889/66), setCookie will now have a new response type

* misc: promisify secondary calls, remove github PR hyperlink, fix setOptions typing

* lint: apply linting rules
  • Loading branch information
alanbixby authored Aug 16, 2024
1 parent 1aa2d50 commit 2be4343
Show file tree
Hide file tree
Showing 8 changed files with 95 additions and 24 deletions.
6 changes: 3 additions & 3 deletions lib/client/setCookie.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
const options = require('../options.js')
const getCurrentUser = require('../util/getCurrentUser.js').func
const getAuthenticatedUser = require('../util/getAuthenticatedUser.js').func

exports.required = ['cookie']
exports.optional = ['validate']
Expand All @@ -11,7 +11,7 @@ exports.optional = ['validate']
* @alias setCookie
* @param {string} cookie - The cookie to sign in with.
* @param {boolean=} [validate=true] - Whether to validate the cookie or not.
* @returns {Promise<LoggedInUserData>}
* @returns {Promise<AuthenticatedUserData>}
* @example const noblox = require("noblox.js")
* noblox.setCookie("cookie").then(function() {
* //your code here
Expand All @@ -28,7 +28,7 @@ exports.func = async function (args) {
return false
}
try {
const res = await getCurrentUser({ jar: { session: args.cookie } })
const res = await getAuthenticatedUser({ jar: { session: args.cookie } })
options.jar.session = args.cookie
return res
} catch (error) {
Expand Down
44 changes: 44 additions & 0 deletions lib/economy/getUserFunds.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
// Includes
const http = require('../util/http.js').func

// Args
exports.required = ['userId']
exports.optional = ['jar']

// Docs
/**
* 🔓 Gets the amount of robux for the authenticated user.
* @category User
* @param {number} userId - Must match the userId of the authenticated user
* @alias getUserFunds
* @returns {Promise<number>}
* @example const noblox = require("noblox.js")
* // Login using your cookie
* const currentUser = await noblox.setCookie(process.env.ROBLOXCOOKIE)
* const robux = await noblox.getUserFunds(currentUser.id)
*/

// Define
function getUserFunds (userId, jar) {
return http({
url: `//economy.roblox.com/v1/users/${userId}/currency`,
options: {
jar,
resolveWithFullResponse: true
}
})
.then(({ statusCode, body }) => {
const { robux, errors } = JSON.parse(body)
if (statusCode === 200) {
return robux
} else if (statusCode === 400 || statusCode === 403) {
throw new Error(`${errors[0].message} | userId: ${userId}`)
} else {
throw new Error(`An unknown error occurred with getUserFunds() | [${statusCode}] userId: ${userId}`)
}
})
}

exports.func = function ({ userId, jar }) {
return getUserFunds(userId, jar)
}
1 change: 1 addition & 0 deletions lib/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ noblox.getGroupRevenueSummary = require('./economy/getGroupRevenueSummary.js')
noblox.getGroupTransactions = require('./economy/getGroupTransactions.js')
noblox.getResaleData = require('./economy/getResaleData.js')
noblox.getResellers = require('./economy/getResellers.js')
noblox.getUserFunds = require('./economy/getUserFunds.js')
noblox.getUserTransactions = require('./economy/getUserTransactions.js')
noblox.onGroupTransaction = require('./economy/onGroupTransaction.js')
noblox.acceptFriendRequest = require('./friends/acceptFriendRequest.js')
Expand Down
42 changes: 28 additions & 14 deletions lib/util/getCurrentUser.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
// Includes
const http = require('./http.js').func
const settings = require('../../settings.json')

const noblox = require('../index.js')

// Args
exports.optional = ['option', 'jar']

// Docs
Expand All @@ -12,6 +13,7 @@ exports.optional = ['option', 'jar']
* @param {string=} option - A specific option to return.
* @returns {LoggedInUserData}
* @example const noblox = require("noblox.js")
* @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
* // Login using your cookie.
* const user = await noblox.getCurrentUser()
**/
Expand All @@ -20,23 +22,35 @@ exports.optional = ['option', 'jar']
exports.func = async function (args) {
const jar = args.jar
const option = args.option
const httpOpt = {
url: '//www.roblox.com/mobileapi/userinfo',
options: {
resolveWithFullResponse: true,
method: 'GET',
followRedirect: true,
jar
}
if (settings.show_deprecation_warnings) {
console.warn('[DEPRECATED]: getCurrentUser() is deprecated by Roblox; use getAuthenticatedUser(), getPremium(), getThumbnails(), or getUserFunds() instead!')
console.warn(' > Opt out of these warnings using noblox.setOptions({ show_deprecation_warnings: false })')
}
const res = await http(httpOpt)
if (res.statusCode !== 200) {
throw new Error('You are not logged in.')

const currentUser = await noblox.getAuthenticatedUser(jar)
const [premiumStatus, thumbnailResponse, robuxBalance] = await Promise.all(
[
noblox.getPremium(currentUser.id, jar),
noblox.getPlayerThumbnail(currentUser.id, '352x352', 'png', false, 'Body', jar),
noblox.getUserFunds(currentUser.id, jar)
]
)

const json = {
UserID: currentUser.id,
UserName: currentUser.name,
RobuxBalance: robuxBalance,
ThumbnailUrl: thumbnailResponse[0].imageUrl,
IsAnyBuildersClubMember: false,
IsPremium: premiumStatus,
DEPRECATION_WARNING: '[DEPRECATED]: noblox.getCurrentUser() is deprecated; use getAuthenticatedUser(), getPremium(), getThumbnails(), or getUserFunds() instead!'
}
const json = JSON.parse(res.body)

if (!option) {
return json
}

// Support queried rgequests `getCurrentUser('UserID') -> only UserID`
const searchKey = Object.keys(json).filter((key) => {
return option.toLowerCase() === key.toLowerCase()
})[0]
Expand Down
2 changes: 1 addition & 1 deletion lib/util/setOptions.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ const settings = require('../../settings.json')
* altering the settings.json file. Objects passed to this function should match the format of the settings.json file.
* Unknown keys, or malformed options will be rejected with an error.
* @category Utility
* @param {NobloxOptions} newOptions - The new options to set, structured as per [settings.json](https://github.com/noblox/noblox.js/blob/master/settings.json)
* @param {Partial<NobloxOptions>} newOptions - The new options to set, structured as per [settings.json](https://github.com/noblox/noblox.js/blob/master/settings.json)
* @returns void
* @see [settings.json](https://github.com/noblox/noblox.js/blob/master/settings.json) - default package settings
* @example const noblox = require("noblox.js")
Expand Down
3 changes: 3 additions & 0 deletions settings.json
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
{
"show_deprecation_warnings": true,
"show_deprecation_warnings_desc": "Prints console warnings for functions that are being polyfilled by newer methods due to upstream Roblox API changes",

"session_only": true,
"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.",

Expand Down
15 changes: 11 additions & 4 deletions typings/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ declare module "noblox.js" {
* NobloxOptions for setOptions, based from settings.json
*/
interface NobloxOptions {
/** Prints console warnings for functions that are being polyfilled by newer methods due to upstream Roblox API changes */
show_deprecation_warnings: boolean;

/** Minimizes data usage and speed up requests by only saving session cookies, disable if you need other cookies to be saved as well. (Default: true) */
session_only: boolean;

Expand Down Expand Up @@ -996,9 +999,8 @@ declare module "noblox.js" {
UserID: number,
UserName: string,
RobuxBalance: number,
TicketsBalance: number,
ThumbnailUrl: string,
IsAnyBuildersClubMember: boolean,
IsAnyBuildersClubMember: false,
IsPremium: boolean
}

Expand Down Expand Up @@ -1670,7 +1672,7 @@ declare module "noblox.js" {
* 🔐 Allows the user to login with a provided cookie string, bypassing the username/password captcha issues.
* By default, the provided cookie will be validated by making a HTTP request. To disable this behaviour, pass false as the second optional parameter (shouldValidate).
*/
function setCookie<B extends boolean = true>(cookie: string, shouldValidate?: B): B extends false ? boolean : Promise<LoggedInUserData>
function setCookie<B extends boolean = true>(cookie: string, shouldValidate?: B): B extends false ? boolean : Promise<AuthenticatedUserData>

/// DataStores

Expand Down Expand Up @@ -1770,6 +1772,11 @@ declare module "noblox.js" {
*/
function getUserTransactions(transactionType?: "Sale" | "Purchase" | "AffiliateSale" | "DevEx" | "GroupPayout" | "AdImpressionPayout", limit?: number, sortOrder?: SortOrder, jar?: CookieJar): Promise<TransactionItem[]>;

/**
* 🔐 Returns the current user's robux balance
*/
function getUserFunds(userId?: number, jar?: CookieJar): Promise<number>;

/// Friends

/**
Expand Down Expand Up @@ -2297,7 +2304,7 @@ declare module "noblox.js" {
* @param newOptions - The new options to set, structured as per settings.json
* @see https://github.com/noblox/noblox.js/blob/master/settings.json
*/
function setOptions(newOptions: NobloxOptions): void
function setOptions(newOptions: Partial<NobloxOptions>): void

// Events

Expand Down
6 changes: 4 additions & 2 deletions typings/jsDocs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ type CookieJar = {
* NobloxOptions for setOptions, based from settings.json
*/
type NobloxOptions = {
/** Prints console warnings for functions that are being polyfilled by newer methods due to upstream Roblox API changes */
show_deprecation_warnings: boolean;

/** Minimizes data usage and speed up requests by only saving session cookies, disable if you need other cookies to be saved as well. (Default: true) */
session_only: boolean;

Expand Down Expand Up @@ -1374,9 +1377,8 @@ type LoggedInUserData = {
UserID: number,
UserName: string,
RobuxBalance: number,
TicketsBalance: number,
ThumbnailUrl: string,
IsAnyBuildersClubMember: boolean,
IsAnyBuildersClubMember: false,
IsPremium: boolean
}

Expand Down

0 comments on commit 2be4343

Please sign in to comment.