@ix-xs/metamob.api 2.0.0 → 3.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/README.md CHANGED
@@ -1,18 +1,18 @@
1
- <img align=right src="https://metamob.fr/img/otomai.png">
2
- <h1><img src="https://metamob.fr/img/logo.png">Metamob</h1>
3
- <h3>Gérez vos monstres de l'Eternelle Moisson sur Dofus !</h3>
4
- <a href="https://metamob.fr/connexion">Connectez-vous</a> ou <a href="https://metamob.fr/inscription">Inscrivez-vous</a> pour profiter des avantages du site :
5
- <ul>
6
- <li>Suivez votre avancement dans la quête</li>
7
- <li>Gérez finement vos monstres</li>
8
- <li>Visualisez votre profil</li>
9
- <li>Echangez avec d'autres joueurs</li>
10
- <li>Une question ? Regardez <a href="https://metamob.fr/aide">l'aide</a></li>
11
- </ul>
1
+ # ![Metamob](https://beta.metamob.fr/img/pierre_dame_small.png) [Metamob](https://beta.metamob.fr)
2
+
3
+ <img align=right src="https://beta.metamob.fr/img/ocre.png">
4
+ <div>
5
+ <div>
6
+ <h3>Complétez votre quête du Dofus Ocre</h3>
7
+ <p>Suivez votre progression dans la quête de l'Ocre, gérez votre inventaire de monstres et échangez avec la communauté pour compléter votre collection.</p>
8
+ <p>Compatible avec Dofus Unity, Dofus Retro et Dofus Touch</p>
9
+ </div>
10
+ </div>
11
+
12
12
  <br>
13
13
  <br>
14
14
 
15
- # 🔥 @ix-xs/metamob.api
15
+ # @ix-xs/metamob.api
16
16
 
17
17
  <div align="center">
18
18
 
