diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 0f97088..cd460eb 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -2,34 +2,32 @@ name: Bug report about: 'Create a report to help us improve' title: '' -labels: '' +labels: 'bug' assignees: '' - --- Please make sure you're on the latest version before submitting. - # What's Happening? - + ## How to reproduce: - + ## Affected Platforms: -- [ ] macOS -- [ ] Windows -- [ ] Linux (Specify) -- [ ] iOS -- [ ] Android +- [ ] macOS +- [ ] Windows +- [ ] Linux (Specify) +- [ ] iOS +- [ ] Android -Version: +Version: ## Browser: -- [ ] Chromium-based (ex: Brave or Chrome) -- [ ] Webkit-based (ex: Safari) -- [ ] Gecko-based (ex: Firefox) +- [ ] Chromium-based (ex: Brave or Chrome) +- [ ] Webkit-based (ex: Safari) +- [ ] Gecko-based (ex: Firefox) diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 0000000..287182e --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,15 @@ +--- +name: Feature Request +about: 'Suggest a specific feature or enhancement' +title: '' +labels: 'enhancement' +assignees: '' +--- + +# What does the feature entail? + + + +# Why is this feature important? + + diff --git a/.github/ISSUE_TEMPLATE/new_instance.md b/.github/ISSUE_TEMPLATE/new_instance.md deleted file mode 100644 index 287c5f5..0000000 --- a/.github/ISSUE_TEMPLATE/new_instance.md +++ /dev/null @@ -1,12 +0,0 @@ ---- -name: New Instance -about: 'Add my public instance to the list' -title: "[INSTANCE] New public instance" -labels: '' -assignees: '' - ---- - -Instance URL: -Region (Written Out - ex United States): -Operated by (Link to your site): diff --git a/.github/workflows/docker-image.yml b/.github/workflows/docker-image.yml index 5b0d110..c7d3ceb 100644 --- a/.github/workflows/docker-image.yml +++ b/.github/workflows/docker-image.yml @@ -22,9 +22,13 @@ jobs: steps: - name: Checkout repository uses: actions/checkout@v4 + - name: Set up QEMU + uses: docker/setup-qemu-action@v3 + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v3 # Uses the `docker/login-action` action to log in to the Container registry registry using the account and password that will publish the packages. Once published, the packages are scoped to the account defined here. - name: Log in to the Container registry - uses: docker/login-action@65b78e6e13532edd9afa3aa52ac7964289d1a9c1 + uses: docker/login-action@v3 with: registry: ${{ env.REGISTRY }} username: ${{ github.actor }} @@ -32,16 +36,17 @@ jobs: # This step uses [docker/metadata-action](https://github.com/docker/metadata-action#about) to extract tags and labels that will be applied to the specified image. The `id` "meta" allows the output of this step to be referenced in a subsequent step. The `images` value provides the base name for the tags and labels. - name: Extract metadata (tags, labels) for Docker id: meta - uses: docker/metadata-action@9ec57ed1fcdbf14dcef7dfbe97b2010124a938b7 + uses: docker/metadata-action@v5 with: images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }} # This step uses the `docker/build-push-action` action to build the image, based on your repository's `Dockerfile`. If the build succeeds, it pushes the image to GitHub Packages. # It uses the `context` parameter to define the build's context as the set of files located in the specified path. For more information, see "[Usage](https://github.com/docker/build-push-action#usage)" in the README of the `docker/build-push-action` repository. # It uses the `tags` and `labels` parameters to tag and label the image with the output from the "meta" step. - name: Build and push Docker image - uses: docker/build-push-action@f2a1d5e99d037542a71f64918e516c093c6f3fc4 + uses: docker/build-push-action@v6 with: context: . push: true + platforms: linux/amd64,linux/arm64 tags: ${{ steps.meta.outputs.tags }} - labels: ${{ steps.meta.outputs.labels }} + labels: ${{ steps.meta.outputs.labels }} \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index df6bb71..59c477b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.22.1-alpine3.19 as build +FROM golang:1.22.1-alpine3.19 AS build WORKDIR /app @@ -9,17 +9,23 @@ RUN go mod download COPY . . -ENV CGO_ENABLED=0 +# Architecture and OS are set dynamically (by BuildKit) +ARG TARGETOS +ARG TARGETARCH +ENV CGO_ENABLED=0 GOOS=$TARGETOS GOARCH=$TARGETARCH -RUN go build -o anonymousoverflow +RUN go build -o anonymousoverflow && go build -o healthcheck ./src/healthcheck FROM scratch COPY --from=build /app/anonymousoverflow /anonymousoverflow +COPY --from=build /app/healthcheck /healthcheck COPY templates /templates COPY public /public COPY --from=build /etc/ssl/certs /etc/ssl/certs +HEALTHCHECK --interval=60s --timeout=5s --start-period=2s --retries=3 CMD [ "/healthcheck","http://localhost:8080/healthz" ] + EXPOSE 8080 CMD ["/anonymousoverflow"] \ No newline at end of file diff --git a/README.md b/README.md index 73c1add..be2437d 100644 --- a/README.md +++ b/README.md @@ -12,48 +12,9 @@ This project is super lightweight by design. The UI is simple and the frontend i  -## Clearnet Instances +## Instances -| Instance URL | Region | Notes | -| ----------------------------------------------------------------------------------------- | ---------------------------- | ------------------------------------------------------------------------------------------------ | -| [code.whatever.social](https://code.whatever.social) | Germany | Operated by [Whatever Social](https://whatever.social) and [http.james](https://httpjames.space) | -| [ao.vern.cc](https://ao.vern.cc) | United States | Operated by [vern.cc](https://vern.cc) | -| [overflow.smnz.de](https://overflow.smnz.de) | Germany | Operated by [smnz.de](https://smnz.de) | -| [overflow.lunar.icu](https://overflow.lunar.icu) | Germany | Operated by [lunar.icu](https://lunar.icu/) | -| [overflow.adminforge.de](https://overflow.adminforge.de/) | Germany | Operated by [adminForge](https://adminforge.de/) | -| [overflow.hostux.net](https://overflow.hostux.net/) | France | Operated by [Hostux](https://hostux.net/) | -| [overflow.projectsegfau.lt](https://overflow.projectsegfau.lt/) | United States, France, India | Operated by [Project Segfault](https://projectsegfau.lt/) | -| [code.xbdm.fun](https://code.xbdm.fun) | Germany | Operated by [xbdm.fun](https://xbdm.fun) | -| [overflow.fascinated.cc](https://overflow.fascinated.cc/) | Germany | Operated by [fascinated.cc](https://fascinated.cc/) | -| [ao.bloat.cat](https://ao.bloat.cat) | Romania | Operated by [bloat.cat](https://bloat.cat) | -| [anonoverflow.frontendfriendly.xyz](https://anonoverflow.frontendfriendly.xyz/) | United States | Operated by [frontendfriendly.xyz](https://frontendfriendly.xyz/) | -| [ao.owo.si](https://ao.owo.si/) | Germany | Operated by [owo.si](https://owo.si/) | -| [overflow.datura.network](https://overflow.datura.network/) | Germany | Operated by [datura.network](https://datura.network) | -| [overflow.freedit.eu](overflow.freedit.eu) | United States | Operated by [freedit.eu](https://freedit.eu) | -| [ao.ftw.lol](https://ao.ftw.lol) | Germany | Operated by [ftw.lol](https://ftw.lol) | -| [anonoverflow.hyperreal.coffee](https://anonoverflow.hyperreal.coffee) | United States | Operated by [hyperreal.coffee](https://hyperreal.coffee) | -| [a.opnxng.com](a.opnxng.com) | Singapore | Operated by [opnxng.com](https://about.opnxng.com) | -| [overflow.sudovanilla.com](https://overflow.sudovanilla.com) | United States | Operated by [SudoVanilla](https://sudovanilla.com) | -| [anonymousoverflow.privacyfucking.rocks](https://anonymousoverflow.privacyfucking.rocks/) | Germany | Operated by [privacyfucking.rocks](https://privacyfucking.rocks) | -| [exchange.seitan-ayoub.lol](https://exchange.seitan-ayoub.lol) | Germany | Operated by [Seitan Ayoub](https://seitan-ayoub.lol) | -| [overflow.r4fo.com](https://overflow.r4fo.com) | The Netherlands | Operated by [r4fo.com](https://r4fo.com) | -| [overflow.ducks.party](https://overflow.ducks.party) | The Netherlands | Operated by [ducks.party](https://ducks.party) | -| [ao.ngn.tf](https://ao.ngn.tf) | Turkey | Operated by [ngn](https://ngn.tf) | -| [overflow.snine.nl](https://overflow.snine.nl) | The Netherlands | Operated by [snine](https://snine.nl) | -| [anonymousoverflow.privacyredirect.com](https://anonymousoverflow.privacyredirect.com) | Finland | Operated by [privacyredirect.com](https://privacyredirect.com/) | -| [soflow.nerdvpn.de](https://soflow.nerdvpn.de) | Ukraine | Operated by [Sommerwiesel](https://github.com/Sommerwiesel) | - -## Other Instances - -| Instance URL | Region | Notes | -| ---------------------------------------------------------------------------------------------------------------------------------------------------------- | --------------- | --------------------------------------------------------- | -| [ao.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion](http://ao.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion) | United States | Operated by [vern.cc](https://vern.cc) | -| [vernmzgraj6aaoafmehupvtkkynpaa67rxcdj2kinwiy6konn6rq.b32.i2p](http://vernmzgraj6aaoafmehupvtkkynpaa67rxcdj2kinwiy6konn6rq.b32.i2p) | United States | Operated by [vern.cc](https://vern.cc) | -| [overflow.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion](http://overflow.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion/) | Luxembourg | Operated by [Project Segfault](https://projectsegfau.lt/) | -| [overflow.daturab6drmkhyeia4ch5gvfc2f3wgo6bhjrv3pz6n7kxmvoznlkq4yd.onion](http://overflow.daturab6drmkhyeia4ch5gvfc2f3wgo6bhjrv3pz6n7kxmvoznlkq4yd.onion/) | Germany | Operated by [datura.network](https://datura.network) | -| [ao.pk47sgwhncn5cgidm7bofngmh7lc7ukjdpk5bjwfemmyp27ovl25ikyd.onion](http://ao.pk47sgwhncn5cgidm7bofngmh7lc7ukjdpk5bjwfemmyp27ovl25ikyd.onion/) | Germany | Operated by [owo.si](https://owo.si/) | -| [ay7akchgdh76r4lc62hzd52z6xqoh67loototsetvqxo5o7ngo5q.b32.i2p](http://ay7akchgdh76r4lc62hzd52z6xqoh67loototsetvqxo5o7ngo5q.b32.i2p/) | Germany | Operated by [owo.si](https://owo.si/) | -| [overflow.r4focoma7gu2zdwwcjjad47ysxt634lg73sxmdbkdozanwqslho5ohyd.onion](http://overflow.r4focoma7gu2zdwwcjjad47ysxt634lg73sxmdbkdozanwqslho5ohyd.onion) | The Netherlands | Operated by [r4fo.com](https://r4fo.com) | +Visit the [AnonymousOverflow Hub](https://aohub.httpjames.space) for a list of instances. ## Why use AnonymousOverflow over StackOverflow? @@ -82,7 +43,7 @@ StackOverflow has a cluttered UI that might distract you from the content you're The open-source [Libredirect](https://github.com/libredirect/libredirect) extension for Firefox and Chromium-based desktop browsers has support for redirections to AnonymousOverflow. To enable this, simply open the extension settings, click on Stack Overflow, then toggle "Enable". That's it, now Stack Overflow links will go to AnonymousOverflow. -The open-source [FREEdirector](https://openuserjs.org/scripts/sjehuda/FREEdirector) user.js script for web browsers with userscript support. You can install it with a web extension like [Greasemonkey](https://greasespot.net/), [Tampermonkey](https://tampermonkey.net/) or [Violentmonkey](https://violentmonkey.github.io/). Once installed, Stack Overflow links will go to AnonymousOverflow. +The open-source [Proxy_Redirect](https://openuserjs.org/scripts/sjehuda/Proxy_Redirect) user.js script for web browsers with userscript support. You can install it with a web extension like [Greasemonkey](https://greasespot.net/), [Tampermonkey](https://tampermonkey.net/) or [Violentmonkey](https://violentmonkey.github.io/). Once installed, Stack Overflow links will go to AnonymousOverflow. ## How it works diff --git a/config/version.go b/config/version.go index 45201be..d2a1fa2 100644 --- a/config/version.go +++ b/config/version.go @@ -1,3 +1,3 @@ package config -var Version = "1.12.1" +var Version = "1.13.0" diff --git a/go.mod b/go.mod index fa77182..b5fb1e7 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/PuerkitoBio/goquery v1.9.1 github.com/alecthomas/chroma v0.10.0 - github.com/gin-gonic/gin v1.9.1 + github.com/gin-gonic/gin v1.10.0 github.com/go-resty/resty/v2 v2.12.0 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/joho/godotenv v1.5.1 @@ -13,34 +13,55 @@ require ( require ( github.com/andybalholm/cascadia v1.3.2 // indirect - github.com/bytedance/sonic v1.11.3 // indirect + github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect + github.com/bytedance/sonic v1.11.6 // indirect + github.com/bytedance/sonic/loader v0.1.1 // indirect + github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d // indirect github.com/chenzhuoyu/iasm v0.9.1 // indirect + github.com/cloudwego/base64x v0.1.4 // indirect + github.com/cloudwego/iasm v0.2.0 // indirect github.com/davecgh/go-spew v1.1.1 // indirect + github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f // indirect github.com/dlclark/regexp2 v1.11.0 // indirect github.com/gabriel-vasile/mimetype v1.4.3 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect - github.com/go-playground/validator/v10 v10.19.0 // indirect + github.com/go-playground/validator/v10 v10.20.0 // indirect github.com/goccy/go-json v0.10.2 // indirect + github.com/golang/snappy v0.0.4 // indirect + github.com/google/uuid v1.3.1 // indirect + github.com/influxdata/influxdb-client-go/v2 v2.13.0 // indirect + github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 // indirect github.com/json-iterator/go v1.1.12 // indirect + github.com/klauspost/compress v1.16.7 // indirect github.com/klauspost/cpuid/v2 v2.2.7 // indirect github.com/leodido/go-urn v1.4.0 // indirect github.com/mattn/go-isatty v0.0.20 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect - github.com/pelletier/go-toml/v2 v2.2.0 // indirect + github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe // indirect + github.com/oapi-codegen/runtime v1.0.0 // indirect + github.com/pelletier/go-toml/v2 v2.2.2 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect + github.com/redis/go-redis/v9 v9.5.3 // indirect github.com/stretchr/testify v1.9.0 // indirect + github.com/tavsec/gin-healthcheck v1.6.2 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect github.com/ugorji/go/codec v1.2.12 // indirect - golang.org/x/arch v0.7.0 // indirect - golang.org/x/crypto v0.22.0 // indirect - golang.org/x/net v0.24.0 // indirect - golang.org/x/sys v0.19.0 // indirect - golang.org/x/text v0.14.0 // indirect - google.golang.org/protobuf v1.33.0 // indirect + github.com/xdg-go/pbkdf2 v1.0.0 // indirect + github.com/xdg-go/scram v1.1.2 // indirect + github.com/xdg-go/stringprep v1.0.4 // indirect + github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d // indirect + go.mongodb.org/mongo-driver v1.15.0 // indirect + golang.org/x/arch v0.8.0 // indirect + golang.org/x/crypto v0.23.0 // indirect + golang.org/x/net v0.25.0 // indirect + golang.org/x/sync v0.7.0 // indirect + golang.org/x/sys v0.20.0 // indirect + golang.org/x/text v0.15.0 // indirect + google.golang.org/protobuf v1.34.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/go.sum b/go.sum index 67eb02b..4ec3994 100644 --- a/go.sum +++ b/go.sum @@ -2,16 +2,26 @@ github.com/PuerkitoBio/goquery v1.8.0 h1:PJTF7AmFCFKk1N6V6jmKfrNH9tV5pNE6lZMkG0g github.com/PuerkitoBio/goquery v1.8.0/go.mod h1:ypIiRMtY7COPGk+I/YbZLbxsxn9g5ejnI2HSMtkjZvI= github.com/PuerkitoBio/goquery v1.9.1 h1:mTL6XjbJTZdpfL+Gwl5U2h1l9yEkJjhmlTeV9VPW7UI= github.com/PuerkitoBio/goquery v1.9.1/go.mod h1:cW1n6TmIMDoORQU5IU/P1T3tGFunOeXEpGP2WHRwkbY= +github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/alecthomas/chroma v0.10.0 h1:7XDcGkCQopCNKjZHfYrNLraA+M7e0fMiJ/Mfikbfjek= github.com/alecthomas/chroma v0.10.0/go.mod h1:jtJATyUxlIORhUOFNA9NZDWGAQ8wpxQQqNSB4rjA/1s= github.com/andybalholm/cascadia v1.3.1 h1:nhxRkql1kdYCc8Snf7D5/D3spOX+dBgjA6u8x004T2c= github.com/andybalholm/cascadia v1.3.1/go.mod h1:R4bJ1UQfqADjvDa4P6HZHLh/3OxWWEqc0Sk8XGwHqvA= github.com/andybalholm/cascadia v1.3.2 h1:3Xi6Dw5lHF15JtdcmAHD3i1+T8plmv7BQ/nsViSLyss= github.com/andybalholm/cascadia v1.3.2/go.mod h1:7gtRlve5FxPPgIgX36uWBX58OdBsSS6lUvCFb+h7KvU= +github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ= +github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk= +github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= github.com/bytedance/sonic v1.10.0-rc/go.mod h1:ElCzW+ufi8qKqNW0FY314xriJhyJhuoJ3gFZdAHF7NM= github.com/bytedance/sonic v1.11.3 h1:jRN+yEjakWh8aK5FzrciUHG8OFXK+4/KrAX/ysEtHAA= github.com/bytedance/sonic v1.11.3/go.mod h1:iZcSUejdk5aukTND/Eu/ivjQuEL0Cu9/rf50Hi0u/g4= +github.com/bytedance/sonic v1.11.6 h1:oUp34TzMlL+OY1OUWxHqsdkgC/Zfc85zGqw9siXjrc0= +github.com/bytedance/sonic v1.11.6/go.mod h1:LysEHSvpvDySVdC2f87zGWf6CIKJcAvqab1ZaiQtds4= +github.com/bytedance/sonic/loader v0.1.1 h1:c+e5Pt1k/cy5wMveRDyk2X4B9hF4g7an8N3zCYjJFNM= +github.com/bytedance/sonic/loader v0.1.1/go.mod h1:ncP89zfokxS5LZrJxl5z0UJcsk4M4yY2JpfqGeCtNLU= +github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= +github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY= github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk= github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d h1:77cEq6EriyTZ0g/qfRdp61a3Uu/AWrgIq2s0ClJV1g0= @@ -19,10 +29,16 @@ github.com/chenzhuoyu/base64x v0.0.0-20230717121745-296ad89f973d/go.mod h1:8EPpV github.com/chenzhuoyu/iasm v0.9.0/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= github.com/chenzhuoyu/iasm v0.9.1 h1:tUHQJXo3NhBqw6s33wkGn9SP3bvrWLdlVIJ3hQBL7P0= github.com/chenzhuoyu/iasm v0.9.1/go.mod h1:Xjy2NpN3h7aUqeqM+woSuuvxmIe6+DDsiNLIrkAmYog= +github.com/cloudwego/base64x v0.1.4 h1:jwCgWpFanWmN8xoIUHa2rtzmkd5J2plF/dnLS6Xd/0Y= +github.com/cloudwego/base64x v0.1.4/go.mod h1:0zlkT4Wn5C6NdauXdJRhSKRlJvmclQ1hhJgA0rcu/8w= +github.com/cloudwego/iasm v0.2.0 h1:1KNIy1I1H9hNNFEEH3DVnI4UujN+1zjpuk6gwHLTssg= +github.com/cloudwego/iasm v0.2.0/go.mod h1:8rXZaNYT2n95jn+zTI1sDr+IgcD2GVs0nlbbQPiEFhY= github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78= +github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc= github.com/dlclark/regexp2 v1.4.0/go.mod h1:2pZnwuY/m+8K6iRw6wQdMtk+rH5tNGR1i55kozfMjCc= github.com/dlclark/regexp2 v1.7.0 h1:7lJfhqlPssTb1WQx4yvTHN0uElPEv52sbaECrAQxjAo= github.com/dlclark/regexp2 v1.7.0/go.mod h1:DHkYz0B9wPfa6wondMfaivmHpzrQ3v9q8cnmRbL6yW8= @@ -36,6 +52,8 @@ github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY= github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398= github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= +github.com/gin-gonic/gin v1.10.0 h1:nTuyha1TYqgedzytsKYqna+DfLos46nTv2ygFy86HFU= +github.com/gin-gonic/gin v1.10.0/go.mod h1:4PMNQiOhvDRa013RKVbsiNwoyezlm2rm0uX/T7kzp5Y= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s= @@ -51,6 +69,8 @@ github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJ github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU= github.com/go-playground/validator/v10 v10.19.0 h1:ol+5Fu+cSq9JD7SoSqe04GMI92cbn0+wvQ3bZ8b/AU4= github.com/go-playground/validator/v10 v10.19.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= +github.com/go-playground/validator/v10 v10.20.0 h1:K9ISHbSaI0lyB2eWMPJo+kOS/FBExVwjEviJTixqxL8= +github.com/go-playground/validator/v10 v10.20.0/go.mod h1:dbuPbCMFw/DrkbEynArYaCwl3amGuJotoKCe95atGMM= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-resty/resty/v2 v2.12.0 h1:rsVL8P90LFvkUYq/V5BTVe203WfRIU4gvcf+yfzJzGA= @@ -64,15 +84,26 @@ github.com/golang-jwt/jwt/v4 v4.4.3/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= +github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM= +github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= +github.com/google/uuid v1.3.1 h1:KjJaJ9iWZ3jOFZIf1Lqf4laDRCasjl0BCmnEGxkdLb4= +github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/influxdata/influxdb-client-go/v2 v2.13.0 h1:ioBbLmR5NMbAjP4UVA5r9b5xGjpABD7j65pI8kFphDM= +github.com/influxdata/influxdb-client-go/v2 v2.13.0/go.mod h1:k+spCbt9hcvqvUiz0sr5D8LolXHqAAOfPw9v/RIRHl4= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839 h1:W9WBk7wlPfJLvMCdtV4zPulc4uCPrlywQOmbFOhgQNU= +github.com/influxdata/line-protocol v0.0.0-20200327222509-2487e7298839/go.mod h1:xaLFMmpvUxqXtVkUJfg9QmT88cDaCJ3ZKgdZ78oO8Qo= github.com/joho/godotenv v1.4.0 h1:3l4+N6zfMWnkbPEXKng2o2/MR5mSwTrBih4ZEkkz1lg= github.com/joho/godotenv v1.4.0/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= +github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= +github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I= +github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM= github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws= @@ -98,16 +129,25 @@ github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe h1:iruDEfMl2E6fbMZ9s0scYfZQ84/6SPL6zC8ACM2oIL0= +github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= +github.com/oapi-codegen/runtime v1.0.0 h1:P4rqFX5fMFWqRzY9M/3YF9+aPSPPB06IzP2P7oOxrWo= +github.com/oapi-codegen/runtime v1.0.0/go.mod h1:LmCUMQuPB4M/nLXilQXhHw+BLZdDb18B34OO356yJ/A= github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= github.com/pelletier/go-toml/v2 v2.2.0 h1:QLgLl2yMN7N+ruc31VynXs1vhMZa7CeHHejIeBAsoHo= github.com/pelletier/go-toml/v2 v2.2.0/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= +github.com/pelletier/go-toml/v2 v2.2.2 h1:aYUidT7k73Pcl9nb2gScu7NSrKCSHIDE89b3+6Wq+LM= +github.com/pelletier/go-toml/v2 v2.2.2/go.mod h1:1t835xjRzz80PqgE6HHgN2JOsmgYu/h4qDAS4n929Rs= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= 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/redis/go-redis/v9 v9.5.3 h1:fOAp1/uJG+ZtcITgZOfYFmTKPE7n4Vclj1wZFgRciUU= +github.com/redis/go-redis/v9 v9.5.3/go.mod h1:hdY0cQFCN4fnSYT6TkisLufl/4W5UIXyv0b/CLO2V2M= github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8= github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= +github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= @@ -122,16 +162,30 @@ github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tavsec/gin-healthcheck v1.6.2 h1:F89IFXXtYOy3p4gne8WFkos3r7vjMbE+R3C/v70dTW0= +github.com/tavsec/gin-healthcheck v1.6.2/go.mod h1:VcZ4f44KqMnwbzRBrr7VYni2GmkMErd/44QuM5Dy/YI= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= github.com/ugorji/go/codec v1.2.8 h1:sgBJS6COt0b/P40VouWKdseidkDgHxYGm0SAglUHfP0= github.com/ugorji/go/codec v1.2.8/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/ugorji/go/codec v1.2.12 h1:9LC83zGrHhuUA9l16C9AHXAqEV/2wBQ4nkvumAE65EE= github.com/ugorji/go/codec v1.2.12/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c= +github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI= +github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY= +github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4= +github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8= +github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d h1:splanxYIlg+5LfHAM6xpdFEAYOk8iySO56hMFq6uLyA= +github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA= github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY= +go.mongodb.org/mongo-driver v1.15.0 h1:rJCKC8eEliewXjZGf0ddURtl7tTVy1TK3bfl0gkUSLc= +go.mongodb.org/mongo-driver v1.15.0/go.mod h1:Vzb0Mk/pa7e6cWw85R4F/endUC3u0U9jGcNU603k65c= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/arch v0.7.0 h1:pskyeJh/3AmoQ8CPE95vxHLqp1G1GfGNXTmcl9NEKTc= golang.org/x/arch v0.7.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= +golang.org/x/arch v0.8.0 h1:3wRIsP3pM4yUptoR96otTUOXI367OS0+c9eeRi9doIc= +golang.org/x/arch v0.8.0/go.mod h1:FEVrYAQjsQXMVJ1nsMoVVXPZg6p2JE2mx8psSWTDQys= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= @@ -141,6 +195,8 @@ golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDf golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/crypto v0.22.0 h1:g1v0xeRhjcugydODzvb3mEM9SQ0HGp9s/nh3COQ/C30= golang.org/x/crypto v0.22.0/go.mod h1:vr6Su+7cTlO45qkww3VDJlzDn0ctJvRgYbC2NvXHt+M= +golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI= +golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -158,9 +214,13 @@ golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg= golang.org/x/net v0.24.0 h1:1PcaxkF854Fu3+lvBIx5SYn9wRlBzzcnHZSiaFFAb0w= golang.org/x/net v0.24.0/go.mod h1:2Q7sJY5mzlzWjKtYUEXSlBWCdyaioyXzRB2RtU8KVE8= +golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac= +golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM= golang.org/x/sync v0.0.0-20190423024810-112230192c58/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.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= +golang.org/x/sync v0.7.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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -178,6 +238,8 @@ golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.19.0 h1:q5f1RH2jigJ1MoAWp2KTp3gm5zAGFUTarQZ5U386+4o= golang.org/x/sys v0.19.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y= +golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= 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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -189,11 +251,14 @@ 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.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.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ= golang.org/x/text v0.7.0 h1:4BRB4x83lYWy72KwLD/qYDuTu7q9PjSagHvijDw7cLo= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.14.0 h1:ScX5w1eTa3QqT8oi6+ziP7dTV1S2+ALU0bI+0zXKWiQ= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= +golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk= +golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM= 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= @@ -207,6 +272,8 @@ google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175 google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= +google.golang.org/protobuf v1.34.1 h1:9ddQBjfCyZPOHPUiPxpYESBLc+T8P3E+Vo4IbKZgFWg= +google.golang.org/protobuf v1.34.1/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/instances.json b/instances.json new file mode 100644 index 0000000..5d15b83 --- /dev/null +++ b/instances.json @@ -0,0 +1,232 @@ +{ + "clearnet": [ + { + "url": "https://code.whatever.social", + "regions": ["Canada", "United States"], + "operators": ["https://whatever.social", "https://httpjames.space"] + }, + { + "url": "https://ao.vern.cc", + "regions": ["United States"], + "operators": ["https://vern.cc"] + }, + { + "url": "https://overflow.smnz.de", + "regions": ["Germany"], + "operators": ["https://smnz.de"] + }, + { + "url": "https://overflow.lunar.icu", + "regions": ["Germany"], + "operators": ["https://lunar.icu/"] + }, + { + "url": "https://overflow.adminforge.de/", + "regions": ["Germany"], + "operators": ["https://adminforge.de/"] + }, + { + "url": "https://overflow.hostux.net/", + "regions": ["France"], + "operators": ["https://hostux.net/"] + }, + { + "url": "https://overflow.projectsegfau.lt/", + "regions": ["United States", "Germany", "India"], + "operators": ["https://projectsegfau.lt/"] + }, + { + "url": "https://code.xbdm.fun", + "regions": ["Germany"], + "operators": ["https://xbdm.fun"] + }, + { + "url": "https://overflow.fascinated.cc/", + "regions": ["Germany"], + "operators": ["https://fascinated.cc/"] + }, + { + "url": "https://ao.bloat.cat", + "regions": ["Germany"], + "operators": ["https://bloat.cat"] + }, + { + "url": "https://anonoverflow.frontendfriendly.xyz/", + "regions": ["United States"], + "operators": ["https://frontendfriendly.xyz/"] + }, + { + "url": "https://ao.owo.si/", + "regions": ["Germany"], + "operators": ["https://owo.si/"] + }, + { + "url": "https://overflow.datura.network/", + "regions": ["Germany"], + "operators": ["https://datura.network"] + }, + { + "url": "https://overflow.freedit.eu", + "regions": ["United States"], + "operators": ["https://freedit.eu"] + }, + { + "url": "https://ao.rootdo.com", + "regions": ["Germany"], + "operators": ["https://rootdo.com"] + }, + { + "url": "https://anonoverflow.hyperreal.coffee", + "regions": ["Germany"], + "operators": ["https://hyperreal.coffee"] + }, + { + "url": "https://o.sudovanilla.org", + "regions": ["United States"], + "operators": ["https://sudovanilla.org"] + }, + { + "url": "https://anonymousoverflow.privacyfucking.rocks/", + "regions": ["Germany"], + "operators": ["https://privacyfucking.rocks"] + }, + { + "url": "https://exchange.seitan-ayoub.lol", + "regions": ["Germany"], + "operators": ["https://seitan-ayoub.lol"] + }, + { + "url": "https://overflow.r4fo.com", + "regions": ["The Netherlands"], + "operators": ["https://r4fo.com"] + }, + { + "url": "https://overflow.ducks.party", + "regions": ["The Netherlands"], + "operators": ["https://ducks.party"] + }, + { + "url": "https://ao.ngn.tf", + "regions": ["Turkey"], + "operators": ["https://ngn.tf"] + }, + { + "url": "https://overflow.snine.nl", + "regions": ["The Netherlands"], + "operators": ["https://snine.nl"] + }, + { + "url": "https://anonymousoverflow.privacyredirect.com", + "regions": ["Finland"], + "operators": ["https://privacyredirect.com/"] + }, + { + "url": "https://soflow.nerdvpn.de", + "regions": ["Ukraine"], + "operators": ["https://nerdvpn.de"] + }, + { + "url": "https://overflow.einfachzocken.eu/", + "regions": ["Germany"], + "operators": ["https://einfachzocken.eu"] + }, + { + "url": "https://overflow.seasi.dev/", + "regions": ["Singapore"], + "operators": ["https://seasi.dev/"] + }, + { + "url": "https://anonymousoverflow.catsarch.com", + "regions": ["United States"], + "operators": ["https://catsarch.com"] + }, + { + "url": "https://overflow.darkness.services/", + "regions": ["United States"], + "operators": ["https://zzz.darkness.services"] + }, + { + "url": "https://anonflow.aketawi.space/", + "regions": ["Russia"], + "operators": ["https://www.aketawi.space/"] + }, + { + "url": "https://ao.bunk.lol", + "regions": ["Iceland"], + "operators": ["https://bunk.lol"] + }, + { + "url": "https://o.iii.st/", + "regions": ["Germany"], + "operators": ["https://iii.st/"] + }, + { + "url": "https://overflow.canine.tools/", + "regions": ["United States"], + "operators": ["https://canine.tools/"] + } + ], + + "onion": [ + { + "url": "http://ao.vernccvbvyi5qhfzyqengccj7lkove6bjot2xhh5kajhwvidqafczrad.onion", + "regions": ["United States"], + "operators": ["https://vern.cc"] + }, + { + "url": "http://overflow.pjsfkvpxlinjamtawaksbnnaqs2fc2mtvmozrzckxh7f3kis6yea25ad.onion/", + "regions": ["Germany"], + "operators": ["https://projectsegfau.lt/"] + }, + { + "url": "http://overflow.daturab6drmkhyeia4ch5gvfc2f3wgo6bhjrv3pz6n7kxmvoznlkq4yd.onion/", + "regions": ["Germany"], + "operators": ["https://datura.network"] + }, + { + "url": "http://ao.pk47sgwhncn5cgidm7bofngmh7lc7ukjdpk5bjwfemmyp27ovl25ikyd.onion/", + "regions": ["Germany"], + "operators": ["https://owo.si/"] + }, + { + "url": "http://overflow.r4focoma7gu2zdwwcjjad47ysxt634lg73sxmdbkdozanwqslho5ohyd.onion", + "regions": ["The Netherlands"], + "operators": ["https://r4fo.com"] + }, + { + "url": "http://anonymousoverflow.catsarchywsyuss6jdxlypsw5dc7owd5u5tr6bujxb7o6xw2hipqehyd.onion/", + "regions": ["United States"], + "operators": ["https://catsarch.com"] + }, + { + "url": "http://overflow.darknessrdor43qkl2ngwitj72zdavfz2cead4t5ed72bybgauww5lyd.onion/", + "regions": ["United States"], + "operators": [ + "http://darknessrdor43qkl2ngwitj72zdavfz2cead4t5ed72bybgauww5lyd.onion/" + ] + }, + { + "url": "http://o.zx56doutynmbgezxtpccduajwcblzx7fgio2yuy57a3jingco2c6fvqd.onion/", + "regions": ["Germany"], + "operators": ["https://iii.st/"] + } + ], + + "i2p": [ + { + "url": "http://vernmzgraj6aaoafmehupvtkkynpaa67rxcdj2kinwiy6konn6rq.b32.i2p", + "regions": ["United States"], + "operators": ["https://vern.cc"] + }, + { + "url": "http://ay7akchgdh76r4lc62hzd52z6xqoh67loototsetvqxo5o7ngo5q.b32.i2p/", + "regions": ["Germany"], + "operators": ["https://owo.si/"] + }, + { + "url": "http://ocp7zhdsbl2mjabv5ma5jvbzg2dqzglieayjvyj4j2r7qvsqlboa.b32.i2p/", + "regions": ["United States"], + "operators": ["https://catsarch.com"] + } + ] +} diff --git a/main.go b/main.go index 625b161..c9cc96c 100644 --- a/main.go +++ b/main.go @@ -8,6 +8,9 @@ import ( "os" "github.com/gin-gonic/gin" + healthcheck "github.com/tavsec/gin-healthcheck" + "github.com/tavsec/gin-healthcheck/checks" + "github.com/tavsec/gin-healthcheck/config" ) func main() { @@ -35,7 +38,6 @@ func main() { r.Use(gin.Recovery()) r.Use(middleware.XssPreventionHeaders()) - r.Use(middleware.NoCacheMiddleware()) r.Use(middleware.OptionsMiddleware()) r.Use(middleware.Ratelimit()) @@ -55,6 +57,23 @@ func main() { r.GET("/q/:id", routes.RedirectShortenedOverflowURL) r.GET("/q/:id/:answerId", routes.RedirectShortenedOverflowURL) + exchangeRouter := r.Group("/exchange/:sub") + { + exchangeRouter.GET("/questions/:id/:title", routes.ViewQuestion) + exchangeRouter.GET("/questions/:id", func(c *gin.Context) { + // redirect user to the question with the title + c.Redirect(302, fmt.Sprintf("/exchange/%s/questions/%s/placeholder", c.Param("sub"), c.Param("id"))) + }) + exchangeRouter.GET("/questions/:id/:title/:answerId", func(c *gin.Context) { + // redirect user to the answer with the title + c.Redirect(302, fmt.Sprintf("/exchange/%s/questions/%s/%s#%s", c.Param("sub"), c.Param("id"), c.Param("title"), c.Param("answerId"))) + }) + exchangeRouter.GET("/q/:id/:answerId", routes.RedirectShortenedOverflowURL) + exchangeRouter.GET("/q/:id", routes.RedirectShortenedOverflowURL) + exchangeRouter.GET("/a/:id/:answerId", routes.RedirectShortenedOverflowURL) + exchangeRouter.GET("/a/:id", routes.RedirectShortenedOverflowURL) + } + r.GET("/questions/:id", func(c *gin.Context) { // redirect user to the question with the title c.Redirect(302, fmt.Sprintf("/questions/%s/placeholder", c.Param("id"))) @@ -64,17 +83,14 @@ func main() { // redirect user to the answer with the title c.Redirect(302, fmt.Sprintf("/questions/%s/%s#%s", c.Param("id"), c.Param("title"), c.Param("answerId"))) }) - r.GET("/exchange/:sub/questions/:id/:title", routes.ViewQuestion) - r.GET("/exchange/:sub/questions/:id", func(c *gin.Context) { - // redirect user to the question with the title - c.Redirect(302, fmt.Sprintf("/exchange/%s/questions/%s/placeholder", c.Param("sub"), c.Param("id"))) - }) - r.GET("/exchange/:sub/questions/:id/:title/:answerId", func(c *gin.Context) { - // redirect user to the answer with the title - c.Redirect(302, fmt.Sprintf("/exchange/%s/questions/%s/%s#%s", c.Param("sub"), c.Param("id"), c.Param("title"), c.Param("answerId"))) - }) r.GET("/proxy", routes.GetImage) + r.GET("/version", routes.GetVersion) + + soPingCheck := checks.NewPingCheck("https://stackoverflow.com", "GET", 5000, nil, nil) + sePingCheck := checks.NewPingCheck("https://stackexchange.com", "GET", 5000, nil, nil) + healthcheck.New(r, config.DefaultConfig(), []checks.Check{soPingCheck, sePingCheck}) + r.Run(fmt.Sprintf("%s:%s", host, port)) } diff --git a/public/codecircles.svg b/public/codecircles.svg new file mode 100644 index 0000000..58fd99b --- /dev/null +++ b/public/codecircles.svg @@ -0,0 +1,6 @@ + diff --git a/public/codecircles.webp b/public/codecircles.webp index 7744569..01f747c 100644 Binary files a/public/codecircles.webp and b/public/codecircles.webp differ diff --git a/public/globals.css b/public/globals.css index 72a84a4..1592648 100644 --- a/public/globals.css +++ b/public/globals.css @@ -1,36 +1,67 @@ :root { + --code-bg: #36383d; + --code-fg: #ffffff; +} + +:root, +[data-theme="dark"] { --main-bg: #1b1f26; --text-color: #fff; --muted-text-color: #b3b3b3; - --code-bg: #36383d; --input-bg: #2b303b; --input-bg-hover: #3b404b; - --meta-bg: rgb(82, 82, 98); + --meta-bg: #525262; --divider-color: #42464e; --link-color: #92adff; } -[data-theme='light'] { - --main-bg: rgb(219, 219, 219); +@media (prefers-color-scheme: light) { + :root:not([data-theme="dark"]) { + --main-bg: #dbdbdb; + --text-color: #000; + --muted-text-color: #636363; + --input-bg: #bcbcbc; + --input-bg-hover: #a8a8a8; + --meta-bg: #aaa8a8; + --divider-color: #b5b5b5; + --link-color: #335ad0; + } +} + +[data-theme="light"] { + --main-bg: #dbdbdb; --text-color: #000; --muted-text-color: #636363; - --code-bg: #36383d; - --input-bg: rgb(188, 188, 188); - --input-bg-hover: rgb(168, 168, 168); - --meta-bg: rgb(170, 168, 168); + --input-bg: #bcbcbc; + --input-bg-hover: #a8a8a8; + --meta-bg: #aaa8a8; --divider-color: #b5b5b5; --link-color: #335ad0; } a { color: var(--link-color); + word-wrap: break-word; } html { + margin: auto; + max-width: 40rem; +} + +@media only screen and (max-width: calc(40rem + 2rem)) { + body { + padding-left: 1rem; + padding-right: 1rem; + } +} + +body { + background-color: var(--main-bg); + color: var(--text-color); + font-family: sans-serif; + margin: 0; - padding: 0; - width: 100vw; - height: 100vh; } .icon { diff --git a/public/home.css b/public/home.css index e499a09..d947c81 100644 --- a/public/home.css +++ b/public/home.css @@ -1,21 +1,10 @@ body { - background-color: var(--main-bg); - font-family: sans-serif; - display: flex; - justify-content: center; - align-items: center; - height: 100vh; - width: 100vw; - - margin: 0; - - color: var(--text-color); } .container { - width: 40rem; + margin: auto; } .footer { @@ -44,7 +33,7 @@ body { .view-input:focus { outline: none; - border: 2px solid rgb(168, 168, 168); + border: 2px solid #a8a8a8; } .view-button { @@ -71,7 +60,7 @@ body { } .error { - background-color: rgb(255, 129, 129); + background-color: #ff8181; } .error, @@ -104,10 +93,3 @@ body { width: 2rem; height: 2rem; } - -@media screen and (max-width: 800px) { - body { - padding: 1rem; - box-sizing: border-box; - } -} diff --git a/public/question.css b/public/question.css index ada56f3..a9b8bae 100644 --- a/public/question.css +++ b/public/question.css @@ -1,35 +1,5 @@ body { - margin: 0; - width: 100vw; - height: 100vh; - - overflow-x: hidden; - - background-color: var(--main-bg); - color: var(--text-color); - font-family: sans-serif; - - display: flex; - justify-content: center; - - padding-left: 5rem; - padding-right: 5rem; padding-top: 2rem; - - box-sizing: border-box; -} - -@media (orientation: landscape) { - .parent { - max-width: 50%; - width: fit-content; - } -} -@media (orientation: portrait) { - .parent { - max-width: 90%; - width: fit-content; - } } .header { @@ -55,14 +25,14 @@ code { background-color: var(--code-bg); padding: 0.15rem; border-radius: 5px; - color: white; + color: var(--code-fg); } pre { background-color: var(--code-bg); padding: 1rem; border-radius: 5px; - color: var(--text-color); + color: var(--code-fg); overflow-x: auto; line-height: 1.35; } @@ -162,6 +132,7 @@ img { .answers-header { display: flex; + flex-wrap: wrap; justify-content: space-between; align-items: center; } @@ -195,10 +166,3 @@ img { justify-content: center; align-items: center; } - -@media only screen and (max-width: 800px) { - body { - padding-left: 1rem; - padding-right: 1rem; - } -} diff --git a/src/healthcheck/healthcheck.go b/src/healthcheck/healthcheck.go new file mode 100644 index 0000000..24b2318 --- /dev/null +++ b/src/healthcheck/healthcheck.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + "log" + "net/http" + "os" +) + +func main() { + if len(os.Args) < 2 { + log.Fatal("Expected URL as command-line argument") + os.Exit(1) + } + url := os.Args[1] + fmt.Println(url) + if _, err := http.Get(url); err != nil { + os.Exit(1) + } +} diff --git a/src/middleware/noCache.go b/src/middleware/noCache.go deleted file mode 100644 index 0b5c8a5..0000000 --- a/src/middleware/noCache.go +++ /dev/null @@ -1,12 +0,0 @@ -package middleware - -import "github.com/gin-gonic/gin" - -func NoCacheMiddleware() gin.HandlerFunc { - return func(c *gin.Context) { - c.Header("Cache-Control", "no-cache, no-store, must-revalidate") - c.Header("Pragma", "no-cache") - c.Header("Expires", "0") - c.Next() - } -} diff --git a/src/middleware/options.go b/src/middleware/options.go index 95b9d94..a0fea14 100644 --- a/src/middleware/options.go +++ b/src/middleware/options.go @@ -7,7 +7,6 @@ import ( func OptionsMiddleware() gin.HandlerFunc { return func(c *gin.Context) { c.Set("disable_images", false) - c.Set("theme", "dark") imagesCookie, err := c.Cookie("disable_images") if err == nil { @@ -16,13 +15,6 @@ func OptionsMiddleware() gin.HandlerFunc { } } - themeCookie, err := c.Cookie("theme") - if err == nil { - if themeCookie == "light" { - c.Set("theme", "light") - } - } - c.Next() } } diff --git a/src/middleware/ratelimit.go b/src/middleware/ratelimit.go index bc0bf47..d83c901 100644 --- a/src/middleware/ratelimit.go +++ b/src/middleware/ratelimit.go @@ -47,7 +47,6 @@ func Ratelimit() gin.HandlerFunc { if val.(int) > 30 { c.HTML(429, "home.html", gin.H{ "errorMessage": "You have exceeded the request limit. Please try again in a minute.", - "theme": c.MustGet("theme").(string), "version": config.Version, }) c.Abort() diff --git a/src/routes/home.go b/src/routes/home.go index 5c546cd..78202e1 100644 --- a/src/routes/home.go +++ b/src/routes/home.go @@ -2,6 +2,7 @@ package routes import ( "anonymousoverflow/config" + "anonymousoverflow/src/utils" "fmt" "regexp" "strings" @@ -10,9 +11,10 @@ import ( ) func GetHome(c *gin.Context) { + theme := utils.GetThemeFromEnv() c.HTML(200, "home.html", gin.H{ "version": config.Version, - "theme": c.MustGet("theme").(string), + "theme": theme, }) } @@ -62,7 +64,6 @@ func PostHome(c *gin.Context) { if err := c.ShouldBind(&body); err != nil { c.HTML(400, "home.html", gin.H{ "errorMessage": "Invalid request body", - "theme": c.MustGet("theme").(string), }) return } @@ -70,9 +71,10 @@ func PostHome(c *gin.Context) { translated := translateUrl(body.URL) if translated == "" { + theme := utils.GetThemeFromEnv() c.HTML(400, "home.html", gin.H{ "errorMessage": "Invalid stack overflow/exchange URL", - "theme": c.MustGet("theme").(string), + "theme": theme, }) return } diff --git a/src/routes/options.go b/src/routes/options.go index a665be2..c0c8718 100644 --- a/src/routes/options.go +++ b/src/routes/options.go @@ -2,9 +2,8 @@ package routes import ( "anonymousoverflow/config" + "anonymousoverflow/src/utils" "fmt" - "os" - "strings" "github.com/gin-gonic/gin" ) @@ -19,28 +18,12 @@ func ChangeOptions(c *gin.Context) { text = "enabled" } c.SetCookie("disable_images", fmt.Sprintf("%t", !c.MustGet("disable_images").(bool)), 60*60*24*365*10, "/", "", false, true) + theme := utils.GetThemeFromEnv() c.HTML(200, "home.html", gin.H{ "successMessage": "Images are now " + text, - "theme": c.MustGet("theme").(string), "version": config.Version, + "theme": theme, }) - - case "theme": - text := "dark" - if c.MustGet("theme").(string) == "dark" { - text = "light" - } - - c.SetCookie("theme", text, 60*60*24*365*10, "/", "", false, true) - // get redirect url from query - redirectUrl := c.Query("redirect_url") - - if !strings.HasPrefix(redirectUrl, os.Getenv("APP_URL")) { - redirectUrl = os.Getenv("APP_URL") - } - - c.Redirect(302, redirectUrl) - default: c.String(400, "400 Bad Request") } diff --git a/src/routes/question.go b/src/routes/question.go index f4f99f3..3b6274b 100644 --- a/src/routes/question.go +++ b/src/routes/question.go @@ -34,7 +34,6 @@ func ViewQuestion(c *gin.Context) { if _, err := strconv.Atoi(questionId); err != nil { c.HTML(400, "home.html", gin.H{ "errorMessage": "Invalid question ID", - "theme": c.MustGet("theme").(string), "version": config.Version, }) return @@ -60,7 +59,6 @@ func ViewQuestion(c *gin.Context) { if resp.StatusCode() != 200 { c.HTML(500, "home.html", gin.H{ "errorMessage": fmt.Sprintf("Received a non-OK status code %d", resp.StatusCode()), - "theme": c.MustGet("theme").(string), "version": config.Version, }) return @@ -74,7 +72,6 @@ func ViewQuestion(c *gin.Context) { if err != nil { c.HTML(500, "home.html", gin.H{ "errorMessage": "Unable to parse question data", - "theme": c.MustGet("theme").(string), "version": config.Version, }) return @@ -84,7 +81,6 @@ func ViewQuestion(c *gin.Context) { if err != nil { c.HTML(500, "home.html", gin.H{ "errorMessage": "Failed to extract question data", - "theme": c.MustGet("theme").(string), "version": config.Version, }) return @@ -94,7 +90,6 @@ func ViewQuestion(c *gin.Context) { if err != nil { c.HTML(500, "home.html", gin.H{ "errorMessage": "Failed to extract answer data", - "theme": c.MustGet("theme").(string), "version": config.Version, }) return @@ -106,14 +101,16 @@ func ViewQuestion(c *gin.Context) { imagePolicy = "'self'" } + theme := utils.GetThemeFromEnv() + c.HTML(200, "question.html", gin.H{ "question": newFilteredQuestion, "answers": answers, "imagePolicy": imagePolicy, - "theme": c.MustGet("theme").(string), "currentUrl": fmt.Sprintf("%s%s", os.Getenv("APP_URL"), c.Request.URL.Path), "sortValue": params.SoSortValue, "domain": domain, + "theme": theme, }) } @@ -132,7 +129,6 @@ func parseAndValidateParameters(c *gin.Context) (inputs viewQuestionInputs, err if _, err = strconv.Atoi(questionId); err != nil { c.HTML(400, "home.html", gin.H{ "errorMessage": "Invalid question ID", - "theme": c.MustGet("theme").(string), "version": config.Version, }) return @@ -231,6 +227,8 @@ func extractAnswersData(doc *goquery.Document, domain string) ([]types.FilteredA doc.Find("div.answer").Each(func(i int, s *goquery.Selection) { var answer types.FilteredAnswer + answer.ID = s.AttrOr("data-answerid", "") + postLayout := s.Find("div.post-layout").First() // Extract upvotes. @@ -250,6 +248,8 @@ func extractAnswersData(doc *goquery.Document, domain string) ([]types.FilteredA processedAnswerBody := utils.ProcessHTMLBody(answerBodyHTML) answer.Body = template.HTML(processedAnswerBody) + answer.Comments = utils.FindAndReturnComments(answerBodyHTML, domain, postLayout) + // Extract author information and timestamp. extractAnswerAuthorInfo(s, &answer, domain) diff --git a/src/routes/shortened.go b/src/routes/shortened.go index 9f608f8..494b5bc 100644 --- a/src/routes/shortened.go +++ b/src/routes/shortened.go @@ -4,6 +4,7 @@ import ( "fmt" "net/http" "os" + "strings" "github.com/gin-gonic/gin" "github.com/go-resty/resty/v2" @@ -12,6 +13,7 @@ import ( func RedirectShortenedOverflowURL(c *gin.Context) { id := c.Param("id") answerId := c.Param("answerId") + sub := c.Param("sub") // fetch the stack overflow URL client := resty.New() @@ -21,11 +23,16 @@ func RedirectShortenedOverflowURL(c *gin.Context) { }), ) - resp, err := client.R().Get(fmt.Sprintf("https://www.stackoverflow.com/a/%s/%s", id, answerId)) + domain := "www.stackoverflow.com" + if strings.Contains(sub, ".") { + domain = sub + } else if sub != "" { + domain = fmt.Sprintf("%s.stackexchange.com", sub) + } + resp, err := client.R().Get(fmt.Sprintf("https://%s/a/%s/%s", domain, id, answerId)) if err != nil { c.HTML(400, "home.html", gin.H{ "errorMessage": "Unable to fetch stack overflow URL", - "theme": c.MustGet("theme").(string), }) return } @@ -33,7 +40,6 @@ func RedirectShortenedOverflowURL(c *gin.Context) { if resp.StatusCode() != 302 { c.HTML(400, "home.html", gin.H{ "errorMessage": fmt.Sprintf("Unexpected HTTP status from origin: %d", resp.StatusCode()), - "theme": c.MustGet("theme").(string), }) return } @@ -41,5 +47,10 @@ func RedirectShortenedOverflowURL(c *gin.Context) { // get the redirect URL location := resp.Header().Get("Location") - c.Redirect(302, fmt.Sprintf("%s%s", os.Getenv("APP_URL"), location)) + redirectPrefix := os.Getenv("APP_URL") + if sub != "" { + redirectPrefix += fmt.Sprintf("/exchange/%s", sub) + } + + c.Redirect(302, fmt.Sprintf("%s%s", redirectPrefix, location)) } diff --git a/src/routes/version.go b/src/routes/version.go new file mode 100644 index 0000000..d7dc5c5 --- /dev/null +++ b/src/routes/version.go @@ -0,0 +1,10 @@ +package routes + +import ( + "anonymousoverflow/config" + "github.com/gin-gonic/gin" +) + +func GetVersion(c *gin.Context) { + c.String(200, config.Version) +} diff --git a/src/utils/theme.go b/src/utils/theme.go new file mode 100644 index 0000000..b78d9c4 --- /dev/null +++ b/src/utils/theme.go @@ -0,0 +1,11 @@ +package utils + +import "os" + +func GetThemeFromEnv() string { + theme := os.Getenv("THEME") + if theme == "" { + theme = "auto" + } + return theme +} diff --git a/templates/home.html b/templates/home.html index 2189aca..490039f 100644 --- a/templates/home.html +++ b/templates/home.html @@ -1,81 +1,62 @@ -
-- AnonymousOverflow allows you to view StackOverflow threads - without the cluttered interface and exposing your IP address, - browsing habits and other browser fingerprint data to - StackOverflow. -
- {{ if .successMessage }} -Success: {{ .successMessage }}
-Error: {{ .errorMessage }}
-+ AnonymousOverflow allows you to view StackOverflow threads + without the cluttered interface and exposing your IP address, + browsing habits and other browser fingerprint data to + StackOverflow. +
+ {{ if .successMessage }} +Success: {{ .successMessage }}
+Error: {{ .errorMessage }}
+