added user comments

This commit is contained in:
orangix 2023-08-15 17:38:44 +02:00
parent 493a17385a
commit 3faef9aeb9
No known key found for this signature in database
GPG Key ID: C31D4A86601C8416
6 changed files with 232 additions and 45 deletions

View File

@ -9,21 +9,21 @@ import (
"codeberg.org/rimgo/rimgo/utils"
"github.com/dustin/go-humanize"
"github.com/microcosm-cc/bluemonday"
"github.com/patrickmn/go-cache"
"github.com/tidwall/gjson"
"gitlab.com/golang-commonmark/linkify"
)
type Comment struct {
Comments []Comment
User User
User User
Post Submission
Id string
Comment string
Upvotes int64
Downvotes int64
Platform string
CreatedAt string
RelTime string
RelTime string
UpdatedAt string
DeletedAt string
}
@ -55,7 +55,6 @@ func (client *Client) FetchComments(galleryID string) ([]Comment, error) {
)
wg.Wait()
client.Cache.Set(galleryID + "-comments", comments, cache.DefaultExpiration)
return comments, nil
}
@ -130,13 +129,14 @@ func parseComment(data gjson.Result) Comment {
Username: data.Get("account.username").String(),
Avatar: userAvatar,
},
Post: parseSubmission(data.Get("post")),
Id: data.Get("id").String(),
Comment: comment,
Upvotes: data.Get("upvote_count").Int(),
Downvotes: data.Get("downvote_count").Int(),
Platform: data.Get("platform").String(),
CreatedAt: createdAt,
RelTime: humanize.Time(createdTime),
RelTime: humanize.Time(createdTime),
UpdatedAt: updatedAt,
DeletedAt: deletedAt,
}

View File

@ -8,6 +8,7 @@ import (
"time"
"codeberg.org/rimgo/rimgo/utils"
"github.com/patrickmn/go-cache"
"github.com/tidwall/gjson"
)
@ -64,7 +65,7 @@ func (client *Client) FetchUser(username string) (User, error) {
CreatedAt: createdTime.Format("January 2, 2006"),
}
client.Cache.Set(username + "-user", user, 1*time.Hour)
client.Cache.Set(username+"-user", user, 1*time.Hour)
return user, nil
}
@ -89,41 +90,7 @@ func (client *Client) FetchSubmissions(username string, sort string, page string
go func() {
defer wg.Done()
coverData := value.Get("images.#(id==\"" + value.Get("cover").String() + "\")")
cover := Media{
Id: value.Get("id").String(),
Description: value.Get("description").String(),
Type: strings.Split(value.Get("type").String(), "/")[0],
Url: strings.ReplaceAll(value.Get("link").String(), "https://i.imgur.com", ""),
}
if coverData.Exists() {
cover = Media{
Id: coverData.Get("id").String(),
Description: coverData.Get("description").String(),
Type: strings.Split(coverData.Get("type").String(), "/")[0],
Url: strings.ReplaceAll(coverData.Get("link").String(), "https://i.imgur.com", ""),
}
}
id := value.Get("id").String()
link := "/a/" + id
if value.Get("in_gallery").Bool() {
link = "/gallery/" + id
}
submissions = append(submissions, Submission{
Id: id,
Link: link,
Title: value.Get("title").String(),
Cover: cover,
Points: value.Get("points").Int(),
Upvotes: value.Get("ups").Int(),
Downvotes: value.Get("downs").Int(),
Comments: value.Get("comment_count").Int(),
Views: value.Get("views").Int(),
IsAlbum: value.Get("is_album").Bool(),
})
submissions = append(submissions, parseSubmission(value))
}()
return true
@ -131,6 +98,91 @@ func (client *Client) FetchSubmissions(username string, sort string, page string
)
wg.Wait()
client.Cache.Set(username + "-submissions", submissions, 15*time.Minute)
client.Cache.Set(username+"-submissions", submissions, 15*time.Minute)
return submissions, nil
}
func (client *Client) FetchUserComments(username string, page string) ([]Comment, error) {
req, err := http.NewRequest("GET", "https://api.imgur.com/comment/v1/comments", nil)
if err != nil {
return []Comment{}, err
}
utils.SetReqHeaders(req)
q := req.URL.Query()
q.Add("client_id", client.ClientID)
q.Add("filter[account]", "eq:wouldaponybyanyothernamebeasoffencive")
q.Add("include", "account,post")
q.Add("sort", "new")
req.URL.RawQuery = q.Encode()
res, err := http.DefaultClient.Do(req)
if err != nil {
return []Comment{}, err
}
body, err := io.ReadAll(res.Body)
if err != nil {
return []Comment{}, err
}
data := gjson.Parse(string(body))
wg := sync.WaitGroup{}
comments := make([]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()
client.Cache.Set(username+"-usercomments-"+page, comments, cache.DefaultExpiration)
return comments, nil
}
func parseSubmission(value gjson.Result) Submission {
coverData := value.Get("images.#(id==\"" + value.Get("cover").String() + "\")")
cover := Media{
Id: value.Get("id").String(),
Description: value.Get("description").String(),
Type: strings.Split(value.Get("type").String(), "/")[0],
Url: strings.ReplaceAll(value.Get("link").String(), "https://i.imgur.com", ""),
}
if coverData.Exists() {
cover = Media{
Id: coverData.Get("id").String(),
Description: coverData.Get("description").String(),
Type: strings.Split(coverData.Get("type").String(), "/")[0],
Url: strings.ReplaceAll(coverData.Get("link").String(), "https://i.imgur.com", ""),
}
}
id := value.Get("id").String()
link := "/a/" + id
if value.Get("in_gallery").Bool() {
link = "/gallery/" + id
}
return Submission{
Id: id,
Link: link,
Title: value.Get("title").String(),
Cover: cover,
Points: value.Get("points").Int(),
Upvotes: value.Get("ups").Int(),
Downvotes: value.Get("downs").Int(),
Comments: value.Get("comment_count").Int(),
Views: value.Get("views").Int(),
IsAlbum: value.Get("is_album").Bool(),
}
}

View File

@ -121,8 +121,9 @@ func main() {
app.Get("/a/:postID/embed", pages.HandleEmbed)
app.Get("/t/:tag", pages.HandleTag)
app.Get("/t/:tag/:postID", pages.HandlePost)
app.Get("/user/:userID", pages.HandleUser)
app.Get("/r/:sub/:postID", pages.HandlePost)
app.Get("/user/:userID", pages.HandleUser)
app.Get("/user/:userID/comments", pages.HandleUserComments)
app.Get("/user/:userID/cover", pages.HandleUserCover)
app.Get("/user/:userID/avatar", pages.HandleUserAvatar)
app.Get("/gallery/:postID", pages.HandlePost)

View File

@ -51,7 +51,56 @@ func HandleUser(c *fiber.Ctx) error {
"user": user,
"submissions": submissions,
"page": page,
"nextPage": pageNumber + 1,
"prevPage": pageNumber - 1,
"nextPage": pageNumber + 1,
"prevPage": pageNumber - 1,
})
}
func HandleUserComments(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Cache-Control", "public,max-age=604800")
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; media-src 'self'; style-src 'unsafe-inline' 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
page := "0"
if c.Query("page") != "" {
page = c.Query("page")
}
pageNumber, err := strconv.Atoi(c.Query("page"))
if err != nil {
pageNumber = 0
}
user, err := ApiClient.FetchUser(c.Params("userID"))
if err != nil && err.Error() == "ratelimited by imgur" {
return c.Status(429).Render("errors/429", fiber.Map{
"path": c.Path(),
})
}
if err != nil {
return err
}
if user.Username == "" {
return c.Status(404).Render("errors/404", nil)
}
comments, err := ApiClient.FetchUserComments(c.Params("userID"), page)
if err != nil && err.Error() == "ratelimited by imgur" {
c.Status(429)
return c.Render("errors/429", fiber.Map{
"path": c.Path(),
})
}
if err != nil {
return err
}
return c.Render("userComments", fiber.Map{
"user": user,
"comments": comments,
"page": page,
"nextPage": pageNumber + 1,
"prevPage": pageNumber - 1,
})
}

