2017-05-09 17:09:45 +02:00
package apiService
2017-05-09 18:37:40 +02:00
import (
2017-05-11 05:04:11 +02:00
"encoding/hex"
"errors"
2017-05-11 06:12:54 +02:00
"fmt"
2017-05-11 05:04:11 +02:00
"io"
2017-05-09 19:37:39 +02:00
"net/http"
"net/url"
2017-05-09 18:37:40 +02:00
"reflect"
2017-05-09 19:37:39 +02:00
"regexp"
"strings"
2017-05-09 18:37:40 +02:00
2017-05-09 20:54:50 +02:00
"github.com/ewhal/nyaa/model"
2017-05-10 20:42:20 +02:00
"github.com/ewhal/nyaa/service"
2017-05-11 05:04:11 +02:00
"github.com/ewhal/nyaa/service/upload"
"github.com/ewhal/nyaa/util/metainfo"
"github.com/zeebo/bencode"
2017-05-09 18:37:40 +02:00
)
type torrentsQuery struct {
Category int ` json:"category" `
SubCategory int ` json:"sub_category" `
Status int ` json:"status" `
Uploader int ` json:"uploader" `
Downloads int ` json:"downloads" `
}
type TorrentsRequest struct {
Query torrentsQuery ` json:"search" `
Page int ` json:"page" `
MaxPerPage int ` json:"limit" `
}
2017-05-09 19:37:39 +02:00
//accept torrent files?
2017-05-09 20:54:50 +02:00
type TorrentRequest struct {
2017-05-09 19:37:39 +02:00
Name string ` json:"name" `
Category int ` json:"category" `
SubCategory int ` json:"sub_category" `
2017-05-09 22:24:32 +02:00
Magnet string ` json:"magnet" `
Hash string ` json:"hash" `
2017-05-09 19:37:39 +02:00
Description string ` json:"description" `
}
2017-05-09 20:54:50 +02:00
type UpdateRequest struct {
Consistency, formatting, error checking, cleanup, and a couple bug fixes (#245)
* Checkpoint: it builds
The config, db, model, network, os, and public packages have had some
fixes to glaringly obvious flaws, dead code removed, and stylistic
changes.
* Style changes and old code removal in router
Router needs a lot of work done to its (lack of) error handling.
* Dead code removal and style changes
Now up to util/email/email.go. After I'm finished with the initial sweep
I'll go back and fix error handling and security issues. Then I'll fix
the broken API. Then I'll go through to add documentation and fix code
visibility.
* Finish dead code removal and style changes
Vendored libraries not touched. Everything still needs security fixes
and documentation. There's also one case of broken functionality.
* Fix accidental find-and-replace
* Style, error checking, saftey, bug fix changes
* Redo error checking erased during merge
* Re-add merge-erased fix. Make Safe safe.
2017-05-10 04:34:40 +02:00
ID int ` json:"id" `
2017-05-09 20:54:50 +02:00
Update TorrentRequest ` json:"update" `
}
2017-05-10 20:42:20 +02:00
func ( r * TorrentsRequest ) ToParams ( ) serviceBase . WhereParams {
res := serviceBase . WhereParams { }
2017-05-09 18:37:40 +02:00
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 "
}
conditions += v . Type ( ) . Field ( i ) . Tag . Get ( "json" ) + " = ?"
res . Params = append ( res . Params , field . Interface ( ) )
}
}
res . Conditions = conditions
return res
}
2017-05-09 19:37:39 +02:00
2017-05-09 22:24:32 +02:00
func validateName ( r * TorrentRequest ) ( error , int ) {
2017-05-11 05:04:11 +02:00
/ * if len ( r . Name ) < 100 { //isn't this too much?
2017-05-09 19:37:39 +02:00
return ErrShortName , http . StatusNotAcceptable
2017-05-11 05:04:11 +02:00
} * /
2017-05-09 22:24:32 +02:00
return nil , http . StatusOK
}
func validateCategory ( r * TorrentRequest ) ( error , int ) {
2017-05-09 19:37:39 +02:00
if r . Category == 0 {
return ErrCategory , http . StatusNotAcceptable
}
2017-05-09 22:24:32 +02:00
return nil , http . StatusOK
}
func validateSubCategory ( r * TorrentRequest ) ( error , int ) {
2017-05-09 19:37:39 +02:00
if r . SubCategory == 0 {
return ErrSubCategory , http . StatusNotAcceptable
}
2017-05-09 22:24:32 +02:00
return nil , http . StatusOK
}
2017-05-09 19:37:39 +02:00
2017-05-09 22:24:32 +02:00
func validateMagnet ( r * TorrentRequest ) ( error , int ) {
magnetUrl , err := url . Parse ( string ( r . Magnet ) ) //?
if err != nil {
return err , http . StatusInternalServerError
}
exactTopic := magnetUrl . Query ( ) . Get ( "xt" )
2017-05-11 06:12:54 +02:00
fmt . Println ( exactTopic )
2017-05-09 22:24:32 +02:00
if ! strings . HasPrefix ( exactTopic , "urn:btih:" ) {
return ErrMagnet , http . StatusNotAcceptable
2017-05-09 19:37:39 +02:00
}
2017-05-11 06:12:54 +02:00
exactTopic = strings . SplitAfter ( exactTopic , ":" ) [ 2 ]
r . Hash = strings . ToUpper ( strings . Split ( exactTopic , "&" ) [ 0 ] )
2017-05-09 22:24:32 +02:00
return nil , http . StatusOK
}
2017-05-09 19:37:39 +02:00
2017-05-09 22:24:32 +02:00
func validateHash ( r * TorrentRequest ) ( error , int ) {
r . Hash = strings . ToUpper ( r . Hash )
2017-05-11 06:12:54 +02:00
matched , err := regexp . MatchString ( "^[0-9A-Z]+$" , r . Hash ) //fucking garbage
2017-05-09 19:37:39 +02:00
if err != nil {
return err , http . StatusInternalServerError
}
if ! matched {
return ErrHash , http . StatusNotAcceptable
}
return nil , http . StatusOK
}
2017-05-09 20:54:50 +02:00
2017-05-09 22:24:32 +02:00
func ( r * TorrentRequest ) ValidateUpload ( ) ( err error , code int ) {
validators := [ ] func ( r * TorrentRequest ) ( error , int ) {
validateName ,
validateCategory ,
validateSubCategory ,
validateMagnet ,
validateHash ,
2017-05-09 20:54:50 +02:00
}
2017-05-09 22:24:32 +02:00
for i , validator := range validators {
if r . Hash != "" && i == 3 {
continue
2017-05-09 20:54:50 +02:00
}
2017-05-09 22:24:32 +02:00
err , code = validator ( r )
2017-05-09 20:54:50 +02:00
if err != nil {
2017-05-09 22:24:32 +02:00
break
}
}
return err , code
}
2017-05-11 05:04:11 +02:00
func ( r * TorrentRequest ) ValidateMultipartUpload ( req * http . Request ) ( int64 , error , int ) {
tfile , _ , err := req . FormFile ( "torrent" )
if err == nil {
var torrent metainfo . TorrentFile
// decode torrent
if _ , err = tfile . Seek ( 0 , io . SeekStart ) ; err != nil {
return 0 , err , http . StatusInternalServerError
}
if err = bencode . NewDecoder ( tfile ) . Decode ( & torrent ) ; err != nil {
return 0 , err , http . StatusInternalServerError
}
// check a few things
if torrent . IsPrivate ( ) {
2017-05-11 06:12:54 +02:00
return 0 , errors . New ( "private torrents not allowed" ) , http . StatusNotAcceptable
2017-05-11 05:04:11 +02:00
}
trackers := torrent . GetAllAnnounceURLS ( )
if ! uploadService . CheckTrackers ( trackers ) {
2017-05-11 06:12:54 +02:00
return 0 , errors . New ( "tracker(s) not allowed" ) , http . StatusNotAcceptable
2017-05-11 05:04:11 +02:00
}
if r . Name == "" {
r . Name = torrent . TorrentName ( )
}
binInfohash , err := torrent . Infohash ( )
if err != nil {
return 0 , err , http . StatusInternalServerError
}
r . Hash = strings . ToUpper ( hex . EncodeToString ( binInfohash [ : ] ) )
// extract filesize
filesize := int64 ( torrent . TotalSize ( ) )
err , code := r . ValidateUpload ( )
return filesize , err , code
}
return 0 , err , http . StatusInternalServerError
}
2017-05-09 22:24:32 +02:00
func ( r * TorrentRequest ) ValidateUpdate ( ) ( err error , code int ) {
validators := [ ] func ( r * TorrentRequest ) ( error , int ) {
validateName ,
validateCategory ,
validateSubCategory ,
validateMagnet ,
validateHash ,
}
//don't update not requested values
//rewrite with reflect?
for i , validator := range validators {
if ( r . Name == "" && i == 0 ) || ( r . Category == 0 && i == 1 ) ||
( r . SubCategory == 0 && i == 2 ) ||
( r . Hash != "" || r . Magnet == "" && i == 3 ) || ( r . Hash == "" && i == 4 ) {
continue
2017-05-09 20:54:50 +02:00
}
2017-05-09 22:24:32 +02:00
err , code = validator ( r )
if err != nil {
break
2017-05-09 20:54:50 +02:00
}
}
2017-05-09 22:24:32 +02:00
return err , code
2017-05-09 20:54:50 +02:00
}
//rewrite with reflect ?
Consistency, formatting, error checking, cleanup, and a couple bug fixes (#245)
* Checkpoint: it builds
The config, db, model, network, os, and public packages have had some
fixes to glaringly obvious flaws, dead code removed, and stylistic
changes.
* Style changes and old code removal in router
Router needs a lot of work done to its (lack of) error handling.
* Dead code removal and style changes
Now up to util/email/email.go. After I'm finished with the initial sweep
I'll go back and fix error handling and security issues. Then I'll fix
the broken API. Then I'll go through to add documentation and fix code
visibility.
* Finish dead code removal and style changes
Vendored libraries not touched. Everything still needs security fixes
and documentation. There's also one case of broken functionality.
* Fix accidental find-and-replace
* Style, error checking, saftey, bug fix changes
* Redo error checking erased during merge
* Re-add merge-erased fix. Make Safe safe.
2017-05-10 04:34:40 +02:00
func ( r * UpdateRequest ) UpdateTorrent ( t * model . Torrent ) {
2017-05-09 20:54:50 +02:00
if r . Update . Name != "" {
t . Name = r . Update . Name
}
if r . Update . Hash != "" {
t . Hash = r . Update . Hash
}
if r . Update . Category != 0 {
t . Category = r . Update . Category
}
if r . Update . SubCategory != 0 {
Consistency, formatting, error checking, cleanup, and a couple bug fixes (#245)
* Checkpoint: it builds
The config, db, model, network, os, and public packages have had some
fixes to glaringly obvious flaws, dead code removed, and stylistic
changes.
* Style changes and old code removal in router
Router needs a lot of work done to its (lack of) error handling.
* Dead code removal and style changes
Now up to util/email/email.go. After I'm finished with the initial sweep
I'll go back and fix error handling and security issues. Then I'll fix
the broken API. Then I'll go through to add documentation and fix code
visibility.
* Finish dead code removal and style changes
Vendored libraries not touched. Everything still needs security fixes
and documentation. There's also one case of broken functionality.
* Fix accidental find-and-replace
* Style, error checking, saftey, bug fix changes
* Redo error checking erased during merge
* Re-add merge-erased fix. Make Safe safe.
2017-05-10 04:34:40 +02:00
t . SubCategory = r . Update . SubCategory
2017-05-09 20:54:50 +02:00
}
if r . Update . Description != "" {
t . Description = r . Update . Description
}
}