2017-07-02 16:54:55 +02:00
package structs
2017-05-10 12:03:49 +03:00
2017-05-14 19:31:17 -04:00
import (
2017-06-20 02:06:01 +02:00
"math"
"time"
2017-06-13 08:31:11 -03:00
humanize "github.com/dustin/go-humanize"
2017-05-14 19:31:17 -04: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-14 19:31:17 -04:00
)
2017-05-10 12:03:49 +03:00
const (
2017-07-23 15:46:29 +10:00
// ShowAll by default show all torrents
ShowAll Status = 0
// FilterRemakes filter torrent remakes
FilterRemakes = 2
// Trusted trusted torrents
Trusted = 3
// APlus torrents not used anymore
APlus = 4
2017-05-10 12:03:49 +03:00
)
2017-07-23 15:46:29 +10:00
// Status torrent status
2017-07-02 16:54:55 +02:00
type Status uint8
2017-07-23 15:46:29 +10:00
// SortMode selected sort mode
2017-07-02 16:54:55 +02:00
type SortMode uint8
2017-07-23 15:46:29 +10:00
// Category torrent categories
2017-07-02 16:54:55 +02:00
type Category struct {
Main , Sub uint8
}
2017-07-23 15:46:29 +10:00
// SizeBytes size in bytes
2017-07-02 16:54:55 +02:00
type SizeBytes uint64
2017-07-23 15:46:29 +10:00
// DateFilter date to filter for
2017-07-02 16:54:55 +02:00
type DateFilter string
2017-07-23 15:46:29 +10:00
// Categories multiple torrent categories
2017-07-02 16:54:55 +02:00
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
2017-07-15 01:44:09 +02:00
Deleted bool // False means filter deleted torrents
2017-07-02 16:54:55 +02:00
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 )
}
2017-07-15 01:44:09 +02:00
return fmt . Sprintf ( "%s%s%s%d%d%d%d%d%d%d%s%s%d%d%s%t%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 , p . Deleted )
2017-07-05 14:29:31 +02:00
}
2017-05-25 19:48:14 -04:00
func ( st * Status ) ToString ( ) string {
switch * st {
case FilterRemakes :
return "2"
2017-06-20 21:59:00 -04:00
case Trusted :
2017-05-25 19:48:14 -04:00
return "3"
2017-06-20 21:59:00 -04:00
case APlus :
return "4"
2017-05-25 19:48:14 -04:00
}
return ""
}
2017-05-14 19:31:17 -04:00
func ( st * Status ) Parse ( s string ) {
switch s {
case "2" :
2017-06-20 21:59:00 -04:00
* st = FilterRemakes
2017-05-14 19:31:17 -04:00
case "3" :
2017-06-20 21:59:00 -04:00
* st = Trusted
case "4" :
2017-05-14 19:31:17 -04:00
* st = APlus
default :
* st = ShowAll
}
}
2017-05-10 12:03:49 +03:00
const (
ID SortMode = iota
Name
Date
Downloads
Size
2017-05-11 07:40:50 -04:00
Seeders
Leechers
Completed
2017-05-10 12:03:49 +03:00
)
2017-05-14 19:31:17 -04: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-20 21:28:56 -04:00
* s = Date
2017-05-14 19:31:17 -04:00
}
}
2017-05-25 19:48:14 -04: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-05-31 22:04:49 -04:00
return "name.raw"
2017-05-25 19:48:14 -04: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 08:31:11 -03: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 08:31:11 -03:00
}
2017-05-10 12:03:49 +03: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-14 19:31:17 -04:00
func ( c Category ) IsSet ( ) bool {
2017-05-25 19:48:14 -04: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-14 19:31:17 -04: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-14 19:31:17 -04:00
}
}
2017-06-18 00:30:12 +02:00
return categories
2017-05-14 19:31:17 -04:00
}
2017-06-18 00:30:12 +02:00
return Categories { }
2017-05-14 19:31:17 -04: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 08:31:11 -03: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 08:31:11 -03:00
return true
}