diff --git a/filemanager.go b/filemanager.go index 2a729bcb..0a54cdfd 100644 --- a/filemanager.go +++ b/filemanager.go @@ -121,15 +121,6 @@ type FileManager struct { Commands map[string][]string } -type StaticGen interface { - SettingsPath() string - - Hook(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) - Preview(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) - Publish(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) - Schedule(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) -} - // Command is a command function. type Command func(r *http.Request, m *FileManager, u *User) error @@ -357,6 +348,8 @@ func (m *FileManager) ServeHTTP(w http.ResponseWriter, r *http.Request) { } } +// EnableStaticGen attaches a static generator to the current File Manager +// instance. func (m *FileManager) EnableStaticGen(data StaticGen) error { if reflect.TypeOf(data).Kind() != reflect.Ptr { return errors.New("data should be a pointer to interface, not interface") diff --git a/resource.go b/resource.go index e1269a45..4570bba7 100644 --- a/resource.go +++ b/resource.go @@ -5,13 +5,16 @@ import ( "fmt" "io" "io/ioutil" + "log" "net/http" "net/url" "os" "path/filepath" "strings" + "time" "github.com/hacdias/fileutils" + "github.com/robfig/cron" ) // sanitizeURL sanitizes the URL to prevent path transversal @@ -231,10 +234,45 @@ func resourcePublishSchedule(c *RequestContext, w http.ResponseWriter, r *http.R } if publish == "true" { - return c.StaticGen.Publish(c, w, r) + return resourcePublish(c, w, r) } - return c.StaticGen.Schedule(c, w, r) + t, err := time.Parse("2006-01-02T15:04", schedule) + if err != nil { + return http.StatusInternalServerError, err + } + + scheduler := cron.New() + scheduler.AddFunc(t.Format("05 04 15 02 01 *"), func() { + _, err := resourcePublish(c, w, r) + if err != nil { + log.Print(err) + } + }) + + scheduler.Start() + return http.StatusOK, nil +} + +func resourcePublish(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) { + path := filepath.Join(string(c.User.FileSystem), r.URL.Path) + + // Before save command handler. + if err := c.Runner("before_publish", path); err != nil { + return http.StatusInternalServerError, err + } + + code, err := c.StaticGen.Publish(c, w, r) + if err != nil { + return code, err + } + + // Executed the before publish command. + if err := c.Runner("before_publish", path); err != nil { + return http.StatusInternalServerError, err + } + + return code, nil } // resourcePatchHandler is the entry point for resource handler. diff --git a/staticgen.go b/staticgen.go index 5aa0a1bd..73027c51 100644 --- a/staticgen.go +++ b/staticgen.go @@ -9,17 +9,23 @@ import ( "os/exec" "path/filepath" "strings" - "time" "github.com/hacdias/varutils" - "github.com/robfig/cron" ) var ( - // ErrUnsupportedFileType ... - ErrUnsupportedFileType = errors.New("The type of the provided file isn't supported for this action") + errUnsupportedFileType = errors.New("The type of the provided file isn't supported for this action") ) +// StaticGen is a static website generator. +type StaticGen interface { + SettingsPath() string + + Hook(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) + Preview(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) + Publish(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) +} + // Hugo is the Hugo static website generator. type Hugo struct { // Website root @@ -89,7 +95,7 @@ func (h Hugo) Hook(c *RequestContext, w http.ResponseWriter, r *http.Request) (i // If the request isn't for a markdown file, we can't // handle it. if ext != ".markdown" && ext != ".md" { - return http.StatusBadRequest, ErrUnsupportedFileType + return http.StatusBadRequest, errUnsupportedFileType } // Tries to create a new file based on this archetype. @@ -107,11 +113,6 @@ func (h Hugo) Hook(c *RequestContext, w http.ResponseWriter, r *http.Request) (i func (h Hugo) Publish(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) { filename := filepath.Join(string(c.User.FileSystem), r.URL.Path) - // Before save command handler. - if err := c.Runner("before_publish", filename); err != nil { - return http.StatusInternalServerError, err - } - // We only run undraft command if it is a file. if strings.HasSuffix(filename, ".md") && strings.HasSuffix(filename, ".markdown") { if err := h.undraft(filename); err != nil { @@ -122,37 +123,9 @@ func (h Hugo) Publish(c *RequestContext, w http.ResponseWriter, r *http.Request) // Regenerates the file h.run(false) - // Executed the before publish command. - if err := c.Runner("before_publish", filename); err != nil { - return http.StatusInternalServerError, err - } - return 0, nil } -// Schedule schedules a post. -func (h Hugo) Schedule(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) { - t, err := time.Parse("2006-01-02T15:04", r.Header.Get("Schedule")) - path := filepath.Join(string(c.User.FileSystem), r.URL.Path) - path = filepath.Clean(path) - - if err != nil { - return http.StatusInternalServerError, err - } - - scheduler := cron.New() - scheduler.AddFunc(t.Format("05 04 15 02 01 *"), func() { - if err := h.undraft(path); err != nil { - log.Printf(err.Error()) - } - - h.run(false) - }) - - scheduler.Start() - return http.StatusOK, nil -} - // Preview handles the preview path. func (h *Hugo) Preview(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) { // Get a new temporary path if there is none. @@ -252,11 +225,6 @@ func (j Jekyll) Hook(c *RequestContext, w http.ResponseWriter, r *http.Request) func (j Jekyll) Publish(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) { filename := filepath.Join(string(c.User.FileSystem), r.URL.Path) - // Before save command handler. - if err := c.Runner("before_publish", filename); err != nil { - return http.StatusInternalServerError, err - } - // We only run undraft command if it is a file. if err := j.undraft(filename); err != nil { return http.StatusInternalServerError, err @@ -265,37 +233,9 @@ func (j Jekyll) Publish(c *RequestContext, w http.ResponseWriter, r *http.Reques // Regenerates the file j.run() - // Executed the before publish command. - if err := c.Runner("before_publish", filename); err != nil { - return http.StatusInternalServerError, err - } - return 0, nil } -// Schedule schedules a post. -func (j Jekyll) Schedule(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) { - t, err := time.Parse("2006-01-02T15:04", r.Header.Get("Schedule")) - path := filepath.Join(string(c.User.FileSystem), r.URL.Path) - path = filepath.Clean(path) - - if err != nil { - return http.StatusInternalServerError, err - } - - scheduler := cron.New() - scheduler.AddFunc(t.Format("05 04 15 02 01 *"), func() { - if err := j.undraft(path); err != nil { - log.Printf(err.Error()) - } - - j.run() - }) - - scheduler.Start() - return http.StatusOK, nil -} - // Preview handles the preview path. func (j *Jekyll) Preview(c *RequestContext, w http.ResponseWriter, r *http.Request) (int, error) { // Get a new temporary path if there is none.