stophy 0.3.0 → 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/README.md +60 -84
- package/dist/index.cjs +558 -334
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22667 -1403
- package/dist/index.d.ts +22667 -1403
- package/dist/index.js +558 -334
- package/dist/index.js.map +1 -1
- package/package.json +13 -10
package/dist/index.cjs
CHANGED
|
@@ -2,334 +2,599 @@
|
|
|
2
2
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
|
-
var clientFetch = require('@hey-api/client-fetch');
|
|
6
|
-
|
|
7
|
-
// src/generated/client.gen.ts
|
|
8
|
-
var client = clientFetch.createClient(
|
|
9
|
-
clientFetch.createConfig({
|
|
10
|
-
baseUrl: "https://api.stophy.dev"
|
|
11
|
-
})
|
|
12
|
-
);
|
|
13
|
-
|
|
14
|
-
// src/generated/sdk.gen.ts
|
|
15
|
-
var searchVideos = (options) => {
|
|
16
|
-
return (options.client ?? client).post({
|
|
17
|
-
security: [
|
|
18
|
-
{
|
|
19
|
-
scheme: "bearer",
|
|
20
|
-
type: "http"
|
|
21
|
-
}
|
|
22
|
-
],
|
|
23
|
-
url: "/v1/search",
|
|
24
|
-
...options,
|
|
25
|
-
headers: {
|
|
26
|
-
"Content-Type": "application/json",
|
|
27
|
-
...options?.headers
|
|
28
|
-
}
|
|
29
|
-
});
|
|
30
|
-
};
|
|
31
|
-
var getVideo = (options) => {
|
|
32
|
-
return (options.client ?? client).post({
|
|
33
|
-
security: [
|
|
34
|
-
{
|
|
35
|
-
scheme: "bearer",
|
|
36
|
-
type: "http"
|
|
37
|
-
}
|
|
38
|
-
],
|
|
39
|
-
url: "/v1/video",
|
|
40
|
-
...options,
|
|
41
|
-
headers: {
|
|
42
|
-
"Content-Type": "application/json",
|
|
43
|
-
...options?.headers
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
};
|
|
47
|
-
var getChannel = (options) => {
|
|
48
|
-
return (options.client ?? client).post({
|
|
49
|
-
security: [
|
|
50
|
-
{
|
|
51
|
-
scheme: "bearer",
|
|
52
|
-
type: "http"
|
|
53
|
-
}
|
|
54
|
-
],
|
|
55
|
-
url: "/v1/channel",
|
|
56
|
-
...options,
|
|
57
|
-
headers: {
|
|
58
|
-
"Content-Type": "application/json",
|
|
59
|
-
...options?.headers
|
|
60
|
-
}
|
|
61
|
-
});
|
|
62
|
-
};
|
|
63
|
-
var getPlaylist = (options) => {
|
|
64
|
-
return (options.client ?? client).post({
|
|
65
|
-
security: [
|
|
66
|
-
{
|
|
67
|
-
scheme: "bearer",
|
|
68
|
-
type: "http"
|
|
69
|
-
}
|
|
70
|
-
],
|
|
71
|
-
url: "/v1/playlist",
|
|
72
|
-
...options,
|
|
73
|
-
headers: {
|
|
74
|
-
"Content-Type": "application/json",
|
|
75
|
-
...options?.headers
|
|
76
|
-
}
|
|
77
|
-
});
|
|
78
|
-
};
|
|
79
|
-
var getSuggestions = (options) => {
|
|
80
|
-
return (options.client ?? client).post({
|
|
81
|
-
security: [
|
|
82
|
-
{
|
|
83
|
-
scheme: "bearer",
|
|
84
|
-
type: "http"
|
|
85
|
-
}
|
|
86
|
-
],
|
|
87
|
-
url: "/v1/suggest",
|
|
88
|
-
...options,
|
|
89
|
-
headers: {
|
|
90
|
-
"Content-Type": "application/json",
|
|
91
|
-
...options?.headers
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
};
|
|
95
|
-
var youtubeMusic = (options) => {
|
|
96
|
-
return (options.client ?? client).post({
|
|
97
|
-
security: [
|
|
98
|
-
{
|
|
99
|
-
scheme: "bearer",
|
|
100
|
-
type: "http"
|
|
101
|
-
}
|
|
102
|
-
],
|
|
103
|
-
url: "/v1/music",
|
|
104
|
-
...options,
|
|
105
|
-
headers: {
|
|
106
|
-
"Content-Type": "application/json",
|
|
107
|
-
...options?.headers
|
|
108
|
-
}
|
|
109
|
-
});
|
|
110
|
-
};
|
|
111
|
-
var youtubeKids = (options) => {
|
|
112
|
-
return (options.client ?? client).post({
|
|
113
|
-
security: [
|
|
114
|
-
{
|
|
115
|
-
scheme: "bearer",
|
|
116
|
-
type: "http"
|
|
117
|
-
}
|
|
118
|
-
],
|
|
119
|
-
url: "/v1/kids",
|
|
120
|
-
...options,
|
|
121
|
-
headers: {
|
|
122
|
-
"Content-Type": "application/json",
|
|
123
|
-
...options?.headers
|
|
124
|
-
}
|
|
125
|
-
});
|
|
126
|
-
};
|
|
127
|
-
var getCredits = (options) => {
|
|
128
|
-
return (options?.client ?? client).get({
|
|
129
|
-
security: [
|
|
130
|
-
{
|
|
131
|
-
scheme: "bearer",
|
|
132
|
-
type: "http"
|
|
133
|
-
}
|
|
134
|
-
],
|
|
135
|
-
url: "/v1/credits",
|
|
136
|
-
...options
|
|
137
|
-
});
|
|
138
|
-
};
|
|
139
|
-
var getUsage = (options) => {
|
|
140
|
-
return (options?.client ?? client).get({
|
|
141
|
-
security: [
|
|
142
|
-
{
|
|
143
|
-
scheme: "bearer",
|
|
144
|
-
type: "http"
|
|
145
|
-
}
|
|
146
|
-
],
|
|
147
|
-
url: "/v1/usage",
|
|
148
|
-
...options
|
|
149
|
-
});
|
|
150
|
-
};
|
|
151
|
-
var getLogs = (options) => {
|
|
152
|
-
return (options?.client ?? client).get({
|
|
153
|
-
security: [
|
|
154
|
-
{
|
|
155
|
-
scheme: "bearer",
|
|
156
|
-
type: "http"
|
|
157
|
-
}
|
|
158
|
-
],
|
|
159
|
-
url: "/v1/logs",
|
|
160
|
-
...options
|
|
161
|
-
});
|
|
162
|
-
};
|
|
163
|
-
|
|
164
5
|
// src/errors.ts
|
|
165
6
|
var StophyError = class extends Error {
|
|
166
7
|
code;
|
|
8
|
+
retryable;
|
|
9
|
+
retryAfterSeconds;
|
|
167
10
|
status;
|
|
168
11
|
requestId;
|
|
169
|
-
details;
|
|
170
12
|
constructor(message, options) {
|
|
171
13
|
super(message);
|
|
172
14
|
this.name = "StophyError";
|
|
173
15
|
this.status = options.status;
|
|
174
16
|
this.code = options.code;
|
|
17
|
+
this.retryable = options.retryable;
|
|
18
|
+
this.retryAfterSeconds = options.retryAfterSeconds;
|
|
175
19
|
this.requestId = options.requestId;
|
|
176
|
-
this.details = options.details;
|
|
177
20
|
}
|
|
178
21
|
};
|
|
179
22
|
|
|
180
|
-
// src/
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
options.maxRetries ?? 2,
|
|
193
|
-
options.retryInitialDelayMs ?? 500
|
|
194
|
-
)
|
|
195
|
-
})
|
|
23
|
+
// src/account.ts
|
|
24
|
+
function usage(call) {
|
|
25
|
+
return call({ method: "GET", path: "/v1/usage" }).then(parseUsage);
|
|
26
|
+
}
|
|
27
|
+
function logs(call, query) {
|
|
28
|
+
const params = {};
|
|
29
|
+
if (query?.apiKeyId !== void 0) params.apiKeyId = query.apiKeyId;
|
|
30
|
+
if (query?.days !== void 0) params.days = query.days;
|
|
31
|
+
if (query?.endpoint !== void 0) params.endpoint = query.endpoint;
|
|
32
|
+
if (query?.page !== void 0) params.page = query.page;
|
|
33
|
+
return call({ method: "GET", path: "/v1/logs", query: params }).then(
|
|
34
|
+
parseLogs
|
|
196
35
|
);
|
|
197
36
|
}
|
|
198
|
-
function
|
|
199
|
-
if (
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
37
|
+
function parseUsage(value) {
|
|
38
|
+
if (!isRecord(value)) return unexpected("usage");
|
|
39
|
+
const balanceMicros = numberField(value, "balanceMicros");
|
|
40
|
+
const creditsUsed = numberField(value, "creditsUsed");
|
|
41
|
+
const requestCount = numberField(value, "requestCount");
|
|
42
|
+
return { balanceMicros, creditsUsed, requestCount };
|
|
43
|
+
}
|
|
44
|
+
function parseLogs(value) {
|
|
45
|
+
if (!isRecord(value) || !Array.isArray(value.logs) || !Array.isArray(value.endpoints)) {
|
|
46
|
+
return unexpected("logs");
|
|
47
|
+
}
|
|
48
|
+
return {
|
|
49
|
+
endpoints: value.endpoints.map((item) => {
|
|
50
|
+
if (typeof item !== "string") return unexpected("logs.endpoints");
|
|
51
|
+
return item;
|
|
52
|
+
}),
|
|
53
|
+
logs: value.logs.map(parseLog),
|
|
54
|
+
page: numberField(value, "page"),
|
|
55
|
+
pageSize: numberField(value, "pageSize"),
|
|
56
|
+
total: numberField(value, "total"),
|
|
57
|
+
totalPages: numberField(value, "totalPages")
|
|
217
58
|
};
|
|
218
59
|
}
|
|
219
|
-
function
|
|
220
|
-
|
|
221
|
-
return
|
|
60
|
+
function parseLog(value) {
|
|
61
|
+
if (!isRecord(value)) return unexpected("logs.logs");
|
|
62
|
+
return {
|
|
63
|
+
apiKeyId: stringOrNull(value, "apiKeyId"),
|
|
64
|
+
apiKeyName: stringOrNull(value, "apiKeyName"),
|
|
65
|
+
createdAt: stringField(value, "createdAt"),
|
|
66
|
+
credits: numberField(value, "credits"),
|
|
67
|
+
durationMs: numberOrNull(value, "durationMs"),
|
|
68
|
+
endpoint: stringField(value, "endpoint"),
|
|
69
|
+
id: stringField(value, "id"),
|
|
70
|
+
method: stringField(value, "method"),
|
|
71
|
+
response: stringField(value, "response"),
|
|
72
|
+
status: numberField(value, "status")
|
|
73
|
+
};
|
|
222
74
|
}
|
|
223
|
-
function
|
|
224
|
-
const
|
|
225
|
-
if (
|
|
226
|
-
|
|
227
|
-
if (!Number.isNaN(seconds)) return seconds * 1e3;
|
|
228
|
-
const date = Date.parse(header);
|
|
229
|
-
return Number.isNaN(date) ? null : Math.max(0, date - Date.now());
|
|
75
|
+
function numberField(record, field) {
|
|
76
|
+
const value = record[field];
|
|
77
|
+
if (typeof value !== "number") return unexpected(field);
|
|
78
|
+
return value;
|
|
230
79
|
}
|
|
231
|
-
function
|
|
232
|
-
|
|
80
|
+
function numberOrNull(record, field) {
|
|
81
|
+
const value = record[field];
|
|
82
|
+
if (value === null) return null;
|
|
83
|
+
if (typeof value !== "number") return unexpected(field);
|
|
84
|
+
return value;
|
|
233
85
|
}
|
|
234
|
-
function
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
throw new StophyError(
|
|
239
|
-
error.error ?? `Stophy request failed with status ${result.response.status}`,
|
|
240
|
-
{
|
|
241
|
-
status: result.response.status,
|
|
242
|
-
code: error.code,
|
|
243
|
-
requestId: result.response.headers.get("x-request-id") ?? void 0,
|
|
244
|
-
details: error.details
|
|
245
|
-
}
|
|
246
|
-
);
|
|
86
|
+
function stringField(record, field) {
|
|
87
|
+
const value = record[field];
|
|
88
|
+
if (typeof value !== "string") return unexpected(field);
|
|
89
|
+
return value;
|
|
247
90
|
}
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
91
|
+
function stringOrNull(record, field) {
|
|
92
|
+
const value = record[field];
|
|
93
|
+
if (value === null) return null;
|
|
94
|
+
if (typeof value !== "string") return unexpected(field);
|
|
95
|
+
return value;
|
|
252
96
|
}
|
|
253
|
-
function
|
|
254
|
-
|
|
97
|
+
function unexpected(field) {
|
|
98
|
+
throw new StophyError(`Stophy returned an unexpected ${field}`, {
|
|
99
|
+
status: 200,
|
|
100
|
+
retryable: false
|
|
101
|
+
});
|
|
255
102
|
}
|
|
256
|
-
function
|
|
257
|
-
return
|
|
103
|
+
function isRecord(value) {
|
|
104
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
258
105
|
}
|
|
259
106
|
|
|
260
|
-
// src/
|
|
261
|
-
function
|
|
262
|
-
|
|
263
|
-
|
|
107
|
+
// src/bind.ts
|
|
108
|
+
function post(path, call) {
|
|
109
|
+
function run(body, options) {
|
|
110
|
+
return call({ method: "POST", path, body, options });
|
|
111
|
+
}
|
|
112
|
+
return run;
|
|
264
113
|
}
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
114
|
+
function postOptional(path, call) {
|
|
115
|
+
function run(body, options) {
|
|
116
|
+
if (isMarkdownOptions(body) && options === void 0) {
|
|
117
|
+
return call({ method: "POST", path, body: {}, options: body });
|
|
118
|
+
}
|
|
119
|
+
return call({ method: "POST", path, body: body ?? {}, options });
|
|
120
|
+
}
|
|
121
|
+
return run;
|
|
122
|
+
}
|
|
123
|
+
function get(path, call) {
|
|
124
|
+
function run(options) {
|
|
125
|
+
return call({ method: "GET", path, options });
|
|
126
|
+
}
|
|
127
|
+
return run;
|
|
128
|
+
}
|
|
129
|
+
function isMarkdownOptions(value) {
|
|
130
|
+
if (typeof value !== "object" || value === null) return false;
|
|
131
|
+
return "format" in value && value.format === "markdown";
|
|
269
132
|
}
|
|
270
133
|
|
|
271
|
-
// src/
|
|
272
|
-
function
|
|
273
|
-
return
|
|
134
|
+
// src/generated/surface.gen.ts
|
|
135
|
+
function bindSurface(call) {
|
|
136
|
+
return {
|
|
137
|
+
endpoints: get("/v1/endpoints", call),
|
|
138
|
+
web: {
|
|
139
|
+
search: post("/v1/web/search", call),
|
|
140
|
+
news: postOptional("/v1/web/news", call),
|
|
141
|
+
contacts: post("/v1/web/contacts", call)
|
|
142
|
+
},
|
|
143
|
+
youtube: {
|
|
144
|
+
search: post("/v1/youtube/search", call),
|
|
145
|
+
video: post("/v1/youtube/video", call),
|
|
146
|
+
transcript: post("/v1/youtube/transcript", call),
|
|
147
|
+
comments: Object.assign(post("/v1/youtube/comments", call), {
|
|
148
|
+
replies: post("/v1/youtube/comments/replies", call)
|
|
149
|
+
}),
|
|
150
|
+
channel: post("/v1/youtube/channel", call),
|
|
151
|
+
playlist: post("/v1/youtube/playlist", call),
|
|
152
|
+
suggest: post("/v1/youtube/suggest", call)
|
|
153
|
+
},
|
|
154
|
+
reddit: {
|
|
155
|
+
search: post("/v1/reddit/search", call),
|
|
156
|
+
post: post("/v1/reddit/post", call),
|
|
157
|
+
comments: {
|
|
158
|
+
more: post("/v1/reddit/comments/more", call)
|
|
159
|
+
},
|
|
160
|
+
subreddit: post("/v1/reddit/subreddit", call),
|
|
161
|
+
user: post("/v1/reddit/user", call),
|
|
162
|
+
domain: post("/v1/reddit/domain", call)
|
|
163
|
+
},
|
|
164
|
+
maps: {
|
|
165
|
+
search: post("/v1/maps/search", call),
|
|
166
|
+
place: post("/v1/maps/place", call),
|
|
167
|
+
reviews: post("/v1/maps/reviews", call)
|
|
168
|
+
},
|
|
169
|
+
instagram: {
|
|
170
|
+
profile: post("/v1/instagram/profile", call),
|
|
171
|
+
posts: post("/v1/instagram/posts", call),
|
|
172
|
+
post: post("/v1/instagram/post", call),
|
|
173
|
+
url: post("/v1/instagram/url", call),
|
|
174
|
+
search: post("/v1/instagram/search", call),
|
|
175
|
+
transcript: post("/v1/instagram/transcript", call),
|
|
176
|
+
comments: Object.assign(post("/v1/instagram/comments", call), {
|
|
177
|
+
replies: post("/v1/instagram/comments/replies", call)
|
|
178
|
+
})
|
|
179
|
+
},
|
|
180
|
+
tiktok: {
|
|
181
|
+
profile: post("/v1/tiktok/profile", call),
|
|
182
|
+
video: post("/v1/tiktok/video", call),
|
|
183
|
+
url: post("/v1/tiktok/url", call),
|
|
184
|
+
transcript: post("/v1/tiktok/transcript", call),
|
|
185
|
+
posts: post("/v1/tiktok/posts", call),
|
|
186
|
+
hashtag: post("/v1/tiktok/hashtag", call),
|
|
187
|
+
comments: Object.assign(post("/v1/tiktok/comments", call), {
|
|
188
|
+
replies: post("/v1/tiktok/comments/replies", call)
|
|
189
|
+
}),
|
|
190
|
+
search: post("/v1/tiktok/search", call),
|
|
191
|
+
ads: {
|
|
192
|
+
search: postOptional("/v1/tiktok/ads/search", call),
|
|
193
|
+
ad: post("/v1/tiktok/ads/ad", call)
|
|
194
|
+
}
|
|
195
|
+
},
|
|
196
|
+
bluesky: {
|
|
197
|
+
profile: post("/v1/bluesky/profile", call),
|
|
198
|
+
posts: post("/v1/bluesky/posts", call),
|
|
199
|
+
post: post("/v1/bluesky/post", call),
|
|
200
|
+
followers: post("/v1/bluesky/followers", call)
|
|
201
|
+
},
|
|
202
|
+
mastodon: {
|
|
203
|
+
profile: post("/v1/mastodon/profile", call),
|
|
204
|
+
posts: post("/v1/mastodon/posts", call),
|
|
205
|
+
post: post("/v1/mastodon/post", call),
|
|
206
|
+
hashtag: post("/v1/mastodon/hashtag", call)
|
|
207
|
+
},
|
|
208
|
+
threads: {
|
|
209
|
+
profile: post("/v1/threads/profile", call),
|
|
210
|
+
posts: post("/v1/threads/posts", call),
|
|
211
|
+
post: post("/v1/threads/post", call),
|
|
212
|
+
search: post("/v1/threads/search", call)
|
|
213
|
+
},
|
|
214
|
+
telegram: {
|
|
215
|
+
channel: post("/v1/telegram/channel", call),
|
|
216
|
+
posts: post("/v1/telegram/posts", call),
|
|
217
|
+
post: post("/v1/telegram/post", call)
|
|
218
|
+
},
|
|
219
|
+
meta: {
|
|
220
|
+
ads: {
|
|
221
|
+
search: post("/v1/meta/ads/search", call),
|
|
222
|
+
page: post("/v1/meta/ads/page", call),
|
|
223
|
+
ad: post("/v1/meta/ads/ad", call)
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
linkedin: {
|
|
227
|
+
jobs: {
|
|
228
|
+
search: postOptional("/v1/linkedin/jobs/search", call),
|
|
229
|
+
job: post("/v1/linkedin/jobs/job", call)
|
|
230
|
+
},
|
|
231
|
+
ads: {
|
|
232
|
+
search: postOptional("/v1/linkedin/ads/search", call),
|
|
233
|
+
ad: post("/v1/linkedin/ads/ad", call)
|
|
234
|
+
},
|
|
235
|
+
company: Object.assign(post("/v1/linkedin/company", call), {
|
|
236
|
+
posts: post("/v1/linkedin/company/posts", call)
|
|
237
|
+
}),
|
|
238
|
+
profile: post("/v1/linkedin/profile", call),
|
|
239
|
+
posts: postOptional("/v1/linkedin/posts", call)
|
|
240
|
+
},
|
|
241
|
+
zillow: {
|
|
242
|
+
search: postOptional("/v1/zillow/search", call),
|
|
243
|
+
property: post("/v1/zillow/property", call)
|
|
244
|
+
},
|
|
245
|
+
google: {
|
|
246
|
+
ads: {
|
|
247
|
+
advertisers: post("/v1/google/ads/advertisers", call),
|
|
248
|
+
search: postOptional("/v1/google/ads/search", call),
|
|
249
|
+
ad: post("/v1/google/ads/ad", call)
|
|
250
|
+
},
|
|
251
|
+
suggest: post("/v1/google/suggest", call),
|
|
252
|
+
trends: {
|
|
253
|
+
interest: post("/v1/google/trends/interest", call),
|
|
254
|
+
regions: post("/v1/google/trends/regions", call),
|
|
255
|
+
related: post("/v1/google/trends/related", call),
|
|
256
|
+
trending: postOptional("/v1/google/trends/trending", call)
|
|
257
|
+
}
|
|
258
|
+
},
|
|
259
|
+
upwork: {
|
|
260
|
+
search: postOptional("/v1/upwork/search", call),
|
|
261
|
+
job: post("/v1/upwork/job", call)
|
|
262
|
+
},
|
|
263
|
+
amazon: {
|
|
264
|
+
suggest: post("/v1/amazon/suggest", call),
|
|
265
|
+
search: postOptional("/v1/amazon/search", call),
|
|
266
|
+
product: post("/v1/amazon/product", call),
|
|
267
|
+
bestsellers: post("/v1/amazon/bestsellers", call)
|
|
268
|
+
},
|
|
269
|
+
site: {
|
|
270
|
+
map: post("/v1/site/map", call),
|
|
271
|
+
seo: post("/v1/site/seo", call)
|
|
272
|
+
},
|
|
273
|
+
domain: {
|
|
274
|
+
whois: post("/v1/domain/whois", call),
|
|
275
|
+
dns: post("/v1/domain/dns", call),
|
|
276
|
+
tech: post("/v1/domain/tech", call)
|
|
277
|
+
},
|
|
278
|
+
email: {
|
|
279
|
+
check: post("/v1/email/check", call)
|
|
280
|
+
},
|
|
281
|
+
crypto: {
|
|
282
|
+
coins: postOptional("/v1/crypto/coins", call),
|
|
283
|
+
coin: post("/v1/crypto/coin", call),
|
|
284
|
+
history: post("/v1/crypto/history", call),
|
|
285
|
+
trending: postOptional("/v1/crypto/trending", call),
|
|
286
|
+
categories: postOptional("/v1/crypto/categories", call),
|
|
287
|
+
movers: postOptional("/v1/crypto/movers", call),
|
|
288
|
+
new: postOptional("/v1/crypto/new", call),
|
|
289
|
+
dex: {
|
|
290
|
+
search: post("/v1/crypto/dex/search", call),
|
|
291
|
+
pairs: post("/v1/crypto/dex/pairs", call),
|
|
292
|
+
token: post("/v1/crypto/dex/token", call),
|
|
293
|
+
new: postOptional("/v1/crypto/dex/new", call)
|
|
294
|
+
},
|
|
295
|
+
pump: {
|
|
296
|
+
coins: postOptional("/v1/crypto/pump/coins", call),
|
|
297
|
+
coin: post("/v1/crypto/pump/coin", call),
|
|
298
|
+
trades: post("/v1/crypto/pump/trades", call)
|
|
299
|
+
},
|
|
300
|
+
wallet: post("/v1/crypto/wallet", call),
|
|
301
|
+
token: {
|
|
302
|
+
holders: post("/v1/crypto/token/holders", call)
|
|
303
|
+
},
|
|
304
|
+
binance: {
|
|
305
|
+
announcements: postOptional("/v1/crypto/binance/announcements", call)
|
|
306
|
+
}
|
|
307
|
+
},
|
|
308
|
+
indeed: {
|
|
309
|
+
search: postOptional("/v1/indeed/search", call),
|
|
310
|
+
job: post("/v1/indeed/job", call)
|
|
311
|
+
},
|
|
312
|
+
tripadvisor: {
|
|
313
|
+
search: post("/v1/tripadvisor/search", call),
|
|
314
|
+
place: post("/v1/tripadvisor/place", call),
|
|
315
|
+
reviews: post("/v1/tripadvisor/reviews", call)
|
|
316
|
+
},
|
|
317
|
+
googletravel: {
|
|
318
|
+
flights: post("/v1/googletravel/flights", call)
|
|
319
|
+
},
|
|
320
|
+
shopify: {
|
|
321
|
+
products: post("/v1/shopify/products", call),
|
|
322
|
+
collections: post("/v1/shopify/collections", call),
|
|
323
|
+
store: post("/v1/shopify/store", call)
|
|
324
|
+
},
|
|
325
|
+
walmart: {
|
|
326
|
+
search: post("/v1/walmart/search", call),
|
|
327
|
+
product: post("/v1/walmart/product", call)
|
|
328
|
+
},
|
|
329
|
+
aliexpress: {
|
|
330
|
+
search: post("/v1/aliexpress/search", call),
|
|
331
|
+
product: post("/v1/aliexpress/product", call)
|
|
332
|
+
},
|
|
333
|
+
appstore: {
|
|
334
|
+
app: post("/v1/appstore/app", call),
|
|
335
|
+
search: post("/v1/appstore/search", call),
|
|
336
|
+
reviews: post("/v1/appstore/reviews", call),
|
|
337
|
+
top: postOptional("/v1/appstore/top", call)
|
|
338
|
+
},
|
|
339
|
+
googleplay: {
|
|
340
|
+
app: post("/v1/googleplay/app", call),
|
|
341
|
+
search: post("/v1/googleplay/search", call),
|
|
342
|
+
reviews: post("/v1/googleplay/reviews", call)
|
|
343
|
+
},
|
|
344
|
+
airbnb: {
|
|
345
|
+
search: post("/v1/airbnb/search", call),
|
|
346
|
+
listing: post("/v1/airbnb/listing", call),
|
|
347
|
+
calendar: post("/v1/airbnb/calendar", call),
|
|
348
|
+
reviews: post("/v1/airbnb/reviews", call)
|
|
349
|
+
},
|
|
350
|
+
redfin: {
|
|
351
|
+
search: post("/v1/redfin/search", call),
|
|
352
|
+
property: post("/v1/redfin/property", call)
|
|
353
|
+
},
|
|
354
|
+
realtor: {
|
|
355
|
+
search: post("/v1/realtor/search", call),
|
|
356
|
+
property: post("/v1/realtor/property", call)
|
|
357
|
+
},
|
|
358
|
+
rightmove: {
|
|
359
|
+
search: post("/v1/rightmove/search", call),
|
|
360
|
+
property: post("/v1/rightmove/property", call)
|
|
361
|
+
},
|
|
362
|
+
immoscout: {
|
|
363
|
+
search: post("/v1/immoscout/search", call),
|
|
364
|
+
listing: post("/v1/immoscout/listing", call)
|
|
365
|
+
},
|
|
366
|
+
pinterest: {
|
|
367
|
+
search: post("/v1/pinterest/search", call),
|
|
368
|
+
pin: post("/v1/pinterest/pin", call),
|
|
369
|
+
board: post("/v1/pinterest/board", call),
|
|
370
|
+
user: post("/v1/pinterest/user", call),
|
|
371
|
+
ads: {
|
|
372
|
+
search: post("/v1/pinterest/ads/search", call),
|
|
373
|
+
ad: post("/v1/pinterest/ads/ad", call)
|
|
374
|
+
}
|
|
375
|
+
},
|
|
376
|
+
x: {
|
|
377
|
+
tweet: post("/v1/x/tweet", call)
|
|
378
|
+
},
|
|
379
|
+
kick: {
|
|
380
|
+
channel: post("/v1/kick/channel", call),
|
|
381
|
+
videos: post("/v1/kick/videos", call),
|
|
382
|
+
clips: post("/v1/kick/clips", call)
|
|
383
|
+
},
|
|
384
|
+
finance: {
|
|
385
|
+
quote: post("/v1/finance/quote", call),
|
|
386
|
+
history: post("/v1/finance/history", call),
|
|
387
|
+
search: post("/v1/finance/search", call),
|
|
388
|
+
profile: post("/v1/finance/profile", call)
|
|
389
|
+
},
|
|
390
|
+
microsoft: {
|
|
391
|
+
ads: {
|
|
392
|
+
search: postOptional("/v1/microsoft/ads/search", call),
|
|
393
|
+
ad: post("/v1/microsoft/ads/ad", call),
|
|
394
|
+
advertisers: post("/v1/microsoft/ads/advertisers", call)
|
|
395
|
+
}
|
|
396
|
+
},
|
|
397
|
+
snapchat: {
|
|
398
|
+
profile: post("/v1/snapchat/profile", call),
|
|
399
|
+
ads: {
|
|
400
|
+
search: post("/v1/snapchat/ads/search", call),
|
|
401
|
+
ad: post("/v1/snapchat/ads/ad", call)
|
|
402
|
+
}
|
|
403
|
+
},
|
|
404
|
+
tumblr: {
|
|
405
|
+
blog: post("/v1/tumblr/blog", call),
|
|
406
|
+
posts: post("/v1/tumblr/posts", call),
|
|
407
|
+
post: post("/v1/tumblr/post", call),
|
|
408
|
+
search: post("/v1/tumblr/search", call)
|
|
409
|
+
},
|
|
410
|
+
quora: {
|
|
411
|
+
question: post("/v1/quora/question", call)
|
|
412
|
+
}
|
|
413
|
+
};
|
|
274
414
|
}
|
|
275
415
|
|
|
276
|
-
//
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
416
|
+
// package.json
|
|
417
|
+
var version = "1.0.0";
|
|
418
|
+
|
|
419
|
+
// src/transport.ts
|
|
420
|
+
var DEFAULT_BASE_URL = "https://api.stophy.dev";
|
|
421
|
+
var DEFAULT_TIMEOUT_MS = 3e4;
|
|
422
|
+
var MAX_RETRY_WAIT_SECONDS = 60;
|
|
423
|
+
var RETRYABLE_STATUS = /* @__PURE__ */ new Set([429, 500, 502, 503, 504]);
|
|
424
|
+
var USER_AGENT = `stophy-typescript/${version}`;
|
|
425
|
+
function createCaller(options) {
|
|
426
|
+
const baseFetch = options.fetch ?? globalThis.fetch;
|
|
427
|
+
const baseUrl = (options.baseUrl ?? DEFAULT_BASE_URL).replace(/\/$/, "");
|
|
428
|
+
const retry = {
|
|
429
|
+
maxRetries: options.maxRetries ?? 2,
|
|
430
|
+
initialDelayMs: options.retryInitialDelayMs ?? 500,
|
|
431
|
+
timeoutMs: options.timeoutMs ?? DEFAULT_TIMEOUT_MS
|
|
432
|
+
};
|
|
433
|
+
return async (spec) => {
|
|
434
|
+
const markdown = spec.options?.format === "markdown";
|
|
435
|
+
const headers = new Headers(options.headers);
|
|
436
|
+
if (typeof document === "undefined" && !headers.has("user-agent")) {
|
|
437
|
+
headers.set("user-agent", USER_AGENT);
|
|
438
|
+
}
|
|
439
|
+
if (options.apiKey) {
|
|
440
|
+
headers.set("authorization", `Bearer ${options.apiKey}`);
|
|
441
|
+
}
|
|
442
|
+
headers.set("accept", markdown ? "text/markdown" : "application/json");
|
|
443
|
+
if (spec.body !== void 0)
|
|
444
|
+
headers.set("content-type", "application/json");
|
|
445
|
+
const url = withQuery(`${baseUrl}${spec.path}`, spec.query);
|
|
446
|
+
return send(
|
|
447
|
+
baseFetch,
|
|
448
|
+
url,
|
|
449
|
+
(signal) => ({
|
|
450
|
+
method: spec.method,
|
|
451
|
+
headers,
|
|
452
|
+
body: spec.body === void 0 ? void 0 : JSON.stringify(spec.body),
|
|
453
|
+
signal
|
|
454
|
+
}),
|
|
455
|
+
markdown,
|
|
456
|
+
spec.options?.signal,
|
|
457
|
+
retry
|
|
458
|
+
);
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
async function send(baseFetch, url, init, markdown, signal, retry) {
|
|
462
|
+
for (let n = 0; ; n += 1) {
|
|
463
|
+
const deadline = withDeadline(signal, retry.timeoutMs);
|
|
464
|
+
let waitMs;
|
|
465
|
+
try {
|
|
466
|
+
const response = await baseFetch(url, init(deadline.signal)).catch(
|
|
467
|
+
(error) => {
|
|
468
|
+
if (deadline.signal.aborted || n >= retry.maxRetries) throw error;
|
|
469
|
+
return void 0;
|
|
470
|
+
}
|
|
471
|
+
);
|
|
472
|
+
if (response === void 0) {
|
|
473
|
+
waitMs = backoffMs(n, retry.initialDelayMs);
|
|
474
|
+
} else if (n < retry.maxRetries && RETRYABLE_STATUS.has(response.status)) {
|
|
475
|
+
const error = await errorFrom(response);
|
|
476
|
+
const seconds = error.retryAfterSeconds;
|
|
477
|
+
if (seconds !== void 0 && seconds > MAX_RETRY_WAIT_SECONDS) {
|
|
478
|
+
throw error;
|
|
479
|
+
}
|
|
480
|
+
waitMs = seconds === void 0 ? backoffMs(n, retry.initialDelayMs) : seconds * 1e3;
|
|
481
|
+
} else {
|
|
482
|
+
return await readBody(response, markdown);
|
|
483
|
+
}
|
|
484
|
+
} finally {
|
|
485
|
+
deadline.clear();
|
|
486
|
+
}
|
|
487
|
+
await sleep(waitMs);
|
|
488
|
+
}
|
|
489
|
+
}
|
|
490
|
+
function withDeadline(signal, timeoutMs) {
|
|
491
|
+
const controller = new AbortController();
|
|
492
|
+
const abort = () => controller.abort(signal?.reason);
|
|
493
|
+
if (signal?.aborted) abort();
|
|
494
|
+
else signal?.addEventListener("abort", abort, { once: true });
|
|
495
|
+
const timer = setTimeout(
|
|
496
|
+
() => controller.abort(
|
|
497
|
+
new DOMException(
|
|
498
|
+
`Stophy request timed out after ${timeoutMs} ms`,
|
|
499
|
+
"TimeoutError"
|
|
500
|
+
)
|
|
501
|
+
),
|
|
502
|
+
timeoutMs
|
|
281
503
|
);
|
|
504
|
+
return {
|
|
505
|
+
signal: controller.signal,
|
|
506
|
+
clear: () => {
|
|
507
|
+
clearTimeout(timer);
|
|
508
|
+
signal?.removeEventListener("abort", abort);
|
|
509
|
+
}
|
|
510
|
+
};
|
|
282
511
|
}
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
if (
|
|
287
|
-
|
|
512
|
+
async function readBody(response, markdown) {
|
|
513
|
+
if (!response.ok) throw await errorFrom(response);
|
|
514
|
+
const text = await response.text();
|
|
515
|
+
if (markdown) return text;
|
|
516
|
+
if (!text) {
|
|
517
|
+
throw failed(response, "Stophy returned an empty response", {});
|
|
518
|
+
}
|
|
519
|
+
try {
|
|
520
|
+
return JSON.parse(text);
|
|
521
|
+
} catch {
|
|
522
|
+
throw failed(response, "Stophy returned a non-JSON response", {});
|
|
288
523
|
}
|
|
289
|
-
const body = typeof queryOrBody === "string" ? { q: queryOrBody, ...options } : queryOrBody;
|
|
290
|
-
return searchVideos({ client: client2, body }).then(unwrap);
|
|
291
524
|
}
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
if (
|
|
296
|
-
|
|
525
|
+
async function errorFrom(response) {
|
|
526
|
+
const text = await response.text();
|
|
527
|
+
let body;
|
|
528
|
+
if (text) {
|
|
529
|
+
try {
|
|
530
|
+
body = JSON.parse(text);
|
|
531
|
+
} catch {
|
|
532
|
+
body = void 0;
|
|
533
|
+
}
|
|
297
534
|
}
|
|
298
|
-
const
|
|
299
|
-
|
|
300
|
-
|
|
535
|
+
const error = readError(body);
|
|
536
|
+
const retryAfterSeconds = error.retryAfterSeconds ?? headerRetryAfter(response);
|
|
537
|
+
return failed(
|
|
538
|
+
response,
|
|
539
|
+
error.message ?? `Stophy request failed with status ${response.status}`,
|
|
540
|
+
{
|
|
541
|
+
code: error.code,
|
|
542
|
+
retryable: error.retryable ?? RETRYABLE_STATUS.has(response.status),
|
|
543
|
+
retryAfterSeconds,
|
|
544
|
+
requestId: error.requestId ?? headerRequestId(response)
|
|
545
|
+
}
|
|
301
546
|
);
|
|
302
547
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
548
|
+
function failed(response, message, options) {
|
|
549
|
+
return new StophyError(message, {
|
|
550
|
+
status: response.status,
|
|
551
|
+
code: options.code,
|
|
552
|
+
retryable: options.retryable ?? false,
|
|
553
|
+
retryAfterSeconds: options.retryAfterSeconds,
|
|
554
|
+
requestId: options.requestId ?? headerRequestId(response)
|
|
555
|
+
});
|
|
307
556
|
}
|
|
308
|
-
function
|
|
309
|
-
|
|
557
|
+
function readError(body) {
|
|
558
|
+
if (!isRecord2(body) || !isRecord2(body.error)) return {};
|
|
559
|
+
const error = body.error;
|
|
560
|
+
return {
|
|
561
|
+
code: typeof error.code === "string" ? error.code : void 0,
|
|
562
|
+
message: typeof error.message === "string" ? error.message : void 0,
|
|
563
|
+
retryable: typeof error.retryable === "boolean" ? error.retryable : void 0,
|
|
564
|
+
retryAfterSeconds: typeof error.retryAfterSeconds === "number" ? error.retryAfterSeconds : void 0,
|
|
565
|
+
requestId: typeof error.requestId === "string" ? error.requestId : void 0
|
|
566
|
+
};
|
|
310
567
|
}
|
|
311
|
-
function
|
|
312
|
-
return
|
|
568
|
+
function isRecord2(value) {
|
|
569
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
313
570
|
}
|
|
314
|
-
function
|
|
315
|
-
return
|
|
316
|
-
type: "comments",
|
|
317
|
-
videoUrl,
|
|
318
|
-
...options
|
|
319
|
-
});
|
|
571
|
+
function headerRequestId(response) {
|
|
572
|
+
return response.headers.get("x-request-id") ?? void 0;
|
|
320
573
|
}
|
|
321
|
-
function
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
574
|
+
function headerRetryAfter(response) {
|
|
575
|
+
const header = response.headers.get("retry-after");
|
|
576
|
+
if (!header) return void 0;
|
|
577
|
+
const seconds = Number(header);
|
|
578
|
+
if (Number.isFinite(seconds)) return seconds;
|
|
579
|
+
const date = Date.parse(header);
|
|
580
|
+
if (Number.isNaN(date)) return void 0;
|
|
581
|
+
return Math.max(0, Math.ceil((date - Date.now()) / 1e3));
|
|
326
582
|
}
|
|
327
|
-
function
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
}
|
|
583
|
+
function withQuery(url, query) {
|
|
584
|
+
if (!query) return url;
|
|
585
|
+
const params = new URLSearchParams();
|
|
586
|
+
for (const [key, value] of Object.entries(query)) {
|
|
587
|
+
if (value !== void 0) params.set(key, String(value));
|
|
588
|
+
}
|
|
589
|
+
const text = params.toString();
|
|
590
|
+
return text ? `${url}?${text}` : url;
|
|
591
|
+
}
|
|
592
|
+
function backoffMs(attempt, base) {
|
|
593
|
+
const window = base * 2 ** attempt;
|
|
594
|
+
return window / 2 + Math.random() * (window / 2);
|
|
595
|
+
}
|
|
596
|
+
function sleep(ms) {
|
|
597
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
333
598
|
}
|
|
334
599
|
|
|
335
600
|
// src/client.ts
|
|
@@ -337,65 +602,24 @@ function env(name) {
|
|
|
337
602
|
return typeof process === "undefined" ? void 0 : process.env[name];
|
|
338
603
|
}
|
|
339
604
|
var Stophy = class {
|
|
340
|
-
|
|
605
|
+
#call;
|
|
341
606
|
constructor(input = {}) {
|
|
342
607
|
const options = typeof input === "string" ? { apiKey: input } : input;
|
|
343
608
|
const apiKey = options.apiKey?.trim() || env("STOPHY_API_KEY")?.trim();
|
|
344
|
-
|
|
345
|
-
throw new Error(
|
|
346
|
-
"Stophy: provide `apiKey` or set the STOPHY_API_KEY environment variable."
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
|
-
this.client = createTransport({
|
|
609
|
+
this.#call = createCaller({
|
|
350
610
|
...options,
|
|
351
611
|
apiKey,
|
|
352
612
|
baseUrl: options.baseUrl ?? env("STOPHY_BASE_URL")
|
|
353
613
|
});
|
|
614
|
+
Object.assign(this, bindSurface(this.#call));
|
|
354
615
|
}
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
videoDetails(videoUrl) {
|
|
359
|
-
return videoDetails(this.client, videoUrl);
|
|
360
|
-
}
|
|
361
|
-
transcript(videoUrl, options) {
|
|
362
|
-
return transcript(this.client, videoUrl, options);
|
|
363
|
-
}
|
|
364
|
-
comments(videoUrl, options) {
|
|
365
|
-
return comments(this.client, videoUrl, options);
|
|
366
|
-
}
|
|
367
|
-
replies(continuationToken) {
|
|
368
|
-
return replies(this.client, continuationToken);
|
|
369
|
-
}
|
|
370
|
-
liveChat(videoUrl, options) {
|
|
371
|
-
return liveChat(this.client, videoUrl, options);
|
|
372
|
-
}
|
|
373
|
-
async search(queryOrBody, options) {
|
|
374
|
-
return search(this.client, queryOrBody, options);
|
|
375
|
-
}
|
|
376
|
-
async channel(urlOrBody, options) {
|
|
377
|
-
return channel(this.client, urlOrBody, options);
|
|
378
|
-
}
|
|
379
|
-
async playlist(urlOrBody, options) {
|
|
380
|
-
return playlist(this.client, urlOrBody, options);
|
|
381
|
-
}
|
|
382
|
-
async suggest(queryOrOptions, options) {
|
|
383
|
-
return suggest(this.client, queryOrOptions, options);
|
|
384
|
-
}
|
|
385
|
-
music(body) {
|
|
386
|
-
return music(this.client, body);
|
|
387
|
-
}
|
|
388
|
-
kids(body) {
|
|
389
|
-
return kids(this.client, body);
|
|
390
|
-
}
|
|
391
|
-
credits() {
|
|
392
|
-
return credits(this.client);
|
|
616
|
+
/** Current balance and lifetime usage. Requires an API key. */
|
|
617
|
+
usage() {
|
|
618
|
+
return usage(this.#call);
|
|
393
619
|
}
|
|
620
|
+
/** Recent metered requests. Requires an API key. */
|
|
394
621
|
logs(query) {
|
|
395
|
-
return logs(this
|
|
396
|
-
}
|
|
397
|
-
usage(query) {
|
|
398
|
-
return usage(this.client, query);
|
|
622
|
+
return logs(this.#call, query);
|
|
399
623
|
}
|
|
400
624
|
};
|
|
401
625
|
|