@@ -21,252 +21,785 @@
21
21
  ![NPM](https://img.shields.io/badge/NPM-%23CB3837.svg?style=for-the-badge&logo=npm&logoColor=white)
22
22
  ![GitHub](https://img.shields.io/badge/github-%23121011.svg?style=for-the-badge&logo=github&logoColor=white)
23
23
 
24
- **🚀 SDK JavaScript officieux pour l'API Metamob - Dofus 🐉**
25
-
26
- *Une librairie performante pour interagir avec l'écosystème Dofus via Metamob*
27
-
28
24
  [![npm version](https://badge.fury.io/js/%40ix-xs%2Fmetamob.api.svg)](https://www.npmjs.com/package/@ix-xs/metamob.api)
29
25
  [![Downloads](https://img.shields.io/npm/dm/@ix-xs/metamob.api.svg)](https://www.npmjs.com/package/@ix-xs/metamob.api)
30
26
  [![License](https://img.shields.io/npm/l/@ix-xs/metamob.api.svg)](https://github.com/ix-xs/metamob.api/blob/main/LICENSE)
31
27
 
32
28
  </div>
29
+ <br>
33
30
 
34
- ---
31
+ ## 📖 Table des matières
35
32
 
36
- ## 🌟 Aperçu
33
+ - [✨ Présentation](#-présentation)
34
+ - [🚀 Installation](#-installation)
35
+ - [🔐 Authentification](#-authentification)
36
+ - [⚙️ Limites de l'API](#️-limites-de-lapi)
37
+ - [📦 Structure des réponses](#-structure-des-réponses)
38
+ - [💾 Cache de données](#-cache-de-données)
39
+ - [📚 Documentation API](#-documentation-api)
40
+ - [Versions du jeu](#versions-du-jeu)
41
+ - [Serveurs](#serveurs)
42
+ - [Types de monstres](#types-de-monstres)
43
+ - [Modèles de quête](#modèles-de-quête)
44
+ - [Recherche d'utilisateurs](#recherche-dutilisateurs)
45
+ - [Profils utilisateurs](#profils-utilisateurs)
46
+ - [Quêtes utilisateurs](#quêtes-utilisateurs)
37
47
 
38
- **@ix-xs/metamob.api** est un SDK JavaScript moderne et puissant conçu spécialement pour l'API Metamob, permettant aux développeurs de créer facilement des applications Dofus avec une intégration fluide et performante.
48
+ ## Présentation
39
49
 
40
- ### Fonctionnalités principales
50
+ **@ix-xs/metamob.api** est un client Node.js complet pour accéder programmatiquement à l'[API Metamob](https://beta.metamob.fr/help/api). Metamob est une plateforme communautaire dédiée au **suivi de la quête de l'Ocre** dans l'univers Dofus, permettant aux joueurs de gérer leur inventaire de monstres et d'échanger avec d'autres collectionneurs.
41
51
 
42
- - 🔥 **Cache intelligent** avec synchronisation automatique disque/mémoire
43
- - ⚡ **Performances optimales** grâce à un système de cache avancé
44
- - 🛡️ **Sécurité renforcée** avec écriture atomique des fichiers
45
- - 🎯 **API moderne** avec support complet TypeScript (jsdoc)
46
- - 📖 **Documentation complète** avec exemples pratiques
47
- - 🔄 **Rate limiting** automatique avec retry intelligent
48
- - 🌐 **Support complet** de toutes les endpoints Metamob
52
+ ### 🎮 Compatible avec
49
53
 
50
- ---
54
+ - **Dofus Unity** - Version moderne du jeu
55
+ - **Dofus Retro (1.29)** - Version rétro/classique
56
+ - **Dofus Touch** - Version mobile
51
57
 
52
- ## 🚀 Installation rapide
58
+ ### 🎯 Cas d'usage
59
+
60
+ - 📊 **Bots Discord** - Créer des commandes pour consulter les données Metamob
61
+ - 🔧 **Outils personnalisés** - Développer des applications pour gérer votre progression
62
+ - 📈 **Intégrations** - Combiner Metamob avec d'autres services (webhooks, monitoring, etc.)
63
+
64
+ ## 🚀 Installation
65
+
66
+ ### NPM
53
67
 
54
68
  ```bash
55
- # NPM
56
69
  npm install @ix-xs/metamob.api
70
+ ```
71
+
72
+ ## 🔐 Authentification
73
+
74
+ ### Créer une clé API
75
+
76
+ 1. ✅ Connectez-vous à votre compte sur [Metamob](https://beta.metamob.fr)
77
+ 2. ⚙️ Accédez à vos **Paramètres**
78
+ 3. 🔑 Naviguez vers la section **Clé API**
79
+ 4. ✨ Cliquez sur **Générer une clé**
80
+ 5. 📋 **Copiez** votre clé (elle ne sera plus affichée après cette étape)
57
81
 
58
- # Yarn
59
- yarn add @ix-xs/metamob.api
82
+ ## ⚙️ Limites de l'API
60
83
 
61
- # PNPM
62
- pnpm add @ix-xs/metamob.api
84
+ L'API Metamob applique des **rate limits** pour garantir la stabilité du service :
85
+
86
+ ### Rate Limiting
87
+
88
+ | Limite | Valeur |
89
+ | ----------------------- | ------------------------ |
90
+ | **Requêtes par minute** | 60 par clé API |
91
+ | **Code de dépassement** | `429 Too Many Requests` |
92
+ | **En-tête de retry** | `Retry-After` (secondes) |
93
+
94
+ ## 📦 Structure des réponses
95
+
96
+ Toutes les requêtes retournent un objet JSON **normalisé** avec une structure cohérente :
97
+
98
+ ### Format standard
99
+
100
+ ```javascript
101
+ {
102
+ ok: boolean, // Indique le succès de la requête
103
+ status: number, // Code HTTP (200, 404, 429, 500, etc.)
104
+ statusText: string, // Libellé HTTP ("OK", "Not Found", etc.)
105
+ data?: Object|Object[], // Données retournées (absent si ok = false)
106
+ pagination?: { // Présent uniquement pour les listes paginées
107
+ total: number, // Nombre total d'éléments
108
+ limit: number, // Nombre d'éléments par page
109
+ offset: number, // Index du premier élément
110
+ },
111
+ error?: string, // Message d'erreur (si ok = false)
112
+ retryAfter?: number, // Délai avant nouvelle tentative (si status = 429)
113
+ }
63
114
  ```
64
115
 
65
- ### 📋 Prérequis
116
+ ### Exemple : succès
66
117
 
67
- - **Node.js** >= 18.0.0
68
- - **NPM** >= 8.0.0
69
- - Une clé API Metamob valide
118
+ ```javascript
119
+ {
120
+ ok: true,
121
+ status: 200,
122
+ statusText: "OK",
123
+ data: [
124
+ { id: 1, name: "Brial", community: "France", ... },
125
+ { id: 2, name: "Rafal", community: "France", ... },
126
+ ],
127
+ pagination: {
128
+ total: 20,
129
+ limit: 20,
130
+ offset: 0
131
+ }
132
+ }
133
+ ```
70
134
 
71
- ---
135
+ ### Exemple : erreur
136
+
137
+ ```javascript
138
+ {
139
+ ok: false,
140
+ status: 404,
141
+ statusText: "Not Found",
142
+ error: "Utilisateur 'xyz' non trouvé"
143
+ }
144
+ ```
145
+
146
+ ### Exemple : rate limit
147
+
148
+ ```javascript
149
+ {
150
+ ok: false,
151
+ status: 429,
152
+ statusText: "Too Many Requests",
153
+ retryAfter: 45,
154
+ error: "Trop de requêtes. Veuillez réessayer après 45 secondes"
155
+ }
156
+ ```
157
+
158
+ ## 💾 Cache de données
72
159
 
73
- ## 💡 Utilisation de base
160
+ ### 🎯 Concept
161
+
162
+ Ce package intègre un **cache de données statiques** embarqué sous forme de fichiers JSON. Ces données correspondent à des informations quasi-permanentes côté Metamob (serveurs, types de monstres, catalogues, etc.).
163
+
164
+ ### ✅ Avantages du cache
165
+
166
+ | Avantage | Description |
167
+ | -------------------------- | ------------------------------------------------------------ |
168
+ | **🚀 Performance** | Pas de requête API pour les données statiques |
169
+ | **📉 Réduction API** | Économise vos appels API pour les vraies données |
170
+ | **🎯 Recherche intuitive** | Rechercher par nom au lieu de chercher par ID |
171
+ | **↔️ Conversion** | Convertir facilement ID ↔ Nom |
172
+ | **⚡ Offline** | Données disponibles même sans réseau (après première charge) |
173
+
174
+ ### 📊 Données en cache
175
+
176
+ | Clé | Contenu | Utilité |
177
+ | -------------- | ----------------------------------------------- | ----------------------------------- |
178
+ | `gameVersions` | Versions du jeu (Unity, Retro, Touch) | Identifier les versions disponibles |
179
+ | `servers` | Liste des serveurs par communauté | Chercher un serveur par nom |
180
+ | `monsterTypes` | Types de monstres (monstre, archimonstre, boss) | Filtrer par type |
181
+ | `monsters` | Catalogue complet des monstres multilingues | Rechercher un monstre par nom |
182
+
183
+ ### 🔍 Utilisation du cache
74
184
 
75
185
  ```javascript
76
- const metamobAPI = require("@ix-xs/metamob.api");
77
- const client = new metamobAPI("VOTRE_CLÉ_API_METAMOB");
186
+ // Au lieu de faire :
187
+ client.getMonsters(); // requête GET /monsters -> paginé
188
+
189
+ // Vous pouvez faire :
190
+ client.cache.monsters; // cache, complet
191
+ ```
192
+
193
+ ### 🔄 Mise à jour du cache
194
+
195
+ Le cache n'est **pas mis à jour automatiquement** depuis l'API en temps réel. Les mises à jour sont gérées via de **nouvelles versions du package** NPM.
196
+
197
+ **Pour obtenir les dernières données :**
198
+
199
+ ```bash
200
+ npm update @ix-xs/metamob.api
201
+ ```
202
+
203
+ Les données en cache reflètent les informations les plus récentes de Metamob à chaque nouvelle version du package.
204
+
205
+ ### ⚠️ Limitations
206
+
207
+ - Le cache est **read-only** (lecture seule)
208
+ - Les données statiques changent rarement, mais peuvent être obsolètes entre versions
209
+ - Pour les données **dynamiques** (profils, quêtes), utiliser les endpoints API appropriés
78
210
 
79
- // Utilisation du cache (recommandé)
80
- console.log(client.cache.servers); // Serveurs en cache
81
- console.log(client.cache.monsters); // Monstres en cache
82
- console.log(client.cache.areas); // Zones en cache
211
+ ## 📚 Documentation API
83
212
 
84
- // Ou récupération via API
85
- const servers = await client.getServers();
86
- const user = await client.getUser("Ix-xs");
87
- const monsters = await client.getUserMonsters("Ix-xs");
213
+ ### Initialisation
214
+
215
+ ```javascript
216
+ const MetamobAPI = require("@ix-xs/metamob.api");
217
+ const client = new MetamobAPI(process.env.METAMOB_API_KEY);
88
218
  ```
89
219
 
90
220
  ---
91
221
 
92
- ## 🏗️ Architecture du cache
222
+ ### Versions du jeu
223
+
224
+ Récupérer la liste des versions du jeu disponibles sur Metamob.
93
225
 
94
- ### 🧠 Cache intelligent multicouche
226
+ #### Signature
227
+
228
+ ```javascript
229
+ getGameVersions(options?: { game_name?: string })
230
+ ```
231
+
232
+ #### Types
233
+
234
+ ```javascript
235
+ /**
236
+ * @typedef {object} GameVersion
237
+ * @property {number} id - Identifiant unique
238
+ * @property {string} name - Nom de la version ("Dofus (Unity)", "Dofus Retro (1.29)", "Dofus Touch")
239
+ */
240
+ ```
95
241
 
96
- Notre système de cache combine :
242
+ #### Exemples
97
243
 
98
- - **📁 Cache disque** : Persistance des données via JSON
99
- - **💾 Cache mémoire** : Accès ultra-rapide via `require()`
100
- - **🔄 Synchronisation automatique** : Mise à jour seamless
101
- - **🛡️ Écriture atomique** : Prévention de la corruption des données
244
+ **Lister toutes les versions**
102
245
 
103
246
  ```javascript
104
- // Le cache est automatiquement synchronisé
105
- await client.getServers(); // Met à jour le cache si nécessaire
247
+ const response = await client.getGameVersions();
106
248
 
107
- // Accès instantané depuis le cache mémoire
108
- const servers = client.cache.servers;
249
+ if (!response.ok) {
250
+ return console.error(response.error ?? response.statusText);
251
+ }
252
+
253
+ response.data.forEach((version) => {
254
+ console.log(`${version.id}: ${version.name}`);
255
+ });
256
+ // Output:
257
+ // 1: Dofus (Unity)
258
+ // 2: Dofus Retro (1.29)
259
+ // 3: Dofus Touch
109
260
  ```
110
261
 
111
- ### 📊 Types de cache disponibles
262
+ **Récupérer une version spécifique**
112
263
 
113
- | Type | Description | Endpoint |
114
- |------|-------------|----------|
115
- | `servers` | Serveurs Dofus | `/serveurs` |
116
- | `monsters` | Base de données des monstres | `/monstres` |
117
- | `areas` | Zones de jeu | `/zones` |
118
- | `subareas` | Sous-zones détaillées | `/sous-zones` |
264
+ ```javascript
265
+ const response = await client.getGameVersions({
266
+ game_name: "Dofus (Unity)",
267
+ });
268
+
269
+ if (response.ok) {
270
+ console.log(response.data);
271
+ // { id: 1, name: "Dofus (Unity)" }
272
+ }
273
+ ```
119
274
 
120
275
  ---
121
276
 
122
- ## 🔧 API complète
277
+ ### Serveurs
278
+
279
+ Récupérer la liste des serveurs de jeu disponibles.
123
280
 
124
- ### 👤 Gestion des utilisateurs
281
+ #### Signature
125
282
 
126
283
  ```javascript
127
- // Informations utilisateur
128
- const user = await client.getUser("pseudo");
284
+ getServers(options?: { server_name?: string })
285
+ ```
129
286
 
130
- // Monstres d'un utilisateur
131
- const userMonsters = await client.getUserMonsters("pseudo");
287
+ #### Types
288
+
289
+ ```javascript
290
+ /**
291
+ * @typedef {object} Server
292
+ * @property {number} id - Identifiant unique
293
+ * @property {string} name - Nom du serveur
294
+ * @property {string} community - Communauté ("World" ou "France")
295
+ * @property {GameVersion} game_version - Version du jeu du serveur
296
+ */
297
+ ```
132
298
 
133
- // Mise à jour des monstres
134
- await client.setUserMonsters("pseudo", "unique_id", [
135
- { monstre: "Arakne", etat: "recherche", quantite: 5 },
136
- { monstre: "Boufton Blanc", etat: "propose", quantite: 2 }
137
- ]);
299
+ #### Serveurs disponibles
300
+
301
+ | France | World |
302
+ | ---------- | ---------- |
303
+ | Brial | Brial |
304
+ | Rafal | Rafal |
305
+ | Salar | Salar |
306
+ | Kourial | Kourial |
307
+ | Dakal | Dakal |
308
+ | Mikhal | Mikhal |
309
+ | Imagiro | Imagiro |
310
+ | Hell Mina | Hell Mina |
311
+ | Tylezia | Tylezia |
312
+ | Orukam | Orukam |
313
+ | Tal Kasha | Tal Kasha |
314
+ | Draconiros | Draconiros |
315
+ | Ombre | Ombre |
316
+ | Fallanster | Fallanster |
317
+ | Boune | Boune |
318
+ | Allisteria | Allisteria |
319
+ | Blair | Blair |
320
+ | Kelerog | Kelerog |
321
+ | Talok | Talok |
322
+ | Tiliwan | Tiliwan |
323
+
324
+ #### Exemples
325
+
326
+ **Lister tous les serveurs**
138
327
 
139
- // Réinitialisation des monstres
140
- await client.resetUserMonsters("pseudo", "unique_id");
328
+ ```javascript
329
+ const response = await client.getServers();
330
+
331
+ if (response.ok) {
332
+ response.data.forEach((server) => {
333
+ console.log(
334
+ `${server.name} (${server.community}) - ${server.game_version.name}`,
335
+ );
336
+ });
337
+ }
338
+ ```
339
+
340
+ **Récupérer un serveur spécifique**
341
+
342
+ ```javascript
343
+ const response = await client.getServers({
344
+ server_name: "Brial",
345
+ });
346
+
347
+ if (response.ok) {
348
+ console.log(response.data);
349
+ // {
350
+ // id: 1,
351
+ // name: "Brial",
352
+ // community: "France",
353
+ // game_version: { id: 1, name: "Dofus (Unity)" }
354
+ // }
355
+ }
356
+ ```
357
+
358
+ **Grouper par communauté**
359
+
360
+ ```javascript
361
+ const response = await client.getServers();
362
+
363
+ if (response.ok) {
364
+ const byRegion = response.data.reduce((acc, server) => {
365
+ if (!acc[server.community]) acc[server.community] = [];
366
+ acc[server.community].push(server.name);
367
+ return acc;
368
+ }, {});
369
+
370
+ console.log(byRegion);
371
+ // {
372
+ // France: ["Brial", "Rafal", ...],
373
+ // World: ["Brial", "Rafal", ...]
374
+ // }
375
+ }
141
376
  ```
142
377
 
143
- ### 🎮 Données de jeu
378
+ ---
379
+
380
+ ### Types de monstres
381
+
382
+ Récupérer les catégories de monstres.
383
+
384
+ #### Signature
144
385
 
145
386
  ```javascript
146
- // Cache instantané (recommandé)
147
- const servers = client.cache.servers;
148
- const monsters = client.cache.monsters;
149
- const areas = client.cache.areas;
150
- const subareas = client.cache.subareas;
387
+ getMonsterTypes(options?: { type_name?: string })
388
+ ```
389
+
390
+ #### Types
151
391
 
152
- // Ou via API avec mise à jour du cache
153
- const freshServers = await client.getServers();
154
- const freshMonsters = await client.getMonsters();
155
- const freshAreas = await client.getAreas();
156
- const freshSubareas = await client.getSubareas();
392
+ ```javascript
393
+ /**
394
+ * @typedef {object} MonsterType
395
+ * @property {number} id - Identifiant unique
396
+ * @property {object} name - Nom multilingue
397
+ * @property {string} name.fr - Nom en français
398
+ * @property {string} name.en - Nom en anglais
399
+ * @property {string} name.es - Nom en espagnol
400
+ */
157
401
  ```
158
402
 
159
- ### 🐙 Kralamoures
403
+ #### Types disponibles
404
+
405
+ | Français | Anglais | Espagnol |
406
+ | ------------ | ----------- | ------------- |
407
+ | Monstre | Monster | Monstruo |
408
+ | Archimonstre | Archmonster | Archimonstruo |
409
+ | Boss | Boss | Boss |
410
+
411
+ #### Exemples
412
+
413
+ **Lister tous les types**
160
414
 
161
415
  ```javascript
162
- // Toutes les ouvertures kralamoures
163
- const kralamoures = await client.getKralamoures();
416
+ const response = await client.getMonsterTypes();
417
+
418
+ if (response.ok) {
419
+ response.data.forEach((type) => {
420
+ console.log(
421
+ `FR: ${type.name.fr}, EN: ${type.name.en}, ES: ${type.name.es}`,
422
+ );
423
+ });
424
+ }
425
+ ```
164
426
 
165
- // Avec filtres
166
- const filtered = await client.getKralamoures({
167
- server: "Salar",
168
- start_date: "2025-01-01",
169
- end_date: "2025-12-31"
427
+ **Récupérer un type spécifique**
428
+
429
+ ```javascript
430
+ const response = await client.getMonsterTypes({
431
+ type_name: "boss",
170
432
  });
433
+
434
+ if (response.ok) {
435
+ console.log(response.data);
436
+ // {
437
+ // id: 3,
438
+ // name: { fr: "Boss", en: "Boss", es: "Boss" }
439
+ // }
440
+ }
171
441
  ```
172
442
 
173
443
  ---
174
444
 
175
- ### 📊 Structure de réponse
445
+ ### Modèles de quête
176
446
 
177
- Toutes les méthodes retournent un objet standardisé :
447
+ Récupérer les modèles de quête avec la liste des monstres à capturer par étape.
448
+
449
+ #### Signature
178
450
 
179
451
  ```javascript
180
- {
181
- ok: boolean, // Succès de la requête
182
- status: number, // Code de statut HTTP
183
- statusText: string, // Message de statut
184
- retryAfter?: number, // Délai avant retry (si 429)
185
- errors?: string[], // Erreurs éventuelles
186
- data?: any // Données de réponse
452
+ getQuestTemplates(options?: {
453
+ game_name?: string,
454
+ step?: number,
455
+ limit?: number,
456
+ offset?: number
457
+ })
458
+ ```
459
+
460
+ #### Types
461
+
462
+ ```javascript
463
+ /**
464
+ * @typedef {object} QuestTemplate
465
+ * @property {number} id - Identifiant
466
+ * @property {GameVersion} game_version - Version du jeu
467
+ * @property {number} monster_count - Nombre total de monstres
468
+ * @property {number} step_count - Nombre d'étapes
469
+ *
470
+ * @typedef {object} QuestTemplateDetail
471
+ * @property {number} id - Identifiant
472
+ * @property {GameVersion} game_version - Version du jeu
473
+ * @property {Array} monsters - Monstres avec leur étape
474
+ * @property {Pagination} pagination - Infos de pagination
475
+ */
476
+ ```
477
+
478
+ #### Exemples
479
+
480
+ **Lister les modèles de quête**
481
+
482
+ ```javascript
483
+ const response = await client.getQuestTemplates();
484
+
485
+ if (response.ok) {
486
+ console.log(`Modèles trouvés: ${response.pagination.total}`);
487
+ response.data.forEach((template) => {
488
+ console.log(
489
+ `${template.game_version.name}: ${template.monster_count} monstres en ${template.step_count} étapes`,
490
+ );
491
+ });
492
+ }
493
+ ```
494
+
495
+ **Récupérer les monstres d'une étape spécifique**
496
+
497
+ ```javascript
498
+ const response = await client.getQuestTemplates({
499
+ game_name: "Dofus (Unity)",
500
+ step: 1,
501
+ limit: 50,
502
+ });
503
+
504
+ if (response.ok) {
505
+ console.log(`Étape 1 - Monstres à capturer:`);
506
+ response.data.monsters.forEach((monster) => {
507
+ console.log(`- ${monster.name.fr} (étape ${monster.step})`);
508
+ });
509
+ }
510
+ ```
511
+
512
+ **Pagination**
513
+
514
+ ```javascript
515
+ const response = await client.getQuestTemplates({
516
+ game_name: "Dofus (Unity)",
517
+ step: 1,
518
+ limit: 10,
519
+ offset: 20, // Sauter les 20 premiers résultats
520
+ });
521
+
522
+ if (response.ok) {
523
+ console.log(`Résultats 21-30 sur ${response.pagination.total}`);
187
524
  }
188
525
  ```
189
526
 
190
527
  ---
191
528
 
192
- ## Optimisations avancées
529
+ ### Recherche d'utilisateurs
530
+
531
+ Rechercher des utilisateurs ayant des quêtes publiques.
532
+
533
+ #### Signature
534
+
535
+ ```javascript
536
+ searchUsers(
537
+ query: string,
538
+ options?: {
539
+ server_name?: string,
540
+ active_within_days?: number,
541
+ limit?: number,
542
+ offset?: number
543
+ }
544
+ )
545
+ ```
546
+
547
+ #### Paramètres
548
+
549
+ | Paramètre | Requis | Type | Description |
550
+ | -------------------- | ------ | ------ | ------------------------------------------------------- |
551
+ | `query` | ✅ | string | Terme de recherche (min. 3 caractères) |
552
+ | `server_name` | ❌ | string | Filtrer par serveur |
553
+ | `active_within_days` | ❌ | number | Actifs dans les N derniers jours (défaut: 90, max: 365) |
554
+ | `limit` | ❌ | number | Nombre de résultats (défaut: 20, max: 50) |
555
+ | `offset` | ❌ | number | Décalage pour pagination (défaut: 0) |
556
+
557
+ #### Types
558
+
559
+ ```javascript
560
+ /**
561
+ * @typedef {object} UserAvatar
562
+ * @property {number} id - Identifiant de l'avatar
563
+ * @property {object} name - Nom multilingue
564
+ * @property {string} image - URL de l'image
565
+ *
566
+ * @typedef {object} Search
567
+ * @property {string} username - Nom d'utilisateur
568
+ * @property {UserAvatar} avatar - Avatar utilisateur
569
+ * @property {string} last_active - Dernière activité (ISO 8601)
570
+ */
571
+ ```
572
+
573
+ #### Exemples
193
574
 
194
- ### 🚀 Cache Strategy
575
+ **Recherche basique**
195
576
 
196
577
  ```javascript
197
- // Préférez toujours le cache pour les données statiques
198
- const servers = client.cache.servers; // ✅ Instantané
199
- const servers = await client.getServers(); // ❌ Plus lent
578
+ const response = await client.searchUsers("jean");
579
+
580
+ if (!response.ok) {
581
+ return console.error(response.error);
582
+ }
200
583
 
201
- // Le cache se met à jour automatiquement si nécessaire
584
+ response.data.forEach((user) => {
585
+ console.log(`${user.username} (${user.avatar.name.fr})`);
586
+ });
202
587
  ```
203
588
 
204
- ### 🔄 Rate Limiting
589
+ **Filtrer par serveur et activité**
205
590
 
206
- Le SDK gère automatiquement :
207
- - **Détection du rate limiting** (429)
208
- - **Retry automatique** avec backoff
209
- - **Headers de retry** respectés
591
+ ```javascript
592
+ const response = await client.searchUsers("jean", {
593
+ server_name: "Brial",
594
+ active_within_days: 30, // Actifs dans les 30 derniers jours
595
+ limit: 10,
596
+ });
597
+
598
+ if (response.ok) {
599
+ console.log(`${response.pagination.total} utilisateurs trouvés`);
600
+ response.data.forEach((user) => {
601
+ console.log(`- ${user.username} (dernière activité: ${user.last_active})`);
602
+ });
603
+ }
604
+ ```
605
+
606
+ **Pagination avancée**
607
+
608
+ ```javascript
609
+ async function searchAllUsers(query, pageSize = 50) {
610
+ let allResults = [];
611
+ let offset = 0;
612
+ let hasMore = true;
613
+
614
+ while (hasMore) {
615
+ const response = await client.searchUsers(query, {
616
+ limit: pageSize,
617
+ offset,
618
+ });
619
+
620
+ if (!response.ok) break;
621
+
622
+ allResults.push(...response.data);
623
+ hasMore =
624
+ response.pagination.offset + response.pagination.limit <
625
+ response.pagination.total;
626
+ offset += pageSize;
627
+ }
628
+
629
+ return allResults;
630
+ }
631
+ ```
210
632
 
211
633
  ---
212
634
 
213
- ## 🛠️ Configuration avancée
635
+ ### Profils utilisateurs
636
+
637
+ Récupérer le profil détaillé d'un utilisateur.
214
638
 
215
- ### 📁 Structure des fichiers cache
639
+ #### Signature
216
640
 
641
+ ```javascript
642
+ getUser(username: string)
217
643
  ```
218
- .cache/
219
- ├── $.js # Index des caches
220
- ├── servers.json # Serveurs
221
- ├── monsters.json # Monstres
222
- ├── areas.json # Zones
223
- └── subareas.json # Sous-zones
644
+
645
+ #### Types
646
+
647
+ ```javascript
648
+ /**
649
+ * @typedef {object} User
650
+ * @property {string} username - Nom d'utilisateur
651
+ * @property {string} bio - Biographie de l'utilisateur
652
+ * @property {UserAvatar} avatar - Avatar utilisateur
653
+ * @property {string} created_at - Date de création du compte (ISO 8601)
654
+ * @property {string} last_active - Dernière activité (ISO 8601)
655
+ */
224
656
  ```
225
657
 
226
- ### 🔧 Personnalisation
658
+ #### Exemples
227
659
 
228
- Le cache utilise :
229
- - **write-file-atomic** pour l'écriture sécurisée
230
- - **Formatage JSON** avec indentation (4 espaces)
231
- - **Rechargement automatique** du cache Node.js
660
+ **Récupérer un profil**
232
661
 
233
- ---
662
+ ```javascript
663
+ const response = await client.getUser("ix-xs");
234
664
 
235
- ## 🏆 Contributeurs & Support
665
+ if (!response.ok) {
666
+ return console.error(`Utilisateur non trouvé: ${response.error}`);
667
+ }
236
668
 
237
- <div align="center">
669
+ const user = response.data;
670
+ console.log(`
671
+ ${user.username}
672
+ Avatar: ${user.avatar.name.fr}
673
+ Bio: ${user.bio || "Pas de bio"}
674
+ Compte créé: ${new Date(user.created_at).toLocaleDateString("fr-FR")}
675
+ Dernière activité: ${new Date(user.last_active).toLocaleDateString("fr-FR")}
676
+ `);
677
+ ```
238
678
 
239
- ### 👨‍💻 Créateur
679
+ **Vérifier l'activité d'un utilisateur**
240
680
 
241
- <img src="https://cdn.discordapp.com/avatars/782307250751406091/a_3f71f1ac5e1664038fdf33c2c408482e.gif" style="border-radius:0.5rem; width:5rem; height:auto">
681
+ ```javascript
682
+ const response = await client.getUser("jean");
242
683
 
243
- **Ix-xs**
244
- *Développeur auto-didacte & Passionné Dofus*
684
+ if (response.ok) {
685
+ const user = response.data;
686
+ const daysSinceActive = Math.floor(
687
+ (Date.now() - new Date(user.last_active)) / (1000 * 60 * 60 * 24),
688
+ );
245
689
 
246
- [![Discord](https://img.shields.io/badge/Discord-5865F2?style=for-the-badge&logo=discord&logoColor=white)](https://discord.gg/user/ix-xs)
247
- [![GitHub](https://img.shields.io/badge/GitHub-181717?style=for-the-badge&logo=github&logoColor=white)](https://github.com/ix-xs)
690
+ console.log(`${user.username} a été actif il y a ${daysSinceActive} jours`);
691
+ }
692
+ ```
248
693
 
249
694
  ---
250
695
 
251
- ### 💬 Besoin d'aide ?
696
+ ### Quêtes utilisateurs
252
697
 
253
- - 🐛 **Issues** : [GitHub Issues](https://github.com/ix-xs/metamob.api/issues)
254
- - 💬 **Discord** : `Ix-xs` - Contact direct
698
+ Récupérer la liste des quêtes publiques d'un utilisateur.
255
699
 
256
- </div>
700
+ #### Signature
257
701
 
258
- ---
702
+ ```javascript
703
+ getUserQuests(username: string)
704
+ ```
259
705
 
260
- <div align="center">
706
+ #### Types
707
+
708
+ ```javascript
709
+ /**
710
+ * @typedef {object} Quest
711
+ * @property {string} slug - Identifiant unique de la quête
712
+ * @property {string} character_name - Nom du personnage Dofus
713
+ * @property {number} current_step - Étape actuelle de la quête
714
+ * @property {number} parallel_quests - Nombre de quêtes parallèles
715
+ * @property {number} wanted_count - Nombre de monstres recherchés
716
+ * @property {number} offered_count - Nombre de monstres proposés
717
+ * @property {Server} server - Serveur du personnage
718
+ * @property {QuestTemplate} quest_template - Modèle de quête
719
+ */
720
+ ```
721
+
722
+ #### Exemples
723
+
724
+ **Lister les quêtes d'un utilisateur**
725
+
726
+ ```javascript
727
+ const response = await client.getUserQuests("ix-xs");
261
728
 
262
- **🌟 Si ce projet vous aide, n'hésitez pas à lui donner une étoile !**
729
+ if (!response.ok) {
730
+ return console.error(response.error);
731
+ }
732
+
733
+ response.data.forEach((quest) => {
734
+ console.log(`
735
+ Personnage: ${quest.character_name}
736
+ Serveur: ${quest.server.name}
737
+ Étape: ${quest.current_step}/${quest.quest_template.step_count}
738
+ Recherche: ${quest.wanted_count} / Proposé: ${quest.offered_count}
739
+ `);
740
+ });
741
+ ```
742
+
743
+ **Analyser la progression de quête**
744
+
745
+ ```javascript
746
+ const response = await client.getUserQuests("jean");
747
+
748
+ if (response.ok) {
749
+ response.data.forEach((quest) => {
750
+ const progression = Math.floor(
751
+ (quest.current_step / quest.quest_template.step_count) * 100,
752
+ );
753
+
754
+ console.log(`
755
+ ${quest.character_name}: ${progression}% complété
756
+ Étape ${quest.current_step}/${quest.quest_template.step_count}
757
+ Progression: ${"█".repeat(Math.floor(progression / 5))}${"░".repeat(20 - Math.floor(progression / 5))}
758
+ `);
759
+ });
760
+ }
761
+ ```
762
+
763
+ **Trouver des fournisseurs de monstres**
764
+
765
+ ```javascript
766
+ const response = await client.getUserQuests("jean");
767
+
768
+ if (response.ok) {
769
+ const providers = response.data.filter((quest) => quest.offered_count > 0);
263
770
 
264
- [![Star on GitHub](https://img.shields.io/github/stars/ix-xs/metamob.api.svg?style=social)](https://github.com/ix-xs/metamob.api/stargazers)
771
+ console.log(
772
+ `${quest.character_name} propose ${quest.offered_count} monstres`,
773
+ );
774
+ }
775
+ ```
776
+
777
+ ## 🔗 Ressources
778
+
779
+ - 🌐 [Site Metamob](https://beta.metamob.fr)
780
+ - 📖 [Documentation API Officielle](https://beta.metamob.fr/help/api)
781
+ - 📦 [Package NPM](https://www.npmjs.com/package/@ix-xs/metamob.api)
782
+ - 🔧 [GitHub Repository](https://github.com/ix-xs/metamob.api)
783
+ - 💬 [Discord Community](https://discord.gg/SadWCNf2pk)
784
+
785
+ ## 🐛 Signaler un bug
786
+
787
+ Avez-vous trouvé un bug ? Créez une issue sur GitHub :
788
+
789
+ 👉 [GitHub Issues](https://github.com/ix-xs/metamob.api/issues)
265
790
 
266
- *Développé avec ❤️ pour la communauté Dofus*
791
+ ## 👨‍💼 Auteur
792
+
793
+ ![ix-xs](https://cdn.discordapp.com/avatars/782307250751406091/a_3f71f1ac5e1664038fdf33c2c408482e.gif?size=48) **ix-xs**
267
794
 
268
795
  ---
269
796
 
270
- **⚡ Propulsé par l'API Metamob | Optimisé pour la performance | Conçu pour les développeurs**
797
+ <div align="center">
798
+
799
+ **Fait avec ❤️ pour la communauté Dofus**
271
800
 
272
- </div>
801
+ ⭐ N'oubliez pas de mettre une star si ce projet vous a aidé !
802
+
803
+ [GitHub](https://github.com/ix-xs/metamob.api) • [NPM](https://www.npmjs.com/package/@ix-xs/metamob.api) • [Site Metamob](https://beta.metamob.fr)
804
+
805
+ </div>