mirror of
https://github.com/TeamPiped/instances-api.git
synced 2024-08-14 23:57:19 +00:00
Merge pull request #44 from Bnyro/main
Parallel instance checks and improved error messages, code cleanup
This commit is contained in:
commit
bb978ea3a3
1 changed files with 192 additions and 114 deletions
306
main.go
306
main.go
|
@ -3,7 +3,8 @@ package main
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/gofiber/fiber/v2"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -11,8 +12,11 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/gofiber/fiber/v2"
|
||||||
|
|
||||||
"github.com/gofiber/fiber/v2/middleware/cors"
|
"github.com/gofiber/fiber/v2/middleware/cors"
|
||||||
"github.com/gofiber/fiber/v2/middleware/etag"
|
"github.com/gofiber/fiber/v2/middleware/etag"
|
||||||
"github.com/google/go-github/v53/github"
|
"github.com/google/go-github/v53/github"
|
||||||
|
@ -40,6 +44,157 @@ type FrontendConfig struct {
|
||||||
S3Enabled bool `json:"s3Enabled"`
|
S3Enabled bool `json:"s3Enabled"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var client = http.Client{
|
||||||
|
Timeout: 10 * time.Second,
|
||||||
|
}
|
||||||
|
|
||||||
|
func testUrl(url string) (*http.Response, error) {
|
||||||
|
resp, err := client.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
if resp.StatusCode != 200 {
|
||||||
|
return resp, errors.New(fmt.Sprintf("Invalid response code at %s: %d", url, resp.StatusCode))
|
||||||
|
}
|
||||||
|
return resp, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func testCaching(ApiUrl string) (bool, error) {
|
||||||
|
resp, err := testUrl(ApiUrl + "/trending?region=US")
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
oldTiming := resp.Header.Get("Server-Timing")
|
||||||
|
resp, err = testUrl(ApiUrl + "/trending?region=US")
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
newTiming := resp.Header.Get("Server-Timing")
|
||||||
|
cacheWorking := oldTiming == newTiming
|
||||||
|
return cacheWorking, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getConfig(ApiUrl string) (FrontendConfig, error) {
|
||||||
|
resp, err := testUrl(ApiUrl + "/config")
|
||||||
|
if err != nil {
|
||||||
|
return FrontendConfig{}, err
|
||||||
|
}
|
||||||
|
bytes, err := io.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return FrontendConfig{}, err
|
||||||
|
}
|
||||||
|
var config FrontendConfig
|
||||||
|
err = json.Unmarshal(bytes, &config)
|
||||||
|
if err != nil {
|
||||||
|
return FrontendConfig{}, err
|
||||||
|
}
|
||||||
|
return config, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getInstanceDetails(split []string, latest string) (Instance, error) {
|
||||||
|
ApiUrl := strings.TrimSpace(split[1])
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
errorChannel := make(chan error)
|
||||||
|
// the amount of tests to do
|
||||||
|
wg.Add(6)
|
||||||
|
|
||||||
|
var lastChecked int64
|
||||||
|
var registered int64
|
||||||
|
var config FrontendConfig
|
||||||
|
var hash string
|
||||||
|
var version string
|
||||||
|
var cacheWorking bool
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
wg.Wait()
|
||||||
|
close(errorChannel)
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
if _, err := testUrl(ApiUrl + "/healthcheck"); err != nil {
|
||||||
|
errorChannel <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
lastChecked = time.Now().Unix()
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
resp, err := testUrl(ApiUrl + "/registered/badge")
|
||||||
|
if err != nil {
|
||||||
|
errorChannel <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
registered, err = strconv.ParseInt(number_re.FindString(resp.Request.URL.Path), 10, 32)
|
||||||
|
if err != nil {
|
||||||
|
errorChannel <- err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
resp, err := testUrl(ApiUrl + "/version")
|
||||||
|
if err != nil {
|
||||||
|
errorChannel <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
buf := new(strings.Builder)
|
||||||
|
_, err = io.Copy(buf, resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
errorChannel <- err
|
||||||
|
return
|
||||||
|
}
|
||||||
|
version = strings.TrimSpace(buf.String())
|
||||||
|
version_split := strings.Split(version, "-")
|
||||||
|
hash = version_split[len(version_split)-1]
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
var err error
|
||||||
|
config, err = getConfig(ApiUrl)
|
||||||
|
if err != nil {
|
||||||
|
errorChannel <- err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
var err error
|
||||||
|
cacheWorking, err = testCaching(ApiUrl)
|
||||||
|
if err != nil {
|
||||||
|
errorChannel <- err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
go func() {
|
||||||
|
defer wg.Done()
|
||||||
|
// check if instance can fetch videos
|
||||||
|
if _, err := testUrl(ApiUrl + "/streams/jNQXAC9IVRw"); err != nil {
|
||||||
|
errorChannel <- err
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
for err := range errorChannel {
|
||||||
|
return Instance{}, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return Instance{
|
||||||
|
Name: strings.TrimSpace(split[0]),
|
||||||
|
ApiUrl: ApiUrl,
|
||||||
|
Locations: strings.TrimSpace(split[2]),
|
||||||
|
Cdn: strings.TrimSpace(split[3]) == "Yes",
|
||||||
|
Registered: int(registered),
|
||||||
|
LastChecked: lastChecked,
|
||||||
|
Version: version,
|
||||||
|
UpToDate: strings.Contains(latest, hash),
|
||||||
|
Cache: cacheWorking,
|
||||||
|
S3Enabled: config.S3Enabled,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
||||||
func monitorInstances() {
|
func monitorInstances() {
|
||||||
ctx := context.Background()
|
ctx := context.Background()
|
||||||
var tc *http.Client
|
var tc *http.Client
|
||||||
|
@ -76,7 +231,6 @@ func monitorInstances() {
|
||||||
}
|
}
|
||||||
|
|
||||||
if resp.StatusCode == 200 {
|
if resp.StatusCode == 200 {
|
||||||
|
|
||||||
// parse the response
|
// parse the response
|
||||||
buf := new(strings.Builder)
|
buf := new(strings.Builder)
|
||||||
_, err := io.Copy(buf, resp.Body)
|
_, err := io.Copy(buf, resp.Body)
|
||||||
|
@ -88,124 +242,45 @@ func monitorInstances() {
|
||||||
|
|
||||||
lines := strings.Split(buf.String(), "\n")
|
lines := strings.Split(buf.String(), "\n")
|
||||||
|
|
||||||
instances := []Instance{}
|
instancesMap := make(map[int]Instance)
|
||||||
|
|
||||||
|
wg := sync.WaitGroup{}
|
||||||
|
|
||||||
skipped := 0
|
skipped := 0
|
||||||
|
checking := 0
|
||||||
for _, line := range lines {
|
for _, line := range lines {
|
||||||
split := strings.Split(line, "|")
|
split := strings.Split(line, "|")
|
||||||
if len(split) >= 5 {
|
|
||||||
if skipped < 2 {
|
if len(split) < 5 {
|
||||||
skipped++
|
continue
|
||||||
continue
|
}
|
||||||
}
|
|
||||||
ApiUrl := strings.TrimSpace(split[1])
|
// skip first two table lines
|
||||||
resp, err := http.Get(ApiUrl + "/healthcheck")
|
if skipped < 2 {
|
||||||
if err != nil {
|
skipped++
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
wg.Add(1)
|
||||||
|
go func(i int, split []string) {
|
||||||
|
defer wg.Done()
|
||||||
|
instance, err := getInstanceDetails(split, latest)
|
||||||
|
if err == nil {
|
||||||
|
instancesMap[i] = instance
|
||||||
|
} else {
|
||||||
log.Print(err)
|
log.Print(err)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
LastChecked := time.Now().Unix()
|
}(checking, split)
|
||||||
if resp.StatusCode != 200 {
|
checking++
|
||||||
continue
|
}
|
||||||
}
|
wg.Wait()
|
||||||
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
|
|
||||||
}
|
|
||||||
resp, err = http.Get(ApiUrl + "/version")
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
buf := new(strings.Builder)
|
|
||||||
_, err = io.Copy(buf, resp.Body)
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
version := strings.TrimSpace(buf.String())
|
|
||||||
version_split := strings.Split(version, "-")
|
|
||||||
hash := version_split[len(version_split)-1]
|
|
||||||
|
|
||||||
resp, err = http.Get(ApiUrl + "/config")
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
bytes, err := io.ReadAll(resp.Body)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
var config FrontendConfig
|
|
||||||
|
|
||||||
err = json.Unmarshal(bytes, &config)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
cache_working := false
|
|
||||||
|
|
||||||
resp, err = http.Get(ApiUrl + "/trending?region=US")
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if resp.StatusCode == 200 {
|
|
||||||
old_timing := resp.Header.Get("Server-Timing")
|
|
||||||
resp, err = http.Get(ApiUrl + "/trending?region=US")
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if resp.StatusCode == 200 {
|
|
||||||
new_timing := resp.Header.Get("Server-Timing")
|
|
||||||
if old_timing == new_timing {
|
|
||||||
cache_working = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if instance can fetch videos
|
|
||||||
resp, err = http.Get(ApiUrl + "/streams/jNQXAC9IVRw")
|
|
||||||
if err != nil {
|
|
||||||
log.Print(err)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if resp.StatusCode != 200 {
|
|
||||||
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,
|
|
||||||
Version: version,
|
|
||||||
UpToDate: strings.Contains(latest, hash),
|
|
||||||
Cache: cache_working,
|
|
||||||
S3Enabled: config.S3Enabled,
|
|
||||||
})
|
|
||||||
|
|
||||||
|
// Map to ordered array
|
||||||
|
var instances []Instance
|
||||||
|
for i := 0; i < checking; i++ {
|
||||||
|
instance, ok := instancesMap[i]
|
||||||
|
if ok {
|
||||||
|
instances = append(instances, instance)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -228,5 +303,8 @@ func main() {
|
||||||
return c.JSON(monitored_instances)
|
return c.JSON(monitored_instances)
|
||||||
})
|
})
|
||||||
|
|
||||||
app.Listen(":3000")
|
err := app.Listen(":3000")
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue