2017-07-16 17:20:35 +02:00
package templates
2017-05-05 03:53:38 +02:00
2017-05-05 06:07:45 +02:00
import (
"html/template"
"math"
"net/url"
"strconv"
2017-05-17 16:05:42 +02:00
"time"
2017-05-14 21:45:50 +02:00
2017-07-11 22:25:52 +02:00
"strings"
2017-06-28 13:42:38 +02:00
"github.com/CloudyKit/jet"
2017-05-17 07:58:40 +02:00
"github.com/NyaaPantsu/nyaa/config"
2017-06-29 13:15:23 +02:00
"github.com/NyaaPantsu/nyaa/models"
"github.com/NyaaPantsu/nyaa/models/torrents"
2017-07-02 16:54:55 +02:00
"github.com/NyaaPantsu/nyaa/utils/categories"
"github.com/NyaaPantsu/nyaa/utils/filelist"
2017-07-02 23:53:23 +02:00
"github.com/NyaaPantsu/nyaa/utils/format"
2017-07-02 16:54:55 +02:00
"github.com/NyaaPantsu/nyaa/utils/publicSettings"
"github.com/NyaaPantsu/nyaa/utils/torrentLanguages"
Consistency, formatting, error checking, cleanup, and a couple bug fixes (#245)
* Checkpoint: it builds
The config, db, model, network, os, and public packages have had some
fixes to glaringly obvious flaws, dead code removed, and stylistic
changes.
* Style changes and old code removal in router
Router needs a lot of work done to its (lack of) error handling.
* Dead code removal and style changes
Now up to util/email/email.go. After I'm finished with the initial sweep
I'll go back and fix error handling and security issues. Then I'll fix
the broken API. Then I'll go through to add documentation and fix code
visibility.
* Finish dead code removal and style changes
Vendored libraries not touched. Everything still needs security fixes
and documentation. There's also one case of broken functionality.
* Fix accidental find-and-replace
* Style, error checking, saftey, bug fix changes
* Redo error checking erased during merge
* Re-add merge-erased fix. Make Safe safe.
2017-05-10 04:34:40 +02:00
)
2017-05-05 03:53:38 +02:00
2017-05-25 21:54:58 +02:00
// FuncMap : Functions accessible in templates by {{ $.Function }}
2017-06-28 13:42:38 +02:00
func templateFunctions ( vars jet . VarMap ) jet . VarMap {
2017-07-19 21:33:07 +02:00
vars . Set ( "getRawQuery" , getRawQuery )
vars . Set ( "genSearchWithOrdering" , genSearchWithOrdering )
vars . Set ( "genSortArrows" , genSortArrows )
vars . Set ( "genNav" , genNav )
vars . Set ( "Sukebei" , config . IsSukebei )
vars . Set ( "getDefaultLanguage" , publicSettings . GetDefaultLanguage )
vars . Set ( "FlagCode" , flagCode )
vars . Set ( "getAvatar" , getAvatar )
2017-05-18 01:03:11 +02:00
2017-07-19 21:33:07 +02:00
vars . Set ( "formatDateRFC" , formatDateRFC )
vars . Set ( "GetHostname" , format . GetHostname )
vars . Set ( "GetCategories" , categories . GetSelect )
vars . Set ( "GetCategory" , getCategory )
vars . Set ( "CategoryName" , categoryName )
vars . Set ( "GetTorrentLanguages" , torrentLanguages . GetTorrentLanguages )
vars . Set ( "LanguageName" , languageName )
vars . Set ( "LanguageNameFromCode" , languageNameFromCode )
vars . Set ( "fileSize" , fileSize )
vars . Set ( "DefaultUserSettings" , defaultUserSettings )
vars . Set ( "makeTreeViewData" , makeTreeViewData )
vars . Set ( "lastID" , lastID )
vars . Set ( "getReportDescription" , getReportDescription )
vars . Set ( "genUploaderLink" , genUploaderLink )
vars . Set ( "genActivityContent" , genActivityContent )
vars . Set ( "contains" , contains )
return vars
}
func getRawQuery ( currentURL * url . URL ) string {
return currentURL . RawQuery
}
func genSearchWithOrdering ( currentURL * url . URL , sortBy string ) string {
values := currentURL . Query ( )
order := false //Default is DESC
sort := "2" //Default is Date (Actually ID, but Date is the same thing)
2017-05-20 01:10:16 +02:00
2017-07-19 21:33:07 +02:00
if _ , ok := values [ "order" ] ; ok {
order , _ = strconv . ParseBool ( values [ "order" ] [ 0 ] )
}
if _ , ok := values [ "sort" ] ; ok {
sort = values [ "sort" ] [ 0 ]
}
2017-05-18 01:03:11 +02:00
2017-07-19 21:33:07 +02:00
if sort == sortBy {
order = ! order //Flip order by repeat-clicking
} else {
order = false //Default to descending when sorting by something new
}
2017-05-13 18:53:54 +02:00
2017-07-19 21:33:07 +02:00
values . Set ( "sort" , sortBy )
values . Set ( "order" , strconv . FormatBool ( order ) )
2017-05-14 14:30:09 +02:00
2017-07-19 21:33:07 +02:00
u , _ := url . Parse ( "/search" )
u . RawQuery = values . Encode ( )
2017-05-15 02:01:04 +02:00
2017-07-19 21:33:07 +02:00
return u . String ( )
}
2017-05-18 01:03:11 +02:00
2017-07-19 21:33:07 +02:00
func genSortArrows ( currentURL * url . URL , sortBy string ) template . HTML {
values := currentURL . Query ( )
leftclass := "sortarrowdim"
rightclass := "sortarrowdim"
2017-05-18 01:03:11 +02:00
2017-07-19 21:33:07 +02:00
order := false
sort := "2"
if _ , ok := values [ "order" ] ; ok {
order , _ = strconv . ParseBool ( values [ "order" ] [ 0 ] )
}
if _ , ok := values [ "sort" ] ; ok {
sort = values [ "sort" ] [ 0 ]
}
if sort == sortBy {
if order {
rightclass = ""
} else {
leftclass = ""
2017-05-15 02:01:04 +02:00
}
2017-07-19 21:33:07 +02:00
}
2017-05-15 02:01:04 +02:00
2017-07-19 21:33:07 +02:00
arrows := "<span class=\"sortarrowleft " + leftclass + "\">▼</span><span class=\"" + rightclass + "\">▲</span>"
2017-05-15 02:01:04 +02:00
2017-07-19 21:33:07 +02:00
return template . HTML ( arrows )
}
2017-05-05 03:53:38 +02:00
2017-07-19 21:33:07 +02:00
func genNav ( nav Navigation , currentURL * url . URL , pagesSelectable int ) template . HTML {
var ret = ""
if nav . TotalItem > 0 {
maxPages := math . Ceil ( float64 ( nav . TotalItem ) / float64 ( nav . MaxItemPerPage ) )
2017-07-02 23:53:23 +02:00
2017-07-19 21:33:07 +02:00
if nav . CurrentPage - 1 > 0 {
url := "/" + nav . Route + "/1"
ret = ret + "<a id=\"page-prev\" href=\"" + url + "?" + currentURL . RawQuery + "\" aria-label=\"Previous\"><li><span aria-hidden=\"true\">«</span></li></a>"
2017-06-17 04:24:30 +02:00
}
2017-07-19 21:33:07 +02:00
startValue := 1
if nav . CurrentPage > pagesSelectable / 2 {
startValue = ( int ( math . Min ( ( float64 ( nav . CurrentPage ) + math . Floor ( float64 ( pagesSelectable ) / 2 ) ) , maxPages ) ) - pagesSelectable + 1 )
2017-05-22 18:25:04 +02:00
}
2017-07-19 21:33:07 +02:00
if startValue < 1 {
startValue = 1
2017-07-11 23:34:59 +02:00
}
2017-07-19 21:33:07 +02:00
endValue := ( startValue + pagesSelectable - 1 )
if endValue > int ( maxPages ) {
endValue = int ( maxPages )
}
for i := startValue ; i <= endValue ; i ++ {
pageNum := strconv . Itoa ( i )
url := "/" + nav . Route + "/" + pageNum
ret = ret + "<a aria-label=\"Page " + strconv . Itoa ( i ) + "\" href=\"" + url + "?" + currentURL . RawQuery + "\">" + "<li"
if i == nav . CurrentPage {
ret = ret + " class=\"active\""
2017-07-11 22:25:52 +02:00
}
2017-07-19 21:33:07 +02:00
ret = ret + ">" + strconv . Itoa ( i ) + "</li></a>"
}
if nav . CurrentPage < int ( maxPages ) {
url := "/" + nav . Route + "/" + strconv . Itoa ( nav . CurrentPage + 1 )
ret = ret + "<a id=\"page-next\" href=\"" + url + "?" + currentURL . RawQuery + "\" aria-label=\"Next\"><li><span aria-hidden=\"true\">»</span></li></a>"
2017-06-12 01:14:26 +02:00
}
2017-07-19 21:33:07 +02:00
itemsThisPageStart := nav . MaxItemPerPage * ( nav . CurrentPage - 1 ) + 1
itemsThisPageEnd := nav . MaxItemPerPage * nav . CurrentPage
if nav . TotalItem < itemsThisPageEnd {
itemsThisPageEnd = nav . TotalItem
2017-05-26 03:53:18 +02:00
}
2017-07-19 21:33:07 +02:00
ret = ret + "<p>" + strconv . Itoa ( itemsThisPageStart ) + "-" + strconv . Itoa ( itemsThisPageEnd ) + "/" + strconv . Itoa ( nav . TotalItem ) + "</p>"
}
return template . HTML ( ret )
}
2017-05-30 00:28:21 +02:00
2017-07-19 21:33:07 +02:00
func flagCode ( languageCode string ) string {
return publicSettings . Flag ( languageCode , true )
}
2017-05-30 00:28:21 +02:00
2017-07-19 21:33:07 +02:00
func getAvatar ( hash string , size int ) string {
return "https://www.gravatar.com/avatar/" + hash + "?s=" + strconv . Itoa ( size )
}
func formatDateRFC ( t time . Time ) string {
// because time.* isn't available in templates...
return t . Format ( time . RFC3339 )
}
func getCategory ( category string , keepParent bool ) categories . Categories {
cats := categories . GetSelect ( true , true )
found := false
categoryRet := categories . Categories { }
for _ , v := range cats {
if v . ID == category + "_" {
found = true
if keepParent {
categoryRet = append ( categoryRet , v )
2017-05-30 00:28:21 +02:00
}
2017-07-19 21:33:07 +02:00
} else if len ( v . ID ) <= 2 && len ( categoryRet ) > 0 {
break
} else if found {
categoryRet = append ( categoryRet , v )
}
}
return categoryRet
}
func categoryName ( category string , subCategory string ) string {
s := category + "_" + subCategory
if category , ok := categories . GetByID ( s ) ; ok {
return category . Name
}
return ""
}
func languageName ( lang publicSettings . Language , T publicSettings . TemplateTfunc ) string {
if strings . Contains ( lang . Name , "," ) {
langs := strings . Split ( lang . Name , ", " )
tags := strings . Split ( lang . Tag , ", " )
for k := range langs {
langs [ k ] = strings . Title ( publicSettings . Translate ( tags [ k ] , string ( T ( "language_code" ) ) ) )
2017-05-30 00:28:21 +02:00
}
2017-07-19 21:33:07 +02:00
return strings . Join ( langs , ", " )
}
return strings . Title ( lang . Translate ( T ( "language_code" ) ) )
}
func languageNameFromCode ( languageCode string , T publicSettings . TemplateTfunc ) string {
if strings . Contains ( languageCode , "," ) {
tags := strings . Split ( languageCode , ", " )
var langs [ ] string
for k := range tags {
langs = append ( langs , strings . Title ( publicSettings . Translate ( tags [ k ] , string ( T ( "language_code" ) ) ) ) )
2017-06-04 02:28:33 +02:00
}
2017-07-19 21:33:07 +02:00
return strings . Join ( langs , ", " )
}
return strings . Title ( publicSettings . Translate ( languageCode , string ( T ( "language_code" ) ) ) )
}
func fileSize ( filesize int64 , T publicSettings . TemplateTfunc ) template . HTML {
if filesize == 0 {
return T ( "unknown" )
}
return template . HTML ( format . FileSize ( filesize ) )
}
func defaultUserSettings ( s string ) bool {
return config . Get ( ) . Users . DefaultUserSettings [ s ]
}
func makeTreeViewData ( f * filelist . FileListFolder , nestLevel int , T publicSettings . TemplateTfunc , identifierChain string ) interface { } {
return struct {
Folder * filelist . FileListFolder
NestLevel int
T publicSettings . TemplateTfunc
IdentifierChain string
} { f , nestLevel , T , identifierChain }
}
func lastID ( currentURL * url . URL , torrents [ ] models . TorrentJSON ) int {
if len ( torrents ) == 0 {
return 0
}
values := currentURL . Query ( )
order := false
sort := "2"
if _ , ok := values [ "order" ] ; ok {
order , _ = strconv . ParseBool ( values [ "order" ] [ 0 ] )
}
if _ , ok := values [ "sort" ] ; ok {
sort = values [ "sort" ] [ 0 ]
}
lastID := 0
if sort == "2" || sort == "" {
if order {
lastID = int ( torrents [ len ( torrents ) - 1 ] . ID )
} else if len ( torrents ) > 0 {
lastID = int ( torrents [ 0 ] . ID )
2017-06-06 00:06:04 +02:00
}
2017-07-19 21:33:07 +02:00
}
return lastID
}
func getReportDescription ( d string , T publicSettings . TemplateTfunc ) string {
if d == "illegal" {
return "Illegal content"
} else if d == "spam" {
return "Spam / Garbage"
} else if d == "wrongcat" {
return "Wrong category"
} else if d == "dup" {
return "Duplicate / Deprecated"
}
return string ( T ( d ) )
}
func genUploaderLink ( uploaderID uint , uploaderName template . HTML , torrentHidden bool ) template . HTML {
uploaderID , username := torrents . HideUser ( uploaderID , string ( uploaderName ) , torrentHidden )
if uploaderID == 0 {
return template . HTML ( username )
}
url := "/user/" + strconv . Itoa ( int ( uploaderID ) ) + "/" + username
2017-06-28 13:42:38 +02:00
2017-07-19 21:33:07 +02:00
return template . HTML ( "<a href=\"" + url + "\">" + username + "</a>" )
}
func genActivityContent ( a models . Activity , T publicSettings . TemplateTfunc ) template . HTML {
return a . ToLocale ( T )
}
func contains ( arr interface { } , comp string ) bool {
switch str := arr . ( type ) {
case string :
if str == comp {
return true
2017-07-04 02:07:25 +02:00
}
2017-07-19 21:33:07 +02:00
case publicSettings . Language :
if str . Code == comp {
return true
}
default :
2017-07-04 02:07:25 +02:00
return false
2017-07-19 21:33:07 +02:00
}
return false
2017-05-05 06:07:45 +02:00
}