Skip to content

Commit

Permalink
Expand API and expose more realm config data (#40)
Browse files Browse the repository at this point in the history
* Added near full coverage of bedrock realm API (missing misc)

* Removed some unneeded returning of realm object
Copied bedrock realm API functions that also apply to Java over to Java
Updated Realm object and BedrockRealmAPI class

* Fixed linting failure

* Renamed texture pack required function
Removed removeAllRealmPlayers function due to invalid request
Added params to methods in Realm.js
Created tests and responses for the new functions
Added documentation for the new functions

* Removed removeAllRealmPlayers from table of contents

* Renamed removeRealmInvite function
Fixed body of userPermission request
Moved functions that are the same into RealmAPI class
Renamed removePlayerFromRealm uuid param to xuid

* Made detailed a param for getSubscriptionInfo
Changed configuration parameter to be an Object instead of a String

* No need for a custom configuration constructor

* Fixed missing type returns in index.ts
Updated docs to reflect type changes
Formatted what functions return to reflect their custom types

* Fixed lint fail

* Fixed failing tests

* comment out changeRealmConfiguration method

---------

Co-authored-by: extremeheat <[email protected]>
  • Loading branch information
Ian Tapply and extremeheat authored Jan 12, 2024
1 parent f5ec7c5 commit 866ce6a
Show file tree
Hide file tree
Showing 8 changed files with 837 additions and 42 deletions.
354 changes: 349 additions & 5 deletions docs/API.md

Large diffs are not rendered by default.

84 changes: 59 additions & 25 deletions index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,19 @@ declare module 'prismarine-realms' {
*/
constructor(authflow: Authflow, platform: 'bedrock' | 'java')

static from(authflow: Authflow, platform: 'bedrock' | 'java'): BedrockRealmAPI | JavaRealmAPI
static from(authflow: Authflow, platform: 'bedrock' | 'java'): BedrockRealmAPI | JavaRealmAPI

getRealms(): Promise<Realm[]>
getRealm(realmId: string): Promise<Realm>
getRealmAddress(realmId: string): Promise<Address>
getRealmBackups(realmId: string, slotId: string): Promise<Backup[]>
getRealmWorldDownload(realmId: string, slotId: string, backupId?: string | 'latest'): Promise<Download>
restoreRealmFromBackup(realmId: string, slotId: string, backupId: string): Promise<void>
changeRealmState(realmId: string, state: 'open' | 'close'): Promise<void>
restoreRealmFromBackup(realmId: string, slotId: string, backupId: string): Promise<string>
changeRealmState(realmId: string, state: 'open' | 'close'): Promise<boolean>
getRealmSubscriptionInfo(realmId: string, detailed: boolean): Promise<RealmSubscriptionInfo | RealmSubscriptionInfoDetailed>
changeRealmActiveSlot(realmId: string, slotId: number): Promise<boolean>
changeRealmNameAndDescription(realmId: string, name: string, description: string): Promise<void>
deleteRealm(realmId: string): Promise<void>

}

Expand All @@ -31,7 +35,18 @@ declare module 'prismarine-realms' {
getPendingInvites(): Promise<RealmPlayerInvite[]>
acceptRealmInvitation(invitationId: string): Promise<void>
rejectRealmInvitation(invitationId: string): Promise<void>
acceptRealmInviteFromCode(realmInviteCode: string): Promise<void>
acceptRealmInviteFromCode(realmInviteCode: string): Promise<Realm>
resetRealm(realmId: string): Promise<void>
// changeRealmConfiguration(realmId: string, configuration: any): Promise<void>
removePlayerFromRealm(realmId: string, xuid: string): Promise<Realm>
opRealmPlayer(realmId: string, uuid: string): Promise<Realm>
deopRealmPlayer(realmId: string, uuid: string): Promise<Realm>
banPlayerFromRealm(realmId: string, uuid: string): Promise<void>
unbanPlayerFromRealm(realmId: string, uuid: string): Promise<void>
removeRealmFromJoinedList(realmId: string): Promise<void>
changeIsTexturePackRequired(realmId: string, forced: boolean): Promise<void>
changeRealmDefaultPermission(realmId: string, permission: string): Promise<void>
changeRealmPlayerPermission(realmId: string, permission: string, uuid: string): Promise<void>
}

export class JavaRealmAPI extends RealmAPI {
Expand All @@ -41,10 +56,14 @@ declare module 'prismarine-realms' {
export interface Realm {
getAddress(): Promise<Address>
invitePlayer(uuid: string, name: string): Promise<Realm>
open(): Promise<void>
close(): Promise<void>
open(): Promise<boolean>
close(): Promise<boolean>
delete(): Promise<void>
getBackups(): Promise<Backup[]>
getWorldDownload(): Promise<Download>
getSubscriptionInfo(): Promise<RealmSubscriptionInfo | RealmSubscriptionInfoDetailed>
changeActiveSlot(): Promise<boolean>
changeNameAndDescription(): Promise<void>
id: number
remoteSubscriptionId: string
owner: string | null
Expand Down Expand Up @@ -77,16 +96,16 @@ declare module 'prismarine-realms' {
lastModifiedDate: number
size: number
metadata: {
gameDifficulty: string
name: string
gameServerVersion: string
enabledPacks: {
resourcePack: string
behaviorPack: string
}
description: string | null
gamemode: string
worldType: string
gameDifficulty: string
name: string
gameServerVersion: string
enabledPacks: {
resourcePack: string
behaviorPack: string
}
description: string | null
gamemode: string
worldType: string
}
}

Expand All @@ -101,6 +120,22 @@ declare module 'prismarine-realms' {
token?: string // Bedrock only
}

export interface RealmSubscriptionInfo {
startDate: number
daysLeft: number
subscriptionType: string
}

export interface RealmSubscriptionInfoDetailed {
type: string
store: string
startDate: number
endDate: number
renewalPeriod: number
daysLeft: number
subscriptionId: string
}

export interface RealmPlayerInvite {
invitationId: string
worldName: string
Expand All @@ -120,22 +155,21 @@ declare module 'prismarine-realms' {
}

export interface RealmPlayer {
uuid: string,
name: string,
operator: boolean,
accepted: boolean,
online: boolean,
permission: string
uuid: string,
name: string,
operator: boolean,
accepted: boolean,
online: boolean,
permission: string
}

export interface Slot {
options: string
slotId: number
options: string
slotId: number
}

export interface Address {
host: string
port: number
}

}
88 changes: 83 additions & 5 deletions src/bedrock/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ module.exports = class BedrockRealmAPI extends RealmAPI {
async acceptRealmInviteFromCode (inviteCode) {
if (!inviteCode) throw new Error('Need to provide a realm invite code/link')
const clean = inviteCode.replace(/https:\/\/realms.gg\//g, '')
await this.rest.post(`/invites/v1/link/accept/${clean}`)
const data = await this.rest.post(`/invites/v1/link/accept/${clean}`)
return new Realm(this, data)
}

async invitePlayer (realmId, uuid) {
Expand All @@ -90,12 +91,89 @@ module.exports = class BedrockRealmAPI extends RealmAPI {
return new Realm(this, data)
}

async changeRealmState (realmId, state) {
return await this.rest.put(`/worlds/${realmId}/${state}`)
}

async getRealmWorldDownload (realmId, slotId, backupId = 'latest') {
const data = await this.rest.get(`/archive/download/world/${realmId}/${slotId}/${backupId}`) // if backupId = latest will get the world as it is now not the most recent backup
return new Download(this, data)
}

async resetRealm (realmId) {
await this.rest.put(`/worlds/${realmId}/reset`)
}

// Reference https://github.com/PrismarineJS/prismarine-realms/issues/34 for configuration structure
// async changeRealmConfiguration (realmId, configuration) {
// await this.rest.put(`/worlds/${realmId}/configuration`, {
// body: configuration
// })
// }

async removePlayerFromRealm (realmId, xuid) {
const data = await this.rest.put(`/invites/${realmId}/invite/update`, {
body: {
invites: {
[xuid]: 'REMOVE'
}
}
})
return new Realm(this, data)
}

async opRealmPlayer (realmId, uuid) {
const data = await this.rest.put(`/invites/${realmId}/invite/update`, {
body: {
invites: {
[uuid]: 'OP'
}
}
})
return new Realm(this, data)
}

async deopRealmPlayer (realmId, uuid) {
const data = await this.rest.put(`/invites/${realmId}/invite/update`, {
body: {
invites: {
[uuid]: 'DEOP'
}
}
})
return new Realm(this, data)
}

async banPlayerFromRealm (realmId, uuid) {
await this.rest.post(`/worlds/${realmId}/blocklist/${uuid}`)
}

async unbanPlayerFromRealm (realmId, uuid) {
await this.rest.delete(`/worlds/${realmId}/blocklist/${uuid}`)
}

async removeRealmFromJoinedList (realmId) {
await this.rest.delete(`/invites/${realmId}`)
}

async changeIsTexturePackRequired (realmId, forced) {
if (forced) {
await this.rest.put(`/world/${realmId}/content/texturePacksRequired`)
} else {
await this.rest.delete(`/world/${realmId}/content/texturePacksRequired`)
}
}

async changeRealmDefaultPermission (realmId, permission) {
await this.rest.put(`/world/${realmId}/defaultPermission`, {
body: {
permission: permission.toUpperCase()
}
})
}

async changeRealmPlayerPermission (realmId, permission, uuid) {
await this.rest.put(`/world/${realmId}/userPermission`, {
body: {
permission: permission.toUpperCase(),
xuid: uuid
}
})
}
}
43 changes: 43 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,49 @@ class RealmAPI {
async restoreRealmFromBackup (realmId, backupId) {
return await this.rest.put(`/worlds/${realmId}/backups?backupId=${encodeURIComponent(backupId)}&clientSupportsRetries`)
}

async getRealmSubscriptionInfo (realmId, detailed = false) {
if (detailed) {
const data = await this.rest.get(`/subscriptions/${realmId}/details`)
return {
type: data.type,
store: data.store,
startDate: data.startDate,
endDate: data.endDate,
renewalPeriod: data.renewalPeriod,
daysLeft: data.daysLeft,
subscriptionId: data.subscriptionId
}
} else {
const data = await this.rest.get(`/subscriptions/${realmId}`)
return {
startDate: data.startDate,
daysLeft: data.daysLeft,
subscriptionType: data.subscriptionType
}
}
}

async changeRealmState (realmId, state) {
return await this.rest.put(`/worlds/${realmId}/${state}`)
}

async changeRealmActiveSlot (realmId, slotId) {
return await this.rest.put(`/worlds/${realmId}/slot/${slotId}`)
}

async changeRealmNameAndDescription (realmId, name, description) {
await this.rest.post(`/worlds/${realmId}`, {
body: {
name,
description
}
})
}

async deleteRealm (realmId) {
await this.rest.delete(`/worlds/${realmId}`)
}
}

module.exports = RealmAPI
4 changes: 0 additions & 4 deletions src/java/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,6 @@ module.exports = class JavaRealmAPI extends RealmAPI {
return new Realm(this, data)
}

async changeRealmState (realmId, state) {
return await this.rest.put(`/worlds/${realmId}/${state}`)
}

async getRealmWorldDownload (realmId, slotId) {
const data = await this.rest.get(`/worlds/${realmId}/slot/${slotId}/download`)
return new Download(this, data)
Expand Down
16 changes: 16 additions & 0 deletions src/structures/Realm.js
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,27 @@ module.exports = class Realm {
return this.#api.changeRealmState(this.id, 'close')
}

async delete () {
return this.#api.deleteRealm(this.id)
}

async getWorldDownload () {
return this.#api.getRealmWorldDownload(this.id, this.activeSlot, 'latest')
}

async getBackups () {
return this.#api.getRealmBackups(this.id, this.activeSlot)
}

async getSubscriptionInfo (detailed = false) {
return this.#api.getRealmSubscriptionInfo(this.id, detailed)
}

async changeActiveSlot (slotId) {
return this.#api.changeRealmActiveSlot(this.id, slotId)
}

async changeNameAndDescription (name, description) {
return this.#api.changeRealmNameAndDescription(this.id, name, description)
}
}
Loading

0 comments on commit 866ce6a

Please sign in to comment.