@botbye/node-core

中文文档
2.2.1发布于 2026/10/14MITTypeScriptESM + CJS零依赖近 30 天下载 2万

Bot Bye! 节点核心模块 Js

中文使用文档
文档目录24 节
  1. 安装
  2. 配置
  3. moduleApiFactory 选项
  4. HTTP 客户端
  5. init 选项
  6. 建立定制一体化
  7. 使用量
  8. validate --边缘级机器人检查
  9. risk ——域级风险评分
  10. full ——边缘检查和域评分在一个呼叫中
  11. 回应
  12. 你的计划是什么
  13. 反应实例
  14. 高级: 多个实例
  15. 水电费
  16. 反钓鱼
  17. 配置
  18. phishingModuleApiFactory 选项
  19. Phishing HTTP 客户端
  20. phishing.init 选项
  21. 使用量
  22. 建立定制一体化
  23. 高级: 多个实例
  24. 文档

@ botbye/ 节点核心

再见! node.js的核心模块——所有BotBye框架集成所使用的低层构件.

当环境没有特定框架集成时使用此软件包,或者当您需要完全控制请求信息如何传递到SDK时使用此软件包.

对于大多数使用的情况,更喜欢针对具体框架的一揽子方案:

完整文档: https://botbye.com/docs/server-side/node-js/core 页面存档备份,存于互联网档案馆

安装

npm i @botbye/node-core
yarn add @botbye/node-core

配置

@botbye/node-core 不导出 init 财务报告和审定财务报表 evaluate 直接说 打电话 moduleApiFactory 创建 SDK 实例 :

import { moduleApiFactory } from "@botbye/node-core";
import { nodeHttpClient } from "@botbye/node-core/node-http-client";

const { init, evaluate, dev } = moduleApiFactory({
  httpClient: nodeHttpClient,
});

init({
  // Use your project server-key
  serverKey: "00000000-0000-0000-0000-000000000000",
});

打电话 init 在应用程序启动时,在呼叫之前 evaluate。 。 。 .

moduleApiFactory 选项

选项类型需求说明
httpClientTHttpClient对HTTP客户端用于API呼叫. 见 HTTP 客户端。 。 。 .
requestInfoExtractor(request: R, global: TGlobalOptions) => TRequestInfo没有将自定义请求对象转换为请求信息, 启用 { request: R } 内 evaluate。见 建立定制一体化。 。 。 .
urlstring没有取代Bot Bye API的终点. 也可以通过 init。 。 。 .

HTTP 客户端

有两个内置的HTTP客户端:

导入路径何时使用
@botbye/node-core/node-http-client标准节点.js环境(使用内置) http编号 :https(中文(简体) )
@botbye/node-core/fetch-http-client带有获取 API (Deno, Bun, 边缘运行时间) 的运行时间

如果两者都不符合(海关代理、特殊认证头、重试逻辑),则执行 THttpClient 接口 :

import type { THttpClient } from "@botbye/node-core";

const myHttpClient: THttpClient = {
  type: "my-client",
  call(url, init) {
    const controller = new AbortController();
    const result = fetch(url, {
      method: init.method,
      headers: init.headers,
      body: JSON.stringify(init.body),
      signal: controller.signal,
    }).then((r) => r.text());
    return { result, abort: () => controller.abort() };
  },
};

init 选项

