예제 #1
0
func std_layout(blog_config map[string]interface{}, f func(w http.ResponseWriter, req *http.Request)) func(w http.ResponseWriter, req *http.Request) {

	p := func(w http.ResponseWriter, req *http.Request) {
		appcontext := appengine.NewContext(req)
		myurl, err := realhostname(req, appcontext)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		scheme := "http://"
		if req.TLS != nil {
			scheme = "https://"
		}
		context := map[string]interface{}{"app_url": scheme + myurl + config.Stringify(blog_config["blog_root"])}

		bloginfo := config.Stringify_map(config.Merge(blog_config, context))

		start := time.Now()
		template_dir := "templates/"

		h := mustache.RenderFile(template_dir+"header.html.mustache", bloginfo)
		io.WriteString(w, h)

		f(w, req)

		sidebar(w, req, blog_config)

		delta := time.Since(start).Seconds()

		timing := map[string]interface{}{"timing": fmt.Sprintf("%0.2fs", delta)}
		if delta > 0.100 {
			timing["slow_code"] = "true"
		}

		u := user.Current(appcontext)
		if u != nil {
			logout, err := user.LogoutURL(appcontext, "/")
			if err != nil {
				http.Error(w, "error generating logout URL!", http.StatusInternalServerError)
				appcontext.Errorf("user.LogoutURL: %v", err)
				return
			}
			timing["me"] = fmt.Sprintf("%s", u)
			timing["logout"] = logout
		}

		bloginfo = config.Stringify_map(config.Merge(blog_config, timing))
		f := mustache.RenderFile(template_dir+"footer.html.mustache", bloginfo)
		io.WriteString(w, f)
	}

	return p
}
예제 #2
0
func GetSitemap(blog_config map[string]interface{}) func(w http.ResponseWriter, req *http.Request) {
	template_dir := "templates/"
	l := func(w http.ResponseWriter, req *http.Request) {
		appcontext := appengine.NewContext(req)

		myurl, err := realhostname(req, appcontext)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		scheme := "http://"
		if req.TLS != nil {
			scheme = "https://"
		}

		urlprefix := scheme + myurl + config.Stringify(blog_config["blog_root"])

		postchan := make(chan post.Post, 16)
		errchan := make(chan error)
		go post.ExecuteQuery(appcontext, post.GetAllPosts(), -1, -1, post.NullFilter, postchan, errchan)

		entries := bytes.NewBufferString("")

		me_context := map[string]interface{}{"url": urlprefix,
			"lastmod_date": post.GetLatestDate(appcontext).Format("2006-01-02")}
		me_total_con := config.Stringify_map(config.Merge(blog_config, me_context))
		me_c := mustache.RenderFile(template_dir+"sitemap_entry.mustache", me_total_con)
		io.WriteString(entries, me_c)
		for p := range postchan {
			context := map[string]interface{}{"url": urlprefix + "article/" + p.StickyUrl,
				"lastmod_date": p.Postdate.Format("2006-01-02")}
			total_con := config.Stringify_map(config.Merge(blog_config, context))
			c := mustache.RenderFile(template_dir+"sitemap_entry.mustache", total_con)
			io.WriteString(entries, c)
		}

		err, ok := <-errchan
		if ok {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		context := map[string]interface{}{"content": entries}
		total_con := config.Stringify_map(config.Merge(blog_config, context))
		c := mustache.RenderFile(template_dir+"sitemap.mustache", total_con)
		io.WriteString(w, c)
	}
	return l
}
예제 #3
0
func entrybar(blog_config map[string]interface{}, w http.ResponseWriter, req *http.Request) {
	template_dir := "templates/"
	appcontext := appengine.NewContext(req)
	myurl, err := realhostname(req, appcontext)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
	scheme := "http://"
	if req.TLS != nil {
		scheme = "https://"
	}

	urlprefix := scheme + myurl + config.Stringify(blog_config["blog_root"])

	postchan := make(chan post.Post, 16)
	errchan := make(chan error)
	go post.ExecuteQuery(appcontext, post.GetAllPosts(), -1, -1, func(post.Post) bool { return true }, postchan, errchan)

	for p := range postchan {
		context := map[string]interface{}{"url": urlprefix + "article/" + p.StickyUrl,
			"lastmod_date": p.Postdate.Format("2006-01-02")}
		total_con := config.Stringify_map(config.Merge(blog_config, context))
		c := mustache.RenderFile(template_dir+"edit_entrybar.html.mustache", total_con)
		io.WriteString(w, c)
	}

	err, ok := <-errchan
	if ok {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}
}
예제 #4
0
func sidebar(w http.ResponseWriter, req *http.Request, blog_config map[string]interface{}) {
	template_dir := "templates/"

	sidebar_links := bytes.NewBufferString("")

	context := map[string]interface{}{"label_link": "http://qrunk.com",
		"label_title": "qrunk.com"}
	total_con := config.Stringify_map(config.Merge(blog_config, context))
	c := mustache.RenderFile(template_dir+"sidebar_entry.html.mustache", total_con)
	io.WriteString(sidebar_links, c)

	sidebar_topics := bytes.NewBufferString("")

	appcontext := appengine.NewContext(req)
	tags, counts, err := post.GetAllTags(appcontext)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	for i := range tags {
		n, count := tags[i], counts[i]
		context = map[string]interface{}{"label_link": "/label/" + n,
			"label_title": n,
			"label_count": fmt.Sprintf("%v", count)}
		total_con = config.Stringify_map(config.Merge(blog_config, context))
		c = mustache.RenderFile(template_dir+"sidebar_entry.html.mustache", total_con)
		io.WriteString(sidebar_topics, c)
	}

	context = map[string]interface{}{"sidebar_links": string(sidebar_links.Bytes()),
		"sidebar_topics": string(sidebar_topics.Bytes())}
	total_con = config.Stringify_map(config.Merge(blog_config, context))
	c = mustache.RenderFile(template_dir+"sidebar.html.mustache", total_con)
	io.WriteString(w, c)
}
예제 #5
0
func LabelList(blog_config map[string]interface{}, url_stem string) func(w http.ResponseWriter, req *http.Request) {
	limit, err := getLimit(blog_config)
	if err != nil {
		panic(err)
	}

	l := func(w http.ResponseWriter, req *http.Request) {
		label := req.URL.Query().Get(":label")
		context := map[string]interface{}{"search_label": label}
		total_con := config.Merge(blog_config, context)
		q := func(w http.ResponseWriter, req *http.Request) {
			list(w, req, total_con, url_stem, 0, limit, post.GetPostsMatchingTagCurried(label))
		}
		std_layout(total_con, q)(w, req)
	}

	return l
}
예제 #6
0
func LabelPage(blog_config map[string]interface{}, url_stem string) func(w http.ResponseWriter, req *http.Request) {
	l := func(w http.ResponseWriter, req *http.Request) {
		label := req.URL.Query().Get(":label")
		context := map[string]interface{}{"search_label": label}
		total_con := config.Merge(blog_config, context)
		q := func(w http.ResponseWriter, req *http.Request) {
			limit, err := getLimit(blog_config)
			if err != nil {
				panic(err)
			}
			offset, err := getOffset(req, limit, ":page")
			if err != nil {
				http.Error(w, "bad request: "+err.Error(), http.StatusBadRequest)
				return
			} else {
				list(w, req, total_con, url_stem, offset, limit, post.GetPostsMatchingTagCurried(label))
			}
		}
		std_layout(total_con, q)(w, req)
	}

	return l
}
예제 #7
0
func list(w http.ResponseWriter, req *http.Request, blog_config map[string]interface{}, url_stem string, offset int, limit int, keygen func(appengine.Context) ([]*datastore.Key, error)) {

	appcontext := appengine.NewContext(req)
	template_dir := "templates/"
	postchan := make(chan post.FullPost, 16)
	errchan := make(chan error)

	keys, err := keygen(appcontext)
	if err != nil {
		http.Error(w, err.Error(), http.StatusInternalServerError)
		return
	}

	idx := len(keys)

	pages := idx / limit
	if (idx % limit) > 0 {
		pages += 1
	}

	curpage := offset / limit

	if idx < 1 {
		io.WriteString(w, fmt.Sprintf("<div class=\"entry\"><p>no posts found :(</p></div>"))
	} else {
		//go post.ExecuteQuery(appcontext, query, offset, limit, postchan, errchan)
		go post.GetPosts(appcontext, keys, offset, limit, postchan, errchan)

		myurl, err := realhostname(req, appcontext)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		scheme := "http://"
		if req.TLS != nil {
			scheme = "https://"
		}

		urlprefix := scheme + myurl + config.Stringify(blog_config["blog_root"])

		for p := range postchan {
			con := bytes.NewBuffer(blackfriday.MarkdownCommon(bytes.NewBufferString(p.Content).Bytes())).String()
			context := map[string]interface{}{"c": con, "labels": labels(p.Post.Tags, blog_config),
				"link_to_entry": urlprefix + "article/" + p.Post.StickyUrl,
				"post_date":     p.Post.Postdate.Format("Jan 02 2006"),
				"post_title":    p.Post.Title}
			total_con := config.Stringify_map(config.Merge(blog_config, context))
			c := mustache.RenderFile(template_dir+"list_entry.html.mustache", total_con)
			io.WriteString(w, c)
		}

		err, ok := <-errchan
		if ok {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		context := map[string]interface{}{}

		root := config.Stringify(blog_config["blog_root"])

		context["prev_page"] = "&lt;&lt; prev"
		context["next_page"] = "next &gt;&gt;"

		if pages > 1 {
			context["pb"] = "true"
		}
		if curpage > 0 {
			context["prev_page"] = fmt.Sprintf("<a href=\"%v%v/%v\">&lt;&lt; prev</a>", root, url_stem, curpage-1)
		}
		if curpage < (pages - 1) {
			context["next_page"] = fmt.Sprintf("<a href=\"%v%v/%v\">next &gt;&gt;</a>", root, url_stem, curpage+1)
		}

		total_con := config.Stringify_map(config.Merge(blog_config, context))
		c := mustache.RenderFile(template_dir+"list.html.mustache", total_con)
		io.WriteString(w, c)
	}
}
예제 #8
0
func EditPost(blog_config map[string]interface{}) func(w http.ResponseWriter, req *http.Request) {
	template_dir := "templates/"
	l := func(w http.ResponseWriter, req *http.Request) {
		appcontext := appengine.NewContext(req)

		context := map[string]interface{}{}

		name := req.URL.Query().Get(":name")
		if name != "" {
			query := post.GetPostsMatchingUrl(req.URL.Query().Get(":name"))
			idx, err := post.GetCount(appcontext, query)

			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
			}

			if idx < 1 {
				context["articlesource"] = "Enter your post here!"
				context["labels"] = "visible"
				context["title"] = "No post with that URL found, making new post!"
			} else {
				var ps []post.Post
				keys, err := query.GetAll(appcontext, &ps)
				if err != nil {
					http.Error(w, err.Error(), http.StatusInternalServerError)
				}

				p := ps[0]
				tags, err := post.GetTagSlice(appcontext, keys[0])
				if err != nil {
					http.Error(w, err.Error(), http.StatusInternalServerError)
				}

				content, err := post.GetPostContent(appcontext, p)
				if err != nil {
					http.Error(w, err.Error(), http.StatusInternalServerError)
				}

				context["articlesource"] = content
				context["labels"] = strings.Join(tags, ", ")
				context["title"] = p.Title
			}
		} else {
			context["articlesource"] = "Enter your post here!"
			context["labels"] = "visible, enter, labels, here"
			context["title"] = "enter title here"
		}

		key := fmt.Sprintf("%v", rand.Int())
		tok, err := channel.Create(appcontext, key)
		if err != nil {
			http.Error(w, "Couldn't create Channel", http.StatusInternalServerError)
			appcontext.Errorf("channel.Create: %v", err)
			return
		}

		posturl := "/admin/post?g=" + key
		uploadurl, err := blobstore.UploadURL(appcontext, posturl, nil)
		if err != nil {
			http.Error(w, "Couldn't create blob URL", http.StatusInternalServerError)
			appcontext.Errorf("blobstore.UploadURL: %v", err)
			return
		}

		context["token"] = tok
		context["session"] = key
		context["uploadurl"] = uploadurl

		total_con := config.Stringify_map(config.Merge(blog_config, context))
		c := mustache.RenderFile(template_dir+"edit.html.mustache", total_con)
		io.WriteString(w, c)

		if err != nil {
			appcontext.Errorf("mainTemplate: %v", err)
		}
	}
	return admin_layout(blog_config, l)
}
예제 #9
0
func GetRSS(blog_config map[string]interface{}) func(w http.ResponseWriter, req *http.Request) {
	template_dir := "templates/"
	l := func(w http.ResponseWriter, req *http.Request) {
		limit, err := getLimit(blog_config)
		if err != nil {
			panic(err)
		}

		appcontext := appengine.NewContext(req)

		myurl, err := realhostname(req, appcontext)
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}
		scheme := "http://"
		if req.TLS != nil {
			scheme = "https://"
		}

		urlprefix := scheme + myurl + config.Stringify(blog_config["blog_root"])

		keys, err := post.GetPostsMatchingTag(appcontext, "visible")
		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		idx := len(keys)

		offset := 0

		entries := new(bytes.Buffer)
		if idx >= 1 {
			postchan := make(chan post.FullPost, 16)
			errchan := make(chan error)

			go post.GetPosts(appcontext, keys, offset, limit, postchan, errchan)
			for p := range postchan {
				con := bytes.NewBuffer(blackfriday.MarkdownCommon(bytes.NewBufferString(p.Content).Bytes())).String()
				context := map[string]interface{}{"c": con,
					"link_to_entry": urlprefix + "article/" + p.Post.StickyUrl,
					"post_date":     p.Post.Postdate.Format("Jan 02 2006"),
					"post_title":    p.Post.Title}
				total_con := config.Stringify_map(config.Merge(blog_config, context))
				c := mustache.RenderFile(template_dir+"rss_entry.html.mustache", total_con)
				io.WriteString(entries, c)
			}
			err, ok := <-errchan
			if ok {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}

		}

		context := map[string]interface{}{
			"lastmod_date": post.GetLatestDate(appcontext).Format("2006-01-02"),
			"content":      entries,
		}

		total_con := config.Stringify_map(config.Merge(blog_config, context))
		c := mustache.RenderFile(template_dir+"rss.mustache", total_con)
		io.WriteString(w, c)
	}
	return l
}
예제 #10
0
func GetArticle(blog_config map[string]interface{}, url_stem string) func(w http.ResponseWriter, req *http.Request) {
	template_dir := "templates/"
	l := func(w http.ResponseWriter, req *http.Request) {
		appcontext := appengine.NewContext(req)
		query := post.GetPostsMatchingUrl(req.URL.Query().Get(":name"))
		idx, err := post.GetCount(appcontext, query)

		if err != nil {
			http.Error(w, err.Error(), http.StatusInternalServerError)
			return
		}

		if idx < 1 {
			http.Error(w, err.Error(), http.StatusNotFound)
			io.WriteString(w, fmt.Sprintf("<div class=\"entry\"><p>no posts found :(</p></div>"))
			return
		} else {

			myurl, err := realhostname(req, appcontext)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}
			scheme := "http://"
			if req.TLS != nil {
				scheme = "https://"
			}

			urlprefix := scheme + myurl + config.Stringify(blog_config["blog_root"])

			var ps []post.Post
			keys, err := query.GetAll(appcontext, &ps)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}

			p := ps[0]
			tags, err := post.GetTagSlice(appcontext, keys[0])
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				return
			}

			content, err := post.GetPostContent(appcontext, p)
			if err != nil {
				http.Error(w, err.Error(), http.StatusInternalServerError)
				appcontext.Errorf("post.GetPostContent: %v", err)
				return
			}
			con := bytes.NewBuffer(blackfriday.MarkdownCommon(bytes.NewBufferString(content).Bytes())).String()
			context := map[string]interface{}{"c": con, "labels": labels(tags, blog_config),
				"link_to_entry":   urlprefix + "article/" + p.StickyUrl,
				"comment_display": "none",
				"post_date":       p.Postdate.Format("Oct 02 2006"),
				"post_title":      p.Title}
			total_con := config.Stringify_map(config.Merge(blog_config, context))
			c := mustache.RenderFile(template_dir+"entry.html.mustache", total_con)
			io.WriteString(w, c)
		}
	}
	return std_layout(blog_config, l)
}