@ejercito-fam/habbo-api 1.0.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/.github/workflows/pr.yml +18 -0
- package/.prettierignore +1 -0
- package/.yarn/releases/yarn-4.7.0.cjs +935 -0
- package/.yarnrc.yml +5 -0
- package/LICENSE +21 -0
- package/README.md +9 -0
- package/package.json +45 -0
- package/src/constants.ts +25 -0
- package/src/habbo.ts +36 -0
- package/src/index.ts +9 -0
- package/src/routes/achievements.ts +67 -0
- package/src/routes/base.ts +33 -0
- package/src/routes/groups.ts +139 -0
- package/src/routes/lists.ts +41 -0
- package/src/routes/marketplace.ts +36 -0
- package/src/routes/ping.ts +17 -0
- package/src/routes/rooms.ts +35 -0
- package/src/routes/users.ts +448 -0
- package/src/tsconfig.json +14 -0
- package/tsconfig.base.json +3 -0
- package/tsconfig.eslint.json +8 -0
package/.yarnrc.yml
ADDED
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 EjercitoFAM
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Bot
|
|
2
|
+
|
|
3
|
+
## Setup
|
|
4
|
+
|
|
5
|
+
To manage dependencies, it is recommended to use Yarn, using `yarn --immutable` to install dependencies.
|
|
6
|
+
|
|
7
|
+
Create a `.env.development.local` file inside the `src` directory, copying the template from the `.env` file in the same
|
|
8
|
+
directory, and then fill in the fields. The ENV loader is powered by
|
|
9
|
+
[`@skyra/env-utilities`](https://www.npmjs.com/package/@skyra/env-utilities), more information in the package.
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ejercito-fam/habbo-api",
|
|
3
|
+
"description": "A typed Habbo API library",
|
|
4
|
+
"version": "1.0.0",
|
|
5
|
+
"main": "./dist/main.js",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"start": "node ./dist/main.js",
|
|
9
|
+
"build": "tsc -b src",
|
|
10
|
+
"dev": "yarn build && yarn start",
|
|
11
|
+
"prepublishOnly": "yarn build"
|
|
12
|
+
},
|
|
13
|
+
"exports": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js"
|
|
16
|
+
},
|
|
17
|
+
"dependencies": {
|
|
18
|
+
"@skyra/safe-fetch": "^1.1.3"
|
|
19
|
+
},
|
|
20
|
+
"devDependencies": {
|
|
21
|
+
"@sapphire/eslint-config": "^5.0.5",
|
|
22
|
+
"@sapphire/prettier-config": "^2.0.0",
|
|
23
|
+
"@sapphire/ts-config": "^5.0.1",
|
|
24
|
+
"@types/node": "^22.15.2",
|
|
25
|
+
"@typescript-eslint/eslint-plugin": "^8.31.0",
|
|
26
|
+
"@typescript-eslint/parser": "^8.31.0",
|
|
27
|
+
"eslint": "^9.25.1",
|
|
28
|
+
"eslint-config-prettier": "^10.1.2",
|
|
29
|
+
"eslint-plugin-prettier": "^5.2.6",
|
|
30
|
+
"prettier": "^3.5.3",
|
|
31
|
+
"typescript": "^5.8.3"
|
|
32
|
+
},
|
|
33
|
+
"publishConfig": {
|
|
34
|
+
"access": "public"
|
|
35
|
+
},
|
|
36
|
+
"prettier": "@sapphire/prettier-config",
|
|
37
|
+
"eslintConfig": {
|
|
38
|
+
"extends": "@sapphire",
|
|
39
|
+
"ignorePatterns": [
|
|
40
|
+
"node_modules/",
|
|
41
|
+
"dist/"
|
|
42
|
+
]
|
|
43
|
+
},
|
|
44
|
+
"packageManager": "yarn@4.7.0"
|
|
45
|
+
}
|
package/src/constants.ts
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export enum HotelDomainTLD {
|
|
2
|
+
Brazilian = '.com.br',
|
|
3
|
+
Danish = '.dk',
|
|
4
|
+
Dutch = '.nl',
|
|
5
|
+
Finnish = '.fi',
|
|
6
|
+
French = '.fr',
|
|
7
|
+
German = '.de',
|
|
8
|
+
International = '.com',
|
|
9
|
+
Italian = '.it',
|
|
10
|
+
Spanish = '.es',
|
|
11
|
+
Turkish = '.com.tr'
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const HotelDomainURL = {
|
|
15
|
+
Brazilian: `https://www.habbo${HotelDomainTLD.Brazilian}`,
|
|
16
|
+
Danish: `https://www.habbo${HotelDomainTLD.Danish}`,
|
|
17
|
+
Dutch: `https://www.habbo${HotelDomainTLD.Dutch}`,
|
|
18
|
+
Finnish: `https://www.habbo${HotelDomainTLD.Finnish}`,
|
|
19
|
+
French: `https://www.habbo${HotelDomainTLD.French}`,
|
|
20
|
+
German: `https://www.habbo${HotelDomainTLD.German}`,
|
|
21
|
+
International: `https://www.habbo${HotelDomainTLD.International}`,
|
|
22
|
+
Italian: `https://www.habbo${HotelDomainTLD.Italian}`,
|
|
23
|
+
Spanish: `https://www.habbo${HotelDomainTLD.Spanish}`,
|
|
24
|
+
Turkish: `https://www.habbo${HotelDomainTLD.Turkish}`
|
|
25
|
+
} as const;
|
package/src/habbo.ts
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { HotelDomainURL } from 'constants.js';
|
|
2
|
+
import { AchievementsAPI } from './routes/achievements.js';
|
|
3
|
+
import { GroupsAPI } from './routes/groups.js';
|
|
4
|
+
import { ListsAPI } from './routes/lists.js';
|
|
5
|
+
import { MarketplaceAPI } from './routes/marketplace.js';
|
|
6
|
+
import { PingAPI } from './routes/ping.js';
|
|
7
|
+
import { RoomsAPI } from './routes/rooms.js';
|
|
8
|
+
import { UsersAPI } from './routes/users.js';
|
|
9
|
+
|
|
10
|
+
export class Habbo {
|
|
11
|
+
public readonly achievements: AchievementsAPI;
|
|
12
|
+
public readonly groups: GroupsAPI;
|
|
13
|
+
public readonly lists: ListsAPI;
|
|
14
|
+
public readonly marketplace: MarketplaceAPI;
|
|
15
|
+
public readonly ping: PingAPI;
|
|
16
|
+
public readonly rooms: RoomsAPI;
|
|
17
|
+
public readonly users: UsersAPI;
|
|
18
|
+
|
|
19
|
+
public constructor(options?: HabboOptions) {
|
|
20
|
+
const baseURL = options?.baseURL ?? HotelDomainURL.International;
|
|
21
|
+
const timeout = options?.timeout ?? null;
|
|
22
|
+
|
|
23
|
+
this.achievements = new AchievementsAPI(baseURL, timeout);
|
|
24
|
+
this.groups = new GroupsAPI(baseURL, timeout);
|
|
25
|
+
this.lists = new ListsAPI(baseURL, timeout);
|
|
26
|
+
this.marketplace = new MarketplaceAPI(baseURL, timeout);
|
|
27
|
+
this.ping = new PingAPI(baseURL, timeout);
|
|
28
|
+
this.rooms = new RoomsAPI(baseURL, timeout);
|
|
29
|
+
this.users = new UsersAPI(baseURL, timeout);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export interface HabboOptions {
|
|
34
|
+
baseURL?: string | null | undefined;
|
|
35
|
+
timeout?: number | null | undefined;
|
|
36
|
+
}
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export * from './constants.js';
|
|
2
|
+
export * from './habbo.js';
|
|
3
|
+
export * from './routes/achievements.js';
|
|
4
|
+
export * from './routes/groups.js';
|
|
5
|
+
export * from './routes/lists.js';
|
|
6
|
+
export * from './routes/marketplace.js';
|
|
7
|
+
export * from './routes/ping.js';
|
|
8
|
+
export * from './routes/rooms.js';
|
|
9
|
+
export * from './routes/users.js';
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { Json, type FetchResult } from '@skyra/safe-fetch';
|
|
2
|
+
import { BaseAPI, type APIOptions } from './base.js';
|
|
3
|
+
import type { HabboUserId } from './users.js';
|
|
4
|
+
|
|
5
|
+
export class AchievementsAPI extends BaseAPI {
|
|
6
|
+
/**
|
|
7
|
+
* Get all achievements
|
|
8
|
+
*
|
|
9
|
+
* @param options - The options for the API call
|
|
10
|
+
*/
|
|
11
|
+
public getAll(options?: APIOptions): Promise<FetchResult<Achievement[]>> {
|
|
12
|
+
const url = this.formatURL('/api/public/achievements');
|
|
13
|
+
return Json<Achievement[]>(this.fetch(url, options));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get the achievements from a specified user ID
|
|
18
|
+
*
|
|
19
|
+
* @param id - The ID of the user
|
|
20
|
+
* @param options - The options for the API call
|
|
21
|
+
*/
|
|
22
|
+
public getByUserId(id: HabboUserId, options?: APIOptions): Promise<FetchResult<UserAchievement[]>> {
|
|
23
|
+
const url = this.formatURL(`/api/public/achievements/${id}`);
|
|
24
|
+
return Json<UserAchievement[]>(this.fetch(url, options));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get the image URL for an achievement
|
|
29
|
+
*
|
|
30
|
+
* @param achievementName - The name of the achievement, retrieved from {@linkcode AchievementData.name}
|
|
31
|
+
*
|
|
32
|
+
* @unstable This feature is not documented, use at your own risk
|
|
33
|
+
*/
|
|
34
|
+
public getImageURL(achievementName: string): URL {
|
|
35
|
+
return new URL(`https://images.habbo.com/c_images/album1584/${achievementName}.png`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export interface Achievement {
|
|
40
|
+
achievement: AchievementData;
|
|
41
|
+
levelRequirements: AchievementRequirements;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export interface UserAchievement {
|
|
45
|
+
achievement: AchievementData;
|
|
46
|
+
level: number;
|
|
47
|
+
score: number;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export interface AchievementData {
|
|
51
|
+
id: number;
|
|
52
|
+
name: string;
|
|
53
|
+
creationTime: `${bigint}-${bigint}-${bigint}`;
|
|
54
|
+
state: AchievementDataState;
|
|
55
|
+
category: string;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export enum AchievementDataState {
|
|
59
|
+
Enabled = 'ENABLED',
|
|
60
|
+
Archived = 'ARCHIVED',
|
|
61
|
+
OffSeason = 'OFF_SEASON'
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export interface AchievementRequirements {
|
|
65
|
+
level: number;
|
|
66
|
+
requiredScore: number;
|
|
67
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { safeFetch, type FetchResult } from '@skyra/safe-fetch';
|
|
2
|
+
|
|
3
|
+
export abstract class BaseAPI {
|
|
4
|
+
protected readonly baseURL: string;
|
|
5
|
+
protected readonly timeout: number | null;
|
|
6
|
+
|
|
7
|
+
public constructor(baseURL: string, timeout?: number | null | undefined) {
|
|
8
|
+
this.baseURL = baseURL;
|
|
9
|
+
this.timeout = timeout ?? null;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
protected formatURL(route: string): URL {
|
|
13
|
+
return new URL(route, this.baseURL);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
protected fetch(url: string | URL, options?: APIOptions): Promise<FetchResult<Response>> {
|
|
17
|
+
return safeFetch(url, { headers: { 'Content-Type': 'application/json' }, signal: this.#getSignalOrDefault(options) });
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
#getSignalOrDefault(options?: APIOptions): AbortSignal | null {
|
|
21
|
+
if (typeof options === 'object' && options !== null) {
|
|
22
|
+
if (typeof options.signal === 'number') return AbortSignal.timeout(options.signal);
|
|
23
|
+
if (typeof options.signal === 'object' && options.signal !== null) return options.signal;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (typeof this.timeout === 'number') return AbortSignal.timeout(this.timeout);
|
|
27
|
+
return null;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface APIOptions {
|
|
32
|
+
signal?: AbortSignal | number | null | undefined;
|
|
33
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
import { Json, type FetchResult } from '@skyra/safe-fetch';
|
|
2
|
+
import { BaseAPI, type APIOptions } from './base.js';
|
|
3
|
+
|
|
4
|
+
export class GroupsAPI extends BaseAPI {
|
|
5
|
+
/**
|
|
6
|
+
* Get the data for a group given its identifier
|
|
7
|
+
*
|
|
8
|
+
* @param id - The ID of the group
|
|
9
|
+
* @param options - The options for the API call
|
|
10
|
+
*/
|
|
11
|
+
public getByUniqueId(id: HabboGroupId, options?: APIOptions): Promise<FetchResult<HabboGroup>> {
|
|
12
|
+
const url = this.formatURL(`/api/public/groups/${id}`);
|
|
13
|
+
return Json<HabboGroup>(this.fetch(url, options));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get the members from a group given its identifier
|
|
18
|
+
*
|
|
19
|
+
* @param id - The ID of the group
|
|
20
|
+
* @param options - The options for the API call
|
|
21
|
+
*/
|
|
22
|
+
public getGroupMembers(id: HabboGroupId, options?: APIOptions): Promise<FetchResult<HabboGroupMember[]>> {
|
|
23
|
+
const url = this.formatURL(`/api/public/groups/${id}/members`);
|
|
24
|
+
return Json<HabboGroupMember[]>(this.fetch(url, options));
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Get the image URL for a badge
|
|
29
|
+
*
|
|
30
|
+
* @param badgeCode - The badge's code, retrieved from {@linkcode HabboGroup.badgeCode}
|
|
31
|
+
*
|
|
32
|
+
* @unstable This feature is not documented, use at your own risk
|
|
33
|
+
*/
|
|
34
|
+
public getGroupBadgeImageURL(badgeCode: string): URL {
|
|
35
|
+
return this.formatURL(`/habbo-imaging/badge/${badgeCode}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
export type HabboGroupId = `g-hh${string}-${string};`
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Represents a Habbo group.
|
|
43
|
+
*/
|
|
44
|
+
export interface HabboGroup {
|
|
45
|
+
/**
|
|
46
|
+
* The unique identifier of the group.
|
|
47
|
+
*/
|
|
48
|
+
id: HabboGroupId;
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The name of the group.
|
|
52
|
+
*/
|
|
53
|
+
name: string;
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The description of the group.
|
|
57
|
+
*/
|
|
58
|
+
description: string;
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* The type of the group.
|
|
62
|
+
*/
|
|
63
|
+
type: HabboGroupType;
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* The ID of the room associated with the group, or null if no room is associated.
|
|
67
|
+
*/
|
|
68
|
+
roomId: number | null;
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* The badge code of the group.
|
|
72
|
+
*/
|
|
73
|
+
badgeCode: string;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Enum representing the type of a Habbo group.
|
|
78
|
+
*/
|
|
79
|
+
export enum HabboGroupType {
|
|
80
|
+
/**
|
|
81
|
+
* A normal group (public).
|
|
82
|
+
*/
|
|
83
|
+
NORMAL = 'NORMAL',
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* A favourite (exclusive) group.
|
|
87
|
+
*/
|
|
88
|
+
FAVOURITE = 'EXCLUSIVE',
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* A private (closed) group.
|
|
92
|
+
*/
|
|
93
|
+
PRIVATE = 'CLOSED'
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Represents a member of a Habbo group.
|
|
98
|
+
*/
|
|
99
|
+
export interface HabboGroupMember {
|
|
100
|
+
/**
|
|
101
|
+
* Indicates whether the member is online.
|
|
102
|
+
*/
|
|
103
|
+
online: boolean;
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* The gender of the member.
|
|
107
|
+
*/
|
|
108
|
+
gender: 'm' | 'f';
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* The motto of the member.
|
|
112
|
+
*/
|
|
113
|
+
motto: string;
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* The figure of the member in the Habbo world.
|
|
117
|
+
*/
|
|
118
|
+
habboFigure: string;
|
|
119
|
+
|
|
120
|
+
/**
|
|
121
|
+
* The date since the member joined the group.
|
|
122
|
+
*/
|
|
123
|
+
memberSince: string;
|
|
124
|
+
|
|
125
|
+
/**
|
|
126
|
+
* The unique identifier of the member.
|
|
127
|
+
*/
|
|
128
|
+
uniqueId: string;
|
|
129
|
+
|
|
130
|
+
/**
|
|
131
|
+
* The name of the member.
|
|
132
|
+
*/
|
|
133
|
+
name: string;
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Indicates whether the member is an admin of the group.
|
|
137
|
+
*/
|
|
138
|
+
isAdmin: boolean;
|
|
139
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { type FetchResult } from '@skyra/safe-fetch';
|
|
2
|
+
import { BaseAPI, type APIOptions } from './base.js';
|
|
3
|
+
|
|
4
|
+
export class ListsAPI extends BaseAPI {
|
|
5
|
+
/**
|
|
6
|
+
* Get the hot looks from the hotel
|
|
7
|
+
*
|
|
8
|
+
* @param options - The options for the API call
|
|
9
|
+
*/
|
|
10
|
+
public async getHotLooks(options: APIOptions): Promise<FetchResult<HabboHotLookList>> {
|
|
11
|
+
const url = this.formatURL('/api/public/lists/hotlooks');
|
|
12
|
+
const data = await this.fetch(url, options);
|
|
13
|
+
return data.map(async (result) => this.#parseHotLooksXML(await result.text())).intoPromise();
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
#parseHotLooksXML(data: string): HabboHotLookList {
|
|
17
|
+
const urlResult = /url="(.*)"/.exec(data);
|
|
18
|
+
if (urlResult === null) throw new SyntaxError('Could not read hot looks');
|
|
19
|
+
|
|
20
|
+
const url = urlResult[1];
|
|
21
|
+
const entries = [] as HabboHotLookListItem[];
|
|
22
|
+
for (const result of data.matchAll(/gender="(\w)" figure="(.+)" hash="(.+)"/g)) {
|
|
23
|
+
entries.push({ gender: result[1] as 'f' | 'm', figure: result[2], hash: result[3] });
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (entries.length === 0) throw new SyntaxError('Could not read hot looks');
|
|
27
|
+
|
|
28
|
+
return { url, entries };
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export interface HabboHotLookList {
|
|
33
|
+
url: string;
|
|
34
|
+
entries: HabboHotLookListItem[];
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface HabboHotLookListItem {
|
|
38
|
+
gender: 'f' | 'm';
|
|
39
|
+
figure: string;
|
|
40
|
+
hash: string;
|
|
41
|
+
}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { Json, type FetchResult } from '@skyra/safe-fetch';
|
|
2
|
+
import { BaseAPI, type APIOptions } from './base.js';
|
|
3
|
+
|
|
4
|
+
export class MarketplaceAPI extends BaseAPI {
|
|
5
|
+
/**
|
|
6
|
+
* Get the marketplace stats for a room item
|
|
7
|
+
*
|
|
8
|
+
* @param roomItemName - The name of the room item
|
|
9
|
+
* @param options - The options for the API call
|
|
10
|
+
*/
|
|
11
|
+
public getRoomItemStats(roomItemName: string, options?: APIOptions): Promise<FetchResult<MarketplaceStats>> {
|
|
12
|
+
const url = this.formatURL(`/api/public/marketplace/stats/roomItem/${roomItemName}`);
|
|
13
|
+
return Json<MarketplaceStats>(this.fetch(url, options));
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get the marketplace stats for a wall item
|
|
18
|
+
*
|
|
19
|
+
* @param wallItemName - The name of the wall item
|
|
20
|
+
* @param options - The options for the API call
|
|
21
|
+
*/
|
|
22
|
+
public getWallItemStats(wallItemName: string, options?: APIOptions): Promise<FetchResult<MarketplaceStats>> {
|
|
23
|
+
const url = this.formatURL(`/api/public/marketplace/stats/wallItem/${wallItemName}`);
|
|
24
|
+
return Json<MarketplaceStats>(this.fetch(url, options));
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export interface MarketplaceStats {
|
|
29
|
+
status: 'OK';
|
|
30
|
+
statsDate: `${bigint}-${bigint}-${bigint}`;
|
|
31
|
+
soldItemCount: number;
|
|
32
|
+
creditSum: number;
|
|
33
|
+
averagePrice: number;
|
|
34
|
+
totalOpenOffers: number;
|
|
35
|
+
historyLimitInDays: number;
|
|
36
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { type APIOptions, BaseAPI } from './base.js';
|
|
2
|
+
|
|
3
|
+
export class PingAPI extends BaseAPI {
|
|
4
|
+
/**
|
|
5
|
+
* Pings Habbo, returning the measured time using {@linkcode performance.now()}
|
|
6
|
+
*
|
|
7
|
+
* @param options - The options for the API call
|
|
8
|
+
*/
|
|
9
|
+
public async get(options?: APIOptions): Promise<number | null> {
|
|
10
|
+
const url = this.formatURL('/api/public/ping');
|
|
11
|
+
const now = performance.now();
|
|
12
|
+
return (await this.fetch(url, options)).match({
|
|
13
|
+
ok: () => performance.now() - now,
|
|
14
|
+
err: () => null
|
|
15
|
+
});
|
|
16
|
+
}
|
|
17
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type FetchResult, Json } from '@skyra/safe-fetch';
|
|
2
|
+
import { type APIOptions, BaseAPI } from './base.js';
|
|
3
|
+
|
|
4
|
+
export class RoomsAPI extends BaseAPI {
|
|
5
|
+
/**
|
|
6
|
+
* Get a room by its ID
|
|
7
|
+
*
|
|
8
|
+
* @param roomId - The ID of the room
|
|
9
|
+
* @param options - The options for the API call
|
|
10
|
+
*/
|
|
11
|
+
public async getById(roomId: number, options?: APIOptions): Promise<FetchResult<HabboRoom>> {
|
|
12
|
+
const url = this.formatURL(`/api/public/rooms/${roomId}`);
|
|
13
|
+
return Json<HabboRoom>(this.fetch(url, options));
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export interface HabboRoom {
|
|
18
|
+
id: number;
|
|
19
|
+
name: string;
|
|
20
|
+
description: string;
|
|
21
|
+
creationTime: `${bigint}-${bigint}-${bigint}T${string}`;
|
|
22
|
+
habboGroupId: string;
|
|
23
|
+
tags: string[];
|
|
24
|
+
maximumVisitors: number;
|
|
25
|
+
showOwnerName: boolean;
|
|
26
|
+
ownerName: string;
|
|
27
|
+
ownerUniqueId: string;
|
|
28
|
+
categories: string[];
|
|
29
|
+
thumbnailUrl: string;
|
|
30
|
+
imageUrl: string;
|
|
31
|
+
rating: number;
|
|
32
|
+
uniqueId: HabboRoomUniqueId;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export type HabboRoomUniqueId = `r-hh${string}-${string}`;
|