Merge branch 'dev' into filelist-fetching
Cette révision appartient à :
révision
0cf75e345a
|
@ -0,0 +1,30 @@
|
|||
|
||||
**You have been visited by the CoC(K)**
|
||||
|
||||
|
||||
_.+._
|
||||
(^\/^\/^)
|
||||
\@☆@☆@/
|
||||
CoC(k) {_____}
|
||||
Code Of Conduct Killer _oOPPYbo.
|
||||
_,ooO8O' `Ob
|
||||
_,ooOPP"' Ob dO
|
||||
_oooOP"'' `Oo. ,O[
|
||||
Ob _,ooOPP'' `YYboOP
|
||||
`O[ _ooOP"'' _,oOPP"'
|
||||
YOooooOP' _ooOP"'
|
||||
'' ,ooOP''
|
||||
,odPP''
|
||||
_,oOP'
|
||||
ooOP"'
|
||||
_oOP'o
|
||||
,OP YOL
|
||||
,O. ,OP Yb contribute code or you're a racist
|
||||
dO' " Yb get offended as a responsible adult
|
||||
]O. dO spread this like happy herpes
|
||||
Ob _,o. dOP
|
||||
`Ooo___ooOP'`YbooodPP just imagine what would happen
|
||||
'`"""'' `''' if we all decided to understand
|
||||
|
||||
|
||||
Sweet blessing be upon you but **ONLY** if comment `ebin` to this commit.
|
|
@ -39,6 +39,7 @@ func getTorrentList(c *gin.Context) (torrents []models.Torrent, createdAsTime ti
|
|||
title = "Sukebei Pantsu"
|
||||
}
|
||||
|
||||
|
||||
pagenum := 1
|
||||
if page == "" && offset > 0 { // first page for offset is 0
|
||||
pagenum = offset + 1
|
||||
|
@ -86,7 +87,12 @@ func getTorrentList(c *gin.Context) (torrents []models.Torrent, createdAsTime ti
|
|||
user = 0
|
||||
}
|
||||
|
||||
_, torrents, _, err = search.AuthorizedQuery(c, pagenum, currentUser.CurrentOrJanitor(uint(user)), currentUser.CurrentOrJanitor(uint(user)))
|
||||
var searchParam search.TorrentParam
|
||||
searchParam, torrents, _, err = search.AuthorizedQuery(c, pagenum, currentUser.CurrentOrJanitor(uint(user)), currentUser.CurrentOrJanitor(uint(user)))
|
||||
|
||||
if searchParam.NameLike != "" {
|
||||
title += " - " + searchParam.NameLike
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -9,11 +9,10 @@ import (
|
|||
"github.com/NyaaPantsu/nyaa/controllers/router"
|
||||
"github.com/NyaaPantsu/nyaa/models/comments"
|
||||
"github.com/NyaaPantsu/nyaa/models/torrents"
|
||||
"github.com/NyaaPantsu/nyaa/models"
|
||||
"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"
|
||||
)
|
||||
|
||||
|
@ -39,6 +38,9 @@ func PostCommentHandler(c *gin.Context) {
|
|||
if currentUser.IsBanned() {
|
||||
messages.AddErrorT("errors", "account_banned")
|
||||
}
|
||||
if torrent.Status == models.TorrentStatusBlocked && !currentUser.CurrentOrJanitor(torrent.UploaderID) {
|
||||
messages.AddErrorT("errors", "torrent_locked")
|
||||
}
|
||||
content := sanitize.Sanitize(c.PostForm("comment"), "comment")
|
||||
|
||||
userID := currentUser.ID
|
||||
|
@ -60,12 +62,5 @@ func PostCommentHandler(c *gin.Context) {
|
|||
}
|
||||
}
|
||||
|
||||
captchaID := ""
|
||||
//Generate a captcha
|
||||
if currentUser.NeedsCaptcha() {
|
||||
captchaID = captcha.GetID()
|
||||
}
|
||||
|
||||
folder := filelist.FileListToFolder(torrent.FileList, "root")
|
||||
templates.Torrent(c, torrent.ToJSON(), folder, captchaID)
|
||||
ViewHandler(c)
|
||||
}
|
||||
|
|
|
@ -313,7 +313,11 @@ func (t *Torrent) ToJSON() TorrentJSON {
|
|||
}
|
||||
for _, c := range t.Comments {
|
||||
if c.User != nil {
|
||||
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})
|
||||
role := c.User.GetRole()
|
||||
if t.UploaderID == c.User.ID && !c.User.IsBanned() {
|
||||
role = "userstatus_uploader"
|
||||
}
|
||||
commentsJSON = append(commentsJSON, CommentJSON{Username: c.User.Username, UserID: int(c.User.ID), UserStatus: role, Content: sanitize.MarkdownToHTML(c.Content), Date: c.CreatedAt.UTC(), UserAvatar: c.User.MD5})
|
||||
} else {
|
||||
commentsJSON = append(commentsJSON, CommentJSON{})
|
||||
}
|
||||
|
|
|
@ -37,13 +37,11 @@ func NewTorrentEvent(user *models.User, torrent *models.Torrent) error {
|
|||
url := "/view/" + strconv.FormatUint(uint64(torrent.ID), 10)
|
||||
if user.ID > 0 && config.Get().Users.DefaultUserSettings["new_torrent"] { // If we are a member and notifications for new torrents are enabled
|
||||
user.GetFollowers() // We populate the liked field for users
|
||||
if len(user.Followers) > 0 { // If we are followed by at least someone
|
||||
for _, follower := range user.Followers {
|
||||
follower.ParseSettings() // We need to call it before checking settings
|
||||
if follower.Settings.Get("new_torrent") {
|
||||
T, _, _ := publicSettings.TfuncAndLanguageWithFallback(follower.Language, follower.Language) // We need to send the notification to every user in their language
|
||||
notifications.NotifyUser(&follower, torrent.Identifier(), fmt.Sprintf(T("new_torrent_uploaded"), torrent.Name, user.Username), url, follower.Settings.Get("new_torrent_email"))
|
||||
}
|
||||
for _, follower := range user.Followers {
|
||||
follower.ParseSettings() // We need to call it before checking settings
|
||||
if follower.Settings.Get("new_torrent") {
|
||||
T, _, _ := publicSettings.TfuncAndLanguageWithFallback(follower.Language, follower.Language) // We need to send the notification to every user in their language
|
||||
notifications.NotifyUser(&follower, torrent.Identifier(), fmt.Sprintf(T("new_torrent_uploaded"), torrent.Name, user.Username), url, follower.Settings.Get("new_torrent_email"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -260,17 +260,19 @@ func (u *User) ToJSON() UserJSON {
|
|||
}
|
||||
|
||||
// GetLikings : Gets who is followed by the user
|
||||
func (u *User) GetLikings() {
|
||||
func (u *User) GetLikings() int {
|
||||
var liked []User
|
||||
ORM.Joins("JOIN user_follows on user_follows.following=?", u.ID).Where("users.user_id = user_follows.user_id").Group("users.user_id").Find(&liked)
|
||||
u.Likings = liked
|
||||
return len(u.Likings)
|
||||
}
|
||||
|
||||
// GetFollowers : Gets who is following the user
|
||||
func (u *User) GetFollowers() {
|
||||
func (u *User) GetFollowers() int {
|
||||
var likings []User
|
||||
ORM.Joins("JOIN user_follows on user_follows.user_id=?", u.ID).Where("users.user_id = user_follows.following").Group("users.user_id").Find(&likings)
|
||||
u.Followers = likings
|
||||
return len(u.Followers)
|
||||
}
|
||||
|
||||
// SetFollow : Makes a user follow another
|
||||
|
@ -278,6 +280,7 @@ func (u *User) SetFollow(follower *User) {
|
|||
if follower.ID > 0 && u.ID > 0 {
|
||||
var userFollows = UserFollows{UserID: u.ID, FollowerID: follower.ID}
|
||||
ORM.Create(&userFollows)
|
||||
u.Likings = append(u.Likings, *follower)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -286,6 +289,15 @@ func (u *User) RemoveFollow(follower *User) {
|
|||
if follower.ID > 0 && u.ID > 0 {
|
||||
var userFollows = UserFollows{UserID: u.ID, FollowerID: follower.ID}
|
||||
ORM.Delete(&userFollows)
|
||||
for i, followr := range u.Likings {
|
||||
if followr.ID == follower.ID {
|
||||
u.Likings[i] = u.Likings[len(u.Likings)-1]
|
||||
// The very last follower will take the place of the one that is getting deleted in the array
|
||||
u.Likings = u.Likings[:len(u.Likings)-1]
|
||||
// We now proceed to delete the very last array element since it got copied to another position
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -452,8 +452,12 @@ select.form-input {
|
|||
margin-bottom: 0;
|
||||
width: 85px!important;
|
||||
}
|
||||
.refine-container-2 [name="hash"] {
|
||||
float: right;
|
||||
width: 187px!important;
|
||||
}
|
||||
.refine-date {
|
||||
width: 98px!important;
|
||||
width: 135px!important;
|
||||
}
|
||||
|
||||
.categories a {
|
||||
|
@ -462,7 +466,7 @@ select.form-input {
|
|||
padding: 10px 5px;
|
||||
}
|
||||
|
||||
#announce {
|
||||
.announce {
|
||||
margin-bottom: 4px;
|
||||
padding: 7px 10px;
|
||||
background-color: #D9EDF7;
|
||||
|
@ -470,7 +474,7 @@ select.form-input {
|
|||
border-radius: 7px;
|
||||
}
|
||||
|
||||
#announce:before {
|
||||
.announce:before {
|
||||
content: "!";
|
||||
vertical-align: middle;
|
||||
float: left;
|
||||
|
@ -478,6 +482,13 @@ select.form-input {
|
|||
font-size: 2.2em;
|
||||
font-weight: bold;
|
||||
}
|
||||
.announcement-content :first-child {
|
||||
margin-top: 0;
|
||||
}
|
||||
|
||||
.announcement-content :last-child {
|
||||
margin-bottom: 0;
|
||||
}
|
||||
|
||||
.results {
|
||||
padding: 0!important;
|
||||
|
@ -857,6 +868,9 @@ html, body {
|
|||
float: none!important;
|
||||
max-width: none;
|
||||
}
|
||||
.refine-container-2 [name="hash"] {
|
||||
float: none;
|
||||
}
|
||||
.upload-form-table .table-checkboxes {
|
||||
padding: 3px 0!important;
|
||||
width: 100%;
|
||||
|
|
|
@ -767,14 +767,9 @@ span.tag {
|
|||
.torrent-info-data #subscribe-link::before, .torrent-info-data #subscribe-link:: after {
|
||||
color: #111111;
|
||||
}
|
||||
.content > p:first-child+div.centered+div.refine+div #reportPopup {
|
||||
top: 145px;
|
||||
}
|
||||
.content > p:first-child+div#announce+div.refine+div #reportPopup {
|
||||
top: 110px;
|
||||
}
|
||||
.content > div#announce:first-child+div.refine+div #reportPopup {
|
||||
top: 65px;
|
||||
|
||||
.box {
|
||||
position: relative;
|
||||
}
|
||||
#reportPopup {
|
||||
text-decoration: underline dotted;
|
||||
|
@ -783,8 +778,8 @@ span.tag {
|
|||
background: none;
|
||||
color: #106655!important;
|
||||
position: absolute;
|
||||
top: 103px;
|
||||
right: 11px;
|
||||
top: 6px;
|
||||
right: 0;
|
||||
}
|
||||
.comment-content :first-child {
|
||||
margin-top: 5px;
|
||||
|
|
|
@ -163,7 +163,7 @@ td.tr-le, .error-text {
|
|||
background-size: 100%;
|
||||
}
|
||||
|
||||
#announce {
|
||||
.announce {
|
||||
color: #3a4249;
|
||||
background-color: #fff5e7;
|
||||
border-color: #ecd2ae;
|
||||
|
|
|
@ -238,7 +238,7 @@ a.form-input[class*="btn"]:hover {
|
|||
background: #cc4f4f;
|
||||
}
|
||||
|
||||
#announce {
|
||||
.announce {
|
||||
color: #3a4249;
|
||||
background-color: #F4E0C9;
|
||||
border-color: #ae875b;
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<form style="text-align:left;padding-left:10px;padding-right:10px;" method="POST" action="{{ if Form.ID > 0}}?id={{ Form.ID }}{{end}}">
|
||||
<div class="form-group">
|
||||
<label for="message">{{ T("message")}}</label>
|
||||
<textarea name="message" id="message" class="form-input up-input" placeholder="{{ T("message")}}" required>{{Form.Message}}</textarea>
|
||||
<textarea name="message" id="message" class="form-input up-input markdown-container" placeholder="{{ T("message")}}" required>{{Form.Message}}</textarea>
|
||||
{{ yield errors(name="Message")}}
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -19,3 +19,7 @@
|
|||
</form>
|
||||
</div>
|
||||
{{end}}
|
||||
{{ block footer_js()}}
|
||||
<script type="text/javascript" src="{{ URL.Parse("/js/simplemde.min.js") }}"></script>
|
||||
<script type="text/javascript">new SimpleMDE({ element: document.getElementById("message"), spellChecker: false, showIcons: [ "strikethrough", "code", "table", "horizontal-rule" ] });</script>
|
||||
{{end}}
|
||||
|
|
|
@ -99,7 +99,7 @@ var deleteButtons = document.querySelectorAll("button.form-input.btn-red")
|
|||
e.preventDefault()
|
||||
if(needConfirmation && !confirm("Are you sure?")) {
|
||||
return
|
||||
} else if(!needConfirmation) {
|
||||
} else {
|
||||
var form = this.parentNode
|
||||
var formInputs = form.querySelectorAll('input')
|
||||
var query = ""
|
||||
|
|
|
@ -55,12 +55,12 @@ func NewSearchForm(c *gin.Context) SearchForm {
|
|||
ShowRefine: false,
|
||||
SizeType: sizeType,
|
||||
User: c.Query("user"),
|
||||
UserName: "",
|
||||
UserName: "",
|
||||
DateType: c.Query("dateType"),
|
||||
MinSize: c.Query("minSize"), // We need to overwrite the value here, since size are formatted
|
||||
MaxSize: c.Query("maxSize"), // We need to overwrite the value here, since size are formatted
|
||||
FromDate: c.Query("fromDate"), // We need to overwrite the value here, since we can have toDate instead and date are formatted
|
||||
ToDate: c.Query("toDate"), // We need to overwrite the value here, since date are formatted
|
||||
SearchURL: "/search",
|
||||
SearchURL: "/search",
|
||||
}
|
||||
}
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
{{ block content_body_base()}}
|
||||
{{ if isset(Infos["system"])}}
|
||||
{{ range Infos["system"]}}
|
||||
<div id="announce"><span style="font-weight:bold;">{{T("announcement")}}</span><br>{{ .|raw }}</div>
|
||||
<div class="announce"><b>{{T("announcement")}}</b><br><span class="announcement-content">{{ .|raw }}</span></div>
|
||||
{{ end }}
|
||||
{{ end }}
|
||||
{{ yield search_refine(url=URL.Parse(Search.SearchURL)) }}
|
||||
|
|
|
@ -55,7 +55,6 @@
|
|||
<input class="form-input refine-date" name="fromDate" type="text" value="{{Search.FromDate}}" placeholder="YYYY/MM/DD"/>
|
||||
{{ T("to")}}
|
||||
<input class="form-input refine-date spacing" size="7" name="toDate" type="text" value="{{Search.ToDate}}" placeholder="YYYY/MM/DD"/>
|
||||
{{ T("exclude_user") }}: <input type="text" name="nuserID" placeholder="UserID" value="" class="form-input refine-userid" style="width: 62px;">
|
||||
</span>
|
||||
<span class="form-refine" style="margin-bottom: 2px;">
|
||||
<span class="spacing">{{T("sort_by")}}</span>
|
||||
|
@ -71,6 +70,7 @@
|
|||
<option value="true">{{T("ascending")}}</option>
|
||||
<option value="false" {{if !Search.Order}}selected{{end}}>{{T("descending")}}</option>
|
||||
</select>
|
||||
{{ T("exclude_user") }}: <input type="text" name="nuserID" placeholder="UserID" value="" class="form-input refine-userid" style="width: 62px;">
|
||||
</span>
|
||||
</div>
|
||||
<div class="refine-container-2">
|
||||
|
@ -83,7 +83,7 @@
|
|||
{{end}}
|
||||
</select>
|
||||
<span style="margin: 0 5px;">Hash:</span>
|
||||
<input type="text" name="hash" placeholder="Torrent hash" class="form-input" value="" style="width: 218px!important">
|
||||
<input type="text" name="hash" placeholder="Torrent hash" class="form-input">
|
||||
</span>
|
||||
<span class="form-refine">
|
||||
<span class="spacing">Tags:</span>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{ extends "layouts/index_site" }}
|
||||
{{ import "layouts/partials/helpers/search" }}
|
||||
{{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 title()}}{{GenSearchName(Search, URL.String(), T)}}{{end}}
|
||||
{{block contclass()}}{{if User.IsModerator() }}content-admin{{end}}{{end}}
|
||||
{{block content_body()}}
|
||||
{{ if OldNav || Theme == "classic"}}
|
||||
|
|
|
@ -66,27 +66,6 @@
|
|||
<td class="table-input-label"><label for="desc">{{ T("torrent_description")}}</label></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>
|
||||
<td class="table-input">
|
||||
<div class="checkbox-container"><input disabled type="checkbox" value="" name="anidex_upload" id="anidex_upload" {{if User.AnidexAPIToken != ""}}checked disabled{{end}} class="form-torrent"/></div>
|
||||
<input disabled name="anidex_api" id="anidex_api" placeholder="Coming soon... (hopefully)" class="form-input up-input" type="text" value="{{User.AnidexAPIToken}}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="hidden">
|
||||
<td class="table-input-label"><label for="nyaasi_api">Upload to Nyaa.si:</label></td>
|
||||
<td class="table-input">
|
||||
<div class="checkbox-container"><input disabled type="checkbox" value="" name="nyaasi_upload" id="nyaasi_upload" {{if User.NyaasiAPIToken != ""}}checked disabled{{end}} class="form-torrent"/></div>
|
||||
<input disabled name="nyaasi_api" id="nyaasi_api" placeholder="Coming soon... (hopefully)" class="form-input up-input" type="text" value="{{User.NyaasiAPIToken}}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr class="hidden">
|
||||
<td class="table-input-label"><label for="tokyot_api">Upload to TokyoTosho:</label></td>
|
||||
<td class="table-input">
|
||||
<div class="checkbox-container"><input disabled type="checkbox" value="" name="tokyot_upload" id="tokyot_upload" {{if User.TokyoTAPIToken != ""}}checked disabled{{end}} class="form-torrent"/></div>
|
||||
<input disabled name="tokyot_api" id="tokyot_api" placeholder="Coming soon... (hopefully)" class="form-input up-input" type="text" value="{{User.TokyoTAPIToken }}"/>
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="table-input-label">{{ T("torrent_tags")}}:</td>
|
||||
<td class="table-input">
|
||||
|
|
|
@ -155,6 +155,23 @@
|
|||
</table>
|
||||
</div>
|
||||
<div class="torrent-buttons">
|
||||
{{ if User.IsModerator() }}
|
||||
<form enctype="multipart/form-data" method="POST" action="{{ if !Sukebei()}}{{Config.WebAddress.Sukebei}}/upload{{else}}{{Config.WebAddress.Nyaa}}/upload{{end}}" id="copy-torrent">
|
||||
{{ yield csrf_field()}}
|
||||
<input type="hidden" name="name" value="{{Torrent.Name}}">
|
||||
<input type="hidden" name="magnet" value="{{Torrent.Magnet}}">
|
||||
<input type="hidden" name="c" value="{{Torrent.Category}}_{{Torrent.SubCategory}}">
|
||||
<input type="hidden" name="desc" value="{{Torrent.Description}}">
|
||||
<input type="hidden" name="hidden" value="{{Torrent.Hidden}}">
|
||||
<input type="hidden" name="remake" value="{{Torrent.Status == 2}}">
|
||||
<input type="hidden" name="website_link" value="{{Torrent.WebsiteLink}}">
|
||||
<input type="hidden" name="filesize" value="{{Torrent.Filesize}}">
|
||||
{{ range _, lang := Torrent.Languages}}
|
||||
<input type="hidden" name="languages" value="{{lang}}">
|
||||
{{end}}
|
||||
<input type="submit" class="form-input btn-blue" style="float: right;" value="Upload to {{if Sukebei()}}Nyaa{{else}}Sukebei{{end}}">
|
||||
</form>
|
||||
{{end}}
|
||||
<a href="{{Torrent.Magnet}}" class="form-input btn-green download" style="float:left;height: auto;margin-right: 0.5em;">
|
||||
<div class="icon-magnet"></div>{{ T("magnet_link")}}
|
||||
</a>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{{ extends "layouts/profile" }}
|
||||
{{ import "layouts/partials/menu/profile" }}
|
||||
{{block title()}}{{ T("profile_edit_page", User.Username) }}{{end}}
|
||||
{{block title()}}{{ T("my_notifications") }}{{end}}
|
||||
{{ block profile_navigation()}}{{ yield profile_menu(route="profile") }}{{end}}
|
||||
{{block profile_content()}}
|
||||
<table class="notification-table">
|
||||
|
|
|
@ -188,7 +188,7 @@ func userProfileBase(c *gin.Context, templateName string, userProfile *models.Us
|
|||
}
|
||||
|
||||
variables.Set("UserProfile", userProfile)
|
||||
variables.Set("NbTorrents", []int64{int64(nbTorrents),uploadedSize})
|
||||
variables.Set("NbTorrents", []int64{int64(nbTorrents), uploadedSize})
|
||||
Render(c, path.Join(SiteDir, "user", templateName), variables)
|
||||
}
|
||||
|
||||
|
|
|
@ -42,6 +42,7 @@ func templateFunctions(vars jet.VarMap) jet.VarMap {
|
|||
vars.Set("CategoryName", categoryName)
|
||||
vars.Set("GetCategoryName", GetCategoryName)
|
||||
vars.Set("GetTorrentLanguages", torrentLanguages.GetTorrentLanguages)
|
||||
vars.Set("GenSearchName", GenSearchName)
|
||||
vars.Set("LanguageName", languageName)
|
||||
vars.Set("LanguageNameFromCode", languageNameFromCode)
|
||||
vars.Set("fileSize", fileSize)
|
||||
|
@ -346,7 +347,7 @@ func torrentFileExists(hash string, TorrentLink string) bool {
|
|||
return true
|
||||
}
|
||||
Openfile, err := os.Open(fmt.Sprintf("%s%c%s.torrent", config.Get().Torrents.FileStorage, os.PathSeparator, hash))
|
||||
if err != nil {
|
||||
if err != nil || len(TorrentLink) == 0 {
|
||||
//File doesn't exist
|
||||
return false
|
||||
}
|
||||
|
@ -451,3 +452,19 @@ func formatDate(Date time.Time, short bool) string {
|
|||
return fmt.Sprintf("%d/%d/%d, %d:%.2d:%.2d AM UTC+0", Date.Month(), Date.Day(), Date.Year(), Date.Hour(), Date.Minute(), Date.Second())
|
||||
}
|
||||
}
|
||||
|
||||
func GenSearchName(Search SearchForm, currentURL string, T publicSettings.TemplateTfunc) string {
|
||||
if currentURL == "/" {
|
||||
return string(T("home"))
|
||||
}
|
||||
if Search.UserName != "" {
|
||||
return Search.UserName
|
||||
}
|
||||
if Search.NameSearch != "" {
|
||||
return Search.NameSearch
|
||||
}
|
||||
if Search.Category != "" {
|
||||
return string(T(GetCategoryName(Search.Category)))
|
||||
}
|
||||
return string(T("search"))
|
||||
}
|
||||
|
|
|
@ -830,6 +830,54 @@ func testFormatDate(t *testing.T) {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
func testGenSearchName(t *testing.T) {
|
||||
var tests = []struct {
|
||||
Search SearchForm
|
||||
currentURL string
|
||||
Expected string
|
||||
}{
|
||||
{
|
||||
Search: SearchForm{},
|
||||
currentURL: "/",
|
||||
Expected: "home",
|
||||
},
|
||||
{
|
||||
Search: SearchForm{},
|
||||
currentURL: "/search",
|
||||
Expected: "search",
|
||||
},
|
||||
{
|
||||
Search: SearchForm{UserName: "yiiT"},
|
||||
currentURL: "/username/yiiT/search",
|
||||
Expected: "yiiT",
|
||||
},
|
||||
{
|
||||
Search: SearchForm{Category: "3_"},
|
||||
currentURL: "/search?c=3_",
|
||||
Expected: "anime",
|
||||
},
|
||||
{
|
||||
Search: SearchForm{Category: "3_12"},
|
||||
currentURL: "/search?c=3_12",
|
||||
Expected: "anime_amv",
|
||||
},
|
||||
}
|
||||
for _, test := range tests {
|
||||
Ts, _, err := publicSettings.TfuncAndLanguageWithFallback("en-us")
|
||||
if err != nil {
|
||||
t.Error("Couldn't load language files!")
|
||||
}
|
||||
var T publicSettings.TemplateTfunc
|
||||
T = func(id string, args ...interface{}) template.HTML {
|
||||
return template.HTML(fmt.Sprintf(Ts(id), args...))
|
||||
}
|
||||
value := GenSearchName(test.Search, test.currentURL, T)
|
||||
if value != test.Expected {
|
||||
t.Errorf("Unexpected value from the function GenSearchName, got '%s' wanted '%s'", value, test.Expected)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func mockupTemplateT(t *testing.T) publicSettings.TemplateTfunc {
|
||||
conf := config.Get().I18n
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
},
|
||||
{
|
||||
"id": "no_cp",
|
||||
"translation": "児童ポルノ禁止 (ロリはこれに含まれません)"
|
||||
"translation": "児童ポルノ禁止 (ロリは OK)"
|
||||
},
|
||||
{
|
||||
"id": "asia",
|
||||
|
@ -1525,7 +1525,7 @@
|
|||
},
|
||||
{
|
||||
"id": "activity_list",
|
||||
"translation": "アクティビティー一覧"
|
||||
"translation": "アクティビティー 一覧"
|
||||
},
|
||||
{
|
||||
"id": "activities",
|
||||
|
@ -1553,7 +1553,7 @@
|
|||
},
|
||||
{
|
||||
"id": "error_less_date",
|
||||
"translation": "%s は現在の日付および時刻より小さくなければなりません"
|
||||
"translation": "%s は現在の日時より小さくなければなりません"
|
||||
},
|
||||
{
|
||||
"id": "error_less_array",
|
||||
|
@ -1569,11 +1569,11 @@
|
|||
},
|
||||
{
|
||||
"id": "error_less_equal_date",
|
||||
"translation": "%s は現在の日付および時刻以下でなければなりません"
|
||||
"translation": "%s は現在の日時以下でなければなりません"
|
||||
},
|
||||
{
|
||||
"id": "error_greater_date",
|
||||
"translation": "%s は現在の日付および時刻より大きくなければなりません"
|
||||
"translation": "%s は現在の日時より大きくなければなりません"
|
||||
},
|
||||
{
|
||||
"id": "error_greater_length",
|
||||
|
@ -1585,7 +1585,7 @@
|
|||
},
|
||||
{
|
||||
"id": "error_greater_equal_date",
|
||||
"translation": "%s は現在の日付および時刻以上でなければなりません"
|
||||
"translation": "%s は現在の日時以上でなければなりません"
|
||||
},
|
||||
{
|
||||
"id": "error_max_field",
|
||||
|
@ -1689,7 +1689,7 @@
|
|||
},
|
||||
{
|
||||
"id": "error_contains",
|
||||
"translation": "%s にはテキスト '%s' が含まれている必要があります"
|
||||
"translation": "%s には文字列 '%s' が含まれている必要があります"
|
||||
},
|
||||
{
|
||||
"id": "error_contains_any",
|
||||
|
@ -1765,7 +1765,7 @@
|
|||
},
|
||||
{
|
||||
"id": "sort_by",
|
||||
"translation": "ソート:"
|
||||
"translation": "並べ替え:"
|
||||
},
|
||||
{
|
||||
"id": "ascending",
|
||||
|
@ -1913,7 +1913,7 @@
|
|||
},
|
||||
{
|
||||
"id": "torrent_cat_is_english",
|
||||
"translation": "Torrent カテゴリーは英語への翻訳となっていますが、言語が英語になっていません。英語に変更しました"
|
||||
"translation": "Torrent カテゴリーは英語翻訳となっていますが、言語が英語になっていません。英語に変更しました"
|
||||
},
|
||||
{
|
||||
"id": "torrent_cat_not_english",
|
||||
|
@ -1921,7 +1921,7 @@
|
|||
},
|
||||
{
|
||||
"id": "torrent_magnet_invalid",
|
||||
"translation": "magnet リンクをパースできません。お確かめください"
|
||||
"translation": "magnet リンクをパースできません。ご確認ください"
|
||||
},
|
||||
{
|
||||
"id": "torrent_hash_invalid",
|
||||
|
@ -1961,7 +1961,7 @@
|
|||
},
|
||||
{
|
||||
"id": "reupload",
|
||||
"translation": "欠落した、もしくは関係のない追加ファイルを含む、他のユーザーの Torrent の再アップロード"
|
||||
"translation": "欠落した、もしくは関連のない追加ファイルを含む、他のユーザーの Torrent の再アップロード"
|
||||
},
|
||||
{
|
||||
"id": "red",
|
||||
|
@ -1981,11 +1981,11 @@
|
|||
},
|
||||
{
|
||||
"id": "faq_ads_explanation",
|
||||
"translation": "これは決して軽率な判断ではなく、皆様から寄せられたご意見を徹底的に検討したものです。しかしながら、最終的にこれが pantsu に資金を供給し、継続的な活動を保証する唯一の持続可能な解決策であると感じています。<br/>私たちは資金の調達源について考えてきましたが、他に資金の調達に近づく選択肢はありません。<br>その結果、A-ADS の広告が私たちとユーザーにとって最良の選択であると判断しました。これらの広告は、シンプルで邪魔にならず、決してサイトのユーザーエクスペリエンスを阻害するものではなく、いかなる形態のトラッキングも含まれません。"
|
||||
"translation": "これは決して軽率な判断ではなく、皆様から寄せられたご意見を徹底的に検討したものです。しかしながら、最終的にこれが pantsu に資金を供給し、継続的な活動を保証する唯一の持続可能な解決策であると感じています。<br/>私たちは資金の調達源について考えてきましたが、他に資金の調達に近づく選択肢はありません。<br>そして、A-ADS の広告が私たちとユーザーにとって最良の選択であると判断しました。これらの広告は、シンプルで邪魔にならず、決してサイトのユーザーエクスペリエンスを阻害するものではなく、いかなる形態のトラッキングも含まれません。"
|
||||
},
|
||||
{
|
||||
"id": "torrent_preview",
|
||||
"translation": "Torrent のプレビュー"
|
||||
"translation": "Torrent プレビュー"
|
||||
},
|
||||
{
|
||||
"id": "announcement",
|
||||
|
@ -2173,7 +2173,7 @@
|
|||
},
|
||||
{
|
||||
"id": "related_to",
|
||||
"translation": "以下に関連:"
|
||||
"translation": "関連項目:"
|
||||
},
|
||||
{
|
||||
"id": "expire",
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
|
||||
"github.com/NyaaPantsu/nyaa/models/notifications"
|
||||
"github.com/NyaaPantsu/nyaa/utils/publicSettings"
|
||||
"github.com/NyaaPantsu/nyaa/utils/sanitize"
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/nicksnyder/go-i18n/i18n"
|
||||
)
|
||||
|
@ -34,7 +35,7 @@ func GetMessages(c *gin.Context) *Messages {
|
|||
mes := &Messages{make(map[string][]string), make(map[string][]string), c, T}
|
||||
announcements, _ := notifications.CheckAnnouncement()
|
||||
for _, announcement := range announcements {
|
||||
mes.AddInfo("system", announcement.Content)
|
||||
mes.AddInfo("system", string(sanitize.MarkdownToHTML(announcement.Content)))
|
||||
}
|
||||
c.Set(MessagesKey, mes)
|
||||
return mes
|
||||
|
|
|
@ -32,7 +32,7 @@ func (d *DateFilter) ParseOld(s string, dateType string) bool {
|
|||
}
|
||||
|
||||
// Parse parses a date to a datefilter object and return true if it succeeded
|
||||
// This functions accept only date formatted in this way YYYY/MM/DD
|
||||
// This function accept dates formatted in these way YYYY/MM/DD AND YYYY-MM-DD
|
||||
func (d *DateFilter) Parse(s string) bool {
|
||||
if s == "" {
|
||||
*d = ""
|
||||
|
@ -40,8 +40,11 @@ func (d *DateFilter) Parse(s string) bool {
|
|||
}
|
||||
date, err := time.Parse("2006/01/02", s)
|
||||
if err != nil {
|
||||
*d = ""
|
||||
return false
|
||||
date, err = time.Parse("2006-01-02", s)
|
||||
if err != nil {
|
||||
*d = ""
|
||||
return false
|
||||
}
|
||||
}
|
||||
*d = DateFilter(date.Format("2006-01-02"))
|
||||
return true
|
||||
|
|
|
@ -40,6 +40,7 @@ type TorrentParam struct {
|
|||
ToDate DateFilter
|
||||
NotNull string // csv
|
||||
NameLike string // csv
|
||||
NameSearch string //Contains what NameLike contains but without the excluded keywords, not used for search, just for page title
|
||||
Languages publicSettings.Languages
|
||||
MinSize SizeBytes
|
||||
MaxSize SizeBytes
|
||||
|
@ -117,6 +118,12 @@ func (p *TorrentParam) FromRequest(c *gin.Context) {
|
|||
// Search by name
|
||||
// We take the search arguments from "q" in url
|
||||
p.NameLike = strings.TrimSpace(c.Query("q"))
|
||||
|
||||
for _, word := range strings.Fields(p.NameLike) {
|
||||
if word[0] != '-' {
|
||||
p.NameSearch += word + " "
|
||||
}
|
||||
}
|
||||
|
||||
// Maximum results returned
|
||||
// We take the maxximum results to display from "limit" in url
|
||||
|
@ -252,8 +259,10 @@ 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.Locked {
|
||||
//query.Append("!status:5")
|
||||
//This line breaks ES but this check is needed
|
||||
}
|
||||
|
||||
|
||||
|
@ -410,7 +419,8 @@ func (p *TorrentParam) toDBQuery(c *gin.Context) *Query {
|
|||
}
|
||||
if p.Status != 0 {
|
||||
query.Append(p.Status.ToDBQuery())
|
||||
} else if !p.Locked {
|
||||
}
|
||||
if !p.Locked {
|
||||
query.Append("status IS NOT ?", 5)
|
||||
}
|
||||
|
||||
|
@ -452,6 +462,12 @@ func (p *TorrentParam) toDBQuery(c *gin.Context) *Query {
|
|||
|
||||
querySplit := strings.Fields(p.NameLike)
|
||||
for _, word := range querySplit {
|
||||
if word[0] == '-' && len(word) > 1 {
|
||||
//Exclude words starting with -
|
||||
query.Append("torrent_name NOT "+searchOperator, "%"+word[1:]+"%")
|
||||
continue
|
||||
}
|
||||
|
||||
firstRune, _ := utf8.DecodeRuneInString(word)
|
||||
if len(word) == 1 && unicode.IsPunct(firstRune) {
|
||||
// some queries have a single punctuation character
|
||||
|
@ -525,5 +541,6 @@ func (p *TorrentParam) Clone() TorrentParam {
|
|||
Languages: p.Languages,
|
||||
MinSize: p.MinSize,
|
||||
MaxSize: p.MaxSize,
|
||||
Locked: p.Locked,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ func TestTorrentParam_FromRequest(t *testing.T) {
|
|||
c = mockRequest(t, "/?fromID=3&q=xx&c=_")
|
||||
torrentParam.FromRequest(c)
|
||||
defTorrent.FromID, defTorrent.NameLike = 3, "xx"
|
||||
defTorrent.NameSearch = "xx "
|
||||
assert.Equal(defTorrent, torrentParam)
|
||||
}
|
||||
|
||||
|
@ -57,14 +58,14 @@ func TestTorrentParam_ToESQuery(t *testing.T) {
|
|||
Test TorrentParam
|
||||
Expected string
|
||||
}{
|
||||
{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"},
|
||||
{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"},
|
||||
}
|
||||
|
||||
for _, test := range tests {
|
||||
|
|
Référencer dans un nouveau ticket