package main import ( "backend/config" "backend/queries" "backend/typesdefs" "fmt" "io" "log" "math/rand" "net/http" "os" "strconv" "strings" "text/template" "time" "github.com/labstack/echo/v4" ) type Server struct { miogest *MiogestHandler config *config.Config } func NewServer(cfg *config.Config) (*Server, error) { miogest := NewMiogestHandler() if miogest == nil { return nil, fmt.Errorf("error connecting to miogest") } return &Server{ miogest: miogest, config: cfg, }, nil } func (s *Server) SetupRoutes() *echo.Echo { funcs := map[string]any{ "contains": strings.Contains, "hasPrefix": strings.HasPrefix, "hasSuffix": strings.HasSuffix, "getImage": func(txt string) string { return txt[7:] }, "isWebp": func(txt string) bool { return strings.Contains(txt, "webp") }, } t := &Template{ templates: template.Must(template.New("").Funcs(funcs).ParseGlob("public/views/*.html")), } e := echo.New() e.Renderer = t // MISC e.Static("/static", "public/static") e.GET("/", func(c echo.Context) error { return c.Render(http.StatusOK, "main", map[string]any{ "imageOption": s.config.Images.Enabled, "concurrentImages": s.config.Images.ConcurrentLimit, }) }) e.GET("/test", func(c echo.Context) error { files, err := ListBucket("images") if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } return c.JSONPretty(http.StatusOK, map[string]any{ "files": files, }, " ") }) e.POST("/testpost", func(c echo.Context) error { // Get the form value test := c.FormValue("test") fmt.Println("test:", test) return c.String(http.StatusOK, "OK") }) e.GET("/health", func(c echo.Context) error { h := queries.HealthCheck() s_error := HealthCheckStorage() var s string if s_error != nil { s = s_error.Error() } else { s = "OK" } return c.JSONPretty(http.StatusOK, fmt.Sprintf("DB Connection: %v, Storage Connection: %v", h, s), " ") }) // MIOGEST ROUTES e.GET("/cats", func(c echo.Context) error { var data = s.miogest.GetCaratteristiche() return c.JSONPretty(http.StatusOK, data, " ") }) e.GET("/categ", func(c echo.Context) error { var data = s.miogest.GetCategorie() return c.JSONPretty(http.StatusOK, data, " ") }) e.GET("/miogest", func(c echo.Context) error { data, err := s.miogest.GetAnnunci() if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } return c.JSONPretty(http.StatusOK, data, " ") }) e.GET("/miogest-sample", func(c echo.Context) error { xml, err := s.miogest.GetAnnunci() if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } rand := rand.Intn(len(xml.Annuncio)) data := xml.Annuncio[rand] return c.JSONPretty(http.StatusOK, data, " ") }) e.GET("/parse", func(c echo.Context) error { start := time.Now() var data, err = s.miogest.GetAnnunciParsed(nil, nil, false) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } end := time.Now() fmt.Println("time taken:", end.Sub(start).String()) return c.JSONPretty(http.StatusOK, data, " ") }) e.GET("/update", func(c echo.Context) error { forceMediaStale := false forceMediaStr := c.QueryParam("forcemedia") if forceMediaStr == "true" { forceMediaStale = true } imgPool := []typesdefs.MediaToProcess{} videoPool := []typesdefs.MediaToProcess{} data, err := s.miogest.GetAnnunciParsed(&imgPool, &videoPool, forceMediaStale) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } err = queries.AnnunciInsert(data, true) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } imgRefs, err := ProcessImagePool(&imgPool) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } err = queries.SetImagesToDB(&imgRefs) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } videoRefs, err := ProcessVideoPool(&videoPool) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } err = queries.SetVideosToDB(&videoRefs) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } /* err = invalidateAllAnnunciFB() if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } */ log.Println("Update completed") return c.String(http.StatusOK, "Updated") }) e.GET("/update-cod/:cod", func(c echo.Context) error { cod := c.Param("cod") imgPool := []typesdefs.MediaToProcess{} videoPool := []typesdefs.MediaToProcess{} data, err := s.miogest.GetAnnuncioParsed(cod, &imgPool, &videoPool) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } err = queries.AnnunciInsert(data, false) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } imgRefs, err := ProcessImagePool(&imgPool) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } err = queries.SetImagesToDB(&imgRefs) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } videoRefs, err := ProcessVideoPool(&videoPool) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } err = queries.SetVideosToDB(&videoRefs) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } /* url := fmt.Sprintf("https://www.infoalloggi.it/annuncio/%s", cod) err = invalidateFacebookCache(url) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } */ log.Printf("Update %s completed", cod) return c.String(http.StatusOK, "Updated") }) // BACKUP ROUTES /* e.GET("/upload-backup", func(c echo.Context) error { return c.Render(http.StatusOK, "backup-upload", nil) }) e.POST("/upload-backup", func(c echo.Context) error { file, err := c.FormFile("file") if err != nil { return err } src, err := file.Open() if err != nil { return err } defer src.Close() dst, err := os.Create("bkp.xml") if err != nil { return err } defer dst.Close() if _, err = io.Copy(dst, src); err != nil { return err } return c.HTML(http.StatusOK, fmt.Sprintf("

File %s uploaded successfully.

", file.Filename)) }) e.GET("/bkp", func(c echo.Context) error { data := From_Backup() return c.JSONPretty(http.StatusOK, data, " ") }) e.GET("/parsebkp", func(c echo.Context) error { var data = ParseUpdateBkp(s.miogest) return c.JSONPretty(http.StatusOK, data, " ") }) e.GET("/setbkp", func(c echo.Context) error { var data = ParseUpdateBkp(s.miogest) err := queries.SetFromBkp(data) if err != nil { return c.String(http.StatusInternalServerError, err.Error()) } return c.String(http.StatusOK, "Setted") }) */ //IMAGE ROUTES e.GET("/initcwebp", func(c echo.Context) error { Conversion("test.jpg") return c.String(http.StatusOK, "Cwebp initialized") }) e.POST("/image-option-toggle", func(c echo.Context) error { // Toggle the imageOption value s.config.Images.Enabled = !s.config.Images.Enabled // Convert the boolean value to a string and set the environment variable os.Setenv("IMAGEOPTION", strconv.FormatBool(s.config.Images.Enabled)) return c.String(http.StatusOK, "OK") }) return e } func (s *Server) Start() { e := s.SetupRoutes() Conversion("test.jpg") fmt.Println("Image Option: ", s.config.Images.Enabled) fmt.Println("Concurrent Images: ", s.config.Images.ConcurrentLimit) fmt.Println("Server url: http://localhost:" + strconv.Itoa(s.config.Server.Port)) e.Logger.Info(e.Start(":" + strconv.Itoa(s.config.Server.Port))) } func main() { cfg := config.Load() server, err := NewServer(cfg) if err != nil { log.Fatalf("Server initialization error: %v", err) } server.Start() } type Template struct { templates *template.Template } func (t *Template) Render(w io.Writer, name string, data any, c echo.Context) error { return t.templates.ExecuteTemplate(w, name, data) }