zeroclaw / backend /pkg /utils /utils.go
personalbotai
Initial commit from picoclaw
da590a7
package utils
import (
"crypto/rand"
"encoding/hex"
"fmt"
"net/url"
"os"
"path/filepath"
"strings"
"time"
)
// GenerateID creates a unique identifier
func GenerateID() string {
b := make([]byte, 8)
rand.Read(b)
return hex.EncodeToString(b)
}
// Now returns current time
func Now() time.Time {
return time.Now()
}
// IsValidGitHubURL validates if a URL is a valid GitHub repository URL
func IsValidGitHubURL(u string) bool {
parsed, err := url.Parse(u)
if err != nil {
return false
}
if parsed.Host != "github.com" && parsed.Host != "www.github.com" {
return false
}
parts := strings.Split(strings.Trim(parsed.Path, "/"), "/")
return len(parts) >= 2
}
// SaveResult stores analysis result and diagram (in-memory for now)
func SaveResult(id string, diagram interface{}) {
// In production, store in database or cache
// For now, we'll use a simple in-memory map
getDiagramStore()[id] = diagram
}
// GetDiagram retrieves a diagram by ID
func GetDiagram(id string) interface{} {
store := getDiagramStore()
if diagram, ok := store[id]; ok {
return diagram
}
return nil
}
// GetStatus retrieves analysis status (simplified)
func GetStatus(id string) map[string]interface{} {
// In production, this would fetch from database
diagram := GetDiagram(id)
if diagram == nil {
return nil
}
return map[string]interface{}{
"id": id,
"status": "completed",
}
}
// In-memory storage (for development only)
var diagramStore = make(map[string]interface{})
func getDiagramStore() map[string]interface{} {
return diagramStore
}
// CountLines counts lines in a directory (simplified)
func CountLines(dir string) int {
total := 0
filepath.WalkDir(dir, func(path string, d os.DirEntry, err error) error {
if err != nil || d.IsDir() {
return nil
}
// Skip binary files and certain extensions
ext := strings.ToLower(filepath.Ext(path))
skipExts := map[string]bool{
".png": true, ".jpg": true, ".jpeg": true, ".gif": true,
".pdf": true, ".zip": true, ".tar": true, ".gz": true,
}
if skipExts[ext] {
return nil
}
data, err := os.ReadFile(path)
if err != nil {
return nil
}
lines := strings.Count(string(data), "\n")
if len(data) > 0 && !strings.HasSuffix(string(data), "\n") {
lines++
}
total += lines
return nil
})
return total
}
// CountDirectories counts directories in a structure
func CountDirectories(root models.RepositoryStructure) int {
count := 0
var walk func(models.RepositoryStructure)
walk = func(node models.RepositoryStructure) {
if node.Type == "directory" {
count++
}
for _, child := range node.Children {
walk(child)
}
}
walk(root)
return count
}
// RunCommand executes a shell command (placeholder)
func RunCommand(command string) error {
// In production, use exec.Command
return fmt.Errorf("not implemented")
}
// Models reference (to avoid circular import)
type RepositoryStructure struct {
Name string
Type string
Path string
Children []RepositoryStructure
}