app

package
v0.0.0-...-ae5ca2e Latest Latest
Warning

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

Go to latest
Published: Aug 30, 2026 License: MIT Imports: 61 Imported by: 0

Documentation

Index

Constants

View Source
const (
	ReportDispositionNoViolation    = "no_violation"
	ReportDispositionRequestChanges = "request_changes"
	ReportDispositionActionTaken    = "action_taken"
	ReportDispositionEscalated      = "escalated"
)
View Source
const (
	ReaderFontSerif    = "serif"
	ReaderFontSans     = "sans"
	ReaderFontDyslexic = "dyslexic"

	ReaderPageBackground = "background"
	ReaderPageSurface    = "surface"

	ReaderThemeSystem = "system"
	ReaderThemeLight  = "light"
	ReaderThemeDark   = "dark"
)
View Source
const (
	BOOK_COVER_DIRECTORY = "book-covers"
)
View Source
const MaxChapterNameLength = 200
View Source
const UserDataMaxSize = 20 * 1024

Variables

View Source
var (
	ErrTypeSignUp    = apperror.AppErrors.NewType("signup")
	ErrUsernameTaken = ErrTypeSignUp.New("username is already taken")

	ErrTypeAuthenticationError = apperror.AppErrors.NewType("authentication", apperror.ErrTraitAuthorizationIssue)
	ErrInvalidCredentials      = ErrTypeAuthenticationError.New("invalid credentials")
	ErrUserBanned              = ErrTypeAuthenticationError.New("user is banned")
)
View Source
var (
	ErrTypeBookNotFound = apperror.AppErrors.NewType("book404", apperror.ErrTraitEntityNotFound)
	ErrTypeBookPrivated = apperror.AppErrors.NewType("access_denied_book_private", apperror.ErrTraitForbidden)
)
View Source
var (
	ErrTypeBookSanitizationFailed = apperror.AppErrors.NewType("content_sanitization_failed")
	ErrTypeChaptersReorder        = apperror.AppErrors.NewType("chapters_reorder")
	ErrDraftNotFound              = apperror.AppErrors.NewType("draft_not_found", errorx.NotFound(), apperror.ErrTraitEntityNotFound).New("draft not found")
	ErrTypeChapterDoesNotExist    = apperror.AppErrors.NewType("chapter_not_found", apperror.ErrTraitEntityNotFound)
)
View Source
var (
	ErrEmptyBookName   = errors.New("empty book name")
	ErrBookNameTooLong = errors.New("invalid book name")
	BookSummaryTooLong = errors.New("book summary is too long")
)
View Source
var (
	CollectionErrors       = apperror.AppErrors.NewSubNamespace("collection")
	ErrCollectionNotExists = CollectionErrors.NewType("404", apperror.ErrTraitEntityNotFound).New("collection not found")
)
View Source
var (
	CommentErrors                = apperror.AppErrors.NewSubNamespace("comment")
	ErrTypeCommentNotFound       = CommentErrors.NewType("not_found", apperror.ErrTraitEntityNotFound)
	ErrTypeCommentContentInvalid = CommentErrors.NewType("invalid_content", apperror.ErrTraitValidationError)
	ErrCommentUpdateForbidden    = CommentErrors.NewType("update_forbidden", apperror.ErrTraitForbidden).New("only the comment author can edit this comment")
	ErrCommentContentEmpty       = ErrTypeCommentContentInvalid.New("comment content is empty")
	ErrCommentContentTooLarge    = ErrTypeCommentContentInvalid.New("comment content is too large")
)
View Source
var (
	ErrModerationForbidden       = apperror.AppErrors.NewType("moderation_forbidden", apperror.ErrTraitAuthorizationIssue).New("moderator privileges are required")
	ErrModerationReason          = apperror.AppErrors.NewType("moderation_reason_required").New("a moderation reason is required")
	ErrInvalidLoginHistoryFilter = apperror.AppErrors.NewType("invalid_login_history_filter").New("invalid login history filter")
)
View Source
var (
	ModerationBookErrors                = apperror.AppErrors.NewSubNamespace("mod_books")
	InvalidModerationActionError        = ModerationBookErrors.NewType("invalid_mod_action")
	ErrInvalidModerationAction_NoReason = InvalidModerationActionError.New("no reason provided")
	ModerationBookNotFoundError         = ModerationBookErrors.NewType("book_404", apperror.ErrTraitEntityNotFound)
)
View Source
var (
	ErrInvalidReportDisposition = apperror.AppErrors.NewType("invalid_report_disposition").New("invalid report disposition")
	ErrReportAlreadyResolved    = apperror.AppErrors.NewType("report_already_resolved").New("report is already resolved")
	ErrReportPolicyReason       = apperror.AppErrors.NewType("report_policy_reason_required").New("a policy reason is required")
	ErrReportInternalNote       = apperror.AppErrors.NewType("report_internal_note_too_long").New("internal note must not exceed 1000 characters")
)
View Source
var (
	ReadingListErrors            = apperror.AppErrors.NewSubNamespace("reading_list")
	ReadingListInvalidTransition = ReadingListErrors.NewType("invalid_transition")
	ErrReadingListEmptyBook      = ReadingListInvalidTransition.NewSubtype("empty_book").New("cannot update reading list for empty book")
	ReadingListChapterNotFound   = ReadingListErrors.NewType("chapter404")
)
View Source
var (
	ErrInvalidReportTarget = apperror.AppErrors.NewType("invalid_report_target").New("report target must be a user, book, or comment")
	ErrReportReason        = apperror.AppErrors.NewType("report_reason_required").New("a report reason is required")
	ErrReportTargetMissing = apperror.AppErrors.NewType("report_target_not_found", apperror.ErrTraitEntityNotFound).New("report target not found")
	ErrReportNotFound      = apperror.AppErrors.NewType("report_not_found", apperror.ErrTraitEntityNotFound).New("report not found")
)
View Source
var (
	SignUpErrors                       = apperror.AppErrors.NewSubNamespace("signup")
	SignUpInvalidInput                 = SignUpErrors.NewType("invalid")
	SignUpEmailVerificationErrors      = SignUpErrors.NewSubNamespace("email_verification")
	SignUpEmailVerificationNA          = SignUpEmailVerificationErrors.NewType("na")
	SignUpEmailVerificationRateLimit   = SignUpEmailVerificationErrors.NewType("rate_limit")
	SignUpEmailVerificationTimedOut    = SignUpEmailVerificationErrors.NewType("timedout")
	SignUpEmailVerificationInvalidCode = SignUpEmailVerificationErrors.NewType("invalid_code")
)
View Source
var (
	RoleUser      = UserRole("user")
	RoleAdmin     = UserRole("admin")
	RoleSystem    = UserRole("system")
	RoleModerator = UserRole("moderator")

	AllRoles = []UserRole{
		RoleUser,
		RoleAdmin,
		RoleSystem,
		RoleModerator,
	}
)
View Source
var (
	ErrUserNotFound    = apperror.AppErrors.NewType("user_not_found", apperror.ErrTraitEntityNotFound).New("user not found")
	ErrFollowYourself  = apperror.AppErrors.NewType("follow_yourself").New("you can't follow yourself")
	ErrInvalidUserRole = apperror.AppErrors.NewType("invalid_user_role").New("invalid user role")
	ErrUserNameInvalid = apperror.AppErrors.NewType("invalid_username")
	ErrEmailInvalid    = apperror.AppErrors.NewType("invalid_email")
)
View Source
var (
	ErrUserDataKeyNotAllowed = errors.New("user data key is not allowed")
	ErrUserDataTooLarge      = errors.New("user data exceeds the 20KB size limit")
)
View Source
var (
	DefaultPaginationRestrictions = PaginationRestrictions{
		MaxPageSize:  100,
		MaxPageCount: 1000,
	}
)
View Source
var ErrInvalidReportAction = apperror.AppErrors.NewType("invalid_report_action").New("action is not valid for this report target")
View Source
var (
	ErrInvalidUploadURI = errors.New("invalid upload uri schema")
)
View Source
var (
	ErrSessionNotFound = apperror.AppErrors.NewType("session_not_found").New("session not found")
)
View Source
var (
	ErrTagNotFound = apperror.AppErrors.NewType("tag404", apperror.ErrTraitEntityNotFound).New("tag with this ID cannot be found")
)
View Source
var (
	GlobalFeatureFlags struct {
		DisableCache bool
	}
)
View Source
var (
	PasswordError = apperror.AppErrors.NewType("password")
)

Functions

func AppVersion

func AppVersion() string

func ArrInt64StringToInt64

func ArrInt64StringToInt64(v []Int64String) []int64

func GenID

func GenID() int64

func IsCommonPageSize

func IsCommonPageSize(pageSize int32) bool

func MapSlice

func MapSlice[T, U any](ts []T, f func(T) U) []U

func MoveItem

func MoveItem[T comparable](arr []T, item T, newPositionIndex int) (int, bool)

MoveItem moves an item in the list, returns new position of item and a boolean representing the successfullness of the operation (true if successful), if operation was unsuccessful then newPosition returned SHOULD be -1

func ValidateEmail

func ValidateEmail(email string) error

func ValidatePassword

func ValidatePassword(pwd string, r PasswordRequirements) error

func ValidateUserName

func ValidateUserName(value string) error

Types

type AddCommentCommand

type AddCommentCommand struct {
	UserID          uuid.UUID
	ChapterID       int64
	ParentCommentID Nullable[int64]
	Content         string
}

func (*AddCommentCommand) Validate

func (c *AddCommentCommand) Validate() error

type AddCommentResult

type AddCommentResult struct {
	Comment CommentDto
}

type AddToCollectionsCommand

type AddToCollectionsCommand struct {
	ActorUserID  uuid.UUID
	CollectionID []int64
	BookID       int64
}

type AgeRating

type AgeRating string

go2tsdef:generate

const (
	AgeRatingUnknown AgeRating = "?"
	AgeRatingG       AgeRating = "G"
	AgeRatingPG      AgeRating = "PG"
	AgeRatingPG13    AgeRating = "PG-13"
	AgeRatingR       AgeRating = "R"
	AgeRatingNC17    AgeRating = "NC-17"
)

