révision
d96a35d031
11 fichiers modifiés avec 128 ajouts et 52 suppressions
|
@ -31,7 +31,7 @@ func GormInit(conf *config.Config) (*gorm.DB, error) {
|
||||||
if config.Environment == "DEVELOPMENT" {
|
if config.Environment == "DEVELOPMENT" {
|
||||||
db.LogMode(true)
|
db.LogMode(true)
|
||||||
// db.DropTable(&model.User{}, "UserFollower")
|
// db.DropTable(&model.User{}, "UserFollower")
|
||||||
db.AutoMigrate(&model.Torrents{}, &model.UsersFollowers{}, &model.User{}, &model.Role{}, &model.Language{})
|
db.AutoMigrate(&model.Torrents{}, &model.UsersFollowers{}, &model.User{}, &model.Role{}, &model.Language{}, &model.Comment{})
|
||||||
// db.AutoMigrate(&model.Comment{})
|
// db.AutoMigrate(&model.Comment{})
|
||||||
// db.Model(&model.User{}).AddIndex("idx_user_token", "token")
|
// db.Model(&model.User{}).AddIndex("idx_user_token", "token")
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,14 @@ import (
|
||||||
|
|
||||||
// Comment is a comment model.
|
// Comment is a comment model.
|
||||||
type Comment struct {
|
type Comment struct {
|
||||||
Id int `json:"id"`
|
Id int `json:"id"`
|
||||||
Content string `json:"content"`
|
Content string `json:"content"`
|
||||||
UserId int `json:"userId"`
|
UserId int `json:"userId"`
|
||||||
TorrentId int
|
Username string `json:"username"` // this is duplicate but it'll be faster rite?
|
||||||
|
TorrentId int
|
||||||
// LikingCount int `json:"likingCount"`
|
// LikingCount int `json:"likingCount"`
|
||||||
CreatedAt time.Time `json:"createdAt"`
|
CreatedAt time.Time `json:"createdAt"`
|
||||||
UpdatedAt time.Time `json:"updatedAt"`
|
UpdatedAt time.Time `json:"updatedAt"`
|
||||||
DeletedAt time.Time `json:"deletedAt"`
|
DeletedAt *time.Time `json:"deletedAt""`
|
||||||
User User `json:"user"`
|
User User `json:"user"`
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,17 +21,18 @@ type Feed struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type Torrents struct {
|
type Torrents struct {
|
||||||
Id int `gorm:"column:torrent_id;primary_key"`
|
Id int `gorm:"column:torrent_id;primary_key"`
|
||||||
Name string `gorm:"column:torrent_name"`
|
Name string `gorm:"column:torrent_name"`
|
||||||
Category int `gorm:"column:category_id"`
|
Category int `gorm:"column:category_id"`
|
||||||
Sub_Category int `gorm:"column:sub_category_id"`
|
Sub_Category int `gorm:"column:sub_category_id"`
|
||||||
Status int `gorm:"column:status_id"`
|
Status int `gorm:"column:status_id"`
|
||||||
Hash string `gorm:"column:torrent_hash"`
|
Hash string `gorm:"column:torrent_hash"`
|
||||||
Date int64 `gorm:"column:date"`
|
Date int64 `gorm:"column:date"`
|
||||||
Downloads int `gorm:"column:downloads"`
|
Downloads int `gorm:"column:downloads"`
|
||||||
Filesize int64 `gorm:"column:filesize"`
|
Filesize int64 `gorm:"column:filesize"`
|
||||||
Description string `gorm:"column:description"`
|
Description string `gorm:"column:description"`
|
||||||
Comments []byte `gorm:"column:comments"`
|
OldComments []byte `gorm:"column:comments"`
|
||||||
|
Comments []Comment `gorm:"ForeignKey:TorrentId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We need JSON Object instead because of Magnet URL that is not in the database but generated dynamically
|
/* We need JSON Object instead because of Magnet URL that is not in the database but generated dynamically
|
||||||
|
@ -41,12 +42,12 @@ JSON Models Oject
|
||||||
*/
|
*/
|
||||||
|
|
||||||
type ApiResultJson struct {
|
type ApiResultJson struct {
|
||||||
Torrents []TorrentsJson `json:"torrents"`
|
Torrents []TorrentsJson `json:"torrents"`
|
||||||
QueryRecordCount int `json:"queryRecordCount"`
|
QueryRecordCount int `json:"queryRecordCount"`
|
||||||
TotalRecordCount int `json:"totalRecordCount"`
|
TotalRecordCount int `json:"totalRecordCount"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type CommentsJson struct {
|
type OldCommentsJson struct {
|
||||||
C template.HTML `json:"c"`
|
C template.HTML `json:"c"`
|
||||||
Us string `json:"us"`
|
Us string `json:"us"`
|
||||||
Un string `json:"un"`
|
Un string `json:"un"`
|
||||||
|
@ -56,26 +57,50 @@ type CommentsJson struct {
|
||||||
ID string `json:"id"`
|
ID string `json:"id"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type CommentsJson struct {
|
||||||
|
Content template.HTML `json:"content"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
}
|
||||||
|
|
||||||
type TorrentsJson struct {
|
type TorrentsJson struct {
|
||||||
Id string `json:"id"`
|
Id string `json:"id"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Status int `json:"status"`
|
Status int `json:"status"`
|
||||||
Hash string `json:"hash"`
|
Hash string `json:"hash"`
|
||||||
Date string `json:"date"`
|
Date string `json:"date"`
|
||||||
Filesize string `json:"filesize"`
|
Filesize string `json:"filesize"`
|
||||||
Description template.HTML `json:"description"`
|
Description template.HTML `json:"description"`
|
||||||
Comments []CommentsJson `json:"comments"`
|
Comments []CommentsJson `json:"comments"`
|
||||||
Sub_Category string `json:"sub_category"`
|
Sub_Category string `json:"sub_category"`
|
||||||
Category string `json:"category"`
|
Category string `json:"category"`
|
||||||
Magnet template.URL `json:"magnet"`
|
Magnet template.URL `json:"magnet"`
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Model Conversion to Json */
|
/* Model Conversion to Json */
|
||||||
|
|
||||||
func (t *Torrents) ToJson() TorrentsJson {
|
func (t *Torrents) ToJson() TorrentsJson {
|
||||||
magnet := util.InfoHashToMagnet(strings.TrimSpace(t.Hash), t.Name, config.Trackers...)
|
magnet := util.InfoHashToMagnet(strings.TrimSpace(t.Hash), t.Name, config.Trackers...)
|
||||||
b := []CommentsJson{}
|
offset := 0
|
||||||
_ = json.Unmarshal([]byte(t.Comments), &b)
|
var commentsJson []CommentsJson
|
||||||
|
if len(t.OldComments) != 0 {
|
||||||
|
b := []OldCommentsJson{}
|
||||||
|
err := json.Unmarshal([]byte(t.OldComments), &b)
|
||||||
|
if err == nil {
|
||||||
|
commentsJson = make([]CommentsJson, len(t.Comments)+len(b))
|
||||||
|
offset = len(b)
|
||||||
|
for i, commentJson := range b {
|
||||||
|
commentsJson[i] = CommentsJson{Content: commentJson.C,
|
||||||
|
Username: commentJson.Un}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
commentsJson = make([]CommentsJson, len(t.Comments))
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
commentsJson = make([]CommentsJson, len(t.Comments))
|
||||||
|
}
|
||||||
|
for i, comment := range t.Comments {
|
||||||
|
commentsJson[i+offset] = CommentsJson{Content: template.HTML(comment.Content), Username: comment.Username}
|
||||||
|
}
|
||||||
res := TorrentsJson{
|
res := TorrentsJson{
|
||||||
Id: strconv.Itoa(t.Id),
|
Id: strconv.Itoa(t.Id),
|
||||||
Name: html.UnescapeString(t.Name),
|
Name: html.UnescapeString(t.Name),
|
||||||
|
@ -84,7 +109,7 @@ func (t *Torrents) ToJson() TorrentsJson {
|
||||||
Date: time.Unix(t.Date, 0).Format(time.RFC3339),
|
Date: time.Unix(t.Date, 0).Format(time.RFC3339),
|
||||||
Filesize: util.FormatFilesize2(t.Filesize),
|
Filesize: util.FormatFilesize2(t.Filesize),
|
||||||
Description: template.HTML(t.Description),
|
Description: template.HTML(t.Description),
|
||||||
Comments: b,
|
Comments: commentsJson,
|
||||||
Sub_Category: strconv.Itoa(t.Sub_Category),
|
Sub_Category: strconv.Itoa(t.Sub_Category),
|
||||||
Category: strconv.Itoa(t.Category),
|
Category: strconv.Itoa(t.Category),
|
||||||
Magnet: util.Safe(magnet)}
|
Magnet: util.Safe(magnet)}
|
||||||
|
|
|
@ -187,3 +187,9 @@ div.container div.blockBody:nth-of-type(2) table tr:first-of-type th:last-of-typ
|
||||||
.navbar {
|
.navbar {
|
||||||
border-radius: 0px;
|
border-radius: 0px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
:target {
|
||||||
|
background-color: #585b4f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -191,4 +191,8 @@ div.container div.blockBody:nth-of-type(2) table tr:first-of-type th:last-of-typ
|
||||||
.navbar-nav>li>a.profile-image {
|
.navbar-nav>li>a.profile-image {
|
||||||
padding-top: 10px;
|
padding-top: 10px;
|
||||||
padding-bottom: 10px;
|
padding-bottom: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
:target {
|
||||||
|
background-color: #e5eecc;
|
||||||
|
}
|
||||||
|
|
|
@ -46,7 +46,8 @@ func init() {
|
||||||
Router.Handle("/api/view/{id}", gzipAPIViewHandler).Methods("GET")
|
Router.Handle("/api/view/{id}", gzipAPIViewHandler).Methods("GET")
|
||||||
Router.Handle("/faq", gzipFaqHandler).Name("faq")
|
Router.Handle("/faq", gzipFaqHandler).Name("faq")
|
||||||
Router.Handle("/feed", gzipRssHandler).Name("feed")
|
Router.Handle("/feed", gzipRssHandler).Name("feed")
|
||||||
Router.Handle("/view/{id}", gzipViewHandler).Name("view_torrent")
|
Router.Handle("/view/{id}", gzipViewHandler).Methods("GET").Name("view_torrent")
|
||||||
|
Router.HandleFunc("/view/{id}", PostCommentHandler).Methods("POST").Name("post_comment")
|
||||||
Router.Handle("/upload", gzipUploadHandler).Name("upload")
|
Router.Handle("/upload", gzipUploadHandler).Name("upload")
|
||||||
Router.Handle("/user/register", gzipUserRegisterFormHandler).Name("user_register").Methods("GET")
|
Router.Handle("/user/register", gzipUserRegisterFormHandler).Name("user_register").Methods("GET")
|
||||||
Router.Handle("/user/login", gzipUserLoginFormHandler).Name("user_login").Methods("GET")
|
Router.Handle("/user/login", gzipUserLoginFormHandler).Name("user_login").Methods("GET")
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"github.com/ewhal/nyaa/model"
|
"github.com/ewhal/nyaa/model"
|
||||||
userForms "github.com/ewhal/nyaa/service/user/form"
|
userForms "github.com/ewhal/nyaa/service/user/form"
|
||||||
"github.com/ewhal/nyaa/service/user"
|
"github.com/ewhal/nyaa/service/user"
|
||||||
|
"github.com/ewhal/nyaa/service/captcha"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -34,6 +35,7 @@ type NotFoundTemplateVariables struct {
|
||||||
|
|
||||||
type ViewTemplateVariables struct {
|
type ViewTemplateVariables struct {
|
||||||
Torrent model.TorrentsJson
|
Torrent model.TorrentsJson
|
||||||
|
Captcha captcha.Captcha
|
||||||
Search SearchForm
|
Search SearchForm
|
||||||
Navigation Navigation
|
Navigation Navigation
|
||||||
User model.User
|
User model.User
|
||||||
|
@ -137,4 +139,4 @@ func NewSearchForm(params ...string) (searchForm SearchForm) {
|
||||||
func GetUser(r *http.Request) model.User {
|
func GetUser(r *http.Request) model.User {
|
||||||
user, _ , _ := userService.RetrieveCurrentUser(r)
|
user, _ , _ := userService.RetrieveCurrentUser(r)
|
||||||
return user
|
return user
|
||||||
}
|
}
|
||||||
|
|
|
@ -35,8 +35,7 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
Hash: uploadForm.Infohash,
|
Hash: uploadForm.Infohash,
|
||||||
Date: time.Now().Unix(),
|
Date: time.Now().Unix(),
|
||||||
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}
|
||||||
Comments: []byte{}}
|
|
||||||
db.ORM.Create(&torrent)
|
db.ORM.Create(&torrent)
|
||||||
fmt.Printf("%+v\n", torrent)
|
fmt.Printf("%+v\n", torrent)
|
||||||
url, err := Router.Get("view_torrent").URL("id", strconv.Itoa(torrent.Id))
|
url, err := Router.Get("view_torrent").URL("id", strconv.Itoa(torrent.Id))
|
||||||
|
|
|
@ -2,7 +2,11 @@ package router
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/ewhal/nyaa/db"
|
||||||
|
"github.com/ewhal/nyaa/model"
|
||||||
|
"github.com/ewhal/nyaa/service/captcha"
|
||||||
"github.com/ewhal/nyaa/service/torrent"
|
"github.com/ewhal/nyaa/service/torrent"
|
||||||
"github.com/ewhal/nyaa/util/log"
|
"github.com/ewhal/nyaa/util/log"
|
||||||
"github.com/gorilla/mux"
|
"github.com/gorilla/mux"
|
||||||
|
@ -18,11 +22,32 @@ func ViewHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
b := torrent.ToJson()
|
b := torrent.ToJson()
|
||||||
|
htv := ViewTemplateVariables{b, captcha.Captcha{CaptchaID: captcha.GetID()}, NewSearchForm(), Navigation{}, GetUser(r), r.URL, mux.CurrentRoute(r)}
|
||||||
htv := ViewTemplateVariables{b, NewSearchForm(), Navigation{}, GetUser(r), r.URL, mux.CurrentRoute(r)}
|
|
||||||
|
|
||||||
err = viewTemplate.ExecuteTemplate(w, "index.html", htv)
|
err = viewTemplate.ExecuteTemplate(w, "index.html", htv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Errorf("ViewHandler(): %s", err)
|
log.Errorf("ViewHandler(): %s", err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PostCommentHandler(w http.ResponseWriter, r *http.Request) {
|
||||||
|
vars := mux.Vars(r)
|
||||||
|
id := vars["id"]
|
||||||
|
|
||||||
|
userCaptcha := captcha.Extract(r)
|
||||||
|
if !captcha.Authenticate(userCaptcha) {
|
||||||
|
http.Error(w, "bad captcha", 403)
|
||||||
|
}
|
||||||
|
content := p.Sanitize(r.FormValue("comment"))
|
||||||
|
|
||||||
|
idNum, err := strconv.Atoi(id)
|
||||||
|
comment := model.Comment{Username: "れんちょん", Content: content, TorrentId: idNum}
|
||||||
|
db.ORM.Create(&comment)
|
||||||
|
|
||||||
|
url, err := Router.Get("view_torrent").URL("id", id)
|
||||||
|
if err == nil {
|
||||||
|
http.Redirect(w, r, url.String(), 302)
|
||||||
|
} else {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -45,7 +45,7 @@ func GetFeeds() []model.Feed {
|
||||||
func GetTorrentById(id string) (model.Torrents, error) {
|
func GetTorrentById(id string) (model.Torrents, error) {
|
||||||
var torrent model.Torrents
|
var torrent model.Torrents
|
||||||
|
|
||||||
if db.ORM.Where("torrent_id = ?", id).Find(&torrent).RecordNotFound() {
|
if db.ORM.Where("torrent_id = ?", id).Preload("Comments").Find(&torrent).RecordNotFound() {
|
||||||
return torrent, errors.New("Article is not found.")
|
return torrent, errors.New("Article is not found.")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
<td>Links</td>
|
<td>Links</td>
|
||||||
<td>
|
<td>
|
||||||
<a aria-label="Magnet Button" href="{{.Magnet}}" type="button" class="btn btn-success download-btn">
|
<a aria-label="Magnet Button" href="{{.Magnet}}" type="button" class="btn btn-success download-btn">
|
||||||
<span class="glyphicon glyphicon-magnet" aria-hidden="true"></span> Download!</button>
|
<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">
|
<a aria-label="Torrent file" href="http://anicache.com/torrent/{{.Hash}}.torrent" type="button" class="btn btn-success">
|
||||||
|
@ -47,13 +47,26 @@
|
||||||
<td>Comments</td>
|
<td>Comments</td>
|
||||||
<td></td>
|
<td></td>
|
||||||
</tr>
|
</tr>
|
||||||
{{ range .Comments }}
|
{{ range $index, $element := .Comments }}
|
||||||
<tr class="comment-row">
|
<tr class="comment-row" id="comment_{{$index}}">
|
||||||
<td>{{.Un}}</td>
|
<td>
|
||||||
<td>{{.C}}</td>
|
<a href="#comment_{{$index}}">{{$index}}</a>
|
||||||
|
{{.Username}}
|
||||||
|
</td>
|
||||||
|
<td>{{.Content}}</td>
|
||||||
</tr>
|
</tr>
|
||||||
{{end}}
|
{{end}}
|
||||||
</table>
|
</table>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
<form method="post">
|
||||||
|
<div class="form-group">
|
||||||
|
<label for="comment">Submit a Comment</label>
|
||||||
|
<textarea name="comment" class="form-control" rows="5"></textarea>
|
||||||
|
</div>
|
||||||
|
{{with .Captcha}}
|
||||||
|
{{block "captcha" .}}{{end}}
|
||||||
|
{{end}}
|
||||||
|
<input type="submit" value="Submit">
|
||||||
|
</form>
|
||||||
</div>
|
</div>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
|
Référencer dans un nouveau ticket