8d467c8ca7
* feat: use strictNullChecking * feat: switch logger to Winston * feat(scrapeURL): first batch * fix(scrapeURL): error swallow * fix(scrapeURL): add timeout to EngineResultsTracker * fix(scrapeURL): report unexpected error to sentry * chore: remove unused modules * feat(transfomers/coerce): warn when a format's response is missing * feat(scrapeURL): feature flag priorities, engine quality sorting, PDF and DOCX support * (add note) * feat(scrapeURL): wip readme * feat(scrapeURL): LLM extract * feat(scrapeURL): better warnings * fix(scrapeURL/engines/fire-engine;playwright): fix screenshot * feat(scrapeURL): add forceEngine internal option * feat(scrapeURL/engines): scrapingbee * feat(scrapeURL/transformars): uploadScreenshot * feat(scrapeURL): more intense tests * bunch of stuff * get rid of WebScraper (mostly) * adapt batch scrape * add staging deploy workflow * fix yaml * fix logger issues * fix v1 test schema * feat(scrapeURL/fire-engine/chrome-cdp): remove wait inserts on actions * scrapeURL: v0 backwards compat * logger fixes * feat(scrapeurl): v0 returnOnlyUrls support * fix(scrapeURL/v0): URL leniency * fix(batch-scrape): ts non-nullable * fix(scrapeURL/fire-engine/chromecdp): fix wait action * fix(logger): remove error debug key * feat(requests.http): use dotenv expression * fix(scrapeURL/extractMetadata): extract custom metadata * fix crawl option conversion * feat(scrapeURL): Add retry logic to robustFetch * fix(scrapeURL): crawl stuff * fix(scrapeURL): LLM extract * fix(scrapeURL/v0): search fix * fix(tests/v0): grant larger response size to v0 crawl status * feat(scrapeURL): basic fetch engine * feat(scrapeURL): playwright engine * feat(scrapeURL): add url-specific parameters * Update readme and examples * added e2e tests for most parameters. Still a few actions, location and iframes to be done. * fixed type * Nick: * Update scrape.ts * Update index.ts * added actions and base64 check * Nick: skipTls feature flag? * 403 * todo * todo * fixes * yeet headers from url specific params * add warning when final engine has feature deficit * expose engine results tracker for ScrapeEvents implementation * ingest scrape events * fixed some tests * comment * Update index.test.ts * fixed rawHtml * Update index.test.ts * update comments * move geolocation to global f-e option, fix removeBase64Images * Nick: * trim url-specific params * Update index.ts --------- Co-authored-by: Eric Ciarla <ericciarla@yahoo.com> Co-authored-by: rafaelmmiller <8574157+rafaelmmiller@users.noreply.github.com> Co-authored-by: Nicolas <nicolascamara29@gmail.com>
216 lines
4.3 KiB
TypeScript
216 lines
4.3 KiB
TypeScript
import { RateLimiterRedis } from "rate-limiter-flexible";
|
|
import { RateLimiterMode } from "../../src/types";
|
|
import Redis from "ioredis";
|
|
|
|
const RATE_LIMITS = {
|
|
crawl: {
|
|
default: 3,
|
|
free: 2,
|
|
starter: 10,
|
|
standard: 5,
|
|
standardOld: 40,
|
|
scale: 50,
|
|
hobby: 3,
|
|
standardNew: 10,
|
|
standardnew: 10,
|
|
growth: 50,
|
|
growthdouble: 50,
|
|
etier2c: 300,
|
|
etier1a: 1000,
|
|
etier2a: 300,
|
|
},
|
|
scrape: {
|
|
default: 20,
|
|
free: 10,
|
|
starter: 100,
|
|
standard: 100,
|
|
standardOld: 100,
|
|
scale: 500,
|
|
hobby: 20,
|
|
standardNew: 100,
|
|
standardnew: 100,
|
|
growth: 1000,
|
|
growthdouble: 1000,
|
|
etier2c: 2500,
|
|
etier1a: 1000,
|
|
etier2a: 2500,
|
|
},
|
|
search: {
|
|
default: 20,
|
|
free: 5,
|
|
starter: 50,
|
|
standard: 50,
|
|
standardOld: 40,
|
|
scale: 500,
|
|
hobby: 10,
|
|
standardNew: 50,
|
|
standardnew: 50,
|
|
growth: 500,
|
|
growthdouble: 500,
|
|
etier2c: 2500,
|
|
etier1a: 1000,
|
|
etier2a: 2500,
|
|
},
|
|
map:{
|
|
default: 20,
|
|
free: 5,
|
|
starter: 50,
|
|
standard: 50,
|
|
standardOld: 50,
|
|
scale: 500,
|
|
hobby: 10,
|
|
standardNew: 50,
|
|
standardnew: 50,
|
|
growth: 500,
|
|
growthdouble: 500,
|
|
etier2c: 2500,
|
|
etier1a: 1000,
|
|
etier2a: 2500,
|
|
},
|
|
preview: {
|
|
free: 5,
|
|
default: 5,
|
|
},
|
|
account: {
|
|
free: 100,
|
|
default: 100,
|
|
},
|
|
crawlStatus: {
|
|
free: 150,
|
|
default: 250,
|
|
},
|
|
testSuite: {
|
|
free: 10000,
|
|
default: 10000,
|
|
},
|
|
};
|
|
|
|
export const redisRateLimitClient = new Redis(
|
|
process.env.REDIS_RATE_LIMIT_URL!
|
|
)
|
|
|
|
const createRateLimiter = (keyPrefix, points) =>
|
|
new RateLimiterRedis({
|
|
storeClient: redisRateLimitClient,
|
|
keyPrefix,
|
|
points,
|
|
duration: 60, // Duration in seconds
|
|
});
|
|
|
|
export const serverRateLimiter = createRateLimiter(
|
|
"server",
|
|
RATE_LIMITS.account.default
|
|
);
|
|
|
|
export const testSuiteRateLimiter = new RateLimiterRedis({
|
|
storeClient: redisRateLimitClient,
|
|
keyPrefix: "test-suite",
|
|
points: 10000,
|
|
duration: 60, // Duration in seconds
|
|
});
|
|
|
|
export const devBRateLimiter = new RateLimiterRedis({
|
|
storeClient: redisRateLimitClient,
|
|
keyPrefix: "dev-b",
|
|
points: 1200,
|
|
duration: 60, // Duration in seconds
|
|
});
|
|
|
|
export const manualRateLimiter = new RateLimiterRedis({
|
|
storeClient: redisRateLimitClient,
|
|
keyPrefix: "manual",
|
|
points: 2000,
|
|
duration: 60, // Duration in seconds
|
|
});
|
|
|
|
|
|
export const scrapeStatusRateLimiter = new RateLimiterRedis({
|
|
storeClient: redisRateLimitClient,
|
|
keyPrefix: "scrape-status",
|
|
points: 400,
|
|
duration: 60, // Duration in seconds
|
|
});
|
|
|
|
export const etier1aRateLimiter = new RateLimiterRedis({
|
|
storeClient: redisRateLimitClient,
|
|
keyPrefix: "etier1a",
|
|
points: 10000,
|
|
duration: 60, // Duration in seconds
|
|
});
|
|
|
|
export const etier2aRateLimiter = new RateLimiterRedis({
|
|
storeClient: redisRateLimitClient,
|
|
keyPrefix: "etier2a",
|
|
points: 2500,
|
|
duration: 60, // Duration in seconds
|
|
});
|
|
|
|
const testSuiteTokens = [
|
|
"a01ccae",
|
|
"6254cf9",
|
|
"0f96e673",
|
|
"23befa1b",
|
|
"69141c4",
|
|
"48f9a97",
|
|
"5dc70ad",
|
|
"e5e60e5",
|
|
"65181ba",
|
|
"77c85b7",
|
|
"8567275",
|
|
"6c46abb",
|
|
"cb0ff78",
|
|
"fd769b2",
|
|
"cbb3462", // don't remove (s-ai)
|
|
"824abcd" // don't remove (s-ai)
|
|
];
|
|
|
|
const manual = ["69be9e74-7624-4990-b20d-08e0acc70cf6"];
|
|
|
|
function makePlanKey(plan?: string) {
|
|
return plan ? plan.replace("-", "") : "default"; // "default"
|
|
}
|
|
|
|
export function getRateLimiterPoints(
|
|
mode: RateLimiterMode,
|
|
token?: string,
|
|
plan?: string,
|
|
teamId?: string
|
|
) : number {
|
|
const rateLimitConfig = RATE_LIMITS[mode]; // {default : 5}
|
|
|
|
if (!rateLimitConfig) return RATE_LIMITS.account.default;
|
|
|
|
const points : number =
|
|
rateLimitConfig[makePlanKey(plan)] || rateLimitConfig.default; // 5
|
|
return points;
|
|
}
|
|
|
|
export function getRateLimiter(
|
|
mode: RateLimiterMode,
|
|
token?: string,
|
|
plan?: string,
|
|
teamId?: string
|
|
) : RateLimiterRedis {
|
|
if (token && testSuiteTokens.some(testToken => token.includes(testToken))) {
|
|
return testSuiteRateLimiter;
|
|
}
|
|
|
|
if(teamId && teamId === process.env.DEV_B_TEAM_ID) {
|
|
return devBRateLimiter;
|
|
}
|
|
|
|
if(teamId && teamId === process.env.ETIER1A_TEAM_ID) {
|
|
return etier1aRateLimiter;
|
|
}
|
|
|
|
if(teamId && teamId === process.env.ETIER2A_TEAM_ID) {
|
|
return etier2aRateLimiter;
|
|
}
|
|
|
|
if(teamId && manual.includes(teamId)) {
|
|
return manualRateLimiter;
|
|
}
|
|
|
|
return createRateLimiter(`${mode}-${makePlanKey(plan)}`, getRateLimiterPoints(mode, token, plan, teamId));
|
|
}
|