Albirew/nyaa-pantsu
Albirew
/
nyaa-pantsu
Archivé
1
0
Bifurcation 0
Cette révision appartient à :
Eliot Whalan 2017-05-28 19:57:38 +10:00
révision cdd382cd34
Signature inconnue de Forgejo
ID de la clé GPG: C0A42175139840D6
37 fichiers modifiés avec 673 ajouts et 188 suppressions

Voir le fichier

@ -103,7 +103,7 @@ func (p *TorrentParam) ToFilterQuery() string {
}
if p.UserID != 0 {
query += "uploader_id:" + strconv.FormatInt(int64(p.UserID), 10)
query += " uploader_id:" + strconv.FormatInt(int64(p.UserID), 10)
}
if p.Status != ShowAll {

Voir le fichier

@ -6,7 +6,7 @@ package config
var Trackers = []string{
"udp://tracker.doko.moe:6969",
"udp://tracker.coppersurfer.tk:6969",
"udp://zer0day.to:1337/announce",
"udp://tracker.zer0day.to:1337/announce",
"udp://tracker.leechers-paradise.org:6969",
"udp://explodie.org:6969",
"udp://tracker.opentrackr.org:1337",

Voir le fichier

@ -16,7 +16,7 @@ import (
"github.com/NyaaPantsu/nyaa/service/scraper"
"github.com/NyaaPantsu/nyaa/service/torrent/metainfoFetcher"
"github.com/NyaaPantsu/nyaa/service/user"
"github.com/NyaaPantsu/nyaa/util/languages"
"github.com/NyaaPantsu/nyaa/util/publicSettings"
"github.com/NyaaPantsu/nyaa/util/log"
"github.com/NyaaPantsu/nyaa/util/search"
"github.com/NyaaPantsu/nyaa/util/signals"
@ -129,7 +129,7 @@ func main() {
if err != nil {
log.Fatal(err.Error())
}
err = languages.InitI18n(conf.I18n, userService.NewCurrentUserRetriever())
err = publicSettings.InitI18n(conf.I18n, userService.NewCurrentUserRetriever())
if err != nil {
log.Fatal(err.Error())
}

Voir le fichier

@ -49,6 +49,7 @@ type Torrent struct {
Category int `gorm:"column:category"`
SubCategory int `gorm:"column:sub_category"`
Status int `gorm:"column:status"`
Hidden bool `gorm:"column:hidden"`
Date time.Time `gorm:"column:date"`
UploaderID uint `gorm:"column:uploader"`
Downloads int `gorm:"column:downloads"`
@ -267,8 +268,13 @@ func (t *Torrent) ToJSON() TorrentJSON {
})
uploader := ""
if t.Uploader != nil {
var uploaderID uint
if t.Hidden {
uploader = "れんちょん"
uploaderID = 0
} else if t.Uploader != nil {
uploader = t.Uploader.Username
uploaderID = t.UploaderID
}
torrentlink := ""
if t.ID <= config.LastOldTorrentID && len(config.TorrentCacheLink) > 0 {
@ -292,7 +298,7 @@ func (t *Torrent) ToJSON() TorrentJSON {
SubCategory: strconv.Itoa(t.SubCategory),
Category: strconv.Itoa(t.Category),
Downloads: t.Downloads,
UploaderID: t.UploaderID,
UploaderID: uploaderID,
UploaderName: util.SafeText(uploader),
OldUploader: util.SafeText(t.OldUploader),
WebsiteLink: util.Safe(t.WebsiteLink),

Voir le fichier

@ -31,6 +31,7 @@ type User struct {
APIToken string `gorm:"column:api_token"`
APITokenExpiry time.Time `gorm:"column:api_token_expiry"`
Language string `gorm:"column:language"`
Theme string `gorm:"column:theme"`
UserSettings string `gorm:"column:settings"`
// TODO: move this to PublicUser
@ -62,7 +63,7 @@ func (u User) Size() (s int) {
4*3 + //time.Time
3*2 + // arrays
// string arrays
len(u.Username) + len(u.Password) + len(u.Email) + len(u.APIToken) + len(u.MD5) + len(u.Language)
len(u.Username) + len(u.Password) + len(u.Email) + len(u.APIToken) + len(u.MD5) + len(u.Language) + len(u.Theme)
s *= 8
// Ignoring foreign key users. Fuck them.

Voir le fichier

@ -115,7 +115,7 @@ select.form-input {
pointer-events: none;
}
.form-input.search-box { margin-right: -20px; }
.form-input.search-box { margin-right: -20px; padding-right: 20px; }
.form-input.search-box + .search-icon {
left: -5px;
position: relative;
@ -221,8 +221,8 @@ select.form-input {
.results { padding: 0 }
table {
width: 100%;
border-collapse:collapse;
width: 100%;
table-layout: fixed;
}
@ -251,7 +251,7 @@ th { border-bottom-width: 2px; }
.tr-size { width: 90px; }
.tr-se, .tr-le { font-weight: bold; }
.tr-se, .tr-le, .tr-dl { width: 50px; }
.tr-date { width: 90px; }
.tr-date { width: 100px; }
.sort-arrows { margin-left: 0.2rem; }
.sort-arrows span {
@ -278,8 +278,8 @@ th { border-bottom-width: 2px; }
min-width: 35px;
}
.pagination li:first-child { border-radius: 3px 0 0 3px; }
.pagination li:nth-last-child(2) { border-radius: 0 3px 3px 0; border-right-width: 1px !important}
.pagination a:first-child li { border-radius: 3px 0 0 3px; }
.pagination a:nth-last-child(2) li { border-radius: 0 3px 3px 0; border-right-width: 1px !important}
#footer { width: 100%; bottom: 0; left: 0; margin-top: 40px;}
@ -287,6 +287,8 @@ th { border-bottom-width: 2px; }
.footer {
text-align: center;
padding: 1rem 0 1.2rem 0;
position: relative;
z-index: 2;
}
.footer-opt {
@ -376,7 +378,7 @@ a:hover { color: #238BC7; }
.form-input { border-color: #BBC9CF !important; background: #fafafa; color: #666; }
.form-input.btn:hover { background: rgba(192,192,192,0.2); }
.btn:hover, .up-btn:hover { background: rgba(192,192,192,0.2); }
.form-input:focus { box-shadow: 0 0 5px #fff; }
@ -468,7 +470,7 @@ td.tr-le { color: #E84C4C; }
font-weight: bold;
}
.torrent-info-data {
width: 60%;
width: 50%;
}
.torrent-info-row {
text-align: left;
@ -518,6 +520,10 @@ td.tr-le { color: #E84C4C; }
}
.profile-content {
width: 70%;
text-align: left;
}
div.profile-content.box > nav > ul > li {
border-right-width: 1px;
}
.magnet-icon {
display: inline-block;
@ -589,6 +595,9 @@ input#show-filelist:checked ~ #filelist {
#filelist tr {
background: none; /* Striped lines will look really ugly due to how it's drawn */
}
.table-filelist {
width: 100%;
}
.tr-filelist {
--nest-level: 0;
}
@ -610,7 +619,7 @@ input#show-filelist:checked ~ #filelist {
}
/* Filesize column */
.tr-filelist td:nth-child(2) {
width: 30%;
width: 20%;
text-align: center;
}
/* Input that show/hides each folder */

Voir le fichier

@ -11,6 +11,40 @@ function toggleNightMode() {
localStorage.setItem("night", (night == "true") ? "false" : "true");
}
// Switches between themes when a new one is selected
function switchThemes(){
themeName = document.getElementById("theme-selector").value
var head = document.getElementsByTagName("head")[0];
// Remove the theme in place, it fails if one isn't set
try{
head.removeChild(document.getElementById("theme"));
} catch(err){}
// Don't add a node if we don't want extra styling
if(themeName === ""){
return;
}
// Create the new one and put it back
var newTheme = document.createElement("link");
newTheme.setAttribute("rel", "stylesheet");
newTheme.setAttribute("href", "/css/"+ themeName + ".css");
newTheme.setAttribute("id", "theme");
head.appendChild(newTheme);
}
function toggleMascot(btn) {
var state= btn.value;
if (state == "hide") {
btn.innerHTML = "Mascot";
document.getElementById("mascot").className = "hide";
btn.value = "show";
} else {
btn.innerHTML = "Mascot";
document.getElementById("mascot").className = "";
btn.value = "hide";
}
}
// Used by spoiler tags
function toggleLayer(elem) {
if (elem.classList.contains("hide"))
@ -21,7 +55,7 @@ function toggleLayer(elem) {
// Date formatting
var lang = document.getElementsByTagName("html")[0].getAttribute("lang");
var ymdOpt = { year: "numeric", month: "2-digit", day: "2-digit" };
var ymdOpt = { year: "numeric", month: "short", day: "numeric" };
var hmOpt = { hour: "numeric", minute: "numeric" };
var list = document.getElementsByClassName("date-short");
@ -42,16 +76,24 @@ window.onload = function() {
var shiftWindow = function() { scrollBy(0, -70) };
if (location.hash) shiftWindow();
window.addEventListener("hashchange", shiftWindow);
document.getElementsByClassName("search-box")[0].addEventListener("focus", function (e) {
var w = document.getElementsByClassName("h-user")[0].offsetWidth;
document.getElementsByClassName("h-user")[0].style.display = "none";
document.getElementsByClassName("search-box")[0].style.width = document.getElementsByClassName("search-box")[0].offsetWidth + w + "px";
});
document.getElementsByClassName("search-box")[0].addEventListener("blur", function (e) {
document.getElementsByClassName("search-box")[0].style.width = "";
document.getElementsByClassName("h-user")[0].style.display = "inline-block";
});
};
function playVoice() {
switch (theme) {
case "tomorrow.css":
if (explosion) {
explosion.play();
break;
default:
}
else {
nyanpassu.volume = 0.5;
nyanpassu.play();
break;
}
}
}

Voir le fichier

@ -3,13 +3,14 @@ package router
import (
"encoding/json"
"fmt"
elastic "gopkg.in/olivere/elastic.v5"
"html"
"net/http"
"strconv"
"strings"
"time"
elastic "gopkg.in/olivere/elastic.v5"
"github.com/NyaaPantsu/nyaa/config"
"github.com/NyaaPantsu/nyaa/db"
"github.com/NyaaPantsu/nyaa/model"
@ -172,6 +173,8 @@ func APIUploadHandler(w http.ResponseWriter, r *http.Request) {
upload.Category, _ = strconv.Atoi(r.FormValue("category"))
upload.SubCategory, _ = strconv.Atoi(r.FormValue("sub_category"))
upload.Description = r.FormValue("description")
upload.Remake, _ = strconv.ParseBool(r.FormValue("remake"))
upload.WebsiteLink = r.FormValue("website_link")
var err error
var code int
@ -197,14 +200,22 @@ func APIUploadHandler(w http.ResponseWriter, r *http.Request) {
Name: upload.Name,
Category: upload.Category,
SubCategory: upload.SubCategory,
Status: 1,
Status: model.TorrentStatusNormal,
Hash: upload.Hash,
Date: time.Now(),
Filesize: filesize,
Description: upload.Description,
UploaderID: user.ID,
Uploader: &user,
WebsiteLink: upload.WebsiteLink,
}
if upload.Remake {
torrent.Status = model.TorrentStatusRemake
} else if user.IsTrusted() {
torrent.Status = model.TorrentStatusTrusted
}
db.ORM.Create(&torrent)
client, err := elastic.NewClient()

Voir le fichier

@ -275,6 +275,7 @@ func TorrentEditModPanel(w http.ResponseWriter, r *http.Request) {
uploadForm.Name = torrentJSON.Name
uploadForm.Category = torrentJSON.Category + "_" + torrentJSON.SubCategory
uploadForm.Status = torrentJSON.Status
uploadForm.Hidden = torrent.Hidden
uploadForm.WebsiteLink = string(torrentJSON.WebsiteLink)
uploadForm.Description = string(torrentJSON.Description)
htv := formTemplateVariables{newPanelCommonVariables(r), uploadForm, messages.GetAllErrors(), messages.GetAllInfos()}
@ -300,6 +301,7 @@ func TorrentPostEditModPanel(w http.ResponseWriter, r *http.Request) {
torrent.Category = uploadForm.CategoryID
torrent.SubCategory = uploadForm.SubCategoryID
torrent.Status = uploadForm.Status
torrent.Hidden = uploadForm.Hidden
torrent.WebsiteLink = uploadForm.WebsiteLink
torrent.Description = uploadForm.Description
// torrent.Uploader = nil // GORM will create a new user otherwise (wtf?!)

Voir le fichier

@ -5,7 +5,7 @@ import (
"net/http"
"github.com/NyaaPantsu/nyaa/service/user"
"github.com/NyaaPantsu/nyaa/util/languages"
"github.com/NyaaPantsu/nyaa/util/publicSettings"
"github.com/NyaaPantsu/nyaa/util/timeHelper"
)
@ -15,11 +15,10 @@ type LanguagesJSONResponse struct {
Languages map[string]string `json:"languages"`
}
// SeeLanguagesHandler : Controller to view the languages
func SeeLanguagesHandler(w http.ResponseWriter, r *http.Request) {
_, Tlang := languages.GetTfuncAndLanguageFromRequest(r)
availableLanguages := languages.GetAvailableLanguages()
// SeePublicSettingsHandler : Controller to view the languages and themes
func SeePublicSettingsHandler(w http.ResponseWriter, r *http.Request) {
_, Tlang := publicSettings.GetTfuncAndLanguageFromRequest(r)
availableLanguages := publicSettings.GetAvailableLanguages()
defer r.Body.Close()
contentType := r.Header.Get("Content-Type")
if contentType == "application/json" {
@ -35,7 +34,7 @@ func SeeLanguagesHandler(w http.ResponseWriter, r *http.Request) {
Language: Tlang.Tag,
Languages: availableLanguages,
}
err := changeLanguageTemplate.ExecuteTemplate(w, "index.html", clv)
err := changePublicSettingsTemplate.ExecuteTemplate(w, "index.html", clv)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
return
@ -43,25 +42,29 @@ func SeeLanguagesHandler(w http.ResponseWriter, r *http.Request) {
}
}
// ChangeLanguageHandler : Controller for changing the current language
func ChangeLanguageHandler(w http.ResponseWriter, r *http.Request) {
// ChangePublicSettingsHandler : Controller for changing the current language and theme
func ChangePublicSettingsHandler(w http.ResponseWriter, r *http.Request) {
theme := r.FormValue("theme")
lang := r.FormValue("language")
availableLanguages := publicSettings.GetAvailableLanguages()
defer r.Body.Close()
availableLanguages := languages.GetAvailableLanguages()
if _, exists := availableLanguages[lang]; !exists {
http.Error(w, "Language not available", http.StatusInternalServerError)
return
}
// If logged in, update user language; if not, set cookie.
// If logged in, update user language.
user, _ := userService.CurrentUser(r)
if user.ID > 0 {
user.Language = lang
user.Theme = theme
// I don't know if I should use this...
userService.UpdateUserCore(&user)
}
// Set cookie
http.SetCookie(w, &http.Cookie{Name: "lang", Value: lang, Expires: timeHelper.FewDaysLater(365)})
http.SetCookie(w, &http.Cookie{Name: "theme", Value: theme, Expires: timeHelper.FewDaysLater(365)})
url, _ := Router.Get("home").URL()
http.Redirect(w, r, url.String(), http.StatusSeeOther)

Voir le fichier

@ -29,6 +29,7 @@ func init() {
gzipUserProfileHandler := http.HandlerFunc(UserProfileHandler)
gzipUserAPIKeyResetHandler := http.HandlerFunc(UserAPIKeyResetHandler)
gzipUserDetailsHandler := http.HandlerFunc(UserDetailsHandler)
downloadTorrentHandler := http.HandlerFunc(DownloadTorrent)
gzipUserProfileFormHandler := http.HandlerFunc(UserProfileFormHandler)
gzipUserNotificationsHandler := http.HandlerFunc(UserNotificationsHandler)
gzipDumpsHandler := handlers.CompressHandler(dumpsHandler)
@ -78,6 +79,9 @@ func init() {
Router.HandleFunc("/user/{id}/{username}/feed", RSSHandler).Name("feed_user")
Router.HandleFunc("/user/{id}/{username}/feed/{page}", RSSHandler).Name("feed_user_page")
// !!! This line need to have the same download location as the one define in config.TorrentStorageLink !!!
Router.Handle("/download/{hash}", wrapHandler(downloadTorrentHandler)).Name("torrent_download")
// INFO Everything under /mod should be wrapped by wrapModHandler. This make
// sure the page is only accessible by moderators
// TODO Find a native mux way to add a 'prehook' for route /mod
@ -114,8 +118,8 @@ func init() {
Router.Handle("/dumps", gzipDatabaseDumpHandler).Name("dump").Methods("GET")
Router.HandleFunc("/language", SeeLanguagesHandler).Methods("GET").Name("see_languages")
Router.HandleFunc("/language", ChangeLanguageHandler).Methods("POST").Name("change_language")
Router.HandleFunc("/settings", SeePublicSettingsHandler).Methods("GET").Name("see_languages")
Router.HandleFunc("/settings", ChangePublicSettingsHandler).Methods("POST").Name("see_languages")
Router.NotFoundHandler = http.HandlerFunc(NotFoundHandler)
}

Voir le fichier

@ -26,7 +26,7 @@ var homeTemplate,
viewUserDeleteTemplate,
userTorrentEd,
notFoundTemplate,
changeLanguageTemplate,
changePublicSettingsTemplate,
databaseDumpTemplate *template.Template
var panelIndex,
@ -128,10 +128,11 @@ func ReloadTemplates() {
file: "404.html",
},
{
templ: &changeLanguageTemplate,
name: "change_language",
file: "change_language.html",
templ: &changePublicSettingsTemplate,
name: "change_settings",
file: "public_settings.html",
},
}
for idx := range pubTempls {
pubTempls[idx].indexFile = filepath.Join(TemplateDir, "index.html")

Voir le fichier

@ -12,12 +12,12 @@ import (
"github.com/NyaaPantsu/nyaa/util"
"github.com/NyaaPantsu/nyaa/util/categories"
"github.com/NyaaPantsu/nyaa/util/filelist"
"github.com/NyaaPantsu/nyaa/util/languages"
"github.com/NyaaPantsu/nyaa/util/publicSettings"
)
type captchaData struct {
CaptchaID string
T languages.TemplateTfunc
T publicSettings.TemplateTfunc
}
// FuncMap : Functions accessible in templates by {{ $.Function }}
@ -146,7 +146,7 @@ var FuncMap = template.FuncMap{
return template.HTML(ret)
},
"Sukebei": config.IsSukebei,
"getDefaultLanguage": languages.GetDefaultLanguage,
"getDefaultLanguage": publicSettings.GetDefaultLanguage,
"getAvatar": func(hash string, size int) string {
return "https://www.gravatar.com/avatar/" + hash + "?s=" + strconv.Itoa(size)
},
@ -180,23 +180,23 @@ var FuncMap = template.FuncMap{
}
return ""
},
"fileSize": func(filesize int64, T languages.TemplateTfunc) template.HTML {
"fileSize": func(filesize int64, T publicSettings.TemplateTfunc) template.HTML {
if filesize == 0 {
return T("unknown")
}
return template.HTML(util.FormatFilesize(filesize))
},
"makeCaptchaData": func(captchaID string, T languages.TemplateTfunc) captchaData {
"makeCaptchaData": func(captchaID string, T publicSettings.TemplateTfunc) captchaData {
return captchaData{captchaID, T}
},
"DefaultUserSettings": func(s string) bool {
return config.DefaultUserSettings[s]
},
"makeTreeViewData": func(f *filelist.FileListFolder, nestLevel int, T languages.TemplateTfunc, identifierChain string) interface{} {
"makeTreeViewData": func(f *filelist.FileListFolder, nestLevel int, T publicSettings.TemplateTfunc, identifierChain string) interface{} {
return struct{
Folder *filelist.FileListFolder
NestLevel int
T languages.TemplateTfunc
T publicSettings.TemplateTfunc
IdentifierChain string
}{ f, nestLevel, T, identifierChain }
},

Voir le fichier

@ -9,7 +9,7 @@ import (
"github.com/NyaaPantsu/nyaa/service/user"
userForms "github.com/NyaaPantsu/nyaa/service/user/form"
"github.com/NyaaPantsu/nyaa/util/filelist"
"github.com/NyaaPantsu/nyaa/util/languages"
"github.com/NyaaPantsu/nyaa/util/publicSettings"
"github.com/gorilla/mux"
)
@ -74,6 +74,12 @@ type changeLanguageVariables struct {
Languages map[string]string
}
type publicSettingsVariables struct {
commonTemplateVariables
Language string
Languages map[string]string
}
/* MODERATION Variables */
type panelIndexVbs struct {
@ -91,7 +97,8 @@ type panelIndexVbs struct {
type commonTemplateVariables struct {
Navigation navigation
Search searchForm
T languages.TemplateTfunc
T publicSettings.TemplateTfunc
Theme string
User *model.User
URL *url.URL // for parsing URL in templates
Route *mux.Route // for getting current route in templates
@ -140,7 +147,8 @@ func newCommonVariables(r *http.Request) commonTemplateVariables {
return commonTemplateVariables{
Navigation: newNavigation(),
Search: newSearchForm(),
T: languages.GetTfuncFromRequest(r),
T: publicSettings.GetTfuncFromRequest(r),
Theme: publicSettings.GetThemeFromRequest(r),
User: getUser(r),
URL: r.URL,
Route: mux.CurrentRoute(r),

Voir le fichier

@ -38,6 +38,7 @@ type uploadForm struct {
Remake bool
Description string
Status int
Hidden bool
CaptchaID string
WebsiteLink string
@ -61,6 +62,7 @@ const uploadFormRemake = "remake"
const uploadFormDescription = "desc"
const uploadFormWebsiteLink = "website_link"
const uploadFormStatus = "status"
const uploadFormHidden = "hidden"
// error indicating that you can't send both a magnet link and torrent
var errTorrentPlusMagnet = errors.New("Upload either a torrent file or magnet link, not both")
@ -77,7 +79,7 @@ var errInvalidTorrentName = errors.New("Torrent name is invalid")
// error indicating a torrent's description is invalid
var errInvalidTorrentDescription = errors.New("Torrent description is invalid")
// error indicating a torrent's description is invalid
// error indicating a torrent's website link is invalid
var errInvalidWebsiteLink = errors.New("Website url or IRC link is invalid")
// error indicating a torrent's category is invalid
@ -97,6 +99,7 @@ func (f *uploadForm) ExtractInfo(r *http.Request) error {
f.Status, _ = strconv.Atoi(r.FormValue(uploadFormStatus))
f.Magnet = r.FormValue(uploadFormMagnet)
f.Remake = r.FormValue(uploadFormRemake) == "on"
f.Hidden = r.FormValue(uploadFormHidden) == "on"
// trim whitespace
f.Name = util.TrimWhitespaces(f.Name)
@ -242,6 +245,7 @@ func (f *uploadForm) ExtractEditInfo(r *http.Request) error {
f.Category = r.FormValue(uploadFormCategory)
f.WebsiteLink = r.FormValue(uploadFormWebsiteLink)
f.Description = r.FormValue(uploadFormDescription)
f.Hidden = r.FormValue(uploadFormHidden) == "on"
f.Status, _ = strconv.Atoi(r.FormValue(uploadFormStatus))
// trim whitespace

Voir le fichier

@ -2,11 +2,12 @@ package router
import (
"fmt"
elastic "gopkg.in/olivere/elastic.v5"
"net/http"
"strconv"
"time"
elastic "gopkg.in/olivere/elastic.v5"
"github.com/NyaaPantsu/nyaa/config"
"github.com/NyaaPantsu/nyaa/db"
"github.com/NyaaPantsu/nyaa/model"
@ -16,9 +17,9 @@ import (
"github.com/NyaaPantsu/nyaa/service/upload"
"github.com/NyaaPantsu/nyaa/service/user"
"github.com/NyaaPantsu/nyaa/service/user/permission"
"github.com/NyaaPantsu/nyaa/util/languages"
"github.com/NyaaPantsu/nyaa/util/log"
msg "github.com/NyaaPantsu/nyaa/util/messages"
"github.com/NyaaPantsu/nyaa/util/publicSettings"
)
// UploadHandler : Main Controller for uploading a torrent
@ -80,6 +81,7 @@ func UploadPostHandler(w http.ResponseWriter, r *http.Request) {
Category: uploadForm.CategoryID,
SubCategory: uploadForm.SubCategoryID,
Status: status,
Hidden: uploadForm.Hidden,
Hash: uploadForm.Infohash,
Date: time.Now(),
Filesize: uploadForm.Filesize,
@ -109,7 +111,7 @@ func UploadPostHandler(w http.ResponseWriter, r *http.Request) {
for _, follower := range user.Followers {
follower.ParseSettings() // We need to call it before checking settings
if follower.Settings.Get("new_torrent") {
T, _, _ := languages.TfuncAndLanguageWithFallback(follower.Language, follower.Language) // We need to send the notification to every user in their language
T, _, _ := publicSettings.TfuncAndLanguageWithFallback(follower.Language, follower.Language) // We need to send the notification to every user in their language
notifierService.NotifyUser(&follower, torrent.Identifier(), fmt.Sprintf(T("new_torrent_uploaded"), torrent.Name, user.Username), url.String(), follower.Settings.Get("new_torrent_email"))
}

Voir le fichier

@ -12,7 +12,7 @@ import (
"github.com/NyaaPantsu/nyaa/service/user/form"
"github.com/NyaaPantsu/nyaa/service/user/permission"
"github.com/NyaaPantsu/nyaa/util/crypto"
"github.com/NyaaPantsu/nyaa/util/languages"
"github.com/NyaaPantsu/nyaa/util/publicSettings"
msg "github.com/NyaaPantsu/nyaa/util/messages"
"github.com/NyaaPantsu/nyaa/util/modelHelper"
"github.com/gorilla/mux"
@ -72,7 +72,7 @@ func UserProfileHandler(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
vars := mux.Vars(r)
id := vars["id"]
Ts, _ := languages.GetTfuncAndLanguageFromRequest(r)
Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
messages := msg.GetMessages(r)
userProfile, _, errorUser := userService.RetrieveUserForAdmin(id)
@ -125,7 +125,7 @@ func UserDetailsHandler(w http.ResponseWriter, r *http.Request) {
if userPermission.CurrentOrAdmin(currentUser, userProfile.ID) {
b := form.UserForm{}
modelHelper.BindValueForm(&b, r)
availableLanguages := languages.GetAvailableLanguages()
availableLanguages := publicSettings.GetAvailableLanguages()
userProfile.ParseSettings()
htv := userProfileEditVariables{newCommonVariables(r), &userProfile, b, messages.GetAllErrors(), messages.GetAllInfos(), availableLanguages}
err := viewProfileEditTemplate.ExecuteTemplate(w, "index.html", htv)
@ -154,7 +154,7 @@ func UserProfileFormHandler(w http.ResponseWriter, r *http.Request) {
userForm := form.UserForm{}
userSettingsForm := form.UserSettingsForm{}
Ts, _ := languages.GetTfuncAndLanguageFromRequest(r)
Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
if len(r.PostFormValue("email")) > 0 {
form.EmailValidation(r.PostFormValue("email"), messages)
@ -189,7 +189,7 @@ func UserProfileFormHandler(w http.ResponseWriter, r *http.Request) {
}
}
}
availableLanguages := languages.GetAvailableLanguages()
availableLanguages := publicSettings.GetAvailableLanguages()
upev := userProfileEditVariables{
commonTemplateVariables: newCommonVariables(r),
UserProfile: &userProfile,
@ -325,7 +325,7 @@ func UserNotificationsHandler(w http.ResponseWriter, r *http.Request) {
currentUser := getUser(r)
if currentUser.ID > 0 {
messages := msg.GetMessages(r)
Ts, _ := languages.GetTfuncAndLanguageFromRequest(r)
Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
if r.URL.Query()["clear"] != nil {
notifierService.DeleteAllNotifications(currentUser.ID)
messages.AddInfo("infos", Ts("notifications_cleared"))
@ -348,7 +348,7 @@ func UserAPIKeyResetHandler(w http.ResponseWriter, r *http.Request) {
id := vars["id"]
currentUser := getUser(r)
Ts, _ := languages.GetTfuncAndLanguageFromRequest(r)
Ts, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
messages := msg.GetMessages(r)
userProfile, _, errorUser := userService.RetrieveUserForAdmin(id)
if errorUser != nil || !userPermission.CurrentOrAdmin(currentUser, userProfile.ID) || userProfile.ID == 0 {

Voir le fichier

@ -2,11 +2,15 @@ package router
import (
"fmt"
"io"
"net/http"
"strconv"
"strings"
"time"
"os"
"github.com/NyaaPantsu/nyaa/config"
"github.com/NyaaPantsu/nyaa/db"
"github.com/NyaaPantsu/nyaa/model"
"github.com/NyaaPantsu/nyaa/service"
@ -17,9 +21,9 @@ import (
"github.com/NyaaPantsu/nyaa/service/user/permission"
"github.com/NyaaPantsu/nyaa/util"
"github.com/NyaaPantsu/nyaa/util/filelist"
"github.com/NyaaPantsu/nyaa/util/languages"
"github.com/NyaaPantsu/nyaa/util/log"
msg "github.com/NyaaPantsu/nyaa/util/messages"
"github.com/NyaaPantsu/nyaa/util/publicSettings"
"github.com/gorilla/mux"
)
@ -113,7 +117,7 @@ func PostCommentHandler(w http.ResponseWriter, r *http.Request) {
url, err := Router.Get("view_torrent").URL("id", strconv.FormatUint(uint64(torrent.ID), 10))
torrent.Uploader.ParseSettings()
if torrent.Uploader.Settings.Get("new_comment") {
T, _, _ := languages.TfuncAndLanguageWithFallback(torrent.Uploader.Language, torrent.Uploader.Language) // We need to send the notification to every user in their language
T, _, _ := publicSettings.TfuncAndLanguageWithFallback(torrent.Uploader.Language, torrent.Uploader.Language) // We need to send the notification to every user in their language
notifierService.NotifyUser(torrent.Uploader, comment.Identifier(), fmt.Sprintf(T("new_comment_on_torrent"), torrent.Name), url.String(), torrent.Uploader.Settings.Get("new_comment_email"))
}
@ -170,6 +174,7 @@ func TorrentEditUserPanel(w http.ResponseWriter, r *http.Request) {
uploadForm.Remake = torrent.Status == model.TorrentStatusRemake
uploadForm.WebsiteLink = string(torrent.WebsiteLink)
uploadForm.Description = string(torrent.Description)
uploadForm.Hidden = torrent.Hidden
htv := formTemplateVariables{newCommonVariables(r), uploadForm, messages.GetAllErrors(), messages.GetAllInfos()}
err := userTorrentEd.ExecuteTemplate(w, "index.html", htv)
log.CheckError(err)
@ -204,6 +209,7 @@ func TorrentPostEditUserPanel(w http.ResponseWriter, r *http.Request) {
torrent.Category = uploadForm.CategoryID
torrent.SubCategory = uploadForm.SubCategoryID
torrent.Status = status
torrent.Hidden = uploadForm.Hidden
torrent.WebsiteLink = uploadForm.WebsiteLink
torrent.Description = uploadForm.Description
// torrent.Uploader = nil // GORM will create a new user otherwise (wtf?!)
@ -240,3 +246,46 @@ func TorrentDeleteUserPanel(w http.ResponseWriter, r *http.Request) {
NotFoundHandler(w, r)
}
}
// DownloadTorrent : Controller for downloading a torrent
func DownloadTorrent(w http.ResponseWriter, r *http.Request) {
defer r.Body.Close()
vars := mux.Vars(r)
hash := vars["hash"]
if hash == "" && len(config.TorrentFileStorage) == 0 {
//File not found, send 404
http.Error(w, "File not found.", 404)
return
}
//Check if file exists and open
Openfile, err := os.Open(fmt.Sprintf("%s%c%s.torrent", config.TorrentFileStorage, os.PathSeparator, hash))
defer Openfile.Close() //Close after function return
if err != nil {
//File not found, send 404
http.Error(w, "File not found.", 404)
return
}
//Get the file size
FileStat, _ := Openfile.Stat() //Get info from file
FileSize := strconv.FormatInt(FileStat.Size(), 10) //Get file size as a string
torrent, err := torrentService.GetRawTorrentByHash(hash)
if err != nil {
//File not found, send 404
http.Error(w, "File not found.", 404)
return
}
w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s.torrent\"", torrent.Name))
w.Header().Set("Content-Type", "application/x-bittorrent")
w.Header().Set("Content-Length", FileSize)
//Send the file
// We reset the offset to 0
Openfile.Seek(0, 0)
io.Copy(w, Openfile) //'Copy' the file to the client
return
}

Voir le fichier

@ -43,6 +43,8 @@ type TorrentRequest struct {
Magnet string `json:"magnet"`
Hash string `json:"hash"`
Description string `json:"description"`
Remake bool `json:"remake"`
WebsiteLink string `json:"website_link"`
}
// UpdateRequest struct
@ -94,6 +96,17 @@ func validateSubCategory(r *TorrentRequest) (error, int) {
return nil, http.StatusOK
}
func validateWebsiteLink(r *TorrentRequest) (error, int) {
if r.WebsiteLink != "" {
// WebsiteLink
urlRegexp, _ := regexp.Compile(`^(https?:\/\/|ircs?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?$`)
if !urlRegexp.MatchString(r.WebsiteLink) {
return ErrWebsiteLink, http.StatusNotAcceptable
}
}
return nil, http.StatusOK
}
func validateMagnet(r *TorrentRequest) (error, int) {
magnetURL, err := url.Parse(string(r.Magnet)) //?
if err != nil {
@ -144,6 +157,7 @@ func (r *TorrentRequest) ValidateUpload() (err error, code int) {
validateSubCategory,
validateMagnet,
validateHash,
validateWebsiteLink,
}
for i, validator := range validators {
@ -206,6 +220,7 @@ func (r *TorrentRequest) ValidateUpdate() (err error, code int) {
validateSubCategory,
validateMagnet,
validateHash,
validateWebsiteLink,
}
//don't update not requested values
@ -243,4 +258,7 @@ func (r *UpdateRequest) UpdateTorrent(t *model.Torrent) {
if r.Update.Description != "" {
t.Description = r.Update.Description
}
if r.Update.WebsiteLink != "" {
t.WebsiteLink = r.Update.WebsiteLink
}
}

Voir le fichier

@ -11,6 +11,9 @@ var ErrCategory = errors.New("this category doesn't exist")
// ErrSubCategory : Error for not found sub category used by api
var ErrSubCategory = errors.New("this sub category doesn't exist")
// ErrWebsiteLink : error indicating a torrent's website link is invalid
var ErrWebsiteLink = errors.New("website url or IRC link is invalid")
// ErrMagnet : Error for incorrect magnet used by api
var ErrMagnet = errors.New("incorrect magnet")

Voir le fichier

@ -2,11 +2,12 @@ package torrentService
import (
"errors"
elastic "gopkg.in/olivere/elastic.v5"
"net/http"
"strconv"
"strings"
elastic "gopkg.in/olivere/elastic.v5"
"github.com/NyaaPantsu/nyaa/config"
"github.com/NyaaPantsu/nyaa/db"
"github.com/NyaaPantsu/nyaa/model"
@ -99,7 +100,17 @@ func GetTorrentByID(id string) (torrent model.Torrent, err error) {
func GetRawTorrentByID(id uint) (torrent model.Torrent, err error) {
err = nil
if db.ORM.Where("torrent_id = ?", id).Find(&torrent).RecordNotFound() {
err = errors.New("Article is not found")
err = errors.New("Torrent is not found")
}
return
}
// GetRawTorrentByHash : Get torrent with id without user or comments
// won't fetch user or comments
func GetRawTorrentByHash(hash string) (torrent model.Torrent, err error) {
err = nil
if db.ORM.Where("torrent_hash = ?", hash).Find(&torrent).RecordNotFound() {
err = errors.New("Torrent is not found")
}
return
}

Voir le fichier

@ -11,7 +11,7 @@ import (
"github.com/NyaaPantsu/nyaa/db"
"github.com/NyaaPantsu/nyaa/model"
"github.com/NyaaPantsu/nyaa/util/email"
"github.com/NyaaPantsu/nyaa/util/languages"
"github.com/NyaaPantsu/nyaa/util/publicSettings"
"github.com/NyaaPantsu/nyaa/util/timeHelper"
"github.com/gorilla/securecookie"
)
@ -20,7 +20,7 @@ var verificationHandler = securecookie.New(config.EmailTokenHashKey, nil)
// SendEmailVerification sends an email verification token via email.
func SendEmailVerification(to string, token string) error {
T, err := languages.GetDefaultTfunc()
T, err := publicSettings.GetDefaultTfunc()
if err != nil {
return err
}

Voir le fichier

@ -3,6 +3,6 @@
<div>
<h1>{{call $.T "404_not_found"}}</h1>
<br />
<img class="center-block center-image" src="/img/404.svg"></img>
<img class="center-block center-image" src="/img/404.svg" />
</div>
{{end}}

Voir le fichier

@ -46,7 +46,7 @@
<h2 id="trackers">{{call $.T "which_trackers_do_you_recommend"}}</h2>
<p>{{call $.T "answer_which_trackers_do_you_recommend"}}</p>
<pre>udp://tracker.doko.moe:6969
udp://zer0day.to:1337/announce
udp://tracker.zer0day.to:1337/announce
udp://tracker.leechers-paradise.org:6969
udp://explodie.org:6969
udp://tracker.opentrackr.org:1337

Voir le fichier

@ -11,14 +11,14 @@
<form role="form" method="POST">
<label class="input-label">{{call $.T "api_token" }}:</label>
<p style="font-family: monospace;">{{.APIToken}}</p>
<a class="form-input" href="{{ genRoute "user_profile_apireset" "id" (print .ID) "username" .Username }}">Reset Api key</a> <br> <br>
<a class="form-input up-input" href="{{ genRoute "user_profile_apireset" "id" (print .ID) "username" .Username }}">Reset Api key</a> <br> <br>
<label class="input-label">{{ call $.T "email_address" }}:</label> <br>
<input class="form-input" type="text" name="email" id="email" value="{{.Email}}"> <br>
<input class="form-input up-input" type="text" name="email" id="email" value="{{.Email}}"> <br>
{{ range (index $.FormErrors "email")}}
<p class="text-error">{{ . }}</p>
{{end}}
<label class="input-label">{{ call $.T "language"}}:</label> <br>
<select id="language" name="language" class="form-input">
<select id="language" name="language" class="form-input up-input">
{{ $userLanguage := .Language }}
{{ range $tag, $translatedName := $.Languages }}
<option value="{{ $tag }}" {{ if or (eq $userLanguage $tag) (and (eq $userLanguage "") (eq $tag getDefaultLanguage)) }}selected{{end}}>{{ $translatedName }} {{if eq $tag getDefaultLanguage}}({{ call $.T "default" }}){{end}}</option>
@ -29,18 +29,18 @@
{{end}}
{{ if not (HasAdmin $.User)}}
<label class="input-label">{{ call $.T "current_password"}}:</label> <br>
<input class="form-input" name="current_password" id="current_password" type="password"> <br>
<input class="form-input up-input up-input" name="current_password" id="current_password" type="password"> <br>
{{ range (index $.FormErrors "current_password")}}
<p class="text-error">{{ . }}</p>
{{end}}
{{end}}
<label class="input-label">{{ call $.T "password"}}:</label> <br>
<input class="form-input" name="password" id="password" type="password"> <br>
<input class="form-input up-input up-input" name="password" id="password" type="password"> <br>
{{ range (index $.FormErrors "password")}}
<p class="text-error">{{ . }}</p>
{{end}}
<label class="input-label">{{ call $.T "confirm_password"}}:</label> <br>
<input class="form-input" name="password_confirmation" id="password_confirmation" type="password"> <br>
<input class="form-input up-input up-input" name="password_confirmation" id="password_confirmation" type="password"> <br>
{{ range (index $.FormErrors "password_confirmation")}}
<p class="text-error">{{ . }}</p>
{{end}}
@ -48,7 +48,7 @@
{{ with .Settings }}
{{ if DefaultUserSettings "new_torrent"}}
<label class="input-label">{{ call $.T "new_torrent_settings" }}:</label> <br>
<select id="new_torrent" name="new_torrent" class="form-control">
<select id="new_torrent" name="new_torrent" class="form-input up-input">
<option value="0" {{ if not (.Get "new_torrent") }}selected{{end}}>{{ call $.T "no"}}</option>
<option value="1" {{ if .Get "new_torrent" }}selected{{end}}>{{ call $.T "yes"}}</option>
</select> <br>
@ -58,7 +58,7 @@
{{end}}
{{ if DefaultUserSettings "new_torrent_email"}}
<label class="input-label">{{ call $.T "new_torrent_email_settings" }}:</label> <br>
<select id="new_torrent_email" name="new_torrent_email" class="form-control">
<select id="new_torrent_email" name="new_torrent_email" class="form-input up-input">
<option value="0" {{ if not (.Get "new_torrent_email") }}selected{{end}}>{{ call $.T "no"}}</option>
<option value="1" {{ if .Get "new_torrent_email"}}selected{{end}}>{{ call $.T "yes"}}</option>
</select> <br>
@ -68,7 +68,7 @@
{{end}}
{{ if DefaultUserSettings "new_comment"}}
<label class="input-label">{{ call $.T "new_comment_settings" }}:</label> <br>
<select id="new_comment" name="new_comment" class="form-control">
<select id="new_comment" name="new_comment" class="form-input up-input">
<option value="0" {{ if not (.Get "new_comment") }}selected{{end}}>{{ call $.T "no"}}</option>
<option value="1" {{ if .Get "new_comment" }}selected{{end}}>{{ call $.T "yes"}}</option>
</select> <br>
@ -78,7 +78,7 @@
{{end}}
{{ if DefaultUserSettings "new_comment_email"}}
<label class="input-label">{{ call $.T "new_comment_email_settings" }}:</label> <br>
<select id="new_comment_email" name="new_comment_email" class="form-control">
<select id="new_comment_email" name="new_comment_email" class="form-input up-input">
<option value="0" {{ if not (.Get "new_comment_email") }}selected{{end}}>{{ call $.T "no"}}</option>
<option value="1" {{ if .Get "new_comment_email" }}selected{{end}}>{{ call $.T "yes"}}</option>
</select> <br>
@ -88,7 +88,7 @@
{{end}}
{{ if DefaultUserSettings "new_responses"}}
<label class="input-label">{{ call $.T "new_responses_settings" }}:</label> <br>
<select id="new_responses" name="new_responses" class="form-control">
<select id="new_responses" name="new_responses" class="form-input up-input">
<option value="0" {{ if not (.Get "new_responses") }}selected{{end}}>{{ call $.T "no"}}</option>
<option value="1" {{ if .Get "new_responses" }}selected{{end}}>{{ call $.T "yes"}}</option>
</select> <br>
@ -98,7 +98,7 @@
{{end}}
{{ if DefaultUserSettings "new_responses_email"}}
<label class="input-label">{{ call $.T "new_responses_email_settings" }}:</label> <br>
<select id="new_responses_email" name="new_responses_email" class="form-control">
<select id="new_responses_email" name="new_responses_email" class="form-input up-input">
<option value="0" {{ if not (.Get "new_responses_email") }}selected{{end}}>{{ call $.T "no"}}</option>
<option value="1" {{ if .Get "new_responses_email" }}selected{{end}}>{{ call $.T "yes"}}</option>
</select> <br>
@ -108,7 +108,7 @@
{{end}}
{{ if DefaultUserSettings "new_follower"}}
<label class="input-label">{{ call $.T "new_follower_settings" }}:</label> <br>
<select id="new_follower" name="new_follower" class="form-control">
<select id="new_follower" name="new_follower" class="form-input up-input">
<option value="0" {{ if not (.Get "new_follower") }}selected{{end}}>{{ call $.T "no"}}</option>
<option value="1" {{ if .Get "new_follower" }}selected{{end}}>{{ call $.T "yes"}}</option>
</select> <br>
@ -118,7 +118,7 @@
{{end}}
{{ if DefaultUserSettings "new_follower_email"}}
<label class="input-label">{{ call $.T "new_follower_email_settings" }}:</label> <br>
<select id="new_follower_email" name="new_follower_email" class="form-control">
<select id="new_follower_email" name="new_follower_email" class="form-input up-input">
<option value="0" {{ if not (.Get "new_follower_email") }}selected{{end}}>{{ call $.T "no"}}</option>
<option value="1" {{ if .Get "new_follower_email"}}selected{{end}}>{{ call $.T "yes"}}</option>
</select> <br>
@ -128,7 +128,7 @@
{{end}}
{{ if DefaultUserSettings "followed"}}
<label class="input-label">{{ call $.T "followed_settings" }}:</label> <br>
<select id="followed" name="followed" class="form-control">
<select id="followed" name="followed" class="form-input up-input">
<option value="0" {{ if not (.Get "followed") }}selected{{end}}>{{ call $.T "no"}}</option>
<option value="1" {{ if .Get "followed" }}selected{{end}}>{{ call $.T "yes"}}</option>
</select><br>
@ -138,7 +138,7 @@
{{end}}
{{ if DefaultUserSettings "followed_email"}}
<label class="input-label">{{ call $.T "followed_email_settings" }}:</label> <br>
<select id="followed_email" name="followed_email" class="form-control">
<select id="followed_email" name="followed_email" class="form-input up-input">
<option value="0" {{ if not (.Get "followed_email") }}selected{{end}}>{{ call $.T "no"}}</option>
<option value="1" {{ if .Get "followed_email" }}selected{{end}}>{{ call $.T "yes"}}</option>
</select> <br>
@ -150,12 +150,12 @@
{{ if HasAdmin $.User}}
<h3>{{ call $.T "moderation"}}</h3>
<label class="input-label">{{ call $.T "username"}}:</label> <br>
<input class="form-control" name="username" id="username" type="text" value="{{.Username}}">
<input class="form-input up-input" name="username" id="username" type="text" value="{{.Username}}">
{{ range (index $.FormErrors "username")}}
<p class="text-error">{{ . }}</p>
{{end}}
<label class="input-label">{{ call $.T "role" }}:</label>
<select id="status" name="status" class="form-control">
<select id="status" name="status" class="form-input up-input">
<option value="-1" {{ if eq .Status -1 }}selected{{end}}>{{ call $.T "banned"}}</option>
<option value="0" {{ if eq .Status 0 }}selected{{end}}>{{ call $.T "member"}} ({{ call $.T "default" }})</option>
<option value="1" {{ if eq .Status 1 }}selected{{end}}>{{ call $.T "trusted_member"}}</option>
@ -168,9 +168,9 @@
{{end}}
{{end}}
<label class="input-label"></label>
<input type="submit" class="btn btn-primary" name="save" value="{{ call $.T "save_changes"}}">
<input type="submit" class="form-input" name="save" value="{{ call $.T "save_changes"}}">
<span></span>
<input type="reset" class="btn btn-default" value="{{ call $.T "cancel"}}">
<input type="reset" class="form-input" value="{{ call $.T "cancel"}}">
</form>
</div>
{{ if CurrentOrAdmin $.User .ID }}

Voir le fichier

@ -44,7 +44,7 @@
<td class="tr-size hide-xs">
{{ fileSize .Filesize $.T }}
</td>
<td class="tr-date home-td date-short hide-xs">{{.Date}}</td>
<td class="tr-date date-short hide-xs">{{.Date}}</td>
</tr>
{{end}}
{{end}}

Voir le fichier

@ -32,7 +32,12 @@
<option value="4" {{if eq .Status 4}}selected{{end}}>A+</option>
</select>
</div>
{{ if $.User }}
<p>
<input type="checkbox" name="hidden" id="hidden" {{ if .Hidden }}checked{{end}}>
<label for="hidden">{{call $.T "mark_as_hidden"}}</label>
</p>
{{ end }}
<div class="form-group">
<label for="website_link">{{call $.T "website_link"}}</label>
<input name="website_link" id="website_link" class="form-control" type="text" value="{{.WebsiteLink}}">

Voir le fichier

@ -12,24 +12,18 @@
<!-- RSS Feed with Context -->
<link href="{{ block "rss_link" . }}{{ genRouteWithQuery "feed" .URL }}{{end}}" rel="alternate" type="application/rss+xml" title="Nyaa Pantsu - {{block "rsstitle" .}}Last torrents{{end}} RSS Feed" />
<!-- do NOT move -->
<link rel="stylesheet" href="https://cdn.jsdelivr.net/simplemde/latest/simplemde.min.css">
<link rel="stylesheet" id="style" href="{{.URL.Parse "/css/main.css"}}?v=3">
<link rel="stylesheet" id="theme" href="">
<!-- Base theme -->
<link rel="stylesheet" id="style" href="{{.URL.Parse "/css/main.css"}}?v=2">
<!-- User selected theme, if any -->
{{if $.Theme}}<link rel="stylesheet" id="theme" href="/css/{{$.Theme}}.css">{{end}}
<!-- Search Box for Google -->
<script type="application/ld+json">{"@context":"https://schema.org","@type":"WebSite","url":"https://nyaa.pantsu.cat/","potentialAction":{"@type":"SearchAction","target":"https://nyaa.pantsu.cat/search?q={search_term_string}","query-input":"required name=search_term_string"}}</script>
<script>
// We need this inline javascript for preventing theme flickering
function changeTheme(opt) {
theme = opt.value;
localStorage.setItem("theme", theme);
document.getElementById("theme").href = "/css/" + theme;
console.log(theme);
}
function toggleMascot(btn) {
var state= btn.value;
if (state == "hide") {
@ -42,24 +36,10 @@
btn.value = "hide";
}
}
function setTheme() {
var themeFromStorage = localStorage.getItem('theme');
document.getElementById('theme').href = "/css/" + themeFromStorage;
window.addEventListener("load", () => {
var selectOptions = document.getElementById("theme_select").children
for (var option of selectOptions) {
option.selected = option.value == themeFromStorage;
}
});
}
</script>
<!-- Fix theme switching for google chrome where onload doesn't work -->
<script type="text/javascript">
setTheme();
</script>
{{ block "additional_header" .}}{{end}}
</head>
<body onload="setTheme();">
<body>
<nav id="header" class="header">
<div class="container">
<div class="h-left">
@ -93,14 +73,16 @@
{{block "content" .}}{{call $.T "nothing_here"}}{{end}}
</div>
<div id="mascot" class="hide-xs" onclick="playVoice();"></div>
{{ if eq .Theme "tomorrow" }}
<audio id="explosion" hidden preload="none">
<source src="https://megumin.love/sounds/explosion.mp3" type="audio/mpeg">
</audio>
{{ else }}
<audio id="nyanpassu" hidden preload="none">
<source src="https://a.doko.moe/sewang.mp3" type="audio/mpeg">
</audio>
<audio id="explosion" hidden preload="none">
<source src="https://megumin.love/sounds/explosion.mp3" type="audio/mpeg">
</audio>
<div class="pagination">
{{end}}
<div class="pagination">
{{ genNav .Navigation .URL 15 }}
</div>
@ -108,15 +90,8 @@
<div class="container footer center">
<div class="footer-opt">
<select onchange="changeTheme(this.options[this.selectedIndex])" name="Theme" id="theme_select" class="form-input">
<option value="">Default</option>
<option value="g.css">/g/ Anon</option>
<option value="tomorrow.css">Tomorrow</option>
</select>
<button class="form-input btn" onclick="toggleMascot(this)" value="hide"><span class="oi" data-glyph="eye"></span> Mascot</button>
<p><a href="/language">Change Language</a></p>
<p><a href="/settings">Change Settings</a></p>
</div>
<span><i>Powered by <a href="#">NyaaPantsu</a></i></span>

Voir le fichier

@ -11,8 +11,18 @@
<option value="{{ $tag }}" {{ if eq $currentLanguage $tag }}selected{{end}}>{{ $translatedName }}</option>
{{ end }}
</select>
<h3>{{call $.T "theme"}}</h3>
<select id="theme-selector" name="theme" class="form-input" onchange="switchThemes()">
<option value="{{$.Theme}}" selected>{{call $.T "select"}}</option>
<option value="g">/g/</option>
<option value="tomorrow">Tomorrow</option>
<option value="">None</option>
</select>
</br>
</br>
<button type="submit" class="form-input btn">{{call $.T "save_changes"}}</button>
</div>
</form>
<div style="padding-bottom: 1em"></div>
</div>

Voir le fichier

@ -8,7 +8,7 @@
{{end}}
<h3>{{call $.T "name"}}</h3>
<input type="text" name="name" id="name" class="form-input up-input" placeholder="{{call $.T "file_name"}}" value="{{.Name}}" autofocus required>
<input type="text" name="name" id="name" class="form-input up-input" placeholder="{{call $.T "file_name"}}" value="{{.Name}}" autofocus>
<h3>{{call $.T "torrent_file"}}</h3>
<input type="file" name="torrent" id="torrent" class="up-input" accept=".torrent">
@ -29,7 +29,12 @@
<input type="checkbox" name="remake" id="remake" >
<label for="remake">{{call $.T "mark_as_remake"}}</label>
</p>
{{ if $.User }}
<p>
<input type="checkbox" name="hidden" id="hidden" >
<label for="hidden">{{call $.T "mark_as_hidden"}}</label>
</p>
{{ end }}
<h3>{{call $.T "website_link"}}</h3>
<input name="website_link" id="website_link" class="form-input up-input" type="text" value="{{.WebsiteLink}}">

Voir le fichier

@ -26,7 +26,12 @@
<input type="checkbox" name="remake" id="remake" {{ if .Remake }}checked{{end}}>
<label for="remake">{{call $.T "mark_as_remake"}}</label>
</div>
{{ if $.User }}
<p>
<input type="checkbox" name="hidden" id="hidden" {{ if .Hidden }}checked{{end}}>
<label for="hidden">{{call $.T "mark_as_hidden"}}</label>
</p>
{{ end }}
<div class="form-group">
<label for="website_link">{{call $.T "website_link"}}</label>
<input name="website_link" id="website_link" class="form-control" type="text" value="{{.WebsiteLink}}">

Voir le fichier

@ -43,15 +43,15 @@
<table>
<tr class="torrent-info-row">
<td class="torrent-info-td torrent-info-label">{{ call $.T "category" }}:</td><td class="torrent-info-td torrent-info-data" style="padding:0"><a href="{{$.URL.Parse (printf "/search?c=%s_%s" .Category .SubCategory) }}">{{ if Sukebei}}{{ call $.T (CategoryName .Category .SubCategory) }}{{else}}{{ call $.T (CategoryName .Category .SubCategory) }}{{end}}</a> <br></td>
<td class="torrent-info-td torrent-info-label">{{ call $.T "date" }}:</td><td class="torrent-info-td date-short">{{.Date}}</td>
<td class="torrent-info-td torrent-info-label">{{ call $.T "date" }}:</td><td class="torrent-info-td date-full">{{.Date}}</td>
</tr>
<tr class="torrent-info-row">
<td class="torrent-info-td torrent-info-label">{{ call $.T "uploaded_by" }}:</td><td class="torrent-view-td torrent-info-data"><a href="{{ genRoute "user_profile" "id" ( print .UploaderID ) "username" (print .UploaderName) }}">{{.UploaderName}}</a></td>
<td class="torrent-info-td torrent-info-label">{{call $.T "seeders"}}:</td><td class="torrent-info-td">{{if .LastScrape.IsZero}}{{call $.T "unknown"}}{{else}}{{.Seeders}}{{end}}</td>
<td class="torrent-info-td torrent-info-label">{{call $.T "seeders"}}:</td><td class="tr-se torrent-info-td">{{if .LastScrape.IsZero}}{{call $.T "unknown"}}{{else}}{{.Seeders}}{{end}}</td>
</tr>
<tr class="torrent-info-row">
<td class="torrent-info-td torrent-info-label">{{ call $.T "website_link" }}:</td><td class="torrent-view-td torrent-info-data">{{if ne .WebsiteLink ""}}<a href="{{.WebsiteLink}}">{{.WebsiteLink}}</a>{{else}}<a href="//nyaa.pantsu.cat">nyaa.pantsu.cat{{end}}</td>
<td class="torrent-info-td torrent-info-label">{{call $.T "leechers"}}:</td><td class="torrent-info-td">{{if .LastScrape.IsZero}}{{call $.T "unknown"}}{{else}}{{.Leechers}}{{end}}</td>
<td class="torrent-info-td torrent-info-label">{{call $.T "leechers"}}:</td><td class="tr-le torrent-info-td">{{if .LastScrape.IsZero}}{{call $.T "unknown"}}{{else}}{{.Leechers}}{{end}}</td>
</tr>
<tr class="torrent-info-row">
<td class="torrent-info-td torrent-info-label">{{call $.T "hash"}}:</td><td style="font-family: monospace;" class="torrent-view-td torrent-info-data">{{.Hash}}</td>
@ -59,12 +59,14 @@
</tr>
<tr class="torrent-info-row">
<td class="torrent-info-td torrent-info-label">{{call $.T "size"}}:</td><td class="torrent-view-td torrent-info-data">{{ fileSize .Filesize $.T }}</td>
<td class="torrent-info-td torrent-info-label">{{call $.T "last_scraped"}}</td><td class="torrent-info-td">{{if not .LastScrape.IsZero}}{{formatDateRFC .LastScrape}}{{else}}{{call $.T "unknown"}}{{end}}</td>
<td class="torrent-info-td torrent-info-label">{{call $.T "last_scraped"}}</td><td class="torrent-info-td{{if not .LastScrape.IsZero}} date-full">{{formatDateRFC .LastScrape}}{{else}}">{{call $.T "unknown"}}{{end}}</td>
</tr>
</table>
<div class="torrent-buttons">
<a href="{{.Magnet}}" class="form-input">{{call $.T "magnet_link"}}</a>
{{ if ne .TorrentLink ""}}
<a href="{{.TorrentLink}}" class="form-input">{{call $.T "torrent_file"}}</a>
{{end}}
{{ if gt $.User.ID 0}}
<script>
function reportPopup() {
@ -97,9 +99,9 @@
<div class="torrent-info-box" id="filelist">
{{ if gt (len .FileList) 0 }}
{{/* how do i concat lol */}}
<table>
<table class="table-filelist">
<thead>
<th style="width: 70%">{{call $.T "filename"}}</th>
<th style="width: 80%">{{call $.T "filename"}}</th>
<th>{{call $.T "size"}}</th>
</thead>
<tbody>

Voir le fichier

@ -37,15 +37,15 @@
},
{
"id": "email_address",
"translation": "Adresse email"
"translation": "Adresse email "
},
{
"id": "password",
"translation": "Mot de passe"
"translation": "Mot de passe "
},
{
"id": "confirm_password",
"translation": "Confirmer le mot de passe"
"translation": "Confirmer le mot de passe "
},
{
"id": "i_agree",
@ -141,7 +141,7 @@
},
{
"id": "category",
"translation": "Catégorie"
"translation": "Catégorie "
},
{
"id": "name",
@ -149,7 +149,7 @@
},
{
"id": "date",
"translation": "Date"
"translation": "Date "
},
{
"id": "size",
@ -537,11 +537,15 @@
},
{
"id": "hash",
"translation": "Info Hash"
"translation": "Info Hash "
},
{
"id": "description",
"translation": "Description"
},
{
"id": "no_description",
"translation": "Aucune description disponible."
},
{
"id": "comments",
@ -565,11 +569,11 @@
},
{
"id": "language",
"translation": "Langue"
"translation": "Langue "
},
{
"id": "current_password",
"translation": "Mot de passe actuel"
"translation": "Mot de passe actuel "
},
{
"id": "role",
@ -593,7 +597,7 @@
},
{
"id": "api_token",
"translation": "Authentifieur d'API"
"translation": "Authentifieur d'API "
},
{
"id": "save_changes",
@ -657,15 +661,15 @@
},
{
"id": "seeders",
"translation": "Seeders"
"translation": "Seeders "
},
{
"id": "leechers",
"translation": "Leechers"
"translation": "Leechers "
},
{
"id": "completed",
"translation": "Téléchargements"
"translation": "Téléchargements "
},
{
"id": "change_language",
@ -685,19 +689,23 @@
},
{
"id": "website_link",
"translation": "Site web"
"translation": "Site web "
},
{
"id": "files",
"translation": "Liste des fichiers"
},
{
"id": "no_files",
"translation": "Aucun fichier trouvé."
},
{
"id": "filename",
"translation": "Nom du fichier"
},
{
"id": "uploaded_by",
"translation": "Uploadé par"
"translation": "Uploadé par "
},
{
"id": "download_btn",
@ -757,7 +765,7 @@
},
{
"id": "last_scraped",
"translation": "Dernier scrape : "
"translation": "Dernier scrape :"
},
{
"id": "server_status_link",

Voir le fichier

@ -20,115 +20,115 @@
"translation": "Kattints az alábbi linkre jelszavad visszaállításához."
},
{
"id":"register_title",
"id": "register_title",
"translation": "Új felhasználói fiók létrehozása"
},
{
"id":"signup_box_title",
"id": "signup_box_title",
"translation": "Kérlek Regisztrálj <small>Ingyenes, és mindig is az lesz.</small>"
},
{
"id":"username",
"id": "username",
"translation": "Felhasználónév"
},
{
"id":"email_address_or_username",
"id": "email_address_or_username",
"translation": "E-mail Cím vagy Felhasználónév"
},
{
"id":"email_address",
"id": "email_address",
"translation": "E-mail Cím"
},
{
"id":"password",
"id": "password",
"translation": "Jelszó"
},
{
"id":"confirm_password",
"id": "confirm_password",
"translation": "Jelszó mégegyszer"
},
{
"id":"i_agree",
"id": "i_agree",
"translation": "Beleegyezek"
},
{
"id":"terms_conditions_confirm",
"id": "terms_conditions_confirm",
"translation": "A <strong class=\"label label-primary\">Regisztráció</strong>-ra kattintva beleegyezel az oldal <a href=\"#\" data-toggle=\"modal\" data-target=\"#t_and_c_m\">Felhasználási Feltételei</a>-be, és a Cookie-k használatába."
},
{
"id":"signin",
"id": "signin",
"translation": "Bejelentkezés"
},
{
"id":"register",
"id": "register",
"translation": "Regisztráció"
},
{
"id":"terms_conditions",
"id": "terms_conditions",
"translation": "Felhasználási Feltételek"
},
{
"id":"terms_conditions_full",
"id": "terms_conditions_full",
"translation": "Valami Szar."
},
{
"id":"remember_me",
"id": "remember_me",
"translation": "Emlékezz Rám"
},
{
"id":"forgot_password",
"id": "forgot_password",
"translation": "Elfelejtett Jelszó?"
},
{
"id":"sign_in_box_title",
"id": "sign_in_box_title",
"translation": "Kérlek Jelentkezz Be"
},
{
"id":"sign_in_title",
"id": "sign_in_title",
"translation": "Bejelentkezés"
},
{
"id":"register_success_title",
"id": "register_success_title",
"translation": "Sikeres Regisztráció"
},
{
"id":"sign_up_success",
"id": "sign_up_success",
"translation": "Köszönjük, hogy regisztráltál!"
},
{
"id":"verify_success",
"id": "verify_success",
"translation": "<i style=\"color:limegreen\" class=\"glyphicon glyphicon-ok-circle\"></i>A felhasználói fiókod aktiválásra került."
},
{
"id":"signup_verification_email",
"id": "signup_verification_email",
"translation": "Végezetül kérlek nézd meg a bejövő e-mailjeidet (a Spam mappát is!) az Ellenörző E-mail miatt."
},
{
"id":"signup_verification_noemail",
"id": "signup_verification_noemail",
"translation": "Sikeres Regisztráció, mostmár használhatod a felhasználói fiókodat."
},
{
"id":"settings",
"id": "settings",
"translation": "Fiók Beállításai"
},
{
"id":"torrents",
"id": "torrents",
"translation": "Torrentek"
},
{
"id":"follow",
"id": "follow",
"translation": "Követés"
},
{
"id":"profile_page",
"id": "profile_page",
"translation": "%s Profilja"
},
{
"id":"see_more_torrents_from",
"id": "see_more_torrents_from",
"translation": "További torrentek megtekintése %s-től "
},
{
"id":"category",
"id": "category",
"translation": "Kategória"
},
{
@ -610,5 +610,293 @@
{
"id": "language_code",
"translation": "hu-hu"
},
{
"id": "delete",
"translation": "Törlés"
},
{
"id": "website_link",
"translation": "Oldal linkje"
},
{
"id": "files",
"translation": "Fájlok"
},
{
"id": "no_files",
"translation": "Nincsenek meg a fájlok? Na, az meg hogy lehet?"
},
{
"id": "filename",
"translation": "Fájlnév"
},
{
"id": "uploaded_by",
"translation": "Feltöltötte: "
},
{
"id": "download_btn",
"translation": "Letöltés!"
},
{
"id": "report_btn",
"translation": "Bejelentés"
},
{
"id": "are_you_sure",
"translation": "Biztos vagy benne?"
},
{
"id": "report_torrent_number",
"translation": "#%s számú torránt bejelentése"
},
{
"id": "report_type",
"translation": "Bejelentés jellege"
},
{
"id": "illegal_content",
"translation": "Illegális tartalom"
},
{
"id": "spam_garbage",
"translation": "Spam / Szemét"
},
{
"id": "wrong_category",
"translation": "Hibás kategória"
},
{
"id": "duplicate_deprecated",
"translation": "Másolat / elavult"
},
{
"id": "captcha",
"translation": "Captcha"
},
{
"id": "file_name",
"translation": "Fájlnév"
},
{
"id": "cancel",
"translation": "Mégse"
},
{
"id": "please_include_our_tracker",
"translation": "Kérlek a trackerek között add meg a udp://tracker.doko.moe:6969-et is."
},
{
"id": "unknown",
"translation": "Ismeretlen"
},
{
"id": "last_scraped",
"translation": "legutóbb kiselejtezett: "
},
{
"id": "server_status_link",
"translation": "Itt találhatod meg a szerver állapotát"
},
{
"id": "no_database_dumps_available",
"translation": "Jelenleg nincsenek adatbázis dumpok. "
},
{
"id": "clear_notifications",
"translation": "Értesítések törlése"
},
{
"id": "notifications_cleared",
"translation": "Értesítések törölve!"
},
{
"id": "my_notifications",
"translation": "Értesítéseim"
},
{
"id": "new_torrent_uploaded",
"translation": "Új torrent: \"%s\". Feltöltötte: %s"
},
{
"id": "preferences",
"translation": "Beállítások"
},
{
"id": "new_torrent_settings",
"translation": "Értesíts, ha egy követett felhasználó új torrentet tölt fel."
},
{
"id": "new_torrent_email_settings",
"translation": "Értesíts e-mailben, ha egy követett felhasználó új torrentet tölt fel."
},
{
"id": "new_comment_settings",
"translation": "Értesíts, ha a torrentemre új megjegyzés érkezik"
},
{
"id": "new_comment_email_settings",
"translation": "Értesíts e-mailben, ha a torrentemre új megjegyzés érkezik"
},
{
"id": "new_responses_settings",
"translation": "Értesíts, ha válasz érkezik az egyik megjegyzésemre"
},
{
"id": "new_responses_email_settings",
"translation": "Értesíts e-mailben, ha válasz érkezik az egyik megjegyzésemre"
},
{
"id": "new_follower_settings",
"translation": "Értesíts, ha valaki elkezd követni."
},
{
"id": "new_follower_email_settings",
"translation": "Értesíts e-mailban, ha valaki elkezd követni."
},
{
"id": "followed_settings",
"translation": "Értesíts, ha elkezdek valakit követni"
},
{
"id": "followed_email_settings",
"translation": "Értesíts e-mailben, ha elkezdek valakit követni"
},
{
"id": "yes",
"translation": "Igen"
},
{
"id": "no",
"translation": "Nem"
},
{
"id": "new_comment_on_torrent",
"translation": "Új komment a torrenten: \"%s\""
},
{
"id": "no_action_selected",
"translation": "Meg kell adnod, hogy mit akarsz csinálni a kijelöléssel."
},
{
"id": "no_move_location_selected",
"translation": "Té ném mégmondání hová vinni kijelulés"
},
{
"id": "select_one_element",
"translation": "Legalább egy elemet ki kell választanod"
},
{
"id": "torrent_moved",
"translation": "Torrent %s elmozdítva!"
},
{
"id": "no_status_exist",
"translation": "Nincs olyan állapot, hogy %d."
},
{
"id": "torrent_deleted",
"translation": "Torrent %s kitörölve!"
},
{
"id": "no_action_exist",
"translation": "Nincs olyan művelet, hogy %s."
},
{
"id": "torrent_not_exist",
"translation": "Nem létezik torrent %s azonosítóval."
},
{
"id": "something_went_wrong",
"translation": "Valami elromlott..."
},
{
"id": "nb_torrents_updated",
"translation": "%d torrent feltöltve."
},
{
"id": "torrent_updated",
"translation": "Torrent részletek frissítve."
},
{
"id": "fail_torrent_update",
"translation": "Nem sikerült frissíteni a torrentet."
},
{
"id": "bad_captcha",
"translation": "Hibás captcha."
},
{
"id": "comment_empty",
"translation": "Üres megjegyzés."
},
{
"id": "no_owner_selected",
"translation": "Szükség van egy új torrent tulajra."
},
{
"id": "no_category_selected",
"translation": "Nincs kijelölve kategória"
},
{
"id": "no_user_found_id",
"translation": "Az adatbázisban nincs felhasználó %d azonosítóval."
},
{
"id": "invalid_torrent_category",
"translation": "Ez a kategória nem létezik."
},
{
"id": "torrent_owner_changed",
"translation": "\"%s\" torrent tulaját sikeresen lecserélted."
},
{
"id": "torrent_category_changed",
"translation": "\"%s\" torrent kategóriájáját sikeresen megváltoztattad."
},
{
"id": "torrent_reports_deleted",
"translation": "\"%s\" torrent bejelentéseit sikeresen kitörölted."
},
{
"id": "edit",
"translation": "Szerkesztés"
},
{
"id": "delete_definitely_torrent_warning",
"translation": "A fájlokat nem leszel képes visszaszerezni, viszont másokat sem tudsz megállítani attól, hogy újra feltöltsék."
},
{
"id": "delete_definitely",
"translation": "Biztosan töröld."
},
{
"id": "torrent_unblock",
"translation": "Felnyitás"
},
{
"id": "torrent_block",
"translation": "Lezárás"
},
{
"id": "torrent_deleted_definitely",
"translation": "A torrent ki lett törölve az adatbázisról."
},
{
"id": "torrent_unblocked",
"translation": "A torrent fel van nyitva."
},
{
"id": "torrent_blocked",
"translation": "A torrent le van zárva."
},
{
"id": "torrent_nav_notdeleted",
"translation": "A Torrentek nincsenek törölve"
},
{
"id": "torrent_nav_deleted",
"translation": "A Torrentek törölve lettek"
}
]

Voir le fichier

@ -4,7 +4,7 @@ import (
"fmt"
"net/http"
"github.com/NyaaPantsu/nyaa/util/languages"
"github.com/NyaaPantsu/nyaa/util/publicSettings"
"github.com/gorilla/context"
"github.com/nicksnyder/go-i18n/i18n"
)
@ -24,13 +24,13 @@ type Messages struct {
func GetMessages(r *http.Request) *Messages {
if rv := context.Get(r, MessagesKey); rv != nil {
mes := rv.(*Messages)
T, _ := languages.GetTfuncAndLanguageFromRequest(r)
T, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
mes.T = T
mes.r = r
return mes
}
context.Set(r, MessagesKey, &Messages{})
T, _ := languages.GetTfuncAndLanguageFromRequest(r)
T, _ := publicSettings.GetTfuncAndLanguageFromRequest(r)
return &Messages{make(map[string][]string), make(map[string][]string), r, T}
}

Voir le fichier

@ -1,4 +1,4 @@
package languages
package publicSettings
import (
"errors"
@ -133,6 +133,19 @@ func GetTfuncFromRequest(r *http.Request) TemplateTfunc {
}
}
// GetThemeFromRequest: Gets the user selected theme from the request
func GetThemeFromRequest(r *http.Request) string {
user, _ := getCurrentUser(r)
if user.ID > 0 {
return user.Theme
}
cookie, err := r.Cookie("theme")
if err == nil {
return cookie.Value
}
return ""
}
func getCurrentUser(r *http.Request) (model.User, error) {
if userRetriever == nil {
return model.User{}, errors.New("failed to get current user: no user retriever set")

Voir le fichier

@ -1,4 +1,4 @@
package languages
package publicSettings
import (
"path"