inbox_service.go 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. package v1
  2. import (
  3. "context"
  4. "fmt"
  5. "time"
  6. "google.golang.org/grpc/codes"
  7. "google.golang.org/grpc/status"
  8. "google.golang.org/protobuf/types/known/emptypb"
  9. "google.golang.org/protobuf/types/known/timestamppb"
  10. v1pb "github.com/usememos/memos/proto/gen/api/v1"
  11. "github.com/usememos/memos/store"
  12. )
  13. func (s *APIV1Service) ListInboxes(ctx context.Context, request *v1pb.ListInboxesRequest) (*v1pb.ListInboxesResponse, error) {
  14. user, err := s.GetCurrentUser(ctx)
  15. if err != nil {
  16. return nil, status.Errorf(codes.Internal, "failed to get user")
  17. }
  18. var limit, offset int
  19. if request.PageToken != "" {
  20. var pageToken v1pb.PageToken
  21. if err := unmarshalPageToken(request.PageToken, &pageToken); err != nil {
  22. return nil, status.Errorf(codes.InvalidArgument, "invalid page token: %v", err)
  23. }
  24. limit = int(pageToken.Limit)
  25. offset = int(pageToken.Offset)
  26. } else {
  27. limit = int(request.PageSize)
  28. }
  29. if limit <= 0 {
  30. limit = DefaultPageSize
  31. }
  32. limitPlusOne := limit + 1
  33. inboxes, err := s.Store.ListInboxes(ctx, &store.FindInbox{
  34. ReceiverID: &user.ID,
  35. Limit: &limitPlusOne,
  36. Offset: &offset,
  37. })
  38. if err != nil {
  39. return nil, status.Errorf(codes.Internal, "failed to list inbox: %v", err)
  40. }
  41. inboxMessages := []*v1pb.Inbox{}
  42. nextPageToken := ""
  43. if len(inboxes) == limitPlusOne {
  44. inboxes = inboxes[:limit]
  45. nextPageToken, err = getPageToken(limit, offset+limit)
  46. if err != nil {
  47. return nil, status.Errorf(codes.Internal, "failed to get next page token, error: %v", err)
  48. }
  49. }
  50. for _, inbox := range inboxes {
  51. inboxMessage := convertInboxFromStore(inbox)
  52. if inboxMessage.Type == v1pb.Inbox_TYPE_UNSPECIFIED {
  53. continue
  54. }
  55. inboxMessages = append(inboxMessages, inboxMessage)
  56. }
  57. response := &v1pb.ListInboxesResponse{
  58. Inboxes: inboxMessages,
  59. NextPageToken: nextPageToken,
  60. }
  61. return response, nil
  62. }
  63. func (s *APIV1Service) UpdateInbox(ctx context.Context, request *v1pb.UpdateInboxRequest) (*v1pb.Inbox, error) {
  64. if request.UpdateMask == nil || len(request.UpdateMask.Paths) == 0 {
  65. return nil, status.Errorf(codes.InvalidArgument, "update mask is required")
  66. }
  67. inboxID, err := ExtractInboxIDFromName(request.Inbox.Name)
  68. if err != nil {
  69. return nil, status.Errorf(codes.InvalidArgument, "invalid inbox name: %v", err)
  70. }
  71. update := &store.UpdateInbox{
  72. ID: inboxID,
  73. }
  74. for _, field := range request.UpdateMask.Paths {
  75. if field == "status" {
  76. if request.Inbox.Status == v1pb.Inbox_STATUS_UNSPECIFIED {
  77. return nil, status.Errorf(codes.InvalidArgument, "status is required")
  78. }
  79. update.Status = convertInboxStatusToStore(request.Inbox.Status)
  80. }
  81. }
  82. inbox, err := s.Store.UpdateInbox(ctx, update)
  83. if err != nil {
  84. return nil, status.Errorf(codes.Internal, "failed to update inbox: %v", err)
  85. }
  86. return convertInboxFromStore(inbox), nil
  87. }
  88. func (s *APIV1Service) DeleteInbox(ctx context.Context, request *v1pb.DeleteInboxRequest) (*emptypb.Empty, error) {
  89. inboxID, err := ExtractInboxIDFromName(request.Name)
  90. if err != nil {
  91. return nil, status.Errorf(codes.InvalidArgument, "invalid inbox name: %v", err)
  92. }
  93. if err := s.Store.DeleteInbox(ctx, &store.DeleteInbox{
  94. ID: inboxID,
  95. }); err != nil {
  96. return nil, status.Errorf(codes.Internal, "failed to update inbox: %v", err)
  97. }
  98. return &emptypb.Empty{}, nil
  99. }
  100. func convertInboxFromStore(inbox *store.Inbox) *v1pb.Inbox {
  101. return &v1pb.Inbox{
  102. Name: fmt.Sprintf("%s%d", InboxNamePrefix, inbox.ID),
  103. Sender: fmt.Sprintf("%s%d", UserNamePrefix, inbox.SenderID),
  104. Receiver: fmt.Sprintf("%s%d", UserNamePrefix, inbox.ReceiverID),
  105. Status: convertInboxStatusFromStore(inbox.Status),
  106. CreateTime: timestamppb.New(time.Unix(inbox.CreatedTs, 0)),
  107. Type: v1pb.Inbox_Type(inbox.Message.Type),
  108. ActivityId: inbox.Message.ActivityId,
  109. }
  110. }
  111. func convertInboxStatusFromStore(status store.InboxStatus) v1pb.Inbox_Status {
  112. switch status {
  113. case store.UNREAD:
  114. return v1pb.Inbox_UNREAD
  115. case store.ARCHIVED:
  116. return v1pb.Inbox_ARCHIVED
  117. default:
  118. return v1pb.Inbox_STATUS_UNSPECIFIED
  119. }
  120. }
  121. func convertInboxStatusToStore(status v1pb.Inbox_Status) store.InboxStatus {
  122. switch status {
  123. case v1pb.Inbox_UNREAD:
  124. return store.UNREAD
  125. case v1pb.Inbox_ARCHIVED:
  126. return store.ARCHIVED
  127. default:
  128. return store.UNREAD
  129. }
  130. }