furtrack-api 1.0.1 → 1.1.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
@@ -2,6 +2,8 @@
2
2
 
3
3
  An unofficial Node.js package for accessing the Furtrack API.
4
4
 
5
+ > ⚠️ **Warning**: This package was built by **reverse engineering the FurTrack frontend**, and it is a **best-effort implementation**. FurTrack's internal API may change at any time, which can cause this package to break or behave unexpectedly.
6
+
5
7
 
6
8
  ## Features
7
9
 
@@ -75,6 +77,11 @@ api.getAlbum('username', 'albumid').then(album => {
75
77
  console.log(album)
76
78
  })
77
79
 
80
+ // Fetch all tags
81
+ api.getTags().then(tags => {
82
+ console.log(tags);
83
+ })
84
+
78
85
  ```
79
86
 
80
87
  Functions which return a list of arrays additional support a page argument, FurTrack generally paginates albums longer than 200 images, by default only the first page is retrieved.
@@ -94,4 +101,4 @@ const characters = FurtrackAPI.getTagsByType(tags, FurtrackAPI.TagTypes.Characte
94
101
 
95
102
  ---
96
103
 
97
- MIT License © 2025 blumlaut
104
+ MIT License © 2025 blumlaut
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "furtrack-api",
3
- "version": "1.0.1",
3
+ "version": "1.1.0",
4
4
  "description": "An inofficial package for accessing the Furtrack API.",
5
5
  "main": "src/index.js",
6
6
  "scripts": {
package/src/index.js CHANGED
@@ -29,6 +29,9 @@ const https = require('https');
29
29
  * @param {Object} [options] - Additional fetch options.
30
30
  * @returns {Promise<Object>} The parsed JSON response.
31
31
  *
32
+ * @method getTags Fetches all tags from FurTrack.
33
+ * @returns {Promise<Object>} Tags data with success flag and tags array.
34
+ *
32
35
  * @method getTag Fetches information about a specific tag.
33
36
  * @param {string} tag - The tag to fetch.
34
37
  * @returns {Promise<Object>} Tag information.
@@ -116,7 +119,7 @@ class FurtrackAPI {
116
119
  '2:': this.TagTypes.Maker,
117
120
  '3:': this.TagTypes.Photographer,
118
121
  '5:': this.TagTypes.Event,
119
- '6': this.TagTypes.Species,
122
+ '6:': this.TagTypes.Species,
120
123
 
121
124
  };
122
125
 
@@ -142,6 +145,10 @@ class FurtrackAPI {
142
145
  return res.json();
143
146
  }
144
147
 
148
+ getTags() {
149
+ return this.fetchJSON(`/get/tags/all`);
150
+ }
151
+
145
152
  getTag(tag) {
146
153
  return this.fetchJSON(`/get/index/${encodeURIComponent(tag)}`);
147
154
  }
@@ -155,7 +162,7 @@ class FurtrackAPI {
155
162
  }
156
163
 
157
164
  async getPostsByTag(tag, page = 0) {
158
- const response = await this.fetchJSON(`/get/tag/${encodeURIComponent(tag)}${page > 0 ? `/${page}` : ''}`);
165
+ const response = await this.fetchJSON(`/view/index/${encodeURIComponent(tag)}${page > 0 ? `/${page}` : ''}`);
159
166
  return response.posts || [];
160
167
  }
161
168
 
@@ -195,13 +202,78 @@ class FurtrackAPI {
195
202
  }
196
203
 
197
204
 
198
- static getTagsByType(tags, type) {
205
+ static getTagsByType(tags, type) {
199
206
  return tags
200
207
  .map(tag => this.parseTag(tag.tagName))
201
208
  .filter(parsed => parsed.type === type)
202
209
  .map(parsed => parsed.value);
203
210
  }
204
211
 
212
+ /**
213
+ * Fetches all character tags associated with a maker tag.
214
+ * Returns the full character metadata including tag counts and followers.
215
+ *
216
+ * @param {string} makerTag - The maker tag (e.g., "wild_dog_works" or "maker:wild_dog_works").
217
+ * @returns {Promise<Array>} Array of character tag objects with metadata.
218
+ *
219
+ * @example
220
+ * const characters = await api.getCharactersByMaker('wild_dog_works');
221
+ * // Returns: [{ tagName: '1:colby_(husky)', tagType: 1, tagTitle: 'Colby', ... }, ...]
222
+ */
223
+ async getCharactersByMaker(makerTag) {
224
+ // Normalize tag format
225
+ if (!makerTag.startsWith('2:')) {
226
+ makerTag = `2:${makerTag}`;
227
+ }
228
+ const tagData = await this.getTag(makerTag.replace('2:', 'maker:'));
229
+ return tagData.tagmeta?.tagChildrenFull || [];
230
+ }
231
+
232
+ /**
233
+ * Fetches all related tags for a character, including makers, species, and color tags.
234
+ *
235
+ * @param {string} characterTag - The character tag (e.g., "colby_(husky)" or "character:colby_(husky)").
236
+ * @returns {Promise<Object>} Object with categorized related tags.
237
+ * @returns {Promise<Object>.makers} Array of maker tag values.
238
+ * @returns {Promise<Object>.species} Array of species tag values.
239
+ * @returns {Promise<Object>.colors} Array of color/general tag values.
240
+ * @returns {Promise<Object>.all} Array of all related tag names.
241
+ *
242
+ * @example
243
+ * const related = await api.getRelatedTagsByCharacter('colby_(husky)');
244
+ * // Returns: { makers: ['wild_dog_works', 'pyrope_costumes'], species: ['husky'], colors: ['black', 'blue', ...], all: [...] }
245
+ */
246
+ async getRelatedTagsByCharacter(characterTag) {
247
+ // Normalize tag format
248
+ if (!characterTag.startsWith('1:')) {
249
+ characterTag = `1:${characterTag}`;
250
+ }
251
+ const tagData = await this.getTag(characterTag.replace('1:', 'character:'));
252
+ const tagAlso = tagData.tagmeta?.tagAlso || [];
253
+
254
+ return {
255
+ makers: FurtrackAPI.getTagsByType(tagAlso.map(t => ({ tagName: t })), FurtrackAPI.TagTypes.Maker),
256
+ species: FurtrackAPI.getTagsByType(tagAlso.map(t => ({ tagName: t })), FurtrackAPI.TagTypes.Species),
257
+ colors: tagAlso.filter(t => !t.startsWith('1:') && !t.startsWith('2:') && !t.startsWith('3:') && !t.startsWith('5:') && !t.startsWith('6:')),
258
+ all: tagAlso
259
+ };
260
+ }
261
+
262
+ /**
263
+ * Fetches all makers associated with a character tag.
264
+ *
265
+ * @param {string} characterTag - The character tag (e.g., "colby_(husky)" or "character:colby_(husky)").
266
+ * @returns {Promise<Array>} Array of maker tag values.
267
+ *
268
+ * @example
269
+ * const makers = await api.getMakersByCharacter('colby_(husky)');
270
+ * // Returns: ['wild_dog_works', 'pyrope_costumes']
271
+ */
272
+ async getMakersByCharacter(characterTag) {
273
+ const related = await this.getRelatedTagsByCharacter(characterTag);
274
+ return related.makers;
275
+ }
276
+
205
277
  }
206
278
 
207
279
  module.exports = FurtrackAPI;
package/src/index.test.js CHANGED
@@ -50,7 +50,7 @@ describe('FurtrackAPI', () => {
50
50
  expect(result).toEqual({ type: FurtrackAPI.TagTypes.Event, value: 'SomeEvent' });
51
51
  });
52
52
  test('parses species tag', () => {
53
- const result = api.parseTag('6Wolf');
53
+ const result = api.parseTag('6:Wolf');
54
54
  expect(result).toEqual({ type: FurtrackAPI.TagTypes.Species, value: 'Wolf' });
55
55
  });
56
56
  test('parses general tag', () => {