mirror of
https://codeberg.org/video-prize-ranch/rimgo.git
synced 2026-02-15 21:16:16 +00:00
Compare commits
38 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f1fbc2401 | ||
|
|
4afb7cefe7 | ||
|
|
20715f53af | ||
|
|
ac9582df0a | ||
|
|
0ce85ed2bd | ||
|
|
09a76779c9 | ||
|
|
337796b9be | ||
|
|
927ea20fad | ||
|
|
7433265991 | ||
|
|
fb82afc7dd | ||
|
|
1579e59dca | ||
|
|
6d528c7d0a | ||
|
|
9a6173a662 | ||
|
|
c366f95f6b | ||
|
|
f5e1669a61 | ||
|
|
dd78541a46 | ||
|
|
29203a1a78 | ||
|
|
13a72701e1 | ||
|
|
252b557450 | ||
|
|
f46ef8b029 | ||
|
|
1376b5da9d | ||
|
|
157407c013 | ||
|
|
8fe3f73568 | ||
|
|
5cce60c3ad | ||
|
|
1ec92f4809 | ||
|
|
7a0c008bba | ||
|
|
d354d6314a | ||
|
|
121ad6b157 | ||
|
|
fc88bfbca5 | ||
|
|
0fea1e46a3 | ||
|
|
877ee7faa9 | ||
|
|
d490581c44 | ||
|
|
730aead3a1 | ||
|
|
2024f7f6cf | ||
|
|
34ecc2a32b | ||
|
|
e5e1c38058 | ||
|
|
493a17385a | ||
|
|
a8abb43f3a |
7
Justfile
7
Justfile
@@ -4,4 +4,9 @@ build:
|
|||||||
|
|
||||||
dev:
|
dev:
|
||||||
tailwindcss -i static/tailwind.css -o static/app.css -m -w &
|
tailwindcss -i static/tailwind.css -o static/app.css -m -w &
|
||||||
go run github.com/cosmtrek/air@latest -c .air.toml
|
go run github.com/air-verse/air@latest -c .air.toml
|
||||||
|
|
||||||
|
tag-vpr:
|
||||||
|
podman pull codeberg.org/rimgo/rimgo:latest
|
||||||
|
podman image tag codeberg.org/rimgo/rimgo:latest codeberg.org/video-prize-ranch/rimgo:latest
|
||||||
|
podman push codeberg.org/video-prize-ranch/rimgo:latest
|
||||||
58
README.md
58
README.md
@@ -65,59 +65,8 @@ Stack Overflow: `https://i.stack.imgur.com/KnO3v.jpg?s=64&g=1` -> `https://rimgo
|
|||||||
To automatically redirect Imgur links, see [Redirection](https://rimgo.codeberg.page/docs/usage/redirection/).
|
To automatically redirect Imgur links, see [Redirection](https://rimgo.codeberg.page/docs/usage/redirection/).
|
||||||
|
|
||||||
## Instances
|
## Instances
|
||||||
Open an issue to have your instance listed here! See the rules for the instance list [here](https://rimgo.codeberg.page/docs/usage/instance-list-rules/).
|
|
||||||
|
|
||||||
> For more details on instance privacy, see https://rimgo.codeberg.page/docs/usage/instance-privacy/
|
Available at https://rimgo.codeberg.page/ or https://codeberg.org/rimgo/instances
|
||||||
|
|
||||||
### Clearnet
|
|
||||||
|
|
||||||
| URL | Country | Provider | Privacy | Notes |
|
|
||||||
| :------------------------------------------------------------ | :----------- | :----------------------- | :-------------------- | :---- |
|
|
||||||
| [rimgo.pussthecat.org](https://rimgo.pussthecat.org) | 🇩🇪 DE | Hetzner | ⚠️ Data collected | |
|
|
||||||
| [rimgo.totaldarkness.net](https://rimgo.totaldarkness.net) | 🇨🇦 CA | Vultr | ✅ Data not collected | |
|
|
||||||
| [rimgo.bus-hit.me](https://rimgo.bus-hit.me) | 🇨🇦 CA | Oracle | ⚠️ Data collected | |
|
|
||||||
| [imgur.artemislena.eu](https://imgur.artemislena.eu) | 🇩🇪 DE | Vodafone Deutschland | ✅ Data not collected | Self-hosted, provider is ISP |
|
|
||||||
| [rimgo.vern.cc](https://rimgo.vern.cc) | 🇺🇸 US | OVHCloud | ✅ Data not collected | [Edited theme](https://git.vern.cc/root/modifications/src/branch/master/rimgo) |
|
|
||||||
| [rim.odyssey346.dev](https://rim.odyssey346.dev/) | 🇫🇷️ FR | Trolling Solutions (OVH) | ✅ Data not collected | |
|
|
||||||
| [i.habedieeh.re](https://i.habedieeh.re/) | 🇨🇦️ CA | Oracle Cloud | ✅ Data not collected | |
|
|
||||||
| [rimgo.hostux.net](https://rimgo.hostux.net/) | 🇫🇷️ FR | Gandi | ⚠️ Data collected | |
|
|
||||||
| [ri.zzls.xyz](https://ri.zzls.xyz/) | 🇨🇱 CL | TELEFÓNICA CHILE | ✅ Data not collected | Self-hosted, provider is ISP |
|
|
||||||
| [rimgo.lunar.icu](https://rimgo.marcopisco.com/) | 🇩🇪 DE | Cloudflare | ✅ Data not collected | |
|
|
||||||
| [imgur.010032.xyz](https://imgur.010032.xyz/) | 🇰🇷 KR | Oracle Cloud | ✅ Data not collected | |
|
|
||||||
| [rimgo.kling.gg](https://rimgo.kling.gg/) | 🇳🇱 NL | RamNode | ✅ Data not collected | |
|
|
||||||
| [i.01r.xyz](https://i.01r.xyz/) | 🇺🇸 US | Cloudflare | ✅ Data not collected | |
|
|
||||||
| [rimgo.projectsegfau.lt](https://rimgo.projectsegfau.lt/) | 🇱🇺 LU, 🇺🇸 US, 🇮🇳 IN | See below | ✅ Data not collected | |
|
|
||||||
| [rimgo.eu.projectsegfau.lt](https://rimgo.projectsegfau.lt/) | 🇱🇺 LU | FranTech Solutions | ✅ Data not collected | |
|
|
||||||
| [rimgo.us.projectsegfau.lt](https://rimgo.projectsegfau.lt/) | 🇺🇸 US | DigitalOcean | ✅ Data not collected | |
|
|
||||||
| [rimgo.in.projectsegfau.lt](https://rimgo.projectsegfau.lt/) | 🇮🇳 IN | Airtel | ✅ Data not collected | |
|
|
||||||
| [rimgo.fascinated.cc](https://rimgo.fascinated.cc/) | 🇺🇸 US | Cloudflare | ✅ Data not collected | |
|
|
||||||
| [rimgo.whateveritworks.org](https://rimgo.whateveritworks.org/) | 🇩🇪 DE | Cloudflare | ✅ Data not collected | |
|
|
||||||
| [rimgo.nohost.network](https://rimgo.nohost.network/) | 🇲🇽 MX | Telmex | ✅ Data not collected | |
|
|
||||||
| [rimgo.catsarch.com](https://rimgo.catsarch.com/) | 🇺🇸 US | Comcast | ✅ Data not collected | Self-hosted, provider is ISP |
|
|
||||||
| [rimgo.frontendfriendly.xyz](https://rimgo.frontendfriendly.xyz/) | 🇩🇪 DE | Hetzner | ⚠️ Data collected | |
|
|
||||||
|
|
||||||
### Tor
|
|
||||||
|
|
||||||
| URL | Privacy | Notes |
|
|
||||||
| :-- | :------ | :----------------------- |
|
|
||||||
| [rimgo.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion](http://rimgo.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion) | ✅ Data not collected | Onion of rimgo.vern.cc |
|
|
||||||
| [imgur.lpoaj7z2zkajuhgnlltpeqh3zyq7wk2iyeggqaduhgxhyajtdt2j7wad.onion](http://imgur.lpoaj7z2zkajuhgnlltpeqh3zyq7wk2iyeggqaduhgxhyajtdt2j7wad.onion) | ✅ Data not collected | Onion of imgur.artemislena.eu |
|
|
||||||
| [rim.odysfvr23q5wgt7i456o5t3trw2cw5dgn56vbjfbq2m7xsc5vqbqpcyd.onion](http://rim.odysfvr23q5wgt7i456o5t3trw2cw5dgn56vbjfbq2m7xsc5vqbqpcyd.onion) | ⚠️ Data collected | |
|
|
||||||
| [tdp6uqjtmok723suum5ms3jbquht6d7dssug4cgcxhfniatb25gcipad.onion](http://tdp6uqjtmok723suum5ms3jbquht6d7dssug4cgcxhfniatb25gcipad.onion) | ✅ Data not collected | Onion of rimgo.privacytools.io |
|
|
||||||
| [i.habeehrhadazsw3izbrbilqajalfyqqln54mrja3iwpqxgcuxnus7eid.onion](http://i.habeehrhadazsw3izbrbilqajalfyqqln54mrja3iwpqxgcuxnus7eid.onion/) | ✅ Data not collected | Onion of i.habedieeh.re |
|
|
||||||
| [rimgo.zzlsghu6mvvwyy75mvga6gaf4znbp3erk5xwfzedb4gg6qqh2j6rlvid.onion](http://rimgo.zzlsghu6mvvwyy75mvga6gaf4znbp3erk5xwfzedb4gg6qqh2j6rlvid.onion/) | ✅ Data not collected | Onion of ri.zzls.xyz |
|
|
||||||
| [tdn7zoxctmsopey77mp4eg2gazaudyhgbuyytf4zpk5u7lknlxlgbnid.onion/](http://tdn7zoxctmsopey77mp4eg2gazaudyhgbuyytf4zpk5u7lknlxlgbnid.onion/) | ✅ Data not collected | Onion of rimgo.kling.gg |
|
|
||||||
| [rimgo.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion](http://rimgo.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion/) | ✅ Data not collected | Onion of rimgo.eu.projectsegfau.lt |
|
|
||||||
|
|
||||||
### I2P
|
|
||||||
|
|
||||||
| URL | Privacy | Notes |
|
|
||||||
| :-- | :------ | :----------------------- |
|
|
||||||
| [rimgo.i2p](http://rimgo.i2p) | ✅ Data not collected | i.habedieeh.re on I2P |
|
|
||||||
| [rimgov7l2tqyrm5txrtvhtnfyrzkc5d7ipafofavchbnnyog4r3q.b32.i2p](http://rimgov7l2tqyrm5txrtvhtnfyrzkc5d7ipafofavchbnnyog4r3q.b32.i2p) | ✅ Data not collected | Same as rimgo.i2p |
|
|
||||||
| [rimgo.zzls.i2p](http://rimgo.zzls.i2p) | ✅ Data not collected | ri.zzls.xyz on I2P |
|
|
||||||
| [p57356k2xwhxrg2lxrjajcftkrptv4zejeeblzfgkcvpzuetkz2a.b32.i2p](http://p57356k2xwhxrg2lxrjajcftkrptv4zejeeblzfgkcvpzuetkz2a.b32.i2p) | ✅ Data not collected | Same as rimgo.zzls.i2p |
|
|
||||||
| [ovzamsts5czfx3jasbbhbccyyl2z7qmdngtlqxdh4oi7abhdz3ia.b32.i2p](http://ovzamsts5czfx3jasbbhbccyyl2z7qmdngtlqxdh4oi7abhdz3ia.b32.i2p) | ✅ Data not collected | rimgo.kling.gg on I2P |
|
|
||||||
|
|
||||||
## Install
|
## Install
|
||||||
|
|
||||||
@@ -128,7 +77,10 @@ See [Install](https://rimgo.codeberg.page/docs/getting-started/install/).
|
|||||||
See [Configuration](https://rimgo.codeberg.page/docs/usage/configuration/).
|
See [Configuration](https://rimgo.codeberg.page/docs/usage/configuration/).
|
||||||
|
|
||||||
## Contributing
|
## Contributing
|
||||||
Pull requests are welcome! If you have any questions or bug reports, open an [issue](https://codeberg.org/rimgo/rimgo/issues/new).
|
Pull requests are welcome! If you have any questions or bug reports, open an [issue](https://codeberg.org/rimgo/rimgo/issues/new). Please remember to follow our [Code of Conduct](https://rimgo.codeberg.page/docs/code-of-conduct/)!
|
||||||
|
|
||||||
## License
|
## License
|
||||||
This software is released under the AGPL-3.0 license. If you make any modifications to the code and distribute it (including use on a network server), you must publicly distribute your changes and release them under the AGPL-3.0.
|
This software is released under the AGPL-3.0 license. If you make any modifications to the code and distribute it (including use on a network server), you must publicly distribute your changes and release them under the AGPL-3.0.
|
||||||
|
|
||||||
|
## Legal notice
|
||||||
|
rimgo does not allow uploads or host any content, media. All content on any rimgo instances is from Imgur™. Imgur is a trademark of Imgur, Inc. Any issues with content on rimgo should be be reported to Imgur. rimgo is not affiliated with Imgur, Inc.
|
||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
type Comment struct {
|
type Comment struct {
|
||||||
Comments []Comment
|
Comments []Comment
|
||||||
User User
|
User User
|
||||||
|
Post Submission
|
||||||
Id string
|
Id string
|
||||||
Comment string
|
Comment string
|
||||||
Upvotes int64
|
Upvotes int64
|
||||||
@@ -130,6 +131,7 @@ func parseComment(data gjson.Result) Comment {
|
|||||||
Username: data.Get("account.username").String(),
|
Username: data.Get("account.username").String(),
|
||||||
Avatar: userAvatar,
|
Avatar: userAvatar,
|
||||||
},
|
},
|
||||||
|
Post: parseSubmission(data.Get("post")),
|
||||||
Id: data.Get("id").String(),
|
Id: data.Get("id").String(),
|
||||||
Comment: comment,
|
Comment: comment,
|
||||||
Upvotes: data.Get("upvote_count").Int(),
|
Upvotes: data.Get("upvote_count").Int(),
|
||||||
|
|||||||
24
api/tag.go
24
api/tag.go
@@ -1,10 +1,10 @@
|
|||||||
package api
|
package api
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"io/ioutil"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
|
||||||
|
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
@@ -21,6 +21,9 @@ type Tag struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) FetchTag(tag string, sort string, page string) (Tag, error) {
|
func (client *Client) FetchTag(tag string, sort string, page string) (Tag, error) {
|
||||||
|
// Dots are automatically removed on Imgur, so more cache hits
|
||||||
|
tag = strings.ReplaceAll(tag, ".", "")
|
||||||
|
|
||||||
cacheData, found := client.Cache.Get(tag + sort + page + "-tag")
|
cacheData, found := client.Cache.Get(tag + sort + page + "-tag")
|
||||||
if found {
|
if found {
|
||||||
return cacheData.(Tag), nil
|
return cacheData.(Tag), nil
|
||||||
@@ -57,25 +60,25 @@ func (client *Client) FetchTag(tag string, sort string, page string) (Tag, error
|
|||||||
return Tag{}, err
|
return Tag{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
body, err := ioutil.ReadAll(res.Body)
|
body, err := io.ReadAll(res.Body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return Tag{}, err
|
return Tag{}, err
|
||||||
}
|
}
|
||||||
|
|
||||||
data := gjson.Parse(string(body))
|
data := gjson.Parse(string(body))
|
||||||
|
|
||||||
wg := sync.WaitGroup{}
|
|
||||||
posts := make([]Submission, 0)
|
posts := make([]Submission, 0)
|
||||||
data.Get("posts").ForEach(
|
data.Get("posts").ForEach(
|
||||||
func(key, value gjson.Result) bool {
|
func(key, value gjson.Result) bool {
|
||||||
wg.Add(1)
|
url, _ := url.Parse(strings.ReplaceAll(value.Get("url").String(), "https://imgur.com", ""))
|
||||||
|
q := url.Query()
|
||||||
|
q.Add("tag", tag+"."+sort+"."+page+"."+key.String())
|
||||||
|
url.RawQuery = q.Encode()
|
||||||
|
|
||||||
go func() {
|
|
||||||
defer wg.Done()
|
|
||||||
posts = append(posts, Submission{
|
posts = append(posts, Submission{
|
||||||
Id: value.Get("id").String(),
|
Id: value.Get("id").String(),
|
||||||
Title: value.Get("title").String(),
|
Title: value.Get("title").String(),
|
||||||
Link: strings.ReplaceAll(value.Get("url").String(), "https://imgur.com", ""),
|
Link: url.String(),
|
||||||
Cover: Media{
|
Cover: Media{
|
||||||
Id: value.Get("cover_id").String(),
|
Id: value.Get("cover_id").String(),
|
||||||
Type: value.Get("cover.type").String(),
|
Type: value.Get("cover.type").String(),
|
||||||
@@ -88,14 +91,11 @@ func (client *Client) FetchTag(tag string, sort string, page string) (Tag, error
|
|||||||
Views: value.Get("view_count").Int(),
|
Views: value.Get("view_count").Int(),
|
||||||
IsAlbum: value.Get("is_album").Bool(),
|
IsAlbum: value.Get("is_album").Bool(),
|
||||||
})
|
})
|
||||||
}()
|
|
||||||
|
|
||||||
return true
|
return true
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
tagData := Tag{
|
tagData := Tag{
|
||||||
Tag: tag,
|
Tag: tag,
|
||||||
Display: data.Get("display").String(),
|
Display: data.Get("display").String(),
|
||||||
@@ -105,6 +105,6 @@ func (client *Client) FetchTag(tag string, sort string, page string) (Tag, error
|
|||||||
Background: "/" + data.Get("background_id").String() + ".webp",
|
Background: "/" + data.Get("background_id").String() + ".webp",
|
||||||
}
|
}
|
||||||
|
|
||||||
client.Cache.Set(tag + sort + page + "-tag", tagData, cache.DefaultExpiration)
|
client.Cache.Set(tag+sort+page+"-tag", tagData, 4*cache.DefaultExpiration)
|
||||||
return tagData, nil
|
return tagData, nil
|
||||||
}
|
}
|
||||||
|
|||||||
107
api/trending.go
Normal file
107
api/trending.go
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
package api
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"codeberg.org/rimgo/rimgo/utils"
|
||||||
|
"github.com/patrickmn/go-cache"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (client *Client) FetchTrending(section, sort, page string) ([]Submission, error) {
|
||||||
|
cacheData, found := client.Cache.Get(fmt.Sprintf("trending-%s-%s-%s", section, sort, page))
|
||||||
|
if found {
|
||||||
|
return cacheData.([]Submission), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", "https://api.imgur.com/post/v1/posts", nil)
|
||||||
|
if err != nil {
|
||||||
|
return []Submission{}, err
|
||||||
|
}
|
||||||
|
utils.SetReqHeaders(req)
|
||||||
|
|
||||||
|
q := req.URL.Query()
|
||||||
|
q.Add("client_id", client.ClientID)
|
||||||
|
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":
|
||||||
|
fallthrough
|
||||||
|
default:
|
||||||
|
q.Add("filter[window]", "week")
|
||||||
|
q.Add("sort", "-viral")
|
||||||
|
sort = "popular"
|
||||||
|
}
|
||||||
|
switch section {
|
||||||
|
case "hot":
|
||||||
|
q.Add("filter[section]", "eq:hot")
|
||||||
|
case "new":
|
||||||
|
q.Add("filter[section]", "eq:new")
|
||||||
|
case "top":
|
||||||
|
q.Add("filter[section]", "eq:top")
|
||||||
|
q.Add("filter[window]", "day")
|
||||||
|
default:
|
||||||
|
q.Add("filter[section]", "eq:hot")
|
||||||
|
section = "hot"
|
||||||
|
}
|
||||||
|
|
||||||
|
req.URL.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
res, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return []Submission{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return []Submission{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data := gjson.Parse(string(body))
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
posts := make([]Submission, 0)
|
||||||
|
data.ForEach(
|
||||||
|
func(key, value gjson.Result) bool {
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
posts = append(posts, Submission{
|
||||||
|
Id: value.Get("id").String(),
|
||||||
|
Title: value.Get("title").String(),
|
||||||
|
Link: strings.ReplaceAll(value.Get("url").String(), "https://imgur.com", ""),
|
||||||
|
Cover: 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()
|
||||||
|
|
||||||
|
client.Cache.Set(fmt.Sprintf("trending-%s-%s-%s", section, sort, page), posts, cache.DefaultExpiration)
|
||||||
|
return posts, nil
|
||||||
|
}
|
||||||
150
api/user.go
150
api/user.go
@@ -8,6 +8,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"codeberg.org/rimgo/rimgo/utils"
|
"codeberg.org/rimgo/rimgo/utils"
|
||||||
|
"github.com/patrickmn/go-cache"
|
||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -69,7 +70,7 @@ func (client *Client) FetchUser(username string) (User, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (client *Client) FetchSubmissions(username string, sort string, page string) ([]Submission, error) {
|
func (client *Client) FetchSubmissions(username string, sort string, page string) ([]Submission, error) {
|
||||||
cacheData, found := client.Cache.Get(username + "-submissions")
|
cacheData, found := client.Cache.Get(username + "-submissions-" + sort + page)
|
||||||
if found {
|
if found {
|
||||||
return cacheData.([]Submission), nil
|
return cacheData.([]Submission), nil
|
||||||
}
|
}
|
||||||
@@ -89,20 +90,140 @@ func (client *Client) FetchSubmissions(username string, sort string, page string
|
|||||||
go func() {
|
go func() {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
|
|
||||||
coverData := value.Get("images.#(id==\"" + value.Get("cover").String() + "\")")
|
submissions = append(submissions, parseSubmission(value))
|
||||||
cover := Media{
|
}()
|
||||||
Id: value.Get("id").String(),
|
|
||||||
Description: value.Get("description").String(),
|
return true
|
||||||
Type: strings.Split(value.Get("type").String(), "/")[0],
|
},
|
||||||
Url: strings.ReplaceAll(value.Get("link").String(), "https://i.imgur.com", ""),
|
)
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
client.Cache.Set(username+"-submissions-"+sort+page, submissions, 15*time.Minute)
|
||||||
|
return submissions, nil
|
||||||
}
|
}
|
||||||
if coverData.Exists() {
|
|
||||||
|
func (client *Client) FetchUserFavorites(username string, sort string, page string) ([]Submission, error) {
|
||||||
|
cacheData, found := client.Cache.Get(username + "-favorites-" + sort + page)
|
||||||
|
if found {
|
||||||
|
return cacheData.([]Submission), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
req, err := http.NewRequest("GET", "https://api.imgur.com/3/account/"+username+"/gallery_favorites/"+page+"/"+sort, nil)
|
||||||
|
if err != nil {
|
||||||
|
return []Submission{}, err
|
||||||
|
}
|
||||||
|
utils.SetReqHeaders(req)
|
||||||
|
q := req.URL.Query()
|
||||||
|
q.Add("client_id", client.ClientID)
|
||||||
|
req.URL.RawQuery = q.Encode()
|
||||||
|
|
||||||
|
res, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return []Submission{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
body, err := io.ReadAll(res.Body)
|
||||||
|
if err != nil {
|
||||||
|
return []Submission{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
data := gjson.Parse(string(body))
|
||||||
|
|
||||||
|
submissions := []Submission{}
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
data.Get("data").ForEach(
|
||||||
|
func(key, value gjson.Result) bool {
|
||||||
|
wg.Add(1)
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
|
||||||
|
submissions = append(submissions, parseSubmission(value))
|
||||||
|
}()
|
||||||
|
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
)
|
||||||
|
wg.Wait()
|
||||||
|
|
||||||
|
client.Cache.Set(username+"-favorites-"+sort+page, submissions, 15*time.Minute)
|
||||||
|
return submissions, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (client *Client) FetchUserComments(username string) ([]Comment, error) {
|
||||||
|
cacheData, found := client.Cache.Get(username + "-usercomments")
|
||||||
|
if found {
|
||||||
|
return cacheData.([]Comment), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
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:"+username)
|
||||||
|
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))
|
||||||
|
|
||||||
|
comments := make([]Comment, 0)
|
||||||
|
data.Get("data").ForEach(
|
||||||
|
func(key, value gjson.Result) bool {
|
||||||
|
comments = append(comments, parseComment(value))
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
client.Cache.Set(username+"-usercomments", comments, cache.DefaultExpiration)
|
||||||
|
return comments, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func parseSubmission(value gjson.Result) Submission {
|
||||||
|
var cover Media
|
||||||
|
c := value.Get("cover")
|
||||||
|
coverData := value.Get("images.#(id==\"" + c.String() + "\")")
|
||||||
|
switch {
|
||||||
|
case c.Type == gjson.String && coverData.Exists():
|
||||||
cover = Media{
|
cover = Media{
|
||||||
Id: coverData.Get("id").String(),
|
Id: coverData.Get("id").String(),
|
||||||
Description: coverData.Get("description").String(),
|
Description: coverData.Get("description").String(),
|
||||||
Type: strings.Split(coverData.Get("type").String(), "/")[0],
|
Type: strings.Split(coverData.Get("type").String(), "/")[0],
|
||||||
Url: strings.ReplaceAll(coverData.Get("link").String(), "https://i.imgur.com", ""),
|
Url: strings.ReplaceAll(coverData.Get("link").String(), "https://i.imgur.com", ""),
|
||||||
}
|
}
|
||||||
|
// This case is when fetching comments
|
||||||
|
case c.Type != gjson.Null:
|
||||||
|
cover = Media{
|
||||||
|
Id: c.Get("id").String(),
|
||||||
|
Url: strings.ReplaceAll(c.Get("url").String(), "https://i.imgur.com", ""),
|
||||||
|
}
|
||||||
|
// Replace with thumbnails here because it's easier.
|
||||||
|
if strings.HasSuffix(cover.Url, ".mp4") {
|
||||||
|
cover.Url = cover.Url[:len(cover.Url)-3] + "webp"
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
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", ""),
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
id := value.Get("id").String()
|
id := value.Get("id").String()
|
||||||
@@ -112,7 +233,7 @@ func (client *Client) FetchSubmissions(username string, sort string, page string
|
|||||||
link = "/gallery/" + id
|
link = "/gallery/" + id
|
||||||
}
|
}
|
||||||
|
|
||||||
submissions = append(submissions, Submission{
|
return Submission{
|
||||||
Id: id,
|
Id: id,
|
||||||
Link: link,
|
Link: link,
|
||||||
Title: value.Get("title").String(),
|
Title: value.Get("title").String(),
|
||||||
@@ -123,14 +244,5 @@ func (client *Client) FetchSubmissions(username string, sort string, page string
|
|||||||
Comments: value.Get("comment_count").Int(),
|
Comments: value.Get("comment_count").Int(),
|
||||||
Views: value.Get("views").Int(),
|
Views: value.Get("views").Int(),
|
||||||
IsAlbum: value.Get("is_album").Bool(),
|
IsAlbum: value.Get("is_album").Bool(),
|
||||||
})
|
}
|
||||||
}()
|
|
||||||
|
|
||||||
return true
|
|
||||||
},
|
|
||||||
)
|
|
||||||
wg.Wait()
|
|
||||||
|
|
||||||
client.Cache.Set(username + "-submissions", submissions, 15*time.Minute)
|
|
||||||
return submissions, nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
43
go.mod
43
go.mod
@@ -1,41 +1,44 @@
|
|||||||
module codeberg.org/rimgo/rimgo
|
module codeberg.org/rimgo/rimgo
|
||||||
|
|
||||||
go 1.17
|
go 1.21
|
||||||
|
|
||||||
|
toolchain go1.21.4
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/PuerkitoBio/goquery v1.8.1
|
github.com/PuerkitoBio/goquery v1.9.2
|
||||||
github.com/aymerick/raymond v2.0.2+incompatible
|
|
||||||
github.com/dustin/go-humanize v1.0.1
|
github.com/dustin/go-humanize v1.0.1
|
||||||
github.com/gofiber/fiber/v2 v2.48.0
|
github.com/gofiber/fiber/v2 v2.52.4
|
||||||
github.com/gofiber/template/handlebars/v2 v2.1.4
|
github.com/gofiber/template/handlebars/v2 v2.1.9
|
||||||
github.com/joho/godotenv v1.5.1
|
github.com/joho/godotenv v1.5.1
|
||||||
github.com/microcosm-cc/bluemonday v1.0.25
|
github.com/mailgun/raymond/v2 v2.0.48
|
||||||
|
github.com/microcosm-cc/bluemonday v1.0.26
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/tidwall/gjson v1.14.4
|
github.com/tidwall/gjson v1.17.1
|
||||||
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3
|
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/andybalholm/brotli v1.0.5 // indirect
|
github.com/andybalholm/brotli v1.1.0 // indirect
|
||||||
github.com/andybalholm/cascadia v1.3.2 // indirect
|
github.com/andybalholm/cascadia v1.3.2 // indirect
|
||||||
github.com/aymerick/douceur v0.2.0 // indirect
|
github.com/aymerick/douceur v0.2.0 // indirect
|
||||||
github.com/gofiber/template v1.8.2 // indirect
|
github.com/gofiber/template v1.8.3 // indirect
|
||||||
github.com/gofiber/utils v1.1.0 // indirect
|
github.com/gofiber/utils v1.1.0 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.6.0 // indirect
|
||||||
github.com/gorilla/css v1.0.0 // indirect
|
github.com/gorilla/css v1.0.1 // indirect
|
||||||
github.com/klauspost/compress v1.16.7 // indirect
|
github.com/klauspost/compress v1.17.9 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||||
github.com/mattn/go-runewidth v0.0.14 // indirect
|
github.com/mattn/go-runewidth v0.0.15 // indirect
|
||||||
github.com/philhofer/fwd v1.1.2 // indirect
|
github.com/philhofer/fwd v1.1.2 // indirect
|
||||||
github.com/rivo/uniseg v0.4.4 // indirect
|
github.com/rivo/uniseg v0.4.7 // indirect
|
||||||
|
github.com/sirupsen/logrus v1.9.3 // indirect
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.1 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
github.com/tinylib/msgp v1.1.8 // indirect
|
github.com/tinylib/msgp v1.1.9 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasthttp v1.48.0 // indirect
|
github.com/valyala/fasthttp v1.55.0 // indirect
|
||||||
github.com/valyala/tcplisten v1.0.0 // indirect
|
github.com/valyala/tcplisten v1.0.0 // indirect
|
||||||
golang.org/x/net v0.12.0 // indirect
|
golang.org/x/net v0.26.0 // indirect
|
||||||
golang.org/x/sys v0.10.0 // indirect
|
golang.org/x/sys v0.21.0 // indirect
|
||||||
golang.org/x/text v0.11.0 // indirect
|
golang.org/x/text v0.16.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
136
go.sum
136
go.sum
@@ -1,148 +1,124 @@
|
|||||||
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM=
|
github.com/PuerkitoBio/goquery v1.9.2 h1:4/wZksC3KgkQw7SQgkKotmKljk0M6V8TUvA8Wb4yPeE=
|
||||||
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ=
|
github.com/PuerkitoBio/goquery v1.9.2/go.mod h1:GHPCaP0ODyyxqcNoFGYlAprUFH81NuRPd0GX3Zu2Mvk=
|
||||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
github.com/andybalholm/brotli v1.1.0 h1:eLKJA0d02Lf0mVpIDgYnqXcUn0GqVmEFny3VuID1U3M=
|
||||||
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
github.com/andybalholm/brotli v1.1.0/go.mod h1:sms7XGricyQI9K10gOSf56VKKWS4oLer58Q+mhRPtnY=
|
||||||
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA=
|
|
||||||
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss=
|
||||||
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
|
||||||
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
|
||||||
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
|
||||||
github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
|
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.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/gofiber/fiber/v2 v2.46.0/go.mod h1:DNl0/c37WLe0g92U6lx1VMQuxGUQY5V7EIaVoEsUffc=
|
github.com/gofiber/fiber/v2 v2.52.4 h1:P+T+4iK7VaqUsq2PALYEfBBo6bJZ4q3FP8cZ84EggTM=
|
||||||
github.com/gofiber/fiber/v2 v2.48.0 h1:cRVMCb9aUJDsyHxGFLwz/sGzDggdailZZyptU9F9cU0=
|
github.com/gofiber/fiber/v2 v2.52.4/go.mod h1:KEOE+cXMhXG0zHc9d8+E38hoX+ZN7bhOtgeF2oT6jrQ=
|
||||||
github.com/gofiber/fiber/v2 v2.48.0/go.mod h1:xqJgfqrc23FJuqGOW6DVgi3HyZEm2Mn9pRqUb2kHSX8=
|
github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
|
||||||
github.com/gofiber/template v1.8.2 h1:PIv9s/7Uq6m+Fm2MDNd20pAFFKt5wWs7ZBd8iV9pWwk=
|
github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
|
||||||
github.com/gofiber/template v1.8.2/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
|
github.com/gofiber/template/handlebars/v2 v2.1.9 h1:NXzwrqBtXyy1JlgwIPAU5KoyorEZ1PLnTyS51W2nPwM=
|
||||||
github.com/gofiber/template/handlebars/v2 v2.1.4 h1:m/GwEnzv5bpifOg9BrpCIzkhD2GU10E5oZjI8NdDbYY=
|
github.com/gofiber/template/handlebars/v2 v2.1.9/go.mod h1:yi2z68McoNaCB5G7NCP5duB8py0zfpiJPqcl6mfWYrE=
|
||||||
github.com/gofiber/template/handlebars/v2 v2.1.4/go.mod h1:bb6ip6ZEgBqKSdZcbnFLlfL8PcCRslnX6WgpcxVBiTE=
|
|
||||||
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
|
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
|
||||||
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
|
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY=
|
github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
|
||||||
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c=
|
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
|
||||||
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
|
||||||
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
|
||||||
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA=
|
||||||
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
github.com/klauspost/compress v1.17.9/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
|
||||||
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
|
github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
|
||||||
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
|
||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||||
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA=
|
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U=
|
||||||
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU=
|
github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
||||||
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
|
github.com/microcosm-cc/bluemonday v1.0.26 h1:xbqSvqzQMeEHCqMi64VAs4d8uy6Mequs3rQ0k/Khz58=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg=
|
github.com/microcosm-cc/bluemonday v1.0.26/go.mod h1:JyzOCs9gkyQyjs+6h10UEVSe02CGwkhd72Xdqh78TWs=
|
||||||
github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE=
|
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU=
|
|
||||||
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
|
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw=
|
||||||
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
|
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
|
||||||
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis=
|
github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
|
||||||
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
|
||||||
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8=
|
github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
|
||||||
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4=
|
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
|
||||||
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g=
|
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||||
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||||
|
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||||
|
github.com/tidwall/gjson v1.17.1 h1:wlYEnwqAHgzmhNUFfw7Xalt2JzQvsMx2Se4PcoFCT/U=
|
||||||
|
github.com/tidwall/gjson v1.17.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||||
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw=
|
github.com/tinylib/msgp v1.1.9 h1:SHf3yoO2sGA0veCJeCBYLHuttAVFHGm2RHgNodW7wQU=
|
||||||
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0=
|
github.com/tinylib/msgp v1.1.9/go.mod h1:BCXGB54lDD8qUEPmiG0cQQUANC4IUQyB2ItS2UDlO/k=
|
||||||
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
|
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
github.com/valyala/fasthttp v1.55.0 h1:Zkefzgt6a7+bVKHnu/YaYSOPfNYNisSVBo/unVCf8k8=
|
||||||
github.com/valyala/fasthttp v1.48.0 h1:oJWvHb9BIZToTQS3MuQ2R3bJZiNSa2KiNdeI8A+79Tc=
|
github.com/valyala/fasthttp v1.55.0/go.mod h1:NkY9JtkrpPKmgwV3HTaS2HWaJss9RSIsRVfcxxoHiOM=
|
||||||
github.com/valyala/fasthttp v1.48.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
|
|
||||||
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
|
||||||
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3 h1:1Coh5BsUBlXoEJmIEaNzVAWrtg9k7/eJzailMQr1grw=
|
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3 h1:1Coh5BsUBlXoEJmIEaNzVAWrtg9k7/eJzailMQr1grw=
|
||||||
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8=
|
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
|
||||||
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio=
|
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
|
||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|
||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
|
||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
|
||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
|
||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|
||||||
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
|
||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
|
||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
golang.org/x/net v0.26.0 h1:soB7SVo0PWrY4vPW/+ay0jKDNScG2X9wFeYlXIvJsOQ=
|
||||||
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50=
|
golang.org/x/net v0.26.0/go.mod h1:5YKkiSynbBIh3p6iOc/vibscux0x38BZDkn8sCUPxHE=
|
||||||
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA=
|
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.21.0 h1:rF+pYz3DAGSQAxAu1CbC7catZg4ebC4UIeIhKxBZvws=
|
||||||
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA=
|
golang.org/x/sys v0.21.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||||
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
|
|
||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
|
|
||||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
|
||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
|
||||||
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o=
|
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|
||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
|
||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4=
|
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||||
golang.org/x/text v0.11.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
|
|
||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
|
|||||||
@@ -28,21 +28,6 @@
|
|||||||
],
|
],
|
||||||
"cloudflare": false
|
"cloudflare": false
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"url": "https://rimgo.vern.cc",
|
|
||||||
"onion": "http://rimgo.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion",
|
|
||||||
"countries": [
|
|
||||||
"ca"
|
|
||||||
],
|
|
||||||
"cloudflare": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"url": "https://rim.odyssey346.dev",
|
|
||||||
"countries": [
|
|
||||||
"fr"
|
|
||||||
],
|
|
||||||
"cloudflare": false
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"url": "https://imgur.010032.xyz",
|
"url": "https://imgur.010032.xyz",
|
||||||
"countries": [
|
"countries": [
|
||||||
@@ -98,18 +83,32 @@
|
|||||||
"cloudflare": false
|
"cloudflare": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://i.01r.xyz",
|
"url": "https://rimgo.eu.projectsegfau.lt",
|
||||||
|
"countries": [
|
||||||
|
"fr"
|
||||||
|
],
|
||||||
|
"cloudflare": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://rimgo.us.projectsegfau.lt",
|
||||||
"countries": [
|
"countries": [
|
||||||
"us"
|
"us"
|
||||||
],
|
],
|
||||||
"cloudflare": true
|
"cloudflare": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://rimgo.in.projectsegfau.lt",
|
||||||
|
"countries": [
|
||||||
|
"in"
|
||||||
|
],
|
||||||
|
"cloudflare": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://rimgo.fascinated.cc",
|
"url": "https://rimgo.fascinated.cc",
|
||||||
"countries": [
|
"countries": [
|
||||||
"us"
|
"us"
|
||||||
],
|
],
|
||||||
"cloudflare": true
|
"cloudflare": false
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"url": "https://rimgo.whateveritworks.org",
|
"url": "https://rimgo.whateveritworks.org",
|
||||||
@@ -138,5 +137,26 @@
|
|||||||
"de"
|
"de"
|
||||||
],
|
],
|
||||||
"cloudflare": false
|
"cloudflare": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://rimgo.drgns.space",
|
||||||
|
"countries": [
|
||||||
|
"us"
|
||||||
|
],
|
||||||
|
"cloudflare": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://rimgo.quantenzitrone.eu",
|
||||||
|
"countries": [
|
||||||
|
"cz"
|
||||||
|
],
|
||||||
|
"cloudflare": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"url": "https://rimgo.frylo.net",
|
||||||
|
"countries": [
|
||||||
|
"nl"
|
||||||
|
],
|
||||||
|
"cloudflare": false
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
32
main.go
32
main.go
@@ -11,7 +11,7 @@ import (
|
|||||||
"codeberg.org/rimgo/rimgo/static"
|
"codeberg.org/rimgo/rimgo/static"
|
||||||
"codeberg.org/rimgo/rimgo/utils"
|
"codeberg.org/rimgo/rimgo/utils"
|
||||||
"codeberg.org/rimgo/rimgo/views"
|
"codeberg.org/rimgo/rimgo/views"
|
||||||
"github.com/aymerick/raymond"
|
"github.com/mailgun/raymond/v2"
|
||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
"github.com/gofiber/fiber/v2/middleware/cache"
|
"github.com/gofiber/fiber/v2/middleware/cache"
|
||||||
"github.com/gofiber/fiber/v2/middleware/filesystem"
|
"github.com/gofiber/fiber/v2/middleware/filesystem"
|
||||||
@@ -52,14 +52,7 @@ func main() {
|
|||||||
code = e.Code
|
code = e.Code
|
||||||
}
|
}
|
||||||
|
|
||||||
err = ctx.Status(code).Render("errors/error", fiber.Map{
|
return utils.RenderError(ctx, code)
|
||||||
"err": err,
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
return ctx.Status(fiber.StatusInternalServerError).SendString("Internal Server Error")
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
@@ -72,22 +65,31 @@ func main() {
|
|||||||
|
|
||||||
if os.Getenv("ENV") == "dev" {
|
if os.Getenv("ENV") == "dev" {
|
||||||
app.Use("/static", filesystem.New(filesystem.Config{
|
app.Use("/static", filesystem.New(filesystem.Config{
|
||||||
MaxAge: 2592000,
|
|
||||||
Root: http.Dir("./static"),
|
Root: http.Dir("./static"),
|
||||||
}))
|
}))
|
||||||
app.Get("/errors/429", func(c *fiber.Ctx) error {
|
app.Get("/errors/429", func(c *fiber.Ctx) error {
|
||||||
return c.Render("errors/429", nil)
|
return c.Render("errors/429", nil)
|
||||||
})
|
})
|
||||||
|
app.Get("/errors/429/img", func(c *fiber.Ctx) error {
|
||||||
|
return c.Redirect("/static/img/error-429.png")
|
||||||
|
})
|
||||||
app.Get("/errors/404", func(c *fiber.Ctx) error {
|
app.Get("/errors/404", func(c *fiber.Ctx) error {
|
||||||
return c.Render("errors/404", nil)
|
return c.Render("errors/404", nil)
|
||||||
})
|
})
|
||||||
|
app.Get("/errors/404/img", func(c *fiber.Ctx) error {
|
||||||
|
return c.Redirect("/static/img/error-404.png")
|
||||||
|
})
|
||||||
app.Get("/errors/error", func(c *fiber.Ctx) error {
|
app.Get("/errors/error", func(c *fiber.Ctx) error {
|
||||||
return c.Render("errors/error", fiber.Map{
|
return c.Render("errors/error", fiber.Map{
|
||||||
"err": "Test error",
|
"err": "Test error",
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
app.Get("/errors/error/img", func(c *fiber.Ctx) error {
|
||||||
|
return c.Redirect("/static/img/error-generic.png")
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
app.Use("/static", filesystem.New(filesystem.Config{
|
app.Use("/static", filesystem.New(filesystem.Config{
|
||||||
|
MaxAge: 2592000,
|
||||||
Root: http.FS(static.GetFiles()),
|
Root: http.FS(static.GetFiles()),
|
||||||
}))
|
}))
|
||||||
app.Use(cache.New(cache.Config{
|
app.Use(cache.New(cache.Config{
|
||||||
@@ -116,12 +118,15 @@ func main() {
|
|||||||
app.Get("/about", pages.HandleAbout)
|
app.Get("/about", pages.HandleAbout)
|
||||||
app.Get("/privacy", pages.HandlePrivacy)
|
app.Get("/privacy", pages.HandlePrivacy)
|
||||||
app.Get("/search", pages.HandleSearch)
|
app.Get("/search", pages.HandleSearch)
|
||||||
|
app.Get("/trending", pages.HandleTrending)
|
||||||
app.Get("/a/:postID", pages.HandlePost)
|
app.Get("/a/:postID", pages.HandlePost)
|
||||||
app.Get("/a/:postID/embed", pages.HandleEmbed)
|
app.Get("/a/:postID/embed", pages.HandleEmbed)
|
||||||
app.Get("/t/:tag", pages.HandleTag)
|
app.Get("/t/:tag", pages.HandleTag)
|
||||||
app.Get("/t/:tag/:postID", pages.HandlePost)
|
app.Get("/t/:tag/:postID", pages.HandlePost)
|
||||||
app.Get("/user/:userID", pages.HandleUser)
|
|
||||||
app.Get("/r/:sub/:postID", pages.HandlePost)
|
app.Get("/r/:sub/:postID", pages.HandlePost)
|
||||||
|
app.Get("/user/:userID", pages.HandleUser)
|
||||||
|
app.Get("/user/:userID/favorites", pages.HandleUserFavorites)
|
||||||
|
app.Get("/user/:userID/comments", pages.HandleUserComments)
|
||||||
app.Get("/user/:userID/cover", pages.HandleUserCover)
|
app.Get("/user/:userID/cover", pages.HandleUserCover)
|
||||||
app.Get("/user/:userID/avatar", pages.HandleUserAvatar)
|
app.Get("/user/:userID/avatar", pages.HandleUserAvatar)
|
||||||
app.Get("/gallery/:postID", pages.HandlePost)
|
app.Get("/gallery/:postID", pages.HandlePost)
|
||||||
@@ -132,5 +137,8 @@ func main() {
|
|||||||
app.Get("/:postID", pages.HandlePost)
|
app.Get("/:postID", pages.HandlePost)
|
||||||
app.Get("/:postID/embed", pages.HandleEmbed)
|
app.Get("/:postID/embed", pages.HandleEmbed)
|
||||||
|
|
||||||
app.Listen(utils.Config.Addr + ":" + utils.Config.Port)
|
err := app.Listen(utils.Config.Addr + ":" + utils.Config.Port)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,10 +23,10 @@ func HandleEmbed(c *fiber.Ctx) error {
|
|||||||
post, err = ApiClient.FetchMedia(c.Params("postID"))
|
post, err = ApiClient.FetchMedia(c.Params("postID"))
|
||||||
}
|
}
|
||||||
if err != nil && err.Error() == "ratelimited by imgur" {
|
if err != nil && err.Error() == "ratelimited by imgur" {
|
||||||
return c.Status(429).Render("errors/429", nil)
|
return utils.RenderError(c, 429)
|
||||||
}
|
}
|
||||||
if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") {
|
if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") {
|
||||||
return c.Status(404).Render("errors/404", nil)
|
return utils.RenderError(c, 404)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import (
|
|||||||
|
|
||||||
func HandleMedia(c *fiber.Ctx) error {
|
func HandleMedia(c *fiber.Ctx) error {
|
||||||
c.Set("Cache-Control", "public,max-age=31557600")
|
c.Set("Cache-Control", "public,max-age=31557600")
|
||||||
|
c.Set("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self'")
|
||||||
if strings.HasPrefix(c.Path(), "/stack") {
|
if strings.HasPrefix(c.Path(), "/stack") {
|
||||||
return handleMedia(c, "https://i.stack.imgur.com/"+strings.ReplaceAll(c.Params("baseName"), "stack/", "")+"."+c.Params("extension"))
|
return handleMedia(c, "https://i.stack.imgur.com/"+strings.ReplaceAll(c.Params("baseName"), "stack/", "")+"."+c.Params("extension"))
|
||||||
} else {
|
} else {
|
||||||
@@ -20,13 +21,15 @@ func HandleMedia(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
func HandleUserCover(c *fiber.Ctx) error {
|
func HandleUserCover(c *fiber.Ctx) error {
|
||||||
c.Set("Cache-Control", "public,max-age=604800")
|
c.Set("Cache-Control", "public,max-age=604800")
|
||||||
|
c.Set("Content-Security-Policy", "default-src 'none'")
|
||||||
return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/cover?maxwidth=2560")
|
return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/cover?maxwidth=2560")
|
||||||
};
|
}
|
||||||
|
|
||||||
func HandleUserAvatar(c *fiber.Ctx) error {
|
func HandleUserAvatar(c *fiber.Ctx) error {
|
||||||
c.Set("Cache-Control", "public,max-age=604800")
|
c.Set("Cache-Control", "public,max-age=604800")
|
||||||
|
c.Set("Content-Security-Policy", "default-src 'none'")
|
||||||
return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/avatar")
|
return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/avatar")
|
||||||
};
|
}
|
||||||
|
|
||||||
func handleMedia(c *fiber.Ctx, url string) error {
|
func handleMedia(c *fiber.Ctx, url string) error {
|
||||||
utils.SetHeaders(c)
|
utils.SetHeaders(c)
|
||||||
@@ -57,19 +60,14 @@ func handleMedia(c *fiber.Ctx, url string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Status(res.StatusCode)
|
if res.StatusCode == 404 || strings.Contains(res.Request.URL.String(), "error/404") {
|
||||||
if res.StatusCode == 404 {
|
return utils.RenderError(c, 404)
|
||||||
return c.Render("errors/404", fiber.Map{
|
|
||||||
"path": c.Path(),
|
|
||||||
})
|
|
||||||
} else if res.StatusCode == 429 {
|
} else if res.StatusCode == 429 {
|
||||||
return c.Render("errors/429", fiber.Map{
|
return utils.RenderError(c, 429)
|
||||||
"path": c.Path(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.Set("Accept-Ranges", "bytes")
|
c.Set("Accept-Ranges", "bytes")
|
||||||
c.Set("Content-Type", res.Header.Get("Content-Type"));
|
c.Set("Content-Type", res.Header.Get("Content-Type"))
|
||||||
c.Set("Content-Length", res.Header.Get("Content-Length"))
|
c.Set("Content-Length", res.Header.Get("Content-Length"))
|
||||||
if res.Header.Get("Content-Range") != "" {
|
if res.Header.Get("Content-Range") != "" {
|
||||||
c.Set("Content-Range", res.Header.Get("Content-Range"))
|
c.Set("Content-Range", res.Header.Get("Content-Range"))
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package pages
|
|||||||
import (
|
import (
|
||||||
"crypto/rand"
|
"crypto/rand"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"codeberg.org/rimgo/rimgo/api"
|
"codeberg.org/rimgo/rimgo/api"
|
||||||
@@ -10,28 +11,53 @@ import (
|
|||||||
"github.com/gofiber/fiber/v2"
|
"github.com/gofiber/fiber/v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Cursed function
|
||||||
|
func nextInTag(client *api.Client, tagname, sort, page, I string) string {
|
||||||
|
i, err := strconv.Atoi(I)
|
||||||
|
if err != nil || i < 0 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
tag, err := client.FetchTag(tagname, sort, page)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
if i >= len(tag.Posts)-1 {
|
||||||
|
pageNumber, _ := strconv.Atoi(page)
|
||||||
|
tagn, err := client.FetchTag(tagname, sort, strconv.Itoa(pageNumber+1))
|
||||||
|
// Check length - Imgur will not return an error if there are no more posts and you request the next page
|
||||||
|
if err != nil || len(tagn.Posts) < 1 {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return tagn.Posts[0].Link
|
||||||
|
}
|
||||||
|
return tag.Posts[i+1].Link
|
||||||
|
}
|
||||||
|
|
||||||
func HandlePost(c *fiber.Ctx) error {
|
func HandlePost(c *fiber.Ctx) error {
|
||||||
utils.SetHeaders(c)
|
utils.SetHeaders(c)
|
||||||
c.Set("X-Frame-Options", "DENY")
|
c.Set("X-Frame-Options", "DENY")
|
||||||
|
|
||||||
|
postId := c.Params("postID")
|
||||||
|
if strings.Contains(postId, "-") {
|
||||||
|
postId = postId[len(postId)-7:]
|
||||||
|
}
|
||||||
|
|
||||||
post, err := api.Album{}, error(nil)
|
post, err := api.Album{}, error(nil)
|
||||||
switch {
|
switch {
|
||||||
case strings.HasPrefix(c.Path(), "/a"):
|
case strings.HasPrefix(c.Path(), "/a"):
|
||||||
post, err = ApiClient.FetchAlbum(c.Params("postID"))
|
post, err = ApiClient.FetchAlbum(postId)
|
||||||
case strings.HasPrefix(c.Path(), "/gallery"):
|
case strings.HasPrefix(c.Path(), "/gallery"):
|
||||||
post, err = ApiClient.FetchPosts(c.Params("postID"))
|
post, err = ApiClient.FetchPosts(postId)
|
||||||
case strings.HasPrefix(c.Path(), "/t"):
|
case strings.HasPrefix(c.Path(), "/t"):
|
||||||
post, err = ApiClient.FetchPosts(c.Params("postID"))
|
post, err = ApiClient.FetchPosts(postId)
|
||||||
default:
|
default:
|
||||||
post, err = ApiClient.FetchMedia(c.Params("postID"))
|
post, err = ApiClient.FetchMedia(postId)
|
||||||
}
|
}
|
||||||
if err != nil && err.Error() == "ratelimited by imgur" {
|
if err != nil && err.Error() == "ratelimited by imgur" {
|
||||||
return c.Status(429).Render("errors/429", fiber.Map{
|
return utils.RenderError(c, 429)
|
||||||
"path": c.Path(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") {
|
if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") {
|
||||||
return c.Status(404).Render("errors/404", nil)
|
return utils.RenderError(c, 404)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -40,7 +66,7 @@ func HandlePost(c *fiber.Ctx) error {
|
|||||||
comments := []api.Comment{}
|
comments := []api.Comment{}
|
||||||
if post.SharedWithCommunity {
|
if post.SharedWithCommunity {
|
||||||
c.Set("Cache-Control", "public,max-age=604800")
|
c.Set("Cache-Control", "public,max-age=604800")
|
||||||
comments, err = ApiClient.FetchComments(c.Params("postID"))
|
comments, err = ApiClient.FetchComments(postId)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -58,8 +84,16 @@ func HandlePost(c *fiber.Ctx) error {
|
|||||||
}
|
}
|
||||||
c.Set("Content-Security-Policy", csp)
|
c.Set("Content-Security-Policy", csp)
|
||||||
|
|
||||||
|
var next string
|
||||||
|
tagParam := strings.Split(c.Query("tag"), ".")
|
||||||
|
if len(tagParam) == 4 {
|
||||||
|
tag, sort, page, index := tagParam[0], tagParam[1], tagParam[2], tagParam[3]
|
||||||
|
next = nextInTag(ApiClient, tag, sort, page, index)
|
||||||
|
}
|
||||||
|
|
||||||
return c.Render("post", fiber.Map{
|
return c.Render("post", fiber.Map{
|
||||||
"post": post,
|
"post": post,
|
||||||
|
"next": next,
|
||||||
"comments": comments,
|
"comments": comments,
|
||||||
"nonce": nonce,
|
"nonce": nonce,
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
func HandlePrivacy(c *fiber.Ctx) error {
|
func HandlePrivacy(c *fiber.Ctx) error {
|
||||||
utils.SetHeaders(c)
|
utils.SetHeaders(c)
|
||||||
c.Set("X-Frame-Options", "DENY")
|
c.Set("X-Frame-Options", "DENY")
|
||||||
|
c.Set("Content-Security-Policy", "default-src 'none'; form-action 'self'; style-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
|
||||||
|
|
||||||
return c.Render("privacy", fiber.Map{
|
return c.Render("privacy", fiber.Map{
|
||||||
"config": utils.Config,
|
"config": utils.Config,
|
||||||
|
|||||||
@@ -29,11 +29,6 @@ func HandleSearch(c *fiber.Ctx) error {
|
|||||||
pageNumber = 0
|
pageNumber = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
displayPrevPage := true
|
|
||||||
if page == "0" {
|
|
||||||
displayPrevPage = false
|
|
||||||
}
|
|
||||||
|
|
||||||
results, err := ApiClient.Search(query, page)
|
results, err := ApiClient.Search(query, page)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -42,8 +37,7 @@ func HandleSearch(c *fiber.Ctx) error {
|
|||||||
return c.Render("search", fiber.Map{
|
return c.Render("search", fiber.Map{
|
||||||
"query": query,
|
"query": query,
|
||||||
"results": results,
|
"results": results,
|
||||||
"page": pageNumber + 1,
|
"page": pageNumber,
|
||||||
"displayPrev": displayPrevPage,
|
|
||||||
"nextPage": pageNumber + 1,
|
"nextPage": pageNumber + 1,
|
||||||
"prevPage": pageNumber - 1,
|
"prevPage": pageNumber - 1,
|
||||||
})
|
})
|
||||||
|
|||||||
12
pages/tag.go
12
pages/tag.go
@@ -23,28 +23,20 @@ func HandleTag(c *fiber.Ctx) error {
|
|||||||
pageNumber = 0
|
pageNumber = 0
|
||||||
}
|
}
|
||||||
|
|
||||||
displayPrevPage := true
|
|
||||||
if page == "1" {
|
|
||||||
displayPrevPage = false
|
|
||||||
}
|
|
||||||
|
|
||||||
tag, err := ApiClient.FetchTag(c.Params("tag"), c.Query("sort"), page)
|
tag, err := ApiClient.FetchTag(c.Params("tag"), c.Query("sort"), page)
|
||||||
if err != nil && err.Error() == "ratelimited by imgur" {
|
if err != nil && err.Error() == "ratelimited by imgur" {
|
||||||
return c.Status(429).Render("errors/429", fiber.Map{
|
return utils.RenderError(c, 429)
|
||||||
"path": c.Path(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if tag.Display == "" {
|
if tag.Display == "" {
|
||||||
return c.Status(404).Render("errors/404", nil)
|
return utils.RenderError(c, 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
return c.Render("tag", fiber.Map{
|
return c.Render("tag", fiber.Map{
|
||||||
"tag": tag,
|
"tag": tag,
|
||||||
"page": page,
|
"page": page,
|
||||||
"displayPrev": displayPrevPage,
|
|
||||||
"nextPage": pageNumber + 1,
|
"nextPage": pageNumber + 1,
|
||||||
"prevPage": pageNumber - 1,
|
"prevPage": pageNumber - 1,
|
||||||
})
|
})
|
||||||
|
|||||||
52
pages/trending.go
Normal file
52
pages/trending.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package pages
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"codeberg.org/rimgo/rimgo/utils"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func HandleTrending(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'; style-src 'unsafe-inline' 'self'; media-src 'self'; img-src 'self'; manifest-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 = 1
|
||||||
|
}
|
||||||
|
|
||||||
|
section := c.Query("section")
|
||||||
|
switch section {
|
||||||
|
case "hot", "new", "top":
|
||||||
|
default:
|
||||||
|
section = "hot"
|
||||||
|
}
|
||||||
|
sort := c.Query("sort")
|
||||||
|
switch sort {
|
||||||
|
case "newest", "best", "popular":
|
||||||
|
default:
|
||||||
|
sort = "popular"
|
||||||
|
}
|
||||||
|
|
||||||
|
results, err := ApiClient.FetchTrending(section, sort, page)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Render("trending", fiber.Map{
|
||||||
|
"results": results,
|
||||||
|
"section": section,
|
||||||
|
"sort": sort,
|
||||||
|
"page": pageNumber,
|
||||||
|
"nextPage": pageNumber + 1,
|
||||||
|
"prevPage": pageNumber - 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -25,23 +25,19 @@ func HandleUser(c *fiber.Ctx) error {
|
|||||||
|
|
||||||
user, err := ApiClient.FetchUser(c.Params("userID"))
|
user, err := ApiClient.FetchUser(c.Params("userID"))
|
||||||
if err != nil && err.Error() == "ratelimited by imgur" {
|
if err != nil && err.Error() == "ratelimited by imgur" {
|
||||||
return c.Status(429).Render("errors/429", fiber.Map{
|
return utils.RenderError(c, 429)
|
||||||
"path": c.Path(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if user.Username == "" {
|
if user.Username == "" {
|
||||||
return c.Status(404).Render("errors/404", nil)
|
return utils.RenderError(c, 404)
|
||||||
}
|
}
|
||||||
|
|
||||||
submissions, err := ApiClient.FetchSubmissions(c.Params("userID"), "newest", page)
|
submissions, err := ApiClient.FetchSubmissions(c.Params("userID"), "newest", page)
|
||||||
if err != nil && err.Error() == "ratelimited by imgur" {
|
if err != nil && err.Error() == "ratelimited by imgur" {
|
||||||
c.Status(429)
|
c.Status(429)
|
||||||
return c.Render("errors/429", fiber.Map{
|
return utils.RenderError(c, 429)
|
||||||
"path": c.Path(),
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -55,3 +51,79 @@ func HandleUser(c *fiber.Ctx) error {
|
|||||||
"prevPage": 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")
|
||||||
|
|
||||||
|
user, err := ApiClient.FetchUser(c.Params("userID"))
|
||||||
|
if err != nil && err.Error() == "ratelimited by imgur" {
|
||||||
|
return utils.RenderError(c, 429)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if user.Username == "" {
|
||||||
|
return utils.RenderError(c, 404)
|
||||||
|
}
|
||||||
|
|
||||||
|
comments, err := ApiClient.FetchUserComments(c.Params("userID"))
|
||||||
|
if err != nil && err.Error() == "ratelimited by imgur" {
|
||||||
|
c.Status(429)
|
||||||
|
return utils.RenderError(c, 429)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Render("userComments", fiber.Map{
|
||||||
|
"user": user,
|
||||||
|
"comments": comments,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func HandleUserFavorites(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 utils.RenderError(c, 429)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if user.Username == "" {
|
||||||
|
return utils.RenderError(c, 404)
|
||||||
|
}
|
||||||
|
|
||||||
|
favorites, err := ApiClient.FetchUserFavorites(c.Params("userID"), "newest", page)
|
||||||
|
if err != nil && err.Error() == "ratelimited by imgur" {
|
||||||
|
return utils.RenderError(c, 429)
|
||||||
|
}
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
return c.Render("userFavorites", fiber.Map{
|
||||||
|
"user": user,
|
||||||
|
"favorites": favorites,
|
||||||
|
"page": page,
|
||||||
|
"nextPage": pageNumber + 1,
|
||||||
|
"prevPage": pageNumber - 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "rimgo",
|
"name": "rimgo",
|
||||||
"short_name": "rimgo",
|
"short_name": "rimgo",
|
||||||
|
"start_url": "/",
|
||||||
"icons": [
|
"icons": [
|
||||||
{
|
{
|
||||||
"src": "/static/favicon/android-chrome-192x192.png",
|
"src": "/static/favicon/android-chrome-192x192.png",
|
||||||
|
|||||||
1
static/icons/PhArrowUpRight.svg
Normal file
1
static/icons/PhArrowUpRight.svg
Normal file
@@ -0,0 +1 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><path fill="currentColor" d="M200 64v104a8 8 0 0 1-16 0V83.31L69.66 197.66a8 8 0 0 1-11.32-11.32L172.69 72H88a8 8 0 0 1 0-16h104a8 8 0 0 1 8 8Z"/></svg>
|
||||||
|
After Width: | Height: | Size: 239 B |
BIN
static/img/error-404.png
Normal file
BIN
static/img/error-404.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 16 KiB |
BIN
static/img/error-429.png
Normal file
BIN
static/img/error-429.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 19 KiB |
BIN
static/img/error-generic.png
Normal file
BIN
static/img/error-generic.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 17 KiB |
@@ -7,7 +7,7 @@ body {
|
|||||||
}
|
}
|
||||||
|
|
||||||
p a {
|
p a {
|
||||||
text-decoration: underline
|
@apply break-words underline
|
||||||
}
|
}
|
||||||
|
|
||||||
.posts {
|
.posts {
|
||||||
|
|||||||
25
utils/error.go
Normal file
25
utils/error.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
package utils
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"codeberg.org/rimgo/rimgo/static"
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func RenderError(c *fiber.Ctx, code int) error {
|
||||||
|
if !strings.Contains(c.Get("Accept"), "html") && c.Params("extension") != "" {
|
||||||
|
codeStr := "generic"
|
||||||
|
if code != 0 {
|
||||||
|
codeStr = strconv.Itoa(code)
|
||||||
|
}
|
||||||
|
img, _ := static.GetFiles().ReadFile("img/error-" + codeStr + ".png")
|
||||||
|
c.Set("Content-Type", "image/png")
|
||||||
|
return c.Status(code).Send(img)
|
||||||
|
} else {
|
||||||
|
return c.Status(code).Render("errors/" + strconv.Itoa(code), fiber.Map{
|
||||||
|
"path": c.Path(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -13,6 +13,7 @@
|
|||||||
<header class="my-8 p-8 rounded-xl flex flex-col gap-4 items-center justify-center bg-gradient-to-r from-blue-400 to-emerald-400">
|
<header class="my-8 p-8 rounded-xl flex flex-col gap-4 items-center justify-center bg-gradient-to-r from-blue-400 to-emerald-400">
|
||||||
<h2 class="font-bold text-white text-2xl">The fast, private image viewer for Imgur.</h2>
|
<h2 class="font-bold text-white text-2xl">The fast, private image viewer for Imgur.</h2>
|
||||||
{{> partials/searchBar }}
|
{{> partials/searchBar }}
|
||||||
|
<a class="flex gap-1 items-center" href="/trending">Or see what's trending <img class="invert" src="/static/icons/PhArrowUpRight.svg" alt="" height="18" width="18" /></a>
|
||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main class="my-8">
|
<main class="my-8">
|
||||||
@@ -24,8 +25,8 @@
|
|||||||
rimgo is not affiliated with Imgur, all content is proxied from Imgur.
|
rimgo is not affiliated with Imgur, all content is proxied from Imgur.
|
||||||
</p>
|
</p>
|
||||||
<br/>
|
<br/>
|
||||||
<h3 class="font-bold text-xl">Notice</h3>
|
<h3 class="font-bold text-xl">Legal notice</h3>
|
||||||
<p>All images and media are from Imgur. rimgo does not allow uploads or comments. Any issues with content should be reported to Imgur.</p>
|
<p>rimgo does not allow uploads or host any content, media. All content on any rimgo instances is from Imgur™. Imgur is a trademark of Imgur, Inc. Any issues with content on rimgo should be be reported to Imgur. rimgo is not affiliated with Imgur, Inc.</p>
|
||||||
</main>
|
</main>
|
||||||
|
|
||||||
<h2 class="font-bold text-2xl">This instance</h2>
|
<h2 class="font-bold text-2xl">This instance</h2>
|
||||||
|
|||||||
22
views/partials/contextComment.hbs
Normal file
22
views/partials/contextComment.hbs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
<a href="{{Post.Link}}">
|
||||||
|
<div class="sm:grid gap-4 w-full" style="grid-template-columns: 120px 1fr;">
|
||||||
|
<img class="object-cover block w-full h-[300px] sm:w-[120px] sm:h-[140px] rounded-lg rounded-b-none sm:rounded-b-lg" src="{{this.Post.Cover.Url}}" alt="">
|
||||||
|
<div class="flex flex-col gap-2 bg-slate-600 p-4 rounded-lg rounded-t-none sm:rounded-t-lg w-full">
|
||||||
|
<div class="flex flex-col h-full">
|
||||||
|
<p class="md-container">{{{this.Comment}}}</p>
|
||||||
|
<div class="flex-grow"></div>
|
||||||
|
<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>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
@@ -25,7 +25,8 @@
|
|||||||
</header>
|
</header>
|
||||||
|
|
||||||
<main>
|
<main>
|
||||||
<div class="flex gap-4 items-center my-4">
|
<div class="flex flex-col sm:flex-row my-4 w-full justify-between">
|
||||||
|
<div class="flex flex-col gap-2 md:flex-row md:gap-4 md:items-center">
|
||||||
{{#if post.User.Username}}
|
{{#if post.User.Username}}
|
||||||
<a href="/user/{{post.User.Username}}" class="flex gap-2 items-center">
|
<a href="/user/{{post.User.Username}}" class="flex gap-2 items-center">
|
||||||
<img src="{{post.User.Avatar}}" class="rounded-full" width="36" height="36" />
|
<img src="{{post.User.Avatar}}" class="rounded-full" width="36" height="36" />
|
||||||
@@ -51,8 +52,14 @@
|
|||||||
{{/if}}
|
{{/if}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{{#noteq next ""}}
|
||||||
|
<a href="{{next}}" class="self-end">
|
||||||
|
<button class="p-2 rounded-lg bg-slate-600">Next ></button>
|
||||||
|
</a>
|
||||||
|
{{/noteq}}
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="flex flex-center flex-col">
|
<div class="flex flex-center flex-col break-words">
|
||||||
{{#each post.Media}}
|
{{#each post.Media}}
|
||||||
{{#if this.Title}}
|
{{#if this.Title}}
|
||||||
<h4 class="font-bold">{{this.Title}}</h4>
|
<h4 class="font-bold">{{this.Title}}</h4>
|
||||||
@@ -101,7 +108,8 @@
|
|||||||
{{#if comments}}
|
{{#if comments}}
|
||||||
<div>
|
<div>
|
||||||
<input id="comments__expandBtn" type="checkbox" checked>
|
<input id="comments__expandBtn" type="checkbox" checked>
|
||||||
<label class="comments__expandBtn__label my-2 py-4 border-solid border-t-2 border-slate-400" for="comments__expandBtn">
|
<label class="comments__expandBtn__label my-2 py-4 border-solid border-t-2 border-slate-400"
|
||||||
|
for="comments__expandBtn">
|
||||||
<h3 class="text-xl font-bold">Comments ({{post.Comments}})</h3>
|
<h3 class="text-xl font-bold">Comments ({{post.Comments}})</h3>
|
||||||
<span class="text-xl font-bold"></span>
|
<span class="text-xl font-bold"></span>
|
||||||
</label>
|
</label>
|
||||||
|
|||||||
@@ -22,10 +22,10 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="flex justify-between mt-4 font-bold">
|
<div class="flex justify-between mt-4 font-bold">
|
||||||
{{#if displayPrev}}
|
{{#noteq page "0"}}
|
||||||
<a href="/search?q={{query}}&page={{prevPage}}">Previous page</a>
|
<a href="/search?q={{query}}&page={{prevPage}}">Previous page</a>
|
||||||
{{/if}}
|
{{/noteq}}
|
||||||
<p>Page {{page}}</p>
|
<p>Page {{nextPage}}</p>
|
||||||
<a href="/search?q={{query}}&page={{nextPage}}">Next page</a>
|
<a href="/search?q={{query}}&page={{nextPage}}">Next page</a>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
@@ -45,10 +45,11 @@
|
|||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="mt-4 font-bold">
|
<div class="flex justify-between mt-4 font-bold">
|
||||||
{{#if displayPrev}}
|
{{#noteq page "1"}}
|
||||||
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>
|
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>
|
||||||
{{/if}}
|
{{/noteq}}
|
||||||
|
<p>Page {{nextPage}}</p>
|
||||||
<a href="{{channel.RelUrl}}?page={{nextPage}}">Next page</a>
|
<a href="{{channel.RelUrl}}?page={{nextPage}}">Next page</a>
|
||||||
</div>
|
</div>
|
||||||
</main>
|
</main>
|
||||||
|
|||||||
79
views/trending.hbs
Normal file
79
views/trending.hbs
Normal file
@@ -0,0 +1,79 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>Trending - 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 bg-gradient-to-r from-blue-400 to-emerald-400">
|
||||||
|
<div class="flex flex-col items-center justify-center text-center">
|
||||||
|
<h2 class="text-2xl font-extrabold">Trending</h2>
|
||||||
|
</div>
|
||||||
|
<div class="flex flex-col sm:flex-row sm:justify-between">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
{{#equal section "hot"}}
|
||||||
|
<a href="?section=hot&sort={{sort}}"><b>Hot</b></a>
|
||||||
|
<a href="?section=new&sort={{sort}}">New</a>
|
||||||
|
<a href="?section=top&sort={{sort}}">Top</a>
|
||||||
|
{{/equal}}
|
||||||
|
{{#equal section "new"}}
|
||||||
|
<a href="?section=hot&sort={{sort}}">Hot</a>
|
||||||
|
<a href="?section=new&sort={{sort}}"><b>New</b></a>
|
||||||
|
<a href="?section=top&sort={{sort}}">Top</a>
|
||||||
|
{{/equal}}
|
||||||
|
{{#equal section "top"}}
|
||||||
|
<a href="?section=hot&sort={{sort}}">Hot</a>
|
||||||
|
<a href="?section=new&sort={{sort}}">New</a>
|
||||||
|
<a href="?section=top&sort={{sort}}"><b>Top</b></a>
|
||||||
|
{{/equal}}
|
||||||
|
</div>
|
||||||
|
<hr class="sm:hidden my-2" />
|
||||||
|
<div class="flex flex-col sm:items-end">
|
||||||
|
{{#equal sort "popular"}}
|
||||||
|
<a href="?section={{section}}&sort=popular"><b>Popular</b></a>
|
||||||
|
<a href="?section={{section}}&sort=newest">Newest</a>
|
||||||
|
<a href="?section={{section}}&sort=best">Best</a>
|
||||||
|
{{/equal}}
|
||||||
|
{{#equal sort "newest"}}
|
||||||
|
<a href="?section={{section}}&sort=popular">Popular</a>
|
||||||
|
<a href="?section={{section}}&sort=newest"><b>Newest</b></a>
|
||||||
|
<a href="?section={{section}}&sort=best">Best</a>
|
||||||
|
{{/equal}}
|
||||||
|
{{#equal sort "best"}}
|
||||||
|
<a href="?section={{section}}&sort=popular">Popular</a>
|
||||||
|
<a href="?section={{section}}&sort=newest">Newest</a>
|
||||||
|
<a href="?section={{section}}&sort=best"><b>Best</b></a>
|
||||||
|
{{/equal}}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="posts">
|
||||||
|
{{#each results}}
|
||||||
|
{{> partials/post }}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex justify-between mt-4 font-bold">
|
||||||
|
{{#noteq page "1"}}
|
||||||
|
<a href="/trending?section={{section}}&sort={{sort}}&page={{prevPage}}">Previous page</a>
|
||||||
|
{{/noteq}}
|
||||||
|
<p>Page {{page}}</p>
|
||||||
|
<a href="/trending?section={{section}}&sort={{sort}}&page={{nextPage}}">Next page</a>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{{> partials/footer }}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
@@ -15,12 +15,18 @@
|
|||||||
</section>
|
</section>
|
||||||
|
|
||||||
<header class="p-4 rounded-xl text-white mb-4" style="background-image: url('{{user.Cover}}');">
|
<header class="p-4 rounded-xl text-white mb-4" style="background-image: url('{{user.Cover}}');">
|
||||||
<div class="flex items-center gap-2">
|
<div class="flex flex-col sm:flex-row items-center gap-2">
|
||||||
<img class="rounded-full" src="{{user.Avatar}}" width="72" height="72">
|
<img class="rounded-full" src="{{user.Avatar}}" width="72" height="72">
|
||||||
<div>
|
<div class="items-center sm:items-start text-center sm:text-left">
|
||||||
<h2 class="font-bold text-2xl">{{user.Username}}</h2>
|
<h2 class="font-bold text-2xl">{{user.Username}}</h2>
|
||||||
<p>{{user.Points}} pts · {{user.CreatedAt}}</p>
|
<p>{{user.Points}} pts · {{user.CreatedAt}}</p>
|
||||||
</div>
|
</div>
|
||||||
|
<hr class="sm:border-0 flex-grow">
|
||||||
|
<div class="flex flex-col items-center sm:items-end">
|
||||||
|
<a href="/user/{{user.Username}}"><b>Submissions</b></a>
|
||||||
|
<a href="/user/{{user.Username}}/favorites">Favorites</a>
|
||||||
|
<a href="/user/{{user.Username}}/comments">Comments</a>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<p class="mt-2">{{user.Bio}}</p>
|
<p class="mt-2">{{user.Bio}}</p>
|
||||||
</header>
|
</header>
|
||||||
|
|||||||
45
views/userComments.hbs
Normal file
45
views/userComments.hbs
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>{{user.Username}}'s comments - 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 flex-col sm:flex-row items-center gap-2">
|
||||||
|
<img class="rounded-full" src="{{user.Avatar}}" width="72" height="72">
|
||||||
|
<div class="items-center sm:items-start text-center sm:text-left">
|
||||||
|
<h2 class="font-bold text-2xl">{{user.Username}}</h2>
|
||||||
|
<p>{{user.Points}} pts · {{user.CreatedAt}}</p>
|
||||||
|
</div>
|
||||||
|
<hr class="sm:border-0 flex-grow">
|
||||||
|
<div class="flex flex-col items-center sm:items-end">
|
||||||
|
<a href="/user/{{user.Username}}">Submissions</a>
|
||||||
|
<a href="/user/{{user.Username}}/favorites">Favorites</a>
|
||||||
|
<a href="/user/{{user.Username}}/comments"><b>Comments</b></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="mt-2">{{user.Bio}}</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="comments flex flex-col gap-4">
|
||||||
|
{{#each comments}}
|
||||||
|
{{> partials/contextComment }}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{{> partials/footer }}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
52
views/userFavorites.hbs
Normal file
52
views/userFavorites.hbs
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
<!DOCTYPE html>
|
||||||
|
<html lang="en">
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title>{{user.Username}}'s favorites - 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 flex-col sm:flex-row items-center gap-2">
|
||||||
|
<img class="rounded-full" src="{{user.Avatar}}" width="72" height="72">
|
||||||
|
<div class="items-center sm:items-start text-center sm:text-left">
|
||||||
|
<h2 class="font-bold text-2xl">{{user.Username}}</h2>
|
||||||
|
<p>{{user.Points}} pts · {{user.CreatedAt}}</p>
|
||||||
|
</div>
|
||||||
|
<hr class="sm:border-0 flex-grow">
|
||||||
|
<div class="flex flex-col items-center sm:items-end">
|
||||||
|
<a href="/user/{{user.Username}}">Submissions</a>
|
||||||
|
<a href="/user/{{user.Username}}/favorites"><b>Favorites</b></a>
|
||||||
|
<a href="/user/{{user.Username}}/comments">Comments</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="mt-2">{{user.Bio}}</p>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="posts">
|
||||||
|
{{#each favorites}}
|
||||||
|
{{> partials/post }}
|
||||||
|
{{/each}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="flex mt-4 font-bold justify-between">
|
||||||
|
{{#noteq page "0" }}
|
||||||
|
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>
|
||||||
|
{{/noteq}}
|
||||||
|
<a href="{{channel.RelUrl}}?page={{nextPage}}">Next page</a>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
|
||||||
|
{{> partials/footer }}
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
||||||
Reference in New Issue
Block a user