func getIndex(w http.ResponseWriter, r *http.Request, ctx routes.Context) error { tpl, err := routes.LoadTemplates("base.tpl", "index.tpl") if err != nil { return tracederror.New(err) } recent, err := models.GetRecentBlogPosts(ctx.DB, 4, 0) if err != nil { return tracederror.New(err) } featured, err := models.GetRecentPostsInCategory(ctx.DB, "featured", 1, 0) if err != nil { return tracederror.New(err) } if len(featured) == 0 { return tracederror.New(fmt.Errorf("No featured posts?")) } data := indexPage{ Posts: recent, Featured: featured[0], } return routes.RenderTemplateWithData(w, r, tpl, &data) }
func LoadTemplates(str ...string) (*template.Template, error) { pathed := []string{} for _, v := range str { pathed = append(pathed, fmt.Sprintf("assets/templates/%s", v)) } res := template.New(str[0]) // Load default functions. mapping := template.FuncMap{ "blackfriday": templateBlackfriday, "s3img": s3img, "add": add, "slug": slug, "timef": timef, "darkenimg": linearGradient, } res = res.Funcs(mapping) res, err := res.ParseFiles(pathed...) if err != nil { log.Print(tracederror.New(err)) return nil, tracederror.New(err) } return res, tracederror.New(err) }
func getGenericArchive(w http.ResponseWriter, r *http.Request, ctx routes.Context) error { vars := mux.Vars(r) page, err := strconv.ParseInt(vars["page"], 10, 32) if err != nil { return tracederror.New(err) } if page <= 0 { return routes.MakeHttpError(fmt.Errorf("Page must be larger than 0"), http.StatusBadRequest, r) } tpl, err := routes.LoadTemplates("base.tpl", "archive.tpl") if err != nil { return routes.MakeHttpError(err, http.StatusNotFound, r) } posts, err := models.GetRecentBlogPosts(ctx.DB, 100, int32((page-1)*100)) if err != nil { return tracederror.New(err) } data := archivePage{ Page: int32(page), Posts: posts, Category: "All", } return routes.RenderTemplateWithData(w, r, tpl, data) }
func postEdit(w http.ResponseWriter, r *http.Request, ctx routes.Context) error { err := routes.CheckAuth(r, ctx) if err != nil { return err } body, err := ioutil.ReadAll(r.Body) if err != nil { return routes.MakeHttpError(err, http.StatusBadRequest, r) } res := editBody{} err = json.Unmarshal(body, &res) if err != nil { return routes.MakeHttpError(err, http.StatusBadRequest, r) } post := &models.BlogPost{ ID: res.ID, CategoryID: 1, } if res.ID != 0 { post, err = models.GetBlogPostByID(ctx.DB, res.ID) if err != nil { return tracederror.New(err) } } post.Content = res.Content post.Title = res.Title post.CategoryID = res.Category post.Hero = res.Hero t := time.Unix(int64(res.Publish), 0) post.Publish = &t if res.Publish == 0 { post.Publish = nil } err = post.Save(ctx.DB) if err != nil { return tracederror.New(err) } result := editResponse{ ID: post.ID, } bytes, err := json.Marshal(result) if err != nil { return tracederror.New(err) } w.Write(bytes) return nil }
func LoadConfigurationFromFileAndEnvironment(file string, cfg interface{}) error { bytes, err := ioutil.ReadFile(file) if err != nil { return tracederror.New(err) } err = json.Unmarshal(bytes, cfg) if err != nil { return tracederror.New(err) } err = LoadConfigurationFromEnvironmentVariables(cfg) return tracederror.New(err) }
func GetImagesInGallery(bucket *s3.Bucket, g *Gallery) ([]Image, error) { pre := fmt.Sprintf("%s%s", g.S3Prefix, "orig-") res, err := bucket.List(pre, "/", "", 1000) if err != nil { return nil, tracederror.New(err) } paths := []Image{} for _, v := range res.Contents { if v.Key[len(v.Key)-1] != '/' { raw := strings.TrimPrefix(v.Key, pre) t, err := time.Parse("2006-01-02T15:04:05.000Z", v.LastModified) if err != nil { log.Print("Couldn't parse time from amazon, assuming 'now' for upload date.") log.Print(err) t = time.Now() } paths = append(paths, Image{ Thumb: fmt.Sprintf("%sthumb-%s", g.S3Prefix, raw), Orig: fmt.Sprintf("%sorig-%s", g.S3Prefix, raw), Hero: fmt.Sprintf("%shero-%s", g.S3Prefix, raw), ETag: v.ETag, LastModified: t, }) } } sort.Sort(ByDate(paths)) return paths, nil }
func GetHiddenGalleries(db sqlx.Ext) ([]Gallery, error) { q := `SELECT * FROM galleries` res := []Gallery{} err := sqlx.Select(db, &res, q) return res, tracederror.New(err) }
func GetGalleries(db sqlx.Ext) ([]Gallery, error) { q := `SELECT * FROM galleries WHERE displayed` res := []Gallery{} err := sqlx.Select(db, &res, q) return res, tracederror.New(err) }
func GetGalleryByID(db sqlx.Ext, id int32) (*Gallery, error) { q := `SELECT * FROM galleries WHERE id=$1` res := Gallery{} err := sqlx.Get(db, &res, q, id) return &res, tracederror.New(err) }
func GetCategories(db sqlx.Ext) ([]BlogCategory, error) { q := ` SELECT * FROM blog_categories ORDER BY id; ` res := []BlogCategory{} err := sqlx.Select(db, &res, q) return res, tracederror.New(err) }
func GetBlogPostByID(db sqlx.Ext, id int32) (*BlogPost, error) { q := ` SELECT p.*, c.category AS category_value FROM blog_posts p JOIN blog_categories c ON c.id = p.category WHERE p.id = $1 ` res := BlogPost{} err := sqlx.Get(db, &res, q, id) return &res, tracederror.New(err) }
func getCategoryArchive(w http.ResponseWriter, r *http.Request, ctx routes.Context) error { vars := mux.Vars(r) page, err := strconv.ParseInt(vars["page"], 10, 32) if err != nil { return tracederror.New(err) } if page <= 0 { return routes.MakeHttpError(fmt.Errorf("Page must be larger than 0"), http.StatusBadRequest, r) } category := vars["category"] valid, err := models.IsValidCategory(ctx.DB, category) if err != nil { return tracederror.New(err) } if !valid { return routes.MakeHttpError(fmt.Errorf("Invalid category %s", category), http.StatusBadRequest, r) } tpl, err := routes.LoadTemplates("base.tpl", "archive.tpl") if err != nil { return routes.MakeHttpError(err, http.StatusNotFound, r) } posts, err := models.GetRecentPostsInCategory(ctx.DB, category, 100, int32((page-1)*100)) if err != nil { return tracederror.New(err) } data := archivePage{ Page: int32(page), Posts: posts, Category: strings.Title(category), } return routes.RenderTemplateWithData(w, r, tpl, data) }
func getEdit(w http.ResponseWriter, r *http.Request, ctx routes.Context) error { err := routes.CheckAuth(r, ctx) if err != nil { return err } vars := mux.Vars(r) id := int64(0) if vars["id"] != "new" { id, err = strconv.ParseInt(vars["id"], 10, 64) if err != nil { return tracederror.New(err) } } post := &models.BlogPost{} if id != 0 { post, err = models.GetBlogPostByID(ctx.DB, int32(id)) if err != nil { return routes.MakeHttpError(err, http.StatusNotFound, r) } } categories, err := models.GetCategories(ctx.DB) if err != nil { return tracederror.New(err) } tpl, err := routes.LoadTemplates("base.tpl", "edit.tpl") if err != nil { return tracederror.New(err) } data := editPage{ Post: post, Categories: categories, } return routes.RenderTemplateWithData(w, r, tpl, &data) }
func IsValidCategory(db sqlx.Ext, category string) (bool, error) { q := `SELECT * FROM blog_categories WHERE category = $1` res := []BlogCategory{} err := sqlx.Select(db, &res, q, category) if err != nil { return false, tracederror.New(err) } return len(res) == 1, nil }
func getPost(w http.ResponseWriter, r *http.Request, ctx routes.Context) error { vars := mux.Vars(r) tpl, err := routes.LoadTemplates("base.tpl", "post.tpl") if err != nil { return tracederror.New(err) } recent, err := models.GetRecentBlogPosts(ctx.DB, 4, 0) if err != nil { return tracederror.New(err) } id, err := strconv.ParseInt(vars["id"], 10, 32) if err != nil { return tracederror.New(err) } self, err := models.GetBlogPostByID(ctx.DB, int32(id)) if err != nil { return tracederror.New(err) } authErr := routes.CheckAuth(r, ctx) if self.Publish == nil && authErr != nil { return routes.MakeHttpError(nil, http.StatusNotFound, r) } if self.Publish != nil && self.Publish.After(time.Now().UTC()) && authErr != nil { return routes.MakeHttpError(nil, http.StatusNotFound, r) } data := postPage{ Post: self, Recent: recent, } return routes.RenderTemplateWithData(w, r, tpl, &data) }
func postRender(w http.ResponseWriter, r *http.Request, ctx routes.Context) error { err := routes.CheckAuth(r, ctx) if err != nil { return err } tpl, err := routes.LoadTemplates("render.tpl") if err != nil { return tracederror.New(err) } body, err := ioutil.ReadAll(r.Body) if err != nil { return tracederror.New(err) } bodyStr := string(body) bodyStr = strings.Replace(bodyStr, "{:truncate}", "", 1) bodyStr = strings.Replace(bodyStr, "{:longtruncate}", "", 1) return routes.RenderTemplateWithData(w, r, tpl, bodyStr) }
func GetRecentBlogPosts(db sqlx.Ext, count int32, offset int32) ([]BlogPost, error) { q := ` SELECT p.*, c.category AS category_value FROM blog_posts p JOIN blog_categories c ON c.id = p.category WHERE publish IS NOT NULL AND NOT c.hidden ORDER BY publish DESC LIMIT $1 OFFSET $2 ` res := []BlogPost{} err := sqlx.Select(db, &res, q, count, offset) return res, tracederror.New(err) }
func importImage(args []string, context *routes.Context) error { //Args in the format // gallery <image> if len(args) < 2 { return fmt.Errorf("usage: <gallery> <image>") } args[0] = strings.TrimSpace(args[0]) log.Print(args) // Step 1: create a sha-256 hash of the file contents. f, err := ioutil.ReadFile(args[1]) if err != nil { return tracederror.New(err) } sum := sha256.Sum256(f) key := base64.URLEncoding.EncodeToString(sum[:]) ext := filepath.Ext(args[1]) m := mime.TypeByExtension(ext) // Step 2: Upload the original file to orig-<sha256>.jpg log.Printf("Uploading %s to %s/%s", args[1], args[0], key) err = context.Bucket.Put(fmt.Sprintf("%s/orig-%s", args[0], key), f, m, s3.PublicRead) if err != nil { return tracederror.New(err) } convbinary := "convert" if runtime.GOOS == "windows" { convbinary = "imgconvert" } // Step 3: Generate thumbnails/hero by cutting it through the center. os.Mkdir("temp", 0777) target := fmt.Sprintf("temp/%s%s", key, ext) cmd := exec.Command(convbinary, args[1], "-gravity", "center", "-resize", "25%", target) _, err = cmd.CombinedOutput() if err != nil { return tracederror.New(err) } f, err = ioutil.ReadFile(target) if err != nil { return tracederror.New(err) } log.Printf("Uploading thumbnail...") err = context.Bucket.Put(fmt.Sprintf("%s/thumb-%s", args[0], key), f, m, s3.PublicRead) if err != nil { return tracederror.New(err) } cmd = exec.Command(convbinary, args[1], "-gravity", "center", "-crop", "1200x400+0+0", target) _, err = cmd.CombinedOutput() if err != nil { return tracederror.New(err) } f, err = ioutil.ReadFile(target) if err != nil { return tracederror.New(err) } log.Printf("Uploading hero...") err = context.Bucket.Put(fmt.Sprintf("%s/hero-%s", args[0], key), f, m, s3.PublicRead) if err != nil { return tracederror.New(err) } os.Remove(target) log.Printf("Cleaning cache") clearCache(args, context) log.Printf("Saving Original Image URL to Clipboard...") url := context.Bucket.URL(fmt.Sprintf("/%s/orig-%s", args[0], key)) clipboard.WriteAll(url) return nil }