package oplcli import ( "fmt" "log/slog" "os" "path/filepath" "regexp" "strings" ) func scanGameFileForID(filename string) (string, error) { file, err := os.Open(filename) if err != nil { slog.Error("Failed to open file", "file", filename, "err", err) return "", err } defer file.Close() const bufferSize = 1024 * 1024 // 1MB buffer := make([]byte, bufferSize) n, err := file.Read(buffer) if err != nil && n == 0 { slog.Error("Failed to read file", "file", file, "err", err) return "", err } id, found := scanBufferForID(buffer[:n]) if !found { slog.Error("No PS2 ID found in the file", "file", file) return "", fmt.Errorf("no PS2 game ID found in file") } return id, nil } func scanBufferForID(buffer []byte) (string, bool) { pattern := regexp.MustCompile(`(SLUS|SLES|SLPS|SCUS|SCES|SCPS)[_\-\s]?\d{3}[\._\-\s]?\d{2}`) match := pattern.Find(buffer) if match != nil { gameID := string(match) return normalizeGameID(gameID), true } return "", false } func normalizeGameID(id string) string { re := regexp.MustCompile(`(?i)^([A-Z]{4})[^0-9]*([0-9]{3})[^0-9]*([0-9]{2})$`) id = strings.TrimSpace(id) matches := re.FindStringSubmatch(id) if len(matches) != 4 { return "" } prefix := strings.ToUpper(matches[1]) number := matches[2] + "." + matches[3] return prefix + "_" + number } func renameGameFile(filePath, gameName string) (string, error) { ext := filepath.Ext(filePath) dir := filepath.Dir(filePath) newPath := filepath.Join(dir, gameName+ext) if filePath == newPath { return filePath, nil } // Do not overwrite existing files if _, err := os.Stat(newPath); err == nil { return "", fmt.Errorf("file already exists: %s", newPath) } else if !os.IsNotExist(err) { return "", fmt.Errorf("failed to check destination: %w", err) } // rename file err := os.Rename(filePath, newPath) if err != nil { return "", fmt.Errorf("failed to rename file: %w", err) } return newPath, nil }