From 52743017a36b811014ff10f66cda94d3e7929f70 Mon Sep 17 00:00:00 2001 From: Steven Date: Fri, 15 Dec 2023 07:32:49 +0800 Subject: [PATCH] chore: implement memo route --- .gitignore | 1 + server/frontend/frontend.go | 57 ++++++++++++++++++++++++++++++++++--- server/server.go | 10 +++---- 3 files changed, 58 insertions(+), 10 deletions(-) diff --git a/.gitignore b/.gitignore index 9b988506..4a6159e4 100644 --- a/.gitignore +++ b/.gitignore @@ -6,6 +6,7 @@ tmp # Frontend asset web/dist +server/frontend/dist # build folder build diff --git a/server/frontend/frontend.go b/server/frontend/frontend.go index d1e9b943..81eea94c 100644 --- a/server/frontend/frontend.go +++ b/server/frontend/frontend.go @@ -2,6 +2,7 @@ package frontend import ( "embed" + "fmt" "io/fs" "net/http" "strings" @@ -10,6 +11,8 @@ import ( "github.com/labstack/echo/v4/middleware" "github.com/usememos/memos/internal/util" + "github.com/usememos/memos/server/profile" + "github.com/usememos/memos/store" ) //go:embed dist @@ -18,7 +21,19 @@ var embeddedFiles embed.FS //go:embed dist/index.html var rawIndexHTML string -func Serve(e *echo.Echo) { +type FrontendService struct { + Profile *profile.Profile + Store *store.Store +} + +func NewFrontendService(profile *profile.Profile, store *store.Store) *FrontendService { + return &FrontendService{ + Profile: profile, + Store: store, + } +} + +func (s *FrontendService) Serve(e *echo.Echo) { // Use echo static middleware to serve the built dist folder // refer: https://github.com/labstack/echo/blob/master/middleware/static.go e.Use(middleware.StaticWithConfig(middleware.StaticConfig{ @@ -44,16 +59,50 @@ func Serve(e *echo.Echo) { Filesystem: getFileSystem("dist/assets"), })) - registerRoutes(e) + s.registerRoutes(e) } -func registerRoutes(e *echo.Echo) { +func (s *FrontendService) registerRoutes(e *echo.Echo) { e.GET("/m/:memoID", func(c echo.Context) error { - indexHTML := strings.ReplaceAll(rawIndexHTML, "", ""+"\n") + ctx := c.Request().Context() + memoID, err := util.ConvertStringToInt32(c.Param("memoID")) + if err != nil { + return echo.NewHTTPError(http.StatusBadRequest, "invalid memo id") + } + + memo, err := s.Store.GetMemo(ctx, &store.FindMemo{ + ID: &memoID, + }) + if err != nil { + return echo.NewHTTPError(http.StatusInternalServerError, "failed to retrieve memo") + } + if memo == nil { + return echo.NewHTTPError(http.StatusNotFound, "memo not found") + } + if memo.Visibility != store.Public { + return echo.NewHTTPError(http.StatusForbidden, "memo is not public") + } + indexHTML := strings.ReplaceAll(rawIndexHTML, "", generateMemoMetadata(memo)) return c.HTML(http.StatusOK, indexHTML) }) } +func generateMemoMetadata(memo *store.Memo) string { + metadataList := []string{ + fmt.Sprintf(``, memo.Content), + fmt.Sprintf(``, fmt.Sprintf("Memos - %d", memo.ID)), + fmt.Sprintf(``, memo.Content), + fmt.Sprintf(``, "https://www.usememos.com/logo.png"), + ``, + // Twitter related metadata. + fmt.Sprintf(``, fmt.Sprintf("Memos - %d", memo.ID)), + fmt.Sprintf(``, memo.Content), + fmt.Sprintf(``, "https://www.usememos.com/logo.png"), + ``, + } + return strings.Join(metadataList, "\n") +} + func getFileSystem(path string) http.FileSystem { fs, err := fs.Sub(embeddedFiles, path) if err != nil { diff --git a/server/server.go b/server/server.go index 93585fae..aed33630 100644 --- a/server/server.go +++ b/server/server.go @@ -33,9 +33,6 @@ type Server struct { Profile *profile.Profile Store *store.Store - // API services. - apiV2Service *apiv2.APIV2Service - // Asynchronous runners. backupRunner *backup.BackupRunner telegramBot *telegram.Bot @@ -84,7 +81,8 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store s.ID = serverID // Serve frontend. - frontend.Serve(e) + frontendService := frontend.NewFrontendService(profile, store) + frontendService.Serve(e) // Serve swagger in dev/demo mode. if profile.Mode == "dev" || profile.Mode == "demo" { @@ -110,9 +108,9 @@ func NewServer(ctx context.Context, profile *profile.Profile, store *store.Store apiV1Service := apiv1.NewAPIV1Service(s.Secret, profile, store, s.telegramBot) apiV1Service.Register(rootGroup) - s.apiV2Service = apiv2.NewAPIV2Service(s.Secret, profile, store, s.Profile.Port+1) + apiV2Service := apiv2.NewAPIV2Service(s.Secret, profile, store, s.Profile.Port+1) // Register gRPC gateway as api v2. - if err := s.apiV2Service.RegisterGateway(ctx, e); err != nil { + if err := apiV2Service.RegisterGateway(ctx, e); err != nil { return nil, errors.Wrap(err, "failed to register gRPC gateway") }