2017-07-01 23:09:35 +02:00
package upload
2017-05-11 05:04:11 +02:00
import (
2017-07-01 23:09:35 +02:00
"fmt"
"io"
"io/ioutil"
"mime/multipart"
"os"
"reflect"
"strings"
2017-05-27 00:45:18 +02:00
2017-05-20 01:10:16 +02:00
"github.com/NyaaPantsu/nyaa/config"
2017-06-29 13:15:23 +02:00
"github.com/NyaaPantsu/nyaa/models"
2017-07-01 23:09:35 +02:00
"github.com/NyaaPantsu/nyaa/service"
"github.com/NyaaPantsu/nyaa/util/sanitize"
"github.com/NyaaPantsu/nyaa/util/validator/torrent"
"github.com/gin-gonic/gin"
2017-05-11 05:04:11 +02:00
)
2017-07-01 23:09:35 +02:00
// form names
const uploadFormTorrent = "torrent"
type torrentsQuery struct {
Category int ` json:"category" `
SubCategory int ` json:"sub_category" `
Status int ` json:"status" `
Uploader int ` json:"uploader" `
Downloads int ` json:"downloads" `
}
// TorrentsRequest struct
type TorrentsRequest struct {
Query torrentsQuery ` json:"search" `
Page int ` json:"page" `
MaxPerPage int ` json:"limit" `
}
// APIResultJSON for torrents in json for api
type APIResultJSON struct {
Torrents [ ] models . TorrentJSON ` json:"torrents" `
QueryRecordCount int ` json:"queryRecordCount" `
TotalRecordCount int ` json:"totalRecordCount" `
}
// ToParams : Convert a torrentsrequest to searchparams
func ( r * TorrentsRequest ) ToParams ( ) serviceBase . WhereParams {
res := serviceBase . WhereParams { }
conditions := ""
v := reflect . ValueOf ( r . Query )
for i := 0 ; i < v . NumField ( ) ; i ++ {
field := v . Field ( i )
if field . Interface ( ) != reflect . Zero ( field . Type ( ) ) . Interface ( ) {
if i != 0 {
conditions += " AND "
2017-05-11 05:04:11 +02:00
}
2017-07-01 23:09:35 +02:00
conditions += v . Type ( ) . Field ( i ) . Tag . Get ( "json" ) + " = ?"
res . Params = append ( res . Params , field . Interface ( ) )
2017-05-11 05:04:11 +02:00
}
}
2017-07-01 23:09:35 +02:00
res . Conditions = conditions
return res
2017-05-11 05:04:11 +02:00
}
2017-05-20 01:10:16 +02:00
2017-07-01 23:09:35 +02:00
// ExtractEditInfo : takes an http request and computes all fields for this form
func ExtractEditInfo ( c * gin . Context , r * torrentValidator . TorrentRequest ) error {
err := ExtractBasicValue ( c , r )
if err != nil {
return err
}
err = r . ValidateName ( )
if err != nil {
return err
}
err = r . ExtractCategory ( )
if err != nil {
return err
}
err = r . ExtractLanguage ( )
return err
}
// ExtractBasicValue : takes an http request and computes all basic fields for this form
func ExtractBasicValue ( c * gin . Context , r * torrentValidator . TorrentRequest ) error {
c . Bind ( r )
// trim whitespace
r . Name = strings . TrimSpace ( r . Name )
r . Description = sanitize . Sanitize ( strings . TrimSpace ( r . Description ) , "default" )
r . WebsiteLink = strings . TrimSpace ( r . WebsiteLink )
r . Magnet = strings . TrimSpace ( r . Magnet )
// then actually check that we have everything we need
err := r . ValidateDescription ( )
if err != nil {
return err
}
err = r . ValidateWebsiteLink ( )
return err
}
// ExtractInfo : takes an http request and computes all fields for this form
func ExtractInfo ( c * gin . Context , r * torrentValidator . TorrentRequest ) error {
err := ExtractBasicValue ( c , r )
if err != nil {
return err
}
err = r . ExtractCategory ( )
if err != nil {
return err
}
err = r . ExtractLanguage ( )
if err != nil {
return err
}
tfile , err := r . ValidateMultipartUpload ( c , uploadFormTorrent )
if err != nil {
return err
}
// We check name only here, reason: we can try to retrieve them from the torrent file
err = r . ValidateName ( )
if err != nil {
return err
}
// after data has been checked & extracted, write it to disk
if len ( config . Conf . Torrents . FileStorage ) > 0 {
err := writeTorrentToDisk ( tfile , r . Infohash + ".torrent" , & r . Filepath )
if err != nil {
return err
2017-05-20 01:10:16 +02:00
}
2017-07-01 23:09:35 +02:00
} else {
r . Filepath = ""
}
return nil
}
// UpdateTorrent : Update torrent model
//rewrite with reflect ?
func UpdateTorrent ( r * torrentValidator . UpdateRequest , t * models . Torrent , currentUser * models . User ) {
if r . Update . Name != "" {
t . Name = r . Update . Name
}
if r . Update . Infohash != "" {
t . Hash = r . Update . Infohash
}
if r . Update . CategoryID != 0 {
t . Category = r . Update . CategoryID
}
if r . Update . SubCategoryID != 0 {
t . SubCategory = r . Update . SubCategoryID
}
if r . Update . Description != "" {
t . Description = r . Update . Description
}
if r . Update . WebsiteLink != "" {
t . WebsiteLink = r . Update . WebsiteLink
}
status := models . TorrentStatusNormal
if r . Update . Remake { // overrides trusted
status = models . TorrentStatusRemake
} else if currentUser . IsTrusted ( ) {
status = models . TorrentStatusTrusted
}
t . Status = status
}
func writeTorrentToDisk ( file multipart . File , name string , fullpath * string ) error {
_ , seekErr := file . Seek ( 0 , io . SeekStart )
if seekErr != nil {
return seekErr
}
b , err := ioutil . ReadAll ( file )
if err != nil {
return err
}
* fullpath = fmt . Sprintf ( "%s%c%s" , config . Conf . Torrents . FileStorage , os . PathSeparator , name )
return ioutil . WriteFile ( * fullpath , b , 0644 )
}
// NewTorrentRequest : creates a new torrent request struc with some default value
func NewTorrentRequest ( params ... string ) ( torrentRequest torrentValidator . TorrentRequest ) {
if len ( params ) > 1 {
torrentRequest . Category = params [ 0 ]
} else {
torrentRequest . Category = "3_12"
}
if len ( params ) > 2 {
torrentRequest . Description = params [ 1 ]
} else {
torrentRequest . Description = "Description"
2017-05-20 01:10:16 +02:00
}
2017-07-01 23:09:35 +02:00
return
2017-05-20 01:10:16 +02:00
}