Skip to content

Commit c9de2c1

Browse files
update to match the backend and make the usage api better
1 parent 30c9d8b commit c9de2c1

12 files changed

Lines changed: 330 additions & 59 deletions

File tree

README.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
1-
# mcutils-js-api
1+
# Minecraft Utilities - JavaScript API
22

3-
To install dependencies:
3+
TypeScript client for the [McUtils API](https://mc.fascinated.cc/api) - server status, player lookups, skins, that sort of thing.
44

55
```bash
6-
bun install
6+
bun add mcutils-js-api
77
```
88

9-
To run:
9+
```typescript
10+
import McUtilsAPI from "mcutils-js-api";
1011

11-
```bash
12-
bun run src/index.ts
13-
```
12+
const api = new McUtilsAPI();
13+
const { player, error } = await api.fetchPlayer("ImFascinated");
1414

15-
This project was created using `bun init` in bun v1.3.1. [Bun](https://bun.com) is a fast all-in-one JavaScript runtime.
15+
if (error) {
16+
console.error(error.message);
17+
} else {
18+
console.log(player?.username);
19+
}
20+
```

bun.lock

Lines changed: 1 addition & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "mcutils-js-api",
3-
"version": "1.0.5",
3+
"version": "2.0.0",
44
"module": "dist/index.js",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

src/index.ts

Lines changed: 206 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -1,45 +1,215 @@
11
import type { ErrorResponse } from "./types/response/error-response";
2-
import { BedrockServer } from "./types/server/bedrock-server";
2+
import type { BedrockServer } from "./types/server/bedrock-server";
33
import type { JavaServer } from "./types/server/java-server";
4+
import type { CachedPlayer } from "./types/player/cached-player";
5+
import type { CachedPlayerName } from "./types/player/cached-player-name";
46

5-
const API_BASE = process.env.MCUTILS_API_BASE || "https://mc.fascinated.cc/api";
7+
export class McUtilsAPI {
8+
private readonly endpoint: string;
69

7-
/**
8-
* Fetch a Java Minecraft server.
9-
*
10-
* @param host the host to fetch the server using (eg: aetheria.cc)
11-
* @returns the server or the error (if one occured)
12-
*/
13-
export async function fetchJavaServer(
14-
host: string
15-
): Promise<{ server?: JavaServer; error?: ErrorResponse }> {
16-
const response = await fetch(`${API_BASE}/server/java/${host}`);
17-
if (response.ok) {
10+
constructor(endpoint: string = "https://mc.fascinated.cc/api") {
11+
this.endpoint = endpoint;
12+
}
13+
14+
/**
15+
* Build URL search params string from a record of key-value pairs.
16+
*
17+
* @param params record of param names to string values
18+
* @returns query string including leading `?`, or empty string if no params
19+
*/
20+
buildParams(params: Record<string, string>): string {
21+
const str = new URLSearchParams(params).toString();
22+
return str ? `?${str}` : "";
23+
}
24+
25+
/**
26+
* Fetch a Java Minecraft server.
27+
*
28+
* @param host the host to fetch the server using (eg: aetheria.cc)
29+
* @returns the server or the error (if one occurred)
30+
*/
31+
async fetchJavaServer(
32+
host: string
33+
): Promise<{ server?: JavaServer; error?: ErrorResponse }> {
34+
const response = await fetch(`${this.endpoint}/server/java/${host}`);
35+
if (response.ok) {
36+
return {
37+
server: (await response.json()) as JavaServer,
38+
};
39+
}
40+
return {
41+
error: (await response.json()) as ErrorResponse,
42+
};
43+
}
44+
45+
/**
46+
* Fetch a Bedrock Minecraft server.
47+
*
48+
* @param host the host to fetch the server using (eg: geo.hivebedrock.network)
49+
* @returns the server or the error (if one occurred)
50+
*/
51+
async fetchBedrockServer(
52+
host: string
53+
): Promise<{ server?: BedrockServer; error?: ErrorResponse }> {
54+
const response = await fetch(`${this.endpoint}/server/bedrock/${host}`);
55+
if (response.ok) {
56+
return {
57+
server: (await response.json()) as BedrockServer,
58+
};
59+
}
60+
return {
61+
error: (await response.json()) as ErrorResponse,
62+
};
63+
}
64+
65+
/**
66+
* Fetch whether a server is blocked by Mojang.
67+
*
68+
* @param host the hostname to check (eg: aetheria.cc)
69+
* @returns the blocked status or the error (if one occurred)
70+
*/
71+
async fetchServerBlocked(
72+
host: string
73+
): Promise<{ blocked?: boolean; error?: ErrorResponse }> {
74+
const response = await fetch(`${this.endpoint}/server/blocked/${host}`);
75+
if (response.ok) {
76+
const json = (await response.json()) as { blocked: boolean };
77+
return { blocked: json.blocked };
78+
}
79+
return {
80+
error: (await response.json()) as ErrorResponse,
81+
};
82+
}
83+
84+
/**
85+
* Fetch a player by UUID or username.
86+
*
87+
* @param id the UUID or username of the player (eg: ImFascinated)
88+
* @returns the player or the error (if one occurred)
89+
*/
90+
async fetchPlayer(
91+
id: string
92+
): Promise<{ player?: CachedPlayer; error?: ErrorResponse }> {
93+
const response = await fetch(`${this.endpoint}/player/${id}`);
94+
if (response.ok) {
95+
return {
96+
player: (await response.json()) as CachedPlayer,
97+
};
98+
}
99+
return {
100+
error: (await response.json()) as ErrorResponse,
101+
};
102+
}
103+
104+
/**
105+
* Resolve a username to UUID (or UUID to username).
106+
*
107+
* @param id the UUID or username to resolve (eg: ImFascinated)
108+
* @returns the player name data or the error (if one occurred)
109+
*/
110+
async fetchPlayerUuid(
111+
id: string
112+
): Promise<{ playerName?: CachedPlayerName; error?: ErrorResponse }> {
113+
const response = await fetch(`${this.endpoint}/player/uuid/${id}`);
114+
if (response.ok) {
115+
return {
116+
playerName: (await response.json()) as CachedPlayerName,
117+
};
118+
}
119+
return {
120+
error: (await response.json()) as ErrorResponse,
121+
};
122+
}
123+
124+
/**
125+
* Fetch a server favicon/icon image.
126+
*
127+
* @param host the hostname of the server (eg: aetheria.cc)
128+
* @returns the PNG image or the error (if one occurred)
129+
*/
130+
async fetchServerIcon(
131+
host: string
132+
): Promise<{ image?: ArrayBuffer; error?: ErrorResponse }> {
133+
const response = await fetch(`${this.endpoint}/server/icon/${host}`);
134+
if (response.ok) {
135+
return { image: await response.arrayBuffer() };
136+
}
137+
return {
138+
error: (await response.json()) as ErrorResponse,
139+
};
140+
}
141+
142+
/**
143+
* Fetch a server preview image.
144+
*
145+
* @param platform the platform (java or bedrock)
146+
* @param host the hostname of the server (eg: aetheria.cc)
147+
* @param size the image size (default: 768)
148+
* @returns the PNG image or the error (if one occurred)
149+
*/
150+
async fetchServerPreview(
151+
platform: string,
152+
host: string,
153+
size = 768
154+
): Promise<{ image?: ArrayBuffer; error?: ErrorResponse }> {
155+
const response = await fetch(
156+
`${this.endpoint}/server/${platform}/preview/${host}${this.buildParams({ size: String(size) })}`
157+
);
158+
if (response.ok) {
159+
return { image: await response.arrayBuffer() };
160+
}
161+
return {
162+
error: (await response.json()) as ErrorResponse,
163+
};
164+
}
165+
166+
/**
167+
* Fetch a player's skin image.
168+
*
169+
* @param id the UUID or username of the player (eg: ImFascinated)
170+
* @param extension the image format - png or jpg (default: png)
171+
* @returns the skin image or the error (if one occurred)
172+
*/
173+
async fetchPlayerSkin(
174+
id: string,
175+
extension = "png"
176+
): Promise<{ image?: ArrayBuffer; error?: ErrorResponse }> {
177+
const response = await fetch(`${this.endpoint}/player/${id}/skin.${extension}`);
178+
if (response.ok) {
179+
return { image: await response.arrayBuffer() };
180+
}
181+
return {
182+
error: (await response.json()) as ErrorResponse,
183+
};
184+
}
185+
186+
/**
187+
* Fetch a specific part of a player's skin (eg: head, body).
188+
*
189+
* @param id the UUID or username of the player (eg: ImFascinated)
190+
* @param part the skin part to fetch (eg: head)
191+
* @param extension the image format - png or jpg (default: png)
192+
* @param size the image size (default: 256)
193+
* @param overlays whether to render skin overlay layers (default: false)
194+
* @returns the skin part image or the error (if one occurred)
195+
*/
196+
async fetchPlayerSkinPart(
197+
id: string,
198+
part: string,
199+
extension = "png",
200+
size = 256,
201+
overlays = false
202+
): Promise<{ image?: ArrayBuffer; error?: ErrorResponse }> {
203+
const response = await fetch(
204+
`${this.endpoint}/player/${id}/skin/${part}.${extension}${this.buildParams({ size: String(size), overlays: String(overlays) })}`
205+
);
206+
if (response.ok) {
207+
return { image: await response.arrayBuffer() };
208+
}
18209
return {
19-
server: (await response.json()) as JavaServer,
210+
error: (await response.json()) as ErrorResponse,
20211
};
21212
}
22-
return {
23-
error: (await response.json()) as ErrorResponse,
24-
};
25213
}
26214

27-
/**
28-
* Fetch a Bedrock Minecraft server.
29-
*
30-
* @param host the host to fetch the server using (eg: geo.hivebedrock.network)
31-
* @returns the server or the error (if one occured)
32-
*/
33-
export async function fetchBedrockServer(
34-
host: string
35-
): Promise<{ server?: BedrockServer; error?: ErrorResponse }> {
36-
const response = await fetch(`${API_BASE}/server/bedrock/${host}`);
37-
if (response.ok) {
38-
return {
39-
server: (await response.json()) as BedrockServer,
40-
};
41-
}
42-
return {
43-
error: (await response.json()) as ErrorResponse,
44-
};
45-
}
215+
export default McUtilsAPI;

src/test.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import McUtilsAPI from ".";
2+
3+
const api = new McUtilsAPI();
4+
5+
api.fetchJavaServer("aetheria.cc").then((result) => {
6+
console.log(result);
7+
});
8+
api.fetchPlayer("ImFascinated").then((result) => {
9+
console.log(result);
10+
});

src/types/dns/dns-record.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
export interface ARecord {
2+
type: "A";
3+
ttl: number;
4+
name?: string;
5+
address?: string;
6+
}
7+
8+
export interface SRVRecord {
9+
type: "SRV";
10+
ttl: number;
11+
name: string;
12+
target: string;
13+
priority: number;
14+
weight: number;
15+
port: number;
16+
}
17+
18+
export type DnsRecord = ARecord | SRVRecord;
Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
import type { Cache } from "../cache";
2+
3+
export type CachedPlayerNameData = {
4+
username: string;
5+
uniqueId: string;
6+
};
7+
8+
export type CachedPlayerName = Cache & CachedPlayerNameData;

src/types/player/cached-player.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import type { Cache } from "../cache";
2+
import type { Player } from "./player";
3+
4+
export type CachedPlayer = Cache & Player;

src/types/player/player.ts

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
export type SkinModel = "DEFAULT" | "SLIM";
2+
3+
export type SkinParts = Record<string, string>;
4+
5+
export type Skin = {
6+
model: SkinModel;
7+
legacy: boolean;
8+
url: string;
9+
parts: SkinParts;
10+
};
11+
12+
export type Cape = {
13+
id?: string;
14+
};
15+
16+
export type ProfileProperty = {
17+
name: string;
18+
value: string;
19+
signature?: string;
20+
};
21+
22+
export type Player = {
23+
uniqueId: string;
24+
username: string;
25+
legacyAccount: boolean;
26+
skin?: Skin | null;
27+
cape?: Cape | null;
28+
rawProperties?: ProfileProperty[];
29+
};

src/types/server/bedrock-server.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
import type { Server } from "./server";
22

33
export interface BedrockServer extends Server {
4+
id: string;
45
edition: ServerEdition;
56
version: ServerVersion;
67
gamemode: ServerGamemode;
7-
};
8+
}
89

910
export type ServerEdition = "MCPE" | "MCEE";
1011

0 commit comments

Comments
 (0)