选项类型需求说明
serverKeystring对来自您的 BotBye 项目的服务器密钥
urlstring没有覆盖 Bot Bye API 端点( 默认 : https://verify.botbye.com(中文(简体) )
logger.level"error" | "warn" | "info" | "debug" | "log"没有日志级别( 默认 ): "info"(中文(简体) )
logger.loggerTLogger没有自定义日志实例执行 { error, warn, info, debug, log }
timeouts.evaluatenumber没有每个超时( 毫秒) evaluate 调用

建立定制一体化

requestInfoExtractor 允许您为任何尚未被官方软件包覆盖的框架构建一等集成。 它弥合了框架的本地请求对象与 TRequestInfo 形状 evaluate 内部需要.

它会做什么:

何时 requestInfoExtractor 提供, evaluate 获得第二个调用表: 而不是明确通过字段, 您可以通过 { request: YourRequestObject }。提取器被自动调用以获取 ip, (中文(简体) ), headers, (中文(简体) ), requestMethod,以及 requestUri 从它.

// Without requestInfoExtractor — explicit fields only
evaluate({ type: "validate", request: { ip, headers, requestMethod, requestUri, token } });

// With requestInfoExtractor — framework request object accepted directly
evaluate({ type: "validate", request: { request: req, token } });

这两种形式并存有效。 已经通过球场的路线继续明确发挥作用.

控件处理 :

提取器也可返回 a token 字段(例如从已知标题中取出)。 如果打电话者也通过 token 事件的价值优先。 这样可以让提取器提供合理的默认,同时允许每个调用时的覆盖.

类型脚本 :

通用参数 R 打开 moduleApiFactory<R> 流动到 evaluate 签名。 提供 requestInfoExtractor 是什么让输入 { request: R } 窗体有效 :

import { moduleApiFactory } from "@botbye/node-core";
import { nodeHttpClient } from "@botbye/node-core/node-http-client";
import type { Request } from "express";

const { init, evaluate, dev } = moduleApiFactory<Request>({
  httpClient: nodeHttpClient,
  requestInfoExtractor: (req, global) => {
    try {
      return {
        ip: req.ip ?? req.socket.remoteAddress ?? "0.0.0.0",
        headers: req.headers as Record<string, string>,
        requestMethod: req.method,
        requestUri: req.url,
        token: req.headers["x-botbye-token"] as string ?? null,
      };
    } catch {
      global.logger.warn("Failed to extract request info from Express request");
      return { ip: "0.0.0.0", headers: {} };
    }
  },
});

init({
  // Use your project server-key
  serverKey: "00000000-0000-0000-0000-000000000000",
});

// Now evaluate accepts Express Request directly
app.use(async (req, res, next) => {
  const result = await evaluate({
    type: "validate",
    request: {
      request: req,
      // "x-botbye-token" is an example — pass the token from wherever you store it
      token: req.headers["x-botbye-token"] as string,
    },
  });

  if (result.decision === "BLOCK") {
    return res.status(403).json({ error: "Forbidden" });
  }

  next();
});

这个 global 移交给提取器的参数 global.logger ——当请求对象畸形或出乎意料时用于警告.

使用量

打电话 evaluate 带有事件对象描述您对请求的了解。 它还带来一个决定决定的承诺.

有三种活动类型—— validate, (中文(简体) ), risk,以及 full 每一个都适合你申请的不同层次.

无 requestInfoExtractor,所有请求字段必须明确提供——没有任何框架请求可以通过.


validate --边缘级机器人检查

在边缘使用 — API网关, 路由处理器, 中间软件—— 当你只想知道时 : 这是机器人提出的要求吗? 不需要用户或域名上下文 .

活动字段 :

{
  type: "validate";
  request:
    // Option A: custom request object — only available when requestInfoExtractor is configured
    | { request: R; token?: string | null }
    // Option B: explicit fields
    | { ip: string; headers: Record<string, string>; requestMethod?: string | null; requestUri?: string | null; token?: string | null };
  customFields?: Record<string, string>;
}

从您的运行时请求对象中取出 IP 和信头 。 备选案文A——直接传递框架请求对象——要求 requestInfoExtractor 将配置在 moduleApiFactory; 见 建立定制一体化编辑 token 是一个一次性符号,由 Bot 再见客户端 SDK 包含关于用户设备的信息。 不论客户寄给什么,都通过;如果没有收到任何信使,将作出决定 "BLOCK" 由于一个无效的符号.

async function handleRequest(ip, headers, method, url, token) {
  const result = await evaluate({
    type: "validate",
    request: {
      ip,
      headers,
      requestMethod: method,
      requestUri: url,
      token,
    },
  });

  if (result.decision === "BLOCK") {
    return { status: 403 };
  }

  // proceed normally
}

risk ——域级风险评分

使用已经了解用户的内部服务:认证,支付,账户管理等. 目的从"这是机器人吗?"转移到了 "对于这个用户来说,有什么可疑的吗?" ——凭证填充,账户接管,账户共享,登录新地物.

活动字段 :

{
  type: "risk";
  request:
    // Option A: custom request object — only available when requestInfoExtractor is configured
    | { request: R }
    // Option B: explicit fields
    | { ip: string; headers?: Record<string, string>; requestMethod?: string | null; requestUri?: string | null; token?: string | null };
  event: {
    type: string;
    status: "ATTEMPTED" | "SUCCESSFUL" | "FAILED" | "UNKNOWN";
  };
  user: {
    accountId: string;
    username?: string | null;
    email?: string | null;
    phone?: string | null;
  };
  customFields?: Record<string, string>;
  botbyeResult?: string;
}

event 财务报告和审定财务报表 user 它们是关键的领域——它们界定了正在采取什么行动,以及由谁采取行动,这是促使风险得分的因素. ip 同样重要的是: IP访问账户的 Bot Bye 轨迹可以探测到诸如账户共享、认证输入和可疑地理登录等模式。 直接传过来 { ip },或者如果 requestInfoExtractor 已配置 - 见 建立定制一体化。 。 。 .

// Inside an auth service, after a login attempt
async function onLoginAttempt({ ip, userId, email, loginSucceeded }) {
  const result = await evaluate({
    type: "risk",
    request: { ip },
    event: {
      type: "login",
      status: loginSucceeded ? "SUCCESSFUL" : "FAILED",
      // "SUCCESSFUL" | "FAILED" | "ATTEMPTED" | "UNKNOWN"
    },
    user: {
      accountId: userId,
      email,
    },
  });

  if (result.decision === "BLOCK") {
    // Lock account, trigger MFA, send alert, etc.
  }
}

链接 validate 财务报告和审定财务报表 risk 事件

当对同一请求进行两层评价时——例如,一次在边缘(type: "validate"),然后再次在域服务内(type: "risk") —— Bot Bye可以将这两起事件联系起来,并在仪表板上作为单个事件展示.

这个 validate 答复包括 botbye_result 绳子。 通过它作为 botbyeResult 输入 risk 要求建立链接:

// Edge layer — validate the bot token
const edgeResult = await evaluate({
  type: "validate",
  request: {
    ip,
    headers,
    requestMethod: method,
    requestUri: url,
    token,
  },
});

// Pass edgeResult.botbye_result to your domain service however you like —
// a request header, a context object, a function argument, etc.
const edgeBotbyeResult = edgeResult.botbye_result;

// Domain service — risk scoring linked to the edge validation above
const riskResult = await evaluate({
  type: "risk",
  request: { ip },
  event: {
    type: "login",
    status: loginSucceeded ? "SUCCESSFUL" : "FAILED",
  },
  user: {
    accountId: userId,
    email,
  },
  botbyeResult: edgeBotbyeResult,
});

botbye_result 在答复中是可选的——如果没有,删去 botbyeResult 事件将被独立记录.


full ——边缘检查和域评分在一个呼叫中

当您同时拥有全部上下文时使用:原始请求、 令牌、 用户和事件 。 登录端点是一个典型的例子——它接收到HTTP请求并立即知道用户和结果.

活动字段 :

{
  type: "full";
  request:
    // Option A: custom request object — only available when requestInfoExtractor is configured
    | { request: R; token?: string | null }
    // Option B: explicit fields
    | { ip: string; headers: Record<string, string>; requestMethod?: string | null; requestUri?: string | null; token?: string | null };
  event: {
    type: string;
    status: "ATTEMPTED" | "SUCCESSFUL" | "FAILED" | "UNKNOWN";
  };
  user: {
    accountId: string;
    username?: string | null;
    email?: string | null;
    phone?: string | null;
  };
  customFields?: Record<string, string>;
}

等同运行 validate 财务报告和审定财务报表 risk 在一个电话。 备选案文A要求 requestInfoExtractor 看到了吗 建立定制一体化。 。 。 .

async function handleLogin({ ip, headers, method, url, token, email, password }) {
  const user = await findUser(email);
  const loginSucceeded = user && (await checkPassword(user, password));

  const result = await evaluate({
    type: "full",
    request: {
      ip,
      headers,
      requestMethod: method,
      requestUri: url,
      token,
    },
    event: {
      type: "login",
      status: loginSucceeded ? "SUCCESSFUL" : "FAILED",
    },
    user: {
      accountId: user?.id ?? "unknown",
      email,
    },
  });

  if (result.decision === "BLOCK") {
    return { status: 403 };
  }

  // proceed normally
}

回应

evaluate 总是返回 a Promise<TEvaluationResult>数字 :

type TEvaluationResult =
  | {
      decision: "ALLOW" | "BLOCK" | "CHALLENGE";
      request_id: string;
      risk_score: number;
      scores: Record<string, number>;
      signals: string[];
      botbye_result?: string;
    }
  | {
      decision: "ALLOW";
      botbye_result?: string;
      error: { message: string };
    };

检查 result.decision 决定如何处理请求:

  • "ALLOW" - 请求似乎合法,正常进行
  • "BLOCK" - 探测到机器人或可疑活动,阻止请求
  • "CHALLENGE" - 不确定,考虑发布CAPTCHA、外交部或额外的核查步骤

当答复中包含 error 字段,该请求没有得到充分评价。 一个 集成错误 失败 关闭 与 decision: "BLOCK" 财务报告和审定财务报表 signals: ["evaluation_error"] 成型不良的有效载荷,或解决任何项目的钥匙(Invalid server key,或 Invalid site key 用于调用; 密钥是 UUID , 所以错误的密钥会清晰地分析, 并且只检查失败 。 A 类 Bot Bye-side 失败 失败 打开 与 decision: "ALLOW",所以我们自己的过失 并不阻挡真正的用户,和 SDK 软件 做同样的,没有 request_id,当它从未收到任何决定时——请求超时,连接出错,或无法解析的反应. 监视器 error.message 无论是哪种方式,并解决根本原因.

你的计划是什么

risk_score, (中文(简体) ), scores 和探测器 signals 现从 启动器 计划好 打开 免费 页:1 判决是一样的,而且 request_id 仍然在那里, 但这三个回来空白: risk_score 实值 0.0, (中文(简体) ), scores 实值 {},以及 signals 只保留你身边名字的原因 而不是 我们的探测器.. token_expected, (中文(简体) ), script_loading_error, (中文(简体) ), token_generation_error, (中文(简体) ), raw_token_changed 财务报告和审定财务报表 banned_by_rule你写的规则的判决.

每项计划的保护行为都相同;只有对决定的解释才不予考虑。 所以,分支 打开 decision永远不要 risk_score 上面的门槛 将每个自由计划请求都视为低风险.

反应实例

被屏蔽( 检测到的机器人) :

{
  "request_id": "f77b2abd-c5d7-44f0-be4f-174b04876583",
  "decision": "BLOCK",
  "risk_score": 0.95,
  "scores": { "bot": 0.95 },
  "signals": ["AutomationTool"]
}

允许 :

{
  "request_id": "f77b2abd-c5d7-44f0-be4f-174b04876583",
  "decision": "ALLOW",
  "risk_score": 0.05,
  "scores": { "bot": 0.05, "ato": 0.02 },
  "signals": []
}

挑战:

{
  "request_id": "f77b2abd-c5d7-44f0-be4f-174b04876583",
  "decision": "CHALLENGE",
  "risk_score": 0.65,
  "scores": { "bot": 0.65 },
  "signals": ["SuspiciousFingerprint"],
  "challenge": { "type": "CAPTCHA", "token": "..." }
}

无效 serverKey 已知项目(未关闭):

{
  "request_id": "f77b2abd-c5d7-44f0-be4f-174b04876583",
  "decision": "BLOCK",
  "risk_score": 1.0,
  "scores": {},
  "signals": ["evaluation_error"],
  "error": { "message": "Invalid server key" }
}

SDK从未收到决定( 未打开) :

{
  "decision": "ALLOW",
  "error": { "message": "connection error" }
}

高级: 多个实例

使用 moduleApiFactory 创建独立的 SDK 实例( 当保护多个项目不受一个服务的影响时有用) :

import { moduleApiFactory } from "@botbye/node-core";
import { nodeHttpClient } from "@botbye/node-core/node-http-client";

const sdkA = moduleApiFactory({ httpClient: nodeHttpClient });
const sdkB = moduleApiFactory({ httpClient: nodeHttpClient });

sdkA.init({
  // Use your project server-key
  serverKey: "00000000-0000-0000-0000-000000000000",
});

sdkB.init({
  // Use your project server-key
  serverKey: "11111111-1111-1111-1111-111111111111",
});

水电费

import { moduleApiFactory } from "@botbye/node-core";
import { nodeHttpClient } from "@botbye/node-core/node-http-client";

const { dev } = moduleApiFactory({ httpClient: nodeHttpClient });

// Change log verbosity at runtime
dev.setLoggerLevel("debug"); // "error" | "warn" | "info" | "debug" | "log"

反钓鱼

Bot Bye的反钓鱼探测器 看起来像是复制你页面的站点 此集成为检测服务 捕捉器 因此,BotBye域名对客户端保持隐藏.

反钓鱼是由它自己识别出 clientKey (可在Dashboard上的您 Phishing 工程中找到),而不是用于 evaluate,因此它被配置和连接 单独,通过 phishingModuleApiFactory。 。 。 .

配置

import { phishingModuleApiFactory } from "@botbye/node-core";
import { nodePhishingHttpClient } from "@botbye/node-core/phishing-node-http-client";

const phishing = phishingModuleApiFactory({
  httpClient: nodePhishingHttpClient,
});

phishing.init({
  // clientKey from your Phishing Project on the Admin Dashboard
  clientKey: "00000000-0000-0000-0000-000000000000",
});

打电话 phishing.init 在应用程序启动时,在满足任何捕捉者请求之前.

phishingModuleApiFactory 选项

选项类型需求说明
httpClientTPhishingHttpClient对HTTP客户端用于捕捉者呼叫. 见 HTTP 客户端 见下文.
catcherRequestInfoExtractor(request: R, global: TPhishingGlobalOptions) => TPhishingCatcherRequestInfo没有将自定义请求对象转换为 { headers },启用 { request: R } 内 fetchCatcher相同的想法 requestInfoExtractor 以上——见 建立定制一体化。 。 。 .
urlstring没有取代Bot Bye API的终点. 也可以通过 phishing.init。 。 。 .

Phishing HTTP 客户端

Phishing呼叫使用自己的HTTP客户端接口(TPhishingHttpClient页:1 evaluate是因为 THttpClient ——两者不可互换. 有两个内置客户端:

导入路径何时使用
@botbye/node-core/phishing-node-http-client标准节点.js环境(使用内置) http编号 :https(中文(简体) )
@botbye/node-core/phishing-fetch-http-client带有获取 API (Deno, Bun, 边缘运行时间) 的运行时间

phishing.init 选项

选项类型需求说明
clientKeystring对clientKey 从您管理板上的 Phishing 工程
urlstring没有覆盖 Bot Bye API 端点( 默认 : https://verify.botbye.com(中文(简体) )
logger.level"error" | "warn" | "info" | "debug" | "log"没有日志级别( 默认 ): "info"(中文(简体) )
logger.loggerTLogger没有自定义日志实例执行 { error, warn, info, debug, log }
timeouts.fetchCatchernumber没有每个超时( 毫秒) fetchCatcher 调用

使用量

反钓鱼需要 两条路线的原产地,每个代理通过 fetchCatcher数字 :

  • SVG 路线 - 为SVG捕手服务。 这是您的 URL 客户端 通行证给 getCatcher({ url })。 。 。 .
  • PNG 路线 ——服务于SVG参考的PNG(通过 innerPngUrl) (中文(简体) ).

无 catcherRequestInfoExtractor,通过 headers 明确而不是请求对象。 对于SVG, innerPngUrl 应该是 绝对 URL 您的 PNG 路由 —— 浏览器直接从您的源头装入 PNG .

// Absolute URL of your PNG endpoint — the SVG catcher references it through innerPngUrl.
const PNG_CATCHER_URL = "https://your-site.example/botbye-catcher.png";

async function serveSvgCatcher(headers) {
  const catcher = await phishing.fetchCatcher({
    headers,
    format: "svg",
    innerPngUrl: PNG_CATCHER_URL, // absolute URL of the PNG endpoint below
  });

  return { status: catcher.status, headers: catcher.headers, body: catcher.body };
}

async function servePngCatcher(headers) {
  const catcher = await phishing.fetchCatcher({ headers, format: "png" });

  return { status: catcher.status, headers: catcher.headers, body: catcher.body };
}

fetchCatcher 总是返回 a Promise<TUpstreamFetchCatcherResult>数字 :

type TUpstreamFetchCatcherResult = {
  status: number;
  headers: Record<string, string>;
  body: Uint8Array;
  error?: { message: string };
};

中继 status, (中文(简体) ), headers,以及 body 确切的电话取决于您的运行时间(res.writeHead编号 :res.end, (中文(简体) ), new Response(...)(见a/c.5/49/70,附件).

我们建议嵌入 SVG 捕捉器:它旨在继续跟踪,即使一个钓鱼网站将您的所有资产复制到自己的基础设施(PNG路线存在是因为SVG捕捉者依赖于它).

建立定制一体化

碞钩 requestInfoExtractor 页:1 evaluate, (中文(简体) ), catcherRequestInfoExtractor 让我们 fetchCatcher 直接接受框架的本地请求对象—— { request: R } ——改为 { headers }。 。 。 .

import { phishingModuleApiFactory } from "@botbye/node-core";
import { nodePhishingHttpClient } from "@botbye/node-core/phishing-node-http-client";
import type { Request } from "express";

const phishing = phishingModuleApiFactory<Request>({
  httpClient: nodePhishingHttpClient,
  catcherRequestInfoExtractor: (request) => ({
    headers: request.headers as Record<string, string>,
  }),
});

phishing.init({
  clientKey: "00000000-0000-0000-0000-000000000000",
});

// Now fetchCatcher accepts an Express Request directly
app.get("/botbye-catcher.svg", async (req, res) => {
  const catcher = await phishing.fetchCatcher({
    request: req,
    format: "svg",
    innerPngUrl: PNG_CATCHER_URL,
  });

  res.status(catcher.status).set(catcher.headers).send(Buffer.from(catcher.body));
});

高级: 多个实例

使用 phishingModuleApiFactory 创建独立的 SDK 实例( 当保护多个项目不受一个服务的影响时有用) :

import { phishingModuleApiFactory } from "@botbye/node-core";
import { nodePhishingHttpClient } from "@botbye/node-core/phishing-node-http-client";

const phishingA = phishingModuleApiFactory({ httpClient: nodePhishingHttpClient });
const phishingB = phishingModuleApiFactory({ httpClient: nodePhishingHttpClient });

phishingA.init({
  clientKey: "00000000-0000-0000-0000-000000000000",
});

phishingB.init({
  clientKey: "11111111-1111-1111-1111-111111111111",
});

文档

版本与发布记录

@botbye/node-core 共发布 6 个版本,首次发布于 2026/05/20;过去 12 个月发布了 6 个版本。

版本发布日期距今
2.2.1latest2026/10/1425 天前
2.2.02026/07/163 个月前
2.1.22026/06/254 个月前
2.1.12026/05/265 个月前
2.1.02026/05/265 个月前
2.0.02026/05/205 个月前

关于 @botbye/node-core 的常见问题

@botbye/node-core 是什么?

Bot Bye! 节点核心模块 Js

如何安装 @botbye/node-core?

在项目目录运行 npm install @botbye/node-core,或使用 pnpm add / yarn add / bun add。

@botbye/node-core 支持 TypeScript 吗?

支持。包内自带 TypeScript 类型声明(package.json 声明了 types 入口),安装后即可获得类型提示,无需再安装 @types 包。

@botbye/node-core 支持 ESM 还是 CommonJS?

同时提供 ES Module 与 CommonJS 入口,import 和 require() 都可以使用,打包工具会自动选择合适的版本。

@botbye/node-core 可以商用吗?

@botbye/node-core 使用 MIT 许可。宽松许可:允许商业使用、修改和再分发,通常只需在分发时保留原版权与许可声明。以上为概括,不构成法律意见,请以许可原文为准。

@botbye/node-core 的下载量有多少?

根据 npm 官方下载统计,@botbye/node-core 在 2026/10/09 – 2026/11/07 这 30 天内被下载 20,369 次,日均约 679 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入,适合横向比较热度,不能直接等同于使用人数。

@botbye/node-core 还在维护吗?

最新版本 2.2.1 发布于 2026/10/14(25 天前);至今共发布 6 个版本,其中过去 12 个月发布了 6 个;首次发布于 2026/05/20。发布频率只是参考信号:功能稳定的工具可能很少需要更新,建议结合源码仓库的 issue 和提交记录判断。