Albirew/nyaa-pantsu
Albirew
/
nyaa-pantsu
Archivé
1
0
Bifurcation 0

Merge branch 'dev' into filelist-fetching

Cette révision appartient à :
kilo 2017-11-16 19:51:01 +01:00 révisé par GitHub
révision 43b16edb20
Signature inconnue de Forgejo
ID de la clé GPG: 4AEE18F83AFDEB23
50 fichiers modifiés avec 991 ajouts et 311 suppressions

Voir le fichier

@ -32,7 +32,7 @@ func ActivityListHandler(c *gin.Context) {
}
var conditions []string
var values []interface{}
if userid != "" && currentUser.HasAdmin() {
if userid != "" && currentUser.IsModerator() {
conditions = append(conditions, "user_id = ?")
values = append(values, userid)
}

Voir le fichier

@ -433,7 +433,7 @@ func APISearchHandler(c *gin.Context) {
userID = 0
}
_, torrentSearch, nbTorrents, err := search.AuthorizedQuery(c, pagenum, currentUser.CurrentOrAdmin(uint(userID)))
_, torrentSearch, nbTorrents, err := search.AuthorizedQuery(c, pagenum, currentUser.CurrentOrJanitor(uint(userID)), currentUser.CurrentOrJanitor(uint(userID)))
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)

Voir le fichier

@ -86,7 +86,7 @@ func getTorrentList(c *gin.Context) (torrents []models.Torrent, createdAsTime ti
user = 0
}
_, torrents, _, err = search.AuthorizedQuery(c, pagenum, currentUser.CurrentOrAdmin(uint(user)))
_, torrents, _, err = search.AuthorizedQuery(c, pagenum, currentUser.CurrentOrJanitor(uint(user)), currentUser.CurrentOrJanitor(uint(user)))
return
}

Voir le fichier

