Albirew/nyaa-pantsu
Archivé
1
0
Bifurcation 0
Cette révision appartient à :
ayame-git 2017-05-10 00:02:44 +03:00
révision ab330e77c7
19 fichiers modifiés avec 225 ajouts et 82 suppressions

Voir le fichier

@ -1,8 +1,14 @@
package config package config
const ( const (
// TorrentFileStorage = "/var/tmp/torrent_outgoing" // TorrentFileStorage = "/var/www/wherever/you/want"
// TorrentStorageLink = "https://your.site/somewhere/%s.torrent"
TorrentFileStorage = "" TorrentFileStorage = ""
TorrentStorageLink = ""
// TODO: deprecate this and move all files to the same server
TorrentCacheLink = "http://anicache.com/torrent/%s.torrent"
//disable uploads by default //disable uploads by default
UploadsDisabled = 1 UploadsDisabled = 1
) )

Voir le fichier

@ -30,7 +30,7 @@ func GormInit(conf *config.Config) (*gorm.DB, error) {
// db.SingularTable(true) // db.SingularTable(true)
if config.Environment == "DEVELOPMENT" { if config.Environment == "DEVELOPMENT" {
db.LogMode(true) db.LogMode(true)
db.AutoMigrate(&model.Torrents{}, &model.UsersFollowers{}, &model.User{}, &model.Comment{}, &model.OldComment{}) db.AutoMigrate(&model.Torrents{}, &model.UserFollows{}, &model.User{}, &model.Comment{}, &model.OldComment{})
// db.Model(&model.User{}).AddIndex("idx_user_token", "token") // db.Model(&model.User{}).AddIndex("idx_user_token", "token")
} }

12
main.go
Voir le fichier

@ -15,12 +15,19 @@ import (
"net/http" "net/http"
"os" "os"
"path/filepath"
"time" "time"
) )
func initI18N() { func initI18N() {
/* Initialize the languages translation */ /* Initialize the languages translation */
i18n.MustLoadTranslationFile("translations/en-us.all.json") i18n.MustLoadTranslationFile("translations/en-us.all.json")
paths, err := filepath.Glob("translations/*.json")
if err == nil {
for _, path := range paths {
i18n.LoadTranslationFile(path)
}
}
} }
func RunServer(conf *config.Config) { func RunServer(conf *config.Config) {
@ -55,7 +62,10 @@ func main() {
if err != nil { if err != nil {
log.CheckError(err) log.CheckError(err)
} }
db.ORM, _ = db.GormInit(conf) db.ORM, err = db.GormInit(conf)
if err != nil {
log.Fatal(err.Error())
}
initI18N() initI18N()
go signals.Handle() go signals.Handle()
if len(config.TorrentFileStorage) > 0 { if len(config.TorrentFileStorage) > 0 {

Voir le fichier

@ -4,7 +4,7 @@ import (
"github.com/ewhal/nyaa/config" "github.com/ewhal/nyaa/config"
"github.com/ewhal/nyaa/util" "github.com/ewhal/nyaa/util"
"html" "fmt"
"html/template" "html/template"
"strconv" "strconv"
"strings" "strings"
@ -34,7 +34,7 @@ type Torrents struct {
Description string `gorm:"column:description"` Description string `gorm:"column:description"`
WebsiteLink string `gorm:"column:website_link"` WebsiteLink string `gorm:"column:website_link"`
Uploader *User `gorm:"ForeignKey:uploader"` Uploader *User `gorm:"ForeignKey:UploaderId"`
OldComments []OldComment `gorm:"ForeignKey:torrent_id"` OldComments []OldComment `gorm:"ForeignKey:torrent_id"`
Comments []Comment `gorm:"ForeignKey:torrent_id"` Comments []Comment `gorm:"ForeignKey:torrent_id"`
} }
@ -66,8 +66,10 @@ type TorrentsJson struct {
Category string `json:"category"` Category string `json:"category"`
Downloads int `json:"downloads"` Downloads int `json:"downloads"`
UploaderId uint `json:"uploader_id"` UploaderId uint `json:"uploader_id"`
UploaderName template.HTML `json:"uploader_name"`
WebsiteLink template.URL `json:"website_link"` WebsiteLink template.URL `json:"website_link"`
Magnet template.URL `json:"magnet"` Magnet template.URL `json:"magnet"`
TorrentLink template.URL `json:"torrent"`
} }
/* Model Conversion to Json */ /* Model Conversion to Json */
@ -79,12 +81,21 @@ func (t *Torrents) ToJson() TorrentsJson {
commentsJson = append(commentsJson, CommentsJson{Username: c.Username, Content: template.HTML(c.Content), Date: c.Date}) commentsJson = append(commentsJson, CommentsJson{Username: c.Username, Content: template.HTML(c.Content), Date: c.Date})
} }
for _, c := range t.Comments { for _, c := range t.Comments {
commentsJson = append(commentsJson, CommentsJson{Username: c.User.Username, Content: util.MarkdownToHTML(c.Content), Date: c.CreatedAt}) commentsJson = append(commentsJson, CommentsJson{Username: c.User.Username, Content: util.MarkdownToHTML(c.Content), Date: c.CreatedAt})
} }
uploader := ""
if t.Uploader != nil {
uploader = t.Uploader.Username
}
torrentlink := ""
if t.Id <= config.LastOldTorrentId && len(config.TorrentCacheLink) > 0 {
torrentlink = fmt.Sprintf(config.TorrentCacheLink, t.Hash)
} else if t.Id > config.LastOldTorrentId && len(config.TorrentStorageLink) > 0 {
torrentlink = fmt.Sprintf(config.TorrentStorageLink, t.Hash)
}
res := TorrentsJson{ res := TorrentsJson{
Id: strconv.FormatUint(uint64(t.Id), 10), Id: strconv.FormatUint(uint64(t.Id), 10),
Name: html.UnescapeString(t.Name), Name: t.Name,
Status: t.Status, Status: t.Status,
Hash: t.Hash, Hash: t.Hash,
Date: t.Date.Format(time.RFC3339), Date: t.Date.Format(time.RFC3339),
@ -95,8 +106,10 @@ func (t *Torrents) ToJson() TorrentsJson {
Category: strconv.Itoa(t.Category), Category: strconv.Itoa(t.Category),
Downloads: t.Downloads, Downloads: t.Downloads,
UploaderId: t.UploaderId, UploaderId: t.UploaderId,
UploaderName: util.SafeText(uploader),
WebsiteLink: util.Safe(t.WebsiteLink), WebsiteLink: util.Safe(t.WebsiteLink),
Magnet: util.Safe(magnet)} Magnet: util.Safe(magnet),
TorrentLink: util.Safe(torrentlink)}
return res return res
} }

Voir le fichier

@ -4,38 +4,34 @@ import (
"time" "time"
) )
// omit is the bool type for omitting a field of struct.
type omit bool
type User struct { type User struct {
Id uint `gorm:"column:user_id;primary_key"` Id uint `gorm:"column:user_id;primary_key"`
Username string `gorm:"column:username"` Username string `gorm:"column:username"`
Password string `gorm:"column:password"` Password string `gorm:"column:password"`
Email string `gorm:"column:email"` Email string `gorm:"column:email"`
Status int `gorm:"column:status"` Status int `gorm:"column:status"`
CreatedAt time.Time `gorm:"column:created_at"` CreatedAt time.Time `gorm:"column:created_at"`
UpdatedAt time.Time `gorm:"column:updated_at"` UpdatedAt time.Time `gorm:"column:updated_at"`
/*Api*/ Token string `gorm:"column:api_token"` Token string `gorm:"column:api_token"`
//ApiTokenExpiry TokenExpiration time.Time `gorm:"column:api_token_expiry"`
Language string `gorm:"column:language"`
// Liking // TODO: move this to PublicUser
LikingCount int `json:"likingCount"` LikingCount int `json:"likingCount" gorm:"-"`
LikedCount int `json:"likedCount"` LikedCount int `json:"likedCount" gorm:"-"`
Likings []User `gorm:"foreignkey:userId;associationforeignkey:follower_id;many2many:users_followers;"` Likings []User `gorm:"foreignkey:userId;associationforeignkey:follower_id;many2many:user_follows"`
Liked []User `gorm:"foreignkey:follower_id;associationforeignkey:userId;many2many:users_followers;"` Liked []User `gorm:"foreignkey:follower_id;associationforeignkey:userId;many2many:user_follows"`
Md5 string `json:"md5"` Md5 string `json:"md5"` // Used for gravatar
TokenExpiration time.Time `gorm:"column:api_token_expiry"`
Language string `gorm:"column:language"`
Torrents []Torrents `gorm:"ForeignKey:UploaderId"` Torrents []Torrents `gorm:"ForeignKey:UploaderId"`
} }
type PublicUser struct { type PublicUser struct {
User *User User *User
} }
// UsersFollowers is a relation table to relate users each other. // different users following eachother
type UsersFollowers struct { type UserFollows struct {
UserID uint `gorm:"column:userId"` UserID uint `gorm:"column:user_id"`
FollowerID uint `gorm:"column:follower_id"` FollowerID uint `gorm:"column:following"`
} }

Voir le fichier

@ -143,6 +143,7 @@ func ApiUpdateHandler(w http.ResponseWriter, r *http.Request) {
return return
} }
<<<<<<< HEAD
contentType := r.Header.Get("Content-Type") contentType := r.Header.Get("Content-Type")
if contentType == "application/json" { if contentType == "application/json" {
token := r.Header.Get("Authorization") token := r.Header.Get("Authorization")
@ -185,4 +186,21 @@ func ApiUpdateHandler(w http.ResponseWriter, r *http.Request) {
db.ORM.Save(&torrent) db.ORM.Save(&torrent)
fmt.Printf("%+v\n", torrent) fmt.Printf("%+v\n", torrent)
} }
=======
torrent := model.Torrents{
Name: b.Name,
Category: category,
Sub_Category: sub_category,
Status: 1,
Hash: b.Hash,
Date: time.Now(),
Filesize: 0,
Description: string(b.Description)}
err = db.ORM.Create(&torrent).Error
if err != nil {
util.SendError(w, err, 500)
return
}
fmt.Printf("%+v\n", torrent)
>>>>>>> 7ea85cf3140d8f9c32c3637b7e9f73a0e744aee8
} }