func AsRating

func AsRating(v string) AgeRating

func (AgeRating) IsAdult

func (r AgeRating) IsAdult() bool

type AuthService

type AuthService interface {
	SignIn(ctx context.Context, input SignInCommand) (SignInResult, error)
	CreateSessionForUser(ctx context.Context, userID uuid.UUID, userAgent, ip string) (string, error)
	SignOut(ctx context.Context, sessionID string) error
	EnsureAdminUserExists(ctx context.Context) error
}

func NewAuthService

func NewAuthService(db DB, sessions SessionService) AuthService

type BanUserCommand

type BanUserCommand struct {
	ActorUserID, UserID uuid.UUID
	Until               time.Time
	Reason              string
}

type BookActionType

type BookActionType string
const (
	BookActionTypeBan         BookActionType = "ban"
	BookActionTypeShadowBan   BookActionType = "shadow_ban"
	BookActionTypePermRemoval BookActionType = "perm_removal"
	BookActionTypeUnBan       BookActionType = "un_ban"
	BookActionTypeUnShadowBan BookActionType = "un_shadow_ban"
)

type BookAdultWarning

type BookAdultWarning struct {
	IsBookAdult bool
	HasAdultTag bool
}

func (BookAdultWarning) ShouldShowWarning

func (w BookAdultWarning) ShouldShowWarning() bool

type BookBackgroundService

type BookBackgroundService interface {
	BookRecalculationIngest
	Start() error
	Stop()
}

func NewBookBackgroundService

func NewBookBackgroundService(db DB, lc fx.Lifecycle, log *zap.SugaredLogger) BookBackgroundService

func NewDummyBookBackgroundService

func NewDummyBookBackgroundService() BookBackgroundService

type BookCollectionDto

type BookCollectionDto struct {
	ID       int64  `json:"id,string"`
	Name     string `json:"name"`
	Position int    `json:"pos"`
	Size     int    `json:"size"`
}

go2tsdef:generate

type BookCover

type BookCover struct {
	URL string `json:"url"`
}

go2tsdef:generate

type BookDetailsAuthorDto

type BookDetailsAuthorDto struct {
	ID   uuid.UUID `json:"id"`
	Name string    `json:"name"`
}

go2tsdef:generate

type BookDetailsDto

type BookDetailsDto struct {
	ID                  int64                 `json:"id,string"`
	Name                string                `json:"name"`
	AgeRating           AgeRating             `json:"ageRating"`
	IsAdult             bool                  `json:"adult"`
	Tags                []DefinedTagDto       `json:"tags"`
	Words               int                   `json:"words"`
	WordsPerChapter     int                   `json:"wordsPerChapter"`
	CreatedAt           time.Time             `json:"createdAt"`
	Collections         []BookCollectionDto   `json:"collections"`
	Author              BookDetailsAuthorDto  `json:"author"`
	Permissions         BookUserPermissions   `json:"permissions"`
	Summary             string                `json:"summary"`
	Notifications       []GenericNotification `json:"notifications,omitempty"`
	Cover               BookCover             `json:"cover"`
	Rating              Nullable[float64]     `json:"rating"`
	Votes               int32                 `json:"votes"`
	Reviews             int32                 `json:"reviews"`
	IsPubliclyAvailable bool                  `json:"isPubliclyAvailable"`
	Slug                string                `json:"slug"`
	FirstChapterID      Nullable[int64]       `json:"firstChapterId"`
}

func (BookDetailsDto) GetAdultWarning

func (d BookDetailsDto) GetAdultWarning() (warnData BookAdultWarning)

type BookExtremes

type BookExtremes struct {
	Words           Int32Range `json:"words"`
	Chapters        Int32Range `json:"chapters"`
	WordsPerChapter Int32Range `json:"wordsPerChapter"`
	Favorites       Int32Range `json:"favorites"`
}

type BookLibraryDto

type BookLibraryDto struct {
	ID          int64                                       `json:"id,string"`
	Name        string                                      `json:"name"`
	Cover       BookCover                                   `json:"cover"`
	AgeRating   AgeRating                                   `json:"ageRating"`
	LastChapter Nullable[BookReadingListItemLastChapterDto] `json:"lastChapter"`
}

type BookListDto

type BookListDto struct {
	ID              int64                `json:"id,string"`
	Slug            string               `json:"slug"`
	Name            string               `json:"name"`
	Author          BookDetailsAuthorDto `json:"-"`
	CreatedAt       time.Time            `json:"createdAt"`
	AgeRating       AgeRating            `json:"ageRating"`
	Words           int                  `json:"words"`
	WordsPerChapter int                  `json:"wordsPerChapter"`
	Chapters        int                  `json:"chapters"`
	Cover           BookCover            `json:"cover"`
	IsPinned        bool                 `json:"isPinned"`
}

type BookLogResult

type BookLogResult struct {
	Entries         []BookModerationLog
	Page            int32
	PageSize        int32
	HasNextPage     bool
	HasPreviousPage bool
	TotalPages      uint32
}

type BookManagerService

type BookManagerService interface {
	GetUserBooks(ctx context.Context, input ManagerGetUserBooksQuery) (ManagerGetUserBooksQuery_Result, error)
	GetBook(ctx context.Context, query ManagerGetBookQuery) (ManagerGetBookQuery_Result, error)
	CreateBook(ctx context.Context, input CreateBookCommand) (int64, error)
	UpdateBook(ctx context.Context, input UpdateBookCommand) error
	UploadBookCover(ctx context.Context, input UploadBookCoverCommand) (UploadBookCoverCommand_Result, error)
	TrashBook(ctx context.Context, input TrashBookCommand) error
	UntrashBook(ctx context.Context, input UntrashBookCommand) error

	UpdateBookChaptersOrder(ctx context.Context, input UpdateBookChapterOrdersCommand) (UpdateBookChapterOrdersCommand_Result, error)
	CreateBookChapter(ctx context.Context, input CreateBookChapterCommand) (CreateBookChapterCommand_Result, error)
	ReorderChapters(ctx context.Context, input ReorderChaptersCommand) error
	GetBookChapters(ctx context.Context, query ManagerGetBookChaptersQuery) (ManagerGetBookChaptersQuery_Result, error)
	GetChapter(ctx context.Context, query ManagerGetChapterQuery) (ManagerGetChapterQuery_Result, error)
	UpdateBookChapter(ctx context.Context, cmd UpdateBookChapterCommand) error

	GetDraft(ctx context.Context, query GetDraftQuery) (DraftDto, error)
	UpdateDraft(ctx context.Context, cmd UpdateDraftCommand) error
	UpdateDraftChapterName(ctx context.Context, cmd UpdateDraftChapterNameCommand) error
	UpdateDraftContent(ctx context.Context, cmd UpdateDraftContentCommand) error
	DeleteDraft(ctx context.Context, cmd DeleteDraftCommand) error
	PublishDraft(ctx context.Context, cmd PublishDraftCommand) error
	ScheduleDraft(ctx context.Context, cmd ScheduleDraftCommand) error
	CreateDraft(ctx context.Context, cmd CreateDraftCommand) (int64, error)
	GetLatestDraft(ctx context.Context, cmd GetLatestDraftQuery) (Nullable[int64], error)
}

func NewBookManagerService

func NewBookManagerService(deps BookManagerServiceDeps, db dal.DB) BookManagerService

type BookManagerServiceDeps

type BookManagerServiceDeps struct {
	fx.In

	DB                 DB
	TagsService        TagsService
	UsersService       UserService
	UploadService      *UploadService
	BookReindexService BookReindexService
	MetricService      analytics.MetricService
	Log                *zap.SugaredLogger
	Markup             *content.MarkupEngine
	FontPolicy         bookfont.Policy
}

type BookModerationChapter

type BookModerationChapter struct {
	ID                                   int64
	Name                                 string
	CreatedAt                            time.Time
	UpdatedAt                            *time.Time
	Words                                int32
	IsPubliclyVisible, HasPendingReports bool
}

type BookModerationInfo

type BookModerationInfo struct {
	ID                  int64
	Name                string
	Summary             string
	IsBanned            bool
	IsShadowBanned      bool
	IsPermDeleted       bool
	AuthorUserID        uuid.UUID
	AuthorUserName      string
	CreatedAt           time.Time
	AgeRating           string
	IsPubliclyVisible   bool
	Words               int32
	Chapters            int32
	ReportsCount        int64
	LatestPendingReport *BookPendingReport
	BanReason           string
}

type BookModerationLog

type BookModerationLog struct {
	Time          time.Time
	Action        BookActionType
	Payload       json.RawMessage
	Reason        string
	ActorUserID   uuid.UUID
	ActorUserName string
}

type BookPendingReport

type BookPendingReport struct {
	ID             int64
	Number, Reason string
	Time           time.Time
}

type BookReadingListDto

type BookReadingListDto struct {
	Status        ReadingListStatus     `json:"status"`
	ChapterID     Nullable[Int64String] `json:"chapterId"`
	ChapterName   string                `json:"chapterName"`
	ChapterOrder  int32                 `json:"chapterOrder"`
	LastUpdatedAt time.Time             `json:"lastUpdatedAt"`
}

go2tsdef:generate

type BookReadingListItemLastChapterDto

type BookReadingListItemLastChapterDto struct {
	ID    int64  `json:"id,string"`
	Name  string `json:"name"`
	Order int32  `json:"order"`
}

type BookRecalculationIngest

type BookRecalculationIngest interface {
	ScheduleBookRecalculation(bookID int64)
}

type BookReindexService

type BookReindexService interface {
	Reindex(ctx context.Context, id int64) error
	ScheduleReindex(ctx context.Context, id int64)
	ScheduleReindexAll() error
}

func NewBookFullReindexService

func NewBookFullReindexService(db store.DBTX, osClient *opensearchapi.Client, log *zap.SugaredLogger) BookReindexService

func NewDummyBookReindexService

func NewDummyBookReindexService() BookReindexService

type BookReviewsDistribution

type BookReviewsDistribution [10]int32

type BookSearchItem

