Controllers are now separated
They are in different folders and all loaded in controllers/router.go. This means that you only have to create a folder with a router.go file and import this folder in main router.go to add a handler.
Cette révision appartient à :
Parent
eb5ded4a27
révision
2c8344faf9
|
@ -1,4 +1,4 @@
|
|||
package controllers
|
||||
package activitiesController
|
||||
|
||||
import (
|
||||
"html"
|
||||
|
@ -6,6 +6,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models/activities"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/log"
|
||||
|
@ -21,7 +22,7 @@ func ActivityListHandler(c *gin.Context) {
|
|||
filter := c.Query("filter")
|
||||
|
||||
var err error
|
||||
currentUser := getUser(c)
|
||||
currentUser := router.GetUser(c)
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
|
@ -0,0 +1,8 @@
|
|||
package activitiesController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
router.Get().Any("/activities", ActivityListHandler)
|
||||
router.Get().Any("/activities/p/:page", ActivityListHandler)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package controllers
|
||||
package apiController
|
||||
|
||||
import (
|
||||
"html"
|
||||
|
@ -8,6 +8,7 @@ import (
|
|||
"time"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/controllers/feed"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
|
@ -80,7 +81,7 @@ func APIHandler(c *gin.Context) {
|
|||
c.Header("Content-Type", "application/json")
|
||||
t := c.Query("t")
|
||||
if t != "" {
|
||||
RSSTorznabHandler(c)
|
||||
feedController.RSSTorznabHandler(c)
|
||||
} else {
|
||||
page := c.Param("page")
|
||||
whereParams := structs.WhereParams{}
|
||||
|
@ -467,7 +468,7 @@ func APISearchHandler(c *gin.Context) {
|
|||
return
|
||||
}
|
||||
if pagenum <= 0 {
|
||||
NotFoundHandler(c)
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package apiController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
api := router.Get().Group("/api")
|
||||
{
|
||||
api.GET("", APIHandler)
|
||||
api.GET("/p/:page", APIHandler)
|
||||
api.GET("/view/:id", APIViewHandler)
|
||||
api.HEAD("/view/:id", APIViewHeadHandler)
|
||||
api.POST("/upload", APIUploadHandler)
|
||||
api.POST("/login", APILoginHandler)
|
||||
api.GET("/token/check", APICheckTokenHandler)
|
||||
api.GET("/token/refresh", APIRefreshTokenHandler)
|
||||
api.Any("/search", APISearchHandler)
|
||||
api.Any("/search/p/:page", APISearchHandler)
|
||||
api.PUT("/update", APIUpdateHandler)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package captchaController
|
||||
|
||||
import (
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/utils/captcha"
|
||||
)
|
||||
|
||||
func init() {
|
||||
router.Get().Any("/captcha/*hash", captcha.ServeFiles)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package controllers
|
||||
package databasedumpsController
|
||||
|
||||
import (
|
||||
"fmt"
|
|
@ -0,0 +1,7 @@
|
|||
package databasedumpsController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
router.Get().Any("/dumps", DatabaseDumpHandler)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package controllers
|
||||
package faqController
|
||||
|
||||
import (
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
|
@ -0,0 +1,7 @@
|
|||
package faqController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
router.Get().Any("/faq", FaqHandler)
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package feedController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/utils/feeds"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/feeds"
|
||||
)
|
||||
|
||||
// RSSEztvHandler : Controller for displaying rss feed, accepting common search arguments
|
||||
func RSSEztvHandler(c *gin.Context) {
|
||||
// We only get the basic variable for rss based on search param
|
||||
torrents, createdAsTime, title, err := getTorrentList(c)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
feed := &nyaafeeds.RssFeed{
|
||||
Title: title,
|
||||
Link: config.WebAddress() + "/",
|
||||
PubDate: createdAsTime.String(),
|
||||
}
|
||||
feed.Items = make([]*nyaafeeds.RssItem, len(torrents))
|
||||
|
||||
for i, torrent := range torrents {
|
||||
torrentJSON := torrent.ToJSON()
|
||||
feed.Items[i] = &nyaafeeds.RssItem{
|
||||
Title: torrentJSON.Name,
|
||||
Link: config.WebAddress() + "/download/" + torrentJSON.Hash,
|
||||
Category: &nyaafeeds.RssCategory{
|
||||
Domain: config.WebAddress() + "/search?c=" + torrentJSON.Category + "_" + torrentJSON.SubCategory,
|
||||
},
|
||||
Description: string(torrentJSON.Description),
|
||||
Comments: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
PubDate: torrent.Date.Format(time.RFC822),
|
||||
GUID: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
Enclosure: &nyaafeeds.RssEnclosure{
|
||||
URL: config.WebAddress() + "/download/" + strings.TrimSpace(torrentJSON.Hash),
|
||||
Length: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
Type: "application/x-bittorrent",
|
||||
},
|
||||
Torrent: &nyaafeeds.RssTorrent{
|
||||
Xmlns: "http://xmlns.ezrss.it/0.1/",
|
||||
FileName: torrentJSON.Name + ".torrent",
|
||||
ContentLength: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
InfoHash: torrentJSON.Hash,
|
||||
MagnetURI: string(torrentJSON.Magnet),
|
||||
},
|
||||
}
|
||||
}
|
||||
// allow cross domain AJAX requests
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
rss, rssErr := feeds.ToXML(feed)
|
||||
if rssErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, rssErr)
|
||||
}
|
||||
|
||||
_, writeErr := c.Writer.Write([]byte(rss))
|
||||
if writeErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, writeErr)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package feedController
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"html"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/NyaaPantsu/nyaa/utils/feeds"
|
||||
"github.com/NyaaPantsu/nyaa/utils/search"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func getTorrentList(c *gin.Context) (torrents []models.Torrent, createdAsTime time.Time, title string, err error) {
|
||||
page := c.Param("page")
|
||||
userID := c.Param("id")
|
||||
cat := c.Query("cat")
|
||||
offset := 0
|
||||
if c.Query("offset") != "" {
|
||||
offset, err = strconv.Atoi(html.EscapeString(c.Query("offset")))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
createdAsTime = time.Now()
|
||||
|
||||
if len(torrents) > 0 {
|
||||
createdAsTime = torrents[0].Date
|
||||
}
|
||||
|
||||
title = "Nyaa Pantsu"
|
||||
if config.IsSukebei() {
|
||||
title = "Sukebei Pantsu"
|
||||
}
|
||||
|
||||
pagenum := 1
|
||||
if page == "" && offset > 0 { // first page for offset is 0
|
||||
pagenum = offset + 1
|
||||
} else if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if pagenum <= 0 {
|
||||
err = errors.New("Page number is invalid")
|
||||
return
|
||||
}
|
||||
|
||||
if userID != "" {
|
||||
userIDnum := 0
|
||||
userIDnum, err = strconv.Atoi(html.EscapeString(userID))
|
||||
// Should we have a feed for anonymous uploads?
|
||||
if err != nil || userIDnum == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
_, _, err = users.FindForAdmin(uint(userIDnum))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Set the user ID on the request, so that SearchByQuery finds it.
|
||||
query := c.Request.URL.Query()
|
||||
query.Set("userID", userID)
|
||||
c.Request.URL.RawQuery = query.Encode()
|
||||
}
|
||||
|
||||
if cat != "" {
|
||||
query := c.Request.URL.Query()
|
||||
catConv := nyaafeeds.ConvertToCat(cat)
|
||||
if catConv == "" {
|
||||
return
|
||||
}
|
||||
query.Set("c", catConv)
|
||||
c.Request.URL.RawQuery = query.Encode()
|
||||
}
|
||||
|
||||
_, torrents, err = search.ByQueryNoCount(c, pagenum)
|
||||
|
||||
return
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package feedController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/utils/feeds"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/feeds"
|
||||
)
|
||||
|
||||
// RSSMagnetHandler : Controller for displaying rss feeds with magnet URL, accepting common search arguments
|
||||
func RSSMagnetHandler(c *gin.Context) {
|
||||
// We only get the basic variable for rss based on search param
|
||||
torrents, createdAsTime, title, err := getTorrentList(c)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
feed := &nyaafeeds.RssFeed{
|
||||
Title: title,
|
||||
Link: config.WebAddress() + "/",
|
||||
PubDate: createdAsTime.String(),
|
||||
}
|
||||
feed.Items = make([]*nyaafeeds.RssItem, len(torrents))
|
||||
|
||||
for i, torrent := range torrents {
|
||||
torrentJSON := torrent.ToJSON()
|
||||
feed.Items[i] = &nyaafeeds.RssItem{
|
||||
Title: torrentJSON.Name,
|
||||
Link: &nyaafeeds.RssMagnetLink{Text: string(torrentJSON.Magnet)},
|
||||
Description: string(torrentJSON.Description),
|
||||
PubDate: torrent.Date.Format(time.RFC822),
|
||||
GUID: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
Enclosure: &nyaafeeds.RssEnclosure{
|
||||
URL: config.WebAddress() + "/download/" + strings.TrimSpace(torrentJSON.Hash),
|
||||
Length: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
Type: "application/x-bittorrent",
|
||||
},
|
||||
}
|
||||
}
|
||||
// allow cross domain AJAX requests
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
rss, rssErr := feeds.ToXML(feed)
|
||||
if rssErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, rssErr)
|
||||
}
|
||||
|
||||
_, writeErr := c.Writer.Write([]byte(rss))
|
||||
if writeErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, writeErr)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
package feedController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
router.Get().Any("/feed", RSSHandler)
|
||||
router.Get().Any("/feed/p/:page", RSSHandler)
|
||||
router.Get().Any("/feed/magnet", RSSMagnetHandler)
|
||||
router.Get().Any("/feed/magnet/p/:page", RSSMagnetHandler)
|
||||
router.Get().Any("/feed/torznab", RSSTorznabHandler)
|
||||
router.Get().Any("/feed/torznab/api", RSSTorznabHandler)
|
||||
router.Get().Any("/feed/torznab/p/:page", RSSTorznabHandler)
|
||||
router.Get().Any("/feed/eztv", RSSEztvHandler)
|
||||
router.Get().Any("/feed/eztv/p/:page", RSSEztvHandler)
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package feedController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/utils/feeds"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/feeds"
|
||||
)
|
||||
|
||||
// RSSHandler : Controller for displaying rss feed, accepting common search arguments
|
||||
func RSSHandler(c *gin.Context) {
|
||||
// We only get the basic variable for rss based on search param
|
||||
torrents, createdAsTime, title, err := getTorrentList(c)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
feed := &nyaafeeds.RssFeed{
|
||||
Title: title,
|
||||
Link: config.WebAddress() + "/",
|
||||
PubDate: createdAsTime.String(),
|
||||
}
|
||||
feed.Items = make([]*nyaafeeds.RssItem, len(torrents))
|
||||
|
||||
for i, torrent := range torrents {
|
||||
torrentJSON := torrent.ToJSON()
|
||||
feed.Items[i] = &nyaafeeds.RssItem{
|
||||
Title: torrentJSON.Name,
|
||||
Link: config.WebAddress() + "/download/" + torrentJSON.Hash,
|
||||
Description: string(torrentJSON.Description),
|
||||
PubDate: torrent.Date.Format(time.RFC822),
|
||||
GUID: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
Enclosure: &nyaafeeds.RssEnclosure{
|
||||
URL: config.WebAddress() + "/download/" + strings.TrimSpace(torrentJSON.Hash),
|
||||
Length: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
Type: "application/x-bittorrent",
|
||||
},
|
||||
}
|
||||
}
|
||||
// allow cross domain AJAX requests
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
rss, rssErr := feeds.ToXML(feed)
|
||||
if rssErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, rssErr)
|
||||
}
|
||||
|
||||
_, writeErr := c.Writer.Write([]byte(rss))
|
||||
if writeErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, writeErr)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,194 @@
|
|||
package feedController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/utils/categories"
|
||||
"github.com/NyaaPantsu/nyaa/utils/feeds"
|
||||
"github.com/NyaaPantsu/nyaa/utils/publicSettings"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/feeds"
|
||||
)
|
||||
|
||||
// RSSTorznabHandler : Controller for displaying rss feed, accepting common search arguments
|
||||
func RSSTorznabHandler(c *gin.Context) {
|
||||
t := c.Query("t")
|
||||
rss := ""
|
||||
title := "Nyaa Pantsu"
|
||||
if config.IsSukebei() {
|
||||
title = "Sukebei Pantsu"
|
||||
}
|
||||
if t == "caps" {
|
||||
T := publicSettings.GetTfuncFromRequest(c)
|
||||
cats := categories.GetSelect(true, true)
|
||||
var categories []*nyaafeeds.RssCategoryTorznab
|
||||
categories = append(categories, &nyaafeeds.RssCategoryTorznab{
|
||||
ID: "5070",
|
||||
Name: "Anime",
|
||||
Description: "Anime",
|
||||
})
|
||||
|
||||
last := 0
|
||||
for _, v := range cats {
|
||||
if len(v.ID) <= 2 {
|
||||
categories = append(categories, &nyaafeeds.RssCategoryTorznab{
|
||||
ID: nyaafeeds.ConvertFromCat(v.ID),
|
||||
Name: string(T(v.Name)),
|
||||
})
|
||||
last++
|
||||
} else {
|
||||
categories[last].Subcat = append(categories[last].Subcat, &nyaafeeds.RssSubCat{
|
||||
ID: nyaafeeds.ConvertFromCat(v.ID),
|
||||
Name: string(T(v.Name)),
|
||||
})
|
||||
}
|
||||
}
|
||||
feed := &nyaafeeds.RssCaps{
|
||||
Server: &nyaafeeds.RssServer{
|
||||
Version: "1.0",
|
||||
Title: title,
|
||||
Strapline: "...",
|
||||
Email: config.Get().Email.From,
|
||||
URL: config.WebAddress(),
|
||||
Image: config.WebAddress() + "/img/logo.png",
|
||||
},
|
||||
Limits: &nyaafeeds.RssLimits{
|
||||
Max: "300",
|
||||
Default: "50",
|
||||
},
|
||||
Registration: &nyaafeeds.RssRegistration{
|
||||
Available: "yes",
|
||||
Open: "yes",
|
||||
},
|
||||
Searching: &nyaafeeds.RssSearching{
|
||||
Search: &nyaafeeds.RssSearch{
|
||||
Available: "yes",
|
||||
SupportedParams: "q",
|
||||
},
|
||||
TvSearch: &nyaafeeds.RssSearch{
|
||||
Available: "no",
|
||||
},
|
||||
MovieSearch: &nyaafeeds.RssSearch{
|
||||
Available: "no",
|
||||
},
|
||||
},
|
||||
Categories: &nyaafeeds.RssCategories{
|
||||
Category: categories,
|
||||
},
|
||||
}
|
||||
var rssErr error
|
||||
rss, rssErr = feeds.ToXML(feed)
|
||||
if rssErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, rssErr)
|
||||
}
|
||||
} else {
|
||||
// We only get the basic variable for rss based on search param
|
||||
torrents, createdAsTime, title, err := getTorrentList(c)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
feed := &nyaafeeds.RssFeed{
|
||||
Title: title,
|
||||
Xmlns: "http://torznab.com/schemas/2015/feed",
|
||||
Link: config.WebAddress() + "/",
|
||||
PubDate: createdAsTime.String(),
|
||||
}
|
||||
feed.Items = make([]*nyaafeeds.RssItem, len(torrents))
|
||||
|
||||
for i, torrent := range torrents {
|
||||
|
||||
torrentJSON := torrent.ToJSON()
|
||||
filesNumber := ""
|
||||
if len(torrentJSON.FileList) > 0 {
|
||||
filesNumber = strconv.Itoa(len(torrentJSON.FileList))
|
||||
}
|
||||
seeders := ""
|
||||
if torrentJSON.Seeders > 0 {
|
||||
seeders = strconv.Itoa(int(torrentJSON.Seeders))
|
||||
}
|
||||
leechers := ""
|
||||
if torrentJSON.Leechers > 0 {
|
||||
leechers = strconv.Itoa(int(torrentJSON.Leechers))
|
||||
}
|
||||
feed.Items[i] = &nyaafeeds.RssItem{
|
||||
Title: torrentJSON.Name,
|
||||
Link: config.WebAddress() + "/download/" + torrentJSON.Hash,
|
||||
Category: &nyaafeeds.RssCategory{
|
||||
Domain: config.WebAddress() + "/search?c=" + torrentJSON.Category + "_" + torrentJSON.SubCategory,
|
||||
},
|
||||
Description: string(torrentJSON.Description),
|
||||
Comments: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
PubDate: torrent.Date.Format(time.RFC822),
|
||||
GUID: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
Enclosure: &nyaafeeds.RssEnclosure{
|
||||
URL: config.WebAddress() + "/download/" + strings.TrimSpace(torrentJSON.Hash),
|
||||
Length: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
Type: "application/x-bittorrent",
|
||||
},
|
||||
}
|
||||
torznab := []*nyaafeeds.RssTorznab{}
|
||||
if torrentJSON.Filesize > 0 {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "size",
|
||||
Value: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
})
|
||||
}
|
||||
if filesNumber != "" {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "files",
|
||||
Value: filesNumber,
|
||||
})
|
||||
}
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "grabs",
|
||||
Value: strconv.Itoa(int(torrentJSON.Completed)),
|
||||
})
|
||||
if seeders != "" {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "seeders",
|
||||
Value: seeders,
|
||||
})
|
||||
}
|
||||
if leechers != "" {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "leechers",
|
||||
Value: leechers,
|
||||
})
|
||||
}
|
||||
if torrentJSON.Hash != "" {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "infohash",
|
||||
Value: torrentJSON.Hash,
|
||||
})
|
||||
}
|
||||
if torrentJSON.Magnet != "" {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "magneturl",
|
||||
Value: string(torrentJSON.Magnet),
|
||||
})
|
||||
}
|
||||
if len(torznab) > 0 {
|
||||
feed.Items[i].Torznab = torznab
|
||||
}
|
||||
}
|
||||
var rssErr error
|
||||
rss, rssErr = feeds.ToXML(feed)
|
||||
if rssErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, rssErr)
|
||||
}
|
||||
}
|
||||
// allow cross domain AJAX requests
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
|
||||
_, writeErr := c.Writer.Write([]byte(rss))
|
||||
if writeErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, writeErr)
|
||||
}
|
||||
}
|
|
@ -1,16 +1,18 @@
|
|||
package controllers
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/log"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func errorMiddleware() gin.HandlerFunc {
|
||||
// Middleware for managing errors on status
|
||||
func ErrorMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
c.Next()
|
||||
if config.Get().Environment == "DEVELOPMENT" {
|
||||
|
@ -31,10 +33,10 @@ func errorMiddleware() gin.HandlerFunc {
|
|||
}
|
||||
}
|
||||
|
||||
// Make sure the user is a moderator, otherwise return forbidden
|
||||
func modMiddleware() gin.HandlerFunc {
|
||||
// ModMiddleware Make sure the user is a moderator, otherwise return forbidden
|
||||
func ModMiddleware() gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
currentUser := getUser(c)
|
||||
currentUser := router.GetUser(c)
|
||||
if !currentUser.HasAdmin() {
|
||||
NotFoundHandler(c)
|
||||
}
|
||||
|
@ -44,7 +46,7 @@ func modMiddleware() gin.HandlerFunc {
|
|||
|
||||
func pprofHandler(handler http.HandlerFunc) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
currentUser := getUser(c)
|
||||
currentUser := router.GetUser(c)
|
||||
if currentUser.HasAdmin() {
|
||||
handler.ServeHTTP(c.Writer, c.Request)
|
||||
} else {
|
|
@ -1,4 +1,4 @@
|
|||
package controllers
|
||||
package middlewares
|
||||
|
||||
import (
|
||||
"net/http"
|
|
@ -0,0 +1,7 @@
|
|||
package middlewares
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
router.Get().Use(ErrorMiddleware())
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// APIMassMod : This function is used on the frontend for the mass
|
||||
/* Query is: action=status|delete|owner|category|multiple
|
||||
* Needed: torrent_id[] Ids of torrents in checkboxes of name torrent_id
|
||||
*
|
||||
* Needed on context:
|
||||
* status=0|1|2|3|4 according to config/find.go (can be omitted if action=delete|owner|category|multiple)
|
||||
* owner is the User ID of the new owner of the torrents (can be omitted if action=delete|status|category|multiple)
|
||||
* category is the category string (eg. 1_3) of the new category of the torrents (can be omitted if action=delete|status|owner|multiple)
|
||||
*
|
||||
* withreport is the bool to enable torrent reports deletion (can be omitted)
|
||||
*
|
||||
* In case of action=multiple, torrents can be at the same time changed status, owner and category
|
||||
*/
|
||||
func APIMassMod(c *gin.Context) {
|
||||
torrentManyAction(c)
|
||||
messages := msg.GetMessages(c) // new utils for errors and infos
|
||||
c.Header("Content-Type", "application/json")
|
||||
|
||||
var mapOk map[string]interface{}
|
||||
if !messages.HasErrors() {
|
||||
mapOk = map[string]interface{}{"ok": true, "infos": messages.GetAllInfos()["infos"]}
|
||||
} else { // We need to show error messages
|
||||
mapOk = map[string]interface{}{"ok": false, "errors": messages.GetAllErrors()["errors"]}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, mapOk)
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"html"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/activities"
|
||||
"github.com/NyaaPantsu/nyaa/models/comments"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// CommentsListPanel : Controller for listing comments, can accept pages and userID
|
||||
func CommentsListPanel(c *gin.Context) {
|
||||
page := c.Param("page")
|
||||
pagenum := 1
|
||||
offset := 100
|
||||
userid := c.Query("userid")
|
||||
var err error
|
||||
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
var conditions string
|
||||
var values []interface{}
|
||||
if userid != "" {
|
||||
conditions = "user_id = ?"
|
||||
values = append(values, userid)
|
||||
}
|
||||
|
||||
comments, nbComments := comments.FindAll(offset, (pagenum-1)*offset, conditions, values...)
|
||||
nav := templates.Navigation{nbComments, offset, pagenum, "mod/comments/p"}
|
||||
templates.ModelList(c, "admin/commentlist.jet.html", comments, nav, templates.NewSearchForm(c))
|
||||
}
|
||||
|
||||
// CommentDeleteModPanel : Controller for deleting a comment
|
||||
func CommentDeleteModPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
comment, _, err := comments.Delete(uint(id))
|
||||
if err == nil {
|
||||
activities.Log(&models.User{}, comment.Identifier(), "delete", "comment_deleted_by", strconv.Itoa(int(comment.ID)), comment.User.Username, router.GetUser(c).Username)
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusSeeOther, "/mod/comments?deleted")
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"html"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/log"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/search"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// DeletedTorrentsModPanel : Controller for viewing deleted torrents, accept common search arguments
|
||||
func DeletedTorrentsModPanel(c *gin.Context) {
|
||||
page := c.Param("page")
|
||||
messages := msg.GetMessages(c) // new utils for errors and infos
|
||||
deleted := c.Request.URL.Query()["deleted"]
|
||||
unblocked := c.Request.URL.Query()["unblocked"]
|
||||
blocked := c.Request.URL.Query()["blocked"]
|
||||
if deleted != nil {
|
||||
messages.AddInfoT("infos", "torrent_deleted_definitely")
|
||||
}
|
||||
if blocked != nil {
|
||||
messages.AddInfoT("infos", "torrent_blocked")
|
||||
}
|
||||
if unblocked != nil {
|
||||
messages.AddInfoT("infos", "torrent_unblocked")
|
||||
}
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
searchParam, torrents, count, err := search.ByQueryDeleted(c, pagenum)
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
category := ""
|
||||
if len(searchParam.Category) > 0 {
|
||||
category = searchParam.Category[0].String()
|
||||
}
|
||||
searchForm := templates.SearchForm{
|
||||
TorrentParam: searchParam,
|
||||
Category: category,
|
||||
ShowItemsPerPage: true,
|
||||
}
|
||||
|
||||
nav := templates.Navigation{count, int(searchParam.Max), pagenum, "mod/torrents/deleted/p"}
|
||||
search := searchForm
|
||||
templates.ModelList(c, "admin/torrentlist.jet.html", torrents, nav, search)
|
||||
}
|
||||
|
||||
// DeletedTorrentsPostPanel : Controller for viewing deleted torrents after a mass update, accept common search arguments
|
||||
func DeletedTorrentsPostPanel(c *gin.Context) {
|
||||
torrentManyAction(c)
|
||||
DeletedTorrentsModPanel(c)
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/activities"
|
||||
"github.com/NyaaPantsu/nyaa/models/reports"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/NyaaPantsu/nyaa/utils/categories"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/search/structs"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
/*
|
||||
* Controller to modify multiple torrents and can be used by the owner of the torrent or admin
|
||||
*/
|
||||
func torrentManyAction(c *gin.Context) {
|
||||
currentUser := router.GetUser(c)
|
||||
|
||||
torrentsSelected := c.PostFormArray("torrent_id") // should be []string
|
||||
action := c.PostForm("action")
|
||||
status, _ := strconv.Atoi(c.PostForm("status"))
|
||||
owner, _ := strconv.Atoi(c.PostForm("owner"))
|
||||
category := c.PostForm("category")
|
||||
withReport, _ := strconv.ParseBool(c.DefaultPostForm("withreport", "false"))
|
||||
messages := msg.GetMessages(c) // new utils for errors and infos
|
||||
catID, subCatID := -1, -1
|
||||
var err error
|
||||
|
||||
if action == "" {
|
||||
messages.AddErrorT("errors", "no_action_selected")
|
||||
}
|
||||
if action == "status" && c.PostForm("status") == "" { // We need to check the form value, not the int one because hidden is 0
|
||||
messages.AddErrorT("errors", "no_move_location_selected")
|
||||
}
|
||||
if action == "owner" && c.PostForm("owner") == "" { // We need to check the form value, not the int one because renchon is 0
|
||||
messages.AddErrorT("errors", "no_owner_selected")
|
||||
}
|
||||
if action == "category" && category == "" {
|
||||
messages.AddErrorT("errors", "no_category_selected")
|
||||
}
|
||||
if len(torrentsSelected) == 0 {
|
||||
messages.AddErrorT("errors", "select_one_element")
|
||||
}
|
||||
|
||||
if !config.Get().Torrents.Status[status] { // Check if the status exist
|
||||
messages.AddErrorTf("errors", "no_status_exist", status)
|
||||
status = -1
|
||||
}
|
||||
if !currentUser.HasAdmin() {
|
||||
if c.PostForm("status") != "" { // Condition to check if a user try to change torrent status without having the right permission
|
||||
if (status == models.TorrentStatusTrusted && !currentUser.IsTrusted()) || status == models.TorrentStatusAPlus || status == 0 {
|
||||
status = models.TorrentStatusNormal
|
||||
}
|
||||
}
|
||||
if c.PostForm("owner") != "" { // Only admins can change owner of torrents
|
||||
owner = -1
|
||||
}
|
||||
withReport = false // Users should not be able to remove reports
|
||||
}
|
||||
if c.PostForm("owner") != "" && currentUser.HasAdmin() { // We check that the user given exist and if not we return an error
|
||||
_, _, errorUser := users.FindForAdmin(uint(owner))
|
||||
if errorUser != nil {
|
||||
messages.AddErrorTf("errors", "no_user_found_id", owner)
|
||||
owner = -1
|
||||
}
|
||||
}
|
||||
if category != "" {
|
||||
catsSplit := strings.Split(category, "_")
|
||||
// need this to prevent out of index panics
|
||||
if len(catsSplit) == 2 {
|
||||
catID, err = strconv.Atoi(catsSplit[0])
|
||||
if err != nil {
|
||||
messages.AddErrorT("errors", "invalid_torrent_category")
|
||||
}
|
||||
subCatID, err = strconv.Atoi(catsSplit[1])
|
||||
if err != nil {
|
||||
messages.AddErrorT("errors", "invalid_torrent_category")
|
||||
}
|
||||
|
||||
if !categories.Exists(category) {
|
||||
messages.AddErrorT("errors", "invalid_torrent_category")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !messages.HasErrors() {
|
||||
for _, torrentID := range torrentsSelected {
|
||||
id, _ := strconv.Atoi(torrentID)
|
||||
torrent, _ := torrents.FindByID(uint(id))
|
||||
if torrent.ID > 0 && currentUser.CurrentOrAdmin(torrent.UploaderID) {
|
||||
if action == "status" || action == "multiple" || action == "category" || action == "owner" {
|
||||
|
||||
/* If we don't delete, we make changes according to the form posted and we save at the end */
|
||||
if c.PostForm("status") != "" && status != -1 {
|
||||
torrent.Status = status
|
||||
messages.AddInfoTf("infos", "torrent_moved", torrent.Name)
|
||||
}
|
||||
if c.PostForm("owner") != "" && owner != -1 {
|
||||
torrent.UploaderID = uint(owner)
|
||||
messages.AddInfoTf("infos", "torrent_owner_changed", torrent.Name)
|
||||
}
|
||||
if category != "" && catID != -1 && subCatID != -1 {
|
||||
torrent.Category = catID
|
||||
torrent.SubCategory = subCatID
|
||||
messages.AddInfoTf("infos", "torrent_category_changed", torrent.Name)
|
||||
}
|
||||
|
||||
/* Changes are done, we save */
|
||||
_, err := torrent.UpdateUnscope()
|
||||
if err == nil {
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "edited", "torrent_edited_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
|
||||
}
|
||||
} else if action == "delete" {
|
||||
if status == models.TorrentStatusBlocked { // Then we should lock torrents before deleting them
|
||||
torrent.Status = status
|
||||
messages.AddInfoTf("infos", "torrent_moved", torrent.Name)
|
||||
torrent.UpdateUnscope()
|
||||
}
|
||||
_, _, err = torrent.Delete(false)
|
||||
if err != nil {
|
||||
messages.ImportFromError("errors", err)
|
||||
} else {
|
||||
messages.AddInfoTf("infos", "torrent_deleted", torrent.Name)
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "deleted", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
|
||||
}
|
||||
} else {
|
||||
messages.AddErrorTf("errors", "no_action_exist", action)
|
||||
}
|
||||
if withReport {
|
||||
whereParams := structs.CreateWhereParams("torrent_id = ?", torrentID)
|
||||
reports, _, _ := reports.FindOrderBy(&whereParams, "", 0, 0)
|
||||
for _, report := range reports {
|
||||
report.Delete(false)
|
||||
}
|
||||
messages.AddInfoTf("infos", "torrent_reports_deleted", torrent.Name)
|
||||
}
|
||||
} else {
|
||||
messages.AddErrorTf("errors", "torrent_not_exist", torrentID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/comments"
|
||||
"github.com/NyaaPantsu/nyaa/models/reports"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// IndexModPanel : Controller for showing index page of Mod Panel
|
||||
func IndexModPanel(c *gin.Context) {
|
||||
offset := 10
|
||||
torrents, _, _ := torrents.FindAll(offset, 0)
|
||||
users, _ := users.FindUsersForAdmin(offset, 0)
|
||||
comments, _ := comments.FindAll(offset, 0, "", "")
|
||||
torrentReports, _, _ := reports.GetAll(offset, 0)
|
||||
|
||||
templates.PanelAdmin(c, torrents, models.TorrentReportsToJSON(torrentReports), users, comments)
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator/torrent"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// TorrentReassignModPanel : Controller for reassigning a torrent, after GET request
|
||||
func TorrentReassignModPanel(c *gin.Context) {
|
||||
templates.Form(c, "admin/reassign.jet.html", torrentValidator.ReassignForm{})
|
||||
}
|
||||
|
||||
// ExecuteAction : Function for applying the changes from ReassignForm
|
||||
func ExecuteReassign(f *torrentValidator.ReassignForm) (int, error) {
|
||||
var toBeChanged []uint
|
||||
var err error
|
||||
if f.By == "olduser" {
|
||||
toBeChanged, err = users.FindOldUploadsByUsername(f.Data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else if f.By == "torrentid" {
|
||||
toBeChanged = f.Torrents
|
||||
}
|
||||
|
||||
num := 0
|
||||
for _, torrentID := range toBeChanged {
|
||||
torrent, err2 := torrents.FindRawByID(torrentID)
|
||||
if err2 == nil {
|
||||
torrent.UploaderID = f.AssignTo
|
||||
torrent.Update(true)
|
||||
num++
|
||||
}
|
||||
}
|
||||
return num, nil
|
||||
}
|
||||
|
||||
// TorrentPostReassignModPanel : Controller for reassigning a torrent, after POST request
|
||||
func TorrentPostReassignModPanel(c *gin.Context) {
|
||||
var rForm torrentValidator.ReassignForm
|
||||
messages := msg.GetMessages(c)
|
||||
|
||||
if rForm.ExtractInfo(c) {
|
||||
count, err2 := ExecuteReassign(&rForm)
|
||||
if err2 != nil {
|
||||
messages.AddErrorT("errors", "something_went_wrong")
|
||||
} else {
|
||||
messages.AddInfoTf("infos", "nb_torrents_updated", count)
|
||||
}
|
||||
}
|
||||
templates.Form(c, "admin/reassign.jet.html", rForm)
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/reports"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// TorrentReportListPanel : Controller for listing torrent reports, can accept pages
|
||||
func TorrentReportListPanel(c *gin.Context) {
|
||||
page := c.Param("page")
|
||||
pagenum := 1
|
||||
offset := 100
|
||||
var err error
|
||||
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
torrentReports, nbReports, _ := reports.GetAll(offset, (pagenum-1)*offset)
|
||||
|
||||
reportJSON := models.TorrentReportsToJSON(torrentReports)
|
||||
nav := templates.Navigation{nbReports, offset, pagenum, "mod/reports/p"}
|
||||
templates.ModelList(c, "admin/torrent_report.jet.html", reportJSON, nav, templates.NewSearchForm(c))
|
||||
}
|
||||
|
||||
// TorrentReportDeleteModPanel : Controller for deleting a torrent report
|
||||
func TorrentReportDeleteModPanel(c *gin.Context) {
|
||||
id := c.Query("id")
|
||||
|
||||
fmt.Println(id)
|
||||
idNum, _ := strconv.ParseUint(id, 10, 64)
|
||||
_, _, _ = reports.Delete(uint(idNum))
|
||||
/* If we need to log report delete activity
|
||||
if err == nil {
|
||||
activity.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_report_deleted_by", strconv.Itoa(int(report.ID)), router.GetUser(c).Username)
|
||||
}
|
||||
*/
|
||||
c.Redirect(http.StatusSeeOther, "/mod/reports?deleted")
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"github.com/NyaaPantsu/nyaa/controllers/middlewares"
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
)
|
||||
|
||||
func init() {
|
||||
modRoutes := router.Get().Group("/mod", middlewares.ModMiddleware())
|
||||
{
|
||||
modRoutes.Any("/", IndexModPanel)
|
||||
modRoutes.GET("/torrents", TorrentsListPanel)
|
||||
modRoutes.GET("/torrents/p/:page", TorrentsListPanel)
|
||||
modRoutes.POST("/torrents", TorrentsPostListPanel)
|
||||
modRoutes.POST("/torrents/p/:page", TorrentsPostListPanel)
|
||||
modRoutes.GET("/torrents/deleted", DeletedTorrentsModPanel)
|
||||
modRoutes.GET("/torrents/deleted/p/:page", DeletedTorrentsModPanel)
|
||||
modRoutes.POST("/torrents/deleted", DeletedTorrentsPostPanel)
|
||||
modRoutes.POST("/torrents/deleted/p/:page", DeletedTorrentsPostPanel)
|
||||
modRoutes.Any("/reports", TorrentReportListPanel)
|
||||
modRoutes.Any("/reports/p/:page", TorrentReportListPanel)
|
||||
modRoutes.Any("/users", UsersListPanel)
|
||||
modRoutes.Any("/users/p/:page", UsersListPanel)
|
||||
modRoutes.Any("/comments", CommentsListPanel)
|
||||
modRoutes.Any("/comments/p/:page", CommentsListPanel)
|
||||
modRoutes.Any("/comment", CommentsListPanel) // TODO
|
||||
modRoutes.GET("/torrent", TorrentEditModPanel)
|
||||
modRoutes.POST("/torrent", TorrentPostEditModPanel)
|
||||
modRoutes.Any("/torrent/delete", TorrentDeleteModPanel)
|
||||
modRoutes.Any("/torrent/block", TorrentBlockModPanel)
|
||||
modRoutes.Any("/report/delete", TorrentReportDeleteModPanel)
|
||||
modRoutes.Any("/comment/delete", CommentDeleteModPanel)
|
||||
modRoutes.GET("/reassign", TorrentReassignModPanel)
|
||||
modRoutes.POST("/reassign", TorrentPostReassignModPanel)
|
||||
apiMod := modRoutes.Group("/api")
|
||||
apiMod.Any("/torrents", APIMassMod)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,193 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"html"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/activities"
|
||||
"github.com/NyaaPantsu/nyaa/models/reports"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/log"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/search"
|
||||
"github.com/NyaaPantsu/nyaa/utils/search/structs"
|
||||
"github.com/NyaaPantsu/nyaa/utils/upload"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator/torrent"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// TorrentsListPanel : Controller for listing torrents, can accept common search arguments
|
||||
func TorrentsListPanel(c *gin.Context) {
|
||||
page := c.Param("page")
|
||||
messages := msg.GetMessages(c)
|
||||
deleted := c.Request.URL.Query()["deleted"]
|
||||
unblocked := c.Request.URL.Query()["unblocked"]
|
||||
blocked := c.Request.URL.Query()["blocked"]
|
||||
if deleted != nil {
|
||||
messages.AddInfoTf("infos", "torrent_deleted", "")
|
||||
}
|
||||
if blocked != nil {
|
||||
messages.AddInfoT("infos", "torrent_blocked")
|
||||
}
|
||||
if unblocked != nil {
|
||||
messages.AddInfoT("infos", "torrent_unblocked")
|
||||
}
|
||||
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
searchParam, torrents, count, err := search.ByQueryWithUser(c, pagenum)
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
category := ""
|
||||
if len(searchParam.Category) > 0 {
|
||||
category = searchParam.Category[0].String()
|
||||
}
|
||||
searchForm := templates.SearchForm{
|
||||
TorrentParam: searchParam,
|
||||
Category: category,
|
||||
ShowItemsPerPage: true,
|
||||
}
|
||||
|
||||
nav := templates.Navigation{count, int(searchParam.Max), pagenum, "mod/torrents/p"}
|
||||
|
||||
templates.ModelList(c, "admin/torrentlist.jet.html", torrents, nav, searchForm)
|
||||
}
|
||||
|
||||
// TorrentEditModPanel : Controller for editing a torrent after GET request
|
||||
func TorrentEditModPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
torrent, _ := torrents.FindUnscopeByID(uint(id))
|
||||
|
||||
torrentJSON := torrent.ToJSON()
|
||||
uploadForm := upload.NewTorrentRequest()
|
||||
uploadForm.Name = torrentJSON.Name
|
||||
uploadForm.Category = torrentJSON.Category + "_" + torrentJSON.SubCategory
|
||||
uploadForm.Status = torrentJSON.Status
|
||||
uploadForm.Hidden = torrent.Hidden
|
||||
uploadForm.WebsiteLink = string(torrentJSON.WebsiteLink)
|
||||
uploadForm.Description = string(torrentJSON.Description)
|
||||
uploadForm.Languages = torrent.Languages
|
||||
|
||||
templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm)
|
||||
}
|
||||
|
||||
// TorrentPostEditModPanel : Controller for editing a torrent after POST request
|
||||
func TorrentPostEditModPanel(c *gin.Context) {
|
||||
var uploadForm torrentValidator.TorrentRequest
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
messages := msg.GetMessages(c)
|
||||
torrent, _ := torrents.FindUnscopeByID(uint(id))
|
||||
if torrent.ID > 0 {
|
||||
errUp := upload.ExtractEditInfo(c, &uploadForm)
|
||||
if errUp != nil {
|
||||
messages.AddErrorT("errors", "fail_torrent_update")
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
// update some (but not all!) values
|
||||
torrent.Name = uploadForm.Name
|
||||
torrent.Category = uploadForm.CategoryID
|
||||
torrent.SubCategory = uploadForm.SubCategoryID
|
||||
torrent.Status = uploadForm.Status
|
||||
torrent.Hidden = uploadForm.Hidden
|
||||
torrent.WebsiteLink = uploadForm.WebsiteLink
|
||||
torrent.Description = uploadForm.Description
|
||||
torrent.Languages = uploadForm.Languages
|
||||
_, err := torrent.UpdateUnscope()
|
||||
messages.AddInfoT("infos", "torrent_updated")
|
||||
if err == nil { // We only log edit torrent for admins
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "edit", "torrent_edited_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
|
||||
}
|
||||
}
|
||||
}
|
||||
templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm)
|
||||
}
|
||||
|
||||
// TorrentDeleteModPanel : Controller for deleting a torrent
|
||||
func TorrentDeleteModPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
definitely := c.Request.URL.Query()["definitely"]
|
||||
|
||||
var returnRoute = "/mod/torrents"
|
||||
torrent, errFind := torrents.FindByID(uint(id))
|
||||
if errFind == nil {
|
||||
var err error
|
||||
if definitely != nil {
|
||||
_, _, err = torrent.DefinitelyDelete()
|
||||
|
||||
//delete reports of torrent
|
||||
whereParams := structs.CreateWhereParams("torrent_id = ?", id)
|
||||
reports, _, _ := reports.FindOrderBy(&whereParams, "", 0, 0)
|
||||
for _, report := range reports {
|
||||
report.Delete(true)
|
||||
}
|
||||
returnRoute = "/mod/torrents/deleted"
|
||||
} else {
|
||||
_, _, err = torrent.Delete(false)
|
||||
|
||||
//delete reports of torrent
|
||||
whereParams := structs.CreateWhereParams("torrent_id = ?", id)
|
||||
reports, _, _ := reports.FindOrderBy(&whereParams, "", 0, 0)
|
||||
for _, report := range reports {
|
||||
report.Delete(false)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
|
||||
}
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusSeeOther, returnRoute+"?deleted")
|
||||
}
|
||||
|
||||
// TorrentBlockModPanel : Controller to lock torrents, redirecting to previous page
|
||||
func TorrentBlockModPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
torrent, _, err := torrents.ToggleBlock(uint(id))
|
||||
var returnRoute, action string
|
||||
if torrent.IsDeleted() {
|
||||
returnRoute = "/mod/torrents/deleted"
|
||||
} else {
|
||||
returnRoute = "/mod/torrents"
|
||||
}
|
||||
if torrent.IsBlocked() {
|
||||
action = "blocked"
|
||||
} else {
|
||||
action = "unblocked"
|
||||
}
|
||||
if err == nil {
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
activities.Log(&models.User{}, torrent.Identifier(), action, "torrent_"+action+"_by", strconv.Itoa(int(torrent.ID)), username, router.GetUser(c).Username)
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusSeeOther, returnRoute+"?"+action)
|
||||
}
|
||||
|
||||
// TorrentsPostListPanel : Controller for listing torrents, after POST request when mass update
|
||||
func TorrentsPostListPanel(c *gin.Context) {
|
||||
torrentManyAction(c)
|
||||
TorrentsListPanel(c)
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
package moderatorController
|
||||
|
||||
import (
|
||||
"html"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/log"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UsersListPanel : Controller for listing users, can accept pages
|
||||
func UsersListPanel(c *gin.Context) {
|
||||
page := c.Param("page")
|
||||
pagenum := 1
|
||||
offset := 100
|
||||
var err error
|
||||
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
users, nbUsers := users.FindUsersForAdmin(offset, (pagenum-1)*offset)
|
||||
nav := templates.Navigation{nbUsers, offset, pagenum, "mod/users/p"}
|
||||
templates.ModelList(c, "admin/userlist.jet.html", users, nav, templates.NewSearchForm(c))
|
||||
}
|
|
@ -1,568 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"html"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/activities"
|
||||
"github.com/NyaaPantsu/nyaa/models/comments"
|
||||
"github.com/NyaaPantsu/nyaa/models/reports"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/categories"
|
||||
"github.com/NyaaPantsu/nyaa/utils/log"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/search"
|
||||
"github.com/NyaaPantsu/nyaa/utils/search/structs"
|
||||
"github.com/NyaaPantsu/nyaa/utils/upload"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator/torrent"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// IndexModPanel : Controller for showing index page of Mod Panel
|
||||
func IndexModPanel(c *gin.Context) {
|
||||
offset := 10
|
||||
torrents, _, _ := torrents.FindAll(offset, 0)
|
||||
users, _ := users.FindUsersForAdmin(offset, 0)
|
||||
comments, _ := comments.FindAll(offset, 0, "", "")
|
||||
torrentReports, _, _ := reports.GetAll(offset, 0)
|
||||
|
||||
templates.PanelAdmin(c, torrents, models.TorrentReportsToJSON(torrentReports), users, comments)
|
||||
}
|
||||
|
||||
// TorrentsListPanel : Controller for listing torrents, can accept common search arguments
|
||||
func TorrentsListPanel(c *gin.Context) {
|
||||
page := c.Param("page")
|
||||
messages := msg.GetMessages(c)
|
||||
deleted := c.Request.URL.Query()["deleted"]
|
||||
unblocked := c.Request.URL.Query()["unblocked"]
|
||||
blocked := c.Request.URL.Query()["blocked"]
|
||||
if deleted != nil {
|
||||
messages.AddInfoTf("infos", "torrent_deleted", "")
|
||||
}
|
||||
if blocked != nil {
|
||||
messages.AddInfoT("infos", "torrent_blocked")
|
||||
}
|
||||
if unblocked != nil {
|
||||
messages.AddInfoT("infos", "torrent_unblocked")
|
||||
}
|
||||
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
searchParam, torrents, count, err := search.ByQueryWithUser(c, pagenum)
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
category := ""
|
||||
if len(searchParam.Category) > 0 {
|
||||
category = searchParam.Category[0].String()
|
||||
}
|
||||
searchForm := templates.SearchForm{
|
||||
TorrentParam: searchParam,
|
||||
Category: category,
|
||||
ShowItemsPerPage: true,
|
||||
}
|
||||
|
||||
nav := templates.Navigation{count, int(searchParam.Max), pagenum, "mod/torrents/p"}
|
||||
|
||||
templates.ModelList(c, "admin/torrentlist.jet.html", torrents, nav, searchForm)
|
||||
}
|
||||
|
||||
// TorrentReportListPanel : Controller for listing torrent reports, can accept pages
|
||||
func TorrentReportListPanel(c *gin.Context) {
|
||||
page := c.Param("page")
|
||||
pagenum := 1
|
||||
offset := 100
|
||||
var err error
|
||||
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
torrentReports, nbReports, _ := reports.GetAll(offset, (pagenum-1)*offset)
|
||||
|
||||
reportJSON := models.TorrentReportsToJSON(torrentReports)
|
||||
nav := templates.Navigation{nbReports, offset, pagenum, "mod/reports/p"}
|
||||
templates.ModelList(c, "admin/torrent_report.jet.html", reportJSON, nav, templates.NewSearchForm(c))
|
||||
}
|
||||
|
||||
// UsersListPanel : Controller for listing users, can accept pages
|
||||
func UsersListPanel(c *gin.Context) {
|
||||
page := c.Param("page")
|
||||
pagenum := 1
|
||||
offset := 100
|
||||
var err error
|
||||
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
users, nbUsers := users.FindUsersForAdmin(offset, (pagenum-1)*offset)
|
||||
nav := templates.Navigation{nbUsers, offset, pagenum, "mod/users/p"}
|
||||
templates.ModelList(c, "admin/userlist.jet.html", users, nav, templates.NewSearchForm(c))
|
||||
}
|
||||
|
||||
// CommentsListPanel : Controller for listing comments, can accept pages and userID
|
||||
func CommentsListPanel(c *gin.Context) {
|
||||
page := c.Param("page")
|
||||
pagenum := 1
|
||||
offset := 100
|
||||
userid := c.Query("userid")
|
||||
var err error
|
||||
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
var conditions string
|
||||
var values []interface{}
|
||||
if userid != "" {
|
||||
conditions = "user_id = ?"
|
||||
values = append(values, userid)
|
||||
}
|
||||
|
||||
comments, nbComments := comments.FindAll(offset, (pagenum-1)*offset, conditions, values...)
|
||||
nav := templates.Navigation{nbComments, offset, pagenum, "mod/comments/p"}
|
||||
templates.ModelList(c, "admin/commentlist.jet.html", comments, nav, templates.NewSearchForm(c))
|
||||
}
|
||||
|
||||
// TorrentEditModPanel : Controller for editing a torrent after GET request
|
||||
func TorrentEditModPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
torrent, _ := torrents.FindUnscopeByID(uint(id))
|
||||
|
||||
torrentJSON := torrent.ToJSON()
|
||||
uploadForm := upload.NewTorrentRequest()
|
||||
uploadForm.Name = torrentJSON.Name
|
||||
uploadForm.Category = torrentJSON.Category + "_" + torrentJSON.SubCategory
|
||||
uploadForm.Status = torrentJSON.Status
|
||||
uploadForm.Hidden = torrent.Hidden
|
||||
uploadForm.WebsiteLink = string(torrentJSON.WebsiteLink)
|
||||
uploadForm.Description = string(torrentJSON.Description)
|
||||
uploadForm.Languages = torrent.Languages
|
||||
|
||||
templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm)
|
||||
}
|
||||
|
||||
// TorrentPostEditModPanel : Controller for editing a torrent after POST request
|
||||
func TorrentPostEditModPanel(c *gin.Context) {
|
||||
var uploadForm torrentValidator.TorrentRequest
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
messages := msg.GetMessages(c)
|
||||
torrent, _ := torrents.FindUnscopeByID(uint(id))
|
||||
if torrent.ID > 0 {
|
||||
errUp := upload.ExtractEditInfo(c, &uploadForm)
|
||||
if errUp != nil {
|
||||
messages.AddErrorT("errors", "fail_torrent_update")
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
// update some (but not all!) values
|
||||
torrent.Name = uploadForm.Name
|
||||
torrent.Category = uploadForm.CategoryID
|
||||
torrent.SubCategory = uploadForm.SubCategoryID
|
||||
torrent.Status = uploadForm.Status
|
||||
torrent.Hidden = uploadForm.Hidden
|
||||
torrent.WebsiteLink = uploadForm.WebsiteLink
|
||||
torrent.Description = uploadForm.Description
|
||||
torrent.Languages = uploadForm.Languages
|
||||
_, err := torrent.UpdateUnscope()
|
||||
messages.AddInfoT("infos", "torrent_updated")
|
||||
if err == nil { // We only log edit torrent for admins
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "edit", "torrent_edited_by", strconv.Itoa(int(torrent.ID)), username, getUser(c).Username)
|
||||
}
|
||||
}
|
||||
}
|
||||
templates.Form(c, "admin/paneltorrentedit.jet.html", uploadForm)
|
||||
}
|
||||
|
||||
// CommentDeleteModPanel : Controller for deleting a comment
|
||||
func CommentDeleteModPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
comment, _, err := comments.Delete(uint(id))
|
||||
if err == nil {
|
||||
activities.Log(&models.User{}, comment.Identifier(), "delete", "comment_deleted_by", strconv.Itoa(int(comment.ID)), comment.User.Username, getUser(c).Username)
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusSeeOther, "/mod/comments?deleted")
|
||||
}
|
||||
|
||||
// TorrentDeleteModPanel : Controller for deleting a torrent
|
||||
func TorrentDeleteModPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
definitely := c.Request.URL.Query()["definitely"]
|
||||
|
||||
var returnRoute = "/mod/torrents"
|
||||
torrent, errFind := torrents.FindByID(uint(id))
|
||||
if errFind == nil {
|
||||
var err error
|
||||
if definitely != nil {
|
||||
_, _, err = torrent.DefinitelyDelete()
|
||||
|
||||
//delete reports of torrent
|
||||
whereParams := structs.CreateWhereParams("torrent_id = ?", id)
|
||||
reports, _, _ := reports.FindOrderBy(&whereParams, "", 0, 0)
|
||||
for _, report := range reports {
|
||||
report.Delete(true)
|
||||
}
|
||||
returnRoute = "/mod/torrents/deleted"
|
||||
} else {
|
||||
_, _, err = torrent.Delete(false)
|
||||
|
||||
//delete reports of torrent
|
||||
whereParams := structs.CreateWhereParams("torrent_id = ?", id)
|
||||
reports, _, _ := reports.FindOrderBy(&whereParams, "", 0, 0)
|
||||
for _, report := range reports {
|
||||
report.Delete(false)
|
||||
}
|
||||
}
|
||||
if err == nil {
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, getUser(c).Username)
|
||||
}
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusSeeOther, returnRoute+"?deleted")
|
||||
}
|
||||
|
||||
// TorrentReportDeleteModPanel : Controller for deleting a torrent report
|
||||
func TorrentReportDeleteModPanel(c *gin.Context) {
|
||||
id := c.Query("id")
|
||||
|
||||
fmt.Println(id)
|
||||
idNum, _ := strconv.ParseUint(id, 10, 64)
|
||||
_, _, _ = reports.Delete(uint(idNum))
|
||||
/* If we need to log report delete activity
|
||||
if err == nil {
|
||||
activity.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_report_deleted_by", strconv.Itoa(int(report.ID)), getUser(c).Username)
|
||||
}
|
||||
*/
|
||||
c.Redirect(http.StatusSeeOther, "/mod/reports?deleted")
|
||||
}
|
||||
|
||||
// TorrentReassignModPanel : Controller for reassigning a torrent, after GET request
|
||||
func TorrentReassignModPanel(c *gin.Context) {
|
||||
templates.Form(c, "admin/reassign.jet.html", torrentValidator.ReassignForm{})
|
||||
}
|
||||
|
||||
// ExecuteAction : Function for applying the changes from ReassignForm
|
||||
func ExecuteReassign(f *torrentValidator.ReassignForm) (int, error) {
|
||||
var toBeChanged []uint
|
||||
var err error
|
||||
if f.By == "olduser" {
|
||||
toBeChanged, err = users.FindOldUploadsByUsername(f.Data)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
} else if f.By == "torrentid" {
|
||||
toBeChanged = f.Torrents
|
||||
}
|
||||
|
||||
num := 0
|
||||
for _, torrentID := range toBeChanged {
|
||||
torrent, err2 := torrents.FindRawByID(torrentID)
|
||||
if err2 == nil {
|
||||
torrent.UploaderID = f.AssignTo
|
||||
torrent.Update(true)
|
||||
num++
|
||||
}
|
||||
}
|
||||
return num, nil
|
||||
}
|
||||
|
||||
// TorrentPostReassignModPanel : Controller for reassigning a torrent, after POST request
|
||||
func TorrentPostReassignModPanel(c *gin.Context) {
|
||||
var rForm torrentValidator.ReassignForm
|
||||
messages := msg.GetMessages(c)
|
||||
|
||||
if rForm.ExtractInfo(c) {
|
||||
count, err2 := ExecuteReassign(&rForm)
|
||||
if err2 != nil {
|
||||
messages.AddErrorT("errors", "something_went_wrong")
|
||||
} else {
|
||||
messages.AddInfoTf("infos", "nb_torrents_updated", count)
|
||||
}
|
||||
}
|
||||
templates.Form(c, "admin/reassign.jet.html", rForm)
|
||||
}
|
||||
|
||||
// TorrentsPostListPanel : Controller for listing torrents, after POST request when mass update
|
||||
func TorrentsPostListPanel(c *gin.Context) {
|
||||
torrentManyAction(c)
|
||||
TorrentsListPanel(c)
|
||||
}
|
||||
|
||||
// APIMassMod : This function is used on the frontend for the mass
|
||||
/* Query is: action=status|delete|owner|category|multiple
|
||||
* Needed: torrent_id[] Ids of torrents in checkboxes of name torrent_id
|
||||
*
|
||||
* Needed on context:
|
||||
* status=0|1|2|3|4 according to config/find.go (can be omitted if action=delete|owner|category|multiple)
|
||||
* owner is the User ID of the new owner of the torrents (can be omitted if action=delete|status|category|multiple)
|
||||
* category is the category string (eg. 1_3) of the new category of the torrents (can be omitted if action=delete|status|owner|multiple)
|
||||
*
|
||||
* withreport is the bool to enable torrent reports deletion (can be omitted)
|
||||
*
|
||||
* In case of action=multiple, torrents can be at the same time changed status, owner and category
|
||||
*/
|
||||
func APIMassMod(c *gin.Context) {
|
||||
torrentManyAction(c)
|
||||
messages := msg.GetMessages(c) // new utils for errors and infos
|
||||
c.Header("Content-Type", "application/json")
|
||||
|
||||
var mapOk map[string]interface{}
|
||||
if !messages.HasErrors() {
|
||||
mapOk = map[string]interface{}{"ok": true, "infos": messages.GetAllInfos()["infos"]}
|
||||
} else { // We need to show error messages
|
||||
mapOk = map[string]interface{}{"ok": false, "errors": messages.GetAllErrors()["errors"]}
|
||||
}
|
||||
|
||||
c.JSON(http.StatusOK, mapOk)
|
||||
}
|
||||
|
||||
// DeletedTorrentsModPanel : Controller for viewing deleted torrents, accept common search arguments
|
||||
func DeletedTorrentsModPanel(c *gin.Context) {
|
||||
page := c.Param("page")
|
||||
messages := msg.GetMessages(c) // new utils for errors and infos
|
||||
deleted := c.Request.URL.Query()["deleted"]
|
||||
unblocked := c.Request.URL.Query()["unblocked"]
|
||||
blocked := c.Request.URL.Query()["blocked"]
|
||||
if deleted != nil {
|
||||
messages.AddInfoT("infos", "torrent_deleted_definitely")
|
||||
}
|
||||
if blocked != nil {
|
||||
messages.AddInfoT("infos", "torrent_blocked")
|
||||
}
|
||||
if unblocked != nil {
|
||||
messages.AddInfoT("infos", "torrent_unblocked")
|
||||
}
|
||||
var err error
|
||||
pagenum := 1
|
||||
if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if !log.CheckError(err) {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
searchParam, torrents, count, err := search.ByQueryDeleted(c, pagenum)
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
category := ""
|
||||
if len(searchParam.Category) > 0 {
|
||||
category = searchParam.Category[0].String()
|
||||
}
|
||||
searchForm := templates.SearchForm{
|
||||
TorrentParam: searchParam,
|
||||
Category: category,
|
||||
ShowItemsPerPage: true,
|
||||
}
|
||||
|
||||
nav := templates.Navigation{count, int(searchParam.Max), pagenum, "mod/torrents/deleted/p"}
|
||||
search := searchForm
|
||||
templates.ModelList(c, "admin/torrentlist.jet.html", torrents, nav, search)
|
||||
}
|
||||
|
||||
// DeletedTorrentsPostPanel : Controller for viewing deleted torrents after a mass update, accept common search arguments
|
||||
func DeletedTorrentsPostPanel(c *gin.Context) {
|
||||
torrentManyAction(c)
|
||||
DeletedTorrentsModPanel(c)
|
||||
}
|
||||
|
||||
// TorrentBlockModPanel : Controller to lock torrents, redirecting to previous page
|
||||
func TorrentBlockModPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
torrent, _, err := torrents.ToggleBlock(uint(id))
|
||||
var returnRoute, action string
|
||||
if torrent.IsDeleted() {
|
||||
returnRoute = "/mod/torrents/deleted"
|
||||
} else {
|
||||
returnRoute = "/mod/torrents"
|
||||
}
|
||||
if torrent.IsBlocked() {
|
||||
action = "blocked"
|
||||
} else {
|
||||
action = "unblocked"
|
||||
}
|
||||
if err == nil {
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
activities.Log(&models.User{}, torrent.Identifier(), action, "torrent_"+action+"_by", strconv.Itoa(int(torrent.ID)), username, getUser(c).Username)
|
||||
}
|
||||
|
||||
c.Redirect(http.StatusSeeOther, returnRoute+"?"+action)
|
||||
}
|
||||
|
||||
/*
|
||||
* Controller to modify multiple torrents and can be used by the owner of the torrent or admin
|
||||
*/
|
||||
func torrentManyAction(c *gin.Context) {
|
||||
currentUser := getUser(c)
|
||||
|
||||
torrentsSelected := c.PostFormArray("torrent_id") // should be []string
|
||||
action := c.PostForm("action")
|
||||
status, _ := strconv.Atoi(c.PostForm("status"))
|
||||
owner, _ := strconv.Atoi(c.PostForm("owner"))
|
||||
category := c.PostForm("category")
|
||||
withReport, _ := strconv.ParseBool(c.DefaultPostForm("withreport", "false"))
|
||||
messages := msg.GetMessages(c) // new utils for errors and infos
|
||||
catID, subCatID := -1, -1
|
||||
var err error
|
||||
|
||||
if action == "" {
|
||||
messages.AddErrorT("errors", "no_action_selected")
|
||||
}
|
||||
if action == "status" && c.PostForm("status") == "" { // We need to check the form value, not the int one because hidden is 0
|
||||
messages.AddErrorT("errors", "no_move_location_selected")
|
||||
}
|
||||
if action == "owner" && c.PostForm("owner") == "" { // We need to check the form value, not the int one because renchon is 0
|
||||
messages.AddErrorT("errors", "no_owner_selected")
|
||||
}
|
||||
if action == "category" && category == "" {
|
||||
messages.AddErrorT("errors", "no_category_selected")
|
||||
}
|
||||
if len(torrentsSelected) == 0 {
|
||||
messages.AddErrorT("errors", "select_one_element")
|
||||
}
|
||||
|
||||
if !config.Get().Torrents.Status[status] { // Check if the status exist
|
||||
messages.AddErrorTf("errors", "no_status_exist", status)
|
||||
status = -1
|
||||
}
|
||||
if !currentUser.HasAdmin() {
|
||||
if c.PostForm("status") != "" { // Condition to check if a user try to change torrent status without having the right permission
|
||||
if (status == models.TorrentStatusTrusted && !currentUser.IsTrusted()) || status == models.TorrentStatusAPlus || status == 0 {
|
||||
status = models.TorrentStatusNormal
|
||||
}
|
||||
}
|
||||
if c.PostForm("owner") != "" { // Only admins can change owner of torrents
|
||||
owner = -1
|
||||
}
|
||||
withReport = false // Users should not be able to remove reports
|
||||
}
|
||||
if c.PostForm("owner") != "" && currentUser.HasAdmin() { // We check that the user given exist and if not we return an error
|
||||
_, _, errorUser := users.FindForAdmin(uint(owner))
|
||||
if errorUser != nil {
|
||||
messages.AddErrorTf("errors", "no_user_found_id", owner)
|
||||
owner = -1
|
||||
}
|
||||
}
|
||||
if category != "" {
|
||||
catsSplit := strings.Split(category, "_")
|
||||
// need this to prevent out of index panics
|
||||
if len(catsSplit) == 2 {
|
||||
catID, err = strconv.Atoi(catsSplit[0])
|
||||
if err != nil {
|
||||
messages.AddErrorT("errors", "invalid_torrent_category")
|
||||
}
|
||||
subCatID, err = strconv.Atoi(catsSplit[1])
|
||||
if err != nil {
|
||||
messages.AddErrorT("errors", "invalid_torrent_category")
|
||||
}
|
||||
|
||||
if !categories.Exists(category) {
|
||||
messages.AddErrorT("errors", "invalid_torrent_category")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if !messages.HasErrors() {
|
||||
for _, torrentID := range torrentsSelected {
|
||||
id, _ := strconv.Atoi(torrentID)
|
||||
torrent, _ := torrents.FindByID(uint(id))
|
||||
if torrent.ID > 0 && currentUser.CurrentOrAdmin(torrent.UploaderID) {
|
||||
if action == "status" || action == "multiple" || action == "category" || action == "owner" {
|
||||
|
||||
/* If we don't delete, we make changes according to the form posted and we save at the end */
|
||||
if c.PostForm("status") != "" && status != -1 {
|
||||
torrent.Status = status
|
||||
messages.AddInfoTf("infos", "torrent_moved", torrent.Name)
|
||||
}
|
||||
if c.PostForm("owner") != "" && owner != -1 {
|
||||
torrent.UploaderID = uint(owner)
|
||||
messages.AddInfoTf("infos", "torrent_owner_changed", torrent.Name)
|
||||
}
|
||||
if category != "" && catID != -1 && subCatID != -1 {
|
||||
torrent.Category = catID
|
||||
torrent.SubCategory = subCatID
|
||||
messages.AddInfoTf("infos", "torrent_category_changed", torrent.Name)
|
||||
}
|
||||
|
||||
/* Changes are done, we save */
|
||||
_, err := torrent.UpdateUnscope()
|
||||
if err == nil {
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "edited", "torrent_edited_by", strconv.Itoa(int(torrent.ID)), username, getUser(c).Username)
|
||||
}
|
||||
} else if action == "delete" {
|
||||
if status == models.TorrentStatusBlocked { // Then we should lock torrents before deleting them
|
||||
torrent.Status = status
|
||||
messages.AddInfoTf("infos", "torrent_moved", torrent.Name)
|
||||
torrent.UpdateUnscope()
|
||||
}
|
||||
_, _, err = torrent.Delete(false)
|
||||
if err != nil {
|
||||
messages.ImportFromError("errors", err)
|
||||
} else {
|
||||
messages.AddInfoTf("infos", "torrent_deleted", torrent.Name)
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "deleted", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, getUser(c).Username)
|
||||
}
|
||||
} else {
|
||||
messages.AddErrorTf("errors", "no_action_exist", action)
|
||||
}
|
||||
if withReport {
|
||||
whereParams := structs.CreateWhereParams("torrent_id = ?", torrentID)
|
||||
reports, _, _ := reports.FindOrderBy(&whereParams, "", 0, 0)
|
||||
for _, report := range reports {
|
||||
report.Delete(false)
|
||||
}
|
||||
messages.AddInfoTf("infos", "torrent_reports_deleted", torrent.Name)
|
||||
}
|
||||
} else {
|
||||
messages.AddErrorTf("errors", "torrent_not_exist", torrentID)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -44,7 +44,7 @@
|
|||
//
|
||||
// https://blog.golang.org/2011/06/profiling-go-programs.html
|
||||
//
|
||||
package controllers
|
||||
package pprofController
|
||||
|
||||
import (
|
||||
"bufio"
|
|
@ -0,0 +1,18 @@
|
|||
package pprofController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/middlewares"
|
||||
|
||||
func init() {
|
||||
// Adding pprof support
|
||||
pprofRoutes := router.Get().Group("/debug/pprof", middlewares.ModMiddleware())
|
||||
{
|
||||
pprofRoutes.GET("/", PprofIndex)
|
||||
pprofRoutes.GET("/block", PprofIndex)
|
||||
pprofRoutes.GET("/heap", PprofIndex)
|
||||
pprofRoutes.GET("/profile", PprofProfile)
|
||||
pprofRoutes.POST("/symbol", PprofSymbol)
|
||||
pprofRoutes.GET("/symbol", PprofSymbol)
|
||||
pprofRoutes.GET("/trace", PprofTrace)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package reportController
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models/reports"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/captcha"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ReportTorrentHandler : Controller for sending a torrent report
|
||||
func ReportTorrentHandler(c *gin.Context) {
|
||||
fmt.Println("report")
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 32)
|
||||
messages := msg.GetMessages(c)
|
||||
captchaError := "?reported"
|
||||
currentUser := router.GetUser(c)
|
||||
if currentUser.NeedsCaptcha() {
|
||||
userCaptcha := captcha.Extract(c)
|
||||
if !captcha.Authenticate(userCaptcha) {
|
||||
captchaError = "?badcaptcha"
|
||||
messages.AddErrorT("errors", "bad_captcha")
|
||||
}
|
||||
}
|
||||
torrent, err := torrents.FindByID(uint(id))
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
_, err := reports.Create(c.PostForm("report_type"), torrent, currentUser)
|
||||
messages.AddInfoTf("infos", "report_msg", id)
|
||||
if err != nil {
|
||||
messages.ImportFromError("errors", err)
|
||||
}
|
||||
c.Redirect(http.StatusSeeOther, "/view/"+strconv.Itoa(int(torrent.ID))+captchaError)
|
||||
} else {
|
||||
ReportViewTorrentHandler(c)
|
||||
}
|
||||
}
|
||||
|
||||
// ReportViewTorrentHandler : Controller for sending a torrent report
|
||||
func ReportViewTorrentHandler(c *gin.Context) {
|
||||
|
||||
type Report struct {
|
||||
ID uint
|
||||
CaptchaID string
|
||||
}
|
||||
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 32)
|
||||
messages := msg.GetMessages(c)
|
||||
currentUser := router.GetUser(c)
|
||||
if currentUser.ID > 0 {
|
||||
torrent, err := torrents.FindByID(uint(id))
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
captchaID := ""
|
||||
if currentUser.NeedsCaptcha() {
|
||||
captchaID = captcha.GetID()
|
||||
}
|
||||
templates.Form(c, "site/torrents/report.jet.html", Report{torrent.ID, captchaID})
|
||||
} else {
|
||||
c.Status(404)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,12 @@
|
|||
package reportController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
reportRoutes := router.Get().Group("/report")
|
||||
{
|
||||
//reporting a torrent
|
||||
reportRoutes.GET("/:id", ReportViewTorrentHandler)
|
||||
reportRoutes.POST("/:id", ReportTorrentHandler)
|
||||
}
|
||||
}
|
|
@ -3,159 +3,30 @@ package controllers
|
|||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/utils/captcha"
|
||||
"github.com/gin-gonic/gin"
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/activities" // activities controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/api" // api controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/captcha" // captcha controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/databasedumps" // databasedumps controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/faq" // faq controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/feed" // feed controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/middlewares" // middlewares
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/moderator" // moderator controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/pprof" // pprof controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/report" // report controller
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/search" // search controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/settings" // settings controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/torrent" // torrent controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/upload" // upload controller
|
||||
_ "github.com/NyaaPantsu/nyaa/controllers/user" // user controller
|
||||
"github.com/justinas/nosurf"
|
||||
)
|
||||
|
||||
// Router variable for exporting the route configuration
|
||||
var Router *gin.Engine
|
||||
|
||||
// CSRFRouter : CSRF protection for Router variable for exporting the route configuration
|
||||
var CSRFRouter *nosurf.CSRFHandler
|
||||
|
||||
func init() {
|
||||
Router = gin.New()
|
||||
//Router.Use(gzip.Gzip(gzip.DefaultCompression)) // FIXME I can't make it work :/
|
||||
Router.Use(gin.Logger())
|
||||
Router.Use(gin.Recovery())
|
||||
Router.Use(errorMiddleware())
|
||||
|
||||
// Static file handlers
|
||||
// TODO Use config from cli
|
||||
// TODO Make sure the directory exists
|
||||
Router.StaticFS("/css/", http.Dir("./public/css/"))
|
||||
Router.StaticFS("/js/", http.Dir("./public/js/"))
|
||||
Router.StaticFS("/img/", http.Dir("./public/img/"))
|
||||
Router.StaticFS("/apidoc/", http.Dir("./apidoc/"))
|
||||
Router.StaticFS("/dbdumps/", http.Dir(DatabaseDumpPath))
|
||||
Router.StaticFS("/gpg/", http.Dir(GPGPublicKeyPath))
|
||||
|
||||
// We don't need CSRF here
|
||||
Router.Any("/", SearchHandler)
|
||||
Router.Any("/p/:page", SearchHandler)
|
||||
Router.Any("/search", SearchHandler)
|
||||
Router.Any("/search/:page", SearchHandler)
|
||||
Router.Any("/verify/email/:token", UserVerifyEmailHandler)
|
||||
Router.Any("/faq", FaqHandler)
|
||||
Router.Any("/activities", ActivityListHandler)
|
||||
Router.Any("/activities/p/:page", ActivityListHandler)
|
||||
Router.Any("/feed", RSSHandler)
|
||||
Router.Any("/feed/p/:page", RSSHandler)
|
||||
Router.Any("/feed/magnet", RSSMagnetHandler)
|
||||
Router.Any("/feed/magnet/p/:page", RSSMagnetHandler)
|
||||
Router.Any("/feed/torznab", RSSTorznabHandler)
|
||||
Router.Any("/feed/torznab/api", RSSTorznabHandler)
|
||||
Router.Any("/feed/torznab/p/:page", RSSTorznabHandler)
|
||||
Router.Any("/feed/eztv", RSSEztvHandler)
|
||||
Router.Any("/feed/eztv/p/:page", RSSEztvHandler)
|
||||
|
||||
// !!! This line need to have the same download location as the one define in config.TorrentStorageLink !!!
|
||||
Router.Any("/download/:hash", DownloadTorrent)
|
||||
|
||||
Router.Any("/upload", UploadHandler)
|
||||
Router.POST("/login", UserLoginPostHandler)
|
||||
Router.GET("/register", UserRegisterFormHandler)
|
||||
Router.GET("/login", UserLoginFormHandler)
|
||||
Router.POST("/register", UserRegisterPostHandler)
|
||||
Router.POST("/logout", UserLogoutHandler)
|
||||
Router.GET("/notifications", UserNotificationsHandler)
|
||||
|
||||
reportRoutes := Router.Group("/report")
|
||||
{
|
||||
//reporting a torrent
|
||||
reportRoutes.GET("/:id", ReportViewTorrentHandler)
|
||||
reportRoutes.POST("/:id", ReportTorrentHandler)
|
||||
}
|
||||
torrentViewRoutes := Router.Group("/view")
|
||||
{
|
||||
torrentViewRoutes.GET("/:id", ViewHandler)
|
||||
torrentViewRoutes.HEAD("/:id", ViewHeadHandler)
|
||||
torrentViewRoutes.POST("/:id", PostCommentHandler)
|
||||
}
|
||||
torrentRoutes := Router.Group("/torrent")
|
||||
{
|
||||
torrentRoutes.GET("/", TorrentEditUserPanel)
|
||||
torrentRoutes.POST("/", TorrentPostEditUserPanel)
|
||||
torrentRoutes.GET("/delete", TorrentDeleteUserPanel)
|
||||
}
|
||||
userRoutes := Router.Group("/user")
|
||||
{
|
||||
userRoutes.GET("/:id/:username", UserProfileHandler)
|
||||
userRoutes.GET("/:id/:username/follow", UserFollowHandler)
|
||||
userRoutes.GET("/:id/:username/edit", UserDetailsHandler)
|
||||
userRoutes.POST("/:id/:username/edit", UserProfileFormHandler)
|
||||
userRoutes.GET("/:id/:username/apireset", UserAPIKeyResetHandler)
|
||||
userRoutes.GET("/:id/:username/feed/*page", RSSHandler)
|
||||
}
|
||||
// We don't need CSRF here
|
||||
api := Router.Group("/api")
|
||||
{
|
||||
api.GET("", APIHandler)
|
||||
api.GET("/p/:page", APIHandler)
|
||||
api.GET("/view/:id", APIViewHandler)
|
||||
api.HEAD("/view/:id", APIViewHeadHandler)
|
||||
api.POST("/upload", APIUploadHandler)
|
||||
api.POST("/login", APILoginHandler)
|
||||
api.GET("/token/check", APICheckTokenHandler)
|
||||
api.GET("/token/refresh", APIRefreshTokenHandler)
|
||||
api.Any("/search", APISearchHandler)
|
||||
api.Any("/search/p/:page", APISearchHandler)
|
||||
api.PUT("/update", APIUpdateHandler)
|
||||
}
|
||||
|
||||
// INFO Everything under /mod should be wrapped by wrapModHandler. This make
|
||||
// sure the page is only accessible by moderators
|
||||
// We don't need CSRF here
|
||||
modRoutes := Router.Group("/mod", modMiddleware())
|
||||
{
|
||||
modRoutes.Any("/", IndexModPanel)
|
||||
modRoutes.GET("/torrents", TorrentsListPanel)
|
||||
modRoutes.GET("/torrents/p/:page", TorrentsListPanel)
|
||||
modRoutes.POST("/torrents", TorrentsPostListPanel)
|
||||
modRoutes.POST("/torrents/p/:page", TorrentsPostListPanel)
|
||||
modRoutes.GET("/torrents/deleted", DeletedTorrentsModPanel)
|
||||
modRoutes.GET("/torrents/deleted/p/:page", DeletedTorrentsModPanel)
|
||||
modRoutes.POST("/torrents/deleted", DeletedTorrentsPostPanel)
|
||||
modRoutes.POST("/torrents/deleted/p/:page", DeletedTorrentsPostPanel)
|
||||
modRoutes.Any("/reports", TorrentReportListPanel)
|
||||
modRoutes.Any("/reports/p/:page", TorrentReportListPanel)
|
||||
modRoutes.Any("/users", UsersListPanel)
|
||||
modRoutes.Any("/users/p/:page", UsersListPanel)
|
||||
modRoutes.Any("/comments", CommentsListPanel)
|
||||
modRoutes.Any("/comments/p/:page", CommentsListPanel)
|
||||
modRoutes.Any("/comment", CommentsListPanel) // TODO
|
||||
modRoutes.GET("/torrent", TorrentEditModPanel)
|
||||
modRoutes.POST("/torrent", TorrentPostEditModPanel)
|
||||
modRoutes.Any("/torrent/delete", TorrentDeleteModPanel)
|
||||
modRoutes.Any("/torrent/block", TorrentBlockModPanel)
|
||||
modRoutes.Any("/report/delete", TorrentReportDeleteModPanel)
|
||||
modRoutes.Any("/comment/delete", CommentDeleteModPanel)
|
||||
modRoutes.GET("/reassign", TorrentReassignModPanel)
|
||||
modRoutes.POST("/reassign", TorrentPostReassignModPanel)
|
||||
apiMod := modRoutes.Group("/api")
|
||||
apiMod.Any("/torrents", APIMassMod)
|
||||
}
|
||||
|
||||
Router.Any("/captcha/*hash", captcha.ServeFiles)
|
||||
|
||||
Router.Any("/dumps", DatabaseDumpHandler)
|
||||
|
||||
Router.GET("/settings", SeePublicSettingsHandler)
|
||||
Router.POST("/settings", ChangePublicSettingsHandler)
|
||||
|
||||
// Adding pprof support
|
||||
pprofRoutes := Router.Group("/debug/pprof", modMiddleware())
|
||||
{
|
||||
pprofRoutes.GET("/", PprofIndex)
|
||||
pprofRoutes.GET("/block", PprofIndex)
|
||||
pprofRoutes.GET("/heap", PprofIndex)
|
||||
pprofRoutes.GET("/profile", PprofProfile)
|
||||
pprofRoutes.POST("/symbol", PprofSymbol)
|
||||
pprofRoutes.GET("/symbol", PprofSymbol)
|
||||
pprofRoutes.GET("/trace", PprofTrace)
|
||||
}
|
||||
CSRFRouter = nosurf.New(Router)
|
||||
CSRFRouter = nosurf.New(router.Get())
|
||||
CSRFRouter.ExemptRegexp("/api(?:/.+)*")
|
||||
CSRFRouter.ExemptRegexp("/mod(?:/.+)*")
|
||||
CSRFRouter.ExemptPath("/upload")
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
package controllers
|
||||
package router
|
||||
|
||||
import (
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
|
@ -6,7 +6,8 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func getUser(c *gin.Context) *models.User {
|
||||
// GetUser return the current user from the context
|
||||
func GetUser(c *gin.Context) *models.User {
|
||||
user, _, _ := cookies.CurrentUser(c)
|
||||
if user == nil {
|
||||
return &models.User{}
|
|
@ -0,0 +1,20 @@
|
|||
package router
|
||||
|
||||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
var router *gin.Engine
|
||||
var once sync.Once
|
||||
|
||||
// Get return a router signleton
|
||||
func Get() *gin.Engine {
|
||||
once.Do(func() {
|
||||
router = gin.New()
|
||||
router.Use(gin.Logger())
|
||||
router.Use(gin.Recovery())
|
||||
})
|
||||
return router
|
||||
}
|
|
@ -1,415 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"html"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/NyaaPantsu/nyaa/utils/categories"
|
||||
"github.com/NyaaPantsu/nyaa/utils/feeds"
|
||||
"github.com/NyaaPantsu/nyaa/utils/publicSettings"
|
||||
"github.com/NyaaPantsu/nyaa/utils/search"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/gorilla/feeds"
|
||||
)
|
||||
|
||||
// RSSHandler : Controller for displaying rss feed, accepting common search arguments
|
||||
func RSSHandler(c *gin.Context) {
|
||||
// We only get the basic variable for rss based on search param
|
||||
torrents, createdAsTime, title, err := getTorrentList(c)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
feed := &nyaafeeds.RssFeed{
|
||||
Title: title,
|
||||
Link: config.WebAddress() + "/",
|
||||
PubDate: createdAsTime.String(),
|
||||
}
|
||||
feed.Items = make([]*nyaafeeds.RssItem, len(torrents))
|
||||
|
||||
for i, torrent := range torrents {
|
||||
torrentJSON := torrent.ToJSON()
|
||||
feed.Items[i] = &nyaafeeds.RssItem{
|
||||
Title: torrentJSON.Name,
|
||||
Link: config.WebAddress() + "/download/" + torrentJSON.Hash,
|
||||
Description: string(torrentJSON.Description),
|
||||
PubDate: torrent.Date.Format(time.RFC822),
|
||||
GUID: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
Enclosure: &nyaafeeds.RssEnclosure{
|
||||
URL: config.WebAddress() + "/download/" + strings.TrimSpace(torrentJSON.Hash),
|
||||
Length: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
Type: "application/x-bittorrent",
|
||||
},
|
||||
}
|
||||
}
|
||||
// allow cross domain AJAX requests
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
rss, rssErr := feeds.ToXML(feed)
|
||||
if rssErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, rssErr)
|
||||
}
|
||||
|
||||
_, writeErr := c.Writer.Write([]byte(rss))
|
||||
if writeErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, writeErr)
|
||||
}
|
||||
}
|
||||
|
||||
// RSSMagnetHandler : Controller for displaying rss feeds with magnet URL, accepting common search arguments
|
||||
func RSSMagnetHandler(c *gin.Context) {
|
||||
// We only get the basic variable for rss based on search param
|
||||
torrents, createdAsTime, title, err := getTorrentList(c)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
feed := &nyaafeeds.RssFeed{
|
||||
Title: title,
|
||||
Link: config.WebAddress() + "/",
|
||||
PubDate: createdAsTime.String(),
|
||||
}
|
||||
feed.Items = make([]*nyaafeeds.RssItem, len(torrents))
|
||||
|
||||
for i, torrent := range torrents {
|
||||
torrentJSON := torrent.ToJSON()
|
||||
feed.Items[i] = &nyaafeeds.RssItem{
|
||||
Title: torrentJSON.Name,
|
||||
Link: &nyaafeeds.RssMagnetLink{Text: string(torrentJSON.Magnet)},
|
||||
Description: string(torrentJSON.Description),
|
||||
PubDate: torrent.Date.Format(time.RFC822),
|
||||
GUID: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
Enclosure: &nyaafeeds.RssEnclosure{
|
||||
URL: config.WebAddress() + "/download/" + strings.TrimSpace(torrentJSON.Hash),
|
||||
Length: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
Type: "application/x-bittorrent",
|
||||
},
|
||||
}
|
||||
}
|
||||
// allow cross domain AJAX requests
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
rss, rssErr := feeds.ToXML(feed)
|
||||
if rssErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, rssErr)
|
||||
}
|
||||
|
||||
_, writeErr := c.Writer.Write([]byte(rss))
|
||||
if writeErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, writeErr)
|
||||
}
|
||||
}
|
||||
|
||||
// RSSEztvHandler : Controller for displaying rss feed, accepting common search arguments
|
||||
func RSSEztvHandler(c *gin.Context) {
|
||||
// We only get the basic variable for rss based on search param
|
||||
torrents, createdAsTime, title, err := getTorrentList(c)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, err)
|
||||
return
|
||||
}
|
||||
|
||||
feed := &nyaafeeds.RssFeed{
|
||||
Title: title,
|
||||
Link: config.WebAddress() + "/",
|
||||
PubDate: createdAsTime.String(),
|
||||
}
|
||||
feed.Items = make([]*nyaafeeds.RssItem, len(torrents))
|
||||
|
||||
for i, torrent := range torrents {
|
||||
torrentJSON := torrent.ToJSON()
|
||||
feed.Items[i] = &nyaafeeds.RssItem{
|
||||
Title: torrentJSON.Name,
|
||||
Link: config.WebAddress() + "/download/" + torrentJSON.Hash,
|
||||
Category: &nyaafeeds.RssCategory{
|
||||
Domain: config.WebAddress() + "/search?c=" + torrentJSON.Category + "_" + torrentJSON.SubCategory,
|
||||
},
|
||||
Description: string(torrentJSON.Description),
|
||||
Comments: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
PubDate: torrent.Date.Format(time.RFC822),
|
||||
GUID: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
Enclosure: &nyaafeeds.RssEnclosure{
|
||||
URL: config.WebAddress() + "/download/" + strings.TrimSpace(torrentJSON.Hash),
|
||||
Length: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
Type: "application/x-bittorrent",
|
||||
},
|
||||
Torrent: &nyaafeeds.RssTorrent{
|
||||
Xmlns: "http://xmlns.ezrss.it/0.1/",
|
||||
FileName: torrentJSON.Name + ".torrent",
|
||||
ContentLength: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
InfoHash: torrentJSON.Hash,
|
||||
MagnetURI: string(torrentJSON.Magnet),
|
||||
},
|
||||
}
|
||||
}
|
||||
// allow cross domain AJAX requests
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
rss, rssErr := feeds.ToXML(feed)
|
||||
if rssErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, rssErr)
|
||||
}
|
||||
|
||||
_, writeErr := c.Writer.Write([]byte(rss))
|
||||
if writeErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, writeErr)
|
||||
}
|
||||
}
|
||||
|
||||
// RSSTorznabHandler : Controller for displaying rss feed, accepting common search arguments
|
||||
func RSSTorznabHandler(c *gin.Context) {
|
||||
t := c.Query("t")
|
||||
rss := ""
|
||||
title := "Nyaa Pantsu"
|
||||
if config.IsSukebei() {
|
||||
title = "Sukebei Pantsu"
|
||||
}
|
||||
if t == "caps" {
|
||||
T := publicSettings.GetTfuncFromRequest(c)
|
||||
cats := categories.GetSelect(true, true)
|
||||
var categories []*nyaafeeds.RssCategoryTorznab
|
||||
categories = append(categories, &nyaafeeds.RssCategoryTorznab{
|
||||
ID: "5070",
|
||||
Name: "Anime",
|
||||
Description: "Anime",
|
||||
})
|
||||
|
||||
last := 0
|
||||
for _, v := range cats {
|
||||
if len(v.ID) <= 2 {
|
||||
categories = append(categories, &nyaafeeds.RssCategoryTorznab{
|
||||
ID: nyaafeeds.ConvertFromCat(v.ID),
|
||||
Name: string(T(v.Name)),
|
||||
})
|
||||
last++
|
||||
} else {
|
||||
categories[last].Subcat = append(categories[last].Subcat, &nyaafeeds.RssSubCat{
|
||||
ID: nyaafeeds.ConvertFromCat(v.ID),
|
||||
Name: string(T(v.Name)),
|
||||
})
|
||||
}
|
||||
}
|
||||
feed := &nyaafeeds.RssCaps{
|
||||
Server: &nyaafeeds.RssServer{
|
||||
Version: "1.0",
|
||||
Title: title,
|
||||
Strapline: "...",
|
||||
Email: config.Get().Email.From,
|
||||
URL: config.WebAddress(),
|
||||
Image: config.WebAddress() + "/img/logo.png",
|
||||
},
|
||||
Limits: &nyaafeeds.RssLimits{
|
||||
Max: "300",
|
||||
Default: "50",
|
||||
},
|
||||
Registration: &nyaafeeds.RssRegistration{
|
||||
Available: "yes",
|
||||
Open: "yes",
|
||||
},
|
||||
Searching: &nyaafeeds.RssSearching{
|
||||
Search: &nyaafeeds.RssSearch{
|
||||
Available: "yes",
|
||||
SupportedParams: "q",
|
||||
},
|
||||
TvSearch: &nyaafeeds.RssSearch{
|
||||
Available: "no",
|
||||
},
|
||||
MovieSearch: &nyaafeeds.RssSearch{
|
||||
Available: "no",
|
||||
},
|
||||
},
|
||||
Categories: &nyaafeeds.RssCategories{
|
||||
Category: categories,
|
||||
},
|
||||
}
|
||||
var rssErr error
|
||||
rss, rssErr = feeds.ToXML(feed)
|
||||
if rssErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, rssErr)
|
||||
}
|
||||
} else {
|
||||
// We only get the basic variable for rss based on search param
|
||||
torrents, createdAsTime, title, err := getTorrentList(c)
|
||||
|
||||
if err != nil {
|
||||
c.AbortWithError(http.StatusBadRequest, err)
|
||||
return
|
||||
}
|
||||
|
||||
feed := &nyaafeeds.RssFeed{
|
||||
Title: title,
|
||||
Xmlns: "http://torznab.com/schemas/2015/feed",
|
||||
Link: config.WebAddress() + "/",
|
||||
PubDate: createdAsTime.String(),
|
||||
}
|
||||
feed.Items = make([]*nyaafeeds.RssItem, len(torrents))
|
||||
|
||||
for i, torrent := range torrents {
|
||||
|
||||
torrentJSON := torrent.ToJSON()
|
||||
filesNumber := ""
|
||||
if len(torrentJSON.FileList) > 0 {
|
||||
filesNumber = strconv.Itoa(len(torrentJSON.FileList))
|
||||
}
|
||||
seeders := ""
|
||||
if torrentJSON.Seeders > 0 {
|
||||
seeders = strconv.Itoa(int(torrentJSON.Seeders))
|
||||
}
|
||||
leechers := ""
|
||||
if torrentJSON.Leechers > 0 {
|
||||
leechers = strconv.Itoa(int(torrentJSON.Leechers))
|
||||
}
|
||||
feed.Items[i] = &nyaafeeds.RssItem{
|
||||
Title: torrentJSON.Name,
|
||||
Link: config.WebAddress() + "/download/" + torrentJSON.Hash,
|
||||
Category: &nyaafeeds.RssCategory{
|
||||
Domain: config.WebAddress() + "/search?c=" + torrentJSON.Category + "_" + torrentJSON.SubCategory,
|
||||
},
|
||||
Description: string(torrentJSON.Description),
|
||||
Comments: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
PubDate: torrent.Date.Format(time.RFC822),
|
||||
GUID: config.WebAddress() + "/view/" + strconv.FormatUint(uint64(torrentJSON.ID), 10),
|
||||
Enclosure: &nyaafeeds.RssEnclosure{
|
||||
URL: config.WebAddress() + "/download/" + strings.TrimSpace(torrentJSON.Hash),
|
||||
Length: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
Type: "application/x-bittorrent",
|
||||
},
|
||||
}
|
||||
torznab := []*nyaafeeds.RssTorznab{}
|
||||
if torrentJSON.Filesize > 0 {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "size",
|
||||
Value: strconv.FormatUint(uint64(torrentJSON.Filesize), 10),
|
||||
})
|
||||
}
|
||||
if filesNumber != "" {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "files",
|
||||
Value: filesNumber,
|
||||
})
|
||||
}
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "grabs",
|
||||
Value: strconv.Itoa(int(torrentJSON.Completed)),
|
||||
})
|
||||
if seeders != "" {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "seeders",
|
||||
Value: seeders,
|
||||
})
|
||||
}
|
||||
if leechers != "" {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "leechers",
|
||||
Value: leechers,
|
||||
})
|
||||
}
|
||||
if torrentJSON.Hash != "" {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "infohash",
|
||||
Value: torrentJSON.Hash,
|
||||
})
|
||||
}
|
||||
if torrentJSON.Magnet != "" {
|
||||
torznab = append(torznab, &nyaafeeds.RssTorznab{
|
||||
Name: "magneturl",
|
||||
Value: string(torrentJSON.Magnet),
|
||||
})
|
||||
}
|
||||
if len(torznab) > 0 {
|
||||
feed.Items[i].Torznab = torznab
|
||||
}
|
||||
}
|
||||
var rssErr error
|
||||
rss, rssErr = feeds.ToXML(feed)
|
||||
if rssErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, rssErr)
|
||||
}
|
||||
}
|
||||
// allow cross domain AJAX requests
|
||||
c.Header("Access-Control-Allow-Origin", "*")
|
||||
|
||||
_, writeErr := c.Writer.Write([]byte(rss))
|
||||
if writeErr != nil {
|
||||
c.AbortWithError(http.StatusInternalServerError, writeErr)
|
||||
}
|
||||
}
|
||||
|
||||
func getTorrentList(c *gin.Context) (torrents []models.Torrent, createdAsTime time.Time, title string, err error) {
|
||||
page := c.Param("page")
|
||||
userID := c.Param("id")
|
||||
cat := c.Query("cat")
|
||||
offset := 0
|
||||
if c.Query("offset") != "" {
|
||||
offset, err = strconv.Atoi(html.EscapeString(c.Query("offset")))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
createdAsTime = time.Now()
|
||||
|
||||
if len(torrents) > 0 {
|
||||
createdAsTime = torrents[0].Date
|
||||
}
|
||||
|
||||
title = "Nyaa Pantsu"
|
||||
if config.IsSukebei() {
|
||||
title = "Sukebei Pantsu"
|
||||
}
|
||||
|
||||
pagenum := 1
|
||||
if page == "" && offset > 0 { // first page for offset is 0
|
||||
pagenum = offset + 1
|
||||
} else if page != "" {
|
||||
pagenum, err = strconv.Atoi(html.EscapeString(page))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
if pagenum <= 0 {
|
||||
err = errors.New("Page number is invalid")
|
||||
return
|
||||
}
|
||||
|
||||
if userID != "" {
|
||||
userIDnum := 0
|
||||
userIDnum, err = strconv.Atoi(html.EscapeString(userID))
|
||||
// Should we have a feed for anonymous uploads?
|
||||
if err != nil || userIDnum == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
_, _, err = users.FindForAdmin(uint(userIDnum))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
// Set the user ID on the request, so that SearchByQuery finds it.
|
||||
query := c.Request.URL.Query()
|
||||
query.Set("userID", userID)
|
||||
c.Request.URL.RawQuery = query.Encode()
|
||||
}
|
||||
|
||||
if cat != "" {
|
||||
query := c.Request.URL.Query()
|
||||
catConv := nyaafeeds.ConvertToCat(cat)
|
||||
if catConv == "" {
|
||||
return
|
||||
}
|
||||
query.Set("c", catConv)
|
||||
c.Request.URL.RawQuery = query.Encode()
|
||||
}
|
||||
|
||||
_, torrents, err = search.ByQueryNoCount(c, pagenum)
|
||||
|
||||
return
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
package searchController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
router.Get().Any("/", SearchHandler)
|
||||
router.Get().Any("/p/:page", SearchHandler)
|
||||
router.Get().Any("/search", SearchHandler)
|
||||
router.Get().Any("/search/:page", SearchHandler)
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package controllers
|
||||
package searchController
|
||||
|
||||
import (
|
||||
"html"
|
|
@ -0,0 +1,8 @@
|
|||
package settingsController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
router.Get().GET("/settings", SeePublicSettingsHandler)
|
||||
router.Get().POST("/settings", ChangePublicSettingsHandler)
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
package controllers
|
||||
package settingsController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/publicSettings"
|
||||
|
@ -52,7 +53,7 @@ func ChangePublicSettingsHandler(c *gin.Context) {
|
|||
}
|
||||
|
||||
// If logged in, update user settings.
|
||||
user := getUser(c)
|
||||
user := router.GetUser(c)
|
||||
if user.ID > 0 {
|
||||
user.Language = lang
|
||||
user.Theme = theme
|
|
@ -0,0 +1,20 @@
|
|||
package staticController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/databasedumps"
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
)
|
||||
|
||||
func init() {
|
||||
// Static file handlers
|
||||
// TODO Use config from cli
|
||||
// TODO Make sure the directory exists
|
||||
router.Get().StaticFS("/css/", http.Dir("./public/css/"))
|
||||
router.Get().StaticFS("/js/", http.Dir("./public/js/"))
|
||||
router.Get().StaticFS("/img/", http.Dir("./public/img/"))
|
||||
router.Get().StaticFS("/apidoc/", http.Dir("./apidoc/"))
|
||||
router.Get().StaticFS("/dbdumps/", http.Dir(databasedumpsController.DatabaseDumpPath))
|
||||
router.Get().StaticFS("/gpg/", http.Dir(databasedumpsController.GPGPublicKeyPath))
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package torrentController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models/comments"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/utils/captcha"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/sanitize"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// PostCommentHandler : Controller for posting a comment
|
||||
func PostCommentHandler(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 32)
|
||||
|
||||
torrent, err := torrents.FindByID(uint(id))
|
||||
if err != nil {
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
currentUser := router.GetUser(c)
|
||||
messages := msg.GetMessages(c)
|
||||
|
||||
if currentUser.NeedsCaptcha() {
|
||||
userCaptcha := captcha.Extract(c)
|
||||
if !captcha.Authenticate(userCaptcha) {
|
||||
messages.AddErrorT("errors", "bad_captcha")
|
||||
}
|
||||
}
|
||||
content := sanitize.Sanitize(c.PostForm("comment"), "comment")
|
||||
|
||||
if strings.TrimSpace(content) == "" {
|
||||
messages.AddErrorT("errors", "comment_empty")
|
||||
}
|
||||
if len(content) > config.Get().CommentLength {
|
||||
messages.AddErrorT("errors", "comment_toolong")
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
|
||||
_, err := comments.Create(content, torrent, currentUser)
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
}
|
||||
url := "/view/" + strconv.FormatUint(uint64(torrent.ID), 10)
|
||||
c.Redirect(302, url)
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package torrentController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/activities"
|
||||
"github.com/NyaaPantsu/nyaa/models/reports"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/utils/search/structs"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// TorrentDeleteUserPanel : Controller for deleting a user torrent by a user
|
||||
func TorrentDeleteUserPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
currentUser := router.GetUser(c)
|
||||
torrent, _ := torrents.FindByID(uint(id))
|
||||
if currentUser.CurrentOrAdmin(torrent.UploaderID) {
|
||||
_, _, err := torrent.Delete(false)
|
||||
if err == nil {
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
if currentUser.HasAdmin() { // We hide username on log activity if user is not admin and torrent is hidden
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, currentUser.Username)
|
||||
} else {
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, username)
|
||||
}
|
||||
//delete reports of torrent
|
||||
whereParams := structs.CreateWhereParams("torrent_id = ?", id)
|
||||
torrentReports, _, _ := reports.FindOrderBy(&whereParams, "", 0, 0)
|
||||
for _, report := range torrentReports {
|
||||
report.Delete(false)
|
||||
}
|
||||
}
|
||||
c.Redirect(http.StatusSeeOther, "/?deleted")
|
||||
} else {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
package torrentController
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"os"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// DownloadTorrent : Controller for downloading a torrent
|
||||
func DownloadTorrent(c *gin.Context) {
|
||||
hash := c.Param("hash")
|
||||
|
||||
if hash == "" && len(config.Get().Torrents.FileStorage) == 0 {
|
||||
//File not found, send 404
|
||||
c.AbortWithError(http.StatusNotFound, errors.New("File not found"))
|
||||
return
|
||||
}
|
||||
|
||||
//Check if file exists and open
|
||||
Openfile, err := os.Open(fmt.Sprintf("%s%c%s.torrent", config.Get().Torrents.FileStorage, os.PathSeparator, hash))
|
||||
if err != nil {
|
||||
//File not found, send 404
|
||||
c.AbortWithError(http.StatusNotFound, errors.New("File not found"))
|
||||
return
|
||||
}
|
||||
defer Openfile.Close() //Close after function return
|
||||
|
||||
//Get the file size
|
||||
FileStat, _ := Openfile.Stat() //Get info from file
|
||||
FileSize := strconv.FormatInt(FileStat.Size(), 10) //Get file size as a string
|
||||
|
||||
torrent, err := torrents.FindRawByHash(hash)
|
||||
|
||||
if err != nil {
|
||||
//File not found, send 404
|
||||
c.AbortWithError(http.StatusNotFound, errors.New("File not found"))
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.torrent\"", torrent.Name))
|
||||
c.Header("Content-Type", "application/x-bittorrent")
|
||||
c.Header("Content-Length", FileSize)
|
||||
//Send the file
|
||||
// We reset the offset to 0
|
||||
Openfile.Seek(0, 0)
|
||||
io.Copy(c.Writer, Openfile) //'Copy' the file to the client
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package torrentController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/upload"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator/torrent"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// TorrentEditUserPanel : Controller for editing a user torrent by a user, after GET request
|
||||
func TorrentEditUserPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
torrent, _ := torrents.FindByID(uint(id))
|
||||
currentUser := router.GetUser(c)
|
||||
if currentUser.CurrentOrAdmin(torrent.UploaderID) {
|
||||
uploadForm := torrentValidator.TorrentRequest{}
|
||||
uploadForm.Name = torrent.Name
|
||||
uploadForm.Category = strconv.Itoa(torrent.Category) + "_" + strconv.Itoa(torrent.SubCategory)
|
||||
uploadForm.Remake = torrent.Status == models.TorrentStatusRemake
|
||||
uploadForm.WebsiteLink = string(torrent.WebsiteLink)
|
||||
uploadForm.Description = string(torrent.Description)
|
||||
uploadForm.Hidden = torrent.Hidden
|
||||
uploadForm.Languages = torrent.Languages
|
||||
templates.Form(c, "site/torrents/edit.jet.html", uploadForm)
|
||||
} else {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
// TorrentPostEditUserPanel : Controller for editing a user torrent by a user, after post request
|
||||
func TorrentPostEditUserPanel(c *gin.Context) {
|
||||
var uploadForm torrentValidator.UpdateRequest
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
uploadForm.ID = uint(id)
|
||||
messages := msg.GetMessages(c)
|
||||
torrent, _ := torrents.FindByID(uint(id))
|
||||
currentUser := router.GetUser(c)
|
||||
if torrent.ID > 0 && currentUser.CurrentOrAdmin(torrent.UploaderID) {
|
||||
errUp := upload.ExtractEditInfo(c, &uploadForm.Update)
|
||||
if errUp != nil {
|
||||
messages.AddErrorT("errors", "fail_torrent_update")
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
upload.UpdateTorrent(&uploadForm, torrent, currentUser).Update(currentUser.HasAdmin())
|
||||
messages.AddInfoT("infos", "torrent_updated")
|
||||
}
|
||||
templates.Form(c, "site/torrents/edit.jet.html", uploadForm.Update)
|
||||
} else {
|
||||
c.AbortWithStatus(http.StatusNotFound)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package torrentController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
router.Get().Any("/download/:hash", DownloadTorrent)
|
||||
|
||||
torrentRoutes := router.Get().Group("/torrent")
|
||||
{
|
||||
torrentRoutes.GET("/", TorrentEditUserPanel)
|
||||
torrentRoutes.POST("/", TorrentPostEditUserPanel)
|
||||
torrentRoutes.GET("/delete", TorrentDeleteUserPanel)
|
||||
}
|
||||
torrentViewRoutes := router.Get().Group("/view")
|
||||
{
|
||||
torrentViewRoutes.GET("/:id", ViewHandler)
|
||||
torrentViewRoutes.HEAD("/:id", ViewHeadHandler)
|
||||
torrentViewRoutes.POST("/:id", PostCommentHandler)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
package torrentController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models/notifications"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/captcha"
|
||||
"github.com/NyaaPantsu/nyaa/utils/filelist"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ViewHandler : Controller for displaying a torrent
|
||||
func ViewHandler(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 32)
|
||||
messages := msg.GetMessages(c)
|
||||
user := router.GetUser(c)
|
||||
|
||||
if c.Request.URL.Query()["success"] != nil {
|
||||
messages.AddInfoT("infos", "torrent_uploaded")
|
||||
}
|
||||
if c.Request.URL.Query()["badcaptcha"] != nil {
|
||||
messages.AddErrorT("errors", "bad_captcha")
|
||||
}
|
||||
if c.Request.URL.Query()["reported"] != nil {
|
||||
messages.AddInfoTf("infos", "report_msg", id)
|
||||
}
|
||||
|
||||
torrent, err := torrents.FindByID(uint(id))
|
||||
|
||||
if c.Request.URL.Query()["notif"] != nil {
|
||||
notifications.ToggleReadNotification(torrent.Identifier(), user.ID)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
b := torrent.ToJSON()
|
||||
folder := filelist.FileListToFolder(torrent.FileList, "root")
|
||||
captchaID := ""
|
||||
if user.NeedsCaptcha() {
|
||||
captchaID = captcha.GetID()
|
||||
}
|
||||
templates.Torrent(c, b, folder, captchaID)
|
||||
}
|
||||
|
||||
// ViewHeadHandler : Controller for checking a torrent
|
||||
func ViewHeadHandler(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = torrents.FindRawByID(uint(id))
|
||||
|
||||
if err != nil {
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
c.AbortWithStatus(http.StatusOK)
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package uploadController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
|
||||
func init() {
|
||||
router.Get().Any("/upload", UploadHandler)
|
||||
}
|
|
@ -1,10 +1,11 @@
|
|||
package controllers
|
||||
package uploadController
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/captcha"
|
||||
|
@ -17,7 +18,7 @@ import (
|
|||
|
||||
// UploadHandler : Main Controller for uploading a torrent
|
||||
func UploadHandler(c *gin.Context) {
|
||||
user := getUser(c)
|
||||
user := router.GetUser(c)
|
||||
if !user.CanUpload() {
|
||||
T := publicSettings.GetTfuncFromRequest(c)
|
||||
c.AbortWithError(http.StatusBadRequest, errors.New(string(T("uploads_disabled"))))
|
||||
|
@ -34,7 +35,7 @@ func UploadHandler(c *gin.Context) {
|
|||
// UploadPostHandler : Controller for uploading a torrent, after POST request, redirect or makes error in messages
|
||||
func UploadPostHandler(c *gin.Context) {
|
||||
var uploadForm torrentValidator.TorrentRequest
|
||||
user := getUser(c)
|
||||
user := router.GetUser(c)
|
||||
messages := msg.GetMessages(c) // new utils for errors and infos
|
||||
|
||||
if user.NeedsCaptcha() {
|
||||
|
@ -68,7 +69,7 @@ func UploadPostHandler(c *gin.Context) {
|
|||
func UploadGetHandler(c *gin.Context) {
|
||||
var uploadForm torrentValidator.TorrentRequest
|
||||
_ = upload.ExtractInfo(c, &uploadForm)
|
||||
user := getUser(c)
|
||||
user := router.GetUser(c)
|
||||
if user.NeedsCaptcha() {
|
||||
uploadForm.CaptchaID = captcha.GetID()
|
||||
} else {
|
|
@ -0,0 +1,29 @@
|
|||
package userController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UserFollowHandler : Controller to follow/unfollow users, need user id to follow
|
||||
func UserFollowHandler(c *gin.Context) {
|
||||
var followAction string
|
||||
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
currentUser := router.GetUser(c)
|
||||
user, _, errorUser := users.FindForAdmin(uint(id))
|
||||
if errorUser == nil && user.ID > 0 {
|
||||
if !currentUser.IsFollower(user) {
|
||||
followAction = "followed"
|
||||
currentUser.SetFollow(user)
|
||||
} else {
|
||||
followAction = "unfollowed"
|
||||
currentUser.RemoveFollow(user)
|
||||
}
|
||||
}
|
||||
url := "/user/" + strconv.Itoa(int(user.ID)) + "/" + user.Username + "?" + followAction
|
||||
c.Redirect(http.StatusSeeOther, url)
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
package userController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/cookies"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator/user"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UserLoginFormHandler : Getting View User Login
|
||||
func UserLoginFormHandler(c *gin.Context) {
|
||||
_, _, errorUser := cookies.CurrentUser(c)
|
||||
// User is already connected, redirect to home
|
||||
if errorUser == nil {
|
||||
c.Redirect(http.StatusSeeOther, "/")
|
||||
return
|
||||
}
|
||||
|
||||
loginForm := userValidator.LoginForm{
|
||||
RedirectTo: c.DefaultQuery("redirectTo", ""),
|
||||
}
|
||||
templates.Form(c, "site/user/login.jet.html", loginForm)
|
||||
}
|
||||
|
||||
// UserLoginPostHandler : Post Login controller
|
||||
func UserLoginPostHandler(c *gin.Context) {
|
||||
b := userValidator.LoginForm{}
|
||||
c.Bind(&b)
|
||||
messages := msg.GetMessages(c)
|
||||
|
||||
validator.ValidateForm(&b, messages)
|
||||
if !messages.HasErrors() {
|
||||
_, _, errorUser := cookies.CreateUserAuthentication(c, &b)
|
||||
if errorUser == nil {
|
||||
url := c.DefaultPostForm("redirectTo", "/")
|
||||
c.Redirect(http.StatusSeeOther, url)
|
||||
return
|
||||
}
|
||||
messages.ErrorT(errorUser)
|
||||
}
|
||||
UserLoginFormHandler(c)
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package userController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/utils/cookies"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UserLogoutHandler : Controller to logout users
|
||||
func UserLogoutHandler(c *gin.Context) {
|
||||
logout := c.PostForm("logout")
|
||||
if logout != "" {
|
||||
cookies.Clear(c)
|
||||
url := c.DefaultPostForm("redirectTo", "/")
|
||||
c.Redirect(http.StatusSeeOther, url)
|
||||
} else {
|
||||
c.Status(http.StatusNotFound)
|
||||
}
|
||||
}
|
|
@ -1,15 +1,16 @@
|
|||
package controllers
|
||||
package userController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"net/http"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/notifications"
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/captcha"
|
||||
"github.com/NyaaPantsu/nyaa/utils/cookies"
|
||||
"github.com/NyaaPantsu/nyaa/utils/crypto"
|
||||
"github.com/NyaaPantsu/nyaa/utils/email"
|
||||
|
@ -21,35 +22,6 @@ import (
|
|||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UserRegisterFormHandler : Getting View User Registration
|
||||
func UserRegisterFormHandler(c *gin.Context) {
|
||||
_, _, errorUser := cookies.CurrentUser(c)
|
||||
// User is already connected, redirect to home
|
||||
if errorUser == nil {
|
||||
SearchHandler(c)
|
||||
return
|
||||
}
|
||||
registrationForm := userValidator.RegistrationForm{}
|
||||
c.Bind(®istrationForm)
|
||||
registrationForm.CaptchaID = captcha.GetID()
|
||||
templates.Form(c, "site/user/register.jet.html", registrationForm)
|
||||
}
|
||||
|
||||
// UserLoginFormHandler : Getting View User Login
|
||||
func UserLoginFormHandler(c *gin.Context) {
|
||||
_, _, errorUser := cookies.CurrentUser(c)
|
||||
// User is already connected, redirect to home
|
||||
if errorUser == nil {
|
||||
SearchHandler(c)
|
||||
return
|
||||
}
|
||||
|
||||
loginForm := userValidator.LoginForm{
|
||||
RedirectTo: c.DefaultQuery("redirectTo", ""),
|
||||
}
|
||||
templates.Form(c, "site/user/login.jet.html", loginForm)
|
||||
}
|
||||
|
||||
// UserProfileHandler : Getting User Profile
|
||||
func UserProfileHandler(c *gin.Context) {
|
||||
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
|
@ -58,7 +30,7 @@ func UserProfileHandler(c *gin.Context) {
|
|||
|
||||
userProfile, _, errorUser := users.FindForAdmin(uint(id))
|
||||
if errorUser == nil {
|
||||
currentUser := getUser(c)
|
||||
currentUser := router.GetUser(c)
|
||||
follow := c.Request.URL.Query()["followed"]
|
||||
unfollow := c.Request.URL.Query()["unfollowed"]
|
||||
deleteVar := c.Request.URL.Query()["delete"]
|
||||
|
@ -95,14 +67,14 @@ func UserProfileHandler(c *gin.Context) {
|
|||
templates.UserProfile(c, userProfile)
|
||||
}
|
||||
} else {
|
||||
NotFoundHandler(c)
|
||||
c.Status(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
// UserDetailsHandler : Getting User Profile Details View
|
||||
func UserDetailsHandler(c *gin.Context) {
|
||||
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
currentUser := getUser(c)
|
||||
currentUser := router.GetUser(c)
|
||||
|
||||
userProfile, _, errorUser := users.FindForAdmin(uint(id))
|
||||
if errorUser == nil && currentUser.CurrentOrAdmin(userProfile.ID) {
|
||||
|
@ -112,17 +84,17 @@ func UserDetailsHandler(c *gin.Context) {
|
|||
userProfile.ParseSettings()
|
||||
templates.UserProfileEdit(c, userProfile, b, availableLanguages)
|
||||
} else {
|
||||
NotFoundHandler(c)
|
||||
c.Status(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
// UserProfileFormHandler : Getting View User Profile Update
|
||||
func UserProfileFormHandler(c *gin.Context) {
|
||||
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
currentUser := getUser(c)
|
||||
currentUser := router.GetUser(c)
|
||||
userProfile, _, errorUser := users.FindForAdmin(uint(id))
|
||||
if errorUser != nil || !currentUser.CurrentOrAdmin(userProfile.ID) || userProfile.ID == 0 {
|
||||
NotFoundHandler(c)
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
userProfile.ParseSettings()
|
||||
|
@ -176,114 +148,9 @@ func UserProfileFormHandler(c *gin.Context) {
|
|||
templates.UserProfileEdit(c, userProfile, userForm, availableLanguages)
|
||||
}
|
||||
|
||||
// UserRegisterPostHandler : Post Registration controller, we do some check on the form here, the rest on user service
|
||||
func UserRegisterPostHandler(c *gin.Context) {
|
||||
b := userValidator.RegistrationForm{}
|
||||
messages := msg.GetMessages(c)
|
||||
|
||||
if !captcha.Authenticate(captcha.Extract(c)) {
|
||||
messages.AddErrorT("errors", "bad_captcha")
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
if len(c.PostForm("email")) > 0 {
|
||||
if !userValidator.EmailValidation(c.PostForm("email")) {
|
||||
messages.AddErrorT("email", "email_not_valid")
|
||||
}
|
||||
}
|
||||
if !userValidator.ValidateUsername(c.PostForm("username")) {
|
||||
messages.AddErrorT("username", "username_illegal")
|
||||
}
|
||||
|
||||
if !messages.HasErrors() {
|
||||
c.Bind(&b)
|
||||
validator.ValidateForm(&b, messages)
|
||||
if !messages.HasErrors() {
|
||||
user, _ := users.CreateUser(c)
|
||||
if !messages.HasErrors() {
|
||||
_, err := cookies.SetLogin(c, user)
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
if b.Email != "" {
|
||||
email.SendVerificationToUser(user, b.Email)
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
templates.Static(c, "site/static/signup_success.jet.html")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if messages.HasErrors() {
|
||||
UserRegisterFormHandler(c)
|
||||
}
|
||||
}
|
||||
|
||||
// UserVerifyEmailHandler : Controller when verifying email, needs a token
|
||||
func UserVerifyEmailHandler(c *gin.Context) {
|
||||
token := c.Param("token")
|
||||
messages := msg.GetMessages(c)
|
||||
|
||||
_, errEmail := email.EmailVerification(token, c)
|
||||
if errEmail != nil {
|
||||
messages.ImportFromError("errors", errEmail)
|
||||
}
|
||||
templates.Static(c, "site/static/verify_success.jet.html")
|
||||
}
|
||||
|
||||
// UserLoginPostHandler : Post Login controller
|
||||
func UserLoginPostHandler(c *gin.Context) {
|
||||
b := userValidator.LoginForm{}
|
||||
c.Bind(&b)
|
||||
messages := msg.GetMessages(c)
|
||||
|
||||
validator.ValidateForm(&b, messages)
|
||||
if !messages.HasErrors() {
|
||||
_, _, errorUser := cookies.CreateUserAuthentication(c, &b)
|
||||
if errorUser == nil {
|
||||
url := c.DefaultPostForm("redirectTo", "/")
|
||||
c.Redirect(http.StatusSeeOther, url)
|
||||
return
|
||||
}
|
||||
messages.ErrorT(errorUser)
|
||||
}
|
||||
UserLoginFormHandler(c)
|
||||
}
|
||||
|
||||
// UserLogoutHandler : Controller to logout users
|
||||
func UserLogoutHandler(c *gin.Context) {
|
||||
logout := c.PostForm("logout")
|
||||
if logout != "" {
|
||||
cookies.Clear(c)
|
||||
url := c.DefaultPostForm("redirectTo", "/")
|
||||
c.Redirect(http.StatusSeeOther, url)
|
||||
} else {
|
||||
NotFoundHandler(c)
|
||||
}
|
||||
}
|
||||
|
||||
// UserFollowHandler : Controller to follow/unfollow users, need user id to follow
|
||||
func UserFollowHandler(c *gin.Context) {
|
||||
var followAction string
|
||||
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
currentUser := getUser(c)
|
||||
user, _, errorUser := users.FindForAdmin(uint(id))
|
||||
if errorUser == nil && user.ID > 0 {
|
||||
if !currentUser.IsFollower(user) {
|
||||
followAction = "followed"
|
||||
currentUser.SetFollow(user)
|
||||
} else {
|
||||
followAction = "unfollowed"
|
||||
currentUser.RemoveFollow(user)
|
||||
}
|
||||
}
|
||||
url := "/user/" + strconv.Itoa(int(user.ID)) + "/" + user.Username + "?" + followAction
|
||||
c.Redirect(http.StatusSeeOther, url)
|
||||
}
|
||||
|
||||
// UserNotificationsHandler : Controller to show user notifications
|
||||
func UserNotificationsHandler(c *gin.Context) {
|
||||
currentUser := getUser(c)
|
||||
currentUser := router.GetUser(c)
|
||||
if currentUser.ID > 0 {
|
||||
messages := msg.GetMessages(c)
|
||||
if c.Request.URL.Query()["clear"] != nil {
|
||||
|
@ -293,19 +160,19 @@ func UserNotificationsHandler(c *gin.Context) {
|
|||
}
|
||||
templates.UserProfileNotifications(c, currentUser)
|
||||
} else {
|
||||
NotFoundHandler(c)
|
||||
c.Status(http.StatusNotFound)
|
||||
}
|
||||
}
|
||||
|
||||
// UserAPIKeyResetHandler : Controller to reset user api key
|
||||
func UserAPIKeyResetHandler(c *gin.Context) {
|
||||
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
|
||||
currentUser := getUser(c)
|
||||
currentUser := router.GetUser(c)
|
||||
|
||||
messages := msg.GetMessages(c)
|
||||
userProfile, _, errorUser := users.FindForAdmin(uint(id))
|
||||
if errorUser != nil || !currentUser.CurrentOrAdmin(userProfile.ID) || userProfile.ID == 0 {
|
||||
NotFoundHandler(c)
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
userProfile.APIToken, _ = crypto.GenerateRandomToken32()
|
|
@ -0,0 +1,72 @@
|
|||
package userController
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/models/users"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/captcha"
|
||||
"github.com/NyaaPantsu/nyaa/utils/cookies"
|
||||
"github.com/NyaaPantsu/nyaa/utils/email"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator/user"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UserRegisterFormHandler : Getting View User Registration
|
||||
func UserRegisterFormHandler(c *gin.Context) {
|
||||
_, _, errorUser := cookies.CurrentUser(c)
|
||||
// User is already connected, redirect to home
|
||||
if errorUser == nil {
|
||||
c.Redirect(http.StatusSeeOther, "/")
|
||||
return
|
||||
}
|
||||
registrationForm := userValidator.RegistrationForm{}
|
||||
c.Bind(®istrationForm)
|
||||
registrationForm.CaptchaID = captcha.GetID()
|
||||
templates.Form(c, "site/user/register.jet.html", registrationForm)
|
||||
}
|
||||
|
||||
// UserRegisterPostHandler : Post Registration controller, we do some check on the form here, the rest on user service
|
||||
func UserRegisterPostHandler(c *gin.Context) {
|
||||
b := userValidator.RegistrationForm{}
|
||||
messages := msg.GetMessages(c)
|
||||
|
||||
if !captcha.Authenticate(captcha.Extract(c)) {
|
||||
messages.AddErrorT("errors", "bad_captcha")
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
if len(c.PostForm("email")) > 0 {
|
||||
if !userValidator.EmailValidation(c.PostForm("email")) {
|
||||
messages.AddErrorT("email", "email_not_valid")
|
||||
}
|
||||
}
|
||||
if !userValidator.ValidateUsername(c.PostForm("username")) {
|
||||
messages.AddErrorT("username", "username_illegal")
|
||||
}
|
||||
|
||||
if !messages.HasErrors() {
|
||||
c.Bind(&b)
|
||||
validator.ValidateForm(&b, messages)
|
||||
if !messages.HasErrors() {
|
||||
user, _ := users.CreateUser(c)
|
||||
if !messages.HasErrors() {
|
||||
_, err := cookies.SetLogin(c, user)
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
if b.Email != "" {
|
||||
email.SendVerificationToUser(user, b.Email)
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
templates.Static(c, "site/static/signup_success.jet.html")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if messages.HasErrors() {
|
||||
UserRegisterFormHandler(c)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package userController
|
||||
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
import "github.com/NyaaPantsu/nyaa/controllers/feed"
|
||||
|
||||
func init() {
|
||||
|
||||
// Login
|
||||
router.Get().POST("/login", UserLoginPostHandler)
|
||||
router.Get().GET("/login", UserLoginFormHandler)
|
||||
|
||||
// Register
|
||||
router.Get().GET("/register", UserRegisterFormHandler)
|
||||
router.Get().POST("/register", UserRegisterPostHandler)
|
||||
|
||||
// Logout
|
||||
router.Get().POST("/logout", UserLogoutHandler)
|
||||
|
||||
// Notifications
|
||||
router.Get().GET("/notifications", UserNotificationsHandler)
|
||||
|
||||
// Verify Email
|
||||
router.Get().Any("/verify/email/:token", UserVerifyEmailHandler)
|
||||
|
||||
// User Profile specific routes
|
||||
userRoutes := router.Get().Group("/user")
|
||||
{
|
||||
userRoutes.GET("/:id/:username", UserProfileHandler)
|
||||
userRoutes.GET("/:id/:username/follow", UserFollowHandler)
|
||||
userRoutes.GET("/:id/:username/edit", UserDetailsHandler)
|
||||
userRoutes.POST("/:id/:username/edit", UserProfileFormHandler)
|
||||
userRoutes.GET("/:id/:username/apireset", UserAPIKeyResetHandler)
|
||||
userRoutes.GET("/:id/:username/feed/*page", feedController.RSSHandler)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package userController
|
||||
|
||||
import (
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/email"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// UserVerifyEmailHandler : Controller when verifying email, needs a token
|
||||
func UserVerifyEmailHandler(c *gin.Context) {
|
||||
token := c.Param("token")
|
||||
messages := msg.GetMessages(c)
|
||||
|
||||
_, errEmail := email.EmailVerification(token, c)
|
||||
if errEmail != nil {
|
||||
messages.ImportFromError("errors", errEmail)
|
||||
}
|
||||
templates.Static(c, "site/static/verify_success.jet.html")
|
||||
}
|
|
@ -1,288 +0,0 @@
|
|||
package controllers
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net/http"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"os"
|
||||
|
||||
"github.com/NyaaPantsu/nyaa/config"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/activities"
|
||||
"github.com/NyaaPantsu/nyaa/models/comments"
|
||||
"github.com/NyaaPantsu/nyaa/models/notifications"
|
||||
"github.com/NyaaPantsu/nyaa/models/reports"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/templates"
|
||||
"github.com/NyaaPantsu/nyaa/utils/captcha"
|
||||
"github.com/NyaaPantsu/nyaa/utils/filelist"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/sanitize"
|
||||
"github.com/NyaaPantsu/nyaa/utils/search/structs"
|
||||
"github.com/NyaaPantsu/nyaa/utils/upload"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator/torrent"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
// ViewHandler : Controller for displaying a torrent
|
||||
func ViewHandler(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 32)
|
||||
messages := msg.GetMessages(c)
|
||||
user := getUser(c)
|
||||
|
||||
if c.Request.URL.Query()["success"] != nil {
|
||||
messages.AddInfoT("infos", "torrent_uploaded")
|
||||
}
|
||||
if c.Request.URL.Query()["badcaptcha"] != nil {
|
||||
messages.AddErrorT("errors", "bad_captcha")
|
||||
}
|
||||
if c.Request.URL.Query()["reported"] != nil {
|
||||
messages.AddInfoTf("infos", "report_msg", id)
|
||||
}
|
||||
|
||||
torrent, err := torrents.FindByID(uint(id))
|
||||
|
||||
if c.Request.URL.Query()["notif"] != nil {
|
||||
notifications.ToggleReadNotification(torrent.Identifier(), user.ID)
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
NotFoundHandler(c)
|
||||
return
|
||||
}
|
||||
b := torrent.ToJSON()
|
||||
folder := filelist.FileListToFolder(torrent.FileList, "root")
|
||||
captchaID := ""
|
||||
if user.NeedsCaptcha() {
|
||||
captchaID = captcha.GetID()
|
||||
}
|
||||
templates.Torrent(c, b, folder, captchaID)
|
||||
}
|
||||
|
||||
// ViewHeadHandler : Controller for checking a torrent
|
||||
func ViewHeadHandler(c *gin.Context) {
|
||||
id, err := strconv.ParseInt(c.Param("id"), 10, 32)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
_, err = torrents.FindRawByID(uint(id))
|
||||
|
||||
if err != nil {
|
||||
NotFoundHandler(c)
|
||||
return
|
||||
}
|
||||
|
||||
c.AbortWithStatus(http.StatusOK)
|
||||
}
|
||||
|
||||
// PostCommentHandler : Controller for posting a comment
|
||||
func PostCommentHandler(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 32)
|
||||
|
||||
torrent, err := torrents.FindByID(uint(id))
|
||||
if err != nil {
|
||||
NotFoundHandler(c)
|
||||
return
|
||||
}
|
||||
|
||||
currentUser := getUser(c)
|
||||
messages := msg.GetMessages(c)
|
||||
|
||||
if currentUser.NeedsCaptcha() {
|
||||
userCaptcha := captcha.Extract(c)
|
||||
if !captcha.Authenticate(userCaptcha) {
|
||||
messages.AddErrorT("errors", "bad_captcha")
|
||||
}
|
||||
}
|
||||
content := sanitize.Sanitize(c.PostForm("comment"), "comment")
|
||||
|
||||
if strings.TrimSpace(content) == "" {
|
||||
messages.AddErrorT("errors", "comment_empty")
|
||||
}
|
||||
if len(content) > config.Get().CommentLength {
|
||||
messages.AddErrorT("errors", "comment_toolong")
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
|
||||
_, err := comments.Create(content, torrent, currentUser)
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
}
|
||||
url := "/view/" + strconv.FormatUint(uint64(torrent.ID), 10)
|
||||
c.Redirect(302, url)
|
||||
}
|
||||
|
||||
// ReportTorrentHandler : Controller for sending a torrent report
|
||||
func ReportTorrentHandler(c *gin.Context) {
|
||||
fmt.Println("report")
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 32)
|
||||
messages := msg.GetMessages(c)
|
||||
captchaError := "?reported"
|
||||
currentUser := getUser(c)
|
||||
if currentUser.NeedsCaptcha() {
|
||||
userCaptcha := captcha.Extract(c)
|
||||
if !captcha.Authenticate(userCaptcha) {
|
||||
captchaError = "?badcaptcha"
|
||||
messages.AddErrorT("errors", "bad_captcha")
|
||||
}
|
||||
}
|
||||
torrent, err := torrents.FindByID(uint(id))
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
_, err := reports.Create(c.PostForm("report_type"), torrent, currentUser)
|
||||
messages.AddInfoTf("infos", "report_msg", id)
|
||||
if err != nil {
|
||||
messages.ImportFromError("errors", err)
|
||||
}
|
||||
c.Redirect(http.StatusSeeOther, "/view/"+strconv.Itoa(int(torrent.ID))+captchaError)
|
||||
} else {
|
||||
ReportViewTorrentHandler(c)
|
||||
}
|
||||
}
|
||||
|
||||
// ReportTorrentHandler: Controller for sending a torrent report
|
||||
func ReportViewTorrentHandler(c *gin.Context) {
|
||||
|
||||
type Report struct {
|
||||
ID uint
|
||||
CaptchaID string
|
||||
}
|
||||
|
||||
id, _ := strconv.ParseInt(c.Param("id"), 10, 32)
|
||||
messages := msg.GetMessages(c)
|
||||
currentUser := getUser(c)
|
||||
if currentUser.ID > 0 {
|
||||
torrent, err := torrents.FindByID(uint(id))
|
||||
if err != nil {
|
||||
messages.Error(err)
|
||||
}
|
||||
captchaID := ""
|
||||
if currentUser.NeedsCaptcha() {
|
||||
captchaID = captcha.GetID()
|
||||
}
|
||||
templates.Form(c, "site/torrents/report.jet.html", Report{torrent.ID, captchaID})
|
||||
} else {
|
||||
c.Status(404)
|
||||
}
|
||||
}
|
||||
|
||||
// TorrentEditUserPanel : Controller for editing a user torrent by a user, after GET request
|
||||
func TorrentEditUserPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
torrent, _ := torrents.FindByID(uint(id))
|
||||
currentUser := getUser(c)
|
||||
if currentUser.CurrentOrAdmin(torrent.UploaderID) {
|
||||
uploadForm := torrentValidator.TorrentRequest{}
|
||||
uploadForm.Name = torrent.Name
|
||||
uploadForm.Category = strconv.Itoa(torrent.Category) + "_" + strconv.Itoa(torrent.SubCategory)
|
||||
uploadForm.Remake = torrent.Status == models.TorrentStatusRemake
|
||||
uploadForm.WebsiteLink = string(torrent.WebsiteLink)
|
||||
uploadForm.Description = string(torrent.Description)
|
||||
uploadForm.Hidden = torrent.Hidden
|
||||
uploadForm.Languages = torrent.Languages
|
||||
templates.Form(c, "site/torrents/edit.jet.html", uploadForm)
|
||||
} else {
|
||||
NotFoundHandler(c)
|
||||
}
|
||||
}
|
||||
|
||||
// TorrentPostEditUserPanel : Controller for editing a user torrent by a user, after post request
|
||||
func TorrentPostEditUserPanel(c *gin.Context) {
|
||||
var uploadForm torrentValidator.UpdateRequest
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
uploadForm.ID = uint(id)
|
||||
messages := msg.GetMessages(c)
|
||||
torrent, _ := torrents.FindByID(uint(id))
|
||||
currentUser := getUser(c)
|
||||
if torrent.ID > 0 && currentUser.CurrentOrAdmin(torrent.UploaderID) {
|
||||
errUp := upload.ExtractEditInfo(c, &uploadForm.Update)
|
||||
if errUp != nil {
|
||||
messages.AddErrorT("errors", "fail_torrent_update")
|
||||
}
|
||||
if !messages.HasErrors() {
|
||||
upload.UpdateTorrent(&uploadForm, torrent, currentUser).Update(currentUser.HasAdmin())
|
||||
messages.AddInfoT("infos", "torrent_updated")
|
||||
}
|
||||
templates.Form(c, "site/torrents/edit.jet.html", uploadForm.Update)
|
||||
} else {
|
||||
NotFoundHandler(c)
|
||||
}
|
||||
}
|
||||
|
||||
// TorrentDeleteUserPanel : Controller for deleting a user torrent by a user
|
||||
func TorrentDeleteUserPanel(c *gin.Context) {
|
||||
id, _ := strconv.ParseInt(c.Query("id"), 10, 32)
|
||||
currentUser := getUser(c)
|
||||
torrent, _ := torrents.FindByID(uint(id))
|
||||
if currentUser.CurrentOrAdmin(torrent.UploaderID) {
|
||||
_, _, err := torrent.Delete(false)
|
||||
if err == nil {
|
||||
if torrent.Uploader == nil {
|
||||
torrent.Uploader = &models.User{}
|
||||
}
|
||||
_, username := torrents.HideUser(torrent.UploaderID, torrent.Uploader.Username, torrent.Hidden)
|
||||
if currentUser.HasAdmin() { // We hide username on log activity if user is not admin and torrent is hidden
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, currentUser.Username)
|
||||
} else {
|
||||
activities.Log(&models.User{}, torrent.Identifier(), "delete", "torrent_deleted_by", strconv.Itoa(int(torrent.ID)), username, username)
|
||||
}
|
||||
//delete reports of torrent
|
||||
whereParams := structs.CreateWhereParams("torrent_id = ?", id)
|
||||
torrentReports, _, _ := reports.FindOrderBy(&whereParams, "", 0, 0)
|
||||
for _, report := range torrentReports {
|
||||
report.Delete(false)
|
||||
}
|
||||
}
|
||||
c.Redirect(http.StatusSeeOther, "/?deleted")
|
||||
} else {
|
||||
NotFoundHandler(c)
|
||||
}
|
||||
}
|
||||
|
||||
// DownloadTorrent : Controller for downloading a torrent
|
||||
func DownloadTorrent(c *gin.Context) {
|
||||
hash := c.Param("hash")
|
||||
|
||||
if hash == "" && len(config.Get().Torrents.FileStorage) == 0 {
|
||||
//File not found, send 404
|
||||
c.AbortWithError(http.StatusNotFound, errors.New("File not found"))
|
||||
return
|
||||
}
|
||||
|
||||
//Check if file exists and open
|
||||
Openfile, err := os.Open(fmt.Sprintf("%s%c%s.torrent", config.Get().Torrents.FileStorage, os.PathSeparator, hash))
|
||||
if err != nil {
|
||||
//File not found, send 404
|
||||
c.AbortWithError(http.StatusNotFound, errors.New("File not found"))
|
||||
return
|
||||
}
|
||||
defer Openfile.Close() //Close after function return
|
||||
|
||||
//Get the file size
|
||||
FileStat, _ := Openfile.Stat() //Get info from file
|
||||
FileSize := strconv.FormatInt(FileStat.Size(), 10) //Get file size as a string
|
||||
|
||||
torrent, err := torrents.FindRawByHash(hash)
|
||||
|
||||
if err != nil {
|
||||
//File not found, send 404
|
||||
c.AbortWithError(http.StatusNotFound, errors.New("File not found"))
|
||||
return
|
||||
}
|
||||
|
||||
c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.torrent\"", torrent.Name))
|
||||
c.Header("Content-Type", "application/x-bittorrent")
|
||||
c.Header("Content-Length", FileSize)
|
||||
//Send the file
|
||||
// We reset the offset to 0
|
||||
Openfile.Seek(0, 0)
|
||||
io.Copy(c.Writer, Openfile) //'Copy' the file to the client
|
||||
}
|
Référencer dans un nouveau ticket