Add blog API
This commit is contained in:
		| @@ -62,6 +62,8 @@ func Start(conf common.Conf, dbO *sql.DB) *gin.Engine { | |||||||
| 			gv1.GET("/tokens", Method(v1.TokenGET)) | 			gv1.GET("/tokens", Method(v1.TokenGET)) | ||||||
| 			gv1.GET("/users/self", Method(v1.UserSelfGET)) | 			gv1.GET("/users/self", Method(v1.UserSelfGET)) | ||||||
| 			gv1.GET("/tokens/self", Method(v1.TokenSelfGET)) | 			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 | 			// ReadConfidential privilege required | ||||||
| 			gv1.GET("/friends", Method(v1.FriendsGET, common.PrivilegeReadConfidential)) | 			gv1.GET("/friends", Method(v1.FriendsGET, common.PrivilegeReadConfidential)) | ||||||
|   | |||||||
							
								
								
									
										87
									
								
								app/v1/blog.go
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								app/v1/blog.go
									
									
									
									
									
										Normal file
									
								
							| @@ -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 | ||||||
|  | } | ||||||
							
								
								
									
										9
									
								
								main.go
									
									
									
									
									
								
							
							
						
						
									
										9
									
								
								main.go
									
									
									
									
									
								
							| @@ -4,6 +4,7 @@ import ( | |||||||
| 	"database/sql" | 	"database/sql" | ||||||
| 	"fmt" | 	"fmt" | ||||||
| 	"log" | 	"log" | ||||||
|  | 	"strings" | ||||||
| 	"syscall" | 	"syscall" | ||||||
|  |  | ||||||
| 	"git.zxq.co/ripple/rippleapi/app" | 	"git.zxq.co/ripple/rippleapi/app" | ||||||
| @@ -39,6 +40,14 @@ func main() { | |||||||
|  |  | ||||||
| 	schiavo.Prefix = "Ripple API" | 	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 | 	var err error | ||||||
| 	db, err = sql.Open(conf.DatabaseType, conf.DSN) | 	db, err = sql.Open(conf.DatabaseType, conf.DSN) | ||||||
| 	if err != nil { | 	if err != nil { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user