@unavatar/core 3.46.13 → 3.46.16

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
@@ -100,7 +100,7 @@
100
100
 
101
101
  ---
102
102
 
103
- Last updated on July 2, 2026
103
+ Last updated on August 18, 2026
104
104
 
105
105
  ![logo](https://unavatar.io/api/og ":id=banner")
106
106
 
@@ -293,7 +293,7 @@ Rate limit status can be verified using these response headers:
293
293
  | `x-rate-limit-reset` | UTC epoch seconds when the current window resets |
294
294
 
295
295
  ```bash
296
- $curl-Ihttps://unavatar.io/github/kikobeats
296
+ curl-Ihttps://unavatar.io/github/kikobeats
297
297
 
298
298
  x-rate-limit-limit:25
299
299
 
@@ -435,7 +435,7 @@ Every request has a cost in tokens (**\$0.010 per token**) based on the proxy ti
435
435
  The proxy tier used is returned in the `x-proxy-tier` response header, and the total cost in the `x-unavatar-cost` header.
436
436
 
437
437
  ```bash
438
- $curl-I-H"x-api-key: sk_YOUR_SECRET_KEY"https://unavatar.io/instagram/kikobeats
438
+ curl-I-H"x-api-key: sk_YOUR_SECRET_KEY"https://unavatar.io/instagram/kikobeats
439
439
 
440
440
  x-pricing-tier:pro
441
441
 
@@ -471,7 +471,7 @@ To check the cache status in real requests, inspect these response headers:
471
471
  | `cache-control` | Shows cache policy and effective TTL (for example `public, max-age=3600` for `ttl=1h`). |
472
472
 
473
473
  ```bash
474
- $curl-I-H"x-api-key: sk_YOUR_SECRET_KEY""https://unavatar.io/github/kikobeats?ttl=1h"
474
+ curl-I-H"x-api-key: sk_YOUR_SECRET_KEY""https://unavatar.io/github/kikobeats?ttl=1h"
475
475
 
476
476
  cache-control:public,max-age=3600
477
477
 
@@ -1172,7 +1172,7 @@ These headers help you understand pricing, limits, and request diagnostics.
1172
1172
  | `retry-after` | Seconds until rate limit resets (only on 429 responses) |
1173
1173
 
1174
1174
  ```bash
1175
- $curl-I-H"x-api-key: sk_YOUR_SECRET_KEY"https://unavatar.io/github/kikobeats
1175
+ curl-I-H"x-api-key: sk_YOUR_SECRET_KEY"https://unavatar.io/github/kikobeats
1176
1176
 
1177
1177
  x-pricing-tier:pro
1178
1178
 
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@unavatar/core",
3
3
  "description": "Get unified user avatar from social networks, including Instagram, SoundCloud, Telegram, Twitter, YouTube & more.",
4
4
  "homepage": "https://unavatar.io",
5
- "version": "3.46.13",
5
+ "version": "3.46.16",
6
6
  "main": "src/index.js",
7
7
  "exports": {
8
8
  ".": "./src/index.js",
@@ -125,26 +125,26 @@
125
125
  "@keyvhq/multi": "~2.2.6",
126
126
  "@keyvhq/offline": "~2.2.0",
127
127
  "@keyvhq/redis": "~2.2.3",
128
- "@metascraper/helpers": "~5.55.0",
128
+ "@metascraper/helpers": "~5.56.2",
129
129
  "@microlink/mql": "~0.18.0",
130
130
  "@microlink/ping-url": "~1.5.0",
131
131
  "bimi-url": "~1.0.0",
132
- "browserless": "~13.7.1",
132
+ "browserless": "~13.8.0",
133
133
  "cacheable-lookup": "~6.1.0",
134
134
  "data-uri-regex": "~0.1.4",
135
135
  "debug-logfmt": "~1.4.10",
136
136
  "got": "~11.8.6",
137
- "html-get": "~2.26.0",
137
+ "html-get": "~2.27.0",
138
138
  "https-tls": "~1.0.24",
139
139
  "ipaddr.js": "~2.5.0",
140
140
  "is-absolute-url": "~3.0.3",
141
- "is-antibot": "~2.3.0",
141
+ "is-antibot": "~2.5.0",
142
142
  "is-email-like": "~1.0.0",
143
143
  "lodash": "~4.18.1",
144
144
  "ms": "~2.1.3",
145
145
  "p-any": "~3.0.0",
146
146
  "p-timeout": "~4.1.0",
147
- "puppeteer": "~25.7.0",
147
+ "puppeteer": "~25.8.0",
148
148
  "re2": "~1.26.0",
149
149
  "srcset": "~4.0.0",
150
150
  "stable-regex": "~1.0.1",
@@ -162,7 +162,8 @@
162
162
  "c8": "latest",
163
163
  "cheerio": "latest",
164
164
  "ci-publish": "latest",
165
- "conventional-changelog-cli": "latest",
165
+ "conventional-changelog": "latest",
166
+ "conventional-changelog-conventionalcommits": "latest",
166
167
  "finepack": "latest",
167
168
  "git-authors-cli": "latest",
168
169
  "github-generate-release": "latest",
@@ -186,7 +187,7 @@
186
187
  "contributors": "(git-authors-cli && finepack && git add package.json && git commit -m 'build: contributors' --no-verify) || true",
187
188
  "postrelease": "pnpm release:tags && pnpm release:github && (ci-publish || pnpm publish --access=public)",
188
189
  "release": "pnpm release:version && pnpm release:changelog && pnpm release:commit && pnpm release:tag",
189
- "release:changelog": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s",
190
+ "release:changelog": "conventional-changelog -p conventionalcommits -i CHANGELOG.md",
190
191
  "release:commit": "git add package.json CHANGELOG.md && git commit -m \"chore(release): $(node -p \"require('./package.json').version\")\"",
191
192
  "release:github": "github-generate-release",
192
193
  "release:tag": "git tag -a v$(node -p \"require('./package.json').version\") -m \"v$(node -p \"require('./package.json').version\")\"",
@@ -1,13 +1,50 @@
1
1
  'use strict'
2
2
 
3
- const getAvatarUrl = input =>
4
- `https://www.printables.com/${input.startsWith('@') ? input : `@${input}`}`
3
+ const API_URL = 'https://api.printables.com/graphql/'
4
+ const MEDIA_URL = 'https://media.printables.com'
5
5
 
6
- module.exports = ({ createHtmlProvider, getOgImage }) =>
7
- createHtmlProvider({
8
- name: 'printables',
9
- url: getAvatarUrl,
10
- getter: getOgImage
11
- })
6
+ const SEARCH_QUERY = `query SearchUsers($query: String!) {
7
+ result: searchUsers2(query: $query, limit: 10) {
8
+ items { handle avatarFilePath }
9
+ }
10
+ }`
12
11
 
13
- module.exports.getAvatarUrl = getAvatarUrl
12
+ const normalizeHandle = input =>
13
+ String(input || '')
14
+ .trim()
15
+ .replace(/^@/, '')
16
+ .trim()
17
+
18
+ const getAvatar = (body, handle) => {
19
+ const items = body?.data?.result?.items
20
+ if (!Array.isArray(items) || !handle) return
21
+
22
+ const user = items.find(
23
+ item => String(item?.handle || '').toLowerCase() === handle.toLowerCase()
24
+ )
25
+ const path = user?.avatarFilePath
26
+ if (!path) return
27
+
28
+ return `${MEDIA_URL}/${path.replace(/^\//, '')}`
29
+ }
30
+
31
+ module.exports = ({ got }) =>
32
+ async function printables (input) {
33
+ const handle = normalizeHandle(input)
34
+ if (!handle) return
35
+
36
+ const { body, statusCode } = await got(API_URL, {
37
+ method: 'POST',
38
+ responseType: 'json',
39
+ throwHttpErrors: false,
40
+ json: { query: SEARCH_QUERY, variables: { query: handle } },
41
+ headers: { origin: 'https://www.printables.com' }
42
+ })
43
+
44
+ if (statusCode >= 400) return
45
+
46
+ return getAvatar(body, handle)
47
+ }
48
+
49
+ module.exports.getAvatar = getAvatar
50
+ module.exports.normalizeHandle = normalizeHandle
@@ -7,18 +7,20 @@ const unbracket = hostname =>
7
7
  ? hostname.slice(1, -1)
8
8
  : hostname
9
9
 
10
+ const isReservedAddress = address => ip.process(address).range() !== 'unicast'
11
+
10
12
  module.exports = ({ cacheableLookup }) => {
11
- const getIpAddress = async hostname => {
12
- if (ip.IPv4.isIPv4(hostname)) return hostname
13
+ const getIpAddresses = async hostname => {
14
+ if (ip.IPv4.isIPv4(hostname)) return [hostname]
13
15
  const literal = unbracket(hostname)
14
- if (ip.IPv6.isIPv6(literal)) return literal
15
- const { address } = await cacheableLookup.lookupAsync(hostname)
16
- return address
16
+ if (ip.IPv6.isIPv6(literal)) return [literal]
17
+ const result = await cacheableLookup.lookupAsync(hostname, { all: true })
18
+ return result.map(entry => entry.address)
17
19
  }
18
20
 
19
21
  return async hostname => {
20
- const ipAddress = await getIpAddress(hostname)
21
- return ip.process(ipAddress).range() !== 'unicast'
22
+ const addresses = await getIpAddresses(hostname)
23
+ return addresses.some(isReservedAddress)
22
24
  }
23
25
  }
24
26