From 263b1f5075b875e48974efe03bcea90f9525b441 Mon Sep 17 00:00:00 2001 From: Andrew Zhao Date: Sun, 7 May 2017 19:06:11 -0700 Subject: [PATCH 1/6] implemented comments and display --- model/comment.go | 17 ++++---- model/torrent.go | 83 +++++++++++++++++++++++++------------- router/uploadHandler.go | 3 +- service/torrent/torrent.go | 2 +- templates/view.html | 4 +- 5 files changed, 67 insertions(+), 42 deletions(-) diff --git a/model/comment.go b/model/comment.go index 7752f7af..26ec333c 100644 --- a/model/comment.go +++ b/model/comment.go @@ -6,13 +6,14 @@ import ( // Comment is a comment model. type Comment struct { - Id int `json:"id"` - Content string `json:"content"` - UserId int `json:"userId"` - TorrentId int + Id int `json:"id"` + Content string `json:"content"` + UserId int `json:"userId"` + Username string `json:"username"` // this is duplicate but it'll be faster rite? + TorrentId int // LikingCount int `json:"likingCount"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - DeletedAt time.Time `json:"deletedAt"` - User User `json:"user"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt time.Time `json:"deletedAt"` + User User `json:"user"` } diff --git a/model/torrent.go b/model/torrent.go index bb4c3b20..e3ab1c1e 100644 --- a/model/torrent.go +++ b/model/torrent.go @@ -21,17 +21,18 @@ type Feed struct { } type Torrents struct { - Id int `gorm:"column:torrent_id;primary_key"` - Name string `gorm:"column:torrent_name"` - Category int `gorm:"column:category_id"` - Sub_Category int `gorm:"column:sub_category_id"` - Status int `gorm:"column:status_id"` - Hash string `gorm:"column:torrent_hash"` - Date int64 `gorm:"column:date"` - Downloads int `gorm:"column:downloads"` - Filesize int64 `gorm:"column:filesize"` - Description string `gorm:"column:description"` - Comments []byte `gorm:"column:comments"` + Id int `gorm:"column:torrent_id;primary_key"` + Name string `gorm:"column:torrent_name"` + Category int `gorm:"column:category_id"` + Sub_Category int `gorm:"column:sub_category_id"` + Status int `gorm:"column:status_id"` + Hash string `gorm:"column:torrent_hash"` + Date int64 `gorm:"column:date"` + Downloads int `gorm:"column:downloads"` + Filesize int64 `gorm:"column:filesize"` + Description string `gorm:"column:description"` + 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 @@ -41,12 +42,12 @@ JSON Models Oject */ type ApiResultJson struct { - Torrents []TorrentsJson `json:"torrents"` - QueryRecordCount int `json:"queryRecordCount"` - TotalRecordCount int `json:"totalRecordCount"` + Torrents []TorrentsJson `json:"torrents"` + QueryRecordCount int `json:"queryRecordCount"` + TotalRecordCount int `json:"totalRecordCount"` } -type CommentsJson struct { +type OldCommentsJson struct { C template.HTML `json:"c"` Us string `json:"us"` Un string `json:"un"` @@ -56,26 +57,50 @@ type CommentsJson struct { ID string `json:"id"` } +type CommentsJson struct { + Content template.HTML `json:"content"` + Username string `json:"username"` +} + type TorrentsJson struct { - Id string `json:"id"` - Name string `json:"name"` - Status int `json:"status"` - Hash string `json:"hash"` - Date string `json:"date"` - Filesize string `json:"filesize"` - Description template.HTML `json:"description"` - Comments []CommentsJson `json:"comments"` - Sub_Category string `json:"sub_category"` - Category string `json:"category"` - Magnet template.URL `json:"magnet"` + Id string `json:"id"` + Name string `json:"name"` + Status int `json:"status"` + Hash string `json:"hash"` + Date string `json:"date"` + Filesize string `json:"filesize"` + Description template.HTML `json:"description"` + Comments []CommentsJson `json:"comments"` + Sub_Category string `json:"sub_category"` + Category string `json:"category"` + Magnet template.URL `json:"magnet"` } /* Model Conversion to Json */ func (t *Torrents) ToJson() TorrentsJson { magnet := util.InfoHashToMagnet(strings.TrimSpace(t.Hash), t.Name, config.Trackers...) - b := []CommentsJson{} - _ = json.Unmarshal([]byte(t.Comments), &b) + offset := 0 + 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{ Id: strconv.Itoa(t.Id), Name: html.UnescapeString(t.Name), @@ -84,7 +109,7 @@ func (t *Torrents) ToJson() TorrentsJson { Date: time.Unix(t.Date, 0).Format(time.RFC3339), Filesize: util.FormatFilesize2(t.Filesize), Description: template.HTML(t.Description), - Comments: b, + Comments: commentsJson, Sub_Category: strconv.Itoa(t.Sub_Category), Category: strconv.Itoa(t.Category), Magnet: util.Safe(magnet)} diff --git a/router/uploadHandler.go b/router/uploadHandler.go index ec60e012..5e9481ac 100644 --- a/router/uploadHandler.go +++ b/router/uploadHandler.go @@ -35,8 +35,7 @@ func UploadHandler(w http.ResponseWriter, r *http.Request) { Hash: uploadForm.Infohash, Date: time.Now().Unix(), Filesize: uploadForm.Filesize, // FIXME: should set to NULL instead of 0 - Description: uploadForm.Description, - Comments: []byte{}} + Description: uploadForm.Description} db.ORM.Create(&torrent) fmt.Printf("%+v\n", torrent) url, err := Router.Get("view_torrent").URL("id", strconv.Itoa(torrent.Id)) diff --git a/service/torrent/torrent.go b/service/torrent/torrent.go index d977ce94..1e5260e7 100644 --- a/service/torrent/torrent.go +++ b/service/torrent/torrent.go @@ -45,7 +45,7 @@ func GetFeeds() []model.Feed { func GetTorrentById(id string) (model.Torrents, error) { 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.") } diff --git a/templates/view.html b/templates/view.html index 43a898cd..f31fc190 100644 --- a/templates/view.html +++ b/templates/view.html @@ -49,8 +49,8 @@ {{ range .Comments }} - {{.Un}} - {{.C}} + {{.Username}} + {{.Content}} {{end}} From 15b1552f4e0753addc05de0501c82675802019ae Mon Sep 17 00:00:00 2001 From: Andrew Zhao Date: Sun, 7 May 2017 20:34:12 -0700 Subject: [PATCH 2/6] initial implementation of making comments --- model/comment.go | 8 ++++---- router/router.go | 3 ++- router/templateVariables.go | 4 +++- router/viewTorrentHandler.go | 29 +++++++++++++++++++++++++++-- templates/view.html | 14 ++++++++++++-- 5 files changed, 48 insertions(+), 10 deletions(-) diff --git a/model/comment.go b/model/comment.go index 26ec333c..721c0183 100644 --- a/model/comment.go +++ b/model/comment.go @@ -12,8 +12,8 @@ type Comment struct { Username string `json:"username"` // this is duplicate but it'll be faster rite? TorrentId int // LikingCount int `json:"likingCount"` - CreatedAt time.Time `json:"createdAt"` - UpdatedAt time.Time `json:"updatedAt"` - DeletedAt time.Time `json:"deletedAt"` - User User `json:"user"` + CreatedAt time.Time `json:"createdAt"` + UpdatedAt time.Time `json:"updatedAt"` + DeletedAt *time.Time `json:"deletedAt""` + User User `json:"user"` } diff --git a/router/router.go b/router/router.go index ecd9384c..52761354 100644 --- a/router/router.go +++ b/router/router.go @@ -46,7 +46,8 @@ func init() { Router.Handle("/api/view/{id}", gzipAPIViewHandler).Methods("GET") Router.Handle("/faq", gzipFaqHandler).Name("faq") 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("/user/register", gzipUserRegisterFormHandler).Name("user_register").Methods("GET") Router.Handle("/user/login", gzipUserLoginFormHandler).Name("user_login").Methods("GET") diff --git a/router/templateVariables.go b/router/templateVariables.go index 32eb7b8f..e73bcf15 100644 --- a/router/templateVariables.go +++ b/router/templateVariables.go @@ -7,6 +7,7 @@ import ( "github.com/ewhal/nyaa/model" userForms "github.com/ewhal/nyaa/service/user/form" "github.com/ewhal/nyaa/service/user" + "github.com/ewhal/nyaa/service/captcha" "github.com/gorilla/mux" ) @@ -34,6 +35,7 @@ type NotFoundTemplateVariables struct { type ViewTemplateVariables struct { Torrent model.TorrentsJson + Captcha captcha.Captcha Search SearchForm Navigation Navigation User model.User @@ -137,4 +139,4 @@ func NewSearchForm(params ...string) (searchForm SearchForm) { func GetUser(r *http.Request) model.User { user, _ , _ := userService.RetrieveCurrentUser(r) return user -} \ No newline at end of file +} diff --git a/router/viewTorrentHandler.go b/router/viewTorrentHandler.go index a52b8483..65a077e5 100644 --- a/router/viewTorrentHandler.go +++ b/router/viewTorrentHandler.go @@ -2,7 +2,11 @@ package router import ( "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/util/log" "github.com/gorilla/mux" @@ -18,11 +22,32 @@ func ViewHandler(w http.ResponseWriter, r *http.Request) { return } b := torrent.ToJson() - - htv := ViewTemplateVariables{b, NewSearchForm(), Navigation{}, GetUser(r), r.URL, mux.CurrentRoute(r)} + htv := ViewTemplateVariables{b, captcha.Captcha{CaptchaID: captcha.GetID()}, NewSearchForm(), Navigation{}, GetUser(r), r.URL, mux.CurrentRoute(r)} err = viewTemplate.ExecuteTemplate(w, "index.html", htv) if err != nil { 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 := 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) + } +} diff --git a/templates/view.html b/templates/view.html index f31fc190..2b5ebd33 100644 --- a/templates/view.html +++ b/templates/view.html @@ -30,7 +30,7 @@ Links - Download! + Download! @@ -54,6 +54,16 @@ {{end}} - {{end}} + {{end}} +
+
+ + +
+ {{with .Captcha}} + {{block "captcha" .}}{{end}} + {{end}} + +
{{end}} From 260e5bab46f341f1faaf9f044ae53501871d1381 Mon Sep 17 00:00:00 2001 From: Andrew Zhao Date: Sun, 7 May 2017 20:40:00 -0700 Subject: [PATCH 3/6] auto migrate comments table --- db/gorm.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/db/gorm.go b/db/gorm.go index a2cd4617..eeb5226e 100644 --- a/db/gorm.go +++ b/db/gorm.go @@ -31,7 +31,7 @@ func GormInit(conf *config.Config) (*gorm.DB, error) { if config.Environment == "DEVELOPMENT" { db.LogMode(true) // 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.Model(&model.User{}).AddIndex("idx_user_token", "token") From fd976fc7e0947e0cdd694a697f77262f266be2e9 Mon Sep 17 00:00:00 2001 From: Andrew Zhao Date: Sun, 7 May 2017 21:49:00 -0700 Subject: [PATCH 4/6] add clickable comment targets --- public/css/style-night.css | 6 ++++++ public/css/style.css | 6 +++++- templates/view.html | 9 ++++++--- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/public/css/style-night.css b/public/css/style-night.css index 024902ab..289f738c 100644 --- a/public/css/style-night.css +++ b/public/css/style-night.css @@ -187,3 +187,9 @@ div.container div.blockBody:nth-of-type(2) table tr:first-of-type th:last-of-typ .navbar { border-radius: 0px; } + + +:target { + background-color: #585b4f; +} + diff --git a/public/css/style.css b/public/css/style.css index 86db4521..dadcf202 100644 --- a/public/css/style.css +++ b/public/css/style.css @@ -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 { padding-top: 10px; padding-bottom: 10px; -} \ No newline at end of file +} + +:target { + background-color: #e5eecc; +} diff --git a/templates/view.html b/templates/view.html index 2b5ebd33..ce3f1426 100644 --- a/templates/view.html +++ b/templates/view.html @@ -47,9 +47,12 @@ Comments - {{ range .Comments }} - - {{.Username}} + {{ range $index, $element := .Comments }} + + +
{{$index}} + {{.Username}} + {{.Content}} {{end}} From f04b1ed659bc54329c0384e6e4ccdbae97a3e574 Mon Sep 17 00:00:00 2001 From: Andrew Zhao Date: Sun, 7 May 2017 21:58:21 -0700 Subject: [PATCH 5/6] sanitize comments --- router/viewTorrentHandler.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/router/viewTorrentHandler.go b/router/viewTorrentHandler.go index 65a077e5..dfe244e8 100644 --- a/router/viewTorrentHandler.go +++ b/router/viewTorrentHandler.go @@ -10,8 +10,11 @@ import ( "github.com/ewhal/nyaa/service/torrent" "github.com/ewhal/nyaa/util/log" "github.com/gorilla/mux" + "github.com/microcosm-cc/bluemonday" ) +var p = bluemonday.UGCPolicy() + func ViewHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id := vars["id"] @@ -38,7 +41,7 @@ func PostCommentHandler(w http.ResponseWriter, r *http.Request) { if !captcha.Authenticate(userCaptcha) { http.Error(w, "bad captcha", 403) } - content := r.FormValue("comment") + content := p.Sanitize(r.FormValue("comment")) idNum, err := strconv.Atoi(id) comment := model.Comment{Username: "れんちょん", Content: content, TorrentId: idNum} From b7a76c9d5db1ec113b4beffe34fb31f82dd53b3b Mon Sep 17 00:00:00 2001 From: Andrew Zhao Date: Sun, 7 May 2017 22:01:46 -0700 Subject: [PATCH 6/6] dont need these to compile --- router/viewTorrentHandler.go | 3 --- 1 file changed, 3 deletions(-) diff --git a/router/viewTorrentHandler.go b/router/viewTorrentHandler.go index dfe244e8..1dc95d57 100644 --- a/router/viewTorrentHandler.go +++ b/router/viewTorrentHandler.go @@ -10,11 +10,8 @@ import ( "github.com/ewhal/nyaa/service/torrent" "github.com/ewhal/nyaa/util/log" "github.com/gorilla/mux" - "github.com/microcosm-cc/bluemonday" ) -var p = bluemonday.UGCPolicy() - func ViewHandler(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) id := vars["id"]