type BookSearchItem struct {
	ID              int64                `json:"id,string"`
	Name            string               `json:"name"`
	Slug            string               `json:"slug"`
	CreatedAt       time.Time            `json:"createdAt"`
	AgeRating       AgeRating            `json:"ageRating"`
	Words           int                  `json:"words"`
	WordsPerChapter int                  `json:"wordsPerChapter"`
	Chapters        int                  `json:"chapters"`
	Summary         string               `json:"summary"`
	Author          BookDetailsAuthorDto `json:"author"`
	Cover           BookCover            `json:"cover"`
	Tags            []Int64String        `json:"tags"`
	Collections     []BookCollectionDto  `json:"collections"`
}

type BookSearchQuery

type BookSearchQuery struct {
	UserID uuid.NullUUID

	Query string
	Sort  BookSearchSort

	Words           Int32Range
	Chapters        Int32Range
	WordsPerChapter Int32Range

	IncludeTags  []int64
	ExcludeTags  []int64
	IncludeUsers []uuid.UUID
	ExcludeUsers []uuid.UUID

	IncludeBanned bool
	IncludeHidden bool
	IncludeEmpty  bool

	Page     uint32
	PageSize uint
}

type BookSearchResult

type BookSearchResult struct {
	TookUSTotal int64
	TookUS      int64
	Meta        BookSearchResultMeta
	Books       []BookSearchItem
	PageSize    uint32
	Page        uint32
	TotalPages  uint32
	Total       int64
	Tags        []DefinedTagDto
}

type BookSearchResultMeta

type BookSearchResultMeta struct {
	CacheKey    string `json:"cacheKey"`
	CacheHit    bool   `json:"cacheHit"`
	CacheTookUS int64  `json:"cacheTook"`
}

type BookSearchSort

type BookSearchSort string
const (
	BookSearchSortRelevance       BookSearchSort = ""
	BookSearchSortChapters        BookSearchSort = "chapters"
	BookSearchSortWords           BookSearchSort = "words"
	BookSearchSortWordsPerChapter BookSearchSort = "words-per-chapter"
	BookSearchSortLastUpdated     BookSearchSort = "last-updated"
	BookSearchSortCreatedAt       BookSearchSort = "created-at"
	BookSearchSortReviews         BookSearchSort = "reviews"
	BookSearchSortReaders         BookSearchSort = "readers"
	BookSearchSortWeightedRating  BookSearchSort = "weighted-rating"
	BookSearchSortRandom          BookSearchSort = "random"
)

func ParseBookSearchSort

func ParseBookSearchSort(value string) BookSearchSort

func (BookSearchSort) IsImplemented

func (s BookSearchSort) IsImplemented() bool

type BookService

type BookService interface {
	GetBookDetails(ctx context.Context, query GetBookQuery) (BookDetailsDto, error)
	GetBookChapters(ctx context.Context, query GetBookChaptersQuery) ([]ChapterListDto, error)
	GetBookChapter(ctx context.Context, query GetBookChapterQuery) (GetBookChapterResult, error)
	GetRandomBookID(ctx context.Context) (Nullable[int64], error)
	GetPinnedBooks(ctx context.Context, input GetPinnedUserBooksQuery) (GetPinnedUserBooksResult, error)
	GetBooksById(ctx context.Context, ids []int64) ([]BookListDto, error)
}

func NewBookService

func NewBookService(
	db store.DBTX,
	tagsService TagsService,
	uploadService *UploadService,
	readingListService ReadingListService,
	reviewService ReviewsService,
	log *zap.SugaredLogger,
) BookService

type BookTags

type BookTags struct {
	ParentTagIds []int64
	TagIds       []int64
}

type BookUserPermissions

type BookUserPermissions struct {
	CanEdit bool `json:"canEdit"`
}

type CaptchaSettings

type CaptchaSettings struct {
	GoogleRecaptchaKey string
	Type               string
}

type CensorMode

type CensorMode store.CensorMode

type ChapterDto

type ChapterDto struct {
	ID            int64                        `json:"id,string"`
	Name          string                       `json:"name"`
	Words         int32                        `json:"words"`
	Content       string                       `json:"content"`
	CreatedAt     time.Time                    `json:"createdAt"`
	Order         int32                        `json:"order"`
	Summary       string                       `json:"summary"`
	NextChapter   Nullable[ChapterNextPrevDto] `json:"nextChapter"`
	PrevChapter   Nullable[ChapterNextPrevDto] `json:"prevChapter"`
	BookID        int64                        `json:"bookId"`
	CommentsCount int64                        `json:"commentsCount"`
	Fonts         []string                     `json:"fonts"`
}

type ChapterListDto

type ChapterListDto struct {
	ID        int64     `json:"id,string"`
	Order     int       `json:"order"`
	Name      string    `json:"name"`
	Words     int       `json:"words"`
	CreatedAt time.Time `json:"createdAt"`
	Summary   string    `json:"summary"`
}

type ChapterNextPrevDto

type ChapterNextPrevDto struct {
	ID    int64  `json:"id,string"`
	Name  string `json:"name"`
	Order int32  `json:"order"`
}

type ChapterOrderModification

type ChapterOrderModification struct {
	ChapterID        int64
	NewPositionIndex int
}

type CollectionBook2Dto

type CollectionBook2Dto struct {
	ID         int64
	Name       string
	Slug       string
	Summary    string
	AuthorName string
	AuthorID   uuid.UUID
	Cover      BookCover
	Tags       []DefinedTagDto
}

type CollectionBookDto

type CollectionBookDto struct {
	ID    int64
	Name  string
	Cover BookCover
}

type CollectionDto

type CollectionDto struct {
	ID            int64
	Name          string
	Slug          string
	BooksCount    int
	LastUpdatedAt Nullable[time.Time]
	UserID        uuid.UUID
	UserName      string
	IsPublic      bool
	Summary       string
}

go2tsdef:generate

type CollectionService

type CollectionService interface {
	GetUserCollections(ctx context.Context, query GetUserCollectionsQuery) (GetUserCollectionsResult, error)
	GetRecentUserCollections(ctx context.Context, query GetRecentCollectionsQuery) ([]CollectionDto, error)
	CreateCollection(ctx context.Context, cmd CreateCollectionCommand) (int64, error)
	UpdateCollection(ctx context.Context, cmd UpdateCollectionCommand) error
	AddToCollections(ctx context.Context, cmd AddToCollectionsCommand) error
	RemoveFromCollection(ctx context.Context, cmd RemoveFromCollectionCommand) error
	GetBookCollections(ctx context.Context, query GetBookCollectionsQuery) ([]CollectionDto, error)

	GetCollectionBooks(ctx context.Context, query GetCollectionBooksQuery) (GetCollectionBooksResult, error)
	GetCollectionBooksMap(ctx context.Context, collections []CollectionDto) (map[int64][]CollectionBookDto, error)
	GetCollection(ctx context.Context, id int64) (Nullable[CollectionDto], error)
	DeleteCollection(ctx context.Context, cmd DeleteCollectionCommand) error
}

func NewCollectionsService

func NewCollectionsService(db DB, tagsService TagsService, uploadService *UploadService, log *zap.SugaredLogger) CollectionService

type CommentDto

type CommentDto struct {
	ID             int64               `json:"id,string"`
	Content        string              `json:"content"`
	User           CommentUserDto      `json:"user"`
	CreatedAt      time.Time           `json:"createdAt"`
	UpdatedAt      Nullable[time.Time] `json:"updatedAt"`
	LikedAt        Nullable[time.Time] `json:"likedAt"`
	Likes          int64               `json:"likes"`
	LikesUpdatedAt time.Time           `json:"likesUpdatedAt"`
	Subcomments    int                 `json:"subcomments"`
	Deleted        bool                `json:"deleted"`
}

go2tsdef:generate

func (CommentDto) RealLikesCount

func (c CommentDto) RealLikesCount() int64

type CommentSort

type CommentSort string
const (
	CommentSortNewest  CommentSort = "newest"
	CommentSortOldest  CommentSort = "oldest"
	CommentSortPopular CommentSort = "popular"
)

func ParseCommentSort

func ParseCommentSort(value string) CommentSort

type CommentUserDto

type CommentUserDto struct {
	ID     uuid.UUID `json:"id"`
	Name   string    `json:"name"`
	Avatar string    `json:"avatar"`
}

go2tsdef:generate

type CommentsService

type CommentsService interface {
	GetList(ctx context.Context, query GetCommentsQuery) (GetCommentsResult, error)
	GetReplies(ctx context.Context, query GetCommentRepliesQuery) (GetCommentRepliesResult, error)

	AddComment(ctx context.Context, command AddCommentCommand) (AddCommentResult, error)
	UpdateComment(ctx context.Context, command UpdateCommentCommand) (UpdateCommentResult, error)
	LikeComment(ctx context.Context, command LikeCommentCommand) (bool, error)
}

func NewCommentsService

func NewCommentsService(db store.DBTX) CommentsService

type ContentModerationRepository

type ContentModerationRepository interface {
	SetChapterVisibilityAndLog(ctx context.Context, chapterID int64, visible bool, log ModerationAuditEntry) error
	SetCommentRemovedAndLog(ctx context.Context, commentID int64, removed bool, log ModerationAuditEntry) error
	SetUserBanAndLog(ctx context.Context, userID uuid.UUID, expiresAt time.Time, banned bool, log ModerationAuditEntry) error
	RenameUserAndLog(ctx context.Context, userID uuid.UUID, name string, log ModerationAuditEntry) error
	ChangeUserAboutAndLog(ctx context.Context, userID uuid.UUID, about string, log ModerationAuditEntry) error
}

ContentModerationRepository is the persistence port for application-level moderation. Every mutation must update its target and append its audit entry atomically in the generalized moderation log.

func NewContentModerationRepository

func NewContentModerationRepository(db DB) ContentModerationRepository

type ContentRestrictions

type ContentRestrictions struct {
	// if true - whole website is considered "adult"
	AdultWebsite bool
}

type CreateBookChapterCommand

type CreateBookChapterCommand struct {
	BookID            int64
	Name              string
	Content           string
	Summary           string
	UserID            uuid.UUID
	IsPubliclyVisible bool
}

type CreateBookChapterCommand_Result

