diff --git a/api/f.ts b/api/f.ts deleted file mode 100644 index 31380c0..0000000 --- a/api/f.ts +++ /dev/null @@ -1,19 +0,0 @@ -export const fetchUserPosts = async (userID: string, sort: Sorting = 'newest'): Promise => { - /* eslint-disable max-len */ - // https://api.imgur.com/3/account/mombotnumber5/submissions/0/newest?album_previews=1&client_id=${CLIENT_ID} - const response = await get( - ``, - ); - return JSON.parse(response.body).data; - /* eslint-enable max-len */ -} - -export const fetchTagPosts = async (tagID: string, sort: Sorting = 'viral'): Promise => { - /* eslint-disable max-len */ - // https://api.imgur.com/3/account/mombotnumber5/submissions/0/newest?album_previews=1&client_id=${CLIENT_ID} - const response = await get( - `https://api.imgur.com/3/gallery/t/${tagID.toLowerCase()}/${sort}/week/0?client_id=${CONFIG.imgur_client_id}`, - ); - return JSON.parse(response.body).data; - /* eslint-enable max-len */ -} \ No newline at end of file diff --git a/api/tag.go b/api/tag.go new file mode 100644 index 0000000..7e6a8bf --- /dev/null +++ b/api/tag.go @@ -0,0 +1,93 @@ +package api + +import ( + "io/ioutil" + "net/http" + "strings" + "sync" + + "codeberg.org/video-prize-ranch/rimgo/types" + "github.com/spf13/viper" + "github.com/tidwall/gjson" +) + +func FetchTag(tag string, sort string, page string) (types.Tag, error) { + req, err := http.NewRequest("GET", "https://api.imgur.com/post/v1/posts/t/"+tag, nil) + if err != nil { + return types.Tag{}, err + } + + q := req.URL.Query() + q.Add("client_id", viper.GetString("RIMGU_IMGUR_CLIENT_ID")) + q.Add("include", "cover") + q.Add("page", page) + + switch sort { + case "newest": + q.Add("filter[window]", "week") + q.Add("sort", "-time") + case "best": + q.Add("filter[window]", "all") + q.Add("sort", "-top") + case "popular": + default: + q.Add("filter[window]", "week") + q.Add("sort", "-viral") + sort = "popular" + } + + req.URL.RawQuery = q.Encode() + + res, err := http.DefaultClient.Do(req) + if err != nil { + return types.Tag{}, err + } + + body, err := ioutil.ReadAll(res.Body) + if err != nil { + return types.Tag{}, err + } + + data := gjson.Parse(string(body)) + + wg := sync.WaitGroup{} + posts := make([]types.Submission, 0) + data.Get("posts").ForEach( + func(key, value gjson.Result) bool { + wg.Add(1) + + go func() { + defer wg.Done() + posts = append(posts, types.Submission{ + Id: value.Get("id").String(), + Title: value.Get("title").String(), + Link: strings.ReplaceAll(value.Get("url").String(), "https://imgur.com", ""), + Cover: types.Media{ + Id: value.Get("cover_id").String(), + Type: value.Get("cover.type").String(), + Url: strings.ReplaceAll(value.Get("cover.url").String(), "https://i.imgur.com", ""), + }, + Points: value.Get("point_count").Int(), + Upvotes: value.Get("upvote_count").Int(), + Downvotes: value.Get("downvote_count").Int(), + Comments: value.Get("comment_count").Int(), + Views: value.Get("view_count").Int(), + IsAlbum: value.Get("is_album").Bool(), + }) + }() + + return true + }, + ) + + wg.Wait() + + return types.Tag{ + Tag: tag, + Display: data.Get("display").String(), + Sort: sort, + PostCount: data.Get("post_count").Int(), + Posts: posts, + Background: "/" + data.Get("background_id").String() + ".webp", + }, nil +} diff --git a/main.go b/main.go index 8a23cdc..84df114 100644 --- a/main.go +++ b/main.go @@ -53,7 +53,7 @@ func main() { app.Get("/:baseName.:extension", pages.HandleMedia) app.Get("/:postID", pages.HandlePost) app.Get("/a/:galleryID", pages.HandleGallery) - //app.Get("/t/:tagID", pages.HandleAlbum) + app.Get("/t/:tag", pages.HandleTag) app.Get("/user/:userID", pages.HandleUser) app.Get("/r/:sub/:postID", pages.HandlePost) app.Get("/user/:userID/cover", pages.HandleUserCover) diff --git a/pages/tag.go b/pages/tag.go new file mode 100644 index 0000000..2187584 --- /dev/null +++ b/pages/tag.go @@ -0,0 +1,43 @@ +package pages + +import ( + "strconv" + + "codeberg.org/video-prize-ranch/rimgo/api" + "codeberg.org/video-prize-ranch/rimgo/utils" + "github.com/gofiber/fiber/v2" +) + +func HandleTag(c *fiber.Ctx) error { + utils.SetHeaders(c) + c.Set("Cache-Control", "public,max-age=604800") + c.Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline' 'self'; img-src 'self'; font-src 'self'; block-all-mixed-content") + + page := "1" + if c.Query("page") != "" { + page = c.Query("page") + } + + pageNumber, err := strconv.Atoi(c.Query("page")) + if err != nil { + pageNumber = 0 + } + + displayPrevPage := true + if page == "1" { + displayPrevPage = false + } + + tag, err := api.FetchTag(c.Params("tag"), c.Query("sort"), page) + if err != nil { + return err + } + + return c.Render("tag", fiber.Map{ + "tag": tag, + "page": page, + "displayPrev": displayPrevPage, + "nextPage": pageNumber + 1, + "prevPage": pageNumber - 1, + }) +} diff --git a/static/css/base.css b/static/css/base.css index 2f0c529..c9c6500 100644 --- a/static/css/base.css +++ b/static/css/base.css @@ -8,6 +8,10 @@ a > h2 { color: white; } +h2, p { + margin: 0; +} + body { background-color: #212121; color: white; @@ -33,6 +37,49 @@ main { margin: 0 24vw; } +.posts { + margin-top: 1em; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + grid-auto-rows: 1fr; + gap: 1rem; +} + +.post { + border-radius: 12px; + background-color: #3b3b3b; + font-weight: 400; +} + +img, +video:not(:fullscreen) { + object-fit: cover; + aspect-ratio: 1; +} + +.post__title { + margin: 0 6px; + white-space: nowrap; + text-overflow: ellipsis; + overflow: hidden; +} + +.post__meta { + padding: 6px; + display: flex; + gap: 10px; +} + +.post__meta .material-icons-outlined { + font-size: 1rem; +} + +.pageSelector { + display: flex; + justify-content: space-between; + margin-top: 1em; +} + footer { display: flex; justify-content: center; diff --git a/static/css/tag.css b/static/css/tag.css new file mode 100644 index 0000000..407f48e --- /dev/null +++ b/static/css/tag.css @@ -0,0 +1,27 @@ +main { + margin: 0 12vw; +} + +.tagMeta { + padding: 2em; + border-radius: 12px; +} + +.tagMeta__info { + display: flex; + flex-direction: column; + gap: 10px; + text-align: center; + justify-content: center; + align-items: center; +} + +.tagMeta__sort { + display: flex; + flex-direction: column; + gap: 4px; +} + +.tagMeta__sort a { + font-weight: 400; +} \ No newline at end of file diff --git a/static/css/user.css b/static/css/user.css index 1e3b607..706b1a2 100644 --- a/static/css/user.css +++ b/static/css/user.css @@ -2,12 +2,8 @@ main { margin: 0 12vw; } -h2, p { - margin: 0; -} - .userMeta { - padding: 2vw; + padding: 2em; border-radius: 12px; } @@ -23,47 +19,4 @@ h2, p { .pfp { border-radius: 100%; -} - -.posts { - margin-top: 1em; - display: grid; - grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); - grid-auto-rows: 1fr; - gap: 1rem; -} - -.post { - border-radius: 12px; - background-color: #3b3b3b; - font-weight: 400; -} - -img, -video:not(:fullscreen) { - object-fit: cover; - aspect-ratio: 1; -} - -.post__title { - margin: 0 6px; - white-space: nowrap; - text-overflow: ellipsis; - overflow: hidden; -} - -.post__meta { - padding: 6px; - display: flex; - gap: 10px; -} - -.post__meta .material-icons-outlined { - font-size: 1rem; -} - -.pageSelector { - display: flex; - justify-content: space-between; - margin-top: 1em; } \ No newline at end of file diff --git a/types/Submission.go b/types/Submission.go new file mode 100644 index 0000000..33cd535 --- /dev/null +++ b/types/Submission.go @@ -0,0 +1,14 @@ +package types + +type Submission struct { + Id string + Title string + Link string + Cover Media + Points int64 + Upvotes int64 + Downvotes int64 + Comments int64 + Views int64 + IsAlbum bool +} \ No newline at end of file diff --git a/types/Tag.go b/types/Tag.go new file mode 100644 index 0000000..82db55b --- /dev/null +++ b/types/Tag.go @@ -0,0 +1,10 @@ +package types + +type Tag struct { + Tag string + Display string + Sort string + PostCount int64 + Posts []Submission + Background string +} \ No newline at end of file diff --git a/types/User.go b/types/User.go index 63b50ba..868975f 100644 --- a/types/User.go +++ b/types/User.go @@ -8,17 +8,4 @@ type User struct { Cover string Avatar string CreatedAt string -} - -type Submission struct { - Id string - Title string - Link string - Cover Media - Points int64 - Upvotes int64 - Downvotes int64 - Comments int64 - Views int64 - IsAlbum bool -} +} \ No newline at end of file diff --git a/views/tag.hbs b/views/tag.hbs new file mode 100644 index 0000000..4a653cd --- /dev/null +++ b/views/tag.hbs @@ -0,0 +1,59 @@ + + + + + {{tag.Display}} - rimgo + + {{> partials/head }} + + + + + + + + {{> partials/header }} + +
+
+
+

{{tag.Display}}

+

{{tag.PostCount}} posts

+
+
+ {{#equal tag.Sort "popular"}} + Popular + Newest + Best + {{/equal}} + {{#equal tag.Sort "newest"}} + Popular + Newest + Best + {{/equal}} + {{#equal tag.Sort "best"}} + Popular + Newest + Best + {{/equal}} +
+
+ +
+ {{#each tag.Posts}} + {{> partials/post }} + {{/each}} +
+ +
+ {{#if displayPrev}} + Previous page + {{/if}} + Next page +
+
+ + {{> partials/footer }} + + + \ No newline at end of file