steamutils 1.5.40 → 1.5.42

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/_steamproto.js CHANGED
@@ -12,8 +12,13 @@ export class SteamProto {
12
12
  }
13
13
 
14
14
  toProto() {
15
- const filePath = path.join(`${__dirname}/protos/`, this._proto.filename);
16
- const root = new Protobuf.Root().loadSync([gpf.getProtoPath("google/protobuf/descriptor.proto"), filePath], {
15
+ const localProto = path.join(`${__dirname}/protos/`, this._proto.filename);
16
+ console.log(`localProto: ${localProto}`);
17
+
18
+ const descriptorPath = gpf.getProtoPath("protobuf/descriptor.proto");
19
+ console.log(`descriptorPath: ${descriptorPath}`);
20
+
21
+ const root = new Protobuf.Root().loadSync([descriptorPath, localProto], {
17
22
  keepCase: true,
18
23
  });
19
24
  return root.lookupType(this._proto.name);
@@ -12,8 +12,13 @@ export class SteamProto {
12
12
  }
13
13
 
14
14
  toProto() {
15
- const filePath = path.join(`${__dirname}/protos/`, this._proto.filename);
16
- const root = new Protobuf.Root().loadSync([gpf.getProtoPath("google/protobuf/descriptor.proto"), filePath], {
15
+ const localProto = path.join(`${__dirname}/protos/`, this._proto.filename);
16
+ console.log(`localProto: ${localProto}`);
17
+
18
+ const descriptorPath = gpf.getProtoPath("protobuf/descriptor.proto");
19
+ console.log(`descriptorPath: ${descriptorPath}`);
20
+
21
+ const root = new Protobuf.Root().loadSync([descriptorPath, localProto], {
17
22
  keepCase: true,
18
23
  });
19
24
  return root.lookupType(this._proto.name);
package/index.js CHANGED
@@ -5,7 +5,7 @@ import moment from "moment";
5
5
  import { hex2b64, Key as RSA } from "node-bignumber";
6
6
  import SteamID from "steamid";
7
7
  import qs from "qs";
8
- import { console_log, convertLongsToNumbers, downloadImage, formatMarketHistoryDate, getCleanObject, getImageSize, JSON_parse, JSON_stringify, removeSpaceKeys, secretAsBuffer, sleep } from "./utils.js";
8
+ import { console_log, convertLongsToNumbers, downloadImage, formatMarketHistoryDate, getCleanObject, getImageSize, isJWT, JSON_parse, JSON_stringify, removeSpaceKeys, secretAsBuffer, sleep } from "./utils.js";
9
9
  import { Header, request } from "./axios.js";
10
10
  import { getTableHasHeaders, querySelectorAll, table2json } from "./cheerio.js";
11
11
  import { getJSObjectFronXML } from "./xml2json.js";
@@ -807,9 +807,25 @@ export default class SteamUser {
807
807
  };
808
808
  }
809
809
 
810
- static async getAppVersion(appID) {
810
+ /**
811
+ * Fetches up-to-date status and version information for a Steam app by appID.
812
+ *
813
+ * @param {number|string} appID - The Steam app ID to query.
814
+ * @returns {Promise<{
815
+ * response: {
816
+ * success: boolean,
817
+ * up_to_date: boolean,
818
+ * version_is_listable: boolean,
819
+ * required_version: number,
820
+ * message: string
821
+ * }
822
+ * }|undefined>} The API response object, or undefined if an error occurs.
823
+ *
824
+ */
825
+ static async getSteamAppVersionInfo(appID) {
811
826
  try {
812
- return (await request(`https://api.steampowered.com/ISteamApps/UpToDateCheck/v1/?format=json&appid=${appID}&version=0`)).data.response.required_version;
827
+ const response = await fetch(`https://api.steampowered.com/ISteamApps/UpToDateCheck/v1/?format=json&appid=${appID}&version=0`);
828
+ return await response.json();
813
829
  } catch (e) {}
814
830
  }
815
831
 
@@ -4496,20 +4512,48 @@ export default class SteamUser {
4496
4512
  return await SteamUser.resolveUsers(steamIDs, this.getCookies());
4497
4513
  }
4498
4514
 
4499
- static async resolveUsers(steamIDs = [], cookie) {
4515
+ /**
4516
+ * @typedef {Object} SteamUserProfile
4517
+ * @property {string} steamId - The user's 64-bit SteamID.
4518
+ * @property {number} accountId - The user's numeric account ID.
4519
+ * @property {string} name - The Steam persona name.
4520
+ * @property {string} realName - The user's real name (may be empty).
4521
+ * @property {string} avatarHash - The user's avatar hash or identifier.
4522
+ * @property {string} customURL - The user's custom profile URL (may be empty).
4523
+ * @property {number} personaState - The user's online status/state.
4524
+ * @property {string} city - The user's city (may be empty).
4525
+ * @property {string} state - The user's state/region (may be empty).
4526
+ * @property {string} country - The user's country code (may be empty).
4527
+ * @property {boolean} isFriend - Whether the user is a friend.
4528
+ * @property {number} friendsInCommon - Number of mutual friends.
4529
+ */
4530
+
4531
+ /**
4532
+ * Resolves an array of Steam user IDs to their profile information using the Steam Community API.
4533
+ *
4534
+ * @param {(string|number)[]} steamIds - Array of Steam IDs (each a string or number).
4535
+ * @param {string} [cookie] - Optional session cookie for Steam authentication.
4536
+ * @returns {Promise<SteamUserProfile[]>} Promise resolving to an array of Steam user profile objects.
4537
+ *
4538
+ * @example
4539
+ * const users = await SteamUser.resolveUsers(['76561199409201417']);
4540
+ */
4541
+ static async resolveUsers(steamIds, cookie) {
4500
4542
  //steamIDs max = 200
4501
- if (typeof steamIDs === "string") {
4502
- steamIDs = [steamIDs];
4543
+
4544
+ if (!Array.isArray(steamIds) || !steamIds.every((id) => typeof id === "string" || typeof id === "number")) {
4545
+ console.error("steamIds must be an array of string or number.");
4546
+ return [];
4503
4547
  }
4504
4548
 
4505
- steamIDs = _.uniq(steamIDs);
4549
+ steamIds = _.uniq(steamIds);
4506
4550
 
4507
- if (steamIDs.length > 200) {
4508
- return _.flatten(await Promise.all(_.chunk(steamIDs, 200).map((_steamIDs) => SteamUser.resolveUsers(_steamIDs, cookie))));
4551
+ if (steamIds.length > 200) {
4552
+ return _.flatten(await Promise.all(_.chunk(steamIds, 200).map((_steamIds) => SteamUser.resolveUsers(_steamIds, cookie))));
4509
4553
  }
4510
4554
 
4511
4555
  const { data } = await request({
4512
- url: `https://steamcommunity.com/actions/ajaxresolveusers?steamids=${steamIDs.join(",")}`,
4556
+ url: `https://steamcommunity.com/actions/ajaxresolveusers?steamids=${steamIds.join(",")}`,
4513
4557
  headers: { ...(cookie && { cookie }) },
4514
4558
  });
4515
4559
 
@@ -4520,21 +4564,43 @@ export default class SteamUser {
4520
4564
  return data.map(function (player) {
4521
4565
  return {
4522
4566
  steamId: player.steamid,
4523
- accountid: player.accountid,
4567
+ accountId: player.accountid,
4524
4568
  name: player.persona_name,
4525
- realname: player.real_name,
4569
+ realName: player.real_name,
4526
4570
  avatarHash: player.avatar_url,
4527
4571
  customURL: player.profile_url,
4528
- persona_state: player.persona_state,
4572
+ personaState: player.persona_state,
4529
4573
  city: player.city,
4530
4574
  state: player.state,
4531
4575
  country: player.country,
4532
- is_friend: player.is_friend,
4533
- friends_in_common: player.friends_in_common,
4576
+ isFriend: player.is_friend,
4577
+ friendsInCommon: player.friends_in_common,
4534
4578
  };
4535
4579
  });
4536
4580
  }
4537
4581
 
4582
+ /**
4583
+ * Resolves a single Steam user ID to its profile information using the Steam Community API.
4584
+ *
4585
+ * @param {string|number} steamId - The Steam ID to resolve.
4586
+ * @param {string} [cookie] - Optional session cookie for Steam authentication.
4587
+ * @returns {Promise<SteamUserProfile|undefined>} Resolves to a user profile object, or undefined if not found or if input is invalid.
4588
+ *
4589
+ * @example
4590
+ * const user = await SteamUser.resolveUser('76561199409201417');
4591
+ * if (user) {
4592
+ * console.log(user.name);
4593
+ * }
4594
+ */
4595
+ static async resolveUser(steamId, cookie) {
4596
+ if (typeof steamId !== "string" && typeof steamId !== "number") {
4597
+ console.error("resolveUser: steamId must be a string or number. Received:", steamId);
4598
+ return;
4599
+ }
4600
+ const users = await this.resolveUsers([steamId], cookie);
4601
+ return users[0];
4602
+ }
4603
+
4538
4604
  static GetAvatarURLFromHash(hash, size) {
4539
4605
  if (!hash) {
4540
4606
  return;
@@ -4658,10 +4724,25 @@ export default class SteamUser {
4658
4724
  return list;
4659
4725
  }
4660
4726
 
4727
+ /**
4728
+ * Retrieves the current Steam Guard status for the account.
4729
+ *
4730
+ * Makes an HTTP request to the Steam two-factor management page,
4731
+ * parses the response, and determines the type of Steam Guard authentication enabled:
4732
+ * - "steam_authenticator" (mobile authenticator is enabled)
4733
+ * - "email_authenticator" (email confirmation is enabled)
4734
+ * - "none_authenticator" (no two-factor is enabled)
4735
+ *
4736
+ * If the request fails (ResponseError), returns null.
4737
+ *
4738
+ * @async
4739
+ * @returns {Promise<"steam_authenticator"|"email_authenticator"|"none_authenticator"|null>}
4740
+ * A string representing the authenticator type, or null if the request fails.
4741
+ */
4661
4742
  async getSteamGuardStatus() {
4662
4743
  const result = await this._httpRequest(`https://store.steampowered.com/twofactor/manage_action`);
4663
4744
  if (result instanceof ResponseError) {
4664
- return result;
4745
+ return nuill;
4665
4746
  }
4666
4747
  const $ = cheerio.load(result?.data || "");
4667
4748
 
@@ -4678,7 +4759,20 @@ export default class SteamUser {
4678
4759
  }
4679
4760
  }
4680
4761
 
4681
- async turningSteamGuardOff() {
4762
+ /**
4763
+ * Attempts to initiate the process of turning Steam Guard off for the account.
4764
+ *
4765
+ * Sends a POST request to Steam's two-factor management endpoint to request the
4766
+ * removal of Steam Guard. It then checks the response to verify whether the request
4767
+ * to turn Steam Guard off was successfully triggered (an email confirmation is sent).
4768
+ *
4769
+ * @async
4770
+ * @returns {Promise<boolean>}
4771
+ * Returns `true` if turning Steam Guard off requires email confirmation and the
4772
+ * corresponding message is found in the response;
4773
+ * returns `false` if an error occurs (e.g., a ResponseError is returned).
4774
+ */
4775
+ async requestSteamGuardDeactivation() {
4682
4776
  const result = await this._httpRequest({
4683
4777
  url: `https://store.steampowered.com/twofactor/manage_action`,
4684
4778
  headers: {
@@ -4692,13 +4786,25 @@ export default class SteamUser {
4692
4786
  method: "POST",
4693
4787
  });
4694
4788
  if (result instanceof ResponseError) {
4695
- return result;
4789
+ return false;
4696
4790
  }
4697
4791
  const $ = cheerio.load(result?.data || "");
4698
4792
  return $("title").text() === `Steam Guard Mobile Authenticator` && !!result?.data?.includes?.(`Turning Steam Guard off requires confirmation. We've sent you an email with a link to confirm disabling Steam Guard.`);
4699
4793
  }
4700
4794
 
4701
- async turningEmailAuthenticatorCheckOn() {
4795
+ /**
4796
+ * Activates the email-based Steam Guard authenticator for the account.
4797
+ *
4798
+ * Sends a POST request to Steam's two-factor management endpoint to enable email-based authentication.
4799
+ * Returns `true` if the response confirms that the email authenticator is enabled,
4800
+ * or `false` if the request fails or the response does not indicate successful activation.
4801
+ *
4802
+ * @async
4803
+ * @returns {Promise<boolean>}
4804
+ * Returns `true` if the email authenticator is activated successfully,
4805
+ * or `false` otherwise.
4806
+ */
4807
+ async activateEmailSteamGuard() {
4702
4808
  const result = await this._httpRequest({
4703
4809
  url: `https://store.steampowered.com/twofactor/manage_action`,
4704
4810
  headers: {
@@ -4713,19 +4819,31 @@ export default class SteamUser {
4713
4819
  method: "POST",
4714
4820
  });
4715
4821
  if (result instanceof ResponseError) {
4716
- return result;
4822
+ return false;
4717
4823
  }
4718
4824
  const $ = cheerio.load(result?.data || "");
4719
4825
  return $("title").text() === `Steam Guard Mobile Authenticator` && $("#email_authenticator_check")?.attr("checked") == "checked";
4720
4826
  }
4721
4827
 
4722
- async getPhoneManage() {
4723
- //Ends in 17
4828
+ /**
4829
+ * Retrieves the current phone number status associated with the Steam account.
4830
+ *
4831
+ * Performs an HTTP request to the Steam phone management page and parses the response to
4832
+ * determine if a phone number is bound to the account.
4833
+ * - Returns `'none'` if no phone number is linked.
4834
+ * - Returns a string describing the phone (e.g., 'Ends in 17') if one is bound.
4835
+ * - Returns `null` on request failure or unexpected page content.
4836
+ *
4837
+ * @async
4838
+ * @returns {Promise<string|null>}
4839
+ * The phone number status: `'none'`, a phone description string (like 'Ends in 17'), or `null` if the request fails.
4840
+ */
4841
+ async getPhoneNumberStatus() {
4724
4842
  const result = await this._httpRequest({
4725
4843
  url: `https://store.steampowered.com/phone/manage`,
4726
4844
  });
4727
4845
  if (result instanceof ResponseError) {
4728
- return result;
4846
+ return null;
4729
4847
  }
4730
4848
  const $ = cheerio.load(result?.data || "");
4731
4849
  const pageheader = $("h2.pageheader").text();
@@ -4733,7 +4851,7 @@ export default class SteamUser {
4733
4851
  case "Add a phone number to your account":
4734
4852
  return "none";
4735
4853
  case "Manage phone number":
4736
- return $(".phone_header_description > span").text(); //Ends in 17}
4854
+ return $(".phone_header_description > span").text(); //Example: Ends in 17
4737
4855
  }
4738
4856
  }
4739
4857
 
@@ -6769,34 +6887,102 @@ export default class SteamUser {
6769
6887
  return { error };
6770
6888
  }
6771
6889
 
6772
- async enableTwoFactor(accessToken) {
6773
- if (!accessToken || typeof accessToken !== "string") {
6774
- return { error: "Invalid accessToken: " + accessToken };
6890
+ /**
6891
+ * @typedef {Object} SteamAuthenticatorResponse
6892
+ * @property {string} shared_secret
6893
+ * @property {string} serial_number
6894
+ * @property {string} revocation_code
6895
+ * @property {string} uri
6896
+ * @property {string} server_time
6897
+ * @property {string} account_name
6898
+ * @property {string} token_gid
6899
+ * @property {string} identity_secret
6900
+ * @property {string} secret_1
6901
+ * @property {number} status
6902
+ * @property {number} confirm_type
6903
+ */
6904
+
6905
+ /**
6906
+ * @typedef {Object} AddSteamAuthenticatorResult
6907
+ * @property {boolean} success - Whether enabling 2FA was successful.
6908
+ * @property {SteamAuthenticatorResponse} [response] - The response object if successful.
6909
+ * @property {string} [error] - Error message if unsuccessful.
6910
+ */
6911
+
6912
+ /**
6913
+ * Adds a Steam mobile authenticator to the account.
6914
+ *
6915
+ * @async
6916
+ * @param {string} accessToken - Steam access token (must be a valid JWT).
6917
+ * @returns {Promise<AddSteamAuthenticatorResult>}
6918
+ */
6919
+ async addSteamAuthenticator(accessToken) {
6920
+ if (!isJWT(accessToken)) {
6921
+ return {
6922
+ success: false,
6923
+ error: `Invalid accessToken (must be JWT): ${accessToken}`,
6924
+ };
6775
6925
  }
6776
6926
 
6777
- const SteamCommunity = (await import("steamcommunity")).default;
6778
- let error = null;
6927
+ const steamId = this.getSteamIdUser();
6928
+ const formData = new URLSearchParams({
6929
+ steamid: steamId,
6930
+ authenticator_type: 1,
6931
+ device_identifier: SteamTotp.getDeviceID(steamId),
6932
+ sms_phone_id: "1",
6933
+ version: 2,
6934
+ }).toString();
6935
+
6936
+ const url = `https://api.steampowered.com/ITwoFactorService/AddAuthenticator/v1/?access_token=${encodeURIComponent(accessToken)}`;
6937
+ const headersBase = {
6938
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36",
6939
+ Origin: "https://api.steampowered.com",
6940
+ "Content-Type": "application/x-www-form-urlencoded",
6941
+ };
6942
+
6943
+ let lastError = null;
6944
+
6779
6945
  for (const cookie of this._cookies) {
6780
6946
  try {
6781
- const community = new SteamCommunity();
6782
- community.setCookies(cookie.toString().split(";"));
6783
- community.oAuthToken = accessToken;
6784
- try {
6785
- community.setMobileAppAccessToken(accessToken);
6786
- } catch (e) {}
6787
- const response = await new Promise((resolve) => {
6788
- community.enableTwoFactor((error, response) => {
6789
- resolve({ error, response });
6790
- });
6947
+ const response = await axios.request({
6948
+ method: "POST",
6949
+ url,
6950
+ headers: {
6951
+ ...headersBase,
6952
+ Cookie: cookie,
6953
+ },
6954
+ data: formData,
6791
6955
  });
6792
- if (!response.error) {
6793
- return { ...response, success: true };
6956
+ if (response.data && response.data.response) {
6957
+ return {
6958
+ success: true,
6959
+ response: response.data.response,
6960
+ };
6794
6961
  } else {
6795
- error = response.error;
6962
+ return {
6963
+ success: false,
6964
+ error: `Unexpected API response: ${JSON.stringify(response.data)}`,
6965
+ };
6796
6966
  }
6797
- } catch (e) {}
6967
+ } catch (error) {
6968
+ // Prepare a clear error message
6969
+ let apiError = "Unknown error";
6970
+ if (error.code === "ECONNABORTED") {
6971
+ apiError = "Request timed out";
6972
+ } else if (error.response && error.response.data) {
6973
+ apiError = typeof error.response.data === "object" ? JSON.stringify(error.response.data) : String(error.response.data);
6974
+ } else if (error.message) {
6975
+ apiError = error.message;
6976
+ }
6977
+ lastError = apiError;
6978
+ }
6798
6979
  }
6799
- return { error };
6980
+
6981
+ // All attempts failed.
6982
+ return {
6983
+ success: false,
6984
+ error: lastError || "Failed to add Steam authenticator: No cookies provided or all attempts failed.",
6985
+ };
6800
6986
  }
6801
6987
 
6802
6988
  async finalizeTwoFactor(accessToken, identitySecret, finalizeTwoFactorCode) {
@@ -7558,6 +7744,7 @@ export default class SteamUser {
7558
7744
  });
7559
7745
  return revokeRefreshTokenResult?.data;
7560
7746
  }
7747
+
7561
7748
  async revokeAccessToken(accessToken, tokenId, sharedSecret) {
7562
7749
  if (!accessToken || typeof accessToken !== "string") {
7563
7750
  console.error("revokeAccessToken", "invalid accessToken", accessToken);
@@ -7989,7 +8176,7 @@ export default class SteamUser {
7989
8176
  /**
7990
8177
  * Fetches Steam batched loyalty reward items for given app ID(s).
7991
8178
  * @param {number|number[]} appIds - A Steam App ID or array of App IDs.
7992
- * @returns {Promise<Array<{eresult: number, response: BatchedLoyaltyRewardItemsResponse}>>}
8179
+ * @returns {Promise<Array<{eresult: number, response: BatchedLoyaltyRewardItemsResponse}>|null|undefined>}
7993
8180
  */
7994
8181
  static async fetchBatchedLoyaltyRewardItems(appIds) {
7995
8182
  if (!appIds) {
@@ -8035,7 +8222,7 @@ export default class SteamUser {
8035
8222
  responseType: "arraybuffer",
8036
8223
  });
8037
8224
  if (result instanceof ResponseError) {
8038
- return result;
8225
+ return;
8039
8226
  }
8040
8227
 
8041
8228
  try {
@@ -8181,71 +8368,132 @@ export default class SteamUser {
8181
8368
  return apps.filter((app) => app.event_app);
8182
8369
  }
8183
8370
 
8184
- static async decodeQRImage(imageURL) {
8185
- let response = null;
8371
+ /**
8372
+ * Downloads an image from the given URL, decodes its QR code and returns the result.
8373
+ *
8374
+ * @param {string} imageURL - The URL of the image containing the QR code.
8375
+ * @returns {Promise<{ success: boolean, message: string, decodedQR: string | null }>}
8376
+ */
8377
+ static async extractQRCodeFromImageURL(imageURL) {
8378
+ // Validate URL format first
8186
8379
  try {
8187
- response = await axios.get(imageURL, {
8188
- responseType: "arraybuffer",
8189
- });
8190
- } catch (e) {}
8191
- const imageBuffer = response?.data;
8192
- if (!imageBuffer) {
8193
- return;
8380
+ new URL(imageURL);
8381
+ } catch (e) {
8382
+ return {
8383
+ success: false,
8384
+ message: "The provided imageURL is not a valid URL.",
8385
+ decodedQR: null,
8386
+ };
8194
8387
  }
8195
- try {
8196
- const { Jimp } = await import("jimp");
8197
8388
 
8198
- // Load the image with Jimp
8199
- const image = await Jimp.read(imageBuffer);
8389
+ let jimp, jsQR, imageBuffer;
8390
+ try {
8391
+ // Parallelize imports and fetch
8392
+ const [{ Jimp }, { default: jsQRmod }, response] = await Promise.all([import("jimp"), import("jsqr"), fetch(imageURL)]);
8393
+ jimp = Jimp;
8394
+ jsQR = jsQRmod;
8200
8395
 
8201
- // Get the image data
8202
- const imageData = {
8203
- data: new Uint8ClampedArray(image.bitmap.data),
8204
- width: image.bitmap.width,
8205
- height: image.bitmap.height,
8396
+ if (!response.ok) {
8397
+ return {
8398
+ success: false,
8399
+ message: `Failed to fetch image: HTTP ${response.status} ${response.statusText}`,
8400
+ decodedQR: null,
8401
+ };
8402
+ }
8403
+ imageBuffer = await response.arrayBuffer();
8404
+ if (!imageBuffer) {
8405
+ return {
8406
+ success: false,
8407
+ message: "Empty image data.",
8408
+ decodedQR: null,
8409
+ };
8410
+ }
8411
+ } catch (e) {
8412
+ return {
8413
+ success: false,
8414
+ message: `Initialization or fetch failure: ${e.message || e}`,
8415
+ decodedQR: null,
8206
8416
  };
8417
+ }
8207
8418
 
8208
- // Use jsQR to decode the QR code
8209
- const jsQR = (await import("jsqr")).default;
8210
- const decodedQR = jsQR(imageData.data, imageData.width, imageData.height);
8419
+ try {
8420
+ // Jimp accepts Buffer in Node.js, use Buffer.from(arrayBuffer)
8421
+ const image = await jimp.read(Buffer.from(imageBuffer));
8422
+ const { data, width, height } = image.bitmap;
8423
+ const clampedData = data instanceof Uint8ClampedArray ? data : new Uint8ClampedArray(data);
8424
+ const decodedQR = jsQR(clampedData, width, height);
8211
8425
 
8212
8426
  if (!decodedQR) {
8213
- return "QR code not found in the image.";
8427
+ return {
8428
+ success: false,
8429
+ message: "QR code not found in the image.",
8430
+ decodedQR: null,
8431
+ };
8214
8432
  }
8215
-
8216
- return decodedQR.data;
8433
+ return {
8434
+ success: true,
8435
+ message: "QR code successfully decoded.",
8436
+ decodedQR: decodedQR.data,
8437
+ };
8217
8438
  } catch (error) {
8218
- console.error("Error decoding QR code:", error);
8439
+ return {
8440
+ success: false,
8441
+ message: `Error decoding QR code: ${error.message || error}`,
8442
+ decodedQR: null,
8443
+ };
8219
8444
  }
8220
8445
  }
8221
8446
 
8222
- static async approveLoginRequest(steamId, url, sharedSecret, accessToken) {
8447
+ /**
8448
+ * Approves a Steam login request.
8449
+ * @param {string} steamId - Steam user ID.
8450
+ * @param {string} qrChallengeUrl - QR challenge URL.
8451
+ * @param {string} sharedSecret - Shared secret for TOTP.
8452
+ * @param {string} accessToken - API access token.
8453
+ * @returns {Promise<{steamId: string, error: string|null, success: boolean}>}
8454
+ */
8455
+ static async approveLoginRequest(steamId, qrChallengeUrl, sharedSecret, accessToken) {
8223
8456
  try {
8224
8457
  const { LoginApprover } = await import("steam-session");
8225
- const approver = new LoginApprover(accessToken, sharedSecret, {});
8226
- await approver.approveAuthSession({
8227
- qrChallengeUrl: url,
8228
- approve: true,
8229
- });
8230
-
8231
- return {
8232
- steamId,
8233
- error: null,
8234
- };
8458
+ const approver = new LoginApprover(accessToken, sharedSecret);
8459
+ await approver.approveAuthSession({ qrChallengeUrl, approve: true });
8460
+ return { steamId, error: null, success: true };
8235
8461
  } catch (error) {
8236
- console.error(`[${steamId}] approveLoginRequest Error`, error);
8237
- return {
8238
- steamId,
8239
- error: error || "Error",
8240
- };
8462
+ return { steamId, error: error?.message || "Unknown error", success: false };
8241
8463
  }
8242
8464
  }
8243
8465
 
8244
- static async getAuthSessionInfo(steamId, url, sharedSecret, accessToken) {
8466
+ /**
8467
+ * @typedef {Object} SessionInfo
8468
+ * @property {string} ip - The IP address of the session.
8469
+ * @property {Object} location - Geolocation details.
8470
+ * @property {string} location.geoloc - Latitude and longitude as a string.
8471
+ * @property {string} location.city - City of the session.
8472
+ * @property {string} location.state - State or region of the session.
8473
+ * @property {number} platformType - Numeric platform type indicator.
8474
+ * @property {string} deviceFriendlyName - Friendly name of the device.
8475
+ * @property {number} version - Version of the protocol/session.
8476
+ * @property {number} loginHistory - Login history flag or value.
8477
+ * @property {boolean} locationMismatch - Whether the location mismatches profile.
8478
+ * @property {boolean} highUsageLogin - Whether this is a high-usage login.
8479
+ * @property {number} requestedPersistence - Type/level of session persistence requested.
8480
+ * @property {string} steamId - Steam ID associated with the session.
8481
+ */
8482
+
8483
+ /**
8484
+ * Retrieves Steam authentication session information.
8485
+ *
8486
+ * @param {string} steamId - The Steam user ID.
8487
+ * @param {string} qrChallengeUrl - The QR challenge URL.
8488
+ * @param {string} sharedSecret - The shared secret for authentication.
8489
+ * @param {string} accessToken - The access token.
8490
+ * @returns {Promise<{steamId: string, sessionInfo?: SessionInfo, error?: string}>} Result containing the original Steam ID, session info if successful, or error message if failed.
8491
+ */
8492
+ static async getAuthSessionInfo(steamId, qrChallengeUrl, sharedSecret, accessToken) {
8245
8493
  try {
8246
8494
  const { LoginApprover } = await import("steam-session");
8247
8495
  const approver = new LoginApprover(accessToken, sharedSecret, {});
8248
- const sessionInfo = await approver.getAuthSessionInfo(url);
8496
+ const sessionInfo = await approver.getAuthSessionInfo(qrChallengeUrl);
8249
8497
  sessionInfo.steamId = steamId;
8250
8498
 
8251
8499
  return {
@@ -8253,10 +8501,9 @@ export default class SteamUser {
8253
8501
  sessionInfo,
8254
8502
  };
8255
8503
  } catch (error) {
8256
- console.error(`[${steamId}] getAuthSessionInfo Error`, error);
8257
8504
  return {
8258
8505
  steamId,
8259
- error,
8506
+ error: error?.message || "Unknown error",
8260
8507
  };
8261
8508
  }
8262
8509
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "steamutils",
3
- "version": "1.5.40",
3
+ "version": "1.5.42",
4
4
  "main": "index.js",
5
5
  "dependencies": {
6
6
  "alpha-common-utils": "^1.0.6",
package/steamproto.js CHANGED
@@ -12,8 +12,13 @@ export class SteamProto {
12
12
  }
13
13
 
14
14
  toProto() {
15
- const filePath = path.join(`${__dirname}/protos/`, this._proto.filename);
16
- const root = new Protobuf.Root().loadSync([gpf.getProtoPath("google/protobuf/descriptor.proto"), filePath], {
15
+ const localProto = path.join(`${__dirname}/protos/`, this._proto.filename);
16
+ console.log(`localProto: ${localProto}`);
17
+
18
+ const descriptorPath = gpf.getProtoPath("protobuf/descriptor.proto");
19
+ console.log(`descriptorPath: ${descriptorPath}`);
20
+
21
+ const root = new Protobuf.Root().loadSync([descriptorPath, localProto], {
17
22
  keepCase: true,
18
23
  });
19
24
  return root.lookupType(this._proto.name);