From 8feaabb04282728d691976882da056544d6f6174 Mon Sep 17 00:00:00 2001 From: FireMasterK <20838718+FireMasterK@users.noreply.github.com> Date: Mon, 14 Feb 2022 07:35:02 +0000 Subject: [PATCH] Add initial code. --- .dockerignore | 6 ++ .github/workflows/build-docker.yml | 38 ++++++++++ Dockerfile | 24 ++++++ README.md | 10 ++- docker-compose.yml | 8 ++ go.mod | 14 ++++ go.sum | 39 ++++++++++ main.go | 118 +++++++++++++++++++++++++++++ 8 files changed, 256 insertions(+), 1 deletion(-) create mode 100644 .dockerignore create mode 100644 .github/workflows/build-docker.yml create mode 100644 Dockerfile create mode 100644 docker-compose.yml create mode 100644 go.mod create mode 100644 go.sum create mode 100644 main.go diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..4ee019e --- /dev/null +++ b/.dockerignore @@ -0,0 +1,6 @@ +.github/ +.dockerignore +.git +.gitignore +*.md +LICENSE diff --git a/.github/workflows/build-docker.yml b/.github/workflows/build-docker.yml new file mode 100644 index 0000000..2798395 --- /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/piped-instances-api:latest + cache-from: type=gha + cache-to: type=gha,mode=max diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..13bbeb3 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,24 @@ +FROM golang:latest AS build + +WORKDIR /app/ + +COPY go.mod go.sum ./ + +RUN go mod download + +COPY . . + +RUN go build -ldflags "-s -w" main.go + +FROM debian:unstable-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/instances-api + +EXPOSE 3000 +CMD ./instances-api diff --git a/README.md b/README.md index d6f1f92..dbc0d34 100644 --- a/README.md +++ b/README.md @@ -1 +1,9 @@ -# instances-api \ No newline at end of file +# Instances-Api + +## Hosting it yourself + +```bash +docker-compose up -d +``` + +You can now access the API at: http://127.0.0.1:3000 diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000..73f8d5b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,8 @@ +version: '3' + +services: + instances-api: + image: 1337kavin/piped-instances-api + ports: + - "127.0.0.1:3000:3000" + restart: unless-stopped diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..52cc20e --- /dev/null +++ b/go.mod @@ -0,0 +1,14 @@ +module github.com/TeamPiped/instances-api/v2 + +go 1.17 + +require github.com/gofiber/fiber/v2 v2.26.0 + +require ( + github.com/andybalholm/brotli v1.0.4 // indirect + github.com/klauspost/compress v1.14.2 // indirect + github.com/valyala/bytebufferpool v1.0.0 // indirect + github.com/valyala/fasthttp v1.33.0 // indirect + github.com/valyala/tcplisten v1.0.0 // indirect + golang.org/x/sys v0.0.0-20220209214540-3681064d5158 // indirect +) diff --git a/go.sum b/go.sum new file mode 100644 index 0000000..dc17932 --- /dev/null +++ b/go.sum @@ -0,0 +1,39 @@ +github.com/andybalholm/brotli v1.0.2 h1:JKnhI/XQ75uFBTiuzXpzFrUriDPiZjlOSzh6wXogP0E= +github.com/andybalholm/brotli v1.0.2/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= +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.26.0 h1:Awnfqp3fqbZzV3wZWMRJ6Xo2U8X0Ls68M7tXjx52NcM= +github.com/gofiber/fiber/v2 v2.26.0/go.mod h1:7efVWcBOZi1PyMWznnbitjnARPA7nYZxmQXJVod0bo0= +github.com/golang/snappy v0.0.3/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= +github.com/klauspost/compress v1.13.4 h1:0zhec2I8zGnjWcKyLl6i3gPqKANCCn5e9xmviEEeX6s= +github.com/klauspost/compress v1.13.4/go.mod h1:8dP1Hq4DHOhN9w426knH3Rhby4rFm6D8eO+e+Dq5Gzg= +github.com/klauspost/compress v1.14.1/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +github.com/klauspost/compress v1.14.2 h1:S0OHlFk/Gbon/yauFJ4FfJJF5V0fc5HbBTJazi28pRw= +github.com/klauspost/compress v1.14.2/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= +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.32.0 h1:keswgWzyKyNIIjz2a7JmCYHOOIkRp6HMx9oTV6QrZWY= +github.com/valyala/fasthttp v1.32.0/go.mod h1:2rsYD01CKFrjjsvFxx75KlEUNpWNBY9JWD3K/7o2Cus= +github.com/valyala/fasthttp v1.33.0 h1:mHBKd98J5NcXuBddgjvim1i3kWzlng1SzLhrnBOU9g8= +github.com/valyala/fasthttp v1.33.0/go.mod h1:KJRK/MXx0J+yd0c5hlR+s1tIHD72sniU8ZJjl97LIw4= +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-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= +golang.org/x/crypto v0.0.0-20220112180741-5e0467b6c7ce/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +golang.org/x/net v0.0.0-20220111093109-d55c255bac03/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= +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-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E= +golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/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-20220111092808-5a964db01320/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158 h1:rm+CHSpPEEW2IsXUib1ThaHIjuBVZjxNgSKmBLFfD4c= +golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= +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/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..144f758 --- /dev/null +++ b/main.go @@ -0,0 +1,118 @@ +package main + +import ( + "io" + "log" + "net/http" + "regexp" + "strconv" + "strings" + "time" + + "github.com/gofiber/fiber/v2" + "github.com/gofiber/fiber/v2/middleware/etag" +) + +var monitored_instances = []Instance{} + +var number_re = regexp.MustCompile(`(?m)(\d+)`) + +type Instance struct { + Name string `json:"name"` + ApiUrl string `json:"api_url"` + Locations string `json:"locations"` + Cdn bool `json:"cdn"` + Registered int `json:"registered"` + LastChecked int64 `json:"last_checked"` +} + +func monitorInstances() { + // do forever + for { + // send a request to get markdown from GitHub + resp, err := http.Get("https://raw.githubusercontent.com/wiki/TeamPiped/Piped-Frontend/Instances.md") + if err != nil { + log.Print(err) + continue + } + + if resp.StatusCode == 200 { + + // parse the response + buf := new(strings.Builder) + _, err := io.Copy(buf, resp.Body) + + if err != nil { + log.Print(err) + continue + } + + lines := strings.Split(buf.String(), "\n") + + instances := []Instance{} + + skipped := 0 + for _, line := range lines { + split := strings.Split(line, "|") + if len(split) >= 5 { + if skipped < 2 { + skipped++ + continue + } + ApiUrl := strings.TrimSpace(split[1]) + resp, err := http.Get(ApiUrl + "/healthcheck") + if err != nil { + log.Print(err) + continue + } + LastChecked := time.Now().Unix() + if resp.StatusCode != 200 { + continue + } + resp, err = http.Get(ApiUrl + "/registered/badge") + if err != nil { + log.Print(err) + continue + } + registered, err := strconv.ParseInt(number_re.FindString(resp.Request.URL.Path), 10, 32) + if err != nil { + log.Print(err) + continue + } + + instances = append(instances, Instance{ + Name: strings.TrimSpace(split[0]), + ApiUrl: ApiUrl, + Locations: strings.TrimSpace(split[2]), + Cdn: strings.TrimSpace(split[3]) == "Yes", + Registered: int(registered), + LastChecked: LastChecked, + }) + + } + } + + // update the global instances variable + monitored_instances = instances + } + resp.Body.Close() + time.Sleep(time.Minute) + } +} + +func main() { + go monitorInstances() + + app := fiber.New( + fiber.Config{ + Prefork: true, + }, + ) + app.Use(etag.New()) + + app.Get("/", func(c *fiber.Ctx) error { + return c.JSON(monitored_instances) + }) + + app.Listen(":3000") +}