Last active
August 3, 2025 13:15
-
-
Save pyt0xic/95c6a511755e6652f05eea868f600d31 to your computer and use it in GitHub Desktop.
Start Refrag Retakes Server
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| package main | |
| import ( | |
| "bytes" | |
| "encoding/json" | |
| "fmt" | |
| "io" | |
| "log" | |
| "net/http" | |
| "os" | |
| "strconv" | |
| "time" | |
| "github.com/joho/godotenv" | |
| ) | |
| const ( | |
| refragAPIEndpoint = "https://api.refrag.gg/auth/sign_in" | |
| refragStartServerEndpoint = "https://api.refrag.gg/cs_servers/start_new_server" | |
| refragRunningServersEndpoint = "https://api.refrag.gg/cs_servers/running" | |
| refragOrigin = "https://play.refrag.gg" | |
| outputFilename = "refrag_login_data.json" | |
| ) | |
| // LoginRequest represents the login request payload | |
| type LoginRequest struct { | |
| Email string `json:"email"` | |
| Password string `json:"password"` | |
| Remember bool `json:"remember"` | |
| } | |
| // LoginResponse represents the API response data | |
| type LoginResponse struct { | |
| Data struct { | |
| Email string `json:"email"` | |
| Provider string `json:"provider"` | |
| UID string `json:"uid"` | |
| MatchAuthToken string `json:"match_auth_token"` | |
| ID int `json:"id"` | |
| AllowPasswordChange bool `json:"allow_password_change"` | |
| Name any `json:"name"` | |
| Nickname any `json:"nickname"` | |
| Image any `json:"image"` | |
| TeamID any `json:"team_id"` | |
| SteamID string `json:"steam_id"` | |
| IsBetaTester any `json:"is_beta_tester"` | |
| HasScrimAccess bool `json:"has_scrim_access"` | |
| AdminAccess bool `json:"admin_access"` | |
| CustomProAccess bool `json:"custom_pro_access"` | |
| WarmupKillCount int `json:"warmup_kill_count"` | |
| EmailSignUp bool `json:"email_sign_up"` | |
| ServerSettings []ServerSettings `json:"server_settings"` | |
| CustomCompetitor any `json:"custom_competitor"` | |
| CustomPlayer any `json:"custom_player"` | |
| CustomTeam any `json:"custom_team"` | |
| FaceitNickname string `json:"faceit_nickname"` | |
| UUID string `json:"uuid"` | |
| Username any `json:"username"` | |
| DiscordID any `json:"discord_id"` | |
| DiscordTag any `json:"discord_tag"` | |
| ReceiveEmailForNotifications bool `json:"receive_email_for_notifications"` | |
| ReceiveEmailForAccessCodes bool `json:"receive_email_for_access_codes"` | |
| OnboardedStepsCompleted int `json:"onboarded_steps_completed"` | |
| SashID int `json:"sash_id"` | |
| Level int `json:"level"` | |
| FaceitPlayerID any `json:"faceit_player_id"` | |
| CommunityMod bool `json:"community_mod"` | |
| SteamProfileJSON SteamProfile `json:"steam_profile_json"` | |
| // Other fields omitted for brevity | |
| } `json:"data"` | |
| } | |
| type ServerSettings struct { | |
| Modules []Module `json:"modules"` | |
| ModName string `json:"mod_name"` | |
| } | |
| type Module struct { | |
| Module string `json:"module"` | |
| Settings string `json:"settings"` | |
| } | |
| type SteamProfile struct { | |
| Avatar string `json:"avatar"` | |
| GameID string `json:"gameid"` | |
| SteamID string `json:"steamid"` | |
| Realname string `json:"realname"` | |
| Avatarfull string `json:"avatarfull"` | |
| Avatarhash string `json:"avatarhash"` | |
| Profileurl string `json:"profileurl"` | |
| Personaname string `json:"personaname"` | |
| Timecreated int `json:"timecreated"` | |
| Avatarmedium string `json:"avatarmedium"` | |
| Lobbysteamid string `json:"lobbysteamid"` | |
| Personastate int `json:"personastate"` | |
| Profilestate int `json:"profilestate"` | |
| Gameextrainfo string `json:"gameextrainfo"` | |
| Primaryclanid string `json:"primaryclanid"` | |
| Loccountrycode string `json:"loccountrycode"` | |
| Commentpermission int `json:"commentpermission"` | |
| Personastateflags int `json:"personastateflags"` | |
| Communityvisibilitystate int `json:"communityvisibilitystate"` | |
| } | |
| // AuthHeaders holds the authentication headers received from the API | |
| type AuthHeaders struct { | |
| AccessToken string `json:"access_token"` | |
| Authorization string `json:"authorization"` | |
| Client string `json:"client"` | |
| Expiry string `json:"expiry"` | |
| UID string `json:"uid"` | |
| } | |
| // SavedData represents the complete data structure to save to file | |
| type SavedData struct { | |
| Response LoginResponse `json:"response"` | |
| Headers AuthHeaders `json:"headers"` | |
| } | |
| // StartServerRequest represents the payload for starting a new server | |
| type StartServerRequest struct { | |
| ServerLocationID int `json:"server_location_id"` | |
| Game string `json:"game"` | |
| BetaServer bool `json:"betaServer"` | |
| SecureServer bool `json:"secureServer"` | |
| IsAssessment bool `json:"is_assessment"` | |
| LaunchSettings LaunchSettings `json:"launch_settings"` | |
| } | |
| type LaunchSettings struct { | |
| Mod string `json:"mod"` | |
| Map string `json:"map"` | |
| } | |
| // ServerResponse represents a server in the API responses | |
| type ServerResponse struct { | |
| ID int `json:"id"` | |
| IP string `json:"ip"` | |
| Port int `json:"port"` | |
| Status string `json:"status"` | |
| Password string `json:"password"` | |
| VACSecure bool `json:"vac_secure"` | |
| ActiveMap string `json:"active_map"` | |
| ActiveMod string `json:"active_mod"` | |
| ConnectedPlayers any `json:"connected_players"` | |
| IsAssessment bool `json:"is_assessment"` | |
| Game string `json:"game"` | |
| RawIP string `json:"raw_ip"` | |
| IsScrim bool `json:"is_scrim"` | |
| ServerLocation string `json:"server_location"` | |
| StartedBy User `json:"started_by"` | |
| Team Team `json:"team"` | |
| } | |
| type User struct { | |
| ID int `json:"id"` | |
| SteamProfile SteamProfile `json:"steam_profile"` | |
| } | |
| type Team struct { | |
| Name string `json:"name"` | |
| ID int `json:"id"` | |
| } | |
| func main() { | |
| fmt.Println("Logging in to refrag.gg...") | |
| // Load credentials from env vars or .env file | |
| email, password, err := loadCredentials() | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| // Log in to the API | |
| response, headers, err := loginToRefrag(email, password) | |
| if err != nil { | |
| log.Fatal("Login failed: ", err) | |
| } | |
| // Save the data to file | |
| if err := saveLoginResponseData(response, headers); err != nil { | |
| log.Fatal("Failed to save response data: ", err) | |
| } | |
| // Print success message with auth headers | |
| printLoginSuccess(headers) | |
| // Load server parameters from environment variables | |
| mapName, mod, locationID, err := loadServerParameters() | |
| if err != nil { | |
| log.Fatal(err) | |
| } | |
| // Start a new server | |
| server, err := StartServer(headers, locationID, "cs2", mod, mapName) | |
| if err != nil { | |
| log.Fatal("Failed to start server: ", err) | |
| } | |
| fmt.Printf("Server started! Connect: %s:%d (Password: %s)\n", server.IP, server.Port, server.Password) | |
| // Loop until password is available | |
| maxAttempts := 30 // Avoid infinite loops | |
| time.Sleep(3 * time.Second) | |
| for i := 0; i < maxAttempts; i++ { | |
| // Sleep for 3 seconds at the start of each iteration | |
| fmt.Printf("Waiting for 3 seconds (attempt %d/%d)...\n", i+1, maxAttempts) | |
| time.Sleep(3 * time.Second) | |
| // Get running servers | |
| servers, err := GetRunningServers(headers) | |
| if err != nil { | |
| log.Printf("Failed to get running servers: %v. Retrying...", err) | |
| continue | |
| } | |
| fmt.Printf("Running Servers (%d):\n", len(servers)) | |
| // Look for our server | |
| var foundServer bool | |
| for _, srv := range servers { | |
| fmt.Printf(" %s:%d - %s on %s (Status: %s, Password: %s)\n", | |
| srv.IP, srv.Port, srv.ActiveMod, srv.ActiveMap, srv.Status, srv.Password) | |
| // If this is our server and password is available | |
| if srv.ID == server.ID && srv.Password != "" && srv.Status == "online" { | |
| fmt.Printf("\nServer is ready! Connect: %s:%d (Password: %s)\n", srv.IP, srv.Port, srv.Password) | |
| fmt.Printf("\nconnect %s:%d; password %s\n", srv.IP, srv.Port, srv.Password) | |
| return | |
| } | |
| } | |
| if !foundServer { | |
| fmt.Println("Our server is not in the list. It might be still starting up...") | |
| } else { | |
| fmt.Println("Server found but password not yet available.") | |
| } | |
| } | |
| fmt.Println("Maximum attempts reached. Please check server status manually.") | |
| } | |
| // loadCredentials loads REFRAG_EMAIL and REFRAG_PASSWORD from environment or .env file | |
| func loadCredentials() (email, password string, err error) { | |
| // Load .env file if it exists | |
| if err := godotenv.Load(); err != nil { | |
| fmt.Println("No .env file found, using environment variables directly") | |
| } | |
| // Get credentials from environment variables | |
| email = os.Getenv("REFRAG_EMAIL") | |
| password = os.Getenv("REFRAG_PASSWORD") | |
| if email == "" || password == "" { | |
| return "", "", fmt.Errorf("REFRAG_EMAIL and REFRAG_PASSWORD environment variables must be set") | |
| } | |
| return email, password, nil | |
| } | |
| // loadServerParameters loads REFRAG_MAP, REFRAG_MOD, and REFRAG_LOCATION_ID from environment variables | |
| func loadServerParameters() (mapName, mod string, locationID int, err error) { | |
| mapName = os.Getenv("REFRAG_MAP") | |
| mod = os.Getenv("REFRAG_MOD") | |
| locationIDStr := os.Getenv("REFRAG_LOCATION_ID") | |
| if mapName == "" { | |
| mapName = "de_ancient" // Default map | |
| } | |
| if mod == "" { | |
| mod = "retakes" // Default mod | |
| } | |
| if locationIDStr == "" { | |
| locationID = 16 // Default location ID (change as needed) | |
| } else { | |
| locationID, err = strconv.Atoi(locationIDStr) | |
| if err != nil { | |
| return "", "", 0, fmt.Errorf("invalid REFRAG_LOCATION_ID: %w", err) | |
| } | |
| } | |
| return mapName, mod, locationID, nil | |
| } | |
| // loginToRefrag attempts to login to the Refrag API and returns the response and auth headers | |
| func loginToRefrag(email, password string) (*LoginResponse, *AuthHeaders, error) { | |
| // Create login request payload | |
| loginData := LoginRequest{ | |
| Email: email, | |
| Password: password, | |
| Remember: false, | |
| } | |
| // Convert to JSON | |
| jsonData, err := json.Marshal(loginData) | |
| if err != nil { | |
| return nil, nil, fmt.Errorf("failed to marshal JSON: %w", err) | |
| } | |
| // Create and configure the HTTP request | |
| req, err := http.NewRequest(http.MethodPost, refragAPIEndpoint, bytes.NewBuffer(jsonData)) | |
| if err != nil { | |
| return nil, nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| // Set headers | |
| setLoginRequestHeaders(req) | |
| // Send the request | |
| client := &http.Client{} | |
| resp, err := client.Do(req) | |
| if err != nil { | |
| return nil, nil, fmt.Errorf("failed to send request: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| // Read the response body | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, nil, fmt.Errorf("failed to read response: %w", err) | |
| } | |
| // Parse the JSON response | |
| var loginResponse LoginResponse | |
| err = json.Unmarshal(body, &loginResponse) | |
| if err != nil { | |
| return nil, nil, fmt.Errorf("failed to parse JSON response: %w", err) | |
| } | |
| // Extract authentication headers | |
| headers := &AuthHeaders{ | |
| AccessToken: resp.Header.Get("access-token"), | |
| Authorization: resp.Header.Get("authorization"), | |
| Client: resp.Header.Get("client"), | |
| Expiry: resp.Header.Get("expiry"), | |
| UID: resp.Header.Get("uid"), | |
| } | |
| return &loginResponse, headers, nil | |
| } | |
| // setLoginRequestHeaders adds all required headers to the HTTP request | |
| func setLoginRequestHeaders(req *http.Request) { | |
| req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0") | |
| req.Header.Set("Accept", "application/json, text/plain, */*") | |
| req.Header.Set("Accept-Language", "en-US,en;q=0.5") | |
| req.Header.Set("Content-Type", "application/json") | |
| req.Header.Set("Origin", refragOrigin) | |
| req.Header.Set("DNT", "1") | |
| req.Header.Set("Connection", "keep-alive") | |
| req.Header.Set("Referer", refragOrigin+"/") | |
| req.Header.Set("Sec-Fetch-Dest", "empty") | |
| req.Header.Set("Sec-Fetch-Mode", "cors") | |
| req.Header.Set("Sec-Fetch-Site", "same-site") | |
| req.Header.Set("Priority", "u=0") | |
| req.Header.Set("TE", "trailers") | |
| } | |
| // saveLoginResponseData saves the login response and headers to a JSON file | |
| func saveLoginResponseData(response *LoginResponse, headers *AuthHeaders) error { | |
| savedData := SavedData{ | |
| Response: *response, | |
| Headers: *headers, | |
| } | |
| // Convert to JSON for storage | |
| outputJSON, err := json.MarshalIndent(savedData, "", " ") | |
| if err != nil { | |
| return fmt.Errorf("failed to create output JSON: %w", err) | |
| } | |
| // Save to file | |
| err = os.WriteFile(outputFilename, outputJSON, 0644) | |
| if err != nil { | |
| return fmt.Errorf("failed to write to file: %w", err) | |
| } | |
| return nil | |
| } | |
| // printLoginSuccess prints the successful login information | |
| func printLoginSuccess(headers *AuthHeaders) { | |
| fmt.Println("Login successful!") | |
| fmt.Println("Access Token:", headers.AccessToken) | |
| fmt.Println("Authorization:", headers.Authorization) | |
| fmt.Println("Client:", headers.Client) | |
| fmt.Println("Expiry:", headers.Expiry) | |
| fmt.Println("UID:", headers.UID) | |
| fmt.Println("Response data saved to", outputFilename) | |
| } | |
| // StartServer starts a new server with the given parameters | |
| func StartServer(auth *AuthHeaders, locationID int, game string, mod string, mapName string) (*ServerResponse, error) { | |
| fmt.Println("Starting a new server...") | |
| // Create server request payload | |
| requestData := StartServerRequest{ | |
| ServerLocationID: locationID, | |
| Game: game, | |
| BetaServer: false, | |
| SecureServer: false, | |
| IsAssessment: false, | |
| LaunchSettings: LaunchSettings{ | |
| Mod: mod, | |
| Map: mapName, | |
| }, | |
| } | |
| // Convert to JSON | |
| jsonData, err := json.Marshal(requestData) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to marshal JSON: %w", err) | |
| } | |
| // Create and configure the HTTP request | |
| req, err := http.NewRequest(http.MethodPost, refragStartServerEndpoint, bytes.NewBuffer(jsonData)) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| // Set headers | |
| setRefragRequestHeaders(req, auth) | |
| req.Header.Set("X-GAME", game) | |
| req.Header.Set("X-TEAM-ID", "272803") // This could be made dynamic if needed | |
| // Send the request | |
| client := &http.Client{} | |
| resp, err := client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to send request: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| // Read the response body | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response: %w", err) | |
| } | |
| // Parse the JSON response | |
| var serverResponse ServerResponse | |
| err = json.Unmarshal(body, &serverResponse) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to parse JSON response: %w", err) | |
| } | |
| return &serverResponse, nil | |
| } | |
| // GetRunningServers retrieves all currently running servers | |
| func GetRunningServers(auth *AuthHeaders) ([]ServerResponse, error) { | |
| fmt.Println("Getting running servers...") | |
| // Create and configure the HTTP request | |
| req, err := http.NewRequest(http.MethodGet, refragRunningServersEndpoint, nil) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to create request: %w", err) | |
| } | |
| // Set headers | |
| setRefragRequestHeaders(req, auth) | |
| req.Header.Set("X-GAME", "cs2") | |
| req.Header.Set("X-TEAM-ID", "272803") // This could be made dynamic if needed | |
| // Send the request | |
| client := &http.Client{} | |
| resp, err := client.Do(req) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to send request: %w", err) | |
| } | |
| defer resp.Body.Close() | |
| // Read the response body | |
| body, err := io.ReadAll(resp.Body) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to read response: %w", err) | |
| } | |
| // Parse the JSON response | |
| var servers []ServerResponse | |
| err = json.Unmarshal(body, &servers) | |
| if err != nil { | |
| return nil, fmt.Errorf("failed to parse JSON response: %w", err) | |
| } | |
| return servers, nil | |
| } | |
| // setRefragRequestHeaders sets the necessary authentication headers for Refrag API requests | |
| func setRefragRequestHeaders(req *http.Request, auth *AuthHeaders) { | |
| req.Header.Set("User-Agent", "Mozilla/5.0 (X11; Linux x86_64; rv:139.0) Gecko/20100101 Firefox/139.0") | |
| req.Header.Set("Accept", "application/json, text/plain, */*") | |
| req.Header.Set("Accept-Language", "en-US,en;q=0.5") | |
| req.Header.Set("Content-Type", "application/json") | |
| req.Header.Set("Origin", refragOrigin) | |
| req.Header.Set("DNT", "1") | |
| req.Header.Set("Connection", "keep-alive") | |
| req.Header.Set("Referer", refragOrigin+"/") | |
| req.Header.Set("Sec-Fetch-Dest", "empty") | |
| req.Header.Set("Sec-Fetch-Mode", "cors") | |
| req.Header.Set("Sec-Fetch-Site", "same-site") | |
| req.Header.Set("Priority", "u=0") | |
| req.Header.Set("TE", "trailers") | |
| // Authentication headers | |
| req.Header.Set("Token-Type", "Bearer") | |
| req.Header.Set("Access-Token", auth.AccessToken) | |
| req.Header.Set("Client", auth.Client) | |
| req.Header.Set("Uid", auth.UID) | |
| req.Header.Set("Expiry", auth.Expiry) | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment