bedrock-portal 0.3.1 → 0.5.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 CHANGED
@@ -2,7 +2,7 @@
2
2
  [![NPM version](https://img.shields.io/npm/v/bedrock-portal.svg)](http://npmjs.com/package/bedrock-portal)
3
3
  [![Discord](https://img.shields.io/badge/chat-on%20discord-brightgreen.svg)](https://discord.gg/KTyd9HWuBD)
4
4
 
5
- Handles and creates a Minecraft Bedrock game session which will redirect players to the specified server
5
+ Handles and creates a Minecraft Bedrock game session which will redirect players to the specified server. Join our [Discord](https://discord.com/invite/KTyd9HWuBD) for support.
6
6
 
7
7
  ## Installation
8
8
  ```shell
@@ -57,6 +57,43 @@ main();
57
57
 
58
58
  Modules are used to extend the functionality of the BedrockPortal class.
59
59
 
60
+ ### redirectFromRealm
61
+
62
+ > Requires [bedrock-protocol](https://github.com/PrismarineJS/bedrock-protocol) to be installed. `npm install bedrock-protocol`
63
+
64
+ Invites players when they join a Realm to the specified server or if they use the chat command. `#.use(Modules.redirectFromRealm, options);`
65
+
66
+ Options:
67
+ - **clientOptions**: ClientOptions - The client options to use when connecting to the Realm. These are passed directly to a [bedrock-protocol createClient](https://github.com/PrismarineJS/bedrock-protocol/blob/master/docs/API.md#becreateclientoptions--client) function. See the documentation for more information.
68
+ - **chatCommand**: object - Options for the chat command
69
+ - **enabled**: boolean - Whether sending the command in chat should trigger an invite (default: true)
70
+ - **message**: string - The message to send in chat to run the command (default: 'invite')
71
+ - **cooldown**: number - The cooldown between being able to send the command in chat (default: 60000ms)
72
+
73
+ ```js
74
+ const { BedrockPortal, Modules } = require('bedrock-portal');
75
+
76
+ const portal = new BedrockPortal(auth, { ... })
77
+
78
+ portal.use(Modules.redirectFromRealm, {
79
+ // The client options to use when connecting to the Realm.
80
+ clientOptions: {
81
+ realms: {
82
+ realmInvite: ''
83
+ }
84
+ }
85
+ // Options for the chat command
86
+ chatCommand: {
87
+ // Whether sending the command in chat should trigger an invite (optional - defaults to true)
88
+ enabled: true,
89
+ // The message to send in chat to run the command (optional - defaults to 'invite')
90
+ message: 'invite',
91
+ // The cooldown between being able to send the command in chat (optional - defaults to 60000ms)
92
+ cooldown: 60000,
93
+ }
94
+ }
95
+ ```
96
+
60
97
  ### autoFriendAdd
61
98
 
62
99
  Automatically adds the account's followers as friends and invites them to the game. `#.use(Modules.autoFriendAdd);`
@@ -78,11 +115,41 @@ portal.use(Modules.autoFriendAdd);
78
115
  // or
79
116
 
80
117
  portal.use(Modules.autoFriendAdd, {
118
+ // When a friend is added, automatically invite them to the game
81
119
  inviteOnAdd: true,
82
- conditionToMeet: (player) => player.presenceState === 'Online', // Only add friends that are online and remove friends that are offline
83
- // checkInterval: 30000, // How often to check for friends to add/remove (optional - defaults to 30000ms)
84
- // addInterval: 2000, // How long to wait between adding friends (optional - defaults to 2000ms)
85
- // removeInterval: 2000, // How long to wait between removing friends (optional - defaults to 2000ms)
120
+ // Only add friends that are online and remove friends that are offline
121
+ conditionToMeet: (player) => player.presenceState === 'Online',
122
+ // How often to check for friends to add/remove (optional - defaults to 30000ms)
123
+ checkInterval: 30000,
124
+ // How long to wait between adding friends (optional - defaults to 2000ms)
125
+ addInterval: 2000,
126
+ // How long to wait between removing friends (optional - defaults to 2000ms)
127
+ removeInterval: 2000,
128
+ });
129
+ ```
130
+
131
+ ### inviteOnMessage
132
+
133
+ Automatically invites players to the game when they send a message in the chat. `#.use(Modules.inviteOnMessage);`
134
+
135
+ Options:
136
+ - **command**: string - The command to use to invite players (default: 'invite')
137
+ - **checkInterval**: number - How often to check for messages (default: 30000ms)
138
+
139
+ ```js
140
+ const { BedrockPortal, Modules } = require('bedrock-portal');
141
+
142
+ const portal = new BedrockPortal(auth, { ... })
143
+
144
+ portal.use(Modules.inviteOnMessage);
145
+
146
+ // or
147
+
148
+ portal.use(Modules.inviteOnMessage, {
149
+ // The command to use to invite players (optional - defaults to 'invite')
150
+ command: 'invite',
151
+ // How often to check for messages (optional - defaults to 30000ms)
152
+ checkInterval: 30000,
86
153
  });
87
154
  ```
88
155
 
@@ -157,6 +224,9 @@ Emitted when a player is removed as a friend. This event is only emitted when th
157
224
  **Parameters**
158
225
  - player - [Player](#player) object
159
226
 
227
+ ### portal.on('messageRecieved', (message) => {})
228
+ Emitted when a message is recieved from a player. This event is only emitted when the `inviteOnMessage` module is enabled.
229
+
160
230
  ## Objects
161
231
 
162
232
  ### Player
@@ -23,10 +23,15 @@ const main = async () => {
23
23
 
24
24
  portal.use(Modules.autoFriendAdd, { // Automatically adds friends to the session
25
25
  inviteOnAdd: true,
26
- conditionToMeet: (player) => player.presenceState === 'Online', // Only add friends that are online and remove friends that are offline
27
- // checkInterval: 30000, // How often to check for friends to add/remove (optional - defaults to 30000ms)
28
- addInterval: 2000, // How long to wait between adding friends (optional - defaults to 2000ms)
29
- removeInterval: 2000, // How long to wait between removing friends (optional - defaults to 2000ms)
26
+ // conditionToMeet: (player) => player.presenceState === 'Online', // Only add friends that are online and remove friends that are offline
27
+ // checkInterval: 30000, // How often to check for friends to add/remove (optional - defaults to 30000ms)
28
+ // addInterval: 2000, // How long to wait between adding friends (optional - defaults to 2000ms)
29
+ // removeInterval: 2000, // How long to wait between removing friends (optional - defaults to 2000ms)
30
+ });
31
+
32
+ portal.use(Modules.inviteOnMessage, { // Automatically invites players when they send a message with the specified command
33
+ command: 'invite', // The command to use to invite players (optional - defaults to 'invite')
34
+ checkInterval: 30000, // How often to check for messages (optional - defaults to 30000ms)
30
35
  });
31
36
 
32
37
  // Put your event listeners before portal.start() to ensure you don't miss any events
@@ -59,6 +64,10 @@ const main = async () => {
59
64
  console.log('Friend Removed: ', player);
60
65
  });
61
66
 
67
+ portal.on('messageRecieved', (message) => { // Emits when a message is received. Only emitted if inviteOnMessage module is used
68
+ console.log('Message Received: ', message);
69
+ });
70
+
62
71
  await portal.start(); // Starts the session
63
72
 
64
73
  await portal.invitePlayer('p3'); // gamertag or xuid to invite
@@ -0,0 +1,58 @@
1
+ /* eslint-disable no-multi-spaces */
2
+
3
+ const { BedrockPortal, Modules, Joinability } = require('bedrock-portal');
4
+ const { Authflow, Titles } = require('prismarine-auth');
5
+
6
+ const main = async () => {
7
+ const auth = new Authflow('example', './', { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' });
8
+
9
+ const portal = new BedrockPortal(auth, {
10
+ ip: 'geyserconnect.net',
11
+ port: 19132, // The port of the server (optional - defaults to 19132)
12
+ joinability: Joinability.FriendsOfFriends, // The joinability of the session (optional - defaults to Joinability.FriendsOfFriends)
13
+ disableAltCheck: false, // Disables the alt check (optional - defaults to false)
14
+ });
15
+
16
+ portal.use(Modules.redirectFromRealm, { // Automatically invite players to the server when they join a Realm
17
+ clientOptions: { // Options for the bedrock-protocol client, see https://github.com/PrismarineJS/bedrock-protocol for options
18
+ realms: {
19
+ realmId: '', // The realm ID of the realm to invite players from
20
+ realmInvite: '', // The invite code of the realm to invite players from
21
+ pickRealm: (realms) => realms[0], // A function to pick a realm from the list of realms
22
+ },
23
+ onMsaCode: console.log, // A function to handle the MSA code
24
+ },
25
+ chatCommand: { // Options for the chat command
26
+ enabled: true, // Whether sending the command in chat should trigger an invite (optional - defaults to true)
27
+ cooldown: 60000, // The cooldown of the command in milliseconds (optional - defaults to 60000)
28
+ message: 'invite', // The message to send in chat to run the command (optional - defaults to 'invite')
29
+ },
30
+ });
31
+
32
+ // Put your event listeners before portal.start() to ensure you don't miss any events
33
+
34
+ portal.on('rtaEvent', (event) => { // Emits when an RTA event is received
35
+ console.log('RTA Event: ', event);
36
+ });
37
+
38
+ portal.on('sessionCreated', (session) => { // Emits when the session is created'
39
+ console.log('Session Created: ', session);
40
+ });
41
+
42
+ portal.on('sessionUpdated', (session) => { // Emits when the session is updated
43
+ console.log('Session Updated: ', session);
44
+ });
45
+
46
+ portal.on('playerJoin', (player) => { // Emits when a player joins the session
47
+ console.log('Player Join: ', player);
48
+ });
49
+
50
+ portal.on('playerLeave', (player) => { // Emits when a player leaves the session
51
+ console.log('Player Leave: ', player);
52
+ });
53
+
54
+ await portal.start(); // Starts the session
55
+
56
+ };
57
+
58
+ main();
package/index.d.ts CHANGED
@@ -173,6 +173,8 @@ declare module 'bedrock-portal' {
173
173
  * })
174
174
  */
175
175
  autoFriendAdd: InstanceType<typeof ExtendedModule>
176
+ inviteOnMessage: InstanceType<typeof ExtendedModule>
177
+ redirectFromRealm: InstanceType<typeof ExtendedModule>
176
178
  }
177
179
 
178
180
  export interface RTAEvent {
package/index.js CHANGED
@@ -3,6 +3,8 @@ module.exports = {
3
3
  Module : require('./src/classes/Module'),
4
4
  Modules: {
5
5
  autoFriendAdd: require('./src/modules/autoFriendAdd'),
6
+ inviteOnMessage: require('./src/modules/inviteOnMessage'),
7
+ redirectFromRealm: require('./src/modules/redirectFromRealm'),
6
8
  },
7
9
  Joinability: {
8
10
  InviteOnly: 'invite_only',
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bedrock-portal",
3
- "version": "0.3.1",
3
+ "version": "0.5.0",
4
4
  "description": "Creates a joinable session in Minecraft Bedrock Edition that can route players to their a specified host",
5
5
  "main": "index.js",
6
6
  "scripts": {
@@ -0,0 +1,68 @@
1
+ /* eslint-disable no-constant-condition */
2
+ const Module = require('../classes/Module.js');
3
+
4
+ class IniteOnMessage extends Module {
5
+ constructor() {
6
+ super('initeOnMessage', 'Automatically invite players to the server when they message you');
7
+ this.options = {
8
+ command: 'invite',
9
+ checkInterval: 30000,
10
+ };
11
+ this.cache = [];
12
+ }
13
+
14
+ async run(portal, { rest, rta }) {
15
+
16
+ const initeOnMessage = async () => {
17
+ const primaryMessages = await rest.get('https://xblmessaging.xboxlive.com/network/xbox/users/me/inbox/primary', { contractVersion: 1 });
18
+ const secondaryMessages = await rest.get('https://xblmessaging.xboxlive.com/network/xbox/users/me/inbox/secondary', { contractVersion: 1 });
19
+
20
+ const messages = [...primaryMessages.conversations, ...secondaryMessages.conversations];
21
+
22
+ const contentMessages = messages.filter(message => message.lastMessage.type === 'ContentMessage');
23
+
24
+ this.debug(`Found ${contentMessages.length} content message(s)`);
25
+
26
+ if (this.cache.length === 0) return this.cache = contentMessages;
27
+
28
+ // use #.lastMessage.messageId
29
+ const newMessages = contentMessages.filter(message => this.cache.some(cacheMessage => cacheMessage.lastMessage.messageId !== message.lastMessage.messageId && cacheMessage.conversationId === message.conversationId));
30
+
31
+ this.debug(`Found ${newMessages.length} new message(s)`);
32
+
33
+ if (newMessages.length === 0) return;
34
+
35
+ for (const message of newMessages) {
36
+ portal.emit('messageRecieved', message.lastMessage);
37
+
38
+ const senderXuid = message.lastMessage.sender;
39
+
40
+ if (senderXuid === '0') continue;
41
+
42
+ this.debug(`Received message from ${senderXuid}`);
43
+
44
+ const content = message.lastMessage.contentPayload.content.parts.find(part => part.contentType === 'text')?.text;
45
+
46
+ if (!content) continue;
47
+
48
+ if (content.toLowerCase() === this.options.command.toLowerCase()) {
49
+ await portal.invitePlayer(senderXuid);
50
+ }
51
+ }
52
+
53
+ this.cache = contentMessages;
54
+ };
55
+
56
+ while (!this.stopped) {
57
+ try {
58
+ await initeOnMessage();
59
+ await new Promise(resolve => setTimeout(resolve, this.options.checkInterval));
60
+ }
61
+ catch (error) {
62
+ this.debug(`Error: ${error.message}`, error);
63
+ }
64
+ }
65
+ }
66
+ }
67
+
68
+ module.exports = IniteOnMessage;
@@ -0,0 +1,81 @@
1
+ const Module = require('../classes/Module.js');
2
+
3
+ const cd = new Set();
4
+
5
+ class RedirectFromRealm extends Module {
6
+ constructor() {
7
+ super('redirectFromRealm', 'Automatically invite players to the server when they join a Realm');
8
+ this.options = {
9
+ clientOptions: { }, // Options for the bedrock-protocol client
10
+ chatCommand: {
11
+ enabled: true,
12
+ cooldown: 60000,
13
+ message: 'invite',
14
+ },
15
+ };
16
+ try {
17
+ this.bedrock = require('bedrock-protocol');
18
+ }
19
+ catch (e) {
20
+ console.trace('bedrock-protocol is not installed, please run "npm i bedrock-protocol" to use this module');
21
+ process.exit(1);
22
+ }
23
+ }
24
+
25
+ async run(portal, { rest, rta }) {
26
+
27
+ const { clientOptions } = this.options;
28
+
29
+ const client = await this.initClient(clientOptions, portal).catch(error => ({ error }));
30
+
31
+ if (client.error) return console.error(`Error connecting to Realm - ${client.error.message}. BedrockPortal will continue to run, but will not be able to redirect players from this realm.`);
32
+
33
+ }
34
+
35
+ async initClient(options, portal) {
36
+ return new Promise((resolve, reject) => {
37
+
38
+ this.client = this.bedrock.createClient(options);
39
+
40
+ this.client.once('error', (e) => (this.client = null, reject(e)));
41
+ this.client.once('disconnect', (e) => (this.client = null, reject(e)));
42
+
43
+ this.client.once('spawn', () => {
44
+ this.heartbeat = setInterval(async () => {
45
+ this.debug(`Sending heartbeat to Realm - Status: ${this.client?.status}`);
46
+ if (this.client === null || this.client.status === 0) {
47
+ this.client = null;
48
+ clearInterval(this.heartbeat);
49
+ this.debug('Attempting to reconnect to Realm');
50
+ return await this.initClient(options, portal).catch(err => {
51
+ this.debug(`Error reconnecting to Realm - ${err.message}`);
52
+ });
53
+ }
54
+ }, 30000);
55
+ resolve(this.client);
56
+ });
57
+
58
+ this.client.on('player_list', async packet => {
59
+ if (packet.records.type === 'add') {
60
+ for (const record of packet.records.records) {
61
+ try { await await portal.invitePlayer(record.xbox_user_id); }
62
+ catch (e) { this.debug(`Failed to invite ${record.xbox_user_id} - ${e.message}`); }
63
+ }
64
+ }
65
+ });
66
+
67
+ this.client.on('text', async (packet) => {
68
+ if (!this.options.chatCommand.enabled || packet.type !== 'chat' || cd.has(packet.xuid)) return;
69
+ if (packet.message.toLowerCase() === this.options.chatCommand.message.toLowerCase()) {
70
+ cd.add(packet.xuid);
71
+ setTimeout(() => cd.delete(packet.xuid), this.options.chatCommand.cooldown);
72
+ try { await await portal.invitePlayer(packet.xuid); }
73
+ catch (e) { this.debug(`Failed to invite ${packet.xuid} - ${e.message}`); }
74
+ }
75
+ });
76
+
77
+ });
78
+ }
79
+ }
80
+
81
+ module.exports = RedirectFromRealm;
package/src/rest.js CHANGED
@@ -81,7 +81,9 @@ module.exports = class Rest {
81
81
  const response = await this.get(`https://profile.xboxlive.com/users/${target}/profile/settings`, { params: { settings }, contractVersion: 2 });
82
82
 
83
83
  const [avatar, gamerscore, gamertag, tier, reputation, colour, realname, bio, location, modernGamertag, modernGamertagSuffix, uniqueModernGamertag, realnameOverride, tenureLevel, watermarks, isQuarantined, linkedAccounts] = response.profileUsers[0].settings.map(e=> e.value);
84
- const colourData = await axios.get(colour).then(e => e.data);
84
+ const colourData = await axios.get(colour, { timeout: 5000 })
85
+ .then(e => e.data)
86
+ .catch(() => ({ primaryColor: '000000', secondaryColor: '000000', tertiaryColor: '000000' }));
85
87
 
86
88
  return {
87
89
  xuid: response.profileUsers[0].id,