54 Commits

Author SHA1 Message Date
video-prize-ranch
7b946e55b6 Update dependencies 2022-04-22 11:59:32 -04:00
video-prize-ranch
088f46a5bb Remove viper and file configuration 2022-04-22 11:55:53 -04:00
video-prize-ranch
4a41e59d34 Add recover middleware 2022-04-22 11:38:09 -04:00
video-prize-ranch
6c49dee732 Favicon on Direct Image Links (closes #23) 2022-04-10 11:24:54 -04:00
video-prize-ranch
12684be6aa Add manifest-src to CSP and add name to manifest (closes #27) 2022-04-10 11:21:41 -04:00
video-prize-ranch
94b74675b1 Update 'README.md' 2022-04-03 17:27:18 +02:00
video-prize-ranch
72f6c56f62 Merge pull request 'Update 'instances.json'' (#24) from xnaas/rimgo:xnaas/instance-json-patch into main
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/24
2022-04-03 13:55:42 +02:00
xnaas
43deb1087c Update 'instances.json'
Update instances.json to include all instances as of 1f25128b8e
2022-04-02 03:04:02 +02:00
video-prize-ranch
1f25128b8e Merge pull request 'Updated Instances' (#22) from xnaas/rimgo:xnaas/instance-patch into main
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/22
2022-04-02 01:15:32 +02:00
xnaas
f75846b42e Update 'README.md' 2022-04-02 01:14:38 +02:00
xnaas
0749462457 Updated Instances
I figured this could look a lot prettier when editing...

* add i.actionsack.com instance (mine)
* show Cloudflare instances as 😿 like Bibliogram instance list does
* separate clearnet, Tor, and I2P into their own subsections
2022-04-02 01:03:12 +02:00
video-prize-ranch
afb1dd28a2 Update 'README.md' 2022-03-24 12:50:56 +01:00
video-prize-ranch
abcb3218dd Add rimgo.lunar.icu (#20) 2022-03-23 21:20:32 -04:00
video-prize-ranch
1bb3353f70 Update buildx 2022-03-22 18:29:23 -04:00
video-prize-ranch
5522ec8e99 Readd Redirector config 2022-03-22 16:56:27 -04:00
video-prize-ranch
7a0248f5aa Improvements on mobile 2022-03-21 22:20:16 -04:00
video-prize-ranch
ff8017d9b1 Replace Redirector with LibRedirect 2022-03-21 22:01:16 -04:00
video-prize-ranch
d96e0768bc Remove old rimgu code 2022-03-21 21:57:30 -04:00
video-prize-ranch
a13a064547 Remove rimgo.bcow.xyz 2022-03-21 21:57:30 -04:00
video-prize-ranch
f236963444 Merge pull request 'docs(instances): add .onion & .i2p' (#19) from curben/rimgo:onion-i2p into main
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/19
2022-03-20 03:20:46 +01:00
video-prize-ranch
b03264b143 Add official image to docker-compose 2022-03-19 16:00:48 -04:00
video-prize-ranch
11a70b6e76 Switch to scratch image 2022-03-19 15:58:12 -04:00
Ming Di Leom
5f8bc2b7b8 docs(instances): add .onion & .i2p 2022-03-19 05:51:30 +00:00
video-prize-ranch
038842a36b Update dependencies 2022-03-16 13:33:31 -04:00
video-prize-ranch
90ab3b37d3 Caching (closes #18) 2022-03-15 22:56:34 -04:00
video-prize-ranch
db2195d17f Update buildx 2022-03-09 19:51:51 -05:00
video-prize-ranch
34e779595d Merge pull request 'docs(instances): add esmailelbob onion' (#17) from curben/rimgo:esmail-onion into main
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/17
2022-03-03 03:07:55 +01:00
Ming Di Leom
c10076d36b docs(instances): add esmailelbob onion 2022-03-02 06:55:42 +00:00
video-prize-ranch
4572499658 Add support for .gifv (closes #13) and fixes loading media IDs 2022-02-22 19:06:39 -05:00
video-prize-ranch
156452713b Cache go modules 2022-02-21 12:26:31 -05:00
video-prize-ranch
718a017ccf Add GitLab CI 2022-02-21 12:23:23 -05:00
video-prize-ranch
d9b8b660f4 Fix images in galleries 2022-02-21 12:17:28 -05:00
video-prize-ranch
36793004f8 Display tags in posts (#11) 2022-02-21 12:14:00 -05:00
video-prize-ranch
003b61a69d Change sort link color 2022-02-21 12:09:44 -05:00
video-prize-ranch
cf5a1ac18b Delete h.ts 2022-02-21 11:03:18 -05:00
video-prize-ranch
07a202da8f Initial tags support (#11) 2022-02-18 16:56:56 -05:00
video-prize-ranch
5ba3b386a6 Single-media posts that are neither albums nor galleries (closes #15) 2022-02-17 16:07:15 -05:00
video-prize-ranch
ece82ce9ab Revert pull request 14 2022-02-12 12:09:15 -05:00
video-prize-ranch
7f4d090943 Update README 2022-02-11 18:50:24 -05:00
video-prize-ranch
601172a987 Merge pull request 'Some README updates' (#14) from esmailelbob/rimgo:main into main
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/14
2022-02-12 00:43:24 +01:00
esmailelbob
d90bf77e57 Some README updates
* Added my instance
* Fixed a security bug with docker, DO NOT use sudo with docker ;) - (thanks to: https://nickjanetakis.com/blog/docker-tip-20-running-docker-without-sudo-on-linux)

Signed-off-by: esmailelbob <esmailelbob@noreply.codeberg.org>
2022-02-10 08:18:54 +01:00
video-prize-ranch
a029f0d197 Fix single user posts (#10) 2022-02-09 20:04:25 -05:00
video-prize-ranch
379a1f3b81 Switch to h4 2022-02-09 20:04:09 -05:00
video-prize-ranch
9f746c8dbf Fix not showing user information on anonymous posts 2022-02-08 15:39:07 -05:00
video-prize-ranch
11e8a00c1d Fix loading posts that return 404 from albums 2022-02-08 15:37:07 -05:00
video-prize-ranch
5a015c48f1 Add instances.json (#12) 2022-02-02 15:19:00 -05:00
video-prize-ranch
86afc22616 Switch to gjson 2022-02-02 11:05:36 -05:00
video-prize-ranch
4ea95ff592 Use instance URL on redirector config 2022-02-02 10:54:00 -05:00
video-prize-ranch
220ecd847a Use instance domain on frontpage 2022-02-02 10:53:33 -05:00
video-prize-ranch
740f62abd9 Don't show - when there is no title 2022-02-02 10:48:25 -05:00
video-prize-ranch
6e5b0ee127 Add user to albums 2022-02-02 10:46:47 -05:00
video-prize-ranch
41012edf9e Add pages for users 2022-02-02 10:22:48 -05:00
video-prize-ranch
5596998511 Allow fullscreen in permissions-policy 2022-02-02 10:20:14 -05:00
video-prize-ranch
1dec0d4ca2 Add new instance 2022-01-28 19:12:38 -05:00
44 changed files with 907 additions and 515 deletions

21
.gitlab-ci.yml Normal file
View File

@@ -0,0 +1,21 @@
variables:
REPO_NAME: codeberg.org/video-prize-ranch/rimgo
DOCKER_HOST: tcp://docker:2375
build:
image: docker:20
stage: deploy
services:
- name: docker:20-dind
command: ["--experimental"]
before_script:
- mkdir -p ~/.docker/cli-plugins
- wget -O ~/.docker/cli-plugins/docker-buildx https://github.com/docker/buildx/releases/download/v0.8.1/buildx-v0.8.1.linux-amd64
- chmod +x ~/.docker/cli-plugins/docker-buildx
- docker run --rm --privileged multiarch/qemu-user-static --reset -p yes
script:
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker context create mybuilder
- docker buildx create --use --name mybuilder mybuilder
- docker pull $CI_REGISTRY_IMAGE:latest || true
- docker buildx build --cache-from $CI_REGISTRY_IMAGE:latest --platform linux/amd64,linux/arm64 --push -t $CI_REGISTRY_IMAGE:latest .

View File

@@ -1,14 +1,16 @@
FROM golang:alpine AS build
WORKDIR /src
RUN apk --no-cache add git
RUN apk --no-cache add git ca-certificates
RUN git clone https://codeberg.org/video-prize-ranch/rimgo .
RUN go build
RUN go mod download
RUN CGO_ENABLED=0 go build
FROM alpine:latest as bin
FROM scratch as bin
WORKDIR /app
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /src/rimgo .
EXPOSE 3000

View File

@@ -6,26 +6,32 @@ An alternative frontend for Imgur. Based on [rimgu](https://codeberg.org/3np/rim
<a href="https://www.gnu.org/licenses/agpl-3.0.en.html">
<img alt="License: AGPLv3" src="https://shields.io/badge/License-AGPL%20v3-blue.svg">
</a>
<a href="https://matrix.to/#/#rimgo:nitro.chat">
<img alt="Matrix" src="https://img.shields.io/badge/chat-matrix-blue">
</a>
<a href="https://gitlab.com/overtime-zone-wildfowl/rimgo">
<img alt="CI" src="https://gitlab.com/overtime-zone-wildfowl/rimgo/badges/main/pipeline.svg">
</a>
It's read-only and works without JavaScript. Images and albums can be viewed without wasting resources from downloading and running tracking scripts. No sign-up nags.
## Features
- [x] URL-compatible with i.imgur.com - just replace the domain in the URL
- [x] Images and videos (gifv, mp4)
- [ ] Galleries with comments
- [x] Albums
- [ ] User page
- [ ] Tag page
- URL-compatible with i.imgur.com - just replace the domain in the URL
- Images and videos (~~gifv~~, mp4)
- Galleries with comments
- Albums
- User page
- Tag page
This is currently very early stage software. Some things left to implement (contributions welcome!):
Some things left to implement (contributions welcome!):
- [x] Streaming (currently media is downloaded in full in rimgu before it's returned)
- [ ] Localization/internationalization
- [x] Pretty CSS styling (responsive?)
- [ ] Support for other popular image sites
- [ ] Filtering and exploration on user/tags pages
- [ ] Responsive scaling of videos on user/tags pages
- [x] Filtering and exploration on user/tags pages
- [x] Responsive scaling of videos on user/tags pages
- [x] Logo
Things that are considered out of scope:
@@ -38,16 +44,33 @@ Things that are considered out of scope:
Open an issue to have your instance listed here!
| Website | Country | Cloudflare |
|------------------------------------------------------------------------------------------------------------------------------------------|---------|------------|
| [i.bcow.xyz](https://i.bcow.xyz/) (official) | 🇨🇦 CA | |
| [rimgo.pussthecat.org](https://rimgo.pussthecat.org/) | 🇩🇪 DE | |
| [img.riverside.rocks](https://img.riverside.rocks) | 🇺🇸 US | |
| [rimgo.totaldarkness.net](https://rimgo.totaldarkness.net/) | 🇨🇦 CA | |
| [rimgo.bus-hit.me](https://rimgo.bus-hit.me/) | 🇨🇦 CA | |
| [l4d4owboqr6xcmd6lf64gbegel62kbudu3x3jnldz2mx6mhn3bsv3zyd.onion](http://l4d4owboqr6xcmd6lf64gbegel62kbudu3x3jnldz2mx6mhn3bsv3zyd.onion/) | | |
| [jx3dpcwedpzu2mh54obk5gvl64i2ln7pt5mrzd75s4jnndkqwzaim7ad.onion](http://jx3dpcwedpzu2mh54obk5gvl64i2ln7pt5mrzd75s4jnndkqwzaim7ad.onion) | 🇺🇸 US | |
### Clearnet
| URL | Country | Cloudflare |
| :--------------------------------------------------------- | :------ | :--------- |
| [i.bcow.xyz](https://i.bcow.xyz) (official) | 🇨🇦 CA | |
| [rimgo.pussthecat.org](https://rimgo.pussthecat.org) | 🇩🇪 DE | |
| [img.riverside.rocks](https://img.riverside.rocks) | 🇺🇸 US | |
| [rimgo.totaldarkness.net](https://rimgo.totaldarkness.net) | 🇨🇦 CA | |
| [rimgo.bus-hit.me](https://rimgo.bus-hit.me) | 🇨🇦 CA | |
| [rimgo.esmailelbob.xyz](https://rimgo.esmailelbob.xyz) | 🇨🇦 CA | |
| [rimgo.lunar.icu](https://rimgo.lunar.icu) | 🇩🇪 DE | 😢 |
| [i.actionsack.com](https://i.actionsack.com) | 🇺🇸 US | 😢 |
### Tor
| URL | Country |
| :-- | :------ |
| [l4d4owboqr6xcmd6lf64gbegel62kbudu3x3jnldz2mx6mhn3bsv3zyd.onion](http://l4d4owboqr6xcmd6lf64gbegel62kbudu3x3jnldz2mx6mhn3bsv3zyd.onion/) | N/A |
| [jx3dpcwedpzu2mh54obk5gvl64i2ln7pt5mrzd75s4jnndkqwzaim7ad.onion](http://jx3dpcwedpzu2mh54obk5gvl64i2ln7pt5mrzd75s4jnndkqwzaim7ad.onion) | 🇺🇸 US |
| [rimgo.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion](http://rimgo.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion) | 🇨🇦 CA |
| [be7udfhmnzqyt7cxysg6c4pbawarvaofjjywp35nhd5qamewdfxl6sid.onion](http://be7udfhmnzqyt7cxysg6c4pbawarvaofjjywp35nhd5qamewdfxl6sid.onion) | 🇦🇺 AU |
### I2P
| URL | Country |
| :-- | :------ |
| [xazdnfgtzmcbcxhmcbbvr4uodd6jtn4fdiayasghywdn227xsmoa.b32.i2p](http://xazdnfgtzmcbcxhmcbbvr4uodd6jtn4fdiayasghywdn227xsmoa.b32.i2p) | 🇦🇺 AU |
## Install
rimgo can run on any platform Go compiles on.
@@ -95,22 +118,20 @@ You can now run rimgo.
./rimgo
```
## Configuration
rimgo can be configured using environment variables or a config file.
rimgo can be configured using environment variables.
### Environment variables
| Name | Default |
|-----------------------|-----------------|
| RIMGU_PORT | 3000 |
| RIMGU_HOST | localhost |
| RIMGU_ADDRESS | 0.0.0.0 |
| RIMGU_IMGUR_CLIENT_ID | 546c25a59c58ad7 |
| Name | Default |
|-----------------|-----------------|
| PORT | 3000 |
| ADDRESS | 0.0.0.0 |
| IMGUR_CLIENT_ID | 546c25a59c58ad7 |
## Contributing
PRs are welcome!
PRs are welcome! You can also send patches to `cb.8a3w5@simplelogin.co` but pull requests are preferred.
This software is released under the AGPL 3.0 license. In short, this means that if you make any modifications to the code and then publish the result (e.g. by hosting the result on a web server), you must publicly distribute your changes and declare that they also use AGPL 3.0.

View File

@@ -4,17 +4,23 @@ import (
"io"
"net/http"
"strings"
"time"
"codeberg.org/video-prize-ranch/rimgo/types"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/spf13/viper"
"github.com/patrickmn/go-cache"
"github.com/tidwall/gjson"
)
func FetchAlbum(albumID string) (types.Album, error) {
// https://api.imgur.com/post/v1/albums/zk7mdKH?client_id=${CLIENT_ID}&include=media%2Caccount
var albumCache = cache.New(1*time.Hour, 15*time.Minute)
res, err := http.Get("https://api.imgur.com/post/v1/albums/" + albumID + "?client_id=" + viper.GetString("RIMGU_IMGUR_CLIENT_ID") + "&include=media%2Caccount")
func FetchAlbum(albumID string) (types.Album, error) {
cacheData, found := albumCache.Get(albumID + "-album")
if found {
return cacheData.(types.Album), nil
}
res, err := http.Get("https://api.imgur.com/post/v1/albums/" + albumID + "?client_id=" + utils.Config["imgurId"].(string) + "&include=media%2Caccount")
if err != nil {
return types.Album{}, err
}
@@ -27,17 +33,23 @@ func FetchAlbum(albumID string) (types.Album, error) {
data := gjson.Parse(string(body))
album := types.Album{}
if data.Get("shared_with_community").Bool() {
if data.Get("shared_with_community").Bool() || res.StatusCode == 404 {
album, err = FetchPosts(albumID)
} else {
album, err = ParseAlbum(data)
}
albumCache.Set(albumID + "-album", album, cache.DefaultExpiration)
return album, err
}
func FetchPosts(albumID string) (types.Album, error) {
res, err := http.Get("https://api.imgur.com/post/v1/posts/" + albumID + "?client_id=" + viper.GetString("RIMGU_IMGUR_CLIENT_ID") + "&include=media%2Caccount")
cacheData, found := albumCache.Get(albumID + "-posts")
if found {
return cacheData.(types.Album), nil
}
res, err := http.Get("https://api.imgur.com/post/v1/posts/" + albumID + "?client_id=" + utils.Config["imgurId"].(string) + "&include=media%2Caccount%2Ctags")
if err != nil {
return types.Album{}, err
}
@@ -48,8 +60,39 @@ func FetchPosts(albumID string) (types.Album, error) {
}
data := gjson.Parse(string(body))
album, err := ParseAlbum(data)
if err != nil {
return types.Album{}, err
}
return ParseAlbum(data)
albumCache.Set(albumID + "-posts", album, cache.DefaultExpiration)
return album, nil
}
func FetchMedia(mediaID string) (types.Album, error) {
cacheData, found := albumCache.Get(mediaID + "-media")
if found {
return cacheData.(types.Album), nil
}
res, err := http.Get("https://api.imgur.com/post/v1/media/" + mediaID + "?client_id=" + utils.Config["imgurId"].(string) + "&include=media%2Caccount")
if err != nil {
return types.Album{}, err
}
body, err := io.ReadAll(res.Body)
if err != nil {
return types.Album{}, err
}
data := gjson.Parse(string(body))
album, err := ParseAlbum(data)
if err != nil {
return types.Album{}, err
}
albumCache.Set(mediaID + "-media", album, cache.DefaultExpiration)
return album, nil
}
func ParseAlbum(data gjson.Result) (types.Album, error) {
@@ -73,12 +116,24 @@ func ParseAlbum(data gjson.Result) (types.Album, error) {
},
)
tags := make([]types.Tag, 0)
data.Get("tags").ForEach(
func(key gjson.Result, value gjson.Result) bool {
tags = append(tags, types.Tag{
Tag: value.Get("tag").String(),
Display: value.Get("display").String(),
Background: "/" + value.Get("background_id").String() + ".webp",
})
return true
},
)
createdAt, err := utils.FormatDate(data.Get("created_at").String())
if err != nil {
return types.Album{}, err
}
return types.Album{
album := types.Album{
Id: data.Get("id").String(),
Title: data.Get("title").String(),
SharedWithCommunity: data.Get("shared_with_community").Bool(),
@@ -88,5 +143,17 @@ func ParseAlbum(data gjson.Result) (types.Album, error) {
Comments: data.Get("comment_count").Int(),
CreatedAt: createdAt,
Media: media,
}, nil
Tags: tags,
}
account := data.Get("account")
if account.Raw != "" {
album.User = types.User{
Id: account.Get("id").Int(),
Username: account.Get("username").String(),
Avatar: strings.ReplaceAll(account.Get("avatar_url").String(), "https://i.imgur.com", ""),
}
}
return album, nil
}

View File

@@ -10,14 +10,19 @@ import (
"codeberg.org/video-prize-ranch/rimgo/types"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/dustin/go-humanize"
"github.com/spf13/viper"
"github.com/patrickmn/go-cache"
"github.com/tidwall/gjson"
)
func FetchComments(galleryID string) ([]types.Comment, error) {
// https://api.imgur.com/comment/v1/comments?client_id=546c25a59c58ad7&filter[post]=eq:g1bk7CB&include=account&per_page=30&sort=best
var commentCache = cache.New(15*time.Minute, 15*time.Minute)
res, err := http.Get("https://api.imgur.com/comment/v1/comments?client_id=" + viper.GetString("RIMGU_IMGUR_CLIENT_ID") + "&filter[post]=eq:" + galleryID + "&include=account,adconfig&per_page=30&sort=best")
func FetchComments(galleryID string) ([]types.Comment, error) {
cacheData, found := commentCache.Get(galleryID)
if found {
return cacheData.([]types.Comment), nil
}
res, err := http.Get("https://api.imgur.com/comment/v1/comments?client_id=" + utils.Config["imgurId"].(string) + "&filter[post]=eq:" + galleryID + "&include=account,adconfig&per_page=30&sort=best")
if err != nil {
return []types.Comment{}, err
}
@@ -45,6 +50,7 @@ func FetchComments(galleryID string) ([]types.Comment, error) {
)
wg.Wait()
commentCache.Set(galleryID, comments, cache.DefaultExpiration)
return comments, nil
}

View File

@@ -1,19 +0,0 @@
export const fetchUserPosts = async (userID: string, sort: Sorting = 'newest'): Promise<Post[]> => {
/* eslint-disable max-len */
// https://api.imgur.com/3/account/mombotnumber5/submissions/0/newest?album_previews=1&client_id=${CLIENT_ID}
const response = await get(
``,
);
return JSON.parse(response.body).data;
/* eslint-enable max-len */
}
export const fetchTagPosts = async (tagID: string, sort: Sorting = 'viral'): Promise<TagResult> => {
/* eslint-disable max-len */
// https://api.imgur.com/3/account/mombotnumber5/submissions/0/newest?album_previews=1&client_id=${CLIENT_ID}
const response = await get(
`https://api.imgur.com/3/gallery/t/${tagID.toLowerCase()}/${sort}/week/0?client_id=${CONFIG.imgur_client_id}`,
);
return JSON.parse(response.body).data;
/* eslint-enable max-len */
}

105
api/tag.go Normal file
View File

@@ -0,0 +1,105 @@
package api
import (
"io/ioutil"
"net/http"
"strings"
"sync"
"time"
"codeberg.org/video-prize-ranch/rimgo/types"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/patrickmn/go-cache"
"github.com/tidwall/gjson"
)
var tagCache = cache.New(15*time.Minute, 15*time.Minute)
func FetchTag(tag string, sort string, page string) (types.Tag, error) {
cacheData, found := tagCache.Get(tag + sort + page)
if found {
return cacheData.(types.Tag), nil
}
req, err := http.NewRequest("GET", "https://api.imgur.com/post/v1/posts/t/"+tag, nil)
if err != nil {
return types.Tag{}, err
}
q := req.URL.Query()
q.Add("client_id", utils.Config["imgurId"].(string))
q.Add("include", "cover")
q.Add("page", page)
switch sort {
case "newest":
q.Add("filter[window]", "week")
q.Add("sort", "-time")
case "best":
q.Add("filter[window]", "all")
q.Add("sort", "-top")
case "popular":
default:
q.Add("filter[window]", "week")
q.Add("sort", "-viral")
sort = "popular"
}
req.URL.RawQuery = q.Encode()
res, err := http.DefaultClient.Do(req)
if err != nil {
return types.Tag{}, err
}
body, err := ioutil.ReadAll(res.Body)
if err != nil {
return types.Tag{}, err
}
data := gjson.Parse(string(body))
wg := sync.WaitGroup{}
posts := make([]types.Submission, 0)
data.Get("posts").ForEach(
func(key, value gjson.Result) bool {
wg.Add(1)
go func() {
defer wg.Done()
posts = append(posts, types.Submission{
Id: value.Get("id").String(),
Title: value.Get("title").String(),
Link: strings.ReplaceAll(value.Get("url").String(), "https://imgur.com", ""),
Cover: types.Media{
Id: value.Get("cover_id").String(),
Type: value.Get("cover.type").String(),
Url: strings.ReplaceAll(value.Get("cover.url").String(), "https://i.imgur.com", ""),
},
Points: value.Get("point_count").Int(),
Upvotes: value.Get("upvote_count").Int(),
Downvotes: value.Get("downvote_count").Int(),
Comments: value.Get("comment_count").Int(),
Views: value.Get("view_count").Int(),
IsAlbum: value.Get("is_album").Bool(),
})
}()
return true
},
)
wg.Wait()
tagData := types.Tag{
Tag: tag,
Display: data.Get("display").String(),
Sort: sort,
PostCount: data.Get("post_count").Int(),
Posts: posts,
Background: "/" + data.Get("background_id").String() + ".webp",
}
tagCache.Set(tag, tagData, cache.DefaultExpiration)
return tagData, nil
}

View File

@@ -1,7 +1,6 @@
package api
import (
"encoding/json"
"io"
"net/http"
"strings"
@@ -9,12 +8,20 @@ import (
"time"
"codeberg.org/video-prize-ranch/rimgo/types"
"github.com/spf13/viper"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/patrickmn/go-cache"
"github.com/tidwall/gjson"
)
var userCache = cache.New(30*time.Minute, 15*time.Minute)
func FetchUser(username string) (types.User, error) {
res, err := http.Get("https://api.imgur.com/account/v1/accounts/" + username + "?client_id=" + viper.GetString("RIMGU_IMGUR_CLIENT_ID"))
cacheData, found := userCache.Get(username)
if found {
return cacheData.(types.User), nil
}
res, err := http.Get("https://api.imgur.com/account/v1/accounts/" + username + "?client_id=" + utils.Config["imgurId"].(string))
if err != nil {
return types.User{}, err
}
@@ -24,23 +31,31 @@ func FetchUser(username string) (types.User, error) {
return types.User{}, err
}
var user types.User
err = json.Unmarshal(body, &user)
if err != nil {
return types.User{}, err
data := gjson.Parse(string(body))
createdTime, _ := time.Parse(time.RFC3339, data.Get("created_at").String())
user := types.User{
Id: data.Get("id").Int(),
Bio: data.Get("bio").String(),
Username: data.Get("username").String(),
Points: data.Get("reputation_count").Int(),
Cover: strings.ReplaceAll(data.Get("cover_url").String(), "https://imgur.com", ""),
Avatar: strings.ReplaceAll(data.Get("avatar_url").String(), "https://i.imgur.com", ""),
CreatedAt: createdTime.Format("January 2, 2006"),
}
user.Cover = strings.ReplaceAll(user.Cover, "https://imgur.com", "")
user.Avatar = strings.ReplaceAll(user.Avatar, "https://i.imgur.com", "")
createdTime, _ := time.Parse("2006-01-02T15:04:05Z", user.CreatedAt)
user.CreatedAt = createdTime.Format("January 2, 2006")
userCache.Set(username, user, 1*time.Hour)
return user, nil
}
func FetchSubmissions(username string, sort string, page string) ([]types.Submission, error) {
res, err := http.Get("https://api.imgur.com/3/account/" + username + "/submissions/" + page + "/" + sort + "?album_previews=1&client_id=" + viper.GetString("RIMGU_IMGUR_CLIENT_ID"))
cacheData, found := userCache.Get(username + "-submissions")
if found {
return cacheData.([]types.Submission), nil
}
res, err := http.Get("https://api.imgur.com/3/account/" + username + "/submissions/" + page + "/" + sort + "?album_previews=1&client_id=" + utils.Config["imgurId"].(string))
if err != nil {
return []types.Submission{}, err
}
@@ -62,24 +77,37 @@ func FetchSubmissions(username string, sort string, page string) ([]types.Submis
go func() {
defer wg.Done()
cover := value.Get("images.#(id==\"" + value.Get("cover").String() + "\")")
coverData := value.Get("images.#(id==\"" + value.Get("cover").String() + "\")")
cover := types.Media{}
if coverData.Exists() {
cover = types.Media{
Id: coverData.Get("id").String(),
Description: coverData.Get("description").String(),
Type: strings.Split(coverData.Get("type").String(), "/")[0],
Url: strings.ReplaceAll(coverData.Get("link").String(), "https://i.imgur.com", ""),
}
} else {
cover = types.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()
submissions = append(submissions, types.Submission{
Id: value.Get("id").String(),
Link: strings.ReplaceAll(value.Get("link").String(), "https://imgur.com", ""),
Id: id,
Link: "/a/" + id,
Title: value.Get("title").String(),
Cover: types.Media{
Id: cover.Get("id").String(),
Description: cover.Get("description").String(),
Type: strings.Split(cover.Get("type").String(), "/")[0],
Url: strings.ReplaceAll(cover.Get("link").String(), "https://i.imgur.com", ""),
},
Points: cover.Get("points").Int(),
Upvotes: cover.Get("ups").Int(),
Downvotes: cover.Get("downs").Int(),
Comments: cover.Get("comment_count").Int(),
Views: cover.Get("views").Int(),
IsAlbum: cover.Get("is_album").Bool(),
Cover: cover,
Points: value.Get("points").Int(),
Upvotes: value.Get("ups").Int(),
Downvotes: value.Get("downs").Int(),
Comments: value.Get("comment_count").Int(),
Views: value.Get("views").Int(),
IsAlbum: value.Get("is_album").Bool(),
})
}()
@@ -87,5 +115,7 @@ func FetchSubmissions(username string, sort string, page string) ([]types.Submis
},
)
wg.Wait()
userCache.Set(username + "-submissions", submissions, 15*time.Minute)
return submissions, nil
}

View File

@@ -1,4 +0,0 @@
RIMGU_PORT: 3000
RIMGU_HOST: localhost
RIMGU_ADDRESS: 0.0.0.0
RIMGU_IMGUR_CLIENT_ID: 546c25a59c58ad7

View File

@@ -2,7 +2,8 @@ version: '3'
services:
rimgo:
#image: quay.io/pussthecatorg/rimgo # Uncomment to use image
#image: registry.gitlab.com/overtime-zone-wildfowl/rimgo # Uncomment to use image, official image
#image: quay.io/pussthecatorg/rimgo # Unofficial image
build: .
ports:
- 3000:3000

29
go.mod
View File

@@ -4,33 +4,20 @@ go 1.17
require (
github.com/dustin/go-humanize v1.0.0
github.com/gofiber/fiber/v2 v2.24.0
github.com/gofiber/template v1.6.21
github.com/spf13/viper v1.10.1
github.com/tidwall/gjson v1.12.1
github.com/gofiber/fiber/v2 v2.32.0
github.com/gofiber/template v1.6.27
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/tidwall/gjson v1.14.1
)
require (
github.com/andybalholm/brotli v1.0.2 // indirect
github.com/andybalholm/brotli v1.0.4 // indirect
github.com/aymerick/raymond v2.0.2+incompatible // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/klauspost/compress v1.13.4 // indirect
github.com/magiconair/properties v1.8.5 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect
github.com/spf13/afero v1.6.0 // indirect
github.com/spf13/cast v1.4.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/subosito/gotenv v1.2.0 // indirect
github.com/klauspost/compress v1.15.1 // indirect
github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.0 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.31.0 // indirect
github.com/valyala/fasthttp v1.35.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 // indirect
golang.org/x/text v0.3.7 // indirect
gopkg.in/ini.v1 v1.66.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 // indirect
)

135
go.sum
View File

@@ -25,6 +25,7 @@ cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aD
cloud.google.com/go v0.93.3/go.mod h1:8utlLll2EF5XMAV15woO4lSbWQlk8rer9aLOfLh7+YI=
cloud.google.com/go v0.94.1/go.mod h1:qAlAugsXlC+JWO+Bke5vCtc9ONxjQT3drlTTnAplMW4=
cloud.google.com/go v0.97.0/go.mod h1:GF7l59pYBVlXQIBLx3a761cZ41F9bBH3JUlihCt2Udc=
cloud.google.com/go v0.98.0/go.mod h1:ua6Ush4NALrHk5QXDWnjvZHN93OuF0HfuEPq9I1X0cM=
cloud.google.com/go v0.99.0/go.mod h1:w0Xx2nLzqWJPuozYQX+hFfCSI8WioryfRDzkoI/Y2ZA=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/bigquery v1.3.0/go.mod h1:PjpwJnslEMmckchkHFfq+HTD2DmtT67aNFKH1/VBDHE=
@@ -34,7 +35,6 @@ cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4g
cloud.google.com/go/bigquery v1.8.0/go.mod h1:J5hqkt3O0uAFnINi6JXValWIb1v0goeZM77hZzJN/fQ=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
cloud.google.com/go/datastore v1.1.0/go.mod h1:umbIZjpQpHh4hmRpGhH4tLFup+FVzqBi1b3c64qFpCk=
cloud.google.com/go/firestore v1.1.0/go.mod h1:ulACoGHTpvq5r8rxGJ4ddJZBZqakUQqClKRT5SZwBmk=
cloud.google.com/go/firestore v1.6.1/go.mod h1:asNXNOzBdyVQmEU+ggO8UPodTkEVFW5Qx+rwHnAz+EY=
cloud.google.com/go/pubsub v1.0.1/go.mod h1:R0Gpsv3s54REJCy4fxDixWD93lHJMoZTyQ2kNxGRt3I=
cloud.google.com/go/pubsub v1.1.0/go.mod h1:EwwdRX2sKPjnvnqCa270oGRyludottCI76h+R3AArQw=
@@ -52,14 +52,14 @@ github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3
github.com/CloudyKit/jet/v6 v6.1.0/go.mod h1:d3ypHeIRNo2+XyqnGA8s+aphtcVpjP5hPwP/Lzo7Ro4=
github.com/DataDog/datadog-go v3.2.0+incompatible/go.mod h1:LButxg5PwREeZtORoXG3tL4fMGNddJ+vMq1mwgfaqoQ=
github.com/Joker/hpp v1.0.0/go.mod h1:8x5n+M1Hp5hC0g8okX3sR3vFQwynaX/UgSOM9MeBKzY=
github.com/Joker/jade v1.1.1/go.mod h1:C5O3w7HbsWdb9ik1puKS81QsllcBd+CXRVCbXFwSdsE=
github.com/Joker/jade v1.1.3/go.mod h1:T+2WLyt7VH6Lp0TRxQrUYEs64nRc83wkMQrfeIQKduM=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E=
github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY=
github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/circbuf v0.0.0-20150827004946-bbbad097214e/go.mod h1:3U/XgcO3hCbHZ8TKRvWD2dDTCfh9M9ya+I9JpbB7O8o=
github.com/armon/go-metrics v0.0.0-20180917152333-f0300d1749da/go.mod h1:Q73ZrmVTwzkszR9V5SSuryQ31EELlFMUz1kKyl939pY=
@@ -72,8 +72,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
github.com/bketelsen/crypt v0.0.4/go.mod h1:aI6NrJ0pMGgvZKL1iVgXLnfIFJtfV+bKCoqOes/6LfM=
github.com/cbroglie/mustache v1.3.0/go.mod h1:w58RIHjw/L7DPyRX2CcCTduNmcP1dvztaHP72ciSfh0=
github.com/cbroglie/mustache v1.3.1/go.mod h1:SS1FTIghy0sjse4DUVGV1k/40B1qE1XkD9DtDsHo9iM=
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/census-instrumentation/opencensus-proto v0.3.0/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc=
@@ -97,10 +96,9 @@ github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWH
github.com/cncf/xds/go v0.0.0-20211130200136-a8f946100490/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
github.com/cpuguy83/go-md2man/v2 v2.0.0/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
github.com/cpuguy83/go-md2man/v2 v2.0.1/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
@@ -120,8 +118,6 @@ github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5Kwzbycv
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU=
@@ -133,10 +129,14 @@ github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9
github.com/go-logfmt/logfmt v0.4.0/go.mod h1:3RMwSq7FuexP4Kalkev3ejPJsZTpXXBr9+V4qmtdjCk=
github.com/go-stack/stack v1.8.0/go.mod h1:v0f6uXyyMGvRgIKkXu+yp6POWl0qKG85gN/melR3HDY=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofiber/fiber/v2 v2.24.0 h1:18rpLoQMJBVlLtX/PwgHj3hIxPSeWfN1YeDJ2lEnzjU=
github.com/gofiber/fiber/v2 v2.24.0/go.mod h1:MR1usVH3JHYRyQwMe2eZXRSZHRX38fkV+A7CPB+DlDQ=
github.com/gofiber/template v1.6.21 h1:oIqrnpHnCWhbdBIme5AHBsM7c93H2vrb6Xyloj7UZoU=
github.com/gofiber/template v1.6.21/go.mod h1:1ORcy7sg3WW/YVeAyeGkcCtT63HjEj3+qxHNz+oZoFk=
github.com/gofiber/fiber/v2 v2.29.0 h1:wopU1kXxdD9XxvQqYd1vSWMGu2PiZN0yy+DojygTRRA=
github.com/gofiber/fiber/v2 v2.29.0/go.mod h1:1Ega6O199a3Y7yDGuM9FyXDPYQfv+7/y48wl6WCwUF4=
github.com/gofiber/fiber/v2 v2.32.0 h1:lpgcGEq1UENv27uVuOaufAhU8wUKnX8yb9L7559Neec=
github.com/gofiber/fiber/v2 v2.32.0/go.mod h1:CMy5ZLiXkn6qwthrl03YMyW1NLfj0rhxz2LKl4t7ZTY=
github.com/gofiber/template v1.6.25 h1:wAh92yCfP2XQvxBRK8VchbjAJnNz/y+p4uD94WBs1MI=
github.com/gofiber/template v1.6.25/go.mod h1:/hE+mSK1VTEK9YVX1ySE2ix12xOXdgi28nrsVaRq2u4=
github.com/gofiber/template v1.6.27 h1:gjQuNY3zgV1JtOezX0kIffOOlHHj7XWeFMntOVYYTrE=
github.com/gofiber/template v1.6.27/go.mod h1:R4tRVdtOAhuPpXKoVeJUM8wU6N8ewT3XXPSa5Bx8KJU=
github.com/gogo/protobuf v1.1.1/go.mod h1:r8qH/GZQm5c6nD/R0oafs1akxWv10x8SbQlK7atdtwQ=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
@@ -210,11 +210,8 @@ github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gax-go/v2 v2.1.0/go.mod h1:Q3nei7sK6ybPYH7twZdmQpAd1MKb7pfu6SK+H1/DsU0=
github.com/googleapis/gax-go/v2 v2.1.1/go.mod h1:hddJymUZASv3XPyGkUpKj8pPO47Rmb0eJc8R6ouapiM=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
github.com/hashicorp/consul/api v1.1.0/go.mod h1:VmuI/Lkw1nC05EYQWNKwWGbkg+FbDBtguAZLlVdkD9Q=
github.com/hashicorp/consul/api v1.12.0/go.mod h1:6pVBMo0ebnYdt2S3H87XhekM/HHrUoTD2XXb/VrZVy0=
github.com/hashicorp/consul/sdk v0.1.1/go.mod h1:VKf9jXwCTEY1QZP2MOLRhb5i/I/ssyNV1vwHyQBF0x8=
github.com/hashicorp/consul/api v1.11.0/go.mod h1:XjsvQN+RJGWI2TWy1/kqaE16HrR2J/FWgkYjdZQsX9M=
github.com/hashicorp/consul/sdk v0.8.0/go.mod h1:GBvyrGALthsZObzUGsfgHZQDXjg4lOjagTIwIR1vPms=
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
@@ -228,24 +225,21 @@ github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iP
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
github.com/hashicorp/go-multierror v1.1.0/go.mod h1:spPvp8C1qA32ftKqdAHm4hHTbPw+vmowP0z+KUhOZdA=
github.com/hashicorp/go-retryablehttp v0.5.3/go.mod h1:9B5zBasrRhHXnJnui7y6sL7es7NDiJgTc6Er0maI1Xs=
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
github.com/hashicorp/go-rootcerts v1.0.2/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdvsLplgctolz4=
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.1/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
github.com/hashicorp/logutils v1.0.0/go.mod h1:QIAnNjmIWmVIIkWDTG1z5v++HQmx9WQRO+LraFDTW64=
github.com/hashicorp/mdns v1.0.0/go.mod h1:tL+uN++7HEJ6SQLQ2/p+z2pH24WQKWjBPkE0mNTz8vQ=
github.com/hashicorp/mdns v1.0.1/go.mod h1:4gW7WsVCke5TE7EPeYliwHlRUyBtfCwuFwuMg2DmyNY=
github.com/hashicorp/mdns v1.0.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
github.com/hashicorp/memberlist v0.2.2/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/memberlist v0.3.0/go.mod h1:MS2lj3INKhZjWNqd3N0m3J+Jxf3DAOnAH9VT3Sh9MUE=
github.com/hashicorp/serf v0.8.2/go.mod h1:6hOLApaqBFA1NXqRQAsxw9QxuDEvNxSQRwA/JwenrHc=
github.com/hashicorp/serf v0.9.5/go.mod h1:UWDWwZeL5cuWDJdl0C6wrvrUwEqtQ4ZKBKKENpqIUyk=
github.com/hashicorp/serf v0.9.6/go.mod h1:TXZNMjZQijwlDvp+r0b63xZ45H7JmCmgg4gpTwn9UV4=
github.com/iancoleman/strcase v0.2.0/go.mod h1:iwCmte+B7n89clKwxIoIXy/HfoL7AsD47ZCWhYzw7ho=
github.com/ianlancetaylor/demangle v0.0.0-20181102032728-5e5cf60278f6/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
@@ -257,12 +251,13 @@ github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
github.com/julienschmidt/httprouter v1.2.0/go.mod h1:SYymIcj16QtmaHHD7aYtjjsJG7VTCxuUUipMqKk8s4w=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s=
github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg=
github.com/klauspost/compress v1.15.0 h1:xqfchp4whNFxn5A4XFyyYtitiWI8Hy5EW59jEwcyL6U=
github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/compress v1.15.1 h1:y9FcTHGyrebwfP0ZZqFiaxTaiDnUrGkJkI+f583BL1A=
github.com/klauspost/compress v1.15.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
github.com/kr/logfmt v0.0.0-20140226030751-b84e30acd515/go.mod h1:+0opPa2QZZtGFBFZlji/RkVcI2GknAs/DXo4wKdlNEc=
@@ -270,10 +265,8 @@ github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORN
github.com/kr/pretty v0.2.0/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/lyft/protoc-gen-star v0.5.3/go.mod h1:V0xaHgaf5oCCqmcxYcWiDfTiKsZsRc87/1qhoTACD8w=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
@@ -291,17 +284,11 @@ github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5
github.com/miekg/dns v1.0.14/go.mod h1:W1PPwlIAgtquWBMBEV9nkV9Cazfe8ScdGz/Lj7v3Nrg=
github.com/miekg/dns v1.1.26/go.mod h1:bPDLeHnStXmXAq1m/Ch/hvfNHr14JKNPMBo3VZKjuso=
github.com/miekg/dns v1.1.41/go.mod h1:p6aan82bvRIyn+zDIv9xYNUpwa73JcSh9BKwknJysuI=
github.com/mitchellh/cli v1.0.0/go.mod h1:hNIlj7HEI86fIcpObd7a0FcrxTWetlwJDGcceTlRvqc=
github.com/mitchellh/cli v1.1.0/go.mod h1:xcISNoH86gajksDmfB23e/pu+B+GeFRMYmoHXxx3xhI=
github.com/mitchellh/go-homedir v1.0.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/go-testing-interface v1.0.0/go.mod h1:kRemZodwjscx+RGhAo8eIhFbs2+BFgRtFPeD/KE+zxI=
github.com/mitchellh/gox v0.4.0/go.mod h1:Sd9lOJ0+aimLBi73mGofS1ycjY8lL3uZM3JPS42BGNg=
github.com/mitchellh/iochan v1.0.0/go.mod h1:JwYml1nuB7xOzsp52dPpHFffvOCDupsG0QubkSMEySY=
github.com/mitchellh/mapstructure v0.0.0-20160808181253-ca63d7c062ee/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/mapstructure v1.4.1/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/mitchellh/mapstructure v1.4.3 h1:OVowDSCllw/YjdLkam3/sm7wEtOy59d8ndGgCcyj8cs=
github.com/mitchellh/mapstructure v1.4.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
@@ -309,17 +296,15 @@ github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lN
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
github.com/mwitkow/go-conntrack v0.0.0-20161129095857-cc309e4a2223/go.mod h1:qRWi+5nqEBWmkhHvq77mSJWrCKwh8bxhgT7d/eI7P4U=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
github.com/pascaldekloe/goe v0.0.0-20180627143212-57f6aae5913c/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pascaldekloe/goe v0.1.0/go.mod h1:lzWF7FIEvWOWxwDKqyGYQf6ZUaNfKdP144TG7ZOy1lc=
github.com/pelletier/go-toml v1.9.3/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pelletier/go-toml v1.9.4 h1:tjENF6MfZAg8e4ZmZTeWaWiT2vXtsoO6+iuOjFhECwM=
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/pelletier/go-toml v1.9.4/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/sftp v1.10.1/go.mod h1:lYOWFsE0bwd1+KfKJaKeuokY15vzFx25BLbzYYoAxZI=
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/posener/complete v1.1.1/go.mod h1:em0nMJCgc9GFtwrmVmEMR/ZL6WyhyjMBndrE9hABlRI=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
@@ -337,30 +322,20 @@ github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsT
github.com/prometheus/procfs v0.0.8/go.mod h1:7Qr8sr6344vo1JqZ6HhLceV9o3AJ1Ff+GxbHq6oeK9A=
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
github.com/ryanuber/columnize v0.0.0-20160712163229-9b3edd62028f/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts=
github.com/sagikazarmark/crypt v0.4.0/go.mod h1:ALv2SRj7GxYV4HO9elxH9nS6M9gW+xDNxqmyJ6RfDFM=
github.com/sagikazarmark/crypt v0.3.0/go.mod h1:uD/D+6UF4SrIR1uGEv7bBNkNqLGqUr43MRiaGWX1Nig=
github.com/sean-/seed v0.0.0-20170313163322-e2103e2c3529/go.mod h1:DxrIzT+xaE7yg65j358z/aeFdxmN0P9QXhEzd20vsDc=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.3.3/go.mod h1:5KUK8ByomD5Ti5Artl0RtHeI5pTF7MIDuXL3yY520V4=
github.com/spf13/afero v1.6.0 h1:xoax2sJ2DT8S8xA2paPFjDCScCNeWsg75VG0DLRreiY=
github.com/spf13/afero v1.6.0/go.mod h1:Ai8FlHk4v/PARR026UzYexafAt9roJ7LcLMAmO6Z93I=
github.com/spf13/cast v1.3.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cast v1.4.1 h1:s0hze+J0196ZfEMTs80N7UlFt0BDuQ7Q+JDnHiMWKdA=
github.com/spf13/cast v1.4.1/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v1.2.1/go.mod h1:ExllRjgxM/piMAM+3tAZvg8fsklGAf3tPfi+i8t68Nk=
github.com/spf13/jwalterweatherman v1.1.0 h1:ue6voC5bR5F8YxI5S67j9i582FU4Qvo2bmqnqMYADFk=
github.com/spf13/cobra v1.3.0/go.mod h1:BrRVncBjOJa/eUcVVm9CE+oC6as8k+VYr4NY7WCi9V4=
github.com/spf13/jwalterweatherman v1.1.0/go.mod h1:aNWZUN0dPAAO/Ljvb5BEdw96iTZ0EXowPYD95IqWIGo=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
github.com/spf13/viper v1.8.1/go.mod h1:o0Pch8wJ9BVSWGQMbra6iw0oQ5oktSIBaujf1rJH9Ns=
github.com/spf13/viper v1.10.1 h1:nuJZuYpG7gTj/XqiUwg8bA0cp1+M2mC3J4g5luUYBKk=
github.com/spf13/viper v1.10.1/go.mod h1:IGlFPqhNAPKRxohIzWpI5QEy4kuI7tcl5WvR+8qy1rU=
github.com/spf13/viper v1.10.0/go.mod h1:SoyBPwAtKDzypXNDFKN5kzH7ppppbGZtls1UpIy5AsM=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
@@ -368,12 +343,12 @@ github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UV
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw=
github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.0 h1:6aeJ0bzojgWLa82gDQHcx3S0Lr/O51I9bJ5nv6JFx5w=
github.com/tidwall/gjson v1.14.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.1 h1:iymTbGkQBhveq21bEvAQ81I0LEBork8BFe1CUZXdyuo=
github.com/tidwall/gjson v1.14.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
@@ -381,8 +356,10 @@ github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhso
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM=
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/fasthttp v1.31.0 h1:lrauRLII19afgCs2fnWRJ4M5IkV0lo2FqA61uGkNBfE=
github.com/valyala/fasthttp v1.31.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus=
github.com/valyala/fasthttp v1.34.0 h1:d3AAQJ2DRcxJYHm7OXNXtXt2as1vMDfxeIcFvhmGGm4=
github.com/valyala/fasthttp v1.34.0/go.mod h1:epZA5N+7pY6ZaEKRmstzOuYJx9HI8DI1oaCGZpdH4h0=
github.com/valyala/fasthttp v1.35.0 h1:wwkR8mZn2NbigFsaw2Zj5r+xkmzjbrA/lyTmiSlal/Y=
github.com/valyala/fasthttp v1.35.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I=
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/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0=
@@ -391,11 +368,9 @@ github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9de
github.com/yuin/goldmark v1.1.32/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/etcd/api/v3 v3.5.0/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
github.com/yuin/goldmark v1.4.1/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
go.etcd.io/etcd/api/v3 v3.5.1/go.mod h1:cbVKeC6lCfl7j/8jBhAK6aIYO9XOjdptoxU/nLQcPvs=
go.etcd.io/etcd/client/pkg/v3 v3.5.0/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/pkg/v3 v3.5.1/go.mod h1:IJHfcCEKxYu1Os13ZdwCwIUTUVGYTSAM3YSwc9/Ac1g=
go.etcd.io/etcd/client/v2 v2.305.0/go.mod h1:h9puh54ZTgAKtEbut2oe9P4L/oqKCVB6xsXlzd7alYQ=
go.etcd.io/etcd/client/v2 v2.305.1/go.mod h1:pMEacxZW7o8pg4CrFE7pquyCJJzZvkvdD2RibOCCCGs=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
@@ -417,8 +392,8 @@ golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY=
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-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
@@ -455,11 +430,11 @@ golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.1/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/mod v0.5.1/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181023162649-9b4f9f5ad519/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181114220301-adae6a3d119a/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181201002055-351d144fa1fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
@@ -497,8 +472,10 @@ golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLd
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211015210444-4f30a5c0130f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
@@ -510,7 +487,6 @@ golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ
golang.org/x/oauth2 v0.0.0-20210218202405-ba52d332ba99/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210220000619-9bb904979d93/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210313182246-cd4f82c27b84/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210402161424-2e8d93401602/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
@@ -546,7 +522,6 @@ golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190922100055-0a153f010e69/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190924154521-2837fb4f24fe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191005200804-aed5e4c7ecf9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191008105621-543471e840be/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -592,10 +567,16 @@ golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211019181941-9d821ace8654/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 h1:5hpz5aRr+W1erYCL5JRhSUBJRph7l9XkNveoExlrKYk=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211205182925-97ca703d548d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9 h1:nhht2DYV/Sn3qOayu8lM+cU1ii9sTLUeBQwQQfUHtrs=
golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150 h1:xHms4gcpe1YE7A3yIllJXP16CMAGuqwO2lX1mTyyRRc=
golang.org/x/sys v0.0.0-20220422013727-9388b58f7150/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-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/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.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@@ -604,7 +585,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
@@ -615,7 +595,6 @@ golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312151545-0bb0c0a6e846/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
@@ -626,7 +605,6 @@ golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtn
golang.org/x/tools v0.0.0-20190907020128-2ca718005c18/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20190911174233-4f2ddba30aff/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191012152004-8de300cfc20a/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191112195655-aa38f8e97acc/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191113191852-77e3bb0ad9e7/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191115202509-3a792d9c32b2/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
@@ -640,7 +618,6 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20200204074204-1cc6d1ef6c74/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200207183749-b753a1ba74fa/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200212150539-ea181f53ac56/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200219054238-753a1d49df85/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200224181240-023911ca70b2/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200227222343-706bc42d1f0d/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200304193943-95d2e580d8eb/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
@@ -666,6 +643,7 @@ golang.org/x/tools v0.1.2/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.3/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.4/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.9/go.mod h1:nABZi5QlRsZVlzPpHl034qft6wpY4eDcsTt5AaioBiU=
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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
@@ -691,7 +669,6 @@ google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34q
google.golang.org/api v0.40.0/go.mod h1:fYKFpnQN0DsDSKRVRcQSDQNtqWPfM9i+zNPxepjRCQ8=
google.golang.org/api v0.41.0/go.mod h1:RkxM5lITDfTzmyKFPt+wGrCJbVfniCr2ool8kTBzRTU=
google.golang.org/api v0.43.0/go.mod h1:nQsDGjRXMo4lvh5hP0TKqF244gqhGcr/YSIykhUk/94=
google.golang.org/api v0.44.0/go.mod h1:EBOGZqzyhtvMDoxwS97ctnh0zUmYY6CxqXsc1AvkYD8=
google.golang.org/api v0.47.0/go.mod h1:Wbvgpq1HddcWVtzsVLyfLp8lDg6AA241LmgIL59tHXo=
google.golang.org/api v0.48.0/go.mod h1:71Pr1vy+TAZRPkPs/xlCf5SsU8WjuAWv1Pfjbtukyy4=
google.golang.org/api v0.50.0/go.mod h1:4bNT5pAuq5ji4SRZm+5QIkjny9JAyVD/3gaSihNefaw=
@@ -702,7 +679,7 @@ google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqiv
google.golang.org/api v0.57.0/go.mod h1:dVPlbZyBo2/OjBpmvNdpn2GRm6rPy75jyU7bmhdrMgI=
google.golang.org/api v0.59.0/go.mod h1:sT2boj7M9YJxZzgeZqXogmhfmRWDtPzT31xkieUbuZU=
google.golang.org/api v0.61.0/go.mod h1:xQRti5UdCmoCEqFxcz93fTl338AVqDgyaDRuOZ3hg9I=
google.golang.org/api v0.63.0/go.mod h1:gs4ij2ffTRXwuzzgJl/56BdwJaA194ijkfn++9tDuPo=
google.golang.org/api v0.62.0/go.mod h1:dKmwPCydfsad4qCH08MSdgWjfHOyfpd4VtDGgRFdavw=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/appengine v1.5.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@@ -769,6 +746,8 @@ google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ6
google.golang.org/genproto v0.0.0-20211008145708-270636b82663/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211028162531-8db9c33dc351/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211118181313-81c1377c94b1/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211129164237-f09f9a12af12/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211203200212-54befc351ae9/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211206160659-862468c7d6e0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/genproto v0.0.0-20211208223120-3a66f561d7aa/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
@@ -797,7 +776,7 @@ google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnD
google.golang.org/grpc v1.39.1/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
google.golang.org/grpc v1.40.0/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.40.1/go.mod h1:ogyxbiOoUXAkP+4+xa6PZSE9DZgIHtSpzjDTB9KAK34=
google.golang.org/grpc v1.43.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc v1.42.0/go.mod h1:k+4IHHFw41K8+bbowsex27ge2rCb65oeWqe4jJ590SU=
google.golang.org/grpc/cmd/protoc-gen-go-grpc v1.1.0/go.mod h1:6Kw0yEErY5E/yWrBtf03jp27GLLJujG4z/JK95pnjjw=
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
@@ -816,11 +795,8 @@ gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLks
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b h1:QRR6H1YWRnHb4Y/HeNFCTJLFVxaq6wH4YuVdsUOr75U=
gopkg.in/check.v1 v1.0.0-20200902074654-038fdea0a05b/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/ini.v1 v1.66.2 h1:XfR1dOYubytKy4Shzc2LHrrGhU0lDCfDGG1yLPmpgsI=
gopkg.in/ini.v1 v1.66.2/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@@ -831,7 +807,6 @@ gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

15
instances.json Normal file
View File

@@ -0,0 +1,15 @@
[
"i.bcow.xyz",
"rimgo.pussthecat.org",
"img.riverside.rocks",
"rimgo.totaldarkness.net",
"rimgo.bus-hit.me",
"rimgo.esmailelbob.xyz",
"rimgo.lunar.icu",
"i.actionsack.com",
"l4d4owboqr6xcmd6lf64gbegel62kbudu3x3jnldz2mx6mhn3bsv3zyd.onion",
"jx3dpcwedpzu2mh54obk5gvl64i2ln7pt5mrzd75s4jnndkqwzaim7ad.onion",
"rimgo.lqs5fjmajyp7rvp4qvyubwofzi6d4imua7vs237rkc4m5qogitqwrgyd.onion",
"be7udfhmnzqyt7cxysg6c4pbawarvaofjjywp35nhd5qamewdfxl6sid.onion",
"xazdnfgtzmcbcxhmcbbvr4uodd6jtn4fdiayasghywdn227xsmoa.b32.i2p"
]

38
main.go
View File

@@ -1,44 +1,30 @@
package main
import (
"fmt"
"net/http"
"codeberg.org/video-prize-ranch/rimgo/pages"
"codeberg.org/video-prize-ranch/rimgo/static"
"codeberg.org/video-prize-ranch/rimgo/utils"
"codeberg.org/video-prize-ranch/rimgo/views"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/filesystem"
"github.com/gofiber/fiber/v2/middleware/recover"
"github.com/gofiber/template/handlebars"
"github.com/spf13/viper"
)
func main() {
viper.SetConfigName("config")
viper.SetConfigType("yml")
viper.AddConfigPath("/etc/rimgu/")
viper.AddConfigPath("$HOME/.config/rimgu")
viper.AddConfigPath(".")
viper.AutomaticEnv()
viper.SetDefault("RIMGU_PORT", "3000")
viper.SetDefault("RIMGU_HOST", "localhost")
viper.SetDefault("RIMGU_ADDRESS", "0.0.0.0")
viper.SetDefault("RIMGU_IMGUR_CLIENT_ID", "546c25a59c58ad7")
err := viper.ReadInConfig()
if err != nil {
fmt.Println(err)
}
utils.LoadConfig()
engine := handlebars.NewFileSystem(http.FS(views.GetFiles()), ".hbs")
app := fiber.New(fiber.Config{
Views: engine,
Prefork: viper.GetBool("FIBER_PREFORK"),
Prefork: utils.Config["fiberPrefork"].(bool),
UnescapePath: true,
StreamRequestBody: true,
})
app.Use(recover.New())
app.Use("/static", filesystem.New(filesystem.Config{
Root: http.FS(static.GetFiles()),
}))
@@ -48,15 +34,23 @@ func main() {
_, err := c.Write(file)
return err
})
app.Get("/favicon.ico", func(c *fiber.Ctx) error {
file, _ := static.GetFiles().ReadFile("favicon/favicon.ico")
_, err := c.Write(file)
return err
})
app.Get("/", pages.FrontpageHandler)
app.Get("/", pages.HandleFrontpage)
app.Get("/:postID.gifv", pages.HandleEmbed)
app.Get("/:baseName.:extension", pages.HandleMedia)
app.Get("/:postID", pages.HandlePost)
app.Get("/a/:galleryID", pages.HandleGallery)
//app.Get("/t/:tagID", pages.HandleAlbum)
app.Get("/t/:tag", pages.HandleTag)
app.Get("/user/:userID", pages.HandleUser)
app.Get("/r/:sub/:postID", pages.HandlePost)
app.Get("/user/:userID/cover", pages.HandleUserCover)
app.Get("/user/:userID/avatar", pages.HandleUserAvatar)
app.Get("/gallery/:galleryID", pages.HandleGallery)
app.Listen(":" + viper.GetString("RIMGU_PORT"))
app.Listen(":" + utils.Config["port"].(string))
}

16
pages/embed.go Normal file
View File

@@ -0,0 +1,16 @@
package pages
import (
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/gofiber/fiber/v2"
)
func HandleEmbed(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("Cache-Control", "public,max-age=31557600")
c.Set("Content-Security-Policy", "default-src 'none'; media-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; block-all-mixed-content")
return c.Render("embed", fiber.Map{
"id": c.Params("postID"),
})
}

View File

@@ -5,10 +5,13 @@ import (
"github.com/gofiber/fiber/v2"
)
func FrontpageHandler(c *fiber.Ctx) error {
func HandleFrontpage(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("Cache-Control", "public,max-age=31557600")
c.Set("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self'; font-src 'self'; block-all-mixed-content")
c.Set("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self'; font-src 'self'; manifest-src 'self'; block-all-mixed-content")
return c.Render("frontpage", fiber.Map{})
return c.Render("frontpage", fiber.Map{
"proto": c.Protocol(),
"domain": c.Hostname(),
})
}

View File

@@ -9,7 +9,7 @@ import (
func HandleGallery(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("Content-Security-Policy", "default-src 'none'; media-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; block-all-mixed-content")
c.Set("Content-Security-Policy", "default-src 'none'; media-src 'self'; style-src 'unsafe-inline' 'self'; img-src 'self'; font-src 'self'; manifest-src 'self'; block-all-mixed-content")
album, err := api.FetchAlbum(c.Params("galleryID"))
if err != nil {
@@ -27,8 +27,8 @@ func HandleGallery(c *fiber.Ctx) error {
c.Set("Cache-Control", "public,max-age=31557600")
}
return c.Render("gallery", fiber.Map{
"album": album,
return c.Render("post", fiber.Map{
"post": album,
"comments": comments,
})
}

View File

@@ -1,14 +0,0 @@
export const handleTag = async (request: Hapi.Request, h: Hapi.ResponseToolkit) => {
// https://imgur.com/t/funny
if (!CONFIG.use_api) {
return 'Tag page disabled. Rimgu administrator needs to enable API for this to work.';
}
const tagID = request.params.tagID;
const result = await fetchTagPosts(tagID);
return h.view('posts', {
posts: result.items,
pageTitle: CONFIG.page_title,
tag: result,
util,
});
};

View File

@@ -25,7 +25,7 @@ func HandleUserAvatar(c *fiber.Ctx) error {
func handleMedia(c *fiber.Ctx, url string) error {
utils.SetHeaders(c)
c.Set("Content-Security-Policy", "default-src 'none'; media-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; block-all-mixed-content")
c.Set("Content-Security-Policy", "default-src 'none'; media-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; manifest-src 'self'; block-all-mixed-content")
res, err := http.Get(url)
if err != nil {

45
pages/post.go Normal file
View File

@@ -0,0 +1,45 @@
package pages
import (
"fmt"
"codeberg.org/video-prize-ranch/rimgo/api"
"codeberg.org/video-prize-ranch/rimgo/types"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/gofiber/fiber/v2"
)
func HandlePost(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("Content-Security-Policy", "default-src 'none'; media-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; manifest-src 'self'; block-all-mixed-content")
post, err := api.FetchPosts(c.Params("postID"))
if post.Id == "" {
post, err = api.FetchPosts(c.Params("postID"))
if post.Id == "" {
post, err = api.FetchMedia(c.Params("postID"))
if post.Id == "" {
return fmt.Errorf("404 page not found")
}
}
}
if err != nil {
return err
}
comments := []types.Comment{}
if post.SharedWithCommunity {
c.Set("Cache-Control", "public,max-age=604800")
comments, err = api.FetchComments(c.Params("postID"))
if err != nil {
return err
}
} else {
c.Set("Cache-Control", "public,max-age=31557600")
}
return c.Render("post", fiber.Map{
"post": post,
"comments": comments,
})
}

43
pages/tag.go Normal file
View File

@@ -0,0 +1,43 @@
package pages
import (
"strconv"
"codeberg.org/video-prize-ranch/rimgo/api"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/gofiber/fiber/v2"
)
func HandleTag(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("Cache-Control", "public,max-age=604800")
c.Set("Content-Security-Policy", "default-src 'none'; style-src 'unsafe-inline' 'self'; img-src 'self'; font-src 'self'; 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 = 0
}
displayPrevPage := true
if page == "1" {
displayPrevPage = false
}
tag, err := api.FetchTag(c.Params("tag"), c.Query("sort"), page)
if err != nil {
return err
}
return c.Render("tag", fiber.Map{
"tag": tag,
"page": page,
"displayPrev": displayPrevPage,
"nextPage": pageNumber + 1,
"prevPage": pageNumber - 1,
})
}

View File

@@ -1,6 +1,7 @@
package pages
import (
"strconv"
"sync"
"codeberg.org/video-prize-ranch/rimgo/api"
@@ -12,7 +13,17 @@ import (
func HandleUser(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("Cache-Control", "public,max-age=604800")
c.Set("Content-Security-Policy", "default-src 'none'; media-src 'self'; style-src 'unsafe-inline' 'self'; img-src 'self'; font-src 'self'; block-all-mixed-content")
c.Set("Content-Security-Policy", "default-src 'none'; media-src 'self'; style-src 'unsafe-inline' 'self'; img-src 'self'; font-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
}
wg := sync.WaitGroup{}
wg.Add(2)
@@ -28,7 +39,7 @@ func HandleUser(c *fiber.Ctx) error {
submissions, err := []types.Submission{}, error(nil)
go func() {
defer wg.Done()
submissions, err = api.FetchSubmissions(c.Params("userID"), "newest", "0")
submissions, err = api.FetchSubmissions(c.Params("userID"), "newest", page)
}()
if err != nil {
return err
@@ -38,5 +49,8 @@ func HandleUser(c *fiber.Ctx) error {
return c.Render("user", fiber.Map{
"user": user,
"submissions": submissions,
"page": page,
"nextPage": pageNumber + 1,
"prevPage": pageNumber - 1,
})
}

View File

@@ -1,11 +0,0 @@
export default {
port: process.env.RIMGU_PORT || 8080,
host: process.env.RIMGU_HOST || 'localhost',
address: process.env.RIMGU_ADDRESS || '127.0.0.1',
http_proxy: process.env.RIMGU_HTTP_PROXY || null,
https_proxy: process.env.RIMGU_HTTPS_PROXY || null,
imgur_client_id: process.env.RIMGU_IMGUR_CLIENT_ID || null,
use_api: process.env.RIMGU_USE_API && process.env.RIMGU_USE_API !== 'false',
page_title: process.env.RIMGU_PAGE_TITLE || 'rimgu',
debug: process.env.RIMGU_DEBUG && process.env.RIMGU_DEBUG !== 'false',
};

143
src/types/index.d.ts vendored
View File

@@ -1,143 +0,0 @@
interface Account {
id: number;
username: string;
avatar_url: string;
created_at: string;
}
type MediaMimeType = 'image/jpeg' | 'image/png' | 'image/gif';
type MediaType = 'image';
type MediaExt = 'jpeg' | 'png' | 'gif';
type Sorting = 'newest' | 'oldest' | 'best' | 'viral';
interface Tag {
tag: string;
display: string;
background_id: string;
accent: string;
is_promoted: boolean;
}
interface Media {
id: string;
account_id: number;
mime_type: MediaMimeType;
type: MediaType;
name: string;
basename: string;
url: string;
ext: MediaExt;
width: number;
height: number;
size: number;
metadata: {
title: string;
description: string;
is_animated: boolean;
is_looping: boolean;
duration: number;
has_sound: boolean;
},
created_at: string;
updated_at: string | null;
}
type MediaPlatform = 'ios' | 'android' | 'api' | 'web';
interface Comment {
id: number;
parent_id: number;
comment: string;
account_id: number;
post_id: string;
upvote_count: number;
downvote_count: number;
point_count: number;
vote: null; // ?
platform_id: number;
platform: MediaPlatform;
created_at: string;
updated_at: string;
deleted_at: null;
next: null; //?
comments: Comment[];
account: {
id: number;
username: string;
avatar: string;
}
}
interface Gallery {
id: string;
title: string;
account: Account;
media: Media[];
tags: Tag[];
cover: Media;
}
interface PostTag {
name: string;
display_name: string;
followers: number;
total_items: number;
following: boolean;
is_whitelisted: boolean;
background_hash: string;
thumbnail_hash: string;
accent: string;
background_is_animated: boolean;
thumbnail_is_animated: boolean;
is_promoted: boolean;
description: string;
logo_hash: string;
logo_destination_url: string;
description_annotations: {}
}
interface Post {
id: string;
account_id: number;
type: MediaMimeType;
animated: boolean;
width: number;
height: number;
size: number;
views: number;
bandwidth: number;
vote: null;
favorite: boolean;
nsfw: boolean;
section: string;
account_url: string;
is_ad: boolean;
in_most_viral: boolean;
has_sound: boolean;
tags: PostTag[];
link: string;
comment_count: number;
ups: number;
downs: number;
score: number;
points: number;
is_album: boolean;
}
interface TagResult extends PostTag {
items: Post[];
success: boolean;
status: number;
}
interface UserResult {
id: number;
username: string;
bio: string;
reputation_count: number;
reputation_name: string;
avatar_id: string;
avatar_url: string;
cover_id: string;
cover_url: string;
created_at: string;
}

View File

@@ -1,11 +0,0 @@
export const proxyURL = (url: string): string =>
url.replace(/^https?:\/\/[^.]*\.imgur.com\//, '/');
export const linkify = (content: string) =>
content.replace(
/https?:\/\/[^.]*\.imgur.com\/([\/_a-zA-Z0-9-]+)\.(gifv|mp4)/g,
'<video src="/$1.mp4" class="commentVideo commentObject" loop="" autoplay="" controls=""></video>'
).replace(
/https?:\/\/[^.]*\.imgur.com\/([\/_a-zA-Z0-9-]+\.[a-z0-9A-Z]{2,6})/g,
'<a href="/$1" target="_blank"><img class="commentImage commentObject" src="/$1" loading="lazy" /></a>'
);

View File

@@ -28,5 +28,32 @@ img {
}
.imageMeta__wrapper {
gap: 2rem;
gap: 1rem;
}
.user {
display: flex;
flex-direction: row;
align-items: center;
gap: 5px;
}
.tags {
display: flex;
gap: 10px;
flex-flow: wrap;
}
.tag {
border-radius: 10px;
padding: 7px;
background-color: rgba(0, 0, 0, 0.15);
background-blend-mode: multiply;
min-width: 110px;
}
.tag__display {
font-weight: 700;
color: #fff;
text-align: center;
}

View File

@@ -8,6 +8,10 @@ a > h2 {
color: white;
}
h2, p {
margin: 0;
}
body {
background-color: #212121;
color: white;
@@ -33,6 +37,49 @@ main {
margin: 0 24vw;
}
.posts {
margin-top: 1em;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-auto-rows: 1fr;
gap: 1rem;
}
.post {
border-radius: 12px;
background-color: #3b3b3b;
font-weight: 400;
}
.posts img,
.posts video:not(:fullscreen) {
object-fit: cover;
aspect-ratio: 1;
}
.post__title {
margin: 0 6px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.post__meta {
padding: 6px;
display: flex;
gap: 10px;
}
.post__meta .material-icons-outlined {
font-size: 1rem;
}
.pageSelector {
display: flex;
justify-content: space-between;
margin-top: 1em;
}
footer {
display: flex;
justify-content: center;
@@ -42,7 +89,7 @@ footer {
@media only screen and (max-width: 812px) {
main {
margin: 0;
margin: 0 !important;
}
footer {
flex-direction: column;

13
static/css/embed.css Normal file
View File

@@ -0,0 +1,13 @@
.logo {
filter: invert(180deg), hue-rotate(180deg);
}
.postLink {
display: flex;
flex-direction: row;
align-items: center;
}
.rimgoLink {
width: 100%;
}

View File

@@ -3,4 +3,9 @@ code {
padding: 2px;
border-radius: 4px;
font-size: 0.9em;
}
summary {
cursor: pointer;
user-select: none;
}

28
static/css/tag.css Normal file
View File

@@ -0,0 +1,28 @@
main {
margin: 0 12vw;
}
.tagMeta {
padding: 2em;
border-radius: 12px;
}
.tagMeta__info {
display: flex;
flex-direction: column;
gap: 10px;
text-align: center;
justify-content: center;
align-items: center;
}
.tagMeta__sort {
display: flex;
flex-direction: column;
gap: 4px;
}
.tagMeta__sort a {
font-weight: 400;
color: #fff;
}

View File

@@ -2,12 +2,8 @@ main {
margin: 0 12vw;
}
h2, p {
margin: 0;
}
.userMeta {
padding: 2vw;
padding: 2em;
border-radius: 12px;
}
@@ -23,41 +19,4 @@ h2, p {
.pfp {
border-radius: 100%;
}
.posts {
margin-top: 1em;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-auto-rows: 1fr;
gap: 1rem;
}
.post {
border-radius: 12px;
background-color: #3b3b3b;
font-weight: 400;
}
img,
video:not(:fullscreen) {
object-fit: cover;
aspect-ratio: 1;
}
.post__title {
margin: 0 6px;
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}
.post__meta {
padding: 6px;
display: flex;
gap: 10px;
}
.post__meta .material-icons-outlined {
font-size: 1rem;
}

View File

@@ -1,6 +1,6 @@
{
"name": "",
"short_name": "",
"name": "rimgo",
"short_name": "rimgo",
"icons": [
{
"src": "/static/favicon/android-chrome-192x192.png",

View File

@@ -10,5 +10,7 @@ type Album struct {
CreatedAt string
UpdatedAt string
Comments int64
User User
Media []Media
Tags []Tag
}

14
types/Submission.go Normal file
View File

@@ -0,0 +1,14 @@
package types
type Submission struct {
Id string
Title string
Link string
Cover Media
Points int64
Upvotes int64
Downvotes int64
Comments int64
Views int64
IsAlbum bool
}

10
types/Tag.go Normal file
View File

@@ -0,0 +1,10 @@
package types
type Tag struct {
Tag string
Display string
Sort string
PostCount int64
Posts []Submission
Background string
}

View File

@@ -1,24 +1,11 @@
package types
type User struct {
Id int64 `json:"id"`
Bio string `json:"bio"`
Username string `json:"username"`
Points int64 `json:"reputation_count"`
Cover string `json:"cover_url"`
Avatar string `json:"avatar_url"`
CreatedAt string `json:"created_at"`
}
type Submission struct {
Id string
Title string
Link string
Cover Media
Id int64
Bio string
Username string
Points int64
Upvotes int64
Downvotes int64
Comments int64
Views int64
IsAlbum bool
}
Cover string
Avatar string
CreatedAt string
}

43
utils/config.go Normal file
View File

@@ -0,0 +1,43 @@
package utils
import "os"
var Config map[string]interface{}
func LoadConfig() {
port := "3000"
if os.Getenv("PORT") != "" {
port = os.Getenv("PORT")
}
if os.Getenv("RIMGU_PORT") != "" {
port = os.Getenv("RIMGU_PORT")
}
fiberPrefork := false
if os.Getenv("FIBER_PREFORK") == "true" {
fiberPrefork = true
}
addr := "0.0.0.0"
if os.Getenv("ADDRESS") != "" {
addr = os.Getenv("ADDRESS")
}
if os.Getenv("RIMGU_ADDRESS") != "" {
addr = os.Getenv("RIMGU_ADDRESS")
}
imgurId := "546c25a59c58ad7"
if os.Getenv("IMGUR_CLIENT_ID") != "" {
imgurId = os.Getenv("IMGUR_CLIENT_ID")
}
if os.Getenv("RIMGU_IMGUR_CLIENT_ID") != "" {
imgurId = os.Getenv("RIMGU_IMGUR_CLIENT_ID")
}
Config = map[string]interface{}{
"port": port,
"addr": addr,
"imgurId": imgurId,
"fiberPrefork": fiberPrefork,
}
}

View File

@@ -8,5 +8,5 @@ func SetHeaders(c *fiber.Ctx) {
c.Set("X-Content-Type-Options", "nosniff")
c.Set("X-Robots-Tag", "noindex, noimageindex, nofollow")
c.Set("Strict-Transport-Security", "max-age=31557600")
c.Set("Permissions-Policy", "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(), geolocation=(), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()")
c.Set("Permissions-Policy", "accelerometer=(), ambient-light-sensor=(), autoplay=(), battery=(), camera=(), cross-origin-isolated=(), display-capture=(), document-domain=(), encrypted-media=(), execution-while-not-rendered=(), execution-while-out-of-viewport=(), fullscreen=(self), geolocation=(), gyroscope=(), interest-cohort=(), magnetometer=(), microphone=(), midi=(), navigation-override=(), payment=(), picture-in-picture=(), publickey-credentials-get=(), screen-wake-lock=(), sync-xhr=(), usb=(), web-share=(), xr-spatial-tracking=()")
}

26
views/embed.hbs Normal file
View File

@@ -0,0 +1,26 @@
<!DOCTYPE html>
<html lang="en">
<head>
{{> partials/head }}
<link rel="stylesheet" href="/static/css/embed.css" />
</head>
<body>
<video loop poster="/{{id}}.webp" autoplay width="100%">
<source src="/{{id}}.webm" type="video/webm" />
<source src="/{{id}}.mp4" type="video/mp4" />
</video>
<div class="postLink">
<a href="/{{id}}">
<img src="/static/img/rimgo.svg" width="32px" height="32px" class="logo">
</a>
<a href="/{{id}}" class="rimgoLink">
rimgo
</a>
<a href="/{{id}}.mp4?download=1">download</a>
</div>
</body>
</html>

View File

@@ -3,9 +3,9 @@
<head>
<title>rimgo</title>
{{> partials/head }}
<link rel="stylesheet" href="/static/css/frontpage.css" />
</head>
@@ -14,9 +14,11 @@
{{> partials/header }}
<main>
<p>An alternative frontend for Imgur. Based on <a href="https://codeberg.org/3np/rimgu">rimgu</a> and rewritten in Go.</p>
<p>An alternative frontend for Imgur. Based on <a href="https://codeberg.org/3np/rimgu">rimgu</a> and rewritten in
Go.</p>
<p>It's read-only and works without JavaScript. Images and albums can be viewed without wasting resources from downloading and running tracking scripts. No sign-up nags.</p>
<p>It's read-only and works without JavaScript. Images and albums can be viewed without wasting resources from
downloading and running tracking scripts. No sign-up nags.</p>
<h3>Try it!</h3>
@@ -38,19 +40,23 @@
</ul>
<h2>Usage</h2>
<p>Just replace imgur.com with the domain of this instance! You can setup automatic redirects using <a href="https://github.com/einaregilsson/Redirector">Redirector</a>.</p>
<h3>Redirector configuration</h3>
<ul>
<li>Description: Imgur -> rimgo</li>
<li>Example URL: https://imgur.com/a/H8M4rcp</li>
<li>Include pattern: <code>^https?://(i|).?imgur.com(/.*)?$</code></li>
<li>Redirect to: <code>https://[INSTANCE DOMAIN]$2</code></li>
<li>Pattern type: Regular Expression</li>
</ul>
<p>Just replace imgur.com or i.imgur.com with <code>{{domain}}</code>! You can setup automatic redirects using <a
href="https://github.com/libredirect/libredirect">LibRedirect</a> (recommended) or <a href="https://github.com/einaregilsson/Redirector">Redirector</a>.</p>
<br>
<details>
<summary>
Redirector configuration
</summary>
<ul>
<li>Description: Imgur -> rimgo</li>
<li>Example URL: https://imgur.com/a/H8M4rcp</li>
<li>Include pattern: <code>^https?://i?.?imgur.com(/.*)?$</code></li>
<li>Redirect to: <code>{{proto}}://{{domain}}$2</code></li>
<li>Pattern type: Regular Expression</li>
</ul>
</details>
</main>
{{> partials/footer }}

View File

@@ -1,7 +1,7 @@
<a href="{{Link}}">
<div class="post">
{{#equal Cover.Type "video"}}
<video fullscreen controls loop poster="/{{Cover.Id}}.webp" preload="none" width="100%" height="100%">
<video controls loop poster="/{{Cover.Id}}.webp" preload="none" width="100%" height="100%">
<source src="{{Cover.Url}}" type="video/mp4" />
</video>
{{/equal}}

View File

@@ -2,7 +2,12 @@
<html lang="en">
<head>
<title>{{album.Title}} - rimgo</title>
<title>
{{#if post.Title}}
{{post.Title}} -
{{/if}}
rimgo
</title>
{{> partials/head }}
@@ -16,43 +21,41 @@
{{> partials/header }}
<main>
<h1>{{album.Title}}</h1>
<h1>{{post.Title}}</h1>
<p>{{album.CreatedAt}}</p>
<p>{{post.CreatedAt}}</p>
<div class="imageMeta__wrapper">
{{#if post.User.Username}}
<div class="user">
<a href="/user/{{post.User.Username}}">
<img src="{{post.User.Avatar}}" class="pfp" width="36" height="36" loading="lazy" />
</a>
<a href="/user/{{post.User.Username}}">
<p>
<b>{{post.User.Username}}</b>
</p>
</a>
</div>
{{/if}}
<div class="imageMeta">
<div class="imageMeta__item">
<span class="material-icons-outlined" title="Views">visibility</span>
<p>{{album.Views}}</p>
<p>{{post.Views}}</p>
</div>
{{#if album.SharedWithCommunity}}
<p><span class="material-icons-outlined" title="Likes">thumb_up</span> {{album.Upvotes}}</p>
<p><span class="material-icons-outlined" title="Dislilkes">thumb_down</span> {{album.Downvotes}}</p>
{{#if post.SharedWithCommunity}}
<p><span class="material-icons-outlined" title="Likes">thumb_up</span> {{post.Upvotes}}</p>
<p><span class="material-icons-outlined" title="Dislilkes">thumb_down</span> {{post.Downvotes}}</p>
{{/if}}
</div>
<!--<div class="videoDesc__channel">
<a href="{{claim.Channel.RelUrl}}">
{{#if claim.Channel.Thumbnail}}
<img src="{{claim.Channel.Thumbnail}}&w=56&h=56" class="pfp" width="56" height="56" loading="lazy" />
{{/if}}
</a>
<a href="{{claim.Channel.RelUrl}}">
<p>
<b>{{claim.Channel.Title}}</b>
</p>
</a>
</div>-->
</div>
<br>
{{#each album.Media}}
{{#each post.Media}}
{{#if this.Title}}
<h3>{{this.Title}}</h3>
<h4>{{this.Title}}</h4>
{{/if}}
{{#if this.Description}}
<p>{{this.Description}}</p><br>
<p>{{this.Description}}</p>
{{/if}}
<div class="center">
@@ -69,12 +72,24 @@
<br>
{{/each}}
{{#if post.tags}}
<div class="tags">
{{#each post.tags}}
<a href="/t/{{this.Tag}}">
<div class="tag" style="background-image: url('{{this.Background}}');">
<p class="tag__display">{{this.Display}}</p>
</div>
</a>
{{/each}}
</div>
{{/if}}
{{#if comments}}
<div>
<hr>
<input id="comments__expandBtn" type="checkbox">
<label class="comments__expandBtn__label" for="comments__expandBtn">
<h3>Comments ({{album.Comments}})</h3>
<h3>Comments ({{post.Comments}})</h3>
<span class="comments__expandBtn__icon material-icons-outlined"></span>
</label>
<div class="comments">

59
views/tag.hbs Normal file
View File

@@ -0,0 +1,59 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{tag.Display}} - rimgo</title>
{{> partials/head }}
<link rel="stylesheet" href="/static/fonts/Material-Icons-Outlined.css" />
<link rel="stylesheet" href="/static/css/base.css" />
<link rel="stylesheet" href="/static/css/tag.css" />
</head>
<body>
{{> partials/header }}
<main>
<div class="tagMeta" style="background-image: url('{{tag.Background}}');">
<div class="tagMeta__info">
<h2>{{tag.Display}}</h2>
<p>{{tag.PostCount}} posts</p>
</div>
<div class="tagMeta__sort">
{{#equal tag.Sort "popular"}}
<a href="?sort=popular"><b>Popular</b></a>
<a href="?sort=newest">Newest</a>
<a href="?sort=best">Best</a>
{{/equal}}
{{#equal tag.Sort "newest"}}
<a href="?sort=popular">Popular</a>
<a href="?sort=newest"><b>Newest</b></a>
<a href="?sort=best">Best</a>
{{/equal}}
{{#equal tag.Sort "best"}}
<a href="?sort=popular">Popular</a>
<a href="?sort=newest">Newest</a>
<a href="?sort=best"><b>Best</b></a>
{{/equal}}
</div>
</div>
<div class="posts">
{{#each tag.Posts}}
{{> partials/post }}
{{/each}}
</div>
<div class="pageSelector">
{{#if displayPrev}}
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>
{{/if}}
<a href="{{channel.RelUrl}}?page={{nextPage}}">Next page</a>
</div>
</main>
{{> partials/footer }}
</body>
</html>

View File

@@ -31,6 +31,14 @@
{{> partials/post }}
{{/each}}
</div>
<div class="pageSelector">
{{#equal page "0" }}
{{else}}
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>
{{/equal}}
<a href="{{channel.RelUrl}}?page={{nextPage}}">Next page</a>
</div>
</main>
{{> partials/footer }}