View File

@ -0,0 +1,38 @@
<!-- TODO: remove post titles and instead use cover images -->
<div class="flex flex-col gap-2">
<div class="flex gap-2 items-center">
{{#noteq this.User.Username "[deleted]"}}
<img src="{{this.User.Avatar}}" class="rounded-full" width="24" height="24" loading="lazy">
<p class="whitespace-nowrap text-ellipsis overflow-hidden"></p><a href="/user/{{this.User.Username}}">
<b class="underline">{{this.User.Username}}</b></span>
on <a class="underline" href={{Post.Link}}>post title here {{Post.Title}}</a></p>
</a>
{{/noteq}}
{{#equal this.User.Username "[deleted]"}}
<p class="whitespace-nowrap text-ellipsis overflow-hidden"><b>[deleted]</b>
on <a class="underline" href={{Post.Link}}>post title here {{Post.Title}}</a></p>
{{/equal}}
</div>
<div>
<p>{{{this.Comment}}}</p>
<div class="flex gap-2">
<span title="{{this.CreatedAt}}">{{this.RelTime}}</span>
{{#if this.DeletedAt}}
<span class="text-md">(deleted {{this.DeletedAt}})</span>
{{/if}}
|
<img class="invert icon" src="/static/icons/PhArrowFatUp.svg" alt="Likes" width="24px" height="24px">
{{this.Upvotes}}
<img class="invert icon" src="/static/icons/PhArrowFatDown.svg" alt="Dislikes" width="24px" height="24px">
{{this.Downvotes}}
</div>
</div>
{{#if this.Comments}}
<div class="ml-4 p-2 border-solid border-l-2 border-slate-400">
{{#each this.Comments}}
{{> partials/comment }}
{{/each}}
</div>
{{/if}}
</div>

47
views/userComments.hbs Normal file
View File

@ -0,0 +1,47 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{user.Username}} - rimgo</title>
{{> partials/head }}
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<section class="my-4 w-full flex flex-col items-center">
{{> partials/searchBar }}
</section>
<header class="p-4 rounded-xl text-white mb-4" style="background-image: url('{{user.Cover}}');">
<div class="flex items-center gap-2">
<img class="rounded-full" src="{{user.Avatar}}" width="72" height="72">
<div>
<h2 class="font-bold text-2xl">{{user.Username}}</h2>
<p>{{user.Points}} pts · {{user.CreatedAt}}</p>
</div>
</div>
<p class="mt-2">{{user.Bio}}</p>
</header>
<main>
<div class="comments flex flex-col gap-2">
{{#each comments}}
{{> partials/contextComment }}
{{/each}}
</div>
<div class="mt-4 font-bold">
{{#equal page "0" }}
{{else}}
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>
{{/equal}}
<a href="{{channel.RelUrl}}?page={{nextPage}}">Next page</a>
</div>
</main>
{{> partials/footer }}
</body>
</html>