package handler import ( "encoding/json" "fmt" "github.com/fogleman/gg" "github.com/golang/freetype" "github.com/golang/freetype/truetype" "github.com/gorilla/feeds" "github.com/gorilla/mux" "golang.org/x/image/font" "golang.org/x/image/font/gofont/goregular" "golang.org/x/image/math/fixed" "html/template" "image" "image/color" "image/draw" "status/model" "strconv" "time" //"image/png" "net/http" ) func (h *Handler) showManageView(w http.ResponseWriter, r *http.Request) { logged, err := h.sess.Get(r) if err != nil { unauthorized(w) return } var page int64 = 0 if val, ok := r.URL.Query()["page"]; ok && len(val[0]) == 1 { page, _ = strconv.ParseInt(val[0], 10, 64) } statuses, showMore, err := h.storage.StatusByUsername(logged, 20, page) if err != nil { serverError(w, err) return } session, err := h.sess.Store.Get(r, "status") if err != nil { http.Error(w, err.Error(), http.StatusInternalServerError) return } flash := "" if flashes := session.Flashes(); len(flashes) > 0 { flash = flashes[0].(string) } session.Save(r, w) h.renderLayout(w, "manage", map[string]interface{}{ "statuses": statuses, "showMore": showMore, "page": page, "flash": flash, "next_page": page + 1, "prev_page": page - 1, }, logged) } func (h *Handler) showUserView(w http.ResponseWriter, r *http.Request) { logged, _ := h.sess.Get(r) var page int64 = 0 if val, ok := r.URL.Query()["page"]; ok && len(val[0]) == 1 { page, _ = strconv.ParseInt(val[0], 10, 64) } username := mux.Vars(r)["user"] user, err := h.storage.UserByName(username) if err != nil { notFound(w) return } statuses, showMore, err := h.storage.StatusByUsername(mux.Vars(r)["user"], 20, page) if err != nil { serverError(w, err) return } h.renderLayout(w, "user", map[string]interface{}{ "user": username, "statuses": statuses, "homepage": user.Homepage, "about": template.HTML(user.About), "picture": user.Picture, "email": user.Email, "showMore": showMore, "page": page, "next_page": page + 1, "prev_page": page - 1, }, logged) } type statusjson struct { Author string `json:"author"` Content string `json:"content"` Face string `json:"face"` TimeAgo string `json:"timeAgo"` } func (h *Handler) showUserStatusJSONView(w http.ResponseWriter, r *http.Request) { user := mux.Vars(r)["user"] if !h.storage.UserExists(user) { notFound(w) return } statuses, _, err := h.storage.StatusByUsername(mux.Vars(r)["user"], 1, 0) if err != nil { serverError(w, err) return } w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Content-Type", "application/json") var res statusjson if len(statuses) > 0 { res.Author = statuses[0].User res.Content = statuses[0].Content res.Face = statuses[0].Face res.TimeAgo = statuses[0].TimeAgo() } json.NewEncoder(w).Encode(res) } func (h *Handler) showUserStatusView(w http.ResponseWriter, r *http.Request) { statuses, _, err := h.storage.StatusByUsername(mux.Vars(r)["user"], 1, 0) if err != nil { serverError(w, err) return } var status model.Status if len(statuses) > 0 { status = statuses[0] } h.view("status").Execute(w, map[string]interface{}{"status": status}) } func drawText(canvas *image.RGBA, text string) error { var ( fgColor image.Image fontFace *truetype.Font err error fontSize = 12.0 ) fgColor = image.White fontFace, err = freetype.ParseFont(goregular.TTF) fontDrawer := &font.Drawer{ Dst: canvas, Src: fgColor, Face: truetype.NewFace(fontFace, &truetype.Options{ Size: fontSize, Hinting: font.HintingFull, }), } //textBounds, _ := fontDrawer.BoundString(text) xPosition := fixed.I(20) //textHeight := textBounds.Max.Y - textBounds.Min.Y yPosition := fixed.I(20) fontDrawer.Dot = fixed.Point26_6{ X: xPosition, Y: yPosition, } fontDrawer.DrawString(text) return err } func createAvatar(text string) *image.RGBA { bgColor := color.RGBA{ R: 255, G: 20, B: 100, A: 255, } background := image.NewRGBA(image.Rect(0, 0, 200, 100)) draw.Draw(background, background.Bounds(), &image.Uniform{C: bgColor}, image.Point{}, draw.Src) drawText(background, text) return background } func (h *Handler) showUserStatusBadgeView(w http.ResponseWriter, r *http.Request) { user := mux.Vars(r)["user"] if !h.storage.UserExists(user) { notFound(w) return } statuses, _, err := h.storage.StatusByUsername(mux.Vars(r)["user"], 1, 0) if err != nil { serverError(w, err) return } var username string if len(statuses) > 0 { username = statuses[0].User } background := "#f0ffff" dc := gg.NewContext(88, 31) dc.SetHexColor(background) dc.Clear() dc.SetHexColor("#191970") font, err := truetype.Parse(goregular.TTF) if err != nil { panic("") } face := truetype.NewFace(font, &truetype.Options{ Size: 12, }) dc.SetFontFace(face) if err != nil { fmt.Println(err) } //dc.DrawString(username, 10, 14) dc.DrawStringAnchored(username, 88/2, 8, 0.5, 0.5) dc.DrawStringAnchored("status.cafe", 88/2, 20, 0.5, 0.5) dc.EncodePNG(w) } func (h *Handler) showUserStatusImageView(w http.ResponseWriter, r *http.Request) { user := mux.Vars(r)["user"] if !h.storage.UserExists(user) { notFound(w) return } statuses, _, err := h.storage.StatusByUsername(mux.Vars(r)["user"], 1, 0) if err != nil { serverError(w, err) return } //w.Header().Set("Access-Control-Allow-Origin", "*") //w.Header().Set("Content-Type", "application/json") var text string if len(statuses) > 0 { text = statuses[0].Content } background := "#ffffff" foreground := "#000000" if c := r.URL.Query().Get("background"); c != "" { background = "#" + c } if c := r.URL.Query().Get("foreground"); c != "" { foreground = "#" + c } width := 125 dc := gg.NewContext(width, 125) dc.SetHexColor(background) dc.Clear() dc.SetHexColor(foreground) font, err := truetype.Parse(goregular.TTF) if err != nil { panic("") } face := truetype.NewFace(font, &truetype.Options{ Size: 9, }) dc.SetFontFace(face) if err != nil { fmt.Println(err) } dc.DrawStringWrapped(text, 8, 4, 0, 0, float64(width-(2*8)), 1.5, gg.AlignLeft) dc.EncodePNG(w) //dc.SavePNG("out.png") //avatar := createAvatar(text) //png.Encode(w, avatar) } func truncate(s string, max int) string { if len(s) > max { return s[:max] + "..." } return s } func (h *Handler) showAtomView(w http.ResponseWriter, r *http.Request) { username := mux.Vars(r)["user"] user, err := h.storage.UserByName(username) if err != nil { notFound(w) return } now := time.Now() feed := &feeds.Feed{ Title: user.Name, Link: &feeds.Link{Href: fmt.Sprintf("https://status.cafe/users/%s", username)}, // TODO change the scheme? Author: &feeds.Author{Name: user.Name, Email: "todo@todo.com"}, // TODO EMAIL Created: now, } statuses, _, err := h.storage.StatusByUsername(user.Name, 20, 0) if err != nil { serverError(w, err) return } for _, status := range statuses { if err != nil { serverError(w, err) return } feed.Items = append(feed.Items, &feeds.Item{ Title: fmt.Sprintf("%s - %s", status.User, truncate(status.Content, 50)), Link: &feeds.Link{Href: fmt.Sprintf("https://status.cafe/users/%s/%d", username, status.Id)}, Author: &feeds.Author{Name: user.Name}, Content: status.Content, Created: status.CreatedAt, }) } atom, err := feed.ToAtom() if err != nil { serverError(w, err) return } w.Header().Set("Access-Control-Allow-Origin", "*") w.Header().Set("Content-Type", "application/atom+xml") w.Write([]byte(atom)) }