From 921402b0eedfd0756ca3740466f3a2badc9adc43 Mon Sep 17 00:00:00 2001 From: Howl Date: Thu, 7 Jul 2016 00:20:36 +0200 Subject: [PATCH] Add blog API --- app/start.go | 2 ++ app/v1/blog.go | 87 ++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 9 ++++++ 3 files changed, 98 insertions(+) create mode 100644 app/v1/blog.go diff --git a/app/start.go b/app/start.go index bc0850b..6806a54 100644 --- a/app/start.go +++ b/app/start.go @@ -62,6 +62,8 @@ func Start(conf common.Conf, dbO *sql.DB) *gin.Engine { gv1.GET("/tokens", Method(v1.TokenGET)) gv1.GET("/users/self", Method(v1.UserSelfGET)) gv1.GET("/tokens/self", Method(v1.TokenSelfGET)) + gv1.GET("/blog/posts", Method(v1.BlogPostsGET)) + gv1.GET("/blog/posts/content", Method(v1.BlogPostsContentGET)) // ReadConfidential privilege required gv1.GET("/friends", Method(v1.FriendsGET, common.PrivilegeReadConfidential)) diff --git a/app/v1/blog.go b/app/v1/blog.go new file mode 100644 index 0000000..30ca9ab --- /dev/null +++ b/app/v1/blog.go @@ -0,0 +1,87 @@ +package v1 + +import ( + "time" + + "git.zxq.co/ripple/rippleapi/common" +) + +type blogPost struct { + ID int `json:"id"` + Title string `json:"title"` + Slug string `json:"slug"` + Created time.Time `json:"created"` + Author userData `json:"author"` +} + +type blogPostsResponse struct { + common.ResponseBase + Posts []blogPost `json:"posts"` +} + +// BlogPostsGET retrieves the latest blog posts on the Ripple blog. +func BlogPostsGET(md common.MethodData) common.CodeMessager { + var and string + var params []interface{} + if md.C.Query("id") != "" { + and = "b.id = ?" + params = append(params, md.C.Query("id")) + } + rows, err := md.DB.Query(` + SELECT + b.id, b.title, b.slug, b.created, + + u.id, u.username, s.username_aka, u.register_datetime, + u.privileges, u.latest_activity, s.country + FROM anchor_posts b + LEFT JOIN users u ON b.author = u.id + LEFT JOIN users_stats s ON b.author = s.id + WHERE status = "published" `+and+` + ORDER BY b.id DESC `+common.Paginate(md.C.Query("p"), md.C.Query("l"), 50), params...) + if err != nil { + md.Err(err) + return Err500 + } + + var r blogPostsResponse + for rows.Next() { + var post blogPost + err := rows.Scan( + &post.ID, &post.Title, &post.Slug, &post.Created, + + &post.Author.ID, &post.Author.Username, &post.Author.UsernameAKA, &post.Author.RegisteredOn, + &post.Author.Privileges, &post.Author.LatestActivity, &post.Author.Country, + ) + if err != nil { + md.Err(err) + continue + } + r.Posts = append(r.Posts, post) + } + r.Code = 200 + + return r +} + +type blogPostContent struct { + common.ResponseBase + Content string `json:"content"` +} + +// BlogPostsContentGET retrieves the content of a specific blog post. +func BlogPostsContentGET(md common.MethodData) common.CodeMessager { + field := "markdown" + if _, present := md.C.GetQuery("html"); present { + field = "html" + } + if md.C.Query("id") == "" { + return ErrMissingField("id") + } + var r blogPostContent + err := md.DB.QueryRow("SELECT "+field+" FROM anchor_posts WHERE id = ? AND status = 'published'", md.C.Query("id")).Scan(&r.Content) + if err != nil { + return common.SimpleResponse(404, "no blog post found") + } + r.Code = 200 + return r +} diff --git a/main.go b/main.go index a09463d..49cd8c2 100644 --- a/main.go +++ b/main.go @@ -4,6 +4,7 @@ import ( "database/sql" "fmt" "log" + "strings" "syscall" "git.zxq.co/ripple/rippleapi/app" @@ -39,6 +40,14 @@ func main() { schiavo.Prefix = "Ripple API" + if !strings.Contains(conf.DSN, "parseTime=true") { + c := "?" + if strings.Contains(conf.DSN, "?") { + c = "&" + } + conf.DSN += c + "parseTime=true" + } + var err error db, err = sql.Open(conf.DatabaseType, conf.DSN) if err != nil {