diff --git a/api/album.go b/api/album.go index 9beb3b4..89f5c0a 100644 --- a/api/album.go +++ b/api/album.go @@ -4,9 +4,9 @@ import ( "io" "net/http" "strings" - "time" "codeberg.org/video-prize-ranch/rimgo/types" + "codeberg.org/video-prize-ranch/rimgo/utils" "github.com/spf13/viper" "github.com/tidwall/gjson" ) @@ -35,8 +35,8 @@ func FetchAlbum(albumID string) (types.Album, error) { media = append(media, types.Media{ Id: value.Get("id").String(), Name: value.Get("name").String(), - MimeType: value.Get("mime_type").String(), - Type: value.Get("type").String(), + MimeType: value.Get("mime_type").String(), + Type: value.Get("type").String(), Title: value.Get("metadata.title").String(), Description: value.Get("metadata.description").String(), Url: url, @@ -46,7 +46,7 @@ func FetchAlbum(albumID string) (types.Album, error) { }, ) - createdAt, err := time.Parse("2006-01-02T15:04:05Z", data.Get("created_at").String()) + createdAt, err := utils.FormatDate(data.Get("created_at").String()) if err != nil { return types.Album{}, err } @@ -55,7 +55,10 @@ func FetchAlbum(albumID string) (types.Album, error) { Id: data.Get("id").String(), Title: data.Get("title").String(), Views: data.Get("view_count").Int(), - CreatedAt: createdAt.Format("January 2, 2006 3:04 PM"), + Upvotes: data.Get("upvote_count").Int(), + Downvotes: data.Get("downvote_count").Int(), + Comments: data.Get("comment_count").Int(), + CreatedAt: createdAt, Media: media, }, nil } diff --git a/api/comments.go b/api/comments.go new file mode 100644 index 0000000..4137e81 --- /dev/null +++ b/api/comments.go @@ -0,0 +1,92 @@ +package api + +import ( + "io" + "net/http" + "strings" + "sync" + "time" + + "codeberg.org/video-prize-ranch/rimgo/types" + "codeberg.org/video-prize-ranch/rimgo/utils" + "github.com/dustin/go-humanize" + "github.com/spf13/viper" + "github.com/tidwall/gjson" +) + +func FetchComments(galleryID string) ([]types.Comment, error) { + // https://api.imgur.com/comment/v1/comments?client_id=546c25a59c58ad7&filter[post]=eq:g1bk7CB&include=account&per_page=30&sort=best + + res, err := http.Get("https://api.imgur.com/comment/v1/comments?client_id=" + viper.GetString("RIMGU_IMGUR_CLIENT_ID") + "&filter[post]=eq:" + galleryID + "&include=account,adconfig&per_page=30&sort=best") + if err != nil { + return []types.Comment{}, err + } + + body, err := io.ReadAll(res.Body) + if err != nil { + return []types.Comment{}, err + } + + data := gjson.Parse(string(body)) + + wg := sync.WaitGroup{} + comments := make([]types.Comment, 0) + data.Get("data").ForEach( + func(key, value gjson.Result) bool { + wg.Add(1) + + go func() { + defer wg.Done() + comments = append(comments, ParseComment(value)) + }() + + return true + }, + ) + wg.Wait() + + return comments, nil +} + +func ParseComment(data gjson.Result) types.Comment { + createdTime, _ := time.Parse("2006-01-02T15:04:05Z", data.Get("created_at").String()) + createdAt := createdTime.Format("January 2, 2006 3:04 PM") + updatedAt, _ := utils.FormatDate(data.Get("updated_at").String()) + deletedAt, _ := utils.FormatDate(data.Get("deleted_at").String()) + + userAvatar := strings.ReplaceAll(data.Get("account.avatar").String(), "https://i.imgur.com", "") + + wg := sync.WaitGroup{} + comments := make([]types.Comment, 0) + data.Get("comments").ForEach( + func(key, value gjson.Result) bool { + wg.Add(1) + + go func() { + defer wg.Done() + comments = append(comments, ParseComment(value)) + }() + + return true + }, + ) + wg.Wait() + + return types.Comment{ + Comments: comments, + User: types.User{ + Id: data.Get("account.id").String(), + Username: data.Get("account.username").String(), + Avatar: userAvatar, + }, + Id: data.Get("id").String(), + Comment: data.Get("comment").String(), + Upvotes: data.Get("upvote_count").Int(), + Downvotes: data.Get("downvote_count").Int(), + Platform: data.Get("platform").String(), + CreatedAt: createdAt, + RelTime: humanize.Time(createdTime), + UpdatedAt: updatedAt, + DeletedAt: deletedAt, + } +} diff --git a/api/f.ts b/api/f.ts index ef73ac1..1034b7c 100644 --- a/api/f.ts +++ b/api/f.ts @@ -1,13 +1,3 @@ -export const fetchComments = async (galleryID: string): Promise => { - /* eslint-disable max-len */ - // https://api.imgur.com/comment/v1/comments?client_id=${CLIENT_ID}%5Bpost%5D=eq%3Ag1bk7CB&include=account%2Cadconfig&per_page=30&sort=best - const response = await get( - `https://api.imgur.com/comment/v1/comments?client_id=${CONFIG.imgur_client_id}&filter%5Bpost%5D=eq%3A${galleryID}&include=account%2Cadconfig&per_page=30&sort=best`, - ); - return JSON.parse(response.body).data; - /* eslint-enable max-len */ -} - export const fetchUserInfo = async (userID: string): Promise => { // https://api.imgur.com/account/v1/accounts/hughjaniss?client_id=${CLIENT_ID} const response = await get( diff --git a/go.mod b/go.mod index bc3afdc..4d09f6b 100644 --- a/go.mod +++ b/go.mod @@ -12,6 +12,7 @@ require ( require ( github.com/andybalholm/brotli v1.0.2 // indirect github.com/aymerick/raymond v2.0.2+incompatible // indirect + github.com/dustin/go-humanize v1.0.0 // indirect github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/hashicorp/hcl v1.0.0 // indirect github.com/klauspost/compress v1.13.4 // indirect diff --git a/go.sum b/go.sum index 8493b39..1e5d262 100644 --- a/go.sum +++ b/go.sum @@ -102,6 +102,8 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= +github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= diff --git a/pages/gallery.go b/pages/gallery.go index 99fffbe..eb614cd 100644 --- a/pages/gallery.go +++ b/pages/gallery.go @@ -20,8 +20,14 @@ func HandleGallery(c *fiber.Ctx) error { return err } + comments, err := api.FetchComments(c.Params("galleryID")) + if err != nil { + return err + } + return c.Render("gallery", fiber.Map{ - "album": album, - "isAlbum": false, + "album": album, + "comments": comments, + "isAlbum": false, }) } diff --git a/static/css/album.css b/static/css/album.css index 95e378c..96d028a 100644 --- a/static/css/album.css +++ b/static/css/album.css @@ -11,6 +11,10 @@ img { max-width: 100%; } +.pfp { + border-radius: 100%; +} + .imageMeta__wrapper, .imageMeta__item, .imageMeta { diff --git a/static/css/comments.css b/static/css/comments.css new file mode 100644 index 0000000..37a5d62 --- /dev/null +++ b/static/css/comments.css @@ -0,0 +1,62 @@ +.comment { + display: flex; + flex-direction: column; + gap: 0.5em; +} + +.comments { + gap: 0.25em; + display: flex; + flex-direction: column; +} + +.replies { + margin-left: 20px; + border-left: 2px #d2d2d2 solid; + padding-left: 8px; +} + +#comments__expandBtn { + display: none; +} + +.comments__expandBtn__label { + display: flex; + flex-direction: row; + justify-content: space-between; + align-items: center; + cursor: pointer; + user-select: none; + text-decoration: none; + color: #fff +} + +.comments__expandBtn__icon { + font-size: 24px; +} + +#comments__expandBtn ~ .comments__expandBtn__label > span::after { + content: "expand_more"; +} + +#comments__expandBtn:checked ~ .comments__expandBtn__label > span::after { + content: "expand_less"; +} + +#comments__expandBtn:checked ~ .comments { + display: none; +} + +.comment__media { + display: inline; +} + +.comment__updatedDate { + font-size: 0.8em; +} + +.comment__user { + display: flex; + gap: 6px; + align-items: center; +} \ No newline at end of file diff --git a/types/Album.go b/types/Album.go index 8a476c4..e1da2b2 100644 --- a/types/Album.go +++ b/types/Album.go @@ -8,5 +8,6 @@ type Album struct { Downvotes int64 CreatedAt string UpdatedAt string + Comments int64 Media []Media } diff --git a/types/Comment.go b/types/Comment.go new file mode 100644 index 0000000..3541ed1 --- /dev/null +++ b/types/Comment.go @@ -0,0 +1,15 @@ +package types + +type Comment struct { + Comments []Comment + User User + Id string + Comment string + Upvotes int64 + Downvotes int64 + Platform string + CreatedAt string + RelTime string + UpdatedAt string + DeletedAt string +} diff --git a/utils/formatDate.go b/utils/formatDate.go new file mode 100644 index 0000000..85a014f --- /dev/null +++ b/utils/formatDate.go @@ -0,0 +1,12 @@ +package utils + +import "time" + +func FormatDate(date string) (string, error) { + time, err := time.Parse("2006-01-02T15:04:05Z", date) + if err != nil { + return "", err + } + + return time.Format("Jan 2, 2006 3:04 PM"), nil +} \ No newline at end of file diff --git a/views/gallery.hbs b/views/gallery.hbs index c5bbc13..1a274c2 100644 --- a/views/gallery.hbs +++ b/views/gallery.hbs @@ -3,10 +3,11 @@ {{> partials/head }} - + - + + @@ -65,6 +66,21 @@
{{/each}} + +
+
+ + +
+ {{#each comments}} + {{> partials/comment }} + {{/each}} +
+
+
{{> partials/footer }} diff --git a/views/partials/comment.hbs b/views/partials/comment.hbs new file mode 100644 index 0000000..476e22b --- /dev/null +++ b/views/partials/comment.hbs @@ -0,0 +1,28 @@ +
+
+ + +

{{this.User.Username}}

+ +
+
+ {{{this.Comment}}} +

+ {{this.RelTime}} + {{#if this.UpdatedAt}} + (edited {{this.UpdatedAt}}) + {{/if}} + {{#if this.DeletedAt}} + (deleted {{this.DeletedAt}}) + {{/if}} + | + thumb_up {{this.Upvotes}} + thumb_down {{this.Downvotes}} +

+
+
+ {{#each this.Comments}} + {{> partials/comment }} + {{/each}} +
+
\ No newline at end of file