Albirew/nyaa-pantsu
Archivé
1
0
Bifurcation 0

Merge pull request #136 from sfan5/upl

Fixes & Features for torrent uploads
Cette révision appartient à :
Eliot Whalan 2017-05-07 22:39:27 +10:00 révisé par GitHub
révision aca2f2dc58
10 fichiers modifiés avec 152 ajouts et 38 suppressions

Voir le fichier

@ -1,5 +1,6 @@
package config
// remember to update the FAQ when updating these
var Trackers = []string{
"udp://tracker.coppersurfer.tk:6969",
"udp://zer0day.to:1337/announce",

Voir le fichier

@ -82,7 +82,7 @@ func (t *Torrents) ToJson() TorrentsJson {
Status: t.Status,
Hash: t.Hash,
Date: time.Unix(t.Date, 0).Format(time.RFC3339),
Filesize: util.FormatFilesize(t.Filesize),
Filesize: util.FormatFilesize2(t.Filesize),
Description: template.HTML(t.Description),
Comments: b,
Sub_Category: strconv.Itoa(t.Sub_Category),

31
public/js/uploadPage.js Fichier normal
Voir le fichier

@ -0,0 +1,31 @@
(function() {
var torrent = $("input[name=torrent]"),
magnet = $("input[name=magnet]"),
name = $("input[name=name]");
torrent.on("change", function() {
if (torrent.val() == "") {
enableField(magnet);
name.attr("required", "");
} else {
disableField(magnet);
// .torrent file will allow autofilling name
name.removeAttr("required", "");
}
});
magnet.on("change", function() {
if (magnet.val() == "")
enableField(torrent);
else
disableField(torrent);
});
function enableField(e) {
e.attr("required", "")
.removeAttr("disabled");
}
function disableField(e) {
e.attr("disabled", "")
.removeAttr("required");
}
})();

Voir le fichier

@ -7,6 +7,7 @@ import (
"net/url"
"strconv"
"strings"
"regexp"
"github.com/ewhal/nyaa/service/captcha"
"github.com/ewhal/nyaa/util"
@ -21,10 +22,12 @@ type UploadForm struct {
Magnet string
Infohash string
Category string
CategoryId int
SubCategoryId int
Description string
captcha.Captcha
CategoryId int
SubCategoryId int
Filesize int64
}
// TODO: these should be in another package (?)
@ -44,9 +47,17 @@ const UploadFormCategory = "c"
// form value for description
const UploadFormDescription = "desc"
// error indicating that you can't send both a magnet link and torrent
var ErrTorrentPlusMagnet = errors.New("upload either a torrent file or magnet link, not both")
// error indicating a torrent is private
var ErrPrivateTorrent = errors.New("torrent is private")
// error indicating a problem with its trackers
// FIXME: hardcoded link
var ErrTrackerProblem = errors.New("torrent does not have any (working) trackers: https://nyaa.pantsu.cat/faq#trackers")
// error indicating a torrent's name is invalid
var ErrInvalidTorrentName = errors.New("torrent name is invalid")
@ -74,15 +85,6 @@ func (f *UploadForm) ExtractInfo(r *http.Request) error {
f.Description = p.Sanitize(util.TrimWhitespaces(f.Description))
f.Magnet = util.TrimWhitespaces(f.Magnet)
if len(f.Name) == 0 {
return ErrInvalidTorrentName
}
if len(f.Description) == 0 {
return ErrInvalidTorrentDescription
}
catsSplit := strings.Split(f.Category, "_")
// need this to prevent out of index panics
if len(catsSplit) == 2 {
@ -101,13 +103,10 @@ func (f *UploadForm) ExtractInfo(r *http.Request) error {
return ErrInvalidTorrentCategory
}
if len(f.Magnet) == 0 {
// try parsing torrent file if provided if no magnet is specified
tfile, _, err := r.FormFile(UploadFormTorrent)
if err != nil {
return err
}
// first: parse torrent file (if any) to fill missing information
tfile, _, err := r.FormFile(UploadFormTorrent)
if err == nil {
var torrent metainfo.TorrentFile
// decode torrent
err = bencode.NewDecoder(tfile).Decode(&torrent)
@ -115,17 +114,32 @@ func (f *UploadForm) ExtractInfo(r *http.Request) error {
return metainfo.ErrInvalidTorrentFile
}
// check if torrent is private
// check a few things
if torrent.IsPrivate() {
return ErrPrivateTorrent
}
trackers := torrent.GetAllAnnounceURLS()
if !CheckTrackers(trackers) {
return ErrTrackerProblem
}
// generate magnet
// Name
if len(f.Name) == 0 {
f.Name = torrent.TorrentName()
}
// Magnet link: if a file is provided it should be empty
if len(f.Magnet) != 0 {
return ErrTorrentPlusMagnet
}
binInfohash := torrent.Infohash()
f.Infohash = hex.EncodeToString(binInfohash[:])
f.Infohash = strings.ToUpper(hex.EncodeToString(binInfohash[:]))
f.Magnet = util.InfoHashToMagnet(f.Infohash, f.Name)
f.Infohash = strings.ToUpper(f.Infohash)
// extract filesize
f.Filesize = int64(torrent.TotalSize())
} else {
// No torrent file provided
magnetUrl, parseErr := url.Parse(f.Magnet)
if parseErr != nil {
return metainfo.ErrInvalidTorrentFile
@ -133,14 +147,57 @@ func (f *UploadForm) ExtractInfo(r *http.Request) error {
exactTopic := magnetUrl.Query().Get("xt")
if !strings.HasPrefix(exactTopic, "urn:btih:") {
return metainfo.ErrInvalidTorrentFile
} else {
f.Infohash = strings.ToUpper(strings.TrimPrefix(exactTopic, "urn:btih:"))
}
f.Infohash = strings.ToUpper(strings.TrimPrefix(exactTopic, "urn:btih:"))
matched, err := regexp.MatchString("^[0-9A-F]{40}$", f.Infohash)
if err != nil || !matched {
return metainfo.ErrInvalidTorrentFile
}
f.Filesize = 0
}
// then actually check that we have everything we need
if len(f.Name) == 0 {
return ErrInvalidTorrentName
}
//if len(f.Description) == 0 {
// return ErrInvalidTorrentDescription
//}
return nil
}
var dead_trackers = []string{ // substring matches!
"://open.nyaatorrents.info:6544",
"://tracker.openbittorrent.com:80",
"://tracker.publicbt.com:80",
"://stats.anisource.net:2710",
"://exodus.desync.com",
"://open.demonii.com:1337",
"://tracker.istole.it:80",
"://tracker.ccc.de:80",
"://bt2.careland.com.cn:6969",
"://announce.torrentsmd.com:8080"}
func CheckTrackers(trackers []string) bool {
var numGood int
for _, t := range trackers {
var good bool = true
for _, check := range dead_trackers {
if strings.Contains(t, check) {
good = false
}
}
if good {
numGood += 1
}
}
return numGood > 0
}
// NewUploadForm creates a new upload form given parameters as list
func NewUploadForm(params ...string) (uploadForm UploadForm) {
if len(params) > 1 {

Voir le fichier

@ -17,6 +17,7 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
var uploadForm UploadForm
if r.Method == "POST" {
defer r.Body.Close()
// validation is done in ExtractInfo()
err = uploadForm.ExtractInfo(r)
if err == nil {
if !captcha.Authenticate(uploadForm.Captcha) {
@ -25,7 +26,6 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
return
}
//validate name + hash
//add to db and redirect depending on result
torrent := model.Torrents{
Name: uploadForm.Name,
@ -34,9 +34,10 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
Status: 1,
Hash: uploadForm.Infohash,
Date: time.Now().Unix(),
Filesize: uploadForm.Filesize, // FIXME: should set to NULL instead of 0
Description: uploadForm.Description,
Comments: []byte{}}
fmt.Printf("%+v\n", torrent)
//fmt.Printf("%+v\n", torrent)
db.ORM.Create(&torrent)
fmt.Printf("%+v\n", torrent)
url, err := Router.Get("view_torrent").URL("id", strconv.Itoa(torrent.Id))
@ -44,7 +45,6 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
http.Redirect(w, r, url.String(), 302)
}
}
fmt.Printf("%+v\n", uploadForm)
} else if r.Method == "GET" {
uploadForm.CaptchaID = captcha.GetID(r.RemoteAddr)
htv := UploadTemplateVariables{uploadForm, NewSearchForm(), Navigation{}, r.URL, mux.CurrentRoute(r)}

Voir le fichier

@ -43,6 +43,18 @@
<p>The magnet link should look like this: <span style="font-family:monospace">
magnet:?xt=urn:btih:[hash]&amp;dn=[name]&amp;tr=[tracker]&amp;tr=[...]</span></p>
<h2 id="trackers">Which trackers do you recommend using?</h2>
<p>If your torrent upload is denied because of trackers you'll need to add some of these:</p>
<pre>udp://tracker.coppersurfer.tk:6969
udp://zer0day.to:1337/announce
udp://tracker.leechers-paradise.org:6969
udp://explodie.org:6969
udp://tracker.opentrackr.org:1337
udp://tracker.internetwarriors.net:1337/announce
udp://eddie4.nl:6969/announce
http://mgtracker.org:6969/announce
http://tracker.baka-sub.cf/announce</pre>
<h2>How can I help?</h2>
<p>If you have website development expertise, you can join the #nyaapantsu IRC channel on irc.rizon.net.
If you have any current databases, especially for sukebei, <b>UPLOAD THEM</b>.</p>
@ -54,7 +66,7 @@
<p>It's the author's favorite programming language.</p>
<br />
<img src="https://my.mixtape.moe/omrskw.png">
<img src="https://my.mixtape.moe/omrskw.png" alt="funny meme">
<br />
<h2>nyaa.pantsu.cat and sukebei.pantsu.cat do not host any files.</h2>

Voir le fichier

@ -1,6 +1,7 @@
{{define "captcha"}}
<div class="form-group captcha-container">
<input type="text" name="capthcaID" value="{{.CaptchaID}}" hidden>
<label for="solution">Captcha</label>
<input type="text" name="captchaID" value="{{.CaptchaID}}" hidden>
<img src="/captcha/{{.CaptchaID}}.png">
<input type="number" name="solution" class="form-control" placeholder="Captcha" required>
</div>

Voir le fichier

@ -6,16 +6,16 @@
<form enctype="multipart/form-data" role="upload" method="POST">
<div class="form-group">
<label for="torrent">Torrent file upload</label>
<label for="name">Name</label>
<input type="text" name="name" class="form-control" placeholder="File Name" value="{{.Name}}" required>
</div>
<div class="form-group">
<label for="torrent">Torrent file</label>
<input type="file" name="torrent" id="torrent" accept=".torrent">
<p class="help-block">Upload a torrent file to pre-fill information</p>
<p class="help-block">Uploading a torrent file allows pre-filling some fields, this is recommended.</p>
</div>
<div class="form-group">
<label for="name">FileName</label>
<input type="text" name="name" class="form-control"placeholder="File Name" value="{{.Name}}" required>
</div>
<div class="form-group">
<label for="Magnet">Magnet Link</label>
<label for="magnet">Magnet Link</label>
<input type="text" name="magnet" class="form-control"
style="width:60rem" placeholder="Magnet Link" value="{{.Magnet}}">
</div>
@ -45,6 +45,7 @@
<div class="form-group">
<label for="desc">Torrent Description</label>
<p class="help-block">A limited set of HTML is allowed in the description, make sure to use <span style="font-family:monospace">&lt;br/&gt;</span>.</p>
<textarea name="desc" class="form-control" rows="10">{{.Description}}</textarea>
</div>
@ -56,4 +57,7 @@
</form>
{{end}}
</div>
{{end}}
{{end}}
{{define "js_footer"}}
<script type="text/javascript" charset="utf-8" src="{{.URL.Parse "/js/uploadPage.js"}}"></script>
{{end}}

Voir le fichier

@ -25,3 +25,11 @@ func FormatFilesize(bytes int64) string {
}
return fmt.Sprintf("%.1f %s", value, unit)
}
func FormatFilesize2(bytes int64) string {
if bytes == 0 { // this is what gorm returns for NULL
return "Unknown"
} else {
return FormatFilesize(bytes)
}
}

Voir le fichier

@ -110,7 +110,7 @@ func (tf *TorrentFile) TorrentName() string {
// return true if this torrent is private otherwise return false
func (tf *TorrentFile) IsPrivate() bool {
return tf.Info.Private == nil || *tf.Info.Private == 0
return tf.Info.Private != nil && *tf.Info.Private == 1
}
// calculate infohash