type CreateBookChapterCommand_Result struct {
	ID int64
}

type CreateBookCommand

type CreateBookCommand struct {
	Name              string
	UserID            uuid.UUID
	AgeRating         AgeRating
	Tags              []int64
	Summary           string
	IsPubliclyVisible bool
}

type CreateCollectionCommand

type CreateCollectionCommand struct {
	Name        string
	Description string
	UserID      uuid.UUID
}

type CreateDraftCommand

type CreateDraftCommand struct {
	BookID    int64
	ChapterID int64
	UserID    uuid.UUID
}

type CreateReportCommand

type CreateReportCommand struct {
	ReporterUserID uuid.UUID
	TargetType     ReportTargetType
	TargetID       string
	Reason         string
	Description    string
	BookChapterID  Nullable[int64]
	BookExcerpt    string
}

type CreateSessionCommand

type CreateSessionCommand struct {
	UserID    uuid.UUID
	UserAgent string
	IpAddress string
	ExpiresAt time.Time
}

type CreateTagsCommand

type CreateTagsCommand struct {
	Tags []TagDescriptor
}

type DB deprecated

type DB dal.DB

Deprecated: use dal.DB instead

type DecideModerationReportCommand

type DecideModerationReportCommand struct {
	ActorUserID  uuid.UUID
	ReportID     int64
	Disposition  string
	Action       string
	PolicyReason string
	InternalNote string
	NotifyTarget bool
	Payload      json.RawMessage
}

type DefinedTagDto

type DefinedTagDto struct {
	ID          int64        `json:"id,string"`
	Name        string       `json:"name"`
	Description string       `json:"desc"`
	IsAdult     bool         `json:"adult"`
	IsSpoiler   bool         `json:"spoiler"`
	Category    TagsCategory `json:"cat"`
}

go2tsdef:generate

type DeleteCollectionCommand

type DeleteCollectionCommand struct {
	ActorUserID  uuid.UUID
	CollectionID int64
}

type DeleteDraftCommand

type DeleteDraftCommand struct {
	DraftID int64
	UserID  uuid.UUID
}

type DeleteReviewCommand

type DeleteReviewCommand struct {
	UserID uuid.UUID
	BookID int64
}

type DetailedBookSearchQuery

type DetailedBookSearchQuery struct {
	Query string         `json:"query"`
	Sort  BookSearchSort `json:"sort"`

	Words           Int32Range `json:"words"`
	Chapters        Int32Range `json:"chapters"`
	WordsPerChapter Int32Range `json:"wordsPerChapter"`

	IncludeTags  []DefinedTagDto            `json:"includeTags"`
	ExcludeTags  []DefinedTagDto            `json:"excludeTags"`
	IncludeUsers []UserFromSearchRequestDto `json:"includeUsers"`
	ExcludeUsers []UserFromSearchRequestDto `json:"excludeUsers"`

	IncludeBanned bool `json:"includeBanned"`
	IncludeHidden bool `json:"includeHidden"`
	IncludeEmpty  bool `json:"includeEmpty"`

	Page     uint32 `json:"page"`
	PageSize uint   `json:"pageSize"`
}

func (*DetailedBookSearchQuery) ActiveFilters

func (d *DetailedBookSearchQuery) ActiveFilters() int

type DraftDto

type DraftDto struct {
	ID          int64               `json:"id,string"`
	ChapterName string              `json:"chapterName"`
	Content     string              `json:"content"`
	CreatedAt   time.Time           `json:"createdAt"`
	UpdatedAt   Nullable[time.Time] `json:"updatedAt"`
	ScheduledAt Nullable[time.Time] `json:"scheduledAt"`
	CreatedBy   struct {
		ID   uuid.UUID `json:"id"`
		Name string    `json:"name"`
	} `json:"createdBy"`
	Book struct {
		ID   int64  `json:"id,string"`
		Name string `json:"name"`
	} `json:"book"`
	Chapter struct {
		ID               int64     `json:"id,string"`
		ContentUpdatedAt time.Time `json:"contentUpdatedAt"`
		Fonts            []string  `json:"fonts"`
	} `json:"chapter"`
	IsChapterPubliclyAvailable bool `json:"isChapterPubliclyAvailable"`
}

go2tsdef:generate

type DraftPublishingService

type DraftPublishingService struct {
	// contains filtered or unexported fields
}

func NewDraftPublishingService

func NewDraftPublishingService(
	db DB,
	reindex BookReindexService,
	lifecycle fx.Lifecycle,
	log *zap.SugaredLogger,
) *DraftPublishingService

type EmailVerificationStatus

type EmailVerificationStatus struct {
	CanSendAgainAfter Nullable[time.Time]
	WasSent           bool
}

type FollowUserCommand

type FollowUserCommand struct {
	UserID   uuid.UUID
	Follower uuid.UUID
}

type GenericNotification

type GenericNotification struct {
	ID   string `json:"id"`
	Text string `json:"text"`
}

type GetBookChapterQuery

type GetBookChapterQuery struct {
	BookID      int64
	ChapterID   int64
	ActorUserID uuid.NullUUID
}

type GetBookChapterResult

type GetBookChapterResult struct {
	Chapter ChapterDto
}

type GetBookChaptersQuery

type GetBookChaptersQuery struct {
	ID int64
}

type GetBookCollectionsQuery

type GetBookCollectionsQuery struct {
	ActorUserID uuid.UUID
	BookID      int64
}

type GetBookDraftsQuery

type GetBookDraftsQuery struct {
	Page int
}

type GetBookInfoQuery

type GetBookInfoQuery struct {
	ActorUserID uuid.UUID
	BookID      int64
}

type GetBookLogQuery

type GetBookLogQuery struct {
	Page        uint32
	PageSize    uint32
	OfTypes     []BookActionType
	BookID      int64
	ActorUserID uuid.UUID
}

type GetBookQuery

type GetBookQuery struct {
	ID          int64
	ActorUserID uuid.NullUUID
}

type GetBookReviewsDistributionResult

type GetBookReviewsDistributionResult struct {
	Distribution BookReviewsDistribution
}

type GetBookReviewsQuery

type GetBookReviewsQuery struct {
	BookID   int64
	PageSize int32
	Page     int32
}

type GetBookReviewsResult

type GetBookReviewsResult struct {
	Reviews    []ReviewDto
	Pagination PaginationOptions
}

type GetCollectionBooksQuery

type GetCollectionBooksQuery struct {
	CollectionID int64
	Page         int32
	PageSize     int32
}

type GetCollectionBooksResult

type GetCollectionBooksResult struct {
	Books      []CollectionBook2Dto
	Page       int32
	TotalPages int32
	PageSize   int32
}

type GetCommentRepliesQuery

type GetCommentRepliesQuery struct {
	ActorUserID uuid.NullUUID
	Limit       int32
	Cursor      uint32
	CommentID   int64
}

type GetCommentRepliesResult

type GetCommentRepliesResult struct {
	Cursor     uint32       `json:"cursor"`
	NextCursor uint32       `json:"nextCursor"`
	Comments   []CommentDto `json:"comments"`
}

type GetCommentsQuery

type GetCommentsQuery struct {
	ActorUserID uuid.NullUUID
	Limit       int32
	Cursor      uint32
	ChapterID   int64
	Sort        CommentSort
}

type GetCommentsResult

type GetCommentsResult struct {
	Cursor     uint32
	NextCursor uint32
	Comments   []CommentDto
	Total      int64
}

type GetDraftQuery

type GetDraftQuery struct {
	UserID    uuid.UUID
	DraftID   int64
	ChapterID int64
	BookID    int64
}

type GetLatestDraftQuery

type GetLatestDraftQuery struct {
	BookID    int64
	ChapterID int64
	UserID    uuid.UUID
}

type GetLoginHistoryQuery

type GetLoginHistoryQuery struct {
	ActorUserID, UserID uuid.UUID
	UserIDs             []uuid.UUID
	Search, Status      string
	DateFrom, DateTo    Nullable[time.Time]
	Page, PageSize      uint32
}

type GetModerationReportQuery

type GetModerationReportQuery struct {
	ActorUserID uuid.UUID
	ReportID    int64
}

type GetModerationUserQuery

type GetModerationUserQuery struct {
	ActorUserID uuid.UUID
	UserID      uuid.UUID
}

type GetPinnedUserBooksQuery

type GetPinnedUserBooksQuery struct {
	UserID uuid.UUID
	Limit  int
	Offset int
}

type GetPinnedUserBooksResult

type GetPinnedUserBooksResult struct {
	Books   []BookListDto `json:"books"`
	HasMore bool          `json:"hasMore"`
}

type GetReadingListItemsQuery

type GetReadingListItemsQuery struct {
	UserID uuid.UUID
	Limit  uint32
	Status ReadingListStatus
}

type GetRecentCollectionsQuery

type GetRecentCollectionsQuery struct {
	UserID uuid.UUID
	Limit  int32
}

type GetReviewQuery

type GetReviewQuery struct {
	UserID uuid.UUID
	BookID int64
}

type GetUserCollectionsQuery

type GetUserCollectionsQuery struct {
	UserID   uuid.UUID
	Page     int32
	PageSize int32
}

type GetUserCollectionsResult

type GetUserCollectionsResult struct {
	Collections []CollectionDto
	TotalPages  int32
	Page        int32
}

type GetUserDataQuery

type GetUserDataQuery struct {
	UserID          uuid.UUID
	Key             string
	IgnoreWhitelist bool
}

type GetUserQuery

type GetUserQuery struct {
	ID     uuid.UUID
	UserID uuid.NullUUID
}

type IPLocation

type IPLocation struct {
	Country string `json:"country"`
	Region  string `json:"region"`
	City    string `json:"city"`
}

type IPLocationService

type IPLocationService interface {
	Locate(context.Context, string) (IPLocation, error)
}

func NewIPLocationService

func NewIPLocationService() IPLocationService

type Int32

type Int32 struct {
	Valid bool
	Int32 int32
}

func Int32FromPtr

func Int32FromPtr(i *int32) Int32

func (Int32) MarshalJSON

func (i Int32) MarshalJSON() ([]byte, error)

func (Int32) Ptr

func (i Int32) Ptr() *int32

