From 0abe20df725b1394a1e1c4bec7629e5420aa4eeb Mon Sep 17 00:00:00 2001 From: Mehad Nadeem <34424878+MehadND@users.noreply.github.com> Date: Wed, 13 Mar 2024 14:31:53 +0500 Subject: [PATCH] feat: implemented link previews (server files) (#3073) * feat: implmented link previews (server files) * chore: updated variable name * chore: renamed service file from `metadata_service.go` to `link_service.go` * fix: passing errors * fix: fixed linter warnong about `ctx` --- server/route/api/v2/apidocs.swagger.yaml | 156 ++++++++++------------- server/route/api/v2/link_service.go | 25 ++++ server/route/api/v2/v2.go | 5 + 3 files changed, 95 insertions(+), 91 deletions(-) create mode 100644 server/route/api/v2/link_service.go diff --git a/server/route/api/v2/apidocs.swagger.yaml b/server/route/api/v2/apidocs.swagger.yaml index 30e653c4..0880e423 100644 --- a/server/route/api/v2/apidocs.swagger.yaml +++ b/server/route/api/v2/apidocs.swagger.yaml @@ -7,6 +7,7 @@ tags: - name: UserService - name: AuthService - name: InboxService + - name: LinkService - name: ResourceService - name: MemoService - name: TagService @@ -171,16 +172,12 @@ paths: type: integer format: int32 - name: pageToken - description: |- - A page token, received from a previous `ListMemos` call. - Provide this to retrieve the subsequent page. + description: "A page token, received from a previous `ListMemos` call.\r\nProvide this to retrieve the subsequent page." in: query required: false type: string - name: filter - description: |- - Filter is used to filter memos returned in the list. - Format: "creator == users/{username} && visibilities == ['PUBLIC', 'PROTECTED']" + description: "Filter is used to filter memos returned in the list.\r\nFormat: \"creator == users/{username} && visibilities == ['PUBLIC', 'PROTECTED']\"" in: query required: false type: string @@ -241,17 +238,12 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: name - description: |- - name is the name of the user to get stats for. - Format: users/{username} + description: "name is the name of the user to get stats for.\r\nFormat: users/{username}" in: query required: false type: string - name: timezone - description: |- - timezone location - Format: uses tz identifier - https://en.wikipedia.org/wiki/List_of_tz_database_time_zones + description: "timezone location\r\nFormat: uses tz identifier\r\nhttps://en.wikipedia.org/wiki/List_of_tz_database_time_zones" in: query required: false type: string @@ -583,9 +575,7 @@ paths: $ref: '#/definitions/apiv2RowStatus' creator: type: string - title: |- - The name of the creator. - Format: users/{username} + title: "The name of the creator.\r\nFormat: users/{username}" creatorId: type: integer format: int32 @@ -649,6 +639,25 @@ paths: type: string tags: - MemoService + /api/v2/metadata: + get: + operationId: LinkService_GetLinkMetadata + responses: + "200": + description: A successful response. + schema: + $ref: '#/definitions/v2GetLinkMetadataResponse' + default: + description: An unexpected error response. + schema: + $ref: '#/definitions/googlerpcStatus' + parameters: + - name: url + in: query + required: false + type: string + tags: + - LinkService /api/v2/resources: get: summary: ListResources lists all resources. @@ -818,9 +827,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: user - description: |- - The creator of tags. - Format: users/{username} + description: "The creator of tags.\r\nFormat: users/{username}" in: query required: false type: string @@ -844,9 +851,7 @@ paths: required: false type: string - name: tag.creator - description: |- - The creator of tags. - Format: users/{username} + description: "The creator of tags.\r\nFormat: users/{username}" in: query required: false type: string @@ -886,9 +891,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: user - description: |- - The creator of tags. - Format: users/{username} + description: "The creator of tags.\r\nFormat: users/{username}" in: query required: false type: string @@ -911,9 +914,7 @@ paths: - TagService /api/v2/tags:rename: patch: - summary: |- - RenameTag renames a tag. - All related memos will be updated. + summary: "RenameTag renames a tag.\r\nAll related memos will be updated." operationId: TagService_RenameTag responses: "200": @@ -926,9 +927,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: user - description: |- - The creator of tags. - Format: users/{username} + description: "The creator of tags.\r\nFormat: users/{username}" in: query required: false type: string @@ -1131,9 +1130,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: name - description: |- - The resource name of the workspace setting. - Format: settings/{setting} + description: "The resource name of the workspace setting.\r\nFormat: settings/{setting}" in: path required: true type: string @@ -1155,9 +1152,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: setting.name - description: |- - name is the name of the setting. - Format: settings/{setting} + description: "name is the name of the setting.\r\nFormat: settings/{setting}" in: path required: true type: string @@ -1190,9 +1185,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: inbox.name - description: |- - The name of the inbox. - Format: inboxes/{uid} + description: "The name of the inbox.\r\nFormat: inboxes/{uid}" in: path required: true type: string @@ -1236,9 +1229,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: name_1 - description: |- - The name of the inbox to delete. - Format: inboxes/{uid} + description: "The name of the inbox to delete.\r\nFormat: inboxes/{uid}" in: path required: true type: string @@ -1260,9 +1251,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: name - description: |- - The name of the user. - Format: users/{username} + description: "The name of the user.\r\nFormat: users/{username}" in: path required: true type: string @@ -1283,9 +1272,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: name - description: |- - The name of the user. - Format: users/{username} + description: "The name of the user.\r\nFormat: users/{username}" in: path required: true type: string @@ -1307,9 +1294,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: name - description: |- - The name of the user. - Format: users/{username} + description: "The name of the user.\r\nFormat: users/{username}" in: path required: true type: string @@ -1330,9 +1315,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: name - description: |- - The name of the user. - Format: users/{username} + description: "The name of the user.\r\nFormat: users/{username}" in: path required: true type: string @@ -1359,9 +1342,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: name - description: |- - The name of the user. - Format: users/{username} + description: "The name of the user.\r\nFormat: users/{username}" in: path required: true type: string @@ -1388,9 +1369,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: name - description: |- - The name of the user. - Format: users/{username} + description: "The name of the user.\r\nFormat: users/{username}" in: path required: true type: string @@ -1412,9 +1391,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: setting.name - description: |- - The name of the user. - Format: users/{username} + description: "The name of the user.\r\nFormat: users/{username}" in: path required: true type: string @@ -1454,9 +1431,7 @@ paths: $ref: '#/definitions/googlerpcStatus' parameters: - name: user.name - description: |- - The name of the user. - Format: users/{username} + description: "The name of the user.\r\nFormat: users/{username}" in: path required: true type: string @@ -1608,9 +1583,7 @@ definitions: properties: name: type: string - title: |- - The name of the user. - Format: users/{username} + title: "The name of the user.\r\nFormat: users/{username}" locale: type: string description: The preferred locale of the user. @@ -1667,9 +1640,7 @@ definitions: properties: name: type: string - title: |- - name is the name of the setting. - Format: settings/{setting} + title: "name is the name of the setting.\r\nFormat: settings/{setting}" generalSetting: $ref: '#/definitions/apiv2WorkspaceGeneralSetting' description: general_setting is the general setting of workspace. @@ -1788,6 +1759,11 @@ definitions: properties: user: $ref: '#/definitions/v2User' + v2GetLinkMetadataResponse: + type: object + properties: + metadata: + $ref: '#/definitions/v2Metadata' v2GetMemoByNameResponse: type: object properties: @@ -1823,9 +1799,7 @@ definitions: additionalProperties: type: integer format: int32 - description: |- - stats is the stats of memo creating/updating activities. - key is the year-month-day string. e.g. "2020-01-01". + description: "stats is the stats of memo creating/updating activities.\r\nkey is the year-month-day string. e.g. \"2020-01-01\"." v2GetUserResponse: type: object properties: @@ -1856,9 +1830,7 @@ definitions: properties: name: type: string - title: |- - The name of the inbox. - Format: inboxes/{uid} + title: "The name of the inbox.\r\nFormat: inboxes/{uid}" sender: type: string title: 'Format: users/{username}' @@ -1939,9 +1911,7 @@ definitions: $ref: '#/definitions/v2Memo' nextPageToken: type: string - description: |- - A token, which can be sent as `page_token` to retrieve the next page. - If this field is omitted, there are no subsequent pages. + description: "A token, which can be sent as `page_token` to retrieve the next page.\r\nIf this field is omitted, there are no subsequent pages." v2ListResourcesResponse: type: object properties: @@ -1996,9 +1966,7 @@ definitions: $ref: '#/definitions/apiv2RowStatus' creator: type: string - title: |- - The name of the creator. - Format: users/{username} + title: "The name of the creator.\r\nFormat: users/{username}" creatorId: type: integer format: int32 @@ -2057,6 +2025,16 @@ definitions: - REFERENCE - COMMENT default: TYPE_UNSPECIFIED + v2Metadata: + type: object + properties: + title: + type: string + description: + type: string + image: + type: string + title: Metadata message v2RenameTagResponse: type: object properties: @@ -2120,9 +2098,7 @@ definitions: type: string creator: type: string - title: |- - The creator of tags. - Format: users/{username} + title: "The creator of tags.\r\nFormat: users/{username}" v2UpdateInboxResponse: type: object properties: @@ -2173,9 +2149,7 @@ definitions: properties: name: type: string - title: |- - The name of the user. - Format: users/{username} + title: "The name of the user.\r\nFormat: users/{username}" id: type: integer format: int32 diff --git a/server/route/api/v2/link_service.go b/server/route/api/v2/link_service.go new file mode 100644 index 00000000..ade87872 --- /dev/null +++ b/server/route/api/v2/link_service.go @@ -0,0 +1,25 @@ +package v2 + +import ( + "context" + + getter "github.com/usememos/memos/plugin/http-getter" + apiv2pb "github.com/usememos/memos/proto/gen/api/v2" +) + +func (*APIV2Service) GetMetadata(_ context.Context, request *apiv2pb.GetLinkMetadataRequest) (*apiv2pb.GetLinkMetadataResponse, error) { + urlStr := request.Url + + htmlMeta, err := getter.GetHTMLMeta(urlStr) + if err != nil { + return nil, err + } + + return &apiv2pb.GetLinkMetadataResponse{ + Metadata: &apiv2pb.Metadata{ + Title: htmlMeta.Title, + Description: htmlMeta.Description, + Image: htmlMeta.Image, + }, + }, nil +} diff --git a/server/route/api/v2/v2.go b/server/route/api/v2/v2.go index e416a3ee..ced8b2f2 100644 --- a/server/route/api/v2/v2.go +++ b/server/route/api/v2/v2.go @@ -30,6 +30,7 @@ type APIV2Service struct { apiv2pb.UnimplementedInboxServiceServer apiv2pb.UnimplementedActivityServiceServer apiv2pb.UnimplementedWebhookServiceServer + apiv2pb.UnimplementedLinkServiceServer Secret string Profile *profile.Profile @@ -66,6 +67,7 @@ func NewAPIV2Service(secret string, profile *profile.Profile, store *store.Store apiv2pb.RegisterInboxServiceServer(grpcServer, apiv2Service) apiv2pb.RegisterActivityServiceServer(grpcServer, apiv2Service) apiv2pb.RegisterWebhookServiceServer(grpcServer, apiv2Service) + apiv2pb.RegisterLinkServiceServer(grpcServer, apiv2Service) reflection.Register(grpcServer) return apiv2Service @@ -119,6 +121,9 @@ func (s *APIV2Service) RegisterGateway(ctx context.Context, e *echo.Echo) error if err := apiv2pb.RegisterWebhookServiceHandler(context.Background(), gwMux, conn); err != nil { return err } + if err := apiv2pb.RegisterLinkServiceHandler(context.Background(), gwMux, conn); err != nil { + return err + } e.Any("/api/v2/*", echo.WrapHandler(gwMux)) // GRPC web proxy.