Documentation
¶
Index ¶
- Constants
- Variables
- func RegisterFriendApplyHook(ctx *config.Context)
- func ValidateUserAPIKeySecret() error
- type BindBotReq
- type BindBotResp
- type BotEventAckReq
- type BotEventsReq
- type BotFather
- type BotFriendApply
- type BotHeartbeatReq
- type BotInfo
- type BotReadReceiptReq
- type BotRegisterReq
- type BotRegisterResp
- type BotSendMessageReq
- type BotSyncMessagesReq
- type BotTypingReq
- type CreateBotReq
- type CreateBotResp
- type MintBotResult
- type RobotApplyListResp
- type RobotApplyReq
- type RobotApplyResp
- type RobotApplySureReq
- type UpdateBotReq
- type UserAPIKey
- type UserAPIKeyService
- type UserBotResp
Constants ¶
const ( AccessModeRequireApproval = 0 // 需要审批 AccessModeAutoApprove = 1 // 自动通过 AccessModeForbidden = 2 // 禁止申请 )
const ( // BotFatherUID BotFather的用户UID。真相源在 cmdmenu 叶子包(#335)—— // 读路径模块(user/channel/robot)需要匹配该 UID 却不能 import 本包 //(botfather → user 会成环),这里保留别名供包内调用点使用。 BotFatherUID = cmdmenu.BotFatherUID // BotFatherName BotFather的显示名称 BotFatherName = "BotFather" // BotTokenPrefix Bot Token前缀 BotTokenPrefix = "bf_" // UserAPIKeyPrefix User API Key前缀 UserAPIKeyPrefix = "uk_" // BotUsernameSuffix 机器人用户名后缀 BotUsernameSuffix = "_bot" )
const ( CmdNewBot = "/newbot" CmdMyBots = "/mybots" CmdConnect = "/connect" CmdDisconnect = "/disconnect" CmdSetName = "/setname" CmdSetDescription = "/setdescription" CmdDeleteBot = "/deletebot" CmdToken = "/token" CmdRevoke = "/revoke" CmdCancel = "/cancel" CmdHelp = "/help" CmdStart = "/start" CmdApprove = "/approve" CmdReject = "/reject" CmdPending = "/pending" CmdQuickstart = "/quickstart" CmdInstall = "/install" )
BotFather 命令
const ( StateNone = "" StateWaitingBotName = "waiting_bot_name" StateWaitingSelectBot = "waiting_select_bot" StateWaitingNewName = "waiting_new_name" StateWaitingDescription = "waiting_description" StateWaitingDeleteConfirm = "waiting_delete_confirm" StateWaitingRevokeConfirm = "waiting_revoke_confirm" )
对话状态
const ( FieldState = "state" FieldCommand = "command" FieldBotID = "bot_id" FieldBotName = "bot_name" )
状态上下文字段
const ( ApplyStatusPending = 0 ApplyStatusApproved = 1 ApplyStatusRejected = 2 )
const ( // welcome.go MsgWelcome = "welcome" // command.go — generic / reused MsgUnknownCommand = "unknown_command" MsgSendHelpHint = "send_help_hint" MsgOperationCancelled = "operation_cancelled" MsgOperationError = "operation_error" MsgQueryFailedRetry = "query_failed_retry" MsgQueryFailedCancelled = "query_failed_cancelled" MsgOperationFailedRetry = "operation_failed_retry" MsgNoBotsYet = "no_bots_yet" MsgNoBotsShort = "no_bots_short" MsgNameLengthInvalid = "name_length_invalid" // command.go — newbot / create MsgNewBotPrompt = "newbot_prompt" MsgCreateFailedRetry = "create_failed_retry" MsgBotCreatedNoInfo = "bot_created_no_info" MsgCreatedPrompt = "created_prompt" // command.go — mybots / selection MsgMyBotsList = "mybots_list" MsgBotSelectionList = "bot_selection_list" MsgBotNotFoundRetry = "bot_not_found_retry" // command.go — connect / disconnect MsgSelectBotConnect = "select_bot_connect" MsgSelectBotDisconnect = "select_bot_disconnect" MsgConnectPrompt = "connect_prompt" MsgDisconnectFailedRetry = "disconnect_failed_retry" MsgBotDisconnected = "bot_disconnected" // command.go — setname / setdescription MsgSelectBotSetName = "select_bot_setname" MsgSelectBotSetDesc = "select_bot_setdesc" MsgSetNamePrompt = "set_name_prompt" MsgSetDescPrompt = "set_desc_prompt" MsgUpdateFailedRetry = "update_failed_retry" MsgBotNameUpdated = "bot_name_updated" MsgDescTooLong = "desc_too_long" MsgDescUpdated = "desc_updated" // command.go — deletebot MsgSelectBotDelete = "select_bot_delete" MsgDeleteConfirm = "delete_confirm" MsgDeleteCancelled = "delete_cancelled" MsgDeleteFailedRetry = "delete_failed_retry" MsgBotDeleted = "bot_deleted" // command.go — token / revoke MsgSelectBotToken = "select_bot_token" MsgSelectBotRevoke = "select_bot_revoke" MsgTokenDisplay = "token_display" MsgRevokeConfirm = "revoke_confirm" MsgRevokeFailedRetry = "revoke_failed_retry" MsgTokenRevoked = "token_revoked" // command.go — quickstart / install / help MsgQuickstart = "quickstart" MsgInstall = "install" MsgHelp = "help" // api_apply.go — apply flow (IM notifications + HTTP success messages) MsgApplyAutoApproved = "apply_auto_approved" MsgApplySubmitted = "apply_submitted" MsgNotifyOwnerNewApply = "notify_owner_new_apply" MsgNotifyApplicantApproved = "notify_applicant_approved" MsgNotifyApplicantRejected = "notify_applicant_rejected" // api_apply.go / friend_approve.go — shared friend-added tip MsgFriendAddedTip = "friend_added_tip" // friend_approve.go — friend-apply DM replies & notifications MsgFriendBotNotFound = "friend_bot_not_found" MsgFriendNotCreator = "friend_not_creator" MsgFriendBotNotInSpace = "friend_bot_not_in_space" MsgFriendApplyNotFound = "friend_apply_not_found" MsgFriendAddFailed = "friend_add_failed" MsgFriendApproved = "friend_approved" MsgFriendRejected = "friend_rejected" MsgFriendQueryFailed = "friend_query_failed" MsgFriendPendingEmpty = "friend_pending_empty" MsgFriendNoPendingForBot = "friend_no_pending_for_bot" MsgFriendApproveUsage = "friend_approve_usage" MsgFriendRejectUsage = "friend_reject_usage" MsgFriendApplyNotify = "friend_apply_notify" MsgFriendPendingList = "friend_pending_list" MsgFriendAgoJustNow = "friend_ago_just_now" MsgFriendAgoDays = "friend_ago_days" MsgFriendAgoHours = "friend_ago_hours" MsgFriendAgoMinutes = "friend_ago_minutes" )
Message names — the {{define "..."}} keys. Kept as constants so call sites and the template tree cannot silently drift; allBotMessageKeys backs the completeness test.
Variables ¶
var ErrIntegrationClientDisabled = errors.New("botfather: integration client disabled")
ErrIntegrationClientDisabled is returned when an integration-scoped key issuance attempts to run while the external client is missing or disabled.
Functions ¶
func RegisterFriendApplyHook ¶
RegisterFriendApplyHook 注册好友申请通知回调到 user 模块
func ValidateUserAPIKeySecret ¶ added in v1.6.0
func ValidateUserAPIKeySecret() error
ValidateUserAPIKeySecret is used by integration enable/issuance paths. The BotFather legacy client deliberately does not require this secret so existing /quickstart deployments keep working until uk_ storage hardening is enabled for that client in a dedicated rollout.
Types ¶
type BindBotReq ¶ added in v1.6.0
type BindBotReq struct {
// AgentRef 占用方不透明标签(如 octopush:agent_xxx)。Octo 不解析其语义。
AgentRef string `json:"agent_ref"`
}
BindBotReq 占用(绑定)Bot 请求。
type BindBotResp ¶ added in v1.6.0
type BindBotResp struct {
RobotID string `json:"robot_id"`
BoundAgentRef string `json:"bound_agent_ref"`
BoundAt *string `json:"bound_at"`
}
BindBotResp 占用(绑定)Bot 响应。
type BotEventAckReq ¶
type BotEventAckReq struct {
EventID int64 `json:"event_id"`
}
BotEventAckReq Bot确认事件请求
type BotEventsReq ¶
BotEventsReq Bot获取事件请求
type BotFriendApply ¶
type BotFriendApply struct {
ApplyUID string `json:"apply_uid"`
ApplyName string `json:"apply_name"`
RobotID string `json:"robot_id"`
Remark string `json:"remark"`
Token string `json:"token"` // friend apply token from cache
SpaceID string `json:"space_id"` // 申请来源 Space,用于隔离通知
CreatedAt int64 `json:"created_at"`
}
BotFriendApply 机器人好友申请记录
type BotInfo ¶
type BotInfo struct {
RobotID string `json:"robot_id"`
Name string `json:"name"`
Description string `json:"description"`
BotToken string `json:"bot_token"`
CreatorUID string `json:"creator_uid"`
Status int `json:"status"`
}
BotInfo BotFather中的机器人信息
type BotReadReceiptReq ¶
type BotReadReceiptReq struct {
ChannelID string `json:"channel_id"`
ChannelType uint8 `json:"channel_type"`
MessageIDs []string `json:"message_ids"`
}
BotReadReceiptReq Bot阅读回执请求
type BotRegisterReq ¶
type BotRegisterReq struct {
AgentPlatform string `json:"agent_platform"` // AI Agent 平台名称
AgentVersion string `json:"agent_version"` // Agent 平台版本号
PluginVersion string `json:"plugin_version"` // Octo 插件版本号
}
BotRegisterReq Bot自注册请求(可选字段,兼容旧客户端空 body)
type BotRegisterResp ¶
type BotRegisterResp struct {
RobotID string `json:"robot_id"`
Name string `json:"name"`
IMToken string `json:"im_token"`
WSURL string `json:"ws_url"`
APIURL string `json:"api_url"`
OwnerUID string `json:"owner_uid"`
OwnerChannelID string `json:"owner_channel_id"`
}
BotRegisterResp Bot自注册响应
type BotSendMessageReq ¶
type BotSendMessageReq struct {
ChannelID string `json:"channel_id"`
ChannelType uint8 `json:"channel_type"`
StreamNo string `json:"stream_no"`
Payload map[string]interface{} `json:"payload"`
}
BotSendMessageReq Bot发送消息请求
type BotSyncMessagesReq ¶
type BotSyncMessagesReq struct {
ChannelID string `json:"channel_id"`
ChannelType uint8 `json:"channel_type"`
StartMessageSeq uint32 `json:"start_message_seq"`
EndMessageSeq uint32 `json:"end_message_seq"`
Limit int `json:"limit"`
PullMode int `json:"pull_mode"`
}
BotSyncMessagesReq Bot同步历史消息请求
type BotTypingReq ¶
type BotTypingReq struct {
ChannelID string `json:"channel_id"`
ChannelType uint8 `json:"channel_type"`
}
BotTypingReq Bot输入状态请求
type CreateBotReq ¶
type CreateBotReq struct {
Name string `json:"name"`
Username string `json:"username"`
Description *string `json:"description"`
SpaceID string `json:"space_id"` // 可选,指定 Bot 加入的 Space
}
CreateBotReq 通过API Key创建Bot请求
type CreateBotResp ¶
type CreateBotResp struct {
RobotID string `json:"robot_id"`
Username string `json:"username"`
Name string `json:"name"`
Description string `json:"description"`
BotToken string `json:"bot_token"`
CreatedAt string `json:"created_at"`
}
CreateBotResp 创建Bot响应
type MintBotResult ¶ added in v1.8.0
type MintBotResult struct {
BotUID string // robot_id, also used as IM uid
BotToken string // bf_xxx token for /v1/bot/* authentication
}
MintBotResult is the result of a successful OBO bot mint.
func MintBotOBO ¶ added in v1.8.0
func MintBotOBO(ctx *config.Context, ownerUID, spaceID, displayName, botToken string) (*MintBotResult, error)
MintBotOBO creates a bot on behalf of ownerUID, scoped to the given space.
Unlike the IM /newbot flow (which has space fallback and command-handler state), this is a non-interactive call intended for service-to-service use (e.g. the runtime module creating a bot automatically when a managed agent is provisioned). spaceID is required — no fallback to creator's first space.
botToken must be generated by the server-side caller before invoking this helper. Public HTTP callers do not choose bot credentials.
Steps mirror tryCreateBotCore + the post-create block of createBot:
- create app (idempotent on robot_id)
- insert robot row
- add user (Robot=1)
- add bot to space_member (required; this is authorization state)
- friend owner <-> bot bidirectional (logged-and-continue on failure)
type RobotApplyListResp ¶
type RobotApplyListResp struct {
List []*RobotApplyResp `json:"list"`
Count int64 `json:"count"`
}
RobotApplyListResp 申请列表响应
type RobotApplyReq ¶
type RobotApplyReq struct {
RobotUID string `json:"robot_uid"`
Remark string `json:"remark"`
SpaceID string `json:"space_id"` // Space ID(可选,客户端从 body 传递)
}
RobotApplyReq 申请使用AI的请求
type RobotApplyResp ¶
type RobotApplyResp struct {
ID int64 `json:"id"`
UID string `json:"uid"`
RobotUID string `json:"robot_uid"`
RobotName string `json:"robot_name"`
ApplicantName string `json:"applicant_name"`
OwnerUID string `json:"owner_uid"`
Remark string `json:"remark"`
Status int `json:"status"`
CreatedAt string `json:"created_at"`
}
RobotApplyResp 申请记录响应
type RobotApplySureReq ¶
type RobotApplySureReq struct {
ApplyID int64 `json:"apply_id"`
}
RobotApplySureReq Owner通过申请的请求
type UpdateBotReq ¶
UpdateBotReq 更新Bot请求
type UserAPIKey ¶ added in v1.6.0
UserAPIKey is the resolved, active `uk_` record exposed to callers. It deliberately omits storage-only columns (hash/cipher placeholders, audit fields) so consumers only see what they need.
type UserAPIKeyService ¶ added in v1.6.0
type UserAPIKeyService interface {
// GetOrCreate returns the active plaintext `uk_` for (uid, spaceID,
// clientID), creating one when none exists. Repeated calls return the
// same key (idempotent plaintext echo). A blank clientID defaults to
// the botfather client.
GetOrCreate(uid, spaceID, clientID string) (string, error)
// GetOrCreateForEnabledIntegrationClient is the integration-safe issuance
// path. It serializes with manager disable by locking the integration_client
// row and re-checking enabled state in the same transaction that creates or
// rotates the `uk_` row.
GetOrCreateForEnabledIntegrationClient(uid, spaceID, clientID string) (string, error)
// AuthByKey resolves an active key by its plaintext value. It returns
// (nil, nil) when the key is unknown or revoked.
AuthByKey(plaintext string) (*UserAPIKey, error)
}
UserAPIKeyService owns the get-or-create and authenticate semantics for `uk_` user API keys. botfather (/quickstart) and the integration module (OIDC exchange) share one implementation so both stay consistent on the (uid, space_id, client_id) dimension and the plaintext-echo idempotency contract.
func NewUserAPIKeyService ¶ added in v1.6.0
func NewUserAPIKeyService(ctx *config.Context) UserAPIKeyService
NewUserAPIKeyService builds a UserAPIKeyService. botfather uses it for /quickstart; the integration module uses it to mint `uk_` for external clients.
type UserBotResp ¶
type UserBotResp struct {
RobotID string `json:"robot_id"`
Username string `json:"username"`
Name string `json:"name"`
Description string `json:"description"`
// BotToken 出于安全在列表里恒为空串(不批量泄露 `bf_`);取 token 走单端点。
BotToken string `json:"bot_token"`
CreatedAt string `json:"created_at"`
// BoundAgentRef 占用方不透明标签(如 octopush:agent_xxx);空=空闲。
BoundAgentRef string `json:"bound_agent_ref"`
// BoundAt 占用时间(timeFormart);未占用时为 null(*string,与 doc 的
// string|null 及 unbind 的显式 null 对齐——不用 omitempty 省略字段)。
BoundAt *string `json:"bound_at"`
AgentPlatform string `json:"agent_platform,omitempty"`
AgentVersion string `json:"agent_version,omitempty"`
PluginVersion string `json:"plugin_version,omitempty"`
}
UserBotResp 用户Bot列表项。
安全:列表不批量回填 `bf_` 凭证。为不破坏既有响应契约,保留 bot_token 字段 但**恒为空串**——老客户端读字段不会拿到 undefined,但拿不到真实 token;需要 某个 Bot 的 token 时单独调 GET /v1/user/bots/:bot_id/token。