native

package
v4.2.0 Latest Latest
Warning

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

Go to latest
Published: Oct 11, 2026 License: MIT Imports: 24 Imported by: 0

Documentation

Overview

Package native implements the notification package's v2 routes in the package itself, on the kernel's notification and Telegram tables adopted in place (kernel.storage.adopt), and the e-mail configuration through the kernel's KernelSettings contract. Legacy handlers and native routes share the tables, so a route can switch between them at any time. Responses are byte-compatible with the legacy handlers (internal/tests/notificationcompat).

The e-mail configuration (GET and PUT) and the test send read and write the notification.email.config key of the kernel's v2_system_config through KernelSettings, namespace mail. Its value holds the SMTP password, a secret: the package reads it in clear (kernel.settings.mail.secrets.v1) because it sends the test e-mail itself. Administrators see it masked, as the kernel's handler shows it, and an update that keeps it sends the placeholder, which the kernel replaces with the stored password. A host without the contract leaves the three routes legacy.

Setting the Telegram webhook derives its default URL from the request's scheme and host, which the kernel sends package hosts as request metadata (RequestMetadata.Scheme and Host). The public Telegram webhook has no native handler and stays bridged: it answers bot commands from subscriber data (the subscription token) that no kernel view exposes.

Index

Constants

View Source
const (
	EmailConfigGetRouteID = "notification.admin.notification.email.config.get"
	EmailConfigPutRouteID = "notification.admin.notification.email.config.put"
	TestSendRouteID       = "notification.admin.notification.test.post"
)

Route ids of the routes that read or write the e-mail configuration.

View Source
const SetWebhookRouteID = "notification.admin.telegram.webhook.post"

SetWebhookRouteID is POST /api/v2/admin/telegram/webhook.

Variables

This section is empty.

Functions

func EmailConfigRequestID

func EmailConfigRequestID(token string) string

EmailConfigRequestID names an e-mail configuration update in the kernel's settings request ledger, so a retried request is applied once. token identifies the HTTP request: its Idempotency-Key, else its request id, else a fresh value.

Types

type Binding

