Adding tag post controller
Cette révision appartient à :
Parent
c09beeefa2
révision
e5c115b400
9 fichiers modifiés avec 129 ajouts et 4 suppressions
|
@ -126,6 +126,9 @@ torrents:
|
|||
order: torrent_id
|
||||
# TorrentSort : Default sorting order for torrents
|
||||
sort: DESC
|
||||
tags:
|
||||
# Torrent Tag Max weight for automatic system approval
|
||||
max_weight: 100.00
|
||||
users:
|
||||
default_notifications_settings: {"new_torrent": true, "new_torrent_email": false, "new_comment": true, "new_comment_email": false, "new_responses": false, "new_responses_email": false, "new_follower": false, "new_follower_email": false, "followed": false, "followed_email": false}
|
||||
navigation:
|
||||
|
|
|
@ -46,6 +46,10 @@ type Config struct {
|
|||
Models ModelsConfig `yaml:"models,flow,omitempty"`
|
||||
}
|
||||
|
||||
type Tags struct {
|
||||
MaxWeight float64 `yaml:"max_weight,omitempty"`
|
||||
}
|
||||
|
||||
// WebAddressConfig : Config struct for web addresses
|
||||
type WebAddressConfig struct {
|
||||
Nyaa string `yaml:"nyaa,omitempty"`
|
||||
|
@ -119,6 +123,7 @@ type TorrentsConfig struct {
|
|||
Trackers TrackersConfig `yaml:"trackers,flow,omitempty"`
|
||||
Order string `yaml:"order,omitempty"`
|
||||
Sort string `yaml:"sort,omitempty"`
|
||||
Tags Tags `yaml:"tags,omitempty"`
|
||||
}
|
||||
|
||||
// UsersConfig : Config struct for Users
|
||||
|
|
27
controllers/torrent/tag.go
Fichier normal
27
controllers/torrent/tag.go
Fichier normal
|
@ -0,0 +1,27 @@
|
|||
package torrentController
|
||||
|
||||
import (
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"github.com/NyaaPantsu/nyaa/models/tags"
|
||||
msg "github.com/NyaaPantsu/nyaa/utils/messages"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator"
|
||||
"github.com/NyaaPantsu/nyaa/utils/validator/tags"
|
||||
"github.com/gin-gonic/gin"
|
||||
)
|
||||
|
||||
func postTag(c *gin.Context, torrent *models.Torrent, user *models.User) {
|
||||
messages := msg.GetMessages(c)
|
||||
tagForm := &tagsValidator.CreateForm{}
|
||||
|
||||
c.Bind(tagForm)
|
||||
validator.ValidateForm(tagForm, messages)
|
||||
|
||||
for _, tag := range user.Tags {
|
||||
if tag.Tag == tagForm.Tag {
|
||||
return // already a tag by the user, don't add one more
|
||||
}
|
||||
}
|
||||
|
||||
tags.Create(tagForm.Tag, tagForm.Type, torrent, user) // Add a tag to the db
|
||||
tags.Filter(tagForm.Tag, tagForm.Type, torrent.ID) // Check if we have a tag reaching the maximum weight, if yes, deletes every tag and add only the one accepted
|
||||
}
|
|
@ -20,35 +20,57 @@ func ViewHandler(c *gin.Context) {
|
|||
messages := msg.GetMessages(c)
|
||||
user := router.GetUser(c)
|
||||
|
||||
// Display success message on upload
|
||||
if c.Request.URL.Query()["success"] != nil {
|
||||
messages.AddInfoT("infos", "torrent_uploaded")
|
||||
}
|
||||
// Display success message on edit
|
||||
if c.Request.URL.Query()["success_edit"] != nil {
|
||||
messages.AddInfoT("infos", "torrent_updated")
|
||||
}
|
||||
// Display wrong captcha error message
|
||||
if c.Request.URL.Query()["badcaptcha"] != nil {
|
||||
messages.AddErrorT("errors", "bad_captcha")
|
||||
}
|
||||
// Display reported successful message
|
||||
if c.Request.URL.Query()["reported"] != nil {
|
||||
messages.AddInfoTf("infos", "report_msg", id)
|
||||
}
|
||||
|
||||
// Retrieve the torrent
|
||||
torrent, err := torrents.FindByID(uint(id))
|
||||
|
||||
if c.Request.URL.Query()["notif"] != nil {
|
||||
// If come from notification, toggle the notification as read
|
||||
if c.Request.URL.Query()["notif"] != nil && user.ID > 0 {
|
||||
notifications.ToggleReadNotification(torrent.Identifier(), user.ID)
|
||||
}
|
||||
|
||||
// If torrent not found, display 404
|
||||
if err != nil {
|
||||
c.Status(http.StatusNotFound)
|
||||
return
|
||||
}
|
||||
|
||||
// We load tags for user and torrents
|
||||
user.LoadTags(torrent)
|
||||
torrent.LoadTags()
|
||||
|
||||
// We add a tag if posted
|
||||
if c.PostForm("tag") != "" && user.ID > 0 {
|
||||
postTag(c, torrent, user)
|
||||
}
|
||||
|
||||
// Convert torrent to the JSON Model used to display a torrent
|
||||
// Since many datas need to be parsed from a simple torrent model to the actual display
|
||||
b := torrent.ToJSON()
|
||||
// Get the folder root for the filelist view
|
||||
folder := filelist.FileListToFolder(torrent.FileList, "root")
|
||||
captchaID := ""
|
||||
//Generate a captcha
|
||||
if user.NeedsCaptcha() {
|
||||
captchaID = captcha.GetID()
|
||||
}
|
||||
// Display finally the view
|
||||
templates.Torrent(c, b, folder, captchaID)
|
||||
}
|
||||
|
||||
|
|
|
@ -106,5 +106,9 @@ func GormInit(conf *config.Config, logger Logger) (*gorm.DB, error) {
|
|||
if db.Error != nil {
|
||||
return db, db.Error
|
||||
}
|
||||
db.AutoMigrate(&Tag{})
|
||||
if db.Error != nil {
|
||||
return db, db.Error
|
||||
}
|
||||
return db, nil
|
||||
}
|
||||
|
|
|
@ -1,5 +1,12 @@
|
|||
package models
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"net/http"
|
||||
|
||||
"github.com/fatih/structs"
|
||||
)
|
||||
|
||||
// Tag model for a torrent vote system
|
||||
type Tag struct {
|
||||
TorrentID uint `gorm:"column:torrent_id"`
|
||||
|
@ -8,4 +15,27 @@ type Tag struct {
|
|||
Type string `gorm:"column:type"`
|
||||
Weight float64 `gorm:"column:weight"`
|
||||
Accepted bool `gorm:"column:accepted"`
|
||||
Total float64 `gorm:"-"`
|
||||
}
|
||||
|
||||
// Update a tag
|
||||
func (ta *Tag) Update() (int, error) {
|
||||
if ORM.Model(ta).UpdateColumn(ta.toMap()).Error != nil {
|
||||
return http.StatusInternalServerError, errors.New("Tag was not updated")
|
||||
}
|
||||
return http.StatusOK, nil
|
||||
}
|
||||
|
||||
// Delete : delete a tag based on id
|
||||
func (ta *Tag) Delete() (int, error) {
|
||||
if ORM.Delete(ta).Error != nil {
|
||||
return http.StatusInternalServerError, errors.New("tag_not_deleted")
|
||||
}
|
||||
|
||||
return http.StatusOK, nil
|
||||
}
|
||||
|
||||
// toMap : convert the model to a map of interface
|
||||
func (ta *Tag) toMap() map[string]interface{} {
|
||||
return structs.Map(ta)
|
||||
}
|
||||
|
|
|
@ -98,6 +98,7 @@ type TorrentJSON struct {
|
|||
Completed uint32 `json:"completed"`
|
||||
LastScrape time.Time `json:"last_scrape"`
|
||||
FileList []FileJSON `json:"file_list"`
|
||||
Tags []Tag `json:"-"` // not needed in json to reduce db calls
|
||||
}
|
||||
|
||||
// Size : Returns the total size of memory recursively allocated for this struct
|
||||
|
@ -347,6 +348,7 @@ func (t *Torrent) ToJSON() TorrentJSON {
|
|||
Completed: scrape.Completed,
|
||||
LastScrape: scrape.LastScrape,
|
||||
FileList: fileListJSON,
|
||||
Tags: t.Tags,
|
||||
}
|
||||
|
||||
return res
|
||||
|
@ -365,7 +367,6 @@ func TorrentsToJSON(t []Torrent) []TorrentJSON {
|
|||
|
||||
// Update : Update a torrent based on model
|
||||
func (t *Torrent) Update(unscope bool) (int, error) {
|
||||
cache.C.Delete(t.Identifier())
|
||||
db := ORM
|
||||
if unscope {
|
||||
db = ORM.Unscoped()
|
||||
|
@ -385,6 +386,8 @@ func (t *Torrent) Update(unscope bool) (int, error) {
|
|||
log.Errorf("Unable to update torrent to ES index: %s", err)
|
||||
}
|
||||
}
|
||||
// We only flush cache after update
|
||||
cache.C.Delete(t.Identifier())
|
||||
|
||||
return http.StatusOK, nil
|
||||
}
|
||||
|
@ -394,9 +397,8 @@ func (t *Torrent) UpdateUnscope() (int, error) {
|
|||
return t.Update(true)
|
||||
}
|
||||
|
||||
// DeleteTorrent : delete a torrent based on id
|
||||
// Delete : delete a torrent based on id
|
||||
func (t *Torrent) Delete(definitely bool) (*Torrent, int, error) {
|
||||
cache.C.Flush()
|
||||
db := ORM
|
||||
if definitely {
|
||||
db = ORM.Unscoped()
|
||||
|
@ -413,6 +415,8 @@ func (t *Torrent) Delete(definitely bool) (*Torrent, int, error) {
|
|||
log.Errorf("Unable to delete torrent to ES index: %s", err)
|
||||
}
|
||||
}
|
||||
// We flush cache only after delete
|
||||
cache.C.Flush()
|
||||
return t, http.StatusOK, nil
|
||||
}
|
||||
|
||||
|
@ -426,3 +430,13 @@ func (t *Torrent) DefinitelyDelete() (*Torrent, int, error) {
|
|||
func (t *Torrent) toMap() map[string]interface{} {
|
||||
return structs.Map(t)
|
||||
}
|
||||
|
||||
// LoadTags : load all the unique tags with summed up weight from the database in torrent
|
||||
func (t *Torrent) LoadTags() {
|
||||
// Only load if necessary
|
||||
if len(t.Tags) == 0 {
|
||||
// Should output a query like this: SELECT tag, type, accepted, SUM(weight) as total FROM tags WHERE torrent_id=923000 GROUP BY type, tag ORDER BY type, total DESC
|
||||
err := ORM.Select("tag, type, accepted, SUM(weight) as total").Where("torrent_id = ?", t.ID).Group("type, tag").Order("type ASC, total DESC").Find(&t.Tags).Error
|
||||
log.CheckErrorWithMessage(err, "LOAD_TAGS_ERROR: Couldn't load tags!")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -59,6 +59,7 @@ type User struct {
|
|||
|
||||
UnreadNotifications int `gorm:"-"` // We don't want to loop every notifications when accessing user unread notif
|
||||
Settings UserSettings `gorm:"-"` // We don't want to load settings everytime, stock it as a string, parse it when needed
|
||||
Tags []Tag `gorm:"-"` // We load tags only when viewing a torrent
|
||||
}
|
||||
|
||||
// UserJSON : User model conversion in JSON
|
||||
|
@ -406,3 +407,13 @@ func (u *User) IncreasePantsu() {
|
|||
func (u *User) DecreasePantsu() {
|
||||
u.Pantsu = 0.8 * u.Pantsu // You lose 20% of your pantsu points each wrong vote
|
||||
}
|
||||
|
||||
func (u *User) LoadTags(torrent *Torrent) {
|
||||
if u.ID == 0 {
|
||||
return
|
||||
}
|
||||
if err := ORM.Where("torrent_id = ? AND user_id = ?", torrent.ID, u.ID).Find(&u.Tags).Error; err != nil {
|
||||
log.CheckErrorWithMessage(err, "LOAD_TAGS_ERROR: Couldn't load tags!")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -105,6 +105,15 @@ func FindByID(id uint) (*models.User, int, error) {
|
|||
return user, http.StatusOK, nil
|
||||
}
|
||||
|
||||
// FindRawByID retrieves a user by ID without anything.
|
||||
func FindRawByID(id uint) (*models.User, int, error) {
|
||||
var user = &models.User{}
|
||||
if models.ORM.Last(user, id).RecordNotFound() {
|
||||
return user, http.StatusNotFound, errors.New("user_not_found")
|
||||
}
|
||||
return user, http.StatusOK, nil
|
||||
}
|
||||
|
||||
func SessionByID(id uint) (*models.User, int, error) {
|
||||
var user = &models.User{}
|
||||
if models.ORM.Preload("Notifications").Where("user_id = ?", id).First(user).RecordNotFound() { // We only load unread notifications
|
||||
|
|
Référencer dans un nouveau ticket