botfather

package
v1.10.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 14, 2026 License: Apache-2.0 Imports: 44 Imported by: 0

Documentation

Index

Constants

View Source
const (
	AccessModeRequireApproval = 0 // 需要审批
	AccessModeAutoApprove     = 1 // 自动通过
	AccessModeForbidden       = 2 // 禁止申请
)
View Source
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"
)
View Source
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 命令

View Source
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"
)

对话状态

View Source
const (
	FieldState   = "state"
	FieldCommand = "command"
	FieldBotID   = "bot_id"
	FieldBotName = "bot_name"
)

状态上下文字段

View Source
const (
	ApplyStatusPending  = 0
	ApplyStatusApproved = 1
	ApplyStatusRejected = 2
)
View Source
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

View Source
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

func RegisterFriendApplyHook(ctx *config.Context)

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

type BotEventsReq struct {
	EventID int64 `json:"event_id"`
	Limit   int64 `json:"limit"`
}

BotEventsReq Bot获取事件请求

type BotFather

type BotFather struct {
	log.Log
	// contains filtered or unexported fields
}

BotFather BotFather模块

func New

func New(ctx *config.Context) *BotFather

New 创建BotFather实例

func (*BotFather) Route

func (bf *BotFather) Route(r *wkhttp.WKHttp)

Route 路由配置

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 BotHeartbeatReq

type BotHeartbeatReq struct{}

BotHeartbeatReq Bot心跳请求(REST模式)

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:

  1. create app (idempotent on robot_id)
  2. insert robot row
  3. add user (Robot=1)
  4. add bot to space_member (required; this is authorization state)
  5. 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

type UpdateBotReq struct {
	Name        *string `json:"name"`
	Description *string `json:"description"`
}

UpdateBotReq 更新Bot请求

type UserAPIKey added in v1.6.0

type UserAPIKey struct {
	ID       int64
	UID      string
	SpaceID  string
	ClientID string
	APIKey   string
}

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。

Directories

Path Synopsis
Package cmdmenu owns BotFather's own command menu — the /newbot, /help, ...
Package cmdmenu owns BotFather's own command menu — the /newbot, /help, ...

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL