package handler import ( "fmt" "net/http" "strconv" "github.com/gin-gonic/gin" "gitm/internal/database" "gitm/internal/gitea" "gitm/internal/models" "gitm/internal/sync" ) func HandleListServers(c *gin.Context) { servers, err := database.GetServers() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, servers) } func HandleCreateServer(c *gin.Context) { var req struct { Name string `json:"name" binding:"required"` URL string `json:"url" binding:"required"` Token string `json:"token" binding:"required"` SyncInterval int `json:"sync_interval"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } server := &models.GiteaServer{ Name: req.Name, URL: req.URL, Token: req.Token, SyncInterval: req.SyncInterval, Status: "active", } if err := database.CreateServer(server); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusCreated, server) } func HandleUpdateServer(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"}) return } server, err := database.GetServer(id) if err != nil || server == nil { c.JSON(http.StatusNotFound, gin.H{"error": "Server not found"}) return } var req struct { Name *string `json:"name"` URL *string `json:"url"` Token *string `json:"token"` SyncInterval *int `json:"sync_interval"` Status *string `json:"status"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } if req.Name != nil { server.Name = *req.Name } if req.URL != nil { server.URL = *req.URL } if req.Token != nil { server.Token = *req.Token } if req.SyncInterval != nil { server.SyncInterval = *req.SyncInterval } if req.Status != nil { server.Status = *req.Status } if err := database.UpdateServer(server); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, server) } func HandleDeleteServer(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"}) return } if err := database.DeleteServer(id); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, gin.H{"message": "Server deleted"}) } func HandleTestConnection(c *gin.Context) { var req struct { URL string `json:"url" binding:"required"` Token string `json:"token" binding:"required"` } if err := c.ShouldBindJSON(&req); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } client, err := gitea.NewClient(req.URL, req.Token) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } user, err := client.ValidateToken() if err != nil { c.JSON(http.StatusUnauthorized, gin.H{"error": "Authentication failed"}) return } c.JSON(http.StatusOK, gin.H{"message": "Connection successful", "user": user.Login}) } func HandleListRepos(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"}) return } repos, err := database.GetReposByServer(id) if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } c.JSON(http.StatusOK, repos) } func HandleDiscoverRepos(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"}) return } server, err := database.GetServer(id) if err != nil || server == nil { c.JSON(http.StatusNotFound, gin.H{"error": "Server not found"}) return } client, err := gitea.NewClient(server.URL, server.Token) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } giteaRepos, err := client.GetAllRepos() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } reposDir, _ := database.GetSetting("repos_dir") if reposDir == "" { reposDir = "./data/repos" } serverDir := reposDir + "/" + strconv.FormatInt(id, 10) + "_" + server.Name discovered := 0 for _, gr := range giteaRepos { existing, _ := database.GetRepoByFullName(id, gr.FullName) if existing == nil { repo := &models.Repo{ ServerID: id, Name: gr.Name, FullName: gr.FullName, CloneURL: gr.CloneURL, LocalPath: serverDir + "/" + gr.FullName + ".git", SyncStatus: "pending", } database.CreateRepo(repo) discovered++ } } c.JSON(http.StatusOK, gin.H{ "message": fmt.Sprintf("Discovered %d new repositories", discovered), "total_repos": len(giteaRepos), "new_repos": discovered, }) } func HandleSyncServer(engine *sync.Engine) gin.HandlerFunc { return func(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"}) return } if engine.IsSyncing(id) { c.JSON(http.StatusConflict, gin.H{"error": "Sync already in progress"}) return } go engine.SyncServer(id) c.JSON(http.StatusAccepted, gin.H{"message": "Sync started", "server_id": id}) } } func HandleSyncAll(engine *sync.Engine) gin.HandlerFunc { return func(c *gin.Context) { servers, err := database.GetServers() if err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) return } started := 0 for _, server := range servers { if server.Status == "active" && !engine.IsSyncing(server.ID) { go engine.SyncServer(server.ID) started++ } } c.JSON(http.StatusAccepted, gin.H{"message": fmt.Sprintf("Started sync for %d servers", started)}) } } func HandleGetSyncStatus(engine *sync.Engine) gin.HandlerFunc { return func(c *gin.Context) { id, err := strconv.ParseInt(c.Param("id"), 10, 64) if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid server ID"}) return } status := "idle" if engine.IsSyncing(id) { status = "syncing" } c.JSON(http.StatusOK, gin.H{"server_id": id, "status": status}) } }