diff --git a/README.md b/README.md index ec99e05..a40eaf9 100644 --- a/README.md +++ b/README.md @@ -19,14 +19,14 @@ This package is not meant to be used with your main account. It is meant to be u - authflow - Takes an **Authflow** instance from [prismarine-auth](https://github.com/PrismarineJS/prismarine-auth), you can see the documentation for this [here.](https://github.com/PrismarineJS/prismarine-auth#authflow) - options - **ip** - The IP address of the server to redirect players to (required) - - **port** - The port of the server to redirect players to (default: 19132) - - **joinability** - The joinability of the session (default: Joinability.FriendsOfFriends) - - **world** - The world config to use for the session. Changes the session card which is displayed in the Minecraft client. - - **hostName** - string (default: '{gamertag}'s Portal') - - **name** - string (default: 'BedrockPortal') - - **version** - string (default: '{BedrockPortal version}') - - **memberCount** - number (default: 0) - - **maxMemberCount** - number (default: 10) + - **port** - The port of the server to redirect players to | default: 19132 + - **joinability** - The joinability of the session | default: FriendsOfFriends + - **world** - The world config to use for the session. Changes the session card which is displayed in the Minecraft client. (optional) + - **hostName** - string + - **name** - string + - **version** - string + - **memberCount** - number + - **maxMemberCount** - number ### Create a session redirect to a server ```js @@ -37,9 +37,12 @@ const main = async () => { const auth = new Authflow('example', './', { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }); const portal = new BedrockPortal(auth, { - ip: 'geyserconnect.net', // The server IP & port to redirect players to + // The server IP & port to redirect players to + ip: 'geyserconnect.net', port: 19132, - joinability: Joinability.InviteOnly, // The joinability of the session. Joinability.FriendsOfFriends, Joinability.FriendsOnly, Joinability.InviteOnly + + // The joinability of the session. Joinability.FriendsOfFriends, Joinability.FriendsOnly, Joinability.InviteOnly + joinability: Joinability.FriendsOfFriends }); await portal.start(); @@ -56,7 +59,44 @@ main(); Modules are used to extend the functionality of the BedrockPortal class. -### redirectFromRealm +### MultipleAccounts + +Allows the portal to use multiple accounts to redirect players to the server. `#.use(Modules.MultipleAccounts, options);` + +Options: +- **accounts**: Authflow[] - An array of authflows from [prismarine-auth](https://github.com/PrismarineJS/prismarine-auth), these accounts are automatically added to the host session and allows players to add them as a friend to join the game. (required) + +```js +const { Authflow, Titles } = require('prismarine-auth') +const { BedrockPortal, Modules } = require('bedrock-portal') + +const main = async () => { + const auth = new Authflow('example', './', { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }) + + const portal = new BedrockPortal(auth, { + ip: 'geyserconnect.net', + port: 19132, + }) + + portal.use(Modules.AutoFriendAdd, { + inviteOnAdd: true, + }) + + portal.use(Modules.MultipleAccounts, { + accounts: [ + new Authflow('account1', './', { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }), + new Authflow('account2', './', { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }), + ], + }) + + await portal.start() +} + +main() +``` + + +### RedirectFromRealm > Requires [bedrock-protocol](https://github.com/PrismarineJS/bedrock-protocol) to be installed. `npm install bedrock-protocol` @@ -74,7 +114,7 @@ const { BedrockPortal, Modules } = require('bedrock-portal'); const portal = new BedrockPortal(auth, { ... }) -portal.use(Modules.redirectFromRealm, { +portal.use(Modules.RedirectFromRealm, { // The client options to use when connecting to the Realm. clientOptions: { realms: { @@ -93,7 +133,7 @@ portal.use(Modules.redirectFromRealm, { } ``` -### autoFriendAdd +### AutoFriendAdd Automatically adds the account's followers as friends and invites them to the game. `#.use(Modules.autoFriendAdd);` @@ -109,11 +149,11 @@ const { BedrockPortal, Modules } = require('bedrock-portal'); const portal = new BedrockPortal(auth, { ... }) -portal.use(Modules.autoFriendAdd); +portal.use(Modules.AutoFriendAdd); // or -portal.use(Modules.autoFriendAdd, { +portal.use(Modules.AutoFriendAdd, { // When a friend is added, automatically invite them to the game inviteOnAdd: true, // Only add friends that are online and remove friends that are offline @@ -127,7 +167,7 @@ portal.use(Modules.autoFriendAdd, { }); ``` -### inviteOnMessage +### InviteOnMessage Automatically invites players to the game when they send a message in the chat. `#.use(Modules.inviteOnMessage);` @@ -140,11 +180,11 @@ const { BedrockPortal, Modules } = require('bedrock-portal'); const portal = new BedrockPortal(auth, { ... }) -portal.use(Modules.inviteOnMessage); +portal.use(Modules.InviteOnMessage); // or -portal.use(Modules.inviteOnMessage, { +portal.use(Modules.InviteOnMessage, { // The command to use to invite players (optional - defaults to 'invite') command: 'invite', // How often to check for messages (optional - defaults to 30000ms) @@ -169,256 +209,48 @@ const myModule = class MyModule extends Module { } } - async run(portal, { rest, rta }) { + async run(portal) { // portal - The BedrockPortal instance - // rest - The REST API instance - // rta - The RTA API instance // Do stuff here } + + async stop() { + super.stop(); + // Do stuff when the module is stopped + } } -portal.use(myModule); +portal.use(myModule, { + option1: false, +}); + ``` ## Events -### portal.on('sessionCreated', (session) => {}) +### portal.on('sessionCreated', (session) => void) Emitted when a session is created. -**Parameters** -- session - [Session](#session) object - - -### portal.on('sessionUpdated', (session) => {}) +### portal.on('sessionUpdated', (session) => void) Emitted when a session is updated. -**Parameters** -- session - [Session](#session) object - - -### portal.on('playerJoin', (player) => {}) +### portal.on('playerJoin', (player) => void) Emitted when a player joins the session. -**Parameters** -- player - [Player](#player) object - - -### portal.on('playerLeave', (player) => {}) +### portal.on('playerLeave', (player) => void) Emitted when a player leaves the session. -**Parameters** -- player - [Player](#player) object - -### portal.on('friendAdded', (player) => {}) +### portal.on('friendAdded', (player) => void) Emitted when a player is added as a friend. This event is only emitted when the `autoFriendAdd` module is enabled. -**Parameters** -- player - [Player](#player) object - -### portal.on('friendRemoved', (player) => {}) +### portal.on('friendRemoved', (player) => void) Emitted when a player is removed as a friend. This event is only emitted when the `autoFriendAdd` module is enabled. -**Parameters** -- player - [Player](#player) object - -### portal.on('messageRecieved', (message) => {}) +### portal.on('messageRecieved', (message) => void) Emitted when a message is recieved from a player. This event is only emitted when the `inviteOnMessage` module is enabled. -## Objects - -### Player - -```ts -{ - profile?: { - xuid: string, - avatar: string, - gamerscore: string, - gamertag: string, - tier: string, - reputation: string, - colour: { - primaryColour: string, - secondaryColour: string, - tertiaryColour: string - }, - realname: string, - bio: string, - location: string, - modernGamertag: string, - modernGamertagSuffix: string, - uniqueModernGamertag: string, - realnameOverride: string, - tenureLevel: string, - watermarks: string, - isQuarantined: boolean, - linkedAccounts: [] - } - session?: { - titleId: string - joinTime: string - index: number - connectionId: string - subscriptionId: string - } -} -``` - -### Session - -```ts -{ - membersInfo: { - first: number, - next: number, - count: number, - accepted: number, - active: number - }, - constants: { - system: { - readyRemovalTimeout: number, - reservedRemovalTimeout: number, - sessionEmptyTimeout: number, - inactiveRemovalTimeout: number, - version: number, - maxMembersCount: number, - visibility: string, - capabilities: { - connectivity: boolean, - connectionRequiredForActiveMembers: boolean, - gameplay: boolean, - crossPlay: boolean, - userAuthorizationStyle: boolean - }, - inviteProtocol: string, - memberInitialization: { - membersNeededToStart: number, - } - }, - custom: {} - }, - properties: { - system: { - joinRestriction: 'followed' | 'local', - readRestriction: string, - turn: [] - }, - custom: { - Joinability: string, - hostName: string, - ownerId: string, - rakNetGUID: string, - version: string, - worldName: string, - worldType: string, - protocol: number, - MemberCount: number, - MaxMemberCount: number, - BroadcastSetting: number, - UsesWebSocketsWebRTCSignaling: boolean, - UsesMPSDWebRTCSignaling: boolean, - netherNetEnabled: boolean, - OnlineCrossPlatformGame: boolean, - CrossPlayDisabled: boolean, - TitleId: number, - SupportedConnections: SessionConnection[], - levelId: string, - LanGame: boolean - } - }, - servers: {}, - members: { - [index: number]: SessionMember - } - correlationId: string, - contractVersion: number, - branch: string, - changeNumber: number, - startTime: string -} -``` - -### RawPlayer - -```ts -{ - xuid: string; - isFavorite: boolean; - isFollowingCaller: boolean; - isFollowedByCaller: boolean; - isIdentityShared: boolean; - addedDateTimeUtc: string; - displayName: string; - realName: string; - displayPicRaw: string; - showUserAsAvatar: string; - gamertag: string; - gamerScore: string; - modernGamertag: string; - modernGamertagSuffix: string; - uniqueModernGamertag: string; - xboxOneRep: string; - presenceState: string; - presenceText: string; - presenceDevices: null | any[]; - isBroadcasting: boolean; - isCloaked: null | boolean; - isQuarantined: boolean; - isXbox360Gamerpic: boolean; - lastSeenDateTimeUtc: string; - suggestion: null; - recommendation: null; - search: null; - titleHistory: null; - multiplayerSummary: null; - recentPlayer: null; - follower: { - text: string; - followedDateTime: string; - }; - preferredColor: { - primaryColor: string; - secondaryColor: string; - tertiaryColor: string; - }; - presenceDetails: null; - titlePresence: null; - titleSummaries: null; - presenceTitleIds: null; - detail: { - accountTier: string; - bio: string; - isVerified: boolean; - location: string; - tenure: string; - watermarks: any[]; - blocked: boolean; - mute: boolean; - followerCount: number; - followingCount: number; - hasGamePass: boolean; - }; - communityManagerTitles: null; - socialManager: null; - broadcast: null; - avatar: null; - linkedAccounts: { - networkName: string; - displayName: string; - showOnProfile: boolean; - isFamilyFriendly: boolean; - deeplink: null; - }[]; - colorTheme: string; - preferredFlag: string; - preferredPlatforms: string[]; -} -``` - - ## Debugging You can enable some debugging output using the `DEBUG` enviroment variable. Through node.js, you can add `process.env.DEBUG = 'bedrock-portal*'` at the top of your code. diff --git a/examples/accounts.js b/examples/accounts.js new file mode 100644 index 0000000..bf1a5d0 --- /dev/null +++ b/examples/accounts.js @@ -0,0 +1,33 @@ +process.env.DEBUG = 'bedrock-portal*' + +const { BedrockPortal, Modules } = require('bedrock-portal') +const { Authflow, Titles } = require('prismarine-auth') + +const handleMsaCode = (account, response) => { + console.log(`${account} - ${response.message}`) +} + +const main = async () => { + const auth = new Authflow('example', './', { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }) + + const portal = new BedrockPortal(auth, { + ip: 'geyserconnect.net', + port: 19132, + }) + + portal.use(Modules.AutoFriendAdd, { + inviteOnAdd: true, + }) + + portal.use(Modules.MultipleAccounts, { + accounts: [ + new Authflow('account1', './', { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }, (res) => handleMsaCode('account1', res)), + new Authflow('account2', './', { authTitle: Titles.MinecraftNintendoSwitch, deviceType: 'Nintendo', flow: 'live' }, (res) => handleMsaCode('account2', res)), + ], + }) + + await portal.start() + +} + +main() diff --git a/examples/portal.js b/examples/portal.js index 5a6df63..c13d645 100644 --- a/examples/portal.js +++ b/examples/portal.js @@ -1,5 +1,5 @@ /* eslint-disable no-multi-spaces */ -// process.env.DEBUG = 'bedrock-portal*'; +process.env.DEBUG = 'bedrock-portal*' const { BedrockPortal, Modules, Joinability } = require('bedrock-portal') const { Authflow, Titles } = require('prismarine-auth') @@ -9,68 +9,109 @@ const main = async () => { const portal = new BedrockPortal(auth, { ip: 'geyserconnect.net', - port: 19132, // The port of the server (optional - defaults to 19132) - joinability: Joinability.FriendsOfFriends, // The joinability of the session (optional - defaults to Joinability.FriendsOfFriends) - disableAltCheck: false, // Disables the alt check (optional - defaults to false) - world: { // Only affects the join world card in the friends list (optional) - hostName: 'BedrockPortal', // Displays as the host name of the world - name: 'BedrockPortal', // Displays as the name of the world - version: '1', // Displays as the version of the world - memberCount: 0, // The current member count of the world - maxMemberCount: 10, // The max member count of the world + port: 19132, + + // The joinability of the session (optional - defaults to Joinability.FriendsOfFriends) + joinability: Joinability.FriendsOfFriends, + + // Only affects the join world card in the friends list (optional) + world: { + + // Displays as the host name of the world + hostName: 'BedrockPortal', + + // Displays as the name of the world + name: 'BedrockPortal', + + // Displays as the version of the world + version: '1', + + // The current member count of the world + memberCount: 0, + + // The max member count of the world + maxMemberCount: 10, + }, }) - portal.use(Modules.AutoFriendAdd, { // Automatically adds friends to the session + // Automatically checks for friends to add and removes friends that don't meet the condition + portal.use(Modules.AutoFriendAdd, { + + // Whether to invite players when they are added as a friend (optional - defaults to false) inviteOnAdd: true, - // conditionToMeet: (player) => player.presenceState === 'Online', // Only add friends that are online and remove friends that are offline - // checkInterval: 30000, // How often to check for friends to add/remove (optional - defaults to 30000ms) - // addInterval: 2000, // How long to wait between adding friends (optional - defaults to 2000ms) - // removeInterval: 2000, // How long to wait between removing friends (optional - defaults to 2000ms) + + // Only add friends that are online and remove friends that are offline + conditionToMeet: (player) => player.presenceState === 'Online', + + // How often to check for friends to add/remove (optional - defaults to 30000ms) + checkInterval: 30000, + + // How long to wait between adding friends (optional - defaults to 2000ms) + addInterval: 2000, + + // How long to wait between removing friends (optional - defaults to 2000ms) + removeInterval: 2000, + }) - portal.use(Modules.InviteOnMessage, { // Automatically invites players when they send a message with the specified command - command: 'invite', // The command to use to invite players (optional - defaults to 'invite') - checkInterval: 30000, // How often to check for messages (optional - defaults to 30000ms) + // Automatically invites players when they send a message with the specified command + portal.use(Modules.InviteOnMessage, { + + // The command to use to invite players (optional - defaults to 'invite') + command: 'invite', + + // How often to check for messages (optional - defaults to 30000ms) + checkInterval: 30000, + }) // Put your event listeners before portal.start() to ensure you don't miss any events - portal.on('rtaEvent', (event) => { // Emits when an RTA event is received + // Emits when an RTA event is received + portal.on('rtaEvent', (event) => { console.log('RTA Event: ', event) }) - portal.on('sessionCreated', (session) => { // Emits when the session is created' + // Emits when the session is created' + portal.on('sessionCreated', (session) => { console.log('Session Created: ', session) }) - portal.on('sessionUpdated', (session) => { // Emits when the session is updated + // Emits when the session is updated + portal.on('sessionUpdated', (session) => { console.log('Session Updated: ', session) }) - portal.on('playerJoin', (player) => { // Emits when a player joins the session + // Emits when a player joins the session + portal.on('playerJoin', (player) => { console.log('Player Join: ', player) }) - portal.on('playerLeave', (player) => { // Emits when a player leaves the session + // Emits when a player leaves the session + portal.on('playerLeave', (player) => { console.log('Player Leave: ', player) }) - portal.on('friendAdded', (player) => { // Emits when a friend is added. Only emitted if autoFriendAdd module is used + // Emits when a friend is added. Only emitted if autoFriendAdd module is used + portal.on('friendAdded', (player) => { console.log('Friend Added: ', player) }) - portal.on('friendRemoved', (player) => { // Emits when a friend is removed. Only emitted if autoFriendAdd module is used + // Emits when a friend is removed. Only emitted if autoFriendAdd module is used + portal.on('friendRemoved', (player) => { console.log('Friend Removed: ', player) }) - portal.on('messageRecieved', (message) => { // Emits when a message is received. Only emitted if inviteOnMessage module is used + // Emits when a message is received. Only emitted if inviteOnMessage module is used + portal.on('messageRecieved', (message) => { console.log('Message Received: ', message) }) - await portal.start() // Starts the session + await portal.start() - await portal.invitePlayer('p3') // gamertag or xuid to invite + // Invite a player to the session + await portal.invitePlayer('p3') } diff --git a/examples/realm.js b/examples/realm.js index 773fb99..36088eb 100644 --- a/examples/realm.js +++ b/examples/realm.js @@ -1,6 +1,4 @@ -/* eslint-disable no-multi-spaces */ - -const { BedrockPortal, Modules, Joinability } = require('bedrock-portal') +const { BedrockPortal, Modules } = require('bedrock-portal') const { Authflow, Titles } = require('prismarine-auth') const main = async () => { @@ -8,50 +6,46 @@ const main = async () => { const portal = new BedrockPortal(auth, { ip: 'geyserconnect.net', - port: 19132, // The port of the server (optional - defaults to 19132) - joinability: Joinability.FriendsOfFriends, // The joinability of the session (optional - defaults to Joinability.FriendsOfFriends) - disableAltCheck: false, // Disables the alt check (optional - defaults to false) + port: 19132, }) - portal.use(Modules.redirectFromRealm, { // Automatically invite players to the server when they join a Realm - clientOptions: { // Options for the bedrock-protocol client, see https://github.com/PrismarineJS/bedrock-protocol for options + // Automatically invite players to the server when they join a Realms + portal.use(Modules.RedirectFromRealm, { + + // Options for the bedrock-protocol client, see https://github.com/PrismarineJS/bedrock-protocol for options + clientOptions: { realms: { - realmId: '', // The realm ID of the realm to invite players from - realmInvite: '', // The invite code of the realm to invite players from - pickRealm: (realms) => realms[0], // A function to pick a realm from the list of realms + + // The realm ID of the realm to invite players from + realmId: '', + + // The invite code of the realm to invite players from + realmInvite: '', + + // A function to pick a realm from the list of realms + pickRealm: (realms) => realms[0], }, - onMsaCode: console.log, // A function to handle the MSA code - }, - chatCommand: { // Options for the chat command - enabled: true, // Whether sending the command in chat should trigger an invite (optional - defaults to true) - cooldown: 60000, // The cooldown of the command in milliseconds (optional - defaults to 60000) - message: 'invite', // The message to send in chat to run the command (optional - defaults to 'invite') - }, - }) - // Put your event listeners before portal.start() to ensure you don't miss any events + // A function to handle the MSA code + onMsaCode: console.log, + }, - portal.on('rtaEvent', (event) => { // Emits when an RTA event is received - console.log('RTA Event: ', event) - }) + // Options for the invite command, sends an invite when the message is sent in chat + chatCommand: { - portal.on('sessionCreated', (session) => { // Emits when the session is created' - console.log('Session Created: ', session) - }) + // Whether sending the command in chat should trigger an invite (optional - defaults to true) + enabled: true, - portal.on('sessionUpdated', (session) => { // Emits when the session is updated - console.log('Session Updated: ', session) - }) + // The cooldown of the command in milliseconds (optional - defaults to 60000) + cooldown: 60000, - portal.on('playerJoin', (player) => { // Emits when a player joins the session - console.log('Player Join: ', player) - }) + // The message to send in chat to run the command (optional - defaults to 'invite') + message: 'invite', + }, - portal.on('playerLeave', (player) => { // Emits when a player leaves the session - console.log('Player Leave: ', player) }) - await portal.start() // Starts the session + await portal.start() } diff --git a/src/types/xblmessaging.ts b/src/types/xblmessaging.ts index 904b2e5..8e53186 100644 --- a/src/types/xblmessaging.ts +++ b/src/types/xblmessaging.ts @@ -17,10 +17,10 @@ export interface Conversation { isRead: boolean; muted: boolean; folder: string; - lastMessage: LastMessage; + lastMessage: Message; } -export interface LastMessage { +export interface Message { contentPayload: ContentPayload; timestamp: string; lastUpdateTimestamp: string;