Connor McCutcheon
/ SkyShot
screenshots.go
go
package controllers
import (
	"fmt"
	"log"
	"net/http"
	"strings"
	"sync"
	"theskyscape.com/repo/skykit"
	"theskyscape.com/repo/skyshot/models"
)
func Screenshots(defaultImg []byte) (string, skykit.Handler) {
	return "screenshots", &ScreenshotsController{
		defaultImg: defaultImg,
		mutex:      &sync.Mutex{},
		capturing:  make(map[string]bool),
	}
}
type ScreenshotsController struct {
	skykit.Controller
	defaultImg []byte
	mutex      *sync.Mutex
	capturing  map[string]bool
}
func (c *ScreenshotsController) Setup(app *skykit.Application) {
	c.Controller.Setup(app)
	http.Handle("GET /", c.Serve("home.html", nil))
	http.Handle("GET /{app}", c.Protect(c.handleScreenshot, nil))
	http.Handle("POST /capture", c.Protect(c.handleCapture, nil))
}
func (c ScreenshotsController) Handle(r *http.Request) skykit.Handler {
	c.Request = r
	return &c
}
func (c *ScreenshotsController) RecentScreenshots() []*models.Screenshot {
	screenshots, _ := models.Screenshots.Search("ORDER BY CreatedAt DESC")
	return screenshots
}
func (c *ScreenshotsController) handleScreenshot(w http.ResponseWriter, r *http.Request) {
	appName := strings.ToLower(r.PathValue("app"))
	if appName == "" {
		log.Printf("Screenshot request missing app name")
		http.Error(w, "App name required", http.StatusBadRequest)
		return
	}
	screenshot, err := models.Screenshots.Get(appName)
	if err == nil && screenshot != nil {
		log.Printf("Serving cached screenshot for app: %s", appName)
		w.Header().Set("Content-Type", "image/png")
		w.Header().Set("Cache-Control", "public, max-age=86400") // Cache for 24 hours
		w.Write(screenshot.ImageData)
		return
	}
	go c.captureScreenshot(appName)
	w.Write(c.defaultImg)
}
func (c *ScreenshotsController) handleCapture(w http.ResponseWriter, r *http.Request) {
	appName := strings.ToLower(r.FormValue("app"))
	if appName == "" {
		log.Printf("Capture request missing app name")
		c.Render(w, r, "error.html", "App name is required")
		return
	}
	c.mutex.Lock()
	if _, ok := c.capturing[appName]; ok {
		c.mutex.Unlock()
		log.Printf("Capture: Already capturing for app: %s", appName)
		c.Render(w, r, "warning.html", fmt.Sprintf("Screenshot for %s is being captured", appName))
		return
	}
	c.mutex.Unlock()
	go c.captureScreenshot(appName)
	c.Render(w, r, "success.html", fmt.Sprintf("Screenshot for %s is being captured", appName))
}
func (c *ScreenshotsController) captureScreenshot(app string) {
	c.mutex.Lock()
	if _, ok := c.capturing[app]; ok {
		c.mutex.Unlock()
		log.Printf("Capture: Already capturing for app: %s", app)
		return
	}
	c.capturing[app] = true
	c.mutex.Unlock()
	log.Printf("Background capture starting for app: %s", app)
	imageData, err := models.CaptureScreenshot(app)
	if err != nil {
		log.Printf("Background screenshot capture failed for %s: %v", app, err)
		c.mutex.Lock()
		delete(c.capturing, app)
		c.mutex.Unlock()
		return
	}
	log.Printf("Successfully captured and stored screenshot for %s", imageData.ID)
	c.mutex.Lock()
	delete(c.capturing, app)
	c.mutex.Unlock()
}
No comments yet.