Ctrl K
ComunidadGuías…

internal/domain/themes.go

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
package domain

import "errors"

// Errors related to custom cloud themes (account.createTheme etc.).
var (
	ErrThemeNotFound      = errors.New("theme not found")
	ErrThemeInvalid       = errors.New("theme invalid")
	ErrThemeSlugTaken     = errors.New("theme slug taken")
	ErrThemeFormatInvalid = errors.New("theme format invalid")
)

// ThemeBaseKind corresponds to the five variants of TL baseTheme (classic/day/night/tinted/arctic).
// The client selects the matching ThemeSettings based on the current base theme.
type ThemeBaseKind string

const (
	ThemeBaseClassic ThemeBaseKind = "classic"
	ThemeBaseDay     ThemeBaseKind = "day"
	ThemeBaseNight   ThemeBaseKind = "night"
	ThemeBaseTinted  ThemeBaseKind = "tinted"
	ThemeBaseArctic  ThemeBaseKind = "arctic"
)

// ThemeWallpaperSpec is a pure-gradient wallpaper within a theme setting (corresponding to wallPaperNoFile + wallPaperSettings).
// Custom cloud themes use only solid-color gradients (no download), consistent with the static catalog.
type ThemeWallpaperSpec struct {
	BackgroundColors []int  `json:"background_colors,omitempty"` // at most 4
	Intensity        int    `json:"intensity,omitempty"`
	Rotation         int    `json:"rotation,omitempty"`
	Blur             bool   `json:"blur,omitempty"`
	Motion           bool   `json:"motion,omitempty"`
	Emoticon         string `json:"emoticon,omitempty"`
	Dark             bool   `json:"dark,omitempty"`
}

// WallpaperSettings is the domain-only settings for a channel/private-chat wallpaper. The Has* fields keep TL
// conditional-flag semantics so that legally valid values like black (0) are not lost on persistence.
type WallpaperSettings struct {
	Blur                     bool   `json:"blur,omitempty"`
	Motion                   bool   `json:"motion,omitempty"`
	HasBackgroundColor       bool   `json:"has_background_color,omitempty"`
	BackgroundColor          int    `json:"background_color,omitempty"`
	HasSecondBackgroundColor bool   `json:"has_second_background_color,omitempty"`
	SecondBackgroundColor    int    `json:"second_background_color,omitempty"`
	HasThirdBackgroundColor  bool   `json:"has_third_background_color,omitempty"`
	ThirdBackgroundColor     int    `json:"third_background_color,omitempty"`
	HasFourthBackgroundColor bool   `json:"has_fourth_background_color,omitempty"`
	FourthBackgroundColor    int    `json:"fourth_background_color,omitempty"`
	HasIntensity             bool   `json:"has_intensity,omitempty"`
	Intensity                int    `json:"intensity,omitempty"`
	HasRotation              bool   `json:"has_rotation,omitempty"`
	Rotation                 int    `json:"rotation,omitempty"`
	HasEmoticon              bool   `json:"has_emoticon,omitempty"`
	Emoticon                 string `json:"emoticon,omitempty"`
}

// Empty reports whether no explicit wallpaper rendering settings are present.
func (s WallpaperSettings) Empty() bool {
	return !s.Blur &&
		!s.Motion &&
		!s.HasBackgroundColor &&
		!s.HasSecondBackgroundColor &&
		!s.HasThirdBackgroundColor &&
		!s.HasFourthBackgroundColor &&
		!s.HasIntensity &&
		!s.HasRotation &&
		!s.HasEmoticon
}

// Wallpaper is the domain-only description of a channel/private-chat's current wallpaper. NoFile=true corresponds to
// wallPaperNoFile; otherwise ID+AccessHash/Slug references a catalog/document wallpaper.
type Wallpaper struct {
	ID         int64             `json:"id,omitempty"`
	AccessHash int64             `json:"access_hash,omitempty"`
	Slug       string            `json:"slug,omitempty"`
	NoFile     bool              `json:"no_file,omitempty"`
	Default    bool              `json:"default,omitempty"`
	Pattern    bool              `json:"pattern,omitempty"`
	Dark       bool              `json:"dark,omitempty"`
	Settings   WallpaperSettings `json:"settings,omitempty"`
}