func (*Int32) UnmarshalJSON

func (i *Int32) UnmarshalJSON(b []byte) error

type Int32Range

type Int32Range struct {
	Min Int32 `json:"min"`
	Max Int32 `json:"max"`
}

type Int64String

type Int64String int64

go2tsdef:generate go2tsdef:override_type string

func (Int64String) MarshalJSON

func (i Int64String) MarshalJSON() ([]byte, error)

func (*Int64String) UnmarshalJSON

func (i *Int64String) UnmarshalJSON(b []byte) error

type LikeCommentCommand

type LikeCommentCommand struct {
	CommentID int64
	UserID    uuid.UUID
	Like      bool
}

type ListTagsQuery

type ListTagsQuery struct {
	SearchQuery    string
	Page           uint32
	PageSize       uint32
	OnlyParentTags bool
	OnlyAdultTags  bool
	Category       Nullable[TagsCategory]
}

type ListTagsResult

type ListTagsResult struct {
	Tags       []TagDetailsItemDto
	Page       uint32
	TotalPages uint32
	TotalCount uint32
}

type LoginHistoryEntry

type LoginHistoryEntry struct {
	ID                   int64
	UserID               uuid.UUID
	UserName             string
	IPAddress, UserAgent string
	Location             IPLocation
	LoggedInAt           time.Time
	IsTerminated         bool
	ExpiresAt            time.Time
}

type LoginHistoryRepository

type LoginHistoryRepository interface {
	Search(context.Context, GetLoginHistoryQuery, int32, int32) ([]LoginHistoryEntry, int64, error)
	RecentLocations(context.Context, uuid.UUID) ([]LoginLocation, error)
}

func NewLoginHistoryRepository

func NewLoginHistoryRepository(db DB) LoginHistoryRepository

type LoginHistoryService

type LoginHistoryService interface {
	GetUserLoginHistory(context.Context, GetLoginHistoryQuery) (ModerationPage[LoginHistoryEntry], error)
	GetRecentLoginLocations(context.Context, GetLoginHistoryQuery) ([]LoginLocation, error)
}

type LoginLocation

type LoginLocation struct {
	IPLocation
	LastSeenAt time.Time
}

type ManagerBookChapterDetailsDto

type ManagerBookChapterDetailsDto struct {
	ID                int64     `json:"id,string"`
	Name              string    `json:"name"`
	CreatedAt         time.Time `json:"createdAt"`
	Words             int       `json:"words"`
	Summary           string    `json:"summary"`
	Order             int32     `json:"order"`
	Content           string    `json:"content"`
	IsPubliclyVisible bool      `json:"isPubliclyVisible"`
	Fonts             []string  `json:"fonts"`
}

type ManagerBookChapterDto

type ManagerBookChapterDto struct {
	ID                int64                 `json:"id,string"`
	Name              string                `json:"name"`
	CreatedAt         time.Time             `json:"createdAt"`
	Words             int                   `json:"words"`
	Summary           string                `json:"summary"`
	Order             int32                 `json:"order"`
	IsPubliclyVisible bool                  `json:"isPubliclyVisible"`
	DraftID           Nullable[Int64String] `json:"draftId"`
	ScheduledAt       Nullable[time.Time]   `json:"scheduledAt"`
}

go2tsdef:generate

type ManagerBookDetailsDto

type ManagerBookDetailsDto struct {
	ID                int64                   `json:"id,string"`
	Name              string                  `json:"name"`
	AgeRating         AgeRating               `json:"ageRating"`
	IsAdult           bool                    `json:"adult"`
	Tags              []DefinedTagDto         `json:"tags"`
	Words             int                     `json:"words"`
	WordsPerChapter   int                     `json:"wordsPerChapter"`
	CreatedAt         time.Time               `json:"createdAt"`
	Collections       []BookCollectionDto     `json:"collections"`
	Chapters          []ManagerBookChapterDto `json:"chapters"`
	Author            BookDetailsAuthorDto    `json:"author"`
	Summary           string                  `json:"summary"`
	IsPubliclyVisible bool                    `json:"isPubliclyVisible"`
	IsBanned          bool                    `json:"isBanned"`
	Cover             BookCover               `json:"cover"`
}

go2tsdef:generate

type ManagerBookDto

type ManagerBookDto struct {
	ID                int64                `json:"id,string"`
	Slug              string               `json:"slug"`
	Name              string               `json:"name"`
	CreatedAt         time.Time            `json:"createdAt"`
	AgeRating         AgeRating            `json:"ageRating"`
	Tags              []DefinedTagDto      `json:"tags"`
	Words             int                  `json:"words"`
	WordsPerChapter   int                  `json:"wordsPerChapter"`
	Chapters          int                  `json:"chapters"`
	Collections       []BookCollectionDto  `json:"collections"`
	IsPubliclyVisible bool                 `json:"isPubliclyVisible"`
	IsBanned          bool                 `json:"isBanned"`
	IsTrashed         bool                 `json:"isTrashed"`
	Summary           string               `json:"summary"`
	Cover             BookCover            `json:"cover"`
	Stats             ManagerBookDto_Stats `json:"stats"`
}

go2tsdef:generate

type ManagerBookDto_Stats

type ManagerBookDto_Stats struct {
	Views   analytics.MetricValues `json:"views"`
	Reviews int32                  `json:"reviews"`
	Ratings int32                  `json:"ratings"`
}

go2tsdef:generate

type ManagerGetBookChaptersQuery

type ManagerGetBookChaptersQuery struct {
	BookID int64
	UserID uuid.UUID
}

type ManagerGetBookChaptersQuery_Result

type ManagerGetBookChaptersQuery_Result struct {
	Chapters []ManagerBookChapterDto
}

type ManagerGetBookQuery

type ManagerGetBookQuery struct {
	ActorUserID uuid.UUID
	BookID      int64
}

type ManagerGetBookQuery_Result

type ManagerGetBookQuery_Result struct {
	Book ManagerBookDetailsDto
}

type ManagerGetChapterQuery

type ManagerGetChapterQuery struct {
	BookID    int64
	ChapterID int64
	UserID    uuid.UUID
}

type ManagerGetChapterQuery_Result

type ManagerGetChapterQuery_Result struct {
	Chapter ManagerBookChapterDetailsDto
}

type ManagerGetUserBooksQuery

type ManagerGetUserBooksQuery struct {
	UserID      uuid.UUID
	ActorUserID Nullable[uuid.UUID]
	Page        uint32
	PageSize    uint32
	SearchQuery string
}

type ManagerGetUserBooksQuery_Result

type ManagerGetUserBooksQuery_Result struct {
	Books      []ManagerBookDto
	TotalPages uint32
	PageSize   uint32
	Page       uint32
}

type MarkChapterCommand

type MarkChapterCommand struct {
	ChapterID int64
	UserID    uuid.UUID
}

type ModerateChapterCommand

type ModerateChapterCommand struct {
	ActorUserID uuid.UUID
	ChapterID   int64
	Reason      string
}

type ModerateCommentCommand

type ModerateCommentCommand struct {
	ActorUserID uuid.UUID
	CommentID   int64
	Reason      string
}

type ModerateUserProfileCommand

type ModerateUserProfileCommand struct {
	ActorUserID, UserID uuid.UUID
	Value, Reason       string
}

type ModerationAction

type ModerationAction string
const (
	ModerationActionHideChapter    ModerationAction = "hide_chapter"
	ModerationActionRestoreChapter ModerationAction = "restore_chapter"
	ModerationActionRemoveComment  ModerationAction = "remove_comment"
	ModerationActionRestoreComment ModerationAction = "restore_comment"
	ModerationActionBanUser        ModerationAction = "ban_user"
	ModerationActionUnbanUser      ModerationAction = "unban_user"
	ModerationActionRenameUser     ModerationAction = "rename_user"
	ModerationActionChangeAbout    ModerationAction = "change_user_about"
)

type ModerationAuditEntry

type ModerationAuditEntry struct {
	ID          int64
	Time        time.Time
	Action      ModerationAction
	ActorUserID uuid.UUID
	TargetType  string
	TargetID    string
	Reason      string
	Payload     []byte
}

type ModerationAuditLogEntry

type ModerationAuditLogEntry struct {
	ID                                                  int64
	Time                                                time.Time
	Action, TargetType, TargetID, Reason, ActorUserName string
	Payload                                             json.RawMessage
	ActorUserID                                         uuid.UUID
}

type ModerationAuditLogQuery

type ModerationAuditLogQuery struct {
	ActorUserID    uuid.UUID
	TargetType     string
	Page, PageSize uint32
}

type ModerationAuditLogService

type ModerationAuditLogService interface {
	GetAuditLog(context.Context, ModerationAuditLogQuery) (ModerationPage[ModerationAuditLogEntry], error)
}

func NewModerationAuditLogService

func NewModerationAuditLogService(db DB, auth ModerationAuthorizer) ModerationAuditLogService

type ModerationAuthorizer

type ModerationAuthorizer interface {
	AuthorizeModerator(ctx context.Context, actorUserID uuid.UUID) error
}

ModerationAuthorizer centralizes the role check shared by every moderation service. Keeping it in the application layer prevents controllers from being able to accidentally bypass authorization.

func NewModerationAuthorizer

func NewModerationAuthorizer(users UserService) ModerationAuthorizer

type ModerationBookListEntry

type ModerationBookListEntry struct {
	ID                                                                           int64
	Name                                                                         string
	CreatedAt                                                                    time.Time
	IsBanned, IsShadowBanned, IsTrashed, IsPermanentlyRemoved, IsPubliclyVisible bool
	Words, Chapters                                                              int32
	AuthorUserID                                                                 uuid.UUID
	AuthorUserName                                                               string
	ReportsCount                                                                 int64
}

type ModerationPage

type ModerationPage[T any] struct {
	Entries    []T
	Page       uint32
	PageSize   uint32
	Total      int64
	TotalPages uint32
}

type ModerationPerformBookActionCommand

type ModerationPerformBookActionCommand struct {
	Reason      string
	Value       string
	ActorUserID uuid.UUID
	BookID      int64
}

func (ModerationPerformBookActionCommand) Validate

type ModerationReportActivity

