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"
2017-10-07 01:39:38 +02:00
"path/filepath"
2017-05-05 06:07:45 +02:00
"math"
2017-09-15 02:57:32 +02:00
"math/rand"
2017-05-05 06:07:45 +02:00
"net/url"
"strconv"
2017-05-17 16:05:42 +02:00
"time"
2017-09-06 04:30:49 +02:00
"os"
"fmt"
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 )
2017-09-12 00:17:35 +02:00
vars . Set ( "genSearchWithCategory" , genSearchWithCategory )
2017-07-19 21:33:07 +02:00
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-09-06 04:30:49 +02:00
vars . Set ( "torrentFileExists" , torrentFileExists )
2017-07-19 21:33:07 +02:00
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 )
2017-11-01 08:52:44 +01:00
vars . Set ( "strcmp" , strcmp )
vars . Set ( "strfind" , strfind )
vars . Set ( "rand" , rand )
2017-09-17 22:10:43 +02:00
vars . Set ( "getDomainName" , getDomainName )
2017-10-07 01:39:38 +02:00
vars . Set ( "getThemeList" , getThemeList )
vars . Set ( "formatThemeName" , formatThemeName )
2017-10-11 03:24:09 +02:00
vars . Set ( "formatDate" , formatDate )
2017-07-19 21:33:07 +02:00
return vars
}
func getRawQuery ( currentURL * url . URL ) string {
return currentURL . RawQuery
}
2017-10-18 05:46:58 +02:00
func genSearchWithOrdering ( currentURL * url . URL , sortBy string , searchRoute string ) string {
2017-07-19 21:33:07 +02:00
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-10-18 05:46:58 +02:00
u , _ := url . Parse ( searchRoute )
2017-07-19 21:33:07 +02:00
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-10-18 05:46:58 +02:00
func genSearchWithCategory ( currentURL * url . URL , category string , searchRoute string ) string {
2017-09-12 00:17:35 +02:00
values := currentURL . Query ( )
cat := "_" //Default
if _ , ok := values [ "c" ] ; ok {
cat = values [ "c" ] [ 0 ]
}
cat = category
2017-09-11 19:45:39 +02:00
2017-09-12 00:17:35 +02:00
values . Set ( "c" , cat )
2017-10-18 05:46:58 +02:00
u , _ := url . Parse ( searchRoute )
2017-09-12 00:17:35 +02:00
u . RawQuery = values . Encode ( )
return u . String ( )
}
2017-09-11 19:45:39 +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-09-12 15:03:26 +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-09-12 15:03:26 +02:00
href := ""
display := " style=\"display:none;\""
2017-07-19 21:33:07 +02:00
if nav . CurrentPage - 1 > 0 {
2017-09-12 15:03:26 +02:00
display = ""
href = " href=\"" + "/" + nav . Route + "/1" + "?" + currentURL . RawQuery + "\""
2017-06-17 04:24:30 +02:00
}
2017-09-12 15:03:26 +02:00
ret = ret + "<a id=\"page-prev\"" + display + href + " aria-label=\"Previous\"><span aria-hidden=\"true\">«</span></a>"
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
2017-09-12 15:03:26 +02:00
ret = ret + "<a aria-label=\"Page " + strconv . Itoa ( i ) + "\" href=\"" + url + "?" + currentURL . RawQuery + "\">" + "<span"
2017-07-19 21:33:07 +02:00
if i == nav . CurrentPage {
ret = ret + " class=\"active\""
2017-07-11 22:25:52 +02:00
}
2017-09-12 15:03:26 +02:00
ret = ret + ">" + strconv . Itoa ( i ) + "</span></a>"
2017-07-19 21:33:07 +02:00
}
2017-09-12 15:03:26 +02:00
href = ""
display = " style=\"display:none;\""
2017-07-19 21:33:07 +02:00
if nav . CurrentPage < int ( maxPages ) {
2017-09-12 15:03:26 +02:00
display = ""
2017-10-15 13:18:57 +02:00
href = " href=\"" + "/" + nav . Route + "/" + strconv . Itoa ( int ( maxPages ) ) + "?" + currentURL . RawQuery + "\""
2017-06-12 01:14:26 +02:00
}
2017-09-12 15:03:26 +02:00
ret = ret + "<a id=\"page-next\"" + display + href + " aria-label=\"Next\"><span aria-hidden=\"true\">»</span></a>"
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 {
2017-10-31 22:56:10 +01:00
if hash != "" {
return "https://www.gravatar.com/avatar/" + hash + "?s=" + strconv . Itoa ( size )
} else {
2017-10-31 23:19:10 +01:00
if config . IsSukebei ( ) {
return "/img/sukebei_avatar_" + strconv . Itoa ( size ) + ".jpg"
}
2017-10-31 22:56:10 +01:00
return "/img/avatar_" + strconv . Itoa ( size ) + ".jpg"
}
2017-07-19 21:33:07 +02:00
}
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" ) ) ) )
}
2017-10-31 01:37:24 +01:00
func fileSize ( filesize int64 , T publicSettings . TemplateTfunc , showUnknown bool ) template . HTML {
if showUnknown && filesize == 0 {
2017-07-19 21:33:07 +02:00
return T ( "unknown" )
}
return template . HTML ( format . FileSize ( filesize ) )
}
func defaultUserSettings ( s string ) bool {
return config . Get ( ) . Users . DefaultUserSettings [ s ]
}
2017-07-19 22:12:03 +02:00
func makeTreeViewData ( f * filelist . FileListFolder , nestLevel int , identifierChain string ) interface { } {
2017-07-19 21:33:07 +02:00
return struct {
Folder * filelist . FileListFolder
NestLevel int
IdentifierChain string
2017-07-19 22:12:03 +02:00
} { f , nestLevel , identifierChain }
2017-07-19 21:33:07 +02:00
}
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
}
2017-09-06 04:30:49 +02:00
2017-09-09 14:05:51 +02:00
func torrentFileExists ( hash string , TorrentLink string ) bool {
Torrent Generation on not found error (#1600)
* [WIP] Torrent Generation on not found error
As asked in #1517, it allows on-the-fly torrent generation. Since it uses magnet links, it needs some time to connect to peers. So it can't be instant generation, we need the user to wait and try after a minute at least.
* Replace Fatal by simple error
* attempt at fixing travis
* del
* Add Anacrolyx dependency
* Add back difflib
* Remove .torrent suffix in the url example
* Add some explanations when file missing page shown
* Ignore downloads directory
* Either use cache (third-party site) or own download directory
* Wrong import
* If there is an error then it means we aren't generating a torrent file
May it be "torrent not found" or "We do not store torrent files" which are the two only existing errors for this page
* hash is never empty
* TorrentLink may be empty at times
So we add a /download/:hash link if it is
* Update README.md
* Made a mistake here, need to check if false
* Update en-us.all.json
* Update CHANGELOG.md
* Torrent file generation can be triggered by click on button if JS enabled
* Update download.go
* Update download.go
* Use c.JSON instead of text/template
* Return to default behavior if we don't generate the file
* Don't do the query if returned to default behavior
* Add "Could not generate torrent file" error
* Fix JS condition & lower delay until button updates
* Start download automatically once torrent file is generated
* Fix torrentFileExists() constantly returning false if external torrent download URL
* torrent-view-data is two tables instead of one
This allows the removal of useless things without any problem (e.g Website link), but also a better responsibe design since the previous one separated stats after a certain res looking very wonky
* CSS changes to go along
* Remove useless <b></b>
* Update main.css
* In torrentFileExists, check if filestorage path exists instead of looking at the domain in torrent link
When checking if the file is stored on another server i used to simply check if the domain name was inside the torrent link, but we can straight up check for filestorage length
* Fix JS of on-demand stat fetching
* ScrapeAge variable accessible through view.jet.html
Contains last scraped time in hours, is at -1 is torrent has never been scraped
Stats will get updated if it's either at -1 or above 1460 (2 months old)
* Refresh stats if older than two months OR unknown and older than 24h
Show last scraped date even if stats are unknown
* Add StatsObsolete variable to torrent
Indicating if:
- They can be shown
- They need to be updated
* Update scraped data even if Unknown, prevent users from trying to fetch stats every seconds
* Torrent file stored locally by default
* no need to do all of that if no filestorage
* fix filestorage path
* Fix torrent download button stuck on "Generating torrent file" at rare times
* fix some css rules that didn't work on IE
* Fix panic error
Seems like this error is a known bug from anacrolyx torrent https://github.com/anacrolix/torrent/issues/83
To prevent it, I'm creating a single client and modifying the socket.go to make it not raise a panic but a simple error log.
2017-10-21 09:40:43 +02:00
if ( len ( config . Get ( ) . Torrents . FileStorage ) == 0 ) {
//File isn't stored on our servers
2017-09-09 14:05:51 +02:00
return true
}
2017-09-06 04:30:49 +02:00
Openfile , err := os . Open ( fmt . Sprintf ( "%s%c%s.torrent" , config . Get ( ) . Torrents . FileStorage , os . PathSeparator , hash ) )
if err != nil {
Torrent Generation on not found error (#1600)
* [WIP] Torrent Generation on not found error
As asked in #1517, it allows on-the-fly torrent generation. Since it uses magnet links, it needs some time to connect to peers. So it can't be instant generation, we need the user to wait and try after a minute at least.
* Replace Fatal by simple error
* attempt at fixing travis
* del
* Add Anacrolyx dependency
* Add back difflib
* Remove .torrent suffix in the url example
* Add some explanations when file missing page shown
* Ignore downloads directory
* Either use cache (third-party site) or own download directory
* Wrong import
* If there is an error then it means we aren't generating a torrent file
May it be "torrent not found" or "We do not store torrent files" which are the two only existing errors for this page
* hash is never empty
* TorrentLink may be empty at times
So we add a /download/:hash link if it is
* Update README.md
* Made a mistake here, need to check if false
* Update en-us.all.json
* Update CHANGELOG.md
* Torrent file generation can be triggered by click on button if JS enabled
* Update download.go
* Update download.go
* Use c.JSON instead of text/template
* Return to default behavior if we don't generate the file
* Don't do the query if returned to default behavior
* Add "Could not generate torrent file" error
* Fix JS condition & lower delay until button updates
* Start download automatically once torrent file is generated
* Fix torrentFileExists() constantly returning false if external torrent download URL
* torrent-view-data is two tables instead of one
This allows the removal of useless things without any problem (e.g Website link), but also a better responsibe design since the previous one separated stats after a certain res looking very wonky
* CSS changes to go along
* Remove useless <b></b>
* Update main.css
* In torrentFileExists, check if filestorage path exists instead of looking at the domain in torrent link
When checking if the file is stored on another server i used to simply check if the domain name was inside the torrent link, but we can straight up check for filestorage length
* Fix JS of on-demand stat fetching
* ScrapeAge variable accessible through view.jet.html
Contains last scraped time in hours, is at -1 is torrent has never been scraped
Stats will get updated if it's either at -1 or above 1460 (2 months old)
* Refresh stats if older than two months OR unknown and older than 24h
Show last scraped date even if stats are unknown
* Add StatsObsolete variable to torrent
Indicating if:
- They can be shown
- They need to be updated
* Update scraped data even if Unknown, prevent users from trying to fetch stats every seconds
* Torrent file stored locally by default
* no need to do all of that if no filestorage
* fix filestorage path
* Fix torrent download button stuck on "Generating torrent file" at rare times
* fix some css rules that didn't work on IE
* Fix panic error
Seems like this error is a known bug from anacrolyx torrent https://github.com/anacrolix/torrent/issues/83
To prevent it, I'm creating a single client and modifying the socket.go to make it not raise a panic but a simple error log.
2017-10-21 09:40:43 +02:00
//File doesn't exist
2017-09-06 04:30:49 +02:00
return false
}
defer Openfile . Close ( )
return true
}
2017-09-08 15:08:12 +02:00
2017-11-01 08:52:44 +01:00
func strcmp ( str1 string , str2 string , end int , start int ) bool {
2017-09-08 15:08:12 +02:00
//Compare two strings but has length arguments
len1 := len ( str1 )
len2 := len ( str2 )
if end == - 1 && len1 != len2 {
return false
}
if end == - 1 || end > len1 {
end = len1
}
if end > len2 {
end = len2
}
if start >= end {
return false
}
return strings . Compare ( str1 [ start : end ] , str2 [ start : end ] ) == 0
}
2017-09-09 14:05:51 +02:00
2017-11-01 08:52:44 +01:00
func strfind ( str1 string , searchfor string , start int ) bool {
2017-09-09 14:05:51 +02:00
//Search a string inside another with start parameter
//start parameter indicates where we start searching
len1 := len ( str1 )
Torrent Generation on not found error (#1600)
* [WIP] Torrent Generation on not found error
As asked in #1517, it allows on-the-fly torrent generation. Since it uses magnet links, it needs some time to connect to peers. So it can't be instant generation, we need the user to wait and try after a minute at least.
* Replace Fatal by simple error
* attempt at fixing travis
* del
* Add Anacrolyx dependency
* Add back difflib
* Remove .torrent suffix in the url example
* Add some explanations when file missing page shown
* Ignore downloads directory
* Either use cache (third-party site) or own download directory
* Wrong import
* If there is an error then it means we aren't generating a torrent file
May it be "torrent not found" or "We do not store torrent files" which are the two only existing errors for this page
* hash is never empty
* TorrentLink may be empty at times
So we add a /download/:hash link if it is
* Update README.md
* Made a mistake here, need to check if false
* Update en-us.all.json
* Update CHANGELOG.md
* Torrent file generation can be triggered by click on button if JS enabled
* Update download.go
* Update download.go
* Use c.JSON instead of text/template
* Return to default behavior if we don't generate the file
* Don't do the query if returned to default behavior
* Add "Could not generate torrent file" error
* Fix JS condition & lower delay until button updates
* Start download automatically once torrent file is generated
* Fix torrentFileExists() constantly returning false if external torrent download URL
* torrent-view-data is two tables instead of one
This allows the removal of useless things without any problem (e.g Website link), but also a better responsibe design since the previous one separated stats after a certain res looking very wonky
* CSS changes to go along
* Remove useless <b></b>
* Update main.css
* In torrentFileExists, check if filestorage path exists instead of looking at the domain in torrent link
When checking if the file is stored on another server i used to simply check if the domain name was inside the torrent link, but we can straight up check for filestorage length
* Fix JS of on-demand stat fetching
* ScrapeAge variable accessible through view.jet.html
Contains last scraped time in hours, is at -1 is torrent has never been scraped
Stats will get updated if it's either at -1 or above 1460 (2 months old)
* Refresh stats if older than two months OR unknown and older than 24h
Show last scraped date even if stats are unknown
* Add StatsObsolete variable to torrent
Indicating if:
- They can be shown
- They need to be updated
* Update scraped data even if Unknown, prevent users from trying to fetch stats every seconds
* Torrent file stored locally by default
* no need to do all of that if no filestorage
* fix filestorage path
* Fix torrent download button stuck on "Generating torrent file" at rare times
* fix some css rules that didn't work on IE
* Fix panic error
Seems like this error is a known bug from anacrolyx torrent https://github.com/anacrolix/torrent/issues/83
To prevent it, I'm creating a single client and modifying the socket.go to make it not raise a panic but a simple error log.
2017-10-21 09:40:43 +02:00
if start >= len1 || searchfor == "" {
2017-09-09 14:05:51 +02:00
return false
}
return strings . Contains ( str1 [ start : len1 ] , searchfor )
}
2017-09-15 02:57:32 +02:00
2017-11-01 08:52:44 +01:00
func rand ( max int ) int {
2017-09-20 01:59:17 +02:00
return rand . Intn ( max )
2017-09-15 02:57:32 +02:00
}
2017-09-17 22:10:43 +02:00
func getDomainName ( ) string {
domain := config . Get ( ) . Cookies . DomainName
if config . Get ( ) . Environment == "DEVELOPMENT" {
domain = ""
}
return domain
}
2017-10-07 01:39:38 +02:00
func getThemeList ( ) ( [ ] string ) {
searchDir := "public/css/themes/"
themeList := [ ] string { }
filepath . Walk ( searchDir , func ( path string , f os . FileInfo , err error ) error {
2017-11-01 08:52:44 +01:00
if strfind ( path , ".css" , len ( searchDir ) ) {
2017-10-07 01:39:38 +02:00
//we only want .css file
fileName := path [ len ( searchDir ) : strings . Index ( path , ".css" ) ]
//Remove file extension and path, keep only file name
themeList = append ( themeList , fileName )
}
return nil
} )
return themeList
}
2017-10-10 02:33:38 +02:00
func formatThemeName ( name string , T publicSettings . TemplateTfunc ) string {
translationString := fmt . Sprintf ( "themes_%s" , name )
translatedName := string ( T ( translationString ) )
if translatedName != translationString {
//Translation string exists
return translatedName
}
2017-10-07 01:39:38 +02:00
2017-10-10 02:33:38 +02:00
if len ( name ) == 1 {
name = fmt . Sprintf ( "/%c/" , name [ 0 ] )
2017-10-07 01:39:38 +02:00
} else {
2017-10-10 02:33:38 +02:00
name = strings . Replace ( name , "_" , " " , - 1 )
name = strings . Title ( name )
2017-10-07 01:39:38 +02:00
//Upper case at each start of word
}
2017-10-10 02:33:38 +02:00
return name
2017-10-07 01:39:38 +02:00
}
2017-10-10 02:33:38 +02:00
2017-10-11 03:24:09 +02:00
func formatDate ( Date time . Time , short bool ) string {
Date = Date . UTC ( )
if short {
return fmt . Sprintf ( "%.3s %d, %d" , Date . Month ( ) , Date . Day ( ) , Date . Year ( ) )
}
if Date . Hour ( ) >= 12 {
return fmt . Sprintf ( "%d/%d/%d, %d:%.2d:%.2d PM UTC+0" , Date . Month ( ) , Date . Day ( ) , Date . Year ( ) , Date . Hour ( ) - 12 , Date . Minute ( ) , Date . Second ( ) )
} else {
return fmt . Sprintf ( "%d/%d/%d, %d:%.2d:%.2d AM UTC+0" , Date . Month ( ) , Date . Day ( ) , Date . Year ( ) , Date . Hour ( ) , Date . Minute ( ) , Date . Second ( ) )
}
}