From 5a9d202f0ddd02b5e751c61f472a5ca8f3cefe3d Mon Sep 17 00:00:00 2001 From: Deerain <1deerain1@gmial.com> Date: Thu, 29 Oct 2026 01:43:13 +0300 Subject: [PATCH] write util for parse p2go service --- utils/parser.go | 141 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) create mode 100644 utils/parser.go diff --git a/utils/parser.go b/utils/parser.go new file mode 100644 index 0000000..4e6a16a --- /dev/null +++ b/utils/parser.go @@ -0,0 +1,141 @@ +// !!!ВНИМАНИЕ!!! +// Прошу не запускать часто, +// чтобы не достовлять неудобств сервису + +package main + +import ( + "bytes" + "context" + "encoding/json" + "fmt" + "io" + "log/slog" + "net/http" + "os" + "strings" + "sync" + "time" +) + +const ( + TIMEOUT int = 5 + BASE_URL string = "https://play2go.cloud" + SLEEP int = 5 + OUT_FOLDER string = "./" +) + +type JSON string + +type LinkForParse struct { + Url string + Method string +} + +func (l LinkForParse) String() string { + return fmt.Sprintf("%s %s", strings.ToUpper(l.Method), l.Url) +} + +var parse_links = []LinkForParse{ + {"/api/users/me", http.MethodGet}, +} + +func main() { + ctx, cancel := context.WithCancel(context.Background()) + defer cancel() + + var wg sync.WaitGroup + + token := os.Getenv("ACCESS_TOKEN") + resultChan := make(chan JSON, 1) + + wg.Add(1) + go func() { + defer wg.Done() + defer close(resultChan) + parseProccess(ctx, token, TIMEOUT, parse_links, SLEEP, resultChan) + }() + + wg.Add(1) + go func() { + defer wg.Done() + for result := range resultChan { + slog.Debug("parsed", "data", result) + } + }() + + wg.Wait() + slog.Info("All proccessed finished successfully") +} + +func parseProccess(ctx context.Context, token string, timeout int, links []LinkForParse, sleep int, result chan<- JSON) { + if ctx.Err() != nil { + slog.WarnContext(ctx, "parsing stopped") + } + + for i, link := range parse_links { + parsed, err := parse(ctx, link, token, timeout, nil) + if err != nil { + slog.ErrorContext(ctx, "failed to parse", "link", link.String(), "error", err.Error()) + continue + } + + select { + case result <- parsed: + case <-ctx.Done(): + slog.WarnContext(ctx, "failed to send result: context canceled") + return + } + + if sleep > 0 && i < len(links)-1 { + select { + case <-time.After(time.Duration(timeout) * time.Second): + case <-ctx.Done(): + slog.WarnContext(ctx, "sleep interuppted by context cancellation") + return + } + } + } +} + +func parse(ctx context.Context, link LinkForParse, token string, timeout int, data any) (JSON, error) { + var reader io.Reader + tctx, cancel := context.WithTimeout(ctx, time.Duration(timeout)*time.Second) + defer cancel() + + if data != nil { + d, err := json.Marshal(reader) + if err != nil { + return "", fmt.Errorf("failed to encode: %w", err) + } + reader = bytes.NewReader(d) + } + + fullUrl := BASE_URL + link.Url + req, err := http.NewRequestWithContext(tctx, link.Method, fullUrl, reader) + if err != nil { + return "", fmt.Errorf("failed to create request: %w", err) + } + req.Header.Set("Authorization", fmt.Sprintf("Brarer %s", token)) + req.Header.Set("Accept", "application/json") + if reader != nil { + req.Header.Set("Content-Type", "application/json") + } + + resp, err := http.DefaultClient.Do(req) + if err != nil { + return "", fmt.Errorf("failed to send request: %w", err) + } + defer resp.Body.Close() + + if resp.StatusCode < 200 || resp.StatusCode >= 300 { + return "", fmt.Errorf("http error: %v", resp.StatusCode) + } + + bodyData, err := io.ReadAll(resp.Body) + if err != nil { + return "", fmt.Errorf("failed to read body: %w", err) + } + + return JSON(bodyData), nil +}