Compare commits

...

46 Commits
v1.2.0 ... main

Author SHA1 Message Date
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
43 changed files with 1291 additions and 389 deletions

View File

@ -2,6 +2,7 @@ ADDRESS=0.0.0.0
PORT=3000 PORT=3000
FIBER_PREFORK=false FIBER_PREFORK=false
IMGUR_CLIENT_ID=546c25a59c58ad7 IMGUR_CLIENT_ID=546c25a59c58ad7
SECURE=true
# Instance privacy # Instance privacy
# For more information, see https://codeberg.org/librarian/librarian/wiki/Instance-privacy # For more information, see https://codeberg.org/librarian/librarian/wiki/Instance-privacy

1
.gitignore vendored
View File

@ -2,3 +2,4 @@
tmp tmp
static/app.css static/app.css
dist/ dist/
node_modules

View File

@ -1,6 +1,7 @@
version: 2
before: before:
hooks: hooks:
- tailwindcss -i static/tailwind.css -o static/app.css -m - pnpm run build
- go mod tidy - go mod tidy
project_name: rimgo project_name: rimgo
builds: builds:
@ -16,24 +17,26 @@ builds:
ldflags: ldflags:
- -X codeberg.org/rimgo/rimgo/pages.VersionInfo={{.Version}} - -X codeberg.org/rimgo/rimgo/pages.VersionInfo={{.Version}}
archives: archives:
- format: tar.gz - formats: tar.gz
name_template: >- name_template: >-
{{ .ProjectName }}-{{ .Os }}-{{ .Arch }}{{- if .Arm }}v{{ .Arm }}{{ end }} {{ .ProjectName }}-{{ .Os }}-{{ .Arch }}{{- if .Arm }}v{{ .Arm }}{{ end }}
format_overrides: format_overrides:
- goos: windows - goos: windows
format: zip formats: zip
checksum: checksum:
name_template: 'checksums.txt' name_template: 'checksums.txt'
kos: kos:
- repository: codeberg.org/rimgo/rimgo - repositories:
- codeberg.org/rimgo/rimgo
- codeberg.org/video-prize-ranch/rimgo
tags: tags:
- '{{.Version}}' - '{{.Version}}'
- latest - latest
bare: true bare: true
preserve_import_paths: false preserve_import_paths: false
platforms: platforms:
- linux/amd64 - linux/amd64
- linux/arm64 - linux/arm64
sbom: none sbom: none
gitea_urls: gitea_urls:
api: https://codeberg.org/api/v1 api: https://codeberg.org/api/v1

View File

@ -3,14 +3,14 @@ FROM --platform=$BUILDPLATFORM golang:alpine AS build
ARG TARGETARCH ARG TARGETARCH
WORKDIR /src WORKDIR /src
RUN apk --no-cache add ca-certificates git nodejs npm RUN apk --no-cache add ca-certificates git nodejs pnpm
COPY . . COPY . .
RUN npx tailwindcss -i static/tailwind.css -o static/app.css -m RUN pnpm install && pnpm run build
RUN go mod download 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)" 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 scratch 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 /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

View File

@ -1,7 +1,14 @@
build: build:
tailwindcss -i static/tailwind.css -o static/app.css -m 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)" 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: dev:
tailwindcss -i static/tailwind.css -o static/app.css -m -w & go run github.com/air-verse/air@latest -c .air.toml
go run github.com/cosmtrek/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

View File

