mirror of
https://github.com/httpjamesm/AnonymousOverflow.git
synced 2024-12-06 19:16:43 +01:00
Compare commits
40 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 3d7129a01f | |||
| 20dd62726c | |||
| 4641b5f0a3 | |||
| 6d6fd3c560 | |||
| ff49961c02 | |||
| 8d63054f17 | |||
| 9cc07387ae | |||
| 262aa01568 | |||
| f4ecc9be6a | |||
| 669187dd4d | |||
| 9e806186b7 | |||
| 2ef7e05f4b | |||
| 4760681c55 | |||
| 6495e4a4bd | |||
| 9a6a044d20 | |||
| 7201269609 | |||
| a666e02256 | |||
| 2fe61471fb | |||
| 4e8a7d3553 | |||
| 2bbed5606d | |||
| dbbc9570db | |||
| 37d28dd704 | |||
| 236eb849e4 | |||
| ee5f4eb4b6 | |||
| 975ed51726 | |||
| 5b8e6acf9e | |||
| 92b8707882 | |||
| c95c2d74b3 | |||
| 296b30323a | |||
| 225420029e | |||
| 6736b6440c | |||
| 7dc9856643 | |||
| 5bc43af96d | |||
| 2afecd8ae7 | |||
| bdca47a51e | |||
| 51190f8d69 | |||
| bfa19bc2d2 | |||
| 55b06b986b | |||
| 09de9f11a5 | |||
| 63e9792d2a |
@@ -0,0 +1,44 @@
|
||||
root = "."
|
||||
testdata_dir = "testdata"
|
||||
tmp_dir = "tmp"
|
||||
|
||||
[build]
|
||||
args_bin = []
|
||||
bin = "./tmp/main"
|
||||
cmd = "go build -o ./tmp/main ."
|
||||
delay = 0
|
||||
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
|
||||
exclude_file = []
|
||||
exclude_regex = ["_test.go"]
|
||||
exclude_unchanged = false
|
||||
follow_symlink = false
|
||||
full_bin = ""
|
||||
include_dir = []
|
||||
include_ext = ["go", "tpl", "tmpl", "html"]
|
||||
include_file = []
|
||||
kill_delay = "0s"
|
||||
log = "build-errors.log"
|
||||
poll = false
|
||||
poll_interval = 0
|
||||
rerun = false
|
||||
rerun_delay = 500
|
||||
send_interrupt = false
|
||||
stop_on_error = false
|
||||
|
||||
[color]
|
||||
app = ""
|
||||
build = "yellow"
|
||||
main = "magenta"
|
||||
runner = "green"
|
||||
watcher = "cyan"
|
||||
|
||||
[log]
|
||||
main_only = false
|
||||
time = false
|
||||
|
||||
[misc]
|
||||
clean_on_exit = false
|
||||
|
||||
[screen]
|
||||
clear_on_rebuild = false
|
||||
keep_scroll = true
|
||||
@@ -0,0 +1,47 @@
|
||||
name: Create and publish a Docker image
|
||||
|
||||
# Configures this workflow to run every time a change is pushed to the branch called `release`.
|
||||
on:
|
||||
push:
|
||||
branches: ['release']
|
||||
|
||||
# Defines two custom environment variables for the workflow. These are used for the Container registry domain, and a name for the Docker image that this workflow builds.
|
||||
env:
|
||||
REGISTRY: ghcr.io
|
||||
IMAGE_NAME: ${{ github.repository }}
|
||||
|
||||
# There is a single job in this workflow. It's configured to run on the latest available version of Ubuntu.
|
||||
jobs:
|
||||
build-and-push-image:
|
||||
runs-on: ubuntu-latest
|
||||
# Sets the permissions granted to the `GITHUB_TOKEN` for the actions in this job.
|
||||
permissions:
|
||||
contents: read
|
||||
packages: write
|
||||
#
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
# 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
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
# 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
|
||||
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
|
||||
with:
|
||||
context: .
|
||||
push: true
|
||||
tags: ${{ steps.meta.outputs.tags }}
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
+2
-1
@@ -1,4 +1,5 @@
|
||||
.env
|
||||
docker-compose.yml
|
||||
.DS_Store
|
||||
*bin
|
||||
*bin
|
||||
/tmp
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"trailingComma": "es5",
|
||||
"tabWidth": 4,
|
||||
"semi": false,
|
||||
"singleQuote": true
|
||||
}
|
||||
+14
-9
@@ -1,19 +1,24 @@
|
||||
FROM golang:1.18-alpine
|
||||
|
||||
RUN apk add musl-dev
|
||||
RUN apk add libc-dev
|
||||
RUN apk add gcc
|
||||
FROM golang:1.19-alpine as build
|
||||
|
||||
WORKDIR /app
|
||||
|
||||
COPY go.mod ./
|
||||
COPY go.sum ./
|
||||
COPY go.mod .
|
||||
COPY go.sum .
|
||||
|
||||
RUN go mod download
|
||||
|
||||
COPY ./ /app
|
||||
COPY . .
|
||||
|
||||
RUN go build -o /anonymousoverflow
|
||||
ENV CGO_ENABLED=0
|
||||
|
||||
RUN go build -o anonymousoverflow
|
||||
|
||||
FROM scratch
|
||||
|
||||
COPY --from=build /app/anonymousoverflow /anonymousoverflow
|
||||
COPY templates /templates
|
||||
COPY public /public
|
||||
COPY --from=build /etc/ssl/certs /etc/ssl/certs
|
||||
|
||||
EXPOSE 8080
|
||||
|
||||
|
||||
@@ -14,25 +14,38 @@ This project is super lightweight by design. The UI is simple and the frontend i
|
||||
|
||||
## Clearnet Instances
|
||||
|
||||
| Instance URL | Region | Notes |
|
||||
| ------------------------------------------------------------------------------- | ----------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| Instance URL | Region | Notes |
|
||||
| ------------------------------------------------------------------------------- | ------------------------------- | ------------------------------------------------------------------------------------------------ |
|
||||
| [code.whatever.social](https://code.whatever.social) | United States & The Netherlands | Operated by [Whatever Social](https://whatever.social) and [http.james](https://httpjames.space) |
|
||||
| [overflow.777.tf](https://overflow.777.tf/) | The Netherlands | Operated by [Jae](https://777.tf) |
|
||||
| [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) |
|
||||
| [anonymousoverflow.esmailelbob.xyz](https://anonymousoverflow.esmailelbob.xyz/) | Canada | Operated by [Esmail EL BoB](https://esmailelbob.xyz) |
|
||||
| [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/) |
|
||||
| [ao.foss.wtf](https://ao.foss.wtf) | Germany | Operated by [foss.wtf](https://foss.wtf) |
|
||||
| [overflow.hostux.net](https://overflow.hostux.net/) | France | Operated by [Hostux](https://hostux.net/) |
|
||||
| [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.bloatcat.tk](https://ao.bloatcat.tk) | Iceland | Operated by [bloatcat.tk](https://bloatcat.tk) |
|
||||
| [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)|
|
||||
|
||||
|
||||
## 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) |
|
||||
| [anonymousoverflow.esmail5pdn24shtvieloeedh7ehz3nrwcdivnfhfcedl7gf4kwddhkqd.onion](http://anonymousoverflow.esmail5pdn24shtvieloeedh7ehz3nrwcdivnfhfcedl7gf4kwddhkqd.onion) | Canada | Operated by [Esmail EL BoB](https://esmailelbob.xyz) |
|
||||
| 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/) |
|
||||
|
||||
## Why use AnonymousOverflow over StackOverflow?
|
||||
|
||||
@@ -59,7 +72,9 @@ StackOverflow has a cluttered UI that might distract you from the content you're
|
||||
|
||||
## How to make Stack Overflow links take you to AnonymousOverflow automatically
|
||||
|
||||
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 go to AnonymousOverflow.
|
||||
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.
|
||||
|
||||
## How it works
|
||||
|
||||
@@ -85,8 +100,8 @@ You can easily convert StackOverflow URLs to AnonymousOverflow ones by adding th
|
||||
javascript: (function () {
|
||||
window.location = window.location
|
||||
.toString()
|
||||
.replace(/stackoverflow\.com/, "code.whatever.social");
|
||||
})();
|
||||
.replace(/stackoverflow\.com/, 'code.whatever.social')
|
||||
})()
|
||||
```
|
||||
|
||||
Replace `code.whatever.social` with the domain name of the instance you're using if needed.
|
||||
|
||||
+1
-1
@@ -1,3 +1,3 @@
|
||||
package config
|
||||
|
||||
var Version = "1.8.1"
|
||||
var Version = "1.9.0"
|
||||
|
||||
@@ -7,6 +7,8 @@ require (
|
||||
github.com/alecthomas/chroma v0.10.0
|
||||
github.com/gin-gonic/gin v1.8.2
|
||||
github.com/go-resty/resty/v2 v2.7.0
|
||||
github.com/golang-jwt/jwt/v4 v4.4.3
|
||||
github.com/joho/godotenv v1.4.0
|
||||
)
|
||||
|
||||
require (
|
||||
@@ -17,8 +19,6 @@ require (
|
||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
||||
github.com/go-playground/validator/v10 v10.11.1 // indirect
|
||||
github.com/goccy/go-json v0.10.0 // indirect
|
||||
github.com/golang-jwt/jwt/v4 v4.4.3 // indirect
|
||||
github.com/joho/godotenv v1.4.0 // indirect
|
||||
github.com/json-iterator/go v1.1.12 // indirect
|
||||
github.com/leodido/go-urn v1.2.1 // indirect
|
||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
||||
@@ -27,9 +27,9 @@ require (
|
||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
||||
github.com/ugorji/go/codec v1.2.8 // indirect
|
||||
golang.org/x/crypto v0.4.0 // indirect
|
||||
golang.org/x/net v0.4.0 // indirect
|
||||
golang.org/x/sys v0.3.0 // indirect
|
||||
golang.org/x/text v0.5.0 // indirect
|
||||
golang.org/x/net v0.7.0 // indirect
|
||||
golang.org/x/sys v0.5.0 // indirect
|
||||
golang.org/x/text v0.7.0 // indirect
|
||||
google.golang.org/protobuf v1.28.1 // indirect
|
||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||
)
|
||||
|
||||
@@ -80,20 +80,20 @@ golang.org/x/crypto v0.4.0/go.mod h1:3quD/ATkf6oY+rnes5c3ExXTbLc8mueNue5/DoinL80
|
||||
golang.org/x/net v0.0.0-20210916014120-12bc252f5db8/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.4.0 h1:Q5QPcMlvfxFTAPV0+07Xz/MpK9NTXu2VDUuy0FeMfaU=
|
||||
golang.org/x/net v0.4.0/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE=
|
||||
golang.org/x/net v0.7.0 h1:rJrUqqhjsgNp7KqAIc25s9pZnjU7TUcSY7HcVZjdn1g=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
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-20210806184541-e5e7981a1069/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 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ=
|
||||
golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0 h1:MUK/U/4lj1t1oPg0HfuXDN/Z1wv31ZJ/YcPiGccS4DU=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
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.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM=
|
||||
golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
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/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
|
||||
@@ -50,6 +50,8 @@ func main() {
|
||||
r.GET("/", routes.GetHome)
|
||||
r.POST("/", routes.PostHome)
|
||||
|
||||
r.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")))
|
||||
|
||||
+3
-4
@@ -10,7 +10,7 @@
|
||||
--link-color: #92adff;
|
||||
}
|
||||
|
||||
[data-theme="light"] {
|
||||
[data-theme='light'] {
|
||||
--main-bg: rgb(219, 219, 219);
|
||||
--text-color: #000;
|
||||
--muted-text-color: #636363;
|
||||
@@ -26,7 +26,6 @@ a {
|
||||
color: var(--link-color);
|
||||
}
|
||||
|
||||
|
||||
html {
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
@@ -45,9 +44,9 @@ html {
|
||||
.icon img {
|
||||
background: white;
|
||||
border-radius: 50%;
|
||||
padding: .25rem;
|
||||
padding: 0.25rem;
|
||||
}
|
||||
|
||||
details {
|
||||
cursor: pointer;
|
||||
}
|
||||
}
|
||||
|
||||
+25
-5
@@ -19,9 +19,17 @@ body {
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.parent {
|
||||
max-width: 90%;
|
||||
width: fit-content;
|
||||
@media (orientation: landscape) {
|
||||
.parent {
|
||||
max-width: 50%;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
@media (orientation: portrait) {
|
||||
.parent {
|
||||
max-width: 90%;
|
||||
width: fit-content;
|
||||
}
|
||||
}
|
||||
|
||||
.header {
|
||||
@@ -31,7 +39,7 @@ body {
|
||||
|
||||
.card-tags {
|
||||
display: flex;
|
||||
gap: .5rem;
|
||||
gap: 0.5rem;
|
||||
}
|
||||
|
||||
.card-tags .tag {
|
||||
@@ -94,7 +102,7 @@ img {
|
||||
margin-bottom: 1rem;
|
||||
background-color: var(--meta-bg);
|
||||
color: var(--text-color);
|
||||
|
||||
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
@@ -140,6 +148,18 @@ img {
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
.s-notice .d-flex {
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.s-notice .mr8 {
|
||||
margin-right: 1rem;
|
||||
}
|
||||
|
||||
.s-notice svg {
|
||||
height: 1rem;
|
||||
}
|
||||
|
||||
.answers-header {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
|
||||
+6
-2
@@ -35,10 +35,14 @@ func PostHome(c *gin.Context) {
|
||||
|
||||
soLink := body.URL
|
||||
|
||||
// remove the www.
|
||||
soLink = strings.ReplaceAll(soLink, "www.", "")
|
||||
|
||||
// validate URL
|
||||
isStackOverflow := strings.HasPrefix(soLink, "https://stackoverflow.com/questions/")
|
||||
isShortenedStackOverflow := strings.HasPrefix(soLink, "https://stackoverflow.com/a/")
|
||||
isStackExchange := stackExchangeRegex.MatchString(soLink)
|
||||
if !isStackExchange && !isStackOverflow {
|
||||
if !isStackExchange && !isStackOverflow && !isShortenedStackOverflow {
|
||||
c.HTML(400, "home.html", gin.H{
|
||||
"errorMessage": "Invalid stack overflow/exchange URL",
|
||||
"theme": c.MustGet("theme").(string),
|
||||
@@ -47,7 +51,7 @@ func PostHome(c *gin.Context) {
|
||||
}
|
||||
|
||||
// if stack overflow, trim https://stackoverflow.com
|
||||
if isStackOverflow {
|
||||
if isStackOverflow || isShortenedStackOverflow {
|
||||
c.Redirect(302, strings.TrimPrefix(soLink, "https://stackoverflow.com"))
|
||||
return
|
||||
}
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package routes
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
|
||||
"github.com/gin-gonic/gin"
|
||||
"github.com/go-resty/resty/v2"
|
||||
)
|
||||
|
||||
func RedirectShortenedOverflowURL(c *gin.Context) {
|
||||
id := c.Param("id")
|
||||
|
||||
// fetch the stack overflow URL
|
||||
client := resty.New()
|
||||
client.SetRedirectPolicy(
|
||||
resty.RedirectPolicyFunc(func(req *http.Request, via []*http.Request) error {
|
||||
return http.ErrUseLastResponse
|
||||
}),
|
||||
)
|
||||
|
||||
resp, err := client.R().Get(fmt.Sprintf("https://www.stackoverflow.com/a/%s", id))
|
||||
if err != nil {
|
||||
c.HTML(400, "home.html", gin.H{
|
||||
"errorMessage": "Unable to fetch stack overflow URL",
|
||||
"theme": c.MustGet("theme").(string),
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// get the redirect URL
|
||||
location := resp.Header().Get("Location")
|
||||
|
||||
c.Redirect(302, fmt.Sprintf("%s%s", os.Getenv("APP_URL"), location))
|
||||
}
|
||||
+16
-7
@@ -6,6 +6,7 @@ import (
|
||||
"os"
|
||||
"regexp"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/golang-jwt/jwt/v4"
|
||||
@@ -14,20 +15,28 @@ import (
|
||||
var imgTagRegex = regexp.MustCompile(`<img[^>]*\s+src\s*=\s*"(.*?)"[^>]*>`)
|
||||
|
||||
func ReplaceImgTags(inHtml string) string {
|
||||
// find all img tags
|
||||
imgTags := imgTagRegex.FindAllString(inHtml, -1)
|
||||
|
||||
var wg sync.WaitGroup
|
||||
var mu sync.Mutex
|
||||
|
||||
for _, imgTag := range imgTags {
|
||||
// parse the src="" attribute
|
||||
srcRegex := regexp.MustCompile(`src\s*=\s*"(.*?)"`)
|
||||
src := srcRegex.FindStringSubmatch(imgTag)[1]
|
||||
wg.Add(1)
|
||||
go func(imgTag string) {
|
||||
defer wg.Done()
|
||||
srcRegex := regexp.MustCompile(`src\s*=\s*"(.*?)"`)
|
||||
src := srcRegex.FindStringSubmatch(imgTag)[1]
|
||||
|
||||
authToken, _ := generateImageProxyAuth(src)
|
||||
authToken, _ := generateImageProxyAuth(src)
|
||||
|
||||
// replace the img tag with a proxied url
|
||||
inHtml = strings.Replace(inHtml, imgTag, fmt.Sprintf(`<img src="%s/proxy?auth=%s">`, os.Getenv("APP_URL"), authToken), 1)
|
||||
mu.Lock()
|
||||
defer mu.Unlock()
|
||||
inHtml = strings.Replace(inHtml, imgTag, fmt.Sprintf(`<img src="%s/proxy?auth=%s">`, os.Getenv("APP_URL"), authToken), 1)
|
||||
}(imgTag)
|
||||
}
|
||||
|
||||
wg.Wait()
|
||||
|
||||
return inHtml
|
||||
}
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<!DOCTYPE html>
|
||||
<html data-theme="{{ .theme }}">
|
||||
<head>
|
||||
<title>{{ .question.Title }}</title>
|
||||
<title>{{ .question.Title }} | AnonymousOverflow</title>
|
||||
<link rel="stylesheet" href="/static/question.css" />
|
||||
<link rel="stylesheet" href="/static/syntax.css" />
|
||||
<link rel="stylesheet" href="/static/comments.css" />
|
||||
|
||||
Reference in New Issue
Block a user