// CloneWallpaperPtr returns a detached wallpaper pointer.
func CloneWallpaperPtr(in *Wallpaper) *Wallpaper {
	if in == nil {
		return nil
	}
	out := *in
	return &out
}

// WallpaperEqual compares optional wallpapers by value.
func WallpaperEqual(a, b *Wallpaper) bool {
	if a == nil || b == nil {
		return a == nil && b == nil
	}
	return *a == *b
}

// ThemeSettingsSpec is the color scheme under one base theme (corresponding to themeSettings/inputThemeSettings).
// BaseTheme and AccentColor are required (the TL encoder requires base_theme to be non-empty).
type ThemeSettingsSpec struct {
	BaseTheme             ThemeBaseKind       `json:"base_theme"`
	AccentColor           int                 `json:"accent_color"`
	OutboxAccentColor     int                 `json:"outbox_accent_color,omitempty"`
	HasOutboxAccent       bool                `json:"has_outbox_accent,omitempty"`
	MessageColors         []int               `json:"message_colors,omitempty"`
	MessageColorsAnimated bool                `json:"message_colors_animated,omitempty"`
	Wallpaper             *ThemeWallpaperSpec `json:"wallpaper,omitempty"`
}

// Theme is a persisted custom cloud theme. document_id soft-references documents (no hard foreign key);
// settings is non-empty only for accent themes; a full .attheme theme is downloaded via DocumentID.
type Theme struct {
	ID            int64
	AccessHash    int64
	CreatorUserID int64
	Slug          string
	Title         string
	Emoticon      string
	ForChat       bool
	DocumentID    int64
	Settings      []ThemeSettingsSpec
	InstallsCount int
	CreatedAt     int64 // unix seconds
}

// Clone deep-copies the slice fields so the in-memory store never exposes internal references.
func (t Theme) Clone() Theme {
	out := t
	out.Settings = cloneThemeSettings(t.Settings)
	return out
}

func cloneThemeSettings(in []ThemeSettingsSpec) []ThemeSettingsSpec {
	if in == nil {
		return nil
	}
	out := make([]ThemeSettingsSpec, len(in))
	for i, s := range in {
		out[i] = s
		out[i].MessageColors = append([]int(nil), s.MessageColors...)
		if s.Wallpaper != nil {
			wp := *s.Wallpaper
			wp.BackgroundColors = append([]int(nil), s.Wallpaper.BackgroundColors...)
			out[i].Wallpaper = &wp
		}
	}
	return out
}

// IsCreator reports whether userID created the theme (deciding whether a subsequent client upload uses create or update).
func (t Theme) IsCreator(userID int64) bool {
	return t.CreatorUserID != 0 && t.CreatorUserID == userID
}

// ThemeRef references a theme: by id+access_hash (inputTheme) or slug (inputThemeSlug, a deep link).
type ThemeRef struct {
	ID         int64
	AccessHash int64
	Slug       string
}

// IsZero reports whether the reference is empty (neither id nor slug).
func (r ThemeRef) IsZero() bool { return r.ID == 0 && r.Slug == "" }

// ThemeSpec is the input of createTheme. An empty Slug means the server assigns one automatically.
type ThemeSpec struct {
	CreatorUserID int64
	Slug          string
	Title         string
	Emoticon      string
	ForChat       bool
	DocumentID    int64
	Settings      []ThemeSettingsSpec
}

// ThemeUpdate is a partial update of updateTheme; a nil field means unchanged.
type ThemeUpdate struct {
	Slug       *string
	Title      *string
	DocumentID *int64
	Settings   *[]ThemeSettingsSpec
}