type ModerationReportActivity struct {
	Time        time.Time
	Actor       string
	Description string
	Kind        string
	Decision    *ReportDecision
}

type ModerationReportBookContext

type ModerationReportBookContext struct {
	Scope            string
	Title            string
	Author           string
	CoverURL         string
	Chapter          string
	Excerpt          string
	Rating           string
	Warnings         []string
	PublicationState string
	LastUpdated      time.Time
	RelatedReports   int
	EditedAfter      time.Duration
}

type ModerationReportBookContextData

type ModerationReportBookContextData struct {
	Title, Author, CoverID, Excerpt, Rating   string
	BookID                                    int64
	ChapterID                                 Nullable[int64]
	Chapter                                   Nullable[string]
	Warnings                                  []string
	IsPermanentlyRemoved, IsBanned, IsTrashed bool
	IsPubliclyVisible                         bool
	BookCreatedAt                             time.Time
	ChapterCreatedAt, ChapterUpdatedAt        Nullable[time.Time]
	ChapterContentUpdatedAt                   Nullable[time.Time]
	RelatedReports                            int
}

type ModerationReportCommentContextData

type ModerationReportCommentContextData struct {
	ID, ChapterID, BookID                      int64
	Content, AuthorName, ChapterName, BookName string
	AuthorID                                   uuid.UUID
	CreatedAt                                  time.Time
	UpdatedAt                                  Nullable[time.Time]
	DeletedAt                                  Nullable[time.Time]
	RelatedReports                             int
}

type ModerationReportDetail

type ModerationReportDetail struct {
	Report
	ReporterUserName string
	Status           string
	Priority         string
	Activities       []ModerationReportActivity
	BookContext      *ModerationReportBookContext
	UserContext      *ModerationReportUserContextData
	CommentContext   *ModerationReportCommentContextData
	AvailableActions []string
}

type ModerationReportListEntry

type ModerationReportListEntry struct {
	Report
	ReporterUserName string
}

type ModerationReportUserContextData

type ModerationReportUserContextData struct {
	ID                       uuid.UUID
	Name, Email, About, Role string
	JoinedAt                 time.Time
	IsBanned                 bool
	RelatedReports           int
}

type ModerationUserBook

type ModerationUserBook struct {
	ID                int64
	Name              string
	CreatedAt         time.Time
	IsPubliclyVisible bool
	IsBanned          bool
	IsTrashed         bool
}

type ModerationUserComment

type ModerationUserComment struct {
	ID, ChapterID, BookID          int64
	Content, ChapterName, BookName string
	CreatedAt                      time.Time
	Deleted                        bool
}

type ModerationUserHistoryEntry

type ModerationUserHistoryEntry struct {
	ID            int64
	Time          time.Time
	Type          string
	Reason        string
	Payload       json.RawMessage
	ActorUserID   uuid.UUID
	ActorUserName string
	TargetType    string
	TargetID      string
}

type ModerationUserInfo

type ModerationUserInfo struct {
	ID              uuid.UUID
	Name            string
	Email           string
	About           string
	Avatar          string
	JoinedAt        time.Time
	Role            UserRole
	IsBanned        bool
	IsEmailVerified bool
	BooksTotal      int64
	CommentsTotal   int64
	FollowersTotal  int64
}

type ModerationUserListEntry

type ModerationUserListEntry struct {
	ID          uuid.UUID
	Name        string
	Avatar      string
	JoinedAt    time.Time
	Role        UserRole
	IsBanned    bool
	LastVisitAt *time.Time
	BannedAt    *time.Time
	BanReason   string
}

type ModerationUserPageQuery

type ModerationUserPageQuery struct {
	ActorUserID uuid.UUID
	UserID      uuid.UUID
	Page        uint32
	PageSize    uint32
}

type ModerationUserReport

type ModerationUserReport struct {
	Number, TargetID, Reason, Description, ReporterUserName string
	ID                                                      int64
	Time                                                    time.Time
	TargetType                                              ReportTargetType
	ReporterUserID                                          uuid.UUID
}

type ModerationUsersQuery

type ModerationUsersQuery struct {
	ActorUserID uuid.UUID
	Search      string
	Banned      string
	Role        string
	Page        uint32
	PageSize    uint32
}

type NormalizedSearchRequest

type NormalizedSearchRequest struct {
	UserID uuid.NullUUID

	Words           Int32Range
	Chapters        Int32Range
	WordsPerChapter Int32Range
	Favorites       Int32Range

	IncludeTags  []int64
	ExcludeTags  []int64
	IncludeUsers []uuid.UUID
	ExcludeUsers []uuid.UUID

	IncludeBanned bool
	IncludeHidden bool
	IncludeEmpty  bool

	Limit  uint
	Offset uint
}

type Nullable

type Nullable[T any] struct {
	Value T
	Valid bool
}

func Null

func Null[T any]() Nullable[T]

func NullableFromPtr

func NullableFromPtr[T any](ptr *T) Nullable[T]

func Value

func Value[T any](v T) Nullable[T]

func (Nullable[T]) MarshalJSON

func (v Nullable[T]) MarshalJSON() ([]byte, error)

func (Nullable[T]) Or

func (v Nullable[T]) Or(vv T) T

func (Nullable[T]) Ptr

func (v Nullable[T]) Ptr() *T

func (*Nullable[T]) UnmarshalJSON

func (v *Nullable[T]) UnmarshalJSON(b []byte) error

type PaginationOptions

type PaginationOptions struct {
	Page     int32 `json:"page"`
	PageSize int32 `json:"pageSize"`
}

func (PaginationOptions) Limit

func (opt PaginationOptions) Limit() int32

func (PaginationOptions) Offset

func (opt PaginationOptions) Offset() int32

type PaginationRestrictions

type PaginationRestrictions struct {
	MaxPageSize  int32
	MaxPageCount int32
}

func (PaginationRestrictions) Validate

func (r PaginationRestrictions) Validate(page, pageSize int32) PaginationOptions

type PasswordRequirements

type PasswordRequirements struct {
	Digits         bool
	Symbols        string
	SymbolsEnabled bool
	DifferentCases bool
	MinLength      int
}

type PublishDraftCommand

type PublishDraftCommand struct {
	DraftID    int64
	UserID     uuid.UUID
	MakePublic bool
}

type RatingAndReview

type RatingAndReview struct {
	Rating Nullable[RatingValue] `json:"rating"`
	Review Nullable[ReviewDto]   `json:"review"`
}

go2tsdef:generate

type RatingValue

type RatingValue uint8

go2tsdef:generate

func CreateRatingValue

func CreateRatingValue(v int16) RatingValue

func (RatingValue) MarshalJSON

func (v RatingValue) MarshalJSON() ([]byte, error)

func (RatingValue) ToUint16

func (v RatingValue) ToUint16() int16

func (*RatingValue) UnmarshalJSON

func (v *RatingValue) UnmarshalJSON(data []byte) error

type ReaderPreferences

type ReaderPreferences struct {
	FontSize   int16  `json:"fontSize"`
	FontFamily string `json:"fontFamily"`
	PageColor  string `json:"pageColor"`
	Theme      string `json:"theme"`
}

func DefaultReaderPreferences

func DefaultReaderPreferences() ReaderPreferences

func (ReaderPreferences) Validate

func (p ReaderPreferences) Validate() error

type ReaderPreferencesService

type ReaderPreferencesService interface {
	Get(ctx context.Context, userID uuid.UUID) (Nullable[ReaderPreferences], error)
	Save(ctx context.Context, userID uuid.UUID, preferences ReaderPreferences) error
}

func NewReaderPreferencesService

func NewReaderPreferencesService(db DB) ReaderPreferencesService

type ReadingListService

type ReadingListService interface {
	MarksAsWantToRead(ctx context.Context, userID uuid.UUID, bookID int64) error
	MarkAsDnf(ctx context.Context, userID uuid.UUID, bookID int64) error
	MarkAsRead(ctx context.Context, userID uuid.UUID, bookID int64) error
	MarkAsPaused(ctx context.Context, userID uuid.UUID, bookID int64) error
	MarkAsReading(ctx context.Context, userID uuid.UUID, bookID int64) error
	MarkAsReadingWithChapterID(ctx context.Context, userID uuid.UUID, bookID int64, chapterID int64) error
	GetStatus(ctx context.Context, userID uuid.UUID, bookID int64) (Nullable[BookReadingListDto], error)
	GetReadingListBooks(ctx context.Context, query GetReadingListItemsQuery) ([]BookLibraryDto, error)
	MarkChapterRead(ctx context.Context, command MarkChapterCommand) error
}

func NewReadingListService

func NewReadingListService(db store.DBTX, uploadService *UploadService) ReadingListService

type ReadingListStatus

type ReadingListStatus store.ReadingListStatus

go2tsdef:generate go2tsdef:override_type 'dnf' | 'reading' | 'paused' | 'read' | 'want_to_read'

type RemoveFromCollectionCommand

type RemoveFromCollectionCommand struct {
	CollectionID int64
	BookID       int64
	UserID       uuid.UUID
}

type RenewSessionCommand

type RenewSessionCommand struct {
	SessionID string
	UserAgent string
	IpAddress string
	ExpiresAt time.Time
}

type ReorderChaptersCommand

type ReorderChaptersCommand struct {
	UserID     uuid.UUID
	BookID     int64
	ChapterIDs []int64
}

type Report

type Report struct {
	ID             int64
	Number         string
	Time           time.Time
	ReporterUserID uuid.UUID
	TargetType     ReportTargetType
	TargetID       string
	Reason         string
	Description    string
	BookChapterID  Nullable[int64]
	BookExcerpt    string
	Status         string
	Priority       string
}

type ReportActionExecutor

type ReportActionExecutor interface {
	Execute(context.Context, Report, DecideModerationReportCommand) error
	AvailableActions(Report) []string
}

type ReportDecision

type ReportDecision struct {
	Time          time.Time
	ActorUserID   uuid.UUID
	ActorUserName string
	Disposition   string
	Action        string
	PolicyReason  string
	InternalNote  string
	NotifyTarget  bool
	Payload       []byte
}

type ReportService