type Binding struct {
	ID           uint   `gorm:"primaryKey" json:"id"`
	UserID       uint   `gorm:"uniqueIndex" json:"user_id"`
	TelegramID   int64  `gorm:"uniqueIndex" json:"telegram_id"`
	Username     string `gorm:"size:100" json:"username"`
	FirstName    string `gorm:"size:100" json:"first_name"`
	LastName     string `gorm:"size:100" json:"last_name"`
	LanguageCode string `gorm:"size:10" json:"language_code"`

	IsBanned bool       `gorm:"default:false" json:"is_banned"`
	BannedAt *time.Time `json:"banned_at"`

	NotifyExpire  bool `gorm:"default:true" json:"notify_expire"`
	NotifyTraffic bool `gorm:"default:true" json:"notify_traffic"`
	NotifyTicket  bool `gorm:"default:true" json:"notify_ticket"`

	MessageCount int64     `json:"message_count"`
	LastActive   time.Time `json:"last_active"`

	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

Binding is a v2_telegram_user row: a member's Telegram account. The kernel model's User relation is not loaded; the answers that show the member's e-mail read it from kapi_user_directory_v1.

func (Binding) TableName

func (Binding) TableName() string

TableName is the adopted kernel table.

type Bot

type Bot struct {
	ID      uint   `gorm:"primaryKey" json:"id"`
	Name    string `gorm:"size:100;not null" json:"name"`
	Token   string `gorm:"size:200;not null" json:"token"`
	Enabled bool   `gorm:"default:false" json:"enabled"`

	WebhookURL string `gorm:"size:255" json:"webhook_url"`
	WebhookSet bool   `gorm:"default:false" json:"webhook_set"`

	AdminIDs string `gorm:"type:text" json:"admin_ids"`

	WelcomeMsg string `gorm:"type:text" json:"welcome_msg"`

	AllowBind   bool `gorm:"default:true" json:"allow_bind"`
	AllowSub    bool `gorm:"default:true" json:"allow_sub"`
	AllowTicket bool `gorm:"default:true" json:"allow_ticket"`
	AllowInfo   bool `gorm:"default:true" json:"allow_info"`

	TotalUsers int64 `json:"total_users"`
	TotalChats int64 `json:"total_chats"`

	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

Bot is a v2_telegram_bot row.

func (Bot) TableName

func (Bot) TableName() string

TableName is the adopted kernel table.

type EmailConfig

type EmailConfig struct {
	Host        string `json:"host"`
	Port        int    `json:"port"`
	Username    string `json:"username"`
	Password    string `json:"password"`
	FromName    string `json:"from_name"`
	FromAddress string `json:"from_address"`
	Encryption  string `json:"encryption"`
}

EmailConfig is the kernel's model.EmailConfig: the stored JSON value has its fields in this order.

type Log

type Log struct {
	ID        uint       `gorm:"primaryKey" json:"id"`
	UserID    *uint      `gorm:"index" json:"user_id"`
	Type      string     `gorm:"size:20" json:"type"`
	Event     string     `gorm:"size:50" json:"event"`
	Title     string     `gorm:"size:200" json:"title"`
	Content   string     `gorm:"type:text" json:"content"`
	Status    int        `json:"status"`
	Error     string     `gorm:"size:500" json:"error"`
	SentAt    *time.Time `json:"sent_at"`
	ReadAt    *time.Time `json:"read_at"`
	CreatedAt time.Time  `gorm:"index" json:"created_at"`
}

Log is a v2_notification_log row. Its JSON matches the kernel model, which the member's notification list returns as is.

func (Log) TableName

func (Log) TableName() string

TableName is the adopted kernel table.

type NotifySettingsRequest

type NotifySettingsRequest struct {
	NotifyExpire  *bool `json:"notify_expire"`
	NotifyTraffic *bool `json:"notify_traffic"`
	NotifyTicket  *bool `json:"notify_ticket"`
}

NotifySettingsRequest is the member's notification settings body; its name is part of the decoding messages, as in the kernel's handler.

type Service

type Service struct {
	// Open returns the package's storage connection, on which the adopted
	// tables and the kapi_user_directory_v1 view are visible.
	Open func(ctx context.Context) (*gorm.DB, error)
	// Settings is the kernel's KernelSettings; without it the e-mail
	// configuration and test send have no native handler and stay legacy.
	Settings Settings
	// NewToken names a request that carries neither an Idempotency-Key
	// nor a request id; it defaults to a random UUID.
	NewToken func() string
	// Now defaults to time.Now.
	Now func() time.Time
}

Service holds what the native routes need.

func (*Service) AdminBindings

AdminBindings is GET /api/v2/admin/telegram/users: the members' Telegram bindings, newest first, one page or (all=true) every one.

func (*Service) AdminCreateTemplate

func (s *Service) AdminCreateTemplate(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

AdminCreateTemplate is POST /api/v2/admin/notification/templates.

func (*Service) AdminDeleteTemplate

func (s *Service) AdminDeleteTemplate(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

AdminDeleteTemplate is DELETE /api/v2/admin/notification/templates/:id.

func (*Service) AdminDeleteWebhook

AdminDeleteWebhook is DELETE /api/v2/admin/telegram/webhook: it calls the Bot API's deleteWebhook and records that no webhook is set.

func (*Service) AdminEmailConfig

AdminEmailConfig is GET /api/v2/admin/notification/email/config: the stored configuration over the defaults, with the SMTP password masked as the kernel's handler masks it.

func (*Service) AdminGetBot

AdminGetBot is GET /api/v2/admin/telegram/bot.

func (*Service) AdminLogs

AdminLogs is GET /api/v2/admin/notification/logs.

func (*Service) AdminSetWebhook

AdminSetWebhook is POST /api/v2/admin/telegram/webhook: it calls the Bot API's setWebhook and records the webhook. Without a url in the body the webhook is this Control's /api/v2/telegram/webhook, at the scheme and host of the administrator's request, as the kernel's handler builds it: the request_scheme and request_host the kernel sends. The kernel resolves them from the connection, or from X-Forwarded-Proto/Host only when the peer is a trusted reverse proxy (server.trusted_proxies); forwarding headers never reach the package and are not read here.

A kernel that sends no request scheme or host leaves the request to the legacy handler (pluginhostsdk.ErrNativeUnavailable), which builds the URL from what the kernel's bridge saw.

func (*Service) AdminTelegramBroadcast

func (s *Service) AdminTelegramBroadcast(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

AdminTelegramBroadcast is POST /api/v2/admin/telegram/broadcast: the message goes, one after another, to every member who is not banned and takes at least one kind of notification.

func (*Service) AdminTelegramNotify

func (s *Service) AdminTelegramNotify(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

AdminTelegramNotify is POST /api/v2/admin/telegram/notify: one message to one Telegram chat.

func (*Service) AdminTemplates

AdminTemplates is GET /api/v2/admin/notification/templates.

func (*Service) AdminTestNotification

func (s *Service) AdminTestNotification(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

AdminTestNotification is POST /api/v2/admin/notification/test. An e-mail test is sent from the package host with the stored SMTP configuration, as the kernel's handler sends it; the Telegram and webhook tests are the kernel's stubs, which send nothing and succeed.

func (*Service) AdminUpdateBindingNotify

func (s *Service) AdminUpdateBindingNotify(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

AdminUpdateBindingNotify is PUT /api/v2/admin/telegram/users/:id/notify. notify_enabled sets all three switches unless one is given on its own.

func (*Service) AdminUpdateBot

AdminUpdateBot is PUT /api/v2/admin/telegram/bot. Without a bot row it creates one.

func (*Service) AdminUpdateEmailConfig

func (s *Service) AdminUpdateEmailConfig(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

AdminUpdateEmailConfig is PUT /api/v2/admin/notification/email/config: host, port and sender address are required; a blank password or the placeholder keeps the stored one, and an absent encryption the stored one. The kernel writes the value through KernelSettings (namespace mail); a kept password is sent as the placeholder, which the kernel replaces with the stored one. The kernel records the system configuration audit entry its own handler records, in the same transaction.

func (*Service) AdminUpdateTemplate

func (s *Service) AdminUpdateTemplate(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

AdminUpdateTemplate is PUT /api/v2/admin/notification/templates/:id.

func (*Service) Handlers

func (s *Service) Handlers() map[string]pluginhostsdk.NativeHandler

Handlers returns the native handlers by route id.

func (*Service) UserMarkAllRead

UserMarkAllRead is POST /api/v2/user/notifications/read-all. Like the legacy handler it answers success even when the update fails.

func (*Service) UserMarkRead

UserMarkRead is POST /api/v2/user/notifications/:id/read. The id is compared as given, so one that is not a number matches no row.

func (*Service) UserNotifications

func (s *Service) UserNotifications(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

UserNotifications is GET /api/v2/user/notifications: the caller's notifications, newest first. Unlike the admin log list it does not clamp the page.

func (*Service) UserTelegramNotify

func (s *Service) UserTelegramNotify(_ context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

UserTelegramNotify is POST /api/v2/user/telegram/notify. The body is validated as in the kernel; a valid one is then refused, as the feature is not implemented: no setting is changed.

func (*Service) UserTelegramStatus

func (s *Service) UserTelegramStatus(ctx context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

UserTelegramStatus is GET /api/v2/user/telegram/status.

func (*Service) UserTelegramUnbind

func (s *Service) UserTelegramUnbind(_ context.Context, request pluginhostsdk.NativeRequest) (pluginhostsdk.NativeResponse, error)

UserTelegramUnbind is POST /api/v2/user/telegram/unbind. It is not implemented: it deletes nothing and says so.

func (*Service) UserUnreadCount

UserUnreadCount is GET /api/v2/user/notifications/unread-count. Like the legacy handler it answers 0 when the count fails.

type SetWebhookRequest

type SetWebhookRequest struct {
	URL string `json:"url" binding:"omitempty,url,max=512"`
}

SetWebhookRequest is the kernel's SetWebhookRequest. Its name and tags are the kernel's, so binding and validation errors read the same.

type Settings

Settings is the part of the kernel's KernelSettings contract the native routes call.

type Template

type Template struct {
	ID        uint      `gorm:"primaryKey" json:"id"`
	Name      string    `gorm:"size:100;not null" json:"name"`
	Type      string    `gorm:"size:20;not null" json:"type"`
	Event     string    `gorm:"size:50;not null" json:"event"`
	Title     string    `gorm:"size:200" json:"title"`
	Content   string    `gorm:"type:text" json:"content"`
	Enabled   bool      `gorm:"default:true" json:"enabled"`
	CreatedAt time.Time `json:"created_at"`
	UpdatedAt time.Time `json:"updated_at"`
}

Template is a v2_notification_template row. Its JSON matches the kernel model, which the template answers return as is.

func (Template) TableName

func (Template) TableName() string

TableName is the adopted kernel table.

type UpdateBotRequest

type UpdateBotRequest struct {
	Name           string `json:"name" binding:"omitempty,max=255"`
	Token          string `json:"token" binding:"omitempty,min=1"`
	WelcomeMsg     string `json:"welcome_msg" binding:"omitempty,max=1024"`
	WelcomeMessage string `json:"welcome_message" binding:"omitempty,max=1024"`
	AdminIDs       any    `json:"admin_ids"`
	AllowBind      *bool  `json:"allow_bind"`
	AllowSub       *bool  `json:"allow_sub"`
	AllowTicket    *bool  `json:"allow_ticket"`
	AllowInfo      *bool  `json:"allow_info"`
}

UpdateBotRequest is the bot update body. Its name is part of the validation messages, so it matches the kernel's handler.UpdateBotRequest.

Jump to

Keyboard shortcuts

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