@lark-project/openclaw-lark-project 2026.3.131
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +80 -0
- package/README.zh.md +80 -0
- package/dist/index.js +172 -0
- package/dist/index.js.map +7 -0
- package/dist/skills/feishu-bitable/SKILL.md +248 -0
- package/dist/skills/feishu-bitable/references/examples.md +813 -0
- package/dist/skills/feishu-bitable/references/field-properties.md +763 -0
- package/dist/skills/feishu-bitable/references/record-values.md +911 -0
- package/dist/skills/feishu-calendar/SKILL.md +244 -0
- package/dist/skills/feishu-channel-rules/SKILL.md +18 -0
- package/dist/skills/feishu-channel-rules/references/markdown-syntax.md +138 -0
- package/dist/skills/feishu-create-doc/SKILL.md +719 -0
- package/dist/skills/feishu-fetch-doc/SKILL.md +93 -0
- package/dist/skills/feishu-im-read/SKILL.md +163 -0
- package/dist/skills/feishu-project/SKILL.md +122 -0
- package/dist/skills/feishu-task/SKILL.md +293 -0
- package/dist/skills/feishu-troubleshoot/SKILL.md +70 -0
- package/dist/skills/feishu-update-doc/SKILL.md +285 -0
- package/dist/src/card/builder.js +293 -0
- package/dist/src/card/builder.js.map +7 -0
- package/dist/src/card/cardkit.js +126 -0
- package/dist/src/card/cardkit.js.map +7 -0
- package/dist/src/card/flush-controller.js +107 -0
- package/dist/src/card/flush-controller.js.map +7 -0
- package/dist/src/card/markdown-style.js +57 -0
- package/dist/src/card/markdown-style.js.map +7 -0
- package/dist/src/card/reply-dispatcher-types.js +39 -0
- package/dist/src/card/reply-dispatcher-types.js.map +7 -0
- package/dist/src/card/reply-dispatcher.js +245 -0
- package/dist/src/card/reply-dispatcher.js.map +7 -0
- package/dist/src/card/reply-mode.js +29 -0
- package/dist/src/card/reply-mode.js.map +7 -0
- package/dist/src/card/streaming-card-controller.js +653 -0
- package/dist/src/card/streaming-card-controller.js.map +7 -0
- package/dist/src/card/unavailable-guard.js +76 -0
- package/dist/src/card/unavailable-guard.js.map +7 -0
- package/dist/src/channel/abort-detect.js +79 -0
- package/dist/src/channel/abort-detect.js.map +7 -0
- package/dist/src/channel/chat-queue.js +50 -0
- package/dist/src/channel/chat-queue.js.map +7 -0
- package/dist/src/channel/config-adapter.js +89 -0
- package/dist/src/channel/config-adapter.js.map +7 -0
- package/dist/src/channel/directory.js +133 -0
- package/dist/src/channel/directory.js.map +7 -0
- package/dist/src/channel/event-handlers.js +175 -0
- package/dist/src/channel/event-handlers.js.map +7 -0
- package/dist/src/channel/monitor.js +108 -0
- package/dist/src/channel/monitor.js.map +7 -0
- package/dist/src/channel/onboarding-config.js +76 -0
- package/dist/src/channel/onboarding-config.js.map +7 -0
- package/dist/src/channel/onboarding-migrate.js +55 -0
- package/dist/src/channel/onboarding-migrate.js.map +7 -0
- package/dist/src/channel/onboarding.js +285 -0
- package/dist/src/channel/onboarding.js.map +7 -0
- package/dist/src/channel/plugin.js +260 -0
- package/dist/src/channel/plugin.js.map +7 -0
- package/dist/src/channel/probe.js +14 -0
- package/dist/src/channel/probe.js.map +7 -0
- package/dist/src/channel/types.js +1 -0
- package/dist/src/channel/types.js.map +7 -0
- package/dist/src/commands/auth.js +73 -0
- package/dist/src/commands/auth.js.map +7 -0
- package/dist/src/commands/diagnose.js +658 -0
- package/dist/src/commands/diagnose.js.map +7 -0
- package/dist/src/commands/doctor.js +327 -0
- package/dist/src/commands/doctor.js.map +7 -0
- package/dist/src/commands/index.js +124 -0
- package/dist/src/commands/index.js.map +7 -0
- package/dist/src/core/accounts.js +129 -0
- package/dist/src/core/accounts.js.map +7 -0
- package/dist/src/core/agent-config.js +60 -0
- package/dist/src/core/agent-config.js.map +7 -0
- package/dist/src/core/api-error.js +55 -0
- package/dist/src/core/api-error.js.map +7 -0
- package/dist/src/core/app-owner-fallback.js +17 -0
- package/dist/src/core/app-owner-fallback.js.map +7 -0
- package/dist/src/core/app-scope-checker.js +95 -0
- package/dist/src/core/app-scope-checker.js.map +7 -0
- package/dist/src/core/auth-errors.js +120 -0
- package/dist/src/core/auth-errors.js.map +7 -0
- package/dist/src/core/chat-info-cache.js +102 -0
- package/dist/src/core/chat-info-cache.js.map +7 -0
- package/dist/src/core/config-schema.js +150 -0
- package/dist/src/core/config-schema.js.map +7 -0
- package/dist/src/core/device-flow.js +174 -0
- package/dist/src/core/device-flow.js.map +7 -0
- package/dist/src/core/feishu-fetch.js +12 -0
- package/dist/src/core/feishu-fetch.js.map +7 -0
- package/dist/src/core/footer-config.js +16 -0
- package/dist/src/core/footer-config.js.map +7 -0
- package/dist/src/core/lark-client.js +322 -0
- package/dist/src/core/lark-client.js.map +7 -0
- package/dist/src/core/lark-logger.js +92 -0
- package/dist/src/core/lark-logger.js.map +7 -0
- package/dist/src/core/lark-ticket.js +18 -0
- package/dist/src/core/lark-ticket.js.map +7 -0
- package/dist/src/core/message-unavailable.js +119 -0
- package/dist/src/core/message-unavailable.js.map +7 -0
- package/dist/src/core/owner-policy.js +25 -0
- package/dist/src/core/owner-policy.js.map +7 -0
- package/dist/src/core/permission-url.js +37 -0
- package/dist/src/core/permission-url.js.map +7 -0
- package/dist/src/core/project-auth.js +177 -0
- package/dist/src/core/project-auth.js.map +7 -0
- package/dist/src/core/project-oauth-flow.js +124 -0
- package/dist/src/core/project-oauth-flow.js.map +7 -0
- package/dist/src/core/project-token-store.js +172 -0
- package/dist/src/core/project-token-store.js.map +7 -0
- package/dist/src/core/raw-request.js +45 -0
- package/dist/src/core/raw-request.js.map +7 -0
- package/dist/src/core/scope-manager.js +62 -0
- package/dist/src/core/scope-manager.js.map +7 -0
- package/dist/src/core/security-check.js +118 -0
- package/dist/src/core/security-check.js.map +7 -0
- package/dist/src/core/shutdown-hooks.js +37 -0
- package/dist/src/core/shutdown-hooks.js.map +7 -0
- package/dist/src/core/targets.js +55 -0
- package/dist/src/core/targets.js.map +7 -0
- package/dist/src/core/token-store.js +215 -0
- package/dist/src/core/token-store.js.map +7 -0
- package/dist/src/core/tool-client.js +335 -0
- package/dist/src/core/tool-client.js.map +7 -0
- package/dist/src/core/tool-scopes.js +207 -0
- package/dist/src/core/tool-scopes.js.map +7 -0
- package/dist/src/core/tools-config.js +57 -0
- package/dist/src/core/tools-config.js.map +7 -0
- package/dist/src/core/types.js +1 -0
- package/dist/src/core/types.js.map +7 -0
- package/dist/src/core/uat-client.js +124 -0
- package/dist/src/core/uat-client.js.map +7 -0
- package/dist/src/core/version.js +27 -0
- package/dist/src/core/version.js.map +7 -0
- package/dist/src/messaging/converters/audio.js +19 -0
- package/dist/src/messaging/converters/audio.js.map +7 -0
- package/dist/src/messaging/converters/calendar.js +46 -0
- package/dist/src/messaging/converters/calendar.js.map +7 -0
- package/dist/src/messaging/converters/content-converter.js +61 -0
- package/dist/src/messaging/converters/content-converter.js.map +7 -0
- package/dist/src/messaging/converters/file.js +18 -0
- package/dist/src/messaging/converters/file.js.map +7 -0
- package/dist/src/messaging/converters/folder.js +18 -0
- package/dist/src/messaging/converters/folder.js.map +7 -0
- package/dist/src/messaging/converters/hongbao.js +14 -0
- package/dist/src/messaging/converters/hongbao.js.map +7 -0
- package/dist/src/messaging/converters/image.js +16 -0
- package/dist/src/messaging/converters/image.js.map +7 -0
- package/dist/src/messaging/converters/index.js +48 -0
- package/dist/src/messaging/converters/index.js.map +7 -0
- package/dist/src/messaging/converters/interactive/card-converter.js +1040 -0
- package/dist/src/messaging/converters/interactive/card-converter.js.map +7 -0
- package/dist/src/messaging/converters/interactive/card-utils.js +36 -0
- package/dist/src/messaging/converters/interactive/card-utils.js.map +7 -0
- package/dist/src/messaging/converters/interactive/index.js +19 -0
- package/dist/src/messaging/converters/interactive/index.js.map +7 -0
- package/dist/src/messaging/converters/interactive/legacy.js +53 -0
- package/dist/src/messaging/converters/interactive/legacy.js.map +7 -0
- package/dist/src/messaging/converters/interactive/types.js +23 -0
- package/dist/src/messaging/converters/interactive/types.js.map +7 -0
- package/dist/src/messaging/converters/location.js +17 -0
- package/dist/src/messaging/converters/location.js.map +7 -0
- package/dist/src/messaging/converters/merge-forward.js +143 -0
- package/dist/src/messaging/converters/merge-forward.js.map +7 -0
- package/dist/src/messaging/converters/post.js +113 -0
- package/dist/src/messaging/converters/post.js.map +7 -0
- package/dist/src/messaging/converters/share.js +22 -0
- package/dist/src/messaging/converters/share.js.map +7 -0
- package/dist/src/messaging/converters/sticker.js +16 -0
- package/dist/src/messaging/converters/sticker.js.map +7 -0
- package/dist/src/messaging/converters/system.js +25 -0
- package/dist/src/messaging/converters/system.js.map +7 -0
- package/dist/src/messaging/converters/text.js +12 -0
- package/dist/src/messaging/converters/text.js.map +7 -0
- package/dist/src/messaging/converters/todo.js +37 -0
- package/dist/src/messaging/converters/todo.js.map +7 -0
- package/dist/src/messaging/converters/types.js +1 -0
- package/dist/src/messaging/converters/types.js.map +7 -0
- package/dist/src/messaging/converters/unknown.js +13 -0
- package/dist/src/messaging/converters/unknown.js.map +7 -0
- package/dist/src/messaging/converters/utils.js +35 -0
- package/dist/src/messaging/converters/utils.js.map +7 -0
- package/dist/src/messaging/converters/video-chat.js +21 -0
- package/dist/src/messaging/converters/video-chat.js.map +7 -0
- package/dist/src/messaging/converters/video.js +30 -0
- package/dist/src/messaging/converters/video.js.map +7 -0
- package/dist/src/messaging/converters/vote.js +24 -0
- package/dist/src/messaging/converters/vote.js.map +7 -0
- package/dist/src/messaging/inbound/dedup.js +82 -0
- package/dist/src/messaging/inbound/dedup.js.map +7 -0
- package/dist/src/messaging/inbound/dispatch-builders.js +98 -0
- package/dist/src/messaging/inbound/dispatch-builders.js.map +7 -0
- package/dist/src/messaging/inbound/dispatch-commands.js +94 -0
- package/dist/src/messaging/inbound/dispatch-commands.js.map +7 -0
- package/dist/src/messaging/inbound/dispatch-context.js +96 -0
- package/dist/src/messaging/inbound/dispatch-context.js.map +7 -0
- package/dist/src/messaging/inbound/dispatch.js +150 -0
- package/dist/src/messaging/inbound/dispatch.js.map +7 -0
- package/dist/src/messaging/inbound/enrich.js +137 -0
- package/dist/src/messaging/inbound/enrich.js.map +7 -0
- package/dist/src/messaging/inbound/gate-effects.js +28 -0
- package/dist/src/messaging/inbound/gate-effects.js.map +7 -0
- package/dist/src/messaging/inbound/gate.js +163 -0
- package/dist/src/messaging/inbound/gate.js.map +7 -0
- package/dist/src/messaging/inbound/handler.js +132 -0
- package/dist/src/messaging/inbound/handler.js.map +7 -0
- package/dist/src/messaging/inbound/media-resolver.js +70 -0
- package/dist/src/messaging/inbound/media-resolver.js.map +7 -0
- package/dist/src/messaging/inbound/mention.js +50 -0
- package/dist/src/messaging/inbound/mention.js.map +7 -0
- package/dist/src/messaging/inbound/parse-io.js +41 -0
- package/dist/src/messaging/inbound/parse-io.js.map +7 -0
- package/dist/src/messaging/inbound/parse.js +79 -0
- package/dist/src/messaging/inbound/parse.js.map +7 -0
- package/dist/src/messaging/inbound/permission.js +30 -0
- package/dist/src/messaging/inbound/permission.js.map +7 -0
- package/dist/src/messaging/inbound/policy.js +83 -0
- package/dist/src/messaging/inbound/policy.js.map +7 -0
- package/dist/src/messaging/inbound/reaction-handler.js +162 -0
- package/dist/src/messaging/inbound/reaction-handler.js.map +7 -0
- package/dist/src/messaging/inbound/user-name-cache.js +172 -0
- package/dist/src/messaging/inbound/user-name-cache.js.map +7 -0
- package/dist/src/messaging/outbound/actions.js +239 -0
- package/dist/src/messaging/outbound/actions.js.map +7 -0
- package/dist/src/messaging/outbound/chat-manage.js +74 -0
- package/dist/src/messaging/outbound/chat-manage.js.map +7 -0
- package/dist/src/messaging/outbound/deliver.js +162 -0
- package/dist/src/messaging/outbound/deliver.js.map +7 -0
- package/dist/src/messaging/outbound/fetch.js +7 -0
- package/dist/src/messaging/outbound/fetch.js.map +7 -0
- package/dist/src/messaging/outbound/forward.js +31 -0
- package/dist/src/messaging/outbound/forward.js.map +7 -0
- package/dist/src/messaging/outbound/media-url-utils.js +101 -0
- package/dist/src/messaging/outbound/media-url-utils.js.map +7 -0
- package/dist/src/messaging/outbound/media.js +463 -0
- package/dist/src/messaging/outbound/media.js.map +7 -0
- package/dist/src/messaging/outbound/outbound.js +95 -0
- package/dist/src/messaging/outbound/outbound.js.map +7 -0
- package/dist/src/messaging/outbound/reactions.js +312 -0
- package/dist/src/messaging/outbound/reactions.js.map +7 -0
- package/dist/src/messaging/outbound/send.js +194 -0
- package/dist/src/messaging/outbound/send.js.map +7 -0
- package/dist/src/messaging/outbound/typing.js +77 -0
- package/dist/src/messaging/outbound/typing.js.map +7 -0
- package/dist/src/messaging/shared/message-lookup.js +84 -0
- package/dist/src/messaging/shared/message-lookup.js.map +7 -0
- package/dist/src/messaging/types.js +1 -0
- package/dist/src/messaging/types.js.map +7 -0
- package/dist/src/tools/auto-auth.js +714 -0
- package/dist/src/tools/auto-auth.js.map +7 -0
- package/dist/src/tools/helpers.js +133 -0
- package/dist/src/tools/helpers.js.map +7 -0
- package/dist/src/tools/mcp/doc/create.js +35 -0
- package/dist/src/tools/mcp/doc/create.js.map +7 -0
- package/dist/src/tools/mcp/doc/fetch.js +33 -0
- package/dist/src/tools/mcp/doc/fetch.js.map +7 -0
- package/dist/src/tools/mcp/doc/index.js +32 -0
- package/dist/src/tools/mcp/doc/index.js.map +7 -0
- package/dist/src/tools/mcp/doc/update.js +61 -0
- package/dist/src/tools/mcp/doc/update.js.map +7 -0
- package/dist/src/tools/mcp/project/endpoint.js +25 -0
- package/dist/src/tools/mcp/project/endpoint.js.map +7 -0
- package/dist/src/tools/mcp/project/index.js +27 -0
- package/dist/src/tools/mcp/project/index.js.map +7 -0
- package/dist/src/tools/mcp/project/tools.js +579 -0
- package/dist/src/tools/mcp/project/tools.js.map +7 -0
- package/dist/src/tools/mcp/shared.js +170 -0
- package/dist/src/tools/mcp/shared.js.map +7 -0
- package/dist/src/tools/oapi/bitable/app-table-field.js +244 -0
- package/dist/src/tools/oapi/bitable/app-table-field.js.map +7 -0
- package/dist/src/tools/oapi/bitable/app-table-record.js +501 -0
- package/dist/src/tools/oapi/bitable/app-table-record.js.map +7 -0
- package/dist/src/tools/oapi/bitable/app-table-view.js +226 -0
- package/dist/src/tools/oapi/bitable/app-table-view.js.map +7 -0
- package/dist/src/tools/oapi/bitable/app-table.js +278 -0
- package/dist/src/tools/oapi/bitable/app-table.js.map +7 -0
- package/dist/src/tools/oapi/bitable/app.js +200 -0
- package/dist/src/tools/oapi/bitable/app.js.map +7 -0
- package/dist/src/tools/oapi/bitable/index.js +13 -0
- package/dist/src/tools/oapi/bitable/index.js.map +7 -0
- package/dist/src/tools/oapi/calendar/calendar.js +131 -0
- package/dist/src/tools/oapi/calendar/calendar.js.map +7 -0
- package/dist/src/tools/oapi/calendar/event-attendee.js +301 -0
- package/dist/src/tools/oapi/calendar/event-attendee.js.map +7 -0
- package/dist/src/tools/oapi/calendar/event.js +834 -0
- package/dist/src/tools/oapi/calendar/event.js.map +7 -0
- package/dist/src/tools/oapi/calendar/freebusy.js +111 -0
- package/dist/src/tools/oapi/calendar/freebusy.js.map +7 -0
- package/dist/src/tools/oapi/calendar/index.js +11 -0
- package/dist/src/tools/oapi/calendar/index.js.map +7 -0
- package/dist/src/tools/oapi/chat/chat.js +132 -0
- package/dist/src/tools/oapi/chat/chat.js.map +7 -0
- package/dist/src/tools/oapi/chat/index.js +11 -0
- package/dist/src/tools/oapi/chat/index.js.map +7 -0
- package/dist/src/tools/oapi/chat/members.js +83 -0
- package/dist/src/tools/oapi/chat/members.js.map +7 -0
- package/dist/src/tools/oapi/common/get-user.js +95 -0
- package/dist/src/tools/oapi/common/get-user.js.map +7 -0
- package/dist/src/tools/oapi/common/index.js +7 -0
- package/dist/src/tools/oapi/common/index.js.map +7 -0
- package/dist/src/tools/oapi/common/search-user.js +67 -0
- package/dist/src/tools/oapi/common/search-user.js.map +7 -0
- package/dist/src/tools/oapi/drive/doc-comments.js +310 -0
- package/dist/src/tools/oapi/drive/doc-comments.js.map +7 -0
- package/dist/src/tools/oapi/drive/doc-media.js +314 -0
- package/dist/src/tools/oapi/drive/doc-media.js.map +7 -0
- package/dist/src/tools/oapi/drive/file.js +548 -0
- package/dist/src/tools/oapi/drive/file.js.map +7 -0
- package/dist/src/tools/oapi/drive/index.js +29 -0
- package/dist/src/tools/oapi/drive/index.js.map +7 -0
- package/dist/src/tools/oapi/helpers.js +199 -0
- package/dist/src/tools/oapi/helpers.js.map +7 -0
- package/dist/src/tools/oapi/im/format-messages.js +128 -0
- package/dist/src/tools/oapi/im/format-messages.js.map +7 -0
- package/dist/src/tools/oapi/im/index.js +15 -0
- package/dist/src/tools/oapi/im/index.js.map +7 -0
- package/dist/src/tools/oapi/im/message-read.js +404 -0
- package/dist/src/tools/oapi/im/message-read.js.map +7 -0
- package/dist/src/tools/oapi/im/message.js +179 -0
- package/dist/src/tools/oapi/im/message.js.map +7 -0
- package/dist/src/tools/oapi/im/resource.js +126 -0
- package/dist/src/tools/oapi/im/resource.js.map +7 -0
- package/dist/src/tools/oapi/im/time-utils.js +169 -0
- package/dist/src/tools/oapi/im/time-utils.js.map +7 -0
- package/dist/src/tools/oapi/im/user-name-uat.js +103 -0
- package/dist/src/tools/oapi/im/user-name-uat.js.map +7 -0
- package/dist/src/tools/oapi/index.js +56 -0
- package/dist/src/tools/oapi/index.js.map +7 -0
- package/dist/src/tools/oapi/sdk-types.js +1 -0
- package/dist/src/tools/oapi/sdk-types.js.map +7 -0
- package/dist/src/tools/oapi/search/doc-search.js +215 -0
- package/dist/src/tools/oapi/search/doc-search.js.map +7 -0
- package/dist/src/tools/oapi/search/index.js +25 -0
- package/dist/src/tools/oapi/search/index.js.map +7 -0
- package/dist/src/tools/oapi/sheets/index.js +25 -0
- package/dist/src/tools/oapi/sheets/index.js.map +7 -0
- package/dist/src/tools/oapi/sheets/sheet.js +652 -0
- package/dist/src/tools/oapi/sheets/sheet.js.map +7 -0
- package/dist/src/tools/oapi/task/comment.js +151 -0
- package/dist/src/tools/oapi/task/comment.js.map +7 -0
- package/dist/src/tools/oapi/task/index.js +11 -0
- package/dist/src/tools/oapi/task/index.js.map +7 -0
- package/dist/src/tools/oapi/task/subtask.js +175 -0
- package/dist/src/tools/oapi/task/subtask.js.map +7 -0
- package/dist/src/tools/oapi/task/task.js +405 -0
- package/dist/src/tools/oapi/task/task.js.map +7 -0
- package/dist/src/tools/oapi/task/tasklist.js +366 -0
- package/dist/src/tools/oapi/task/tasklist.js.map +7 -0
- package/dist/src/tools/oapi/wiki/index.js +27 -0
- package/dist/src/tools/oapi/wiki/index.js.map +7 -0
- package/dist/src/tools/oapi/wiki/space-node.js +311 -0
- package/dist/src/tools/oapi/wiki/space-node.js.map +7 -0
- package/dist/src/tools/oapi/wiki/space.js +148 -0
- package/dist/src/tools/oapi/wiki/space.js.map +7 -0
- package/dist/src/tools/oauth-batch-auth.js +125 -0
- package/dist/src/tools/oauth-batch-auth.js.map +7 -0
- package/dist/src/tools/oauth-cards.js +269 -0
- package/dist/src/tools/oauth-cards.js.map +7 -0
- package/dist/src/tools/oauth.js +538 -0
- package/dist/src/tools/oauth.js.map +7 -0
- package/dist/src/tools/onboarding-auth.js +101 -0
- package/dist/src/tools/onboarding-auth.js.map +7 -0
- package/dist/src/tools/project-oauth.js +305 -0
- package/dist/src/tools/project-oauth.js.map +7 -0
- package/dist/src/tools/tat/im/index.js +9 -0
- package/dist/src/tools/tat/im/index.js.map +7 -0
- package/dist/src/tools/tat/im/resource.js +123 -0
- package/dist/src/tools/tat/im/resource.js.map +7 -0
- package/package.json +64 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
import { Type } from "@sinclair/typebox";
|
|
2
|
+
import { json, createToolContext, assertLarkOk, handleInvokeErrorWithAutoAuth } from "../helpers";
|
|
3
|
+
const FeishuImMessageSchema = Type.Union([
|
|
4
|
+
// SEND
|
|
5
|
+
Type.Object({
|
|
6
|
+
action: Type.Literal("send"),
|
|
7
|
+
receive_id_type: Type.Union([Type.Literal("open_id"), Type.Literal("chat_id")], {
|
|
8
|
+
description: "\u63A5\u6536\u8005 ID \u7C7B\u578B\uFF1Aopen_id\uFF08\u79C1\u804A\uFF0Cou_xxx\uFF09\u3001chat_id\uFF08\u7FA4\u804A\uFF0Coc_xxx\uFF09"
|
|
9
|
+
}),
|
|
10
|
+
receive_id: Type.String({
|
|
11
|
+
description: "\u63A5\u6536\u8005 ID\uFF0C\u4E0E receive_id_type \u5BF9\u5E94\u3002open_id \u586B 'ou_xxx'\uFF0Cchat_id \u586B 'oc_xxx'"
|
|
12
|
+
}),
|
|
13
|
+
msg_type: Type.Union(
|
|
14
|
+
[
|
|
15
|
+
Type.Literal("text"),
|
|
16
|
+
Type.Literal("post"),
|
|
17
|
+
Type.Literal("image"),
|
|
18
|
+
Type.Literal("file"),
|
|
19
|
+
Type.Literal("audio"),
|
|
20
|
+
Type.Literal("media"),
|
|
21
|
+
Type.Literal("interactive"),
|
|
22
|
+
Type.Literal("share_chat"),
|
|
23
|
+
Type.Literal("share_user")
|
|
24
|
+
],
|
|
25
|
+
{
|
|
26
|
+
description: "\u6D88\u606F\u7C7B\u578B\uFF1Atext\uFF08\u7EAF\u6587\u672C\uFF09\u3001post\uFF08\u5BCC\u6587\u672C\uFF09\u3001image\uFF08\u56FE\u7247\uFF09\u3001file\uFF08\u6587\u4EF6\uFF09\u3001interactive\uFF08\u6D88\u606F\u5361\u7247\uFF09\u3001share_chat\uFF08\u7FA4\u540D\u7247\uFF09\u3001share_user\uFF08\u4E2A\u4EBA\u540D\u7247\uFF09\u7B49"
|
|
27
|
+
}
|
|
28
|
+
),
|
|
29
|
+
content: Type.String({
|
|
30
|
+
description: `\u6D88\u606F\u5185\u5BB9\uFF08JSON \u5B57\u7B26\u4E32\uFF09\uFF0C\u683C\u5F0F\u53D6\u51B3\u4E8E msg_type\u3002\u793A\u4F8B\uFF1Atext \u2192 '{"text":"\u4F60\u597D"}'\uFF0Cimage \u2192 '{"image_key":"img_xxx"}'\uFF0Cshare_chat \u2192 '{"chat_id":"oc_xxx"}'\uFF0Cpost \u2192 '{"zh_cn":{"title":"\u6807\u9898","content":[[{"tag":"text","text":"\u6B63\u6587"}]]}}'`
|
|
31
|
+
}),
|
|
32
|
+
uuid: Type.Optional(
|
|
33
|
+
Type.String({
|
|
34
|
+
description: "\u5E42\u7B49\u552F\u4E00\u6807\u8BC6\u3002\u540C\u4E00 uuid \u5728 1 \u5C0F\u65F6\u5185\u53EA\u4F1A\u53D1\u9001\u4E00\u6761\u6D88\u606F\uFF0C\u7528\u4E8E\u53BB\u91CD"
|
|
35
|
+
})
|
|
36
|
+
)
|
|
37
|
+
}),
|
|
38
|
+
// REPLY
|
|
39
|
+
Type.Object({
|
|
40
|
+
action: Type.Literal("reply"),
|
|
41
|
+
message_id: Type.String({
|
|
42
|
+
description: "\u88AB\u56DE\u590D\u6D88\u606F\u7684 ID\uFF08om_xxx \u683C\u5F0F\uFF09"
|
|
43
|
+
}),
|
|
44
|
+
msg_type: Type.Union(
|
|
45
|
+
[
|
|
46
|
+
Type.Literal("text"),
|
|
47
|
+
Type.Literal("post"),
|
|
48
|
+
Type.Literal("image"),
|
|
49
|
+
Type.Literal("file"),
|
|
50
|
+
Type.Literal("audio"),
|
|
51
|
+
Type.Literal("media"),
|
|
52
|
+
Type.Literal("interactive"),
|
|
53
|
+
Type.Literal("share_chat"),
|
|
54
|
+
Type.Literal("share_user")
|
|
55
|
+
],
|
|
56
|
+
{
|
|
57
|
+
description: "\u6D88\u606F\u7C7B\u578B\uFF1Atext\uFF08\u7EAF\u6587\u672C\uFF09\u3001post\uFF08\u5BCC\u6587\u672C\uFF09\u3001image\uFF08\u56FE\u7247\uFF09\u3001interactive\uFF08\u6D88\u606F\u5361\u7247\uFF09\u7B49"
|
|
58
|
+
}
|
|
59
|
+
),
|
|
60
|
+
content: Type.String({
|
|
61
|
+
description: "\u56DE\u590D\u6D88\u606F\u5185\u5BB9\uFF08JSON \u5B57\u7B26\u4E32\uFF09\uFF0C\u683C\u5F0F\u540C send \u7684 content"
|
|
62
|
+
}),
|
|
63
|
+
reply_in_thread: Type.Optional(
|
|
64
|
+
Type.Boolean({
|
|
65
|
+
description: "\u662F\u5426\u4EE5\u8BDD\u9898\u5F62\u5F0F\u56DE\u590D\u3002true \u5219\u6D88\u606F\u51FA\u73B0\u5728\u8BE5\u6D88\u606F\u7684\u8BDD\u9898\u4E2D\uFF0Cfalse\uFF08\u9ED8\u8BA4\uFF09\u5219\u51FA\u73B0\u5728\u804A\u5929\u4E3B\u6D41"
|
|
66
|
+
})
|
|
67
|
+
),
|
|
68
|
+
uuid: Type.Optional(
|
|
69
|
+
Type.String({
|
|
70
|
+
description: "\u5E42\u7B49\u552F\u4E00\u6807\u8BC6"
|
|
71
|
+
})
|
|
72
|
+
)
|
|
73
|
+
})
|
|
74
|
+
]);
|
|
75
|
+
function registerFeishuImUserMessageTool(api) {
|
|
76
|
+
if (!api.config) return;
|
|
77
|
+
const cfg = api.config;
|
|
78
|
+
const { toolClient, log } = createToolContext(api, "feishu_im_user_message");
|
|
79
|
+
api.registerTool(
|
|
80
|
+
{
|
|
81
|
+
name: "feishu_im_user_message",
|
|
82
|
+
label: "Feishu: IM User Message",
|
|
83
|
+
description: `\u98DE\u4E66\u7528\u6237\u8EAB\u4EFD IM \u6D88\u606F\u5DE5\u5177\u3002**\u6709\u4E14\u4EC5\u5F53\u7528\u6237\u660E\u786E\u8981\u6C42\u4EE5\u81EA\u5DF1\u8EAB\u4EFD\u53D1\u6D88\u606F\u3001\u56DE\u590D\u6D88\u606F\u65F6\u4F7F\u7528\uFF0C\u5F53\u6CA1\u6709\u660E\u786E\u8981\u6C42\u65F6\u4F18\u5148\u4F7F\u7528message\u7CFB\u7EDF\u5DE5\u5177**\u3002
|
|
84
|
+
|
|
85
|
+
Actions:
|
|
86
|
+
- send\uFF08\u53D1\u9001\u6D88\u606F\uFF09\uFF1A\u53D1\u9001\u6D88\u606F\u5230\u79C1\u804A\u6216\u7FA4\u804A\u3002\u79C1\u804A\u7528 receive_id_type=open_id\uFF0C\u7FA4\u804A\u7528 receive_id_type=chat_id
|
|
87
|
+
- reply\uFF08\u56DE\u590D\u6D88\u606F\uFF09\uFF1A\u56DE\u590D\u6307\u5B9A message_id \u7684\u6D88\u606F\uFF0C\u652F\u6301\u8BDD\u9898\u56DE\u590D\uFF08reply_in_thread=true\uFF09
|
|
88
|
+
|
|
89
|
+
\u3010\u91CD\u8981\u3011content \u5FC5\u987B\u662F\u5408\u6CD5 JSON \u5B57\u7B26\u4E32\uFF0C\u683C\u5F0F\u53D6\u51B3\u4E8E msg_type\u3002\u6700\u5E38\u7528\uFF1Atext \u7C7B\u578B content \u4E3A '{"text":"\u6D88\u606F\u5185\u5BB9"}'\u3002
|
|
90
|
+
|
|
91
|
+
\u3010\u5B89\u5168\u7EA6\u675F\u3011\u6B64\u5DE5\u5177\u4EE5\u7528\u6237\u8EAB\u4EFD\u53D1\u9001\u6D88\u606F\uFF0C\u53D1\u51FA\u540E\u5BF9\u65B9\u770B\u5230\u7684\u53D1\u9001\u8005\u662F\u7528\u6237\u672C\u4EBA\u3002\u8C03\u7528\u524D\u5FC5\u987B\u5148\u5411\u7528\u6237\u786E\u8BA4\uFF1A1) \u53D1\u9001\u5BF9\u8C61\uFF08\u54EA\u4E2A\u4EBA\u6216\u54EA\u4E2A\u7FA4\uFF092) \u6D88\u606F\u5185\u5BB9\u3002\u7981\u6B62\u5728\u7528\u6237\u672A\u660E\u786E\u540C\u610F\u7684\u60C5\u51B5\u4E0B\u81EA\u884C\u53D1\u9001\u6D88\u606F\u3002`,
|
|
92
|
+
parameters: FeishuImMessageSchema,
|
|
93
|
+
async execute(_toolCallId, params) {
|
|
94
|
+
const p = params;
|
|
95
|
+
try {
|
|
96
|
+
const client = toolClient();
|
|
97
|
+
switch (p.action) {
|
|
98
|
+
// -----------------------------------------------------------------
|
|
99
|
+
// SEND MESSAGE
|
|
100
|
+
// -----------------------------------------------------------------
|
|
101
|
+
case "send": {
|
|
102
|
+
log.info(
|
|
103
|
+
`send: receive_id_type=${p.receive_id_type}, receive_id=${p.receive_id}, msg_type=${p.msg_type}`
|
|
104
|
+
);
|
|
105
|
+
const res = await client.invoke(
|
|
106
|
+
"feishu_im_user_message.send",
|
|
107
|
+
(sdk, opts) => sdk.im.v1.message.create(
|
|
108
|
+
{
|
|
109
|
+
params: { receive_id_type: p.receive_id_type },
|
|
110
|
+
data: {
|
|
111
|
+
receive_id: p.receive_id,
|
|
112
|
+
msg_type: p.msg_type,
|
|
113
|
+
content: p.content,
|
|
114
|
+
uuid: p.uuid
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
opts
|
|
118
|
+
),
|
|
119
|
+
{
|
|
120
|
+
as: "user"
|
|
121
|
+
}
|
|
122
|
+
);
|
|
123
|
+
assertLarkOk(res);
|
|
124
|
+
const data = res.data;
|
|
125
|
+
log.info(`send: message sent, message_id=${data?.message_id}`);
|
|
126
|
+
return json({
|
|
127
|
+
message_id: data?.message_id,
|
|
128
|
+
chat_id: data?.chat_id,
|
|
129
|
+
create_time: data?.create_time
|
|
130
|
+
});
|
|
131
|
+
}
|
|
132
|
+
// -----------------------------------------------------------------
|
|
133
|
+
// REPLY MESSAGE
|
|
134
|
+
// -----------------------------------------------------------------
|
|
135
|
+
case "reply": {
|
|
136
|
+
log.info(
|
|
137
|
+
`reply: message_id=${p.message_id}, msg_type=${p.msg_type}, reply_in_thread=${p.reply_in_thread ?? false}`
|
|
138
|
+
);
|
|
139
|
+
const res = await client.invoke(
|
|
140
|
+
"feishu_im_user_message.reply",
|
|
141
|
+
(sdk, opts) => sdk.im.v1.message.reply(
|
|
142
|
+
{
|
|
143
|
+
path: { message_id: p.message_id },
|
|
144
|
+
data: {
|
|
145
|
+
content: p.content,
|
|
146
|
+
msg_type: p.msg_type,
|
|
147
|
+
reply_in_thread: p.reply_in_thread,
|
|
148
|
+
uuid: p.uuid
|
|
149
|
+
}
|
|
150
|
+
},
|
|
151
|
+
opts
|
|
152
|
+
),
|
|
153
|
+
{
|
|
154
|
+
as: "user"
|
|
155
|
+
}
|
|
156
|
+
);
|
|
157
|
+
assertLarkOk(res);
|
|
158
|
+
const data = res.data;
|
|
159
|
+
log.info(`reply: message sent, message_id=${data?.message_id}`);
|
|
160
|
+
return json({
|
|
161
|
+
message_id: data?.message_id,
|
|
162
|
+
chat_id: data?.chat_id,
|
|
163
|
+
create_time: data?.create_time
|
|
164
|
+
});
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
} catch (err) {
|
|
168
|
+
return await handleInvokeErrorWithAutoAuth(err, cfg);
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
},
|
|
172
|
+
{ name: "feishu_im_user_message" }
|
|
173
|
+
);
|
|
174
|
+
api.logger.info?.("feishu_im_user_message: Registered feishu_im_user_message tool");
|
|
175
|
+
}
|
|
176
|
+
export {
|
|
177
|
+
registerFeishuImUserMessageTool
|
|
178
|
+
};
|
|
179
|
+
//# sourceMappingURL=message.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/oapi/im/message.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * feishu_im_user_message tool -- \u4EE5\u7528\u6237\u8EAB\u4EFD\u53D1\u9001/\u56DE\u590D IM \u6D88\u606F\n *\n * Actions: send, reply\n *\n * Uses the Feishu IM API:\n * - send: POST /open-apis/im/v1/messages?receive_id_type=...\n * - reply: POST /open-apis/im/v1/messages/:message_id/reply\n *\n * \u5168\u90E8\u4EE5\u7528\u6237\u8EAB\u4EFD\uFF08user_access_token\uFF09\u8C03\u7528\uFF0Cscope \u6765\u81EA real-scope.json\u3002\n */\n\nimport type { OpenClawPluginApi } from 'openclaw/plugin-sdk';\nimport { Type } from '@sinclair/typebox';\nimport { json, createToolContext, assertLarkOk, handleInvokeErrorWithAutoAuth } from '../helpers';\n\n// ---------------------------------------------------------------------------\n// Schema\n// ---------------------------------------------------------------------------\n\nconst FeishuImMessageSchema = Type.Union([\n // SEND\n Type.Object({\n action: Type.Literal('send'),\n receive_id_type: Type.Union([Type.Literal('open_id'), Type.Literal('chat_id')], {\n description: '\u63A5\u6536\u8005 ID \u7C7B\u578B\uFF1Aopen_id\uFF08\u79C1\u804A\uFF0Cou_xxx\uFF09\u3001chat_id\uFF08\u7FA4\u804A\uFF0Coc_xxx\uFF09',\n }),\n receive_id: Type.String({\n description: \"\u63A5\u6536\u8005 ID\uFF0C\u4E0E receive_id_type \u5BF9\u5E94\u3002open_id \u586B 'ou_xxx'\uFF0Cchat_id \u586B 'oc_xxx'\",\n }),\n msg_type: Type.Union(\n [\n Type.Literal('text'),\n Type.Literal('post'),\n Type.Literal('image'),\n Type.Literal('file'),\n Type.Literal('audio'),\n Type.Literal('media'),\n Type.Literal('interactive'),\n Type.Literal('share_chat'),\n Type.Literal('share_user'),\n ],\n {\n description:\n '\u6D88\u606F\u7C7B\u578B\uFF1Atext\uFF08\u7EAF\u6587\u672C\uFF09\u3001post\uFF08\u5BCC\u6587\u672C\uFF09\u3001image\uFF08\u56FE\u7247\uFF09\u3001file\uFF08\u6587\u4EF6\uFF09\u3001interactive\uFF08\u6D88\u606F\u5361\u7247\uFF09\u3001share_chat\uFF08\u7FA4\u540D\u7247\uFF09\u3001share_user\uFF08\u4E2A\u4EBA\u540D\u7247\uFF09\u7B49',\n },\n ),\n content: Type.String({\n description:\n '\u6D88\u606F\u5185\u5BB9\uFF08JSON \u5B57\u7B26\u4E32\uFF09\uFF0C\u683C\u5F0F\u53D6\u51B3\u4E8E msg_type\u3002' +\n '\u793A\u4F8B\uFF1Atext \u2192 \\'{\"text\":\"\u4F60\u597D\"}\\'\uFF0C' +\n 'image \u2192 \\'{\"image_key\":\"img_xxx\"}\\'\uFF0C' +\n 'share_chat \u2192 \\'{\"chat_id\":\"oc_xxx\"}\\'\uFF0C' +\n 'post \u2192 \\'{\"zh_cn\":{\"title\":\"\u6807\u9898\",\"content\":[[{\"tag\":\"text\",\"text\":\"\u6B63\u6587\"}]]}}\\'',\n }),\n uuid: Type.Optional(\n Type.String({\n description: '\u5E42\u7B49\u552F\u4E00\u6807\u8BC6\u3002\u540C\u4E00 uuid \u5728 1 \u5C0F\u65F6\u5185\u53EA\u4F1A\u53D1\u9001\u4E00\u6761\u6D88\u606F\uFF0C\u7528\u4E8E\u53BB\u91CD',\n }),\n ),\n }),\n\n // REPLY\n Type.Object({\n action: Type.Literal('reply'),\n message_id: Type.String({\n description: '\u88AB\u56DE\u590D\u6D88\u606F\u7684 ID\uFF08om_xxx \u683C\u5F0F\uFF09',\n }),\n msg_type: Type.Union(\n [\n Type.Literal('text'),\n Type.Literal('post'),\n Type.Literal('image'),\n Type.Literal('file'),\n Type.Literal('audio'),\n Type.Literal('media'),\n Type.Literal('interactive'),\n Type.Literal('share_chat'),\n Type.Literal('share_user'),\n ],\n {\n description: '\u6D88\u606F\u7C7B\u578B\uFF1Atext\uFF08\u7EAF\u6587\u672C\uFF09\u3001post\uFF08\u5BCC\u6587\u672C\uFF09\u3001image\uFF08\u56FE\u7247\uFF09\u3001interactive\uFF08\u6D88\u606F\u5361\u7247\uFF09\u7B49',\n },\n ),\n content: Type.String({\n description: '\u56DE\u590D\u6D88\u606F\u5185\u5BB9\uFF08JSON \u5B57\u7B26\u4E32\uFF09\uFF0C\u683C\u5F0F\u540C send \u7684 content',\n }),\n reply_in_thread: Type.Optional(\n Type.Boolean({\n description: '\u662F\u5426\u4EE5\u8BDD\u9898\u5F62\u5F0F\u56DE\u590D\u3002true \u5219\u6D88\u606F\u51FA\u73B0\u5728\u8BE5\u6D88\u606F\u7684\u8BDD\u9898\u4E2D\uFF0Cfalse\uFF08\u9ED8\u8BA4\uFF09\u5219\u51FA\u73B0\u5728\u804A\u5929\u4E3B\u6D41',\n }),\n ),\n uuid: Type.Optional(\n Type.String({\n description: '\u5E42\u7B49\u552F\u4E00\u6807\u8BC6',\n }),\n ),\n }),\n]);\n\n// ---------------------------------------------------------------------------\n// Params type\n// ---------------------------------------------------------------------------\n\ntype FeishuImMessageParams =\n | {\n action: 'send';\n receive_id_type: 'open_id' | 'chat_id';\n receive_id: string;\n msg_type: string;\n content: string;\n uuid?: string;\n }\n | {\n action: 'reply';\n message_id: string;\n msg_type: string;\n content: string;\n reply_in_thread?: boolean;\n uuid?: string;\n };\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\nexport function registerFeishuImUserMessageTool(api: OpenClawPluginApi) {\n if (!api.config) return;\n const cfg = api.config;\n\n const { toolClient, log } = createToolContext(api, 'feishu_im_user_message');\n\n api.registerTool(\n {\n name: 'feishu_im_user_message',\n label: 'Feishu: IM User Message',\n description:\n '\u98DE\u4E66\u7528\u6237\u8EAB\u4EFD IM \u6D88\u606F\u5DE5\u5177\u3002**\u6709\u4E14\u4EC5\u5F53\u7528\u6237\u660E\u786E\u8981\u6C42\u4EE5\u81EA\u5DF1\u8EAB\u4EFD\u53D1\u6D88\u606F\u3001\u56DE\u590D\u6D88\u606F\u65F6\u4F7F\u7528\uFF0C\u5F53\u6CA1\u6709\u660E\u786E\u8981\u6C42\u65F6\u4F18\u5148\u4F7F\u7528message\u7CFB\u7EDF\u5DE5\u5177**\u3002' +\n '\\n\\nActions:' +\n '\\n- send\uFF08\u53D1\u9001\u6D88\u606F\uFF09\uFF1A\u53D1\u9001\u6D88\u606F\u5230\u79C1\u804A\u6216\u7FA4\u804A\u3002\u79C1\u804A\u7528 receive_id_type=open_id\uFF0C\u7FA4\u804A\u7528 receive_id_type=chat_id' +\n '\\n- reply\uFF08\u56DE\u590D\u6D88\u606F\uFF09\uFF1A\u56DE\u590D\u6307\u5B9A message_id \u7684\u6D88\u606F\uFF0C\u652F\u6301\u8BDD\u9898\u56DE\u590D\uFF08reply_in_thread=true\uFF09' +\n '\\n\\n\u3010\u91CD\u8981\u3011content \u5FC5\u987B\u662F\u5408\u6CD5 JSON \u5B57\u7B26\u4E32\uFF0C\u683C\u5F0F\u53D6\u51B3\u4E8E msg_type\u3002' +\n '\u6700\u5E38\u7528\uFF1Atext \u7C7B\u578B content \u4E3A \\'{\"text\":\"\u6D88\u606F\u5185\u5BB9\"}\\'\u3002' +\n '\\n\\n\u3010\u5B89\u5168\u7EA6\u675F\u3011\u6B64\u5DE5\u5177\u4EE5\u7528\u6237\u8EAB\u4EFD\u53D1\u9001\u6D88\u606F\uFF0C\u53D1\u51FA\u540E\u5BF9\u65B9\u770B\u5230\u7684\u53D1\u9001\u8005\u662F\u7528\u6237\u672C\u4EBA\u3002' +\n '\u8C03\u7528\u524D\u5FC5\u987B\u5148\u5411\u7528\u6237\u786E\u8BA4\uFF1A1) \u53D1\u9001\u5BF9\u8C61\uFF08\u54EA\u4E2A\u4EBA\u6216\u54EA\u4E2A\u7FA4\uFF092) \u6D88\u606F\u5185\u5BB9\u3002' +\n '\u7981\u6B62\u5728\u7528\u6237\u672A\u660E\u786E\u540C\u610F\u7684\u60C5\u51B5\u4E0B\u81EA\u884C\u53D1\u9001\u6D88\u606F\u3002',\n parameters: FeishuImMessageSchema,\n async execute(_toolCallId: string, params: unknown) {\n const p = params as FeishuImMessageParams;\n try {\n const client = toolClient();\n\n switch (p.action) {\n // -----------------------------------------------------------------\n // SEND MESSAGE\n // -----------------------------------------------------------------\n case 'send': {\n log.info(\n `send: receive_id_type=${p.receive_id_type}, receive_id=${p.receive_id}, msg_type=${p.msg_type}`,\n );\n\n const res = await client.invoke(\n 'feishu_im_user_message.send',\n (sdk, opts) =>\n sdk.im.v1.message.create(\n {\n params: { receive_id_type: p.receive_id_type },\n data: {\n receive_id: p.receive_id,\n msg_type: p.msg_type,\n content: p.content,\n uuid: p.uuid,\n },\n },\n opts,\n ),\n {\n as: 'user',\n },\n );\n assertLarkOk(res);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const data = res.data as any;\n log.info(`send: message sent, message_id=${data?.message_id}`);\n\n return json({\n message_id: data?.message_id,\n chat_id: data?.chat_id,\n create_time: data?.create_time,\n });\n }\n\n // -----------------------------------------------------------------\n // REPLY MESSAGE\n // -----------------------------------------------------------------\n case 'reply': {\n log.info(\n `reply: message_id=${p.message_id}, msg_type=${p.msg_type}, reply_in_thread=${p.reply_in_thread ?? false}`,\n );\n\n const res = await client.invoke(\n 'feishu_im_user_message.reply',\n (sdk, opts) =>\n sdk.im.v1.message.reply(\n {\n path: { message_id: p.message_id },\n data: {\n content: p.content,\n msg_type: p.msg_type,\n reply_in_thread: p.reply_in_thread,\n uuid: p.uuid,\n },\n },\n opts,\n ),\n {\n as: 'user',\n },\n );\n assertLarkOk(res);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const data = res.data as any;\n log.info(`reply: message sent, message_id=${data?.message_id}`);\n\n return json({\n message_id: data?.message_id,\n chat_id: data?.chat_id,\n create_time: data?.create_time,\n });\n }\n }\n } catch (err) {\n return await handleInvokeErrorWithAutoAuth(err, cfg);\n }\n },\n },\n { name: 'feishu_im_user_message' },\n );\n\n api.logger.info?.('feishu_im_user_message: Registered feishu_im_user_message tool');\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import { buildRandomTempFilePath } from "openclaw/plugin-sdk";
|
|
2
|
+
import { Type } from "@sinclair/typebox";
|
|
3
|
+
import { json, createToolContext, handleInvokeErrorWithAutoAuth } from "../helpers";
|
|
4
|
+
import * as fs from "node:fs/promises";
|
|
5
|
+
import * as path from "node:path";
|
|
6
|
+
const MIME_TO_EXT = {
|
|
7
|
+
// Images
|
|
8
|
+
"image/png": ".png",
|
|
9
|
+
"image/jpeg": ".jpg",
|
|
10
|
+
"image/jpg": ".jpg",
|
|
11
|
+
"image/gif": ".gif",
|
|
12
|
+
"image/webp": ".webp",
|
|
13
|
+
"image/svg+xml": ".svg",
|
|
14
|
+
"image/bmp": ".bmp",
|
|
15
|
+
"image/tiff": ".tiff",
|
|
16
|
+
// Videos
|
|
17
|
+
"video/mp4": ".mp4",
|
|
18
|
+
"video/mpeg": ".mpeg",
|
|
19
|
+
"video/quicktime": ".mov",
|
|
20
|
+
"video/x-msvideo": ".avi",
|
|
21
|
+
"video/webm": ".webm",
|
|
22
|
+
// Audio
|
|
23
|
+
"audio/mpeg": ".mp3",
|
|
24
|
+
"audio/wav": ".wav",
|
|
25
|
+
"audio/ogg": ".ogg",
|
|
26
|
+
"audio/mp4": ".m4a",
|
|
27
|
+
// Documents
|
|
28
|
+
"application/pdf": ".pdf",
|
|
29
|
+
"application/msword": ".doc",
|
|
30
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": ".docx",
|
|
31
|
+
"application/vnd.ms-excel": ".xls",
|
|
32
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": ".xlsx",
|
|
33
|
+
"application/vnd.ms-powerpoint": ".ppt",
|
|
34
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": ".pptx",
|
|
35
|
+
// Others
|
|
36
|
+
"application/zip": ".zip",
|
|
37
|
+
"application/x-rar-compressed": ".rar",
|
|
38
|
+
"text/plain": ".txt",
|
|
39
|
+
"application/json": ".json"
|
|
40
|
+
};
|
|
41
|
+
const FetchResourceSchema = Type.Object({
|
|
42
|
+
message_id: Type.String({
|
|
43
|
+
description: "\u6D88\u606F ID\uFF08om_xxx \u683C\u5F0F\uFF09\uFF0C\u4ECE\u6D88\u606F\u4E8B\u4EF6\u6216\u6D88\u606F\u5217\u8868\u4E2D\u83B7\u53D6"
|
|
44
|
+
}),
|
|
45
|
+
file_key: Type.String({
|
|
46
|
+
description: "\u8D44\u6E90 Key\uFF0C\u4ECE\u6D88\u606F\u4F53\u4E2D\u83B7\u53D6\u3002\u56FE\u7247\u6D88\u606F\u7684 image_key\uFF08img_xxx\uFF09\u6216\u6587\u4EF6\u6D88\u606F\u7684 file_key\uFF08file_xxx\uFF09"
|
|
47
|
+
}),
|
|
48
|
+
type: Type.Union([Type.Literal("image"), Type.Literal("file")], {
|
|
49
|
+
description: "\u8D44\u6E90\u7C7B\u578B\uFF1Aimage\uFF08\u56FE\u7247\u6D88\u606F\u4E2D\u7684\u56FE\u7247\uFF09\u3001file\uFF08\u6587\u4EF6/\u97F3\u9891/\u89C6\u9891\u6D88\u606F\u4E2D\u7684\u6587\u4EF6\uFF09"
|
|
50
|
+
})
|
|
51
|
+
});
|
|
52
|
+
function registerFeishuImUserFetchResourceTool(api) {
|
|
53
|
+
if (!api.config) return;
|
|
54
|
+
const cfg = api.config;
|
|
55
|
+
const { toolClient, log } = createToolContext(api, "feishu_im_user_fetch_resource");
|
|
56
|
+
api.registerTool(
|
|
57
|
+
{
|
|
58
|
+
name: "feishu_im_user_fetch_resource",
|
|
59
|
+
label: "Feishu: IM Fetch Resource",
|
|
60
|
+
description: "\u3010\u4EE5\u7528\u6237\u8EAB\u4EFD\u3011\u4E0B\u8F7D\u98DE\u4E66 IM \u6D88\u606F\u4E2D\u7684\u6587\u4EF6\u6216\u56FE\u7247\u8D44\u6E90\u5230\u672C\u5730\u6587\u4EF6\u3002\u9700\u8981\u7528\u6237 OAuth \u6388\u6743\u3002\n\n\u9002\u7528\u573A\u666F\uFF1A\u5F53\u4F60\u4EE5\u7528\u6237\u8EAB\u4EFD\u8C03\u7528\u4E86\u6D88\u606F\u5217\u8868/\u641C\u7D22\u7B49 API \u83B7\u53D6\u5230 message_id \u548C file_key \u65F6\uFF0C\u5E94\u4F7F\u7528\u672C\u5DE5\u5177\u4EE5\u540C\u6837\u7684\u7528\u6237\u8EAB\u4EFD\u4E0B\u8F7D\u8D44\u6E90\u3002\n\u6CE8\u610F\uFF1A\u5982\u679C message_id \u6765\u81EA\u5F53\u524D\u5BF9\u8BDD\u4E0A\u4E0B\u6587\uFF08\u7528\u6237\u53D1\u7ED9\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3001\u5F15\u7528\u7684\u6D88\u606F\uFF09\uFF0C\u8BF7\u4F7F\u7528 feishu_im_bot_image \u5DE5\u5177\u4EE5\u673A\u5668\u4EBA\u8EAB\u4EFD\u4E0B\u8F7D\uFF0C\u65E0\u9700\u7528\u6237\u6388\u6743\u3002\n\n\u53C2\u6570\u8BF4\u660E\uFF1A\n- message_id\uFF1A\u6D88\u606F ID\uFF08om_xxx\uFF09\uFF0C\u4ECE\u6D88\u606F\u4E8B\u4EF6\u6216\u6D88\u606F\u5217\u8868\u4E2D\u83B7\u53D6\n- file_key\uFF1A\u8D44\u6E90 Key\uFF0C\u4ECE\u6D88\u606F\u4F53\u4E2D\u83B7\u53D6\u3002\u56FE\u7247\u7528 image_key\uFF08img_xxx\uFF09\uFF0C\u6587\u4EF6\u7528 file_key\uFF08file_xxx\uFF09\n- type\uFF1A\u56FE\u7247\u7528 image\uFF0C\u6587\u4EF6/\u97F3\u9891/\u89C6\u9891\u7528 file\n\n\u6587\u4EF6\u81EA\u52A8\u4FDD\u5B58\u5230 /tmp/openclaw/ \u4E0B\uFF0C\u8FD4\u56DE\u503C\u4E2D\u7684 saved_path \u4E3A\u5B9E\u9645\u4FDD\u5B58\u8DEF\u5F84\u3002\n\u9650\u5236\uFF1A\u6587\u4EF6\u5927\u5C0F\u4E0D\u8D85\u8FC7 100MB\u3002\u4E0D\u652F\u6301\u4E0B\u8F7D\u8868\u60C5\u5305\u3001\u5408\u5E76\u8F6C\u53D1\u6D88\u606F\u3001\u5361\u7247\u4E2D\u7684\u8D44\u6E90\u3002",
|
|
61
|
+
parameters: FetchResourceSchema,
|
|
62
|
+
async execute(_toolCallId, params) {
|
|
63
|
+
const p = params;
|
|
64
|
+
try {
|
|
65
|
+
const client = toolClient();
|
|
66
|
+
log.info(`fetch_resource: message_id="${p.message_id}", file_key="${p.file_key}", type="${p.type}"`);
|
|
67
|
+
const res = await client.invoke(
|
|
68
|
+
"feishu_im_user_fetch_resource.default",
|
|
69
|
+
(sdk, opts) => sdk.im.v1.messageResource.get(
|
|
70
|
+
{
|
|
71
|
+
params: { type: p.type },
|
|
72
|
+
path: { message_id: p.message_id, file_key: p.file_key }
|
|
73
|
+
},
|
|
74
|
+
opts
|
|
75
|
+
),
|
|
76
|
+
{
|
|
77
|
+
as: "user"
|
|
78
|
+
}
|
|
79
|
+
);
|
|
80
|
+
const stream = res.getReadableStream();
|
|
81
|
+
const chunks = [];
|
|
82
|
+
for await (const chunk of stream) {
|
|
83
|
+
chunks.push(chunk);
|
|
84
|
+
}
|
|
85
|
+
const buffer = Buffer.concat(chunks);
|
|
86
|
+
log.info(`fetch_resource: downloaded ${buffer.length} bytes`);
|
|
87
|
+
const contentType = res.headers?.["content-type"] || "";
|
|
88
|
+
log.info(`fetch_resource: content-type=${contentType}`);
|
|
89
|
+
const mimeType = contentType ? contentType.split(";")[0].trim() : "";
|
|
90
|
+
const mimeExt = mimeType ? MIME_TO_EXT[mimeType] : void 0;
|
|
91
|
+
const finalPath = buildRandomTempFilePath({
|
|
92
|
+
prefix: "im-resource",
|
|
93
|
+
extension: mimeExt
|
|
94
|
+
});
|
|
95
|
+
log.info(`fetch_resource: saving to ${finalPath}`);
|
|
96
|
+
await fs.mkdir(path.dirname(finalPath), { recursive: true });
|
|
97
|
+
try {
|
|
98
|
+
await fs.writeFile(finalPath, buffer);
|
|
99
|
+
log.info(`fetch_resource: saved to ${finalPath}`);
|
|
100
|
+
return json({
|
|
101
|
+
message_id: p.message_id,
|
|
102
|
+
file_key: p.file_key,
|
|
103
|
+
type: p.type,
|
|
104
|
+
size_bytes: buffer.length,
|
|
105
|
+
content_type: contentType,
|
|
106
|
+
saved_path: finalPath
|
|
107
|
+
});
|
|
108
|
+
} catch (err) {
|
|
109
|
+
log.error(`fetch_resource: failed to save file: ${err}`);
|
|
110
|
+
return json({
|
|
111
|
+
error: `\u4FDD\u5B58\u6587\u4EF6\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
} catch (err) {
|
|
115
|
+
return await handleInvokeErrorWithAutoAuth(err, cfg);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
{ name: "feishu_im_user_fetch_resource" }
|
|
120
|
+
);
|
|
121
|
+
api.logger.info?.("feishu_im_user_fetch_resource: Registered feishu_im_user_fetch_resource tool");
|
|
122
|
+
}
|
|
123
|
+
export {
|
|
124
|
+
registerFeishuImUserFetchResourceTool
|
|
125
|
+
};
|
|
126
|
+
//# sourceMappingURL=resource.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/oapi/im/resource.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * feishu_im_user_fetch_resource tool -- \u4EE5\u7528\u6237\u8EAB\u4EFD\u4E0B\u8F7D IM \u6D88\u606F\u4E2D\u7684\u6587\u4EF6/\u56FE\u7247\u8D44\u6E90\n *\n * \u4F7F\u7528\u98DE\u4E66 API:\n * - im.v1.messageResource.get: GET /open-apis/im/v1/messages/:message_id/resources/:file_key\n *\n * \u5168\u90E8\u4EE5\u7528\u6237\u8EAB\u4EFD\uFF08user_access_token\uFF09\u8C03\u7528\uFF0Cscope \u6765\u81EA real-scope.json\u3002\n */\n\nimport type { OpenClawPluginApi } from 'openclaw/plugin-sdk';\nimport { buildRandomTempFilePath } from 'openclaw/plugin-sdk';\nimport { Type } from '@sinclair/typebox';\nimport { json, createToolContext, handleInvokeErrorWithAutoAuth } from '../helpers';\nimport * as fs from 'node:fs/promises';\nimport * as path from 'node:path';\n\n// ---------------------------------------------------------------------------\n// Helper: MIME type to extension mapping\n// ---------------------------------------------------------------------------\n\nconst MIME_TO_EXT: Record<string, string> = {\n // Images\n 'image/png': '.png',\n 'image/jpeg': '.jpg',\n 'image/jpg': '.jpg',\n 'image/gif': '.gif',\n 'image/webp': '.webp',\n 'image/svg+xml': '.svg',\n 'image/bmp': '.bmp',\n 'image/tiff': '.tiff',\n // Videos\n 'video/mp4': '.mp4',\n 'video/mpeg': '.mpeg',\n 'video/quicktime': '.mov',\n 'video/x-msvideo': '.avi',\n 'video/webm': '.webm',\n // Audio\n 'audio/mpeg': '.mp3',\n 'audio/wav': '.wav',\n 'audio/ogg': '.ogg',\n 'audio/mp4': '.m4a',\n // Documents\n 'application/pdf': '.pdf',\n 'application/msword': '.doc',\n 'application/vnd.openxmlformats-officedocument.wordprocessingml.document': '.docx',\n 'application/vnd.ms-excel': '.xls',\n 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet': '.xlsx',\n 'application/vnd.ms-powerpoint': '.ppt',\n 'application/vnd.openxmlformats-officedocument.presentationml.presentation': '.pptx',\n // Others\n 'application/zip': '.zip',\n 'application/x-rar-compressed': '.rar',\n 'text/plain': '.txt',\n 'application/json': '.json',\n};\n\n// ---------------------------------------------------------------------------\n// Schema\n// ---------------------------------------------------------------------------\n\nconst FetchResourceSchema = Type.Object({\n message_id: Type.String({\n description: '\u6D88\u606F ID\uFF08om_xxx \u683C\u5F0F\uFF09\uFF0C\u4ECE\u6D88\u606F\u4E8B\u4EF6\u6216\u6D88\u606F\u5217\u8868\u4E2D\u83B7\u53D6',\n }),\n file_key: Type.String({\n description: '\u8D44\u6E90 Key\uFF0C\u4ECE\u6D88\u606F\u4F53\u4E2D\u83B7\u53D6\u3002\u56FE\u7247\u6D88\u606F\u7684 image_key\uFF08img_xxx\uFF09\u6216\u6587\u4EF6\u6D88\u606F\u7684 file_key\uFF08file_xxx\uFF09',\n }),\n type: Type.Union([Type.Literal('image'), Type.Literal('file')], {\n description: '\u8D44\u6E90\u7C7B\u578B\uFF1Aimage\uFF08\u56FE\u7247\u6D88\u606F\u4E2D\u7684\u56FE\u7247\uFF09\u3001file\uFF08\u6587\u4EF6/\u97F3\u9891/\u89C6\u9891\u6D88\u606F\u4E2D\u7684\u6587\u4EF6\uFF09',\n }),\n});\n\n// ---------------------------------------------------------------------------\n// Params type\n// ---------------------------------------------------------------------------\n\ninterface FetchResourceParams {\n message_id: string;\n file_key: string;\n type: 'image' | 'file';\n}\n\n// ---------------------------------------------------------------------------\n// Registration\n// ---------------------------------------------------------------------------\n\nexport function registerFeishuImUserFetchResourceTool(api: OpenClawPluginApi) {\n if (!api.config) return;\n const cfg = api.config;\n\n const { toolClient, log } = createToolContext(api, 'feishu_im_user_fetch_resource');\n\n api.registerTool(\n {\n name: 'feishu_im_user_fetch_resource',\n label: 'Feishu: IM Fetch Resource',\n description:\n '\u3010\u4EE5\u7528\u6237\u8EAB\u4EFD\u3011\u4E0B\u8F7D\u98DE\u4E66 IM \u6D88\u606F\u4E2D\u7684\u6587\u4EF6\u6216\u56FE\u7247\u8D44\u6E90\u5230\u672C\u5730\u6587\u4EF6\u3002\u9700\u8981\u7528\u6237 OAuth \u6388\u6743\u3002' +\n '\\n\\n\u9002\u7528\u573A\u666F\uFF1A\u5F53\u4F60\u4EE5\u7528\u6237\u8EAB\u4EFD\u8C03\u7528\u4E86\u6D88\u606F\u5217\u8868/\u641C\u7D22\u7B49 API \u83B7\u53D6\u5230 message_id \u548C file_key \u65F6\uFF0C' +\n '\u5E94\u4F7F\u7528\u672C\u5DE5\u5177\u4EE5\u540C\u6837\u7684\u7528\u6237\u8EAB\u4EFD\u4E0B\u8F7D\u8D44\u6E90\u3002' +\n '\\n\u6CE8\u610F\uFF1A\u5982\u679C message_id \u6765\u81EA\u5F53\u524D\u5BF9\u8BDD\u4E0A\u4E0B\u6587\uFF08\u7528\u6237\u53D1\u7ED9\u673A\u5668\u4EBA\u7684\u6D88\u606F\u3001\u5F15\u7528\u7684\u6D88\u606F\uFF09\uFF0C' +\n '\u8BF7\u4F7F\u7528 feishu_im_bot_image \u5DE5\u5177\u4EE5\u673A\u5668\u4EBA\u8EAB\u4EFD\u4E0B\u8F7D\uFF0C\u65E0\u9700\u7528\u6237\u6388\u6743\u3002' +\n '\\n\\n\u53C2\u6570\u8BF4\u660E\uFF1A' +\n '\\n- message_id\uFF1A\u6D88\u606F ID\uFF08om_xxx\uFF09\uFF0C\u4ECE\u6D88\u606F\u4E8B\u4EF6\u6216\u6D88\u606F\u5217\u8868\u4E2D\u83B7\u53D6' +\n '\\n- file_key\uFF1A\u8D44\u6E90 Key\uFF0C\u4ECE\u6D88\u606F\u4F53\u4E2D\u83B7\u53D6\u3002\u56FE\u7247\u7528 image_key\uFF08img_xxx\uFF09\uFF0C\u6587\u4EF6\u7528 file_key\uFF08file_xxx\uFF09' +\n '\\n- type\uFF1A\u56FE\u7247\u7528 image\uFF0C\u6587\u4EF6/\u97F3\u9891/\u89C6\u9891\u7528 file' +\n '\\n\\n\u6587\u4EF6\u81EA\u52A8\u4FDD\u5B58\u5230 /tmp/openclaw/ \u4E0B\uFF0C\u8FD4\u56DE\u503C\u4E2D\u7684 saved_path \u4E3A\u5B9E\u9645\u4FDD\u5B58\u8DEF\u5F84\u3002' +\n '\\n\u9650\u5236\uFF1A\u6587\u4EF6\u5927\u5C0F\u4E0D\u8D85\u8FC7 100MB\u3002\u4E0D\u652F\u6301\u4E0B\u8F7D\u8868\u60C5\u5305\u3001\u5408\u5E76\u8F6C\u53D1\u6D88\u606F\u3001\u5361\u7247\u4E2D\u7684\u8D44\u6E90\u3002',\n parameters: FetchResourceSchema,\n async execute(_toolCallId: string, params: unknown) {\n const p = params as FetchResourceParams;\n try {\n const client = toolClient();\n\n log.info(`fetch_resource: message_id=\"${p.message_id}\", file_key=\"${p.file_key}\", type=\"${p.type}\"`);\n\n // eslint-disable-next-line @typescript-eslint/no-explicit-any\n const res: any = await client.invoke(\n 'feishu_im_user_fetch_resource.default',\n (sdk, opts) =>\n sdk.im.v1.messageResource.get(\n {\n params: { type: p.type },\n path: { message_id: p.message_id, file_key: p.file_key },\n },\n opts,\n ),\n {\n as: 'user',\n },\n );\n\n // \u54CD\u5E94\u662F\u4E8C\u8FDB\u5236\u6D41\uFF0C\u4F7F\u7528 getReadableStream() \u8BFB\u53D6\n const stream = res.getReadableStream();\n const chunks: Buffer[] = [];\n\n for await (const chunk of stream) {\n chunks.push(chunk);\n }\n\n const buffer = Buffer.concat(chunks);\n\n log.info(`fetch_resource: downloaded ${buffer.length} bytes`);\n\n // \u4ECE\u54CD\u5E94\u5934\u83B7\u53D6 Content-Type\uFF0C\u5E76\u786E\u5B9A\u6587\u4EF6\u6269\u5C55\u540D\n const contentType = res.headers?.['content-type'] || '';\n log.info(`fetch_resource: content-type=${contentType}`);\n\n // \u4ECE Content-Type \u63A8\u65AD\u6269\u5C55\u540D\uFF0C\u81EA\u52A8\u751F\u6210\u4FDD\u5B58\u8DEF\u5F84\n const mimeType = contentType ? contentType.split(';')[0].trim() : '';\n const mimeExt = mimeType ? MIME_TO_EXT[mimeType] : undefined;\n\n const finalPath = buildRandomTempFilePath({\n prefix: 'im-resource',\n extension: mimeExt,\n });\n log.info(`fetch_resource: saving to ${finalPath}`);\n\n // \u786E\u4FDD\u7236\u76EE\u5F55\u5B58\u5728\n await fs.mkdir(path.dirname(finalPath), { recursive: true });\n\n // \u4FDD\u5B58\u6587\u4EF6\n try {\n await fs.writeFile(finalPath, buffer);\n log.info(`fetch_resource: saved to ${finalPath}`);\n\n return json({\n message_id: p.message_id,\n file_key: p.file_key,\n type: p.type,\n size_bytes: buffer.length,\n content_type: contentType,\n saved_path: finalPath,\n });\n } catch (err) {\n log.error(`fetch_resource: failed to save file: ${err}`);\n return json({\n error: `\u4FDD\u5B58\u6587\u4EF6\u5931\u8D25: ${err instanceof Error ? err.message : String(err)}`,\n });\n }\n } catch (err) {\n return await handleInvokeErrorWithAutoAuth(err, cfg);\n }\n },\n },\n { name: 'feishu_im_user_fetch_resource' },\n );\n\n api.logger.info?.('feishu_im_user_fetch_resource: Registered feishu_im_user_fetch_resource tool');\n}\n"],
|
|
5
|
+
"mappings": "AAaA,SAAS,+BAA+B;AACxC,SAAS,YAAY;AACrB,SAAS,MAAM,mBAAmB,qCAAqC;AACvE,YAAY,QAAQ;AACpB,YAAY,UAAU;AAMtB,MAAM,cAAsC;AAAA;AAAA,EAE1C,aAAa;AAAA,EACb,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAa;AAAA,EACb,cAAc;AAAA,EACd,iBAAiB;AAAA,EACjB,aAAa;AAAA,EACb,cAAc;AAAA;AAAA,EAEd,aAAa;AAAA,EACb,cAAc;AAAA,EACd,mBAAmB;AAAA,EACnB,mBAAmB;AAAA,EACnB,cAAc;AAAA;AAAA,EAEd,cAAc;AAAA,EACd,aAAa;AAAA,EACb,aAAa;AAAA,EACb,aAAa;AAAA;AAAA,EAEb,mBAAmB;AAAA,EACnB,sBAAsB;AAAA,EACtB,2EAA2E;AAAA,EAC3E,4BAA4B;AAAA,EAC5B,qEAAqE;AAAA,EACrE,iCAAiC;AAAA,EACjC,6EAA6E;AAAA;AAAA,EAE7E,mBAAmB;AAAA,EACnB,gCAAgC;AAAA,EAChC,cAAc;AAAA,EACd,oBAAoB;AACtB;AAMA,MAAM,sBAAsB,KAAK,OAAO;AAAA,EACtC,YAAY,KAAK,OAAO;AAAA,IACtB,aAAa;AAAA,EACf,CAAC;AAAA,EACD,UAAU,KAAK,OAAO;AAAA,IACpB,aAAa;AAAA,EACf,CAAC;AAAA,EACD,MAAM,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,GAAG,KAAK,QAAQ,MAAM,CAAC,GAAG;AAAA,IAC9D,aAAa;AAAA,EACf,CAAC;AACH,CAAC;AAgBM,SAAS,sCAAsC,KAAwB;AAC5E,MAAI,CAAC,IAAI,OAAQ;AACjB,QAAM,MAAM,IAAI;AAEhB,QAAM,EAAE,YAAY,IAAI,IAAI,kBAAkB,KAAK,+BAA+B;AAElF,MAAI;AAAA,IACF;AAAA,MACE,MAAM;AAAA,MACN,OAAO;AAAA,MACP,aACE;AAAA,MAWF,YAAY;AAAA,MACZ,MAAM,QAAQ,aAAqB,QAAiB;AAClD,cAAM,IAAI;AACV,YAAI;AACF,gBAAM,SAAS,WAAW;AAE1B,cAAI,KAAK,+BAA+B,EAAE,UAAU,gBAAgB,EAAE,QAAQ,YAAY,EAAE,IAAI,GAAG;AAGnG,gBAAM,MAAW,MAAM,OAAO;AAAA,YAC5B;AAAA,YACA,CAAC,KAAK,SACJ,IAAI,GAAG,GAAG,gBAAgB;AAAA,cACxB;AAAA,gBACE,QAAQ,EAAE,MAAM,EAAE,KAAK;AAAA,gBACvB,MAAM,EAAE,YAAY,EAAE,YAAY,UAAU,EAAE,SAAS;AAAA,cACzD;AAAA,cACA;AAAA,YACF;AAAA,YACF;AAAA,cACE,IAAI;AAAA,YACN;AAAA,UACF;AAGA,gBAAM,SAAS,IAAI,kBAAkB;AACrC,gBAAM,SAAmB,CAAC;AAE1B,2BAAiB,SAAS,QAAQ;AAChC,mBAAO,KAAK,KAAK;AAAA,UACnB;AAEA,gBAAM,SAAS,OAAO,OAAO,MAAM;AAEnC,cAAI,KAAK,8BAA8B,OAAO,MAAM,QAAQ;AAG5D,gBAAM,cAAc,IAAI,UAAU,cAAc,KAAK;AACrD,cAAI,KAAK,gCAAgC,WAAW,EAAE;AAGtD,gBAAM,WAAW,cAAc,YAAY,MAAM,GAAG,EAAE,CAAC,EAAE,KAAK,IAAI;AAClE,gBAAM,UAAU,WAAW,YAAY,QAAQ,IAAI;AAEnD,gBAAM,YAAY,wBAAwB;AAAA,YACxC,QAAQ;AAAA,YACR,WAAW;AAAA,UACb,CAAC;AACD,cAAI,KAAK,6BAA6B,SAAS,EAAE;AAGjD,gBAAM,GAAG,MAAM,KAAK,QAAQ,SAAS,GAAG,EAAE,WAAW,KAAK,CAAC;AAG3D,cAAI;AACF,kBAAM,GAAG,UAAU,WAAW,MAAM;AACpC,gBAAI,KAAK,4BAA4B,SAAS,EAAE;AAEhD,mBAAO,KAAK;AAAA,cACV,YAAY,EAAE;AAAA,cACd,UAAU,EAAE;AAAA,cACZ,MAAM,EAAE;AAAA,cACR,YAAY,OAAO;AAAA,cACnB,cAAc;AAAA,cACd,YAAY;AAAA,YACd,CAAC;AAAA,UACH,SAAS,KAAK;AACZ,gBAAI,MAAM,wCAAwC,GAAG,EAAE;AACvD,mBAAO,KAAK;AAAA,cACV,OAAO,yCAAW,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG,CAAC;AAAA,YACpE,CAAC;AAAA,UACH;AAAA,QACF,SAAS,KAAK;AACZ,iBAAO,MAAM,8BAA8B,KAAK,GAAG;AAAA,QACrD;AAAA,MACF;AAAA,IACF;AAAA,IACA,EAAE,MAAM,gCAAgC;AAAA,EAC1C;AAEA,MAAI,OAAO,OAAO,8EAA8E;AAClG;",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
const BJ_OFFSET_MS = 8 * 60 * 60 * 1e3;
|
|
2
|
+
function formatBeijingISO(d) {
|
|
3
|
+
const bj = new Date(d.getTime() + BJ_OFFSET_MS);
|
|
4
|
+
const y = bj.getUTCFullYear();
|
|
5
|
+
const mo = String(bj.getUTCMonth() + 1).padStart(2, "0");
|
|
6
|
+
const da = String(bj.getUTCDate()).padStart(2, "0");
|
|
7
|
+
const h = String(bj.getUTCHours()).padStart(2, "0");
|
|
8
|
+
const mi = String(bj.getUTCMinutes()).padStart(2, "0");
|
|
9
|
+
const s = String(bj.getUTCSeconds()).padStart(2, "0");
|
|
10
|
+
return `${y}-${mo}-${da}T${h}:${mi}:${s}+08:00`;
|
|
11
|
+
}
|
|
12
|
+
function secondsToDateTime(seconds) {
|
|
13
|
+
return formatBeijingISO(new Date(seconds * 1e3));
|
|
14
|
+
}
|
|
15
|
+
function secondsStringToDateTime(seconds) {
|
|
16
|
+
return secondsToDateTime(parseInt(seconds, 10));
|
|
17
|
+
}
|
|
18
|
+
function millisToDateTime(millis) {
|
|
19
|
+
return formatBeijingISO(new Date(millis));
|
|
20
|
+
}
|
|
21
|
+
function millisStringToDateTime(millis) {
|
|
22
|
+
return millisToDateTime(parseInt(millis, 10));
|
|
23
|
+
}
|
|
24
|
+
function dateTimeToSeconds(datetime) {
|
|
25
|
+
const d = new Date(datetime);
|
|
26
|
+
if (isNaN(d.getTime())) {
|
|
27
|
+
throw new Error(`\u65E0\u6CD5\u89E3\u6790 ISO 8601 \u65F6\u95F4: "${datetime}"\u3002\u683C\u5F0F\u793A\u4F8B: 2026-02-27T14:30:00+08:00`);
|
|
28
|
+
}
|
|
29
|
+
return Math.floor(d.getTime() / 1e3);
|
|
30
|
+
}
|
|
31
|
+
function dateTimeToSecondsString(datetime) {
|
|
32
|
+
return dateTimeToSeconds(datetime).toString();
|
|
33
|
+
}
|
|
34
|
+
function dateTimeToMillis(datetime) {
|
|
35
|
+
const d = new Date(datetime);
|
|
36
|
+
if (isNaN(d.getTime())) {
|
|
37
|
+
throw new Error(`\u65E0\u6CD5\u89E3\u6790 ISO 8601 \u65F6\u95F4: "${datetime}"\u3002\u683C\u5F0F\u793A\u4F8B: 2026-02-27T14:30:00+08:00`);
|
|
38
|
+
}
|
|
39
|
+
return d.getTime();
|
|
40
|
+
}
|
|
41
|
+
function parseTimeRange(input) {
|
|
42
|
+
const now = /* @__PURE__ */ new Date();
|
|
43
|
+
const bjNow = toBeijingDate(now);
|
|
44
|
+
let start;
|
|
45
|
+
let end;
|
|
46
|
+
switch (input) {
|
|
47
|
+
case "today":
|
|
48
|
+
start = beijingStartOfDay(bjNow);
|
|
49
|
+
end = now;
|
|
50
|
+
break;
|
|
51
|
+
case "yesterday": {
|
|
52
|
+
const d = new Date(bjNow);
|
|
53
|
+
d.setUTCDate(d.getUTCDate() - 1);
|
|
54
|
+
start = beijingStartOfDay(d);
|
|
55
|
+
end = beijingEndOfDay(d);
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
case "day_before_yesterday": {
|
|
59
|
+
const d = new Date(bjNow);
|
|
60
|
+
d.setUTCDate(d.getUTCDate() - 2);
|
|
61
|
+
start = beijingStartOfDay(d);
|
|
62
|
+
end = beijingEndOfDay(d);
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
case "this_week": {
|
|
66
|
+
const day = bjNow.getUTCDay();
|
|
67
|
+
const diffToMon = day === 0 ? 6 : day - 1;
|
|
68
|
+
const monday = new Date(bjNow);
|
|
69
|
+
monday.setUTCDate(monday.getUTCDate() - diffToMon);
|
|
70
|
+
start = beijingStartOfDay(monday);
|
|
71
|
+
end = now;
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
case "last_week": {
|
|
75
|
+
const day = bjNow.getUTCDay();
|
|
76
|
+
const diffToMon = day === 0 ? 6 : day - 1;
|
|
77
|
+
const thisMonday = new Date(bjNow);
|
|
78
|
+
thisMonday.setUTCDate(thisMonday.getUTCDate() - diffToMon);
|
|
79
|
+
const lastMonday = new Date(thisMonday);
|
|
80
|
+
lastMonday.setUTCDate(lastMonday.getUTCDate() - 7);
|
|
81
|
+
const lastSunday = new Date(thisMonday);
|
|
82
|
+
lastSunday.setUTCDate(lastSunday.getUTCDate() - 1);
|
|
83
|
+
start = beijingStartOfDay(lastMonday);
|
|
84
|
+
end = beijingEndOfDay(lastSunday);
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
case "this_month": {
|
|
88
|
+
const firstDay = new Date(Date.UTC(bjNow.getUTCFullYear(), bjNow.getUTCMonth(), 1));
|
|
89
|
+
start = beijingStartOfDay(firstDay);
|
|
90
|
+
end = now;
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
case "last_month": {
|
|
94
|
+
const firstDayThisMonth = new Date(Date.UTC(bjNow.getUTCFullYear(), bjNow.getUTCMonth(), 1));
|
|
95
|
+
const lastDayPrevMonth = new Date(firstDayThisMonth);
|
|
96
|
+
lastDayPrevMonth.setUTCDate(lastDayPrevMonth.getUTCDate() - 1);
|
|
97
|
+
const firstDayPrevMonth = new Date(
|
|
98
|
+
Date.UTC(lastDayPrevMonth.getUTCFullYear(), lastDayPrevMonth.getUTCMonth(), 1)
|
|
99
|
+
);
|
|
100
|
+
start = beijingStartOfDay(firstDayPrevMonth);
|
|
101
|
+
end = beijingEndOfDay(lastDayPrevMonth);
|
|
102
|
+
break;
|
|
103
|
+
}
|
|
104
|
+
default: {
|
|
105
|
+
const match = input.match(/^last_(\d+)_(minutes?|hours?|days?)$/);
|
|
106
|
+
if (!match) {
|
|
107
|
+
throw new Error(
|
|
108
|
+
`\u4E0D\u652F\u6301\u7684 relative_time \u683C\u5F0F: "${input}"\u3002\u652F\u6301: today, yesterday, day_before_yesterday, this_week, last_week, this_month, last_month, last_{N}_{unit}\uFF08unit: minutes/hours/days\uFF09`
|
|
109
|
+
);
|
|
110
|
+
}
|
|
111
|
+
const n = parseInt(match[1], 10);
|
|
112
|
+
const unit = match[2].replace(/s$/, "");
|
|
113
|
+
start = subtractFromNow(now, n, unit);
|
|
114
|
+
end = now;
|
|
115
|
+
break;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
start: formatBeijingISO(start),
|
|
120
|
+
end: formatBeijingISO(end)
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function parseTimeRangeToSeconds(input) {
|
|
124
|
+
const range = parseTimeRange(input);
|
|
125
|
+
return {
|
|
126
|
+
start: dateTimeToSecondsString(range.start),
|
|
127
|
+
end: dateTimeToSecondsString(range.end)
|
|
128
|
+
};
|
|
129
|
+
}
|
|
130
|
+
function toBeijingDate(d) {
|
|
131
|
+
return new Date(d.getTime() + BJ_OFFSET_MS);
|
|
132
|
+
}
|
|
133
|
+
function beijingStartOfDay(bjDate) {
|
|
134
|
+
return new Date(Date.UTC(bjDate.getUTCFullYear(), bjDate.getUTCMonth(), bjDate.getUTCDate()) - BJ_OFFSET_MS);
|
|
135
|
+
}
|
|
136
|
+
function beijingEndOfDay(bjDate) {
|
|
137
|
+
return new Date(
|
|
138
|
+
Date.UTC(bjDate.getUTCFullYear(), bjDate.getUTCMonth(), bjDate.getUTCDate(), 23, 59, 59) - BJ_OFFSET_MS
|
|
139
|
+
);
|
|
140
|
+
}
|
|
141
|
+
function subtractFromNow(now, n, unit) {
|
|
142
|
+
const d = new Date(now);
|
|
143
|
+
switch (unit) {
|
|
144
|
+
case "minute":
|
|
145
|
+
d.setMinutes(d.getMinutes() - n);
|
|
146
|
+
break;
|
|
147
|
+
case "hour":
|
|
148
|
+
d.setHours(d.getHours() - n);
|
|
149
|
+
break;
|
|
150
|
+
case "day":
|
|
151
|
+
d.setDate(d.getDate() - n);
|
|
152
|
+
break;
|
|
153
|
+
default:
|
|
154
|
+
throw new Error(`\u4E0D\u652F\u6301\u7684\u65F6\u95F4\u5355\u4F4D: ${unit}`);
|
|
155
|
+
}
|
|
156
|
+
return d;
|
|
157
|
+
}
|
|
158
|
+
export {
|
|
159
|
+
dateTimeToMillis,
|
|
160
|
+
dateTimeToSeconds,
|
|
161
|
+
dateTimeToSecondsString,
|
|
162
|
+
millisStringToDateTime,
|
|
163
|
+
millisToDateTime,
|
|
164
|
+
parseTimeRange,
|
|
165
|
+
parseTimeRangeToSeconds,
|
|
166
|
+
secondsStringToDateTime,
|
|
167
|
+
secondsToDateTime
|
|
168
|
+
};
|
|
169
|
+
//# sourceMappingURL=time-utils.js.map
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../../../../../src/tools/oapi/im/time-utils.ts"],
|
|
4
|
+
"sourcesContent": ["/**\n * Copyright (c) 2026 ByteDance Ltd. and/or its affiliates\n * SPDX-License-Identifier: MIT\n *\n * \u65F6\u95F4\u5DE5\u5177\u51FD\u6570 \u2014 \u5BF9\u9F50 Go \u5B9E\u73B0 (time.go + timerange.go)\n *\n * \u4EE5 ISO 8601 (RFC 3339) \u4F5C\u4E3A\u6807\u51C6\u65F6\u95F4\u4EA4\u6362\u683C\u5F0F\uFF0C\n * \u63D0\u4F9B ISO 8601 \u2194 Unix \u8F6C\u6362\u5DE5\u5177\u53CA\u65F6\u95F4\u8303\u56F4\u89E3\u6790\u3002\n */\n\nconst BJ_OFFSET_MS = 8 * 60 * 60 * 1000;\n\n// ===========================================================================\n// ISO 8601 \u2194 Unix \u8F6C\u6362\u5DE5\u5177\uFF08\u5BF9\u9F50 time.go\uFF09\n// ===========================================================================\n\n/** \u5C06 Date \u683C\u5F0F\u5316\u4E3A\u5317\u4EAC\u65F6\u95F4 ISO 8601 \u5B57\u7B26\u4E32 */\nfunction formatBeijingISO(d: Date): string {\n const bj = new Date(d.getTime() + BJ_OFFSET_MS);\n const y = bj.getUTCFullYear();\n const mo = String(bj.getUTCMonth() + 1).padStart(2, '0');\n const da = String(bj.getUTCDate()).padStart(2, '0');\n const h = String(bj.getUTCHours()).padStart(2, '0');\n const mi = String(bj.getUTCMinutes()).padStart(2, '0');\n const s = String(bj.getUTCSeconds()).padStart(2, '0');\n return `${y}-${mo}-${da}T${h}:${mi}:${s}+08:00`;\n}\n\n// ---------------------------------------------------------------------------\n// Unix \u79D2 \u2192 ISO 8601\n// ---------------------------------------------------------------------------\n\n/** Unix \u79D2\uFF08\u6570\u5B57\uFF09\u2192 ISO 8601 \u5317\u4EAC\u65F6\u95F4 */\nexport function secondsToDateTime(seconds: number): string {\n return formatBeijingISO(new Date(seconds * 1000));\n}\n\n/** Unix \u79D2\uFF08\u5B57\u7B26\u4E32\uFF09\u2192 ISO 8601 \u5317\u4EAC\u65F6\u95F4 */\nexport function secondsStringToDateTime(seconds: string): string {\n return secondsToDateTime(parseInt(seconds, 10));\n}\n\n// ---------------------------------------------------------------------------\n// Unix \u6BEB\u79D2 \u2192 ISO 8601\n// ---------------------------------------------------------------------------\n\n/** Unix \u6BEB\u79D2\uFF08\u6570\u5B57\uFF09\u2192 ISO 8601 \u5317\u4EAC\u65F6\u95F4 */\nexport function millisToDateTime(millis: number): string {\n return formatBeijingISO(new Date(millis));\n}\n\n/** Unix \u6BEB\u79D2\uFF08\u5B57\u7B26\u4E32\uFF09\u2192 ISO 8601 \u5317\u4EAC\u65F6\u95F4 */\nexport function millisStringToDateTime(millis: string): string {\n return millisToDateTime(parseInt(millis, 10));\n}\n\n// ---------------------------------------------------------------------------\n// ISO 8601 \u2192 Unix\n// ---------------------------------------------------------------------------\n\n/** ISO 8601 \u2192 Unix \u79D2\uFF08\u6570\u5B57\uFF09 */\nexport function dateTimeToSeconds(datetime: string): number {\n const d = new Date(datetime);\n if (isNaN(d.getTime())) {\n throw new Error(`\u65E0\u6CD5\u89E3\u6790 ISO 8601 \u65F6\u95F4: \"${datetime}\"\u3002\u683C\u5F0F\u793A\u4F8B: 2026-02-27T14:30:00+08:00`);\n }\n return Math.floor(d.getTime() / 1000);\n}\n\n/** ISO 8601 \u2192 Unix \u79D2\uFF08\u5B57\u7B26\u4E32\uFF09 */\nexport function dateTimeToSecondsString(datetime: string): string {\n return dateTimeToSeconds(datetime).toString();\n}\n\n/** ISO 8601 \u2192 Unix \u6BEB\u79D2\uFF08\u6570\u5B57\uFF09 */\nexport function dateTimeToMillis(datetime: string): number {\n const d = new Date(datetime);\n if (isNaN(d.getTime())) {\n throw new Error(`\u65E0\u6CD5\u89E3\u6790 ISO 8601 \u65F6\u95F4: \"${datetime}\"\u3002\u683C\u5F0F\u793A\u4F8B: 2026-02-27T14:30:00+08:00`);\n }\n return d.getTime();\n}\n\n// ===========================================================================\n// \u65F6\u95F4\u8303\u56F4\u89E3\u6790\uFF08\u5BF9\u9F50 timerange.go\uFF09\n// ===========================================================================\n\n/** ISO 8601 \u65F6\u95F4\u8303\u56F4 */\nexport interface TimeRange {\n start: string;\n end: string;\n}\n\n/**\n * \u89E3\u6790\u65F6\u95F4\u8303\u56F4\u6807\u8BC6\uFF0C\u8FD4\u56DE ISO 8601 \u5B57\u7B26\u4E32\u5BF9\u3002\n *\n * \u652F\u6301\u7684\u683C\u5F0F\uFF1A\n * - `today` / `yesterday` / `day_before_yesterday`\n * - `this_week` / `last_week` / `this_month` / `last_month`\n * - `last_{N}_{unit}` \u2014 unit: minutes / hours / days\n *\n * \u6240\u6709\u8BA1\u7B97\u57FA\u4E8E\u5317\u4EAC\u65F6\u95F4 (UTC+8)\u3002\n */\nexport function parseTimeRange(input: string): TimeRange {\n const now = new Date();\n const bjNow = toBeijingDate(now);\n\n let start: Date;\n let end: Date;\n\n switch (input) {\n case 'today':\n start = beijingStartOfDay(bjNow);\n end = now;\n break;\n\n case 'yesterday': {\n const d = new Date(bjNow);\n d.setUTCDate(d.getUTCDate() - 1);\n start = beijingStartOfDay(d);\n end = beijingEndOfDay(d);\n break;\n }\n\n case 'day_before_yesterday': {\n const d = new Date(bjNow);\n d.setUTCDate(d.getUTCDate() - 2);\n start = beijingStartOfDay(d);\n end = beijingEndOfDay(d);\n break;\n }\n\n case 'this_week': {\n const day = bjNow.getUTCDay(); // 0=Sun .. 6=Sat\n const diffToMon = day === 0 ? 6 : day - 1;\n const monday = new Date(bjNow);\n monday.setUTCDate(monday.getUTCDate() - diffToMon);\n start = beijingStartOfDay(monday);\n end = now;\n break;\n }\n\n case 'last_week': {\n const day = bjNow.getUTCDay();\n const diffToMon = day === 0 ? 6 : day - 1;\n const thisMonday = new Date(bjNow);\n thisMonday.setUTCDate(thisMonday.getUTCDate() - diffToMon);\n const lastMonday = new Date(thisMonday);\n lastMonday.setUTCDate(lastMonday.getUTCDate() - 7);\n const lastSunday = new Date(thisMonday);\n lastSunday.setUTCDate(lastSunday.getUTCDate() - 1);\n start = beijingStartOfDay(lastMonday);\n end = beijingEndOfDay(lastSunday);\n break;\n }\n\n case 'this_month': {\n const firstDay = new Date(Date.UTC(bjNow.getUTCFullYear(), bjNow.getUTCMonth(), 1));\n start = beijingStartOfDay(firstDay);\n end = now;\n break;\n }\n\n case 'last_month': {\n const firstDayThisMonth = new Date(Date.UTC(bjNow.getUTCFullYear(), bjNow.getUTCMonth(), 1));\n const lastDayPrevMonth = new Date(firstDayThisMonth);\n lastDayPrevMonth.setUTCDate(lastDayPrevMonth.getUTCDate() - 1);\n const firstDayPrevMonth = new Date(\n Date.UTC(lastDayPrevMonth.getUTCFullYear(), lastDayPrevMonth.getUTCMonth(), 1),\n );\n start = beijingStartOfDay(firstDayPrevMonth);\n end = beijingEndOfDay(lastDayPrevMonth);\n break;\n }\n\n default: {\n // last_{N}_{unit} \u2014 \u53EA\u652F\u6301 minutes / hours / days\uFF08\u5BF9\u9F50 Go\uFF09\n const match = input.match(/^last_(\\d+)_(minutes?|hours?|days?)$/);\n if (!match) {\n throw new Error(\n `\u4E0D\u652F\u6301\u7684 relative_time \u683C\u5F0F: \"${input}\"\u3002` +\n '\u652F\u6301: today, yesterday, day_before_yesterday, this_week, last_week, this_month, last_month, last_{N}_{unit}\uFF08unit: minutes/hours/days\uFF09',\n );\n }\n const n = parseInt(match[1], 10);\n const unit = match[2].replace(/s$/, ''); // normalize plural\n start = subtractFromNow(now, n, unit);\n end = now;\n break;\n }\n }\n\n return {\n start: formatBeijingISO(start),\n end: formatBeijingISO(end),\n };\n}\n\n/**\n * \u89E3\u6790\u65F6\u95F4\u8303\u56F4\u6807\u8BC6\uFF0C\u8FD4\u56DE Unix \u79D2\u5B57\u7B26\u4E32\u5BF9\uFF08\u4F9B SDK \u8C03\u7528\uFF09\u3002\n */\nexport function parseTimeRangeToSeconds(input: string): { start: string; end: string } {\n const range = parseTimeRange(input);\n return {\n start: dateTimeToSecondsString(range.start),\n end: dateTimeToSecondsString(range.end),\n };\n}\n\n// ===========================================================================\n// Internal helpers\n// ===========================================================================\n\n/** \u5C06 UTC Date \u8F6C\u4E3A\u300C\u5317\u4EAC\u65F6\u95F4\u5404\u90E8\u5206\u5B58\u5728 UTC \u5B57\u6BB5\u4E0A\u300D\u7684 Date */\nfunction toBeijingDate(d: Date): Date {\n return new Date(d.getTime() + BJ_OFFSET_MS);\n}\n\n/** \u5317\u4EAC\u65F6\u95F4\u5F53\u5929 00:00:00 \u5BF9\u5E94\u7684\u771F\u5B9E UTC Date */\nfunction beijingStartOfDay(bjDate: Date): Date {\n return new Date(Date.UTC(bjDate.getUTCFullYear(), bjDate.getUTCMonth(), bjDate.getUTCDate()) - BJ_OFFSET_MS);\n}\n\n/** \u5317\u4EAC\u65F6\u95F4\u5F53\u5929 23:59:59 \u5BF9\u5E94\u7684\u771F\u5B9E UTC Date */\nfunction beijingEndOfDay(bjDate: Date): Date {\n return new Date(\n Date.UTC(bjDate.getUTCFullYear(), bjDate.getUTCMonth(), bjDate.getUTCDate(), 23, 59, 59) - BJ_OFFSET_MS,\n );\n}\n\nfunction subtractFromNow(now: Date, n: number, unit: string): Date {\n const d = new Date(now);\n switch (unit) {\n case 'minute':\n d.setMinutes(d.getMinutes() - n);\n break;\n case 'hour':\n d.setHours(d.getHours() - n);\n break;\n case 'day':\n d.setDate(d.getDate() - n);\n break;\n default:\n throw new Error(`\u4E0D\u652F\u6301\u7684\u65F6\u95F4\u5355\u4F4D: ${unit}`);\n }\n return d;\n}\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": []
|
|
7
|
+
}
|