@ -65,58 +65,8 @@ Stack Overflow: `https://i.stack.imgur.com/KnO3v.jpg?s=64&g=1` -> `https://rimgo
To automatically redirect Imgur links, see [Redirection](https://rimgo.codeberg.page/docs/usage/redirection/). To automatically redirect Imgur links, see [Redirection](https://rimgo.codeberg.page/docs/usage/redirection/).
## Instances ## Instances
Open an issue to have your instance listed here! See the rules for the instance list [here](https://rimgo.codeberg.page/docs/usage/instance-list-rules/).
> For more details on instance privacy, see https://rimgo.codeberg.page/docs/usage/instance-privacy/ Available at https://rimgo.codeberg.page/ or https://codeberg.org/rimgo/instances
### Clearnet
| URL | Country | Provider | Privacy | Notes |
| :------------------------------------------------------------ | :----------- | :----------------------- | :-------------------- | :---- |
| [rimgo.pussthecat.org](https://rimgo.pussthecat.org) | 🇩🇪 DE | Hetzner | ⚠️ Data collected | |
| [rimgo.totaldarkness.net](https://rimgo.totaldarkness.net) | 🇨🇦 CA | Vultr | ✅ Data not collected | |
| [rimgo.bus-hit.me](https://rimgo.bus-hit.me) | 🇨🇦 CA | Oracle | ⚠️ Data collected | |
| [imgur.artemislena.eu](https://imgur.artemislena.eu) | 🇩🇪 DE | Vodafone Deutschland | ✅ Data not collected | Self-hosted, provider is ISP |
| [rimgo.vern.cc](https://rimgo.vern.cc) | 🇺🇸 US | OVHCloud | ✅ Data not collected | [Edited theme](https://git.vern.cc/root/modifications/src/branch/master/rimgo) |
| [rim.odyssey346.dev](https://rim.odyssey346.dev/) | 🇫🇷️ FR | Trolling Solutions (OVH) | ✅ Data not collected | |
| [i.habedieeh.re](https://i.habedieeh.re/) | 🇨🇦️ CA | Oracle Cloud | ✅ Data not collected | |
| [rimgo.hostux.net](https://rimgo.hostux.net/) | 🇫🇷️ FR | Gandi | ⚠️ Data collected | |
| [ri.zzls.xyz](https://ri.zzls.xyz/) | 🇨🇱 CL | TELEFÓNICA CHILE | ✅ Data not collected | Self-hosted, provider is ISP |
| [rimgo.lunar.icu](https://rimgo.marcopisco.com/) | 🇩🇪 DE | Cloudflare | ✅ Data not collected | |
| [imgur.010032.xyz](https://imgur.010032.xyz/) | 🇰🇷 KR | Oracle Cloud | ✅ Data not collected | |
| [rimgo.kling.gg](https://rimgo.kling.gg/) | 🇳🇱 NL | RamNode | ✅ Data not collected | |
| [i.01r.xyz](https://i.01r.xyz/) | 🇺🇸 US | Cloudflare | ✅ Data not collected | |
| [rimgo.projectsegfau.lt](https://rimgo.projectsegfau.lt/) | 🇫🇷 FR, 🇺🇸 US, 🇮🇳 IN | See below | ✅ Data not collected | |
| [rimgo.eu.projectsegfau.lt](https://rimgo.eu.projectsegfau.lt/) | 🇫🇷 FR | Orange S.A. | ✅ Data not collected | |
| [rimgo.us.projectsegfau.lt](https://rimgo.us.projectsegfau.lt/) | 🇺🇸 US | Racknerd | ✅ Data not collected | |
| [rimgo.in.projectsegfau.lt](https://rimgo.in.projectsegfau.lt/) | 🇮🇳 IN | Airtel | ✅ Data not collected | |
| [rimgo.whateveritworks.org](https://rimgo.whateveritworks.org/) | 🇩🇪 DE | Cloudflare | ✅ Data not collected | |
| [rimgo.nohost.network](https://rimgo.nohost.network/) | 🇲🇽 MX | Telmex | ✅ Data not collected | |
| [rimgo.catsarch.com](https://rimgo.catsarch.com/) | 🇺🇸 US | Comcast | ✅ Data not collected | Self-hosted, provider is ISP |
| [rimgo.frontendfriendly.xyz](https://rimgo.frontendfriendly.xyz/) | 🇩🇪 DE | Hetzner | ⚠️ Data collected | |
### Tor
| URL | Privacy | Notes |
| :-- | :------ | :----------------------- |
| [rimgo.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion](http://rimgo.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion) | ✅ Data not collected | Onion of rimgo.vern.cc |
| [imgur.lpoaj7z2zkajuhgnlltpeqh3zyq7wk2iyeggqaduhgxhyajtdt2j7wad.onion](http://imgur.lpoaj7z2zkajuhgnlltpeqh3zyq7wk2iyeggqaduhgxhyajtdt2j7wad.onion) | ✅ Data not collected | Onion of imgur.artemislena.eu |
| [rim.odysfvr23q5wgt7i456o5t3trw2cw5dgn56vbjfbq2m7xsc5vqbqpcyd.onion](http://rim.odysfvr23q5wgt7i456o5t3trw2cw5dgn56vbjfbq2m7xsc5vqbqpcyd.onion) | ⚠️ Data collected | |
| [tdp6uqjtmok723suum5ms3jbquht6d7dssug4cgcxhfniatb25gcipad.onion](http://tdp6uqjtmok723suum5ms3jbquht6d7dssug4cgcxhfniatb25gcipad.onion) | ✅ Data not collected | Onion of rimgo.privacytools.io |
| [i.habeehrhadazsw3izbrbilqajalfyqqln54mrja3iwpqxgcuxnus7eid.onion](http://i.habeehrhadazsw3izbrbilqajalfyqqln54mrja3iwpqxgcuxnus7eid.onion/) | ✅ Data not collected | Onion of i.habedieeh.re |
| [rimgo.zzlsghu6mvvwyy75mvga6gaf4znbp3erk5xwfzedb4gg6qqh2j6rlvid.onion](http://rimgo.zzlsghu6mvvwyy75mvga6gaf4znbp3erk5xwfzedb4gg6qqh2j6rlvid.onion/) | ✅ Data not collected | Onion of ri.zzls.xyz |
| [tdn7zoxctmsopey77mp4eg2gazaudyhgbuyytf4zpk5u7lknlxlgbnid.onion/](http://tdn7zoxctmsopey77mp4eg2gazaudyhgbuyytf4zpk5u7lknlxlgbnid.onion/) | ✅ Data not collected | Onion of rimgo.kling.gg |
| [rimgo.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion](http://rimgo.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion/) | ✅ Data not collected | Onion of rimgo.eu.projectsegfau.lt |
### I2P
| URL | Privacy | Notes |
| :-- | :------ | :----------------------- |
| [rimgo.i2p](http://rimgo.i2p) | ✅ Data not collected | i.habedieeh.re on I2P |
| [rimgov7l2tqyrm5txrtvhtnfyrzkc5d7ipafofavchbnnyog4r3q.b32.i2p](http://rimgov7l2tqyrm5txrtvhtnfyrzkc5d7ipafofavchbnnyog4r3q.b32.i2p) | ✅ Data not collected | Same as rimgo.i2p |
| [rimgo.zzls.i2p](http://rimgo.zzls.i2p) | ✅ Data not collected | ri.zzls.xyz on I2P |
| [p57356k2xwhxrg2lxrjajcftkrptv4zejeeblzfgkcvpzuetkz2a.b32.i2p](http://p57356k2xwhxrg2lxrjajcftkrptv4zejeeblzfgkcvpzuetkz2a.b32.i2p) | ✅ Data not collected | Same as rimgo.zzls.i2p |
| [ovzamsts5czfx3jasbbhbccyyl2z7qmdngtlqxdh4oi7abhdz3ia.b32.i2p](http://ovzamsts5czfx3jasbbhbccyyl2z7qmdngtlqxdh4oi7abhdz3ia.b32.i2p) | ✅ Data not collected | rimgo.kling.gg on I2P |
## Install ## Install
@ -127,7 +77,10 @@ See [Install](https://rimgo.codeberg.page/docs/getting-started/install/).
See [Configuration](https://rimgo.codeberg.page/docs/usage/configuration/). See [Configuration](https://rimgo.codeberg.page/docs/usage/configuration/).
## Contributing ## Contributing
Pull requests are welcome! If you have any questions or bug reports, open an [issue](https://codeberg.org/rimgo/rimgo/issues/new). Pull requests are welcome! If you have any questions or bug reports, open an [issue](https://codeberg.org/rimgo/rimgo/issues/new). Please remember to follow our [Code of Conduct](https://rimgo.codeberg.page/docs/code-of-conduct/)!
## License ## License
This software is released under the AGPL-3.0 license. If you make any modifications to the code and distribute it (including use on a network server), you must publicly distribute your changes and release them under the AGPL-3.0. This software is released under the AGPL-3.0 license. If you make any modifications to the code and distribute it (including use on a network server), you must publicly distribute your changes and release them under the AGPL-3.0.
## Legal notice
rimgo does not allow uploads or host any content, media. All content on any rimgo instances is from Imgur™. Imgur is a trademark of Imgur, Inc. Any issues with content on rimgo should be be reported to Imgur. rimgo is not affiliated with Imgur, Inc.

View File

@ -1,10 +1,10 @@
package api package api
import ( import (
"io/ioutil" "io"
"net/http" "net/http"
"net/url"
"strings" "strings"
"sync"
"github.com/patrickmn/go-cache" "github.com/patrickmn/go-cache"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
@ -21,6 +21,9 @@ type Tag struct {
} }
func (client *Client) FetchTag(tag string, sort string, page string) (Tag, error) { func (client *Client) FetchTag(tag string, sort string, page string) (Tag, error) {
// Dots are automatically removed on Imgur, so more cache hits
tag = strings.ReplaceAll(tag, ".", "")
cacheData, found := client.Cache.Get(tag + sort + page + "-tag") cacheData, found := client.Cache.Get(tag + sort + page + "-tag")
if found { if found {
return cacheData.(Tag), nil return cacheData.(Tag), nil
@ -57,54 +60,51 @@ func (client *Client) FetchTag(tag string, sort string, page string) (Tag, error
return Tag{}, err return Tag{}, err
} }
body, err := ioutil.ReadAll(res.Body) body, err := io.ReadAll(res.Body)
if err != nil { if err != nil {
return Tag{}, err return Tag{}, err
} }
data := gjson.Parse(string(body)) data := gjson.Parse(string(body))
wg := sync.WaitGroup{}
posts := make([]Submission, 0) posts := make([]Submission, 0)
data.Get("posts").ForEach( data.Get("posts").ForEach(
func(key, value gjson.Result) bool { func(key, value gjson.Result) bool {
wg.Add(1) url, _ := url.Parse(strings.ReplaceAll(value.Get("url").String(), "https://imgur.com", ""))
q := url.Query()
q.Add("tag", tag+"."+sort+"."+page+"."+key.String())
url.RawQuery = q.Encode()
go func() { posts = append(posts, Submission{
defer wg.Done() Id: value.Get("id").String(),
posts = append(posts, Submission{ Title: value.Get("title").String(),
Id: value.Get("id").String(), Link: url.String(),
Title: value.Get("title").String(), Cover: Media{
Link: strings.ReplaceAll(value.Get("url").String(), "https://imgur.com", ""), Id: value.Get("cover_id").String(),
Cover: Media{ Type: value.Get("cover.type").String(),
Id: value.Get("cover_id").String(), Url: strings.ReplaceAll(value.Get("cover.url").String(), "https://i.imgur.com", ""),
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(),
Points: value.Get("point_count").Int(), Downvotes: value.Get("downvote_count").Int(),
Upvotes: value.Get("upvote_count").Int(), Comments: value.Get("comment_count").Int(),
Downvotes: value.Get("downvote_count").Int(), Views: value.Get("view_count").Int(),
Comments: value.Get("comment_count").Int(), IsAlbum: value.Get("is_album").Bool(),
Views: value.Get("view_count").Int(), })
IsAlbum: value.Get("is_album").Bool(),
})
}()
return true return true
}, },
) )
wg.Wait()
tagData := Tag{ tagData := Tag{
Tag: tag, Tag: tag,
Display: data.Get("display").String(), Display: data.Get("display").String(),
Sort: sort, Sort: sort,
PostCount: data.Get("post_count").Int(), PostCount: data.Get("post_count").Int(),
Posts: posts, Posts: posts,
Background: "/" + data.Get("background_id").String() + ".webp", Background: "/" + data.Get("background_id").String() + ".webp",
} }
client.Cache.Set(tag + sort + page + "-tag", tagData, cache.DefaultExpiration) client.Cache.Set(tag+sort+page+"-tag", tagData, 4*cache.DefaultExpiration)
return tagData, nil return tagData, nil
} }

View File

@ -70,7 +70,7 @@ func (client *Client) FetchUser(username string) (User, error) {
} }
func (client *Client) FetchSubmissions(username string, sort string, page string) ([]Submission, error) { func (client *Client) FetchSubmissions(username string, sort string, page string) ([]Submission, error) {
cacheData, found := client.Cache.Get(username + "-submissions") cacheData, found := client.Cache.Get(username + "-submissions-" + sort + page)
if found { if found {
return cacheData.([]Submission), nil return cacheData.([]Submission), nil
} }
@ -98,7 +98,56 @@ func (client *Client) FetchSubmissions(username string, sort string, page string
) )
wg.Wait() wg.Wait()
client.Cache.Set(username+"-submissions", submissions, 15*time.Minute) client.Cache.Set(username+"-submissions-"+sort+page, submissions, 15*time.Minute)
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 return submissions, nil
} }

View File

@ -1,5 +1,3 @@
version: '3'
services: services:
rimgo: rimgo:
image: codeberg.org/rimgo/rimgo # Official image image: codeberg.org/rimgo/rimgo # Official image

50
go.mod
View File

@ -1,41 +1,45 @@
module codeberg.org/rimgo/rimgo module codeberg.org/rimgo/rimgo
go 1.17 go 1.23
toolchain go1.23.5
require ( require (
github.com/PuerkitoBio/goquery v1.8.1 github.com/PuerkitoBio/goquery v1.10.1
github.com/aymerick/raymond v2.0.2+incompatible
github.com/dustin/go-humanize v1.0.1 github.com/dustin/go-humanize v1.0.1
github.com/gofiber/fiber/v2 v2.48.0 github.com/gofiber/fiber/v2 v2.52.6
github.com/gofiber/template/handlebars/v2 v2.1.4 github.com/gofiber/template/handlebars/v2 v2.1.11
github.com/gorilla/feeds v1.2.0
github.com/joho/godotenv v1.5.1 github.com/joho/godotenv v1.5.1
github.com/microcosm-cc/bluemonday v1.0.25 github.com/mailgun/raymond/v2 v2.0.48
github.com/microcosm-cc/bluemonday v1.0.27
github.com/patrickmn/go-cache v2.1.0+incompatible github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/tidwall/gjson v1.14.4 github.com/tidwall/gjson v1.18.0
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3 gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3
) )
require ( require (
github.com/andybalholm/brotli v1.0.5 // indirect github.com/andybalholm/brotli v1.1.1 // indirect
github.com/andybalholm/cascadia v1.3.2 // indirect github.com/andybalholm/cascadia v1.3.3 // indirect
github.com/aymerick/douceur v0.2.0 // indirect github.com/aymerick/douceur v0.2.0 // indirect
github.com/gofiber/template v1.8.2 // indirect github.com/gofiber/template v1.8.3 // indirect
github.com/gofiber/utils v1.1.0 // indirect github.com/gofiber/utils v1.1.0 // indirect
github.com/google/uuid v1.3.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/css v1.0.0 // indirect github.com/gorilla/css v1.0.1 // indirect
github.com/klauspost/compress v1.16.7 // indirect github.com/klauspost/compress v1.17.11 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.14 // indirect
github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-isatty v0.0.20 // indirect
github.com/mattn/go-runewidth v0.0.14 // indirect github.com/mattn/go-runewidth v0.0.16 // indirect
github.com/philhofer/fwd v1.1.2 // indirect github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c // indirect
github.com/rivo/uniseg v0.4.4 // indirect github.com/rivo/uniseg v0.4.7 // indirect
github.com/sirupsen/logrus v1.9.3 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect
github.com/tinylib/msgp v1.1.8 // indirect github.com/tinylib/msgp v1.2.5 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
github.com/valyala/fasthttp v1.48.0 // indirect github.com/valyala/fasthttp v1.58.0 // indirect
github.com/valyala/tcplisten v1.0.0 // indirect github.com/valyala/tcplisten v1.0.0 // indirect
golang.org/x/net v0.12.0 // indirect golang.org/x/net v0.34.0 // indirect
golang.org/x/sys v0.10.0 // indirect golang.org/x/sys v0.29.0 // indirect
golang.org/x/text v0.11.0 // indirect golang.org/x/text v0.21.0 // indirect
) )

190
go.sum
View File

@ -1,148 +1,162 @@
github.com/PuerkitoBio/goquery v1.8.1 h1:uQxhNlArOIdbrH1tr0UXwdVFgDcZDrZVdcpygAcwmWM= github.com/PuerkitoBio/goquery v1.10.1 h1:Y8JGYUkXWTGRB6Ars3+j3kN0xg1YqqlwvdTV8WTFQcU=
github.com/PuerkitoBio/goquery v1.8.1/go.mod h1:Q8ICL1kNUJ2sXGoAhPGUdYDJvgQgHzJsnnd3H7Ho5jQ= github.com/PuerkitoBio/goquery v1.10.1/go.mod h1:IYiHrOMps66ag56LEH7QYDDupKXyo5A8qrjIx3ZtujY=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.1.1 h1:PR2pgnyFznKEugtsUo0xLdDop5SKXd5Qf5ysW+7XdTA=
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= github.com/andybalholm/brotli v1.1.1/go.mod h1:05ib4cKhjx3OQYUY22hTVd34Bc8upXjOLL2rKwwZBoA=
github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/andybalholm/cascadia v1.3.3 h1:AG2YHrzJIm4BZ19iwJ/DAua6Btl3IwJX+VI4kktS1LM=
github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.3/go.mod h1:xNd9bqTn98Ln4DwST8/nG+H0yuB8Hmgu1YHNnWw0GeA=
github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU=
github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk= github.com/aymerick/douceur v0.2.0 h1:Mv+mAeH1Q+n9Fr+oyamOlAkUNPWPlA8PPGR0QAaYuPk=
github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4= github.com/aymerick/douceur v0.2.0/go.mod h1:wlT5vV2O3h55X9m7iVYN0TBM0NH/MmbLnd30/FjWUq4=
github.com/aymerick/raymond v2.0.2+incompatible h1:VEp3GpgdAnv9B2GFyTvqgcKvY+mfKMjPOA3SbKLtnU0= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/aymerick/raymond v2.0.2+incompatible/go.mod h1:osfaiScAUVup+UC9Nfq76eWqDhXlp+4UYaA8uhTBO6g= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/gofiber/fiber/v2 v2.46.0/go.mod h1:DNl0/c37WLe0g92U6lx1VMQuxGUQY5V7EIaVoEsUffc= github.com/gofiber/fiber/v2 v2.52.6 h1:Rfp+ILPiYSvvVuIPvxrBns+HJp8qGLDnLJawAu27XVI=
github.com/gofiber/fiber/v2 v2.48.0 h1:cRVMCb9aUJDsyHxGFLwz/sGzDggdailZZyptU9F9cU0= github.com/gofiber/fiber/v2 v2.52.6/go.mod h1:YEcBbO/FB+5M1IZNBP9FO3J9281zgPAreiI1oqg8nDw=
github.com/gofiber/fiber/v2 v2.48.0/go.mod h1:xqJgfqrc23FJuqGOW6DVgi3HyZEm2Mn9pRqUb2kHSX8= github.com/gofiber/template v1.8.3 h1:hzHdvMwMo/T2kouz2pPCA0zGiLCeMnoGsQZBTSYgZxc=
github.com/gofiber/template v1.8.2 h1:PIv9s/7Uq6m+Fm2MDNd20pAFFKt5wWs7ZBd8iV9pWwk= github.com/gofiber/template v1.8.3/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8=
github.com/gofiber/template v1.8.2/go.mod h1:bs/2n0pSNPOkRa5VJ8zTIvedcI/lEYxzV3+YPXdBvq8= github.com/gofiber/template/handlebars/v2 v2.1.11 h1:pgPF+DKuIvCl3z/Kj1u6VA/8hLBljH2Rg6LwVFBm7aM=
github.com/gofiber/template/handlebars/v2 v2.1.4 h1:m/GwEnzv5bpifOg9BrpCIzkhD2GU10E5oZjI8NdDbYY= github.com/gofiber/template/handlebars/v2 v2.1.11/go.mod h1:AbKfYOgH+ngxaYXtLzafy4AKLAQ2NrJYbvtWaOX82I4=
github.com/gofiber/template/handlebars/v2 v2.1.4/go.mod h1:bb6ip6ZEgBqKSdZcbnFLlfL8PcCRslnX6WgpcxVBiTE=
github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM= github.com/gofiber/utils v1.1.0 h1:vdEBpn7AzIUJRhe+CiTOJdUcTg4Q9RK+pEa0KPbLdrM=
github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0= github.com/gofiber/utils v1.1.0/go.mod h1:poZpsnhBykfnY1Mc0KeEa6mSHrS3dV0+oBWyeQmb2e0=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
github.com/gorilla/css v1.0.0 h1:BQqNyPTi50JCFMTw/b67hByjMVXZRwGha6wxVGkeihY= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/gorilla/css v1.0.0/go.mod h1:Dn721qIggHpt4+EFCcTLTU/vk5ySda2ReITrtgBl60c= github.com/gorilla/css v1.0.1 h1:ntNaBIghp6JmvWnxbZKANoLyuXTPZ4cAMlo6RyhlbO8=
github.com/gorilla/css v1.0.1/go.mod h1:BvnYkspnSzMmwRK+b8/xgNPLiIuNZr6vbZBTPQ2A3b0=
github.com/gorilla/feeds v1.2.0 h1:O6pBiXJ5JHhPvqy53NsjKOThq+dNFm8+DFrxBEdzSCc=
github.com/gorilla/feeds v1.2.0/go.mod h1:WMib8uJP3BbY+X8Szd1rA5Pzhdfh+HCCAYT2z7Fza6Y=
github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0=
github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4=
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mailgun/raymond/v2 v2.0.48 h1:5dmlB680ZkFG2RN/0lvTAghrSxIESeu9/2aeDqACtjw=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mailgun/raymond/v2 v2.0.48/go.mod h1:lsgvL50kgt1ylcFJYZiULi5fjPBkkhNfj4KA0W54Z18=
github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-runewidth v0.0.14/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/microcosm-cc/bluemonday v1.0.25 h1:4NEwSfiJ+Wva0VxN5B8OwMicaJvD8r9tlJWm9rtloEg= github.com/mattn/go-runewidth v0.0.16 h1:E5ScNMtiwvlvB5paMFdw9p4kSQzbXFikJ5SQO6TULQc=
github.com/microcosm-cc/bluemonday v1.0.25/go.mod h1:ZIOjCQp1OrzBBPIJmfX4qDYFuhU02nx4bn030ixfHLE= github.com/mattn/go-runewidth v0.0.16/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
github.com/microcosm-cc/bluemonday v1.0.27 h1:MpEUotklkwCSLeH+Qdx1VJgNqLlpY2KXwXFM08ygZfk=
github.com/microcosm-cc/bluemonday v1.0.27/go.mod h1:jFi9vgW+H7c3V0lb6nR74Ib/DIB5OBs92Dimizgw2cA=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/philhofer/fwd v1.1.1/go.mod h1:gk3iGcWd9+svBvR0sR+KPcfE+RNWozjowpeBVG3ZVNU= github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c h1:dAMKvw0MlJT1GshSTtih8C2gDs04w8dReiOGXrGLNoY=
github.com/philhofer/fwd v1.1.2 h1:bnDivRJ1EWPjUIRXV5KfORO897HTbpFAQddBdE8t7Gw= github.com/philhofer/fwd v1.1.3-0.20240916144458-20a13a1f6b7c/go.mod h1:RqIHx9QI14HlwKwm98g9Re5prTQ6LdeRQn+gXJFxsJM=
github.com/philhofer/fwd v1.1.2/go.mod h1:qkPdfjR2SIEbspLqpe1tO4n5yICnr2DY7mqEx2tUTP0= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc=
github.com/rivo/uniseg v0.4.4 h1:8TfxU8dW6PdqD27gjM8MVNuicgxIjxpm4K7x4jp8sis= github.com/rivo/uniseg v0.4.7 h1:WUdvkW8uEhrYfLC4ZzdpI2ztxP1I582+49Oc5Mq64VQ=
github.com/rivo/uniseg v0.4.4/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88= github.com/rivo/uniseg v0.4.7/go.mod h1:FN3SvrM+Zdj16jyLfmOkMNblXMcoc8DfTHruCPUcx88=
github.com/savsgio/dictpool v0.0.0-20221023140959-7bf2e61cea94/go.mod h1:90zrgN3D/WJsDd1iXHT96alCoN2KJo6/4x1DZC3wZs8= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/savsgio/gotils v0.0.0-20220530130905-52f3993e8d6d/go.mod h1:Gy+0tqhJvgGlqnTF8CVGP0AaGRjwBtXs/a5PA0Y3+A4= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/savsgio/gotils v0.0.0-20230208104028-c358bd845dee/go.mod h1:qwtSXrKuJh/zsFQ12yEE89xfCrGKK63Rr7ctU/uCo4g= github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/tidwall/gjson v1.18.0 h1:FIDeeyB800efLX89e5a8Y0BNH+LOngJyGrIWxG2FKQY=
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 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
github.com/tinylib/msgp v1.1.6/go.mod h1:75BAfg2hauQhs3qedfdDZmWAPcFMAvJE5b9rGOMufyw= github.com/tinylib/msgp v1.2.5 h1:WeQg1whrXRFiZusidTQqzETkRpGjFjcIhW6uqWH09po=
github.com/tinylib/msgp v1.1.8 h1:FCXC1xanKO4I8plpHGH2P7koL/RzZs12l/+r7vakfm0= github.com/tinylib/msgp v1.2.5/go.mod h1:ykjzy2wzgrlvpDCRc4LA8UXy6D8bzMSuAF3WD57Gok0=
github.com/tinylib/msgp v1.1.8/go.mod h1:qkpG+2ldGg4xRFmx+jfTvZPxfGFhi64BcnL9vkCm/Tw=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasthttp v1.47.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA= github.com/valyala/fasthttp v1.58.0 h1:GGB2dWxSbEprU9j0iMJHgdKYJVDyjrOwF9RE59PbRuE=
github.com/valyala/fasthttp v1.48.0 h1:oJWvHb9BIZToTQS3MuQ2R3bJZiNSa2KiNdeI8A+79Tc= github.com/valyala/fasthttp v1.58.0/go.mod h1:SYXvHHaFp7QZHGKSHmoMipInhrI5StHrhDTYVEjK/Kw=
github.com/valyala/fasthttp v1.48.0/go.mod h1:k2zXd82h/7UZc3VOdJ2WaUqt1uZ/XpXAfE9i+HBC3lA=
github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8=
github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc=
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/xyproto/randomstring v1.0.5 h1:YtlWPoRdgMu3NZtP45drfy1GKoojuR7hmRcnhZqKjWU=
github.com/xyproto/randomstring v1.0.5/go.mod h1:rgmS5DeNXLivK7YprL0pY+lTuhNQW3iGxZ18UQApw/E=
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3 h1:1Coh5BsUBlXoEJmIEaNzVAWrtg9k7/eJzailMQr1grw= gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3 h1:1Coh5BsUBlXoEJmIEaNzVAWrtg9k7/eJzailMQr1grw=
gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8= gitlab.com/golang-commonmark/linkify v0.0.0-20200225224916-64bca66f6ad3/go.mod h1:Gn+LZmCrhPECMD3SOKlE+BOHwhOYD9j7WT9NUtkCrC8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
golang.org/x/crypto v0.11.0/go.mod h1:xgJhtzW8F9jGdVFWZESrid1U1bjeNy4zgy5cRr/CIio= golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/mod v0.7.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.3.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg= golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
golang.org/x/net v0.12.0 h1:cfawfvKITfUsFCeJIHJrbSxpeu/E81khclypR0GVT50= golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
golang.org/x/net v0.12.0/go.mod h1:zEVYFnQC7m/vmpQFELhcD1EWkZlX69l4oqgmer6hfKA= golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
golang.org/x/net v0.34.0 h1:Mb7Mrk043xzHgnRM88suvJFwzVrRfHEHJEl5/71CKw0=
golang.org/x/net v0.34.0/go.mod h1:di0qlW3YNM5oh6GqDGQr92MyTozJPmybPK4Ev/Gm31k=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0 h1:SqMFp9UcQJZa+pmYuAKjd9xq1f0j5rLcDIk0mj4qAsA= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.10.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
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/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U=
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo= golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
golang.org/x/term v0.10.0/go.mod h1:lpqdcUyK/oCiQxvxVrppt5ggO2KCZ5QblwqPnfZ6d5o= golang.org/x/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.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.11.0 h1:LAntKIrcmeSKERyiOh0XMV39LXS8IE9UL2yP7+f5ij4= golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
golang.org/x/text v0.11.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 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.0.0-20201022035929-9cf592e881e9/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
golang.org/x/tools v0.4.0/go.mod h1:UE5sM2OK9E/d67R0ANs2xJizIymRP5gJU295PvKXxjQ=
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

View File

@ -28,21 +28,6 @@
], ],
"cloudflare": false "cloudflare": false
}, },
{
"url": "https://rimgo.vern.cc",
"onion": "http://rimgo.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion",
"countries": [
"ca"
],
"cloudflare": false
},
{
"url": "https://rim.odyssey346.dev",
"countries": [
"fr"
],
"cloudflare": false
},
{ {
"url": "https://imgur.010032.xyz", "url": "https://imgur.010032.xyz",
"countries": [ "countries": [
@ -97,13 +82,6 @@
], ],
"cloudflare": false "cloudflare": false
}, },
{
"url": "https://i.01r.xyz",
"countries": [
"us"
],
"cloudflare": true
},
{ {
"url": "https://rimgo.eu.projectsegfau.lt", "url": "https://rimgo.eu.projectsegfau.lt",
"countries": [ "countries": [
@ -125,6 +103,13 @@
], ],
"cloudflare": false "cloudflare": false
}, },
{
"url": "https://rimgo.fascinated.cc",
"countries": [
"us"
],
"cloudflare": false
},
{ {
"url": "https://rimgo.whateveritworks.org", "url": "https://rimgo.whateveritworks.org",
"countries": [ "countries": [
@ -152,5 +137,26 @@
"de" "de"
], ],
"cloudflare": false "cloudflare": false
},
{
"url": "https://rimgo.drgns.space",
"countries": [
"us"
],
"cloudflare": false
},
{
"url": "https://rimgo.quantenzitrone.eu",
"countries": [
"cz"
],
"cloudflare": false
},
{
"url": "https://rimgo.frylo.net",
"countries": [
"nl"
],
"cloudflare": false
} }
] ]

35
main.go
View File

@ -11,7 +11,7 @@ import (
"codeberg.org/rimgo/rimgo/static" "codeberg.org/rimgo/rimgo/static"
"codeberg.org/rimgo/rimgo/utils" "codeberg.org/rimgo/rimgo/utils"
"codeberg.org/rimgo/rimgo/views" "codeberg.org/rimgo/rimgo/views"
"github.com/aymerick/raymond" "github.com/mailgun/raymond/v2"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cache" "github.com/gofiber/fiber/v2/middleware/cache"
"github.com/gofiber/fiber/v2/middleware/filesystem" "github.com/gofiber/fiber/v2/middleware/filesystem"
@ -52,14 +52,7 @@ func main() {
code = e.Code code = e.Code
} }
err = ctx.Status(code).Render("errors/error", fiber.Map{ return utils.RenderError(ctx, code)
"err": err,
})
if err != nil {
return ctx.Status(fiber.StatusInternalServerError).SendString("Internal Server Error")
}
return nil
}, },
}) })
@ -72,23 +65,32 @@ func main() {
if os.Getenv("ENV") == "dev" { if os.Getenv("ENV") == "dev" {
app.Use("/static", filesystem.New(filesystem.Config{ app.Use("/static", filesystem.New(filesystem.Config{
MaxAge: 2592000, Root: http.Dir("./static"),
Root: http.Dir("./static"),
})) }))
app.Get("/errors/429", func(c *fiber.Ctx) error { app.Get("/errors/429", func(c *fiber.Ctx) error {
return c.Render("errors/429", nil) return c.Render("errors/429", nil)
}) })
app.Get("/errors/429/img", func(c *fiber.Ctx) error {
return c.Redirect("/static/img/error-429.png")
})
app.Get("/errors/404", func(c *fiber.Ctx) error { app.Get("/errors/404", func(c *fiber.Ctx) error {
return c.Render("errors/404", nil) return c.Render("errors/404", nil)
}) })
app.Get("/errors/404/img", func(c *fiber.Ctx) error {
return c.Redirect("/static/img/error-404.png")
})
app.Get("/errors/error", func(c *fiber.Ctx) error { app.Get("/errors/error", func(c *fiber.Ctx) error {
return c.Render("errors/error", fiber.Map{ return c.Render("errors/error", fiber.Map{
"err": "Test error", "err": "Test error",
}) })
}) })
app.Get("/errors/error/img", func(c *fiber.Ctx) error {
return c.Redirect("/static/img/error-generic.png")
})
} else { } else {
app.Use("/static", filesystem.New(filesystem.Config{ app.Use("/static", filesystem.New(filesystem.Config{
Root: http.FS(static.GetFiles()), MaxAge: 2592000,
Root: http.FS(static.GetFiles()),
})) }))
app.Use(cache.New(cache.Config{ app.Use(cache.New(cache.Config{
Expiration: 30 * time.Minute, Expiration: 30 * time.Minute,
@ -116,13 +118,17 @@ func main() {
app.Get("/about", pages.HandleAbout) app.Get("/about", pages.HandleAbout)
app.Get("/privacy", pages.HandlePrivacy) app.Get("/privacy", pages.HandlePrivacy)
app.Get("/search", pages.HandleSearch) app.Get("/search", pages.HandleSearch)
app.Get("/trending.:type", pages.HandleTrendingRSS)
app.Get("/trending", pages.HandleTrending) app.Get("/trending", pages.HandleTrending)
app.Get("/a/:postID", pages.HandlePost) app.Get("/a/:postID", pages.HandlePost)
app.Get("/a/:postID/embed", pages.HandleEmbed) app.Get("/a/:postID/embed", pages.HandleEmbed)
app.Get("/t/:tag.:type", pages.HandleTagRSS)
app.Get("/t/:tag", pages.HandleTag) app.Get("/t/:tag", pages.HandleTag)
app.Get("/t/:tag/:postID", pages.HandlePost) app.Get("/t/:tag/:postID", pages.HandlePost)
app.Get("/r/:sub/: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/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)
@ -134,5 +140,8 @@ func main() {
app.Get("/:postID", pages.HandlePost) app.Get("/:postID", pages.HandlePost)
app.Get("/:postID/embed", pages.HandleEmbed) app.Get("/:postID/embed", pages.HandleEmbed)
app.Listen(utils.Config.Addr + ":" + utils.Config.Port) err := app.Listen(utils.Config.Addr + ":" + utils.Config.Port)
if err != nil {
fmt.Println(err)
}
} }

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"
}
}

View File

@ -23,10 +23,10 @@ func HandleEmbed(c *fiber.Ctx) error {
post, err = ApiClient.FetchMedia(c.Params("postID")) post, err = ApiClient.FetchMedia(c.Params("postID"))
} }
if err != nil && err.Error() == "ratelimited by imgur" { if err != nil && err.Error() == "ratelimited by imgur" {
return c.Status(429).Render("errors/429", nil) return utils.RenderError(c, 429)
} }
if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") { if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") {
return c.Status(404).Render("errors/404", nil) return utils.RenderError(c, 404)
} }
if err != nil { if err != nil {
return err return err

View File

@ -11,22 +11,25 @@ import (
func HandleMedia(c *fiber.Ctx) error { func HandleMedia(c *fiber.Ctx) error {
c.Set("Cache-Control", "public,max-age=31557600") c.Set("Cache-Control", "public,max-age=31557600")
c.Set("Content-Security-Policy", "default-src 'none'; style-src 'self'; img-src 'self'")
if strings.HasPrefix(c.Path(), "/stack") { if strings.HasPrefix(c.Path(), "/stack") {
return handleMedia(c, "https://i.stack.imgur.com/" + strings.ReplaceAll(c.Params("baseName"), "stack/", "") + "." + c.Params("extension")) return handleMedia(c, "https://i.stack.imgur.com/"+strings.ReplaceAll(c.Params("baseName"), "stack/", "")+"."+c.Params("extension"))
} else { } else {
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")
return handleMedia(c, "https://imgur.com/user/" + c.Params("userID") + "/cover?maxwidth=2560") c.Set("Content-Security-Policy", "default-src 'none'")
}; 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")
return handleMedia(c, "https://imgur.com/user/" + c.Params("userID") + "/avatar") c.Set("Content-Security-Policy", "default-src 'none'")
}; return handleMedia(c, "https://imgur.com/user/"+c.Params("userID")+"/avatar")
}
func handleMedia(c *fiber.Ctx, url string) error { func handleMedia(c *fiber.Ctx, url string) error {
utils.SetHeaders(c) utils.SetHeaders(c)
@ -57,19 +60,14 @@ func handleMedia(c *fiber.Ctx, url string) error {
return err return err
} }
c.Status(res.StatusCode) if res.StatusCode == 404 || strings.Contains(res.Request.URL.String(), "error/404") {
if res.StatusCode == 404 { return utils.RenderError(c, 404)
return c.Render("errors/404", fiber.Map{
"path": c.Path(),
})
} else if res.StatusCode == 429 { } else if res.StatusCode == 429 {
return c.Render("errors/429", fiber.Map{ return utils.RenderError(c, 429)
"path": c.Path(),
})
} }
c.Set("Accept-Ranges", "bytes") c.Set("Accept-Ranges", "bytes")
c.Set("Content-Type", res.Header.Get("Content-Type")); c.Set("Content-Type", res.Header.Get("Content-Type"))
c.Set("Content-Length", res.Header.Get("Content-Length")) c.Set("Content-Length", res.Header.Get("Content-Length"))
if res.Header.Get("Content-Range") != "" { if res.Header.Get("Content-Range") != "" {
c.Set("Content-Range", res.Header.Get("Content-Range")) c.Set("Content-Range", res.Header.Get("Content-Range"))

View File

@ -3,6 +3,7 @@ package pages
import ( import (
"crypto/rand" "crypto/rand"
"fmt" "fmt"
"strconv"
"strings" "strings"
"codeberg.org/rimgo/rimgo/api" "codeberg.org/rimgo/rimgo/api"
@ -10,37 +11,62 @@ import (
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
) )
// Cursed function
func nextInTag(client *api.Client, tagname, sort, page, I string) string {
i, err := strconv.Atoi(I)
if err != nil || i < 0 {
return ""
}
tag, err := client.FetchTag(tagname, sort, page)
if err != nil {
return ""
}
if i >= len(tag.Posts)-1 {
pageNumber, _ := strconv.Atoi(page)
tagn, err := client.FetchTag(tagname, sort, strconv.Itoa(pageNumber+1))
// Check length - Imgur will not return an error if there are no more posts and you request the next page
if err != nil || len(tagn.Posts) < 1 {
return ""
}
return tagn.Posts[0].Link
}
return tag.Posts[i+1].Link
}
func HandlePost(c *fiber.Ctx) error { func HandlePost(c *fiber.Ctx) error {
utils.SetHeaders(c) utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY") c.Set("X-Frame-Options", "DENY")
postId := c.Params("postID")
if strings.Contains(postId, "-") {
postId = postId[len(postId)-7:]
}
post, err := api.Album{}, error(nil) post, err := api.Album{}, error(nil)
switch { switch {
case strings.HasPrefix(c.Path(), "/a"): case strings.HasPrefix(c.Path(), "/a"):
post, err = ApiClient.FetchAlbum(c.Params("postID")) post, err = ApiClient.FetchAlbum(postId)
case strings.HasPrefix(c.Path(), "/gallery"): case strings.HasPrefix(c.Path(), "/gallery"):
post, err = ApiClient.FetchPosts(c.Params("postID")) post, err = ApiClient.FetchPosts(postId)
case strings.HasPrefix(c.Path(), "/t"): case strings.HasPrefix(c.Path(), "/t"):
post, err = ApiClient.FetchPosts(c.Params("postID")) post, err = ApiClient.FetchPosts(postId)
default: default:
post, err = ApiClient.FetchMedia(c.Params("postID")) post, err = ApiClient.FetchMedia(postId)
} }
if err != nil && err.Error() == "ratelimited by imgur" { if err != nil && err.Error() == "ratelimited by imgur" {
return c.Status(429).Render("errors/429", fiber.Map{ return utils.RenderError(c, 429)
"path": c.Path(),
})
} }
if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") { if err != nil && post.Id == "" && strings.Contains(err.Error(), "404") {
return c.Status(404).Render("errors/404", nil) return utils.RenderError(c, 404)
} }
if err != nil { if err != nil {
return err return err
} }
comments := []api.Comment{} comments := []api.Comment{}
if post.SharedWithCommunity { if post.SharedWithCommunity {
c.Set("Cache-Control", "public,max-age=604800") c.Set("Cache-Control", "public,max-age=604800")
comments, err = ApiClient.FetchComments(c.Params("postID")) comments, err = ApiClient.FetchComments(postId)
if err != nil { if err != nil {
return err return err
} }
@ -58,8 +84,16 @@ func HandlePost(c *fiber.Ctx) error {
} }
c.Set("Content-Security-Policy", csp) c.Set("Content-Security-Policy", csp)
var next string
tagParam := strings.Split(c.Query("tag"), ".")
if len(tagParam) == 4 {
tag, sort, page, index := tagParam[0], tagParam[1], tagParam[2], tagParam[3]
next = nextInTag(ApiClient, tag, sort, page, index)
}
return c.Render("post", fiber.Map{ return c.Render("post", fiber.Map{
"post": post, "post": post,
"next": next,
"comments": comments, "comments": comments,
"nonce": nonce, "nonce": nonce,
}) })

View File

@ -9,6 +9,7 @@ import (
func HandlePrivacy(c *fiber.Ctx) error { func HandlePrivacy(c *fiber.Ctx) error {
utils.SetHeaders(c) utils.SetHeaders(c)
c.Set("X-Frame-Options", "DENY") c.Set("X-Frame-Options", "DENY")
c.Set("Content-Security-Policy", "default-src 'none'; form-action 'self'; style-src 'self'; img-src 'self'; manifest-src 'self'; block-all-mixed-content")
return c.Render("privacy", fiber.Map{ return c.Render("privacy", fiber.Map{
"config": utils.Config, "config": utils.Config,

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")
}
}

View File

@ -29,11 +29,6 @@ func HandleSearch(c *fiber.Ctx) error {
pageNumber = 0 pageNumber = 0
} }
displayPrevPage := true
if page == "0" {
displayPrevPage = false
}
results, err := ApiClient.Search(query, page) results, err := ApiClient.Search(query, page)
if err != nil { if err != nil {
return err return err
@ -42,8 +37,7 @@ func HandleSearch(c *fiber.Ctx) error {
return c.Render("search", fiber.Map{ return c.Render("search", fiber.Map{
"query": query, "query": query,
"results": results, "results": results,
"page": pageNumber + 1, "page": pageNumber,
"displayPrev": displayPrevPage,
"nextPage": pageNumber + 1, "nextPage": pageNumber + 1,
"prevPage": pageNumber - 1, "prevPage": pageNumber - 1,
}) })

View File

@ -23,29 +23,21 @@ func HandleTag(c *fiber.Ctx) error {
pageNumber = 0 pageNumber = 0
} }
displayPrevPage := true
if page == "1" {
displayPrevPage = false
}
tag, err := ApiClient.FetchTag(c.Params("tag"), c.Query("sort"), page) tag, err := ApiClient.FetchTag(c.Params("tag"), c.Query("sort"), page)
if err != nil && err.Error() == "ratelimited by imgur" { if err != nil && err.Error() == "ratelimited by imgur" {
return c.Status(429).Render("errors/429", fiber.Map{ return utils.RenderError(c, 429)
"path": c.Path(),
})
} }
if err != nil { if err != nil {
return err return err
} }
if tag.Display == "" { if tag.Display == "" {
return c.Status(404).Render("errors/404", nil) return utils.RenderError(c, 404)
} }
return c.Render("tag", fiber.Map{ return c.Render("tag", fiber.Map{
"tag": tag, "tag": tag,
"page": page, "page": page,
"displayPrev": displayPrevPage, "nextPage": pageNumber + 1,
"nextPage": pageNumber + 1, "prevPage": pageNumber - 1,
"prevPage": pageNumber - 1,
}) })
} }

View File

@ -36,11 +36,6 @@ func HandleTrending(c *fiber.Ctx) error {
sort = "popular" sort = "popular"
} }
displayPrevPage := true
if page == "1" {
displayPrevPage = false
}
results, err := ApiClient.FetchTrending(section, sort, page) results, err := ApiClient.FetchTrending(section, sort, page)
if err != nil { if err != nil {
return err return err
@ -51,7 +46,6 @@ func HandleTrending(c *fiber.Ctx) error {
"section": section, "section": section,
"sort": sort, "sort": sort,
"page": pageNumber, "page": pageNumber,
"displayPrev": displayPrevPage,
"nextPage": pageNumber + 1, "nextPage": pageNumber + 1,
"prevPage": pageNumber - 1, "prevPage": pageNumber - 1,
}) })

View File

@ -25,23 +25,19 @@ func HandleUser(c *fiber.Ctx) error {
user, err := ApiClient.FetchUser(c.Params("userID")) user, err := ApiClient.FetchUser(c.Params("userID"))
if err != nil && err.Error() == "ratelimited by imgur" { if err != nil && err.Error() == "ratelimited by imgur" {
return c.Status(429).Render("errors/429", fiber.Map{ return utils.RenderError(c, 429)
"path": c.Path(),
})
} }
if err != nil { if err != nil {
return err return err
} }
if user.Username == "" { if user.Username == "" {
return c.Status(404).Render("errors/404", nil) return utils.RenderError(c, 404)
} }
submissions, err := ApiClient.FetchSubmissions(c.Params("userID"), "newest", page) submissions, err := ApiClient.FetchSubmissions(c.Params("userID"), "newest", page)
if err != nil && err.Error() == "ratelimited by imgur" { if err != nil && err.Error() == "ratelimited by imgur" {
c.Status(429) c.Status(429)
return c.Render("errors/429", fiber.Map{ return utils.RenderError(c, 429)
"path": c.Path(),
})
} }
if err != nil { if err != nil {
return err return err
@ -64,23 +60,19 @@ func HandleUserComments(c *fiber.Ctx) error {
user, err := ApiClient.FetchUser(c.Params("userID")) user, err := ApiClient.FetchUser(c.Params("userID"))
if err != nil && err.Error() == "ratelimited by imgur" { if err != nil && err.Error() == "ratelimited by imgur" {
return c.Status(429).Render("errors/429", fiber.Map{ return utils.RenderError(c, 429)
"path": c.Path(),
})
} }
if err != nil { if err != nil {
return err return err
} }
if user.Username == "" { if user.Username == "" {
return c.Status(404).Render("errors/404", nil) return utils.RenderError(c, 404)
} }
comments, err := ApiClient.FetchUserComments(c.Params("userID")) comments, err := ApiClient.FetchUserComments(c.Params("userID"))
if err != nil && err.Error() == "ratelimited by imgur" { if err != nil && err.Error() == "ratelimited by imgur" {
c.Status(429) c.Status(429)
return c.Render("errors/429", fiber.Map{ return utils.RenderError(c, 429)
"path": c.Path(),
})
} }
if err != nil { if err != nil {
return err return err
@ -91,3 +83,47 @@ func HandleUserComments(c *fiber.Ctx) error {
"comments": comments, "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 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,6 +1,7 @@
{ {
"name": "rimgo", "name": "rimgo",
"short_name": "rimgo", "short_name": "rimgo",
"start_url": "/",
"icons": [ "icons": [
{ {
"src": "/static/favicon/android-chrome-192x192.png", "src": "/static/favicon/android-chrome-192x192.png",

1
static/icons/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

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

View File

@ -1,13 +1,11 @@
@tailwind base; @import "tailwindcss" source("../views");
@tailwind components;
@tailwind utilities;
body { body {
margin: 0 24vw; margin: 0 24vw;
} }
p a { p a {
text-decoration: underline @apply break-words underline
} }
.posts { .posts {

View File

@ -1,8 +0,0 @@
module.exports = {
content: ["./views/*.hbs", "./views/**/*.hbs"],
theme: {
extend: {},
},
variants: {},
plugins: [],
};

View File

@ -9,6 +9,7 @@ type config struct {
Port string Port string
Addr string Addr string
ImgurId string ImgurId string
Secure bool
FiberPrefork bool FiberPrefork bool
ImageCache bool ImageCache bool
CleanupInterval time.Duration CleanupInterval time.Duration
@ -44,10 +45,11 @@ func LoadConfig() {
} }
Config = config{ Config = config{
Port: port, Port: port,
Addr: addr, Addr: addr,
ImgurId: imgurId, ImgurId: imgurId,
FiberPrefork: os.Getenv("FIBER_PREFORK") == "true", Secure: os.Getenv("SECURE") == "true",
FiberPrefork: os.Getenv("FIBER_PREFORK") == "true",
Privacy: map[string]interface{}{ Privacy: map[string]interface{}{
"set": os.Getenv("PRIVACY_NOT_COLLECTED") != "", "set": os.Getenv("PRIVACY_NOT_COLLECTED") != "",
"policy": os.Getenv("PRIVACY_POLICY"), "policy": os.Getenv("PRIVACY_POLICY"),

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(),
})
}
}

11
utils/getUrl.go Normal file
View File

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

View File

@ -25,8 +25,8 @@
rimgo is not affiliated with Imgur, all content is proxied from Imgur. rimgo is not affiliated with Imgur, all content is proxied from Imgur.
</p> </p>
<br/> <br/>
<h3 class="font-bold text-xl">Notice</h3> <h3 class="font-bold text-xl">Legal notice</h3>
<p>All images and media are from Imgur. rimgo does not allow uploads or comments. Any issues with content should be reported to Imgur.</p> <p>rimgo does not allow uploads or host any content, media. All content on any rimgo instances is from Imgur™. Imgur is a trademark of Imgur, Inc. Any issues with content on rimgo should be be reported to Imgur. rimgo is not affiliated with Imgur, Inc.</p>
</main> </main>
<h2 class="font-bold text-2xl">This instance</h2> <h2 class="font-bold text-2xl">This instance</h2>

View File

@ -3,8 +3,8 @@
<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=""> <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 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"> <div class="flex flex-col h-full">
<p>{{{this.Comment}}}</p> <p class="md-container">{{{this.Comment}}}</p>
<div class="flex-grow"></div> <div class="grow"></div>
<div class="flex gap-2"> <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}}

View File

@ -25,34 +25,41 @@
</header> </header>
<main> <main>
<div class="flex gap-4 items-center my-4"> <div class="flex flex-col sm:flex-row my-4 w-full justify-between">
{{#if post.User.Username}} <div class="flex flex-col gap-2 md:flex-row md:gap-4 md:items-center">
<a href="/user/{{post.User.Username}}" class="flex gap-2 items-center"> {{#if post.User.Username}}
<img src="{{post.User.Avatar}}" class="rounded-full" width="36" height="36" /> <a href="/user/{{post.User.Username}}" class="flex gap-2 items-center">
<p> <img src="{{post.User.Avatar}}" class="rounded-full" width="36" height="36" />
<b>{{post.User.Username}}</b> <p>
</p> <b>{{post.User.Username}}</b>
</a> </p>
{{/if}} </a>
<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}} {{/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> </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>
<div class="flex flex-center flex-col"> <div class="flex flex-center flex-col break-words">
{{#each post.Media}} {{#each post.Media}}
{{#if this.Title}} {{#if this.Title}}
<h4 class="font-bold">{{this.Title}}</h4> <h4 class="font-bold">{{this.Title}}</h4>
@ -70,7 +77,7 @@
{{#if this.Description}} {{#if this.Description}}
<p>{{{this.Description}}}</p> <p>{{{this.Description}}}</p>
{{/if}} {{/if}}
{{/each}} {{/each}}
</div> </div>
{{#if post.tags}} {{#if post.tags}}
@ -101,7 +108,8 @@
{{#if comments}} {{#if comments}}
<div> <div>
<input id="comments__expandBtn" type="checkbox" checked> <input id="comments__expandBtn" type="checkbox" checked>
<label class="comments__expandBtn__label my-2 py-4 border-solid border-t-2 border-slate-400" for="comments__expandBtn"> <label class="comments__expandBtn__label my-2 py-4 border-solid border-t-2 border-slate-400"
for="comments__expandBtn">
<h3 class="text-xl font-bold">Comments ({{post.Comments}})</h3> <h3 class="text-xl font-bold">Comments ({{post.Comments}})</h3>
<span class="text-xl font-bold"></span> <span class="text-xl font-bold"></span>
</label> </label>

View File

@ -22,10 +22,10 @@
</div> </div>
<div class="flex justify-between mt-4 font-bold"> <div class="flex justify-between mt-4 font-bold">
{{#if displayPrev}} {{#noteq page "0"}}
<a href="/search?q={{query}}&page={{prevPage}}">Previous page</a> <a href="/search?q={{query}}&page={{prevPage}}">Previous page</a>
{{/if}} {{/noteq}}
<p>Page {{page}}</p> <p>Page {{nextPage}}</p>
<a href="/search?q={{query}}&page={{nextPage}}">Next page</a> <a href="/search?q={{query}}&page={{nextPage}}">Next page</a>
</div> </div>
</main> </main>

View File

@ -5,6 +5,9 @@
<title>{{tag.Display}} - rimgo</title> <title>{{tag.Display}} - rimgo</title>
{{> partials/head }} {{> 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> </head>
<body class="font-sans text-lg bg-slate-800 text-white"> <body class="font-sans text-lg bg-slate-800 text-white">
@ -16,7 +19,12 @@
<header class="p-4 rounded-xl text-white mb-4" style="background-image: url('{{tag.Background}}');"> <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 flex-col items-center justify-center text-center">
<h2 class="text-2xl font-bold">{{tag.Display}}</h2> <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> <p>{{tag.PostCount}} posts</p>
</div> </div>
<div class="flex flex-col"> <div class="flex flex-col">
@ -45,10 +53,11 @@
{{/each}} {{/each}}
</div> </div>
<div class="mt-4 font-bold"> <div class="flex justify-between mt-4 font-bold">
{{#if displayPrev}} {{#noteq page "1"}}
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a> <a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>
{{/if}} {{/noteq}}
<p>Page {{nextPage}}</p>
<a href="{{channel.RelUrl}}?page={{nextPage}}">Next page</a> <a href="{{channel.RelUrl}}?page={{nextPage}}">Next page</a>
</div> </div>
</main> </main>

View File

@ -5,6 +5,9 @@
<title>Trending - rimgo</title> <title>Trending - rimgo</title>
{{> partials/head }} {{> partials/head }}
<link href="/trending.rss" rel="alternate" title="Trending" type="application/rss+xml">
<link href="/trending.atom" rel="alternate" title="Trending" type="application/atom+xml">
<link href="/trending.json" rel="alternate" title="Trending" type="application/feed+json">
</head> </head>
<body class="font-sans text-lg bg-slate-800 text-white"> <body class="font-sans text-lg bg-slate-800 text-white">
@ -15,8 +18,11 @@
</section> </section>
<header class="p-4 rounded-xl text-white mb-4 bg-gradient-to-r from-blue-400 to-emerald-400"> <header class="p-4 rounded-xl text-white mb-4 bg-gradient-to-r from-blue-400 to-emerald-400">
<div class="flex flex-col items-center justify-center text-center"> <div class="flex items-center justify-center text-center gap-2">
<h2 class="text-2xl font-extrabold">Trending</h2> <h2 class="text-2xl font-extrabold">Trending</h2>
<a href="/trending.rss" label="RSS">
<img src="/static/icons/PhRss.svg" width="24px" height="24px" class="invert" />
</a>
</div> </div>
<div class="flex flex-col sm:flex-row sm:justify-between"> <div class="flex flex-col sm:flex-row sm:justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
@ -65,9 +71,9 @@
</div> </div>
<div class="flex justify-between mt-4 font-bold"> <div class="flex justify-between mt-4 font-bold">
{{#if displayPrev}} {{#noteq page "1"}}
<a href="/trending?section={{section}}&sort={{sort}}&page={{prevPage}}">Previous page</a> <a href="/trending?section={{section}}&sort={{sort}}&page={{prevPage}}">Previous page</a>
{{/if}} {{/noteq}}
<p>Page {{page}}</p> <p>Page {{page}}</p>
<a href="/trending?section={{section}}&sort={{sort}}&page={{nextPage}}">Next page</a> <a href="/trending?section={{section}}&sort={{sort}}&page={{nextPage}}">Next page</a>
</div> </div>

View File

@ -5,6 +5,9 @@
<title>{{user.Username}} - rimgo</title> <title>{{user.Username}} - rimgo</title>
{{> partials/head }} {{> partials/head }}
<link href="/user/{{user.Username}}.rss" rel="alternate" title={{user.Username}} type="application/rss+xml">
<link href="/user/{{user.Username}}.atom" rel="alternate" title={{user.Username}} type="application/atom+xml">
<link href="/user/{{user.Username}}.json" rel="alternate" title={{user.Username}} type="application/feed+json">
</head> </head>
<body class="font-sans text-lg bg-slate-800 text-white"> <body class="font-sans text-lg bg-slate-800 text-white">
@ -15,15 +18,21 @@
</section> </section>
<header class="p-4 rounded-xl text-white mb-4" style="background-image: url('{{user.Cover}}');"> <header class="p-4 rounded-xl text-white mb-4" style="background-image: url('{{user.Cover}}');">
<div class="flex items-center gap-2"> <div class="flex flex-col sm:flex-row items-center gap-2">
<img class="rounded-full" src="{{user.Avatar}}" width="72" height="72"> <img class="rounded-full" src="{{user.Avatar}}" width="72" height="72">
<div> <div class="items-center sm:items-start text-center sm:text-left">
<h2 class="font-bold text-2xl">{{user.Username}}</h2> <div class="flex flex-row gap-2 items-center">
<h2 class="font-bold text-2xl">{{user.Username}}</h2>
<a href="/user/{{user.Username}}.rss" label="RSS">
<img src="/static/icons/PhRss.svg" width="24px" height="24px" class="invert" />
</a>
</div>
<p>{{user.Points}} pts · {{user.CreatedAt}}</p> <p>{{user.Points}} pts · {{user.CreatedAt}}</p>
</div> </div>
<hr class="sm:border-0 flex-grow"> <hr class="sm:border-0 grow">
<div class="flex flex-col sm:items-end"> <div class="flex flex-col items-center sm:items-end">
<a href="/user/{{user.Username}}"><b>Submissions</b></a> <a href="/user/{{user.Username}}"><b>Submissions</b></a>
<a href="/user/{{user.Username}}/favorites">Favorites</a>
<a href="/user/{{user.Username}}/comments">Comments</a> <a href="/user/{{user.Username}}/comments">Comments</a>
</div> </div>
</div> </div>

View File

@ -21,9 +21,10 @@
<h2 class="font-bold text-2xl">{{user.Username}}</h2> <h2 class="font-bold text-2xl">{{user.Username}}</h2>
<p>{{user.Points}} pts · {{user.CreatedAt}}</p> <p>{{user.Points}} pts · {{user.CreatedAt}}</p>
</div> </div>
<hr class="sm:border-0 flex-grow"> <hr class="sm:border-0 grow">
<div class="flex flex-col items-center sm:items-end"> <div class="flex flex-col items-center sm:items-end">
<a href="/user/{{user.Username}}">Submissions</a> <a href="/user/{{user.Username}}">Submissions</a>
<a href="/user/{{user.Username}}/favorites">Favorites</a>
<a href="/user/{{user.Username}}/comments"><b>Comments</b></a> <a href="/user/{{user.Username}}/comments"><b>Comments</b></a>
</div> </div>
</div> </div>

52
views/userFavorites.hbs Normal file
View File

@ -0,0 +1,52 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>{{user.Username}}'s favorites - rimgo</title>
{{> partials/head }}
</head>
<body class="font-sans text-lg bg-slate-800 text-white">
{{> partials/nav }}
<section class="my-4 w-full flex flex-col items-center">
{{> partials/searchBar }}
</section>
<header class="p-4 rounded-xl text-white mb-4" style="background-image: url('{{user.Cover}}');">
<div class="flex flex-col sm:flex-row items-center gap-2">
<img class="rounded-full" src="{{user.Avatar}}" width="72" height="72">
<div class="items-center sm:items-start text-center sm:text-left">
<h2 class="font-bold text-2xl">{{user.Username}}</h2>
<p>{{user.Points}} pts · {{user.CreatedAt}}</p>
</div>
<hr class="sm:border-0 grow">
<div class="flex flex-col items-center sm:items-end">
<a href="/user/{{user.Username}}">Submissions</a>
<a href="/user/{{user.Username}}/favorites"><b>Favorites</b></a>
<a href="/user/{{user.Username}}/comments">Comments</a>
</div>
</div>
<p class="mt-2">{{user.Bio}}</p>
</header>
<main>
<div class="posts">
{{#each favorites}}
{{> partials/post }}
{{/each}}
</div>
<div class="flex mt-4 font-bold justify-between">
{{#noteq page "0" }}
<a href="{{channel.RelUrl}}?page={{prevPage}}">Previous page</a>
{{/noteq}}
<a href="{{channel.RelUrl}}?page={{nextPage}}">Next page</a>
</div>
</main>
{{> partials/footer }}
</body>
</html>