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") diff --git a/model/comment.go b/model/comment.go index 7752f7af..721c0183 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/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/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/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/router/viewTorrentHandler.go b/router/viewTorrentHandler.go index a52b8483..1dc95d57 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 := 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) + } +} 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..ce3f1426 100644 --- a/templates/view.html +++ b/templates/view.html @@ -30,7 +30,7 @@ Links - Download! + Download! @@ -47,13 +47,26 @@ Comments - {{ range .Comments }} - - {{.Un}} - {{.C}} + {{ range $index, $element := .Comments }} + + + {{$index}} + {{.Username}} + + {{.Content}} {{end}} - {{end}} + {{end}} +
+
+ + +
+ {{with .Captcha}} + {{block "captcha" .}}{{end}} + {{end}} + +
{{end}}