This commit is contained in:
video-prize-ranch 2022-01-18 18:05:06 -05:00
parent 87c8618cf5
commit 4a1309e0dc
No known key found for this signature in database
GPG Key ID: D8EAA4C5B12A7281
13 changed files with 251 additions and 19 deletions

View File

@ -4,9 +4,9 @@ import (
"io" "io"
"net/http" "net/http"
"strings" "strings"
"time"
"codeberg.org/video-prize-ranch/rimgo/types" "codeberg.org/video-prize-ranch/rimgo/types"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/spf13/viper" "github.com/spf13/viper"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
) )
@ -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 { if err != nil {
return types.Album{}, err return types.Album{}, err
} }
@ -55,7 +55,10 @@ func FetchAlbum(albumID string) (types.Album, error) {
Id: data.Get("id").String(), Id: data.Get("id").String(),
Title: data.Get("title").String(), Title: data.Get("title").String(),
Views: data.Get("view_count").Int(), 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, Media: media,
}, nil }, nil
} }

92
api/comments.go Normal file
View File

@ -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,
}
}

View File

@ -1,13 +1,3 @@
export const fetchComments = async (galleryID: string): Promise<Comment[]> => {
/* 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<UserResult> => { export const fetchUserInfo = async (userID: string): Promise<UserResult> => {
// https://api.imgur.com/account/v1/accounts/hughjaniss?client_id=${CLIENT_ID} // https://api.imgur.com/account/v1/accounts/hughjaniss?client_id=${CLIENT_ID}
const response = await get( const response = await get(

1
go.mod
View File

@ -12,6 +12,7 @@ require (
require ( require (
github.com/andybalholm/brotli v1.0.2 // indirect github.com/andybalholm/brotli v1.0.2 // indirect
github.com/aymerick/raymond v2.0.2+incompatible // 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/fsnotify/fsnotify v1.5.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/hashicorp/hcl v1.0.0 // indirect
github.com/klauspost/compress v1.13.4 // indirect github.com/klauspost/compress v1.13.4 // indirect

2
go.sum
View File

@ -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.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 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 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/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.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= github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=

View File

@ -20,8 +20,14 @@ func HandleGallery(c *fiber.Ctx) error {
return err return err
} }
comments, err := api.FetchComments(c.Params("galleryID"))
if err != nil {
return err
}
return c.Render("gallery", fiber.Map{ return c.Render("gallery", fiber.Map{
"album": album, "album": album,
"comments": comments,
"isAlbum": false, "isAlbum": false,
}) })
} }

View File

@ -11,6 +11,10 @@ img {
max-width: 100%; max-width: 100%;
} }
.pfp {
border-radius: 100%;
}
.imageMeta__wrapper, .imageMeta__wrapper,
.imageMeta__item, .imageMeta__item,
.imageMeta { .imageMeta {

62
static/css/comments.css Normal file
View File

@ -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;
}

View File

@ -8,5 +8,6 @@ type Album struct {
Downvotes int64 Downvotes int64
CreatedAt string CreatedAt string
UpdatedAt string UpdatedAt string
Comments int64
Media []Media Media []Media
} }

15
types/Comment.go Normal file
View File

@ -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
}

12
utils/formatDate.go Normal file
View File

@ -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
}

View File

@ -6,6 +6,7 @@
<link rel="stylesheet" href="/static/fonts/Material-Icons-Outlined.css" /> <link rel="stylesheet" href="/static/fonts/Material-Icons-Outlined.css" />
<link rel="stylesheet" href="/static/css/album.css" /> <link rel="stylesheet" href="/static/css/album.css" />
<link rel="stylesheet" href="/static/css/comments.css" />
</head> </head>
@ -65,6 +66,21 @@
<br> <br>
{{/each}} {{/each}}
<div>
<hr>
<input id="comments__expandBtn" type="checkbox">
<label class="comments__expandBtn__label" for="comments__expandBtn">
<h3>Comments ({{album.Comments}})</h3>
<span class="comments__expandBtn__icon material-icons-outlined"></span>
</label>
<div class="comments">
{{#each comments}}
{{> partials/comment }}
{{/each}}
</div>
</div>
<hr>
</main> </main>
{{> partials/footer }} {{> partials/footer }}

View File

@ -0,0 +1,28 @@
<div class="comment">
<div class="comment__user">
<img src="{{this.User.Avatar}}" class="pfp" width="24" height="24" loading="lazy">
<!--<a href="/user/{{this.User.Username}}">-->
<p><b>{{this.User.Username}}</b></p>
<!--</a>-->
</div>
<div>
{{{this.Comment}}}
<p title="{{this.Date}}">
{{this.RelTime}}
{{#if this.UpdatedAt}}
<span class="comment__updatedDate">(edited {{this.UpdatedAt}})</span>
{{/if}}
{{#if this.DeletedAt}}
<span class="comment__updatedDate">(deleted {{this.DeletedAt}})</span>
{{/if}}
|
<span class="material-icons-outlined">thumb_up</span> {{this.Upvotes}}
<span class="material-icons-outlined">thumb_down</span> {{this.Downvotes}}
</p>
</div>
<div class="replies">
{{#each this.Comments}}
{{> partials/comment }}
{{/each}}
</div>
</div>