209 lines
5.1 KiB
Go
209 lines
5.1 KiB
Go
package database
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
)
|
|
|
|
type Book struct {
|
|
Id string
|
|
Title string
|
|
Authors []string `sql:"authors" pg:",array"`
|
|
Contributor string
|
|
Publisher string
|
|
Description string
|
|
Tags []string `sql:"tags" pg:",array"`
|
|
Date string
|
|
Lang string
|
|
Isbn string
|
|
FileSize int
|
|
Cover bool
|
|
Active bool
|
|
UploadDate time.Time
|
|
Tsv string
|
|
//BadQuality int `bad_quality`
|
|
BadQualityReporters []string `sql:"-"` // TODO: deprecate??
|
|
}
|
|
|
|
// TODO: missing history
|
|
|
|
// AddBook to the database
|
|
func (db *pgDB) AddBook(book Book) error {
|
|
emptyTime := time.Time{}
|
|
if book.UploadDate == emptyTime {
|
|
book.UploadDate = time.Now()
|
|
}
|
|
|
|
return db.sql.Create(&book)
|
|
}
|
|
|
|
// GetBooks matching query
|
|
func (db *pgDB) GetBooks(query string, length int, start int) (books []Book, num int, err error) {
|
|
return db.getBooks(true, query, length, start)
|
|
}
|
|
|
|
// TODO: func (db *pgDB) GetBooksIter() Iter {
|
|
|
|
func (db *pgDB) GetNewBooks(query string, length int, start int) (books []Book, num int, err error) {
|
|
return db.getBooks(false, query, length, start)
|
|
}
|
|
|
|
func (db *pgDB) getBooks(active bool, query string, length int, start int) (books []Book, num int, err error) {
|
|
sqlQuery := db.sql.Model(&books)
|
|
|
|
searchCondition := "active = "
|
|
if active {
|
|
searchCondition = "true"
|
|
} else {
|
|
searchCondition = "false"
|
|
}
|
|
|
|
params := []interface{}{}
|
|
textQuery, columnQuerys := buildQuery(query)
|
|
for _, c := range columnQuerys {
|
|
searchCondition = searchCondition + " AND " + c.column + " ILIKE ?"
|
|
params = append(params, c.value)
|
|
}
|
|
if textQuery != "" {
|
|
searchCondition = searchCondition + " AND to_tsquery(?) @@ tsv"
|
|
params = append(params, textQuery)
|
|
}
|
|
sqlQuery = sqlQuery.Where(searchCondition, params...)
|
|
|
|
if textQuery != "" {
|
|
sqlQuery = sqlQuery.Order("ts_rank(tsv, to_tsquery(?)) DESC, upload_date DESC", textQuery)
|
|
} else {
|
|
sqlQuery = sqlQuery.Order("upload_date DESC")
|
|
}
|
|
|
|
num, err = sqlQuery.
|
|
Offset(start).
|
|
Limit(length).
|
|
SelectAndCountEstimate(100)
|
|
return books, num, err
|
|
}
|
|
|
|
func (db *pgDB) GetBookId(id string) (Book, error) {
|
|
var book Book
|
|
err := db.sql.Model(&book).
|
|
Where("id = ?", id).
|
|
Select()
|
|
return book, err
|
|
}
|
|
|
|
func (db *pgDB) DeleteBook(id string) error {
|
|
_, err := db.sql.Model(&Book{}).
|
|
Where("id = ?", id).
|
|
Delete()
|
|
return err
|
|
}
|
|
|
|
func (db *pgDB) UpdateBook(id string, data map[string]interface{}) error {
|
|
setCondition := ""
|
|
params := []interface{}{}
|
|
for col, val := range data {
|
|
colValid := false
|
|
for _, name := range []string{"title", "authors", "contributor", "publisher",
|
|
"description", "tags", "date", "lang", "isbn"} {
|
|
if col == name {
|
|
colValid = true
|
|
break
|
|
}
|
|
}
|
|
if !colValid {
|
|
continue
|
|
}
|
|
|
|
if len(setCondition) != 0 {
|
|
setCondition += ", "
|
|
}
|
|
setCondition += col + " = ?"
|
|
params = append(params, val)
|
|
}
|
|
_, err := db.sql.Model(&Book{}).
|
|
Set(setCondition, params...).
|
|
Where("id = ?", id).
|
|
Update()
|
|
return err
|
|
}
|
|
|
|
func (db *pgDB) FlagBadQuality(id string, user string) error {
|
|
// TODO: delete me
|
|
return nil
|
|
}
|
|
|
|
func (db *pgDB) ActiveBook(id string) error {
|
|
uploadDate := time.Now()
|
|
_, err := db.sql.Model(&Book{}).
|
|
Set("active = true, upload_date = ? ", uploadDate).
|
|
Where("id = ?", id).
|
|
Update()
|
|
return err
|
|
}
|
|
|
|
func (db *pgDB) IsBookActive(id string) bool {
|
|
var active []bool
|
|
err := db.sql.Model(&Book{}).
|
|
Column("active").
|
|
Where("id = ?", id).
|
|
Select(&active)
|
|
if err != nil || len(active) != 1 {
|
|
return false
|
|
}
|
|
return active[0]
|
|
}
|
|
|
|
type columnq struct {
|
|
column string
|
|
value string
|
|
}
|
|
|
|
func buildQuery(query string) (string, []columnq) {
|
|
textQuery := ""
|
|
columnQuerys := []columnq{}
|
|
words := strings.Split(query, " ")
|
|
for _, w := range words {
|
|
if w == "" {
|
|
continue
|
|
}
|
|
tag := strings.SplitN(w, ":", 2)
|
|
if len(tag) > 1 && tag[1] != "" {
|
|
value := strings.Replace(tag[1], "%", "\\%", 0)
|
|
value = strings.Replace(value, "_", "\\_", 0)
|
|
expr := "%" + value + "%"
|
|
switch tag[0] {
|
|
case "lang":
|
|
columnQuerys = append(columnQuerys, columnq{"lang", value})
|
|
case "author":
|
|
columnQuerys = append(columnQuerys, columnq{"array_to_string(authors, ' ')", expr})
|
|
case "title":
|
|
columnQuerys = append(columnQuerys, columnq{"title", expr})
|
|
case "contributor":
|
|
columnQuerys = append(columnQuerys, columnq{"contributor", expr})
|
|
case "publisher":
|
|
columnQuerys = append(columnQuerys, columnq{"publisher", expr})
|
|
case "subject":
|
|
expr = strings.ToLower(expr)
|
|
columnQuerys = append(columnQuerys, columnq{"array_to_string(tags, ' ')", expr})
|
|
case "tag":
|
|
expr = strings.ToLower(expr)
|
|
columnQuerys = append(columnQuerys, columnq{"array_to_string(tag, ' ')", expr})
|
|
case "isbn":
|
|
columnQuerys = append(columnQuerys, columnq{"isbn", expr})
|
|
case "description":
|
|
columnQuerys = append(columnQuerys, columnq{"description", expr})
|
|
}
|
|
} else {
|
|
if len(textQuery) != 0 {
|
|
lastChar := textQuery[len(textQuery)-1:]
|
|
if w != "&" && w != "|" && lastChar != "&" && lastChar != "|" {
|
|
textQuery += " | "
|
|
} else {
|
|
textQuery += " "
|
|
}
|
|
}
|
|
textQuery += w
|
|
}
|
|
}
|
|
return textQuery, columnQuerys
|
|
}
|