steamcommunity 3.45.3 → 3.46.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.
@@ -1,78 +1,84 @@
1
1
  // If you aren't running this script inside of the repository, replace the following line with:
2
2
  // const SteamCommunity = require('steamcommunity');
3
3
  const SteamCommunity = require('../index.js');
4
+ const SteamSession = require('steam-session');
4
5
  const ReadLine = require('readline');
5
6
  const FS = require('fs');
6
7
 
7
8
  const EResult = SteamCommunity.EResult;
8
9
 
10
+ let g_AbortPromptFunc = null;
11
+
9
12
  let community = new SteamCommunity();
10
- let rl = ReadLine.createInterface({
11
- input: process.stdin,
12
- output: process.stdout
13
- });
14
-
15
- rl.question('Username: ', (accountName) => {
16
- rl.question('Password: ', (password) => {
17
- doLogin(accountName, password);
18
- });
19
- });
20
-
21
- function doLogin(accountName, password, authCode, captcha) {
22
- community.login({
23
- accountName: accountName,
24
- password: password,
25
- authCode: authCode,
26
- captcha: captcha
27
- }, (err, sessionID, cookies, steamguard) => {
28
- if (err) {
29
- if (err.message == 'SteamGuardMobile') {
30
- console.log('This account already has two-factor authentication enabled.');
31
- process.exit();
32
- return;
33
- }
34
13
 
35
- if (err.message == 'SteamGuard') {
36
- console.log(`An email has been sent to your address at ${err.emaildomain}`);
37
- rl.question('Steam Guard Code: ', (code) => {
38
- doLogin(accountName, password, code);
39
- });
14
+ main();
15
+ async function main() {
16
+ let accountName = await promptAsync('Username: ');
17
+ let password = await promptAsync('Password (hidden): ', true);
40
18
 
41
- return;
42
- }
19
+ // Create a LoginSession for us to use to attempt to log into steam
20
+ let session = new SteamSession.LoginSession(SteamSession.EAuthTokenPlatformType.MobileApp);
43
21
 
44
- if (err.message == 'CAPTCHA') {
45
- console.log(err.captchaurl);
46
- rl.question('CAPTCHA: ', (captchaInput) => {
47
- doLogin(accountName, password, authCode, captchaInput);
48
- });
22
+ // Go ahead and attach our event handlers before we do anything else.
23
+ session.on('authenticated', async () => {
24
+ abortPrompt();
49
25
 
50
- return;
51
- }
26
+ let accessToken = session.accessToken;
27
+ let cookies = await session.getWebCookies();
52
28
 
53
- console.log(err);
54
- process.exit();
55
- return;
56
- }
29
+ community.setCookies(cookies);
30
+ community.setMobileAppAccessToken(accessToken);
57
31
 
58
- console.log('Logged on!');
32
+ // Enabling or disabling 2FA is presently the only action in node-steamcommunity which requires an access token.
33
+ // In all other cases, using `community.setCookies(cookies)` is all you need to do in order to be logged in,
34
+ // although there's never any harm in setting a mobile app access token.
59
35
 
60
- if (community.mobileAccessToken) {
61
- // If we already have a mobile access token, we don't need to prompt for one.
62
- doSetup();
63
- return;
64
- }
36
+ doSetup();
37
+ });
65
38
 
66
- console.log('You need to provide a mobile app access token to continue.');
67
- console.log('You can generate one using steam-session (https://www.npmjs.com/package/steam-session).');
68
- console.log('The access token needs to be generated using EAuthTokenPlatformType.MobileApp.');
69
- console.log('Make sure you provide an *ACCESS* token, not a refresh token.');
39
+ session.on('timeout', () => {
40
+ abortPrompt();
41
+ console.log('This login attempt has timed out.');
42
+ });
70
43
 
71
- rl.question('Access Token: ', (accessToken) => {
72
- community.setMobileAppAccessToken(accessToken);
73
- doSetup();
74
- });
44
+ session.on('error', (err) => {
45
+ abortPrompt();
46
+
47
+ // This should ordinarily not happen. This only happens in case there's some kind of unexpected error while
48
+ // polling, e.g. the network connection goes down or Steam chokes on something.
49
+
50
+ console.log(`ERROR: This login attempt has failed! ${err.message}`);
75
51
  });
52
+
53
+ // Start our login attempt
54
+ let startResult = await session.startWithCredentials({accountName, password});
55
+ if (startResult.actionRequired) {
56
+ // Some Steam Guard action is required. We only care about email and device codes; in theory an
57
+ // EmailConfirmation and/or DeviceConfirmation action could be possible, but we're just going to ignore those.
58
+ // If the user does receive a confirmation and accepts it, LoginSession will detect and handle that automatically.
59
+ // The only consequence of ignoring it here is that we don't print a message to the user indicating that they
60
+ // could accept an email or device confirmation.
61
+
62
+ let codeActionTypes = [SteamSession.EAuthSessionGuardType.EmailCode, SteamSession.EAuthSessionGuardType.DeviceCode];
63
+ let codeAction = startResult.validActions.find(action => codeActionTypes.includes(action.type));
64
+ if (codeAction) {
65
+ if (codeAction.type == SteamSession.EAuthSessionGuardType.EmailCode) {
66
+ console.log(`A code has been sent to your email address at ${codeAction.detail}.`);
67
+ } else {
68
+ // We wouldn't expect this to happen since we're trying to enable 2FA, but just in case...
69
+ console.log('You need to provide a Steam Guard Mobile Authenticator code.');
70
+ }
71
+
72
+ let code = await promptAsync('Code: ');
73
+ if (code) {
74
+ await session.submitSteamGuardCode(code);
75
+ }
76
+
77
+ // If we fall through here without submitting a Steam Guard code, that means one of two things:
78
+ // 1. The user pressed enter without providing a code, in which case the script will simply exit
79
+ // 2. The user approved a device/email confirmation, in which case 'authenticated' was emitted and the prompt was canceled
80
+ }
81
+ }
76
82
  }
77
83
 
78
84
  function doSetup() {
@@ -110,22 +116,67 @@ function doSetup() {
110
116
  });
111
117
  }
112
118
 
113
- function promptActivationCode(response) {
114
- rl.question('SMS Code: ', (smsCode) => {
115
- community.finalizeTwoFactor(response.shared_secret, smsCode, (err) => {
116
- if (err) {
117
- if (err.message == 'Invalid activation code') {
118
- console.log(err);
119
- promptActivationCode(response);
120
- return;
121
- }
119
+ async function promptActivationCode(response) {
120
+ if (response.phone_number_hint) {
121
+ console.log(`A code has been sent to your phone ending in ${response.phone_number_hint}.`);
122
+ }
122
123
 
124
+ let smsCode = await promptAsync('SMS Code: ');
125
+ community.finalizeTwoFactor(response.shared_secret, smsCode, (err) => {
126
+ if (err) {
127
+ if (err.message == 'Invalid activation code') {
123
128
  console.log(err);
124
- } else {
125
- console.log('Two-factor authentication enabled!');
129
+ promptActivationCode(response);
130
+ return;
126
131
  }
127
132
 
128
- process.exit();
133
+ console.log(err);
134
+ } else {
135
+ console.log('Two-factor authentication enabled!');
136
+ }
137
+
138
+ process.exit();
139
+ });
140
+ }
141
+
142
+ // Nothing interesting below here, just code for prompting for input from the console.
143
+
144
+ function promptAsync(question, sensitiveInput = false) {
145
+ return new Promise((resolve) => {
146
+ let rl = ReadLine.createInterface({
147
+ input: process.stdin,
148
+ output: sensitiveInput ? null : process.stdout,
149
+ terminal: true
150
+ });
151
+
152
+ g_AbortPromptFunc = () => {
153
+ rl.close();
154
+ resolve('');
155
+ };
156
+
157
+ if (sensitiveInput) {
158
+ // We have to write the question manually if we didn't give readline an output stream
159
+ process.stdout.write(question);
160
+ }
161
+
162
+ rl.question(question, (result) => {
163
+ if (sensitiveInput) {
164
+ // We have to manually print a newline
165
+ process.stdout.write('\n');
166
+ }
167
+
168
+ g_AbortPromptFunc = null;
169
+ rl.close();
170
+ resolve(result);
129
171
  });
130
172
  });
131
173
  }
174
+
175
+ function abortPrompt() {
176
+ if (!g_AbortPromptFunc) {
177
+ return;
178
+ }
179
+
180
+ g_AbortPromptFunc();
181
+ process.stdout.write('\n');
182
+ }