Documentation
¶
Overview ¶
Package plugin provides the public SDK for PaperValet plugins. External plugins build against this package. Internal packages should use the type aliases in internal/interfaces.
Index ¶
- Variables
- func Bold(s string) string
- func Code(v any) string
- func Escape(s string) string
- func Invalid(zh, en string) error
- func Italic(s string) string
- func Link(text, url string) string
- func Mention(text string, id int64) string
- func ParseMarkdown(text string, resolve func(int64) (tg.InputUserClass, error)) (string, []tg.MessageEntityClass)
- func Pre(s string) string
- type Bot
- type BotContext
- type Button
- type ButtonStyle
- type Choice
- type Command
- type CommandContext
- func (c *CommandContext) ArgCount() int
- func (c *CommandContext) Context() context.Context
- func (c *CommandContext) Delete() error
- func (c *CommandContext) DeleteMessages(ids ...int) error
- func (c *CommandContext) Edit(text string) error
- func (c *CommandContext) GetArg(index int) string
- func (c *CommandContext) GetArgs() string
- func (c *CommandContext) HasArg(arg string) bool
- func (c *CommandContext) IsSelf() bool
- func (c *CommandContext) Reply(text string) error
- func (c *CommandContext) ReplyMedia(path, caption string) error
- func (c *CommandContext) ResolvePeer() (tg.InputPeerClass, error)
- func (c *CommandContext) T(key string, args ...any) string
- func (c *CommandContext) Tlocal(zh, en string) string
- func (c *CommandContext) Typing() error
- type CommandError
- type DescENProvider
- type Emitter
- type Handler
- type Host
- type InvalidError
- type Logger
- type Manager
- type MediaDownloader
- type MediaSender
- type MessageEvent
- type Middleware
- type Page
- type PeerResolver
- type Plugin
- type PluginInfo
- type PluginMetadata
- type PluginStatus
- type RegistryProvider
- type Session
- type SessionContext
- type Setting
- type SettingKind
- type Settings
- type SettingsSpec
- type View
Constants ¶
This section is empty.
Variables ¶
var ErrBotNotReady = errors.New("bot not ready")
ErrBotNotReady is returned by Bot calls before the bot has logged in.
var ErrNoMessage = &CommandError{Code: "NO_MESSAGE", Message: "no message in context"}
Functions ¶
func ParseMarkdown ¶ added in v0.1.1
func ParseMarkdown(text string, resolve func(int64) (tg.InputUserClass, error)) (string, []tg.MessageEntityClass)
ParseMarkdown converts Markdown into plain text plus entities. Mentions of users that cannot be resolved degrade to plain text; any other failure falls back to the raw text.
Types ¶
type Bot ¶ added in v0.1.1
type Bot interface {
// Ready reports whether the bot is logged in.
Ready() bool
// Username is the bot's @username without @, "" before login.
Username() string
// SetPage adds or replaces the plugin's page; nil removes it. Pages
// and settings are removed automatically when the plugin unloads.
SetPage(p *Page) error
// Notify sends a view to the owner's bot chat.
Notify(ctx context.Context, v *View) (int, error)
// Send posts a view to a chat the bot can write to.
Send(ctx context.Context, chatID int64, v *View) (int, error)
// Edit replaces a message the bot sent.
Edit(ctx context.Context, chatID int64, msgID int, v *View) error
}
Bot is the companion bot as seen by one plugin (Host().Bot(name)). It only talks to the owner, renders settings panels and plugin pages, and posts messages on the plugin's behalf. Buttons with Data on anything the plugin sends are routed back to its Page.
type BotContext ¶ added in v0.1.1
type BotContext struct {
Ctx context.Context
Lang string
Data string
// Input is the text the owner typed after Ask.
Input string
// contains filtered or unexported fields
}
BotContext is passed to Page.Handle.
func (*BotContext) Alert ¶ added in v0.1.1
func (c *BotContext) Alert(text string)
Alert shows a notice the owner must dismiss.
func (*BotContext) Ask ¶ added in v0.1.1
func (c *BotContext) Ask(key string)
Ask waits for the owner to type text. The next message comes back to Handle with Data set to key and Input set to the text. The returned View should say what to type.
func (*BotContext) Asked ¶ added in v0.1.1
func (c *BotContext) Asked() string
Asked returns the key passed to Ask; read by the host after Handle.
func (*BotContext) Context ¶ added in v0.1.1
func (c *BotContext) Context() context.Context
Context returns the request context.
func (*BotContext) Notice ¶ added in v0.1.1
func (c *BotContext) Notice() (string, bool)
Notice returns the toast text and whether it is an alert; read by the host after Handle.
func (*BotContext) Tlocal ¶ added in v0.1.1
func (c *BotContext) Tlocal(zh, en string) string
Tlocal picks between a Chinese and an English string.
func (*BotContext) Toast ¶ added in v0.1.1
func (c *BotContext) Toast(text string)
Toast shows a short notice on the pressed button.
type Button ¶ added in v0.1.1
type Button struct {
Text string
// Data comes back to Page.Handle as BotContext.Data, at most 32 bytes.
Data string
URL string
// Style colors the button on clients that support it; others show
// it plain.
Style ButtonStyle
}
Button is one inline button. Set Data for a callback or URL for a link.
type ButtonStyle ¶ added in v0.1.1
type ButtonStyle uint8
ButtonStyle is a button background color.
const ( StylePlain ButtonStyle = iota StylePrimary StyleSuccess StyleDanger )
Button colors: Primary for the main action, Success for adding or confirming, Danger for removing.
type Command ¶
type Command struct {
Name string
Aliases []string
Description string
// DescEN is the English description; when set it wins over Description
// for English users (Description stays the Chinese/primary text).
DescEN string
Usage string
// UsageEN is the English usage line; when empty Usage is reused.
UsageEN string
Plugin string
Category string
OwnerOnly bool
Hidden bool
RateLimit int
Handler Handler
}
Command represents a registered command.
type CommandContext ¶
type CommandContext struct {
Command string
Args []string
RawArgs string
Message *MessageEvent
Session *SessionContext
API *tg.Client
PeerResolver PeerResolver
Emitter Emitter
Media MediaSender
Downloader MediaDownloader
PluginName string
// SelfID is the account user id; Message.UserID == SelfID means the
// owner sent the command, otherwise it is delegated sudo traffic.
SelfID int64
// Lang is the active language ("zh-CN"/"en-US") for this command,
// resolved from the i18n manager. Lets plugins localize static help
// text without registering a full catalog.
Lang string
StartTime time.Time
Metadata map[string]any
Ctx context.Context
Logger Logger
I18n func(key string, args ...any) string
}
CommandContext is passed to every command handler.
func (*CommandContext) ArgCount ¶
func (c *CommandContext) ArgCount() int
func (*CommandContext) Context ¶
func (c *CommandContext) Context() context.Context
func (*CommandContext) Delete ¶
func (c *CommandContext) Delete() error
Delete removes the command message.
func (*CommandContext) DeleteMessages ¶ added in v0.1.1
func (c *CommandContext) DeleteMessages(ids ...int) error
DeleteMessages removes messages in the current chat. Channels and supergroups need channels.deleteMessages; messages.deleteMessages there silently does nothing.
func (*CommandContext) Edit ¶
func (c *CommandContext) Edit(text string) error
func (*CommandContext) GetArg ¶
func (c *CommandContext) GetArg(index int) string
func (*CommandContext) GetArgs ¶
func (c *CommandContext) GetArgs() string
func (*CommandContext) HasArg ¶
func (c *CommandContext) HasArg(arg string) bool
func (*CommandContext) IsSelf ¶ added in v0.1.1
func (c *CommandContext) IsSelf() bool
IsSelf reports whether the command came from the owner's own account.
func (*CommandContext) Reply ¶
func (c *CommandContext) Reply(text string) error
func (*CommandContext) ReplyMedia ¶
func (c *CommandContext) ReplyMedia(path, caption string) error
ReplyMedia sends a local file (photo/document) as a reply and deletes nothing.
func (*CommandContext) ResolvePeer ¶
func (c *CommandContext) ResolvePeer() (tg.InputPeerClass, error)
func (*CommandContext) T ¶
func (c *CommandContext) T(key string, args ...any) string
T translates a message key using the command's i18n resolver. Falls back to the raw key when no resolver is wired.
func (*CommandContext) Tlocal ¶ added in v0.1.1
func (c *CommandContext) Tlocal(zh, en string) string
Tlocal picks between a Chinese and an English string by active language.
func (*CommandContext) Typing ¶
func (c *CommandContext) Typing() error
type CommandError ¶
func (*CommandError) Error ¶
func (e *CommandError) Error() string
func (*CommandError) Unwrap ¶
func (e *CommandError) Unwrap() error
type DescENProvider ¶ added in v0.1.1
type DescENProvider interface {
DescEN() string
}
DescENProvider is optionally implemented by plugins that carry an English description alongside the primary one.
type Handler ¶
type Handler func(ctx *CommandContext) error
Handler is the signature for command handlers.
type Host ¶ added in v0.1.1
type Host interface {
API() *tg.Client
PeerResolver() PeerResolver
Media() MediaSender
Downloader() MediaDownloader
// SelfID is the logged-in account id (0 before login completes).
SelfID() int64
// Logger returns a logger named after the plugin.
Logger(name string) Logger
// DataDir returns data/<plugin>, creating it if needed.
DataDir(plugin string) (string, error)
// Send posts a Markdown message to chatID and returns its message id.
// replyTo 0 sends a plain message.
Send(ctx context.Context, chatID int64, text string, replyTo int) (int, error)
// Lang is the active language for userID: zh-CN or en-US.
Lang(userID int64) string
// Settings registers the plugin's settings panel (spec.Plugin must be
// the plugin name) and returns its values. Call it from Init. Options
// are edited in the bot panel, never through commands.
Settings(spec *SettingsSpec) (Settings, error)
// Bot returns the companion bot scoped to the named plugin.
Bot(plugin string) Bot
}
Host gives plugins the same services a CommandContext carries, without needing a triggering message. Safe to keep from Init; network calls work once Start runs (the client is connected by then).
type InvalidError ¶ added in v0.1.1
type InvalidError struct{ Zh, En string }
InvalidError is a validation error with text in both languages.
func (*InvalidError) Error ¶ added in v0.1.1
func (e *InvalidError) Error() string
func (*InvalidError) Text ¶ added in v0.1.1
func (e *InvalidError) Text(lang string) string
Text returns the message in lang ("zh-CN" or "en-US").
type Logger ¶
type Logger interface {
Debug(msg string, keysAndValues ...any)
Info(msg string, keysAndValues ...any)
Warn(msg string, keysAndValues ...any)
Error(msg string, keysAndValues ...any)
Named(name string) Logger
With(keysAndValues ...any) Logger
}
Logger is the minimal logging interface for plugins.
type Manager ¶
type Manager interface {
RegisterPlugin(p Plugin) error
RegisterCommand(cmd *Command) error
UnregisterCommand(name string)
UnregisterPlugin(name string)
Commands() RegistryProvider
GetInfo(name string) (PluginInfo, bool)
GetAllInfo() []PluginInfo
GetPlugin(name string) (Plugin, bool)
Emit(ctx context.Context, eventType string, data any) error
InitAll(ctx context.Context) error
StartAll(ctx context.Context) error
StopAll(ctx context.Context) error
// Host exposes long-lived runtime services so plugins can work outside
// command handlers (schedulers, restored jobs, event listeners).
Host() Host
}
Manager is the plugin manager interface exposed to external plugins.
type MediaDownloader ¶
type MediaDownloader interface {
DownloadMedia(ctx context.Context, msg *MessageEvent) (string, error)
}
MediaDownloader downloads media from a message into a local regular file.
type MediaSender ¶
type MediaSender interface {
SendFile(ctx context.Context, chatID int64, path string, caption string, replyTo int) error
}
MediaSender sends local files to chats. Implemented by internal/media.Manager.
type MessageEvent ¶
type MessageEvent struct {
Update tg.UpdatesClass
Message *tg.Message
Text string
UserID int64
ChatID int64
IsOut bool
IsReply bool
ReplyToID int
Entities []tg.MessageEntityClass
Media tg.MessageMediaClass
Date int
PeerID tg.PeerClass
Raw any
}
MessageEvent represents a processed message event.
type Page ¶ added in v0.1.1
type Page struct {
Title string
TitleEN string
// Command optionally opens the page with /<Command> in the bot chat.
Command string
// Handle renders the page. Data is "" when the page opens, otherwise
// the Data of the pressed button (or the Ask key with Input set).
// The bot appends a back button; do not add one.
Handle func(ctx *BotContext) (*View, error)
}
Page is a custom screen a plugin adds to the bot menu, for things that are more than a setting: lists with per-item buttons, dashboards, wizards. Buttons on messages the plugin posts with Notify, Send or Edit also come back to Handle.
type PeerResolver ¶
type PeerResolver interface {
ResolveFromChatID(ctx context.Context, chatID int64) (tg.InputPeerClass, error)
ResolveUserInChannel(ctx context.Context, channelPeer tg.InputChannelClass, userID int64) (tg.InputPeerClass, error)
ResolveUserFromMessage(ctx context.Context, peer tg.InputPeerClass, msgID int, userID int64) (tg.InputPeerClass, error)
ResolveUsername(ctx context.Context, username string) (tg.InputPeerClass, error)
}
PeerResolver resolves chat/user IDs to InputPeer.
type Plugin ¶
type Plugin interface {
Name() string
Description() string
Init(ctx context.Context, mgr Manager) error
Start(ctx context.Context) error
Stop(ctx context.Context) error
}
Plugin is the interface all plugins must implement.
type PluginInfo ¶
type PluginInfo struct {
Name string
Description string
DescEN string
Status PluginStatus
}
PluginInfo holds plugin metadata.
type PluginMetadata ¶
type PluginMetadata struct {
Name string
Description string
DescEN string
Version string
Author string
MinVersion string
}
PluginMetadata holds plugin metadata for external .so plugins. External plugins export this as `var Metadata *PluginMetadata`.
type PluginStatus ¶
type PluginStatus int
PluginStatus represents plugin lifecycle state.
const ( StatusInactive PluginStatus = iota StatusActive StatusError )
func (PluginStatus) String ¶
func (s PluginStatus) String() string
type RegistryProvider ¶
type RegistryProvider interface {
Get(name string) (*Command, bool)
GetAll() map[string]*Command
GetByPlugin(plugin string) map[string]*Command
GetPrefix() string
GetPrefixes() []string
// SetPrefixes replaces all command prefixes (main prefix first).
SetPrefixes(prefixes []string)
// AddUserAlias registers a runtime alias expanded once during parsing.
// The value is a full command line, e.g. "exec ./deploy.sh".
AddUserAlias(name, cmd string)
RemoveUserAlias(name string)
UserAliases() map[string]string
}
RegistryProvider provides command registry access.
type SessionContext ¶
SessionContext wraps a Session with a request context.
func NewSessionContext ¶
func NewSessionContext(s *Session, ctx context.Context) *SessionContext
NewSessionContext creates a new SessionContext.
func (*SessionContext) Ctx ¶
func (s *SessionContext) Ctx() context.Context
func (*SessionContext) Delete ¶
func (s *SessionContext) Delete(key string)
func (*SessionContext) Set ¶
func (s *SessionContext) Set(key string, value any)
type Setting ¶ added in v0.1.1
type Setting struct {
// Key is the stable id, lowercase letters, digits and _ only.
Key string
Label string
LabelEN string
// Hint is one line shown on the edit screen.
Hint string
HintEN string
Kind SettingKind
// Default must match Kind: bool, string or int.
Default any
Choices []Choice
// Min and Max bound a SettingNumber; both 0 means unbounded.
Min, Max int
// Validate checks typed text (SettingText) and may normalize it.
// Return Invalid(zh, en) so the owner reads the reason in their language.
Validate func(string) (string, error)
// Secret masks the value in the panel.
Secret bool
}
Setting declares one option.
type SettingKind ¶ added in v0.1.1
type SettingKind int
SettingKind selects how the bot panel edits a setting.
const ( // SettingToggle is a bool flipped with one tap. SettingToggle SettingKind = iota // SettingChoice is a string picked from Choices. SettingChoice // SettingText is a string the owner types. SettingText // SettingNumber is an int the owner types, kept within Min..Max. SettingNumber )
type Settings ¶ added in v0.1.1
type Settings interface {
Bool(key string) bool
String(key string) string
Int(key string) int
// Set stores a value; its type must match the setting's Kind.
Set(key string, value any) error
}
Settings reads and writes a plugin's options, persisted in data/<plugin>/settings.json. Reads of unknown keys return zero values.