- Add admin dashboard at /admin route consolidating all user settings - Move user preferences (username, email, password, theme) from separate page - Add ebook library preferences section with folder management - Add scan settings (frequency and auto-scan toggle) with database persistence - Create database migration for scan_frequency_minutes and auto_scan_enabled columns - Add API endpoints for scan settings management: - PUT /api/library/scan-settings - Update scan preferences - GET /api/library/scan-settings - Get current scan settings - Update dashboard navigation to link to admin dashboard - Remove old preferences.html template (functionality moved to admin) - Create Bruno API testing files for library endpoints - Add real-time folder loading and management in admin interface - Implement scan settings persistence and retrieval from database
822 lines
23 KiB
Go
822 lines
23 KiB
Go
// Code generated by sqlc. DO NOT EDIT.
|
|
// versions:
|
|
// sqlc v1.30.0
|
|
// source: queries.sql
|
|
|
|
package database
|
|
|
|
import (
|
|
"context"
|
|
|
|
"github.com/jackc/pgx/v5/pgtype"
|
|
)
|
|
|
|
const AddUserEbookFolder = `-- name: AddUserEbookFolder :one
|
|
INSERT INTO user_ebook_folders (user_id, folder_path) VALUES ($1, $2) RETURNING id, user_id, folder_path, created_at
|
|
`
|
|
|
|
type AddUserEbookFolderParams struct {
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
FolderPath string `db:"folder_path" json:"folder_path"`
|
|
}
|
|
|
|
func (q *Queries) AddUserEbookFolder(ctx context.Context, arg AddUserEbookFolderParams) (UserEbookFolders, error) {
|
|
row := q.db.QueryRow(ctx, AddUserEbookFolder, arg.UserID, arg.FolderPath)
|
|
var i UserEbookFolders
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.UserID,
|
|
&i.FolderPath,
|
|
&i.CreatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const CreateEbook = `-- name: CreateEbook :one
|
|
INSERT INTO ebooks (title, author, isbn, description, file_path, file_size, mime_type, cover_image_path, series, series_number, tags, asin, date_published, publisher, contributors)
|
|
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15)
|
|
RETURNING id, title, author, isbn, description, file_path, file_size, mime_type, cover_image_path, created_at, updated_at, series, series_number, tags, asin, date_published, publisher, contributors
|
|
`
|
|
|
|
type CreateEbookParams struct {
|
|
Title string `db:"title" json:"title"`
|
|
Author pgtype.Text `db:"author" json:"author"`
|
|
Isbn pgtype.Text `db:"isbn" json:"isbn"`
|
|
Description pgtype.Text `db:"description" json:"description"`
|
|
FilePath string `db:"file_path" json:"file_path"`
|
|
FileSize pgtype.Int8 `db:"file_size" json:"file_size"`
|
|
MimeType pgtype.Text `db:"mime_type" json:"mime_type"`
|
|
CoverImagePath pgtype.Text `db:"cover_image_path" json:"cover_image_path"`
|
|
Series pgtype.Text `db:"series" json:"series"`
|
|
SeriesNumber pgtype.Int4 `db:"series_number" json:"series_number"`
|
|
Tags pgtype.Text `db:"tags" json:"tags"`
|
|
Asin pgtype.Text `db:"asin" json:"asin"`
|
|
DatePublished pgtype.Date `db:"date_published" json:"date_published"`
|
|
Publisher pgtype.Text `db:"publisher" json:"publisher"`
|
|
Contributors pgtype.Text `db:"contributors" json:"contributors"`
|
|
}
|
|
|
|
func (q *Queries) CreateEbook(ctx context.Context, arg CreateEbookParams) (Ebooks, error) {
|
|
row := q.db.QueryRow(ctx, CreateEbook,
|
|
arg.Title,
|
|
arg.Author,
|
|
arg.Isbn,
|
|
arg.Description,
|
|
arg.FilePath,
|
|
arg.FileSize,
|
|
arg.MimeType,
|
|
arg.CoverImagePath,
|
|
arg.Series,
|
|
arg.SeriesNumber,
|
|
arg.Tags,
|
|
arg.Asin,
|
|
arg.DatePublished,
|
|
arg.Publisher,
|
|
arg.Contributors,
|
|
)
|
|
var i Ebooks
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Title,
|
|
&i.Author,
|
|
&i.Isbn,
|
|
&i.Description,
|
|
&i.FilePath,
|
|
&i.FileSize,
|
|
&i.MimeType,
|
|
&i.CoverImagePath,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.Series,
|
|
&i.SeriesNumber,
|
|
&i.Tags,
|
|
&i.Asin,
|
|
&i.DatePublished,
|
|
&i.Publisher,
|
|
&i.Contributors,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const CreateEbookRating = `-- name: CreateEbookRating :one
|
|
INSERT INTO ebook_ratings (ebook_id, user_id, rating)
|
|
VALUES ($1, $2, $3)
|
|
ON CONFLICT (ebook_id, user_id)
|
|
DO UPDATE SET
|
|
rating = EXCLUDED.rating,
|
|
updated_at = NOW()
|
|
RETURNING id, ebook_id, user_id, rating, created_at, updated_at
|
|
`
|
|
|
|
type CreateEbookRatingParams struct {
|
|
EbookID pgtype.UUID `db:"ebook_id" json:"ebook_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
Rating int32 `db:"rating" json:"rating"`
|
|
}
|
|
|
|
func (q *Queries) CreateEbookRating(ctx context.Context, arg CreateEbookRatingParams) (EbookRatings, error) {
|
|
row := q.db.QueryRow(ctx, CreateEbookRating, arg.EbookID, arg.UserID, arg.Rating)
|
|
var i EbookRatings
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.EbookID,
|
|
&i.UserID,
|
|
&i.Rating,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const CreateUser = `-- name: CreateUser :one
|
|
INSERT INTO users (email, username, password_hash, theme)
|
|
VALUES ($1, $2, $3, $4)
|
|
RETURNING id, email, username, password_hash, theme, created_at, updated_at, scan_frequency_minutes, auto_scan_enabled
|
|
`
|
|
|
|
type CreateUserParams struct {
|
|
Email string `db:"email" json:"email"`
|
|
Username string `db:"username" json:"username"`
|
|
PasswordHash string `db:"password_hash" json:"password_hash"`
|
|
Theme pgtype.Text `db:"theme" json:"theme"`
|
|
}
|
|
|
|
func (q *Queries) CreateUser(ctx context.Context, arg CreateUserParams) (Users, error) {
|
|
row := q.db.QueryRow(ctx, CreateUser,
|
|
arg.Email,
|
|
arg.Username,
|
|
arg.PasswordHash,
|
|
arg.Theme,
|
|
)
|
|
var i Users
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Email,
|
|
&i.Username,
|
|
&i.PasswordHash,
|
|
&i.Theme,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.ScanFrequencyMinutes,
|
|
&i.AutoScanEnabled,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const DeleteEbook = `-- name: DeleteEbook :exec
|
|
DELETE FROM ebooks WHERE id = $1
|
|
`
|
|
|
|
func (q *Queries) DeleteEbook(ctx context.Context, id pgtype.UUID) error {
|
|
_, err := q.db.Exec(ctx, DeleteEbook, id)
|
|
return err
|
|
}
|
|
|
|
const DeleteEbookRating = `-- name: DeleteEbookRating :exec
|
|
DELETE FROM ebook_ratings WHERE ebook_id = $1 AND user_id = $2
|
|
`
|
|
|
|
type DeleteEbookRatingParams struct {
|
|
EbookID pgtype.UUID `db:"ebook_id" json:"ebook_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
}
|
|
|
|
func (q *Queries) DeleteEbookRating(ctx context.Context, arg DeleteEbookRatingParams) error {
|
|
_, err := q.db.Exec(ctx, DeleteEbookRating, arg.EbookID, arg.UserID)
|
|
return err
|
|
}
|
|
|
|
const DeleteReadingProgress = `-- name: DeleteReadingProgress :exec
|
|
DELETE FROM reading_progress WHERE ebook_id = $1 AND user_id = $2
|
|
`
|
|
|
|
type DeleteReadingProgressParams struct {
|
|
EbookID pgtype.UUID `db:"ebook_id" json:"ebook_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
}
|
|
|
|
func (q *Queries) DeleteReadingProgress(ctx context.Context, arg DeleteReadingProgressParams) error {
|
|
_, err := q.db.Exec(ctx, DeleteReadingProgress, arg.EbookID, arg.UserID)
|
|
return err
|
|
}
|
|
|
|
const DeleteUser = `-- name: DeleteUser :exec
|
|
DELETE FROM users WHERE id = $1
|
|
`
|
|
|
|
func (q *Queries) DeleteUser(ctx context.Context, id pgtype.UUID) error {
|
|
_, err := q.db.Exec(ctx, DeleteUser, id)
|
|
return err
|
|
}
|
|
|
|
const DeleteUserEbookFolder = `-- name: DeleteUserEbookFolder :exec
|
|
DELETE FROM user_ebook_folders WHERE user_id = $1 AND folder_path = $2
|
|
`
|
|
|
|
type DeleteUserEbookFolderParams struct {
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
FolderPath string `db:"folder_path" json:"folder_path"`
|
|
}
|
|
|
|
func (q *Queries) DeleteUserEbookFolder(ctx context.Context, arg DeleteUserEbookFolderParams) error {
|
|
_, err := q.db.Exec(ctx, DeleteUserEbookFolder, arg.UserID, arg.FolderPath)
|
|
return err
|
|
}
|
|
|
|
const GetEbook = `-- name: GetEbook :one
|
|
SELECT id, title, author, isbn, description, file_path, file_size, mime_type, cover_image_path, created_at, updated_at, series, series_number, tags, asin, date_published, publisher, contributors FROM ebooks WHERE id = $1
|
|
`
|
|
|
|
func (q *Queries) GetEbook(ctx context.Context, id pgtype.UUID) (Ebooks, error) {
|
|
row := q.db.QueryRow(ctx, GetEbook, id)
|
|
var i Ebooks
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Title,
|
|
&i.Author,
|
|
&i.Isbn,
|
|
&i.Description,
|
|
&i.FilePath,
|
|
&i.FileSize,
|
|
&i.MimeType,
|
|
&i.CoverImagePath,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.Series,
|
|
&i.SeriesNumber,
|
|
&i.Tags,
|
|
&i.Asin,
|
|
&i.DatePublished,
|
|
&i.Publisher,
|
|
&i.Contributors,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const GetEbookByFilePath = `-- name: GetEbookByFilePath :one
|
|
SELECT id, title, author, isbn, description, file_path, file_size, mime_type, cover_image_path, created_at, updated_at, series, series_number, tags, asin, date_published, publisher, contributors FROM ebooks WHERE file_path = $1
|
|
`
|
|
|
|
func (q *Queries) GetEbookByFilePath(ctx context.Context, filePath string) (Ebooks, error) {
|
|
row := q.db.QueryRow(ctx, GetEbookByFilePath, filePath)
|
|
var i Ebooks
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Title,
|
|
&i.Author,
|
|
&i.Isbn,
|
|
&i.Description,
|
|
&i.FilePath,
|
|
&i.FileSize,
|
|
&i.MimeType,
|
|
&i.CoverImagePath,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.Series,
|
|
&i.SeriesNumber,
|
|
&i.Tags,
|
|
&i.Asin,
|
|
&i.DatePublished,
|
|
&i.Publisher,
|
|
&i.Contributors,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const GetEbookRating = `-- name: GetEbookRating :one
|
|
SELECT id, ebook_id, user_id, rating, created_at, updated_at FROM ebook_ratings WHERE ebook_id = $1 AND user_id = $2
|
|
`
|
|
|
|
type GetEbookRatingParams struct {
|
|
EbookID pgtype.UUID `db:"ebook_id" json:"ebook_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
}
|
|
|
|
func (q *Queries) GetEbookRating(ctx context.Context, arg GetEbookRatingParams) (EbookRatings, error) {
|
|
row := q.db.QueryRow(ctx, GetEbookRating, arg.EbookID, arg.UserID)
|
|
var i EbookRatings
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.EbookID,
|
|
&i.UserID,
|
|
&i.Rating,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const GetEbookRatings = `-- name: GetEbookRatings :many
|
|
SELECT er.id, er.ebook_id, er.user_id, er.rating, er.created_at, er.updated_at, u.username
|
|
FROM ebook_ratings er
|
|
JOIN users u ON er.user_id = u.id
|
|
WHERE er.ebook_id = $1
|
|
ORDER BY er.created_at DESC
|
|
`
|
|
|
|
type GetEbookRatingsRow struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
EbookID pgtype.UUID `db:"ebook_id" json:"ebook_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
Rating int32 `db:"rating" json:"rating"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
Username string `db:"username" json:"username"`
|
|
}
|
|
|
|
func (q *Queries) GetEbookRatings(ctx context.Context, ebookID pgtype.UUID) ([]GetEbookRatingsRow, error) {
|
|
rows, err := q.db.Query(ctx, GetEbookRatings, ebookID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []GetEbookRatingsRow{}
|
|
for rows.Next() {
|
|
var i GetEbookRatingsRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.EbookID,
|
|
&i.UserID,
|
|
&i.Rating,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.Username,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const GetReadingProgress = `-- name: GetReadingProgress :one
|
|
SELECT id, ebook_id, user_id, current_page, total_pages, last_read_at FROM reading_progress WHERE ebook_id = $1 AND user_id = $2
|
|
`
|
|
|
|
type GetReadingProgressParams struct {
|
|
EbookID pgtype.UUID `db:"ebook_id" json:"ebook_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
}
|
|
|
|
func (q *Queries) GetReadingProgress(ctx context.Context, arg GetReadingProgressParams) (ReadingProgress, error) {
|
|
row := q.db.QueryRow(ctx, GetReadingProgress, arg.EbookID, arg.UserID)
|
|
var i ReadingProgress
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.EbookID,
|
|
&i.UserID,
|
|
&i.CurrentPage,
|
|
&i.TotalPages,
|
|
&i.LastReadAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const GetScanSettings = `-- name: GetScanSettings :one
|
|
SELECT scan_frequency_minutes, auto_scan_enabled FROM users WHERE id = $1
|
|
`
|
|
|
|
type GetScanSettingsRow struct {
|
|
ScanFrequencyMinutes pgtype.Int4 `db:"scan_frequency_minutes" json:"scan_frequency_minutes"`
|
|
AutoScanEnabled pgtype.Bool `db:"auto_scan_enabled" json:"auto_scan_enabled"`
|
|
}
|
|
|
|
func (q *Queries) GetScanSettings(ctx context.Context, id pgtype.UUID) (GetScanSettingsRow, error) {
|
|
row := q.db.QueryRow(ctx, GetScanSettings, id)
|
|
var i GetScanSettingsRow
|
|
err := row.Scan(&i.ScanFrequencyMinutes, &i.AutoScanEnabled)
|
|
return i, err
|
|
}
|
|
|
|
const GetUser = `-- name: GetUser :one
|
|
SELECT id, email, username, theme, created_at, updated_at FROM users WHERE id = $1
|
|
`
|
|
|
|
type GetUserRow struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
Email string `db:"email" json:"email"`
|
|
Username string `db:"username" json:"username"`
|
|
Theme pgtype.Text `db:"theme" json:"theme"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
func (q *Queries) GetUser(ctx context.Context, id pgtype.UUID) (GetUserRow, error) {
|
|
row := q.db.QueryRow(ctx, GetUser, id)
|
|
var i GetUserRow
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Email,
|
|
&i.Username,
|
|
&i.Theme,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const GetUserByEmail = `-- name: GetUserByEmail :one
|
|
SELECT id, email, username, password_hash, theme, created_at, updated_at, scan_frequency_minutes, auto_scan_enabled FROM users WHERE email = $1
|
|
`
|
|
|
|
func (q *Queries) GetUserByEmail(ctx context.Context, email string) (Users, error) {
|
|
row := q.db.QueryRow(ctx, GetUserByEmail, email)
|
|
var i Users
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Email,
|
|
&i.Username,
|
|
&i.PasswordHash,
|
|
&i.Theme,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.ScanFrequencyMinutes,
|
|
&i.AutoScanEnabled,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const GetUserByEmailOrUsername = `-- name: GetUserByEmailOrUsername :one
|
|
SELECT id, email, username, password_hash, theme, created_at, updated_at, scan_frequency_minutes, auto_scan_enabled FROM users WHERE email = $1 OR username = $1
|
|
`
|
|
|
|
func (q *Queries) GetUserByEmailOrUsername(ctx context.Context, email string) (Users, error) {
|
|
row := q.db.QueryRow(ctx, GetUserByEmailOrUsername, email)
|
|
var i Users
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Email,
|
|
&i.Username,
|
|
&i.PasswordHash,
|
|
&i.Theme,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.ScanFrequencyMinutes,
|
|
&i.AutoScanEnabled,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const GetUserByUsername = `-- name: GetUserByUsername :one
|
|
SELECT id, email, username, password_hash, theme, created_at, updated_at, scan_frequency_minutes, auto_scan_enabled FROM users WHERE username = $1
|
|
`
|
|
|
|
func (q *Queries) GetUserByUsername(ctx context.Context, username string) (Users, error) {
|
|
row := q.db.QueryRow(ctx, GetUserByUsername, username)
|
|
var i Users
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Email,
|
|
&i.Username,
|
|
&i.PasswordHash,
|
|
&i.Theme,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.ScanFrequencyMinutes,
|
|
&i.AutoScanEnabled,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const GetUserEbookFolders = `-- name: GetUserEbookFolders :many
|
|
SELECT id, user_id, folder_path, created_at FROM user_ebook_folders WHERE user_id = $1 ORDER BY created_at
|
|
`
|
|
|
|
func (q *Queries) GetUserEbookFolders(ctx context.Context, userID pgtype.UUID) ([]UserEbookFolders, error) {
|
|
rows, err := q.db.Query(ctx, GetUserEbookFolders, userID)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []UserEbookFolders{}
|
|
for rows.Next() {
|
|
var i UserEbookFolders
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.UserID,
|
|
&i.FolderPath,
|
|
&i.CreatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const GetUserPasswordHash = `-- name: GetUserPasswordHash :one
|
|
SELECT password_hash FROM users WHERE id = $1
|
|
`
|
|
|
|
func (q *Queries) GetUserPasswordHash(ctx context.Context, id pgtype.UUID) (string, error) {
|
|
row := q.db.QueryRow(ctx, GetUserPasswordHash, id)
|
|
var password_hash string
|
|
err := row.Scan(&password_hash)
|
|
return password_hash, err
|
|
}
|
|
|
|
const ListEbooks = `-- name: ListEbooks :many
|
|
SELECT id, title, author, isbn, description, file_path, file_size, mime_type, cover_image_path, created_at, updated_at, series, series_number, tags, asin, date_published, publisher, contributors FROM ebooks ORDER BY created_at DESC LIMIT $1 OFFSET $2
|
|
`
|
|
|
|
type ListEbooksParams struct {
|
|
Limit int32 `db:"limit" json:"limit"`
|
|
Offset int32 `db:"offset" json:"offset"`
|
|
}
|
|
|
|
func (q *Queries) ListEbooks(ctx context.Context, arg ListEbooksParams) ([]Ebooks, error) {
|
|
rows, err := q.db.Query(ctx, ListEbooks, arg.Limit, arg.Offset)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []Ebooks{}
|
|
for rows.Next() {
|
|
var i Ebooks
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Title,
|
|
&i.Author,
|
|
&i.Isbn,
|
|
&i.Description,
|
|
&i.FilePath,
|
|
&i.FileSize,
|
|
&i.MimeType,
|
|
&i.CoverImagePath,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.Series,
|
|
&i.SeriesNumber,
|
|
&i.Tags,
|
|
&i.Asin,
|
|
&i.DatePublished,
|
|
&i.Publisher,
|
|
&i.Contributors,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const ListUsers = `-- name: ListUsers :many
|
|
SELECT id, email, username, theme, created_at, updated_at FROM users ORDER BY created_at DESC
|
|
`
|
|
|
|
type ListUsersRow struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
Email string `db:"email" json:"email"`
|
|
Username string `db:"username" json:"username"`
|
|
Theme pgtype.Text `db:"theme" json:"theme"`
|
|
CreatedAt pgtype.Timestamptz `db:"created_at" json:"created_at"`
|
|
UpdatedAt pgtype.Timestamptz `db:"updated_at" json:"updated_at"`
|
|
}
|
|
|
|
func (q *Queries) ListUsers(ctx context.Context) ([]ListUsersRow, error) {
|
|
rows, err := q.db.Query(ctx, ListUsers)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
defer rows.Close()
|
|
items := []ListUsersRow{}
|
|
for rows.Next() {
|
|
var i ListUsersRow
|
|
if err := rows.Scan(
|
|
&i.ID,
|
|
&i.Email,
|
|
&i.Username,
|
|
&i.Theme,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
); err != nil {
|
|
return nil, err
|
|
}
|
|
items = append(items, i)
|
|
}
|
|
if err := rows.Err(); err != nil {
|
|
return nil, err
|
|
}
|
|
return items, nil
|
|
}
|
|
|
|
const UpdateEbook = `-- name: UpdateEbook :one
|
|
UPDATE ebooks SET
|
|
title = $2,
|
|
author = $3,
|
|
isbn = $4,
|
|
description = $5,
|
|
cover_image_path = $6,
|
|
series = $7,
|
|
series_number = $8,
|
|
tags = $9,
|
|
asin = $10,
|
|
date_published = $11,
|
|
publisher = $12,
|
|
contributors = $13,
|
|
updated_at = NOW()
|
|
WHERE id = $1
|
|
RETURNING id, title, author, isbn, description, file_path, file_size, mime_type, cover_image_path, created_at, updated_at, series, series_number, tags, asin, date_published, publisher, contributors
|
|
`
|
|
|
|
type UpdateEbookParams struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
Title string `db:"title" json:"title"`
|
|
Author pgtype.Text `db:"author" json:"author"`
|
|
Isbn pgtype.Text `db:"isbn" json:"isbn"`
|
|
Description pgtype.Text `db:"description" json:"description"`
|
|
CoverImagePath pgtype.Text `db:"cover_image_path" json:"cover_image_path"`
|
|
Series pgtype.Text `db:"series" json:"series"`
|
|
SeriesNumber pgtype.Int4 `db:"series_number" json:"series_number"`
|
|
Tags pgtype.Text `db:"tags" json:"tags"`
|
|
Asin pgtype.Text `db:"asin" json:"asin"`
|
|
DatePublished pgtype.Date `db:"date_published" json:"date_published"`
|
|
Publisher pgtype.Text `db:"publisher" json:"publisher"`
|
|
Contributors pgtype.Text `db:"contributors" json:"contributors"`
|
|
}
|
|
|
|
func (q *Queries) UpdateEbook(ctx context.Context, arg UpdateEbookParams) (Ebooks, error) {
|
|
row := q.db.QueryRow(ctx, UpdateEbook,
|
|
arg.ID,
|
|
arg.Title,
|
|
arg.Author,
|
|
arg.Isbn,
|
|
arg.Description,
|
|
arg.CoverImagePath,
|
|
arg.Series,
|
|
arg.SeriesNumber,
|
|
arg.Tags,
|
|
arg.Asin,
|
|
arg.DatePublished,
|
|
arg.Publisher,
|
|
arg.Contributors,
|
|
)
|
|
var i Ebooks
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.Title,
|
|
&i.Author,
|
|
&i.Isbn,
|
|
&i.Description,
|
|
&i.FilePath,
|
|
&i.FileSize,
|
|
&i.MimeType,
|
|
&i.CoverImagePath,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
&i.Series,
|
|
&i.SeriesNumber,
|
|
&i.Tags,
|
|
&i.Asin,
|
|
&i.DatePublished,
|
|
&i.Publisher,
|
|
&i.Contributors,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const UpdateEbookRating = `-- name: UpdateEbookRating :one
|
|
UPDATE ebook_ratings SET
|
|
rating = $3,
|
|
updated_at = NOW()
|
|
WHERE ebook_id = $1 AND user_id = $2
|
|
RETURNING id, ebook_id, user_id, rating, created_at, updated_at
|
|
`
|
|
|
|
type UpdateEbookRatingParams struct {
|
|
EbookID pgtype.UUID `db:"ebook_id" json:"ebook_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
Rating int32 `db:"rating" json:"rating"`
|
|
}
|
|
|
|
func (q *Queries) UpdateEbookRating(ctx context.Context, arg UpdateEbookRatingParams) (EbookRatings, error) {
|
|
row := q.db.QueryRow(ctx, UpdateEbookRating, arg.EbookID, arg.UserID, arg.Rating)
|
|
var i EbookRatings
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.EbookID,
|
|
&i.UserID,
|
|
&i.Rating,
|
|
&i.CreatedAt,
|
|
&i.UpdatedAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const UpdateEmail = `-- name: UpdateEmail :exec
|
|
UPDATE users SET email = $2, updated_at = NOW() WHERE id = $1
|
|
`
|
|
|
|
type UpdateEmailParams struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
Email string `db:"email" json:"email"`
|
|
}
|
|
|
|
func (q *Queries) UpdateEmail(ctx context.Context, arg UpdateEmailParams) error {
|
|
_, err := q.db.Exec(ctx, UpdateEmail, arg.ID, arg.Email)
|
|
return err
|
|
}
|
|
|
|
const UpdatePassword = `-- name: UpdatePassword :exec
|
|
UPDATE users SET password_hash = $2, updated_at = NOW() WHERE id = $1
|
|
`
|
|
|
|
type UpdatePasswordParams struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
PasswordHash string `db:"password_hash" json:"password_hash"`
|
|
}
|
|
|
|
func (q *Queries) UpdatePassword(ctx context.Context, arg UpdatePasswordParams) error {
|
|
_, err := q.db.Exec(ctx, UpdatePassword, arg.ID, arg.PasswordHash)
|
|
return err
|
|
}
|
|
|
|
const UpdateReadingProgress = `-- name: UpdateReadingProgress :one
|
|
INSERT INTO reading_progress (ebook_id, user_id, current_page, total_pages, last_read_at)
|
|
VALUES ($1, $2, $3, $4, NOW())
|
|
ON CONFLICT (ebook_id, user_id)
|
|
DO UPDATE SET
|
|
current_page = EXCLUDED.current_page,
|
|
total_pages = EXCLUDED.total_pages,
|
|
last_read_at = NOW()
|
|
RETURNING id, ebook_id, user_id, current_page, total_pages, last_read_at
|
|
`
|
|
|
|
type UpdateReadingProgressParams struct {
|
|
EbookID pgtype.UUID `db:"ebook_id" json:"ebook_id"`
|
|
UserID pgtype.UUID `db:"user_id" json:"user_id"`
|
|
CurrentPage pgtype.Int4 `db:"current_page" json:"current_page"`
|
|
TotalPages pgtype.Int4 `db:"total_pages" json:"total_pages"`
|
|
}
|
|
|
|
func (q *Queries) UpdateReadingProgress(ctx context.Context, arg UpdateReadingProgressParams) (ReadingProgress, error) {
|
|
row := q.db.QueryRow(ctx, UpdateReadingProgress,
|
|
arg.EbookID,
|
|
arg.UserID,
|
|
arg.CurrentPage,
|
|
arg.TotalPages,
|
|
)
|
|
var i ReadingProgress
|
|
err := row.Scan(
|
|
&i.ID,
|
|
&i.EbookID,
|
|
&i.UserID,
|
|
&i.CurrentPage,
|
|
&i.TotalPages,
|
|
&i.LastReadAt,
|
|
)
|
|
return i, err
|
|
}
|
|
|
|
const UpdateScanSettings = `-- name: UpdateScanSettings :exec
|
|
UPDATE users SET scan_frequency_minutes = $2, auto_scan_enabled = $3, updated_at = NOW() WHERE id = $1
|
|
`
|
|
|
|
type UpdateScanSettingsParams struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
ScanFrequencyMinutes pgtype.Int4 `db:"scan_frequency_minutes" json:"scan_frequency_minutes"`
|
|
AutoScanEnabled pgtype.Bool `db:"auto_scan_enabled" json:"auto_scan_enabled"`
|
|
}
|
|
|
|
func (q *Queries) UpdateScanSettings(ctx context.Context, arg UpdateScanSettingsParams) error {
|
|
_, err := q.db.Exec(ctx, UpdateScanSettings, arg.ID, arg.ScanFrequencyMinutes, arg.AutoScanEnabled)
|
|
return err
|
|
}
|
|
|
|
const UpdateUserTheme = `-- name: UpdateUserTheme :exec
|
|
UPDATE users SET theme = $2, updated_at = NOW() WHERE id = $1
|
|
`
|
|
|
|
type UpdateUserThemeParams struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
Theme pgtype.Text `db:"theme" json:"theme"`
|
|
}
|
|
|
|
func (q *Queries) UpdateUserTheme(ctx context.Context, arg UpdateUserThemeParams) error {
|
|
_, err := q.db.Exec(ctx, UpdateUserTheme, arg.ID, arg.Theme)
|
|
return err
|
|
}
|
|
|
|
const UpdateUsername = `-- name: UpdateUsername :exec
|
|
UPDATE users SET username = $2, updated_at = NOW() WHERE id = $1
|
|
`
|
|
|
|
type UpdateUsernameParams struct {
|
|
ID pgtype.UUID `db:"id" json:"id"`
|
|
Username string `db:"username" json:"username"`
|
|
}
|
|
|
|
func (q *Queries) UpdateUsername(ctx context.Context, arg UpdateUsernameParams) error {
|
|
_, err := q.db.Exec(ctx, UpdateUsername, arg.ID, arg.Username)
|
|
return err
|
|
}
|