Voir le fichier

@ -11,6 +11,7 @@ import (
"github.com/ewhal/nyaa/model" "github.com/ewhal/nyaa/model"
"github.com/ewhal/nyaa/service/captcha" "github.com/ewhal/nyaa/service/captcha"
"github.com/ewhal/nyaa/service/user" "github.com/ewhal/nyaa/service/user"
"github.com/ewhal/nyaa/util"
"github.com/ewhal/nyaa/util/languages" "github.com/ewhal/nyaa/util/languages"
"github.com/gorilla/mux" "github.com/gorilla/mux"
) )
@ -42,7 +43,11 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
Filesize: uploadForm.Filesize, // FIXME: should set to NULL instead of 0 Filesize: uploadForm.Filesize, // FIXME: should set to NULL instead of 0
Description: uploadForm.Description, Description: uploadForm.Description,
UploaderId: user.Id} UploaderId: user.Id}
db.ORM.Create(&torrent) err = db.ORM.Create(&torrent).Error
if err != nil {
util.SendError(w, err, 500)
return
}
fmt.Printf("%+v\n", torrent) fmt.Printf("%+v\n", torrent)
url, err := Router.Get("view_torrent").URL("id", strconv.FormatUint(uint64(torrent.Id), 10)) url, err := Router.Get("view_torrent").URL("id", strconv.FormatUint(uint64(torrent.Id), 10))
if err == nil { if err == nil {

Voir le fichier

@ -9,6 +9,7 @@ import (
"github.com/ewhal/nyaa/model" "github.com/ewhal/nyaa/model"
"github.com/ewhal/nyaa/service/captcha" "github.com/ewhal/nyaa/service/captcha"
"github.com/ewhal/nyaa/service/torrent" "github.com/ewhal/nyaa/service/torrent"
"github.com/ewhal/nyaa/util"
"github.com/ewhal/nyaa/util/languages" "github.com/ewhal/nyaa/util/languages"
"github.com/ewhal/nyaa/util/log" "github.com/ewhal/nyaa/util/log"
"github.com/gorilla/mux" "github.com/gorilla/mux"
@ -47,11 +48,15 @@ func PostCommentHandler(w http.ResponseWriter, r *http.Request) {
idNum_, err := strconv.Atoi(id) idNum_, err := strconv.Atoi(id)
var idNum uint = uint(idNum_) var idNum uint = uint(idNum_)
var userId uint = 0 var userId uint = 0
if (currentUser.Id > 0) { if currentUser.Id > 0 {
userId = currentUser.Id userId = currentUser.Id
} }
comment := model.Comment{TorrentId: idNum, UserId: userId, Content: content, CreatedAt: time.Now()} comment := model.Comment{TorrentId: idNum, UserId: userId, Content: content, CreatedAt: time.Now()}
db.ORM.Create(&comment) err = db.ORM.Create(&comment).Error
if err != nil {
util.SendError(w, err, 500)
return
}
url, err := Router.Get("view_torrent").URL("id", id) url, err := Router.Get("view_torrent").URL("id", id)
if err == nil { if err == nil {

Voir le fichier

@ -23,48 +23,64 @@ type WhereParams struct {
*/ */
// don't need raw SQL once we get MySQL // don't need raw SQL once we get MySQL
func GetFeeds() []model.Feed { func GetFeeds() (result []model.Feed, err error) {
result := make([]model.Feed, 0, 50) result = make([]model.Feed, 0, 50)
rows, err := db.ORM.DB(). rows, err := db.ORM.DB().
Query( Query(
"SELECT `torrent_id` AS `id`, `torrent_name` AS `name`, `torrent_hash` AS `hash`, `timestamp` FROM `torrents` " + "SELECT `torrent_id` AS `id`, `torrent_name` AS `name`, `torrent_hash` AS `hash`, `timestamp` FROM `torrents` " +
"ORDER BY `timestamp` desc LIMIT 50") "ORDER BY `timestamp` desc LIMIT 50")
if err == nil { if err != nil {
for rows.Next() { return nil, err
item := model.Feed{}
rows.Scan(&item.Id, &item.Name, &item.Hash, &item.Timestamp)
magnet := util.InfoHashToMagnet(strings.TrimSpace(item.Hash), item.Name, config.Trackers...)
item.Magnet = magnet
// memory hog
result = append(result, item)
}
rows.Close()
} }
return result defer rows.Close()
for rows.Next() {
item := model.Feed{}
err = rows.Scan(&item.Id, &item.Name, &item.Hash, &item.Timestamp)
if err != nil {
return
}
magnet := util.InfoHashToMagnet(strings.TrimSpace(item.Hash), item.Name, config.Trackers...)
item.Magnet = magnet
// memory hog
result = append(result, item)
}
err = rows.Err()
return
} }
func GetTorrentById(id string) (model.Torrents, error) { func GetTorrentById(id string) (torrent model.Torrents, err error) {
var torrent model.Torrents
id_int, err := strconv.Atoi(id) id_int, err := strconv.Atoi(id)
if err != nil { if err != nil {
return torrent, err return
} }
tmp := db.ORM.Where("torrent_id = ?", id).Preload("Comments") tmp := db.ORM.Where("torrent_id = ?", id).Preload("Comments")
err = tmp.Error
if err != nil {
return
}
if id_int <= config.LastOldTorrentId { if id_int <= config.LastOldTorrentId {
// only preload old comments if they could actually exist // only preload old comments if they could actually exist
tmp = tmp.Preload("OldComments") tmp = tmp.Preload("OldComments")
} }
if tmp.Find(&torrent).RecordNotFound() { if tmp.Find(&torrent).RecordNotFound() {
return torrent, errors.New("Article is not found.") err = errors.New("Article is not found.")
return
} }
// .Preload("Comments.User") doesn't work // GORM relly likes not doing its job correctly
// (or maybe I'm just retarded)
torrent.Uploader = new(model.User)
db.ORM.Where("user_id = ?", torrent.UploaderId).Find(torrent.Uploader)
for i := range torrent.Comments { for i := range torrent.Comments {
torrent.Comments[i].User = new(model.User) torrent.Comments[i].User = new(model.User)
db.ORM.Where("user_id = ?", torrent.Comments[i].UserId).Find(torrent.Comments[i].User) err = db.ORM.Where("user_id = ?", torrent.Comments[i].UserId).Find(torrent.Comments[i].User).Error
if err != nil {
return
}
} }
return torrent, nil return
} }
func GetTorrentsOrderByNoCount(parameters *WhereParams, orderBy string, limit int, offset int) (torrents []model.Torrents, err error) { func GetTorrentsOrderByNoCount(parameters *WhereParams, orderBy string, limit int, offset int) (torrents []model.Torrents, err error) {
@ -77,7 +93,9 @@ func GetTorrentsOrderBy(parameters *WhereParams, orderBy string, limit int, offs
return return
} }
func getTorrentsOrderBy(parameters *WhereParams, orderBy string, limit int, offset int, countAll bool) (torrents []model.Torrents, count int, err error) { func getTorrentsOrderBy(parameters *WhereParams, orderBy string, limit int, offset int, countAll bool) (
torrents []model.Torrents, count int, err error,
) {
var conditionArray []string var conditionArray []string
if strings.HasPrefix(orderBy, "filesize") { if strings.HasPrefix(orderBy, "filesize") {
// torrents w/ NULL filesize fuck up the sorting on postgres // torrents w/ NULL filesize fuck up the sorting on postgres

Voir le fichier

@ -4,14 +4,13 @@ import (
"errors" "errors"
"net/http" "net/http"
"github.com/gorilla/securecookie"
"golang.org/x/crypto/bcrypt"
formStruct "github.com/ewhal/nyaa/service/user/form"
"github.com/ewhal/nyaa/db" "github.com/ewhal/nyaa/db"
"github.com/ewhal/nyaa/model" "github.com/ewhal/nyaa/model"
formStruct "github.com/ewhal/nyaa/service/user/form"
"github.com/ewhal/nyaa/util/log" "github.com/ewhal/nyaa/util/log"
"github.com/ewhal/nyaa/util/modelHelper" "github.com/ewhal/nyaa/util/modelHelper"
"github.com/gorilla/securecookie"
"golang.org/x/crypto/bcrypt"
) )
var cookieHandler = securecookie.New( var cookieHandler = securecookie.New(
@ -118,6 +117,9 @@ func SetCookieHandler(w http.ResponseWriter, email string, pass string) (int, er
// RegisterHanderFromForm sets cookie from a RegistrationForm. // RegisterHanderFromForm sets cookie from a RegistrationForm.
func RegisterHanderFromForm(w http.ResponseWriter, registrationForm formStruct.RegistrationForm) (int, error) { func RegisterHanderFromForm(w http.ResponseWriter, registrationForm formStruct.RegistrationForm) (int, error) {
email := registrationForm.Email email := registrationForm.Email
if email == "" {
email = registrationForm.Username
}
pass := registrationForm.Password pass := registrationForm.Password
log.Debugf("RegisterHandler UserEmail : %s", email) log.Debugf("RegisterHandler UserEmail : %s", email)
log.Debugf("RegisterHandler UserPassword : %s", pass) log.Debugf("RegisterHandler UserPassword : %s", pass)
@ -149,6 +151,6 @@ func CurrentUser(r *http.Request) (model.User, error) {
if db.ORM.Where("api_token = ?", token).First(&user).RecordNotFound() { if db.ORM.Where("api_token = ?", token).First(&user).RecordNotFound() {
return user, errors.New("User is not found.") return user, errors.New("User is not found.")
} }
db.ORM.Model(&user) err = db.ORM.Model(&user).Error
return user, nil return user, err
} }

Voir le fichier

@ -47,14 +47,14 @@ func SuggestUsername(username string) string {
func CheckEmail(email string) bool { func CheckEmail(email string) bool {
if len(email) == 0 { if len(email) == 0 {
return true return false
} }
var count int var count int
db.ORM.Model(model.User{}).Where("email = ?", email).Count(&count) db.ORM.Model(model.User{}).Where("email = ?", email).Count(&count)
if count == 0 { if count != 0 {
return false // duplicate return true // error: duplicate
} }
return true return false
} }
// CreateUserFromForm creates a user from a registration form. // CreateUserFromForm creates a user from a registration form.
@ -62,17 +62,29 @@ func CreateUserFromForm(registrationForm formStruct.RegistrationForm) (model.Use
var user model.User var user model.User
log.Debugf("registrationForm %+v\n", registrationForm) log.Debugf("registrationForm %+v\n", registrationForm)
modelHelper.AssignValue(&user, &registrationForm) modelHelper.AssignValue(&user, &registrationForm)
<<<<<<< HEAD
user.Md5 = crypto.GenerateMD5Hash(user.Email) // Gravatar user.Md5 = crypto.GenerateMD5Hash(user.Email) // Gravatar
=======
if user.Email == "" {
user.Md5 = ""
} else {
user.Md5 = crypto.GenerateMD5Hash(user.Email)
}
>>>>>>> 7ea85cf3140d8f9c32c3637b7e9f73a0e744aee8
token, err := crypto.GenerateRandomToken32() token, err := crypto.GenerateRandomToken32()
if err != nil { if err != nil {
return user, errors.New("Token not generated.") return user, errors.New("Token not generated.")
} }
user.Token = token user.Token = token
user.TokenExpiration = timeHelper.FewDaysLater(config.AuthTokenExpirationDay) user.TokenExpiration = timeHelper.FewDaysLater(config.AuthTokenExpirationDay)
log.Debugf("user %+v\n", user) log.Debugf("user %+v\n", user)
if db.ORM.Create(&user).Error != nil { if db.ORM.Create(&user).Error != nil {
return user, errors.New("User is not created.") return user, errors.New("User is not created.")
} }
user.CreatedAt = time.Now()
return user, nil return user, nil
} }
@ -136,7 +148,12 @@ func RetrieveUsers() []*model.PublicUser {
// UpdateUserCore updates a user. (Applying the modifed data of user). // UpdateUserCore updates a user. (Applying the modifed data of user).
func UpdateUserCore(user *model.User) (int, error) { func UpdateUserCore(user *model.User) (int, error) {
user.Md5 = crypto.GenerateMD5Hash(user.Email) if user.Email == "" {
user.Md5 = ""
} else {
user.Md5 = crypto.GenerateMD5Hash(user.Email)
}
token, err := crypto.GenerateRandomToken32() token, err := crypto.GenerateRandomToken32()
if err != nil { if err != nil {
return http.StatusInternalServerError, errors.New("Token not generated.") return http.StatusInternalServerError, errors.New("Token not generated.")
@ -146,6 +163,7 @@ func UpdateUserCore(user *model.User) (int, error) {
if db.ORM.Save(user).Error != nil { if db.ORM.Save(user).Error != nil {
return http.StatusInternalServerError, errors.New("User is not updated.") return http.StatusInternalServerError, errors.New("User is not updated.")
} }
user.UpdatedAt = time.Now() user.UpdatedAt = time.Now()
return http.StatusOK, nil return http.StatusOK, nil
} }

Voir le fichier

@ -33,9 +33,11 @@
<a href="{{.Magnet}}" title="Magnet link"> <a href="{{.Magnet}}" title="Magnet link">
<span class="glyphicon glyphicon-magnet" aria-hidden="true"></span> <span class="glyphicon glyphicon-magnet" aria-hidden="true"></span>
</a> </a>
<a href="http://anicache.com/torrent/{{.Hash}}.torrent" title="Torrent file"> {{if ne .TorrentLink ""}}
<a href="{{.TorrentLink}}" title="Torrent file">
<span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span> <span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span>
</a> </a>
{{end}}
</td> </td>
</tr> </tr>
{{end}} {{end}}

Voir le fichier

@ -39,9 +39,11 @@
<a href="{{.Magnet}}" title="Magnet link"> <a href="{{.Magnet}}" title="Magnet link">
<span class="glyphicon glyphicon-magnet" aria-hidden="true"></span> <span class="glyphicon glyphicon-magnet" aria-hidden="true"></span>
</a> </a>
<a href="http://anicache.com/torrent/{{.Hash}}.torrent" title="Torrent file"> {{if ne .TorrentLink ""}}
<a href="{{.TorrentLink}}" title="Torrent file">
<span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span> <span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span>
</a> </a>
{{end}}
</td> </td>
</tr> </tr>
{{end}} {{end}}

Voir le fichier

@ -45,7 +45,7 @@
<div class="form-group"> <div class="form-group">
<label for="desc">{{T "torrent_description"}}</label> <label for="desc">{{T "torrent_description"}}</label>
<p class="help-block">{{T "limited_html_set_is_allowed_use"}} <span style="font-family:monospace">&lt;br/&gt;</span>.</p> <p class="help-block">{{T "description_markdown_notice"}}</p>
<textarea name="desc" class="form-control" rows="10">{{.Description}}</textarea> <textarea name="desc" class="form-control" rows="10">{{.Description}}</textarea>
</div> </div>

Voir le fichier

@ -1,4 +1,4 @@
{{define "title"}}{{ T "register_success_title" }}{{end}} {{define "title"}}{{ T "register_success_title" }}{{end}}
{{define "contclass"}}cont-view{{end}} {{define "contclass"}}cont-view{{end}}
{{define "content"}} {{define "content"}}
<div class="blockBody"> <div class="blockBody">
@ -7,9 +7,13 @@
<h2>{{T "sign_up_success"}}</h2> <h2>{{T "sign_up_success"}}</h2>
<hr class="colorgraph"> <hr class="colorgraph">
{{if ne .User.Email ""}}
<p>{{ T "signup_verification_email" }}</p> <p>{{ T "signup_verification_email" }}</p>
{{else}}
<p>{{ T "signup_verification_noemail" }}</p>
{{end}}
</div> </div>
</div> </div>
</div> </div>
{{end}} {{end}}
{{define "js_footer"}}<script type="text/javascript" charset="utf-8" src="{{.URL.Parse "/js/registerPage.js"}}"></script>{{end}} {{define "js_footer"}}<script type="text/javascript" charset="utf-8" src="{{.URL.Parse "/js/registerPage.js"}}"></script>{{end}}

Voir le fichier

@ -26,10 +26,15 @@
<td>{{T "size"}}</td> <td>{{T "size"}}</td>
<td>{{.Filesize}}</td> <td>{{.Filesize}}</td>
</tr> </tr>
<tr>
<td>Uploader</td>
<td><a href="{{$.URL.Parse (printf "/user/%d/-" .UploaderId) }}">{{.UploaderName}}</a></td>
{{if ne .WebsiteLink ""}}
<tr> <tr>
<td>{{T "Link"}}</td> <td>{{T "Link"}}</td>
<td><a href="{{.WebsiteLink}}">{{.WebsiteLink}}</td> <td><a href="{{.WebsiteLink}}">{{.WebsiteLink}}</td>
</tr> </tr>
{{end}}
<tr> <tr>
<td>{{T "links"}}</td> <td>{{T "links"}}</td>
<td> <td>
@ -37,9 +42,11 @@
<span class="glyphicon glyphicon-magnet" aria-hidden="true"></span> Download! <span class="glyphicon glyphicon-magnet" aria-hidden="true"></span> Download!
</a> </a>
<a style="padding-left: 0.5em"></a> <a style="padding-left: 0.5em"></a>
<a aria-label="Torrent file" href="http://anicache.com/torrent/{{.Hash}}.torrent" type="button" class="btn btn-success download-btn"> {{if ne .TorrentLink ""}}
<a aria-label="Torrent file" href="{{.TorrentLink}}" type="button" class="btn btn-success download-btn">
<span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span> Torrent file <span class="glyphicon glyphicon-floppy-save" aria-hidden="true"></span> Torrent file
</a> </a>
{{end}}
</td> </td>
</tr> </tr>
<tr> <tr>

Voir le fichier

@ -101,7 +101,11 @@
}, },
{ {
"id":"signup_verification_email", "id":"signup_verification_email",
"translation": "Now, as the final step of registration please check your mail inbox (or spam) and click the link provided for activating your account!" "translation": "Finally, please check your mail inbox (and spam folder!) for the verification email."
},
{
"id":"signup_verification_noemail",
"translation": "Registration was successful, you may now use your account."
}, },
{ {
"id":"settings", "id":"settings",
@ -197,7 +201,7 @@
}, },
{ {
"id": "sign_in", "id": "sign_in",
"translation": "Sign in" "translation": "Sign In"
}, },
{ {
"id": "sign_up", "id": "sign_up",
@ -328,7 +332,7 @@
"translation": "Torrent file" "translation": "Torrent file"
}, },
{ {
"id": "uploading_torrent_prefills_fields", "id": "uploading_file_prefills_fields",
"translation": "Uploading a torrent file allows pre-filling some fields, this is recommended." "translation": "Uploading a torrent file allows pre-filling some fields, this is recommended."
}, },
{ {
@ -436,8 +440,8 @@
"translation": "Torrent Description" "translation": "Torrent Description"
}, },
{ {
"id": "limited_html_set_is_allowed_use", "id": "description_markdown_notice",
"translation": "A limited set of HTML is allowed in the description, make sure to use" "translation": "Markdown can be used in descriptions."
}, },
{ {
"id": "show_all", "id": "show_all",

Voir le fichier

@ -7,8 +7,34 @@ import (
"net/http" "net/http"
) )
// When go-i18n finds a language with >0 translations, it uses it as the Tfunc
// However, if said language has a missing translation, it won't fallback to the "main" language
func TfuncWithFallback(language string, languages ...string) (i18n.TranslateFunc, error) {
// Use the last language on the args as the fallback one.
fallbackLanguage := language
if languages != nil {
fallbackLanguage = languages[len(languages)-1]
}
T, err1 := i18n.Tfunc(language, languages...)
fallbackT, err2 := i18n.Tfunc(fallbackLanguage)
if err1 != nil && err2 != nil {
// fallbackT is still a valid function even with the error, it returns translationID.
return fallbackT, err2;
}
return func(translationID string, args ...interface{}) string {
if translated := T(translationID, args...); translated != translationID {
return translated
}
return fallbackT(translationID, args...)
}, nil
}
func SetTranslation(tmpl *template.Template, language string, languages ...string) i18n.TranslateFunc { func SetTranslation(tmpl *template.Template, language string, languages ...string) i18n.TranslateFunc {
T, _ := i18n.Tfunc(language, languages...) T, _ := TfuncWithFallback(language, languages...)
tmpl.Funcs(map[string]interface{}{ tmpl.Funcs(map[string]interface{}{
"T": func(str string, args ...interface{}) template.HTML { "T": func(str string, args ...interface{}) template.HTML {
return template.HTML(fmt.Sprintf(T(str), args...)) return template.HTML(fmt.Sprintf(T(str), args...))

Voir le fichier

@ -1,7 +1,14 @@
package util package util
import "html/template" import (
"html"
"html/template"
)
func Safe(s string) template.URL { func Safe(s string) template.URL {
return template.URL(s) return template.URL(s)
} }
func SafeText(s string) template.HTML {
return template.HTML(html.EscapeString(s))
}