type ReportService interface {
	Create(context.Context, CreateReportCommand) (Report, error)
	GetReasons(ReportTargetType) ([]string, error)
}

func NewReportService

func NewReportService(repo ReportRepository) ReportService

type ReportTargetType

type ReportTargetType string
const (
	ReportTargetUser    ReportTargetType = "user"
	ReportTargetBook    ReportTargetType = "book"
	ReportTargetComment ReportTargetType = "comment"
)

type ReviewDto

type ReviewDto struct {
	User      ReviewUserDto       `json:"user"`
	Rating    RatingValue         `json:"rating"`
	Content   string              `json:"content"`
	CreatedAt time.Time           `json:"createdAt"`
	UpdatedAt Nullable[time.Time] `json:"updatedAt"`
	Likes     int32               `json:"likes"`
}

go2tsdef:generate

type ReviewUserDto

type ReviewUserDto struct {
	ID     uuid.UUID `json:"id"`
	Name   string    `json:"name"`
	Avatar string    `json:"avatar"`
}

go2tsdef:generate

type ReviewsService

type ReviewsService interface {
	GetBookReviewsDistribution(ctx context.Context, bookID int64) (GetBookReviewsDistributionResult, error)
	GetBookReviews(ctx context.Context, query GetBookReviewsQuery) (GetBookReviewsResult, error)

	UpdateReview(ctx context.Context, cmd UpdateReviewCommand) (ReviewDto, error)
	UpdateRating(ctx context.Context, cmd UpdateRatingCommand) error

	GetReview(ctx context.Context, query GetReviewQuery) (RatingAndReview, error)
	DeleteReview(ctx context.Context, cmd DeleteReviewCommand) error
}

func NewCachedReviewsService

func NewCachedReviewsService(inner ReviewsService, cache *cache.Cache, log *zap.SugaredLogger) ReviewsService

func NewReviewsService

func NewReviewsService(db DB, userService UserService, backgroundService BookRecalculationIngest) ReviewsService

type ScheduleDraftCommand

type ScheduleDraftCommand struct {
	DraftID     int64
	ChapterID   int64
	BookID      int64
	UserID      uuid.UUID
	ScheduledAt time.Time
}

type SearchModerationBooksQuery

type SearchModerationBooksQuery struct {
	ActorUserID                              uuid.UUID
	Search                                   string
	ExactName, IncludeBanned, IncludeDeleted bool
	Page, PageSize                           uint32
}

type SearchModerationReportsQuery

type SearchModerationReportsQuery struct {
	ActorUserID uuid.UUID
	Search      string
	TargetType  string
	Page        uint32
	PageSize    uint32
}

type SearchService

type SearchService interface {
	SearchBooks(ctx context.Context, req BookSearchQuery) (*BookSearchResult, error)
	GetBookExtremes(ctx context.Context) (*BookExtremes, error)
	ExplainSearchQuery(ctx context.Context, req BookSearchQuery) (DetailedBookSearchQuery, error)
}

func NewCachedSearchService

func NewCachedSearchService(inner SearchService, cache *cache.Cache) SearchService

func NewSearchService

func NewSearchService(db store.DBTX, tagsService TagsService, uploadService *UploadService, userService UserService, osClient *opensearchapi.Client, log *zap.SugaredLogger) SearchService

type SearchUserBooksQuery

type SearchUserBooksQuery struct {
	UserID      uuid.UUID
	ActorUserID Nullable[uuid.UUID]
	Limit       int
	Offset      int
}

type SearchUserBooksResult

type SearchUserBooksResult struct {
}

type SelfUserDto

type SelfUserDto struct {
	ID     uuid.UUID `json:"id"`
	Name   string    `json:"name"`
	Email  string    `json:"email"`
	Role   UserRole  `json:"role"`
	Avatar struct {
		LG string `json:"lg"`
		MD string `json:"md"`
	} `json:"avatar"`
	JoinedAt        time.Time `json:"joinedAt"`
	IsBanned        bool      `json:"isBanned"`
	IsEmailVerified bool      `json:"isEmailVerified"`
	PreferredTheme  string    `json:"preferredTheme"`
}

type SendEmailVerificationCommand

type SendEmailVerificationCommand struct {
	UserID          uuid.UUID
	BypassRateLimit bool
}

type SendEmailVerificationResult

type SendEmailVerificationResult struct {
	CanResendAfter time.Time
}

type SessionInfo

type SessionInfo struct {
	ID           int64      `json:"id"`
	SID          string     `json:"sid"`
	CreatedAt    time.Time  `json:"createdAt"`
	ExpiresAt    time.Time  `json:"expiresAt"`
	UserID       uuid.UUID  `json:"userId"`
	UserAgent    string     `json:"userAgent"`
	IpAddress    string     `json:"ipAddr"`
	Location     IPLocation `json:"location"`
	UserName     string     `json:"userName"`
	UserJoinedAt time.Time  `json:"userJoinedAt"`
	UserRole     UserRole   `json:"userRole"`
}

type SessionPublicInfo

type SessionPublicInfo struct {
	ID        int64         `json:"id,string"`
	UserAgent UserAgentInfo `json:"userAgent"`
	IpAddress string        `json:"ipAddress"`
	Location  IPLocation    `json:"location"`
	CreatedAt time.Time     `json:"createdAt"`
	ExpiresAt time.Time     `json:"expiresAt"`
}

func NewSessionPublicInfo

func NewSessionPublicInfo(session SessionInfo) SessionPublicInfo

func SessionPublicInfoArray

func SessionPublicInfoArray(sessions []SessionInfo) []SessionPublicInfo

type SessionService

type SessionService interface {
	GetBySID(ctx context.Context, sessionID string) (*SessionInfo, error)
	Create(ctx context.Context, command CreateSessionCommand) (*SessionInfo, error)
	GetByUserID(ctx context.Context, userID uuid.UUID) ([]SessionInfo, error)
	TerminateBySID(ctx context.Context, sessionID string) error
	TerminateAllByUserID(ctx context.Context, userID uuid.UUID) error
	Renew(ctx context.Context, command RenewSessionCommand) (*SessionInfo, error)
}

func NewCachedSessionService

func NewCachedSessionService(inner SessionService, cache *cache.Cache) SessionService

func NewSessionService

func NewSessionService(db DB, ipLocations IPLocationService) SessionService

type SetUserDataQuery

type SetUserDataQuery struct {
	UserID          uuid.UUID
	Key             string
	Data            json.RawMessage
	IgnoreWhitelist bool
}

type SignInCommand

type SignInCommand struct {
	Username  string
	Password  string
	UserAgent string
	IpAddress string
}

type SignInResult

type SignInResult struct {
	SessionID string
	UserID    uuid.UUID
}

type SignUpCommand

type SignUpCommand struct {
	Username                  string
	Password                  string
	Email                     string
	UserAgent                 string
	IpAddress                 string
	BypassEmailRequirement    bool
	BypassPasswordRequirement bool
}

type SignUpResult

type SignUpResult struct {
	Created                   bool
	CreatedUserID             uuid.UUID
	EmailTaken                bool
	EmailVerificationRequired bool
}

type SignUpService

type SignUpService interface {
	SignUp(ctx context.Context, cmd SignUpCommand) (SignUpResult, error)
	VerifyEmail(ctx context.Context, cmd VerifyEmailCommand) error
	SendEmailVerification(ctx context.Context, cmd SendEmailVerificationCommand) (SendEmailVerificationResult, error)
	GetEmailVerificationStatus(ctx context.Context, userID uuid.UUID) (EmailVerificationStatus, error)
}

func NewSignUpService

func NewSignUpService(db DB, cfg *koanf.Koanf, siteConfig *SiteConfig, emailService email.Service) SignUpService

type SiteConfig

type SiteConfig struct {
	// contains filtered or unexported fields
}

func NewSiteConfig

func NewSiteConfig(db DB, staticCfg *koanf.Koanf) *SiteConfig

func (*SiteConfig) Get

func (s *SiteConfig) Get() *SiteConfigData

func (*SiteConfig) Load

func (s *SiteConfig) Load(ctx context.Context) error

func (*SiteConfig) Save

func (s *SiteConfig) Save(ctx context.Context, force bool) error

type SiteConfigData

type SiteConfigData struct {
	CaptchaSettings      CaptchaSettings
	PasswordRequirements PasswordRequirements
	ContentRestrictions  ContentRestrictions
}

func (SiteConfigData) Equal

func (d SiteConfigData) Equal(other SiteConfigData) bool

type SiteConfigEntry

type SiteConfigEntry json.RawMessage

type TagDescriptor

type TagDescriptor struct {
	Name      string
	Category  TagsCategory
	IsAdult   bool
	IsWarning bool
	IsSpoiler bool
}

type TagDetailsItemDto

type TagDetailsItemDto struct {
	DefinedTagDto

	SynonymOf Nullable[struct {
		ID   int64
		Name string
	}]
	CreatedAt time.Time
	IsDefault bool
}

type TagsCategory

type TagsCategory uint8

go2tsdef:generate go2tsdef:override_type 'other' | 'warning' | 'fandom' | 'rel' | 'reltype' | 'unknown'

const (
	TagsCategoryOther TagsCategory = iota
	TagsCategoryWarning
	TagsCategoryFandom
	TagsCategoryRelationship
	TagsCategoryRelationshipType
	TagsCategoryGenre
)

func TagsCategoryFromName

func TagsCategoryFromName(name string) TagsCategory

func (TagsCategory) MarshalJSON

func (t TagsCategory) MarshalJSON() ([]byte, error)

func (TagsCategory) String

func (t TagsCategory) String() string

func (*TagsCategory) UnmarshalJSON

func (t *TagsCategory) UnmarshalJSON(b []byte) error

type TagsService

type TagsService interface {
	GetTag(ctx context.Context, id int64) (TagDetailsItemDto, error)
	GetTagsByIds(ctx context.Context, ids []int64) ([]DefinedTagDto, error)
	SearchTags(ctx context.Context, query string) ([]DefinedTagDto, error)
	FindParentTagIds(ctx context.Context, names []int64) (BookTags, error)
	CreateTags(ctx context.Context, cmd CreateTagsCommand) ([]DefinedTagDto, error)
	List(ctx context.Context, query ListTagsQuery) (ListTagsResult, error)
	UpdateTag(ctx context.Context, command UpdateTagCommand) error
}

