diff --git a/config.go b/config.go index 4e14fb4..c55d13b 100644 --- a/config.go +++ b/config.go @@ -63,6 +63,7 @@ type configBlog struct { CustomPages []*customPage `mapstructure:"custompages"` Telegram *configTelegram `mapstructure:"telegram"` PostAsHome bool `mapstructure:"postAsHome"` + RandomPost *randomPost `mapstructure:"randomPost"` } type section struct { @@ -118,6 +119,11 @@ type customPage struct { Data *interface{} `mapstructure:"data"` } +type randomPost struct { + Enabled bool `mapstructure:"enabled"` + Path string `mapstructure:"path"` +} + type configUser struct { Nick string `mapstructure:"nick"` Name string `mapstructure:"name"` diff --git a/go.mod b/go.mod index b0b0862..a0ed8d9 100644 --- a/go.mod +++ b/go.mod @@ -57,12 +57,11 @@ require ( golang.org/x/crypto v0.0.0-20201221181555-eec23a3978ad // indirect golang.org/x/lint v0.0.0-20201208152925-83fdc39ff7b5 // indirect golang.org/x/mod v0.4.1 // indirect - golang.org/x/net v0.0.0-20201224014010-6772e930b67b // indirect + golang.org/x/net v0.0.0-20210119194325-5f4716e94777 // indirect golang.org/x/sync v0.0.0-20201207232520-09787c993a3a - golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78 // indirect golang.org/x/term v0.0.0-20201210144234-2321bbc49cbf // indirect golang.org/x/text v0.3.5 // indirect - golang.org/x/tools v0.0.0-20210115202250-e0d201561e39 // indirect + golang.org/x/tools v0.1.0 // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect diff --git a/go.sum b/go.sum index eccaf24..3da62d0 100644 --- a/go.sum +++ b/go.sum @@ -418,8 +418,8 @@ golang.org/x/net v0.0.0-20200202094626-16171245cfb2/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200707034311-ab3426394381/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b h1:iFwSg7t5GZmB/Q5TjiEAsdoLDrdJRC1RiF2WhuV29Qw= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777 h1:003p0dJM77cxMSyCPFphvZf/Y5/NXf5fzg6ufd1/Oew= +golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -456,8 +456,8 @@ golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c h1:UIcGWL6/wpCfyGuJnRFJRurA+ golang.org/x/sys v0.0.0-20200724161237-0e2f3a69832c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78 h1:nVuTkr9L6Bq62qpUqKo/RnZCFfzDBL0bYo6w9OJUqZY= -golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4 h1:myAQVi0cGEoqQVR5POX+8RR2mrocKqNN1hmeMqhX27k= +golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221 h1:/ZHdbVpdR/jk3g30/d4yUL0JU9kksj8+F/bnQUVLGDM= golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -497,8 +497,8 @@ golang.org/x/tools v0.0.0-20191216052735-49a3e744a425 h1:VvQyQJN0tSuecqgcIxMWnnf golang.org/x/tools v0.0.0-20191216052735-49a3e744a425/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapKDTa4BR/hXlZSLoq2Wpct/0txZ28= golang.org/x/tools v0.0.0-20200609164405-eb789aa7ce50/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE= -golang.org/x/tools v0.0.0-20210115202250-e0d201561e39 h1:BTs2GMGSMWpgtCpv1CE7vkJTv7XcHdcLLnAMu7UbgTY= -golang.org/x/tools v0.0.0-20210115202250-e0d201561e39/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= +golang.org/x/tools v0.1.0 h1:po9/4sTYwZU9lPhi1tOrb4hCv3qrhiQ77LZfGa2OjwY= +golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4= diff --git a/http.go b/http.go index 0a1c5ec..dadc000 100644 --- a/http.go +++ b/http.go @@ -319,6 +319,15 @@ func buildHandler() (http.Handler, error) { } } + // Random post + if rp := blogConfig.RandomPost; rp != nil && rp.Enabled { + randomPath := rp.Path + if randomPath == "" { + randomPath = "/random" + } + r.Get(blogPath+randomPath, redirectToRandomPost(blog)) + } + // Editor r.Route(blogPath+"/editor", func(mpRouter chi.Router) { mpRouter.Use(middleware.NoCache, minifier.Middleware, authMiddleware) diff --git a/posts.go b/posts.go index e363bba..6cb99fd 100644 --- a/posts.go +++ b/posts.go @@ -73,6 +73,17 @@ func servePost(w http.ResponseWriter, r *http.Request) { }) } +func redirectToRandomPost(blog string) func(http.ResponseWriter, *http.Request) { + return func(rw http.ResponseWriter, r *http.Request) { + randomPath, err := getRandomPostPath(blog) + if err != nil { + serveError(rw, r, err.Error(), http.StatusInternalServerError) + return + } + http.Redirect(rw, r, randomPath, http.StatusFound) + } +} + type postPaginationAdapter struct { config *postsRequestConfig nums int64 diff --git a/postsDb.go b/postsDb.go index ec25d39..e253a15 100644 --- a/postsDb.go +++ b/postsDb.go @@ -242,6 +242,20 @@ func getPost(path string) (*post, error) { return posts[0], nil } +func getRandomPostPath(blog string) (string, error) { + var sections []string + for sectionKey := range appConfig.Blogs[blog].Sections { + sections = append(sections, sectionKey) + } + posts, err := getPosts(&postsRequestConfig{randomOrder: true, limit: 1, blog: blog, sections: sections}) + if err != nil { + return "", err + } else if len(posts) == 0 { + return "", errPostNotFound + } + return posts[0].Path, nil +} + type postsRequestConfig struct { search string blog string @@ -255,6 +269,7 @@ type postsRequestConfig struct { parameter string parameterValue string publishedYear, publishedMonth, publishedDay int + randomOrder bool } func buildQuery(config *postsRequestConfig) (query string, args []interface{}) { @@ -313,6 +328,9 @@ func buildQuery(config *postsRequestConfig) (query string, args []interface{}) { } defaultTables := " from " + postsTable + " p left outer join post_parameters pp on p.path = pp.path " defaultSorting := " order by p.published desc " + if config.randomOrder { + defaultSorting = " order by random() " + } if config.path != "" { query = defaultSelection + defaultTables + " where p.path = @path" + defaultSorting args = append(args, sql.Named("path", config.path))