merged
Cette révision appartient à :
révision
ab330e77c7
19 fichiers modifiés avec 225 ajouts et 82 suppressions
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
|
@ -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
12
main.go
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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 {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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, ®istrationForm)
|
modelHelper.AssignValue(&user, ®istrationForm)
|
||||||
|
<<<<<<< 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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
|
@ -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"><br/></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>
|
||||||
|
|
||||||
|
|
|
@ -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}}
|
||||||
|
|
|
@ -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>
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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...))
|
||||||
|
|
11
util/safe.go
11
util/safe.go
|
@ -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))
|
||||||
|
}
|
||||||
|
|
Référencer dans un nouveau ticket