func NewTagsService

func NewTagsService(db store.DBTX) TagsService

type TrashBookCommand

type TrashBookCommand struct {
	BookID      int64
	ActorUserID uuid.UUID
}

type UnfollowUserCommand

type UnfollowUserCommand struct {
	UserID   uuid.UUID
	Follower uuid.UUID
}

type UntrashBookCommand

type UntrashBookCommand struct {
	BookID      int64
	ActorUserID uuid.UUID
}

type UpdateBookChapterCommand

type UpdateBookChapterCommand struct {
	BookID            int64
	ChapterID         int64
	UserID            uuid.UUID
	Name              string
	Summary           string
	IsPubliclyVisible bool
}

type UpdateBookChapterOrdersCommand

type UpdateBookChapterOrdersCommand struct {
	BookID        int64
	Modifications []ChapterOrderModification
}

type UpdateBookChapterOrdersCommand_Result

type UpdateBookChapterOrdersCommand_Result struct {
	ModifiedPositions map[int64]int
}

type UpdateBookCommand

type UpdateBookCommand struct {
	BookID            int64
	UserID            uuid.UUID
	Name              string
	AgeRating         AgeRating
	Tags              []int64
	Summary           string
	IsPubliclyVisible bool
}

type UpdateCollectionCommand

type UpdateCollectionCommand struct {
	ID          int64
	Name        string
	Public      bool
	Summary     string
	ActorUserID uuid.UUID
}

type UpdateCommentCommand

type UpdateCommentCommand struct {
	ID      int64
	Content string
	UserID  uuid.UUID
}

func (*UpdateCommentCommand) Validate

func (c *UpdateCommentCommand) Validate() error

type UpdateCommentResult

type UpdateCommentResult struct {
	Comment CommentDto
}

type UpdateDraftChapterNameCommand

type UpdateDraftChapterNameCommand struct {
	ChapterName string
	ChapterID   int64
	BookID      int64
	DraftID     int64
	UserID      uuid.UUID
}

type UpdateDraftCommand

type UpdateDraftCommand struct {
	Content   string
	Summary   string
	Name      string
	DraftID   int64
	ChapterID int64
	BookID    int64
	UserID    uuid.UUID
}

type UpdateDraftContentCommand

type UpdateDraftContentCommand struct {
	Content   string
	DraftID   int64
	ChapterID int64
	BookID    int64
	UserID    uuid.UUID
}

type UpdateRatingCommand

type UpdateRatingCommand struct {
	BookID int64
	UserID uuid.UUID
	Rating RatingValue
}

type UpdateReviewCommand

type UpdateReviewCommand struct {
	BookID  int64
	UserID  uuid.UUID
	Rating  RatingValue
	Content string
}

type UpdateTagCommand

type UpdateTagCommand struct {
	ID             int64
	Name           string
	Description    string
	IsAdult        bool
	IsSpoiler      bool
	SynonymOfTagID Nullable[int64]
	Type           TagsCategory
	UserID         uuid.UUID
}

type UpdateUserCommand

type UpdateUserCommand struct {
	UserID      uuid.UUID
	ActorUserID uuid.NullUUID
	Password    string
	Role        Nullable[UserRole]
	About       string
	Gender      string
}

type UploadBookCoverCommand

type UploadBookCoverCommand struct {
	UserID uuid.UUID
	BookID int64
	File   io.Reader
}

type UploadBookCoverCommand_Result

type UploadBookCoverCommand_Result struct {
	URL BookCover
}

type UploadConfig

type UploadConfig struct {
	Endpoint     string
	Region       string
	AccessKey    string
	SecretKey    string
	MainBucket   string
	PublicBucket string
	Secure       bool
}

type UploadService

type UploadService struct {
	Client       *minio.Client
	MainBucket   string
	PublicBucket string
	Region       string
	Secure       bool
	Endpoint     string
}

func NewUploadService

func NewUploadService(cfg UploadConfig) *UploadService

func NewUploadServiceFromApplicationConfig

func NewUploadServiceFromApplicationConfig(cfg *koanf.Koanf) *UploadService

func (*UploadService) GetPublicURL

func (s *UploadService) GetPublicURL(path string) string

func (*UploadService) InitBuckets

func (s *UploadService) InitBuckets(ctx context.Context) error

type UploadURI

type UploadURI struct {
	Type UploadURIType
	Key  string
}

func ParseUploadURI

func ParseUploadURI(s string) (*UploadURI, error)

func (UploadURI) String

func (uu UploadURI) String() string

func (UploadURI) URL

func (uu UploadURI) URL() *url.URL

type UploadURIType

type UploadURIType int
const (
	UploadURITypePublicMinio UploadURIType = iota
	UploadURITypePrivateMinio
	UploadURITypeExternal
	UploadURITypeUnknown = 0xffff
)

func (UploadURIType) String

func (t UploadURIType) String() string

type UserAboutDto

type UserAboutDto struct {
	Bio    string `json:"bio"`
	Gender string `json:"gender"`
}

type UserAboutSettings

type UserAboutSettings struct {
	About  string `json:"about"`
	Status string `json:"status"`
	Gender string `json:"gender"`
}

type UserAgentInfo

type UserAgentInfo struct {
	Value   string `json:"value"`
	Version string `json:"ver"`
	Name    string `json:"name"`
	OS      string `json:"os"`
}

type UserCustomizationSetting

type UserCustomizationSetting struct {
	ProfileCSS       string `json:"profileCss"`
	DefaultTheme     string `json:"defaultTheme"`
	EnableProfileCSS bool   `json:"enableProfileCss"`
}

type UserDataService

type UserDataService interface {
	Get(ctx context.Context, query GetUserDataQuery) (Nullable[json.RawMessage], error)
	Set(ctx context.Context, query SetUserDataQuery) error
}

func NewUserDataService

func NewUserDataService(db DB) UserDataService

type UserDetailsDto

type UserDetailsDto struct {
	ID     uuid.UUID `json:"id"`
	Name   string    `json:"name"`
	Email  string    `json:"email"`
	Avatar struct {
		LG string `json:"lg"`
		MD string `json:"md"`
	} `json:"avatar"`
	JoinedAt       time.Time    `json:"joinedAt"`
	IsBanned       bool         `json:"isBanned"`
	Role           UserRole     `json:"role"`
	HasCustomTheme bool         `json:"hasCustomTheme"`
	About          UserAboutDto `json:"about"`
	Followers      int32        `json:"followers"`
	Following      int32        `json:"following"`
	BooksTotal     int32        `json:"booksTotal"`
	HideEmail      bool         `json:"hideEmail"`
	HideStats      bool         `json:"hideStats"`
	HideFavorites  bool         `json:"hideFavorites"`
	IsFollowing    bool         `json:"isFollowing"`
}

type UserFromSearchRequestDto

type UserFromSearchRequestDto struct {
	ID     uuid.UUID `json:"id"`
	Name   string    `json:"name"`
	Avatar string    `json:"avatar"`
}

type UserListResponse

type UserListResponse struct {
	Users      []UserSearchItem `json:"users"`
	Total      int32            `json:"total"`
	Page       uint32           `json:"page"`
	TotalPages int32            `json:"totalPages"`
}

type UserModerationSettings

type UserModerationSettings struct {
	ShowAdultContent bool       `json:"showAdultContent"`
	CensoredTags     []string   `json:"censoredTags"`
	CensoredTagsMode CensorMode `json:"censoredTagsMode"`
}

type UserPrivacySettings

type UserPrivacySettings struct {
	HideStats      bool `json:"hideStats"`
	HideFavorites  bool `json:"hideFavorites"`
	HideComments   bool `json:"hideComments"`
	HideEmail      bool `json:"hideEmail"`
	AllowSearching bool `json:"allowSearching"`
}

type UserRole

type UserRole string

func ParseUserRole

func ParseUserRole(role string) (UserRole, error)

func (UserRole) IsAdmin

func (r UserRole) IsAdmin() bool

func (UserRole) IsModOrHigher

func (r UserRole) IsModOrHigher() bool

type UserSearchItem

type UserSearchItem struct {
	ID       uuid.UUID
	Name     string
	Role     UserRole
	IsBanned bool
	JoinedAt time.Time
	Avatar   string
}

type UserService

type UserService interface {
	GetUserPrivacySettings(ctx context.Context, userID uuid.UUID) (*UserPrivacySettings, error)
	GetUserModerationSettings(ctx context.Context, userID uuid.UUID) (*UserModerationSettings, error)
	GetUserCustomizationSettings(ctx context.Context, userID uuid.UUID) (*UserCustomizationSetting, error)
	GetUserAboutSettings(ctx context.Context, userID uuid.UUID) (*UserAboutSettings, error)

	UpdateUserPrivacySettings(ctx context.Context, userID uuid.UUID, settings UserPrivacySettings) error
	UpdateUserModerationSettings(ctx context.Context, userID uuid.UUID, settings UserModerationSettings) error
	UpdateUserCustomizationSettings(ctx context.Context, userID uuid.UUID, settings UserCustomizationSetting) error
	UpdateUserAboutSettings(ctx context.Context, userID uuid.UUID, settings UserAboutSettings) error

	UpdateUser(ctx context.Context, cmd UpdateUserCommand) error

	GetUserDetails(ctx context.Context, query GetUserQuery) (*UserDetailsDto, error)
	GetUserSelfData(ctx context.Context, userID uuid.UUID) (*SelfUserDto, error)

	FollowUser(ctx context.Context, cmd FollowUserCommand) error
	UnfollowUser(ctx context.Context, cmd UnfollowUserCommand) error

	ListUsers(ctx context.Context, req UsersQuery) (UserListResponse, error)
}

func NewUserService

func NewUserService(db DB) UserService

type UsersQuery

type UsersQuery struct {
	Banned bool
	Role   []UserRole
	Query  string

	Page     uint32
	PageSize uint32
}

type VerifyEmailCommand

type VerifyEmailCommand struct {
	UserID uuid.UUID
	Code   string
}

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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