diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000..2c7d170 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,7 @@ +version: 2 +updates: + # Maintain dependencies for GitHub Actions + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml new file mode 100644 index 0000000..019138d --- /dev/null +++ b/.github/workflows/build-docker.yml @@ -0,0 +1,38 @@ +name: Docker Multi-Architecture Build + +on: + push: + paths-ignore: + - "**.md" + branches: + - main + +jobs: + build-docker: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v2 + - name: Set up QEMU + uses: docker/setup-qemu-action@v1 + with: + platforms: all + - name: Set up Docker Buildx + id: buildx + uses: docker/setup-buildx-action@v1 + with: + version: latest + - name: Login to DockerHub + uses: docker/login-action@v1 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + - name: Build and push + uses: docker/build-push-action@v2 + with: + context: . + file: ./Dockerfile + platforms: linux/386,linux/amd64,linux/arm/v6,linux/arm/v7,linux/arm64/v8 + push: true + tags: 1337kavin/ryd-proxy:latest + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..66fd13c --- /dev/null +++ b/.gitignore @@ -0,0 +1,15 @@ +# Binaries for programs and plugins +*.exe +*.exe~ +*.dll +*.so +*.dylib + +# Test binary, built with `go test -c` +*.test + +# Output of the go coverage tool, specifically when used with LiteIDE +*.out + +# Dependency directories (remove the comment below to include it) +# vendor/ diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..4ac5023 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,21 @@ +FROM golang:latest AS build + +WORKDIR /app/ + +COPY . . + +RUN --mount=type=cache,target=/root/.cache/go-build \ + go build -ldflags "-s -w" main.go + +FROM debian:stable-slim + +RUN apt-get update && apt-get install -y --no-install-recommends \ + ca-certificates \ + && rm -rf /var/lib/apt/lists/* + +WORKDIR /app/ + +COPY --from=build /app/main /app/ryd-proxy + +EXPOSE 3000 +CMD ./ryd-proxy diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..0bca4e2 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,13 @@ +services: + tor-proxy: + image: 1337kavin/alpine-tor:latest + restart: unless-stopped + environment: + - tors=15 + ryd-proxy: + image: 1337kavin/ryd-proxy:latest + restart: unless-stopped + depends_on: + - tor-proxy + ports: + - "127.0.0.1:3000:3000" diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..66f9bf3 --- /dev/null +++ b/go.mod @@ -0,0 +1,13 @@ +module github.com/TeamPiped/RYD-Proxy/v2 + +go 1.18 + +require ( + github.com/andybalholm/brotli v1.0.4 // indirect + github.com/gofiber/fiber/v2 v2.34.1 // indirect + github.com/klauspost/compress v1.15.6 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.37.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..e24e04d --- /dev/null +++ b/go.sum @@ -0,0 +1,28 @@ +github.com/andybalholm/brotli v1.0.4 h1:V7DdXeJtZscaqfNuAdSRuRFzuiKlHSC/Zh3zl9qY3JY= +github.com/andybalholm/brotli v1.0.4/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig= +github.com/gofiber/fiber/v2 v2.34.1 h1:C6saXB7385HvtXX+XMzc5Dqj5S/aEXOfKCW7JNep4rA= +github.com/gofiber/fiber/v2 v2.34.1/go.mod h1:ozRQfS+D7EL1+hMH+gutku0kfx1wLX4hAxDCtDzpj4U= +github.com/klauspost/compress v1.15.0/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.15.6 h1:6D9PcO8QWu0JyaQ2zUMmu16T1T+zjjEpP91guRsvDfY= +github.com/klauspost/compress v1.15.6/go.mod h1:PhcZ0MbTNciWF3rruxRgKxI5NkcHHrHUDtV4Yw2GlzU= +github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= +github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= +github.com/valyala/fasthttp v1.37.0 h1:7WHCyI7EAkQMVmrfBhWTCOaeROb1aCBiTopx63LkMbE= +github.com/valyala/fasthttp v1.37.0/go.mod h1:t/G+3rLek+CyY9bnIE+YlMRddxVAAGjhxndDB4i4C0I= +github.com/valyala/tcplisten v1.0.0 h1:rBHj/Xf+E1tRGZyWIWwJDiRY0zc1Js+CV5DqwacVSA8= +github.com/valyala/tcplisten v1.0.0/go.mod h1:T0xQ8SeCZGxckz9qRXTfG43PvQ/mcWh7FwZEA7Ioqkc= +golang.org/x/crypto v0.0.0-20220214200702-86341886e292/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220225172249-27dd8689420f/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/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-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220227234510-4e6760a101f9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c h1:aFV+BgZ4svzjfabn8ERpuB4JI4N6/rdy1iusx77G3oU= +golang.org/x/sys v0.0.0-20220615213510-4f61da869c0c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= +golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= diff --git a/main.go b/main.go new file mode 100644 index 0000000..7d5a796 --- /dev/null +++ b/main.go @@ -0,0 +1,104 @@ +package main + +import ( + "compress/gzip" + "io" + "log" + "net" + "net/http" + "net/url" + "os" + "regexp" + "time" + + "github.com/andybalholm/brotli" + "github.com/gofiber/fiber/v2" +) + +var client *http.Client + +func main() { + + proxy := os.Getenv("PROXY") + + if proxy == "" { + proxy = "socks5://tor-proxy:5566" + } + + proxyUrl, _ := url.Parse(proxy) + + client = &http.Client{ + Transport: &http.Transport{ + Dial: (&net.Dialer{ + Timeout: 30 * time.Second, + KeepAlive: 30 * time.Second, + }).Dial, + TLSHandshakeTimeout: 10 * time.Second, + ResponseHeaderTimeout: 20 * time.Second, + ExpectContinueTimeout: 1 * time.Second, + IdleConnTimeout: 30 * time.Second, + ForceAttemptHTTP2: true, + MaxConnsPerHost: 0, + MaxIdleConnsPerHost: 10, + MaxIdleConns: 0, + Proxy: http.ProxyURL(proxyUrl), + }, + } + + app := fiber.New( + fiber.Config{ + Prefork: true, + }, + ) + + app.Get("/votes/:videoId", handler) + + log.Fatal(app.Listen(":3000")) +} + +func handler(c *fiber.Ctx) error { + + videoId := c.Params("videoId") + + match, _ := regexp.Match("^([a-zA-Z0-9_-]{11})", []byte(videoId)) + + if !match { + return c.Status(400).SendString("Invalid video id") + } + + for true { + req, _ := http.NewRequest("GET", "https://returnyoutubedislikeapi.com/Votes?videoId="+videoId, nil) + + req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0") + req.Header.Add("Accept", "application/json") + req.Header.Add("Accept-Language", "en-US,en;q=0.5") + req.Header.Add("Accept-Encoding", "gzip, deflate, br") + req.Header.Add("Connection", "keep-alive") + req.Header.Add("Sec-Fetch-Dest", "empty") + req.Header.Add("Sec-Fetch-Mode", "cors") + req.Header.Add("Sec-Fetch-Site", "same-origin") + + resp, err := client.Do(req) + + if err != nil || resp.StatusCode == 429 { + continue + } + + ce := resp.Header.Get("Content-Encoding") + + var stream io.Reader + + if ce == "gzip" { + stream, _ = gzip.NewReader(resp.Body) + } else if ce == "br" { + stream = brotli.NewReader(resp.Body) + } else { + stream = resp.Body + } + + return c.Status(resp.StatusCode).SendStream(stream) + } + + // Should never be reached + return nil +}