mirror of
https://github.com/usememos/memos.git
synced 2025-06-05 22:09:59 +02:00
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`
This commit is contained in:
@@ -7,6 +7,7 @@ tags:
|
|||||||
- name: UserService
|
- name: UserService
|
||||||
- name: AuthService
|
- name: AuthService
|
||||||
- name: InboxService
|
- name: InboxService
|
||||||
|
- name: LinkService
|
||||||
- name: ResourceService
|
- name: ResourceService
|
||||||
- name: MemoService
|
- name: MemoService
|
||||||
- name: TagService
|
- name: TagService
|
||||||
@@ -171,16 +172,12 @@ paths:
|
|||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
- name: pageToken
|
- name: pageToken
|
||||||
description: |-
|
description: "A page token, received from a previous `ListMemos` call.\r\nProvide this to retrieve the subsequent page."
|
||||||
A page token, received from a previous `ListMemos` call.
|
|
||||||
Provide this to retrieve the subsequent page.
|
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
- name: filter
|
- name: filter
|
||||||
description: |-
|
description: "Filter is used to filter memos returned in the list.\r\nFormat: \"creator == users/{username} && visibilities == ['PUBLIC', 'PROTECTED']\""
|
||||||
Filter is used to filter memos returned in the list.
|
|
||||||
Format: "creator == users/{username} && visibilities == ['PUBLIC', 'PROTECTED']"
|
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
@@ -241,17 +238,12 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: name
|
- name: name
|
||||||
description: |-
|
description: "name is the name of the user to get stats for.\r\nFormat: users/{username}"
|
||||||
name is the name of the user to get stats for.
|
|
||||||
Format: users/{username}
|
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
- name: timezone
|
- name: timezone
|
||||||
description: |-
|
description: "timezone location\r\nFormat: uses tz identifier\r\nhttps://en.wikipedia.org/wiki/List_of_tz_database_time_zones"
|
||||||
timezone location
|
|
||||||
Format: uses tz identifier
|
|
||||||
https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
@@ -583,9 +575,7 @@ paths:
|
|||||||
$ref: '#/definitions/apiv2RowStatus'
|
$ref: '#/definitions/apiv2RowStatus'
|
||||||
creator:
|
creator:
|
||||||
type: string
|
type: string
|
||||||
title: |-
|
title: "The name of the creator.\r\nFormat: users/{username}"
|
||||||
The name of the creator.
|
|
||||||
Format: users/{username}
|
|
||||||
creatorId:
|
creatorId:
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
@@ -649,6 +639,25 @@ paths:
|
|||||||
type: string
|
type: string
|
||||||
tags:
|
tags:
|
||||||
- MemoService
|
- 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:
|
/api/v2/resources:
|
||||||
get:
|
get:
|
||||||
summary: ListResources lists all resources.
|
summary: ListResources lists all resources.
|
||||||
@@ -818,9 +827,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: user
|
- name: user
|
||||||
description: |-
|
description: "The creator of tags.\r\nFormat: users/{username}"
|
||||||
The creator of tags.
|
|
||||||
Format: users/{username}
|
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
@@ -844,9 +851,7 @@ paths:
|
|||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
- name: tag.creator
|
- name: tag.creator
|
||||||
description: |-
|
description: "The creator of tags.\r\nFormat: users/{username}"
|
||||||
The creator of tags.
|
|
||||||
Format: users/{username}
|
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
@@ -886,9 +891,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: user
|
- name: user
|
||||||
description: |-
|
description: "The creator of tags.\r\nFormat: users/{username}"
|
||||||
The creator of tags.
|
|
||||||
Format: users/{username}
|
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
@@ -911,9 +914,7 @@ paths:
|
|||||||
- TagService
|
- TagService
|
||||||
/api/v2/tags:rename:
|
/api/v2/tags:rename:
|
||||||
patch:
|
patch:
|
||||||
summary: |-
|
summary: "RenameTag renames a tag.\r\nAll related memos will be updated."
|
||||||
RenameTag renames a tag.
|
|
||||||
All related memos will be updated.
|
|
||||||
operationId: TagService_RenameTag
|
operationId: TagService_RenameTag
|
||||||
responses:
|
responses:
|
||||||
"200":
|
"200":
|
||||||
@@ -926,9 +927,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: user
|
- name: user
|
||||||
description: |-
|
description: "The creator of tags.\r\nFormat: users/{username}"
|
||||||
The creator of tags.
|
|
||||||
Format: users/{username}
|
|
||||||
in: query
|
in: query
|
||||||
required: false
|
required: false
|
||||||
type: string
|
type: string
|
||||||
@@ -1131,9 +1130,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: name
|
- name: name
|
||||||
description: |-
|
description: "The resource name of the workspace setting.\r\nFormat: settings/{setting}"
|
||||||
The resource name of the workspace setting.
|
|
||||||
Format: settings/{setting}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1155,9 +1152,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: setting.name
|
- name: setting.name
|
||||||
description: |-
|
description: "name is the name of the setting.\r\nFormat: settings/{setting}"
|
||||||
name is the name of the setting.
|
|
||||||
Format: settings/{setting}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1190,9 +1185,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: inbox.name
|
- name: inbox.name
|
||||||
description: |-
|
description: "The name of the inbox.\r\nFormat: inboxes/{uid}"
|
||||||
The name of the inbox.
|
|
||||||
Format: inboxes/{uid}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1236,9 +1229,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: name_1
|
- name: name_1
|
||||||
description: |-
|
description: "The name of the inbox to delete.\r\nFormat: inboxes/{uid}"
|
||||||
The name of the inbox to delete.
|
|
||||||
Format: inboxes/{uid}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1260,9 +1251,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: name
|
- name: name
|
||||||
description: |-
|
description: "The name of the user.\r\nFormat: users/{username}"
|
||||||
The name of the user.
|
|
||||||
Format: users/{username}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1283,9 +1272,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: name
|
- name: name
|
||||||
description: |-
|
description: "The name of the user.\r\nFormat: users/{username}"
|
||||||
The name of the user.
|
|
||||||
Format: users/{username}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1307,9 +1294,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: name
|
- name: name
|
||||||
description: |-
|
description: "The name of the user.\r\nFormat: users/{username}"
|
||||||
The name of the user.
|
|
||||||
Format: users/{username}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1330,9 +1315,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: name
|
- name: name
|
||||||
description: |-
|
description: "The name of the user.\r\nFormat: users/{username}"
|
||||||
The name of the user.
|
|
||||||
Format: users/{username}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1359,9 +1342,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: name
|
- name: name
|
||||||
description: |-
|
description: "The name of the user.\r\nFormat: users/{username}"
|
||||||
The name of the user.
|
|
||||||
Format: users/{username}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1388,9 +1369,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: name
|
- name: name
|
||||||
description: |-
|
description: "The name of the user.\r\nFormat: users/{username}"
|
||||||
The name of the user.
|
|
||||||
Format: users/{username}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1412,9 +1391,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: setting.name
|
- name: setting.name
|
||||||
description: |-
|
description: "The name of the user.\r\nFormat: users/{username}"
|
||||||
The name of the user.
|
|
||||||
Format: users/{username}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1454,9 +1431,7 @@ paths:
|
|||||||
$ref: '#/definitions/googlerpcStatus'
|
$ref: '#/definitions/googlerpcStatus'
|
||||||
parameters:
|
parameters:
|
||||||
- name: user.name
|
- name: user.name
|
||||||
description: |-
|
description: "The name of the user.\r\nFormat: users/{username}"
|
||||||
The name of the user.
|
|
||||||
Format: users/{username}
|
|
||||||
in: path
|
in: path
|
||||||
required: true
|
required: true
|
||||||
type: string
|
type: string
|
||||||
@@ -1608,9 +1583,7 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
title: |-
|
title: "The name of the user.\r\nFormat: users/{username}"
|
||||||
The name of the user.
|
|
||||||
Format: users/{username}
|
|
||||||
locale:
|
locale:
|
||||||
type: string
|
type: string
|
||||||
description: The preferred locale of the user.
|
description: The preferred locale of the user.
|
||||||
@@ -1667,9 +1640,7 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
title: |-
|
title: "name is the name of the setting.\r\nFormat: settings/{setting}"
|
||||||
name is the name of the setting.
|
|
||||||
Format: settings/{setting}
|
|
||||||
generalSetting:
|
generalSetting:
|
||||||
$ref: '#/definitions/apiv2WorkspaceGeneralSetting'
|
$ref: '#/definitions/apiv2WorkspaceGeneralSetting'
|
||||||
description: general_setting is the general setting of workspace.
|
description: general_setting is the general setting of workspace.
|
||||||
@@ -1788,6 +1759,11 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
user:
|
user:
|
||||||
$ref: '#/definitions/v2User'
|
$ref: '#/definitions/v2User'
|
||||||
|
v2GetLinkMetadataResponse:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
metadata:
|
||||||
|
$ref: '#/definitions/v2Metadata'
|
||||||
v2GetMemoByNameResponse:
|
v2GetMemoByNameResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -1823,9 +1799,7 @@ definitions:
|
|||||||
additionalProperties:
|
additionalProperties:
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
description: |-
|
description: "stats is the stats of memo creating/updating activities.\r\nkey is the year-month-day string. e.g. \"2020-01-01\"."
|
||||||
stats is the stats of memo creating/updating activities.
|
|
||||||
key is the year-month-day string. e.g. "2020-01-01".
|
|
||||||
v2GetUserResponse:
|
v2GetUserResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -1856,9 +1830,7 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
title: |-
|
title: "The name of the inbox.\r\nFormat: inboxes/{uid}"
|
||||||
The name of the inbox.
|
|
||||||
Format: inboxes/{uid}
|
|
||||||
sender:
|
sender:
|
||||||
type: string
|
type: string
|
||||||
title: 'Format: users/{username}'
|
title: 'Format: users/{username}'
|
||||||
@@ -1939,9 +1911,7 @@ definitions:
|
|||||||
$ref: '#/definitions/v2Memo'
|
$ref: '#/definitions/v2Memo'
|
||||||
nextPageToken:
|
nextPageToken:
|
||||||
type: string
|
type: string
|
||||||
description: |-
|
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."
|
||||||
A token, which can be sent as `page_token` to retrieve the next page.
|
|
||||||
If this field is omitted, there are no subsequent pages.
|
|
||||||
v2ListResourcesResponse:
|
v2ListResourcesResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -1996,9 +1966,7 @@ definitions:
|
|||||||
$ref: '#/definitions/apiv2RowStatus'
|
$ref: '#/definitions/apiv2RowStatus'
|
||||||
creator:
|
creator:
|
||||||
type: string
|
type: string
|
||||||
title: |-
|
title: "The name of the creator.\r\nFormat: users/{username}"
|
||||||
The name of the creator.
|
|
||||||
Format: users/{username}
|
|
||||||
creatorId:
|
creatorId:
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
@@ -2057,6 +2025,16 @@ definitions:
|
|||||||
- REFERENCE
|
- REFERENCE
|
||||||
- COMMENT
|
- COMMENT
|
||||||
default: TYPE_UNSPECIFIED
|
default: TYPE_UNSPECIFIED
|
||||||
|
v2Metadata:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
title:
|
||||||
|
type: string
|
||||||
|
description:
|
||||||
|
type: string
|
||||||
|
image:
|
||||||
|
type: string
|
||||||
|
title: Metadata message
|
||||||
v2RenameTagResponse:
|
v2RenameTagResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -2120,9 +2098,7 @@ definitions:
|
|||||||
type: string
|
type: string
|
||||||
creator:
|
creator:
|
||||||
type: string
|
type: string
|
||||||
title: |-
|
title: "The creator of tags.\r\nFormat: users/{username}"
|
||||||
The creator of tags.
|
|
||||||
Format: users/{username}
|
|
||||||
v2UpdateInboxResponse:
|
v2UpdateInboxResponse:
|
||||||
type: object
|
type: object
|
||||||
properties:
|
properties:
|
||||||
@@ -2173,9 +2149,7 @@ definitions:
|
|||||||
properties:
|
properties:
|
||||||
name:
|
name:
|
||||||
type: string
|
type: string
|
||||||
title: |-
|
title: "The name of the user.\r\nFormat: users/{username}"
|
||||||
The name of the user.
|
|
||||||
Format: users/{username}
|
|
||||||
id:
|
id:
|
||||||
type: integer
|
type: integer
|
||||||
format: int32
|
format: int32
|
||||||
|
25
server/route/api/v2/link_service.go
Normal file
25
server/route/api/v2/link_service.go
Normal file
@@ -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
|
||||||
|
}
|
@@ -30,6 +30,7 @@ type APIV2Service struct {
|
|||||||
apiv2pb.UnimplementedInboxServiceServer
|
apiv2pb.UnimplementedInboxServiceServer
|
||||||
apiv2pb.UnimplementedActivityServiceServer
|
apiv2pb.UnimplementedActivityServiceServer
|
||||||
apiv2pb.UnimplementedWebhookServiceServer
|
apiv2pb.UnimplementedWebhookServiceServer
|
||||||
|
apiv2pb.UnimplementedLinkServiceServer
|
||||||
|
|
||||||
Secret string
|
Secret string
|
||||||
Profile *profile.Profile
|
Profile *profile.Profile
|
||||||
@@ -66,6 +67,7 @@ func NewAPIV2Service(secret string, profile *profile.Profile, store *store.Store
|
|||||||
apiv2pb.RegisterInboxServiceServer(grpcServer, apiv2Service)
|
apiv2pb.RegisterInboxServiceServer(grpcServer, apiv2Service)
|
||||||
apiv2pb.RegisterActivityServiceServer(grpcServer, apiv2Service)
|
apiv2pb.RegisterActivityServiceServer(grpcServer, apiv2Service)
|
||||||
apiv2pb.RegisterWebhookServiceServer(grpcServer, apiv2Service)
|
apiv2pb.RegisterWebhookServiceServer(grpcServer, apiv2Service)
|
||||||
|
apiv2pb.RegisterLinkServiceServer(grpcServer, apiv2Service)
|
||||||
reflection.Register(grpcServer)
|
reflection.Register(grpcServer)
|
||||||
|
|
||||||
return apiv2Service
|
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 {
|
if err := apiv2pb.RegisterWebhookServiceHandler(context.Background(), gwMux, conn); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if err := apiv2pb.RegisterLinkServiceHandler(context.Background(), gwMux, conn); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
e.Any("/api/v2/*", echo.WrapHandler(gwMux))
|
e.Any("/api/v2/*", echo.WrapHandler(gwMux))
|
||||||
|
|
||||||
// GRPC web proxy.
|
// GRPC web proxy.
|
||||||
|
Reference in New Issue
Block a user