{"version":3,"file":"main.cjs","names":["z","obj","path","fs","UAParser","Crawlers","CLIs","Fetchers","Libraries","PREFIX","dns","fs","digit","letter","PREFIX","UAParser","URL","blockedCountries","PREFIX","PREFIX","performance","PREFIX","path","fs"],"sources":["../src/botDetector/types/configSchema.ts","../src/botDetector/db/findDataPath.ts","../src/botDetector/helpers/mmdbDataReaders.ts","../src/botDetector/utils/logger.ts","../src/botDetector/db/dialectUtils.ts","../src/botDetector/db/updateBanned.ts","../src/botDetector/db/updateIsBot.ts","../src/botDetector/db/updateVisitors.ts","../src/botDetector/db/updateVisitorScore.ts","../src/botDetector/db/batchQueue.ts","../src/botDetector/config/storageAdapter.ts","../src/botDetector/config/dbAdapter.ts","../src/botDetector/checkers/CheckerRegistry.ts","../src/botDetector/checkers/badUaChecker.ts","../src/botDetector/config/config.ts","../src/botDetector/helpers/getIPInformation.ts","../src/botDetector/utils/cookieGenerator.ts","../src/botDetector/helpers/UAparser.ts","../src/botDetector/checkers/ipValidation.ts","../src/botDetector/helpers/cache/dnsLookupCache.ts","../src/botDetector/checkers/goodBots/base.ts","../src/botDetector/checkers/goodBots/goodBots.ts","../src/botDetector/checkers/browserTypesAneDevicesCalc.ts","../src/botDetector/utils/regex/acceptLangRegex.ts","../src/botDetector/checkers/acceptLangMap.ts","../src/botDetector/helpers/cache/rateLimitarCache.ts","../src/botDetector/checkers/rateTracker.ts","../src/botDetector/checkers/proxyISPAndCookieCalc.ts","../src/botDetector/checkers/headers/headersBase.ts","../src/botDetector/checkers/headers/headers.ts","../src/botDetector/utils/regex/pathTravelersRegex.ts","../src/botDetector/checkers/UaAndHeaderChecker/base.ts","../src/botDetector/checkers/UaAndHeaderChecker/headersAndUACalc.ts","../src/botDetector/checkers/geoLocationCalc.ts","../src/botDetector/checkers/fireholEscalation.ts","../src/botDetector/checkers/asnClassification.ts","../src/botDetector/checkers/torAnalysis.ts","../src/botDetector/checkers/timezoneConsistency.ts","../src/botDetector/checkers/honeypot.ts","../src/botDetector/helpers/cache/sessionCache.ts","../src/botDetector/checkers/sessionCoherence.ts","../src/botDetector/helpers/cache/timingCache.ts","../src/botDetector/checkers/velocityFingerprint.ts","../src/botDetector/checkers/knownBadIps.ts","../src/botDetector/helpers/exceptions.ts","../src/botDetector/penalties/banIP.ts","../src/botDetector/helpers/processChecks.ts","../src/botDetector/helpers/cache/reputationCache.ts","../src/botDetector.ts","../src/botDetector/helpers/cache/cannaryCache.ts","../src/botDetector/helpers/reputation.ts","../src/botDetector/utils/whitelist.ts","../src/botDetector/utils/nowMysql.ts","../src/botDetector/middlewares/canaryCookieChecker.ts","../src/botDetector/routes/visitorLog.ts","../src/botDetector/db/generator.ts","../src/botDetector/db/schema.ts","../src/botDetector/db/warmUp.ts","../src/botDetector/db/customUpdate.ts"],"sourcesContent":["import z from \"zod\";\nimport type { CacheConfig } from \"./storageTypes.js\";\nimport { DbConfig } from \"./dbTypes.js\";\n\n\n\nconst dbConfigStorage = z.custom<DbConfig>(\n  (val: unknown): val is DbConfig => {\n    if (typeof val !== 'object' || val === null) {\n      return false;\n    }\n    const obj = val as DbConfig;\n    return typeof obj.driver === 'string';\n  },\n  { message: 'Database config must be an object with a valid \"driver\" string' }\n);\n\nconst store = z.object({\n  main: dbConfigStorage,\n}).required().strict();\n\nconst cache = z.custom<CacheConfig>(\n  (val: unknown): val is CacheConfig => {\n    if (typeof val !== 'object' || val === null) {\n      return false;\n    }\n    const obj = val as CacheConfig;\n    return typeof obj.driver === 'string';\n  },\n  { message: 'Storage must be an object with a valid \"driver\" string' }\n);\n\nexport const configSchema = z.object({\n    store,\n        /**\n           * Total ban threshold the system accumaltae before banning.\n           */\n        banScore: z.number().max(100).min(0).default(100),\n            /**\n           * Total ban score the system can assign.\n           */\n        maxScore: z.number().max(100).min(0).default(100),\n            /**\n           * Total score to restore for the next visitor request.\n           */\n        restoredReputationPoints:  z.number().default(10),\n        /**\n     * setNewComputedScore\n     * -------------------\n     * Controls how the bot-detector and the reputation-healer cooperate.\n     *\n     * true  ▸ **Live snapshot mode**  \n     *        – Every request:\n     *          1. Bot-detector recalculates a fresh `botScore`  \n     *          2. Row in **visitors** is overwritten with that score  \n     *          3. Cache is refreshed with the same value  \n     *          4. Reputation-healer subtracts `restoredReputationPoints`\n     *             (if the visitor isn’t banned) and writes the lower score back\n     *             to DB & cache.\n     *        – Net effect: score oscillates  \n     *          `computed → healed → computed → healed …`  \n     *          Useful when you want the latest risk snapshot visible in the DB\n     *          after every page view.\n     *\n     * false ▸ **Snapshot-then-heal mode**  \n     *        – First request for this canary:  \n     *          detector writes the computed score (e.g. 8) to DB & cache.  \n     *        – Subsequent requests while the cache entry lives:  \n     *          detector skips the overwrite → healer slowly counts the\n     *          score down (`–restoredReputationPoints` per hit) and commits\n     *          the lower value.  \n     *        – When the cache expires (TTL) or the visitor clears cookies,\n     *          a fresh snapshot is taken and the cycle restarts.\n     *        – Net effect: score only **decreases** until a new snapshot is taken.\n     *\n     * Example\n     * -------\n     *   banScore = 10, restoredReputationPoints = 1\n     *   R = reqeast\n     *   Flag = true\n     *   ───────────\n     *   R1: detector 8 ➜ DB 8 ➜ healer 7\n     *   R2: detector 8 ➜ DB 8 ➜ healer 7\n     *\n     *   Flag = false\n     *   ────────────\n     *   R1: detector 8 ➜ DB 8, cache 8\n     *   R2: detector (skip) ➜ healer 7 ➜ DB 7, cache 7\n     *   R3: detector (skip) ➜ healer 6 ➜ DB 6, cache 6\n     *\n     * Choose **true** when you always want the latest computed risk stored.  \n     * Choose **false** when you prefer a single snapshot that only decays until\n     * the cache is refreshed.\n     */\n        setNewComputedScore: z.boolean().default(false),\n        whiteList: z.array(z.union([z.ipv4(), z.ipv6(), z.string()])).optional().default([]),\n        checksTimeRateControl: z.object({\n              checkEveryRequest: z.boolean().default(true),\n              checkEvery: z.number().default(1000 * 60 * 5),\n        }).prefault({}),\n\n        batchQueue: z.object({\n            flushIntervalMs: z.number().default(5000),\n            maxBufferSize: z.number().default(100),\n            maxRetries: z.number().default(3),\n        }).prefault({}),\n\n        storage: cache.optional(),\n        \n        checkers: z.object({\n            localeMapsCheck: z.discriminatedUnion('enable', [\n                z.object({\n                    enable: z.literal(false)\n                }),\n\n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.object({\n                        ipAndHeaderMismatch: z.number().default(20),\n                        missingHeader:  z.number().default(20),\n                        missingGeoData:  z.number().default(20),\n                        malformedHeader: z.number().default(30)\n                    }).prefault({}),\n                })\n            ]).prefault({enable: true}),\n\n            knownBadUserAgents: z.discriminatedUnion('enable', [\n                z.object({\n                    enable: z.literal(false)\n                }),\n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.object({\n                        criticalSeverity: z.number().default(100),\n                        highSeverity: z.number().default(80),\n                        mediumSeverity: z.number().default(30),\n                        lowSeverity: z.number().default(10),\n                    }).prefault({})\n                })\n            ]).prefault({enable: true}),\n            \n            enableIpChecks: z.discriminatedUnion('enable', [\n                z.object({\n                    enable: z.literal(false)\n                }),\n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.number().default(10)\n                })\n            ]).prefault({enable: true}),\n\n            enableGoodBotsChecks: z.discriminatedUnion('enable', [\n                z.object({\n                    enable: z.literal(false)\n                }), \n\n                z.object({\n                    enable: z.literal(true),\n            /**\n           *   If settings.banUnlistedBots is true any bot not listed in suffix.json or botsWithoutSuffix will be banned.\n            *   Everything else exact names and any unknown bots when banning is off—hits the IP-range check..\n           */\n                    banUnlistedBots: z.boolean().default(true),\n                    penalties: z.number().default(100)\n                })\n\n            ]).prefault({enable: true}),\n\n            enableBehaviorRateCheck: z.discriminatedUnion('enable', [\n                z.object({\n                    enable: z.literal(false)\n                }),\n\n                z.object({\n                    enable: z.literal(true),\n                    behavioral_window: z.number().default(60_000),\n                    behavioral_threshold: z.number().default(30),\n                    penalties: z.number().default(60)\n                })                                \n            ]).prefault({enable: true}),\n\n            enableProxyIspCookiesChecks: z.discriminatedUnion('enable', [\n                z.object({\n                    enable: z.literal(false)\n                }),\n                \n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.object({\n                        cookieMissing: z.number().default(80),\n                        proxyDetected: z.number().default(40),\n                        multiSourceBonus2to3: z.number().default(10),\n                        multiSourceBonus4plus: z.number().default(20),\n                        hostingDetected: z.number().default(50),\n                        ispUnknown: z.number().default(10),\n                        orgUnknown: z.number().default(10),\n                    }).prefault({}),\n                }),\n            ]).prefault({enable: true}),\n\n            enableUaAndHeaderChecks: z.discriminatedUnion('enable', [\n                z.object({\n                    enable: z.literal(false)\n                }),\n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.object({\n                        headlessBrowser: z.number().default(100),\n                        shortUserAgent: z.number().default(80),\n                        tlsCheckFailed: z.number().default(60),\n                        badUaChecker: z.boolean().default(true)    \n\n                    }).prefault({}),\n                })\n            ]).prefault({enable: true}),\n\n            enableBrowserAndDeviceChecks: z.discriminatedUnion('enable', [\n                z.object({\n                    enable: z.literal(false)\n                }),\n\n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.object({        \n                        cliOrLibrary: z.number().default(100),\n                        internetExplorer: z.number().default(100),\n                        linuxOs: z.number().default(10),\n                        impossibleBrowserCombinations: z.number().default(30),\n                        browserTypeUnknown: z.number().default(10),\n                        browserNameUnknown: z.number().default(10),\n                        desktopWithoutOS: z.number().default(10),\n                        deviceVendorUnknown: z.number().default(10),\n                        browserVersionUnknown: z.number().default(10),\n                        deviceModelUnknown: z.number().default(5),\n                    }).prefault({}),\n                })\n                \n            ]).prefault({enable: true}),\n\n            enableGeoChecks: z.discriminatedUnion('enable', [\n                z.object({\n                    enable: z.literal(false)\n                }),\n              z.object({\n                    enable: z.literal(true),\n                    bannedCountries: z.array(z.string()).optional().default([]),\n                    penalties: z.object({   \n                        countryUnknown: z.number().default(10),\n                        regionUnknown: z.number().default(10),\n                        latLonUnknown: z.number().default(5),\n                        districtUnknown: z.number().default(5),\n                        cityUnknown: z.number().default(10),\n                        timezoneUnknown: z.number().default(10),\n                        subregionUnknown: z.number().default(10),\n                        phoneUnknown: z.number().default(10),\n                        continentUnknown: z.number().default(5),\n                    }).prefault({}),\n                }),\n            ]).prefault({enable: true}),\n\n            enableKnownThreatsDetections: z.discriminatedUnion('enable', [\n                z.object({\n                    enable: z.literal(false)\n                }),\n\n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.object({\n                        anonymiseNetwork: z.number().default(20),\n                        threatLevels: z.object({\n                            criticalLevel1: z.number().default(40),\n                            currentAttacksLevel2: z.number().default(30),\n                            threatLevel3: z.number().default(20),\n                            threatLevel4: z.number().default(10),\n                        }).prefault({}),\n                    }).prefault({})\n                }),\n            ]).prefault({enable: true}),\n\n            enableAsnClassification: z.discriminatedUnion('enable', [\n                z.object({ enable: z.literal(false) }),\n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.object({\n                        contentClassification: z.number().default(20),\n                        unknownClassification: z.number().default(10),\n                        lowVisibilityPenalty: z.number().default(10),\n                        lowVisibilityThreshold: z.number().default(15),\n                        comboHostingLowVisibility: z.number().default(20),\n                    }).prefault({}),\n                }),\n            ]).prefault({ enable: true }),\n\n            enableTorAnalysis: z.discriminatedUnion('enable', [\n                z.object({ enable: z.literal(false) }),\n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.object({\n                        runningNode: z.number().default(15),\n                        exitNode: z.number().default(20),\n                        webExitCapable: z.number().default(15),\n                        guardNode: z.number().default(10),\n                        badExit: z.number().default(40),\n                        obsoleteVersion: z.number().default(10),\n                    }).prefault({}),\n                }),\n            ]).prefault({ enable: true }),\n\n            enableTimezoneConsistency: z.discriminatedUnion('enable', [\n                z.object({ enable: z.literal(false) }),\n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.number().default(20),\n                }),\n            ]).prefault({ enable: true }),\n\n            honeypot: z.discriminatedUnion('enable', [\n                z.object({ enable: z.literal(false) }),\n                z.object({\n                    enable: z.literal(true),\n                    paths: z.array(z.string()).default([]),\n                }),\n            ]).prefault({ enable: true }),\n\n            enableSessionCoherence: z.discriminatedUnion('enable', [\n                z.object({ enable: z.literal(false) }),\n                z.object({\n                    enable: z.literal(true),\n                    penalties: z.object({\n                        pathMismatch: z.number().default(10),\n                        missingReferer: z.number().default(20),\n                        domainMismatch: z.number().default(30),\n                    }).prefault({}),\n                }),\n            ]).prefault({ enable: true }),\n\n            enableVelocityFingerprint: z.discriminatedUnion('enable', [\n                z.object({ enable: z.literal(false) }),\n                z.object({\n                    enable: z.literal(true),\n                    cvThreshold: z.number().default(0.1),\n                    penalties: z.number().default(40),\n                }),\n            ]).prefault({ enable: true }),\n\n            enableKnownBadIpsCheck: z.discriminatedUnion('enable', [\n                z.object({ enable: z.literal(false) }),\n                z.object({\n                    enable: z.literal(true),\n                    highRiskPenalty: z.number().default(30),\n                }),\n            ]).prefault({ enable: true }),\n        }).prefault({}),\n\n        generator: z.object({\n            scoreThreshold: z.number().default(70),\n            generateTypes: z.boolean().default(false),\n            deleteAfterBuild: z.boolean().default(false),\n            mmdbctlPath: z.string().default('mmdbctl')\n        }).prefault({}),\n\n        headerOptions: z.object({\n                weightPerMustHeader: z.number().default(20),\n                missingBrowserEngine: z.number().default(30),\n                postManOrInsomiaHeaders: z.number().default(50),\n                AJAXHeaderExists: z.number().default(30),\n                connectionHeaderIsClose: z.number().default(20),\n                originHeaderIsNULL: z.number().default(10),\n                originHeaderMismatch: z.number().default(30),\n                omittedAcceptHeader: z.number().default(30),\n\n                clientHintsMissingForBlink: z.number().default(30),\n                teHeaderUnexpectedForBlink: z.number().default(10),\n                clientHintsUnexpectedForGecko: z.number().default(30),\n                teHeaderMissingForGecko: z.number().default(20),\n                \n                aggressiveCacheControlOnGet: z.number().default(15),\n                crossSiteRequestMissingReferer: z.number().default(10),\n                inconsistentSecFetchMode: z.number().default(20),\n\n              hostMismatchWeight: z.number().default(40),\n            }).prefault({}),\n\n            pathTraveler: z.object({\n                maxIterations: z.number().default(3),\n                maxPathLength: z.number().default(1500),\n                pathLengthToLong: z.number().default(100),\n                longDecoding: z.number().default(100),\n                traversalDetected: z.number().default(60),\n            }).prefault({}),\n\n        \n            punishmentType: z.object({\n                enableFireWallBan: z.boolean().default(false),\n            }).prefault({}),\n            \n           logLevel: z.enum(['debug', 'info', 'warn', 'error', 'fatal']).default('info'),\n});\n\nexport type BotDetectorConfig = z.infer<typeof configSchema>;\nexport type BotDetectorConfigInput = z.input<typeof configSchema>;","import fs from 'node:fs';\nimport path from 'node:path';\nimport { fileURLToPath } from 'node:url';\n\nconst __moduleDir = path.dirname(fileURLToPath(import.meta.url));\n\nexport function getLibraryRoot(currentDir: string = __moduleDir): string {\n  if (fs.existsSync(path.join(currentDir, 'package.json'))) {\n    return currentDir;\n  }\n  \n  const parentDir = path.resolve(currentDir, '..');\n  if (parentDir === currentDir) throw new Error('Could not find library root');\n  return getLibraryRoot(parentDir);\n}\n\nexport function resolveDataPath(fileName: string): string | never {\n  const root = getLibraryRoot();\n  \n  const possiblePaths = [\n    path.resolve(root, '_data-sources', fileName),\n    path.resolve(root, 'dist', '_data-sources', fileName),\n  ];\n\n  for (const path of possiblePaths) {\n    if (fs.existsSync(path)) return path;\n  }\n\n  if (fileName !== 'banned.mmdb' && fileName !== 'highRisk.mmdb') {\n    throw new Error(\n      `[Bot Detector] Data file \"${fileName}\" not found. ` +\n      `Run 'bot-detector init' to download required data files.`\n    );\n  }\n\n  return '';\n}\n","import maxmind, { Reader } from 'maxmind';\nimport { open, type RootDatabase } from 'lmdb';\nimport type { BgpRecord, CityGeoRecord, GeoRecord, TorRecord, ThreatRecord, CrawlersRecord, ProxyRecord, UserAgentRecord } from '@riavzon/shield-base';\nimport type { BannedRecord, HighRiskRecord } from '../types/generator.js';\nimport { existsSync } from \"node:fs\";\nimport { resolveDataPath } from '@db/findDataPath.js';\n\nexport type ThreatRecordModified = ThreatRecord & { network: string }\n\nexport interface DataReaders {\n    asnDataBase(ip: string): BgpRecord | null;\n    cityDataBase(ip: string): CityGeoRecord | null;\n    countryDataBase(ip: string): GeoRecord | null;\n    goodBotsDataBase(ip: string): CrawlersRecord | null;\n    torDataBase(ip: string): TorRecord | null;\n    proxyDataBase(ip: string): ProxyRecord | null;\n    fireholAnonDataBase(ip: string): ThreatRecordModified | null;\n    fireholLvl1DataBase(ip: string): ThreatRecordModified | null;\n    fireholLvl2DataBase(ip: string): ThreatRecordModified | null;\n    fireholLvl3DataBase(ip: string): ThreatRecordModified | null;\n    fireholLvl4DataBase(ip: string): ThreatRecordModified | null;\n    bannedDataBase(ip: string): BannedRecord | null;\n    highRiskDataBase(ip: string): HighRiskRecord | null;\n    getUserAgentLmdb(): RootDatabase<UserAgentRecord, string>;\n}\n\nexport interface AppReaders {\n    asn: Reader<BgpRecord & maxmind.Response>;\n    city: Reader<CityGeoRecord & maxmind.Response>;\n    country: Reader<GeoRecord & maxmind.Response>;\n    goodBots: Reader<CrawlersRecord & maxmind.Response>;\n    tor: Reader<TorRecord & maxmind.Response>;\n    proxy: Reader<ProxyRecord & maxmind.Response>;\n    fireholAnon: Reader<ThreatRecordModified & maxmind.Response>;\n    fireholLvl1: Reader<ThreatRecordModified & maxmind.Response>;\n    fireholLvl2: Reader<ThreatRecordModified & maxmind.Response>;\n    fireholLvl3: Reader<ThreatRecordModified & maxmind.Response>;\n    fireholLvl4: Reader<ThreatRecordModified & maxmind.Response>;\n    banned?: Reader<BannedRecord & maxmind.Response>;\n    highRisk?: Reader<HighRiskRecord & maxmind.Response>;\n    userAgentLmdb: RootDatabase<UserAgentRecord, string>;\n}\n\n\nexport class DataSources implements DataReaders {\n   private readonly readers: AppReaders;\n   private constructor(readers: AppReaders) {\n    this.readers = readers;\n  }\n\n  public static async initialize(): Promise<DataSources> {\n    const options = { watchForUpdates: process.env.NODE_ENV !== 'test' };\n    \n    const [asn, city, country, goodBots, tor, proxy, fireholAnon, fireholLvl1, fireholLvl2, fireholLvl3, fireholLvl4] = await Promise.all([\n      maxmind.open<BgpRecord & maxmind.Response>(resolveDataPath('asn.mmdb'), options),\n      maxmind.open<CityGeoRecord & maxmind.Response>(resolveDataPath('city.mmdb'), options),\n      maxmind.open<GeoRecord & maxmind.Response>(resolveDataPath('country.mmdb'), options),\n      maxmind.open<CrawlersRecord& maxmind.Response>(resolveDataPath('goodBots.mmdb'), options),\n      maxmind.open<TorRecord & maxmind.Response>(resolveDataPath('tor.mmdb'), options),\n      maxmind.open<ProxyRecord & maxmind.Response>(resolveDataPath('proxy.mmdb'), options),\n      maxmind.open<ThreatRecordModified & maxmind.Response>(resolveDataPath('firehol_anonymous.mmdb'), options),\n      maxmind.open<ThreatRecordModified & maxmind.Response>(resolveDataPath('firehol_l1.mmdb'), options),\n      maxmind.open<ThreatRecordModified & maxmind.Response>(resolveDataPath('firehol_l2.mmdb'), options),\n      maxmind.open<ThreatRecordModified & maxmind.Response>(resolveDataPath('firehol_l3.mmdb'), options),\n      maxmind.open<ThreatRecordModified & maxmind.Response>(resolveDataPath('firehol_l4.mmdb'), options),\n    ]);\n\n    const bannedPath = resolveDataPath('banned.mmdb');\n    const highRiskPath = resolveDataPath('highRisk.mmdb');\n\n    const [banned, highRisk] = await Promise.all([\n      existsSync(bannedPath) ? maxmind.open<BannedRecord & maxmind.Response>(bannedPath, options): Promise.resolve(undefined),\n      existsSync(highRiskPath) ? maxmind.open<HighRiskRecord & maxmind.Response>(highRiskPath, options): Promise.resolve(undefined),\n    ]);\n\n    const userAgentLmdb = open<UserAgentRecord, string>({\n      path: resolveDataPath('useragent-db/useragent.mdb'),\n      name: 'useragent',\n      compression: true,\n      readOnly: true,\n      useVersions: true,\n      sharedStructuresKey: Symbol.for('structures'),\n      pageSize: 4096,\n      cache: {\n          validated: true\n      },\n      noReadAhead: true,\n      maxReaders: 2024,\n    });\n\n    return new DataSources({\n       asn,\n       city,\n       country,\n       goodBots,\n       tor,\n       proxy,\n       fireholAnon,\n       fireholLvl1,\n       fireholLvl2,\n       fireholLvl3,\n       fireholLvl4,\n       banned,\n       highRisk,\n       userAgentLmdb,\n    });\n  }\n    \n  public asnDataBase(ip: string): BgpRecord | null {\n    const result: BgpRecord | null = this.readers.asn.get(ip);\n    return result;\n  }\n\n  public cityDataBase(ip: string): CityGeoRecord | null {\n    const result: CityGeoRecord | null = this.readers.city.get(ip);\n    return result;\n  }\n\n  public countryDataBase(ip: string): GeoRecord | null {\n    const result: GeoRecord | null = this.readers.country.get(ip);\n    return result;\n  }\n\n  public goodBotsDataBase(ip: string): CrawlersRecord | null {\n    const result: CrawlersRecord | null = this.readers.goodBots.get(ip);\n    return result;\n  }\n\n  public torDataBase(ip: string): TorRecord | null {\n    const result: TorRecord | null = this.readers.tor.get(ip);\n    return result;\n  }\n\n  public proxyDataBase(ip: string): ProxyRecord | null {\n    const result: ProxyRecord | null = this.readers.proxy.get(ip);\n    return result;\n  }\n\n  public fireholAnonDataBase(ip: string): ThreatRecordModified | null {\n    const result: ThreatRecordModified | null = this.readers.fireholAnon.get(ip);\n    return result;\n  }\n\n  public fireholLvl1DataBase(ip: string): ThreatRecordModified | null {\n    const result: ThreatRecordModified | null = this.readers.fireholLvl1.get(ip);\n    return result;\n  }\n\n  public fireholLvl2DataBase(ip: string): ThreatRecordModified | null {\n    const result: ThreatRecordModified | null = this.readers.fireholLvl2.get(ip);\n    return result;\n  }\n\n  public fireholLvl3DataBase(ip: string): ThreatRecordModified | null {\n    const result: ThreatRecordModified | null = this.readers.fireholLvl3.get(ip);\n    return result;\n  }\n\n  public fireholLvl4DataBase(ip: string): ThreatRecordModified | null {\n    const result: ThreatRecordModified | null = this.readers.fireholLvl4.get(ip);\n    return result;\n  }\n\n  public bannedDataBase(ip: string): BannedRecord | null {\n    return this.readers.banned?.get(ip) ?? null;\n  }\n\n  public highRiskDataBase(ip: string): HighRiskRecord | null {\n    return this.readers.highRisk?.get(ip) ?? null;\n  }\n\n  public getUserAgentLmdb(): RootDatabase<UserAgentRecord, string> {\n    return this.readers.userAgentLmdb;\n  }\n\n}\n","import { pino, Logger } from 'pino';\nimport { existsSync, mkdirSync } from 'fs';\nimport path from 'path';\nimport { getConfiguration } from '../config/config.js';\n\n\nconst LOG_DIR = path.resolve(process.cwd(), process.env.LOG_DIR || 'bot-detector-logs');\nif (!existsSync(LOG_DIR)) mkdirSync(LOG_DIR, { recursive: true });\n\nconst transport = pino.transport({\n  targets: [\n    {\n      target: 'pino/file',\n      level:  'info',\n      options: {\n        destination: `${LOG_DIR}/info.log`,\n        mkdir: true\n      }\n    },\n    {\n      target: 'pino/file',\n      level:  'warn',\n      options: {\n        destination: `${LOG_DIR}/warn.log`,\n        mkdir: true\n      }\n    },\n    {\n      target: 'pino/file',\n      level:  'error',\n      options: {\n        destination: `${LOG_DIR}/errors.log`,\n        mkdir:true\n      }\n    }\n  ]\n});\n\nlet logger: pino.Logger;  \n\nexport function getLogger(): Logger {\n  if (logger) return logger;      \n  const { logLevel } = getConfiguration();\n  logger = (pino) (\n    {\n    level: logLevel,\n    timestamp: pino.stdTimeFunctions.isoTime,\n    mixin() { return { uptime: process.uptime() }; },\n    redact: {\n      paths: [\n      '*.password',\n       '*.email',\n        'name',\n        'Name',\n        '*.cookies',\n        '*.cookie',\n        'cookies',\n        'cookie',\n        '*.accessToken',\n        '*.refresh_token',\n        '*.secret'\n      ],\n      censor: '[SECRET]'\n     }\n    },\n  transport\n  );\n  return logger;\n}","import type { Database } from 'db0';\n\nexport function isMySQL(db: Database): boolean {\n    return db.dialect === 'mysql';\n}\n\nexport function isSQLite(db: Database): boolean {\n    return db.dialect === 'sqlite';\n}\n\n/** Convert ? placeholders to $1, $2, for PostgreSQL. */\nexport function prep(db: Database, sql: string) {\n    if (db.dialect !== 'postgresql') return db.prepare(sql);\n    let i = 0;\n    return db.prepare(sql.replace(/\\?/g, () => `$${String(++i)}`));\n}\n\n/** Generate positional placeholders for a dynamic list of values. */\nexport function placeholders(db: Database, count: number, offset = 0): string {\n    return Array.from({ length: count }, (_, i) =>\n        db.dialect === 'postgresql' ? `$${String(offset + i + 1)}` : '?'\n    ).join(', ');\n}\n\n/** NOW() equivalent per dialect. */\nexport function now(db: Database): string {\n    return isSQLite(db) ? \"datetime('now')\" : 'NOW()';\n}\n\n/**\n * Upsert conflict clause.\n * MySQL: ON DUPLICATE KEY UPDATE\n * Others: ON CONFLICT(pk) DO UPDATE SET\n */\nexport function onUpsert(db: Database, pk: string): string {\n    return isMySQL(db)\n        ? 'ON DUPLICATE KEY UPDATE'\n        : `ON CONFLICT(${pk}) DO UPDATE SET`;\n}\n\n/**\n * Reference to the incoming row value in an upsert SET clause.\n * MySQL: VALUES(col)\n * Others: excluded.col\n */\nexport function excluded(db: Database, col: string): string {\n    return isMySQL(db) ? `VALUES(${col})` : `excluded.${col}`;\n}\n\n/**\n * INSERT IGNORE equivalent.\n * MySQL: INSERT IGNORE INTO\n * SQLite: INSERT OR IGNORE INTO\n * PostgreSQL: INSERT INTO  (use onConflictDoNothing() as trailing clause)\n */\nexport function insertIgnore(db: Database): string {\n    if (isSQLite(db)) return 'INSERT OR IGNORE INTO';\n    if (isMySQL(db))  return 'INSERT IGNORE INTO';\n    return 'INSERT INTO';\n}\n\n/** Trailing ON CONFLICT DO NOTHING clause, for PostgreSQL. */\nexport function onConflictDoNothing(db: Database): string {\n    return db.dialect === 'postgresql' ? 'ON CONFLICT DO NOTHING' : '';\n}\n","import { getLogger } from '../utils/logger.js';\nimport type { BannedInfo } from '../types/checkersTypes.js';\nimport { getDb } from '../config/config.js';\nimport { prep, onUpsert, excluded } from './dialectUtils.js';\n\nexport async function updateBannedIP(\n  cookie: string,\n  ipAddress: string,\n  country: string,\n  user_agent: string,\n  info: BannedInfo\n) {\n  const db = getDb();\n  const log = getLogger().child({ service: 'BOT DETECTOR', branch: 'db', type: 'updateBannedIP' });\n  const reasonPayload = JSON.stringify(info.reasons);\n  const params = [cookie, ipAddress, country, user_agent, reasonPayload, info.score] satisfies (string | number)[];\n  \n  const ex = (col: string) => excluded(db, col);\n  const upsert = onUpsert(db, 'canary_id');\n  try {\n    await prep(db,\n      `INSERT INTO banned (canary_id, ip_address, country, user_agent, reason, score)\n       VALUES (?, ?, ?, ?, ?, ?)\n       ${upsert}\n       ip_address = ${ex('ip_address')},\n       country = ${ex('country')},\n       user_agent = ${ex('user_agent')},\n       score = ${ex('score')},\n       reason = ${ex('reason')}`\n    ).run(...params);\n    log.info(`Updated Database TABLE - banned. A user has been banned for IP ${ipAddress} (score ${String(info.score)})`);\n  } catch (err: unknown) {\n    log.error({ err }, 'ERROR UPDATING \"banned\" TABLE');\n    throw err;\n  }\n}\n","import { getLogger } from '../utils/logger.js';\nimport { getDb } from '../config/config.js';\nimport { prep } from './dialectUtils.js';\n\nexport async function updateIsBot(isBot: boolean, cookie: string) {\n    const params = [isBot ? 1 : 0, cookie];\n    const db = getDb();\n    const log = getLogger().child({ service: 'BOT DETECTOR', branch: 'db', type: 'updateIsBot' });\n\n    try { \n        await prep(db, `UPDATE visitors SET is_bot = ? WHERE canary_id = ?`).run(...params);\n    } catch (err: unknown) {\n        log.error({ err }, 'ERROR UPDATING IS_BOT');\n        throw err;\n    }\n}\n\n  ","import { userValidation } from '../types/fingerPrint.js';\nimport { getLogger } from '../utils/logger.js';\nimport { getDb } from '../config/config.js';\nimport { prep, onUpsert, excluded, now } from './dialectUtils.js';\n\nexport async function updateVisitor(u: userValidation) {\n  const db = getDb();\n  const log = getLogger().child({service: 'BOT DETECTOR', branch: 'db', type: 'updateVisitors'});\n  const {\n    visitorId,\n    cookie,\n    ipAddress,\n    userAgent,\n    country,\n    region,\n    regionName,\n    city,\n    district,\n    lat,\n    lon,\n    timezone,\n    currency,\n    isp,\n    org,\n    as: asOrg,\n    device_type,\n    browser,\n    proxy,\n    hosting,\n    is_bot,\n    first_seen,\n    last_seen,\n    request_count,\n    deviceVendor,\n    deviceModel,\n    browserType,\n    browserVersion,\n    os,\n    activity_score,\n  } = u;\n  const params = [\n    visitorId,\n    cookie,\n    ipAddress,\n    userAgent,\n    country,\n    region,\n    regionName,\n    city,\n    district,\n    lat,\n    lon,\n    timezone,\n    currency,\n    isp,\n    org,\n    asOrg,\n    device_type,\n    browser,\n    proxy,\n    hosting,\n    is_bot,\n    first_seen,\n    last_seen,\n    request_count,\n    deviceVendor,\n    deviceModel,\n    browserType,\n    browserVersion,\n    os,\n    Number(activity_score) || 0,\n  ].map(value => value === undefined ? null : typeof value === 'boolean' ? (value ? 1 : 0) : value);\n  const ex = (col: string) => excluded(db, col);\n  const upsert = onUpsert(db, 'canary_id');\n  try {\n    await prep(db,\n      `INSERT INTO visitors (\n         visitor_id,\n         canary_id,\n         ip_address,\n         user_agent,\n         country,\n         region,\n         region_name,\n         city,\n         district,\n         lat,\n         lon,\n         timezone,\n         currency,\n         isp,\n         org,\n         as_org,\n         device_type,\n         browser,\n         proxy,\n         hosting,\n         is_bot,\n         first_seen,\n         last_seen,\n         request_count,\n         deviceVendor,\n         deviceModel,\n         browserType,\n         browserVersion,\n         os,\n         suspicious_activity_score\n       ) VALUES (\n         ${params.map(() => '?').join(', ')}\n       )\n       ${upsert}\n         ip_address = ${ex('ip_address')},\n         user_agent = ${ex('user_agent')},\n         country = ${ex('country')},\n         region = ${ex('region')},\n         region_name = ${ex('region_name')},\n         city = ${ex('city')},\n         district = ${ex('district')},\n         lat = ${ex('lat')},\n         lon = ${ex('lon')},\n         timezone = ${ex('timezone')},\n         currency = ${ex('currency')},\n         isp = ${ex('isp')},\n         org = ${ex('org')},\n         as_org = ${ex('as_org')},\n         device_type = ${ex('device_type')},\n         browser = ${ex('browser')},\n         proxy = ${ex('proxy')},\n         hosting = ${ex('hosting')},\n         last_seen = ${now(db)},\n         request_count = request_count + 1,\n         deviceVendor = ${ex('deviceVendor')},\n         deviceModel = ${ex('deviceModel')},\n         browserType = ${ex('browserType')},\n         browserVersion = ${ex('browserVersion')},\n         os = ${ex('os')}`\n    ).run(...params);\n\n    log.info(`Updated visitors table, Visitor row for canary_id=${cookie ?? ''} inserted/updated successfully.`);\n    return;\n  } catch (err: unknown) {\n    log.error({ err },`ERROR UPDATING visitors TABLE`);\n  }\n}\n","import { getLogger } from '../utils/logger.js';\nimport { getDb } from '../config/config.js';\nimport { prep } from './dialectUtils.js';\n\nexport async function updateScore(score: number, cookie: string) {\n  const params = [score, cookie] satisfies (string | number)[];\n  const db = getDb();\n  const log = getLogger().child({ service: 'BOT DETECTOR', branch: 'db', type: 'updateScore' });\n\n  try {\n    await prep(db, `UPDATE visitors SET suspicious_activity_score = ? WHERE canary_id = ?`).run(...params);\n  } catch (err: unknown) {\n    log.error({ err }, 'ERROR UPDATING SCORE');\n    throw err;\n  }\n}\n\n  ","import { updateBannedIP } from \"./updateBanned.js\";\nimport { updateIsBot } from \"./updateIsBot.js\";\nimport { updateVisitor } from \"./updateVisitors.js\";\nimport { updateScore } from \"./updateVisitorScore.js\";\nimport { getConfiguration } from \"../config/config.js\";\nimport { OpParams, BatchQueueOps, Priority, BatchJob } from \"../types/batchQueue.js\";\nimport { getLogger } from \"@utils/logger.js\";\n\n\nexport class BatchQueue {\n    private jobs = new Map<string, BatchJob>();\n    private timer: NodeJS.Timeout | null = null;\n    private flushPromise: Promise<void> | null = null;\n\n    private get config() {\n        return getConfiguration().batchQueue;\n    }\n\n    private get log() {\n        return getLogger().child({service: 'BOT DETECTOR', branch: 'BatchQueue'});\n    }\n\n    public async addQueue<T extends BatchQueueOps>(\n        canary: string,\n        ipAddress: string,\n        type: T,\n        params: OpParams[T],\n        priority: Priority = 'deferred'\n    ): Promise<void> {\n        const key = `${type}:${canary}:${ipAddress}`;\n        this.jobs.set(key, { id: key, type, priority, params });\n\n        if (priority === 'immediate' || this.jobs.size >= this.config.maxBufferSize) {\n            await this.flush();\n        } else this.timer ??= setTimeout(() => void this.flush(), this.config.flushIntervalMs);\n    }\n\n\n    public async flush(): Promise<void> {\n        while (this.flushPromise || this.jobs.size > 0) {\n            if (this.flushPromise) {\n                await this.flushPromise;\n            }\n            if (this.jobs.size > 0) {\n                if (this.timer) {\n                    clearTimeout(this.timer);\n                    this.timer = null;\n                }\n                const currentBatch = Array.from(this.jobs.values());\n                this.jobs.clear();\n                this.flushPromise = this.executeBatch(currentBatch, 0);\n                try {\n                    await this.flushPromise;\n                } finally {\n                    this.flushPromise = null;\n                }\n            }\n        }\n    }\n\n    private runJob(job: BatchJob): Promise<void> {\n        switch (job.type) {\n            case 'visitor_upsert':\n                return updateVisitor((job.params as OpParams['visitor_upsert']).insert);\n            case 'score_update': {\n                const {score, cookie} = job.params as OpParams['score_update'];\n                return updateScore(score, cookie);\n            }\n            case 'is_bot_update': {\n                const {isBot, cookie} = job.params as OpParams['is_bot_update'];\n                return updateIsBot(isBot, cookie);\n            }\n            case 'update_banned_ip': {\n                const {cookie, ipAddress, country, user_agent, info} = job.params as OpParams['update_banned_ip'];\n                return updateBannedIP(cookie, ipAddress, country, user_agent, info);\n            }\n        }\n    }\n\n    private async executeBatch(batch: BatchJob[], retryCount: number): Promise<void> {\n        try {\n            const visitors = batch.filter(j => j.type === 'visitor_upsert');\n            const others = batch.filter(j => j.type !== 'visitor_upsert');\n            if (visitors.length > 0) {\n                await Promise.all(visitors.map(j => this.runJob(j)));\n            }\n            await Promise.all(others.map(j => this.runJob(j)));\n        } catch (err) {\n            this.log.error({err}, `Batch flush failed (Attempt ${String(retryCount + 1)})`);\n\n            if (retryCount < this.config.maxRetries) {\n                await new Promise(res => setTimeout(res, 1000));\n                return this.executeBatch(batch, retryCount + 1);\n            }\n            this.log.error(\"Max retries reached. Discarding batch.\");\n        }\n    }\n\n    public async shutdown(): Promise<void> {\n        this.log.info(\"Shutting down BatchQueue: Draining remaining jobs...\");\n        await this.flush();\n    }\n}","import { createStorage } from 'unstorage';\nimport memoryDriver from 'unstorage/drivers/memory';\nimport type { Driver } from 'unstorage';\nimport type { CacheConfig } from '../types/storageTypes.js';\n\n\nexport async function initStorage(config?: CacheConfig) {\n\n    if (!config) {\n        // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment\n        return createStorage({ driver: memoryDriver() });\n    }\n\n    const { driver, ...opts } = config;\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    let mod: { default: (opts?: any) => Driver };\n\n    switch (driver) {\n        case 'redis':\n            mod = await import('unstorage/drivers/redis');\n            break;\n        case 'upstash':\n            mod = await import('unstorage/drivers/upstash');\n            break;\n        case 'lru':\n            mod = await import('unstorage/drivers/lru-cache');\n            break;\n        case 'fs':\n            mod = await import('unstorage/drivers/fs-lite');\n            break;\n        case 'cloudflare-kv-binding':\n            mod = await import('unstorage/drivers/cloudflare-kv-binding');\n            break;\n        case 'cloudflare-kv-http':\n            mod = await import('unstorage/drivers/cloudflare-kv-http');\n            break;\n        case 'cloudflare-r2-binding':\n            mod = await import('unstorage/drivers/cloudflare-r2-binding');\n            break;\n        case 'vercel':\n            mod = await import('unstorage/drivers/vercel-runtime-cache');\n            break;\n        default:\n            driver satisfies never;\n            // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n            throw new Error(`Unsupported storage driver: ${driver}`);\n    }\n\n    return createStorage({ driver: mod.default(opts) });\n}\n","import { type Connector, createDatabase, type Database } from 'db0';\nimport type { DbConfig } from '../types/dbTypes.js';\n\n\nexport async function initDb(config: DbConfig): Promise<Database> {\n    const { driver, ...opts } = config;\n    // eslint-disable-next-line @typescript-eslint/no-explicit-any\n    let mod: { default: (opts?: any) => Connector };\n\n    switch (driver) {\n        case 'mysql-pool':\n            mod = await import('./mysqlPoolConnector.js');\n            break;\n        case 'postgresql':\n            mod = await import('db0/connectors/postgresql');\n            break;\n        case 'sqlite':\n            mod = await import('db0/connectors/better-sqlite3');\n            break;\n        case 'cloudflare-d1':\n            mod = await import('db0/connectors/cloudflare-d1');\n            break;\n        case 'planetscale':\n            mod = await import('db0/connectors/planetscale');\n            break;\n        default:\n            // eslint-disable-next-line @typescript-eslint/restrict-template-expressions\n            throw new Error(`Unsupported database driver: ${driver}`);\n    }\n\n    return createDatabase(mod.default(opts));\n}\n","import consola from 'consola';\nimport type { IBotChecker, BanReasonCode } from '../types/checkersTypes.js';\nimport type { BotDetectorConfig } from '../types/configSchema.js';\n\nlet registeredCheckers: IBotChecker<BanReasonCode>[] = [];\n\nexport const CheckerRegistry = {\n  register(checker: IBotChecker<BanReasonCode>) {\n    consola.log(`Loaded plugin: ${checker.name}`);\n    registeredCheckers.push(checker);\n  },\n\n  getEnabled(phase: 'cheap' | 'heavy', config: BotDetectorConfig): IBotChecker<BanReasonCode>[] {\n    return registeredCheckers.filter(\n      checker => checker.phase === phase && checker.isEnabled(config)\n    );\n  },\n\n  clear() {\n    registeredCheckers = [];\n  },\n};\n","import { BanReasonCode, IBotChecker } from '../types/checkersTypes.js';\nimport { BotDetectorConfig } from '../types/configSchema.js';\nimport { ValidationContext } from '../types/botDetectorTypes.js';\nimport { CheckerRegistry } from './CheckerRegistry.js';\nimport { getDataSources } from '../config/config.js';\n\nconst SEVERITY_ORDER = ['critical', 'high', 'medium', 'low'] as const;\ntype Severity = typeof SEVERITY_ORDER[number];\nlet patterns: { rx: RegExp; severity: Severity }[] = [];\n\nexport function loadUaPatterns(): void {\n    const db = getDataSources().getUserAgentLmdb();\n    const bucketStrings = new Map<Severity, string[]>(\n        SEVERITY_ORDER.map(sev => [sev, []])\n    );\n\n    for (const { value } of db.getRange({ limit: 10_000 })) {\n        const sev = value.metadata_severity as Severity;\n        bucketStrings.get(sev)?.push(value.useragent_rx);\n    }\n\n    patterns = SEVERITY_ORDER.map(severity => {\n        const patterns = bucketStrings.get(severity) ?? [];\n        if (patterns.length === 0) return null;\n        \n        const combined = patterns.map(p => `(?:${p})`).join('|');\n        return {\n            rx: new RegExp(combined, 'i'),\n            severity\n        };\n    }).filter((p): p is { rx: RegExp; severity: Severity } => p !== null);\n}\n\nexport class BadUaChecker implements IBotChecker<BanReasonCode> {\n  name = 'Bad User Agent list';\n  phase = 'heavy' as const;\n\n  isEnabled(config: BotDetectorConfig) {\n    return config.checkers.knownBadUserAgents.enable;\n  }\n\n  run(ctx: ValidationContext, config: BotDetectorConfig) {\n    const { knownBadUserAgents } = config.checkers;\n    const reasons: 'BAD_UA_DETECTED'[] = [];\n    let score = 0;\n\n    if (!knownBadUserAgents.enable) return { score, reasons };\n\n    if (patterns.length === 0) {\n        loadUaPatterns();\n    }\n\n    const rawUa = ctx.req.get('User-Agent') ?? '';\n    for (const { rx, severity } of patterns) {\n      if (rx.test(rawUa)) {\n        reasons.push('BAD_UA_DETECTED');\n        switch (severity) {\n          case 'critical': score += knownBadUserAgents.penalties.criticalSeverity; break;\n          case 'high': score += knownBadUserAgents.penalties.highSeverity; break;\n          case 'medium': score += knownBadUserAgents.penalties.mediumSeverity; break;\n          case 'low': score += knownBadUserAgents.penalties.lowSeverity; break;\n        }\n        break;\n      }\n    }\n    return { score, reasons };\n  }\n}\n\nCheckerRegistry.register(new BadUaChecker());","import { createConfigManager } from \"@riavzon/utils\";\nimport type { BotDetectorConfig as Configuration, BotDetectorConfigInput } from \"../types/configSchema.js\";\nimport { configSchema } from \"../types/configSchema.js\";\nimport { DataSources } from \"../helpers/mmdbDataReaders.js\";\nimport { BatchQueue } from \"../db/batchQueue.js\";\nimport { initStorage } from \"./storageAdapter.js\";\nimport type { Storage } from 'unstorage';\nimport { initDb } from \"./dbAdapter.js\";\nimport { type Database } from \"db0\";\nimport { loadUaPatterns } from \"../checkers/badUaChecker.js\";\nimport consola from \"consola\";\n\n\nconst {\n  defineConfiguration,\n  getConfiguration\n} = createConfigManager<Configuration>(configSchema, \"Bot Detector\");\n\nlet globalDataSources: DataSources | undefined;\nlet globalBatchQueue: BatchQueue | undefined;\nlet globalStorage: Storage | undefined;\nlet globalDb: Database | undefined;\n\n/**\n * @description\n * The bot detector library's configuration object.\n * Contains the core configuration to make the library usable client side.\n * @module jwtAuth/config\n * @see {@link ./jwtAuth/types/configSchema.js}\n */\nexport async function configuration(config: BotDetectorConfigInput): Promise<void> {\n  const initDataSourcesTask = async () => {\n    globalDataSources ??= await DataSources.initialize();\n    loadUaPatterns();\n  };\n\n  const initBatchQueueTask = () => {\n    if (!globalBatchQueue) {\n      globalBatchQueue = new BatchQueue();\n      process.on('SIGTERM', () => { void globalBatchQueue?.shutdown().then(() => process.exit(0)); });\n      process.on('SIGINT', () => { void globalBatchQueue?.shutdown().then(() => process.exit(0)); });\n    }\n  };\n\n  const initStorageTask = async () => {\n    globalStorage ??= await initStorage(config.storage);\n  };\n\n  const initDbTask = async () => {\n    globalDb ??= await initDb(config.store.main);\n  };\n\n  await defineConfiguration(config, [\n    initDataSourcesTask,\n    initBatchQueueTask,\n    initStorageTask,\n    initDbTask\n  ]);\n}\n\n\nexport { getConfiguration };\n\nexport function getBatchQueue(): BatchQueue {\n  if (!globalBatchQueue) {\n    consola.trace(\"Premature getBatchQueue() call\");\n    throw new Error('BatchQueue not ready. Call configuration() first.');\n  }\n  return globalBatchQueue;\n}\n\nexport function getStorage(): Storage {\n  if (!globalStorage) {\n    consola.trace(\"Premature getStorage() call\");\n    throw new Error('Storage not ready. Call configuration() first.');\n  }\n  return globalStorage;\n}\n\nexport function getDb(): Database {\n    if (!globalDb) {\n      consola.trace(\"Premature getDb() call\");\n      throw new Error('DB not ready. Call configuration() first.');\n    }\n    return globalDb;\n}\n\nexport function getDataSources(): DataSources {\n  if (!globalDataSources) {\n    consola.trace(\"Premature getDataSources() call\");\n    throw new Error(`##### Must be initialized globally #####\n      Bot Detector: DataSources not ready. Call configuration() first.`\n    );\n  }\n  return globalDataSources;\n}\n","import type { GeoResponse } from \"../types/geoTypes.js\";\nimport { getDataSources } from \"../config/config.js\";\n\nconst norm = (string?: string) => string?.trim().toLowerCase();\n  \nexport function getData(ip: string): GeoResponse {\n  const dataSource = getDataSources();\n  const countryLvl = dataSource.countryDataBase(ip);\n  const cityLvl = dataSource.cityDataBase(ip);\n  const asn = dataSource.asnDataBase(ip);\n  const proxy = dataSource.proxyDataBase(ip);\n  const tor = dataSource.torDataBase(ip);\n\n\n  return {\n    country: norm(countryLvl?.name ?? cityLvl?.name),\n    countryCode: norm(countryLvl?.country_code ?? cityLvl?.country_code),\n    region: norm(cityLvl?.region ?? countryLvl?.region),\n    regionName: norm(cityLvl?.continent ?? cityLvl?.subregion ?? countryLvl?.subregion),\n    subregion: norm(cityLvl?.subregion ?? countryLvl?.subregion),\n    state: norm(cityLvl?.state),\n    zipCode: norm(cityLvl?.zip_code),\n    city: norm(cityLvl?.city ?? cityLvl?.capital ?? countryLvl?.capital),\n    phone: norm(cityLvl?.phone ?? countryLvl?.phone),\n    numericCode: norm(cityLvl?.numericCode ?? countryLvl?.numericCode),\n    native: norm(cityLvl?.native ?? countryLvl?.native),\n    continent: norm(cityLvl?.continent),\n    capital: norm(cityLvl?.capital ?? countryLvl?.capital),\n    district: norm(cityLvl?.state),\n    lat: norm(cityLvl?.latitude),\n    lon: norm(cityLvl?.longitude),\n    timezone: norm(cityLvl?.timezone ?? countryLvl?.timezone),\n    timeZoneName: norm(cityLvl?.timeZoneName ?? countryLvl?.timeZoneName),\n    utc_offset: norm(cityLvl?.utc_offset ?? countryLvl?.utc_offset),\n    tld: norm(cityLvl?.tld ?? countryLvl?.tld),\n    nationality: norm(cityLvl?.nationality ?? countryLvl?.nationality),\n    currency: norm(cityLvl?.currency ?? countryLvl?.currency),\n    iso639: norm(cityLvl?.iso639 ?? countryLvl?.iso639),\n    languages: norm(cityLvl?.languages ?? countryLvl?.languages),\n    isp: norm(asn?.asn_name),\n    org: norm(asn?.asn_id),\n    as_org: norm(asn?.asn_name),\n    proxy: proxy ? true : false,\n    hosting: asn?.classification === \"Content\" || Boolean(tor?.exit_addresses),\n  };\n}","import { Response } from \"express\";\n\ninterface cookies {\n    httpOnly: boolean,\n    sameSite: boolean | \"lax\" | \"strict\" | \"none\";\n    maxAge: number; \n    secure: boolean; \n    expires?: Date;\n    domain?: string;\n    path?: string; \n  }\n\n\n\nexport function makeCookie(res: Response, name: string, value: string, options: cookies) {\n\n  if (name.startsWith(\"__Host-\")) {\n    options.secure = true;\n    options.path = \"/\";\n    delete options.domain;\n  }\n\n  if (name.startsWith(\"__Secure-\")) {\n    options.secure = true;\n  }\n\n    res.cookie(name, value, {\n      httpOnly: options.httpOnly,\n      sameSite: options.sameSite,\n      maxAge: options.maxAge,\n      secure: options.secure,\n      expires: options.expires,\n      domain: options.domain,\n      path: options.path,\n      });\n}\n\n\n","import { ParsedUAResult } from '../types/UAparserTypes.js';\nimport { UAParser, UAParserExt } from 'ua-parser-js';\nimport { isAIBot, isBot } from 'ua-parser-js/helpers';\nimport { CLIs, Crawlers, Fetchers, Libraries } from 'ua-parser-js/extensions';\n\n\nexport function parseUA(userAgent: string | number): ParsedUAResult  {\n\n  \n  const botParser = new UAParser(\n    [Crawlers, CLIs, Fetchers, Libraries] as UAParserExt\n  );\n  \n  const uaString = typeof userAgent === 'string'\n    ? userAgent\n    : String(userAgent);\n\n\n  const result = botParser.setUA(uaString).getResult();\n\n  return {\n    device: result.device.type ?? 'desktop',\n    deviceVendor: result.device.vendor,\n    deviceModel: result.device.model,\n    browser: result.browser.name,\n    browserType: result.browser.type,\n    browserVersion: result.browser.version,\n    os: result.os.name,\n    botAI: isAIBot(result),\n    bot: isBot(result),\n    allResults: result,\n  };\n\n}\nexport default parseUA;\n\n\n\n","import { isIP } from 'node:net';\nimport { IBotChecker } from '../types/checkersTypes.js';\nimport { ValidationContext } from '../types/botDetectorTypes.js';\nimport { BotDetectorConfig } from '../types/configSchema.js';\nimport { CheckerRegistry } from './CheckerRegistry.js';\n\nexport class IpChecker implements IBotChecker<'IP_INVALID'> {\n  name = 'IP Validation';\n  phase = 'cheap' as const;\n\n  isEnabled(config: BotDetectorConfig): boolean {\n    return config.checkers.enableIpChecks.enable;\n  }\n\n   run(ctx: ValidationContext, config: BotDetectorConfig) {\n    const isValid = isIP(ctx.ipAddress) !== 0;\n    return {\n      score: isValid ? 0 : config.banScore,\n      reasons: isValid ? [] : ['IP_INVALID' as const]\n    };\n  }\n}\n\nCheckerRegistry.register(new IpChecker());\n","import { getStorage } from '~~/src/botDetector/config/config.js';\n\nexport interface CachedResult {\n  ip: string;\n  trustedBot: boolean;\n}\n\nconst DNS_TTL_SECONDS = 60 * 60 * 2;\nconst PREFIX = 'dns:';\n\nexport const dnsCache = {\n  async get(ip: string): Promise<CachedResult | null> {\n    return getStorage().getItem<CachedResult>(`${PREFIX}${ip}`);\n  },\n\n  async set(ip: string, entry: CachedResult): Promise<void> {\n    await getStorage().setItem(`${PREFIX}${ip}`, entry, { ttl: DNS_TTL_SECONDS });\n  },\n\n  async delete(ip: string): Promise<void> {\n    await getStorage().removeItem(`${PREFIX}${ip}`);\n  },\n\n  async clear(): Promise<void> {\n    await getStorage().clear();\n  }\n};","import { dnsCache } from '@helpers/cache/dnsLookupCache.js';\nimport dns from 'node:dns/promises';\nimport { getDataSources } from '../../config/config.js';\nimport { getLogger } from '@utils/logger.js';\nimport type { Suffix } from '../../types/suffixes.js';\n\nexport class GoodBotsBase {\n private getDomains(suffix: Suffix): string[] {\n        const allDomains: string[] = [];\n\n        for (const key in suffix) {\n\n        const entry = suffix[key];\n        const entrySuffix = entry.suffix;\n\n        if (Array.isArray(entrySuffix)) {\n            allDomains.push(...entrySuffix);\n\n        } else if (typeof entrySuffix === 'string') {\n            allDomains.push(entrySuffix);\n        }\n        }\n        return allDomains;\n  }\n\n  private domains: string[];\n\n  private _logger?: ReturnType<typeof getLogger>;\n  protected get logger(): ReturnType<typeof getLogger> {\n    this._logger ??= getLogger().child({ service: 'botDetector', branch: 'checker', type: 'GoodBotsBase' });\n    return this._logger;\n  }\n\n  constructor(protected suffixes: Suffix) {\n    this.domains = this.getDomains(this.suffixes).map(d => `.${d.toLowerCase()}`);\n  }\n\n  protected async isBotFromTrustedDomain(ip: string): Promise<boolean> {\n        const cached = await dnsCache.get(ip);\n        if (cached) {\n            return cached.trustedBot;\n        }\n\n        try {\n    \n            const hostnames = await dns.reverse(ip);          \n        \n            const matchingHosts = hostnames.filter(host =>\n                this.domains.some(domain => host.endsWith(domain))\n            );\n\n            if (matchingHosts.length === 0) {\n                dnsCache.set(ip, { ip, trustedBot: false }).catch((err: unknown) => {\n                    this.logger.error({ err }, 'Failed to save dnsCache in storage');\n                });\n                return false;\n            }\n            for (const host of matchingHosts) {\n                const addresses = await dns.lookup(host, { all: true });\n\n                if (addresses.some(a => a.address === ip)) {\n                    dnsCache.set(ip, { ip, trustedBot: true }).catch((err: unknown) => {\n                        this.logger.error({ err }, 'Failed to save dnsCache in storage');\n                    });\n\n                    return true;\n                }\n            }\n        } catch(err: unknown) {\n            this.logger.error({ err }, 'DNS reverse lookup failed');\n        }\n            dnsCache.set(ip, { ip, trustedBot: false }).catch((err: unknown) => {\n                this.logger.error({ err }, 'Failed to save dnsCache in storage');\n            });\n            return false;\n  }\n\n  protected isBotIPTrusted(ipAddress: string): boolean {\n    \n    const dataSources = getDataSources();\n    const isKnownBot = dataSources.goodBotsDataBase(ipAddress) !== null;\n  \n    return isKnownBot; \n  }\n}","import fs from 'node:fs';\nimport type { IBotChecker } from \"../../types/checkersTypes.js\";\nimport type { ValidationContext } from \"../../types/botDetectorTypes.js\";\nimport type { BotDetectorConfig } from \"../../types/configSchema.js\";\nimport { CheckerRegistry } from \"../CheckerRegistry.js\";\nimport { GoodBotsBase } from \"./base.js\";\nimport type { Suffix } from '../../types/suffixes.js';\nimport { resolveDataPath } from '@db/findDataPath.js';\n\nconst suffixPath = resolveDataPath('suffix.json');\nconst suffixes = JSON.parse(fs.readFileSync(suffixPath, 'utf-8')) as Suffix;\n\nconst userAgents: string[] = Object.values(suffixes)\n  .flatMap((e) =>\n    Array.isArray(e.useragent) ? e.useragent : [e.useragent]\n  )\n  .map(u => u.toLowerCase());\n  \nexport class GoodBotsChecker extends GoodBotsBase implements IBotChecker<'BAD_BOT_DETECTED' | 'GOOD_BOT_IDENTIFIED'> {\n  name = 'Good/Bad Bot Verification';\n  phase = 'cheap' as const;\n\n  constructor() {\n    super(suffixes);\n  }\n\n  isEnabled(config: BotDetectorConfig): boolean {\n    return config.checkers.enableGoodBotsChecks.enable;\n  }\n\n  async run(ctx: ValidationContext, config: BotDetectorConfig) {\n    const browserType = (ctx.parsedUA.browserType ?? '').toLowerCase();\n    const browserName = (ctx.parsedUA.browser ?? '').toLowerCase();\n    const ipAddress = ctx.ipAddress;\n    \n    const score = 0;\n    const reasons: ('BAD_BOT_DETECTED' | 'GOOD_BOT_IDENTIFIED')[] = [];\n\n    const checkersConfig = config.checkers.enableGoodBotsChecks;\n    if (!checkersConfig.enable) return { score, reasons };\n\n    if (browserType !== 'crawler' && browserType !== 'fetcher') {\n      return { score: 0, reasons: [] };\n    }\n\n    const name = browserName;\n    const botsWithoutSuffix  = ['duckduckbot','gptbot','oai-searchbot','chatgpt-user'].includes(name);\n    const botsWithSuffix = userAgents.some(suf => name.includes(suf));\n\n    if (checkersConfig.banUnlistedBots && !botsWithoutSuffix && !botsWithSuffix) {\n        reasons.push('BAD_BOT_DETECTED');\n        return { score: 0, reasons };   \n    }\n\n    let trusted: boolean;\n\n    if (botsWithSuffix) {\n      trusted = await this.isBotFromTrustedDomain(ipAddress);\n    } else {\n      trusted = this.isBotIPTrusted(ipAddress);\n    }\n\n    if (!trusted) {\n      reasons.push('BAD_BOT_DETECTED');\n      return {\n        score: checkersConfig.penalties,\n        reasons\n      };\n    }\n\n    reasons.push('GOOD_BOT_IDENTIFIED');\n    return { score, reasons };\n  }\n}\n\nCheckerRegistry.register(new GoodBotsChecker());\n","import { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\n\nexport class BrowserDetailsAndDeviceChecker implements IBotChecker<BanReasonCode> {\n  name = 'Browser and Device Verification';\n  phase = 'cheap' as const;\n\n  isEnabled(config: BotDetectorConfig): boolean {\n    return config.checkers.enableBrowserAndDeviceChecks.enable;\n  }\n\n   run(ctx: ValidationContext, config: BotDetectorConfig) {\n    const checkConfig = config.checkers.enableBrowserAndDeviceChecks;\n    const reasons: BanReasonCode[] = [];\n    let score = 0;\n\n    if (!checkConfig.enable) return { score, reasons };\n    const penalties = checkConfig.penalties;\n\n    const bType = ctx.parsedUA.browserType;\n    const bName = ctx.parsedUA.browser ?? \"\";\n    const bOS = ctx.parsedUA.os ?? \"\";\n    const dType = ctx.parsedUA.device ?? \"desktop\";\n\n    if (bType === 'cli' || bType === 'library') {\n        score += penalties.cliOrLibrary;\n        reasons.push('CLI_OR_LIBRARY');\n    } \n\n    if (['ie','iemobile','internet explorer'].includes(bName.toLowerCase())) {\n        score += penalties.internetExplorer; \n        reasons.push('INTERNET_EXPLORER');\n    }\n\n    if (bOS.toLowerCase().includes('kali')) {\n        score += penalties.linuxOs; \n        reasons.push('KALI_LINUX_OS');\n    }\n\n    if (bOS === 'Mac OS' && dType === 'mobile') {\n        score += penalties.impossibleBrowserCombinations; \n        reasons.push('IMPOSSIBLE_BROWSER_COMBINATION' as BanReasonCode);\n    }\n\n    if (bName === 'Safari' && bOS === 'Windows') {\n        score += penalties.impossibleBrowserCombinations; \n        reasons.push('IMPOSSIBLE_BROWSER_COMBINATION' as BanReasonCode);\n    }\n\n    if (dType === 'desktop' && ctx.parsedUA.deviceVendor) {\n        score += penalties.impossibleBrowserCombinations; \n        reasons.push('IMPOSSIBLE_BROWSER_COMBINATION' as BanReasonCode);\n    }\n\n    if (!bType && (!bName || dType !== 'desktop')) {\n        score += penalties.browserTypeUnknown;\n        reasons.push('BROWSER_TYPE_UNKNOWN');\n    }\n\n    if (!bName) {\n        score += penalties.browserNameUnknown;\n        reasons.push('BROWSER_NAME_UNKNOWN');\n    }\n\n    if (dType === 'desktop' && !bOS) {\n        score += penalties.desktopWithoutOS; \n        reasons.push('DESKTOP_WITHOUT_OS');\n    }\n\n    if (dType !== 'desktop' && !ctx.parsedUA.deviceVendor) {\n        score += penalties.deviceVendorUnknown;\n        reasons.push('DEVICE_VENDOR_UNKNOWN');\n    }\n\n    if (!ctx.parsedUA.browserVersion) {\n        score += penalties.browserVersionUnknown; \n        reasons.push('BROWSER_VERSION_UNKNOWN');\n    }\n\n    if (!ctx.parsedUA.deviceModel) {\n        score += penalties.deviceModelUnknown; \n        reasons.push('NO_MODEL');\n    }\n\n    return { score, reasons };\n  }\n}\n\nCheckerRegistry.register(new BrowserDetailsAndDeviceChecker());\n","import { anyOf, createRegExp, exactly, digit, letter, maybe } from \"magic-regexp\";\n\nconst space = anyOf(\" \", \"\\t\").times.any();\n\nconst decimalZero = maybe(anyOf(exactly(\".\", digit.times.between(1, 3))));\nconst qZero = exactly(\"0\", decimalZero);\n\nconst decimalOne = maybe(anyOf(exactly(\".\", exactly(\"0\").times.between(1, 3))));\nconst qOne = exactly(\"1\", decimalOne);\n\nconst qValue = anyOf(qZero, qOne);\n\nconst quality = maybe(\n  anyOf(\n    exactly(space, \";\", space, \"q\", space, \"=\", space, qValue)\n  )\n);\n\nconst primaryTag = letter.times.between(1, 8);\nconst subTag = anyOf(\n  exactly(\"-\", anyOf(letter, digit).times.between(1, 8))\n).times.any();\n\nconst acceptLang = anyOf(\n  exactly(\"*\"),\n  exactly(primaryTag, subTag) \n);\n\nconst language = exactly(acceptLang, quality);\nconst repeatingLanguages = anyOf(\n  exactly(space, \",\", space, language)\n).times.any();\n\nexport const acceptLanguageValidator = createRegExp(\n  exactly(language, repeatingLanguages)\n    .at.lineStart()\n    .at.lineEnd(), \n  [\"i\"]\n);","import { acceptLanguageValidator } from \"../utils/regex/acceptLangRegex.js\";\nimport { IBotChecker, BanReasonCode } from \"../types/checkersTypes.js\";\nimport { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\n\nexport class LocaleMapChecker implements IBotChecker<BanReasonCode> {\n  name = 'Locale and Country Verification';\n  phase = 'cheap' as const;\n\n  isEnabled(config: BotDetectorConfig): boolean {\n    return config.checkers.localeMapsCheck.enable;\n  }\n\n   run(ctx: ValidationContext, config: BotDetectorConfig) {\n    const settings = config.checkers.localeMapsCheck;\n    const reasons: BanReasonCode[] = [];\n    let score = 0;\n\n    if (!settings.enable) return { score, reasons };\n\n    const AccHeader = ctx.req.get('Accept-Language') ?? '';\n    if (!AccHeader) {\n      score += settings.penalties.missingHeader;\n      if (score > 0) reasons.push('LOCALE_MISMATCH');\n      return { score, reasons };\n    }\n\n    const isValidHeader = acceptLanguageValidator.test(AccHeader.trim().toLowerCase());\n\n    if (!isValidHeader) {\n        score += settings.penalties.malformedHeader; \n        if (score > 0) reasons.push('LOCALE_MISMATCH');\n        return { score, reasons };\n    }\n\n    const langs = AccHeader\n      .split(',')\n      .map(entry => {\n        const [tag, q] = entry.trim().split(/\\s*;\\s*q\\s*=\\s*/);\n        return { tag: tag.toLowerCase(), weight: q ? parseFloat(q) : 1 };\n      })\n      .sort((a, b) => b.weight - a.weight);\n\n    const country = ctx.geoData.country;\n    const countryCode = ctx.geoData.countryCode;\n    const iso6 = ctx.geoData.iso639;\n\n    if (!country || !countryCode || !iso6) {\n      score += settings.penalties.missingGeoData;\n      if (score > 0) reasons.push('LOCALE_MISMATCH');\n      return { score, reasons };\n    }\n\n    const expectedCountryCode = countryCode.toLowerCase();\n    const expectedLang = iso6.toLowerCase();\n    const combined = `${expectedLang}-${expectedCountryCode}`;\n\n    let localeMatchesGeo = false;\n\n    for (const { tag, weight } of langs) {\n      if (weight === 0) continue;\n      const parts = tag.split(/[-_]/);\n      const langPart = parts[0];\n      const regionPart = parts.find(p => p.length === 2 && p === expectedCountryCode);\n      \n      if (regionPart) {\n          localeMatchesGeo = true;\n          break;\n      }\n\n      if (langPart === expectedLang) {\n          localeMatchesGeo = true;\n          break;\n      }\n\n      if ((langPart && regionPart) && tag === combined) {\n          localeMatchesGeo = true;\n          break;\n      }\n    }\n\n    if (!localeMatchesGeo) {\n      score += settings.penalties.ipAndHeaderMismatch;\n      if (score > 0) reasons.push('LOCALE_MISMATCH');\n    }\n\n    return { score, reasons };\n  }\n}\n\nCheckerRegistry.register(new LocaleMapChecker());","import { getStorage } from '~~/src/botDetector/config/config.js';\n\nexport interface CachedResult {\n  score: number;\n  timestamp: number;\n  request_count: number;\n}\n\nconst RATE_TTL_SECONDS_FALLBACK = 60 * 2;\nconst PREFIX = 'rate:';\n\nexport const rateCache = {\n  async get(cookie: string): Promise<CachedResult | null> {\n    return getStorage().getItem<CachedResult>(`${PREFIX}${cookie}`);\n  },\n\n  async set(cookie: string, entry: CachedResult, ttlSeconds?: number): Promise<void> {\n    await getStorage().setItem(`${PREFIX}${cookie}`, entry, { ttl: ttlSeconds ?? RATE_TTL_SECONDS_FALLBACK });\n  },\n\n  async delete(cookie: string): Promise<void> {\n    await getStorage().removeItem(`${PREFIX}${cookie}`);\n  },\n\n  async clear(): Promise<void> {\n    await getStorage().clear();\n  }\n};","import { rateCache } from '../helpers/cache/rateLimitarCache.js';\nimport { IBotChecker, BanReasonCode } from \"../types/checkersTypes.js\";\nimport { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\nimport { getLogger } from \"@utils/logger.js\";\n\nexport class BehavioralDbChecker implements IBotChecker<BanReasonCode> {\n  name = 'Behavior Rate Verification';\n  phase = 'heavy' as const;\n  private _logger?: ReturnType<typeof getLogger>;\n  private get logger() {\n    this._logger ??= getLogger().child({ service: 'botDetector', branch: 'checker', type: 'BehavioralDbChecker' });\n    return this._logger;\n  }\n\n  isEnabled(config: BotDetectorConfig): boolean {\n    return config.checkers.enableBehaviorRateCheck.enable;\n  }\n\n  async run(ctx: ValidationContext, config: BotDetectorConfig) {\n    const cookie = ctx.cookie ?? '';\n\n    const checkConfig = config.checkers.enableBehaviorRateCheck;\n    if (!checkConfig.enable) return { score: 0, reasons: [] };\n\n    const BEHAVIORAL_THRESHOLD = checkConfig.behavioral_threshold;\n    const BEHAVIORAL_WINDOW = checkConfig.behavioral_window;\n    const BEHAVIORAL_PENALTY = checkConfig.penalties;\n    const ttlSeconds = Math.ceil(BEHAVIORAL_WINDOW / 1000);\n\n    const cached = await rateCache.get(cookie);\n\n    if (cached) {\n      const ageSinceLastSeen = Date.now() - cached.timestamp;\n\n      if (ageSinceLastSeen <= BEHAVIORAL_WINDOW) {\n        const newCount = cached.request_count + 1;\n        const score = newCount > BEHAVIORAL_THRESHOLD ? BEHAVIORAL_PENALTY : 0;\n\n        rateCache.set(cookie, { ...cached, request_count: newCount, score }, ttlSeconds).catch((err: unknown) => {\n          this.logger.error({ err }, 'Failed to save rateCache in storage');\n        });\n\n        return { score, reasons: score ? ['BEHAVIOR_TOO_FAST' as const] : [] };\n      } else {\n        rateCache.set(cookie, { request_count: 1, timestamp: Date.now(), score: 0 }, ttlSeconds).catch((err: unknown) => {\n          this.logger.error({ err }, 'Failed to reset rateCache in storage');\n        });\n\n        return { score: 0, reasons: [] };\n      }\n    }\n\n    return { score: 0, reasons: [] };\n  }\n}\n\nCheckerRegistry.register(new BehavioralDbChecker());","import { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\n\nexport class ProxyIspAndCookieChecker implements IBotChecker<BanReasonCode> {\n  name = 'Proxy, ISP and Cookie Verification';\n  phase = 'heavy' as const;\n\n  isEnabled(config: BotDetectorConfig): boolean {\n    return config.checkers.enableProxyIspCookiesChecks.enable;\n  }\n\n   run(ctx: ValidationContext, config: BotDetectorConfig) {\n    const checkConfig = config.checkers.enableProxyIspCookiesChecks;\n    const reasons: BanReasonCode[] = [];\n    let score = 0;\n\n    if (!checkConfig.enable) return { score, reasons };\n    const { penalties } = checkConfig;\n\n    const cookie = ctx.cookie ?? '';\n    const proxy = ctx.proxy.isProxy;\n    const proxyType = ctx.proxy.proxyType ?? '';\n    const hosting = ctx.geoData.hosting ?? false;\n    const isp = ctx.geoData.isp ?? '';\n    const org = ctx.geoData.org ?? '';\n\n    if (!cookie) {\n      score += penalties.cookieMissing;\n      reasons.push('COOKIE_MISSING');\n    }\n\n    if (proxy) {\n        score += penalties.proxyDetected;\n        reasons.push('PROXY_DETECTED');\n        if (proxyType) {\n            const sourceCount = proxyType.split(',').length;\n            if (sourceCount >= 4) {\n                score += penalties.multiSourceBonus4plus;\n            } else if (sourceCount >= 2) {\n                score += penalties.multiSourceBonus2to3;\n            }\n        }\n    }\n\n    if (hosting) {\n        score += penalties.hostingDetected;\n        reasons.push('HOSTING_DETECTED');\n    }\n\n    if (!isp) {\n        score += penalties.ispUnknown;\n        reasons.push('ISP_UNKNOWN');\n    }\n\n    if (!org) {\n        score += penalties.orgUnknown;\n        reasons.push('ORG_UNKNOWN');\n    }\n\n    return { score, reasons };\n  }\n}\n\nCheckerRegistry.register(new ProxyIspAndCookieChecker());\n","/* eslint-disable @typescript-eslint/no-unnecessary-condition */\nimport { Request } from \"express\";\nimport { UAParser } from \"ua-parser-js\";\nimport { getConfiguration } from \"../../config/config.js\";\n\nexport class HeadersBase {\n    private readonly config = getConfiguration().headerOptions;\n\n    protected mustHaveHeadersChecker(req: Request) {\n        let score = 0;\n        if (req.httpVersion === '1.0') return score += 40;\n        if(!req.get('User-Agent')) score += this.config.weightPerMustHeader;\n        if(!req.accepts) score += this.config.weightPerMustHeader;\n        if(!req.acceptsEncodings) score += this.config.weightPerMustHeader;\n        if(!req.acceptsLanguages) score += this.config.weightPerMustHeader;\n        if (!req.host) score += this.config.weightPerMustHeader;\n        if (!req.get('Upgrade-Insecure-Requests')) score += this.config.weightPerMustHeader;\n        if (!req.get('x-client-id')) score += this.config.weightPerMustHeader;\n        if (req.httpVersion === '1.1' || req.get('Connection')) {\n            if(!req.get('Connection') || req.get('Connection') !== 'keep-alive') score += this.config.connectionHeaderIsClose;\n        }\n        if (!req.get('sec-fetch-mode') || \n            !req.get('sec-fetch-dest') ||\n            !req.get('sec-fetch-site')\n            ) {\n                score += this.config.weightPerMustHeader;\n            }\n\n        return score;\n    }\n\n    protected async engineHeaders(req: Request) {\n        let score = 0;\n        const ua = req.get('User-Agent');\n        const hints = req.headers as Record<string, string>;\n        const { name } = await new UAParser(ua, hints).getEngine().withClientHints();\n\n        if (!name) return score += this.config.missingBrowserEngine;\n        const headers = Object.keys(hints);\n        const containsCh = headers.some(sec => sec.toLowerCase().startsWith('sec-ch-ua'));\n        const containsTe = headers.some(te => te.toLowerCase() === 'te');\n\n        if (name === 'Blink') {\n            if (!containsCh) score += this.config.clientHintsMissingForBlink;\n            if (containsTe) score += this.config.teHeaderUnexpectedForBlink;\n\n        } else if (name === 'Gecko') {\n            if (containsCh) score += this.config.clientHintsUnexpectedForGecko; \n            if (!containsTe) score += this.config.teHeaderMissingForGecko;\n        } else if(name === 'WebKit') {\n            if (containsCh) score += this.config.clientHintsUnexpectedForGecko;\n            if (containsTe) score += this.config.teHeaderUnexpectedForBlink;\n        };\n        return score;\n    }\n\n    protected weirdHeaders(req: Request) {\n        let score = 0;\n        const accept = req.get('accept');\n        \n        if (accept === '*/*') score += this.config.omittedAcceptHeader;\n        if (req.get('x-requested-with') && req.method === 'GET') score += this.config.AJAXHeaderExists;\n        if (req.get('postman-token') || req.get('insomnia')) score += this.config.postManOrInsomiaHeaders;\n\n        const hostHeader = req.get('X-Forwarded-Host');\n        if (hostHeader && req.hostname && hostHeader !== req.hostname) {\n            score += this.config.hostMismatchWeight; \n        }\n\n        if (req.method === 'GET' && req.get('Cache-Control') === 'no-cache' && req.get('Pragma') === 'no-cache') {\n            score += this.config.aggressiveCacheControlOnGet;\n        }\n\n        if (req.get('sec-fetch-site') === 'cross-site' && !req.get('referer')) {\n            score += this.config.crossSiteRequestMissingReferer;\n        }\n\n          const isBrowserRequest = !req.get('x-client-id');   \n          const isTopNavigation  = req.method === 'GET' && req.get('sec-fetch-dest') === 'document';\n\n          if (isBrowserRequest && !isTopNavigation && req.method !== 'GET') {\n            const origin = req.get('origin');\n            if (!origin) {\n                score += this.config.originHeaderIsNULL;\n            } else if (origin !== `${req.protocol}://${req.hostname}`) {\n                score += this.config.originHeaderMismatch;\n            }\n        }\n        const mode = req.get('sec-fetch-mode');\n        if (isBrowserRequest && mode !== 'same-origin' && mode !== 'navigate') score += this.config.inconsistentSecFetchMode;\n\n        return score;   \n    } \n\n}\n","import { Request } from \"express\";\nimport { HeadersBase } from \"./headersBase.js\";\n\nexport class HeaderAnalysis extends HeadersBase {\n    private readonly req: Request;\n\n    constructor(req: Request) {\n        super();\n        this.req = req;\n    }\n\n    public async scoreHeaders() {\n        const missing = this.mustHaveHeadersChecker(this.req);\n        const engines = await this.engineHeaders(this.req);\n        const weird = this.weirdHeaders(this.req);\n        return missing + engines + weird;\n    }\n\n}","import { createRegExp, anyOf, maybe, exactly } from 'magic-regexp';\n\nconst startOrSlash = anyOf(exactly('').at.lineStart(), '/').grouped();\nconst slashOrEnd = anyOf('/', exactly('').at.lineEnd());\n\nexport const pathRules: { re: RegExp; weight: number }[] = [\n  { re: createRegExp(startOrSlash, '.git', slashOrEnd, ['i']), weight: 10 },\n  { re: createRegExp(startOrSlash, '.git/config', slashOrEnd, ['i']), weight: 10 },         \n  { re: createRegExp(startOrSlash, '.env', maybe(anyOf('.local', '.example')), slashOrEnd, ['i']), weight: 10 },\n  { re: createRegExp(startOrSlash, 'wp-admin', slashOrEnd, ['i']), weight: 8 },\n  { re: createRegExp('/wp-json/wp/v2', slashOrEnd, ['i']), weight: 7 },\n  { re: createRegExp('/', anyOf('jenkins', 'hudson').grouped(), slashOrEnd, ['i']), weight: 9 },            \n  { re: createRegExp('/', anyOf('script', 'login').grouped(), '.groovy', slashOrEnd, ['i']), weight: 8 },\n  { re: createRegExp('/actuator/', anyOf('env', 'health', 'metrics'), slashOrEnd, ['i']), weight: 8 },\n  { re: createRegExp('/web.config', slashOrEnd, ['i']), weight: 7 },\n  { re: createRegExp('/.DS_Store', slashOrEnd, ['i']), weight: 4 },\n  { re: createRegExp('/latest/meta-data/iam', slashOrEnd, ['i']), weight: 10 },           \n  { re: createRegExp(startOrSlash, '.aws/credentials', slashOrEnd, ['i']), weight: 10 },           \n  { re: createRegExp('/Dockerfile', slashOrEnd, ['i']), weight: 7 },            \n  { re: createRegExp('/composer.lock', slashOrEnd, ['i']), weight: 7 },            \n  { re: createRegExp('/jnlpJars/jenkins-cli.jar', slashOrEnd, ['i']), weight: 9 },            \n  { re: createRegExp('/manager/html', slashOrEnd, ['i']), weight: 10 },\n  { re: createRegExp('/shell', maybe('.php'), slashOrEnd, ['i']), weight: 10 },           \n  { re: createRegExp('/', anyOf('grafana', 'kibana', 'prometheus').grouped(), slashOrEnd, ['i']), weight: 7 },           \n  { re: createRegExp('/', anyOf('owa', 'ecp').grouped(), slashOrEnd, ['i']), weight: 8 },        \n  { re: createRegExp('wp-login.php', slashOrEnd, ['i']), weight: 8 },            \n  { re: createRegExp('/swagger-ui', anyOf('/', '.html'), slashOrEnd, ['i']), weight: 6 },            \n  { re: createRegExp('/v2/api-docs', slashOrEnd, ['i']), weight: 5 },            \n  { re: createRegExp('/api-docs', anyOf('/', '.json'), slashOrEnd, ['i']), weight: 5 },            \n  { re: createRegExp('phpmyadmin', slashOrEnd, ['i']), weight: 8 },\n  { re: createRegExp(startOrSlash, '.well-known', slashOrEnd, ['i']), weight: 5 },\n  { re: createRegExp(startOrSlash, '.htaccess', slashOrEnd, ['i']), weight: 7 },\n  { re: createRegExp('composer.json', slashOrEnd, ['i']), weight: 7 },            \n  { re: createRegExp('docker-compose.y', maybe('a'), 'ml', slashOrEnd, ['i']), weight: 7 },            \n  { re: createRegExp('.', anyOf('sql', 'bak', 'old', 'save', 'log', 'ini', 'conf', 'zip', exactly('tar', maybe('.gz'))), slashOrEnd, ['i']), weight: 7 },\n  { re: createRegExp(anyOf('..', '%2e%2e').grouped(), anyOf('/', '\\\\'), ['i']), weight: 5 },\n  { re: createRegExp(anyOf('package-lock.json', 'yarn.lock', '.gitignore').grouped(), slashOrEnd, ['i']), weight: 6 },   \n  { re: createRegExp(startOrSlash, 'admin', slashOrEnd, ['i']), weight: 6 },\n  { re: createRegExp('phpinfo', maybe('.php'), slashOrEnd, ['i']), weight: 8 },            \n  { re: createRegExp(startOrSlash, '.ssh', slashOrEnd, ['i']), weight: 8 },\n  { re: createRegExp(exactly('').at.lineStart(), '/xmlrpc.php', slashOrEnd, ['i']), weight: 8 },            \n  { re: createRegExp(startOrSlash, 'wp-config.php', slashOrEnd, ['i']), weight: 10 },           \n  { re: createRegExp(startOrSlash, anyOf('install', 'setup').grouped(), maybe('.php'), slashOrEnd, ['i']), weight: 8 },            \n  { re: createRegExp(startOrSlash, 'backup', maybe('s'), anyOf('.zip', '.tar.gz', '.sql'), slashOrEnd, ['i']), weight: 8 },   \n  { re: createRegExp(startOrSlash, '.gitlab-ci.yml', slashOrEnd, ['i']), weight: 8 },            \n  { re: createRegExp(startOrSlash, '.svn', slashOrEnd, ['i']), weight: 6 },\n  { re: createRegExp(startOrSlash, '.hg', slashOrEnd, ['i']), weight: 6 },\n  { re: createRegExp(startOrSlash, 'CVS', slashOrEnd, ['i']), weight: 6 },\n  { re: createRegExp(startOrSlash, '.vscode', slashOrEnd, ['i']), weight: 4 },\n  { re: createRegExp(startOrSlash, '.htpasswd', slashOrEnd, ['i']), weight: 8 },            \n  { re: createRegExp('phpunit', maybe('.phar'), slashOrEnd, ['i']), weight: 9 },            \n  { re: createRegExp(startOrSlash, 'config', maybe('uration'), '.', anyOf('php', 'yml', 'json', 'xml', 'ini', 'conf', 'cfg'), slashOrEnd, ['i']), weight: 7 },\n];\n\nexport const whiteList: RegExp[] = [\n  createRegExp(\n    exactly('').at.lineStart(), \n    maybe('/'), \n    exactly('').at.lineEnd()\n  ),\n\n  createRegExp(\n    exactly('').at.lineStart(),\n    '/',\n    anyOf('css', 'js', 'images', 'assets', 'static').grouped(),\n    '/',\n    ['i']\n  ),\n\n  createRegExp(\n    '.',\n    anyOf(\n      'html',\n      'css',\n      'js',\n      'png',\n      exactly('jp', maybe('e'), 'g'),\n      'svg',\n      'map',\n      exactly('woff', maybe('2')),\n      'ttf',\n      'webp'\n    ),\n    exactly('').at.lineEnd(),\n    ['i']\n  ),\n\n  createRegExp(\n    exactly('').at.lineStart(),\n    '/robots.txt',\n    exactly('').at.lineEnd(),\n    ['i']\n  ),\n\n  createRegExp(\n    exactly('').at.lineStart(),\n    '/sitemap.xml',\n    exactly('').at.lineEnd(),\n    ['i']\n  ),\n];","import path from 'path';\nimport { URL } from 'url';\nimport { Request } from 'express';\nimport { pathRules, whiteList } from '@utils/regex/pathTravelersRegex.js';\nimport { BotDetectorConfig } from '../../types/configSchema.js';\n\nexport class UaAndHeaderCheckerBase {\n    protected pathScore(req: Request, config: BotDetectorConfig): number {\n        const settings = config.pathTraveler;\n        const MAX_DECODE_ITERATIONS = settings.maxIterations;\n        const MAX_PATH_LENGTH = settings.maxPathLength;\n        \n        let score = 0;\n        const hostHeader = req.get('x-forwarded-host');\n        const base = `${req.protocol}://${hostHeader ?? req.get('host') ?? ''}`;\n        \n        // eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing\n        const rawPath = req.get('x-original-path') || req.originalUrl;\n\n        const traversalRe = /(?:\\.\\.[\\\\/]|\\.\\.%2f|\\.\\.%5c|%2e%2e[\\\\/]|%2e%2e%2f|%2e%2e%5c)/i;\n        if (traversalRe.test(rawPath)) {\n            return settings.traversalDetected;\n        }\n\n        let pathname: string;\n        try {\n\n            const fullUrl = new URL(rawPath, base);\n            pathname = fullUrl.pathname;\n            \n        } catch {\n            pathname = rawPath.split('?')[0];\n        }\n        \n        \n        \n        if (pathname.length > MAX_PATH_LENGTH) {\n            return settings.pathLengthToLong;\n        }\n        \n        \n        if (whiteList.some(rx => rx.test(pathname))) {\n            return 0;\n        }\n        \n        \n        let decoded = pathname;\n        let totalDecodedLength = 0;\n        for (let i = 0; i < MAX_DECODE_ITERATIONS; i++) {\n        try {\n            const tmp = decodeURIComponent(decoded);\n            if (tmp === decoded) break;\n            totalDecodedLength += tmp.length;\n            if (totalDecodedLength > MAX_PATH_LENGTH * 2) {\n            return settings.longDecoding; \n            }\n            decoded = tmp;\n        } catch {\n            break;\n        }\n        }\n        \n        const normalized = path.normalize(decoded);\n        \n        for (const { re, weight } of pathRules) {\n            if (re.test(normalized)) {\n            score += weight;\n            if (score >= 30) break;\n            }\n        }\n        \n        return score;\n    }\n\n    protected tlsBotScore(req: Request, config: BotDetectorConfig): number {\n      const settings = config.checkers.enableUaAndHeaderChecks;\n      if (!settings.enable) return 0;\n      const { penalties } = settings;\n\n      let score = 0;\n      const proto = req.httpVersion === '2.0' ? 'h2'\n                   : req.httpVersion === '1.1' ? 'http/1.1'\n                   : '';\n    \n      // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n      if (!proto || (proto !== 'h2' && proto !== 'http/1.1')) {\n        score += penalties.tlsCheckFailed;\n      }\n    \n      const cipher = req.get('x-client-cipher') ?? '';\n    \n      const browserCiphers = new Set([\n        'TLS_AES_128_GCM_SHA256', 'TLS_AES_256_GCM_SHA384',\n        'TLS_CHACHA20_POLY1305_SHA256',\n        'ECDHE-ECDSA-AES128-GCM-SHA256', 'ECDHE-RSA-AES128-GCM-SHA256',\n        'ECDHE-ECDSA-CHACHA20-POLY1305', 'ECDHE-RSA-CHACHA20-POLY1305',\n        'ECDHE-ECDSA-AES256-GCM-SHA384', 'ECDHE-RSA-AES256-GCM-SHA384',\n        'AEAD-AES128-GCM-SHA256', 'AEAD-AES256-GCM-SHA384',\n        'TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256',\n        'TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256',\n        'TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384',\n        'TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384',\n        'TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256',\n        'TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256'\n      ]);\n    \n      if (!browserCiphers.has(cipher)) score += penalties.tlsCheckFailed;;\n                                              \n      const tlsVersion = (req.get('x-client-tls-version') ?? '').toLowerCase();\n      const vars = [\"tlsv1.3\", \"tlsv1.2\", \"tls1.3\", \"tls1.2\"];\n      if (\n        tlsVersion &&\n        !vars.includes(tlsVersion)\n      ) {\n        score += penalties.tlsCheckFailed; \n      }\n    \n      return score;\n    }\n}","import { BanReasonCode, IBotChecker } from '../../types/checkersTypes.js';\nimport { HeaderAnalysis } from '../headers/headers.js';\nimport { ValidationContext } from \"../../types/botDetectorTypes.js\";\nimport { BotDetectorConfig } from \"../../types/configSchema.js\";\nimport { CheckerRegistry } from \"../CheckerRegistry.js\";\nimport { anyOf, createRegExp } from 'magic-regexp';\nimport { UaAndHeaderCheckerBase } from './base.js';\n\nexport class UaAndHeaderChecker extends UaAndHeaderCheckerBase implements IBotChecker<BanReasonCode> {\n  name = 'User agent and Header Verification';\n  phase = 'heavy' as const;\n\n  isEnabled(config: BotDetectorConfig): boolean {\n    return config.checkers.enableUaAndHeaderChecks.enable;\n  }\n\n  async run(ctx: ValidationContext, config: BotDetectorConfig) {\n    const checkConfig = config.checkers.enableUaAndHeaderChecks;\n    const reasons: BanReasonCode[] = [];\n    let score = 0;\n\n    if (!checkConfig.enable) return { score, reasons };\n    const { penalties } = checkConfig;\n\n    const req = ctx.req;\n    const uaString = req.get(\"User-Agent\") ?? \"\";\n    const uaLower = uaString.toLowerCase();\n    const regex = createRegExp(anyOf('headless', 'puppeteer', 'selenium', 'playwright', 'phantomjs'));\n    \n    if (regex.test(uaLower)) {\n        score += penalties.headlessBrowser;\n        reasons.push('HEADLESS_BROWSER_DETECTED');\n    }\n\n    if (!uaString || uaString.length < 10) {\n        score += penalties.shortUserAgent;\n        reasons.push('SHORT_USER_AGENT');\n    }\n\n    const tlsCheckScore = this.tlsBotScore(req, config);\n    if (tlsCheckScore > 0) {\n        score += tlsCheckScore;\n        reasons.push('TLS_CHECK_FAILED');\n    }\n\n    const headers = new HeaderAnalysis(req);\n    const headerChecker = await headers.scoreHeaders();\n      \n    if (headerChecker > 0) {\n        score += headerChecker;\n        reasons.push('HEADER_SCORE_TOO_HIGH');\n    }\n\n\n    const pathChecker = this.pathScore(req, config);\n    if (pathChecker > 0) {\n        score += pathChecker;\n        reasons.push('PATH_TRAVELER_FOUND');\n    }\n\n    return { score, reasons };\n  }\n}\n\nCheckerRegistry.register(new UaAndHeaderChecker());","import { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\n\nexport class GeoLocationChecker implements IBotChecker<BanReasonCode> {\n  name = 'Geo-Location Verification';\n  phase = 'heavy' as const;\n\n  isEnabled(config: BotDetectorConfig): boolean {\n    return config.checkers.enableGeoChecks.enable;\n  }\n\n  private isAllowedCountry(country: string, bannedCountries: string[]): boolean {\n    const blockedCountries = bannedCountries;\n    return !blockedCountries.includes(country.trim().toLowerCase());\n  }\n\n   run(ctx: ValidationContext, config: BotDetectorConfig) {\n    const checkConfig = config.checkers.enableGeoChecks;\n    const reasons: BanReasonCode[] = [];\n    let score = 0;\n\n    if (!checkConfig.enable) return { score, reasons };\n    const penalties = checkConfig.penalties;\n    const banScore = config.banScore;\n\n    const details = ctx.geoData;\n    const country = details.country;\n    const countryCode = details.countryCode;\n\n    if (countryCode || country) {\n      const banned = checkConfig.bannedCountries;\n      const codeMatch = !!countryCode && !this.isAllowedCountry(countryCode, banned);\n      const nameMatch = !!country && !this.isAllowedCountry(country, banned);\n      if (codeMatch || nameMatch) {\n        score += banScore;\n        reasons.push('BANNED_COUNTRY');\n      }\n\n    } else {\n      score += penalties.countryUnknown;\n      reasons.push('COUNTRY_UNKNOWN');\n    }\n\n    const region = details.region;\n    const regionName = details.regionName;\n    if (!region || !regionName) {\n        score += penalties.regionUnknown;\n        reasons.push('REGION_UNKNOWN');\n    }\n      \n    if (!details.lat || !details.lon) {\n        score += penalties.latLonUnknown;\n        reasons.push('LAT_LON_UNKNOWN');\n    }\n\n    if (!details.district) {\n        score += penalties.districtUnknown; \n        reasons.push('DISTRICT_UNKNOWN');\n    }\n      \n    if (!details.city) {\n        score += penalties.cityUnknown; \n        reasons.push('CITY_UNKNOWN');\n    }\n\n    if (!details.timezone) {\n        score += penalties.timezoneUnknown;\n        reasons.push('TIMEZONE_UNKNOWN');\n    }\n\n    if (!details.subregion) {\n        score += penalties.subregionUnknown; \n        reasons.push('SUBREGION_UNKNOWN' as BanReasonCode);\n    }\n\n    if (!details.phone) {\n        score += penalties.phoneUnknown;\n        reasons.push('PHONE_UNKNOWN' as BanReasonCode);\n    }\n\n    if (!details.continent) {\n        score += penalties.continentUnknown;\n        reasons.push('CONTINENT_UNKNOWN' as BanReasonCode);\n    }\n\n    return { score, reasons };\n  }\n}\n\nCheckerRegistry.register(new GeoLocationChecker());","import { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\n\nexport class ThreatLevels implements IBotChecker<BanReasonCode> {\n    name = 'Known ThreatLevels';\n    phase = 'cheap' as const;\n\n    isEnabled(config: BotDetectorConfig) {\n        return config.checkers.enableKnownThreatsDetections.enable;\n    }\n    \n     run(ctx: ValidationContext, config: BotDetectorConfig) {\n        const { enableKnownThreatsDetections } = config.checkers;\n        const reasons: BanReasonCode[] = [];\n        let score = 0;\n\n        if (!enableKnownThreatsDetections.enable) return { score, reasons };\n        const {anonymiseNetwork, threatLevels} = enableKnownThreatsDetections.penalties;\n\n        if (ctx.anon) {\n            score += anonymiseNetwork;\n            reasons.push('ANONYMITY_NETWORK');\n        }\n\n        switch (ctx.threatLevel) {\n            case 1: {\n                score += threatLevels.criticalLevel1;\n                reasons.push('FIREHOL_L1_THREAT');\n                break;\n            }\n            case 2: {\n                score += threatLevels.currentAttacksLevel2;\n                reasons.push('FIREHOL_L2_THREAT');\n                break;\n            }\n            case 3: {\n                score += threatLevels.threatLevel3;\n                reasons.push('FIREHOL_L3_THREAT');\n                break;\n            }\n\n            case 4: {\n                score += threatLevels.threatLevel4;\n                reasons.push('FIREHOL_L4_THREAT');\n                break;\n            }\n        }\n\n        return { score, reasons };\n    }\n}\n\nCheckerRegistry.register(new ThreatLevels());","import { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\n\nexport class AsnClassificationChecker implements IBotChecker<BanReasonCode> {\n    name = 'ASN Classification';\n    phase = 'cheap' as const;\n\n    isEnabled(config: BotDetectorConfig): boolean {\n        return config.checkers.enableAsnClassification.enable;\n    }\n\n    run(ctx: ValidationContext, config: BotDetectorConfig) {\n        const checkConfig = config.checkers.enableAsnClassification;\n        const reasons: BanReasonCode[] = [];\n        let score = 0;\n\n        if (!checkConfig.enable) return { score, reasons };\n        const { penalties } = checkConfig;\n        const { classification, hits } = ctx.bgp;\n\n        if (!classification) {\n            score += penalties.unknownClassification;\n            reasons.push('ASN_CLASSIFICATION_UNKNOWN');\n            return { score, reasons };\n        }\n\n        if (classification === 'Content') {\n            score += penalties.contentClassification;\n            reasons.push('ASN_HOSTING_CLASSIFIED');\n        }\n\n        const hitsNum = parseInt(hits ?? '', 10);\n        const isLowVisibility = Number.isFinite(hitsNum) && hitsNum >= 0 && hitsNum < penalties.lowVisibilityThreshold;\n\n        if (isLowVisibility) {\n            score += penalties.lowVisibilityPenalty;\n            reasons.push('ASN_LOW_VISIBILITY');\n        }\n\n        if (classification === 'Content' && isLowVisibility) {\n            score += penalties.comboHostingLowVisibility;\n            reasons.push('ASN_HOSTING_LOW_VISIBILITY_COMBO');\n        }\n\n        return { score, reasons };\n    }\n}\nCheckerRegistry.register(new AsnClassificationChecker());\n","import { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\n\nexport class TorAnalysisChecker implements IBotChecker<BanReasonCode> {\n    name = 'Tor Node Analysis';\n    phase = 'cheap' as const;\n\n    isEnabled(config: BotDetectorConfig): boolean {\n        return config.checkers.enableTorAnalysis.enable;\n    }\n\n    private parseFlags(flags: string | undefined): Set<string> {\n        if (!flags) return new Set();\n        return new Set(flags.split(',').map(f => f.trim()));\n    }\n\n\n    private canExitWebTraffic(summary: string | undefined): boolean {\n        if (!summary) return false;\n        try {\n            const policy = JSON.parse(summary) as { accept?: string[]; reject?: string[] };\n\n            const coversWebPort = (entry: string): boolean => {\n                if (entry === '80' || entry === '443') return true;\n                if (entry.includes('-')) {\n                    const [lo, hi] = entry.split('-').map(Number);\n                    return (lo <= 80 && 80 <= hi) || (lo <= 443 && 443 <= hi);\n                }\n                return false;\n            };\n\n            if (policy.accept) {\n                return policy.accept.some(coversWebPort);\n            }\n\n            if (policy.reject) {\n                return !policy.reject.some(coversWebPort);\n            }\n        } catch {}\n        \n        return false;\n    }\n\n    run(ctx: ValidationContext, config: BotDetectorConfig) {\n        const checkConfig = config.checkers.enableTorAnalysis;\n        const reasons: BanReasonCode[] = [];\n        let score = 0;\n\n        if (!checkConfig.enable) return { score, reasons };\n        // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n        if (!ctx.tor || Object.keys(ctx.tor).length === 0) return { score, reasons };\n\n        const { penalties } = checkConfig;\n        const {\n            running,\n            exit_addresses,\n            flags,\n            recommended_version,\n            version_status,\n            exit_probability,\n            exit_policy_summary,\n            guard_probability,\n        } = ctx.tor;\n\n        const flagSet = this.parseFlags(flags);\n\n        if (running) {\n            score += penalties.runningNode;\n            reasons.push('TOR_ACTIVE_NODE');\n        }\n\n        const isExitNode = (exit_addresses && exit_addresses.length > 0) ?? flagSet.has('Exit');\n        if (isExitNode) {\n            score += penalties.exitNode + Math.ceil((exit_probability ?? 0) * 30);\n            reasons.push('TOR_EXIT_NODE');\n\n            if (this.canExitWebTraffic(exit_policy_summary)) {\n                score += penalties.webExitCapable;\n                reasons.push('TOR_WEB_EXIT_CAPABLE');\n            }\n        }\n\n        if (flagSet.has('BadExit')) {\n            score += penalties.badExit;\n            reasons.push('TOR_BAD_EXIT');\n        }\n\n        if (flagSet.has('Guard') || (guard_probability ?? 0) > 0) {\n            score += penalties.guardNode;\n            reasons.push('TOR_GUARD_NODE');\n        }\n\n        if (recommended_version === false || version_status === 'obsolete') {\n            score += penalties.obsoleteVersion;\n            reasons.push('TOR_OBSOLETE_VERSION');\n        }\n\n        return { score, reasons };\n    }\n}\n\nCheckerRegistry.register(new TorAnalysisChecker());","import { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\n\nexport class TimezoneConsistencyChecker implements IBotChecker<BanReasonCode> {\n    name = 'Timezone Consistency';\n    phase = 'cheap' as const;\n\n    isEnabled(config: BotDetectorConfig): boolean {\n        return config.checkers.enableTimezoneConsistency.enable;\n    }\n\n    run(ctx: ValidationContext, config: BotDetectorConfig) {\n        const checkConfig = config.checkers.enableTimezoneConsistency;\n        const reasons: BanReasonCode[] = [];\n        let score = 0;\n\n        if (!checkConfig.enable) return { score, reasons };\n\n        const geoTimezone = ctx.geoData.timezone?.toLowerCase();\n        if (!geoTimezone) return { score, reasons };\n\n        const tzHeader = ctx.req.get('Sec-CH-UA-Timezone') ?? ctx.req.get('X-Timezone');\n        if (tzHeader && tzHeader.toLowerCase() !== geoTimezone) {\n            score += checkConfig.penalties;\n            reasons.push('TZ_HEADER_GEO_MISMATCH');\n        }\n\n        return { score, reasons };\n    }\n}\nCheckerRegistry.register(new TimezoneConsistencyChecker());\n","import { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\n\nexport class HoneypotChecker implements IBotChecker<BanReasonCode> {\n    name = 'Honeypot Path';\n    phase = 'cheap' as const;\n\n    isEnabled(config: BotDetectorConfig): boolean {\n        return config.checkers.honeypot.enable;\n    }\n\n    run(ctx: ValidationContext, config: BotDetectorConfig) {\n        const checkConfig = config.checkers.honeypot;\n        const reasons: BanReasonCode[] = [];\n\n        if (!checkConfig.enable || checkConfig.paths.length === 0) {\n            return { score: 0, reasons };\n        }\n\n        const requestPath = ctx.req.path.toLowerCase();\n        const hit = checkConfig.paths.some(p => requestPath === p.toLowerCase());\n\n        if (hit) {\n            reasons.push('HONEYPOT_PATH_HIT');\n            reasons.push('BAD_BOT_DETECTED');\n        }\n\n        return { score: 0, reasons };\n    }\n}\n\nCheckerRegistry.register(new HoneypotChecker());","import consola from 'consola';\nimport { getStorage } from '~~/src/botDetector/config/config.js';\n\nexport interface SessionEntry {\n  lastPath: string;\n}\n\nconst SESSION_TTL_SECONDS = 600;\nconst PREFIX = 'session:';\n\nexport const sessionCache = {\n  async get(sessionId: string): Promise<SessionEntry | null> {\n    const key = `${PREFIX}${sessionId}`;\n    const storage = getStorage();\n    const data = await storage.getItem<SessionEntry>(key);\n\n    if (data) {\n      storage.setItem(key, data, { ttl: SESSION_TTL_SECONDS }).catch((err: unknown) => {\n        consola.warn(`Failed to update session TTL for ${key}`, err);\n      });\n    }\n\n    return data;\n  },\n\n  async set(sessionId: string, entry: SessionEntry): Promise<void> {\n    const key = `${PREFIX}${sessionId}`;\n    await getStorage().setItem(key, entry, { ttl: SESSION_TTL_SECONDS });\n  },\n\n  async delete(sessionId: string): Promise<void> {\n    const key = `${PREFIX}${sessionId}`;\n    await getStorage().removeItem(key);\n  },\n\n  async clear(): Promise<void> {\n    await getStorage().clear();\n  }\n\n};","import { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\nimport { sessionCache } from \"../helpers/cache/sessionCache.js\";\nimport { getLogger } from \"@utils/logger.js\";\n\nexport class SessionCoherenceChecker implements IBotChecker<BanReasonCode> {\n    name = 'Session Coherence';\n    phase = 'heavy' as const;\n    \n    private _logger?: ReturnType<typeof getLogger>;\n    private get logger() {\n        this._logger ??= getLogger().child({service: 'botDetector', branch: 'checker', type: 'SessionCoherenceChecker'});\n        return this._logger;\n    }\n\n    isEnabled(config: BotDetectorConfig): boolean {\n        return config.checkers.enableSessionCoherence.enable;\n    }\n\n    async run(ctx: ValidationContext, config: BotDetectorConfig) {\n        const checkConfig = config.checkers.enableSessionCoherence;\n        const reasons: BanReasonCode[] = [];\n        let score = 0;\n\n        if (!checkConfig.enable) return { score, reasons };\n        if (!ctx.cookie) return { score, reasons };\n\n        const currentPath = ctx.req.path;\n        const refererHeader = ctx.req.get('Referer');\n        const secFetchSite = ctx.req.get('Sec-Fetch-Site');\n        const currentHostname = ctx.req.hostname;\n        const cached = await sessionCache.get(ctx.cookie);\n\n        const missingSameOriginReferer = secFetchSite === 'same-origin' && !refererHeader;\n        const missingSubsequentReferer = cached && !refererHeader;\n\n        if (missingSameOriginReferer || missingSubsequentReferer) {\n            score += checkConfig.penalties.missingReferer;\n            reasons.push('SESSION_COHERENCE_MISSING_REFERER');\n        }\n\n        else if (refererHeader) {\n            try {\n                const refererUrl = new URL(refererHeader);\n\n                if (refererUrl.hostname !== currentHostname) {\n                    score += checkConfig.penalties.domainMismatch;\n                    reasons.push('SESSION_COHERENCE_DOMAIN_MISMATCH');\n                } \n\n                else if (cached && refererUrl.pathname !== cached.lastPath) {\n                    score += checkConfig.penalties.pathMismatch;\n                    reasons.push('SESSION_COHERENCE_PATH_MISMATCH');\n                }\n            } catch {\n                score += checkConfig.penalties.missingReferer; \n                reasons.push('SESSION_COHERENCE_INVALID_REFERER');\n            }\n        }\n\n        sessionCache.set(ctx.cookie, { lastPath: currentPath }).catch((err: unknown) => {\n            this.logger.error({err}, 'Failed to save session in storage.');\n        });\n        \n        return { score, reasons };\n    }\n}\n\nCheckerRegistry.register(new SessionCoherenceChecker());","import { getStorage } from '~~/src/botDetector/config/config.js';\n\nconst TIMING_TTL_SECONDS = 60 * 15;\nconst PREFIX = 'timing:';\n\nexport const timingCache = {\n  async get(visitorId: string): Promise<number[] | null> {\n    const key = `${PREFIX}${visitorId}`;\n    return await getStorage().getItem<number[]>(key);\n  },\n\n  async set(visitorId: string, entry: number[]): Promise<void> {\n    const key = `${PREFIX}${visitorId}`;\n    await getStorage().setItem(key, entry, { ttl: TIMING_TTL_SECONDS });\n  },\n\n  async delete(visitorId: string): Promise<void> {\n    const key = `${PREFIX}${visitorId}`;\n    await getStorage().removeItem(key);\n  },\n\n  async clear(): Promise<void> {\n    await getStorage().clear();\n  }\n\n};","import { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\nimport { timingCache } from \"../helpers/cache/timingCache.js\";\nimport { getLogger } from \"@utils/logger.js\";\n\nconst MAX_SAMPLES = 10;\nconst MIN_SAMPLES_TO_EVALUATE = 5;\n\nexport class VelocityFingerprintChecker implements IBotChecker<BanReasonCode> {\n    name = 'Velocity Fingerprinting';\n    phase = 'heavy' as const;\n    private _logger?: ReturnType<typeof getLogger>;\n    private get logger() {\n        this._logger ??= getLogger().child({service: 'botDetector', branch: 'checker', type: 'VelocityFingerprintChecker'});\n        return this._logger;\n    }\n\n    isEnabled(config: BotDetectorConfig): boolean {\n        return config.checkers.enableVelocityFingerprint.enable;\n    }\n\n   async run(ctx: ValidationContext, config: BotDetectorConfig) {\n        const checkConfig = config.checkers.enableVelocityFingerprint;\n        const reasons: BanReasonCode[] = [];\n        let score = 0;\n\n        if (!checkConfig.enable || !ctx.cookie) return { score, reasons };\n\n        const now = Date.now();\n        const existing = await timingCache.get(ctx.cookie) ?? [];\n        const timestamps = [...existing, now].slice(-MAX_SAMPLES);\n\n        timingCache.set(ctx.cookie, timestamps).catch((err: unknown) => {\n            this.logger.error({err}, 'Failed to save timingCache in storage');\n        });\n\n        if (timestamps.length < MIN_SAMPLES_TO_EVALUATE) return { score, reasons };\n\n        const intervals: number[] = [];\n        for (let i = 1; i < timestamps.length; i++) {\n            intervals.push(timestamps[i] - timestamps[i - 1]);\n        }\n\n        const mean = intervals.reduce((a, b) => a + b, 0) / intervals.length;\n        if (mean === 0) return { score, reasons };\n\n        const variance = intervals.reduce((a, b) => a + Math.pow(b - mean, 2), 0) / intervals.length;\n        const cv = Math.sqrt(variance) / mean;\n\n        if (cv < checkConfig.cvThreshold) {\n            score += checkConfig.penalties;\n            reasons.push('TIMING_TOO_REGULAR');\n        }\n\n        return { score, reasons };\n    }\n}\nCheckerRegistry.register(new VelocityFingerprintChecker());","import { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { CheckerRegistry } from \"./CheckerRegistry.js\";\nimport { getDataSources } from \"../config/config.js\";\n\n\nexport class KnownBadIps implements IBotChecker<BanReasonCode> {\n    name = 'KnownBadIps';\n    phase = 'cheap' as const;\n\n    isEnabled(config: BotDetectorConfig) {\n        return config.checkers.enableKnownBadIpsCheck.enable;\n    }\n\n    run(ctx: ValidationContext, config: BotDetectorConfig) {\n        const { enableKnownBadIpsCheck } = config.checkers;\n        const reasons: BanReasonCode[] = [];\n        let score = 0;\n\n        if (!enableKnownBadIpsCheck.enable) return { score, reasons };\n\n        const ds = getDataSources();\n        const ip = ctx.ipAddress;\n\n        const banned = ds.bannedDataBase(ip);\n        if (banned) {\n            reasons.push('PREVIOUSLY_BANNED_IP', 'BAD_BOT_DETECTED');\n            return { score, reasons };\n        }\n\n        const highRisk = ds.highRiskDataBase(ip);\n        if (highRisk) {\n            const ratio = Math.min(highRisk.score / config.banScore, 1);\n            score += Math.round(enableKnownBadIpsCheck.highRiskPenalty * ratio);\n            reasons.push('PREVIOUSLY_HIGH_RISK_IP');\n        }\n\n        return { score, reasons };\n    }\n}\n\nCheckerRegistry.register(new KnownBadIps());","export class BadBotDetected extends Error {\n  constructor(message = 'Bad bot detected') {\n    super(message);\n    this.name = 'BadBotDetected';\n  }\n}\n\nexport class GoodBotDetected extends Error {\n  constructor(message = 'Good bot detected') {\n    super(message);\n    this.name = 'GoodBotDetected';\n  }\n}\n","import { spawn } from 'child_process';\nimport type { BannedInfo } from '../types/checkersTypes.js';\nimport { getLogger } from '../utils/logger.js';\nimport { getConfiguration } from \"../config/config.js\";\n\nconst UFW = '/usr/sbin/ufw';\n\n\nexport function banIp(ip: string, info: BannedInfo): Promise<void> | void { \n  const log = getLogger().child({service: 'BOT DETECTOR', branch: `banIp`, ipAddress: ip, details: info});\n  const {punishmentType} = getConfiguration();\n\n  if (!punishmentType.enableFireWallBan) {\n    log.info(`Firewall punishment ban is disabled, skipping`);\n    return;\n  }\n\n  log.info('about to ban an IP');\n  return new Promise((resolve, reject) => {\n    const child = spawn('sudo', ['-n', UFW, 'insert', '1', 'deny', 'from', ip], {\n      stdio: ['ignore', 'ignore', 'pipe'],\n      detached: true  \n    });\n    child.unref();  \n\n    let stderr = '';\n    const timer = setTimeout(() => {\n      child.kill('SIGKILL');\n      log.warn(`ufw hang timeout on ${ip}`);\n      reject(new Error(`ufw hang timeout on ${ip}`));\n    }, 5_000);\n\n    child.stderr.on('data', (d: Buffer | string) => (stderr += String(d)));\n    child.on('error', err => {\n      clearTimeout(timer);\n      log.fatal({err},`- CRITICAL - UFW spawn failed`);\n      reject(err);\n    });\n    child.on('close', code => {\n      clearTimeout(timer);\n      if (code !== 0) {\n        log.fatal({code},`- CRITICAL - UFW ban failed`);\n        reject(new Error(`ufw exited ${String(code)}`)); return;\n      }\n      log.info(`Banning Detected Bot/Malicious User. IP ${ip} banned (score ${String(info.score)})\\nReasons:\\n- ${info.reasons.join('\\n- ')}`);\n      resolve();\n    });\n  });\n}\n","import type { BanReasonCode, IBotChecker } from \"../types/checkersTypes.js\";\nimport { getLogger } from \"../utils/logger.js\";\nimport { performance } from 'perf_hooks';\nimport { getConfiguration } from \"../config/config.js\";\nimport type { ValidationContext } from \"../types/botDetectorTypes.js\";\nimport type { BotDetectorConfig } from \"../types/configSchema.js\";\nimport { BadBotDetected, GoodBotDetected } from \"./exceptions.js\";\n\nexport async function processChecks(\n  checkers: IBotChecker<BanReasonCode, unknown>[],\n  ctx: ValidationContext<unknown>,\n  config: BotDetectorConfig,\n  botScore: number,\n  reasons: BanReasonCode[],\n  phaseLabel = 'phase' \n): Promise<number> {\n\n    const {banScore} = getConfiguration();\n    const log = getLogger().child({service: `BOT DETECTOR`, branch: 'checks'});\n    const reqId = Date.now(); \n\n    const phaseStart = performance.now();\n    log.info({ phase: phaseLabel, reqId, event: 'start' });\n                 \n    const banLimit = banScore;\n\n    for (const checker of checkers) {\n      const label = checker.name;\n\n      const checkStart = performance.now();\n      log.info({ reqId, check: label, event: 'start' });\n\n      const { score, reasons: rs } = await checker.run(ctx, config);\n\n      const checkEnd = performance.now();\n      log.info({reqId,check: label,event: 'end',durationMs: +(checkEnd - checkStart).toFixed(3),score,reasons: rs,});\n\n      botScore += score;\n      rs.forEach(r => reasons.push(r));\n  \n      if (rs.includes('GOOD_BOT_IDENTIFIED')) throw new GoodBotDetected();\n      if (rs.includes('BAD_BOT_DETECTED')) throw new BadBotDetected();\n\n      if (botScore >= banLimit) {\n      log.warn({ reqId, botScore }, 'Bot detected — aborting checks');\n        break;\n      }\n    }\n  const phaseEnd = performance.now();\n  log.info({\n    reqId,\n    phase: phaseLabel,\n    event: 'end',\n    durationMs: +(phaseEnd - phaseStart).toFixed(3),\n    Score: botScore\n  });\n    return botScore;\n}","import { getStorage, getConfiguration } from '../../config/config.js';\n\nexport interface CachedResult {\n  isBot: boolean;\n  score: number;\n}\n\nconst PREFIX = 'reputation:';\n\nexport const reputationCache = {\n  async get(cookie: string): Promise<CachedResult | null> {\n    return getStorage().getItem<CachedResult>(`${PREFIX}${cookie}`);\n  },\n\n  async set(cookie: string, entry: CachedResult): Promise<void> {\n    const { checksTimeRateControl } = getConfiguration();\n    await getStorage().setItem(`${PREFIX}${cookie}`, entry, { ttl: Math.floor(checksTimeRateControl.checkEvery / 1000) });\n  },\n\n  async delete(cookie: string): Promise<void> {\n    await getStorage().removeItem(`${PREFIX}${cookie}`);\n  },\n\n  async clear(): Promise<void> {\n    await getStorage().clear();\n  }\n};","import './botDetector/checkers/index.js'; \nimport { Request } from 'express';\nimport { CheckerRegistry } from './botDetector/checkers/CheckerRegistry.js';\nimport { ValidationContext } from './botDetector/types/botDetectorTypes.js';\nimport { BadBotDetected, GoodBotDetected } from './botDetector/helpers/exceptions.js';\nimport { banIp } from './botDetector/penalties/banIP.js';\nimport type { ParsedUAResult } from './botDetector/types/UAparserTypes.js';\nimport type { GeoResponse } from './botDetector/types/geoTypes.js';\nimport { BanReasonCode } from './botDetector/types/checkersTypes.js';\nimport { processChecks } from './botDetector/helpers/processChecks.js';\nimport { reputationCache } from './botDetector/helpers/cache/reputationCache.js';\nimport { getLogger } from './botDetector/utils/logger.js';\nimport { getConfiguration, getDataSources, getBatchQueue } from './botDetector/config/config.js';\n\nexport async function uaAndGeoBotDetector(\n  req: Request,\n  ipAddress: string,\n  userAgent: string,\n  geo: GeoResponse,\n  parsedUA: ParsedUAResult,\n  buildCustomContext?: (req: Request) => unknown,\n): Promise<boolean> {\n  \n  const log = getLogger().child({service: 'BOT DETECTOR', branch: 'main'});\n  const {banScore, maxScore, setNewComputedScore} = getConfiguration();\n  const BAN_THRESHOLD = banScore;\n  const MAX_SCORE = maxScore;\n\n  const reasons: BanReasonCode[] = [];\n  let botScore = 0;\n  const cookie: string | undefined = req.cookies.canary_id as string | undefined; \n  const uaString = req.get(\"User-Agent\") ?? \"\";\n  log.info(`BotDetection called for ${req.method} ${req.get('X-Forwarded-Host') ?? ''}`);\n\n  const threatsLevels = getDataSources().fireholLvl1DataBase(ipAddress) ? 1 :\n                      getDataSources().fireholLvl2DataBase(ipAddress) ? 2 :\n                      getDataSources().fireholLvl3DataBase(ipAddress) ? 3 :\n                      getDataSources().fireholLvl4DataBase(ipAddress) ? 4 : null as 1 | 2 | 3 | 4 | null;\n\n  const proxy = () => {\n    const isProxy = getDataSources().proxyDataBase(ipAddress);\n    if (isProxy) {\n      return {\n        proxy: true,\n        proxyType: isProxy.comment\n      };\n    }\n    return { proxy: false };\n  };\n  \n  const {tor, asn, threatLevel, anon} = {\n    tor: getDataSources().torDataBase(ipAddress),\n    asn: getDataSources().asnDataBase(ipAddress),\n    threatLevel: threatsLevels,\n    anon: getDataSources().fireholAnonDataBase(ipAddress) ? true : false,\n  };\n\n  const proxyResult = proxy();\n  const ctx: ValidationContext<unknown> = {\n    req,\n    ipAddress,\n    parsedUA: parsedUA,\n    geoData: geo,\n    cookie,\n    proxy: {\n      isProxy: proxyResult.proxy,\n      proxyType: proxyResult.proxyType\n    },\n    anon,\n    bgp: asn ?? {},\n    tor: tor ?? {},\n    threatLevel,\n    custom: buildCustomContext ? buildCustomContext(req) : {},\n  };\n\n  const cheapChecks = CheckerRegistry.getEnabled('cheap', getConfiguration());\n  const checks = CheckerRegistry.getEnabled('heavy', getConfiguration());\n\n  try {\n    botScore = await processChecks(cheapChecks, ctx, getConfiguration(), botScore, reasons, 'cheapPhase');\n\n    if (botScore < BAN_THRESHOLD) {\n      botScore = await processChecks(checks, ctx, getConfiguration(), botScore, reasons, 'heavyPhase');\n    }\n  } catch (error) {\n    if (error instanceof BadBotDetected) {\n      const bannedInfo = { score: BAN_THRESHOLD, reasons: Array.from(reasons) };\n\n      void banIp(ipAddress, bannedInfo);\n      void getBatchQueue().addQueue(cookie ?? '', ipAddress, 'update_banned_ip', { cookie: cookie ?? '', ipAddress, country: ctx.geoData.country ?? '', user_agent: uaString, info: bannedInfo }, 'deferred');\n\n      void getBatchQueue().addQueue(cookie ?? '', ipAddress, 'is_bot_update', { isBot: true, cookie: cookie ?? '' }, 'deferred');\n      return true;\n    }\n    if (error instanceof GoodBotDetected) {\n      return false;\n    }\n    log.error({error},'unexpected error');\n  }\n\n  botScore = Math.min(botScore, MAX_SCORE);\n  if (botScore >= BAN_THRESHOLD) {\n    log.info(`Starting Ban for ${ipAddress} ${userAgent}`);\n    const bannedInfo = { score: botScore, reasons: Array.from(reasons) };\n\n    void banIp(ipAddress, bannedInfo);\n    void getBatchQueue().addQueue(cookie ?? '', ipAddress, 'update_banned_ip', { cookie: cookie ?? '', ipAddress, country: ctx.geoData.country ?? '', user_agent: uaString, info: bannedInfo }, 'deferred');\n\n    void getBatchQueue().addQueue(cookie ?? '', ipAddress, 'is_bot_update', { isBot: true, cookie: cookie ?? '' }, 'deferred');\n    return true;\n  }\n\n\n  if (setNewComputedScore) {\n    void getBatchQueue().addQueue(cookie ?? '', ipAddress, 'score_update', { score: botScore, cookie: cookie ?? '' }, 'deferred');\n\n    reputationCache.set(cookie ?? '', { isBot: false, score: botScore }).catch((err: unknown) => {\n      log.error({err}, 'Failed to set reputationCache in storage');\n    });\n\n  } else {\n    const cached = await reputationCache.get(cookie ?? '');\n    if (!cached || cached.score === 0) {\n      void getBatchQueue().addQueue(cookie ?? '', ipAddress, 'score_update', { score: botScore, cookie: cookie ?? '' }, 'deferred');\n\n      reputationCache.set(cookie ?? '', { isBot: false, score: botScore }).catch((err: unknown) => {\n         log.error({err}, 'Failed to set reputationCache in storage');\n      });\n      \n    }\n  }\n  return false;\n}\n\n","import { getStorage, getConfiguration } from '../../config/config.js';\n\nexport interface CachedResult {\n  banned: boolean;\n  visitor_id: string;\n}\n\nconst PREFIX = 'visitor:';\n\nexport const visitorCache = {\n  async get(cookie: string): Promise<CachedResult | null> {\n    return getStorage().getItem<CachedResult>(`${PREFIX}${cookie}`);\n  },\n\n  async set(cookie: string, entry: CachedResult): Promise<void> {\n    const { checksTimeRateControl } = getConfiguration();\n    await getStorage().setItem(`${PREFIX}${cookie}`, entry, { ttl: Math.floor(checksTimeRateControl.checkEvery / 1000) });\n  },\n\n  async delete(cookie: string): Promise<void> {\n    await getStorage().removeItem(`${PREFIX}${cookie}`);\n  },\n\n  async clear(): Promise<void> {\n    await getStorage().clear();\n  }\n};","import { reputationCache } from \"./cache/reputationCache.js\";\nimport { getLogger } from \"../utils/logger.js\";\nimport { getBatchQueue, getConfiguration, getDb } from \"../config/config.js\";\nimport { prep } from \"../db/dialectUtils.js\";\n\ninterface VisitorRow {\n  is_bot: number;\n  suspicious_activity_score: number;\n}\n\nexport async function userReputation(cookie: string): Promise<void> {\n  const log = getLogger().child({service: `BOT DETECTOR`, branch: `reputation`});\n  const db = getDb();\n  const {banScore, restoredReputationPoints, setNewComputedScore} = getConfiguration();\n\n  const botScore = banScore;\n\n  const cached = await reputationCache.get(cookie);\n    if (cached) {\n      log.info(`CACHE HIT cookie=${cookie} score=${String(cached.score)} →  (botScore=${String(botScore)})`);\n      if(cached.isBot) {\n        return;\n      }\n\n    // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n    if (!cached.isBot && cached.score > 0 && cached.score < botScore) {\n      log.info(`updating cache score cookie=${cookie} score=${String(cached.score)} →  (botScore=${String(botScore)})`);\n      const newReputation = Math.max(0, cached.score - restoredReputationPoints);\n\n      if (newReputation !== cached.score) {\n        void getBatchQueue().addQueue(cookie, '', 'score_update', { score: newReputation, cookie }, 'deferred');\n        log.info(`updating cache score to DB cookie=${cookie} score=${String(cached.score)} →  (botScore=${String(botScore)})`);\n        reputationCache.set(cookie, {\n          isBot: cached.isBot,\n          score: newReputation\n        }).catch((err: unknown) => {\n          log.error({ err }, 'Failed to save reputationCache in storage');\n        });\n      }\n      log.info(`finished Updating Score from cache to DB cookie: ${cookie} NEW SCORE: ${String(newReputation)}`);\n    }\n    return;\n  }\n\n\n    try {\n        const VisitorQuery = `\n        SELECT is_bot,\n        suspicious_activity_score\n        FROM visitors\n          WHERE canary_id = ?\n          LIMIT 1`;\n\n        const visitor = await prep(db, VisitorQuery).get(cookie) as VisitorRow | undefined;\n\n        if (!visitor)  {\n          log.warn(`no visitor record for canary_id=${cookie}`);\n          return;\n        }\n\n        const isBot = visitor.is_bot === 0 ? false : true;\n        const reputation = visitor.suspicious_activity_score;\n\n\n        if (isBot) return;\n\n        if (!setNewComputedScore) {\n            reputationCache.set(cookie, {\n                isBot:  isBot,\n                score: reputation\n            }).catch((err: unknown) => {\n              log.error({ err }, 'Failed to save reputationCache in storage');\n            });\n        }\n\n        log.info({\n          label: '[REP-GATE]',\n          isBot: isBot,\n          score: reputation,\n          'score>0': reputation > 0,\n          'score<ban': reputation < botScore,\n          healPts: restoredReputationPoints\n        });\n\n\n        // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n        if (!isBot && reputation > 0 && reputation < botScore) {\n          log.info(`calculating new score cookie=${cookie} score=${String(reputation)} →  (botScore=${String(botScore)})`);\n          const newReputation = Math.max(0, reputation - restoredReputationPoints);\n\n          if (newReputation !== reputation) {\n            void getBatchQueue().addQueue(cookie, '', 'score_update', { score: newReputation, cookie }, 'deferred');\n            log.info(`Update Score for cookie', ${cookie}, 'New Score:', ${String(newReputation)}`);\n\n            reputationCache.set(cookie, {\n              isBot: isBot,\n              score: newReputation\n            }).catch((err: unknown) => {\n                log.error({ err }, 'Failed to save reputationCache in storage');\n            });\n          }\n\n        }\n      } catch(err) {\n          log.error({err},`An error occurred updating visitor reputation`);\n      }\n}","/* eslint-disable @typescript-eslint/no-unnecessary-condition */\nimport { getConfiguration } from \"../config/config.js\";\n\n\nexport function getWhiteList(): string[] {\n    const {whiteList} = getConfiguration();\n    if (whiteList) return whiteList;\n    return [];\n}\n\nexport function isInWhiteList(ipAddress: string): boolean {\n    const {whiteList} = getConfiguration();\n\n    if (whiteList) {\n        const match = whiteList.includes(ipAddress);\n        return match;\n    }\n\n    return false;\n}\n\n","export const nowMysql = () => new Date().toISOString().slice(0, 19).replace('T', ' ');","import { getData } from '../helpers/getIPInformation.js';\nimport { makeCookie } from '../utils/cookieGenerator.js';\nimport type { Request, Response, NextFunction, RequestHandler } from \"express\";\nimport { randomBytes, randomUUID } from \"crypto\";\nimport parseUA from '../helpers/UAparser.js';\nimport { uaAndGeoBotDetector } from '../../botDetector.js';\nimport { visitorCache } from '../helpers/cache/cannaryCache.js';\nimport { rateCache } from '../helpers/cache/rateLimitarCache.js';\nimport { userReputation } from '../helpers/reputation.js';\nimport { getLogger } from '../utils/logger.js';\nimport type { userValidation } from '../types/fingerPrint.js';\nimport { getConfiguration, getBatchQueue } from '../config/config.js';\nimport { isInWhiteList } from '../utils/whitelist.js';\nimport { nowMysql } from '@utils/nowMysql.js';\nimport consola from 'consola';\n\ndeclare global {\n  // eslint-disable-next-line @typescript-eslint/no-namespace\n  namespace Express {\n    export interface Request {\n      newVisitorId?: string;\n      botDetection: {\n        success: boolean,\n        banned: boolean,\n        time: string,\n        ipAddress: string\n      }\n    }\n  }\n}\n\n\nexport function validator(\n  buildCustomContext?: (req: Request) => unknown,\n): RequestHandler {\n  return async (req: Request, res: Response, next: NextFunction): Promise<void> => {\n    const {checksTimeRateControl} = getConfiguration();\n    let canary: string | undefined = req.cookies.canary_id as string | undefined;\n    const ua = req.get(\"User-Agent\") ?? \"\";\n    const ip = req.ip ?? '';\n     const log = getLogger().child({service: 'BOT DETECTOR', branch: `main`, canary: canary});\n     log.info(`Validator entered for ${req.method} ${req.get('X-Forwarded-Host') ?? ''}`);\n     log.info({ cookies: req.cookies },`Incoming cookies`);\n     const whiteList = isInWhiteList(ip);\n\n    if (canary) {\n      const cached = await visitorCache.get(canary);\n      if (cached) {\n        if (cached.banned && !whiteList) {\n          res.sendStatus(403);\n          return;\n        }\n        req.newVisitorId = cached.visitor_id;\n        if (!checksTimeRateControl.checkEveryRequest){\n        next(); return;\n      }\n      }\n    }\n    \n  if (!canary) {\n    log.info(`No canary_id cookie found. Generating a new one.`);\n    const cookieValue = randomBytes(32).toString('hex');\n    canary = cookieValue;\n    \n    makeCookie(res,'canary_id', cookieValue, {\n      httpOnly: true,\n      sameSite: \"lax\", \n      maxAge: 1000 * 60 * 60 * 24 * 90,\n      secure: true,\n      path: \"/\", \n    });\n    req.cookies.canary_id = canary;\n    log.info(`New canary_id cookie set:, ${cookieValue}`);\n  }\n\n  const geo = getData(ip);\n  const parsedUA = parseUA(ua);\n  const visitorId = randomUUID();\n\n  const userValidation = {\n      visitorId,\n      cookie: canary,\n      userAgent: ua,\n      ipAddress: ip,\n      device_type: parsedUA.device,\n      browser: parsedUA.browser,\n      is_bot: false,\n      first_seen: nowMysql(),        \n      last_seen: nowMysql(),       \n      request_count: 1,       \n      deviceVendor: parsedUA.deviceVendor,\n      deviceModel: parsedUA.deviceModel,\n      browserType: parsedUA.browserType,\n      browserVersion: parsedUA.browserVersion,\n      os: parsedUA.os,\n      activity_score: '0',\n      ...geo,\n    } as userValidation;\n\n  void getBatchQueue().addQueue(canary, ip, 'visitor_upsert', { insert: userValidation }, 'deferred');\n  req.newVisitorId = visitorId;\n\n    if (whiteList) {\n        log.info(`${ip} is in white list skipping botDetection checks.`);\n\n      visitorCache.set(canary, {\n        banned: false,\n        visitor_id: visitorId\n      }).catch((err: unknown) => { log.error({ err }, 'Failed to save visitorCache in storage'); });\n\n      req.botDetection = {\n      success: true,\n      banned: false,\n      time: new Date().toISOString(),\n      ipAddress: ip\n      };\n\n      next(); return;\n    };\n\n  const brvConfig = getConfiguration().checkers.enableBehaviorRateCheck;\n  if (brvConfig.enable) {\n    const existing = await rateCache.get(canary);\n    if (!existing) {\n      const ttlSeconds = Math.ceil(brvConfig.behavioral_window / 1000);\n      rateCache.set(canary, { score: 0, timestamp: Date.now(), request_count: 1 }, ttlSeconds)\n        .catch((err: unknown) => { log.error({ err }, 'Failed to pre seed rateCache'); });\n    }\n  }\n\n  const isBot = await uaAndGeoBotDetector(req, ip, ua, geo, parsedUA, buildCustomContext);\n\n  visitorCache.set(canary, {\n    banned: isBot,\n    visitor_id: visitorId\n  }).catch((err: unknown) => { log.error({ err }, 'Failed to save visitorCache in storage'); });\n\n  if (isBot) {\n    res.sendStatus(403);\n    return;\n  }\n\n   req.botDetection = {\n    success: true,\n    banned: isBot,\n    time: new Date().toISOString(),\n    ipAddress: ip\n   };\n   \n   userReputation(canary).catch((err: unknown) => { consola.error('[BOT DETECTION - MIDDLEWARE] userReputation failed:', err); });\n\n  next();\n  };\n}\n","import { Router } from 'express';\nimport { validator } from '../middlewares/canaryCookieChecker.js';\n\n\nconst router = Router();\n\nrouter.use('/check', validator(), (req, res) => {\n  res.json({results: req.botDetection, message: 'Fingerprint logged successfully' });\n});\n\nexport default router;\n\n\n","import { compiler } from '@riavzon/shield-base';\nimport { getDb, getConfiguration } from '../config/config.js';\nimport { getLogger } from '../utils/logger.js';\nimport path from 'node:path';\nimport { BannedRecord, BannedRow, HighRiskRecord, HighRiskRow } from '../types/generator.js';\nimport { prep, placeholders } from './dialectUtils.js';\nimport { getLibraryRoot } from './findDataPath.js';\nimport { replaceDirContent } from '@riavzon/utils/server';\nimport fs from 'fs/promises';\n\nconst MMDB_DIR = path.resolve(getLibraryRoot(), '_data-sources');\n\nasync function buildBannedMmdb(generateTypes: boolean, mmdbctlPath: string): Promise<void> {\n    const TEMP_DIR = path.resolve(getLibraryRoot(), '_data-sources', `.tmp_banned_${Date.now().toString()}`);\n    const log = getLogger().child({ service: 'BOT DETECTOR', branch: 'generator', db: 'banned' });\n    const db = getDb();\n\n    const rows = await db.prepare(\n        `SELECT ip_address, country, user_agent, reason, score\n         FROM banned\n         WHERE ip_address IS NOT NULL`\n    ).all() as BannedRow[];\n\n    if (rows.length === 0) {\n        log.info('No banned IPs — skipping banned.mmdb');\n        return;\n    }\n\n    const data: BannedRecord[] = rows.map(r => ({\n        range: r.ip_address,\n        score: r.score,\n        country: r.country,\n        userAgent: r.user_agent,\n        reason: r.reason,\n        comment: 'Automatically generated by @riavzon/botDetector',\n    }));\n    \n    try {\n        await fs.mkdir(TEMP_DIR, { recursive: true });\n        await compiler<BannedRecord>({ \n            type: 'mmdb', \n            input: { \n                data, \n                dataBaseName: 'banned',\n                outputPath: TEMP_DIR,\n                mmdbPath: mmdbctlPath,\n                generateTypes \n            }\n        });\n\n        await replaceDirContent(MMDB_DIR, TEMP_DIR);\n        log.info(`banned.mmdb compiled — ${String(data.length)} entries`);\n\n        if (getConfiguration().generator.deleteAfterBuild) {\n            const compiled = rows.map(r => r.ip_address);\n            const ph = placeholders(db, compiled.length);\n            await prep(db, `DELETE FROM banned WHERE ip_address IN (${ph})`).run(...compiled);\n            log.info(`Deleted ${(String(compiled.length))} rows from banned after build`);\n        }\n\n    } catch (err) {\n        log.error('Failed to build banned.mmdb', err);\n        throw err;\n    } finally {\n        await fs.rm(TEMP_DIR, { recursive: true, force: true });\n    }\n}\n\n\nasync function buildHighRiskMmdb(scoreThreshold: number, generateTypes: boolean, mmdbctlPath: string): Promise<void> {\n    const log = getLogger().child({ service: 'BOT DETECTOR', branch: 'generator', db: 'highRisk' });\n    const TEMP_DIR = path.resolve(MMDB_DIR, `.tmp_highrisk_${Date.now().toString()}`);\n    const db = getDb();\n\n    const rows = await prep(db,\n        `SELECT\n           ip_address, visitor_id, suspicious_activity_score,\n           country, region, region_name, city, lat, lon, timezone,\n           isp, org, browser, browserType, browserVersion, os,\n           device_type, deviceVendor, deviceModel,\n           proxy, hosting, request_count, first_seen, last_seen\n         FROM visitors\n         WHERE suspicious_activity_score >= ? AND ip_address IS NOT NULL`\n    ).all(scoreThreshold) as HighRiskRow[];\n\n    if (rows.length === 0) {\n        log.info(`No high-risk visitors (score >= ${String(scoreThreshold)}) — skipping highRisk.mmdb`);\n        return;\n    }\n\n    const data: HighRiskRecord[] = rows.map(r => ({\n        range: r.ip_address,\n        visitorId: r.visitor_id,\n        score: r.suspicious_activity_score,\n        country: r.country,\n        region: r.region,\n        regionName: r.region_name,\n        city: r.city,\n        lat: r.lat,\n        lon: r.lon,\n        timezone: r.timezone,\n        isp: r.isp,\n        org: r.org,\n        browser: r.browser,\n        browserType: r.browserType,\n        browserVersion: r.browserVersion,\n        os: r.os,\n        deviceType: r.device_type,\n        deviceVendor: r.deviceVendor,\n        deviceModel: r.deviceModel,\n        // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion\n        proxy: Boolean(r.proxy),\n        // eslint-disable-next-line @typescript-eslint/no-unnecessary-type-conversion\n        hosting: Boolean(r.hosting),\n        requestCount: r.request_count,\n        firstSeen: r.first_seen ? r.first_seen.toISOString() : null,\n        lastSeen: r.last_seen  ? r.last_seen.toISOString()  : null,\n        comment: 'Automatically generated by @riavzon/botDetector',\n    }));\n\n    try {\n        await compiler<HighRiskRecord>({ \n            type: 'mmdb', \n            input: { \n                data, \n                dataBaseName: 'highRisk',\n                outputPath: TEMP_DIR,\n                mmdbPath: mmdbctlPath,\n                generateTypes \n            } \n        });\n        await replaceDirContent(MMDB_DIR, TEMP_DIR);\n        log.info(`highRisk.mmdb compiled — ${String(data.length)} entries`);\n\n        if (getConfiguration().generator.deleteAfterBuild) {\n            const compiled = rows.map(r => r.ip_address);\n            const ph = placeholders(db, compiled.length);\n            const scorePh = placeholders(db, 1, compiled.length);\n            await prep(db,\n                `DELETE FROM visitors WHERE ip_address IN (${ph}) AND suspicious_activity_score >= ${scorePh}`\n            ).run(...compiled, scoreThreshold);\n            log.info(`Deleted ${String(compiled.length)} rows from visitors after build`);\n        }\n    } catch(err) {\n        log.error('Failed to build highRisk.mmdb', err);\n        throw err;\n    } finally {\n        await fs.rm(TEMP_DIR, { recursive: true, force: true });\n    }\n}\n\n\nasync function runCycle(): Promise<void> {\n    const log = getLogger().child({ service: 'BOT DETECTOR', branch: 'generator' });\n    const { generator } = getConfiguration();\n\n    log.info('MMDB generation cycle started');\n    try {\n        await Promise.all([\n            buildBannedMmdb(generator.generateTypes, generator.mmdbctlPath),\n            buildHighRiskMmdb(generator.scoreThreshold, generator.generateTypes, generator.mmdbctlPath),\n        ]);\n        log.info('MMDB generation cycle complete');\n    } catch (err) {\n        log.error({ err }, 'MMDB generation cycle failed');\n    }\n}\n\n\nexport async function runGeneration(): Promise<void> {\n    return runCycle();\n}","import type { Database } from 'db0';\nimport { isMySQL, isSQLite } from './dialectUtils.js';\nimport consola from 'consola';\n\nfunction visitorIdDefault(db: Database): string {\n    if (isMySQL(db)) return 'NOT NULL DEFAULT (UUID())';\n    if (db.dialect === 'postgresql') return 'NOT NULL DEFAULT gen_random_uuid()';\n    return 'NOT NULL';\n}\n\nfunction lastSeenDef(db: Database): string {\n    if (isMySQL(db)) return 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP';\n    if (isSQLite(db)) return 'TEXT DEFAULT CURRENT_TIMESTAMP';\n    return 'TIMESTAMP DEFAULT CURRENT_TIMESTAMP';\n}\n\nfunction tableOptions(db: Database): string {\n    return isMySQL(db) ? 'ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci' : '';\n}\n\nfunction timestampType(db: Database): string {\n    return isSQLite(db) ? 'TEXT' : 'TIMESTAMP';\n}\n\nexport async function createTables(db: Database): Promise<void> {\n    const visitorId = visitorIdDefault(db);\n    const lastSeen = lastSeenDef(db);\n    const tblOpts = tableOptions(db);\n    const tsType = timestampType(db);\n\n    const createVisitorsTable = `\n        CREATE TABLE IF NOT EXISTS visitors (\n            visitor_id CHAR(36) ${visitorId} UNIQUE,\n            canary_id VARCHAR(64) PRIMARY KEY,\n            ip_address VARCHAR(45),\n            user_agent TEXT,\n            country VARCHAR(64),\n            region VARCHAR(64),\n            region_name VARCHAR(350),\n            city VARCHAR(64),\n            district VARCHAR(260),\n            lat VARCHAR(150),\n            lon VARCHAR(150),\n            timezone VARCHAR(64),\n            currency VARCHAR(64),\n            isp VARCHAR(64),\n            org VARCHAR(64),\n            as_org VARCHAR(64),\n            device_type VARCHAR(64),\n            browser VARCHAR(64),\n            proxy BOOLEAN,\n            proxy_allowed BOOLEAN DEFAULT false,\n            hosting BOOLEAN,\n            hosting_allowed BOOLEAN DEFAULT false,\n            is_bot BOOLEAN DEFAULT false,\n            first_seen ${tsType} DEFAULT CURRENT_TIMESTAMP,\n            last_seen ${lastSeen},\n            request_count INT DEFAULT 1,\n            deviceVendor VARCHAR(64) DEFAULT 'unknown',\n            deviceModel VARCHAR(64) DEFAULT 'unknown',\n            browserType VARCHAR(64) DEFAULT 'unknown',\n            browserVersion VARCHAR(64) DEFAULT 'unknown',\n            os VARCHAR(64) DEFAULT 'unknown',\n            suspicious_activity_score INT DEFAULT 0\n        ) ${tblOpts}\n    `;\n\n    const createBannedTable = `\n        CREATE TABLE IF NOT EXISTS banned (\n            canary_id VARCHAR(64) PRIMARY KEY,\n            ip_address VARCHAR(45),\n            country VARCHAR(64),\n            user_agent TEXT,\n            reason TEXT,\n            score INT DEFAULT NULL,\n            FOREIGN KEY (canary_id) REFERENCES visitors(canary_id)\n        )\n    `;\n\n    try {\n        await db.exec(createVisitorsTable);\n        await db.exec(createBannedTable);\n\n        consola.success('Tables created successfully.');\n    } catch (error) {\n        consola.error('Error creating tables:', error);\n        throw error;\n    }\n}","import consola from 'consola';\nimport { getDb } from '../config/config.js';\nimport { prep } from './dialectUtils.js';\n\nexport async function warmUp() {\nconst db = getDb();\nawait Promise.all(\n  Array.from({ length: 10 }, () => db.sql`SELECT 1`)\n);\n\nawait prep(db,\n  `SELECT last_seen, request_count\n     FROM visitors\n    WHERE canary_id = ?\n    LIMIT 1`\n).get('00000000‑warm‑up‑row');\n\nconsola.info('botDetector is ready!');\n}","import { getLogger } from \"../utils/logger.js\";\nimport { getDb } from \"../config/config.js\";\nimport { prep } from \"./dialectUtils.js\";\n\nexport interface VisitorFingerPrint {\n    userAgent: string;\n    ipAddress: string;\n    country: string;\n    region: string;\n    regionName: string;\n    city: string;\n    district: string;\n    lat: string;\n    lon: string;\n    timezone: string;\n    currency: string;\n    isp: string;\n    org: string;\n    as: string;\n    device_type: string;\n    browser: string;\n    proxy: boolean;\n    hosting: boolean;\n    deviceVendor: string;\n    deviceModel: string;\n    browserType: string;\n    browserVersion: string;\n    os: string;\n}\n\n\nexport async function updateVisitors(\n    data: VisitorFingerPrint,\n    cookie: string,\n    visitor_id: string,\n): Promise<{ success: boolean; reason?: string }> {\n    const db = getDb();\n    const log = getLogger().child({ service: 'BOT DETECTOR', branch: 'customUpdate' });\n\n    const params = [\n        data.userAgent,\n        data.ipAddress,\n        data.country,\n        data.region,\n        data.regionName,\n        data.city,\n        data.district,\n        data.lat,\n        data.lon,\n        data.timezone,\n        data.currency,\n        data.isp,\n        data.org,\n        data.as,\n        data.device_type,\n        data.browser,\n        data.proxy ? 1 : 0,\n        data.hosting ? 1 : 0,\n        data.deviceVendor,\n        data.deviceModel,\n        data.browserType,\n        data.browserVersion,\n        data.os,\n    ];\n\n    try {\n        const result = await prep(db, `\n            UPDATE visitors\n            SET\n                user_agent = ?,\n                ip_address = ?,\n                country = ?,\n                region = ?,\n                region_name = ?,\n                city = ?,\n                district = ?,\n                lat = ?,\n                lon = ?,\n                timezone = ?,\n                currency = ?,\n                isp = ?,\n                org = ?,\n                as_org = ?,\n                device_type = ?,\n                browser = ?,\n                proxy = ?,\n                hosting = ?,\n                deviceVendor = ?,\n                deviceModel = ?,\n                browserType = ?,\n                browserVersion = ?,\n                os = ?\n            WHERE canary_id  = ?\n              AND visitor_id = ?\n        `).run(...params, cookie, visitor_id);\n\n        if (!result.success) {\n            log.warn({ cookie, visitor_id }, `updateVisitors: no rows affected`);\n            return { success: false, reason: `No visitor found for canary_id=${cookie} visitor_id=${visitor_id}` };\n        }\n\n        log.info({ visitor_id }, `updateVisitors: visitor updated`);\n        return { success: true };\n    } catch (err) {\n        log.error({ err }, `updateVisitors: query failed`);\n        return { success: false, reason: 'DB error — check logs for details' };\n    }\n}\n"],"mappings":"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"}