2017-05-05 16:39:15 +02:00
package search
2017-05-06 12:41:48 +02:00
import (
"net/http"
2017-05-05 16:39:15 +02:00
"strconv"
"strings"
2017-05-08 15:50:18 +02:00
"unicode"
"unicode/utf8"
2017-05-09 01:56:57 +02:00
"github.com/ewhal/nyaa/model"
"github.com/ewhal/nyaa/service/torrent"
"github.com/ewhal/nyaa/util/log"
2017-05-05 16:39:15 +02:00
)
2017-05-09 13:31:58 +02:00
type Status uint8
const (
ShowAll Status = iota
FilterRemakes
Trusted
APlus
)
type SortMode uint8
const (
ID SortMode = iota
Name
Date
Downloads
Size
)
type Category struct {
Main , Sub uint8
}
func ( c Category ) String ( ) ( s string ) {
if c . Main != 0 {
s += strconv . Itoa ( int ( c . Main ) )
}
s += "_"
if c . Sub != 0 {
s += strconv . Itoa ( int ( c . Sub ) )
}
return
}
2017-05-05 16:39:15 +02:00
type SearchParam struct {
2017-05-09 13:31:58 +02:00
Order bool // True means acsending
Status Status
Sort SortMode
Category Category
Max uint
2017-05-06 12:41:48 +02:00
Query string
2017-05-05 16:39:15 +02:00
}
2017-05-09 13:31:58 +02:00
func SearchByQuery ( r * http . Request , pagenum int ) ( search SearchParam , tor [ ] model . Torrents , count int , err error ) {
max , err := strconv . ParseUint ( r . URL . Query ( ) . Get ( "max" ) , 10 , 32 )
if err != nil {
err = nil
max = 50 // default Value maxPerPage
} else if max > 300 {
max = 300
2017-05-05 16:39:15 +02:00
}
2017-05-09 13:31:58 +02:00
search . Max = uint ( max )
search . Query = r . URL . Query ( ) . Get ( "q" )
2017-05-06 12:41:48 +02:00
2017-05-09 13:31:58 +02:00
switch s := r . URL . Query ( ) . Get ( "s" ) ; s {
case "1" :
search . Status = FilterRemakes
case "2" :
search . Status = Trusted
case "3" :
search . Status = APlus
2017-05-06 12:41:48 +02:00
}
2017-05-05 16:39:15 +02:00
2017-05-09 13:31:58 +02:00
catString := r . URL . Query ( ) . Get ( "c" )
if s := catString ; len ( s ) > 1 && s != "_" {
var tmp uint64
tmp , err = strconv . ParseUint ( string ( s [ 0 ] ) , 10 , 8 )
if err != nil {
return
}
search . Category . Main = uint8 ( tmp )
2017-05-05 16:39:15 +02:00
2017-05-09 13:31:58 +02:00
if len ( s ) == 3 {
tmp , err = strconv . ParseUint ( string ( s [ 2 ] ) , 10 , 8 )
if err != nil {
return
}
search . Category . Sub = uint8 ( tmp )
}
2017-05-05 16:39:15 +02:00
}
2017-05-08 16:39:41 +02:00
2017-05-09 13:31:58 +02:00
order_by := ""
switch s := r . URL . Query ( ) . Get ( "sort" ) ; s {
case "1" :
search . Sort = Name
order_by += "torrent_name"
case "2" :
search . Sort = Date
order_by += "date"
case "3" :
search . Sort = Downloads
order_by += "downloads"
case "4" :
search . Sort = Size
order_by += "filesize"
2017-05-08 16:39:41 +02:00
default :
2017-05-09 13:31:58 +02:00
order_by += "torrent_id"
2017-05-05 16:39:15 +02:00
}
2017-05-08 16:39:41 +02:00
2017-05-09 13:31:58 +02:00
order_by += " "
switch s := r . URL . Query ( ) . Get ( "order" ) ; s {
case "true" :
search . Order = true
order_by += "asc"
2017-05-08 16:39:41 +02:00
default :
2017-05-09 13:31:58 +02:00
order_by += "desc"
2017-05-05 16:39:15 +02:00
}
2017-05-08 16:39:41 +02:00
2017-05-09 13:31:58 +02:00
userId := r . URL . Query ( ) . Get ( "userId" )
2017-05-05 16:39:15 +02:00
2017-05-09 01:56:57 +02:00
parameters := torrentService . WhereParams {
Params : make ( [ ] interface { } , 0 , 64 ) ,
}
conditions := make ( [ ] string , 0 , 64 )
2017-05-09 13:31:58 +02:00
if search . Category . Main != 0 {
2017-05-09 05:14:31 +02:00
conditions = append ( conditions , "category = ?" )
2017-05-09 13:31:58 +02:00
parameters . Params = append ( parameters . Params , string ( catString [ 0 ] ) )
2017-05-05 16:39:15 +02:00
}
2017-05-09 13:31:58 +02:00
if search . Category . Sub != 0 {
2017-05-09 05:14:31 +02:00
conditions = append ( conditions , "sub_category = ?" )
2017-05-09 13:31:58 +02:00
parameters . Params = append ( parameters . Params , string ( catString [ 2 ] ) )
2017-05-05 16:39:15 +02:00
}
2017-05-09 04:30:21 +02:00
if userId != "" {
conditions = append ( conditions , "uploader = ?" )
parameters . Params = append ( parameters . Params , userId )
}
2017-05-09 13:31:58 +02:00
if search . Status != 0 {
if search . Status == 3 {
2017-05-09 05:14:31 +02:00
conditions = append ( conditions , "status != ?" )
2017-05-05 22:30:56 +02:00
} else {
2017-05-09 05:14:31 +02:00
conditions = append ( conditions , "status = ?" )
2017-05-05 22:30:56 +02:00
}
2017-05-09 13:31:58 +02:00
parameters . Params = append ( parameters . Params , strconv . Itoa ( int ( search . Status ) + 1 ) )
2017-05-05 16:39:15 +02:00
}
2017-05-09 13:31:58 +02:00
searchQuerySplit := strings . Fields ( search . Query )
2017-05-08 15:50:18 +02:00
for i , word := range searchQuerySplit {
firstRune , _ := utf8 . DecodeRuneInString ( word )
if len ( word ) == 1 && unicode . IsPunct ( firstRune ) {
// some queries have a single punctuation character
// which causes a full scan instead of using the index
// and yields no meaningful results.
// due to len() == 1 we're just looking at 1-byte/ascii
// punctuation characters.
continue
}
2017-05-08 16:39:41 +02:00
// TODO: make this faster ?
conditions = append ( conditions , "torrent_name ILIKE ?" )
parameters . Params = append ( parameters . Params , "%" + searchQuerySplit [ i ] + "%" )
2017-05-05 16:39:15 +02:00
}
parameters . Conditions = strings . Join ( conditions [ : ] , " AND " )
log . Infof ( "SQL query is :: %s\n" , parameters . Conditions )
2017-05-09 13:31:58 +02:00
tor , count , err = torrentService . GetTorrentsOrderBy ( & parameters , order_by , int ( search . Max ) , int ( search . Max ) * ( pagenum - 1 ) )
return
2017-05-05 16:39:15 +02:00
}