bedrock-portal 0.2.6 → 0.3.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.
- package/README.md +85 -0
- package/examples/portal.js +12 -3
- package/package.json +1 -1
- package/src/classes/Module.js +4 -1
- package/src/classes/Player.js +3 -3
- package/src/common/constants.js +1 -1
- package/src/index.js +14 -6
- package/src/modules/autoFriendAdd.js +28 -11
- package/src/rest.js +7 -2
package/README.md
CHANGED
|
@@ -63,6 +63,7 @@ Automatically adds the account's followers as friends and invites them to the ga
|
|
|
63
63
|
|
|
64
64
|
Options:
|
|
65
65
|
- **inviteOnAdd**: boolean - Automatically invites recently added friends to the game (default: false)
|
|
66
|
+
- **conditionToMeet**: (player: RawPlayer) => boolean - A function that returns a boolean. If the function returns true, followers will be added as a friend and the friends that don't will be removed (default: () => true)
|
|
66
67
|
|
|
67
68
|
```js
|
|
68
69
|
const { BedrockPortal, Modules } = require('bedrock-portal');
|
|
@@ -75,6 +76,7 @@ portal.use(Modules.autoFriendAdd);
|
|
|
75
76
|
|
|
76
77
|
portal.use(Modules.autoFriendAdd, {
|
|
77
78
|
inviteOnAdd: true,
|
|
79
|
+
conditionToMeet: (player) => player.presenceState === 'Online', // Only add friends that are online and remove friends that are offline
|
|
78
80
|
});
|
|
79
81
|
```
|
|
80
82
|
|
|
@@ -143,6 +145,12 @@ Emitted when a player is added as a friend. This event is only emitted when the
|
|
|
143
145
|
**Parameters**
|
|
144
146
|
- player - [Player](#player) object
|
|
145
147
|
|
|
148
|
+
### portal.on('friendRemoved', (player) => {})
|
|
149
|
+
Emitted when a player is removed as a friend. This event is only emitted when the `autoFriendAdd` module is enabled.
|
|
150
|
+
|
|
151
|
+
**Parameters**
|
|
152
|
+
- player - [Player](#player) object
|
|
153
|
+
|
|
146
154
|
## Objects
|
|
147
155
|
|
|
148
156
|
### Player
|
|
@@ -258,6 +266,83 @@ Emitted when a player is added as a friend. This event is only emitted when the
|
|
|
258
266
|
}
|
|
259
267
|
```
|
|
260
268
|
|
|
269
|
+
### RawPlayer
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
{
|
|
273
|
+
xuid: string;
|
|
274
|
+
isFavorite: boolean;
|
|
275
|
+
isFollowingCaller: boolean;
|
|
276
|
+
isFollowedByCaller: boolean;
|
|
277
|
+
isIdentityShared: boolean;
|
|
278
|
+
addedDateTimeUtc: string;
|
|
279
|
+
displayName: string;
|
|
280
|
+
realName: string;
|
|
281
|
+
displayPicRaw: string;
|
|
282
|
+
showUserAsAvatar: string;
|
|
283
|
+
gamertag: string;
|
|
284
|
+
gamerScore: string;
|
|
285
|
+
modernGamertag: string;
|
|
286
|
+
modernGamertagSuffix: string;
|
|
287
|
+
uniqueModernGamertag: string;
|
|
288
|
+
xboxOneRep: string;
|
|
289
|
+
presenceState: string;
|
|
290
|
+
presenceText: string;
|
|
291
|
+
presenceDevices: null | any[];
|
|
292
|
+
isBroadcasting: boolean;
|
|
293
|
+
isCloaked: null | boolean;
|
|
294
|
+
isQuarantined: boolean;
|
|
295
|
+
isXbox360Gamerpic: boolean;
|
|
296
|
+
lastSeenDateTimeUtc: string;
|
|
297
|
+
suggestion: null;
|
|
298
|
+
recommendation: null;
|
|
299
|
+
search: null;
|
|
300
|
+
titleHistory: null;
|
|
301
|
+
multiplayerSummary: null;
|
|
302
|
+
recentPlayer: null;
|
|
303
|
+
follower: {
|
|
304
|
+
text: string;
|
|
305
|
+
followedDateTime: string;
|
|
306
|
+
};
|
|
307
|
+
preferredColor: {
|
|
308
|
+
primaryColor: string;
|
|
309
|
+
secondaryColor: string;
|
|
310
|
+
tertiaryColor: string;
|
|
311
|
+
};
|
|
312
|
+
presenceDetails: null;
|
|
313
|
+
titlePresence: null;
|
|
314
|
+
titleSummaries: null;
|
|
315
|
+
presenceTitleIds: null;
|
|
316
|
+
detail: {
|
|
317
|
+
accountTier: string;
|
|
318
|
+
bio: string;
|
|
319
|
+
isVerified: boolean;
|
|
320
|
+
location: string;
|
|
321
|
+
tenure: string;
|
|
322
|
+
watermarks: any[];
|
|
323
|
+
blocked: boolean;
|
|
324
|
+
mute: boolean;
|
|
325
|
+
followerCount: number;
|
|
326
|
+
followingCount: number;
|
|
327
|
+
hasGamePass: boolean;
|
|
328
|
+
};
|
|
329
|
+
communityManagerTitles: null;
|
|
330
|
+
socialManager: null;
|
|
331
|
+
broadcast: null;
|
|
332
|
+
avatar: null;
|
|
333
|
+
linkedAccounts: {
|
|
334
|
+
networkName: string;
|
|
335
|
+
displayName: string;
|
|
336
|
+
showOnProfile: boolean;
|
|
337
|
+
isFamilyFriendly: boolean;
|
|
338
|
+
deeplink: null;
|
|
339
|
+
}[];
|
|
340
|
+
colorTheme: string;
|
|
341
|
+
preferredFlag: string;
|
|
342
|
+
preferredPlatforms: string[];
|
|
343
|
+
}
|
|
344
|
+
```
|
|
345
|
+
|
|
261
346
|
|
|
262
347
|
## Debugging
|
|
263
348
|
|
package/examples/portal.js
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
/* eslint-disable no-multi-spaces */
|
|
2
|
+
// process.env.DEBUG = 'bedrock-portal*';
|
|
3
|
+
|
|
2
4
|
const { BedrockPortal, Modules, Joinability } = require('bedrock-portal');
|
|
3
5
|
const { Authflow, Titles } = require('prismarine-auth');
|
|
4
6
|
|
|
@@ -21,11 +23,10 @@ const main = async () => {
|
|
|
21
23
|
|
|
22
24
|
portal.use(Modules.autoFriendAdd, { // Automatically adds friends to the session
|
|
23
25
|
inviteOnAdd: true,
|
|
26
|
+
conditionToMeet: (player) => player.presenceState === 'Online', // Only add friends that are online and remove friends that are offline
|
|
24
27
|
});
|
|
25
28
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
await portal.invitePlayer('p3'); // gamertag or xuid to invite
|
|
29
|
+
// Put your event listeners before portal.start() to ensure you don't miss any events
|
|
29
30
|
|
|
30
31
|
portal.on('rtaEvent', (event) => { // Emits when an RTA event is received
|
|
31
32
|
console.log('RTA Event: ', event);
|
|
@@ -51,6 +52,14 @@ const main = async () => {
|
|
|
51
52
|
console.log('Friend Added: ', player);
|
|
52
53
|
});
|
|
53
54
|
|
|
55
|
+
portal.on('friendRemoved', (player) => { // Emits when a friend is removed. Only emitted if autoFriendAdd module is used
|
|
56
|
+
console.log('Friend Removed: ', player);
|
|
57
|
+
});
|
|
58
|
+
|
|
59
|
+
await portal.start(); // Starts the session
|
|
60
|
+
|
|
61
|
+
await portal.invitePlayer('p3'); // gamertag or xuid to invite
|
|
62
|
+
|
|
54
63
|
};
|
|
55
64
|
|
|
56
65
|
main();
|
package/package.json
CHANGED
package/src/classes/Module.js
CHANGED
package/src/classes/Player.js
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
class Player {
|
|
2
|
-
constructor(profileData
|
|
2
|
+
constructor(profileData, sessionData) {
|
|
3
3
|
this.profile = {};
|
|
4
4
|
this.session = {};
|
|
5
|
-
this.setXboxProfile(profileData);
|
|
6
|
-
this.setSessionMember(sessionData);
|
|
5
|
+
if (profileData) this.setXboxProfile(profileData);
|
|
6
|
+
if (sessionData) this.setSessionMember(sessionData);
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
static fromSessionMember(data) {
|
package/src/common/constants.js
CHANGED
package/src/index.js
CHANGED
|
@@ -94,7 +94,11 @@ module.exports = class BedrockPortal extends EventEmitter {
|
|
|
94
94
|
async invitePlayer(identifier) {
|
|
95
95
|
debug(`Inviting player, identifier: ${identifier}`);
|
|
96
96
|
|
|
97
|
-
const profile = await this.#rest.getXboxProfile(identifier)
|
|
97
|
+
const profile = await this.#rest.getXboxProfile(identifier)
|
|
98
|
+
.catch(() => { throw new Error(`Failed to get profile for identifier: ${identifier}`); });
|
|
99
|
+
|
|
100
|
+
debug(`Inviting player, Got profile, xuid: ${profile.xuid}`);
|
|
101
|
+
|
|
98
102
|
const invitePayload = {
|
|
99
103
|
invitedXuid: String(profile.xuid),
|
|
100
104
|
inviteAttributes: { titleId: SessionConfig.MinecraftTitleID },
|
|
@@ -220,11 +224,15 @@ module.exports = class BedrockPortal extends EventEmitter {
|
|
|
220
224
|
});
|
|
221
225
|
|
|
222
226
|
if (this.modules) {
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
.
|
|
226
|
-
|
|
227
|
-
|
|
227
|
+
Object.values(this.modules).forEach(async mod => {
|
|
228
|
+
try {
|
|
229
|
+
mod.run(this, { rest: this.#rest, rta: this.#rta });
|
|
230
|
+
debug(`Module ${mod.name} has run`);
|
|
231
|
+
}
|
|
232
|
+
catch (e) {
|
|
233
|
+
debug(`Module ${mod.name} failed to run`, e);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
228
236
|
}
|
|
229
237
|
|
|
230
238
|
}
|
|
@@ -7,6 +7,7 @@ class AutoFriendAdd extends Module {
|
|
|
7
7
|
super('autoFriendAdd', 'Automatically adds followers as friends');
|
|
8
8
|
this.options = {
|
|
9
9
|
inviteOnAdd: false,
|
|
10
|
+
conditionToMeet: () => true,
|
|
10
11
|
};
|
|
11
12
|
}
|
|
12
13
|
|
|
@@ -17,20 +18,12 @@ class AutoFriendAdd extends Module {
|
|
|
17
18
|
|
|
18
19
|
this.debug('Checking for followers to add');
|
|
19
20
|
|
|
20
|
-
const friends = await rest.getXboxFriends()
|
|
21
|
-
.then(people => people.map(e => e.xuid))
|
|
22
|
-
.catch(() => []);
|
|
23
|
-
|
|
24
21
|
const followers = await rest.getXboxFollowers()
|
|
25
22
|
.catch(() => []);
|
|
26
23
|
|
|
27
|
-
|
|
24
|
+
this.debug(`Found ${followers.length} follower(s)`);
|
|
28
25
|
|
|
29
|
-
|
|
30
|
-
this.debug('No followers to add');
|
|
31
|
-
await new Promise(resolve => setTimeout(resolve, 30000));
|
|
32
|
-
continue;
|
|
33
|
-
}
|
|
26
|
+
const needsAdding = followers.filter(res => !res.isFollowedByCaller && this.options.conditionToMeet(res));
|
|
34
27
|
|
|
35
28
|
this.debug(`Adding ${needsAdding.length} account(s) [${needsAdding.map(res => res.gamertag).join(', ')}]`);
|
|
36
29
|
|
|
@@ -49,8 +42,32 @@ class AutoFriendAdd extends Module {
|
|
|
49
42
|
|
|
50
43
|
this.debug(`Added & invited ${account.gamertag}`);
|
|
51
44
|
|
|
52
|
-
await new Promise(resolve => setTimeout(resolve,
|
|
45
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
this.debug('Checking for friends to remove');
|
|
49
|
+
|
|
50
|
+
const friends = await rest.getXboxFriends()
|
|
51
|
+
.catch(() => []);
|
|
52
|
+
|
|
53
|
+
this.debug(`Found ${friends.length} friend(s)`);
|
|
54
|
+
|
|
55
|
+
const needsRemoving = friends.filter(res => !res.isFollowingCaller || !this.options.conditionToMeet(res));
|
|
56
|
+
|
|
57
|
+
this.debug(`Removing ${needsRemoving.length} account(s) [${needsRemoving.map(res => res.gamertag).join(', ')}]`);
|
|
58
|
+
|
|
59
|
+
for (const account of needsRemoving) {
|
|
60
|
+
await rest.removeXboxFriend(account.xuid).catch(err => {
|
|
61
|
+
throw Error(`Failed to remove ${account.gamertag}`, { cause: err });
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
portal.emit('friendRemoved', Player.fromXboxProfile(account));
|
|
65
|
+
|
|
66
|
+
this.debug(`Removed ${account.gamertag}`);
|
|
67
|
+
|
|
68
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
53
69
|
}
|
|
70
|
+
|
|
54
71
|
}
|
|
55
72
|
catch (error) {
|
|
56
73
|
this.debug(`Error: ${error.message}`, error);
|
package/src/rest.js
CHANGED
|
@@ -114,19 +114,24 @@ module.exports = class Rest {
|
|
|
114
114
|
}
|
|
115
115
|
|
|
116
116
|
async getXboxFriends() {
|
|
117
|
-
return await this.get('https://peoplehub.xboxlive.com/users/me/people/social/decoration/
|
|
117
|
+
return await this.get('https://peoplehub.xboxlive.com/users/me/people/social/decoration/detail,preferredColor,follower', { contractVersion: 5 }).then(res => res.people.map(e => this.#parseXboxProfile(e)));
|
|
118
118
|
}
|
|
119
119
|
|
|
120
120
|
async getXboxFollowers() {
|
|
121
|
-
return await this.get('https://peoplehub.xboxlive.com/users/me/people/followers/decoration/
|
|
121
|
+
return await this.get('https://peoplehub.xboxlive.com/users/me/people/followers/decoration/detail,preferredColor,follower', { contractVersion: 5 }).then(res => res.people.map(e => this.#parseXboxProfile(e)));
|
|
122
122
|
}
|
|
123
123
|
|
|
124
124
|
async addXboxFriend(xuid) {
|
|
125
125
|
return await this.put(`https://social.xboxlive.com/users/me/people/xuid(${xuid})`, { contractVersion: 2 });
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
+
async removeXboxFriend(xuid) {
|
|
129
|
+
return await this.delete(`https://social.xboxlive.com/users/me/people/xuid(${xuid})`, { contractVersion: 2 });
|
|
130
|
+
}
|
|
131
|
+
|
|
128
132
|
#parseXboxProfile(profile) {
|
|
129
133
|
return {
|
|
134
|
+
...profile,
|
|
130
135
|
xuid: profile.xuid,
|
|
131
136
|
avatar: profile.displayPicRaw,
|
|
132
137
|
gamerscore: profile.gamerScore,
|