@ -39,7 +39,7 @@ func ErrorMiddleware() gin.HandlerFunc {
func ModMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
currentUser := router.GetUser(c)
if !currentUser.HasAdmin() {
if !currentUser.IsJanitor() {
NotFoundHandler(c)
}
c.Next()

Voir le fichier

@ -61,10 +61,19 @@ func CommentsListPanel(c *gin.Context) {
// CommentDeleteModPanel : Controller for deleting a comment
func CommentDeleteModPanel(c *gin.Context) {
id, _ := strconv.ParseInt(c.PostForm("id"), 10, 32)
id, err := strconv.ParseInt(c.PostForm("id"), 10, 32)
if err != nil {
c.Redirect(http.StatusSeeOther, "/mod/comments")
return
}
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)
username := "れんちょん"
if comment.UserID != 0 {
username = comment.User.Username
}
activities.Log(&models.User{}, comment.Identifier(), "delete", "comment_deleted_by", strconv.Itoa(int(comment.ID)), username, router.GetUser(c).Username)
}
c.Redirect(http.StatusSeeOther, "/mod/comments?deleted")

Voir le fichier

@ -53,7 +53,7 @@ func torrentManyAction(c *gin.Context) {
messages.AddErrorTf("errors", "no_status_exist", status)
status = -1
}
if !currentUser.HasAdmin() {
if !currentUser.IsModerator() {
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
@ -64,7 +64,7 @@ func torrentManyAction(c *gin.Context) {
}
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
if c.PostForm("owner") != "" && currentUser.IsModerator() { // 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)

Voir le fichier

@ -13,10 +13,14 @@ import (
// IndexModPanel : Controller for showing index page of Mod Panel
func IndexModPanel(c *gin.Context) {
offset := 10
torrents, _, _ := torrents.FindAllOrderBy("torrent_id DESC", offset, 0)
torrents, _, _ := torrents.FindAllForAdminsOrderBy("torrent_id DESC", 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)
}
func GuidelinesModPanel(c *gin.Context) {
templates.Static(c, "admin/guidelines.jet.html")
}

Voir le fichier

@ -46,8 +46,11 @@ func init() {
modRoutes.GET("/torrent", TorrentEditModPanel)
modRoutes.POST("/torrent", TorrentPostEditModPanel)
/* Torrent delete routes */
/* Torrent delete routs */
modRoutes.POST("/torrent/delete", TorrentDeleteModPanel)
/* Guidelines route */
modRoutes.Any("/guidelines", GuidelinesModPanel)
/* Announcement edit view */
modRoutes.GET("/announcement/form", addAnnouncement)

Voir le fichier

@ -120,38 +120,43 @@ func TorrentPostEditModPanel(c *gin.Context) {
// TorrentDeleteModPanel : Controller for deleting a torrent
func TorrentDeleteModPanel(c *gin.Context) {
id, _ := strconv.ParseInt(c.PostForm("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()
returnRoute = "/mod/torrents/deleted"
} else {
_, _, err = torrent.Delete(false)
}
//delete reports of torrent
query := &search.Query{}
query.Append("torrent_id", id)
reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
for _, report := range reports {
report.Delete()
}
if err == nil {
if torrent.Uploader == nil {
torrent.Uploader = &models.User{}
currentUser := router.GetUser(c)
if currentUser.IsModerator() {
id, _ := strconv.ParseInt(c.PostForm("id"), 10, 32)
definitely := c.Request.URL.Query()["definitely"]
torrent, errFind := torrents.FindByID(uint(id))
if errFind == nil {
var err error
if definitely != nil {
_, _, err = torrent.DefinitelyDelete()
returnRoute = "/mod/torrents/deleted"
} else {
_, _, err = torrent.Delete(false)
}
//delete reports of torrent
query := &search.Query{}
query.Append("torrent_id", id)
reports, _, _ := reports.FindOrderBy(query, "", 0, 0)
for _, report := range reports {
report.Delete()
}
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, currentUser.Username)
}
_, 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")
}
c.Redirect(http.StatusSeeOther, returnRoute+"?deleted")
c.Redirect(http.StatusSeeOther, returnRoute)
}
// DeleteTagsModPanel : Controller for deleting all torrent tags

Voir le fichier

@ -76,7 +76,7 @@ func SearchHandler(c *gin.Context) {
return
}
searchParam, torrents, nbTorrents, err := search.AuthorizedQuery(c, pagenum, currentUser.CurrentOrAdmin(uint(userID)))
searchParam, torrents, nbTorrents, err := search.AuthorizedQuery(c, pagenum, currentUser.CurrentOrJanitor(uint(userID)), currentUser.IsJanitor())
if err != nil {
c.AbortWithError(http.StatusInternalServerError, err)
return

Voir le fichier

@ -10,8 +10,10 @@ import (
"github.com/NyaaPantsu/nyaa/models/comments"
"github.com/NyaaPantsu/nyaa/models/torrents"
"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/templates"
"github.com/gin-gonic/gin"
)
@ -34,6 +36,9 @@ func PostCommentHandler(c *gin.Context) {
messages.AddErrorT("errors", "bad_captcha")
}
}
if currentUser.IsBanned() {
messages.AddErrorT("errors", "account_banned")
}
content := sanitize.Sanitize(c.PostForm("comment"), "comment")
userID := currentUser.ID
@ -54,6 +59,13 @@ func PostCommentHandler(c *gin.Context) {
messages.Error(err)
}
}
url := "/view/" + strconv.FormatUint(uint64(torrent.ID), 10)
c.Redirect(302, url)
captchaID := ""
//Generate a captcha
if currentUser.NeedsCaptcha() {
captchaID = captcha.GetID()
}
folder := filelist.FileListToFolder(torrent.FileList, "root")
templates.Torrent(c, torrent.ToJSON(), folder, captchaID)
}

Voir le fichier

@ -25,7 +25,7 @@ func TorrentDeleteUserPanel(c *gin.Context) {
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
if currentUser.IsModerator() { // 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)

Voir le fichier

@ -52,7 +52,7 @@ func TorrentPostEditUserPanel(c *gin.Context) {
messages.AddErrorT("errors", "fail_torrent_update")
}
if !messages.HasErrors() {
upload.UpdateTorrent(&uploadForm, torrent, currentUser).Update(currentUser.HasAdmin())
upload.UpdateTorrent(&uploadForm, torrent, currentUser).Update(currentUser.IsModerator())
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/view/%d?success_edit", id))
return
}

Voir le fichier

@ -20,23 +20,6 @@ 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))
@ -66,6 +49,27 @@ func ViewHandler(c *gin.Context) {
captchaID = captcha.GetID()
}
// Display success message on upload
if c.Request.URL.Query()["success"] != nil {
if torrent.IsBlocked() {
messages.AddInfoT("infos", "torrent_uploaded_locked")
} else {
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)
}
if c.Request.URL.Query()["followed"] != nil {
messages.AddInfoTf("infos", "user_followed_msg", b.UploaderName)
}

Voir le fichier

@ -58,6 +58,8 @@ func UploadPostHandler(c *gin.Context) {
uploadForm.Status = models.TorrentStatusRemake
} else if user.IsTrusted() {
uploadForm.Status = models.TorrentStatusTrusted
} else if user.IsBanned() {
uploadForm.Status = models.TorrentStatusBlocked
}
err = torrents.ExistOrDelete(uploadForm.Infohash, user)

Voir le fichier

@ -7,9 +7,12 @@ import (
"net/http"
"github.com/NyaaPantsu/nyaa/controllers/router"
"github.com/NyaaPantsu/nyaa/models/notifications"
"github.com/NyaaPantsu/nyaa/models/activities"
"github.com/NyaaPantsu/nyaa/models/users"
"github.com/NyaaPantsu/nyaa/models"
"github.com/NyaaPantsu/nyaa/templates"
"github.com/NyaaPantsu/nyaa/utils/cookies"
"github.com/NyaaPantsu/nyaa/utils/crypto"
@ -33,8 +36,36 @@ func UserProfileDelete(c *gin.Context) {
if err == nil && currentUser.CurrentUserIdentical(userProfile.ID) {
cookies.Clear(c)
}
}
templates.Static(c, "site/static/delete_success.jet.html")
}
} else {
c.AbortWithStatus(http.StatusNotFound)
}
}
// UserProfileBan : Ban an User
func UserProfileBan(c *gin.Context) {
currentUser := router.GetUser(c)
if currentUser.IsJanitor() {
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
userProfile, _, errorUser := users.FindForAdmin(uint(id))
if errorUser == nil && !userProfile.IsModerator() {
action := "user_unbanned_by"
message := "?unbanned"
if userProfile.ToggleBan() {
action = "user_banned_by"
message = "?banned"
}
activities.Log(&models.User{}, fmt.Sprintf("user_%d", id), "edit", action, userProfile.Username, strconv.Itoa(int(id)), currentUser.Username)
c.Redirect(http.StatusSeeOther, fmt.Sprintf("/user/%d/%s", id, c.Param("username") + message))
} else {
c.AbortWithStatus(http.StatusNotFound)
}
} else {
c.AbortWithStatus(http.StatusNotFound)
}
}
@ -150,7 +181,7 @@ func UserDetailsHandler(c *gin.Context) {
}
}
// UserProfileFormHandler : Getting View User Profile Update
// UserProfileFormHandler : Updating User Profile
func UserProfileFormHandler(c *gin.Context) {
id, _ := strconv.ParseUint(c.Param("id"), 10, 32)
currentUser := router.GetUser(c)
@ -178,21 +209,21 @@ func UserProfileFormHandler(c *gin.Context) {
if !messages.HasErrors() {
c.Bind(&userForm)
c.Bind(&userSettingsForm)
if !currentUser.HasAdmin() {
if !currentUser.IsModerator() {
userForm.Username = userProfile.Username
userForm.Status = userProfile.Status
} else {
if userProfile.Status != userForm.Status && userForm.Status == 2 {
if userProfile.Status != userForm.Status && (userForm.Status == 2){
messages.AddErrorT("errors", "elevating_user_error")
}
}
validator.ValidateForm(&userForm, messages)
if !messages.HasErrors() {
if userForm.Email != userProfile.Email {
if currentUser.HasAdmin() {
userProfile.Email = userForm.Email
if currentUser.IsModerator() {
userProfile.Email = userForm.Email // reset, it will be set when user clicks verification
} else {
email.SendVerificationToUser(currentUser, userForm.Email)
email.SendVerificationToUser(userProfile, userForm.Email)
messages.AddInfoTf("infos", "email_changed", userForm.Email)
userForm.Email = userProfile.Email // reset, it will be set when user clicks verification
}
@ -201,10 +232,7 @@ func UserProfileFormHandler(c *gin.Context) {
if err != nil {
messages.Error(err)
}
if userForm.Email != user.Email {
// send verification to new email and keep old
email.SendVerificationToUser(user, userForm.Email)
}
if !messages.HasErrors() {
messages.AddInfoT("infos", "profile_updated")
userProfile = user

Voir le fichier

@ -38,6 +38,7 @@ func init() {
userRoutes.GET("/:id/:username/feed", feedController.RSSHandler)
userRoutes.GET("/:id/:username/feed/:page", feedController.RSSHandler)
userRoutes.POST("/:id/:username/delete", UserProfileDelete)
userRoutes.POST("/:id/:username/ban", UserProfileBan)
}
router.Get().Any("/username", RedirectToUserSearch)

Voir le fichier

@ -313,17 +313,7 @@ func (t *Torrent) ToJSON() TorrentJSON {
}
for _, c := range t.Comments {
if c.User != nil {
userStatus := ""
if c.User.IsBanned() {
userStatus = "userstatus_banned"
}
if c.User.HasAdmin() {
userStatus = "userstatus_moderator"
}
if c.User.ID == t.ID {
userStatus = "userstatus_uploader"
}
commentsJSON = append(commentsJSON, CommentJSON{Username: c.User.Username, UserID: int(c.User.ID), UserStatus: userStatus, Content: sanitize.MarkdownToHTML(c.Content), Date: c.CreatedAt.UTC(), UserAvatar: c.User.MD5})
commentsJSON = append(commentsJSON, CommentJSON{Username: c.User.Username, UserID: int(c.User.ID), UserStatus: c.User.GetRole(), Content: sanitize.MarkdownToHTML(c.Content), Date: c.CreatedAt.UTC(), UserAvatar: c.User.MD5})
} else {
commentsJSON = append(commentsJSON, CommentJSON{})
}

Voir le fichier

@ -154,7 +154,7 @@ func findOrderBy(parameters Query, orderBy string, limit int, offset int, countA
dbQuery = dbQuery.Preload("Uploader")
}
if countAll {
dbQuery = dbQuery.Preload("Comments")
dbQuery = dbQuery.Preload("Comments").Preload("OldComments")
}
if conditions != "" {
@ -191,6 +191,11 @@ func FindAllOrderBy(orderBy string, limit int, offset int) ([]models.Torrent, in
return FindOrderBy(nil, orderBy, limit, offset)
}
// FindAllForAdminsOrderBy : Get all torrents ordered by parameters
func FindAllForAdminsOrderBy(orderBy string, limit int, offset int) ([]models.Torrent, int, error) {
return findOrderBy(nil, orderBy, limit, offset, true, true, false)
}
// FindAll : Get all torrents without order
func FindAll(limit int, offset int) ([]models.Torrent, int, error) {
return FindOrderBy(nil, "", limit, offset)

Voir le fichier

@ -29,6 +29,8 @@ const (
UserStatusModerator = 2
// UserStatusScraped : Int for User status scrapped
UserStatusScraped = 3
// UserStatusModerator : Int for User status moderator
UserStatusJanitor = 4
)
// User model
@ -135,6 +137,11 @@ func (u *User) IsModerator() bool {
return u.Status == UserStatusModerator
}
// IsJanitor : Return true if user is janitor OR moderator
func (u *User) IsJanitor() bool {
return u.Status == UserStatusJanitor || u.Status == UserStatusModerator
}
// IsScraped : Return true if user is a scrapped user
func (u *User) IsScraped() bool {
return u.Status == UserStatusScraped
@ -152,11 +159,18 @@ func (u *User) GetUnreadNotifications() int {
return u.UnreadNotifications
}
// HasAdmin checks that user has an admin permission. Deprecated
func (u *User) HasAdmin() bool {
return u.IsModerator()
// ToggleBan : Ban/Unban an user an user, return true if the user is now banned
func (u *User) ToggleBan() bool {
if u.IsBanned() {
u.Status = UserStatusMember
} else {
u.Status = UserStatusBanned
}
u.Update()
return u.IsBanned()
}
// CurrentOrAdmin check that user has admin permission or user is the current user.
func (u *User) CurrentOrAdmin(userID uint) bool {
if userID == 0 && !u.IsModerator() {
@ -165,6 +179,14 @@ func (u *User) CurrentOrAdmin(userID uint) bool {
log.Debugf("user.ID == userID %d %d %s", u.ID, userID, u.ID == userID)
return (u.IsModerator() || u.ID == userID)
}
// CurrentOrJanitor check that user has janitor permission or user is the current user.
func (u *User) CurrentOrJanitor(userID uint) bool {
if userID == 0 && !u.IsJanitor() {
return false
}
log.Debugf("user.ID == userID %d %d %s", u.ID, userID, u.ID == userID)
return (u.IsJanitor() || u.ID == userID)
}
// CurrentUserIdentical check that userID is same as current user's ID.
// TODO: Inline this (won't go do this for us?)
@ -175,7 +197,7 @@ func (u *User) CurrentUserIdentical(userID uint) bool {
// NeedsCaptcha : Check if a user needs captcha
func (u *User) NeedsCaptcha() bool {
// Trusted members & Moderators don't
return !(u.IsTrusted() || u.IsModerator())
return !(u.IsTrusted() || u.IsJanitor())
}
// CanUpload : Check if a user can upload or if upload is enabled in config
@ -194,6 +216,9 @@ func (u *User) CanUpload() bool {
// GetRole : Get the status/role of a user
func (u *User) GetRole() string {
if u.ID == 0 {
return ""
}
switch u.Status {
case UserStatusBanned:
return "userstatus_banned"
@ -203,6 +228,8 @@ func (u *User) GetRole() string {
return "userstatus_scraped"
case UserStatusTrusted:
return "userstatus_trusted"
case UserStatusJanitor:
return "userstatus_janitor"
case UserStatusModerator:
return "userstatus_moderator"
}

Voir le fichier

@ -44,10 +44,7 @@ func Exists(email string, pass string) (user *models.User, status int, err error
status, err = http.StatusUnauthorized, errors.New("incorrect_password")
return
}
if userExist.IsBanned() {
status, err = http.StatusUnauthorized, errors.New("account_banned")
return
}
if userExist.IsScraped() {
status, err = http.StatusUnauthorized, errors.New("account_need_activation")
return

Voir le fichier

@ -664,7 +664,7 @@ th {
width: auto;
}
.website-nav table tr {
background: none!important;
background: none!important;
}
.website-nav #nav-category-list {
width: 70%;
@ -675,17 +675,17 @@ th {
}
.sub-category-list {
padding-left: 16px;
font-size: 12px;
margin-bottom: 9px;
font-size: 12px;
margin-bottom: 9px;
}
.sub-category-list span{
display: block;
display: block;
}
.sub-category-list span:before {
content: '-» ';
content: '-» ';
}
.sub-category-list span:first-child:before {
content: '';
content: '';
}
textarea {
max-width: 100%;
@ -899,8 +899,8 @@ html, body {
width: 100% !important;
margin-bottom: 15px;
}
.profile-panel .user-search {
max-width: none;
.profile-usermenu, .profile-panel .user-search {
width: 200px!important;
}
.header .h-user {
width: 46px;
@ -939,6 +939,9 @@ html, body {
.upload-form-table .table-input-label {
width: 25%!important;
}
.notification-status {
width: 100px;
}
}
@media (max-height: 750px),(max-width: 500px) {
@ -1030,12 +1033,28 @@ html, body {
.upload-form-table .table-input-label {
display: none;
}
.torrent-view-data {
display: table!important;
}
.torrent-view-data td, .torrent-view-data table {
width: 100%!important;
}
.torrent-view-data {
display: table!important;
}
.torrent-view-data td, .torrent-view-data table {
width: 100%!important;
}
.notification-status {
width: 41px!important;
font-size: 0;
}
#clear-notification a {
display: block;
margin-left: 0px!important;
float: none!important;
margin-top: 2px;
}
.notification-table {
margin-bottom: 108px!important;
}
.notification-date {
width: 100px!important;
}
}
@media (max-width: 440px) {
@ -1062,7 +1081,7 @@ html, body {
}
.profile-sidebar {
display: inline-block;
display: block;
}
.profile-usertitle {
@ -1087,11 +1106,14 @@ html, body {
border-radius: 6px;
}
.profile-usermenu {
min-width: 170px;
.profile-usermenu, .profile-panel .user-search {
width: 170px;
margin: 0 auto;
max-width: calc(100% - 16px);
}
.profile-usermenu a {
.profile-usermenu a, .profile-usermenu button {
display: block;
width: 100%;
margin-bottom: 11px;
}
.profile-usermenu .icon-rss-squared {
@ -1237,7 +1259,7 @@ html, body {
}
.comment-content :first-child {
margin-top: 8px;
margin-top: 8px;
}
.comment-content :last-child {
margin-bottom: 2px;
@ -1251,7 +1273,32 @@ html, body {
}
.comment-form textarea {
margin-bottom: 0;
margin-bottom: 0;
}
.CodeMirror {
cursor: text;
}
.CodeMirror-fullscreen, .editor-toolbar.fullscreen {
max-width: none!important;
}
.editor-toolbar.fullscreen {
padding: 8px 6px!important;
}
.comment-form .CodeMirror, .comment-form .CodeMirror-scroll {
min-height: 122px;
}
.comment-text, .markdown-container {
position: relative;
}
.comment-form .editor-toolbar {
padding: 0 6px;
}
.comment-form .editor-toolbar:before {
margin-bottom: 4px;
}
.comment-form .editor-toolbar:after {
margin-top: 4px;
}
.comment-form h3 {
@ -1792,7 +1839,6 @@ input.filelist-checkbox:checked+table.table-filelist {
}
[class^="btn-"] {
font-weight: bold;
color: white;
}
@ -1851,7 +1897,7 @@ summary:after {
width: 12px;
font-size: 1.5em;
font-weight: bold;
outline: none;
outline: none;
}
details[open] summary:after {
@ -2083,40 +2129,48 @@ p.upload-rules a {
.upload-form-table .table-torrent-link input[type="text"] {
width: 62%;
}
.upload-form-table .editor-statusbar {
position: relative;
margin-top: -27px;
margin-bottom: 2px;
.upload-form-table #desc {
margin-bottom: 20px;
}
.comment-text .editor-statusbar {
right: 9px;
bottom: 20px;
}
.editor-statusbar {
position: absolute;
padding: 0;
right: 8px;
z-index: 1;
bottom: 6px;
}
.upload-form-table details {
margin-bottom: 4px;
margin-bottom: 4px;
}
#anidex-upload-info > div {
height: auto;
padding: 10px 6px;
border-top: none;
height: auto;
padding: 10px 6px;
border-top: none;
}
#anidex-upload-info p {
margin-bottom: 4px;
margin-bottom: 4px;
}
#anidex-upload-info p:first-child {
margin-top: 0;
margin-top: 0;
}
#anidex-upload-info > div > div {
margin-left: 9px;
margin-left: 9px;
}
#anidex-upload-info > div input[type="text"], #anidex-upload-info > div select {
margin-bottom: 4px;
margin-bottom: 4px;
}
#anidex-upload-info > div select {
width: calc(100% - 8px);
width: calc(100% - 8px);
}
#anidex-upload-info > div select[name="anidex_form_category"] option{
color: #000;
color: #000;
text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.3);
font-size: 14px;
font-weight: bold;
@ -2306,7 +2360,6 @@ table.multiple-upload {
}
.profile-panel .user-search {
padding: 0;
max-width: 170px;
}
.user-search [type="text"] {
@ -2390,49 +2443,49 @@ form.delete-form button.form-input.btn-red {
bottom: 8px;
right: 8px;
position: absolute;
width: calc(100% - 16px);
width: calc(100% - 16px);
}
#clear-notification a {
float: right;
margin-left: 3px;
float: right;
margin-left: 3px;
}
.notification-table {
margin-bottom: 44px;
}
.notification-table td {
text-align: center;
padding: 6px 0;
border-bottom: 1px solid;
text-align: center;
padding: 6px 0;
border-bottom: 1px solid;
}
.notification-table tr:hover td {
filter: brightness(1.2);
filter: brightness(1.2);
}
.notification-status {
width: 140px;
width: 140px;
}
.notification-event {
text-align: left!important;
padding: 6px 10px!important;
text-align: left!important;
padding: 6px 10px!important;
}
.notification-date {
width: 195px;
width: 195px;
}
td.notification-status {
border: 1px solid black;
border: 1px solid black;
}
td.notification-status {
background-color: #e4e4e4;
background-color: #e4e4e4;
}
td.notification-status.notification-unread {
background-color: rgb(161, 211, 253);
color: white;
background-color: rgb(161, 211, 253);
color: white;
}
.torrent-report-table td, .torrent-report-table th {
width: 195px;
width: 195px;
}
.td-report-message {
width: auto!important;
width: auto!important;
white-space: normal;
word-break: break-word;
}

Voir le fichier

@ -279,6 +279,9 @@ select.form-input {
.CodeMirror {
padding: 0;
}
.comment-form .CodeMirror, .comment-form .CodeMirror-scroll {
min-height: 70px;
}
.upload-form-table .checkbox-container {
height: 22px;
@ -689,33 +692,58 @@ span.tag {
}
.upload-form-table .table-torrent-link input {
width: 100%!important;
}
.upload-form-table .editor-toolbar {
}
.editor-toolbar, .CodeMirror {
max-width: 459px;
}
.editor-toolbar.fullscreen {
top: 40px;
}
.CodeMirror-fullscreen {
top: 90px;
}
.markdown-container .editor-statusbar {
bottom: 6px;
left: 141px;
}
.editor-statusbar {
bottom: 19px;
left: 209px;
right: unset!important;
}
.editor-toolbar {
padding: 0 2px;
font-size: 10px;
}
.upload-form-table .editor-toolbar, .upload-form-table .CodeMirror {
.editor-toolbar, .CodeMirror {
border-radius: 0;
border-color: #c4c4c4;
opacity: 1;
}
.upload-form-table .editor-toolbar::before {
.editor-toolbar::before {
margin-bottom: 2px;
}
.upload-form-table .editor-toolbar::after {
.editor-toolbar::after {
margin-top: 4px;
}
.upload-form-table .editor-toolbar a {
.editor-toolbar a {
width: 26px;
height: 24px;
}
.upload-form-table .editor-toolbar a:before {
.comment-form .editor-toolbar a {
width: 24px;
height: 20px;
}
.editor-toolbar a:before {
line-height: 25px;
}
.comment-form .editor-toolbar a:before {
line-height: 18px;
}
.upload-form-table .CodeMirror-scroll, .upload-form-table .CodeMirror {
min-height: 120px;
}
.upload-form-table .CodeMirror-scroll {
.CodeMirror-scroll {
max-width: unset!important;
}

Voir le fichier

@ -0,0 +1,8 @@
{{ extends "layouts/index_admin" }}
{{block title()}}{{ T("moderation_guidelines") }}{{end}}
{{ block content_body()}}
<div class="results box">
<h1>{{ T("moderation_guidelines") }}</h1>
<img src="https://www.themarysue.com/wp-content/uploads/2016/09/harassment-guide.png">
</div>
{{end}}

Voir le fichier

@ -14,19 +14,26 @@
</thead>
<tbody>
{{range Torrents}}
<tr>
<tr {{ if .IsBlocked() }}class="locked"{{end}}>
<td class="tr-name home-td">
<a href="/view/{{.ID }}">{{ .Name }}</a>
<a href="/mod/torrent?id={{.ID}}" class="form-input btn-blue float-right">{{ T("edit") }}</a>
</td>
<td class="tr-size home-td">
<a href="/mod/torrents?userID={{.UploaderID}}">{{ .UploaderID }}</a>
<a href="/mod/torrents?userID={{.UploaderID}}">{{ if .Uploader }}{{.Uploader.Username }}{{else}}れんちょん{{end}}</a>
</td>
<td class="tr-size home-td">
<form method="POST" action="/mod/torrent/delete">
<input type="hidden" name="id" value="{{ .ID }}">
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i> {{ T("delete") }}</button>
</form>
{{ if User.IsModerator() }}
<form method="POST" action="/mod/torrent/delete" class="delete-form">
<input type="hidden" name="id" value="{{ .ID }}">
{{ if .IsDeleted() }}<input type="hidden" name="definitely" value="true">{{ end }}
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }} {{ if !.IsDeleted() }}{{ T("delete") }}{{else}}{{ T("delete_definitely_torrent_warning ")}}{{end}}')) return false;"><i class="icon-trash"></i>{{ if .IsDeleted() }}{{ T("delete_definitely") }}{{else}}{{ T("delete") }}{{end}}</button>
</form>
{{end}}
<form method="POST" action="/mod/torrent/block" class="delete-form">
<input type="hidden" name="id" value="{{ .ID }}">
<button type="submit" class="form-input btn-orange" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i>{{ if .IsBlocked() }}{{ T("torrent_unblock") }}{{else}}{{ T("torrent_block") }}{{end}}</button>
</form>
</td>
</tr>
{{end}}
@ -88,10 +95,16 @@
<a href="/user/{{.ID}}/{{.Username }}">{{ .Username }}</a>
</td>
<td class="tr-size home-td">{{if .ID > 0}}
<form method="POST" action="/user/{{.ID}}/{{.Username }}/delete" >
{{ yield csrf_field()}}
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i> {{ T("delete") }}</button>
</form>
{{ if User.IsModerator() }}
<form method="POST" action="/user/{{.ID}}/{{.Username }}/delete" class="delete-form">
{{ yield csrf_field()}}
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i> {{ T("delete") }}</button>
</form>
{{end}}
<form method="POST" action="/user/{{.ID}}/{{.Username }}/ban" class="delete-form">
{{ yield csrf_field()}}
<button type="submit" class="form-input btn-orange" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i>{{ if .IsBanned() }}{{ T("unban") }}{{else}}{{ T("ban") }}{{end}}</button>
</form>
{{end}}
</td>
</tr>

Voir le fichier

@ -38,12 +38,12 @@
</thead>
<tbody>
{{ range Models}}
<tr>
<tr {{ if .Status == 5}}class="locked hidden"{{end}}>
<td class="tr-cb">
<input type="checkbox" class="selectable" name="torrent_id" value="{{.ID }}" />
</td>
<td class="tr-name home-td">
<a href="/view/{{ .ID }}">{{ .Name }}</a> {{ if !.IsDeleted }}
<a href="/view/{{ .ID }}">{{ .Name }}</a> {{ if User.IsModerator() }}
<a href="/mod/torrent?id={{.ID}}" class="form-input btn-blue float-right">
{{ T("edit")}}
</a> {{end}}
@ -57,14 +57,15 @@
<td class="tr-actions home-td"> <form></form>
<form method="POST" action="/mod/torrent/block" class="delete-form">
<input type="hidden" name="id" value="{{ .ID }}">
<button type="submit" class="form-input btn-orange" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i>{{ if .IsBlocked }}{{ T("torrent_unblock") }}{{else}}{{ T("torrent_block") }}{{end}}</button>
<button type="submit" class="form-input btn-orange" {{ if !User.IsModerator() }}onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"{{end}}><i class="icon-trash"></i>{{ if .IsBlocked() }}{{ T("torrent_unblock") }}{{else}}{{ T("torrent_block") }}{{end}}</button>
</form>
{{ if User.IsModerator() }}
<form method="POST" action="/mod/torrent/delete" class="delete-form">
<input type="hidden" name="id" value="{{ .ID }}">
{{ if .IsDeleted }}<input type="hidden" name="definitely" value="true">{{ end }}
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }} {{ if !.IsDeleted }}{{ T("delete") }}{{else}}{{ T("delete_definitely_torrent_warning ")}}{{end}}')) return false;"><i class="icon-trash"></i>{{ if .IsDeleted }}{{ T("delete_definitely") }}{{else}}{{ T("delete") }}{{end}}</button>
{{ if .IsDeleted() }}<input type="hidden" name="definitely" value="true">{{ end }}
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }} {{ if !.IsDeleted() }}{{ T("delete") }}{{else}}{{ T("delete_definitely_torrent_warning ")}}{{end}}')) return false;"><i class="icon-trash"></i>{{ if .IsDeleted() }}{{ T("delete_definitely") }}{{else}}{{ T("delete") }}{{end}}</button>
</form>
{{end}}
</td>
</tr>
{{end}}

Voir le fichier

@ -13,7 +13,7 @@
</thead>
<tbody>
{{ range Models}}
<tr>
<tr {{ if .IsBanned() }}class="locked hidden"{{end}}>
<td class="tr-name home-td">
<a href="/user/{{.ID}}/{{.Username }}">{{ .Username }}</a>
</td>
@ -21,7 +21,10 @@
{{if .ID > 0}}
<form method="POST" action="/user/{{.ID}}/{{.Username }}/delete">
{{ yield csrf_field()}}
{{ if User.IsModerator() }}
<button type="submit" class="form-input btn-red" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i> {{ T("delete") }}</button>
{{end}}
<button type="submit" class="form-input btn-orange" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i> {{ if !.IsBanned() }}{{ T("ban") }}{{else}}{{ T("unban") }}{{end}}</button>
</form>
{{end}}
</td>

Voir le fichier

@ -7,7 +7,7 @@
<a href="{{magnet}}" class="form-input btn-green download" style="height: auto;">
<div class="icon-magnet"></div>{{ T("magnet_link")}}
</a>
{{ if !isset(Errors[name])}}<br/><p>{{ T("pending_torrent") }}</p>{{end}}<br/><br/>
{{ if !isset(Errors["errors"])}}<br/><p>{{ T("pending_torrent") }}</p>{{end}}<br/><br/>
{{ end }}
<img src="/img/no_torrent_file.jpg" alt="No torrent file"/>
</div>

Voir le fichier

@ -1,18 +1,18 @@
{{ import "csrf" }}
{{block badge_user()}}
<div class="h-user">
<div class="h-user {{ if User.IsBanned() }}hidden{{end}}">
{{if User.ID > 0 }}
<button href="#" class="nav-btn">
<div class="user-avatar small">
<img src="{{getAvatar(User.MD5, 50)}}"/>
{{if User.GetUnreadNotifications() > 0}}<span>{{User.GetUnreadNotifications()}}</span>{{end}}
</div>
<span class="user-info" title="{{ User.Username}}">
<span class="user-info" title="{{ User.Username }}">
<span class="hide-md">{{User.Username}}</span>
</span>
</button>
<div class="user-menu">
<a class="nav-btn" href="/user/{{ User.ID }}/{{ User.Username }}">{{ T("profile")}}</a>
<a class="nav-btn" href="/user/{{ User.ID }}/{{ User.Username }}">{{ T("profile")}}{{ if User.IsBanned() }} ({{T("banned")}}){{end}}</a>
<a class="nav-btn notif" href="/notifications">
{{ T("my_notifications")}}
{{if User.GetUnreadNotifications() > 0}}<span class="badge">({{ User.GetUnreadNotifications() }})</span>{{end}}
@ -20,7 +20,7 @@
<a class="nav-btn" href="/user/{{ User.ID }}/{{ User.Username }}/edit">
{{ T("settings")}}
</a>
{{if User.HasAdmin()}}
{{if User.IsJanitor()}}
<a class="nav-btn" href="/mod">{{ T("moderation")}}</a>
{{end}}
<form action="/logout" method="POST">

Voir le fichier

@ -13,7 +13,6 @@
{{ if _% 3 != 2}}{{ if _% 3 == 0}}<td></td>{{end}}<td></td>{{end}}
</tr>{{end}}
{{ end }}
</tr>
</tbody>
</table>
{{ if Search.Category != ""}}

Voir le fichier

@ -7,4 +7,5 @@
<a href="{{URL.Parse("/mod/announcement")}}" class="nav-btn{{if strcmp(URL.String(), "/mod/announcement", 17, 5) }} active{{end}}">{{ T("announcements")}}</a>
<a href="{{URL.Parse("/mod/reports")}}" class="nav-btn{{if URL.String() == "/mod/reports"}} active{{end}}">{{ T("torrent_reports")}}</a>
<a href="{{URL.Parse("/mod/reassign")}}" class="nav-btn{{if URL.String() == "/mod/reassign"}} active{{end}}">{{ T("torrent_reassign")}}</a>
<a href="{{URL.Parse("/mod/guidelines")}}" class="nav-btn{{if URL.String() == "/mod/guidelines"}} active{{end}}">{{ T("guidelines")}}</a>
</div>

Voir le fichier

@ -1,5 +1,6 @@
{{ import "layouts/partials/helpers/csrf" }}
{{ block profile_menu(route="profile") }}
<div class="profile-sidebar">
<div class="profile-sidebar {{ if UserProfile.IsBanned() }} hidden{{end}}">
<!-- SIDEBAR USERPIC -->
<div class="profile-userpic">
<img src="{{ getAvatar(UserProfile.MD5, 130) }}" alt="{{ UserProfile.Username }}"/>
@ -10,9 +11,11 @@
<p class="profile-usertitle-name">
{{ UserProfile.Username}}
</p>
{{ if UserProfile.GetRole() != "" }}
<p class="profile-usertitle-job">
{{T(UserProfile.GetRole())}}
</p>
{{end}}
<p class="profile-usertitle-uploadcount">{{T("followers")}}: <b>{{len(UserProfile.Followers)}}</b><br/>{{ T("torrents_uploaded") }}:<b>{{ NbTorrents[0] }}</b><br>{{T("size")}}: <b>{{fileSize(NbTorrents[1], T, false)}}</b></p>
</div>
<!-- END SIDEBAR USER TITLE -->
@ -43,12 +46,19 @@
{{ if User.CurrentUserIdentical(UserProfile.ID) }}
<a class="form-input" href="/notifications">{{ T("my_notifications")}}</a>
{{end}}
{{if UserProfile.ID > 0 && User.CurrentOrAdmin(UserProfile.ID) }}
<a class="form-input" href="/user/{{UserProfile.ID}}/{{UserProfile.Username}}/edit">
{{ T("settings")}}
</a>
{{end}}
{{if UserProfile.ID > 0}}
{{ if User.CurrentOrAdmin(UserProfile.ID) }}
<a class="form-input" href="/user/{{UserProfile.ID}}/{{UserProfile.Username}}/edit">
{{ T("settings")}}
</a>
{{else if User.IsJanitor() && !UserProfile.IsJanitor() }}
<form method="POST" action="/user/{{UserProfile.ID}}/{{UserProfile.Username}}/ban">
{{ yield csrf_field()}}
<button type="submit" class="form-input btn-blue" onclick="if (!confirm('{{ T("are_you_sure") }}')) return false;"><i class="icon-trash"></i>{{ if UserProfile.IsBanned() }}{{ T("unban") }}{{else}}{{ T("ban") }}{{end}}</button>
</form>
{{end}}
{{end}}
{{end}}
</div>
{{ if User.ID != UserProfile.ID }}
<div class="user-search">

Voir le fichier

@ -17,7 +17,7 @@ Templates.Add("torrents.item", function(torrent) {
} else if (torrent.status == 4) {
tr_class += " aplus"
}
// {{ if User.HasAdmin() }}
// {{ if User.IsModerator() }}
var cb_hide = (!TorrentsMod.enabled) ? " hide" : ""
var cb_show = (TorrentsMod.enabled) ? ' style="display:table-cell;"' : ""
// {{ end }}
@ -43,7 +43,7 @@ Templates.Add("torrents.item", function(torrent) {
}
return `<tr id="torrent_` + torrent.id + `" class="` + tr_class + `">
{{ if User.HasAdmin() }}
{{ if User.IsModerator() }}
<td class="tr-cb` + cb_hide + `"` + cb_show + `>
<input data-name="` + Templates.EncodeEntities(torrent.name) + `" type="checkbox" id="torrent_cb_` + torrent.id + `" name="torrent_id" value="` + torrent.id + `">
</td>

Voir le fichier

@ -1,7 +1,7 @@
{{ extends "layouts/index_site" }}
{{ import "layouts/partials/helpers/search" }}
{{block title()}}{{if Search.UserName == ""}}{{ T("home")}}{{else}}{{Search.UserName}}{{end}}{{end}}
{{block contclass()}}{{if User.HasAdmin() }}content-admin{{end}}{{end}}
{{block title()}}{{if Search.UserName != ""}}{{Search.UserName}}{{else if Search.NameLike != ""}}{{Search.NameLike}}{{else if Search.Category != ""}}{{T(GetCategoryName(Search.Category))}}{{else}}{{ T("home")}}{{end}}{{end}}
{{block contclass()}}{{if User.IsModerator() }}content-admin{{end}}{{end}}
{{block content_body()}}
{{ if OldNav || Theme == "classic"}}
{{ include "layouts/partials/helpers/oldNav" }}
@ -11,7 +11,7 @@
<table>
<thead class="torrent-info">
<tr>
{{ if User.HasAdmin() }}
{{ if User.IsModerator() }}
<th class="tr-cb hide">
<input type="checkbox" name="select_all" onchange="TorrentsMod.selectAll(this.checked)"/>
</th>
@ -55,8 +55,8 @@
</thead>
<tbody id="torrentListResults" {{if AltColors}}class="alt-colors"{{end}}>
{{ range Models}}
<tr id="torrent_{{ .ID }}" class="torrent-info {{if .Status == 2}}remake{{else if .Status == 3}}trusted{{else if .Status == 4}}aplus{{end}}" >
{{ if User.HasAdmin() }}
<tr id="torrent_{{ .ID }}" class="torrent-info {{if .Status == 2}}remake{{else if .Status == 3}}trusted{{else if .Status == 4}}aplus{{else if .Status == 5}}locked hidden{{end}}">
{{ if User.IsModerator() }}
<td class="tr-cb hide">
<input data-name="{{ .Name }}" type="checkbox" id="torrent_cb_{{ .ID }}" name="torrent_id" value="{{ .ID }}"/>
</td>
@ -108,7 +108,7 @@
</tbody>
</table>
</div>
{{ if User.HasAdmin() }}
{{ if User.IsModerator() }}
<div class="modtools">
<button id="show_actions" class="form-input" data-toggle-text="{{ T("hide_mod_tools")}}">{{ T("show_mod_tools")}}</button>
<span class="actions">
@ -175,7 +175,7 @@
<script type="text/javascript" src="{{ URL.Parse("/js/modal.js") }}"></script>
<script type="text/javascript" src="{{ URL.Parse("/js/torrents.js") }}"></script>
<script type="text/javascript" src="{{ URL.Parse("/js/translation.js") }}"></script>
{{ if User.HasAdmin() }}
{{ if User.IsModerator() }}
<script type="text/javascript" src="{{ URL.Parse("/js/torrentsMod.js") }}"></script>
<script type="text/javascript">
// We add translations string

Voir le fichier

@ -64,7 +64,7 @@
</tr>
<tr>
<td class="table-input-label"><label for="desc">{{ T("torrent_description")}}</label></td>
<td class="table-input"><textarea name="desc" id="desc" class="form-input up-input" style="height: 10rem;">{{Form.Description}}</textarea></td>
<td class="table-input markdown-container"><textarea name="desc" id="desc" class="form-input up-input" style="height: 10rem;">{{Form.Description}}</textarea></td>
</tr>
<tr class="hidden">
<td class="table-input-label"><label for="anidex_api">Upload to Anidex:</label></td>

Voir le fichier

@ -163,7 +163,7 @@
</a>
<a id="reportPopup" href="/report/{{Torrent.ID}}" class="form-input">{{ T("report_btn") }}</a>
{{ if User.ID > 0}}
{{ if User.HasAdmin()}}
{{ if User.IsModerator()}}
<form method="POST" action="/mod/torrent/delete" class="delete-form">
{{ yield csrf_field()}}
<input type="hidden" name="id" value="{{ Torrent.ID }}">
@ -217,23 +217,23 @@
{{idx := 1}}
{{previousComment := ""}}
{{previousUser := 0}}
{{range index, element := Torrent.Comments}}
{{if previousComment != element.Content || previousUser != element.UserID || element.UserID == 0}}
{{range _, comment := Torrent.Comments}}
{{if previousComment != comment.Content || previousUser != comment.UserID || comment.UserID == 0}}
<div class="torrent-info-box comment-box">
<span class="comment-index">
<a href="#comment_{{idx}}">{{idx}}</a>
<small style="padding-left: 4px;" class="date-full">{{formatDate(element.Date, false)}}</small>
<small style="padding-left: 4px;" class="date-full">{{formatDate(comment.Date, false)}}</small>
</span>
<span class="comment-userinfo"><img src="{{ getAvatar(element.UserAvatar, 50) }}"/>
{{if element.UserID > 0}}<a href="/user/{{element.UserID}}/{{element.Username}}" class="comment-user">{{element.Username}}</a>{{if element.UserStatus != ""}}<span class="user-status">{{T(element.UserStatus)}}</span>{{end}}{{else}}
<span class="comment-user">れんちょん</span>{{end}}
<span class="comment-userinfo"><img src="{{ getAvatar(comment.UserAvatar, 50) }}"/>
{{if comment.UserID > 0}}<a href="/user/{{comment.UserID}}/{{comment.Username}}" class="comment-user">{{comment.Username}}</a>{{if comment.UserStatus != ""}}<span class="user-status">{{T(comment.UserStatus)}}</span>{{end}}{{else}}
<span class="comment-user">{{ if comment.Username != ""}}{{comment.Username}}{{else}}れんちょん{{end}}</span>{{end}}
</span>
<div class="comment-content">{{element.Content|raw}}</div>
<div class="comment-content">{{comment.Content|raw}}</div>
</div>
{{idx = idx + 1}}
{{end}}
{{previousComment = element.Content}}
{{previousUser = element.UserID}}
{{previousComment = comment.Content}}
{{previousUser = comment.UserID}}
{{end}}
{{ if len(Torrent.Comments) == 0 }}
<p id="no-comment-message">{{ T("torrent_no_comments") }}</p>
@ -341,7 +341,6 @@ Modal.Init({
// order of apparition of the modals
button: ["#reportPopup", "#tagPopup"]
});
{{ if len(Torrent.FileList) == 0 }}
var FileListContainer = document.querySelector("#filelist tbody"),
FileListLabel = document.getElementsByClassName("filelist-control")[0],
@ -370,6 +369,9 @@ Modal.Init({
})
{{end}}
</script>
<script type="text/javascript" src="{{ URL.Parse("/js/simplemde.min.js") }}"></script>
<script type="text/javascript">new SimpleMDE({ element: document.getElementsByName("comment")[0], spellChecker: false, showIcons: [ "strikethrough", "code", "table", "horizontal-rule" ] });</script>
{{ if !torrentFileExists(Torrent.Hash, Torrent.TorrentLink)}}
var torrentLink = document.getElementById("torrent-download-link"),
oldDownloadHtml = torrentLink.innerHTML,

Voir le fichier

@ -33,7 +33,7 @@
</select>
</td>
</tr>
{{ if !User.HasAdmin()}}
{{ if !User.IsModerator()}}
<tr>
<td><label for="current_password">{{ T("current_password") }}</label></td>
<td><input class="form-input up-input up-input" name="current_password" id="current_password" type="password"/></td>
@ -51,7 +51,7 @@
</table>
{{ yield errors(name="Email")}}
{{ yield errors(name="Language")}}
{{ if !User.HasAdmin()}}
{{ if !User.IsModerator()}}
{{ yield errors(name="CurrentPassword")}}
{{end}}
{{ yield errors(name="Password")}}
@ -228,7 +228,7 @@
{{ yield errors(name="FollowedEmail")}}
{{end}}
{{ if User.HasAdmin()}}
{{ if User.IsModerator()}}
<h2>{{ T("moderation")}}</h2>
<table class="user-edit-table">
<tbody>
@ -243,8 +243,9 @@
<option value="-1" {{ if UserProfile.Status == -1 }}selected{{end}}>{{ T("userstatus_banned")}}</option>
<option value="0" {{ if UserProfile.Status == 0 }}selected{{end}}>{{ T("userstatus_member")}} ({{ T("default") }})</option>
<option value="1" {{ if UserProfile.Status == 1 }}selected{{end}}>{{ T("userstatus_trusted")}}</option>
{{ if UserProfile.Status == 2}}
<option value="2" selected>{{ T("userstatus_moderator")}}</option>
{{ if User.Status == 2}}
<option value="4" {{ if UserProfile.Status == 4 }}selected{{end}}>{{ T("userstatus_janitor")}}</option>
<option value="2" {{ if UserProfile.Status == 2 }}selected{{end}}>{{ T("userstatus_moderator")}}</option>
{{end}}
<option value="3" {{ if UserProfile.Status == 3 }}selected{{end}}>{{ T("userstatus_scraped")}}</option>
</select>

Voir le fichier

@ -176,10 +176,10 @@ func userProfileBase(c *gin.Context, templateName string, userProfile *models.Us
query.Set("limit", "15")
c.Request.URL.RawQuery = query.Encode()
nbTorrents := 0
if userProfile.ID > 0 && currentUser.CurrentOrAdmin(userProfile.ID) {
_, userProfile.Torrents, nbTorrents, _ = search.ByQuery(c, 1, true, false, false)
if userProfile.ID > 0 && currentUser.CurrentOrJanitor(userProfile.ID) {
_, userProfile.Torrents, nbTorrents, _ = search.ByQuery(c, 1, true, false, false, true)
} else {
_, userProfile.Torrents, nbTorrents, _ = search.ByQuery(c, 1, true, false, true)
_, userProfile.Torrents, nbTorrents, _ = search.ByQuery(c, 1, true, false, true, false)
}
var uploadedSize int64

Voir le fichier

@ -40,6 +40,7 @@ func templateFunctions(vars jet.VarMap) jet.VarMap {
vars.Set("GetCategories", categories.GetSelect)
vars.Set("GetCategory", getCategory)
vars.Set("CategoryName", categoryName)
vars.Set("GetCategoryName", GetCategoryName)
vars.Set("GetTorrentLanguages", torrentLanguages.GetTorrentLanguages)
vars.Set("LanguageName", languageName)
vars.Set("LanguageNameFromCode", languageNameFromCode)
@ -224,13 +225,16 @@ func getCategory(category string, keepParent bool) categories.Categories {
return categoryRet
}
func categoryName(category string, subCategory string) string {
s := category + "_" + subCategory
return GetCategoryName( category + "_" + subCategory)
}
if category, ok := categories.GetByID(s); ok {
return category.Name
func GetCategoryName(category string) string {
if cat, ok := categories.GetByID(category); ok {
return cat.Name
}
return ""
}
func languageName(lang publicSettings.Language, T publicSettings.TemplateTfunc) string {
if strings.Contains(lang.Name, ",") {
langs := strings.Split(lang.Name, ", ")

Voir le fichier

@ -289,6 +289,37 @@ func TestCategoryName(t *testing.T) {
}
}
func TestCategoryName2(t *testing.T) {
var tests = []struct {
TestCat string
Expected string
}{
{
TestCat: "_",
Expected: "",
},
{
TestCat: "d",
Expected: "",
},
{
TestCat: "3_",
Expected: "anime",
},
{
TestCat: "3_6",
Expected: "anime_raw",
},
}
for _, test := range tests {
value := GetCategoryName(test.TestCat)
if value != test.Expected {
t.Errorf("Unexpected value from the function categoryName, got '%s', wanted '%s' for '%s'", value, test.Expected, test.TestCat)
}
}
}
func TestLanguageName(t *testing.T) {
var tests = []struct {
TestLang publicSettings.Language

Voir le fichier

@ -95,3 +95,15 @@
* + loading_file_list
* + torrent_filelist
* + back_to_torrent
## 2017/11/09
* + userstatus_janitor
* + ban
* + unban
* + user_banned_by
* + user_unbanned_by
## 2017/11/10
* + user_banned
* + user_unbanned
* + torrent_uploaded_locked
* + moderation_guidelines
* + guidelines

Voir le fichier

@ -1,4 +1,8 @@
[
{
"id": "read_rules",
"translation": "Llegiu les <a href=\"/faq#rules\">normes</a> abans de carregar res."
},
{
"id": "rules",
"translation": "Normes"
@ -19,6 +23,10 @@
"id": "rules_sukebei",
"translation": "El contingut per a adults correspon a sukebei.pantsu.cat"
},
{
"id": "rule_tracker_url",
"translation": "<span style='font-weight: bold;'>https://uw0.xyz/</span> és la URL del rastrejador oficial"
},
{
"id": "verify_email_title",
"translation": "Verifiqueu la vostra adreça electrònica de Nyaapantsu."
@ -81,7 +89,7 @@
},
{
"id": "terms_conditions_full",
"translation": "Una mica de merda."
"translation": "<h2>Termes i condicions de NyaaPantsu</h2><h3>1. Termes</h3><p>Si accediu al lloc web ubicat a <a href='https://pantsu.cat'>https://pantsu.cat</a>, accepteu aquests termes del servei, totes les lleis i regulacions aplicables, i accepteu que sou responsable del compliment de totes les lleis locals aplicables. Si no esteu d'acord amb algun d'aquests termes, us és prohibit d'utilitzar o d'accedir a aquest lloc web. El material contingut en aquest lloc web està protegit per les lleis de marques i copyright aplicables.</p><h3>2. Exempció de responsabilitat</h3><ol type='a'><li>El material del lloc web de NyaaPantsu Lda es proporciona 'tal com és'. NyaaPantsu Lda no proporciona cap garantia, explícita o implícita, i per tant nega i s'eximeix de totes les altres garanties, incloent-hi, però sense limitació, les garanties implícites o les condicions de mercantibilitat, adequació per a un fi particular, o el no infringiment de la propietat intel·lectual o la violació d'altres drets.</li><li>De manera addicional, NyaaPantsu Lda no garanteix ni efectua cap representació pel que fa a la precisió, similitud de resultats, o confiabilitat en l'ús del material del seu lloc web o cap altra relació amb aquest material o cap dels llocs enllaçats en aquest lloc.</li></ol><h3>3. Limitacions</h3><p>En cap cas NyaaPantsu Lda o els seus proveïdors seran responsables dels danys (incloent-hi, sense limitació, danys per la pèrdua de dades o de beneficis, o a causa de la interrupció del negoci) que sorgeixin de l'ús o incapacitat d'ús del material del lloc web de NyaaPantsu Lda, fins i tot quan NyaaPantsu Lda o un representant autoritzat de NyaaPantsu Lda hagi estat notificat oralment o per escrit de la possibilitat d'aquests danys. Com que algunes jurisdiccions no permeten limitacions a les garanties implícites, o limitacions en la responsabilitat en els danys incidentals o conseqüencials, és possible que aquestes limitacions no us siguin d'aplicació.</p><h3>4. Precisió del material</h3><p>El material que apareix al lloc web de NyaaPantsu Lda pot incloure errors tècnics, tipogràfics o fotogràfics. NyaaPantsu Lda no garanteix que cap dels materials del seu lloc web siguin precisos, complets o actuals. NyaaPantsu Lda pot fer canvis al material contingut al seu lloc web en qualsevol moment i sense avís. No obstant això, NyaaPantsu Lda no estableix cap compromís d'actualitzar el material.</p><h3>5. Enllaços</h3><p>NyaaPantsu Lda no ha revisat tots els llocs web que s'enllacen al seu lloc web i no és responsable del contingut de cap d'aquests llocs enllaçats. La inclusió d'un enllaç no implica suport del lloc per part de NyaaPantsu Lda. L'ús dels llocs web enllaçats resta sota el propi risc de l'usuari.</p><h3>6. Modificacions</h3><p>NyaaPantsu Lda pot revisar aquests termes del servei del seu lloc web en qualsevol moment sense avís. Si utilitzeu aquest lloc web, accepteu la versió llavors actual d'aquests termes del servei.</p><h3>7. Llei aplicable</h3><p>Aquests termes i condicions són governats i s'interpreten sota les lleis de Portugal i accepteu irrevocablement sotmetre-us a la jurisdicció exclusiva dels tribunals d'aquest estat o ubicació.</p>"
},
{
"id": "remember_me",
@ -131,6 +139,10 @@
"id": "torrents",
"translation": "Torrents"
},
{
"id": "followers",
"translation": "Seguidors"
},
{
"id": "follow",
"translation": "Segueix"
@ -199,6 +211,10 @@
"id": "err_no_results",
"translation": "No s'han trobat resultats"
},
{
"id": "err_no_torrent_file",
"translation": "No s'ha trobat el fitxer torrent"
},
{
"id": "upload",
"translation": "Carrega"
@ -245,7 +261,7 @@
},
{
"id": "userstatus_member",
"translation": "Membres"
"translation": "Membre"
},
{
"id": "no_results_found",
@ -385,7 +401,7 @@
},
{
"id": "select_a_torrent_category",
"translation": "Escolliu una categoria de torrents"
"translation": "Escolliu una categoria de torrent"
},
{
"id": "anime",
@ -523,6 +539,10 @@
"id": "description_markdown_notice",
"translation": "Podeu utilitzar Markdown a les descripcions."
},
{
"id": "comment_markdown_notice",
"translation": "Podeu utilitzar Markdown als comentaris."
},
{
"id": "show_all",
"translation": "Mostra-ho tot"
@ -567,6 +587,10 @@
"id": "submit_a_comment_as_anonymous",
"translation": "Envieu un comentari com a Anònim"
},
{
"id": "torrent_no_comments",
"translation": "No hi ha cap comentari dels usuaris."
},
{
"id": "submit",
"translation": "Envia"
@ -607,6 +631,10 @@
"id": "userstatus_moderator",
"translation": "Moderador"
},
{
"id": "userstatus_uploader",
"translation": "Publicador"
},
{
"id": "api_token",
"translation": "Token de l'API"
@ -755,6 +783,10 @@
"id": "report_type",
"translation": "Tipus d'informe"
},
{
"id": "report_message",
"translation": "Missatge de l'informe"
},
{
"id": "illegal_content",
"translation": "Contingut il·legal"
@ -771,6 +803,14 @@
"id": "duplicate_deprecated",
"translation": "Duplicat / Caducat"
},
{
"id": "nsfw_content",
"translation": "Contingut per a adults"
},
{
"id": "other",
"translation": "Altres"
},
{
"id": "captcha",
"translation": "Captcha"
@ -809,12 +849,28 @@
},
{
"id": "clear_notifications",
"translation": "Neteja les notificacions"
"translation": "Neteja les notificacions llegides"
},
{
"id": "clear_all_notifications",
"translation": "Neteja totes les notificacions"
},
{
"id": "mark_notifications_as_read",
"translation": "Marca les notificacions com a llegides"
},
{
"id": "notifications_cleared",
"translation": "S'han netejat les notificacions!"
},
{
"id": "read_notifications_cleared",
"translation": "S'han netejat les notificacions llegides!"
},
{
"id": "notifications_read",
"translation": "Totes les notificacions s'han marcat com a llegides!"
},
{
"id": "my_notifications",
"translation": "Les meves notificacions"
@ -935,6 +991,10 @@
"id": "delete_report",
"translation": "Suprimeix l'informe"
},
{
"id": "delete_all_reports",
"translation": "Suprimeix tots els informes"
},
{
"id": "comment_deleted",
"translation": "S'ha suprimit el comentari!"
@ -1065,7 +1125,7 @@
},
{
"id": "change_settings",
"translation": "Canvia l'aparença o l'idioma"
"translation": "Canvia l'aparença / Configuració"
},
{
"id": "mascot",
@ -1083,6 +1143,10 @@
"id": "theme_none",
"translation": "Cap"
},
{
"id": "themes_classic",
"translation": "nyaa.se (Beta)"
},
{
"id": "upload_as_anon",
"translation": "Carrega'l anònimament"
@ -1307,6 +1371,18 @@
"id": "mascot_url",
"translation": "URL de la mascota"
},
{
"id": "alternating_color",
"translation": "Color alternat (i tipus de lletra sense negreta)"
},
{
"id": "old_nav",
"translation": "Navegació antiga"
},
{
"id": "old_nav_explanation",
"translation": "Mostra les categories principals i els números de pàgina a la part superior de la pàgina durant una cerca, com nyaa.se."
},
{
"id": "no_notifications",
"translation": "No hi ha notificacions"
@ -1327,10 +1403,6 @@
"id": "torrent_language",
"translation": "Idioma del torrent"
},
{
"id": "language_not_mandatory",
"translation": "L'idioma ja no és obligatori"
},
{
"id": "language_en-us_name",
"translation": "Anglès"
@ -1545,7 +1617,7 @@
},
{
"id": "error_numeric_valid",
"translation": "%s ha se ser un valor numèric vàlid"
"translation": "%s ha de ser un valor numèric vàlid"
},
{
"id": "error_number_valid",
@ -1623,6 +1695,10 @@
"id": "refine_search",
"translation": "Refina la cerca"
},
{
"id": "refine",
"translation": "Refina"
},
{
"id": "between",
"translation": "Entre"
@ -1643,18 +1719,10 @@
"id": "years",
"translation": "Anys"
},
{
"id": "refine",
"translation": "Refina"
},
{
"id": "large",
"translation": "gran."
},
{
"id": "old",
"translation": "antic"
},
{
"id": "optional",
"translation": "Opcional"
@ -1667,6 +1735,34 @@
"id": "show",
"translation": "Mostra"
},
{
"id": "sort_by",
"translation": "Ordena per"
},
{
"id": "ascending",
"translation": "Ascendent"
},
{
"id": "descending",
"translation": "Descendent"
},
{
"id": "quality",
"translation": "Qualitat"
},
{
"id": "exclude_user",
"translation": "Exclou"
},
{
"id": "from_user",
"translation": "De"
},
{
"id": "limit_torrent_count",
"translation": "Límit"
},
{
"id": "username_taken",
"translation": "El nom d'usuari ja està ocupat, podeu escollir: %s"
@ -1759,6 +1855,10 @@
"id": "error_content_type_post",
"translation": "Proporcioneu una capçalera Content-Type: application/json o multipart/form-data"
},
{
"id": "torrent_name",
"translation": "Nom del torrent"
},
{
"id": "torrent_name_invalid",
"translation": "El nom del torrent és invàlid"
@ -1847,10 +1947,26 @@
"id": "torrent_colors",
"translation": "Colors dels torrents"
},
{
"id": "faq_ads",
"translation": "Per què Pantsu té anuncis?"
},
{
"id": "faq_ads_explanation",
"translation": "No és una decisió que hàgim pres a la lleugera, i hem considerat profundament les objeccions que hi heu posat tots, però pensem que és l'única solució sostenible per finançar Pantsu i assegurar el seu funcionament continuar.<br/>Hem pensat molt en les possibles fonts de finançament, i cap altra opció que hàgim considerat s'acostava a ser capaç de finançar Pantsu.<br>Després de pensar-hi molt, hem decidit que fer servir anuncis d'a-ads és la millor opció per a nosaltres i per als nostres usuaris. Aquests anuncis són simples i poc intrusius, no interfereixen de cap manera amb l'experiència del lloc, i no inclouen cap tipus de rastreig."
},
{
"id": "torrent_preview",
"translation": "Previsualitza el torrent"
},
{
"id": "announcement",
"translation": "Anunci"
},
{
"id": "create_anouncement_success",
"translation": "Anunci creat satisfactòriament"
},
{
"id": "update_client_failed",
"translation": "L'actualització del client ha fallat!"
@ -1861,7 +1977,7 @@
},
{
"id": "update_client_panel",
"translation": "Actualitza el client"
"translation": "Actualitza un client"
},
{
"id": "create_client_success",
@ -1923,6 +2039,10 @@
"id": "remove",
"translation": "Suprimeix"
},
{
"id": "close",
"translation": "Tanca"
},
{
"id": "secret",
"translation": "Secret del client"
@ -1931,6 +2051,14 @@
"id": "torrent_age",
"translation": "fa {1} dies i {2} hores"
},
{
"id": "tag",
"translation": "Etiqueta"
},
{
"id": "torrent_tags",
"translation": "Etiquetes"
},
{
"id": "wrong_tag_type",
"translation": "El tipus d'etiqueta escollit no existeix"
@ -1943,6 +2071,14 @@
"id": "tagtype",
"translation": "Tipus d'etiqueta"
},
{
"id": "accepted_tags",
"translation": "Etiquetes acceptades"
},
{
"id": "recommended_tags",
"translation": "Etiquetes recomanades"
},
{
"id": "tagtype_anidbid",
"translation": "Identificador d'AniDB"
@ -1953,10 +2089,166 @@
},
{
"id": "tagtype_videoquality",
"translation": "Etiqueta de qualitat"
"translation": "Qualitat del vídeo"
},
{
"id": "torrent_tags",
"translation": "Etiquetes del torrent"
"id": "tagtype_dlsite",
"translation": "Lloc de descàrrega"
},
{
"id": "tagtype_vgmdbid",
"translation": "Identificador de VGMDB"
},
{
"id": "tagtype_tags",
"translation": "Etiquetes descriptives"
},
{
"id": "tagvalue_select",
"translation": "Selecciona..."
},
{
"id": "tagvalue_full_hd",
"translation": "1080p"
},
{
"id": "tagvalue_hd",
"translation": "720p"
},
{
"id": "tagvalue_sd",
"translation": "480p"
},
{
"id": "tagvalue_bluray",
"translation": "Bluray"
},
{
"id": "announcements",
"translation": "Anuncis"
},
{
"id": "message",
"translation": "Missatge"
},
{
"id": "duration",
"translation": "Durada (hores)"
},
{
"id": "update_annoucement_panel",
"translation": "Actualitza l'anunci"
},
{
"id": "create_annoucement_panel",
"translation": "Crea un anunci"
},
{
"id": "related_to",
"translation": "Relacionat amb"
},
{
"id": "expire",
"translation": "Caduca"
},
{
"id": "complement",
"translation": "Complement"
},
{
"id": "from",
"translation": "Des de"
},
{
"id": "to",
"translation": "fins a"
},
{
"id": "feed_types",
"translation": "Tipus de fonts: RSS (feed), RSS amb enllaços magnètics (magnet), Especificació Torznab (torznab), Especificació EZTV (eztv)"
},
{
"id": "append_query",
"translation": "Podeu afegir la vostra cerca al final de la URL de la font."
},
{
"id": "cookie_warning",
"translation": "Si feu servir aquest lloc web, n'accepteu l'ús de les galetes per personalitzar-ne el contingut.<br/>Aquest missatge s'amagarà quan torneu a carregar la pàgina."
},
{
"id": "pending_torrent",
"translation": "Tingueu paciència, s'està generant el fitxer torrent. Torneu-ho a provar d'aquí uns segons."
},
{
"id": "generating_torrent",
"translation": "S'està generant el fitxer torrent..."
},
{
"id": "generating_torrent_failed",
"translation": "No s'ha pogut generar el fitxer torrent"
},
{
"id": "enabled",
"translation": "Activat"
},
{
"id": "disabled",
"translation": "Desactivat"
},
{
"id": "reset_api_key",
"translation": "Reinicialitza la clau de l'API"
},
{
"id": "tag_error",
"translation": "No s'ha pogut afegir l'etiqueta, comproveu la connexió a internet i que hàgiu omplert tots els camps."
},
{
"id": "search_from_user",
"translation": "Cerca d'aquest usuari..."
},
{
"id": "usersearch_user_not_found",
"translation": "No s'ha trobat l'usuari \"%s\""
},
{
"id": "user_search_explanation",
"translation": "Cerqueu un usuari escrivint-ne el nom d'usuari a la casella de sota"
},
{
"id": "no_api_token",
"translation": "No hi ha token de l'API"
},
{
"id": "search_from_specific_user",
"translation": "Cerca de %s"
},
{
"id": "browsing_user_torrents",
"translation": "Cerca dels torrents de <a href=\"/user/%d/%s\">%s</a>"
},
{
"id": "hours_minutes_ago",
"translation": "fa {0} hores i {1} minuts"
},
{
"id": "days_hours_ago",
"translation": "fa {0} dies i {1} hores"
},
{
"id": "status",
"translation": "Estat"
},
{
"id": "event",
"translation": "Esdeveniment"
},
{
"id": "read",
"translation": "Llegit"
},
{
"id": "unread",
"translation": "No llegit"
}
]

Voir le fichier

@ -607,6 +607,10 @@
"id": "current_password",
"translation": "Current password"
},
{
"id": "default",
"translation": "Default"
},
{
"id": "role",
"translation": "Role"
@ -615,10 +619,6 @@
"id": "userstatus_banned",
"translation": "Banned"
},
{
"id": "default",
"translation": "Default"
},
{
"id": "userstatus_trusted",
"translation": "Trusted member"
@ -631,6 +631,10 @@
"id": "userstatus_moderator",
"translation": "Moderator"
},
{
"id": "userstatus_janitor",
"translation": "Janitor"
},
{
"id": "userstatus_uploader",
"translation": "Uploader"
@ -895,6 +899,10 @@
"id": "torrent_uploaded",
"translation": "torrent uploaded successfully!"
},
{
"id": "torrent_uploaded_locked",
"translation": "Your torrent has been uploaded but is locked because you are banned."
},
{
"id": "preferences",
"translation": "Preferences"
@ -988,9 +996,21 @@
"translation": "Torrent #%d from %s has been locked by %s."
},
{
"id": "torrent_blocked_by",
"id": "torrent_unblocked_by",
"translation": "Torrent #%d from %s has been unlocked by %s."
},
{
"id": "user_banned",
"translation": "User has been banned!"
},
{
"id": "user_banned",
"translation": "User has been unbanned!"
},
{
"id": "user_unbanned_by",
"translation": "User %s(%d) #%d has been unbanned by %s"
},
{
"id": "torrents_deleted",
"translation": "Torrents Deleted"
@ -1111,6 +1131,14 @@
"id": "torrent_block",
"translation": "Lock"
},
{
"id": "unban",
"translation": "Unban"
},
{
"id": "ban",
"translation": "Ban"
},
{
"id": "torrent_deleted_definitely",
"translation": "Torrent has been erased from the database!"
@ -2262,5 +2290,13 @@
{
"id": "unread",
"translation": "Unread"
},
{
"id": "moderation_guidelines",
"translation": "Moderation Guidelines"
},
{
"id": "guidelines",
"translation": "Guidelines"
}
]

Voir le fichier

@ -606,6 +606,10 @@
{
"id": "current_password",
"translation": "Mot de passe actuel"
},
{
"id": "default",
"translation": "Par défaut"
},
{
"id": "role",
@ -615,10 +619,6 @@
"id": "userstatus_banned",
"translation": "Banni"
},
{
"id": "default",
"translation": "Par défaut"
},
{
"id": "userstatus_trusted",
"translation": "Membre de confiance"
@ -631,9 +631,13 @@
"id": "userstatus_moderator",
"translation": "Modérateur"
},
{
"id": "userstatus_janitor",
"translation": "Janiteur"
},
{
"id": "userstatus_uploader",
"translation": "Uploader"
"translation": "Uploadeur"
},
{
"id": "api_token",
@ -763,6 +767,18 @@
"id": "no_files",
"translation": "Aucun fichier trouvé."
},
{
"id": "loading_file_list",
"translation": "Chargement de la liste des fichiers, la récupération des longues listes peut prendre un certain temps..."
},
{
"id": "torrent_filelist",
"translation": "Liste des fichiers du torrent"
},
{
"id": "back_to_torrent",
"translation": "Revenir à \"%s\""
},
{
"id": "uploaded_by",
"translation": "Uploadé par"
@ -883,6 +899,10 @@
"id": "torrent_uploaded",
"translation": "Le torrent a été uploadé avec succès !"
},
{
"id": "torrent_uploaded_locked",
"translation": "Le torrent a été uploadé mais est actuellement bloqué en raison de votre bannissement."
},
{
"id": "preferences",
"translation": "Préférences"
@ -976,9 +996,25 @@
"translation": "Le torrent n° %s de %s a été bloqué par %s."
},
{
"id": "torrent_blocked_by",
"id": "torrent_unblocked_by",
"translation": "Le torrent n° %s de %s a été débloqué par %s."
},
{
"id": "user_banned",
"translation": "L'utilisateur a été banni !"
},
{
"id": "user_banned_by",
"translation": "L'utilisateur %s(%d) #%d a été banni par %s."
},
{
"id": "user_unbanned",
"translation": "L'utilisateur a été débanni !"
},
{
"id": "user_unbanned_by",
"translation": "L'utilisateur %s(%d) #%d a été débanni par %s."
},
{
"id": "torrents_deleted",
"translation": "Torrents supprimés"
@ -1099,6 +1135,14 @@
"id": "torrent_block",
"translation": "Bloquer"
},
{
"id": "unban",
"translation": "Débannir"
},
{
"id": "ban",
"translation": "Bannir"
},
{
"id": "torrent_deleted_definitely",
"translation": "Le torrent a été effacé de la base de données."
@ -1929,7 +1973,7 @@
},
{
"id": "remux",
"translation": "Remux de la version originale d'un autre uploader"
"translation": "Remux de la version originale d'un autre uploadeur"
},
{
"id": "reupload",
@ -2250,5 +2294,13 @@
{
"id": "unread",
"translation": "Non lu"
},
{
"id": "moderation_guidelines",
"translation": "Directives de modération"
},
{
"id": "guidelines",
"translation": "Directives"
}
]

Voir le fichier

@ -537,11 +537,11 @@
},
{
"id": "description_markdown_notice",
"translation": "説明文には MarkDown 記法を使うことができます。"
"translation": "説明文には Markdown 記法を使うことができます。"
},
{
"id": "comment_markdown_notice",
"translation": "コメントには MarkDown 記法を使うことができます。"
"translation": "コメントには Markdown 記法を使うことができます。"
},
{
"id": "show_all",
@ -607,6 +607,10 @@
"id": "current_password",
"translation": "現在のパスワード"
},
{
"id": "default",
"translation": "デフォルト"
},
{
"id": "role",
"translation": "役割"
@ -615,10 +619,6 @@
"id": "userstatus_banned",
"translation": "BAN"
},
{
"id": "default",
"translation": "デフォルト"
},
{
"id": "userstatus_trusted",
"translation": "高信頼アカウント"
@ -631,6 +631,10 @@
"id": "userstatus_moderator",
"translation": "モデレーター"
},
{
"id": "userstatus_janitor",
"translation": "管理人"
},
{
"id": "userstatus_uploader",
"translation": "アップロード者"
@ -883,6 +887,10 @@
"id": "torrent_uploaded",
"translation": "Torrent は正常にアップロードされました。"
},
{
"id": "torrent_uploaded_locked",
"translation": "Torrent はアップロードされましたが、あなたが BAN されているためロック状態になっています。"
},
{
"id": "preferences",
"translation": "カスタム設定"
@ -976,9 +984,21 @@
"translation": "Torrent #%s (%s アップロード) は %s によってロックされました。"
},
{
"id": "torrent_blocked_by",
"id": "torrent_unblocked_by",
"translation": "Torrent #%s (%s アップロード) は %s によってロック解除されました。"
},
{
"id": "user_banned",
"translation": "ユーザーは BAN されました。"
},
{
"id": "user_banned",
"translation": "ユーザーは BAN 解除されました。"
},
{
"id": "user_unbanned_by",
"translation": "ユーザー %s (%d) #%d は %s によって BAN 解除されました。"
},
{
"id": "torrents_deleted",
"translation": "Torrent が削除されました"
@ -1099,6 +1119,14 @@
"id": "torrent_block",
"translation": "ロック"
},
{
"id": "unban",
"translation": "BAN 解除"
},
{
"id": "ban",
"translation": "BAN"
},
{
"id": "torrent_deleted_definitely",
"translation": "Torrent がデータベースから削除されました。"
@ -1723,10 +1751,6 @@
"id": "large",
"translation": " "
},
{
"id": "old",
"translation": "前"
},
{
"id": "optional",
"translation": "任意"
@ -1813,7 +1837,7 @@
},
{
"id": "elevating_user_error",
"translation": "モデレーターへのステータス格は禁止されています"
"translation": "モデレーターへのステータス格は禁止されています"
},
{
"id": "parse_error_line",
@ -1967,6 +1991,10 @@
"id": "announcement",
"translation": "お知らせ"
},
{
"id": "create_anouncement_success",
"translation": "正常にお知らせが作成されました。"
},
{
"id": "update_client_failed",
"translation": "クライアントの更新に失敗しました。"
@ -2250,5 +2278,13 @@
{
"id": "unread",
"translation": "未読"
},
{
"id": "moderation_guidelines",
"translation": "モデレーション ガイドライン"
},
{
"id": "guidelines",
"translation": "ガイドライン"
}
]

Voir le fichier

@ -281,15 +281,15 @@
},
{
"id": "future_not_looking_good",
"translation": "Будущие перспективы для nyaa выглядят не очень хорошо. (Он мертв)"
"translation": "Будущие перспективы для nyaa выглядят не очень хорошо. (Он мёртв)"
},
{
"id": "recovery_effort",
"translation": "Идет процесс восстановления."
"translation": "Идёт процесс восстановления."
},
{
"id": "is_everything_lost",
"translation": "Все пропало?"
"translation": "Всё пропало?"
},
{
"id": "in_short_no",
@ -297,7 +297,7 @@
},
{
"id": "are_some_things_lost",
"translation": "Что-нибудь все же потерялось?"
"translation": "Что-нибудь всё же потерялось?"
},
{
"id": "answer_is_nyaa_db_lost",
@ -309,7 +309,7 @@
},
{
"id": "how_are_we_recovering",
"translation": "Как идет процесс восстановления?"
"translation": "Как идёт процесс восстановления?"
},
{
"id": "answer_how_are_we_recovering",
@ -329,7 +329,7 @@
},
{
"id": "answer_are_the_trackers_working",
"translation": "Даже если трекеры не работают, сиды все еще подключены к децентрализованной сети DHT. Пока файл находится в сети DHT, все должено работать как обычно."
"translation": "Даже если трекеры не работают, сиды всё ещё подключены к децентрализованной сети DHT. Пока файл находится в сети DHT, всё должно работать как обычно."
},
{
"id": "how_do_i_download_the_torrents",
@ -337,11 +337,11 @@
},
{
"id": "answer_how_do_i_download_the_torrents",
"translation": "Просто используйте <b>Magnet-ссылку</b>. Она будет использоваться вашим клиентом BitTorrent для поиска файла в сети DHT, и он должен загрузиться просто отлично."
"translation": "Просто используйте <b>Магнет-ссылку</b>. Она будет использоваться вашим клиентом BitTorrent для поиска файла в сети DHT, и он должен загрузиться просто отлично."
},
{
"id": "magnet_link_should_look_like",
"translation": "Magnet-ссылка должна выглядеть так:"
"translation": "Магнет-ссылка должна выглядеть так:"
},
{
"id": "which_trackers_do_you_recommend",
@ -349,7 +349,7 @@
},
{
"id": "answer_which_trackers_do_you_recommend",
"translation": "У нас теперь есть собственный трекер uw0.xyz, добавьте его в начало списка перед загрузкой. Вам стоит еще добавить эти, просто на случай, если что-то пойдет не так."
"translation": "У нас теперь есть собственный трекер uw0.xyz, добавьте его в начало списка перед загрузкой. Вам стоит еще добавить эти, просто на случай, если что-то пойдёт не так."
},
{
"id": "how_can_i_help",
@ -381,7 +381,7 @@
},
{
"id": "magnet_link",
"translation": "Magnet-ссылка"
"translation": "Магнет-ссылка"
},
{
"id": "all_categories",
@ -549,7 +549,7 @@
},
{
"id": "hash",
"translation": "Хэш"
"translation": "Хеш"
},
{
"id": "description",
@ -621,7 +621,7 @@
},
{
"id": "profile_updated",
"translation": "Ваш профиль был успешно обновлен!"
"translation": "Ваш профиль был успешно обновлён!"
},
{
"id": "delete_account",
@ -633,7 +633,7 @@
},
{
"id": "delete_success",
"translation": "Аккаунт успешно удален!"
"translation": "Аккаунт успешно удалён!"
},
{
"id": "moderation",
@ -761,7 +761,7 @@
},
{
"id": "illegal_content",
"translation": "Запрещенный контент"
"translation": "Запрещённый контент"
},
{
"id": "spam_garbage",
@ -893,7 +893,7 @@
},
{
"id": "no_move_location_selected",
"translation": "Thou has't to telleth whither thee wanteth to moveth thy selection!"
"translation": "Вы должны указать, куда вы хотите переместить свой выбор!"
},
{
"id": "select_one_element",
@ -1173,7 +1173,7 @@
},
{
"id": "delete_reports_with_torrents",
"translation": "Вы хотите удалить отчеты по выбранным торрентам?"
"translation": "Вы хотите удалить отчёты по выбранным торрентам?"
},
{
"id": "with_st",
@ -1181,27 +1181,27 @@
},
{
"id": "and_reports",
"translation": " and reports"
"translation": " и отчёты"
},
{
"id": "reports",
"translation": "reports"
"translation": "отчёты"
},
{
"id": "lock",
"translation": "lock"
"translation": "блок"
},
{
"id": "status_js",
"translation": "status: {0}"
"translation": "статус: {0}"
},
{
"id": "owner_id_js",
"translation": "owner_id: {0}"
"translation": "id_владельца: {0}"
},
{
"id": "category_js",
"translation": "category: {0}"
"translation": "категория: {0}"
},
{
"id": "no_changes",
@ -1321,7 +1321,7 @@
},
{
"id": "alternating_color",
"translation": "Переменный цвет (и не-жирный шрифт)"
"translation": "Переменный цвет (и нежирный шрифт)"
},
{
"id": "no_notifications",
@ -1565,7 +1565,7 @@
},
{
"id": "error_number_valid",
"translation": "%s должно быть дейстивительным числом"
"translation": "%s должно быть действительным числом"
},
{
"id": "error_hexadecimal_valid",
@ -1729,7 +1729,7 @@
},
{
"id": "password_error_generating",
"translation": "Ошибка генерации хэша для вашего пароля"
"translation": "Ошибка генерации хеша для вашего пароля"
},
{
"id": "permission_delete_error",
@ -1781,7 +1781,7 @@
},
{
"id": "error_api_token",
"translation": "Error API токен не существует"
"translation": "Ошибка API, токен не существует"
},
{
"id": "uploads_disabled",
@ -1837,11 +1837,11 @@
},
{
"id": "torrent_magnet_invalid",
"translation": "Magnet-ссылка не может быть спарсена, пожалуйста, проверьте её"
"translation": "Магнет-ссылка не может быть спарсена, пожалуйста, проверьте её"
},
{
"id": "torrent_hash_invalid",
"translation": "Неверный хэш торрента"
"translation": "Неверный хеш торрента"
},
{
"id": "torrent_plus_magnet",
@ -1849,7 +1849,7 @@
},
{
"id": "torrent_file_invalid",
"translation": "Неверный torrent-файл"
"translation": "Неверный торрент-файл"
},
{
"id": "torrent_uri_invalid",
@ -1937,15 +1937,15 @@
},
{
"id": "grant_types",
"translation": "Grant Types"
"translation": "Типы разрешений"
},
{
"id": "response_types",
"translation": "Response Types"
"translation": "Типы ответов"
},
{
"id": "scope",
"translation": "Scopes"
"translation": "Области"
},
{
"id": "owner",
@ -2105,7 +2105,7 @@
},
{
"id": "feed_types",
"translation": "Типы фидов: RSS(feed), RSS с Magnet-ссылками(magnet), Torznab Spec(torznab), EZTV Spec(eztv)"
"translation": "Типы фидов: RSS(feed), RSS с магнет-ссылками(magnet), Torznab Spec(torznab), EZTV Spec(eztv)"
},
{
"id": "append_query",

Voir le fichier

@ -39,25 +39,25 @@ func stringIsASCII(input string) bool {
// ByQueryNoUser : search torrents according to request without user
func ByQueryNoUser(c *gin.Context, pagenum int) (search TorrentParam, tor []models.Torrent, count int, err error) {
search, tor, count, err = ByQuery(c, pagenum, false, false, false)
search, tor, count, err = ByQuery(c, pagenum, false, false, false, false)
return
}
// ByQueryWithUser : search torrents according to request with user
func ByQueryWithUser(c *gin.Context, pagenum int) (search TorrentParam, tor []models.Torrent, count int, err error) {
search, tor, count, err = ByQuery(c, pagenum, true, false, false)
search, tor, count, err = ByQuery(c, pagenum, true, false, false, true)
return
}
// ByQueryDeleted : search deleted torrents according to request with user and count
func ByQueryDeleted(c *gin.Context, pagenum int) (search TorrentParam, tor []models.Torrent, count int, err error) {
search, tor, count, err = ByQuery(c, pagenum, true, true, false)
search, tor, count, err = ByQuery(c, pagenum, true, true, false, true)
return
}
// ByQueryNoHidden : search torrents and filter those hidden
func ByQueryNoHidden(c *gin.Context, pagenum int) (search TorrentParam, tor []models.Torrent, count int, err error) {
search, tor, count, err = ByQuery(c, pagenum, false, false, true)
search, tor, count, err = ByQuery(c, pagenum, false, false, true, false)
return
}
@ -66,11 +66,12 @@ func ByQueryNoHidden(c *gin.Context, pagenum int) (search TorrentParam, tor []mo
// elasticsearch always provide a count to how many hits
// ES doesn't store users
// deleted is unused because es doesn't index deleted torrents
func ByQuery(c *gin.Context, pagenum int, withUser bool, deleted bool, hidden bool) (TorrentParam, []models.Torrent, int, error) {
func ByQuery(c *gin.Context, pagenum int, withUser bool, deleted bool, hidden bool, locked bool) (TorrentParam, []models.Torrent, int, error) {
var torrentParam TorrentParam
torrentParam.FromRequest(c)
torrentParam.Offset = uint32(pagenum)
torrentParam.Hidden = hidden
torrentParam.Locked = locked
torrentParam.Full = withUser
torrentParam.Deleted = deleted
@ -106,6 +107,6 @@ func ByQuery(c *gin.Context, pagenum int, withUser bool, deleted bool, hidden bo
}
// AuthorizedQuery return a seach byquery according to the bool. If false, it doesn't look for hidden torrents, else it looks for every torrents
func AuthorizedQuery(c *gin.Context, pagenum int, authorized bool) (TorrentParam, []models.Torrent, int, error) {
return ByQuery(c, pagenum, true, false, !authorized)
func AuthorizedQuery(c *gin.Context, pagenum int, authorized bool, locked bool) (TorrentParam, []models.Torrent, int, error) {
return ByQuery(c, pagenum, true, false, !authorized, locked)
}

Voir le fichier

@ -26,6 +26,7 @@ type TorrentParam struct {
Full bool // True means load all members
Order bool // True means ascending
Hidden bool // True means filter hidden torrents
Locked bool // False means filter locked torrents
Deleted bool // False means filter deleted torrents
Status Status
Sort SortMode
@ -71,7 +72,7 @@ func (p *TorrentParam) Identifier() string {
tags += p.VideoQuality
dbids := fmt.Sprintf("%d%d%d%s", p.AnidbID, p.VndbID, p.VgmdbID, p.Dlsite)
identifier := fmt.Sprintf("%s%s%s%d%d%d%d%d%d%d%s%s%s%d%s%s%s%t%t%t%t", p.NameLike, p.NotNull, languages, p.Max, p.Offset, p.FromID, p.MinSize, p.MaxSize, p.Status, p.Sort, dbids, p.FromDate, p.ToDate, p.UserID, ids, cats, tags, p.Full, p.Order, p.Hidden, p.Deleted)
identifier := fmt.Sprintf("%s%s%s%d%d%d%d%d%d%d%s%s%s%d%s%s%s%t%t%t%t%t", p.NameLike, p.NotNull, languages, p.Max, p.Offset, p.FromID, p.MinSize, p.MaxSize, p.Status, p.Sort, dbids, p.FromDate, p.ToDate, p.UserID, ids, cats, tags, p.Full, p.Order, p.Hidden, p.Locked, p.Deleted)
return base64.URLEncoding.EncodeToString([]byte(identifier))
}
@ -251,8 +252,11 @@ func (p *TorrentParam) toESQuery(c *gin.Context) *Query {
if p.Status != ShowAll {
query.Append(p.Status.ToESQuery())
} else if !p.Locked {
query.Append(fmt.Sprintf("!(status:%d)", 5))
}
if p.FromID != 0 {
query.Append("id:>" + strconv.FormatInt(int64(p.FromID), 10))
}
@ -406,7 +410,10 @@ func (p *TorrentParam) toDBQuery(c *gin.Context) *Query {
}
if p.Status != 0 {
query.Append(p.Status.ToDBQuery())
} else if !p.Locked {
query.Append("status IS NOT ?", 5)
}
if len(p.NotNull) > 0 {
query.Append(p.NotNull)
}

Voir le fichier

@ -12,13 +12,13 @@ import (
func TestTorrentParam_Identifier(t *testing.T) {
torrentParam := &TorrentParam{}
assert := assert.New(t)
assert.Equal("MDAwMDAwMDAwMDBmYWxzZWZhbHNlZmFsc2VmYWxzZQ==", torrentParam.Identifier(), "It should be empty")
assert.Equal("MDAwMDAwMDAwMDBmYWxzZWZhbHNlZmFsc2VmYWxzZWZhbHNl", torrentParam.Identifier(), "It should be empty")
torrentParam = &TorrentParam{
NameLike: "test",
NotNull: "IS NULL",
Hidden: false,
}
assert.Equal("dGVzdElTIE5VTEwwMDAwMDAwMDAwMGZhbHNlZmFsc2VmYWxzZWZhbHNl", torrentParam.Identifier(), "It should be empty")
assert.Equal("dGVzdElTIE5VTEwwMDAwMDAwMDAwMGZhbHNlZmFsc2VmYWxzZWZhbHNlZmFsc2U=", torrentParam.Identifier(), "It should be empty")
}
func TestTorrentParam_FromRequest(t *testing.T) {
@ -57,14 +57,14 @@ func TestTorrentParam_ToESQuery(t *testing.T) {
Test TorrentParam
Expected string
}{
{TorrentParam{}, ""},
{TorrentParam{NameLike: "lol"}, ""},
{TorrentParam{NameLike: "lol", FromID: 12}, "id:>12"},
{TorrentParam{NameLike: "lol", FromID: 12, FromDate: DateFilter("2017-08-01"), ToDate: DateFilter("2017-08-05")}, "id:>12 date: [2017-08-01 2017-08-05]"},
{TorrentParam{NameLike: "lol", FromID: 12, ToDate: DateFilter("2017-08-05")}, "id:>12 date: [* 2017-08-05]"},
{TorrentParam{NameLike: "lol", FromID: 12, FromDate: DateFilter("2017-08-01")}, "id:>12 date: [2017-08-01 *]"},
{TorrentParam{NameLike: "lol", FromID: 12, Category: Categories{&Category{3, 12}}}, "(category: 3 AND sub_category: 12) id:>12"},
{TorrentParam{NameLike: "lol", FromID: 12, Category: Categories{&Category{3, 12}, &Category{3, 12}}}, "((category: 3 AND sub_category: 12) OR (category: 3 AND sub_category: 12)) id:>12"},
{TorrentParam{}, "!(status:5)"},
{TorrentParam{NameLike: "lol"}, "!(status:5)"},
{TorrentParam{NameLike: "lol", FromID: 12}, "!(status:5) id:>12"},
{TorrentParam{NameLike: "lol", FromID: 12, FromDate: DateFilter("2017-08-01"), ToDate: DateFilter("2017-08-05")}, "!(status:5) id:>12 date: [2017-08-01 2017-08-05]"},
{TorrentParam{NameLike: "lol", FromID: 12, ToDate: DateFilter("2017-08-05")}, "!(status:5) id:>12 date: [* 2017-08-05]"},
{TorrentParam{NameLike: "lol", FromID: 12, FromDate: DateFilter("2017-08-01")}, "!(status:5) id:>12 date: [2017-08-01 *]"},
{TorrentParam{NameLike: "lol", FromID: 12, Category: Categories{&Category{3, 12}}}, "(category: 3 AND sub_category: 12) !(status:5) id:>12"},
{TorrentParam{NameLike: "lol", FromID: 12, Category: Categories{&Category{3, 12}, &Category{3, 12}}}, "((category: 3 AND sub_category: 12) OR (category: 3 AND sub_category: 12)) !(status:5) id:>12"},
}
for _, test := range tests {

Voir le fichier

@ -174,6 +174,9 @@ func UpdateTorrent(r *torrentValidator.UpdateRequest, t *models.Torrent, current
} else if currentUser.IsTrusted() {
status = models.TorrentStatusTrusted
}
if status != t.Status && status != models.TorrentStatusBlocked {
t.DeletedAt = nil
}
t.Status = status
t.Hidden = r.Update.Hidden