Unverified Commit 57dd1fc4 authored by boojack's avatar boojack Committed by GitHub

chore: initial memo service definition (#2077)

* chore: initial memo service definition

* chore: update

* chore: update

* chore: update
parent 7c5296cf
package v1
import (
"encoding/json"
"net/http"
"time"
echosse "github.com/CorrectRoadH/echo-sse"
"github.com/PullRequestInc/go-gpt3"
"github.com/labstack/echo/v4"
"github.com/usememos/memos/plugin/openai"
"github.com/usememos/memos/store"
)
func (s *APIV1Service) registerOpenAIRoutes(g *echo.Group) {
g.POST("/openai/chat-completion", func(c echo.Context) error {
ctx := c.Request().Context()
openAIConfigSetting, err := s.Store.GetSystemSetting(ctx, &store.FindSystemSetting{
Name: SystemSettingOpenAIConfigName.String(),
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find openai key").SetInternal(err)
}
openAIConfig := OpenAIConfig{}
if openAIConfigSetting != nil {
err = json.Unmarshal([]byte(openAIConfigSetting.Value), &openAIConfig)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal openai system setting value").SetInternal(err)
}
}
if openAIConfig.Key == "" {
return echo.NewHTTPError(http.StatusBadRequest, "OpenAI API key not set")
}
messages := []openai.ChatCompletionMessage{}
if err := json.NewDecoder(c.Request().Body).Decode(&messages); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post chat completion request").SetInternal(err)
}
if len(messages) == 0 {
return echo.NewHTTPError(http.StatusBadRequest, "No messages provided")
}
result, err := openai.PostChatCompletion(messages, openAIConfig.Key, openAIConfig.Host)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to post chat completion").SetInternal(err)
}
return c.JSON(http.StatusOK, result)
})
g.POST("/openai/chat-streaming", func(c echo.Context) error {
messages := []gpt3.ChatCompletionRequestMessage{}
if err := json.NewDecoder(c.Request().Body).Decode(&messages); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, "Malformatted post chat completion request").SetInternal(err)
}
if len(messages) == 0 {
return echo.NewHTTPError(http.StatusBadRequest, "No messages provided")
}
ctx := c.Request().Context()
openAIConfigSetting, err := s.Store.GetSystemSetting(ctx, &store.FindSystemSetting{
Name: SystemSettingOpenAIConfigName.String(),
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find openai key").SetInternal(err)
}
openAIConfig := OpenAIConfig{}
if openAIConfigSetting != nil {
err = json.Unmarshal([]byte(openAIConfigSetting.Value), &openAIConfig)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal openai system setting value").SetInternal(err)
}
}
if openAIConfig.Key == "" {
return echo.NewHTTPError(http.StatusBadRequest, "OpenAI API key not set")
}
sse := echosse.NewSSEClint(c)
// to do these things in server may not elegant.
// But move it to openai plugin will break the simple. Because it is a streaming. We must use a channel to do it.
// And we can think it is a forward proxy. So it in here is not a bad idea.
client := gpt3.NewClient(openAIConfig.Key)
err = client.ChatCompletionStream(ctx, gpt3.ChatCompletionRequest{
Model: gpt3.GPT3Dot5Turbo,
Messages: messages,
Stream: true,
},
func(resp *gpt3.ChatCompletionStreamResponse) {
// _ is for to pass the golangci-lint check
_ = sse.SendEvent(resp.Choices[0].Delta.Content)
// to delay 0.5 s
time.Sleep(50 * time.Millisecond)
// the delay is a very good way to make the chatbot more comfortable
// otherwise the chatbot will reply too fast. Believe me it is not good.🤔
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to chat with OpenAI").SetInternal(err)
}
return nil
})
g.GET("/openai/enabled", func(c echo.Context) error {
ctx := c.Request().Context()
openAIConfigSetting, err := s.Store.GetSystemSetting(ctx, &store.FindSystemSetting{
Name: SystemSettingOpenAIConfigName.String(),
})
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to find openai key").SetInternal(err)
}
openAIConfig := OpenAIConfig{}
if openAIConfigSetting != nil {
err = json.Unmarshal([]byte(openAIConfigSetting.Value), &openAIConfig)
if err != nil {
return echo.NewHTTPError(http.StatusInternalServerError, "Failed to unmarshal openai system setting value").SetInternal(err)
}
}
if openAIConfig.Key == "" {
return echo.NewHTTPError(http.StatusBadRequest, "OpenAI API key not set")
}
return c.JSON(http.StatusOK, openAIConfig.Key != "")
})
}
......@@ -42,7 +42,6 @@ func (s *APIV1Service) Register(rootGroup *echo.Group) {
s.registerMemoOrganizerRoutes(apiV1Group)
s.registerMemoResourceRoutes(apiV1Group)
s.registerMemoRelationRoutes(apiV1Group)
s.registerOpenAIRoutes(apiV1Group)
// Register public routes.
publicGroup := rootGroup.Group("/o")
......
......@@ -18,8 +18,18 @@ import (
"google.golang.org/grpc/status"
)
// ContextKey is the key type of context value.
type ContextKey int
const (
// The key name used to store user id in the context
// user id is extracted from the jwt token subject field.
UserIDContextKey ContextKey = iota
)
var authenticationAllowlistMethods = map[string]bool{
"/memos.api.v2.UserService/GetUser": true,
"/memos.api.v2.MemoService/ListMemos": true,
}
// IsAuthenticationAllowed returns whether the method is exempted from authentication.
......@@ -30,15 +40,6 @@ func IsAuthenticationAllowed(fullMethodName string) bool {
return authenticationAllowlistMethods[fullMethodName]
}
// ContextKey is the key type of context value.
type ContextKey int
const (
// The key name used to store user id in the context
// user id is extracted from the jwt token subject field.
UserIDContextKey ContextKey = iota
)
// GRPCAuthInterceptor is the auth interceptor for gRPC server.
type GRPCAuthInterceptor struct {
store *store.Store
......
package v2
import (
"context"
"github.com/google/cel-go/cel"
"github.com/pkg/errors"
apiv2pb "github.com/usememos/memos/proto/gen/api/v2"
"github.com/usememos/memos/store"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
)
type MemoService struct {
apiv2pb.UnimplementedMemoServiceServer
Store *store.Store
}
// NewMemoService creates a new MemoService.
func NewMemoService(store *store.Store) *MemoService {
return &MemoService{
Store: store,
}
}
func (s *MemoService) ListMemos(ctx context.Context, request *apiv2pb.ListMemosRequest) (*apiv2pb.ListMemosResponse, error) {
memoFind := &store.FindMemo{}
if request.PageSize != 0 {
offset := int(request.Page * request.PageSize)
limit := int(request.PageSize)
memoFind.Offset = &offset
memoFind.Limit = &limit
}
if request.Filter != "" {
visibilityString, err := getVisibilityFilter(request.Filter)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid filter: %v", err)
}
memoFind.VisibilityList = []store.Visibility{store.Visibility(visibilityString)}
}
memos, err := s.Store.ListMemos(ctx, memoFind)
if err != nil {
return nil, err
}
memoMessages := make([]*apiv2pb.Memo, len(memos))
for i, memo := range memos {
memoMessages[i] = convertMemoFromStore(memo)
}
response := &apiv2pb.ListMemosResponse{
Memos: memoMessages,
}
return response, nil
}
const visibilityFilterExample = `visibility == "PRIVATE"`
// getVisibilityFilter will parse the simple filter such as `visibility = "PRIVATE"` to "PRIVATE" .
func getVisibilityFilter(filter string) (string, error) {
formatInvalidErr := errors.Errorf("invalid filter %q, example %q", filter, visibilityFilterExample)
e, err := cel.NewEnv(cel.Variable("visibility", cel.StringType))
if err != nil {
return "", err
}
ast, issues := e.Compile(filter)
if issues != nil {
return "", status.Errorf(codes.InvalidArgument, issues.String())
}
expr := ast.Expr()
if expr == nil {
return "", formatInvalidErr
}
callExpr := expr.GetCallExpr()
if callExpr == nil {
return "", formatInvalidErr
}
if callExpr.Function != "_==_" {
return "", formatInvalidErr
}
if len(callExpr.Args) != 2 {
return "", formatInvalidErr
}
if callExpr.Args[0].GetIdentExpr() == nil || callExpr.Args[0].GetIdentExpr().Name != "visibility" {
return "", formatInvalidErr
}
constExpr := callExpr.Args[1].GetConstExpr()
if constExpr == nil {
return "", formatInvalidErr
}
return constExpr.GetStringValue(), nil
}
func convertMemoFromStore(memo *store.Memo) *apiv2pb.Memo {
return &apiv2pb.Memo{
Id: int32(memo.ID),
RowStatus: convertRowStatusFromStore(memo.RowStatus),
CreatedTs: memo.CreatedTs,
UpdatedTs: memo.UpdatedTs,
CreatorId: int32(memo.CreatorID),
Content: memo.Content,
Visibility: convertVisibilityFromStore(memo.Visibility),
Pinned: memo.Pinned,
}
}
func convertVisibilityFromStore(visibility store.Visibility) apiv2pb.Visibility {
switch visibility {
case store.Private:
return apiv2pb.Visibility_PRIVATE
case store.Protected:
return apiv2pb.Visibility_PROTECTED
case store.Public:
return apiv2pb.Visibility_PUBLIC
default:
return apiv2pb.Visibility_VISIBILITY_UNSPECIFIED
}
}
......@@ -37,20 +37,6 @@ func (s *UserService) GetUser(ctx context.Context, request *apiv2pb.GetUserReque
// Data desensitization.
userMessage.OpenId = ""
userSettings, err := s.Store.ListUserSettings(ctx, &store.FindUserSetting{
UserID: &userMessage.Id,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list user settings: %v", err)
}
userID, ok := ctx.Value(UserIDContextKey).(int)
if ok && userID == int(userMessage.Id) {
for _, userSetting := range userSettings {
userMessage.Settings = append(userMessage.Settings, convertUserSettingFromStore(userSetting))
}
}
response := &apiv2pb.GetUserResponse{
User: userMessage,
}
......@@ -69,7 +55,6 @@ func convertUserFromStore(user *store.User) *apiv2pb.User {
Nickname: user.Nickname,
OpenId: user.OpenID,
AvatarUrl: user.AvatarURL,
Settings: []*apiv2pb.UserSetting{},
}
}
......@@ -86,7 +71,8 @@ func convertUserRoleFromStore(role store.Role) apiv2pb.Role {
}
}
func convertUserSettingFromStore(userSetting *store.UserSetting) *apiv2pb.UserSetting {
// ConvertUserSettingFromStore converts a user setting from store to protobuf.
func ConvertUserSettingFromStore(userSetting *store.UserSetting) *apiv2pb.UserSetting {
userSettingKey := apiv2pb.UserSetting_KEY_UNSPECIFIED
userSettingValue := &apiv2pb.UserSettingValue{}
switch userSetting.Key {
......@@ -103,7 +89,7 @@ func convertUserSettingFromStore(userSetting *store.UserSetting) *apiv2pb.UserSe
case "memo-visibility":
userSettingKey = apiv2pb.UserSetting_MEMO_VISIBILITY
userSettingValue.Value = &apiv2pb.UserSettingValue_VisibilityValue{
VisibilityValue: convertVisibilityFromString(userSetting.Value),
VisibilityValue: convertVisibilityFromStore(store.Visibility(userSetting.Value)),
}
case "telegram-user-id":
userSettingKey = apiv2pb.UserSetting_TELEGRAM_USER_ID
......@@ -117,14 +103,3 @@ func convertUserSettingFromStore(userSetting *store.UserSetting) *apiv2pb.UserSe
Value: userSettingValue,
}
}
func convertVisibilityFromString(visibility string) apiv2pb.Visibility {
switch visibility {
case "public":
return apiv2pb.Visibility_PUBLIC
case "private":
return apiv2pb.Visibility_PRIVATE
default:
return apiv2pb.Visibility_VISIBILITY_UNSPECIFIED
}
}
......@@ -3,14 +3,13 @@ module github.com/usememos/memos
go 1.19
require (
github.com/CorrectRoadH/echo-sse v0.1.4
github.com/PullRequestInc/go-gpt3 v1.1.15
github.com/aws/aws-sdk-go-v2 v1.17.4
github.com/aws/aws-sdk-go-v2/config v1.18.12
github.com/aws/aws-sdk-go-v2/credentials v1.13.12
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.11.51
github.com/aws/aws-sdk-go-v2/service/s3 v1.30.3
github.com/disintegration/imaging v1.6.2
github.com/google/cel-go v0.17.1
github.com/google/uuid v1.3.0
github.com/gorilla/feeds v1.1.1
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.2
......@@ -32,10 +31,12 @@ require (
)
require (
github.com/antlr/antlr4/runtime/Go/antlr/v4 v4.0.0-20230305170008-8188dc5388df // indirect
github.com/dustin/go-humanize v1.0.1 // indirect
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/go-internal v1.9.0 // indirect
github.com/stoewer/go-strcase v1.2.0 // indirect
golang.org/x/image v0.7.0 // indirect
golang.org/x/tools v0.6.0 // indirect
google.golang.org/genproto v0.0.0-20230706204954-ccb25ca9f130 // indirect
......
This diff is collapsed.
syntax = "proto3";
package memos.api.v2;
import "api/v2/common.proto";
import "google/api/annotations.proto";
import "google/api/client.proto";
option go_package = "gen/api/v2";
service MemoService {
rpc ListMemos(ListMemosRequest) returns (ListMemosResponse) {
option (google.api.http) = {get: "/api/v2/memos"};
}
rpc GetMemo(GetMemoRequest) returns (GetMemoResponse) {
option (google.api.http) = {get: "/api/v2/memos/{id}"};
option (google.api.method_signature) = "id";
}
}
message Memo {
int32 id = 1;
RowStatus row_status = 2;
int32 creator_id = 3;
int64 created_ts = 4;
int64 updated_ts = 5;
string content = 6;
Visibility visibility = 7;
bool pinned = 8;
}
message ListMemosRequest {
int32 page = 1;
int32 page_size = 2;
// Filter is used to filter memos returned in the list.
string filter = 3;
}
message ListMemosResponse {
repeated Memo memos = 1;
int32 total = 2;
}
message GetMemoRequest {
int32 id = 1;
}
message GetMemoResponse {
Memo memo = 1;
}
enum Visibility {
VISIBILITY_UNSPECIFIED = 0;
PRIVATE = 1;
PROTECTED = 2;
PUBLIC = 3;
}
......@@ -3,6 +3,7 @@ syntax = "proto3";
package memos.api.v2;
import "api/v2/common.proto";
import "api/v2/memo_service.proto";
import "google/api/annotations.proto";
import "google/api/client.proto";
......@@ -35,8 +36,6 @@ message User {
string open_id = 9;
string avatar_url = 10;
repeated UserSetting settings = 11;
}
enum Role {
......@@ -86,13 +85,3 @@ message UserSettingValue {
Visibility visibility_value = 2;
}
}
enum Visibility {
VISIBILITY_UNSPECIFIED = 0;
PRIVATE = 1;
PROTECTED = 2;
PUBLIC = 3;
}
......@@ -6,6 +6,17 @@
- [api/v2/common.proto](#api_v2_common-proto)
- [RowStatus](#memos-api-v2-RowStatus)
- [api/v2/memo_service.proto](#api_v2_memo_service-proto)
- [GetMemoRequest](#memos-api-v2-GetMemoRequest)
- [GetMemoResponse](#memos-api-v2-GetMemoResponse)
- [ListMemosRequest](#memos-api-v2-ListMemosRequest)
- [ListMemosResponse](#memos-api-v2-ListMemosResponse)
- [Memo](#memos-api-v2-Memo)
- [Visibility](#memos-api-v2-Visibility)
- [MemoService](#memos-api-v2-MemoService)
- [api/v2/tag_service.proto](#api_v2_tag_service-proto)
- [ListTagsRequest](#memos-api-v2-ListTagsRequest)
- [ListTagsResponse](#memos-api-v2-ListTagsResponse)
......@@ -22,7 +33,6 @@
- [Role](#memos-api-v2-Role)
- [UserSetting.Key](#memos-api-v2-UserSetting-Key)
- [Visibility](#memos-api-v2-Visibility)
- [UserService](#memos-api-v2-UserService)
......@@ -59,6 +69,132 @@
<a name="api_v2_memo_service-proto"></a>
<p align="right"><a href="#top">Top</a></p>
## api/v2/memo_service.proto
<a name="memos-api-v2-GetMemoRequest"></a>
### GetMemoRequest
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| id | [int32](#int32) | | |
<a name="memos-api-v2-GetMemoResponse"></a>
### GetMemoResponse
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| memo | [Memo](#memos-api-v2-Memo) | | |
<a name="memos-api-v2-ListMemosRequest"></a>
### ListMemosRequest
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| page | [int32](#int32) | | |
| page_size | [int32](#int32) | | |
| filter | [string](#string) | | Filter is used to filter memos returned in the list. |
<a name="memos-api-v2-ListMemosResponse"></a>
### ListMemosResponse
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| memos | [Memo](#memos-api-v2-Memo) | repeated | |
| total | [int32](#int32) | | |
<a name="memos-api-v2-Memo"></a>
### Memo
| Field | Type | Label | Description |
| ----- | ---- | ----- | ----------- |
| id | [int32](#int32) | | |
| row_status | [RowStatus](#memos-api-v2-RowStatus) | | |
| creator_id | [int32](#int32) | | |
| created_ts | [int64](#int64) | | |
| updated_ts | [int64](#int64) | | |
| content | [string](#string) | | |
| visibility | [Visibility](#memos-api-v2-Visibility) | | |
| pinned | [bool](#bool) | | |
<a name="memos-api-v2-Visibility"></a>
### Visibility
| Name | Number | Description |
| ---- | ------ | ----------- |
| VISIBILITY_UNSPECIFIED | 0 | |
| PRIVATE | 1 | |
| PROTECTED | 2 | |
| PUBLIC | 3 | |
<a name="memos-api-v2-MemoService"></a>
### MemoService
| Method Name | Request Type | Response Type | Description |
| ----------- | ------------ | ------------- | ------------|
| ListMemos | [ListMemosRequest](#memos-api-v2-ListMemosRequest) | [ListMemosResponse](#memos-api-v2-ListMemosResponse) | |
| GetMemo | [GetMemoRequest](#memos-api-v2-GetMemoRequest) | [GetMemoResponse](#memos-api-v2-GetMemoResponse) | |
<a name="api_v2_tag_service-proto"></a>
<p align="right"><a href="#top">Top</a></p>
......@@ -186,7 +322,6 @@
| nickname | [string](#string) | | |
| open_id | [string](#string) | | |
| avatar_url | [string](#string) | | |
| settings | [UserSetting](#memos-api-v2-UserSetting) | repeated | |
......@@ -257,20 +392,6 @@
<a name="memos-api-v2-Visibility"></a>
### Visibility
| Name | Number | Description |
| ---- | ------ | ----------- |
| VISIBILITY_UNSPECIFIED | 0 | |
| PRIVATE | 1 | |
| PROTECTED | 2 | |
| PUBLIC | 3 | |
......
This diff is collapsed.
This diff is collapsed.
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.3.0
// - protoc (unknown)
// source: api/v2/memo_service.proto
package apiv2
import (
context "context"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
)
// This is a compile-time assertion to ensure that this generated file
// is compatible with the grpc package it is being compiled against.
// Requires gRPC-Go v1.32.0 or later.
const _ = grpc.SupportPackageIsVersion7
const (
MemoService_ListMemos_FullMethodName = "/memos.api.v2.MemoService/ListMemos"
MemoService_GetMemo_FullMethodName = "/memos.api.v2.MemoService/GetMemo"
)
// MemoServiceClient is the client API for MemoService service.
//
// For semantics around ctx use and closing/ending streaming RPCs, please refer to https://pkg.go.dev/google.golang.org/grpc/?tab=doc#ClientConn.NewStream.
type MemoServiceClient interface {
ListMemos(ctx context.Context, in *ListMemosRequest, opts ...grpc.CallOption) (*ListMemosResponse, error)
GetMemo(ctx context.Context, in *GetMemoRequest, opts ...grpc.CallOption) (*GetMemoResponse, error)
}
type memoServiceClient struct {
cc grpc.ClientConnInterface
}
func NewMemoServiceClient(cc grpc.ClientConnInterface) MemoServiceClient {
return &memoServiceClient{cc}
}
func (c *memoServiceClient) ListMemos(ctx context.Context, in *ListMemosRequest, opts ...grpc.CallOption) (*ListMemosResponse, error) {
out := new(ListMemosResponse)
err := c.cc.Invoke(ctx, MemoService_ListMemos_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *memoServiceClient) GetMemo(ctx context.Context, in *GetMemoRequest, opts ...grpc.CallOption) (*GetMemoResponse, error) {
out := new(GetMemoResponse)
err := c.cc.Invoke(ctx, MemoService_GetMemo_FullMethodName, in, out, opts...)
if err != nil {
return nil, err
}
return out, nil
}
// MemoServiceServer is the server API for MemoService service.
// All implementations must embed UnimplementedMemoServiceServer
// for forward compatibility
type MemoServiceServer interface {
ListMemos(context.Context, *ListMemosRequest) (*ListMemosResponse, error)
GetMemo(context.Context, *GetMemoRequest) (*GetMemoResponse, error)
mustEmbedUnimplementedMemoServiceServer()
}
// UnimplementedMemoServiceServer must be embedded to have forward compatible implementations.
type UnimplementedMemoServiceServer struct {
}
func (UnimplementedMemoServiceServer) ListMemos(context.Context, *ListMemosRequest) (*ListMemosResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method ListMemos not implemented")
}
func (UnimplementedMemoServiceServer) GetMemo(context.Context, *GetMemoRequest) (*GetMemoResponse, error) {
return nil, status.Errorf(codes.Unimplemented, "method GetMemo not implemented")
}
func (UnimplementedMemoServiceServer) mustEmbedUnimplementedMemoServiceServer() {}
// UnsafeMemoServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to MemoServiceServer will
// result in compilation errors.
type UnsafeMemoServiceServer interface {
mustEmbedUnimplementedMemoServiceServer()
}
func RegisterMemoServiceServer(s grpc.ServiceRegistrar, srv MemoServiceServer) {
s.RegisterService(&MemoService_ServiceDesc, srv)
}
func _MemoService_ListMemos_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListMemosRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MemoServiceServer).ListMemos(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: MemoService_ListMemos_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MemoServiceServer).ListMemos(ctx, req.(*ListMemosRequest))
}
return interceptor(ctx, in, info, handler)
}
func _MemoService_GetMemo_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetMemoRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(MemoServiceServer).GetMemo(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: MemoService_GetMemo_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(MemoServiceServer).GetMemo(ctx, req.(*GetMemoRequest))
}
return interceptor(ctx, in, info, handler)
}
// MemoService_ServiceDesc is the grpc.ServiceDesc for MemoService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var MemoService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "memos.api.v2.MemoService",
HandlerType: (*MemoServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListMemos",
Handler: _MemoService_ListMemos_Handler,
},
{
MethodName: "GetMemo",
Handler: _MemoService_GetMemo_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "api/v2/memo_service.proto",
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment