-
Notifications
You must be signed in to change notification settings - Fork 0
Add multi-user monitoring, proxy support, and authentication #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,83 @@ | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| package main | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| import ( | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "fmt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "log" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "net/http" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "os" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/anaminus/rbxauth" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| const cookieFilename = "/data/cookies.txt" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func testAuth() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cfg := &rbxauth.Config{} | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cookies, err := loadCookiesFromFile() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err == nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // If cookies are successfully loaded from file, no need to login again | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Println("Using cookies from file") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Println("No valid cookies found in file, logging in...") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| username := "your_username" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| password := []byte("your_password") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| cookies, step, err := cfg.Login(username, password) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if step != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Handle multi-step verification. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Println("Two-step verification required.") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // You can use step.Resend() and step.Verify() methods to handle the verification process. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } else { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Fatalf("Error logging in: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| err = saveCookiesToFile(cookies) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Printf("Error saving cookies to file: %v", err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| fmt.Println("Successfully logged in!") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| printCookies(cookies) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+14
to
+47
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func testAuth() { | |
| cfg := &rbxauth.Config{} | |
| cookies, err := loadCookiesFromFile() | |
| if err == nil { | |
| // If cookies are successfully loaded from file, no need to login again | |
| log.Println("Using cookies from file") | |
| } else { | |
| log.Println("No valid cookies found in file, logging in...") | |
| username := "your_username" | |
| password := []byte("your_password") | |
| cookies, step, err := cfg.Login(username, password) | |
| if err != nil { | |
| if step != nil { | |
| // Handle multi-step verification. | |
| log.Println("Two-step verification required.") | |
| // You can use step.Resend() and step.Verify() methods to handle the verification process. | |
| } else { | |
| log.Fatalf("Error logging in: %v", err) | |
| } | |
| return | |
| } | |
| err = saveCookiesToFile(cookies) | |
| if err != nil { | |
| log.Printf("Error saving cookies to file: %v", err) | |
| } | |
| } | |
| fmt.Println("Successfully logged in!") | |
| printCookies(cookies) | |
| } |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The printCookies() function prints authentication cookies to stdout, which could expose sensitive session tokens in logs. This is a security risk as these cookies could be used to hijack authenticated sessions.
Consider removing this function or ensuring it's only used in development/debugging contexts, never in production.
| Original file line number | Diff line number | Diff line change | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,4 +1,4 @@ | ||||||||||||
| version: "3.7" | ||||||||||||
| --- | ||||||||||||
|
||||||||||||
| --- | |
| --- | |
| version: "3.8" |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The robloxtracker service has a hard dependency on warp-socks with condition: service_healthy, but the proxy configuration is optional based on environment variables. If PROXY_HOST and PROXY_PORT are not set, the service will still wait for warp-socks to be healthy before starting, creating an unnecessary dependency.
Consider making the depends_on conditional or documenting that the warp-socks dependency should be removed if not using a proxy.
| - robloxtracker-data:/data | |
| - robloxtracker-data:/data | |
| # NOTE: The following dependency on warp-socks is only required if you are using a proxy | |
| # (i.e., if PROXY_HOST and PROXY_PORT are set). If you are not using a proxy, | |
| # you should remove the depends_on block below to avoid unnecessary startup delays. |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Running the warp-socks container with privileged: true grants the container full access to the host system, which is a significant security risk. While the container also has specific capabilities (NET_ADMIN and SYS_ADMIN), the privileged flag is overly permissive.
Consider removing privileged: true and relying only on the specific capabilities that are actually needed. If privileged mode is absolutely necessary, add a comment explaining why.
| privileged: true |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The warp-socks service is configured with replicas: 5 under the deploy section. However, the deploy section is only used in Docker Swarm mode, not with docker-compose up. This configuration will be ignored when using standard docker-compose, meaning only 1 replica will run instead of the intended 5.
If you need multiple replicas with docker-compose, you should use the scale parameter or deploy with Swarm mode. If this is intentional for Swarm deployments only, consider adding a comment to clarify.
| retries: 5 | |
| retries: 5 | |
| # The 'deploy' section is only used in Docker Swarm mode. | |
| # To run multiple replicas with standard docker-compose, use: | |
| # docker-compose up --scale warp-socks=5 |
| Original file line number | Diff line number | Diff line change | ||||
|---|---|---|---|---|---|---|
| @@ -1,10 +1,12 @@ | ||||||
| module github.com/joecryptotoo/robloxtracker | ||||||
|
|
||||||
| go 1.19 | ||||||
| go 1.18 | ||||||
|
||||||
| go 1.18 | |
| go 1.19 |
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -5,24 +5,58 @@ import ( | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| "net/http" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "os" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "strconv" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "strings" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "time" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/prometheus/client_golang/prometheus" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| "github.com/prometheus/client_golang/prometheus/promhttp" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| ) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| func main() { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Create a non-global registry. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| reg := prometheus.NewRegistry() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Get the metrics | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| metrics := robloxMetrics(reg) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| // Check for required environment variables | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userID, err := strconv.ParseInt(os.Getenv("ROBLOX_USER_ID"), 10, 64) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Println(err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userIDsStr := os.Getenv("ROBLOX_USER_IDS") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userIDsStrSlice := strings.Split(userIDsStr, ",") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userIDs := make([]int64, len(userIDsStrSlice)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i, idStr := range userIDsStrSlice { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id, err := strconv.ParseInt(idStr, 10, 64) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Println(err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| userIDs[i] = id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+23
to
+34
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| notifyIDsStr := os.Getenv("NOTIFY_ROBLOX_USER_IDS") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| notifyIDsStrSlice := strings.Split(notifyIDsStr, ",") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| notifyIDs := make([]int64, len(notifyIDsStrSlice)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| for i, idStr := range notifyIDsStrSlice { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| id, err := strconv.ParseInt(idStr, 10, 64) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if err != nil { | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| log.Println(err) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| notifyIDs[i] = id | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+37
to
+46
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| notifyIDsStrSlice := strings.Split(notifyIDsStr, ",") | |
| notifyIDs := make([]int64, len(notifyIDsStrSlice)) | |
| for i, idStr := range notifyIDsStrSlice { | |
| id, err := strconv.ParseInt(idStr, 10, 64) | |
| if err != nil { | |
| log.Println(err) | |
| return | |
| } | |
| notifyIDs[i] = id | |
| var notifyIDs []int64 | |
| if strings.TrimSpace(notifyIDsStr) != "" { | |
| notifyIDsStrSlice := strings.Split(notifyIDsStr, ",") | |
| notifyIDs = make([]int64, 0, len(notifyIDsStrSlice)) | |
| for _, idStr := range notifyIDsStrSlice { | |
| idStr = strings.TrimSpace(idStr) | |
| if idStr == "" { | |
| continue | |
| } | |
| id, err := strconv.ParseInt(idStr, 10, 64) | |
| if err != nil { | |
| log.Println(err) | |
| return | |
| } | |
| notifyIDs = append(notifyIDs, id) | |
| } |
Copilot
AI
Dec 3, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The HTTP server is started without waiting for the monitoring goroutines to be fully initialized. If all monitoring goroutines exit early due to errors (e.g., invalid user IDs), the main function will immediately call log.Fatal(http.ListenAndServe(":8080", nil)) and the server will start even though no monitoring is occurring.
Consider checking that at least one goroutine successfully initialized before starting the HTTP server, or use a WaitGroup to ensure proper synchronization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The cookie file path
/data/cookies.txtis hardcoded. If the/datadirectory doesn't exist or isn't writable (e.g., in environments where the volume isn't mounted), the authentication functions will fail when trying to create or read the file.Consider making the cookie file path configurable via an environment variable with a sensible default, and adding proper error messages that indicate when the directory is missing or not writable.