Compare commits

..

No commits in common. "main" and "main" have entirely different histories.
main ... main

13 changed files with 138 additions and 323 deletions

View File

@ -39,10 +39,10 @@ func GenWhitelist(db *gorm.DB, authorsFilePath string) {
continue
}
if firstLine {
whitelist.WriteString(book.ID.String())
whitelist.WriteString(strconv.FormatUint(book.ID, 10))
firstLine = false
} else {
whitelist.WriteString("\n" + book.ID.String())
whitelist.WriteString("\n" + strconv.FormatUint(book.ID, 10))
}
}
}

View File

@ -11,7 +11,6 @@ import (
"encoding/pem"
"encoding/xml"
"errors"
"fmt"
"image"
"image/color"
"image/draw"
@ -53,7 +52,7 @@ type Search struct {
Books []APIBook `json:"books"`
}
type Person struct {
Id uuid.UUID `json:"id"`
Id int `json:"id"`
Name string `json:"name"`
FirstName string `json:"firstName"`
MiddleName *string `json:"middleName"`
@ -81,7 +80,7 @@ type Books struct {
Filetype string `json:"filetype"`
}
type ShortAPICollection struct {
ID uuid.UUID `json:"id"`
ID uint `json:"id"`
Name string `json:"name"`
}
@ -160,12 +159,12 @@ func AuthMiddleware(publicKey *rsa.PublicKey) gin.HandlerFunc {
ctx.AbortWithStatus(401)
return
}
userIdUUID, err := uuid.Parse(userId)
userIdUint, err := strconv.ParseUint(userId, 10, 64)
if err != nil {
ctx.AbortWithStatus(401)
return
}
ctx.Set("id", userIdUUID.String())
ctx.Set("id", uint(userIdUint))
ctx.Set("scopes", claims.Scopes)
ctx.Next()
}
@ -203,12 +202,12 @@ type Claims struct {
jwt.RegisteredClaims
}
func GenerateJWT(scopes string, userId uuid.UUID, priv *rsa.PrivateKey) (string, error) {
func GenerateJWT(scopes string, userId uint64, priv *rsa.PrivateKey) (string, error) {
claims := &Claims{
Scopes: scopes,
RegisteredClaims: jwt.RegisteredClaims{
ExpiresAt: jwt.NewNumericDate(time.Now().Add(time.Hour * 72)),
Subject: userId.String(),
Subject: strconv.FormatUint(userId, 10),
},
}
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
@ -305,22 +304,22 @@ func main() {
&schemas.Permission{},
)
log.Println("create indexes")
db.Exec("CREATE VIRTUAL TABLE IF NOT EXISTS books_indices USING fts5(book_id, title);")
db.Exec("CREATE VIRTUAL TABLE IF NOT EXISTS books_indices USING fts5(title, content='books', content_rowid='id');")
db.Exec(`
CREATE TRIGGER IF NOT EXISTS books_ai AFTER INSERT ON books BEGIN
INSERT INTO books_indices(book_id, title) VALUES (new.id, new.title);
INSERT INTO books_indices(rowid, title) VALUES (new.id, new.title);
END;
`)
db.Exec(`
CREATE TRIGGER IF NOT EXISTS books_ad AFTER DELETE ON books BEGIN
DELETE FROM books_indices WHERE book_id = old.id;
DELETE FROM books_indices WHERE rowid = old.id;
END;
`)
db.Exec(`
CREATE TRIGGER IF NOT EXISTS books_au AFTER UPDATE ON books BEGIN
UPDATE books_indices SET title = new.title WHERE book_id = old.id;
UPDATE books_indices SET title = new.title WHERE rowid = old.id;
END;
`)
log.Println("migrated!")
@ -358,9 +357,10 @@ func main() {
var books []APIBook
q, isTitle := c.GetQuery("q")
author, isAuthor := c.GetQuery("author")
collection, isCollection := c.GetQuery("collection")
collectionStr, isCollection := c.GetQuery("collection")
limitStr, _ := c.GetQuery("limit")
limit, _ := strconv.ParseInt(limitStr, 10, 64)
collection, _ := strconv.ParseInt(collectionStr, 10, 64)
offsetStr, _ := c.GetQuery("offset")
offset, _ := strconv.ParseInt(offsetStr, 10, 64)
_, _ = author, q
@ -370,12 +370,10 @@ func main() {
Table("books").
Joins("JOIN collection_books ON collection_books.book_id = books.id").
Joins("JOIN collections ON collections.id = collection_books.collection_id")
if strings.Split(collection, "-")[0] == "pub" { // if collection token
fmt.Println("collection link")
if len(strings.Split(collectionStr, "-")) > 1 { // if collection token
query = query.
Where("collections.link = ?", collection)
Where("collections.link = ?", collectionStr)
} else {
fmt.Println("collection")
query = query.
Where("collections.id = ?", collection)
}
@ -393,7 +391,7 @@ func main() {
query = db.
Find(&BooksIndex{}).
Where("books_indices.title MATCH ?", q+"*").
Joins("JOIN books ON books.id=books_indices.book_id").
Joins("JOIN books ON books.id=books_indices.rowid").
Order("rank")
} else if isAuthor && !isTitle {
query = db.
@ -432,11 +430,12 @@ func main() {
})
})
sec.GET("/author/:id", func(ctx *gin.Context) {
authorID, err := uuid.Parse(ctx.Param("id"))
authorID, err := strconv.Atoi(ctx.Param("id"))
if err != nil {
ctx.AbortWithError(400, err)
return
}
_ = authorID
var authorObj schemas.Author
db.Find(&authorObj, "id = ?", authorID)
authorName := personToString(authorObj.FirstName, authorObj.MiddleName, authorObj.LastName)
@ -459,7 +458,7 @@ func main() {
var authors []Person
for _, author := range book.Authors {
authors = append(authors, Person{
Id: author.ID,
Id: int(author.ID),
Name: personToString(author.FirstName, author.MiddleName, author.LastName),
FirstName: author.FirstName,
MiddleName: author.MiddleName,
@ -474,7 +473,7 @@ func main() {
translators = &newSlice
}
*translators = append(*translators, Person{
Id: translator.ID,
Id: int(translator.ID),
Name: personToString(translator.FirstName, translator.MiddleName, translator.LastName),
})
}
@ -493,7 +492,7 @@ func main() {
genreName = *genre.Name
}
*genres = append(*genres, Person{
Id: genre.ID,
Id: int(genre.ID),
Name: genreName,
})
}
@ -761,7 +760,7 @@ func main() {
ctx.AbortWithStatus(403)
return
}
token, _ := GenerateJWT("search books collections read", targetUser.ID, priv)
token, _ := GenerateJWT("search books collections read", uint64(targetUser.ID), priv)
ctx.SetCookie("token", token, 60*60*72, "/", "", false, false)
})
sec.GET("/ping", func(ctx *gin.Context) {
@ -876,11 +875,10 @@ func main() {
ctx.Data(200, "image/webp", decodedImage)
})
sec.GET("/user", func(ctx *gin.Context) {
userId := ctx.MustGet("id").(string)
userIdUUID := uuid.MustParse(userId)
if userIdUUID == uuid.Nil {
userId := ctx.MustGet("id").(uint)
if userId == 0 {
ctx.JSON(200, APIUser{
ID: uuid.Nil,
ID: 0,
Username: "guest",
Name: "Гость",
})
@ -891,33 +889,31 @@ func main() {
ctx.JSON(200, user)
})
sec.POST("/user/collection", func(ctx *gin.Context) {
userId := ctx.MustGet("id").(string)
userIdUUID := uuid.MustParse(userId)
userId := ctx.MustGet("id").(uint)
var requestBody struct {
Link string
}
ctx.BindJSON(&requestBody)
var collection schemas.Collection
db.Where("link = ?", requestBody.Link).Take(&collection)
if collection.ID == uuid.Nil {
if collection.ID == 0 {
ctx.AbortWithStatus(404)
return
}
db.
Model(&schemas.Permission{ID: userIdUUID}).
Model(&schemas.Permission{ID: userId}).
Association("ViewCollections").
Append(&collection)
ctx.Status(204)
})
sec.DELETE("/user/collection/:id", func(ctx *gin.Context) {
// no 404 error, hahaha wtf
userId := ctx.MustGet("id").(string)
userIdUUID := uuid.MustParse(userId)
userId := ctx.MustGet("id").(uint)
collId := ctx.Param("id")
var collection schemas.Collection
db.Find(&collection, "id = ?", collId)
db.Find(&collection, collId)
db.
Model(&schemas.Permission{ID: userIdUUID}).
Model(&schemas.Permission{ID: userId}).
Association("ViewCollections").
Delete(&collection)
ctx.Status(204)
@ -966,16 +962,15 @@ func main() {
// }
// })
sec.GET("/collection", func(ctx *gin.Context) {
userId := ctx.MustGet("id").(string)
userIdUUID := uuid.MustParse(userId)
userId := ctx.MustGet("id")
collections := []struct {
ID uuid.UUID `json:"id"`
ID uint `json:"id"`
Name string `json:"name"`
}{}
db.
Model(&schemas.Permission{ID: userIdUUID}).
Model(&schemas.Permission{ID: userId.(uint)}).
Association("ViewCollections").
Find(&collections)
// db.Model(&schemas.Collection{}).Find(&collections, &schemas.Collection{UserID: userId.(uint)})
@ -983,7 +978,7 @@ func main() {
})
sec.GET("/collection/:id", func(ctx *gin.Context) {
isToken := false
if strings.Split(ctx.Param("id"), "-")[0] == "pub" {
if len(strings.Split(ctx.Param("id"), "-")) > 1 {
isToken = true
}
collection := APICollection{}
@ -997,7 +992,7 @@ func main() {
res = db.
Table("collections"). // what if delete this string?..
Joins("JOIN view_collections ON view_collections.collection_id = collections.id").
Where("view_collections.permission_id = ?", ctx.MustGet("id").(string)).
Where("view_collections.permission_id = ?", ctx.MustGet("id").(uint)).
Where("id = ?", ctx.Param("id")).
Preload("Creator").
Find(&collection)
@ -1009,8 +1004,6 @@ func main() {
ctx.JSON(200, collection)
})
sec.PUT("/collection", func(ctx *gin.Context) {
userId := ctx.MustGet("id").(string)
userIdUUID := uuid.MustParse(userId)
var requestBody struct {
Name string
}
@ -1022,14 +1015,14 @@ func main() {
linkUUID := uuid.New()
newCollection := schemas.Collection{
Name: requestBody.Name,
Creator: schemas.User{ID: userIdUUID},
Creator: schemas.User{ID: ctx.MustGet("id").(uint)},
Link: linkUUID.String(),
Created: time.Now(),
Modified: time.Now(),
}
db.Create(&newCollection)
db.
Model(&schemas.Permission{ID: userIdUUID}).
Model(&schemas.Permission{ID: ctx.MustGet("id").(uint)}).
Association("ViewCollections").
Append(&newCollection)
ctx.JSON(200, gin.H{"id": newCollection.ID})
@ -1038,13 +1031,13 @@ func main() {
var requestBody struct {
BookID string `json:"book_id"`
}
collectionId, err := uuid.Parse(ctx.Param("id"))
collectionId, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
ctx.AbortWithError(400, err)
return
}
ctx.BindJSON(&requestBody)
bookID, err := uuid.Parse(requestBody.BookID)
bookID, err := strconv.ParseUint(requestBody.BookID, 10, 64)
if err != nil {
ctx.AbortWithError(400, err)
return
@ -1062,11 +1055,11 @@ func main() {
return
}
collectionBookAssociation := db.Model(&schemas.Collection{
ID: collectionId,
ID: uint(collectionId),
}).Association("Books")
var associatedBook schemas.Book
collectionBookAssociation.Find(&associatedBook, bookID)
if associatedBook.ID != uuid.Nil {
if associatedBook.ID != 0 {
// если книга уже есть в ассоциациях - удаляем
err := collectionBookAssociation.Delete(associatedBook)
log.Println(err)
@ -1086,36 +1079,32 @@ func main() {
})
sec.DELETE("/collection/:id", func(ctx *gin.Context) {
userId := ctx.MustGet("id").(string)
userIdUUID := uuid.MustParse(userId)
collectionId, err := uuid.Parse(ctx.Param("id"))
collectionId, err := strconv.ParseUint(ctx.Param("id"), 10, 64)
if err != nil {
ctx.AbortWithError(400, err)
return
}
var collection schemas.Collection
db.Take(&collection, collectionId)
if collection.UserID == uuid.Nil {
if collection.UserID == 0 {
ctx.AbortWithStatusJSON(404, gin.H{"err": "collection not found"})
return
}
if collection.UserID != userIdUUID {
if collection.UserID != ctx.MustGet("id").(uint) {
ctx.AbortWithStatus(403)
return
}
db.Model(&schemas.Collection{
ID: collectionId,
ID: uint(collectionId),
}).Association("Books").Clear()
db.
Model(&schemas.Permission{ID: userIdUUID}).
Model(&schemas.Permission{ID: ctx.MustGet("id").(uint)}).
Association("ViewCollections").
Delete(&schemas.Collection{ID: collectionId})
Delete(&schemas.Collection{ID: uint(collectionId)})
db.Delete(&schemas.Collection{}, collectionId)
ctx.Status(204)
})
sec.POST("/book/upload", func(ctx *gin.Context) {
userId := ctx.MustGet("id").(string)
userIdUUID := uuid.MustParse(userId)
form, err := ctx.MultipartForm()
if err != nil {
ctx.String(400, "Форму ты сломал: %s", err.Error())
@ -1130,7 +1119,7 @@ func main() {
fileReader, _ := file.Open()
fileData, _ := io.ReadAll(fileReader)
contentType := file.Header.Get("Content-Type")
var bookID uuid.UUID
var bookID uint64
bookUUID := uuid.NewString()
switch contentType {
case "application/pdf":
@ -1216,26 +1205,26 @@ func main() {
}
var collection schemas.Collection
res := db.Where(&schemas.Collection{Name: "Загрузки", UserID: userIdUUID}).First(&collection)
res := db.Where(&schemas.Collection{Name: "Загрузки", UserID: ctx.MustGet("id").(uint)}).First(&collection)
if res.RowsAffected == 0 {
linkUUID := uuid.New()
newCollection := schemas.Collection{
Name: "Загрузки",
Creator: schemas.User{ID: userIdUUID},
Creator: schemas.User{ID: ctx.MustGet("id").(uint)},
Link: linkUUID.String(),
Created: time.Now(),
Modified: time.Now(),
}
db.Create(&newCollection)
db.
Model(&schemas.Permission{ID: userIdUUID}).
Model(&schemas.Permission{ID: ctx.MustGet("id").(uint)}).
Association("ViewCollections").
Append(&newCollection)
db.Where(&schemas.Collection{Name: "Загрузки", UserID: userIdUUID}).First(&collection)
db.Where(&schemas.Collection{Name: "Загрузки", UserID: ctx.MustGet("id").(uint)}).First(&collection)
}
collectionBookAssociation := db.Model(&schemas.Collection{
ID: collection.ID,
ID: uint(collection.ID),
}).Association("Books")
// если книги еще нет в ассоциациях - создаем
err = collectionBookAssociation.Append(&schemas.Book{ID: bookID})
@ -1280,7 +1269,7 @@ func main() {
}
type APIAuthor struct {
ID uuid.UUID `json:"id"`
ID uint64 `json:"id"`
Key string `json:"key"`
FirstName string `json:"firstName"`
MiddleName string `json:"middleName"`
@ -1292,7 +1281,7 @@ func (APIAuthor) TableName() string {
}
type APIBook struct {
ID uuid.UUID `json:"id"`
ID uint `json:"id"`
Title string `json:"title"`
Authors []APIAuthor `gorm:"many2many:BookAuthor;joinForeignKey:book_id;joinReferences:author_id" json:"authors"`
Filetype string `json:"filetype"`
@ -1303,7 +1292,7 @@ func (APIBook) TableName() string {
}
type APIUser struct {
ID uuid.UUID `gorm:"primaryKey" json:"id"`
ID uint64 `gorm:"primaryKey" json:"id"`
Name string `json:"name"`
Username string `json:"username"`
Collections []ShortAPICollection `json:"collections" gorm:"ForeignKey:id;"`
@ -1315,10 +1304,10 @@ func (APIUser) TableName() string {
}
type APICollection struct {
ID uuid.UUID `gorm:"primaryKey" json:"id"`
ID uint `gorm:"primaryKey" json:"id"`
Link string `gorm:"uniqueIndex" json:"link"`
Name string `json:"name"`
UserID uuid.UUID `json:"user_id"`
UserID uint `json:"user_id"`
Creator APIUser `gorm:"foreignKey:UserID" json:"creator"`
//Books []APIBook `gorm:"many2many:CollectionBook;joinReferences:book_id;joinForeignKey:collection_id" json:"books"`
Created time.Time `json:"created"`

View File

@ -5,7 +5,6 @@ import (
"io"
"mi6e4ka/yabl-api/schemas"
"github.com/google/uuid"
"golang.org/x/net/html/charset"
"gorm.io/gorm"
)
@ -67,7 +66,7 @@ func nilCheck(nilString *string) string {
return *nilString
}
func FB2toDB(tx *gorm.DB, book FB2) uuid.UUID {
func FB2toDB(tx *gorm.DB, book FB2) uint64 {
var genres *[]schemas.Genre
//book.Genres = nil
if book.Genres != nil {

View File

@ -1,41 +1,22 @@
package schemas
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
import "time"
type Language struct {
ID uuid.UUID
ID uint `gorm:",unique;autoIncrement:true"`
Code string `gorm:"primaryKey;index:,unique"`
ISO *string
}
func (b *Language) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Genre struct {
ID uuid.UUID
ID uint `gorm:",unique;autoIncrement:true"`
RawTag string `gorm:"index:,unique"`
Tag *string
Name *string
}
func (b *Genre) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Author struct {
ID uuid.UUID `gorm:"primaryKey;index:,unique;autoIncrement:true"`
ID uint `gorm:"primaryKey;index:,unique;autoIncrement:true"`
Key string `gorm:",unique"`
FirstName string
MiddleName *string
@ -45,15 +26,8 @@ type Author struct {
Books []Book `gorm:"many2many:BookAuthor"`
}
func (b *Author) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type User struct {
ID uuid.UUID `gorm:"primaryKey"`
ID uint `gorm:"primaryKey"`
Username string `gorm:"autoIncrement:false;index:,unique"`
Avatar *string
Name *string
@ -68,54 +42,26 @@ type User struct {
BookShelf []ReaderBook
}
func (b *User) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Translator struct {
ID uuid.UUID `gorm:"primaryKey;index:,unique"`
ID uint `gorm:"primaryKey;index:,unique;autoIncrement:true"`
Key string `gorm:",unique"`
FirstName string
MiddleName *string
LastName *string
}
func (b *Translator) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Sequence struct {
ID uuid.UUID `gorm:",unique"`
ID uint `gorm:",unique;autoIncrement:true"`
Name string `gorm:"primaryKey;index:,unique"`
}
func (b *Sequence) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Publisher struct {
ID uuid.UUID `gorm:",unique;autoIncrement:true"`
ID uint `gorm:",unique;autoIncrement:true"`
Name string `gorm:"primaryKey;index:,unique"`
}
func (b *Publisher) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Book struct {
ID uuid.UUID `gorm:"primaryKey"`
ID uint64 `gorm:"primaryKey"`
Title string
Authors []Author `gorm:"many2many:BookAuthor;References:ID"`
Lang *string
@ -151,72 +97,42 @@ type Book struct {
ExternalCover *string
}
func (b *Book) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
// type Filetype struct {
// ID uint `gorm:"primaryKey"`
// Filetype string `gorm:"uniqueIndex"`
// Name string
// }
type ReaderBook struct {
ID uuid.UUID `gorm:"primaryKey"`
UserID uuid.UUID
BookID uuid.UUID
ID uint `gorm:"primaryKey"`
UserID uint
BookID uint
Book Book `gorm:"foreignKey:BookID"`
Progress float64
LastRead time.Time
}
func (b *ReaderBook) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Collection struct {
ID uuid.UUID `gorm:"primaryKey"`
ID uint `gorm:"primaryKey"`
Link string `gorm:"uniqueIndex"`
Name string
UserID uuid.UUID
UserID uint
Creator User `gorm:"foreignKey:UserID"`
Books []Book `gorm:"many2many:CollectionBook;"`
Created time.Time
Modified time.Time
}
func (b *Collection) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Share struct {
ID uuid.UUID `gorm:"primaryKey"`
ID uint `gorm:"primaryKey"`
Token string `gorm:"uniqueIndex"`
CreatedAt time.Time
ExpiredAt *time.Time
BookID *uuid.UUID
BookID *uint
Book *Book
UserID uuid.UUID
UserID uint
User User
}
func (b *Share) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Permission struct {
ID uuid.UUID `gorm:"primaryKey"`
ID uint `gorm:"primaryKey"`
User User `gorm:"foreignKey:ID"`
EditBooks []Book `gorm:"many2many:EditableBook;"`
BooksWhitelist *[]Book `gorm:"many2many:WhitelistedBook;"`
@ -227,14 +143,6 @@ type Permission struct {
CanUpload bool
CanCreateCollections bool
}
func (b *Permission) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Settings struct {
LibPath string
ReadOnly bool

View File

@ -3,7 +3,6 @@ module book-tools
go 1.24.4
require (
github.com/google/uuid v1.6.0
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/joho/godotenv v1.5.1

View File

@ -1,5 +1,3 @@
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=

View File

@ -13,7 +13,6 @@ import (
"sync/atomic"
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
@ -64,7 +63,7 @@ func (a *App) Run() error {
log.Printf("Failed add book to transaction: %v", tx.Error)
return
}
if bookID != uuid.Nil {
if bookID > 0 {
addedBooks++
}
}

View File

@ -4,7 +4,6 @@ import (
"encoding/xml"
"io"
"github.com/google/uuid"
"golang.org/x/net/html/charset"
"gorm.io/gorm"
)
@ -66,7 +65,7 @@ func nilCheck(nilString *string) string {
return *nilString
}
func FB2toDB(tx *gorm.DB, book FB2) uuid.UUID {
func FB2toDB(tx *gorm.DB, book FB2) uint64 {
var genres *[]Genre
//book.Genres = nil
if book.Genres != nil {

View File

@ -1,41 +1,22 @@
package reaper
import (
"time"
"github.com/google/uuid"
"gorm.io/gorm"
)
import "time"
type Language struct {
ID uuid.UUID
ID uint `gorm:",unique;autoIncrement:true"`
Code string `gorm:"primaryKey;index:,unique"`
ISO *string
}
func (b *Language) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Genre struct {
ID uuid.UUID
ID uint `gorm:",unique;autoIncrement:true"`
RawTag string `gorm:"index:,unique"`
Tag *string
Name *string
}
func (b *Genre) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Author struct {
ID uuid.UUID `gorm:"primaryKey;index:,unique;autoIncrement:true"`
ID uint `gorm:"primaryKey;index:,unique;autoIncrement:true"`
Key string `gorm:",unique"`
FirstName string
MiddleName *string
@ -45,15 +26,8 @@ type Author struct {
Books []Book `gorm:"many2many:BookAuthor"`
}
func (b *Author) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type User struct {
ID uuid.UUID `gorm:"primaryKey"`
ID uint `gorm:"primaryKey"`
Username string `gorm:"autoIncrement:false;index:,unique"`
Avatar *string
Name *string
@ -68,54 +42,26 @@ type User struct {
BookShelf []ReaderBook
}
func (b *User) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Translator struct {
ID uuid.UUID `gorm:"primaryKey;index:,unique"`
ID uint `gorm:"primaryKey;index:,unique;autoIncrement:true"`
Key string `gorm:",unique"`
FirstName string
MiddleName *string
LastName *string
}
func (b *Translator) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Sequence struct {
ID uuid.UUID `gorm:",unique"`
ID uint `gorm:",unique;autoIncrement:true"`
Name string `gorm:"primaryKey;index:,unique"`
}
func (b *Sequence) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Publisher struct {
ID uuid.UUID `gorm:",unique;autoIncrement:true"`
ID uint `gorm:",unique;autoIncrement:true"`
Name string `gorm:"primaryKey;index:,unique"`
}
func (b *Publisher) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Book struct {
ID uuid.UUID `gorm:"primaryKey"`
ID uint64 `gorm:"primaryKey"`
Title string
Authors []Author `gorm:"many2many:BookAuthor;References:ID"`
Lang *string
@ -151,48 +97,26 @@ type Book struct {
ExternalCover *string
}
func (b *Book) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
// type Filetype struct {
// ID uint `gorm:"primaryKey"`
// Filetype string `gorm:"uniqueIndex"`
// Name string
// }
type ReaderBook struct {
ID uuid.UUID `gorm:"primaryKey"`
UserID uuid.UUID
BookID uuid.UUID
ID uint `gorm:"primaryKey"`
UserID uint
BookID uint
Book Book `gorm:"foreignKey:BookID"`
Progress float64
LastRead time.Time
}
func (b *ReaderBook) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}
type Collection struct {
ID uuid.UUID `gorm:"primaryKey"`
ID uint `gorm:"primaryKey"`
Link string `gorm:"uniqueIndex"`
Name string
UserID uuid.UUID
UserID uint
Creator User `gorm:"foreignKey:UserID"`
Books []Book `gorm:"many2many:CollectionBook;"`
Created time.Time
Modified time.Time
}
func (b *Collection) BeforeCreate(tx *gorm.DB) (err error) {
if b.ID == uuid.Nil {
b.ID = uuid.New()
}
return
}

View File

@ -72,7 +72,7 @@ const BookPage = () => {
}
loadImgFromCache();
let localBook = await getBook(id);
if (window.onLine /*&& !localBook*/) {
if (window.onLine && !localBook) {
axios
.get("/book/" + id)
.then((res) => setBookInfo(res.data))

View File

@ -6,13 +6,12 @@
.main_down_menu {
display: none;
position: absolute;
position: fixed;
bottom: 0;
left: 0;
width: calc(100%);
width: 100%;
justify-content: space-around;
background-color: var(--md-sys-color-background);
padding: 5px 0 10px 0;
padding: 10px 0;
z-index: 4;
}
.main_down_menu_item {
@ -39,7 +38,6 @@
.main_page_container {
display: flex;
gap: 50px;
height: 100%;
}
@media screen and (max-width: 470px) { /* кнопки в столбик */

View File

@ -23,7 +23,7 @@ const AccountPage = () => {
icon: "shelves",
},
{
name: "Загрузить",
name: "Загрузить книгу",
path: "/upload",
icon: "upload",
},

View File

@ -57,10 +57,11 @@ function UploadBook() {
setUploadStatuses((prev) => ({ ...prev, [i]: 1 }));
console.log(uploadStatuses);
} else {
toast.error("Ошибка при загрузке книги");
toast("Ошибка на сервере, go дебажить.");
}
} catch (err) {
toast.error("Ошибка при загрузке книги");
console.error("Ошибка:", err);
toast("Шатался интернет или сервер умер.");
}
}
@ -71,9 +72,11 @@ function UploadBook() {
return <span>Недоступно оффлайн</span>;
}
return (
<div className="flex flex-col items-center justify-center h-full w-full">
<div className="flex flex-col items-center justify-center h-screen">
<h1 className="text-2xl font-bold mb-4">Загрузка литературы</h1>
<div
className={`flex items-center justify-around w-[calc(100%-32px)] max-w-lg h-50 mb-4 px-4 rounded-xl flex-col gap-1 transition-colors duration-200 ${uploading ? 'cursor-wait' : 'cursor-pointer'} ${
className={`flex items-center justify-around w-full max-w-lg h-50 mb-4 rounded-xl flex-col gap-1 px-4 border-2 border-dashed transition-colors duration-200 cursor-pointer border-(--md-sys-color-outline) ${
isDragging
? "bg-(--md-sys-color-surface-variant)"
: "bg-(--md-sys-color-inverse-on-surface)"
@ -84,8 +87,8 @@ function UploadBook() {
onDragLeave={handleDragLeave}
>
<>
<span className="font-bold text-center">Перетащите файл или нажмите для выбора</span>
<IconButton className="w-24 h-24" disabled={uploading}>
<span className="font-bold">Перетащи файл сюда или кликни</span>
<IconButton className="w-24 h-24">
<Icon className="text-6xl w-24 h-24">upload_file</Icon>
</IconButton>
<span className="text-sm">Поддерживается .fb2 и .pdf</span>
@ -96,14 +99,13 @@ function UploadBook() {
accept=".fb2,.pdf"
ref={fileSelectorRef}
className="hidden"
disabled={uploading}
onChange={handleFileChange}
/>
</div>
<div className={`w-[calc(100%-32px)] max-w-lg bg-(--md-sys-color-inverse-on-surface) flex p-4 rounded-2xl flex-col max-h-60 overflow-scroll gap-3 mb-4 ${uploadedFiles.length === 0 ? 'hidden' : ''}`}>
<div className="w-full max-w-lg bg-(--md-sys-color-surface-variant) flex p-[18px] rounded-2xl flex-col max-h-60 overflow-scroll gap-3 mb-4">
{uploadedFiles.length === 0 ? <span>Нечего загружать</span> : <></>}
{uploadedFiles.map((file, i) => (
<div className="flex justify-between items-center" key={i}>
<div className="flex justify-between" key={i}>
<span className="truncate w-[calc(100%-42px)] inline-block">
{file.name}
</span>
@ -128,7 +130,7 @@ function UploadBook() {
))}
</div>
<FilledButton onClick={handleUpload} disabled={uploading || uploadedFiles.length===0}>
<FilledButton onClick={handleUpload} disabled={uploading}>
Загрузить
</FilledButton>
</div>