GoBlog/blogstats.go

109 lines
3.8 KiB
Go
Raw Normal View History

2021-01-04 19:29:49 +00:00
package main
import (
2021-04-28 18:03:20 +00:00
"database/sql"
2021-01-04 19:29:49 +00:00
"net/http"
2021-04-28 18:03:20 +00:00
servertiming "github.com/mitchellh/go-server-timing"
2021-01-04 19:29:49 +00:00
)
func serveBlogStats(w http.ResponseWriter, r *http.Request) {
blog := r.Context().Value(blogContextKey).(string)
canonical := blogPath(blog) + appConfig.Blogs[blog].BlogStats.Path
render(w, r, templateBlogStats, &renderData{
BlogString: blog,
Canonical: canonical,
Data: map[string]interface{}{
"TableUrl": canonical + ".table.html",
},
})
}
func serveBlogStatsTable(w http.ResponseWriter, r *http.Request) {
blog := r.Context().Value(blogContextKey).(string)
2021-04-28 18:03:20 +00:00
// Start timing
t := servertiming.FromContext(r.Context()).NewMetric("sq").Start()
// Build query
2021-04-23 18:52:12 +00:00
prq := &postsRequestConfig{
blog: blog,
status: statusPublished,
2021-04-23 18:52:12 +00:00
}
query, params := buildPostsQuery(prq)
query = "select path, mdtext(content) as content, published, substr(published, 1, 4) as year, substr(published, 6, 2) as month from (" + query + ")"
2021-04-30 16:42:10 +00:00
postCount := "coalesce(count(distinct path), 0) as postcount"
charCount := "coalesce(sum(coalesce(length(distinct content), 0)), 0)"
wordCount := "coalesce(sum(wordcount(distinct content)), 0) as wordcount"
wordsPerPost := "coalesce(round(wordcount/postcount,0), 0)"
2021-04-28 18:03:20 +00:00
type statsTableType struct {
Name, Posts, Chars, Words, WordsPerPost string
}
// Count total posts
2021-04-28 18:03:20 +00:00
row, err := appDbQueryRow("select *, "+wordsPerPost+" from (select "+postCount+", "+charCount+", "+wordCount+" from ("+query+"))", params...)
if err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
2021-04-28 18:03:20 +00:00
total := statsTableType{}
if err = row.Scan(&total.Posts, &total.Chars, &total.Words, &total.WordsPerPost); err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
// Count posts per year
rows, err := appDbQuery("select *, "+wordsPerPost+" from (select year, "+postCount+", "+charCount+", "+wordCount+" from ("+query+") where published != '' group by year order by year desc)", params...)
if err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
2021-04-28 18:03:20 +00:00
var years []statsTableType
year := statsTableType{}
for rows.Next() {
2021-04-28 18:03:20 +00:00
if err = rows.Scan(&year.Name, &year.Posts, &year.Chars, &year.Words, &year.WordsPerPost); err == nil {
years = append(years, year)
2021-04-23 18:52:12 +00:00
} else {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
}
// Count posts without date
2021-04-28 18:03:20 +00:00
row, err = appDbQueryRow("select *, "+wordsPerPost+" from (select "+postCount+", "+charCount+", "+wordCount+" from ("+query+") where published = '')", params...)
2021-04-23 18:52:12 +00:00
if err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
2021-04-28 18:03:20 +00:00
noDate := statsTableType{}
if err = row.Scan(&noDate.Posts, &noDate.Chars, &noDate.Words, &noDate.WordsPerPost); err != nil {
2021-04-23 18:52:12 +00:00
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
// Count posts per month per year
2021-04-28 18:03:20 +00:00
months := map[string][]statsTableType{}
month := statsTableType{}
2021-04-23 18:52:12 +00:00
for _, year := range years {
rows, err = appDbQuery("select *, "+wordsPerPost+" from (select month, "+postCount+", "+charCount+", "+wordCount+" from ("+query+") where published != '' and year = @year group by month order by month desc)", append(params, sql.Named("year", year.Name))...)
2021-04-23 18:52:12 +00:00
if err != nil {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
for rows.Next() {
2021-04-28 18:03:20 +00:00
if err = rows.Scan(&month.Name, &month.Posts, &month.Chars, &month.Words, &month.WordsPerPost); err == nil {
months[year.Name] = append(months[year.Name], month)
2021-04-23 18:52:12 +00:00
} else {
serveError(w, r, err.Error(), http.StatusInternalServerError)
return
}
2021-01-04 19:29:49 +00:00
}
}
2021-04-28 18:03:20 +00:00
// Stop timing
t.Stop()
// Render
render(w, r, templateBlogStatsTable, &renderData{
BlogString: blog,
Data: map[string]interface{}{
2021-04-28 18:03:20 +00:00
"total": total,
2021-04-23 18:52:12 +00:00
"years": years,
2021-04-28 18:03:20 +00:00
"withoutdate": noDate,
2021-04-23 18:52:12 +00:00
"months": months,
},
})
2021-01-04 19:29:49 +00:00
}