Documentation
¶
Overview ¶
Package telegram is a self-contained Telegram Bot API client plus the panel's admin bot: it long-polls for commands (view/add/remove users) and pushes scheduled backups to the linked admin chat. It deliberately depends only on the standard library — the Bot API is plain HTTP+JSON — so the panel keeps its minimal dependency surface.
Index ¶
- func SendBackup(ctx context.Context, client *Client, chats []int64, dataDir string, ...) error
- func UserBotLink(botUsername string) string
- func UserDeepLink(botUsername, linkCode string) string
- type CallbackQuery
- type Chat
- type Client
- func (c *Client) AnswerCallback(ctx context.Context, id, text string) error
- func (c *Client) EditMenu(ctx context.Context, chatID, messageID int64, html string, ...) error
- func (c *Client) GetMe(ctx context.Context) (*User, error)
- func (c *Client) GetUpdates(ctx context.Context, offset int64, timeout int) ([]Update, error)
- func (c *Client) SendDocument(ctx context.Context, chatID int64, filename, caption string, r io.Reader) error
- func (c *Client) SendMenu(ctx context.Context, chatID int64, html string, rows [][]InlineButton) error
- func (c *Client) SendMessage(ctx context.Context, chatID int64, html string) error
- func (c *Client) SendPhoto(ctx context.Context, chatID int64, filename, caption string, r io.Reader) error
- type InlineButton
- type Message
- type Panel
- type Service
- type Update
- type User
- type UserService
- type WebAppInfo
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
func SendBackup ¶
func SendBackup(ctx context.Context, client *Client, chats []int64, dataDir string, manifest backup.Manifest, checkpoint func() error, caption string) error
SendBackup checkpoints the DB, builds a fresh tar.gz of the data directory, and uploads it to each chat as a document. It's shared by the scheduler and the panel's "send test backup" action. A per-chat send failure doesn't abort the rest; the first error is returned.
func UserBotLink ¶ added in v0.3.0
UserBotLink is the public bot URL (open /start, no payload).
func UserDeepLink ¶ added in v0.3.0
UserDeepLink builds a t.me link that binds an existing panel user via a one-time, short-lived bind code (see model.TelegramLinkCodeTTL).
Types ¶
type CallbackQuery ¶
type CallbackQuery struct {
ID string `json:"id"`
From *User `json:"from"`
Message *Message `json:"message"`
Data string `json:"data"`
}
CallbackQuery is an inline-button tap (used for the delete confirmation).
type Client ¶
type Client struct {
// contains filtered or unexported fields
}
Client talks to one bot (identified by its token). It's cheap to construct and safe for use from the single bot loop plus the occasional handler-driven send.
func NewClient ¶
NewClient builds a client for the given bot token. The HTTP timeout comfortably exceeds the long-poll window so GetUpdates isn't cut off mid-wait.
func (*Client) AnswerCallback ¶
AnswerCallback acknowledges a button tap so Telegram stops the spinner.
func (*Client) EditMenu ¶
func (c *Client) EditMenu(ctx context.Context, chatID, messageID int64, html string, rows [][]InlineButton) error
EditMenu replaces the text + inline keyboard of an existing message, so the bot's menus navigate in place instead of stacking new messages.
func (*Client) GetMe ¶
GetMe returns the bot's own account (used to show its @username in the panel).
func (*Client) GetUpdates ¶
GetUpdates long-polls for new updates past offset, blocking up to timeout seconds. Only messages and callback queries are requested.
func (*Client) SendDocument ¶
func (c *Client) SendDocument(ctx context.Context, chatID int64, filename, caption string, r io.Reader) error
SendDocument uploads a file to a chat as a document, with an optional caption.
func (*Client) SendMenu ¶
func (c *Client) SendMenu(ctx context.Context, chatID int64, html string, rows [][]InlineButton) error
SendMenu sends an HTML message with an inline keyboard (rows of buttons). Pass a nil/empty rows for a plain message.
func (*Client) SendMessage ¶
SendMessage sends a plain HTML-formatted message (no buttons). HTML parse mode lets the bot bold headers; all dynamic text must be escaped by the caller (esc).
type InlineButton ¶
type InlineButton struct {
Text string `json:"text"`
CallbackData string `json:"callback_data,omitempty"`
URL string `json:"url,omitempty"` // URL button (mutually exclusive with callback_data)
WebApp *WebAppInfo `json:"web_app,omitempty"` // opens a Mini App in-place (private chats only)
}
InlineButton is one inline-keyboard button (label + callback payload).
type Message ¶
type Message struct {
MessageID int64 `json:"message_id"`
From *User `json:"from"`
Chat Chat `json:"chat"`
Text string `json:"text"`
}
Message is the subset of a Telegram message the bot acts on.
type Panel ¶
type Panel interface {
ListUsers() ([]model.User, error)
CreateUser(ctx context.Context, name string, dataLimit, expireAt int64) (*model.User, error)
DeleteUser(ctx context.Context, id int64) error
SetUserEnabled(ctx context.Context, id int64, enabled bool) error
ResetTraffic(ctx context.Context, id int64) error
BackupManifest() backup.Manifest
Location() *time.Location
// Billing (no-op surface unless tariffs are enabled).
ListTariffPlans(includeDisabled bool) ([]model.TariffPlan, error)
ApplyPlanToUser(ctx context.Context, userID, planID int64, extendFromCurrent bool) error
PlanName(planID int64) string
RequestPlanPayment(ctx context.Context, userID, planID int64) (*model.PaymentOrder, string, error)
// CreateRegisteredUser signs a new user up (active, for the open/invite modes).
CreateRegisteredUser(ctx context.Context, name string) (*model.User, error)
// RequestRegistration records a moderated signup (no user yet); ApproveRegistration
// Request creates the user, RejectRegistrationRequest drops it.
RequestRegistration(ctx context.Context, chatID int64, name string) (bool, error)
RegistrationPending(chatID int64) bool
ApproveRegistrationRequest(ctx context.Context, reqID int64) error
RejectRegistrationRequest(ctx context.Context, reqID int64) error
// ActivePaidPlan reports the user's active paid plan (nil = none), and
// CancelUserPlan drops it to the free plan. Together they gate plan switching:
// while a paid plan is active only renewal or cancellation is allowed.
ActivePaidPlan(u model.User) *model.TariffPlan
CancelUserPlan(ctx context.Context, userID int64) error
// Automatic payment providers (no-op surface unless configured).
PaymentMethods() []string
ProviderLabel(key string) string
StartPlanPayment(ctx context.Context, userID, planID int64, provider string) (*model.PaymentOrder, error)
SetUserNotifier(fn func(chatID int64, html string))
SetAdminNotifier(fn func(html string))
SetAdminModerationNotifier(fn func(reqID int64, name, plan string))
// Audit hooks for the actions the bots perform directly on the store.
UnlinkUserTelegram(ctx context.Context, id int64) error
AuditTelegramLinked(ctx context.Context, id int64, username string)
}
Panel is the slice of the core Manager the bot drives. Defining it here (rather than importing core) keeps the dependency one-way — core never imports telegram — and makes the bot trivially testable with a fake. Every mutating method takes a context: it carries the actor for the audit log, so a change made from a bot is attributed to the Telegram admin (or the VPN user) who made it rather than to "system". See the actor package.
type Service ¶
type Service struct {
// contains filtered or unexported fields
}
Service is the running bot: it long-polls for updates and pushes scheduled backups. The whole UI is inline buttons — the only text a user ever types is "/start <code>" to link, and (when prompted) a new user's name. It re-reads settings every cycle, so enabling/disabling, rotating the token, or changing the schedule all take effect without a restart.
type Update ¶
type Update struct {
UpdateID int64 `json:"update_id"`
Message *Message `json:"message"`
Callback *CallbackQuery `json:"callback_query"`
}
Update is one polled event: a message or a callback-query (inline button tap).
type User ¶
type User struct {
ID int64 `json:"id"`
Username string `json:"username"`
FirstName string `json:"first_name"`
}
User / Chat carry only the identifiers the bot needs.
type UserService ¶ added in v0.3.0
type UserService struct {
// contains filtered or unexported fields
}
UserService is the public VPN user bot: open registration, personal subscription menu, and optional deep-link binding for accounts created in the panel.
func NewUser ¶ added in v0.3.0
func NewUser(panel Panel, st *store.Store) *UserService
NewUser builds the public user bot. Call Run to start polling.
func (*UserService) Run ¶ added in v0.3.0
func (s *UserService) Run(ctx context.Context)
Run long-polls the user bot until ctx is cancelled.
type WebAppInfo ¶ added in v0.11.0
type WebAppInfo struct {
URL string `json:"url"`
}
WebAppInfo points a web_app button at an HTTPS page opened inside Telegram as a Mini App. Inline web_app buttons need no @BotFather domain setup, but work only in private chats and require an https:// URL.