diff --git a/src/hmnurl/urls.go b/src/hmnurl/urls.go index d677fc2..f2be182 100644 --- a/src/hmnurl/urls.go +++ b/src/hmnurl/urls.go @@ -433,6 +433,8 @@ func BuildForumPostReply(projectSlug string, subforums []string, threadId int, p return ProjectUrl(builder.String(), nil, projectSlug) } +var RegexWikiArticle = regexp.MustCompile(`^/wiki/(?P\d+)(-([^/]+))?$`) + /* * Blog */ diff --git a/src/website/forums.go b/src/website/forums.go index 15dbca8..9751ff5 100644 --- a/src/website/forums.go +++ b/src/website/forums.go @@ -2,6 +2,7 @@ package website import ( "context" + "errors" "fmt" "net/http" "strconv" @@ -851,6 +852,41 @@ func ForumPostDeleteSubmit(c *RequestContext) ResponseData { } } +func WikiArticleRedirect(c *RequestContext) ResponseData { + threadIdStr := c.PathParams["threadid"] + threadId, err := strconv.Atoi(threadIdStr) + if err != nil { + panic(err) + } + + ithread, err := db.QueryOne(c.Context(), c.Conn, models.Thread{}, + ` + SELECT $columns + FROM handmade_thread + WHERE + id = $1 + AND project_id = $2 + AND NOT deleted + `, + threadId, + c.CurrentProject.ID, + ) + if errors.Is(err, db.ErrNoMatchingRows) { + return FourOhFour(c) + } else if err != nil { + return c.ErrorResponse(http.StatusInternalServerError, oops.New(err, "failed to look up wiki thread")) + } + thread := ithread.(*models.Thread) + + c.Perf.StartBlock("SQL", "Fetch subforum tree") + subforumTree := models.GetFullSubforumTree(c.Context(), c.Conn) + lineageBuilder := models.MakeSubforumLineageBuilder(subforumTree) + c.Perf.EndBlock() + + dest := UrlForGenericThread(thread, lineageBuilder, c.CurrentProject.Slug) + return c.Redirect(dest, http.StatusFound) +} + type commonForumData struct { c *RequestContext diff --git a/src/website/post_helper.go b/src/website/post_helper.go index 767c9f8..8c8fb76 100644 --- a/src/website/post_helper.go +++ b/src/website/post_helper.go @@ -6,7 +6,18 @@ import ( "git.handmade.network/hmn/hmn/src/templates" ) -// NOTE(asaf): Please don't use this if you already know the kind of the post beforehand. Just call the appropriate build function. +// NOTE(asaf): Please don't use these if you already know the kind of the thread beforehand. Just call the appropriate build function. +func UrlForGenericThread(thread *models.Thread, lineageBuilder *models.SubforumLineageBuilder, projectSlug string) string { + switch thread.Type { + case models.ThreadTypeProjectBlogPost: + return hmnurl.BuildBlogThread(projectSlug, thread.ID, thread.Title) + case models.ThreadTypeForumPost: + return hmnurl.BuildForumThread(projectSlug, lineageBuilder.GetSubforumLineageSlugs(*thread.SubforumID), thread.ID, thread.Title, 1) + } + + return hmnurl.BuildProjectHomepage(projectSlug) +} + func UrlForGenericPost(thread *models.Thread, post *models.Post, lineageBuilder *models.SubforumLineageBuilder, projectSlug string) string { switch post.ThreadType { case models.ThreadTypeProjectBlogPost: diff --git a/src/website/routes.go b/src/website/routes.go index ee74dbb..0aeef1f 100644 --- a/src/website/routes.go +++ b/src/website/routes.go @@ -211,6 +211,7 @@ func NewWebsiteRoutes(longRequestContext context.Context, conn *pgxpool.Pool, pe mainRoutes.POST(hmnurl.RegexForumPostEdit, authMiddleware(csrfMiddleware(ForumPostEditSubmit))) mainRoutes.GET(hmnurl.RegexForumPostDelete, authMiddleware(ForumPostDelete)) mainRoutes.POST(hmnurl.RegexForumPostDelete, authMiddleware(csrfMiddleware(ForumPostDeleteSubmit))) + mainRoutes.GET(hmnurl.RegexWikiArticle, WikiArticleRedirect) mainRoutes.GET(hmnurl.RegexBlog, BlogIndex) mainRoutes.GET(hmnurl.RegexBlogNewThread, authMiddleware(BlogNewThread))