memo_relation_service.go 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. package v1
  2. import (
  3. "context"
  4. "fmt"
  5. "github.com/pkg/errors"
  6. "google.golang.org/grpc/codes"
  7. "google.golang.org/grpc/status"
  8. "google.golang.org/protobuf/types/known/emptypb"
  9. v1pb "github.com/usememos/memos/proto/gen/api/v1"
  10. "github.com/usememos/memos/store"
  11. )
  12. func (s *APIV1Service) SetMemoRelations(ctx context.Context, request *v1pb.SetMemoRelationsRequest) (*emptypb.Empty, error) {
  13. memoUID, err := ExtractMemoUIDFromName(request.Name)
  14. if err != nil {
  15. return nil, status.Errorf(codes.InvalidArgument, "invalid memo name: %v", err)
  16. }
  17. memo, err := s.Store.GetMemo(ctx, &store.FindMemo{UID: &memoUID})
  18. if err != nil {
  19. return nil, status.Errorf(codes.Internal, "failed to get memo")
  20. }
  21. referenceType := store.MemoRelationReference
  22. // Delete all reference relations first.
  23. if err := s.Store.DeleteMemoRelation(ctx, &store.DeleteMemoRelation{
  24. MemoID: &memo.ID,
  25. Type: &referenceType,
  26. }); err != nil {
  27. return nil, status.Errorf(codes.Internal, "failed to delete memo relation")
  28. }
  29. for _, relation := range request.Relations {
  30. // Ignore reflexive relations.
  31. if request.Name == relation.RelatedMemo.Name {
  32. continue
  33. }
  34. // Ignore comment relations as there's no need to update a comment's relation.
  35. // Inserting/Deleting a comment is handled elsewhere.
  36. if relation.Type == v1pb.MemoRelation_COMMENT {
  37. continue
  38. }
  39. relatedMemoUID, err := ExtractMemoUIDFromName(relation.RelatedMemo.Name)
  40. if err != nil {
  41. return nil, status.Errorf(codes.InvalidArgument, "invalid related memo name: %v", err)
  42. }
  43. relatedMemo, err := s.Store.GetMemo(ctx, &store.FindMemo{UID: &relatedMemoUID})
  44. if err != nil {
  45. return nil, status.Errorf(codes.Internal, "failed to get related memo")
  46. }
  47. if _, err := s.Store.UpsertMemoRelation(ctx, &store.MemoRelation{
  48. MemoID: memo.ID,
  49. RelatedMemoID: relatedMemo.ID,
  50. Type: convertMemoRelationTypeToStore(relation.Type),
  51. }); err != nil {
  52. return nil, status.Errorf(codes.Internal, "failed to upsert memo relation")
  53. }
  54. }
  55. return &emptypb.Empty{}, nil
  56. }
  57. func (s *APIV1Service) ListMemoRelations(ctx context.Context, request *v1pb.ListMemoRelationsRequest) (*v1pb.ListMemoRelationsResponse, error) {
  58. memoUID, err := ExtractMemoUIDFromName(request.Name)
  59. if err != nil {
  60. return nil, status.Errorf(codes.InvalidArgument, "invalid memo name: %v", err)
  61. }
  62. memo, err := s.Store.GetMemo(ctx, &store.FindMemo{UID: &memoUID})
  63. if err != nil {
  64. return nil, status.Errorf(codes.Internal, "failed to get memo")
  65. }
  66. relationList := []*v1pb.MemoRelation{}
  67. tempList, err := s.Store.ListMemoRelations(ctx, &store.FindMemoRelation{
  68. MemoID: &memo.ID,
  69. })
  70. if err != nil {
  71. return nil, err
  72. }
  73. for _, raw := range tempList {
  74. relation, err := s.convertMemoRelationFromStore(ctx, raw)
  75. if err != nil {
  76. return nil, status.Errorf(codes.Internal, "failed to convert memo relation")
  77. }
  78. relationList = append(relationList, relation)
  79. }
  80. tempList, err = s.Store.ListMemoRelations(ctx, &store.FindMemoRelation{
  81. RelatedMemoID: &memo.ID,
  82. })
  83. if err != nil {
  84. return nil, err
  85. }
  86. for _, raw := range tempList {
  87. relation, err := s.convertMemoRelationFromStore(ctx, raw)
  88. if err != nil {
  89. return nil, status.Errorf(codes.Internal, "failed to convert memo relation")
  90. }
  91. relationList = append(relationList, relation)
  92. }
  93. response := &v1pb.ListMemoRelationsResponse{
  94. Relations: relationList,
  95. }
  96. return response, nil
  97. }
  98. func (s *APIV1Service) convertMemoRelationFromStore(ctx context.Context, memoRelation *store.MemoRelation) (*v1pb.MemoRelation, error) {
  99. memo, err := s.Store.GetMemo(ctx, &store.FindMemo{ID: &memoRelation.MemoID})
  100. if err != nil {
  101. return nil, err
  102. }
  103. memoSnippet, err := getMemoContentSnippet(memo.Content)
  104. if err != nil {
  105. return nil, errors.Wrap(err, "failed to get memo content snippet")
  106. }
  107. relatedMemo, err := s.Store.GetMemo(ctx, &store.FindMemo{ID: &memoRelation.RelatedMemoID})
  108. if err != nil {
  109. return nil, err
  110. }
  111. relatedMemoSnippet, err := getMemoContentSnippet(relatedMemo.Content)
  112. if err != nil {
  113. return nil, errors.Wrap(err, "failed to get related memo content snippet")
  114. }
  115. return &v1pb.MemoRelation{
  116. Memo: &v1pb.MemoRelation_Memo{
  117. Name: fmt.Sprintf("%s%s", MemoNamePrefix, memo.UID),
  118. Uid: memo.UID,
  119. Snippet: memoSnippet,
  120. },
  121. RelatedMemo: &v1pb.MemoRelation_Memo{
  122. Name: fmt.Sprintf("%s%s", MemoNamePrefix, relatedMemo.UID),
  123. Uid: relatedMemo.UID,
  124. Snippet: relatedMemoSnippet,
  125. },
  126. Type: convertMemoRelationTypeFromStore(memoRelation.Type),
  127. }, nil
  128. }
  129. func convertMemoRelationTypeFromStore(relationType store.MemoRelationType) v1pb.MemoRelation_Type {
  130. switch relationType {
  131. case store.MemoRelationReference:
  132. return v1pb.MemoRelation_REFERENCE
  133. case store.MemoRelationComment:
  134. return v1pb.MemoRelation_COMMENT
  135. default:
  136. return v1pb.MemoRelation_TYPE_UNSPECIFIED
  137. }
  138. }
  139. func convertMemoRelationTypeToStore(relationType v1pb.MemoRelation_Type) store.MemoRelationType {
  140. switch relationType {
  141. case v1pb.MemoRelation_REFERENCE:
  142. return store.MemoRelationReference
  143. case v1pb.MemoRelation_COMMENT:
  144. return store.MemoRelationComment
  145. default:
  146. return store.MemoRelationReference
  147. }
  148. }