312 Commits
lambda ... main

Author SHA1 Message Date
video-prize-ranch
23b66cba47 Use full instance url for cache key (#243)
Closes #240

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/243
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2026-01-14 18:27:25 +01:00
video-prize-ranch
eabb7d9917 Allow using 1 or true for all boolean config options (#242)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/242
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2026-01-12 01:52:26 +01:00
video-prize-ranch
3b8ad3f360 Force WebP improvements (#237)
- Allow using `true` or `1` in configuration
- Set Content-Disposition header to use correct file extension when using "Save image as"
- Only rewrite requests from img elements using Sec-Fetch-Dest header

#200
#201

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/237
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2026-01-12 01:46:53 +01:00
orangix
e8ed026962 add protocol to cache key (#241)
fixes #240

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/241
Reviewed-by: video-prize-ranch <video-prize-ranch@noreply.codeberg.org>
Co-authored-by: orangix <uleo8b8g@anonaddy.me>
Co-committed-by: orangix <uleo8b8g@anonaddy.me>
2026-01-12 01:45:24 +01:00
orangix
107a45e58b Merge pull request 'implement x-forwarded-proto' (#239) from x-forwarded-for into main
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/239
Reviewed-by: video-prize-ranch <video-prize-ranch@noreply.codeberg.org>
2026-01-06 04:55:44 +01:00
video-prize-ranch
751616d967 Update Go modules (#238)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/238
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2026-01-06 01:31:06 +01:00
orangix
09222a116f implement x-forwarded-proto 2026-01-05 08:18:55 +01:00
orangix
42174c052d Merge pull request 'Update README' (#231) from A_Cat/rimgo:pr-readme into main
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/231
Reviewed-by: orangix <orangix@noreply.codeberg.org>
2025-10-29 03:54:02 +01:00
A_Cat
c22365100d Update README 2025-10-25 07:01:16 +02:00
video-prize-ranch
26edb6a385 Fix docker files and update tailwind (#216)
- Update tailwind to 4.1.5
- Remove `version` in docker-compose.yml
- Fix CSS build in dockerfile

closes #202

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/216
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2025-05-02 18:33:26 +00:00
video-prize-ranch
dc57521bfa Merge pull request 'Fix goreleaser config' (#199) from fix/goreleaser into main
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/199
2025-03-28 15:15:49 +00:00
video-prize-ranch
44ce694b5b Fix goreleaser config 2025-03-28 11:15:02 -04:00
video-prize-ranch
2cef3880c7 Merge pull request 'Fix package.json scripts' (#198) from fix/tailwind4-3 into main
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/198
2025-03-28 14:59:42 +00:00
video-prize-ranch
061f9b0ebe Fix package.json scripts 2025-03-28 10:59:13 -04:00
video-prize-ranch
7811070f6d Merge pull request 'More fixes for tailwind 4' (#197) from fix/tailwind4-2 into main
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/197
2025-03-28 14:41:01 +00:00
video-prize-ranch
248782a236 More fixes for tailwind 4 2025-03-28 10:40:22 -04:00
video-prize-ranch
1a0016cec3 Merge pull request 'Fixes for Tailwind 4' (#196) from fix/tailwind4 into main
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/196
2025-03-28 14:22:38 +00:00
video-prize-ranch
af919226ed Fixes for tailwind 4 2025-03-28 10:20:32 -04:00
video-prize-ranch
3d2b0eeb2a Merge pull request 'Fix Docker build failure with Tailwind CSS v4' (#195) from nyuuzyou/rimgo:main into main
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/195
2025-03-28 14:05:37 +00:00
nyuuzyou
2cb5bcebf3 Fix Docker build failure with Tailwind CSS v4
This PR fixes the Docker build failure caused by incompatibility with the new CLI command structure of Tailwind CSS v4. Previously, the build failed with the error: `npm error could not determine executable to run.`

https://github.com/tailwindlabs/tailwindcss/discussions/15820
2025-03-27 21:04:13 +00:00
video-prize-ranch
4e3022ce1a Add RSS feeds (#194)
Closes #179

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/194
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2025-02-24 02:48:56 +00:00
video-prize-ranch
65e4a5f08e Update dependencies (#193)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/193
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2025-01-27 02:39:00 +00:00
video-prize-ranch
0f1fbc2401 Update air git repo (#186)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/186
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2024-07-03 13:02:39 +00:00
video-prize-ranch
4afb7cefe7 Add support for new gallery link format (#185)
Fixes #183

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/185
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2024-07-03 12:56:13 +00:00
video-prize-ranch
20715f53af Fix "Internal Server Error" (#182)
Fixes #181

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/182
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2024-06-21 02:14:31 +00:00
video-prize-ranch
ac9582df0a Update dependencies (#180)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/180
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2024-06-21 00:16:32 +00:00
video-prize-ranch
0ce85ed2bd Update go modules (#174)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/174
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2024-02-07 01:16:59 +00:00
orangix
09a76779c9 check page length before return in nextInTag (#173)
fixes #172

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/173
Co-authored-by: orangix <uleo8b8g@anonaddy.me>
Co-committed-by: orangix <uleo8b8g@anonaddy.me>
2024-02-07 01:13:29 +00:00
video-prize-ranch
337796b9be Update Justfile (#170)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/170
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2024-02-05 22:57:33 +00:00
orangix
927ea20fad next button for tagged posts (#169)
No previous button because that would be annoying to implement serverside with pagination etc.

Closes #115

Fixed conflict with #154, #155, #156

Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/169
Reviewed-by: video-prize-ranch <video-prize-ranch@noreply.codeberg.org>
Co-authored-by: orangix <orangix@noreply.codeberg.org>
Co-committed-by: orangix <orangix@noreply.codeberg.org>
2024-02-05 22:47:04 +00:00
orangix
7433265991 Merge pull request 'Errors in image format' (#168) from feature/image-errors into main
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/168
Reviewed-by: orangix <orangix@noreply.codeberg.org>
2024-02-05 21:28:29 +00:00
video-prize-ranch
fb82afc7dd Only show image errors on image direct links 2024-02-05 16:26:54 -05:00
video-prize-ranch
1579e59dca Errors in image format (closes #165) 2024-02-04 21:24:55 -05:00
video-prize-ranch
6d528c7d0a Add start_url to manifest (#161)
Fixes #160

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/161
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2024-01-17 22:11:22 +00:00
video-prize-ranch
9a6173a662 Update dependencies (#162)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/162
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2024-01-17 22:11:01 +00:00
video-prize-ranch
c366f95f6b Replace io/ioutil with io (#159)
io/ioutil is deprecated

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/159
2023-12-11 03:50:36 +00:00
video-prize-ranch
f5e1669a61 Handle error on app.Listen (closes #157) (#158)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/158
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2023-12-11 03:49:58 +00:00
orangix
dd78541a46 Revert "Create images for video-prize-ranch/rimgo image (#154)" (#156)
This reverts commit 13a72701e1.

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/156
Reviewed-by: video-prize-ranch <video-prize-ranch@noreply.codeberg.org>
Co-authored-by: orangix <uleo8b8g@anonaddy.me>
Co-committed-by: orangix <uleo8b8g@anonaddy.me>
2023-11-16 23:52:49 +00:00
video-prize-ranch
29203a1a78 Fix GoReleaser (#155)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/155
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2023-11-16 23:33:00 +00:00
video-prize-ranch
13a72701e1 Create images for video-prize-ranch/rimgo image (#154)
Most instances seem to not have moved to the new image yet

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/154
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2023-11-16 23:27:25 +00:00
video-prize-ranch
252b557450 Update dependencies (#153)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/153
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2023-11-16 23:20:41 +00:00
video-prize-ranch
f46ef8b029 Update instances.json 2023-10-28 15:22:15 -04:00
HexagonCDN
1376b5da9d Add affiliation notice (#152)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/152
Reviewed-by: video-prize-ranch <video-prize-ranch@noreply.codeberg.org>
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: HexagonCDN <hexagoncdn@noreply.codeberg.org>
Co-committed-by: HexagonCDN <hexagoncdn@noreply.codeberg.org>
2023-10-26 01:00:50 +00:00
video-prize-ranch
157407c013 Break words when needed (#150)
Closes #149

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/150
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2023-10-17 22:25:47 +00:00
video-prize-ranch
8fe3f73568 Update README (#148)
Closes #119

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/148
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2023-10-07 20:17:46 +00:00
video-prize-ranch
5cce60c3ad Legal clarity (#147)
Closes #56

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/147
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2023-10-07 19:33:03 +00:00
video-prize-ranch
1ec92f4809 Merge branch 'move-instances' 2023-09-23 19:24:03 -04:00
video-prize-ranch
7a0c008bba Move instances 2023-09-23 19:19:17 -04:00
lostskunk_Donetsk
d354d6314a New instance (#136)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/136
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: lostskunk_Donetsk <lostskunk_donetsk@noreply.codeberg.org>
Co-committed-by: lostskunk_Donetsk <lostskunk_donetsk@noreply.codeberg.org>
2023-09-17 01:20:00 +00:00
video-prize-ranch
121ad6b157 Add rimgo.quantenzitrone.eu (#137) (#139)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/139
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2023-09-16 14:36:35 +00:00
video-prize-ranch
fc88bfbca5 Cleanup previous/next page buttons (#134)
Use noteq to simplify code, add current page to previous/next page bar

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/134
Reviewed-by: orangix <orangix@noreply.codeberg.org>
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2023-08-30 17:24:54 +00:00
orangix
0fea1e46a3 Add user favorites (#133)
Closes #10

Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/133
Reviewed-by: video-prize-ranch <video-prize-ranch@noreply.codeberg.org>
Co-authored-by: orangix <uleo8b8g@anonaddy.me>
Co-committed-by: orangix <uleo8b8g@anonaddy.me>
2023-08-29 22:59:59 +00:00
video-prize-ranch
877ee7faa9 Change max age on cache-control in production 2023-08-16 11:46:41 -04:00
video-prize-ranch
d490581c44 Fix overflowing text on mobile 2023-08-16 11:07:32 -04:00
orangix
730aead3a1 fix header on user submissions 2023-08-16 10:26:35 -04:00
video-prize-ranch
2024f7f6cf Add projectsegfau.lt instances to instances.json 2023-08-15 17:05:07 -04:00
orangix
34ecc2a32b User comments support (#131)
#10

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/131
Co-authored-by: orangix <uleo8b8g@anonaddy.me>
Co-committed-by: orangix <uleo8b8g@anonaddy.me>
2023-08-15 20:38:14 +00:00
Arya K
e5e1c38058 Update location of Project Segfault instance in README (#130)
Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/130
Co-authored-by: Arya K <arya@projectsegfau.lt>
Co-committed-by: Arya K <arya@projectsegfau.lt>
2023-08-15 20:30:58 +00:00
video-prize-ranch
493a17385a Remove rimgo.fascinated.cc (closes #125) 2023-08-14 18:59:35 -04:00
orangix
a8abb43f3a Trending page (#128)
Fixes #46

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/128
Co-authored-by: orangix <orangix@noreply.codeberg.org>
Co-committed-by: orangix <orangix@noreply.codeberg.org>
2023-08-14 22:47:59 +00:00
video-prize-ranch
d69d8dba0e Switch image to ko 2023-08-14 14:13:19 -04:00
video-prize-ranch
e67da2c241 Set gitea url 2023-08-14 14:03:51 -04:00
video-prize-ranch
8de23e6b22 Use default base image 2023-08-14 14:00:02 -04:00
video-prize-ranch
97ba8e827d Add goreleaser config (#105) 2023-08-14 13:56:57 -04:00
video-prize-ranch
2f80594106 Add Justfile (#127) 2023-08-14 13:22:12 -04:00
video-prize-ranch
f29df4fbd9 Fix .jpeg links in comments 2023-08-10 16:16:42 +00:00
video-prize-ranch
928f5145a4 Fix tags 2023-08-10 16:16:31 +00:00
video-prize-ranch
34da56c001 Show full title and username on hover 2023-08-10 16:01:42 +00:00
video-prize-ranch
498e9282e9 Add pages for search 2023-08-10 16:00:42 +00:00
video-prize-ranch
043150d85b Add time to title 2023-08-10 15:36:05 +00:00
video-prize-ranch
f85a581486 Improve when information is long 2023-08-10 15:32:27 +00:00
video-prize-ranch
85035243e9 Search (#122)
#113

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/122
Co-authored-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
Co-committed-by: video-prize-ranch <cb.8a3w5@simplelogin.co>
2023-08-10 15:02:51 +00:00
video-prize-ranch
73170689af Add rimgo.frontendfriendly.xyz (closes #121) 2023-07-31 01:44:23 +00:00
video-prize-ranch
e673ae279f Add rimgo.catsarch.com (#124) 2023-07-29 00:24:08 +00:00
video-prize-ranch
e840649481 Update image 2023-07-20 02:19:25 +00:00
video-prize-ranch
8dba4b7ca0 Replace imgur links in comments 2023-07-20 02:18:15 +00:00
video-prize-ranch
891a952e9b Fix warnings 2023-07-19 23:57:00 +00:00
video-prize-ranch
4ea167fde0 Fix last commit 2023-07-19 23:54:12 +00:00
video-prize-ranch
51f9bf4750 Don't show .env error 2023-07-19 23:51:38 +00:00
video-prize-ranch
6af714f92f Fix docker-compose file 2023-07-19 23:50:51 +00:00
kwaa
ed21e8293e Re-add instance imgur.010032.xyz (#120)
#88 #116

The site has been restored and I no longer use Cloudflare.

Reviewed-on: https://codeberg.org/rimgo/rimgo/pulls/120
Co-authored-by: kwaa <kwaa@noreply.codeberg.org>
Co-committed-by: kwaa <kwaa@noreply.codeberg.org>
2023-07-06 23:47:57 +00:00
video-prize-ranch
d5e635c545 Update README 2023-07-01 16:36:08 +00:00
video-prize-ranch
c163ae690e Support /t/TAG/ID paths (closes #117) 2023-06-29 22:23:14 +00:00
video-prize-ranch
ea74f69c45 Update privacy info for rimgo.bus-hit.me (closes #118) 2023-06-29 21:54:27 +00:00
video-prize-ranch
64908fb75d Remove rimgo.privacytools.io and rimgo.010032.xyz (closes #116) 2023-06-19 15:03:42 +00:00
video-prize-ranch
70c6103e24 Remove unused CSS 2023-06-11 12:43:29 -04:00
video-prize-ranch
23435cbe61 Switch to codeberg.org/rimgo/rimgo 2023-06-10 12:32:41 -04:00
video-prize-ranch
b65ee39162 Switch to codeberg.org/rimgo/rimgo 2023-06-10 12:27:20 -04:00
video-prize-ranch
fe639ab7ef Update dependencies 2023-06-10 12:23:57 -04:00
video-prize-ranch
7c78e156ba Build CSS in Dockerfile 2023-06-10 12:23:29 -04:00
video-prize-ranch
6e891c70d8 Update README 2023-06-10 12:13:59 -04:00
video-prize-ranch
4de1fa1e79 Merge redesign into main (#111) 2023-06-10 12:04:29 -04:00
video-prize-ranch
922480f05a Update 'README.md' 2023-06-03 02:53:50 +00:00
video-prize-ranch
a16a302d5e Add rimgo.nohost.network (closes #110) 2023-06-01 21:06:28 -04:00
video-prize-ranch
f0188614b0 Fix import 2023-05-26 15:52:17 -04:00
video-prize-ranch
311bf9ef25 Remove old image caching 2023-05-26 15:46:32 -04:00
video-prize-ranch
9525106ccc Use browser headers for image requests 2023-05-26 15:45:59 -04:00
NoPlagiarism
5e7cf6ec52 Add WhateverItWorks instance (#109)
`rimgo.xbdm.fun` moved to `rimgo.whateveritworks.org`

Co-authored-by: NoPlagiarism <NoPlagiarism@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/109
Co-authored-by: NoPlagiarism <noplagiarism@noreply.codeberg.org>
Co-committed-by: NoPlagiarism <noplagiarism@noreply.codeberg.org>
2023-05-26 13:23:44 +00:00
video-prize-ranch
2b7de852e6 Remove rimgo.esmailelbob.xyz (#106) 2023-05-22 11:19:50 -04:00
video-prize-ranch
b84b1b8371 Remove rimgo.marcopiso.com (closes #104) 2023-05-07 18:03:58 -04:00
video-prize-ranch
73338df7c7 Update dependencies 2023-05-05 19:25:57 -04:00
Kyle David Rohland
8d0c866417 New Instance: rimgo.xbdm.fun (#103)
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/103
Co-authored-by: Kyle David Rohland <xbdm@xbdm.fun>
Co-committed-by: Kyle David Rohland <xbdm@xbdm.fun>
2023-05-05 22:48:52 +00:00
video-prize-ranch
054a717570 Add rimgo.fascinated.cc (closes #102) 2023-05-03 19:41:05 -04:00
video-prize-ranch
6539c4ed30 Add project segfault onion 2023-04-15 11:16:49 -04:00
video-prize-ranch
b9dd049a83 Add Project Segfault instances (closes #101) 2023-04-02 22:12:26 -04:00
kuantum
9b5af0aeb6 harden docker-compose.yml (#99)
`user: nobody`: the least privileged account.
`read_only: true`: this container doesn't write anything to the filesystem, this removes a vector.
`security_opt`: disallows the container to grab more privileges.
`cap_drop`: this container doesn't need any capabilities, drop them.
`networks`: put `rimgo` into its own network so it cannot see other containers by default.

Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/99
Co-authored-by: kuantum <kuantum@noreply.codeberg.org>
Co-committed-by: kuantum <kuantum@noreply.codeberg.org>
2023-03-28 21:33:03 +00:00
video-prize-ranch
4e065bf455 Merge pull request 'Fix Return Imgur Page Bug' (#96) from rx443/rimgo:main into main
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/96
2023-03-14 22:34:12 +00:00
rx
ffbea7868d Update 'main.go' 2023-03-11 18:26:30 +00:00
rx
30f5fdcbf2 Add instance i.01r.xyz (#92)
Co-authored-by: rx443 <rx443@noreply.codeberg.org>
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/92
Co-authored-by: rx <rx443@noreply.codeberg.org>
Co-committed-by: rx <rx443@noreply.codeberg.org>
2023-03-08 00:26:43 +00:00
HexagonCDN
39c670c81f Update 'README.md' (#94)
1. Simplify GreaseMonkey link code - fixes https://codeberg.org/video-prize-ranch/rimgo/issues/93
2. Add `bash` syntax highlighting to code blocks.

Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/94
Co-authored-by: HexagonCDN <hexagoncdn@noreply.codeberg.org>
Co-committed-by: HexagonCDN <hexagoncdn@noreply.codeberg.org>
2023-03-08 00:23:53 +00:00
video-prize-ranch
2c88b519c9 Update dependencies 2023-03-07 19:18:31 -05:00
video-prize-ranch
c6a9ca3443 Merge pull request 'Add instance rimgo.kling.gg' (#91) from elttil/rimgo:main into main
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/91
2023-02-25 19:40:38 +00:00
Anton Kling
4977c5cbf4 Add instance rimgo.kling.gg 2023-02-16 21:12:12 +01:00
video-prize-ranch
75034fb99b Update rimgo.esmailelbob.xyz (closes #89) 2023-02-15 20:26:50 -05:00
video-prize-ranch
81b63f6dea Update LibRedirect link (#closes #90) 2023-02-15 20:24:46 -05:00
video-prize-ranch
9dd1878421 Update: ri.zzls.xyz (closes #86) 2023-02-04 20:11:54 -05:00
kwaa
0bef79a2a4 Add instance imgur.010032.xyz (#88)
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/88
Co-authored-by: kwaa <kwaa@noreply.codeberg.org>
Co-committed-by: kwaa <kwaa@noreply.codeberg.org>
2023-02-04 23:52:10 +00:00
video-prize-ranch
88f6e5b3b5 Update instances.json and README 2023-01-25 08:57:01 -05:00
video-prize-ranch
11418c96f5 Delete .woodpecker 2023-01-15 10:38:12 -05:00
video-prize-ranch
77b2a2ef91 Remove rimgo.bcow.xyz 2023-01-15 10:38:00 -05:00
video-prize-ranch
a3feae6b30 Seperate API from UI 2023-01-01 15:12:03 -05:00
video-prize-ranch
e03abd0ab9 Use rimgo.codeberg.page for 429 error 2023-01-01 15:05:30 -05:00
video-prize-ranch
dece361d98 Add note about instances.json [ci skip] 2022-12-30 20:47:39 -05:00
video-prize-ranch
841e02c0a9 Add rimgo.lunar.icu (closes #83) [ci skip] 2022-12-30 20:45:02 -05:00
video-prize-ranch
55e2b77e3d Update README [ci skip] 2022-12-28 12:13:46 -05:00
video-prize-ranch
99385f9ef4 Remove rimgo.encrypted-data.xyz [ci skip] 2022-12-22 17:32:02 -05:00
video-prize-ranch
2e3cd312bc Remove rimgo.mha.fi [ci skip] 2022-12-20 19:55:42 -05:00
video-prize-ranch
62910defcf Set schema for woodpecker file 2022-12-20 19:43:11 -05:00
video-prize-ranch
f89306e26a Update modules 2022-12-20 19:41:12 -05:00
video-prize-ranch
e82b47a729 CSS cleanup 2022-12-20 19:35:48 -05:00
Arya K
82c360baa0 Update ~vern rimgo instance location (#81) [ci skip]
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/81
Co-authored-by: Arya K <aryak@vern.cc>
Co-committed-by: Arya K <aryak@vern.cc>
2022-11-27 16:58:29 +00:00
video-prize-ranch
af4c674955 Remove i.actionsack.com and rimgo.privacydev.net (#48) [ci skip] 2022-11-25 21:59:08 -05:00
video-prize-ranch
36a8e99c9a Add rimgo.marcopisco.com (closes #79) [ci skip] 2022-11-25 21:56:49 -05:00
Artemis
2d711df823 L: Updated provider information for artemislena (#80) [ci skip]
L: Uhm, we now have a proper public IPv4 address (full dual stack), so we don't need to route things through that VPS anymore.
Co-authored-by: artemislena <artemis@artemislena.eu>
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/80
Co-authored-by: Artemis <artemislena@noreply.codeberg.org>
Co-committed-by: Artemis <artemislena@noreply.codeberg.org>
2022-11-25 19:18:15 +00:00
video-prize-ranch
bc0c2d8008 Lighthouse accessibility improvements 2022-11-18 12:14:11 -05:00
video-prize-ranch
5c2962d34d Improve CSP and security headers (closes #74) 2022-11-18 12:08:18 -05:00
video-prize-ranch
10289cde51 Improve redirector configuration 2022-11-18 11:57:21 -05:00
video-prize-ranch
b8c2f453e5 Only build when branch is main [ci skip] 2022-11-18 11:56:19 -05:00
video-prize-ranch
459c23013f Add ri.zzls.xyz (closes #77) [ci skip] 2022-11-18 11:40:00 -05:00
Artemis
2d25b12aec L: Update provider details for artemislena.eu instance (#76) [ci skip]
Uhm, sorry, we uh, sort of wanted to do this right after moving? Didn't get to it so far, though, were busy with uni and things, so uh, we're only updating details on our ISP now.

Co-authored-by: artemislena <artemis@artemislena.eu>
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/76
Co-authored-by: Artemis <artemislena@noreply.codeberg.org>
Co-committed-by: Artemis <artemislena@noreply.codeberg.org>
2022-11-12 18:11:33 +01:00
video-prize-ranch
6aba8e7183 Improve README.md accessibility (closes #75) [ci skip] 2022-11-08 20:47:37 -05:00
video-prize-ranch
594ed97746 Add usage section 2022-10-30 21:57:53 -04:00
video-prize-ranch
9c7464cd08 Add alt text (closes #72) 2022-10-28 20:10:11 -04:00
video-prize-ranch
681baf4d54 Change Data to Data collected [ci skip] 2022-10-24 09:35:41 -04:00
valere
e58cfa872e Add Hostux instance (#69) [ci skip]
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/69
Co-authored-by: valere <valere@noreply.codeberg.org>
Co-committed-by: valere <valere@noreply.codeberg.org>
2022-10-24 15:33:20 +02:00
video-prize-ranch
69e7baa594 Add table of contents and improve format [ci skip] 2022-10-22 20:32:17 -04:00
video-prize-ranch
166d1e68f6 Recommend Caddy in README [ci skip] 2022-10-22 20:16:14 -04:00
video-prize-ranch
4cf3861387 Add i.habedieeh.re (closes #66) [ci skip] 2022-10-16 21:41:13 -04:00
video-prize-ranch
9d65fa95b4 Switch to Fiber cache (closes #63) 2022-10-14 20:27:37 -04:00
video-prize-ranch
1f1d930072 Update dependencies 2022-10-14 20:15:57 -04:00
video-prize-ranch
ac1a4056c8 Remove fonts/ 2022-10-13 18:26:29 -04:00
video-prize-ranch
b8469ada4e Switch to Feather Icons 2022-10-13 18:26:08 -04:00
video-prize-ranch
50d71ad321 UI cleanup and changes 2022-10-13 17:29:05 -04:00
video-prize-ranch
7cad41e11d Move description below media (closes #65) 2022-10-13 16:57:12 -04:00
video-prize-ranch
a328b15698 Add display: block to comment media 2022-10-08 18:14:00 -04:00
video-prize-ranch
d30ac03554 Make download link download file 2022-10-08 18:05:41 -04:00
video-prize-ranch
e73bd2e87b Fix gifv overflow 2022-10-08 18:00:06 -04:00
video-prize-ranch
d6ebc9a54a Render media in comments (closes #8) 2022-10-08 17:50:08 -04:00
video-prize-ranch
46465e1e17 Update frontpage to match README 2022-10-08 16:25:33 -04:00
video-prize-ranch
2a5e17628c Fix deploy pipeline 2022-10-06 06:54:04 -04:00
video-prize-ranch
23499a9710 Fix error without query params 2022-10-06 06:53:24 -04:00
video-prize-ranch
b6d400688f Update rimgo.bcow.xyz [ci skip] 2022-10-05 23:11:27 -04:00
video-prize-ranch
b6adca7627 Passthrough query parameters on /stack 2022-10-05 22:24:28 -04:00
video-prize-ranch
740ae0d925 Use 429 error page for 429 errors from Imgur API 2022-10-05 22:16:57 -04:00
video-prize-ranch
cdbd3944d9 Enable controls and fix scaling for gifv (closes #62) 2022-10-05 22:11:43 -04:00
video-prize-ranch
c93d32a043 Don't force webp on /stack 2022-10-05 22:04:21 -04:00
video-prize-ranch
8576b5d517 Update official instance URL (old one will continue to work) [ci skip] 2022-10-01 22:56:26 -04:00
video-prize-ranch
8a899bd85a Add privacy comparison to README [ci skip] 2022-09-30 17:08:16 -04:00
video-prize-ranch
4306b3bb81 Add image cache and use struct for config (closes #58) 2022-09-30 16:57:18 -04:00
video-prize-ranch
f1c058cbfc Support i.stack.imgur.com (#61) 2022-09-30 16:17:24 -04:00
video-prize-ranch
b8d54dede6 Fix Mobile UI issues (closes #57) 2022-09-18 22:04:29 -04:00
esmailelbob
0b25e637cc Update esmailelbob.xyz instance onion (#59) [ci skip]
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/59
Co-authored-by: esmailelbob <esmailelbob@noreply.codeberg.org>
Co-committed-by: esmailelbob <esmailelbob@noreply.codeberg.org>
2022-09-15 23:35:22 +02:00
video-prize-ranch
ced4d817c0 Update rimgo.encrypted-data.xyz (#48) 2022-09-15 17:34:26 -04:00
video-prize-ranch
5944b7253d Improved error handling 2022-09-13 16:31:55 -04:00
video-prize-ranch
1263e66f45 Add error page for ratelimit 2022-09-10 10:11:17 -04:00
video-prize-ranch
f0c1b7f4fe Update rimgo.privacytools.io (closes #51) 2022-09-07 16:57:10 -04:00
video-prize-ranch
432137d5bc Add Redirector configuration to README (closes #49) 2022-09-04 16:26:48 -04:00
video-prize-ranch
d282f57a1c Add rim.odyssey346.dev and onion [ci skip] 2022-09-04 16:18:29 -04:00
video-prize-ranch
f9adc8adb0 Add imgur.artemislena.eu onion (closes #50) 2022-09-04 12:34:31 -04:00
video-prize-ranch
d3799c6f7b Update imgur.artemislena.eu [ci skip] 2022-09-01 15:41:21 -04:00
video-prize-ranch
3431c5c56b Update i.bcow.xyz [ci skip] 2022-09-01 10:43:56 -04:00
video-prize-ranch
3db725cc5f Update privacy for rimgo.bus-hit.me [ci skip] 2022-08-31 20:00:55 -04:00
video-prize-ranch
3a5368fc1f Update privacy for esmailelbob onion [ci skip] 2022-08-31 19:08:02 -04:00
video-prize-ranch
523d347629 Update privacy for rimgo.esmailelbob.xyz [ci skip] 2022-08-31 19:02:58 -04:00
video-prize-ranch
e477c1dabc Fix command in build from source instructions [ci skip] 2022-08-31 18:52:34 -04:00
video-prize-ranch
37259cd1fd Update privacy for rimgo.totaldarkness.net [ci skip] 2022-08-31 18:51:55 -04:00
video-prize-ranch
09945fabbc Update instances.json [ci skip] 2022-08-31 16:02:57 -04:00
video-prize-ranch
3f0382342c Improve instance list [ci skip] (closes #47) 2022-08-31 16:00:49 -04:00
video-prize-ranch
944e7ec387 Update i.bcow.xyz [ci skip] 2022-08-29 20:36:19 -04:00
video-prize-ranch
58bf8469d9 Fix icons 2022-08-29 20:07:20 -04:00
video-prize-ranch
bf0ae28599 Add section on automatic updates and use image by default [ci skip] 2022-08-12 21:22:46 -04:00
video-prize-ranch
ba796cbf09 Fix Docker image name 2022-08-11 16:41:06 -04:00
video-prize-ranch
351dc1b863 Add registry URL 2022-08-11 16:24:34 -04:00
video-prize-ranch
7477f97be4 Fix docker build 2022-08-11 16:04:48 -04:00
video-prize-ranch
ac228e8d1e Switch to codeberg.org for registry 2022-08-11 15:57:23 -04:00
video-prize-ranch
5412b58be5 Set font-display to optional (closes #44) 2022-08-08 17:57:33 -04:00
video-prize-ranch
51fbb8d0a7 Improve post image size 2022-08-04 20:14:17 -04:00
video-prize-ranch
59a148e4f2 Update modules 2022-08-04 19:57:50 -04:00
video-prize-ranch
acf677db89 Add link to privacy page 2022-08-04 19:51:09 -04:00
video-prize-ranch
d50cf2da86 Add support for .env configuration and privacy page (closes #44) 2022-08-04 19:41:55 -04:00
video-prize-ranch
4da9b74949 Merge pull request 'Fixed url' (#45) from BobIsMyManager/rimgo:main into main
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/45
2022-07-26 22:59:36 +02:00
BobIsMyManager
ca6c50b513 Fixed url 2022-07-26 13:52:33 +01:00
video-prize-ranch
150df2435d Fix tag backgrounds 2022-07-22 12:20:51 -04:00
video-prize-ranch
e0efe6caca Move types to api 2022-07-22 11:55:22 -04:00
video-prize-ranch
da42f7cf90 Update README [ci skip] 2022-07-22 11:50:16 -04:00
video-prize-ranch
27736300f8 Update frontpage to match README 2022-07-22 11:48:28 -04:00
video-prize-ranch
416a34c731 Force remote builder for deploy 2022-07-21 11:23:55 -04:00
video-prize-ranch
5a4a55fef0 Revert "Use flyio/flyctl instead of downloading flyctl"
This reverts commit 6b4e6e6436.
2022-07-21 11:22:46 -04:00
video-prize-ranch
6b4e6e6436 Use flyio/flyctl instead of downloading flyctl 2022-07-21 11:19:25 -04:00
video-prize-ranch
be349ec9d9 Allow embedding embeds 2022-07-16 16:02:59 -04:00
video-prize-ranch
95eaf959b0 Support embedded images/albums (closes #41) 2022-07-16 15:59:06 -04:00
video-prize-ranch
3f29e71876 Remove GitLab badge [skip ci] 2022-07-13 14:21:41 -04:00
video-prize-ranch
18c2c88d9f Switch to Codeberg CI 2022-07-13 14:17:23 -04:00
video-prize-ranch
0d1bf4a008 Update instances [skip ci] 2022-07-11 12:19:57 -04:00
video-prize-ranch
4643f6d416 Remove deploy step 2022-06-25 15:26:11 -04:00
video-prize-ranch
d299219533 Add media-src to CSP 2022-06-25 15:23:59 -04:00
video-prize-ranch
d1a6768cef Add support for Range headers 2022-06-25 15:23:13 -04:00
video-prize-ranch
4bdcf9036d Remove i2p instance (broken) [skip ci] 2022-06-20 16:53:25 -04:00
video-prize-ranch
1bed1d4147 Update README [skip ci] 2022-06-20 16:53:04 -04:00
video-prize-ranch
9dbb846ef5 Remove instances from instances.json [skip ci] 2022-06-20 16:45:53 -04:00
video-prize-ranch
b081604e00 Remove instance (outdated) [skip ci] 2022-06-20 15:54:09 -04:00
video-prize-ranch
1b8ab7b2a9 Remove img.riverside.rocks (outdated) and be7ud...onion (broken) [skip ci] 2022-06-20 15:50:23 -04:00
video-prize-ranch
da44d02601 Add Cache-Control to static files 2022-06-18 12:21:22 -04:00
video-prize-ranch
72366d47bd Add link for edited theme [skip ci] 2022-06-18 08:51:08 -04:00
tcdu7ni4i6y2mq2a
d664fcd169 Improve instances.json file (#39) [skip ci]
In this pull request I made few modifications to instances.json file to make it more friendly to any scripts that will be using it as a source of instances in future:

* I added protocol to all URLs. Most scripts expect URLs to already have protocol and lack of it may cause minor issues.
* I turned instances.json from array of strings into array of objects. It makes the list more organized and it would be easier to add or remove instances in future.

Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/39
Co-authored-by: tcdu7ni4i6y2mq2a <tcdu7ni4i6y2mq2a@noreply.codeberg.org>
Co-committed-by: tcdu7ni4i6y2mq2a <tcdu7ni4i6y2mq2a@noreply.codeberg.org>
2022-06-16 16:45:38 +02:00
video-prize-ranch
5b6b8e8b63 Fix emoji [skip ci] 2022-06-12 12:28:28 -04:00
video-prize-ranch
5447d184d1 Add rimgo.encrypted-data.xyz (closes #38) 2022-06-12 12:26:45 -04:00
video-prize-ranch
e022a451af Use address from config (#37) 2022-06-12 12:12:36 -04:00
video-prize-ranch
965f5817c5 Remove instance [skip ci] 2022-06-10 17:03:04 -04:00
Aleksandar "The Cobra" Widulski
2ac2c64d9c Add ~vern onion and add stuff to instances.json (#35) [skip ci]
Signed-off-by: Aleksandar "The Cobra" Widulski <cobra@vern.cc>
Co-authored-by: Aleksandar "The Cobra" Widulski <cobra@vern.cc>
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/35
Co-authored-by: Aleksandar "The Cobra" Widulski <thecobra@riseup.net>
Co-committed-by: Aleksandar "The Cobra" Widulski <thecobra@riseup.net>
2022-06-09 03:15:50 +02:00
Arya K
a4f687da7b Add instance rimgo.vern.cc (#34) [skip ci]
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/34
Co-authored-by: Arya K <aryak@vern.cc>
Co-committed-by: Arya K <aryak@vern.cc>
2022-06-08 20:28:38 +02:00
video-prize-ranch
136631b7b6 Merge pull request 'L: Fix Redirector config.' (#33) from artemislena/rimgo:main into main
Reviewed-on: https://codeberg.org/video-prize-ranch/rimgo/pulls/33
2022-06-08 05:13:00 +02:00
artemislena
6c95c2f16f L: Fix Redirector config. 2022-06-07 14:21:32 +02:00
video-prize-ranch
ceabddc972 Add documentation for FORCE_WEBP 2022-06-04 20:56:04 -04:00
video-prize-ranch
de49f1c647 Fix bug 2022-06-04 20:48:28 -04:00
video-prize-ranch
b323b26b57 Use WebP if the browser supports it (#32) 2022-06-04 20:44:54 -04:00
video-prize-ranch
f3ac0369b1 Add deploy stage [skip ci] 2022-06-04 19:48:31 -04:00
video-prize-ranch
b7d8f02542 Update README [skip ci] 2022-06-04 12:06:22 -04:00
video-prize-ranch
465f36a59e Remove fly.toml [skip ci] 2022-06-04 11:59:44 -04:00
video-prize-ranch
92f80392d4 Fix artifact 2022-06-04 10:49:16 -04:00
video-prize-ranch
3383c24e4f Update CI config 2022-06-04 10:44:07 -04:00
video-prize-ranch
ba2079449c Add binary build 2022-06-04 10:32:14 -04:00
video-prize-ranch
b5081f2c4d Optimize CI 2022-06-03 18:45:14 -04:00
video-prize-ranch
dea4a3e5f1 Fix deploy stage 2022-06-03 18:10:47 -04:00
video-prize-ranch
0ed12fe16d Add imgur.artemislena.eu 2022-06-01 14:29:26 -04:00
video-prize-ranch
73b3391763 Add imgur.artemislena.eu (#31) 2022-06-01 13:55:11 -04:00
video-prize-ranch
2c695d4c61 Update 'README.md' 2022-05-31 13:56:30 +02:00
video-prize-ranch
c0f0d71d01 Print stack trace on error (#26) 2022-05-30 21:33:44 -04:00
video-prize-ranch
730ae1fa10 Add rimgo.privacydev.net (#30) 2022-05-30 21:24:47 -04:00
video-prize-ranch
d05f7f868d Add 404 page 2022-05-23 11:30:17 -04:00
video-prize-ranch
6eee86d682 Improve code reuse 2022-05-23 11:10:50 -04:00
video-prize-ranch
5569feb2c8 Add section on automatic redirects 2022-05-14 12:11:31 -04:00
video-prize-ranch
1b562dc6e7 Fix no access token 2022-05-14 11:59:10 -04:00
video-prize-ranch
eb27abbaae Add deploy stage 2022-05-14 11:47:28 -04:00
video-prize-ranch
500ce9ceba Update README 2022-05-02 23:28:16 -04:00
video-prize-ranch
c86cdb63d3 Update README 2022-04-30 15:51:39 -04:00
video-prize-ranch
cdf35c1b53 go mod tidy 2022-04-22 12:10:59 -04:00
video-prize-ranch
d0904407af Remove file configuration 2022-04-22 12:05:22 -04:00
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
104 changed files with 3896 additions and 1880 deletions

42
.air.toml Normal file
View File

@@ -0,0 +1,42 @@
# Config file for [Air](https://github.com/cosmtrek/air) in TOML format
# Working directory
# . or absolute path, please note that the directories following must be under root.
root = "."
tmp_dir = "tmp"
[build]
full_bin = "ENV=dev go run main.go"
# Watch these filename extensions.
include_ext = ["go", "hbs"]
# Ignore these filename extensions or directories.
exclude_dir = ["tmp", "vendor", "static"]
# Watch these directories if you specified.
include_dir = []
# Exclude files.
exclude_file = []
# This log file places in your tmp_dir.
log = "air.log"
# It's not necessary to trigger build each time file changes if it's too frequent.
delay = 1000 # ms
# Stop running old binary when build errors occur.
stop_on_error = true
# Send Interrupt signal before killing process (windows does not support this feature)
send_interrupt = false
# Delay after sending Interrupt signal
kill_delay = 500 # ms
[log]
# Show log time
time = false
[color]
# Customize each part's color. If no color found, use the raw app log.
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"
[misc]
# Delete tmp directory on exit
clean_on_exit = true

View File

@@ -1,3 +1,3 @@
node_modules .env
samples tmp
dist static/app.css

36
.env.example Normal file
View File

@@ -0,0 +1,36 @@
ADDRESS=0.0.0.0
PORT=3000
FIBER_PREFORK=false
IMGUR_CLIENT_ID=546c25a59c58ad7
SECURE=true
# Instance privacy
# For more information, see https://codeberg.org/librarian/librarian/wiki/Instance-privacy
# Required to be on the instance list.
# Link to a privacy policy (optional)
PRIVACY_POLICY=
# Explain how this data is used/why it is collected (optional)
PRIVACY_MESSAGE=
# Country where instance is located. Leave blank if running on Tor without clearnet.
PRIVACY_COUNTRY=
# Hosting provider or ISP name. Leave blank if running on Tor without clearnet.
PRIVACY_PROVIDER=
# Set to true if you use Cloudflare (using Cloudflare only as DNS (gray cloud icon), set to false)
PRIVACY_CLOUDFLARE=false
# These settings are for NGINX without data collection disabled.
# Instructions for other reverse proxies and to disable data collection:
# https://codeberg.org/librarian/librarian/wiki/Instance-privacy
# Set to true if no data is collected. (overrides all other options)
PRIVACY_NOT_COLLECTED=false
# IP address
PRIVACY_IP=true
# Request URL
PRIVACY_URL=true
# Device Type (User agent)
PRIVACY_DEVICE=true
# If the data collection is only collected when there is an error and only stored for
# a short amount of time while diagnosing an issue.
PRIVACY_DIAGNOSTICS=false

5
.gitignore vendored
View File

@@ -1,2 +1,5 @@
dist .env
tmp
static/app.css
dist/
node_modules node_modules

55
.goreleaser.yaml Normal file
View File

@@ -0,0 +1,55 @@
version: 2
before:
hooks:
- pnpm run build
- go mod tidy
project_name: rimgo
builds:
- env:
- CGO_ENABLED=0
goos:
- linux
- windows
- darwin
goarch:
- amd64
- arm64
ldflags:
- -X codeberg.org/rimgo/rimgo/pages.VersionInfo={{.Version}}
archives:
- formats: tar.gz
name_template: >-
{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}{{- if .Arm }}v{{ .Arm }}{{ end }}
format_overrides:
- goos: windows
formats: zip
checksum:
name_template: 'checksums.txt'
kos:
- repositories:
- codeberg.org/rimgo/rimgo
- codeberg.org/video-prize-ranch/rimgo
tags:
- '{{.Version}}'
- latest
bare: true
preserve_import_paths: false
platforms:
- linux/amd64
- linux/arm64
sbom: none
gitea_urls:
api: https://codeberg.org/api/v1
download: https://codeberg.org
release:
gitea:
owner: rimgo
name: rimgo
name_template: "{{.ProjectName}} v{{.Version}}"
disable: false
mode: append
# The lines beneath this are called `modelines`. See `:help modeline`
# Feel free to remove those if you don't want/use them.
# yaml-language-server: $schema=https://goreleaser.com/static/schema.json
# vim: set ts=2 sw=2 tw=0 fo=cnqoj

View File

@@ -1,14 +1,19 @@
FROM golang:alpine AS build FROM --platform=$BUILDPLATFORM golang:alpine AS build
ARG TARGETARCH
WORKDIR /src WORKDIR /src
RUN apk --no-cache add git RUN apk --no-cache add ca-certificates git nodejs pnpm
RUN git clone https://codeberg.org/video-prize-ranch/rimgo . COPY . .
RUN go build RUN pnpm install && pnpm run build
RUN go mod download
RUN GOOS=linux GOARCH=$TARGETARCH CGO_ENABLED=0 go build -ldflags "-X codeberg.org/rimgo/rimgo/pages.VersionInfo=$(date '+%Y-%m-%d')-$(git rev-list --abbrev-commit -1 HEAD)"
FROM alpine:latest as bin FROM scratch AS bin
WORKDIR /app WORKDIR /app
COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=build /src/rimgo . COPY --from=build /src/rimgo .
EXPOSE 3000 EXPOSE 3000

14
Justfile Normal file
View File

@@ -0,0 +1,14 @@
build:
pnpm run build
CGO_ENABLED=0 go build -o rimgo -ldflags "-X codeberg.org/rimgo/rimgo/pages.VersionInfo=$(date '+%Y-%m-%d')-$(git rev-list --abbrev-commit -1 HEAD)"
dev-css:
pnpm run watch
dev:
go run github.com/air-verse/air@latest -c .air.toml
tag-vpr:
podman pull codeberg.org/rimgo/rimgo:latest
podman image tag codeberg.org/rimgo/rimgo:latest codeberg.org/video-prize-ranch/rimgo:latest
podman push codeberg.org/video-prize-ranch/rimgo:latest

148
README.md
View File

@@ -1,116 +1,84 @@
<img src="https://codeberg.org/video-prize-ranch/rimgo/raw/branch/main/static/img/rimgo.svg" width="96" height="96" /> <img alt="" src="https://codeberg.org/rimgo/rimgo/raw/branch/main/static/img/rimgo.svg" width="96" height="96" />
# rimgo # rimgo
An alternative frontend for Imgur. Based on [rimgu](https://codeberg.org/3np/rimgu) and rewritten in Go. An alternative frontend for Imgur. Originally based on [rimgu](https://codeberg.org/3np/rimgu).
<a href="https://www.gnu.org/licenses/agpl-3.0.en.html"> <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"> <img alt="License: AGPLv3" src="https://shields.io/badge/License-AGPL%20v3-blue.svg" height="20px">
</a>
<a href="https://matrix.to/#/#rimgo:nitro.chat">
<img alt="Matrix" src="https://img.shields.io/badge/chat-matrix-blue" height="20px">
</a> </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. ## Table of Contents
- [Features](#features)
- [Comparison](#comparison)
- [Speed](#speed)
- [Privacy](#privacy)
- [Usage](#usage)
- [Instances](#instances)
- [Contributing](#contributing)
- [License](#license)
### Documentation
Our new documentation is now available at [https://rimgo.codeberg.page/docs/](https://rimgo.codeberg.page/docs/)!
- [Install](https://rimgo.codeberg.page/docs/getting-started/install/)
- [Configuration](https://rimgo.codeberg.page/docs/usage/configuration/)
- [Redirection](https://rimgo.codeberg.page/docs/usage/redirection/)
- [Instance privacy](https://rimgo.codeberg.page/docs/usage/instance-privacy/)
## Features ## Features
- Lightweight
- No JavaScript
- No ads or tracking
- No sign up or app install prompts
- Bandwidth efficient - automatically uses newer image formats (if enabled)
- [x] URL-compatible with i.imgur.com - just replace the domain in the URL ## Comparison
- [x] Images and videos (gifv, mp4) Comparing rimgo to Imgur.
- [ ] Galleries with comments
- [x] Albums
- [ ] User page
- [ ] Tag page
This is currently very early stage software. Some things left to implement (contributions welcome!): ### Speed
Tested using [Google PageSpeed Insights](https://pagespeed.web.dev/).
- [x] Streaming (currently media is downloaded in full in rimgu before it's returned) | | [rimgo](https://pagespeed.web.dev/report?url=https%3A%2F%2Fi.bcow.xyz%2Fgallery%2FgYiQLWy) | [Imgur](https://pagespeed.web.dev/report?url=https%3A%2F%2Fimgur.com%2Fgallery%2FgYiQLWy) |
- [ ] Localization/internationalization | ------------------- | ------- | --------- |
- [x] Pretty CSS styling (responsive?) | Performance | 91 | 28 |
- [ ] Support for other popular image sites | Request count | 29 | 340 |
- [ ] Filtering and exploration on user/tags pages | Resource Size | 218 KiB | 2,542 KiB |
- [ ] Responsive scaling of videos on user/tags pages | Time to Interactive | 1.6s | 23.8s |
- [x] Logo
Things that are considered out of scope: ### Privacy
Imgur collects information about your device and uses tracking cookies for advertising, this is mentioned in their [privacy policy](https://imgur.com/privacy/). [Blacklight](https://themarkup.org/blacklight) found 84 trackers and 264 third-party cookies.
* Uploading, commenting, voting, etc - rimgo is read-only. See what cookies and trackers Imgur uses and where your data gets sent: https://themarkup.org/blacklight?url=imgur.com
* Authentication, serving HTTPS, rate limiting, etc - Use a reverse proxy or load balancer like Caddy, Traefik, or NGINX.
* Anything requiring JavaScript or the client directly interacting with upstream servers. ## Usage
Replace imgur.com or i.imgur.com with the instance domain. For i.stack.imgur.com, replace i.stack.imgur.com with the instance domain and add stack/ before the media ID.
Imgur: `https://imgur.com/gallery/j2sOQkJ` -> `https://rimgo.bcow.xyz/gallery/j2sOQkJ`
Stack Overflow: `https://i.stack.imgur.com/KnO3v.jpg?s=64&g=1` -> `https://rimgo.bcow.xyz/stack/KnO3v.jpg?s=64&g=1`
To automatically redirect Imgur links, see [Redirection](https://rimgo.codeberg.page/docs/usage/redirection/).
## Instances ## Instances
Open an issue to have your instance listed here! Available at https://rimgo.codeberg.page/ or https://codeberg.org/rimgo/instances
| 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 | |
## Install ## Install
rimgo can run on any platform Go compiles on.
### Docker
Install Docker and docker-compose, then clone this repository.
```
git clone https://codeberg.org/video-prize-ranch/rimgo
cd rimgo
```
Edit the `docker-compose.yml` file using your favorite text editor.
```
nvim docker-compose.yml
```
You can now run rimgo.
```
sudo docker-compose up -d
```
### Build from source
#### Requirements
* Go v1.16 or later
Clone the repository and `cd` into it.
```
git clone https://codeberg.org/video-prize-ranch/rimgo
cd rimgo
```
Build rimgo.
```
go build
```
Edit the config file using your preferred editor.
```
nvim config.yml
```
You can now run rimgo.
```
./rimgo
```
See [Install](https://rimgo.codeberg.page/docs/getting-started/install/).
## Configuration ## Configuration
rimgo can be configured using environment variables or a config file. See [Configuration](https://rimgo.codeberg.page/docs/usage/configuration/).
### Environment variables
| Name | Default |
|-----------------------|-----------------|
| RIMGU_PORT | 3000 |
| RIMGU_HOST | localhost |
| RIMGU_ADDRESS | 0.0.0.0 |
| RIMGU_IMGUR_CLIENT_ID | 546c25a59c58ad7 |
## Contributing ## Contributing
Pull requests are welcome! If you have any questions or bug reports, open an [issue](https://codeberg.org/rimgo/rimgo/issues/new). Please remember to follow our [Code of Conduct](https://rimgo.codeberg.page/docs/code-of-conduct/)!
PRs are welcome! ## License
This software is released under the AGPL-3.0 license. If you make any modifications to the code and distribute it (including use on a network server), you must publicly distribute your changes and release them under the AGPL-3.0.
This software is released under the AGPL 3.0 license. 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. ## Legal notice
rimgo does not allow uploads or host any content, media. All content on any rimgo instances is from Imgur™. Imgur is a trademark of Imgur, Inc. Any issues with content on rimgo should be be reported to Imgur. rimgo is not affiliated with Imgur, Inc.

View File

@@ -1,71 +1,117 @@
package api package api
import ( import (
"io"
"net/http"
"strings" "strings"
"time"
"codeberg.org/video-prize-ranch/rimgo/types" "codeberg.org/rimgo/rimgo/utils"
"codeberg.org/video-prize-ranch/rimgo/utils" "github.com/microcosm-cc/bluemonday"
"github.com/spf13/viper"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
) )
func FetchAlbum(albumID string) (types.Album, error) { type Album struct {
// https://api.imgur.com/post/v1/albums/zk7mdKH?client_id=${CLIENT_ID}&include=media%2Caccount Id string
Title string
Views int64
Upvotes int64
Downvotes int64
SharedWithCommunity bool
CreatedAt string
UpdatedAt string
Comments int64
User User
Media []Media
Tags []Tag
}
res, err := http.Get("https://api.imgur.com/post/v1/albums/" + albumID + "?client_id=" + viper.GetString("RIMGU_IMGUR_CLIENT_ID") + "&include=media%2Caccount") type Media struct {
Id string
Name string
Title string
Description string
Url string
Type string
MimeType string
}
func (client *Client) FetchAlbum(albumID string) (Album, error) {
cacheData, found := client.Cache.Get(albumID + "-album")
if found {
return cacheData.(Album), nil
}
data, err := utils.GetJSON("https://api.imgur.com/post/v1/albums/" + albumID + "?client_id=" + client.ClientID + "&include=media%2Caccount")
if err != nil { if err != nil {
return types.Album{}, err return Album{}, err
} }
body, err := io.ReadAll(res.Body) album, err := parseAlbum(data)
if err != nil { if err != nil {
return types.Album{}, err return Album{}, err
}
data := gjson.Parse(string(body))
album := types.Album{}
if data.Get("shared_with_community").Bool() {
album, err = FetchPosts(albumID)
} else {
album, err = ParseAlbum(data)
} }
client.Cache.Set(albumID+"-album", album, 1*time.Hour)
return album, err return album, err
} }
func FetchPosts(albumID string) (types.Album, error) { func (client *Client) FetchPosts(albumID string) (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 := client.Cache.Get(albumID + "-posts")
if found {
return cacheData.(Album), nil
}
data, err := utils.GetJSON("https://api.imgur.com/post/v1/posts/" + albumID + "?client_id=" + client.ClientID + "&include=media%2Caccount%2Ctags")
if err != nil { if err != nil {
return types.Album{}, err return Album{}, err
} }
body, err := io.ReadAll(res.Body) album, err := parseAlbum(data)
if err != nil { if err != nil {
return types.Album{}, err return Album{}, err
} }
data := gjson.Parse(string(body)) client.Cache.Set(albumID+"-posts", album, 1*time.Hour)
return album, nil
return ParseAlbum(data)
} }
func ParseAlbum(data gjson.Result) (types.Album, error) { func (client *Client) FetchMedia(mediaID string) (Album, error) {
media := make([]types.Media, 0) cacheData, found := client.Cache.Get(mediaID + "-media")
if found {
return cacheData.(Album), nil
}
data, err := utils.GetJSON("https://api.imgur.com/post/v1/media/" + mediaID + "?client_id=" + client.ClientID + "&include=media%2Caccount")
if err != nil {
return Album{}, err
}
album, err := parseAlbum(data)
if err != nil {
return Album{}, err
}
client.Cache.Set(mediaID+"-media", album, 1*time.Hour)
return album, nil
}
func parseAlbum(data gjson.Result) (Album, error) {
media := make([]Media, 0)
data.Get("media").ForEach( data.Get("media").ForEach(
func(key gjson.Result, value gjson.Result) bool { func(key gjson.Result, value gjson.Result) bool {
url := value.Get("url").String() url := value.Get("url").String()
url = strings.ReplaceAll(url, "https://i.imgur.com", "") url = strings.ReplaceAll(url, "https://i.imgur.com", "")
media = append(media, types.Media{ description := value.Get("metadata.description").String()
description = strings.ReplaceAll(description, "\n", "<br>")
description = bluemonday.UGCPolicy().Sanitize(description)
media = append(media, Media{
Id: value.Get("id").String(), Id: value.Get("id").String(),
Name: value.Get("name").String(), Name: value.Get("name").String(),
MimeType: value.Get("mime_type").String(), MimeType: value.Get("mime_type").String(),
Type: value.Get("type").String(), Type: value.Get("type").String(),
Title: value.Get("metadata.title").String(), Title: value.Get("metadata.title").String(),
Description: value.Get("metadata.description").String(), Description: description,
Url: url, Url: url,
}) })
@@ -73,12 +119,25 @@ func ParseAlbum(data gjson.Result) (types.Album, error) {
}, },
) )
tags := make([]Tag, 0)
data.Get("tags").ForEach(
func(key gjson.Result, value gjson.Result) bool {
tags = append(tags, Tag{
Tag: value.Get("tag").String(),
Display: value.Get("display").String(),
Background: "/" + value.Get("background_id").String() + ".webp",
BackgroundId: value.Get("background_id").String(),
})
return true
},
)
createdAt, err := utils.FormatDate(data.Get("created_at").String()) createdAt, err := utils.FormatDate(data.Get("created_at").String())
if err != nil { if err != nil {
return types.Album{}, err return Album{}, err
} }
return types.Album{ album := Album{
Id: data.Get("id").String(), Id: data.Get("id").String(),
Title: data.Get("title").String(), Title: data.Get("title").String(),
SharedWithCommunity: data.Get("shared_with_community").Bool(), SharedWithCommunity: data.Get("shared_with_community").Bool(),
@@ -88,5 +147,17 @@ func ParseAlbum(data gjson.Result) (types.Album, error) {
Comments: data.Get("comment_count").Int(), Comments: data.Get("comment_count").Int(),
CreatedAt: createdAt, CreatedAt: createdAt,
Media: media, Media: media,
}, nil Tags: tags,
}
account := data.Get("account")
if account.Raw != "" {
album.User = 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
} }

21
api/client.go Normal file
View File

@@ -0,0 +1,21 @@
package api
import (
"time"
"github.com/patrickmn/go-cache"
)
type Client struct {
ClientID string
Cache *cache.Cache
}
func NewClient(clientId string) (*Client) {
client := Client{
ClientID: clientId,
Cache: cache.New(15*time.Minute, 15*time.Minute),
}
return &client
}

View File

@@ -1,43 +1,54 @@
package api package api
import ( import (
"io" "regexp"
"net/http"
"strings" "strings"
"sync" "sync"
"time" "time"
"codeberg.org/video-prize-ranch/rimgo/types" "codeberg.org/rimgo/rimgo/utils"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/dustin/go-humanize" "github.com/dustin/go-humanize"
"github.com/spf13/viper" "github.com/microcosm-cc/bluemonday"
"github.com/patrickmn/go-cache"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"gitlab.com/golang-commonmark/linkify"
) )
func FetchComments(galleryID string) ([]types.Comment, error) { type Comment struct {
// https://api.imgur.com/comment/v1/comments?client_id=546c25a59c58ad7&filter[post]=eq:g1bk7CB&include=account&per_page=30&sort=best Comments []Comment
User User
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") Post Submission
if err != nil { Id string
return []types.Comment{}, err Comment string
Upvotes int64
Downvotes int64
Platform string
CreatedAt string
RelTime string
UpdatedAt string
DeletedAt string
} }
body, err := io.ReadAll(res.Body) func (client *Client) FetchComments(galleryID string) ([]Comment, error) {
if err != nil { cacheData, found := client.Cache.Get(galleryID + "-comments")
return []types.Comment{}, err if found {
return cacheData.([]Comment), nil
} }
data := gjson.Parse(string(body)) data, err := utils.GetJSON("https://api.imgur.com/comment/v1/comments?client_id=" + client.ClientID + "&filter[post]=eq:" + galleryID + "&include=account,adconfig&per_page=30&sort=best")
if err != nil {
return []Comment{}, nil
}
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
comments := make([]types.Comment, 0) comments := make([]Comment, 0)
data.Get("data").ForEach( data.Get("data").ForEach(
func(key, value gjson.Result) bool { func(key, value gjson.Result) bool {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
comments = append(comments, ParseComment(value)) comments = append(comments, parseComment(value))
}() }()
return true return true
@@ -45,10 +56,18 @@ func FetchComments(galleryID string) ([]types.Comment, error) {
) )
wg.Wait() wg.Wait()
client.Cache.Set(galleryID+"-comments", comments, cache.DefaultExpiration)
return comments, nil return comments, nil
} }
func ParseComment(data gjson.Result) types.Comment { var imgurRe = regexp.MustCompile(`https?://imgur\.com/(gallery|a)?/(.*)`)
var imgurRe2 = regexp.MustCompile(`https?://imgur\.com/(.*)`)
var imgRe = regexp.MustCompile(`https?://i\.imgur\.com/(.*)\.(png|gif|jpe?g|webp)`)
var vidRe = regexp.MustCompile(`https?://i\.imgur\.com/(.*)\.(mp4|webm)`)
var vidFormatRe = regexp.MustCompile(`\.(mp4|webm)`)
var iImgurRe = regexp.MustCompile(`https?://i\.imgur\.com`)
func parseComment(data gjson.Result) Comment {
createdTime, _ := time.Parse("2006-01-02T15:04:05Z", data.Get("created_at").String()) createdTime, _ := time.Parse("2006-01-02T15:04:05Z", data.Get("created_at").String())
createdAt := createdTime.Format("January 2, 2006 3:04 PM") createdAt := createdTime.Format("January 2, 2006 3:04 PM")
updatedAt, _ := utils.FormatDate(data.Get("updated_at").String()) updatedAt, _ := utils.FormatDate(data.Get("updated_at").String())
@@ -57,14 +76,14 @@ func ParseComment(data gjson.Result) types.Comment {
userAvatar := strings.ReplaceAll(data.Get("account.avatar").String(), "https://i.imgur.com", "") userAvatar := strings.ReplaceAll(data.Get("account.avatar").String(), "https://i.imgur.com", "")
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
comments := make([]types.Comment, 0) comments := make([]Comment, 0)
data.Get("comments").ForEach( data.Get("comments").ForEach(
func(key, value gjson.Result) bool { func(key, value gjson.Result) bool {
wg.Add(1) wg.Add(1)
go func() { go func() {
defer wg.Done() defer wg.Done()
comments = append(comments, ParseComment(value)) comments = append(comments, parseComment(value))
}() }()
return true return true
@@ -72,15 +91,49 @@ func ParseComment(data gjson.Result) types.Comment {
) )
wg.Wait() wg.Wait()
return types.Comment{ comment := data.Get("comment").String()
comment = strings.ReplaceAll(comment, "\n", "<br>")
for _, match := range imgRe.FindAllString(comment, -1) {
img := iImgurRe.ReplaceAllString(match, "")
img = `<img src="` + img + `" class="comment__media" loading="lazy"/>`
comment = strings.Replace(comment, match, img, 1)
}
for _, match := range vidRe.FindAllString(comment, -1) {
vid := iImgurRe.ReplaceAllString(match, "")
vid = `<video class="comment__media" controls loop preload="none" poster="` + vidFormatRe.ReplaceAllString(vid, ".webp") + `"><source type="` + strings.Split(vid, ".")[1] + `" src="` + vid + `" /></video>`
comment = strings.Replace(comment, match, vid, 1)
}
for _, l := range linkify.Links(comment) {
origLink := comment[l.Start:l.End]
link := `<a href="` + origLink + `">` + origLink + `</a>`
comment = strings.Replace(comment, origLink, link, 1)
}
comment = imgurRe.ReplaceAllString(comment, "/$1/$2")
comment = imgurRe2.ReplaceAllString(comment, "/$1")
p := bluemonday.UGCPolicy()
p.AllowImages()
p.AllowElements("video", "source")
p.AllowAttrs("src", "tvpe").OnElements("source")
p.AllowAttrs("controls", "loop", "preload", "poster").OnElements("video")
p.AllowAttrs("class", "loading").OnElements("img", "video")
p.RequireNoReferrerOnLinks(true)
p.RequireNoFollowOnLinks(true)
p.RequireCrossOriginAnonymous(true)
comment = p.Sanitize(comment)
return Comment{
Comments: comments, Comments: comments,
User: types.User{ User: User{
Id: data.Get("account.id").Int(), Id: data.Get("account.id").Int(),
Username: data.Get("account.username").String(), Username: data.Get("account.username").String(),
Avatar: userAvatar, Avatar: userAvatar,
}, },
Post: parseSubmission(data.Get("post")),
Id: data.Get("id").String(), Id: data.Get("id").String(),
Comment: data.Get("comment").String(), Comment: comment,
Upvotes: data.Get("upvote_count").Int(), Upvotes: data.Get("upvote_count").Int(),
Downvotes: data.Get("downvote_count").Int(), Downvotes: data.Get("downvote_count").Int(),
Platform: data.Get("platform").String(), Platform: data.Get("platform").String(),

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 */
}

72
api/search.go Normal file
View File

@@ -0,0 +1,72 @@
package api
import (
"fmt"
"net/http"
"net/url"
"strings"
"codeberg.org/rimgo/rimgo/utils"
"github.com/PuerkitoBio/goquery"
)
type SearchResult struct {
Id string
Url string
ImageUrl string
Title string
User string
Points string
Views string
RelTime string
}
func (client *Client) Search(query string, page string) ([]SearchResult, error) {
query = url.QueryEscape(query)
req, err := http.NewRequest("GET", "https://imgur.com/search/all/page/" + page + "?scrolled&q_size_is_mpx=off&qs=list&q=" + query, nil)
if err != nil {
return []SearchResult{}, err
}
utils.SetReqHeaders(req)
res, err := http.DefaultClient.Do(req)
if err != nil {
return []SearchResult{}, err
}
defer res.Body.Close()
if res.StatusCode != 200 {
return []SearchResult{}, fmt.Errorf("invalid status code, got %d", res.StatusCode)
}
doc, err := goquery.NewDocumentFromReader(res.Body)
if err != nil {
return []SearchResult{}, err
}
results := []SearchResult{}
doc.Find(".post-list").Each(func(i int, s *goquery.Selection) {
url, _ := s.Find("a").Attr("href")
imageUrl, _ := s.Find("img").Attr("src")
postInfo := strings.Split(s.Find(".post-info").Text(), "·")
points := strings.TrimSpace(postInfo[0])
points = strings.TrimSuffix(points, " points")
views := strings.TrimSpace(postInfo[1])
views = strings.TrimSuffix(views, " views")
result := SearchResult{
Id: strings.Split(url, "/")[2],
Url: url,
ImageUrl: strings.ReplaceAll(imageUrl, "//i.imgur.com", ""),
Title: s.Find(".search-item-title a").Text(),
User: s.Find(".account").Text(),
Views: views,
Points: points,
RelTime: strings.TrimSpace(postInfo[2]),
}
results = append(results, result)
})
return results, nil
}

110
api/tag.go Normal file
View File

@@ -0,0 +1,110 @@
package api
import (
"io"
"net/http"
"net/url"
"strings"
"github.com/patrickmn/go-cache"
"github.com/tidwall/gjson"
)
type Tag struct {
Tag string
Display string
Sort string
PostCount int64
Posts []Submission
Background string
BackgroundId string
}
func (client *Client) FetchTag(tag string, sort string, page string) (Tag, error) {
// Dots are automatically removed on Imgur, so more cache hits
tag = strings.ReplaceAll(tag, ".", "")
cacheData, found := client.Cache.Get(tag + sort + page + "-tag")
if found {
return cacheData.(Tag), nil
}
req, err := http.NewRequest("GET", "https://api.imgur.com/post/v1/posts/t/"+tag, nil)
if err != nil {
return Tag{}, err
}
q := req.URL.Query()
q.Add("client_id", client.ClientID)
q.Add("include", "cover")
q.Add("page", page)
switch sort {
case "newest":
q.Add("filter[window]", "week")
q.Add("sort", "-time")
case "best":
q.Add("filter[window]", "all")
q.Add("sort", "-top")
case "popular":
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 Tag{}, err
}
body, err := io.ReadAll(res.Body)
if err != nil {
return Tag{}, err
}
data := gjson.Parse(string(body))
posts := make([]Submission, 0)
data.Get("posts").ForEach(
func(key, value gjson.Result) bool {
url, _ := url.Parse(strings.ReplaceAll(value.Get("url").String(), "https://imgur.com", ""))
q := url.Query()
q.Add("tag", tag+"."+sort+"."+page+"."+key.String())
url.RawQuery = q.Encode()
posts = append(posts, Submission{
Id: value.Get("id").String(),
Title: value.Get("title").String(),
Link: url.String(),
Cover: Media{
Id: value.Get("cover_id").String(),
Type: value.Get("cover.type").String(),
Url: strings.ReplaceAll(value.Get("cover.url").String(), "https://i.imgur.com", ""),
},
Points: value.Get("point_count").Int(),
Upvotes: value.Get("upvote_count").Int(),
Downvotes: value.Get("downvote_count").Int(),
Comments: value.Get("comment_count").Int(),
Views: value.Get("view_count").Int(),
IsAlbum: value.Get("is_album").Bool(),
})
return true
},
)
tagData := 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",
}
client.Cache.Set(tag+sort+page+"-tag", tagData, 4*cache.DefaultExpiration)
return tagData, nil
}

107
api/trending.go Normal file
View File

@@ -0,0 +1,107 @@
package api
import (
"fmt"
"io"
"net/http"
"strings"
"sync"
"codeberg.org/rimgo/rimgo/utils"
"github.com/patrickmn/go-cache"
"github.com/tidwall/gjson"
)
func (client *Client) FetchTrending(section, sort, page string) ([]Submission, error) {
cacheData, found := client.Cache.Get(fmt.Sprintf("trending-%s-%s-%s", section, sort, page))
if found {
return cacheData.([]Submission), nil
}
req, err := http.NewRequest("GET", "https://api.imgur.com/post/v1/posts", nil)
if err != nil {
return []Submission{}, err
}
utils.SetReqHeaders(req)
q := req.URL.Query()
q.Add("client_id", client.ClientID)
q.Add("include", "cover")
q.Add("page", page)
switch sort {
case "newest":
q.Add("filter[window]", "week")
q.Add("sort", "-time")
case "best":
q.Add("filter[window]", "all")
q.Add("sort", "-top")
case "popular":
fallthrough
default:
q.Add("filter[window]", "week")
q.Add("sort", "-viral")
sort = "popular"
}
switch section {
case "hot":
q.Add("filter[section]", "eq:hot")
case "new":
q.Add("filter[section]", "eq:new")
case "top":
q.Add("filter[section]", "eq:top")
q.Add("filter[window]", "day")
default:
q.Add("filter[section]", "eq:hot")
section = "hot"
}
req.URL.RawQuery = q.Encode()
res, err := http.DefaultClient.Do(req)
if err != nil {
return []Submission{}, err
}
body, err := io.ReadAll(res.Body)
if err != nil {
return []Submission{}, err
}
data := gjson.Parse(string(body))
wg := sync.WaitGroup{}
posts := make([]Submission, 0)
data.ForEach(
func(key, value gjson.Result) bool {
wg.Add(1)
go func() {
defer wg.Done()
posts = append(posts, Submission{
Id: value.Get("id").String(),
Title: value.Get("title").String(),
Link: strings.ReplaceAll(value.Get("url").String(), "https://imgur.com", ""),
Cover: Media{
Id: value.Get("cover_id").String(),
Type: value.Get("cover.type").String(),
Url: strings.ReplaceAll(value.Get("cover.url").String(), "https://i.imgur.com", ""),
},
Points: value.Get("point_count").Int(),
Upvotes: value.Get("upvote_count").Int(),
Downvotes: value.Get("downvote_count").Int(),
Comments: value.Get("comment_count").Int(),
Views: value.Get("view_count").Int(),
IsAlbum: value.Get("is_album").Bool(),
})
}()
return true
},
)
wg.Wait()
client.Cache.Set(fmt.Sprintf("trending-%s-%s-%s", section, sort, page), posts, cache.DefaultExpiration)
return posts, nil
}

View File

@@ -1,58 +1,86 @@
package api package api
import ( import (
"encoding/json"
"io" "io"
"net/http" "net/http"
"strings" "strings"
"sync" "sync"
"time" "time"
"codeberg.org/video-prize-ranch/rimgo/types" "codeberg.org/rimgo/rimgo/utils"
"github.com/spf13/viper" "github.com/patrickmn/go-cache"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
) )
func FetchUser(username string) (types.User, error) { type User struct {
res, err := http.Get("https://api.imgur.com/account/v1/accounts/" + username + "?client_id=" + viper.GetString("RIMGU_IMGUR_CLIENT_ID")) Id int64
Bio string
Username string
Points int64
Cover string
Avatar string
CreatedAt string
}
type Submission struct {
Id string
Title string
Link string
Cover Media
Points int64
Upvotes int64
Downvotes int64
Comments int64
Views int64
IsAlbum bool
}
func (client *Client) FetchUser(username string) (User, error) {
cacheData, found := client.Cache.Get(username + "-user")
if found {
return cacheData.(User), nil
}
res, err := http.Get("https://api.imgur.com/account/v1/accounts/" + username + "?client_id=" + utils.Config.ImgurId)
if err != nil { if err != nil {
return types.User{}, err return User{}, err
} }
body, err := io.ReadAll(res.Body) body, err := io.ReadAll(res.Body)
if err != nil { if err != nil {
return types.User{}, err return User{}, err
}
var user types.User
err = json.Unmarshal(body, &user)
if err != nil {
return types.User{}, err
}
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")
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"))
if err != nil {
return []types.Submission{}, err
}
body, err := io.ReadAll(res.Body)
if err != nil {
return []types.Submission{}, err
} }
data := gjson.Parse(string(body)) data := gjson.Parse(string(body))
submissions := []types.Submission{} createdTime, _ := time.Parse(time.RFC3339, data.Get("created_at").String())
user := 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"),
}
client.Cache.Set(username+"-user", user, 1*time.Hour)
return user, nil
}
func (client *Client) FetchSubmissions(username string, sort string, page string) ([]Submission, error) {
cacheData, found := client.Cache.Get(username + "-submissions-" + sort + page)
if found {
return cacheData.([]Submission), nil
}
data, err := utils.GetJSON("https://api.imgur.com/3/account/" + username + "/submissions/" + page + "/" + sort + "?album_previews=1&client_id=" + utils.Config.ImgurId)
if err != nil {
return []Submission{}, err
}
submissions := []Submission{}
wg := sync.WaitGroup{} wg := sync.WaitGroup{}
data.Get("data").ForEach( data.Get("data").ForEach(
@@ -62,30 +90,159 @@ func FetchSubmissions(username string, sort string, page string) ([]types.Submis
go func() { go func() {
defer wg.Done() defer wg.Done()
cover := value.Get("images.#(id==\"" + value.Get("cover").String() + "\")") submissions = append(submissions, parseSubmission(value))
submissions = append(submissions, types.Submission{
Id: value.Get("id").String(),
Link: strings.ReplaceAll(value.Get("link").String(), "https://imgur.com", ""),
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(),
})
}() }()
return true return true
}, },
) )
wg.Wait() wg.Wait()
client.Cache.Set(username+"-submissions-"+sort+page, submissions, 15*time.Minute)
return submissions, nil return submissions, nil
} }
func (client *Client) FetchUserFavorites(username string, sort string, page string) ([]Submission, error) {
cacheData, found := client.Cache.Get(username + "-favorites-" + sort + page)
if found {
return cacheData.([]Submission), nil
}
req, err := http.NewRequest("GET", "https://api.imgur.com/3/account/"+username+"/gallery_favorites/"+page+"/"+sort, nil)
if err != nil {
return []Submission{}, err
}
utils.SetReqHeaders(req)
q := req.URL.Query()
q.Add("client_id", client.ClientID)
req.URL.RawQuery = q.Encode()
res, err := http.DefaultClient.Do(req)
if err != nil {
return []Submission{}, err
}
body, err := io.ReadAll(res.Body)
if err != nil {
return []Submission{}, err
}
data := gjson.Parse(string(body))
submissions := []Submission{}
wg := sync.WaitGroup{}
data.Get("data").ForEach(
func(key, value gjson.Result) bool {
wg.Add(1)
go func() {
defer wg.Done()
submissions = append(submissions, parseSubmission(value))
}()
return true
},
)
wg.Wait()
client.Cache.Set(username+"-favorites-"+sort+page, submissions, 15*time.Minute)
return submissions, nil
}
func (client *Client) FetchUserComments(username string) ([]Comment, error) {
cacheData, found := client.Cache.Get(username + "-usercomments")
if found {
return cacheData.([]Comment), nil
}
req, err := http.NewRequest("GET", "https://api.imgur.com/comment/v1/comments", nil)
if err != nil {
return []Comment{}, err
}
utils.SetReqHeaders(req)
q := req.URL.Query()
q.Add("client_id", client.ClientID)
q.Add("filter[account]", "eq:"+username)
q.Add("include", "account,post")
q.Add("sort", "new")
req.URL.RawQuery = q.Encode()
res, err := http.DefaultClient.Do(req)
if err != nil {
return []Comment{}, err
}
body, err := io.ReadAll(res.Body)
if err != nil {
return []Comment{}, err
}
data := gjson.Parse(string(body))
comments := make([]Comment, 0)
data.Get("data").ForEach(
func(key, value gjson.Result) bool {
comments = append(comments, parseComment(value))
return true
},
)
client.Cache.Set(username+"-usercomments", comments, cache.DefaultExpiration)
return comments, nil
}
func parseSubmission(value gjson.Result) Submission {
var cover Media
c := value.Get("cover")
coverData := value.Get("images.#(id==\"" + c.String() + "\")")
switch {
case c.Type == gjson.String && coverData.Exists():
cover = Media{
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", ""),
}
// This case is when fetching comments
case c.Type != gjson.Null:
cover = Media{
Id: c.Get("id").String(),
Url: strings.ReplaceAll(c.Get("url").String(), "https://i.imgur.com", ""),
}
// Replace with thumbnails here because it's easier.
if strings.HasSuffix(cover.Url, ".mp4") {
cover.Url = cover.Url[:len(cover.Url)-3] + "webp"
}
default:
cover = Media{
Id: value.Get("id").String(),
Description: value.Get("description").String(),
Type: strings.Split(value.Get("type").String(), "/")[0],
Url: strings.ReplaceAll(value.Get("link").String(), "https://i.imgur.com", ""),
}
}
id := value.Get("id").String()
link := "/a/" + id
if value.Get("in_gallery").Bool() {
link = "/gallery/" + id
}
return Submission{
Id: id,
Link: link,
Title: value.Get("title").String(),
Cover: cover,
Points: value.Get("points").Int(),
Upvotes: value.Get("ups").Int(),
Downvotes: value.Get("downs").Int(),
Comments: value.Get("comment_count").Int(),
Views: value.Get("views").Int(),
IsAlbum: value.Get("is_album").Bool(),
}
}

View File

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

View File

@@ -1,11 +1,15 @@
version: '3'
services: services:
rimgo: rimgo:
#image: quay.io/pussthecatorg/rimgo # Uncomment to use image image: codeberg.org/rimgo/rimgo # Official image
build: . #image: quay.io/pussthecatorg/rimgo # Unofficial image
#build: . # Uncomment to build from source
ports: ports:
- 3000:3000 - 3000:3000
volumes:
- ./config.yml:/app/config.yml
restart: unless-stopped restart: unless-stopped
user: 65534:65534 # equivalent to `nobody`
read_only: true
security_opt:
- no-new-privileges
cap_drop:
- ALL
env_file: .env

63
go.mod
View File

@@ -1,36 +1,43 @@
module codeberg.org/video-prize-ranch/rimgo module codeberg.org/rimgo/rimgo
go 1.17 go 1.24.0
require ( require (
github.com/dustin/go-humanize v1.0.0 github.com/PuerkitoBio/goquery v1.11.0
github.com/gofiber/fiber/v2 v2.24.0 github.com/dustin/go-humanize v1.0.1
github.com/gofiber/template v1.6.21 github.com/gofiber/fiber/v2 v2.52.10
github.com/spf13/viper v1.10.1 github.com/gofiber/template/handlebars/v2 v2.1.12
github.com/tidwall/gjson v1.12.1 github.com/gorilla/feeds v1.2.0
github.com/joho/godotenv v1.5.1
github.com/mailgun/raymond/v2 v2.0.48
github.com/microcosm-cc/bluemonday v1.0.27
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/tidwall/gjson v1.18.0
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3
) )
require ( require (
github.com/andybalholm/brotli v1.0.2 // indirect github.com/andybalholm/brotli v1.2.0 // indirect
github.com/aymerick/raymond v2.0.2+incompatible // indirect github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/fsnotify/fsnotify v1.5.1 // indirect github.com/aymerick/douceur v0.2.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect github.com/clipperhouse/stringish v0.1.1 // indirect
github.com/klauspost/compress v1.13.4 // indirect github.com/clipperhouse/uax29/v2 v2.3.0 // indirect
github.com/magiconair/properties v1.8.5 // indirect github.com/gofiber/template v1.8.3 // indirect
github.com/mitchellh/mapstructure v1.4.3 // indirect github.com/gofiber/utils v1.2.0 // indirect
github.com/pelletier/go-toml v1.9.4 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/spf13/afero v1.6.0 // indirect github.com/gorilla/css v1.0.1 // indirect
github.com/spf13/cast v1.4.1 // indirect github.com/klauspost/compress v1.18.2 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/spf13/pflag v1.0.5 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/subosito/gotenv v1.2.0 // indirect github.com/mattn/go-runewidth v0.0.19 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/philhofer/fwd v1.2.0 // indirect
github.com/tidwall/pretty v1.2.0 // indirect github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tidwall/match v1.2.0 // indirect
github.com/tidwall/pretty v1.2.1 // indirect
github.com/tinylib/msgp v1.6.3 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.31.0 // indirect github.com/valyala/fasthttp v1.68.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect golang.org/x/net v0.48.0 // indirect
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 // indirect golang.org/x/sys v0.39.0 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.32.0 // indirect
gopkg.in/ini.v1 v1.66.2 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
) )

942
go.sum
View File

@@ -1,845 +1,163 @@
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/PuerkitoBio/goquery v1.11.0 h1:jZ7pwMQXIITcUXNH83LLk+txlaEy6NVOfTuP43xxfqw=
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw= github.com/PuerkitoBio/goquery v1.11.0/go.mod h1:wQHgxUOU3JGuj3oD/QFfxUdlzW6xPHfqyHre6VMY4DQ=
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU= github.com/andybalholm/brotli v1.2.0 h1:ukwgCxwYrmACq68yiUqwIWnGY0cTPox/M94sVwToPjQ=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU= github.com/andybalholm/brotli v1.2.0/go.mod h1:rzTDkvFWvIrjDXZHkuS16NPggd91W3kUSvPlQ1pLaKY=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY= github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc= github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
cloud.google.com/go v0.46.3/go.mod h1:a6bKKbmY7er1mI7TEI4lsAkts/mkhTSZK8w33B4RAg0= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
cloud.google.com/go v0.50.0/go.mod h1:r9sluTvynVuxRIOHXQEHMFffphuXHOMZMycpNR5e6To= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
cloud.google.com/go v0.52.0/go.mod h1:pXajvRH/6o3+F9jDHZWQ5PbGhn+o8w9qiu/CffaVdO4= github.com/clipperhouse/stringish v0.1.1 h1:+NSqMOr3GR6k1FdRhhnXrLfztGzuG+VuFDfatpWHKCs=
cloud.google.com/go v0.53.0/go.mod h1:fp/UouUEsRkN6ryDKNW/Upv/JBKnv6WDthjR6+vze6M= github.com/clipperhouse/stringish v0.1.1/go.mod h1:v/WhFtE1q0ovMta2+m+UbpZ+2/HEXNWYXQgCt4hdOzA=
cloud.google.com/go v0.54.0/go.mod h1:1rq2OEkV3YMf6n/9ZvGWI3GWw0VoqH/1x2nd8Is/bPc= github.com/clipperhouse/uax29/v2 v2.3.0 h1:SNdx9DVUqMoBuBoW3iLOj4FQv3dN5mDtuqwuhIGpJy4=
cloud.google.com/go v0.56.0/go.mod h1:jr7tqZxxKOVYizybht9+26Z/gUq7tiRzu+ACVAMbKVk= github.com/clipperhouse/uax29/v2 v2.3.0/go.mod h1:Wn1g7MK6OoeDT0vL+Q0SQLDz/KpfsVRgg6W7ihQeh4g=
cloud.google.com/go v0.57.0/go.mod h1:oXiQ6Rzq3RAkkY7N6t3TcE6jE+CIBBbA36lwQ1JyzZs=
cloud.google.com/go v0.62.0/go.mod h1:jmCYTdRCQuc1PHIIJ/maLInMho30T/Y0M4hTdTShOYc=
cloud.google.com/go v0.65.0/go.mod h1:O5N8zS7uWy9vkA9vayVHs65eM1ubvY4h553ofrNHObY=
cloud.google.com/go v0.72.0/go.mod h1:M+5Vjvlc2wnp6tjzE102Dw08nGShTscUx2nZMufOKPI=
cloud.google.com/go v0.74.0/go.mod h1:VV1xSbzvo+9QJOxLDaJfTjx5e+MePCpCWwvftOeQmWk=
cloud.google.com/go v0.78.0/go.mod h1:QjdrLG0uq+YwhjoVOLsS1t7TW8fs36kLs4XO5R5ECHg=
cloud.google.com/go v0.79.0/go.mod h1:3bzgcEeQlzbuEAYu4mrWhKqWjmpprinYgKJLgKHnbb8=
cloud.google.com/go v0.81.0/go.mod h1:mk/AM35KwGk/Nm2YSeZbxXdrNK3KZOYHmLkOqC2V6E0=
cloud.google.com/go v0.83.0/go.mod h1:Z7MJUsANfY0pYPdw0lbnivPx4/vhy/e2FEkSkF7vAVY=
cloud.google.com/go v0.84.0/go.mod h1:RazrYuxIK6Kb7YrzzhPoLmCVzl7Sup4NrbKPg8KHSUM=
cloud.google.com/go v0.87.0/go.mod h1:TpDYlFy7vuLzZMMZ+B6iRiELaY7z/gJPaqbMx6mlWcY=
cloud.google.com/go v0.90.0/go.mod h1:kRX0mNRHe0e2rC6oNakvwQqzyDmg57xJ+SZU1eT2aDQ=
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.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=
cloud.google.com/go/bigquery v1.4.0/go.mod h1:S8dzgnTigyfTmLBfrtrhyYhwRxG72rYxvftPBK2Dvzc=
cloud.google.com/go/bigquery v1.5.0/go.mod h1:snEHRnqQbz117VIFhE8bmtwIDY80NLUZUMb4Nv6dBIg=
cloud.google.com/go/bigquery v1.7.0/go.mod h1://okPTzCYNXSlb24MZs83e2Do+h+VXtc4gLoIoXIAPc=
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=
cloud.google.com/go/pubsub v1.2.0/go.mod h1:jhfEVHT8odbXTkndysNHCcx0awwzvfOlguIAii9o8iA=
cloud.google.com/go/pubsub v1.3.1/go.mod h1:i+ucay31+CNRpDW4Lu78I4xXG+O1r/MAHgjpRVR+TSU=
cloud.google.com/go/storage v1.0.0/go.mod h1:IhtSnM/ZTZV8YYJWCY8RULGVqBDmpoyjwiyrjsg+URw=
cloud.google.com/go/storage v1.5.0/go.mod h1:tpKbwo567HUNpVclU5sGELwQWBDZ8gh0ZeosJ0Rtdos=
cloud.google.com/go/storage v1.6.0/go.mod h1:N7U0C8pVQ/+NIKOBQyamJIeKQKkZ+mxpohlUTyfDhBk=
cloud.google.com/go/storage v1.8.0/go.mod h1:Wv1Oy7z6Yz3DshWRJFhqM/UCfaWIRTdp0RXyy7KQOVs=
cloud.google.com/go/storage v1.10.0/go.mod h1:FLPqc6j+Ki4BU591ie1oL6qBQGu2Bl/tZ9ullr3+Kg0=
dmitri.shuralyov.com/gpu/mtl v0.0.0-20190408044501-666a987793e9/go.mod h1:H6x//7gZCb22OMCxBHrMx7a5I7Hp++hsVxbQ4BYO7hU=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/CloudyKit/fastprinter v0.0.0-20200109182630-33d98a066a53/go.mod h1:+3IMCy2vIlbG1XG/0ggNQv0SvxCAIpPM5b1nCz56Xno=
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/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/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=
github.com/armon/go-metrics v0.3.10/go.mod h1:4O98XIr/9W0sxpJ8UaYkvjk10Iff7SnFrb4QAOwNTFc=
github.com/armon/go-radix v0.0.0-20180808171621-7fddfc383310/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/armon/go-radix v1.0.0/go.mod h1:ufUuZ+zHj4x4TnLV4JWEpy2hxWSpsRywHrMgIH9cCH8=
github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0=
github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
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/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=
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/cespare/xxhash/v2 v2.1.2/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
github.com/circonus-labs/circonus-gometrics v2.3.1+incompatible/go.mod h1:nmEj6Dob7S7YxXgwXpfOuvO54S+tGdZdw9fuRZt25Ag=
github.com/circonus-labs/circonusllhist v0.1.3/go.mod h1:kMXHVDlOchFAehlya5ePtbp5jckzBHf4XRpQvBOLI+I=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
github.com/cncf/xds/go v0.0.0-20210312221358-fbca930ec8ed/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210805033703-aa0b78936158/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
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/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.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/eknkc/amber v0.0.0-20171010120322-cdade1c07385/go.mod h1:0vRUJqYpeSZifjYj7uP3BG/gKcuzL9xWVV/Y+cK33KM= github.com/gofiber/fiber/v2 v2.52.10 h1:jRHROi2BuNti6NYXmZ6gbNSfT3zj/8c0xy94GOU5elY=
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/gofiber/fiber/v2 v2.52.10/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4= github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98= github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
github.com/envoyproxy/go-control-plane v0.9.7/go.mod h1:cwu0lG7PUMfa9snN8LXBig5ynNVH9qI8YYLbd1fK2po= github.com/gofiber/template/handlebars/v2 v2.1.12 h1:uWBMEnhTxVyarRjyj5uDrNg8rVMGzi6fhsL+PAJBvb0=
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/gofiber/template/handlebars/v2 v2.1.12/go.mod h1:K3h933a8wPFjIrLRUcnIVPTUW867ND6gqpw0zZ3yKpk=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210217033140-668b12f5399d/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk= github.com/gofiber/utils v1.2.0 h1:NCaqd+Efg3khhN++eeUUTyBz+byIxAsmIjpl8kKOMIc=
github.com/envoyproxy/go-control-plane v0.9.9-0.20210512163311-63b5d3c536b0/go.mod h1:hliV/p42l8fGbc6Y9bQ70uLwIvmJyVE5k4iMKlh8wCQ= github.com/gofiber/utils v1.2.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
github.com/envoyproxy/go-control-plane v0.9.10-0.20210907150352-cf90f659a021/go.mod h1:AFq3mo9L8Lqqiid3OhADV3RfLJnjiw63cSpi+fDTRC0= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/envoyproxy/go-control-plane v0.10.1/go.mod h1:AY7fTTXNdv/aJ2O5jwpxAPOWUZ7hQAEvzN5Pf27BkQQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/envoyproxy/protoc-gen-validate v0.6.2/go.mod h1:2t7qjJNvHPx8IjnBOzl9E9/baC+qXE/TeeyBRzgJDws= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU= github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc=
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk= github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
github.com/flosch/pongo2/v4 v4.0.2/go.mod h1:B5ObFANs/36VwxxlgKpdchIJHMvHB562PW+BWPhwZD8= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/fsnotify/fsnotify v1.5.1 h1:mZcQUHVQUQWoPXXtuf9yuEXKudkV2sx1E06UadKWpgI= github.com/klauspost/compress v1.18.2 h1:iiPHWW0YrcFgpBYhsA6D1+fqHssJscY/Tm/y2Uqnapk=
github.com/fsnotify/fsnotify v1.5.1/go.mod h1:T3375wBYaZdLLcVNkcVbzGHY7f1l/uK5T5Ai1i3InKU= github.com/klauspost/compress v1.18.2/go.mod h1:R0h/fSBs8DE4ENlcrlib3PsXS61voFxhIs2DeRhCvJ4=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/go-gl/glfw v0.0.0-20190409004039-e6da0acd62b1/go.mod h1:vR7hzQXu2zJy9AVAgeJqvqgH9Q5CA+iKCZ2gyEVpxRU= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20191125211704-12ad95a8df72/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-gl/glfw/v3.3/glfw v0.0.0-20200222043503-6f7a984d4dc4/go.mod h1:tQ2UAYgL5IevRw8kRxooKSPJfGvJ9fJQFa0TUsXzTg8=
github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as=
github.com/go-logfmt/logfmt v0.3.0/go.mod h1:Qt1PoO58o5twSAckw1HlFXLmHsOX5/0LbT9GBnD5lWE=
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/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=
github.com/golang/groupcache v0.0.0-20190702054246-869f871628b6/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20191227052852-215e87163ea7/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.2.0/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
github.com/golang/mock v1.3.1/go.mod h1:sBzyDLLjw3U8JLTeZvSv8jJB+tU5PVekmnlKIyFUx0Y=
github.com/golang/mock v1.4.0/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.1/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.3/go.mod h1:UOMv5ysSaYNkG+OFQykRIcU/QvvxJf3p21QfJ2Bt3cw=
github.com/golang/mock v1.4.4/go.mod h1:l3mdAwkq5BuhzHwde/uurv3sEJeZMXNpwsxVWU71h+4=
github.com/golang/mock v1.5.0/go.mod h1:CWnOUgYIOo4TcNZ0wHX3YZCqsaM1I1Jvs6v3mP3KVu8=
github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+LicevLPs=
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk=
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.1/go.mod h1:DopwsBzvsk0Fs44TXzsVbJyPhcCPeIwnvohx4u74HPM=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.4.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.1/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/martian/v3 v3.0.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.1.0/go.mod h1:y5Zk1BBys9G+gd6Jrk0W3cC1+ELVxBWuIGO+w/tUAp0=
github.com/google/martian/v3 v3.2.1/go.mod h1:oBOf6HBosgwRXnUGWUB05QECsc6uvmMiJ3+6W4l/CUk=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/pprof v0.0.0-20191218002539-d4f498aebedc/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200212024743-f11f1df84d12/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200229191704-1ebb73c60ed3/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200430221834-fc25d7d30c6d/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20200708004538-1a94d8640e99/go.mod h1:ZgVRPoUq/hfqzAqh7sHMqb3I9Rq5C59dIz2SbBwJ4eM=
github.com/google/pprof v0.0.0-20201023163331-3e6fc7fc9c4c/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20201203190320-1bf35d6f28c2/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210122040257-d980be63207e/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210226084205-cbba55b83ad5/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210601050228-01bbb1931b22/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210609004039-a478d1d731e9/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/pprof v0.0.0-20210720184732-4bb14d4b1be1/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
github.com/google/renameio v0.1.0/go.mod h1:KWCgfxg9yswjAJkECMjeO8J8rahYeXnNhOm40UhjYkI=
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
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/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=
github.com/hashicorp/go-cleanhttp v0.5.1/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-cleanhttp v0.5.2/go.mod h1:kO/YDlP8L1346E6Sodw+PrpBSV4/SoxCXGY6BqNFT48=
github.com/hashicorp/go-hclog v0.12.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-hclog v1.0.0/go.mod h1:whpDNt7SSdeAju8AWKIWsul05p54N/39EeqMAyrmvFQ=
github.com/hashicorp/go-immutable-radix v1.0.0/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-immutable-radix v1.3.1/go.mod h1:0y9vanUI8NX6FsYoO3zeMjhV/C5i9g4Q3DwcSNZ4P60=
github.com/hashicorp/go-msgpack v0.5.3/go.mod h1:ahLV/dePpqEmjfWmKiqvPkv/twdG7iPBM1vqhUKIvfM=
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.4/go.mod h1:mtBihi+LeNXGtG8L9dX59gAEa12BDtBQSp4v/YAJqrc=
github.com/hashicorp/memberlist v0.1.3/go.mod h1:ajVTdAv/9Im8oMAAj5G31PhhMCZJV2pPBoIllUwCN7I=
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.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=
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.11/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
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/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=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
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 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= 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/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
github.com/magiconair/properties v1.8.5 h1:b6kJs+EmPFMYGkow9GiUyCyOvIwYetYJ3fSaWak/Gls= github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
github.com/magiconair/properties v1.8.5/go.mod h1:y3VJvCyxH9uVvJTWEGAELF3aiYNyPKd5NZ3oSwXrF60= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-colorable v0.1.6/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc= github.com/mattn/go-runewidth v0.0.19 h1:v++JhqYnZuu5jSKrk9RbgF5v4CGUjqRfBm05byFGLdw=
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4= github.com/mattn/go-runewidth v0.0.19/go.mod h1:XBkDxAl56ILZc9knddidhrOlY5R/pDhgLpndooCuJAs=
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s= github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/mattn/go-isatty v0.0.10/go.mod h1:qgIWMr58cqv1PHHyhnkY9lrL7etaEgOFcMEpPG5Rm84= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/philhofer/fwd v1.2.0 h1:e6DnBTl7vGY+Gz322/ASL4Gyp1FspeMvx1RNDoToZuM=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/philhofer/fwd v1.2.0/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/mattn/go-slim v0.0.0-20200618151855-bde33eecb5ee/go.mod h1:ma9TUJeni8LGZMJvOwbAv/FOwiwqIMQN570LnpqCBSM=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
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=
github.com/modern-go/reflect2 v0.0.0-20180701023420-4b7aa43c6742/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
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/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 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 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/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/prometheus/client_golang v1.0.0/go.mod h1:db9x61etRT2tGnBNRi70OPL5FsnadC4Ky3P0J6CfImo= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/prometheus/client_golang v1.4.0/go.mod h1:e9GMxYsXl05ICDXkRhurwBS4Q3OK1iX/F2sw+iXX5zU= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/prometheus/client_model v0.0.0-20180712105110-5c3871d89910/go.mod h1:MbSGuTsp3dbXC40dX6PRTWyKYBIrTGTE9sqQNg2J8bo=
github.com/prometheus/client_model v0.0.0-20190129233127-fd36f4220a90/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/client_model v0.2.0/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
github.com/prometheus/common v0.4.1/go.mod h1:TNfzLD0ON7rHzMJeJkieUDPYmFC7Snx/y86RQel1bk4=
github.com/prometheus/common v0.9.1/go.mod h1:yhUN8i9wzaXS3w1O07YhxHEBxD+W35wd8bs7vj7HSQ4=
github.com/prometheus/procfs v0.0.0-20181005140218-185b4288413d/go.mod h1:c3At6R/oaqEKCNdg8wHV1ftS6bRYblBhIjjI8uT2IGk=
github.com/prometheus/procfs v0.0.2/go.mod h1:TjEm7ze935MbeOT/UhFTIMYKhuLP4wbCsTZCD3I8kEA=
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/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/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/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/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 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= github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
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/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/subosito/gotenv v1.2.0 h1:Slr1R9HxAlEKefgq5jn9U+DnETlIUa6HfgEzj0g5d7s= github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/subosito/gotenv v1.2.0/go.mod h1:N0PQaV/YGNqwC0u51sEeR/aUtSLEXKX9iv69rRypqCw= github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/gjson v1.12.1 h1:ikuZsLdhr8Ws0IdROXUS1Gi4v9Z4pGqpX/CvJkxvfpo= github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
github.com/tidwall/gjson v1.12.1/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/tidwall/gjson v1.18.0/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/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs= github.com/tidwall/match v1.2.0 h1:0pt8FlkOwjN2fPt4bIl4BoNxb98gGHN2ObFEDkrfZnM=
github.com/tidwall/match v1.2.0/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tv42/httpunix v0.0.0-20150427012821-b75d8614f926/go.mod h1:9ESjWnEqriFuLhtthL60Sar/7RFoluCcXsuvEwTV5KM= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tinylib/msgp v1.6.3 h1:bCSxiTz386UTgyT1i0MSCvdbWjVW+8sG3PjkGsZQt4s=
github.com/tinylib/msgp v1.6.3/go.mod h1:RSp0LW9oSxFut3KzESt5Voq4GVWyS+PSulT77roAqEA=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.31.0 h1:lrauRLII19afgCs2fnWRJ4M5IkV0lo2FqA61uGkNBfE= github.com/valyala/fasthttp v1.68.0 h1:v12Nx16iepr8r9ySOwqI+5RBJ/DqTxhOy1HrHoDFnok=
github.com/valyala/fasthttp v1.31.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= github.com/valyala/fasthttp v1.68.0/go.mod h1:5EXiRfYQAoiO/khu4oU9VISC/eVY6JqmSpPJoHCKsz4=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yosssi/ace v0.0.5/go.mod h1:ALfIzm2vT7t5ZE7uoIZqF3TQ7SAOyupFZnkrF5id+K0= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3 h1:1Coh5BsUBlXoEJmIEaNzVAWrtg9k7/eJzailMQr1grw=
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8=
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=
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=
go.opencensus.io v0.22.2/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.3/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.4/go.mod h1:yxeiOL68Rb0Xd1ddK5vPZ/oVn4vY4Ynel7k9FzqtOIw=
go.opencensus.io v0.22.5/go.mod h1:5pWMHQbX5EPX2/62yrJeAkowc+lfs/XD7Uxpq3pI6kk=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
go.uber.org/zap v1.17.0/go.mod h1:MXVU+bhUf/A7Xi2HNOnopQOrmycQ5Ih87HtOu4q5SSo=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181029021203-45a5f77698d3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/crypto v0.0.0-20190923035154-9ee001bba392/go.mod h1:/lpIB1dKB+9EgE3H3cr1v9wB50oz8l4C4h62xy7jSTY= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=
golang.org/x/exp v0.0.0-20190829153037-c13cbed26979/go.mod h1:86+5VVa7VpoJ4kLfm080zCjGlMRFzhUhsZKEZO7MGek=
golang.org/x/exp v0.0.0-20191030013958-a1ab85dbe136/go.mod h1:JXzH8nQsPlswgeRAPE3MuO9GYsAcnJvJ4vnMwN/5qkY=
golang.org/x/exp v0.0.0-20191129062945-2f5052295587/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20191227195350-da58074b4299/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200119233911-0405dc783f0a/go.mod h1:2RIsYlXP63K8oxa1u096TMicItID8zy7Y6sNkU49FU4=
golang.org/x/exp v0.0.0-20200207192155-f17229e696bd/go.mod h1:J/WKrq2StrnmMY6+EHIKF9dgMWnmCNThgcyBT1FY9mM=
golang.org/x/exp v0.0.0-20200224162631-6cc2880d07d6/go.mod h1:3jZMyOhIsHpP37uCMkUooju7aAi5cS1Q23tOzKc+0MU=
golang.org/x/image v0.0.0-20190227222117-0694c2d4d067/go.mod h1:kZ7UVZpmo3dzQBMxlp+ypCbDeSB+sBbTgSJuh5dn5js=
golang.org/x/image v0.0.0-20190802002840-cff245a6509b/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
golang.org/x/lint v0.0.0-20190301231843-5614ed5bae6f/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190409202823-959b441ac422/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190909230951-414d861bb4ac/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
golang.org/x/lint v0.0.0-20191125180803-fdd1cda4f05f/go.mod h1:5qLYkcX4OjUUV8bRuDixDT3tpyyb+LUpUlRWLxfhWrs=
golang.org/x/lint v0.0.0-20200130185559-910be7a94367/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20200302205851-738671d3881b/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPIChWIBhFzV8gjjsPE/fR3IyQdNY=
golang.org/x/mobile v0.0.0-20190312151609-d3739f865fa6/go.mod h1:z+o9i4GpDbdi3rU15maQ/Ox0txvL9dWGYEHz965HBQE=
golang.org/x/mobile v0.0.0-20190719004257-d2bd2a29d028/go.mod h1:E/iHnbuqvinMTCcRqshq8CkpyQDoeVncDDYHnLhea+o=
golang.org/x/mod v0.0.0-20190513183733-4bf6d317e70e/go.mod h1:mXi4GBBbnImb6dmsKGUJ2LatrhH/nqhxcFungHvyanc=
golang.org/x/mod v0.1.0/go.mod h1:0QHyrYULN0/3qlju5TqG8bIK38QM8yzMo5ekMj3DlcY=
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.1.1-0.20191107180719-034126e5016b/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
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/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=
golang.org/x/net v0.0.0-20190327091125-710a502c58a2/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190628185345-da137c7871d7/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190724013045-ca1201d0de80/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190923162816-aa69164e4478/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200222125558-5a598a2470a0/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200506145744-7e3656a0809f/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200520182314-0ba52f642ac2/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
golang.org/x/net v0.0.0-20200625001655-4c5254603344/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201031054903-ff519b6c9102/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201209123823-ac852fbbde11/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210316092652-d523dce5a7f4/go.mod h1:RBQZq4jEuRlivfhVLdyRGr576XBO4/greRjx4P4O3yc= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.0.0-20210410081132-afb366fc7cd1/go.mod h1:9tjilg8BloeKEkVJvy7fQ90B1CfIiPueXVOjqfkSzI8= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.0.0-20210813160813-60bc85c4be6d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY=
golang.org/x/oauth2 v0.0.0-20191202225959-858c2ad4c8b6/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20200902213428-5d25da1a8d43/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201109201403-9fd604954f58/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20201208152858-08078c50e5b5/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
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=
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211005180243-6b3c2da341f1/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A=
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200317015054-43a5402ce75a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20200625203802-6e8e738ad208/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.0.0-20201207232520-09787c993a3a/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20180823144017-11551d06cbcc/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181026203630-95b1ffbd15a5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190502145724-3ef323f4f1fd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
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-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200124204421-9fbb57f87de9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200202164722-d101bd2416d5/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200302150141-5c8b2ff67527/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200501052902-10377860bb8e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200511232937-7e40ca221e25/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200515095857-1151b9dac4a9/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200523222454-059865788121/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200803210538-64077c9b5642/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200905004654-be1d3432aa8f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210220050731-9a76102bfb43/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210305230114-8fe3ee5dd75b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210315160823-c6e025ad8005/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210603125802-9665404d3644/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210816183151-1e6c022a8912/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.0.0-20211124211545-fe61309f8881/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486 h1:5hpz5aRr+W1erYCL5JRhSUBJRph7l9XkNveoExlrKYk= golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.0.0-20211210111614-af8b64212486/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk=
golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks=
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.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/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/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU=
golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
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=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190628153133-6cdbf07be9d0/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190816200558-6889da9d5479/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
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= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20191125144606-a911d9008d1f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.0.0-20191130070609-6e064ea0cf2d/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.0.0-20191216173652-a0e659d51361/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.0.0-20191227053925-7b8e75db28f4/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/tools v0.0.0-20200117161641-43d50277825c/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200122220014-bf1340f18c4a/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28=
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=
golang.org/x/tools v0.0.0-20200312045724-11d5b4c81c7d/go.mod h1:o4KQGtdN14AW+yjsvvwRTJJuXz8XRtIHtEnmAXLyFUw=
golang.org/x/tools v0.0.0-20200331025713-a30bf2db82d4/go.mod h1:Sl4aGygMT6LrqrWclx+PTx3U+LnKx/seiNR+3G19Ar8=
golang.org/x/tools v0.0.0-20200501065659-ab2804fb9c9d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200512131952-2bc93b1c0c88/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200515010526-7d3b6ebf133d/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200618134242-20370b0cb4b2/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200619180055-7c47624df98f/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
golang.org/x/tools v0.0.0-20200729194436-6467de6f59a7/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20200904185747-39188db58858/go.mod h1:Cj7w3i3Rnn0Xh82ur9kSqwfTHTeVxaDqrfMjpcNT6bE=
golang.org/x/tools v0.0.0-20201110124207-079ba7bd75cd/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201201161351-ac6f37ff4c2a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20201208233053-a543418bbed2/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210105154028-b0ab187a4818/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
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/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.13.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.14.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.15.0/go.mod h1:iLdEw5Ide6rF15KTC1Kkl0iskquN2gFfn9o9XIsbkAI=
google.golang.org/api v0.17.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.18.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.19.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.20.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.22.0/go.mod h1:BwFmGc8tA3vsd7r/7kR8DY7iEEGSU04BFxCo5jP/sfE=
google.golang.org/api v0.24.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.28.0/go.mod h1:lIXQywCXRcnZPGlsd8NbLnOjtAoL6em04bJ9+z0MncE=
google.golang.org/api v0.29.0/go.mod h1:Lcubydp8VUV7KeIHD9z2Bys/sm/vGKnG1UHuDBSrHWM=
google.golang.org/api v0.30.0/go.mod h1:QGmEvQ87FHZNiUVJkT14jQNYJ4ZJjdRF23ZXz5138Fc=
google.golang.org/api v0.35.0/go.mod h1:/XrVsuzM0rZmrsbjJutiuftIzeuTQcEeaYcSk/mQ1dg=
google.golang.org/api v0.36.0/go.mod h1:+z5ficQTmoYpPn8LCUNVpK5I7hwkpjbcgqA7I34qYtE=
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=
google.golang.org/api v0.51.0/go.mod h1:t4HdrdoNgyN5cbEfm7Lum0lcLDLiise1F8qDKX00sOU=
google.golang.org/api v0.54.0/go.mod h1:7C4bFFOvVDGXjfDTAsgGwDgAxRDeQ4X8NvUedIt6z3k=
google.golang.org/api v0.55.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
google.golang.org/api v0.56.0/go.mod h1:38yMfeP1kfjsl8isn0tliTjIb1rJXcQi4UXlbqivdVE=
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/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=
google.golang.org/appengine v1.6.1/go.mod h1:i06prIuMbXzDqacNJfV5OdTW448YApPu5ww/cMBSeb0=
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.6/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
google.golang.org/genproto v0.0.0-20190307195333-5fe7a883aa19/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190911173649-1774047e7e51/go.mod h1:IbNlFCBrqXvoKpeg0TB2l7cyZUmoaFKYIwrEpbDKLA8=
google.golang.org/genproto v0.0.0-20191108220845-16a3f7862a1a/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191115194625-c23dd37a84c9/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191216164720-4f79533eabd1/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20191230161307-f3c370f40bfb/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200115191322-ca5a22157cba/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200122232147-0452cf42e150/go.mod h1:n3cpQtvxv34hfy77yVDNjmbRyujviMdxYliBSkLhpCc=
google.golang.org/genproto v0.0.0-20200204135345-fa8e72b47b90/go.mod h1:GmwEX6Z4W5gMy59cAlVYjN9JhxgbQH6Gn+gFDQe2lzA=
google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200228133532-8c2c7df3a383/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200305110556-506484158171/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200312145019-da6875a35672/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200430143042-b979b6f78d84/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200511104702-f5ebc3bea380/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
google.golang.org/genproto v0.0.0-20200515170657-fc4c6c6a6587/go.mod h1:YsZOwe1myG/8QRHRsmBRE1LrgQY60beZKjly0O1fX9U=
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
google.golang.org/genproto v0.0.0-20200618031413-b414f8b61790/go.mod h1:jDfRM7FcilCzHH/e9qn6dsT145K34l5v+OpcnNgKAAA=
google.golang.org/genproto v0.0.0-20200729003335-053ba62fc06f/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200804131852-c06518451d9c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200825200019-8632dd797987/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20200904004341-0bd0a958aa1d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201109203340-2640f1f9cdfb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201201144952-b05cb90ed32e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201210142538-e3217bee35cc/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20201214200347-8c77b98c765d/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210222152913-aa3ee6e6a81c/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210303154014-9728d6b83eeb/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210310155132-4ce2db91004e/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210319143718-93e7006c17a6/go.mod h1:FWY/as6DDZQgahTzZj3fqbO1CbirC29ZNUFHwi0/+no=
google.golang.org/genproto v0.0.0-20210402141018-6c239bbf2bb1/go.mod h1:9lPAdzaEmUacj36I+k7YKbEc5CXzPIeORRgDAUOu28A=
google.golang.org/genproto v0.0.0-20210513213006-bf773b8c8384/go.mod h1:P3QM42oQyzQSnHPnZ/vqoCdDmzH28fzWByN9asMeM8A=
google.golang.org/genproto v0.0.0-20210602131652-f16073e35f0c/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210604141403-392c879c8b08/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210608205507-b6d2f5bf0d7d/go.mod h1:UODoCrxHCcBojKKwX1terBiRUaqAsFqJiF615XL43r0=
google.golang.org/genproto v0.0.0-20210624195500-8bfb893ecb84/go.mod h1:SzzZ/N+nwJDaO1kznhnlzqS8ocJICar6hYhVyhi++24=
google.golang.org/genproto v0.0.0-20210713002101-d411969a0d9a/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210716133855-ce7ef5c701ea/go.mod h1:AxrInvYm1dci+enl5hChSFPOmmUF1+uAa/UsgNRWd7k=
google.golang.org/genproto v0.0.0-20210728212813-7823e685a01f/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210805201207-89edb61ffb67/go.mod h1:ob2IJxKrgPT52GcgX759i1sleT07tiKowYBGbczaW48=
google.golang.org/genproto v0.0.0-20210813162853-db860fec028c/go.mod h1:cFeNkxwySK631ADgubI+/XFU/xp8FD5KIVV4rj8UC5w=
google.golang.org/genproto v0.0.0-20210821163610-241b8fcbd6c8/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210828152312-66f60bf46e71/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210831024726-fe130286e0e2/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210903162649-d08c68adba83/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210909211513-a8c4777a87af/go.mod h1:eFjDcFEctNawg4eG61bRv87N7iHBWyVhJu7u1kqDUXY=
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0/go.mod h1:5CzLGKJ67TSI2B9POpiiyGha0AjJvZIUgRMt1dSmuhc=
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-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=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
google.golang.org/grpc v1.26.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60=
google.golang.org/grpc v1.29.1/go.mod h1:itym6AZVZYACWQqET3MqgPpjcuV5QH3BxFS3IjizoKk=
google.golang.org/grpc v1.30.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.0/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.31.1/go.mod h1:N36X2cJ7JwdamYAgDz+s+rVMFjt3numwzf/HckM8pak=
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
google.golang.org/grpc v1.34.0/go.mod h1:WotjhfgOW/POjDeRt8vscBtXq+2VjORFy659qA51WJ8=
google.golang.org/grpc v1.35.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.36.1/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
google.golang.org/grpc v1.37.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.37.1/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.38.0/go.mod h1:NREThFqKR1f3iQ6oBuvc5LadQuXVGo9rkm5ZGrQdJfM=
google.golang.org/grpc v1.39.0/go.mod h1:PImNr+rS9TWYb2O4/emRugxiyHZ5JyHW5F+RPnDzfrE=
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/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=
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4=
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/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=
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.2.5/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
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 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.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.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/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=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.1-2019.2.3/go.mod h1:a3bituU0lyd329TUQxRnasdCoJDkEUEAqEt0JzvZhAg=
honnef.co/go/tools v0.0.1-2020.1.3/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
honnef.co/go/tools v0.0.1-2020.1.4/go.mod h1:X/FiERA/W4tHapMX5mGpAtMSVEeEUOyHaw9vFzvIQ3k=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
rsc.io/sampler v1.3.0/go.mod h1:T1hPZKmBbMNahiBKFy5HrXp6adAjACjK9JXDnKaTXpA=

162
instances.json Normal file
View File

@@ -0,0 +1,162 @@
[
{
"url": "https://rimgo.pussthecat.org",
"countries": [
"de"
],
"cloudflare": false
},
{
"url": "https://rimgo.totaldarkness.net",
"countries": [
"ca"
],
"cloudflare": false
},
{
"url": "https://rimgo.bus-hit.me",
"countries": [
"ca"
],
"cloudflare": false
},
{
"url": "https://imgur.artemislena.eu",
"onion": "http://imgur.lpoaj7z2zkajuhgnlltpeqh3zyq7wk2iyeggqaduhgxhyajtdt2j7wad.onion",
"countries": [
"de"
],
"cloudflare": false
},
{
"url": "https://imgur.010032.xyz",
"countries": [
"kr"
],
"cloudflare": false
},
{
"url": "https://i.habedieeh.re",
"onion": "http://i.habeehrhadazsw3izbrbilqajalfyqqln54mrja3iwpqxgcuxnus7eid.onion",
"i2p": [
"rimgo.i2p",
"rimgov7l2tqyrm5txrtvhtnfyrzkc5d7ipafofavchbnnyog4r3q.b32.i2p"
],
"countries": [
"ca"
],
"cloudflare": false
},
{
"url": "https://rimgo.hostux.net",
"countries": [
"fr"
],
"cloudflare": false
},
{
"url": "https://ri.zzls.xyz",
"onion": "http://rimgo.zzlsghu6mvvwyy75mvga6gaf4znbp3erk5xwfzedb4gg6qqh2j6rlvid.onion",
"i2p": [
"rimgo.zzls.i2p",
"p57356k2xwhxrg2lxrjajcftkrptv4zejeeblzfgkcvpzuetkz2a.b32.i2p"
],
"countries": [
"cl"
],
"cloudflare": false
},
{
"url": "https://rimgo.lunar.icu",
"countries": [
"de"
],
"cloudflare": true
},
{
"url": "https://rimgo.kling.gg",
"onion": "http://tdn7zoxctmsopey77mp4eg2gazaudyhgbuyytf4zpk5u7lknlxlgbnid.onion",
"i2p": "http://ovzamsts5czfx3jasbbhbccyyl2z7qmdngtlqxdh4oi7abhdz3ia.b32.i2p",
"countries": [
"nl"
],
"cloudflare": false
},
{
"url": "https://rimgo.eu.projectsegfau.lt",
"countries": [
"fr"
],
"cloudflare": false
},
{
"url": "https://rimgo.us.projectsegfau.lt",
"countries": [
"us"
],
"cloudflare": false
},
{
"url": "https://rimgo.in.projectsegfau.lt",
"countries": [
"in"
],
"cloudflare": false
},
{
"url": "https://rimgo.fascinated.cc",
"countries": [
"us"
],
"cloudflare": false
},
{
"url": "https://rimgo.whateveritworks.org",
"countries": [
"de"
],
"cloudflare": true
},
{
"url": "https://rimgo.nohost.network",
"countries": [
"mx"
],
"cloudflare": false
},
{
"url": "https://rimgo.catsarch.com",
"countries": [
"us"
],
"cloudflare": false
},
{
"url": "https://rimgo.frontendfriendly.xyz",
"countries": [
"de"
],
"cloudflare": false
},
{
"url": "https://rimgo.drgns.space",
"countries": [
"us"
],
"cloudflare": false
},
{
"url": "https://rimgo.quantenzitrone.eu",
"countries": [
"cz"
],
"cloudflare": false
},
{
"url": "https://rimgo.frylo.net",
"countries": [
"nl"
],
"cloudflare": false
}
]

145
main.go
View File

@@ -1,62 +1,147 @@
package main package main
import ( import (
"flag"
"fmt" "fmt"
"net/http" "net/http"
"os"
"time"
"codeberg.org/video-prize-ranch/rimgo/pages" "codeberg.org/rimgo/rimgo/pages"
"codeberg.org/video-prize-ranch/rimgo/static" "codeberg.org/rimgo/rimgo/static"
"codeberg.org/video-prize-ranch/rimgo/views" "codeberg.org/rimgo/rimgo/utils"
"codeberg.org/rimgo/rimgo/views"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cache"
"github.com/gofiber/fiber/v2/middleware/filesystem" "github.com/gofiber/fiber/v2/middleware/filesystem"
"github.com/gofiber/template/handlebars" "github.com/gofiber/fiber/v2/middleware/recover"
"github.com/spf13/viper" "github.com/gofiber/template/handlebars/v2"
"github.com/joho/godotenv"
"github.com/mailgun/raymond/v2"
) )
func main() { func main() {
viper.SetConfigName("config") envPath := flag.String("c", ".env", "Path to env file")
viper.SetConfigType("yml") godotenv.Load(*envPath)
viper.AddConfigPath("/etc/rimgu/") utils.LoadConfig()
viper.AddConfigPath("$HOME/.config/rimgu")
viper.AddConfigPath(".")
viper.AutomaticEnv()
viper.SetDefault("RIMGU_PORT", "3000") pages.InitializeApiClient()
viper.SetDefault("RIMGU_HOST", "localhost")
viper.SetDefault("RIMGU_ADDRESS", "0.0.0.0")
viper.SetDefault("RIMGU_IMGUR_CLIENT_ID", "546c25a59c58ad7")
err := viper.ReadInConfig() views := http.FS(views.GetFiles())
if err != nil { if os.Getenv("ENV") == "dev" {
fmt.Println(err) views = http.Dir("./views")
} }
engine := handlebars.NewFileSystem(views, ".hbs")
engine := handlebars.NewFileSystem(http.FS(views.GetFiles()), ".hbs") engine.AddFunc("noteq", func(a interface{}, b interface{}, options *raymond.Options) interface{} {
app := fiber.New(fiber.Config{ if raymond.Str(a) != raymond.Str(b) {
Views: engine, return options.Fn()
Prefork: viper.GetBool("FIBER_PREFORK"), }
UnescapePath: true, return ""
StreamRequestBody: true,
}) })
app := fiber.New(fiber.Config{
Views: engine,
Prefork: utils.Config.FiberPrefork,
UnescapePath: true,
StreamRequestBody: true,
ErrorHandler: func(ctx *fiber.Ctx, err error) error {
code := fiber.StatusInternalServerError
if e, ok := err.(*fiber.Error); ok {
code = e.Code
}
return utils.RenderError(ctx, code)
},
})
app.Use(recover.New(recover.Config{
EnableStackTrace: true,
StackTraceHandler: func(c *fiber.Ctx, e interface{}) {
fmt.Println(e)
},
}))
if os.Getenv("ENV") == "dev" {
app.Use("/static", filesystem.New(filesystem.Config{ app.Use("/static", filesystem.New(filesystem.Config{
Root: http.Dir("./static"),
}))
app.Get("/errors/429", func(c *fiber.Ctx) error {
return c.Render("errors/429", nil)
})
app.Get("/errors/429/img", func(c *fiber.Ctx) error {
return c.Redirect("/static/img/error-429.png")
})
app.Get("/errors/404", func(c *fiber.Ctx) error {
return c.Render("errors/404", nil)
})
app.Get("/errors/404/img", func(c *fiber.Ctx) error {
return c.Redirect("/static/img/error-404.png")
})
app.Get("/errors/error", func(c *fiber.Ctx) error {
return c.Render("errors/error", fiber.Map{
"err": "Test error",
})
})
app.Get("/errors/error/img", func(c *fiber.Ctx) error {
return c.Redirect("/static/img/error-generic.png")
})
} else {
app.Use("/static", filesystem.New(filesystem.Config{
MaxAge: 2592000,
Root: http.FS(static.GetFiles()), Root: http.FS(static.GetFiles()),
})) }))
app.Use(cache.New(cache.Config{
Expiration: 30 * time.Minute,
MaxBytes: 25000000,
KeyGenerator: func(c *fiber.Ctx) string {
return utils.GetInstanceUrl(c) + c.OriginalURL()
},
CacheControl: true,
StoreResponseHeaders: true,
}))
}
app.Get("/robots.txt", func(c *fiber.Ctx) error { app.Get("/robots.txt", func(c *fiber.Ctx) error {
file, _ := static.GetFiles().ReadFile("robots.txt") file, _ := static.GetFiles().ReadFile("robots.txt")
_, err := c.Write(file) _, err := c.Write(file)
return err 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("/:baseName.:extension", pages.HandleMedia) app.Get("/about", pages.HandleAbout)
app.Get("/a/:galleryID", pages.HandleGallery) app.Get("/privacy", pages.HandlePrivacy)
//app.Get("/t/:tagID", pages.HandleAlbum) app.Get("/search", pages.HandleSearch)
app.Get("/trending.:type", pages.HandleTrendingRSS)
app.Get("/trending", pages.HandleTrending)
app.Get("/a/:postID", pages.HandlePost)
app.Get("/a/:postID/embed", pages.HandleEmbed)
app.Get("/t/:tag.:type", pages.HandleTagRSS)
app.Get("/t/:tag", pages.HandleTag)
app.Get("/t/:tag/:postID", pages.HandlePost)
app.Get("/r/:sub/:postID", pages.HandlePost)
app.Get("/user/:userID.:type", pages.HandleUserRSS)
app.Get("/user/:userID", pages.HandleUser) app.Get("/user/:userID", pages.HandleUser)
app.Get("/user/:userID/favorites", pages.HandleUserFavorites)
app.Get("/user/:userID/comments", pages.HandleUserComments)
app.Get("/user/:userID/cover", pages.HandleUserCover) app.Get("/user/:userID/cover", pages.HandleUserCover)
app.Get("/user/:userID/avatar", pages.HandleUserAvatar) app.Get("/user/:userID/avatar", pages.HandleUserAvatar)
app.Get("/gallery/:galleryID", pages.HandleGallery) app.Get("/gallery/:postID", pages.HandlePost)
app.Get("/gallery/:postID/embed", pages.HandleEmbed)
app.Get("/:postID.gifv", pages.HandleGifv)
app.Get("/:baseName.:extension", pages.HandleMedia)
app.Get("/stack/:baseName.:extension", pages.HandleMedia)
app.Get("/:postID", pages.HandlePost)
app.Get("/:postID/embed", pages.HandleEmbed)
app.Listen(":" + viper.GetString("RIMGU_PORT")) err := app.Listen(utils.Config.Addr + ":" + utils.Config.Port)
if err != nil {
fmt.Println(err)
}
} }

10
package.json Normal file
View File

@@ -0,0 +1,10 @@
{
"devDependencies": {
"@tailwindcss/cli": "^4.1.5",
"tailwindcss": "^4.1.5"
},
"scripts": {
"build": "tailwindcss -i static/tailwind.css -o static/app.css",
"watch": "tailwindcss -i static/tailwind.css -o static/app.css --watch"
}
}

22
pages/about.go Normal file
View File

@@ -0,0 +1,22 @@
package pages
import (
"os"
"codeberg.org/rimgo/rimgo/utils"
"github.com/gofiber/fiber/v2"
)
func HandleAbout(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Cache-Control", "public,max-age=31557600")
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; style-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
return c.Render("about", fiber.Map{
"proto": c.Protocol(),
"domain": c.Hostname(),
"force_webp": os.Getenv("FORCE_WEBP"),
})
}

12
pages/apiClient.go Normal file
View File

@@ -0,0 +1,12 @@
package pages
import (
"codeberg.org/rimgo/rimgo/api"
"codeberg.org/rimgo/rimgo/utils"
)
var ApiClient *api.Client
func InitializeApiClient() {
ApiClient = api.NewClient(utils.Config.ImgurId)
}

48
pages/embed.go Normal file
View File

@@ -0,0 +1,48 @@
package pages
import (
"strings"
"codeberg.org/rimgo/rimgo/api"
"codeberg.org/rimgo/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'; base-uri 'none'; form-action 'none'; media-src 'self'; style-src 'self'; img-src 'self'; block-all-mixed-content")
post, err := api.Album{}, error(nil)
switch {
case strings.HasPrefix(c.Path(), "/a"):
post, err = ApiClient.FetchAlbum(c.Params("postID"))
case strings.HasPrefix(c.Path(), "/gallery"):
post, err = ApiClient.FetchPosts(c.Params("postID"))
default:
post, err = ApiClient.FetchMedia(c.Params("postID"))
}
if err != nil && err.Error() == "ratelimited by imgur" {
return utils.RenderError(c, 429)
}
if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") {
return utils.RenderError(c, 404)
}
if err != nil {
return err
}
return c.Render("embed", fiber.Map{
"post": post,
})
}
func HandleGifv(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("Cache-Control", "public,max-age=31557600")
c.Set("Content-Security-Policy", "default-src 'none'; base-uri 'none'; form-action 'none'; media-src 'self'; style-src 'self'; img-src 'self'; block-all-mixed-content")
return c.Render("gifv", fiber.Map{
"id": c.Params("postID"),
})
}

View File

@@ -1,14 +1,20 @@
package pages package pages
import ( import (
"codeberg.org/video-prize-ranch/rimgo/utils" "codeberg.org/rimgo/rimgo/utils"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
func FrontpageHandler(c *fiber.Ctx) error { var VersionInfo string
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")
return c.Render("frontpage", fiber.Map{}) func HandleFrontpage(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Cache-Control", "public,max-age=31557600")
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; style-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
return c.Render("frontpage", fiber.Map{
"config": utils.Config,
"version": VersionInfo,
})
} }

View File

@@ -1,34 +0,0 @@
package pages
import (
"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 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")
album, err := api.FetchAlbum(c.Params("galleryID"))
if err != nil {
return err
}
comments := []types.Comment{}
if album.SharedWithCommunity {
c.Set("Cache-Control", "public,max-age=604800")
comments, err = api.FetchComments(c.Params("galleryID"))
if err != nil {
return err
}
} else {
c.Set("Cache-Control", "public,max-age=31557600")
}
return c.Render("gallery", fiber.Map{
"album": 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

@@ -1,38 +1,84 @@
package pages package pages
import ( import (
"mime"
"net/http" "net/http"
"strconv" "strings"
"codeberg.org/video-prize-ranch/rimgo/utils" "codeberg.org/rimgo/rimgo/utils"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
func HandleMedia(c *fiber.Ctx) error { func HandleMedia(c *fiber.Ctx) error {
c.Set("Cache-Control", "public,max-age=31557600") c.Set("Cache-Control", "public,max-age=31557600")
c.Set("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self'")
if strings.HasPrefix(c.Path(), "/stack") {
return handleMedia(c, "https://i.stack.imgur.com/"+strings.ReplaceAll(c.Params("baseName"), "stack/", "")+"."+c.Params("extension"))
} else {
return handleMedia(c, "https://i.imgur.com/"+c.Params("baseName")+"."+c.Params("extension")) return handleMedia(c, "https://i.imgur.com/"+c.Params("baseName")+"."+c.Params("extension"))
} }
}
func HandleUserCover(c *fiber.Ctx) error { func HandleUserCover(c *fiber.Ctx) error {
c.Set("Cache-Control", "public,max-age=604800") c.Set("Cache-Control", "public,max-age=604800")
c.Set("Content-Security-Policy", "default-src 'none'")
return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/cover?maxwidth=2560") return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/cover?maxwidth=2560")
}; }
func HandleUserAvatar(c *fiber.Ctx) error { func HandleUserAvatar(c *fiber.Ctx) error {
c.Set("Cache-Control", "public,max-age=604800") c.Set("Cache-Control", "public,max-age=604800")
c.Set("Content-Security-Policy", "default-src 'none'")
return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/avatar") return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/avatar")
}; }
func handleMedia(c *fiber.Ctx, url string) error { func handleMedia(c *fiber.Ctx, url string) error {
utils.SetHeaders(c) utils.SetHeaders(c)
c.Set("Content-Security-Policy", "default-src 'none'; media-src 'self'; style-src 'self'; img-src 'self'; font-src 'self'; block-all-mixed-content")
res, err := http.Get(url) if utils.Config.ForceWebp &&
!strings.HasSuffix(c.Path(), ".webp") &&
c.Get("Sec-Fetch-Dest") == "image" &&
c.Query("no_webp") == "" &&
c.Accepts("image/webp") == "image/webp" &&
!strings.HasPrefix(c.Path(), "/stack") {
url = strings.ReplaceAll(url, ".png", ".webp")
url = strings.ReplaceAll(url, ".jpg", ".webp")
url = strings.ReplaceAll(url, ".jpeg", ".webp")
filename := strings.TrimPrefix(c.Path(), "/")
c.Set("Content-Disposition", mime.FormatMediaType("attachment", map[string]string{"filename*": filename}))
}
if strings.HasPrefix(c.Path(), "/stack") && strings.Contains(c.OriginalURL(), "?") {
url = url + "?" + strings.Split(c.OriginalURL(), "?")[1]
}
req, err := http.NewRequest("GET", url, nil)
if err != nil { if err != nil {
return err return err
} }
c.Set("Content-Type", res.Header.Get("Content-Type")); utils.SetReqHeaders(req)
contentLen, _ := strconv.Atoi(res.Header.Get("Content-Length"))
return c.SendStream(res.Body, contentLen) if c.Get("Range") != "" {
req.Header.Set("Range", c.Get("Range"))
}
res, err := http.DefaultClient.Do(req)
if err != nil {
return err
}
if res.StatusCode == 404 || strings.Contains(res.Request.URL.String(), "error/404") {
return utils.RenderError(c, 404)
} else if res.StatusCode == 429 {
return utils.RenderError(c, 429)
}
c.Set("Accept-Ranges", "bytes")
c.Set("Content-Type", res.Header.Get("Content-Type"))
c.Set("Content-Length", res.Header.Get("Content-Length"))
if res.Header.Get("Content-Range") != "" {
c.Set("Content-Range", res.Header.Get("Content-Range"))
}
return c.SendStream(res.Body)
} }

100
pages/post.go Normal file
View File

@@ -0,0 +1,100 @@
package pages
import (
"crypto/rand"
"fmt"
"strconv"
"strings"
"codeberg.org/rimgo/rimgo/api"
"codeberg.org/rimgo/rimgo/utils"
"github.com/gofiber/fiber/v2"
)
// Cursed function
func nextInTag(client *api.Client, tagname, sort, page, I string) string {
i, err := strconv.Atoi(I)
if err != nil || i < 0 {
return ""
}
tag, err := client.FetchTag(tagname, sort, page)
if err != nil {
return ""
}
if i >= len(tag.Posts)-1 {
pageNumber, _ := strconv.Atoi(page)
tagn, err := client.FetchTag(tagname, sort, strconv.Itoa(pageNumber+1))
// Check length - Imgur will not return an error if there are no more posts and you request the next page
if err != nil || len(tagn.Posts) < 1 {
return ""
}
return tagn.Posts[0].Link
}
return tag.Posts[i+1].Link
}
func HandlePost(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
postId := c.Params("postID")
if strings.Contains(postId, "-") {
postId = postId[len(postId)-7:]
}
post, err := api.Album{}, error(nil)
switch {
case strings.HasPrefix(c.Path(), "/a"):
post, err = ApiClient.FetchAlbum(postId)
case strings.HasPrefix(c.Path(), "/gallery"):
post, err = ApiClient.FetchPosts(postId)
case strings.HasPrefix(c.Path(), "/t"):
post, err = ApiClient.FetchPosts(postId)
default:
post, err = ApiClient.FetchMedia(postId)
}
if err != nil && err.Error() == "ratelimited by imgur" {
return utils.RenderError(c, 429)
}
if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") {
return utils.RenderError(c, 404)
}
if err != nil {
return err
}
comments := []api.Comment{}
if post.SharedWithCommunity {
c.Set("Cache-Control", "public,max-age=604800")
comments, err = ApiClient.FetchComments(postId)
if err != nil {
return err
}
} else {
c.Set("Cache-Control", "public,max-age=31557600")
}
nonce := ""
csp := "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; media-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content; style-src 'self'"
if len(post.Tags) != 0 {
b := make([]byte, 8)
rand.Read(b)
nonce = fmt.Sprintf("%x", b)
csp = csp + " 'nonce-" + nonce + "'"
}
c.Set("Content-Security-Policy", csp)
var next string
tagParam := strings.Split(c.Query("tag"), ".")
if len(tagParam) == 4 {
tag, sort, page, index := tagParam[0], tagParam[1], tagParam[2], tagParam[3]
next = nextInTag(ApiClient, tag, sort, page, index)
}
return c.Render("post", fiber.Map{
"post": post,
"next": next,
"comments": comments,
"nonce": nonce,
})
}

18
pages/privacy.go Normal file
View File

@@ -0,0 +1,18 @@
package pages
import (
"github.com/gofiber/fiber/v2"
"codeberg.org/rimgo/rimgo/utils"
)
func HandlePrivacy(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Content-Security-Policy", "default-src 'none'; form-action 'self'; style-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
return c.Render("privacy", fiber.Map{
"config": utils.Config,
"version": VersionInfo,
})
}

136
pages/rss.go Normal file
View File

@@ -0,0 +1,136 @@
package pages
import (
"time"
"codeberg.org/rimgo/rimgo/api"
"codeberg.org/rimgo/rimgo/utils"
"github.com/gofiber/fiber/v2"
"github.com/gorilla/feeds"
)
func HandleTagRSS(c *fiber.Ctx) error {
utils.SetHeaders(c)
tag, err := ApiClient.FetchTag(c.Params("tag"), c.Query("sort"), "1")
if err != nil && err.Error() == "ratelimited by imgur" {
return c.Status(429).SendString("rate limited by imgur")
}
if err != nil {
return err
}
if tag.Display == "" {
return c.Status(404).SendString("tag not found")
}
instance := utils.GetInstanceUrl(c)
feed := &feeds.Feed{
Title: tag.Display + " on Imgur",
Link: &feeds.Link{Href: instance + "/t/" + c.Params("tag")},
Created: time.Now(),
}
return handleFeed(c, instance, feed, tag.Posts)
}
func HandleTrendingRSS(c *fiber.Ctx) error {
utils.SetHeaders(c)
section := c.Query("section")
switch section {
case "hot", "new", "top":
default:
section = "hot"
}
sort := c.Query("sort")
switch sort {
case "newest", "best", "popular":
default:
sort = "popular"
}
results, err := ApiClient.FetchTrending(section, sort, "1")
if err != nil {
return err
}
instance := utils.GetInstanceUrl(c)
feed := &feeds.Feed{
Title: "Trending on Imgur",
Link: &feeds.Link{Href: instance + "/trending"},
Created: time.Now(),
}
return handleFeed(c, instance, feed, results)
}
func HandleUserRSS(c *fiber.Ctx) error {
utils.SetHeaders(c)
user := c.Params("userID")
submissions, err := ApiClient.FetchSubmissions(user, "newest", "1")
if err != nil && err.Error() == "ratelimited by imgur" {
c.Status(429)
return utils.RenderError(c, 429)
}
if err != nil {
return err
}
instance := utils.GetInstanceUrl(c)
feed := &feeds.Feed{
Title: user + " on Imgur",
Link: &feeds.Link{Href: instance + "/user/" + user},
Created: time.Now(),
}
return handleFeed(c, instance, feed, submissions)
}
func handleFeed(c *fiber.Ctx, instance string, feed *feeds.Feed, posts []api.Submission) error {
feed.Items = []*feeds.Item{}
for _, post := range posts {
link := instance + post.Link
item := &feeds.Item{
Title: post.Title,
Link: &feeds.Link{Href: link},
Description: "<a href=\"" + link + "\"><img width=\"480\" src=\"" + instance + "/" + post.Cover.Id + ".jpeg" + "\"></a>",
}
if post.Cover.Type == "video" {
item.Description = "🎞️ Video<br><br>" + item.Description
}
feed.Items = append(feed.Items, item)
}
c.Type(c.Params("type"))
switch c.Params("type") {
case "atom":
body, err := feed.ToAtom()
if err != nil {
return err
}
return c.SendString(body)
case "json":
body, err := feed.ToJSON()
if err != nil {
return err
}
return c.JSON(body)
case "rss":
body, err := feed.ToRss()
if err != nil {
return err
}
return c.SendString(body)
default:
return c.Status(400).SendString("invalid type")
}
}

44
pages/search.go Normal file
View File

@@ -0,0 +1,44 @@
package pages
import (
"strconv"
"codeberg.org/rimgo/rimgo/utils"
"github.com/gofiber/fiber/v2"
)
func HandleSearch(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Cache-Control", "public,max-age=604800")
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; style-src 'unsafe-inline' 'self'; media-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
query := c.Query("q")
if utils.ImgurRe.MatchString(query) {
return c.Redirect(utils.ImgurRe.ReplaceAllString(query, ""))
}
page := "0"
if c.Query("page") != "" {
page = c.Query("page")
}
pageNumber, err := strconv.Atoi(c.Query("page"))
if err != nil {
pageNumber = 0
}
results, err := ApiClient.Search(query, page)
if err != nil {
return err
}
return c.Render("search", fiber.Map{
"query": query,
"results": results,
"page": pageNumber,
"nextPage": pageNumber + 1,
"prevPage": pageNumber - 1,
})
}

43
pages/tag.go Normal file
View File

@@ -0,0 +1,43 @@
package pages
import (
"strconv"
"codeberg.org/rimgo/rimgo/utils"
"github.com/gofiber/fiber/v2"
)
func HandleTag(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Cache-Control", "public,max-age=604800")
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; style-src 'unsafe-inline' 'self'; media-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
page := "1"
if c.Query("page") != "" {
page = c.Query("page")
}
pageNumber, err := strconv.Atoi(c.Query("page"))
if err != nil {
pageNumber = 0
}
tag, err := ApiClient.FetchTag(c.Params("tag"), c.Query("sort"), page)
if err != nil && err.Error() == "ratelimited by imgur" {
return utils.RenderError(c, 429)
}
if err != nil {
return err
}
if tag.Display == "" {
return utils.RenderError(c, 404)
}
return c.Render("tag", fiber.Map{
"tag": tag,
"page": page,
"nextPage": pageNumber + 1,
"prevPage": pageNumber - 1,
})
}

52
pages/trending.go Normal file
View File

@@ -0,0 +1,52 @@
package pages
import (
"strconv"
"codeberg.org/rimgo/rimgo/utils"
"github.com/gofiber/fiber/v2"
)
func HandleTrending(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Cache-Control", "public,max-age=604800")
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; style-src 'unsafe-inline' 'self'; media-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
page := "1"
if c.Query("page") != "" {
page = c.Query("page")
}
pageNumber, err := strconv.Atoi(c.Query("page"))
if err != nil {
pageNumber = 1
}
section := c.Query("section")
switch section {
case "hot", "new", "top":
default:
section = "hot"
}
sort := c.Query("sort")
switch sort {
case "newest", "best", "popular":
default:
sort = "popular"
}
results, err := ApiClient.FetchTrending(section, sort, page)
if err != nil {
return err
}
return c.Render("trending", fiber.Map{
"results": results,
"section": section,
"sort": sort,
"page": pageNumber,
"nextPage": pageNumber + 1,
"prevPage": pageNumber - 1,
})
}

View File

@@ -1,42 +1,129 @@
package pages package pages
import ( import (
"sync" "strconv"
"codeberg.org/video-prize-ranch/rimgo/api" "codeberg.org/rimgo/rimgo/utils"
"codeberg.org/video-prize-ranch/rimgo/types"
"codeberg.org/video-prize-ranch/rimgo/utils"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
func HandleUser(c *fiber.Ctx) error { func HandleUser(c *fiber.Ctx) error {
utils.SetHeaders(c) utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Cache-Control", "public,max-age=604800") 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'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; media-src 'self'; style-src 'unsafe-inline' 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
wg := sync.WaitGroup{} page := "0"
wg.Add(2) if c.Query("page") != "" {
user, err := types.User{}, error(nil) page = c.Query("page")
go func() { }
defer wg.Done()
user, err = api.FetchUser(c.Params("userID")) pageNumber, err := strconv.Atoi(c.Query("page"))
}() if err != nil {
pageNumber = 0
}
user, err := ApiClient.FetchUser(c.Params("userID"))
if err != nil && err.Error() == "ratelimited by imgur" {
return utils.RenderError(c, 429)
}
if err != nil {
return err
}
if user.Username == "" {
return utils.RenderError(c, 404)
}
submissions, err := ApiClient.FetchSubmissions(c.Params("userID"), "newest", page)
if err != nil && err.Error() == "ratelimited by imgur" {
c.Status(429)
return utils.RenderError(c, 429)
}
if err != nil { if err != nil {
return err return err
} }
submissions, err := []types.Submission{}, error(nil)
go func() {
defer wg.Done()
submissions, err = api.FetchSubmissions(c.Params("userID"), "newest", "0")
}()
if err != nil {
return err
}
wg.Wait()
return c.Render("user", fiber.Map{ return c.Render("user", fiber.Map{
"user": user, "user": user,
"submissions": submissions, "submissions": submissions,
"page": page,
"nextPage": pageNumber + 1,
"prevPage": pageNumber - 1,
})
}
func HandleUserComments(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Cache-Control", "public,max-age=604800")
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; media-src 'self'; style-src 'unsafe-inline' 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
user, err := ApiClient.FetchUser(c.Params("userID"))
if err != nil && err.Error() == "ratelimited by imgur" {
return utils.RenderError(c, 429)
}
if err != nil {
return err
}
if user.Username == "" {
return utils.RenderError(c, 404)
}
comments, err := ApiClient.FetchUserComments(c.Params("userID"))
if err != nil && err.Error() == "ratelimited by imgur" {
c.Status(429)
return utils.RenderError(c, 429)
}
if err != nil {
return err
}
return c.Render("userComments", fiber.Map{
"user": user,
"comments": comments,
})
}
func HandleUserFavorites(c *fiber.Ctx) error {
utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY")
c.Set("Cache-Control", "public,max-age=604800")
c.Set("Content-Security-Policy", "default-src 'none'; frame-ancestors 'none'; base-uri 'none'; form-action 'self'; media-src 'self'; style-src 'unsafe-inline' 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
page := "0"
if c.Query("page") != "" {
page = c.Query("page")
}
pageNumber, err := strconv.Atoi(c.Query("page"))
if err != nil {
pageNumber = 0
}
user, err := ApiClient.FetchUser(c.Params("userID"))
if err != nil && err.Error() == "ratelimited by imgur" {
return utils.RenderError(c, 429)
}
if err != nil {
return err
}
if user.Username == "" {
return utils.RenderError(c, 404)
}
favorites, err := ApiClient.FetchUserFavorites(c.Params("userID"), "newest", page)
if err != nil && err.Error() == "ratelimited by imgur" {
return utils.RenderError(c, 429)
}
if err != nil {
return err
}
return c.Render("userFavorites", fiber.Map{
"user": user,
"favorites": favorites,
"page": page,
"nextPage": pageNumber + 1,
"prevPage": pageNumber - 1,
}) })
} }

547
pnpm-lock.yaml generated Normal file
View File

@@ -0,0 +1,547 @@
lockfileVersion: '9.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
importers:
.:
devDependencies:
'@tailwindcss/cli':
specifier: ^4.1.5
version: 4.1.5
tailwindcss:
specifier: ^4.1.5
version: 4.1.5
packages:
'@parcel/watcher-android-arm64@2.5.1':
resolution: {integrity: sha512-KF8+j9nNbUN8vzOFDpRMsaKBHZ/mcjEjMToVMJOhTozkDonQFFrRcfdLWn6yWKCmJKmdVxSgHiYvTCef4/qcBA==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [android]
'@parcel/watcher-darwin-arm64@2.5.1':
resolution: {integrity: sha512-eAzPv5osDmZyBhou8PoF4i6RQXAfeKL9tjb3QzYuccXFMQU0ruIc/POh30ePnaOyD1UXdlKguHBmsTs53tVoPw==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [darwin]
'@parcel/watcher-darwin-x64@2.5.1':
resolution: {integrity: sha512-1ZXDthrnNmwv10A0/3AJNZ9JGlzrF82i3gNQcWOzd7nJ8aj+ILyW1MTxVk35Db0u91oD5Nlk9MBiujMlwmeXZg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [darwin]
'@parcel/watcher-freebsd-x64@2.5.1':
resolution: {integrity: sha512-SI4eljM7Flp9yPuKi8W0ird8TI/JK6CSxju3NojVI6BjHsTyK7zxA9urjVjEKJ5MBYC+bLmMcbAWlZ+rFkLpJQ==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [freebsd]
'@parcel/watcher-linux-arm-glibc@2.5.1':
resolution: {integrity: sha512-RCdZlEyTs8geyBkkcnPWvtXLY44BCeZKmGYRtSgtwwnHR4dxfHRG3gR99XdMEdQ7KeiDdasJwwvNSF5jKtDwdA==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
'@parcel/watcher-linux-arm-musl@2.5.1':
resolution: {integrity: sha512-6E+m/Mm1t1yhB8X412stiKFG3XykmgdIOqhjWj+VL8oHkKABfu/gjFj8DvLrYVHSBNC+/u5PeNrujiSQ1zwd1Q==}
engines: {node: '>= 10.0.0'}
cpu: [arm]
os: [linux]
'@parcel/watcher-linux-arm64-glibc@2.5.1':
resolution: {integrity: sha512-LrGp+f02yU3BN9A+DGuY3v3bmnFUggAITBGriZHUREfNEzZh/GO06FF5u2kx8x+GBEUYfyTGamol4j3m9ANe8w==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-arm64-musl@2.5.1':
resolution: {integrity: sha512-cFOjABi92pMYRXS7AcQv9/M1YuKRw8SZniCDw0ssQb/noPkRzA+HBDkwmyOJYp5wXcsTrhxO0zq1U11cK9jsFg==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [linux]
'@parcel/watcher-linux-x64-glibc@2.5.1':
resolution: {integrity: sha512-GcESn8NZySmfwlTsIur+49yDqSny2IhPeZfXunQi48DMugKeZ7uy1FX83pO0X22sHntJ4Ub+9k34XQCX+oHt2A==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
'@parcel/watcher-linux-x64-musl@2.5.1':
resolution: {integrity: sha512-n0E2EQbatQ3bXhcH2D1XIAANAcTZkQICBPVaxMeaCVBtOpBZpWJuf7LwyWPSBDITb7In8mqQgJ7gH8CILCURXg==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [linux]
'@parcel/watcher-win32-arm64@2.5.1':
resolution: {integrity: sha512-RFzklRvmc3PkjKjry3hLF9wD7ppR4AKcWNzH7kXR7GUe0Igb3Nz8fyPwtZCSquGrhU5HhUNDr/mKBqj7tqA2Vw==}
engines: {node: '>= 10.0.0'}
cpu: [arm64]
os: [win32]
'@parcel/watcher-win32-ia32@2.5.1':
resolution: {integrity: sha512-c2KkcVN+NJmuA7CGlaGD1qJh1cLfDnQsHjE89E60vUEMlqduHGCdCLJCID5geFVM0dOtA3ZiIO8BoEQmzQVfpQ==}
engines: {node: '>= 10.0.0'}
cpu: [ia32]
os: [win32]
'@parcel/watcher-win32-x64@2.5.1':
resolution: {integrity: sha512-9lHBdJITeNR++EvSQVUcaZoWupyHfXe1jZvGZ06O/5MflPcuPLtEphScIBL+AiCWBO46tDSHzWyD0uDmmZqsgA==}
engines: {node: '>= 10.0.0'}
cpu: [x64]
os: [win32]
'@parcel/watcher@2.5.1':
resolution: {integrity: sha512-dfUnCxiN9H4ap84DvD2ubjw+3vUNpstxa0TneY/Paat8a3R4uQZDLSvWjmznAY/DoahqTHl9V46HF/Zs3F29pg==}
engines: {node: '>= 10.0.0'}
'@tailwindcss/cli@4.1.5':
resolution: {integrity: sha512-Kr567rDwDjY1VUnfqh5/+DCpRf4B8lPs5O9flP4kri7n4AM2aubrIxGSh5GN8s+awUKw/U4+6kNlEnZbBNfUeg==}
hasBin: true
'@tailwindcss/node@4.1.5':
resolution: {integrity: sha512-CBhSWo0vLnWhXIvpD0qsPephiaUYfHUX3U9anwDaHZAeuGpTiB3XmsxPAN6qX7bFhipyGBqOa1QYQVVhkOUGxg==}
'@tailwindcss/oxide-android-arm64@4.1.5':
resolution: {integrity: sha512-LVvM0GirXHED02j7hSECm8l9GGJ1RfgpWCW+DRn5TvSaxVsv28gRtoL4aWKGnXqwvI3zu1GABeDNDVZeDPOQrw==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [android]
'@tailwindcss/oxide-darwin-arm64@4.1.5':
resolution: {integrity: sha512-//TfCA3pNrgnw4rRJOqavW7XUk8gsg9ddi8cwcsWXp99tzdBAZW0WXrD8wDyNbqjW316Pk2hiN/NJx/KWHl8oA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [darwin]
'@tailwindcss/oxide-darwin-x64@4.1.5':
resolution: {integrity: sha512-XQorp3Q6/WzRd9OalgHgaqgEbjP3qjHrlSUb5k1EuS1Z9NE9+BbzSORraO+ecW432cbCN7RVGGL/lSnHxcd+7Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [darwin]
'@tailwindcss/oxide-freebsd-x64@4.1.5':
resolution: {integrity: sha512-bPrLWbxo8gAo97ZmrCbOdtlz/Dkuy8NK97aFbVpkJ2nJ2Jo/rsCbu0TlGx8joCuA3q6vMWTSn01JY46iwG+clg==}
engines: {node: '>= 10'}
cpu: [x64]
os: [freebsd]
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.5':
resolution: {integrity: sha512-1gtQJY9JzMAhgAfvd/ZaVOjh/Ju/nCoAsvOVJenWZfs05wb8zq+GOTnZALWGqKIYEtyNpCzvMk+ocGpxwdvaVg==}
engines: {node: '>= 10'}
cpu: [arm]
os: [linux]
'@tailwindcss/oxide-linux-arm64-gnu@4.1.5':
resolution: {integrity: sha512-dtlaHU2v7MtdxBXoqhxwsWjav7oim7Whc6S9wq/i/uUMTWAzq/gijq1InSgn2yTnh43kR+SFvcSyEF0GCNu1PQ==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tailwindcss/oxide-linux-arm64-musl@4.1.5':
resolution: {integrity: sha512-fg0F6nAeYcJ3CriqDT1iVrqALMwD37+sLzXs8Rjy8Z1ZHshJoYceodfyUwGJEsQoTyWbliFNRs2wMQNXtT7MVA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [linux]
'@tailwindcss/oxide-linux-x64-gnu@4.1.5':
resolution: {integrity: sha512-SO+F2YEIAHa1AITwc8oPwMOWhgorPzzcbhWEb+4oLi953h45FklDmM8dPSZ7hNHpIk9p/SCZKUYn35t5fjGtHA==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tailwindcss/oxide-linux-x64-musl@4.1.5':
resolution: {integrity: sha512-6UbBBplywkk/R+PqqioskUeXfKcBht3KU7juTi1UszJLx0KPXUo10v2Ok04iBJIaDPkIFkUOVboXms5Yxvaz+g==}
engines: {node: '>= 10'}
cpu: [x64]
os: [linux]
'@tailwindcss/oxide-wasm32-wasi@4.1.5':
resolution: {integrity: sha512-hwALf2K9FHuiXTPqmo1KeOb83fTRNbe9r/Ixv9ZNQ/R24yw8Ge1HOWDDgTdtzntIaIUJG5dfXCf4g9AD4RiyhQ==}
engines: {node: '>=14.0.0'}
cpu: [wasm32]
bundledDependencies:
- '@napi-rs/wasm-runtime'
- '@emnapi/core'
- '@emnapi/runtime'
- '@tybys/wasm-util'
- '@emnapi/wasi-threads'
- tslib
'@tailwindcss/oxide-win32-arm64-msvc@4.1.5':
resolution: {integrity: sha512-oDKncffWzaovJbkuR7/OTNFRJQVdiw/n8HnzaCItrNQUeQgjy7oUiYpsm9HUBgpmvmDpSSbGaCa2Evzvk3eFmA==}
engines: {node: '>= 10'}
cpu: [arm64]
os: [win32]
'@tailwindcss/oxide-win32-x64-msvc@4.1.5':
resolution: {integrity: sha512-WiR4dtyrFdbb+ov0LK+7XsFOsG+0xs0PKZKkt41KDn9jYpO7baE3bXiudPVkTqUEwNfiglCygQHl2jklvSBi7Q==}
engines: {node: '>= 10'}
cpu: [x64]
os: [win32]
'@tailwindcss/oxide@4.1.5':
resolution: {integrity: sha512-1n4br1znquEvyW/QuqMKQZlBen+jxAbvyduU87RS8R3tUSvByAkcaMTkJepNIrTlYhD+U25K4iiCIxE6BGdRYA==}
engines: {node: '>= 10'}
braces@3.0.3:
resolution: {integrity: sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==}
engines: {node: '>=8'}
detect-libc@1.0.3:
resolution: {integrity: sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==}
engines: {node: '>=0.10'}
hasBin: true
detect-libc@2.0.4:
resolution: {integrity: sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA==}
engines: {node: '>=8'}
enhanced-resolve@5.18.1:
resolution: {integrity: sha512-ZSW3ma5GkcQBIpwZTSRAI8N71Uuwgs93IezB7mf7R60tC8ZbJideoDNKjHn2O9KIlx6rkGTTEk1xUCK2E1Y2Yg==}
engines: {node: '>=10.13.0'}
fill-range@7.1.1:
resolution: {integrity: sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==}
engines: {node: '>=8'}
graceful-fs@4.2.11:
resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==}
is-extglob@2.1.1:
resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==}
engines: {node: '>=0.10.0'}
is-glob@4.0.3:
resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==}
engines: {node: '>=0.10.0'}
is-number@7.0.0:
resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==}
engines: {node: '>=0.12.0'}
jiti@2.4.2:
resolution: {integrity: sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A==}
hasBin: true
lightningcss-darwin-arm64@1.29.2:
resolution: {integrity: sha512-cK/eMabSViKn/PG8U/a7aCorpeKLMlK0bQeNHmdb7qUnBkNPnL+oV5DjJUo0kqWsJUapZsM4jCfYItbqBDvlcA==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [darwin]
lightningcss-darwin-x64@1.29.2:
resolution: {integrity: sha512-j5qYxamyQw4kDXX5hnnCKMf3mLlHvG44f24Qyi2965/Ycz829MYqjrVg2H8BidybHBp9kom4D7DR5VqCKDXS0w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [darwin]
lightningcss-freebsd-x64@1.29.2:
resolution: {integrity: sha512-wDk7M2tM78Ii8ek9YjnY8MjV5f5JN2qNVO+/0BAGZRvXKtQrBC4/cn4ssQIpKIPP44YXw6gFdpUF+Ps+RGsCwg==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [freebsd]
lightningcss-linux-arm-gnueabihf@1.29.2:
resolution: {integrity: sha512-IRUrOrAF2Z+KExdExe3Rz7NSTuuJ2HvCGlMKoquK5pjvo2JY4Rybr+NrKnq0U0hZnx5AnGsuFHjGnNT14w26sg==}
engines: {node: '>= 12.0.0'}
cpu: [arm]
os: [linux]
lightningcss-linux-arm64-gnu@1.29.2:
resolution: {integrity: sha512-KKCpOlmhdjvUTX/mBuaKemp0oeDIBBLFiU5Fnqxh1/DZ4JPZi4evEH7TKoSBFOSOV3J7iEmmBaw/8dpiUvRKlQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-arm64-musl@1.29.2:
resolution: {integrity: sha512-Q64eM1bPlOOUgxFmoPUefqzY1yV3ctFPE6d/Vt7WzLW4rKTv7MyYNky+FWxRpLkNASTnKQUaiMJ87zNODIrrKQ==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
lightningcss-linux-x64-gnu@1.29.2:
resolution: {integrity: sha512-0v6idDCPG6epLXtBH/RPkHvYx74CVziHo6TMYga8O2EiQApnUPZsbR9nFNrg2cgBzk1AYqEd95TlrsL7nYABQg==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-linux-x64-musl@1.29.2:
resolution: {integrity: sha512-rMpz2yawkgGT8RULc5S4WiZopVMOFWjiItBT7aSfDX4NQav6M44rhn5hjtkKzB+wMTRlLLqxkeYEtQ3dd9696w==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
lightningcss-win32-arm64-msvc@1.29.2:
resolution: {integrity: sha512-nL7zRW6evGQqYVu/bKGK+zShyz8OVzsCotFgc7judbt6wnB2KbiKKJwBE4SGoDBQ1O94RjW4asrCjQL4i8Fhbw==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [win32]
lightningcss-win32-x64-msvc@1.29.2:
resolution: {integrity: sha512-EdIUW3B2vLuHmv7urfzMI/h2fmlnOQBk1xlsDxkN1tCWKjNFjfLhGxYk8C8mzpSfr+A6jFFIi8fU6LbQGsRWjA==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [win32]
lightningcss@1.29.2:
resolution: {integrity: sha512-6b6gd/RUXKaw5keVdSEtqFVdzWnU5jMxTUjA2bVcMNPLwSQ08Sv/UodBVtETLCn7k4S1Ibxwh7k68IwLZPgKaA==}
engines: {node: '>= 12.0.0'}
micromatch@4.0.8:
resolution: {integrity: sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==}
engines: {node: '>=8.6'}
mri@1.2.0:
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
engines: {node: '>=4'}
node-addon-api@7.1.1:
resolution: {integrity: sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==}
picocolors@1.1.1:
resolution: {integrity: sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==}
picomatch@2.3.1:
resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==}
engines: {node: '>=8.6'}
tailwindcss@4.1.5:
resolution: {integrity: sha512-nYtSPfWGDiWgCkwQG/m+aX83XCwf62sBgg3bIlNiiOcggnS1x3uVRDAuyelBFL+vJdOPPCGElxv9DjHJjRHiVA==}
tapable@2.2.1:
resolution: {integrity: sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==}
engines: {node: '>=6'}
to-regex-range@5.0.1:
resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==}
engines: {node: '>=8.0'}
snapshots:
'@parcel/watcher-android-arm64@2.5.1':
optional: true
'@parcel/watcher-darwin-arm64@2.5.1':
optional: true
'@parcel/watcher-darwin-x64@2.5.1':
optional: true
'@parcel/watcher-freebsd-x64@2.5.1':
optional: true
'@parcel/watcher-linux-arm-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-arm-musl@2.5.1':
optional: true
'@parcel/watcher-linux-arm64-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-arm64-musl@2.5.1':
optional: true
'@parcel/watcher-linux-x64-glibc@2.5.1':
optional: true
'@parcel/watcher-linux-x64-musl@2.5.1':
optional: true
'@parcel/watcher-win32-arm64@2.5.1':
optional: true
'@parcel/watcher-win32-ia32@2.5.1':
optional: true
'@parcel/watcher-win32-x64@2.5.1':
optional: true
'@parcel/watcher@2.5.1':
dependencies:
detect-libc: 1.0.3
is-glob: 4.0.3
micromatch: 4.0.8
node-addon-api: 7.1.1
optionalDependencies:
'@parcel/watcher-android-arm64': 2.5.1
'@parcel/watcher-darwin-arm64': 2.5.1
'@parcel/watcher-darwin-x64': 2.5.1
'@parcel/watcher-freebsd-x64': 2.5.1
'@parcel/watcher-linux-arm-glibc': 2.5.1
'@parcel/watcher-linux-arm-musl': 2.5.1
'@parcel/watcher-linux-arm64-glibc': 2.5.1
'@parcel/watcher-linux-arm64-musl': 2.5.1
'@parcel/watcher-linux-x64-glibc': 2.5.1
'@parcel/watcher-linux-x64-musl': 2.5.1
'@parcel/watcher-win32-arm64': 2.5.1
'@parcel/watcher-win32-ia32': 2.5.1
'@parcel/watcher-win32-x64': 2.5.1
'@tailwindcss/cli@4.1.5':
dependencies:
'@parcel/watcher': 2.5.1
'@tailwindcss/node': 4.1.5
'@tailwindcss/oxide': 4.1.5
enhanced-resolve: 5.18.1
mri: 1.2.0
picocolors: 1.1.1
tailwindcss: 4.1.5
'@tailwindcss/node@4.1.5':
dependencies:
enhanced-resolve: 5.18.1
jiti: 2.4.2
lightningcss: 1.29.2
tailwindcss: 4.1.5
'@tailwindcss/oxide-android-arm64@4.1.5':
optional: true
'@tailwindcss/oxide-darwin-arm64@4.1.5':
optional: true
'@tailwindcss/oxide-darwin-x64@4.1.5':
optional: true
'@tailwindcss/oxide-freebsd-x64@4.1.5':
optional: true
'@tailwindcss/oxide-linux-arm-gnueabihf@4.1.5':
optional: true
'@tailwindcss/oxide-linux-arm64-gnu@4.1.5':
optional: true
'@tailwindcss/oxide-linux-arm64-musl@4.1.5':
optional: true
'@tailwindcss/oxide-linux-x64-gnu@4.1.5':
optional: true
'@tailwindcss/oxide-linux-x64-musl@4.1.5':
optional: true
'@tailwindcss/oxide-wasm32-wasi@4.1.5':
optional: true
'@tailwindcss/oxide-win32-arm64-msvc@4.1.5':
optional: true
'@tailwindcss/oxide-win32-x64-msvc@4.1.5':
optional: true
'@tailwindcss/oxide@4.1.5':
optionalDependencies:
'@tailwindcss/oxide-android-arm64': 4.1.5
'@tailwindcss/oxide-darwin-arm64': 4.1.5
'@tailwindcss/oxide-darwin-x64': 4.1.5
'@tailwindcss/oxide-freebsd-x64': 4.1.5
'@tailwindcss/oxide-linux-arm-gnueabihf': 4.1.5
'@tailwindcss/oxide-linux-arm64-gnu': 4.1.5
'@tailwindcss/oxide-linux-arm64-musl': 4.1.5
'@tailwindcss/oxide-linux-x64-gnu': 4.1.5
'@tailwindcss/oxide-linux-x64-musl': 4.1.5
'@tailwindcss/oxide-wasm32-wasi': 4.1.5
'@tailwindcss/oxide-win32-arm64-msvc': 4.1.5
'@tailwindcss/oxide-win32-x64-msvc': 4.1.5
braces@3.0.3:
dependencies:
fill-range: 7.1.1
detect-libc@1.0.3: {}
detect-libc@2.0.4: {}
enhanced-resolve@5.18.1:
dependencies:
graceful-fs: 4.2.11
tapable: 2.2.1
fill-range@7.1.1:
dependencies:
to-regex-range: 5.0.1
graceful-fs@4.2.11: {}
is-extglob@2.1.1: {}
is-glob@4.0.3:
dependencies:
is-extglob: 2.1.1
is-number@7.0.0: {}
jiti@2.4.2: {}
lightningcss-darwin-arm64@1.29.2:
optional: true
lightningcss-darwin-x64@1.29.2:
optional: true
lightningcss-freebsd-x64@1.29.2:
optional: true
lightningcss-linux-arm-gnueabihf@1.29.2:
optional: true
lightningcss-linux-arm64-gnu@1.29.2:
optional: true
lightningcss-linux-arm64-musl@1.29.2:
optional: true
lightningcss-linux-x64-gnu@1.29.2:
optional: true
lightningcss-linux-x64-musl@1.29.2:
optional: true
lightningcss-win32-arm64-msvc@1.29.2:
optional: true
lightningcss-win32-x64-msvc@1.29.2:
optional: true
lightningcss@1.29.2:
dependencies:
detect-libc: 2.0.4
optionalDependencies:
lightningcss-darwin-arm64: 1.29.2
lightningcss-darwin-x64: 1.29.2
lightningcss-freebsd-x64: 1.29.2
lightningcss-linux-arm-gnueabihf: 1.29.2
lightningcss-linux-arm64-gnu: 1.29.2
lightningcss-linux-arm64-musl: 1.29.2
lightningcss-linux-x64-gnu: 1.29.2
lightningcss-linux-x64-musl: 1.29.2
lightningcss-win32-arm64-msvc: 1.29.2
lightningcss-win32-x64-msvc: 1.29.2
micromatch@4.0.8:
dependencies:
braces: 3.0.3
picomatch: 2.3.1
mri@1.2.0: {}
node-addon-api@7.1.1: {}
picocolors@1.1.1: {}
picomatch@2.3.1: {}
tailwindcss@4.1.5: {}
tapable@2.2.1: {}
to-regex-range@5.0.1:
dependencies:
is-number: 7.0.0

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

@@ -1,32 +0,0 @@
h1 {
margin: 0;
}
p {
margin: 0.5em 0;
}
video,
img {
max-width: 100%;
}
.pfp {
border-radius: 100%;
}
.imageMeta__wrapper,
.imageMeta__item,
.imageMeta {
display: flex;
gap: 12px;
align-items: center;
}
.imageMeta__item {
gap: 4px;
}
.imageMeta__wrapper {
gap: 2rem;
}

View File

@@ -1,51 +0,0 @@
a {
color: #E0E0E0;
font-weight: 600;
text-decoration: none;
}
a > h2 {
color: white;
}
body {
background-color: #212121;
color: white;
font-size: 18px;
font-family: -apple-system, BlinkMacSystemFont, avenir next, avenir, segoe ui, helvetica neue, helvetica, Ubuntu, roboto, noto, arial, sans-serif;
}
nav {
display: flex;
align-items: center;
}
.center {
display: flex;
justify-content: center;
}
.logo {
filter: invert(1) hue-rotate(180deg);
}
main {
margin: 0 24vw;
}
footer {
display: flex;
justify-content: center;
flex-direction: row;
gap: 10px;
}
@media only screen and (max-width: 812px) {
main {
margin: 0;
}
footer {
flex-direction: column;
text-align: center;
}
}

View File

@@ -1,68 +0,0 @@
.comment {
display: flex;
flex-direction: column;
gap: 0.5em;
}
.comments {
gap: 0.25em;
display: flex;
flex-direction: column;
}
.replies {
margin-left: 20px;
border-left: 2px #424242 solid;
padding-left: 8px;
}
#comments__expandBtn {
display: none;
}
.comments__expandBtn__label {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
cursor: pointer;
user-select: none;
text-decoration: none;
color: #fff
}
.comments__expandBtn__icon {
font-size: 24px;
}
#comments__expandBtn ~ .comments__expandBtn__label > span::after {
content: "expand_more";
}
#comments__expandBtn:checked ~ .comments__expandBtn__label > span::after {
content: "expand_less";
}
#comments__expandBtn:checked ~ .comments {
display: none;
}
.comment__media {
display: inline;
}
.comment__updatedDate {
font-size: 0.8em;
}
.comment__user {
display: flex;
gap: 6px;
align-items: center;
}
.comment__user__username {
white-space: nowrap;
text-overflow: ellipsis;
overflow: hidden;
}

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

@@ -0,0 +1,54 @@
.logo {
filter: invert(180deg), hue-rotate(180deg);
}
body {
overflow: hidden;
}
.mediaWrapper {
display: flex;
justify-content: center;
}
.media {
display: flex;
overflow: auto;
gap: 1rem;
align-items: center;
height: 90vh;
}
.media img, .media video {
height: 100%;
}
.media--gifv {
width: 100vw;
overflow: unset;
justify-content: center;
}
.media--gifv video {
width: 100%;
}
.views {
gap: 4px;
}
.postDetails {
display: flex;
gap: 1rem;
}
h3 {
font-size: 1em;
}
.postMeta {
display: flex;
align-items: center;
justify-content: space-between;
height: 9vh;
}

View File

@@ -1,6 +0,0 @@
code {
background-color: #424242;
padding: 2px;
border-radius: 4px;
font-size: 0.9em;
}

View File

@@ -1,63 +0,0 @@
main {
margin: 0 12vw;
}
h2, p {
margin: 0;
}
.userMeta {
padding: 2vw;
border-radius: 12px;
}
.userMeta__upper {
display: flex;
gap: 10px;
align-items: center;
}
.userMeta__upper__bio {
margin-top: 1em;
}
.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,7 @@
{ {
"name": "", "name": "rimgo",
"short_name": "", "short_name": "rimgo",
"start_url": "/",
"icons": [ "icons": [
{ {
"src": "/static/favicon/android-chrome-192x192.png", "src": "/static/favicon/android-chrome-192x192.png",

View File

@@ -1,22 +0,0 @@
/* fallback */
@font-face {
font-family: 'Material Icons Outlined';
font-style: normal;
font-weight: 400;
src: url(Material-Icons-Outlined.woff2) format('woff2');
}
.material-icons-outlined {
font-family: 'Material Icons Outlined';
font-weight: normal;
font-style: normal;
line-height: 1;
letter-spacing: normal;
text-transform: none;
display: inline-block;
white-space: nowrap;
word-wrap: normal;
direction: ltr;
-moz-font-feature-settings: 'liga';
-moz-osx-font-smoothing: grayscale;
}

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M231.39 132.94A8 8 0 0 0 224 128h-40V48a16 16 0 0 0-16-16H88a16 16 0 0 0-16 16v80H32a8 8 0 0 0-5.66 13.66l96 96a8 8 0 0 0 11.32 0l96-96a8 8 0 0 0 1.73-8.72ZM128 220.69L51.31 144H80a8 8 0 0 0 8-8V48h80v88a8 8 0 0 0 8 8h28.69Z"/></svg>

After

Width:  |  Height:  |  Size: 347 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="m229.66 114.34l-96-96a8 8 0 0 0-11.32 0l-96 96A8 8 0 0 0 32 128h40v80a16 16 0 0 0 16 16h80a16 16 0 0 0 16-16v-80h40a8 8 0 0 0 5.66-13.66ZM176 112a8 8 0 0 0-8 8v88H88v-88a8 8 0 0 0-8-8H51.31L128 35.31L204.69 112Z"/></svg>

After

Width:  |  Height:  |  Size: 334 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em" viewBox="0 0 256 256"><path fill="currentColor" d="M200 64v104a8 8 0 0 1-16 0V83.31L69.66 197.66a8 8 0 0 1-11.32-11.32L172.69 72H88a8 8 0 0 1 0-16h104a8 8 0 0 1 8 8Z"/></svg>

After

Width:  |  Height:  |  Size: 239 B

1
static/icons/PhChat.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M216 48H40a16 16 0 0 0-16 16v160a15.84 15.84 0 0 0 9.25 14.5A16.05 16.05 0 0 0 40 240a15.89 15.89 0 0 0 10.25-3.78a.69.69 0 0 0 .13-.11L82.5 208H216a16 16 0 0 0 16-16V64a16 16 0 0 0-16-16ZM40 224Zm176-32H82.5a16 16 0 0 0-10.3 3.75l-.12.11L40 224V64h176Z"/></svg>

After

Width:  |  Height:  |  Size: 376 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M173.66 98.34a8 8 0 0 1 0 11.32l-56 56a8 8 0 0 1-11.32 0l-24-24a8 8 0 0 1 11.32-11.32L112 148.69l50.34-50.35a8 8 0 0 1 11.32 0ZM232 128A104 104 0 1 1 128 24a104.11 104.11 0 0 1 104 104Zm-16 0a88 88 0 1 0-88 88a88.1 88.1 0 0 0 88-88Z"/></svg>

After

Width:  |  Height:  |  Size: 355 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M224 72h-16v-8a24 24 0 0 0-24-24H40a24 24 0 0 0-24 24v96a24 24 0 0 0 24 24h112v8a24 24 0 0 0 24 24h48a24 24 0 0 0 24-24V96a24 24 0 0 0-24-24ZM40 168a8 8 0 0 1-8-8V64a8 8 0 0 1 8-8h144a8 8 0 0 1 8 8v8h-16a24 24 0 0 0-24 24v72Zm192 24a8 8 0 0 1-8 8h-48a8 8 0 0 1-8-8V96a8 8 0 0 1 8-8h48a8 8 0 0 1 8 8Zm-96 16a8 8 0 0 1-8 8H88a8 8 0 0 1 0-16h40a8 8 0 0 1 8 8Zm80-96a8 8 0 0 1-8 8h-16a8 8 0 0 1 0-16h16a8 8 0 0 1 8 8Z"/></svg>

After

Width:  |  Height:  |  Size: 536 B

1
static/icons/PhEye.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M247.31 124.76c-.35-.79-8.82-19.58-27.65-38.41C194.57 61.26 162.88 48 128 48S61.43 61.26 36.34 86.35C17.51 105.18 9 124 8.69 124.76a8 8 0 0 0 0 6.5c.35.79 8.82 19.57 27.65 38.4C61.43 194.74 93.12 208 128 208s66.57-13.26 91.66-38.34c18.83-18.83 27.3-37.61 27.65-38.4a8 8 0 0 0 0-6.5ZM128 192c-30.78 0-57.67-11.19-79.93-33.25A133.47 133.47 0 0 1 25 128a133.33 133.33 0 0 1 23.07-30.75C70.33 75.19 97.22 64 128 64s57.67 11.19 79.93 33.25A133.46 133.46 0 0 1 231.05 128c-7.21 13.46-38.62 64-103.05 64Zm0-112a48 48 0 1 0 48 48a48.05 48.05 0 0 0-48-48Zm0 80a32 32 0 1 1 32-32a32 32 0 0 1-32 32Z"/></svg>

After

Width:  |  Height:  |  Size: 711 B

1
static/icons/PhGlobe.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24Zm-26.37 144h52.74C149 186.34 140 202.87 128 215.89c-12-13.02-21-29.55-26.37-47.89ZM98 152a145.72 145.72 0 0 1 0-48h60a145.72 145.72 0 0 1 0 48Zm-58-24a87.61 87.61 0 0 1 3.33-24h38.46a161.79 161.79 0 0 0 0 48H43.33A87.61 87.61 0 0 1 40 128Zm114.37-40h-52.74C107 69.66 116 53.13 128 40.11c12 13.02 21 29.55 26.37 47.89Zm19.84 16h38.46a88.15 88.15 0 0 1 0 48h-38.46a161.79 161.79 0 0 0 0-48Zm32.16-16h-35.43a142.39 142.39 0 0 0-20.26-45a88.37 88.37 0 0 1 55.69 45ZM105.32 43a142.39 142.39 0 0 0-20.26 45H49.63a88.37 88.37 0 0 1 55.69-45ZM49.63 168h35.43a142.39 142.39 0 0 0 20.26 45a88.37 88.37 0 0 1-55.69-45Zm101.05 45a142.39 142.39 0 0 0 20.26-45h35.43a88.37 88.37 0 0 1-55.69 45Z"/></svg>

After

Width:  |  Height:  |  Size: 860 B

1
static/icons/PhLink.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M137.54 186.36a8 8 0 0 1 0 11.31l-9.94 10a56 56 0 0 1-79.22-79.27l24.12-24.12a56 56 0 0 1 76.81-2.28a8 8 0 1 1-10.64 12a40 40 0 0 0-54.85 1.63L59.7 139.72a40 40 0 0 0 56.58 56.58l9.94-9.94a8 8 0 0 1 11.32 0Zm70.08-138a56.08 56.08 0 0 0-79.22 0l-9.94 9.95a8 8 0 0 0 11.32 11.31l9.94-9.94a40 40 0 0 1 56.58 56.58l-24.12 24.14a40 40 0 0 1-54.85 1.6a8 8 0 1 0-10.64 12a56 56 0 0 0 76.81-2.26l24.12-24.12a56.08 56.08 0 0 0 0-79.24Z"/></svg>

After

Width:  |  Height:  |  Size: 549 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="m229.66 218.34l-50.07-50.06a88.11 88.11 0 1 0-11.31 11.31l50.06 50.07a8 8 0 0 0 11.32-11.32ZM40 112a72 72 0 1 1 72 72a72.08 72.08 0 0 1-72-72Z"/></svg>

After

Width:  |  Height:  |  Size: 265 B

1
static/icons/PhRss.svg Normal file
View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M106.91 149.09A71.53 71.53 0 0 1 128 200a8 8 0 0 1-16 0a56 56 0 0 0-56-56a8 8 0 0 1 0-16a71.53 71.53 0 0 1 50.91 21.09M56 80a8 8 0 0 0 0 16a104 104 0 0 1 104 104a8 8 0 0 0 16 0A120 120 0 0 0 56 80m118.79 1.21A166.9 166.9 0 0 0 56 32a8 8 0 0 0 0 16a151 151 0 0 1 107.48 44.52A151 151 0 0 1 208 200a8 8 0 0 0 16 0a166.9 166.9 0 0 0-49.21-118.79M60 184a12 12 0 1 0 12 12a12 12 0 0 0-12-12"/></svg>

After

Width:  |  Height:  |  Size: 508 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M236.8 188.09L149.35 36.22a24.76 24.76 0 0 0-42.7 0L19.2 188.09a23.51 23.51 0 0 0 0 23.72A24.35 24.35 0 0 0 40.55 224h174.9a24.35 24.35 0 0 0 21.33-12.19a23.51 23.51 0 0 0 .02-23.72Zm-13.87 15.71a8.5 8.5 0 0 1-7.48 4.2H40.55a8.5 8.5 0 0 1-7.48-4.2a7.59 7.59 0 0 1 0-7.72l87.45-151.87a8.75 8.75 0 0 1 15 0l87.45 151.87a7.59 7.59 0 0 1-.04 7.72ZM120 144v-40a8 8 0 0 1 16 0v40a8 8 0 0 1-16 0Zm20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12Z"/></svg>

After

Width:  |  Height:  |  Size: 555 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M128 24a104 104 0 1 0 104 104A104.11 104.11 0 0 0 128 24Zm0 192a88 88 0 1 1 88-88a88.1 88.1 0 0 1-88 88Zm-8-80V80a8 8 0 0 1 16 0v56a8 8 0 0 1-16 0Zm20 36a12 12 0 1 1-12-12a12 12 0 0 1 12 12Z"/></svg>

After

Width:  |  Height:  |  Size: 313 B

View File

@@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="32" height="32" viewBox="0 0 256 256"><path fill="currentColor" d="M226.76 69a8 8 0 0 0-12.84-2.88l-40.3 37.19l-17.23-3.7l-3.7-17.23l37.19-40.3A8 8 0 0 0 187 29.24A72 72 0 0 0 88 96a72.34 72.34 0 0 0 6 28.94L33.79 177c-.15.12-.29.26-.43.39a32 32 0 0 0 45.26 45.26c.13-.13.27-.28.39-.42L131.06 162A72 72 0 0 0 232 96a71.56 71.56 0 0 0-5.24-27ZM160 152a56.14 56.14 0 0 1-27.07-7a8 8 0 0 0-9.92 1.77l-55.9 64.74a16 16 0 0 1-22.62-22.62L109.18 133a8 8 0 0 0 1.77-9.93a56 56 0 0 1 58.36-82.31l-31.2 33.81a8 8 0 0 0-1.94 7.1l5.66 26.33a8 8 0 0 0 6.14 6.14l26.35 5.66a8 8 0 0 0 7.1-1.94l33.81-31.2A56.06 56.06 0 0 1 160 152Z"/></svg>

After

Width:  |  Height:  |  Size: 673 B

BIN
static/img/error-404.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

BIN
static/img/error-429.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 17 KiB

72
static/tailwind.css Normal file
View File

@@ -0,0 +1,72 @@
@import "tailwindcss" source("../views");
body {
margin: 0 24vw;
}
p a {
@apply break-words underline
}
.posts {
margin-top: 1em;
display: grid;
grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-auto-rows: 1fr;
gap: 1rem;
}
.posts img:not(.icon),
.posts video:not(:fullscreen) {
object-fit: cover;
aspect-ratio: 1;
}
#comments__expandBtn {
display: none;
}
.comments__expandBtn__label {
display: flex;
flex-direction: row;
justify-content: space-between;
align-items: center;
cursor: pointer;
user-select: none;
text-decoration: none;
color: #fff
}
.comments__expandBtn__icon {
font-size: 24px;
}
#comments__expandBtn ~ .comments__expandBtn__label > span::after {
content: "⌄";
}
#comments__expandBtn:checked ~ .comments__expandBtn__label > span::after {
content: "⌃";
}
#comments__expandBtn:checked ~ .comments {
display: none;
}
.comment__media {
height: 12em;
display: block;
margin: 0.5em 0;
}
@media only screen and (max-width: 1280px) {
body {
margin: 0 8vw;
}
}
@media only screen and (max-width: 812px) {
body {
margin: 0 4vw;
}
}

View File

@@ -1,14 +0,0 @@
package types
type Album struct {
Id string
Title string
Views int64
Upvotes int64
Downvotes int64
SharedWithCommunity bool
CreatedAt string
UpdatedAt string
Comments int64
Media []Media
}

View File

@@ -1,15 +0,0 @@
package types
type Comment struct {
Comments []Comment
User User
Id string
Comment string
Upvotes int64
Downvotes int64
Platform string
CreatedAt string
RelTime string
UpdatedAt string
DeletedAt string
}

View File

@@ -1,11 +0,0 @@
package types
type Media struct {
Id string
Name string
Title string
Description string
Url string
Type string
MimeType string
}

View File

@@ -1,24 +0,0 @@
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
Points int64
Upvotes int64
Downvotes int64
Comments int64
Views int64
IsAlbum bool
}

71
utils/config.go Normal file
View File

@@ -0,0 +1,71 @@
package utils
import (
"os"
"time"
)
type config struct {
Port string
Addr string
ImgurId string
ProtocolDetection bool
Secure bool
FiberPrefork bool
ForceWebp bool
ImageCache bool
CleanupInterval time.Duration
CacheDir string
Privacy map[string]interface{}
}
var Config config
func LoadConfig() {
port := "3000"
if os.Getenv("PORT") != "" {
port = os.Getenv("PORT")
}
if os.Getenv("RIMGU_PORT") != "" {
port = os.Getenv("RIMGU_PORT")
}
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 = config{
Port: port,
Addr: addr,
ImgurId: imgurId,
ProtocolDetection: os.Getenv("PROTOCOL_DETECTION") == "true" || os.Getenv("PROTOCOL_DETECTION") == "1",
Secure: os.Getenv("SECURE") == "true" || os.Getenv("SECURE") == "1",
FiberPrefork: os.Getenv("FIBER_PREFORK") == "true" || os.Getenv("FIBER_PREFORK") == "1",
ForceWebp: os.Getenv("FORCE_WEBP") == "true" || os.Getenv("FORCE_WEBP") == "1",
Privacy: map[string]interface{}{
"set": os.Getenv("PRIVACY_NOT_COLLECTED") != "",
"policy": os.Getenv("PRIVACY_POLICY"),
"message": os.Getenv("PRIVACY_MESSAGE"),
"country": os.Getenv("PRIVACY_COUNTRY"),
"provider": os.Getenv("PRIVACY_PROVIDER"),
"cloudflare": os.Getenv("PRIVACY_CLOUDFLARE") == "true" || os.Getenv("PRIVACY_CLOUDFLARE") == "1",
"not_collected": os.Getenv("PRIVACY_NOT_COLLECTED") == "true" || os.Getenv("PRIVACY_NOT_COLLECTED") == "1",
"ip": os.Getenv("PRIVACY_IP") == "true" || os.Getenv("PRIVACY_IP") == "1",
"url": os.Getenv("PRIVACY_URL") == "true" || os.Getenv("PRIVACY_URL") == "1",
"device": os.Getenv("PRIVACY_DEVICE") == "true" || os.Getenv("PRIVACY_DEVICE") == "1",
"diagnostics": os.Getenv("PRIVACY_DIAGNOSTICS") == "true" || os.Getenv("PRIVACY_DIAGNOSTICS") == "1",
},
}
}

25
utils/error.go Normal file
View File

@@ -0,0 +1,25 @@
package utils
import (
"strconv"
"strings"
"codeberg.org/rimgo/rimgo/static"
"github.com/gofiber/fiber/v2"
)
func RenderError(c *fiber.Ctx, code int) error {
if !strings.Contains(c.Get("Accept"), "html") && c.Params("extension") != "" {
codeStr := "generic"
if code != 0 {
codeStr = strconv.Itoa(code)
}
img, _ := static.GetFiles().ReadFile("img/error-" + codeStr + ".png")
c.Set("Content-Type", "image/png")
return c.Status(code).Send(img)
} else {
return c.Status(code).Render("errors/" + strconv.Itoa(code), fiber.Map{
"path": c.Path(),
})
}
}

18
utils/getUrl.go Normal file
View File

@@ -0,0 +1,18 @@
package utils
import "github.com/gofiber/fiber/v2"
func GetInstanceProtocol(c *fiber.Ctx) string {
proto := "https"
if !Config.Secure {
proto = "http"
}
if Config.ProtocolDetection {
proto = c.Get("X-Forwarded-Proto", proto)
}
return proto
}
func GetInstanceUrl(c *fiber.Ctx) string {
return GetInstanceProtocol(c) + "://" + c.Hostname()
}

5
utils/regex.go Normal file
View File

@@ -0,0 +1,5 @@
package utils
import "regexp"
var ImgurRe = regexp.MustCompile(`https?://(i\.)?imgur\.com`)

46
utils/request.go Normal file
View File

@@ -0,0 +1,46 @@
package utils
import (
"fmt"
"io"
"net/http"
"strconv"
"github.com/tidwall/gjson"
)
func GetJSON(url string) (gjson.Result, error) {
req, err := http.NewRequest("GET", url, nil)
if err != nil {
return gjson.Result{}, err
}
SetReqHeaders(req)
client := http.Client{}
res, err := client.Do(req)
if err != nil {
return gjson.Result{}, err
}
rateLimitRemaining := res.Header.Get("X-RateLimit-UserRemaining")
if rateLimitRemaining != "" {
ratelimit, _ := strconv.Atoi(rateLimitRemaining)
if ratelimit <= 0 {
return gjson.Result{}, fmt.Errorf("ratelimited by imgur")
}
}
body, err := io.ReadAll(res.Body)
if err != nil {
return gjson.Result{}, err
}
switch (res.StatusCode) {
case 200:
return gjson.Parse(string(body)), nil
case 429:
return gjson.Result{}, fmt.Errorf("ratelimited by imgur")
default:
return gjson.Result{}, fmt.Errorf("received status %s, expected 200 OK.\n%s", res.Status, string(body))
}
}

View File

@@ -1,12 +1,28 @@
package utils package utils
import "github.com/gofiber/fiber/v2" import (
"net/http"
"github.com/gofiber/fiber/v2"
)
func SetHeaders(c *fiber.Ctx) { func SetHeaders(c *fiber.Ctx) {
c.Set("X-Frame-Options", "DENY")
c.Set("Referrer-Policy", "no-referrer") c.Set("Referrer-Policy", "no-referrer")
c.Set("X-Content-Type-Options", "nosniff") c.Set("X-Content-Type-Options", "nosniff")
c.Set("X-Robots-Tag", "noindex, noimageindex, nofollow") c.Set("X-Robots-Tag", "noindex, noimageindex, nofollow")
c.Set("Strict-Transport-Security", "max-age=31557600") 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=()")
}
func SetReqHeaders(req *http.Request) {
req.Header.Set("Accept", "*/*")
req.Header.Set("Accept-Language", "en-US,en;q=0.5")
req.Header.Set("Cache-Control", "no-cache")
req.Header.Set("Connection", "keep-alive")
req.Header.Set("Origin", "https://imgur.com")
req.Header.Set("Pragma", "no-cache")
req.Header.Set("Sec-Fetch-Dest", "empty")
req.Header.Set("Sec-Fetch-Mode", "cors")
req.Header.Set("Sec-Fetch-Site", "same-site")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 10.0; rv:102.0) Gecko/20100101 Firefox/102.0")
} }

110
views/about.hbs Normal file
View File

@@ -0,0 +1,110 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>About - rimgo</title>
{{> partials/head }}
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<section class="my-4 w-full flex flex-col items-center">
{{> partials/searchBar }}
</section>
<main class="my-8">
<p>An alternative frontend for Imgur. Originally based on <a href="https://codeberg.org/3np/rimgu" rel="noreferrer">rimgu</a>.</p>
<h2 class="font-bold text-2xl my-2">Features</h2>
<ul class="list-disc ml-4">
<li>Lightweight</li>
<li>No JavaScript</li>
<li>No ads or tracking</li>
<li>No sign up or app install prompts</li>
<li>Bandwidth efficient - automatically uses newer image formats (if enabled)</li>
</ul>
<h2 class="font-bold text-2xl my-2">Comparison</h2>
<p>Comparing rimgo to Imgur.</p>
<h3 class="font-bold text-xl my-2">Speed</h3>
<p>Tested using <a href="https://pagespeed.web.dev/" rel="nofollow noreferrer">Google PageSpeed Insights</a>.</p>
<table>
<tr>
<td></td>
<td><a href="https://pagespeed.web.dev/report?url=https%3A%2F%2Fi.bcow.xyz%2Fgallery%2FgYiQLWy" rel="nofollow noreferrer">rimgo</a></td>
<td><a href="https://pagespeed.web.dev/report?url=https%3A%2F%2Fimgur.com%2Fgallery%2FgYiQLWy" rel="nofollow noreferrer">Imgur</a></td>
</tr>
<tr>
<td>Performance</td>
<td>91</td>
<td>28</td>
</tr>
<tr>
<td>Request count</td>
<td>29</td>
<td>340</td>
</tr>
<tr>
<td>Resource Size</td>
<td>218 KiB</td>
<td>2,542 KiB</td>
</tr>
<tr>
<td>Time to Interactive</td>
<td>1.6s</td>
<td>23.8s</td>
</tr>
</table>
<h3 class="font-bold text-xl my-2">Privacy</h3>
<p>Imgur collects information about your device and uses tracking cookies for advertising, this is mentioned in their <a href="https://imgur.com/privacy/" rel="nofollow noreferrer">privacy policy</a>. <a href="https://themarkup.org/blacklight" rel="nofollow noreferrer">Blacklight</a> found 31 trackers and 87 third-party cookies.</p>
<p>See what cookies and trackers Imgur uses and where your data gets sent: <a href="https://themarkup.org/blacklight?url=imgur.com" rel="nofollow noreferrer">https://themarkup.org/blacklight?url=imgur.com</a></p>
<h2 class="font-bold text-2xl my-2">Usage</h2>
<p>Just replace imgur.com or i.imgur.com with <code>{{domain}}</code> (add stack/ before the media ID for i.stack.imgur.com). You can setup automatic redirects using <a href="https://github.com/libredirect/libredirect" rel="nofollow noreferrer">LibRedirect</a> (recommended) or <a href="https://github.com/einaregilsson/Redirector" rel="nofollow noreferrer">Redirector</a>.</p>
{{#if force_webp}}
<p>To download images as their original filetype, add <code>?no_webp=1</code> to the end of the image URL.</p>
{{/if}}
<h2 class="font-bold text-2xl my-2">Automatically redirect links</h2>
<h3 class="font-bold text-xl my-2">LibRedirect</h3>
<p>Use <a href="https://github.com/libredirect/libredirect" rel="nofollow noreferrer">LibRedirect</a> to automatically redirect Imgur links to rimgo!</p>
<h3 class="font-bold text-xl my-2">GreaseMonkey script</h3>
<p>There is a script to redirect Imgur links to rimgo. <a rel="noreferrer" href="https://codeberg.org/zortazert/GreaseMonkey-Redirect/src/branch/main/imgur-to-rimgo.user.js">https://codeberg.org/zortazert/GreaseMonkey-Redirect/src/branch/main/imgur-to-rimgo.user.js</a></p>
<h3 class="font-bold text-xl my-2">Redirector</h3>
<p>You can use the <a href="https://github.com/einaregilsson/Redirector" rel="nofollow noreferrer">Redirector</a> extension to redirect Imgur links to rimgo with the configuration below:</p>
<ul class="list-disc ml-4">
<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}}$1</code></li>
<li>Pattern type: Regular Expression</li>
<li>Advanced Options > Apply to: Check Images</li>
</ul>
<br/>
<p>For Stack Overflow Images:</p>
<ul class="list-disc ml-4">
<li>Description: Stack Overflow Imgur -> rimgo</li>
<li>Example URL: https://i.stack.imgur.com/BTKqD.png?s=128&g=1</li>
<li>Include pattern: <code>^https?://i\.stack\.imgur\.com(/.*)?$</code></li>
<li>Redirect to: <code>{{proto}}://{{domain}}/stack$1</code></li>
<li>Pattern type: Regular Expression</li>
<li>Advanced Options > Apply to: Check Images</li>
</ul>
<h2 class="font-bold text-2xl my-2">Notice</h2>
<p>All images and media are from Imgur. rimgo does not allow uploads or comments. Any issues with content should be reported to Imgur.</p>
</main>
{{> partials/footer }}
</body>
</html>

48
views/embed.hbs Normal file
View File

@@ -0,0 +1,48 @@
<!DOCTYPE html>
<html lang="en">
<head>
{{> partials/head }}
<link rel="stylesheet" href="/static/css/embed.css" />
</head>
<body>
<div class="mediaWrapper">
<div class="media">
{{#each post.Media}}
{{#equal this.Type "image"}}
<img src="{{this.Url}}" loading="lazy">
{{/equal}}
{{#equal this.Type "video"}}
<video controls loop>
<source type="{{this.MimeType}}" src="{{this.Url}}" />
</video>
{{/equal}}
{{/each}}
</div>
</div>
<div class="postMeta">
<div class="postDetails">
{{#if post.TItle}}
<a href="/{{post.Id}}">
<h3>{{post.Title}}</h3>
</a>
{{/if}}
<div class="views flex flex-center">
<img class="icon" src="/static/icons/eye.svg" alt="Views">
<p>{{post.Views}}</p>
</div>
</div>
<div class="flex flex-center">
<a href="/{{post.Id}}">
<img src="/static/img/rimgo.svg" width="32px" height="32px" class="logo">
</a>
<a href="/{{post.Id}}">
rimgo
</a>
</div>
</div>
</body>
</html>

21
views/errors/404.hbs Normal file
View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Not Found - rimgo</title>
{{> partials/head }}
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<main>
<h2 class="text-2xl font-bold">Not Found</h2>
<p>Click <a href="/">here</a> to return to home.</p>
</main>
{{> partials/footer }}
</body>
</html>

21
views/errors/429.hbs Normal file
View File

@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Rate limited by Imgur - rimgo</title>
{{> partials/head }}
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<main>
<h2 class="text-2xl font-bold">Rate limited by Imgur</h2>
<p>This instance has been temporarily blocked by Imgur. <a href="https://rimgo.codeberg.page/#{{ path }}">Try using another instance ></a></p>
</main>
{{> partials/footer }}
</body>
</html>

22
views/errors/error.hbs Normal file
View File

@@ -0,0 +1,22 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Error - rimgo</title>
{{> partials/head }}
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<main class="flex flex-col">
<h2 class="text-2xl font-bold">An error occurred</h2>
<p>You may have found a bug in rimgo. If this is a bug, open an issue on <a href="https://codeberg.org/video-prize-ranch/rimgo/issues/new">Codeberg</a>.</p>
<code class="mt-4 p-2 bg-slate-600 rounded-md">{{err}}</code>
</main>
{{> partials/footer }}
</body>
</html>

View File

@@ -5,54 +5,49 @@
<title>rimgo</title> <title>rimgo</title>
{{> partials/head }} {{> partials/head }}
<link rel="stylesheet" href="/static/css/frontpage.css" />
</head> </head>
<body> <body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/header }} {{> partials/nav }}
<main> <header class="my-8 p-8 rounded-xl flex flex-col gap-4 items-center justify-center bg-gradient-to-r from-blue-400 to-emerald-400">
<p>An alternative frontend for Imgur. Based on <a href="https://codeberg.org/3np/rimgu">rimgu</a> and rewritten in Go.</p> <h2 class="font-bold text-white text-2xl">The fast, private image viewer for Imgur.</h2>
{{> partials/searchBar }}
<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> <a class="flex gap-1 items-center" href="/trending">Or see what's trending <img class="invert" src="/static/icons/PhArrowUpRight.svg" alt="" height="18" width="18" /></a>
</header>
<h3>Try it!</h3>
<ul>
<li><a href="/a/H8M4rcp">Album</a></li>
<li><a href="/gallery/gYiQLWy">Gallery</a></li>
<li><a href="/gallery/cTRwaJU">Video</a></li>
</ul>
<h2>Features</h2>
<ul>
<li>URL-compatible with i.imgur.com - just replace the domain in the URL</li>
<li>Images and videos (gifv, mp4)</li>
<li>Albums</li>
<li>Streaming</li>
<li>Pretty CSS styling (responsive!)</li>
<li>Logo</li>
</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>
<main class="my-8">
<h2 class="font-bold text-2xl">What is rimgo?</h2>
<p>
rimgo is an alternative frontend for Imgur.
Originally based on <a href="https://codeberg.org/3np/rimgu" rel="noreferrer">rimgu</a>.
It's a way to access Imgur without the ads, tracking, and other garbage.
rimgo is not affiliated with Imgur, all content is proxied from Imgur.
</p>
<br/>
<h3 class="font-bold text-xl">Legal notice</h3>
<p>rimgo does not allow uploads or host any content, media. All content on any rimgo instances is from Imgur™. Imgur is a trademark of Imgur, Inc. Any issues with content on rimgo should be be reported to Imgur. rimgo is not affiliated with Imgur, Inc.</p>
</main> </main>
<h2 class="font-bold text-2xl">This instance</h2>
<section class="my-4 lg:m-4 flex flex-col lg:flex-row gap-4 items-center">
{{> partials/privacy }}
<div class="self-start">
<h2 class="text-xl my-2 font-bold">Additional information</h2>
<ul>
<li>Version: {{version}}</li>
<li>Country: {{config.Privacy.country}}</li>
<li>Provider: {{config.Privacy.provider}}</li>
{{#if config.Privacy.cloudflare}}
<li>Using Cloudflare?: Yes</li>
{{else}}
<li>Using Cloudflare?: No</li>
{{/if}}
</ul>
</div>
</section>
<p><a href="/privacy">Learn more about instance privacy ></a></p>
{{> partials/footer }} {{> partials/footer }}
</body> </body>

View File

@@ -1,93 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{album.Title}} - rimgo</title>
{{> partials/head }}
<link rel="stylesheet" href="/static/fonts/Material-Icons-Outlined.css" />
<link rel="stylesheet" href="/static/css/album.css" />
<link rel="stylesheet" href="/static/css/comments.css" />
</head>
<body>
{{> partials/header }}
<main>
<h1>{{album.Title}}</h1>
<p>{{album.CreatedAt}}</p>
<div class="imageMeta__wrapper">
<div class="imageMeta">
<div class="imageMeta__item">
<span class="material-icons-outlined" title="Views">visibility</span>
<p>{{album.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}}
</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}}
{{#if this.Title}}
<h3>{{this.Title}}</h3>
{{/if}}
{{#if this.Description}}
<p>{{this.Description}}</p><br>
{{/if}}
<div class="center">
{{#equal this.Type "image"}}
<img src="{{this.Url}}" loading="lazy">
{{/equal}}
{{#equal this.Type "video"}}
<video controls loop>
<source type="{{this.MimeType}}" src="{{this.Url}}" />
</video>
{{/equal}}
</div>
<br>
{{/each}}
{{#if comments}}
<div>
<hr>
<input id="comments__expandBtn" type="checkbox">
<label class="comments__expandBtn__label" for="comments__expandBtn">
<h3>Comments ({{album.Comments}})</h3>
<span class="comments__expandBtn__icon material-icons-outlined"></span>
</label>
<div class="comments">
{{#each comments}}
{{> partials/comment }}
{{/each}}
</div>
</div>
<hr>
{{/if}}
</main>
{{> partials/footer }}
</body>
</html>

32
views/gifv.hbs Normal file
View File

@@ -0,0 +1,32 @@
<!DOCTYPE html>
<html lang="en">
<head>
{{> partials/head }}
<link rel="stylesheet" href="/static/css/embed.css" />
</head>
<body>
<div class="mediaWrapper">
<div class="media media--gifv">
<video loop poster="/{{id}}.webp" autoplay controls>
<source src="/{{id}}.webm" type="video/webm" />
<source src="/{{id}}.mp4" type="video/mp4" />
</video>
</div>
</div>
<div class="postMeta">
<a href="/{{id}}.mp4" download="{{id}}.mp4">download</a>
<div class="flex flex-center">
<a href="/{{post.Id}}">
<img src="/static/img/rimgo.svg" width="32px" height="32px" class="logo">
</a>
<a href="/{{post.Id}}">
rimgo
</a>
</div>
</div>
</body>
</html>

View File

@@ -1,25 +1,32 @@
<div class="comment"> <div class="flex flex-col gap-2">
<div class="comment__user"> <div class="flex gap-2 items-center">
<img src="{{this.User.Avatar}}" class="pfp" width="24" height="24" loading="lazy"> {{#noteq this.User.Username "[deleted]"}}
<img src="{{this.User.Avatar}}" class="rounded-full" width="24" height="24" loading="lazy">
<a href="/user/{{this.User.Username}}"> <a href="/user/{{this.User.Username}}">
<p class="comment__user__username"><b>{{this.User.Username}}</b></p> <p class="whitespace-nowrap text-ellipsis overflow-hidden"><b>{{this.User.Username}}</b></p>
</a> </a>
{{/noteq}}
{{#equal this.User.Username "[deleted]"}}
<p class="whitespace-nowrap text-ellipsis overflow-hidden"><b>[deleted]</b></p>
{{/equal}}
</div> </div>
<div> <div>
{{{this.Comment}}} <p>{{{this.Comment}}}</p>
<p> <div class="flex gap-2">
<span title="{{this.CreatedAt}}">{{this.RelTime}}</span> <span title="{{this.CreatedAt}}">{{this.RelTime}}</span>
{{#if this.DeletedAt}} {{#if this.DeletedAt}}
<span class="comment__updatedDate">(deleted {{this.DeletedAt}})</span> <span class="text-md">(deleted {{this.DeletedAt}})</span>
{{/if}} {{/if}}
| |
<span class="material-icons-outlined">thumb_up</span> {{this.Upvotes}} <img class="invert icon" src="/static/icons/PhArrowFatUp.svg" alt="Likes" width="24px" height="24px"> {{this.Upvotes}}
<span class="material-icons-outlined">thumb_down</span> {{this.Downvotes}} <img class="invert icon" src="/static/icons/PhArrowFatDown.svg" alt="Dislikes" width="24px" height="24px"> {{this.Downvotes}}
</p>
</div> </div>
<div class="replies"> </div>
{{#if this.Comments}}
<div class="ml-4 p-2 border-solid border-l-2 border-slate-400">
{{#each this.Comments}} {{#each this.Comments}}
{{> partials/comment }} {{> partials/comment }}
{{/each}} {{/each}}
</div> </div>
{{/if}}
</div> </div>

View File

@@ -0,0 +1,22 @@
<a href="{{Post.Link}}">
<div class="sm:grid gap-4 w-full" style="grid-template-columns: 120px 1fr;">
<img class="object-cover block w-full h-[300px] sm:w-[120px] sm:h-[140px] rounded-lg rounded-b-none sm:rounded-b-lg" src="{{this.Post.Cover.Url}}" alt="">
<div class="flex flex-col gap-2 bg-slate-600 p-4 rounded-lg rounded-t-none sm:rounded-t-lg w-full">
<div class="flex flex-col h-full">
<p class="md-container">{{{this.Comment}}}</p>
<div class="grow"></div>
<div class="flex gap-2">
<span title="{{this.CreatedAt}}">{{this.RelTime}}</span>
{{#if this.DeletedAt}}
<span class="text-md">(deleted {{this.DeletedAt}})</span>
{{/if}}
|
<img class="invert icon" src="/static/icons/PhArrowFatUp.svg" alt="Likes" width="24px" height="24px">
{{this.Upvotes}}
<img class="invert icon" src="/static/icons/PhArrowFatDown.svg" alt="Dislikes" width="24px" height="24px">
{{this.Downvotes}}
</div>
</div>
</div>
</div>
</a>

View File

@@ -1,10 +1,14 @@
<br><br><br> <footer class="mt-24 mb-12">
<div class="mb-1 flex gap-4 font-bold">
<footer> <a href="/">
<!--<a href="/privacy"> <div class="flex">
<span class="material-icons-outlined">visibility</span> Privacy <img src="/static/img/rimgo.svg" class="invert hue-rotate-180" width="32" height="32" />
</a>--> <h1 class="text-md font-extrabold">rimgo</h1>
<a href="https://codeberg.org/video-prize-ranch/rimgo" rel="noreferrer"> </div>
<span class="material-icons-outlined">code</span> Source Code
</a> </a>
<a href="https://codeberg.org/rimgo/rimgo">Source Code</a>
<a href="/about">About</a>
<a href="/privacy">Privacy</a>
</div>
<p class="text-md text-slate-200">rimgo does not allow uploads or host any content. Issues with content should be reported to Imgur.</p>
</footer> </footer>

View File

@@ -12,5 +12,4 @@
<meta name="msapplication-config" content="/static/favicon/browserconfig.xml"> <meta name="msapplication-config" content="/static/favicon/browserconfig.xml">
<meta name="theme-color" content="#ffffff"> <meta name="theme-color" content="#ffffff">
<link rel="stylesheet" href="/static/fonts/Material-Icons-Outlined.css" /> <link rel="stylesheet" href="/static/app.css" />
<link rel="stylesheet" href="/static/css/base.css"/>

View File

@@ -1,8 +0,0 @@
<nav>
<a href="/">
<img src="/static/img/rimgo.svg" width="64" height="64" class="logo">
</a>
<a href="/">
<h2>rimgo</h2>
</a>
</nav>

6
views/partials/nav.hbs Normal file
View File

@@ -0,0 +1,6 @@
<a href="/">
<nav class="m-4 flex items-center justify-center">
<img src="/static/img/rimgo.svg" class="invert hue-rotate-180" width="72" height="72" />
<h1 class="font-extrabold text-3xl">rimgo</h1>
</nav>
</a>

View File

@@ -1,32 +1,27 @@
<a href="{{Link}}"> <a href="{{Link}}">
<div class="post"> <div class="bg-slate-600 rounded-lg">
{{#equal Cover.Type "video"}} {{#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" /> <source src="{{Cover.Url}}" type="video/mp4" />
</video> </video>
{{/equal}} {{/equal}}
{{#equal Cover.Type "image"}} {{#equal Cover.Type "image"}}
<img src="{{Cover.Url}}" loading="lazy" width="100%" height="100%"> <img src="{{Cover.Url}}" loading="lazy" width="100%" height="100%">
{{/equal}} {{/equal}}
<p class="post__title">{{Title}}</p> <p class="m-2 text-ellipsis whitespace-nowrap overflow-hidden">{{Title}}</p>
<div class="post__meta"> <div class="flex gap-2 p-2">
<p> <div class="flex gap-1">
<span class="material-icons-outlined"> <img class="invert icon" src="/static/icons/PhArrowFatUp.svg" alt="Points" width="18px" height="18px">
arrow_upward
</span>
{{Points}} {{Points}}
</p> </div>
<p> <div class="flex gap-1">
<span class="material-icons-outlined"> <img class="invert icon" src="/static/icons/PhChat.svg" alt="Comments" width="18px" height="18px">
comment
</span>
{{Comments}} {{Comments}}
<p> </div>
<span class="material-icons-outlined"> <div class="flex gap-1">
visibility <img class="invert icon" src="/static/icons/PhEye.svg" alt="Views" width="18px" height="18px">
</span>
{{Views}} {{Views}}
</p> </div>
</div> </div>
</div> </div>
</a> </a>

View File

@@ -0,0 +1,48 @@
{{#if config.Privacy.not_collected}}
<div class="flex flex-col items-center w-full lg:w-1/2 p-4 bg-slate-600 rounded-lg">
<img class="invert" src="/static/icons/PhCheckCircle.svg" alt="" height="36" width="36" />
<h2 class="font-bold text-xl">Data not collected</h2>
<p class="text-lg">This instance does not collect any data.</p>
</div>
{{/if}}
{{#unless config.Privacy.set}}
<div class="flex flex-col items-center w-full lg:w-1/2 p-4 bg-slate-600 rounded-lg">
<img class="invert" src="/static/icons/PhWarning.svg" alt="" height="36" width="36" />
<h2 class="font-bold text-xl">No details provided</h2>
<p class="text-lg">The operator of this instance will be required to provide privacy details to be added to the instance list.</p>
</div>
{{else}}
{{#unless config.Privacy.not_collected}}
<div class="flex flex-col items-center w-full lg:w-1/2 p-4 bg-slate-600 rounded-lg">
<img class="invert" src="/static/icons/PhWarningCircle.svg" alt="" height="36" width="36" />
<h2 class="font-bold text-xl">Data collected</h2>
<p class="text-lg">The following data may be collected:</p>
<ul class="flex flex-col">
{{#if config.Privacy.ip}}
<li class="flex gap-1">
<img class="invert" src="/static/icons/PhGlobe.svg" alt="" width="24px" height="24px" />
Internet address (IP Address)
</li>
{{/if}}
{{#if config.Privacy.url}}
<li class="flex gap-1">
<img class="invert" src="/static/icons/PhLink.svg" alt="" width="24px" height="24px" />
Page viewed (Request URL)
</li>
{{/if}}
{{#if config.Privacy.device}}
<li class="flex gap-1">
<img class="invert" src="/static/icons/PhDevices.svg" alt="" width="24px" height="24px" />
Device Type (User agent)
</li>
{{/if}}
{{#if config.Privacy.diagnostics}}
<li class="flex gap-1">
<img class="invert" src="/static/icons/PhWrench.svg" alt="" width="24px" height="24px" />
Diagnostics
</li>
{{/if}}
</ul>
</div>
{{/unless}}
{{/unless}}

26
views/partials/result.hbs Normal file
View File

@@ -0,0 +1,26 @@
<div class="bg-slate-600 rounded-lg">
<a href="{{Url}}">
<img src="{{ImageUrl}}?no_webp=1" loading="lazy" width="100%" height="100%">
</a>
<p class="m-2 text-ellipsis whitespace-nowrap overflow-hidden">
<a href="{{Url}}" title="{{Title}}">{{Title}}</a><br />
{{#if User}}
by <a href="/user/{{User}}" title="{{User}}">{{User}}</a>
{{else}}
<br />
{{/if}}
</p>
<div class="flex gap-2 p-2">
<p title="{{RelTime}}" class="text-ellipsis whitespace-nowrap overflow-hidden">
{{RelTime}}
</p>
<div class="flex gap-1">
<img class="invert icon" src="/static/icons/PhArrowFatUp.svg" alt="Points" width="18px" height="18px">
{{Points}}
</div>
<div class="flex gap-1">
<img class="invert icon" src="/static/icons/PhEye.svg" alt="Views" width="18px" height="18px">
{{Views}}
</div>
</div>
</div>

View File

@@ -0,0 +1,6 @@
<form method="GET" action="/search" class="flex gap-2 w-full lg:w-1/2">
<input class="p-2 rounded-lg bg-slate-600 w-full" name="q" type="text" placeholder="Search or paste a link" {{#if query}}value="{{query}}"{{/if}}/>
<button type="submit" class="p-2 rounded-lg bg-slate-600">
<img class="invert icon" src="/static/icons/PhMagnifyingGlass.svg" alt="Search" width="24px" height="24px">
</button>
</form>

128
views/post.hbs Normal file
View File

@@ -0,0 +1,128 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>
{{#if post.Title}}
{{post.Title}} -
{{/if}}
rimgo
</title>
{{> partials/head }}
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<section class="my-4 w-full flex flex-col items-center">
{{> partials/searchBar }}
</section>
<header>
<h1 class="text-3xl font-bold">{{post.Title}}</h1>
<p>{{post.CreatedAt}}</p>
</header>
<main>
<div class="flex flex-col sm:flex-row my-4 w-full justify-between">
<div class="flex flex-col gap-2 md:flex-row md:gap-4 md:items-center">
{{#if post.User.Username}}
<a href="/user/{{post.User.Username}}" class="flex gap-2 items-center">
<img src="{{post.User.Avatar}}" class="rounded-full" width="36" height="36" />
<p>
<b>{{post.User.Username}}</b>
</p>
</a>
{{/if}}
<div class="flex gap-2 items-center">
<div class="flex flex-center gap-2">
<img class="icon invert" src="/static/icons/PhEye.svg" alt="Views" width="24px" height="24px">
<p>{{post.Views}}</p>
</div>
{{#if post.SharedWithCommunity}}
<div class="flex flex-center gap-2">
<img class="icon invert" src="/static/icons/PhArrowFatUp.svg" alt="Likes" width="24px" height="24px">
<p>{{post.Upvotes}}</p>
</div>
<div class="flex flex-center gap-2">
<img class="icon invert" src="/static/icons/PhArrowFatDown.svg" alt="Dislikes" width="24px" height="24px">
<p>{{post.Downvotes}}</p>
</div>
{{/if}}
</div>
</div>
{{#noteq next ""}}
<a href="{{next}}" class="self-end">
<button class="p-2 rounded-lg bg-slate-600">Next &gt;</button>
</a>
{{/noteq}}
</div>
<div class="flex flex-center flex-col break-words">
{{#each post.Media}}
{{#if this.Title}}
<h4 class="font-bold">{{this.Title}}</h4>
{{/if}}
{{#equal this.Type "image"}}
<img class="my-2 max-h-96 object-contain" src="{{this.Url}}" loading="lazy">
{{/equal}}
{{#equal this.Type "video"}}
<video class="my-2 max-h-96 object-contain" controls loop>
<source type="{{this.MimeType}}" src="{{this.Url}}" />
</video>
{{/equal}}
{{#if this.Description}}
<p>{{{this.Description}}}</p>
{{/if}}
{{/each}}
</div>
{{#if post.tags}}
<div class="flex gap-2 my-2 flex-wrap">
<style nonce="{{nonce}}">
{{#each post.tags}}
.{{this.BackgroundId}} { background-image: url('{{this.Background}}') }
{{/each}}
</style>
{{#each post.tags}}
<a href="/t/{{this.Tag}}">
<div class="rounded-md p-4 min-w-[110px] bg-slate-500 {{this.BackgroundId}}">
<p class="font-bold text-white text-center">
{{#if tag.Display}}
{{this.Display}}
{{else}}
{{this.Tag}}
{{/if}}
</p>
</div>
</a>
{{/each}}
</div>
{{/if}}
</main>
<section>
{{#if comments}}
<div>
<input id="comments__expandBtn" type="checkbox" checked>
<label class="comments__expandBtn__label my-2 py-4 border-solid border-t-2 border-slate-400"
for="comments__expandBtn">
<h3 class="text-xl font-bold">Comments ({{post.Comments}})</h3>
<span class="text-xl font-bold"></span>
</label>
<div class="comments flex flex-col gap-2">
{{#each comments}}
{{> partials/comment }}
{{/each}}
</div>
</div>
{{/if}}
</section>
{{> partials/footer }}
</body>
</html>

78
views/privacy.hbs Normal file
View File

@@ -0,0 +1,78 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Privacy - rimgo</title>
{{> partials/head }}
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<section class="my-4 w-full flex flex-col items-center">
{{> partials/searchBar }}
</section>
<header>
<h1 class="text-3xl font-bold">Instance Privacy</h1>
{{#if config.Privacy.policy}}
<p>The instance operator has indicated their instance's privacy practices below. For more information, see the
instance operator's <a href="{{config.Privacy.policy}}">privacy policy</a>.</p>
{{else}}
<p>The instance operator has indicated their instance's privacy practices below.</p>
{{/if}}
{{#if config.Privacy.message}}
<p class="my-4">{{{config.Privacy.message}}}</p>
{{/if}}
</header>
<main class="flex justify-center w-full">
{{> partials/privacy }}
</main>
<section>
<h2 class="text-2xl my-4 font-bold">What is instance privacy?</h2>
<p>Instance privacy aims to bring transparency to the data collected by frontends and encourage privacy friendly practices. There is often no privacy policy and users are forced to trust that the instance operator is not collecting data. However, there is a possibility that the instance operator can put false information so we encourage looking at other factors when selecting an instance.</p>
<ul class="flex flex-col list-outside list-disc mt-2 ml-4">
<li>
<img class="inline invert" src="/static/icons/PhGlobe.svg" alt="" width="24px" height="24px" />
Internet address (IP Address) - This is an address that is given to your computer or internet connection.
This can be used to find your city or region and internet provider but can change depending on your connection.
</li>
<li>
<img class="inline invert" src="/static/icons/PhLink.svg" alt="" width="24px" height="24px" />
Page viewed (Request URL) - This is what page you are viewing.
</li>
<li>
<img class="inline invert" src="/static/icons/PhDevices.svg" alt="" width="24px" height="24px" />
Device Type (User agent) - This is what browser, device, and operating system you are using.
Advanced users can change this with an extension or browser setting.
</li>
<li>
<img class="inline invert" src="/static/icons/PhWrench.svg" alt="" width="24px" height="24px" />
Diagnostics - When this data is only collected when there is an error or only a short amount of time while
diagnosing an issue.
</li>
</ul>
</section>
<section>
<h2 class="text-2xl my-4 font-bold">Additional information</h2>
<ul>
<li>Version: {{version}}</li>
<li>Country: {{config.Privacy.country}}</li>
<li>Provider: {{config.Privacy.provider}}</li>
{{#if config.Privacy.cloudflare}}
<li>Using Cloudflare?: Yes</li>
{{else}}
<li>Using Cloudflare?: No</li>
{{/if}}
</ul>
</section>
{{> 'partials/footer' }}
</body>
</html>

36
views/search.hbs Normal file
View File

@@ -0,0 +1,36 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{query}} - rimgo</title>
{{> partials/head }}
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<section class="my-4 w-full flex flex-col items-center">
{{> partials/searchBar }}
</section>
<main>
<div class="posts">
{{#each results}}
{{> partials/result }}
{{/each}}
</div>
<div class="flex justify-between mt-4 font-bold">
{{#noteq page "0"}}
<a href="/search?q={{query}}&page={{prevPage}}">Previous page</a>
{{/noteq}}
<p>Page {{nextPage}}</p>
<a href="/search?q={{query}}&page={{nextPage}}">Next page</a>
</div>
</main>
{{> partials/footer }}
</body>
</html>

68
views/tag.hbs Normal file
View File

@@ -0,0 +1,68 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{tag.Display}} - rimgo</title>
{{> partials/head }}
<link href="/t/{{tag.Tag}}.rss" rel="alternate" title={{tag.Display}} type="application/rss+xml"
<link href="/t/{{tag.Tag}}.atom" rel="alternate" title={{tag.Display}} type="application/atom+xml">
<link href="/t/{{tag.Tag}}.json" rel="alternate" title={{tag.Display}} type="application/feed+json">
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<section class="my-4 w-full flex flex-col items-center">
{{> partials/searchBar }}
</section>
<header class="p-4 rounded-xl text-white mb-4" style="background-image: url('{{tag.Background}}');">
<div class="flex flex-col items-center justify-center text-center">
<div class="flex gap-2 items-center">
<h2 class="text-2xl font-bold">{{tag.Display}}</h2>
<a href="/t/{{tag.Tag}}.rss" label="RSS">
<img src="/static/icons/PhRss.svg" width="24px" height="24px" class="invert" />
</a>
</div>
<p>{{tag.PostCount}} posts</p>
</div>
<div class="flex flex-col">
{{#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>
</header>
<main>
<div class="posts">
{{#each tag.Posts}}
{{> partials/post }}
{{/each}}
</div>
<div class="flex justify-between mt-4 font-bold">
{{#noteq page "1"}}
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>
{{/noteq}}
<p>Page {{nextPage}}</p>
<a href="{{channel.RelUrl}}?page={{nextPage}}">Next page</a>
</div>
</main>
{{> partials/footer }}
</body>
</html>

Some files were not shown because too many files have changed in this diff Show More