2017-07-02 16:54:55 +02:00
package structs
2017-05-10 11:03:49 +02:00
2017-05-15 01:31:17 +02:00
import (
2017-06-20 02:06:01 +02:00
"math"
"time"
2017-06-13 13:31:11 +02:00
humanize "github.com/dustin/go-humanize"
2017-05-15 01:31:17 +02:00
"strconv"
"strings"
2017-06-18 00:30:12 +02:00
2017-07-05 14:29:31 +02:00
"fmt"
2017-06-18 00:30:12 +02:00
"github.com/NyaaPantsu/nyaa/config"
2017-07-02 16:54:55 +02:00
catUtil "github.com/NyaaPantsu/nyaa/utils/categories"
2017-07-07 14:06:51 +02:00
"github.com/NyaaPantsu/nyaa/utils/publicSettings"
2017-05-15 01:31:17 +02:00
)
2017-05-10 11:03:49 +02:00
const (
2017-07-05 14:29:31 +02:00
ShowAll Status = 0
FilterRemakes = 2
Trusted = 3
APlus = 4
2017-05-10 11:03:49 +02:00
)
2017-07-02 16:54:55 +02:00
type Status uint8
type SortMode uint8
type Category struct {
Main , Sub uint8
}
type SizeBytes uint64
type DateFilter string
type Categories [ ] * Category
// TorrentParam defines all parameters that can be provided when searching for a torrent
type TorrentParam struct {
Full bool // True means load all members
Order bool // True means ascending
Hidden bool // True means filter hidden torrents
Status Status
Sort SortMode
Category Categories
Max uint32
Offset uint32
UserID uint32
TorrentID uint32
FromID uint32
FromDate DateFilter
ToDate DateFilter
NotNull string // csv
NameLike string // csv
2017-07-07 14:06:51 +02:00
Languages publicSettings . Languages
2017-07-02 16:54:55 +02:00
MinSize SizeBytes
MaxSize SizeBytes
}
2017-07-05 14:29:31 +02:00
func ( p * TorrentParam ) Identifier ( ) string {
2017-07-07 00:18:11 +02:00
cats := ""
for _ , v := range p . Category {
cats += fmt . Sprintf ( "%d%d" , v . Main , v . Sub )
}
2017-07-07 14:06:51 +02:00
languages := ""
for _ , v := range p . Languages {
languages += fmt . Sprintf ( "%s%s" , v . Code , v . Name )
}
return fmt . Sprintf ( "%s%s%s%d%d%d%d%d%d%d%s%s%d%d%s%t%t%t" , p . NameLike , p . NotNull , languages , p . Max , p . Offset , p . FromID , p . MinSize , p . MaxSize , p . Status , p . Sort , p . FromDate , p . ToDate , p . UserID , p . TorrentID , cats , p . Full , p . Order , p . Hidden )
2017-07-05 14:29:31 +02:00
}
2017-05-26 01:48:14 +02:00
func ( st * Status ) ToString ( ) string {
switch * st {
case FilterRemakes :
return "2"
2017-06-21 03:59:00 +02:00
case Trusted :
2017-05-26 01:48:14 +02:00
return "3"
2017-06-21 03:59:00 +02:00
case APlus :
return "4"
2017-05-26 01:48:14 +02:00
}
return ""
}
2017-05-15 01:31:17 +02:00
func ( st * Status ) Parse ( s string ) {
switch s {
case "2" :
2017-06-21 03:59:00 +02:00
* st = FilterRemakes
2017-05-15 01:31:17 +02:00
case "3" :
2017-06-21 03:59:00 +02:00
* st = Trusted
case "4" :
2017-05-15 01:31:17 +02:00
* st = APlus
default :
* st = ShowAll
}
}
2017-05-10 11:03:49 +02:00
const (
ID SortMode = iota
Name
Date
Downloads
Size
2017-05-11 13:40:50 +02:00
Seeders
Leechers
Completed
2017-05-10 11:03:49 +02:00
)
2017-05-15 01:31:17 +02:00
func ( s * SortMode ) Parse ( str string ) {
switch str {
case "1" :
* s = Name
case "2" :
* s = Date
case "3" :
* s = Downloads
case "4" :
* s = Size
case "5" :
* s = Seeders
case "6" :
* s = Leechers
case "7" :
* s = Completed
default :
2017-06-21 03:28:56 +02:00
* s = Date
2017-05-15 01:31:17 +02:00
}
}
2017-05-26 01:48:14 +02:00
/ * INFO Always need to keep in sync with the field that are used in the
* elasticsearch index .
* TODO Verify the field in postgres database
* /
func ( s * SortMode ) ToESField ( ) string {
switch * s {
case ID :
return "id"
case Name :
2017-06-01 04:04:49 +02:00
return "name.raw"
2017-05-26 01:48:14 +02:00
case Date :
return "date"
case Downloads :
return "downloads"
case Size :
return "filesize"
case Seeders :
return "seeders"
case Leechers :
return "leechers"
case Completed :
return "completed"
}
return "id"
}
2017-06-13 13:31:11 +02:00
func ( s * SortMode ) ToDBField ( ) string {
switch * s {
case ID :
return "torrent_id"
case Name :
return "torrent_name"
case Date :
return "date"
case Downloads :
return "downloads"
case Size :
return "filesize"
case Seeders :
return "seeders"
case Leechers :
return "leechers"
case Completed :
return "completed"
}
2017-07-10 14:11:05 +02:00
return config . Get ( ) . Torrents . Order
2017-06-13 13:31:11 +02:00
}
2017-05-10 11:03:49 +02:00
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-15 01:31:17 +02:00
func ( c Category ) IsSet ( ) bool {
2017-05-26 01:48:14 +02:00
return c . IsMainSet ( ) && c . IsSubSet ( )
}
func ( c Category ) IsMainSet ( ) bool {
return c . Main != 0
}
func ( c Category ) IsSubSet ( ) bool {
return c . Sub != 0
2017-05-15 01:31:17 +02:00
}
2017-07-07 14:06:51 +02:00
// ParseCategories sets category by string
2017-06-18 00:30:12 +02:00
func ParseCategories ( s string ) [ ] * Category {
if s != "" {
parts := strings . Split ( s , "," )
2017-06-18 02:11:58 +02:00
var categories [ ] * Category
for _ , val := range parts {
2017-06-18 00:30:12 +02:00
partsCat := strings . Split ( val , "_" )
if len ( partsCat ) == 2 {
tmp , err := strconv . ParseUint ( partsCat [ 0 ] , 10 , 8 )
if err == nil {
c := uint8 ( tmp )
tmp , err = strconv . ParseUint ( partsCat [ 1 ] , 10 , 8 )
var sub uint8
if err == nil {
sub = uint8 ( tmp )
}
2017-07-06 21:53:13 +02:00
if catUtil . Exists ( partsCat [ 0 ] + "_" + partsCat [ 1 ] ) {
2017-06-18 02:11:58 +02:00
categories = append ( categories , & Category {
Main : c ,
Sub : sub ,
} )
2017-06-18 00:30:12 +02:00
}
}
2017-05-15 01:31:17 +02:00
}
}
2017-06-18 00:30:12 +02:00
return categories
2017-05-15 01:31:17 +02:00
}
2017-06-18 00:30:12 +02:00
return Categories { }
2017-05-15 01:31:17 +02:00
}
2017-07-07 14:06:51 +02:00
// ParseLanguages sets languages by string
func ParseLanguages ( s string ) publicSettings . Languages {
var languages publicSettings . Languages
if s != "" {
parts := strings . Split ( s , "," )
for _ , lang := range parts {
languages = append ( languages , publicSettings . Language { Name : "" , Code : lang } ) // We just need the code
}
}
return languages
}
2017-06-20 02:06:01 +02:00
func ( sz * SizeBytes ) Parse ( s string , sizeType string ) bool {
if s == "" {
* sz = 0
return false
}
var multiplier uint64
switch sizeType {
case "b" :
multiplier = 1
case "k" :
multiplier = uint64 ( math . Exp2 ( 10 ) )
case "m" :
multiplier = uint64 ( math . Exp2 ( 20 ) )
case "g" :
multiplier = uint64 ( math . Exp2 ( 30 ) )
}
2017-06-13 13:31:11 +02:00
size64 , err := humanize . ParseBytes ( s )
if err != nil {
* sz = 0
return false
}
2017-06-20 02:06:01 +02:00
* sz = SizeBytes ( size64 * multiplier )
return true
}
func ( d * DateFilter ) Parse ( s string , dateType string ) bool {
if s == "" {
* d = ""
return false
}
dateInt , err := strconv . Atoi ( s )
if err != nil {
* d = ""
return false
}
switch dateType {
case "m" :
* d = DateFilter ( time . Now ( ) . AddDate ( 0 , - dateInt , 0 ) . Format ( "2006-01-02" ) )
case "y" :
* d = DateFilter ( time . Now ( ) . AddDate ( - dateInt , 0 , 0 ) . Format ( "2006-01-02" ) )
default :
* d = DateFilter ( time . Now ( ) . AddDate ( 0 , 0 , - dateInt ) . Format ( "2006-01-02" ) )
}
2017-06-13 13:31:11 +02:00
return true
}