fix(api): remove public activity service (#5734)

This commit is contained in:
boojack 2026-03-18 22:42:57 +08:00 committed by GitHub
parent 89c6902895
commit 04f239a2fc
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
23 changed files with 491 additions and 2446 deletions

View File

@ -1,125 +0,0 @@
syntax = "proto3";
package memos.api.v1;
import "google/api/annotations.proto";
import "google/api/client.proto";
import "google/api/field_behavior.proto";
import "google/api/resource.proto";
import "google/protobuf/timestamp.proto";
option go_package = "gen/api/v1";
service ActivityService {
// ListActivities returns a list of activities.
rpc ListActivities(ListActivitiesRequest) returns (ListActivitiesResponse) {
option (google.api.http) = {get: "/api/v1/activities"};
}
// GetActivity returns the activity with the given id.
rpc GetActivity(GetActivityRequest) returns (Activity) {
option (google.api.http) = {get: "/api/v1/{name=activities/*}"};
option (google.api.method_signature) = "name";
}
}
message Activity {
option (google.api.resource) = {
type: "memos.api.v1/Activity"
pattern: "activities/{activity}"
name_field: "name"
singular: "activity"
plural: "activities"
};
// The name of the activity.
// Format: activities/{id}
string name = 1 [
(google.api.field_behavior) = OUTPUT_ONLY,
(google.api.field_behavior) = IDENTIFIER
];
// The name of the creator.
// Format: users/{user}
string creator = 2 [(google.api.field_behavior) = OUTPUT_ONLY];
// The type of the activity.
Type type = 3 [(google.api.field_behavior) = OUTPUT_ONLY];
// The level of the activity.
Level level = 4 [(google.api.field_behavior) = OUTPUT_ONLY];
// The create time of the activity.
google.protobuf.Timestamp create_time = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
// The payload of the activity.
ActivityPayload payload = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
// Activity types.
enum Type {
// Unspecified type.
TYPE_UNSPECIFIED = 0;
// Memo comment activity.
MEMO_COMMENT = 1;
}
// Activity levels.
enum Level {
// Unspecified level.
LEVEL_UNSPECIFIED = 0;
// Info level.
INFO = 1;
// Warn level.
WARN = 2;
// Error level.
ERROR = 3;
}
}
message ActivityPayload {
oneof payload {
// Memo comment activity payload.
ActivityMemoCommentPayload memo_comment = 1;
}
}
// ActivityMemoCommentPayload represents the payload of a memo comment activity.
message ActivityMemoCommentPayload {
// The memo name of comment.
// Format: memos/{memo}
string memo = 1;
// The name of related memo.
// Format: memos/{memo}
string related_memo = 2;
}
message ListActivitiesRequest {
// The maximum number of activities to return.
// The service may return fewer than this value.
// If unspecified, at most 100 activities will be returned.
// The maximum value is 1000; values above 1000 will be coerced to 1000.
int32 page_size = 1;
// A page token, received from a previous `ListActivities` call.
// Provide this to retrieve the subsequent page.
string page_token = 2;
}
message ListActivitiesResponse {
// The activities.
repeated Activity activities = 1;
// A token to retrieve the next page of results.
// Pass this value in the page_token field in the subsequent call to `ListActivities`
// method to retrieve the next page of results.
string next_page_token = 2;
}
message GetActivityRequest {
// The name of the activity.
// Format: activities/{id}, id is the system generated auto-incremented id.
string name = 1 [
(google.api.field_behavior) = REQUIRED,
(google.api.resource_reference) = {type: "memos.api.v1/Activity"}
];
}

View File

@ -626,8 +626,19 @@ message UserNotification {
// The type of the notification.
Type type = 5 [(google.api.field_behavior) = OUTPUT_ONLY];
// The activity ID associated with this notification.
optional int32 activity_id = 6 [(google.api.field_behavior) = OPTIONAL];
oneof payload {
MemoCommentPayload memo_comment = 6 [(google.api.field_behavior) = OUTPUT_ONLY];
}
message MemoCommentPayload {
// The memo name of comment.
// Format: memos/{memo}
string memo = 1;
// The name of related memo.
// Format: memos/{memo}
string related_memo = 2;
}
enum Status {
STATUS_UNSPECIFIED = 0;

View File

@ -1,623 +0,0 @@
// Code generated by protoc-gen-go. DO NOT EDIT.
// versions:
// protoc-gen-go v1.36.11
// protoc (unknown)
// source: api/v1/activity_service.proto
package apiv1
import (
_ "google.golang.org/genproto/googleapis/api/annotations"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
timestamppb "google.golang.org/protobuf/types/known/timestamppb"
reflect "reflect"
sync "sync"
unsafe "unsafe"
)
const (
// Verify that this generated code is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(20 - protoimpl.MinVersion)
// Verify that runtime/protoimpl is sufficiently up-to-date.
_ = protoimpl.EnforceVersion(protoimpl.MaxVersion - 20)
)
// Activity types.
type Activity_Type int32
const (
// Unspecified type.
Activity_TYPE_UNSPECIFIED Activity_Type = 0
// Memo comment activity.
Activity_MEMO_COMMENT Activity_Type = 1
)
// Enum value maps for Activity_Type.
var (
Activity_Type_name = map[int32]string{
0: "TYPE_UNSPECIFIED",
1: "MEMO_COMMENT",
}
Activity_Type_value = map[string]int32{
"TYPE_UNSPECIFIED": 0,
"MEMO_COMMENT": 1,
}
)
func (x Activity_Type) Enum() *Activity_Type {
p := new(Activity_Type)
*p = x
return p
}
func (x Activity_Type) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Activity_Type) Descriptor() protoreflect.EnumDescriptor {
return file_api_v1_activity_service_proto_enumTypes[0].Descriptor()
}
func (Activity_Type) Type() protoreflect.EnumType {
return &file_api_v1_activity_service_proto_enumTypes[0]
}
func (x Activity_Type) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Activity_Type.Descriptor instead.
func (Activity_Type) EnumDescriptor() ([]byte, []int) {
return file_api_v1_activity_service_proto_rawDescGZIP(), []int{0, 0}
}
// Activity levels.
type Activity_Level int32
const (
// Unspecified level.
Activity_LEVEL_UNSPECIFIED Activity_Level = 0
// Info level.
Activity_INFO Activity_Level = 1
// Warn level.
Activity_WARN Activity_Level = 2
// Error level.
Activity_ERROR Activity_Level = 3
)
// Enum value maps for Activity_Level.
var (
Activity_Level_name = map[int32]string{
0: "LEVEL_UNSPECIFIED",
1: "INFO",
2: "WARN",
3: "ERROR",
}
Activity_Level_value = map[string]int32{
"LEVEL_UNSPECIFIED": 0,
"INFO": 1,
"WARN": 2,
"ERROR": 3,
}
)
func (x Activity_Level) Enum() *Activity_Level {
p := new(Activity_Level)
*p = x
return p
}
func (x Activity_Level) String() string {
return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x))
}
func (Activity_Level) Descriptor() protoreflect.EnumDescriptor {
return file_api_v1_activity_service_proto_enumTypes[1].Descriptor()
}
func (Activity_Level) Type() protoreflect.EnumType {
return &file_api_v1_activity_service_proto_enumTypes[1]
}
func (x Activity_Level) Number() protoreflect.EnumNumber {
return protoreflect.EnumNumber(x)
}
// Deprecated: Use Activity_Level.Descriptor instead.
func (Activity_Level) EnumDescriptor() ([]byte, []int) {
return file_api_v1_activity_service_proto_rawDescGZIP(), []int{0, 1}
}
type Activity struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The name of the activity.
// Format: activities/{id}
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
// The name of the creator.
// Format: users/{user}
Creator string `protobuf:"bytes,2,opt,name=creator,proto3" json:"creator,omitempty"`
// The type of the activity.
Type Activity_Type `protobuf:"varint,3,opt,name=type,proto3,enum=memos.api.v1.Activity_Type" json:"type,omitempty"`
// The level of the activity.
Level Activity_Level `protobuf:"varint,4,opt,name=level,proto3,enum=memos.api.v1.Activity_Level" json:"level,omitempty"`
// The create time of the activity.
CreateTime *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"`
// The payload of the activity.
Payload *ActivityPayload `protobuf:"bytes,6,opt,name=payload,proto3" json:"payload,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *Activity) Reset() {
*x = Activity{}
mi := &file_api_v1_activity_service_proto_msgTypes[0]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *Activity) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*Activity) ProtoMessage() {}
func (x *Activity) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_activity_service_proto_msgTypes[0]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use Activity.ProtoReflect.Descriptor instead.
func (*Activity) Descriptor() ([]byte, []int) {
return file_api_v1_activity_service_proto_rawDescGZIP(), []int{0}
}
func (x *Activity) GetName() string {
if x != nil {
return x.Name
}
return ""
}
func (x *Activity) GetCreator() string {
if x != nil {
return x.Creator
}
return ""
}
func (x *Activity) GetType() Activity_Type {
if x != nil {
return x.Type
}
return Activity_TYPE_UNSPECIFIED
}
func (x *Activity) GetLevel() Activity_Level {
if x != nil {
return x.Level
}
return Activity_LEVEL_UNSPECIFIED
}
func (x *Activity) GetCreateTime() *timestamppb.Timestamp {
if x != nil {
return x.CreateTime
}
return nil
}
func (x *Activity) GetPayload() *ActivityPayload {
if x != nil {
return x.Payload
}
return nil
}
type ActivityPayload struct {
state protoimpl.MessageState `protogen:"open.v1"`
// Types that are valid to be assigned to Payload:
//
// *ActivityPayload_MemoComment
Payload isActivityPayload_Payload `protobuf_oneof:"payload"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ActivityPayload) Reset() {
*x = ActivityPayload{}
mi := &file_api_v1_activity_service_proto_msgTypes[1]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ActivityPayload) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ActivityPayload) ProtoMessage() {}
func (x *ActivityPayload) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_activity_service_proto_msgTypes[1]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ActivityPayload.ProtoReflect.Descriptor instead.
func (*ActivityPayload) Descriptor() ([]byte, []int) {
return file_api_v1_activity_service_proto_rawDescGZIP(), []int{1}
}
func (x *ActivityPayload) GetPayload() isActivityPayload_Payload {
if x != nil {
return x.Payload
}
return nil
}
func (x *ActivityPayload) GetMemoComment() *ActivityMemoCommentPayload {
if x != nil {
if x, ok := x.Payload.(*ActivityPayload_MemoComment); ok {
return x.MemoComment
}
}
return nil
}
type isActivityPayload_Payload interface {
isActivityPayload_Payload()
}
type ActivityPayload_MemoComment struct {
// Memo comment activity payload.
MemoComment *ActivityMemoCommentPayload `protobuf:"bytes,1,opt,name=memo_comment,json=memoComment,proto3,oneof"`
}
func (*ActivityPayload_MemoComment) isActivityPayload_Payload() {}
// ActivityMemoCommentPayload represents the payload of a memo comment activity.
type ActivityMemoCommentPayload struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The memo name of comment.
// Format: memos/{memo}
Memo string `protobuf:"bytes,1,opt,name=memo,proto3" json:"memo,omitempty"`
// The name of related memo.
// Format: memos/{memo}
RelatedMemo string `protobuf:"bytes,2,opt,name=related_memo,json=relatedMemo,proto3" json:"related_memo,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ActivityMemoCommentPayload) Reset() {
*x = ActivityMemoCommentPayload{}
mi := &file_api_v1_activity_service_proto_msgTypes[2]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ActivityMemoCommentPayload) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ActivityMemoCommentPayload) ProtoMessage() {}
func (x *ActivityMemoCommentPayload) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_activity_service_proto_msgTypes[2]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ActivityMemoCommentPayload.ProtoReflect.Descriptor instead.
func (*ActivityMemoCommentPayload) Descriptor() ([]byte, []int) {
return file_api_v1_activity_service_proto_rawDescGZIP(), []int{2}
}
func (x *ActivityMemoCommentPayload) GetMemo() string {
if x != nil {
return x.Memo
}
return ""
}
func (x *ActivityMemoCommentPayload) GetRelatedMemo() string {
if x != nil {
return x.RelatedMemo
}
return ""
}
type ListActivitiesRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The maximum number of activities to return.
// The service may return fewer than this value.
// If unspecified, at most 100 activities will be returned.
// The maximum value is 1000; values above 1000 will be coerced to 1000.
PageSize int32 `protobuf:"varint,1,opt,name=page_size,json=pageSize,proto3" json:"page_size,omitempty"`
// A page token, received from a previous `ListActivities` call.
// Provide this to retrieve the subsequent page.
PageToken string `protobuf:"bytes,2,opt,name=page_token,json=pageToken,proto3" json:"page_token,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListActivitiesRequest) Reset() {
*x = ListActivitiesRequest{}
mi := &file_api_v1_activity_service_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListActivitiesRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListActivitiesRequest) ProtoMessage() {}
func (x *ListActivitiesRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_activity_service_proto_msgTypes[3]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListActivitiesRequest.ProtoReflect.Descriptor instead.
func (*ListActivitiesRequest) Descriptor() ([]byte, []int) {
return file_api_v1_activity_service_proto_rawDescGZIP(), []int{3}
}
func (x *ListActivitiesRequest) GetPageSize() int32 {
if x != nil {
return x.PageSize
}
return 0
}
func (x *ListActivitiesRequest) GetPageToken() string {
if x != nil {
return x.PageToken
}
return ""
}
type ListActivitiesResponse struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The activities.
Activities []*Activity `protobuf:"bytes,1,rep,name=activities,proto3" json:"activities,omitempty"`
// A token to retrieve the next page of results.
// Pass this value in the page_token field in the subsequent call to `ListActivities`
// method to retrieve the next page of results.
NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *ListActivitiesResponse) Reset() {
*x = ListActivitiesResponse{}
mi := &file_api_v1_activity_service_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *ListActivitiesResponse) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*ListActivitiesResponse) ProtoMessage() {}
func (x *ListActivitiesResponse) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_activity_service_proto_msgTypes[4]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use ListActivitiesResponse.ProtoReflect.Descriptor instead.
func (*ListActivitiesResponse) Descriptor() ([]byte, []int) {
return file_api_v1_activity_service_proto_rawDescGZIP(), []int{4}
}
func (x *ListActivitiesResponse) GetActivities() []*Activity {
if x != nil {
return x.Activities
}
return nil
}
func (x *ListActivitiesResponse) GetNextPageToken() string {
if x != nil {
return x.NextPageToken
}
return ""
}
type GetActivityRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The name of the activity.
// Format: activities/{id}, id is the system generated auto-incremented id.
Name string `protobuf:"bytes,1,opt,name=name,proto3" json:"name,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *GetActivityRequest) Reset() {
*x = GetActivityRequest{}
mi := &file_api_v1_activity_service_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *GetActivityRequest) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GetActivityRequest) ProtoMessage() {}
func (x *GetActivityRequest) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_activity_service_proto_msgTypes[5]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use GetActivityRequest.ProtoReflect.Descriptor instead.
func (*GetActivityRequest) Descriptor() ([]byte, []int) {
return file_api_v1_activity_service_proto_rawDescGZIP(), []int{5}
}
func (x *GetActivityRequest) GetName() string {
if x != nil {
return x.Name
}
return ""
}
var File_api_v1_activity_service_proto protoreflect.FileDescriptor
const file_api_v1_activity_service_proto_rawDesc = "" +
"\n" +
"\x1dapi/v1/activity_service.proto\x12\fmemos.api.v1\x1a\x1cgoogle/api/annotations.proto\x1a\x17google/api/client.proto\x1a\x1fgoogle/api/field_behavior.proto\x1a\x19google/api/resource.proto\x1a\x1fgoogle/protobuf/timestamp.proto\"\xf2\x03\n" +
"\bActivity\x12\x1a\n" +
"\x04name\x18\x01 \x01(\tB\x06\xe0A\x03\xe0A\bR\x04name\x12\x1d\n" +
"\acreator\x18\x02 \x01(\tB\x03\xe0A\x03R\acreator\x124\n" +
"\x04type\x18\x03 \x01(\x0e2\x1b.memos.api.v1.Activity.TypeB\x03\xe0A\x03R\x04type\x127\n" +
"\x05level\x18\x04 \x01(\x0e2\x1c.memos.api.v1.Activity.LevelB\x03\xe0A\x03R\x05level\x12@\n" +
"\vcreate_time\x18\x05 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
"createTime\x12<\n" +
"\apayload\x18\x06 \x01(\v2\x1d.memos.api.v1.ActivityPayloadB\x03\xe0A\x03R\apayload\".\n" +
"\x04Type\x12\x14\n" +
"\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n" +
"\fMEMO_COMMENT\x10\x01\"=\n" +
"\x05Level\x12\x15\n" +
"\x11LEVEL_UNSPECIFIED\x10\x00\x12\b\n" +
"\x04INFO\x10\x01\x12\b\n" +
"\x04WARN\x10\x02\x12\t\n" +
"\x05ERROR\x10\x03:M\xeaAJ\n" +
"\x15memos.api.v1/Activity\x12\x15activities/{activity}\x1a\x04name*\n" +
"activities2\bactivity\"k\n" +
"\x0fActivityPayload\x12M\n" +
"\fmemo_comment\x18\x01 \x01(\v2(.memos.api.v1.ActivityMemoCommentPayloadH\x00R\vmemoCommentB\t\n" +
"\apayload\"S\n" +
"\x1aActivityMemoCommentPayload\x12\x12\n" +
"\x04memo\x18\x01 \x01(\tR\x04memo\x12!\n" +
"\frelated_memo\x18\x02 \x01(\tR\vrelatedMemo\"S\n" +
"\x15ListActivitiesRequest\x12\x1b\n" +
"\tpage_size\x18\x01 \x01(\x05R\bpageSize\x12\x1d\n" +
"\n" +
"page_token\x18\x02 \x01(\tR\tpageToken\"x\n" +
"\x16ListActivitiesResponse\x126\n" +
"\n" +
"activities\x18\x01 \x03(\v2\x16.memos.api.v1.ActivityR\n" +
"activities\x12&\n" +
"\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"G\n" +
"\x12GetActivityRequest\x121\n" +
"\x04name\x18\x01 \x01(\tB\x1d\xe0A\x02\xfaA\x17\n" +
"\x15memos.api.v1/ActivityR\x04name2\xff\x01\n" +
"\x0fActivityService\x12w\n" +
"\x0eListActivities\x12#.memos.api.v1.ListActivitiesRequest\x1a$.memos.api.v1.ListActivitiesResponse\"\x1a\x82\xd3\xe4\x93\x02\x14\x12\x12/api/v1/activities\x12s\n" +
"\vGetActivity\x12 .memos.api.v1.GetActivityRequest\x1a\x16.memos.api.v1.Activity\"*\xdaA\x04name\x82\xd3\xe4\x93\x02\x1d\x12\x1b/api/v1/{name=activities/*}B\xac\x01\n" +
"\x10com.memos.api.v1B\x14ActivityServiceProtoP\x01Z0github.com/usememos/memos/proto/gen/api/v1;apiv1\xa2\x02\x03MAX\xaa\x02\fMemos.Api.V1\xca\x02\fMemos\\Api\\V1\xe2\x02\x18Memos\\Api\\V1\\GPBMetadata\xea\x02\x0eMemos::Api::V1b\x06proto3"
var (
file_api_v1_activity_service_proto_rawDescOnce sync.Once
file_api_v1_activity_service_proto_rawDescData []byte
)
func file_api_v1_activity_service_proto_rawDescGZIP() []byte {
file_api_v1_activity_service_proto_rawDescOnce.Do(func() {
file_api_v1_activity_service_proto_rawDescData = protoimpl.X.CompressGZIP(unsafe.Slice(unsafe.StringData(file_api_v1_activity_service_proto_rawDesc), len(file_api_v1_activity_service_proto_rawDesc)))
})
return file_api_v1_activity_service_proto_rawDescData
}
var file_api_v1_activity_service_proto_enumTypes = make([]protoimpl.EnumInfo, 2)
var file_api_v1_activity_service_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_api_v1_activity_service_proto_goTypes = []any{
(Activity_Type)(0), // 0: memos.api.v1.Activity.Type
(Activity_Level)(0), // 1: memos.api.v1.Activity.Level
(*Activity)(nil), // 2: memos.api.v1.Activity
(*ActivityPayload)(nil), // 3: memos.api.v1.ActivityPayload
(*ActivityMemoCommentPayload)(nil), // 4: memos.api.v1.ActivityMemoCommentPayload
(*ListActivitiesRequest)(nil), // 5: memos.api.v1.ListActivitiesRequest
(*ListActivitiesResponse)(nil), // 6: memos.api.v1.ListActivitiesResponse
(*GetActivityRequest)(nil), // 7: memos.api.v1.GetActivityRequest
(*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp
}
var file_api_v1_activity_service_proto_depIdxs = []int32{
0, // 0: memos.api.v1.Activity.type:type_name -> memos.api.v1.Activity.Type
1, // 1: memos.api.v1.Activity.level:type_name -> memos.api.v1.Activity.Level
8, // 2: memos.api.v1.Activity.create_time:type_name -> google.protobuf.Timestamp
3, // 3: memos.api.v1.Activity.payload:type_name -> memos.api.v1.ActivityPayload
4, // 4: memos.api.v1.ActivityPayload.memo_comment:type_name -> memos.api.v1.ActivityMemoCommentPayload
2, // 5: memos.api.v1.ListActivitiesResponse.activities:type_name -> memos.api.v1.Activity
5, // 6: memos.api.v1.ActivityService.ListActivities:input_type -> memos.api.v1.ListActivitiesRequest
7, // 7: memos.api.v1.ActivityService.GetActivity:input_type -> memos.api.v1.GetActivityRequest
6, // 8: memos.api.v1.ActivityService.ListActivities:output_type -> memos.api.v1.ListActivitiesResponse
2, // 9: memos.api.v1.ActivityService.GetActivity:output_type -> memos.api.v1.Activity
8, // [8:10] is the sub-list for method output_type
6, // [6:8] is the sub-list for method input_type
6, // [6:6] is the sub-list for extension type_name
6, // [6:6] is the sub-list for extension extendee
0, // [0:6] is the sub-list for field type_name
}
func init() { file_api_v1_activity_service_proto_init() }
func file_api_v1_activity_service_proto_init() {
if File_api_v1_activity_service_proto != nil {
return
}
file_api_v1_activity_service_proto_msgTypes[1].OneofWrappers = []any{
(*ActivityPayload_MemoComment)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_activity_service_proto_rawDesc), len(file_api_v1_activity_service_proto_rawDesc)),
NumEnums: 2,
NumMessages: 6,
NumExtensions: 0,
NumServices: 1,
},
GoTypes: file_api_v1_activity_service_proto_goTypes,
DependencyIndexes: file_api_v1_activity_service_proto_depIdxs,
EnumInfos: file_api_v1_activity_service_proto_enumTypes,
MessageInfos: file_api_v1_activity_service_proto_msgTypes,
}.Build()
File_api_v1_activity_service_proto = out.File
file_api_v1_activity_service_proto_goTypes = nil
file_api_v1_activity_service_proto_depIdxs = nil
}

View File

@ -1,243 +0,0 @@
// Code generated by protoc-gen-grpc-gateway. DO NOT EDIT.
// source: api/v1/activity_service.proto
/*
Package apiv1 is a reverse proxy.
It translates gRPC into RESTful JSON APIs.
*/
package apiv1
import (
"context"
"errors"
"io"
"net/http"
"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
"github.com/grpc-ecosystem/grpc-gateway/v2/utilities"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/grpclog"
"google.golang.org/grpc/metadata"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/proto"
)
// Suppress "imported and not used" errors
var (
_ codes.Code
_ io.Reader
_ status.Status
_ = errors.New
_ = runtime.String
_ = utilities.NewDoubleArray
_ = metadata.Join
)
var filter_ActivityService_ListActivities_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)}
func request_ActivityService_ListActivities_0(ctx context.Context, marshaler runtime.Marshaler, client ActivityServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListActivitiesRequest
metadata runtime.ServerMetadata
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ActivityService_ListActivities_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := client.ListActivities(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_ActivityService_ListActivities_0(ctx context.Context, marshaler runtime.Marshaler, server ActivityServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq ListActivitiesRequest
metadata runtime.ServerMetadata
)
if err := req.ParseForm(); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_ActivityService_ListActivities_0); err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err)
}
msg, err := server.ListActivities(ctx, &protoReq)
return msg, metadata, err
}
func request_ActivityService_GetActivity_0(ctx context.Context, marshaler runtime.Marshaler, client ActivityServiceClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetActivityRequest
metadata runtime.ServerMetadata
err error
)
if req.Body != nil {
_, _ = io.Copy(io.Discard, req.Body)
}
val, ok := pathParams["name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
}
protoReq.Name, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
msg, err := client.GetActivity(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
return msg, metadata, err
}
func local_request_ActivityService_GetActivity_0(ctx context.Context, marshaler runtime.Marshaler, server ActivityServiceServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
var (
protoReq GetActivityRequest
metadata runtime.ServerMetadata
err error
)
val, ok := pathParams["name"]
if !ok {
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "name")
}
protoReq.Name, err = runtime.String(val)
if err != nil {
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "name", err)
}
msg, err := server.GetActivity(ctx, &protoReq)
return msg, metadata, err
}
// RegisterActivityServiceHandlerServer registers the http handlers for service ActivityService to "mux".
// UnaryRPC :call ActivityServiceServer directly.
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
// Note that using this registration option will cause many gRPC library features to stop working. Consider using RegisterActivityServiceHandlerFromEndpoint instead.
// GRPC interceptors will not work for this type of registration. To use interceptors, you must use the "runtime.WithMiddlewares" option in the "runtime.NewServeMux" call.
func RegisterActivityServiceHandlerServer(ctx context.Context, mux *runtime.ServeMux, server ActivityServiceServer) error {
mux.Handle(http.MethodGet, pattern_ActivityService_ListActivities_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.ActivityService/ListActivities", runtime.WithHTTPPathPattern("/api/v1/activities"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_ActivityService_ListActivities_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_ActivityService_ListActivities_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_ActivityService_GetActivity_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
var stream runtime.ServerTransportStream
ctx = grpc.NewContextWithServerTransportStream(ctx, &stream)
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateIncomingContext(ctx, mux, req, "/memos.api.v1.ActivityService/GetActivity", runtime.WithHTTPPathPattern("/api/v1/{name=activities/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := local_request_ActivityService_GetActivity_0(annotatedContext, inboundMarshaler, server, req, pathParams)
md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer())
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_ActivityService_GetActivity_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
// RegisterActivityServiceHandlerFromEndpoint is same as RegisterActivityServiceHandler but
// automatically dials to "endpoint" and closes the connection when "ctx" gets done.
func RegisterActivityServiceHandlerFromEndpoint(ctx context.Context, mux *runtime.ServeMux, endpoint string, opts []grpc.DialOption) (err error) {
conn, err := grpc.NewClient(endpoint, opts...)
if err != nil {
return err
}
defer func() {
if err != nil {
if cerr := conn.Close(); cerr != nil {
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
}
return
}
go func() {
<-ctx.Done()
if cerr := conn.Close(); cerr != nil {
grpclog.Errorf("Failed to close conn to %s: %v", endpoint, cerr)
}
}()
}()
return RegisterActivityServiceHandler(ctx, mux, conn)
}
// RegisterActivityServiceHandler registers the http handlers for service ActivityService to "mux".
// The handlers forward requests to the grpc endpoint over "conn".
func RegisterActivityServiceHandler(ctx context.Context, mux *runtime.ServeMux, conn *grpc.ClientConn) error {
return RegisterActivityServiceHandlerClient(ctx, mux, NewActivityServiceClient(conn))
}
// RegisterActivityServiceHandlerClient registers the http handlers for service ActivityService
// to "mux". The handlers forward requests to the grpc endpoint over the given implementation of "ActivityServiceClient".
// Note: the gRPC framework executes interceptors within the gRPC handler. If the passed in "ActivityServiceClient"
// doesn't go through the normal gRPC flow (creating a gRPC client etc.) then it will be up to the passed in
// "ActivityServiceClient" to call the correct interceptors. This client ignores the HTTP middlewares.
func RegisterActivityServiceHandlerClient(ctx context.Context, mux *runtime.ServeMux, client ActivityServiceClient) error {
mux.Handle(http.MethodGet, pattern_ActivityService_ListActivities_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.ActivityService/ListActivities", runtime.WithHTTPPathPattern("/api/v1/activities"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_ActivityService_ListActivities_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_ActivityService_ListActivities_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
mux.Handle(http.MethodGet, pattern_ActivityService_GetActivity_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
ctx, cancel := context.WithCancel(req.Context())
defer cancel()
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
annotatedContext, err := runtime.AnnotateContext(ctx, mux, req, "/memos.api.v1.ActivityService/GetActivity", runtime.WithHTTPPathPattern("/api/v1/{name=activities/*}"))
if err != nil {
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
return
}
resp, md, err := request_ActivityService_GetActivity_0(annotatedContext, inboundMarshaler, client, req, pathParams)
annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md)
if err != nil {
runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err)
return
}
forward_ActivityService_GetActivity_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
})
return nil
}
var (
pattern_ActivityService_ListActivities_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"api", "v1", "activities"}, ""))
pattern_ActivityService_GetActivity_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 1, 0, 4, 2, 5, 3}, []string{"api", "v1", "activities", "name"}, ""))
)
var (
forward_ActivityService_ListActivities_0 = runtime.ForwardResponseMessage
forward_ActivityService_GetActivity_0 = runtime.ForwardResponseMessage
)

View File

@ -1,163 +0,0 @@
// Code generated by protoc-gen-go-grpc. DO NOT EDIT.
// versions:
// - protoc-gen-go-grpc v1.6.1
// - protoc (unknown)
// source: api/v1/activity_service.proto
package apiv1
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.64.0 or later.
const _ = grpc.SupportPackageIsVersion9
const (
ActivityService_ListActivities_FullMethodName = "/memos.api.v1.ActivityService/ListActivities"
ActivityService_GetActivity_FullMethodName = "/memos.api.v1.ActivityService/GetActivity"
)
// ActivityServiceClient is the client API for ActivityService 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 ActivityServiceClient interface {
// ListActivities returns a list of activities.
ListActivities(ctx context.Context, in *ListActivitiesRequest, opts ...grpc.CallOption) (*ListActivitiesResponse, error)
// GetActivity returns the activity with the given id.
GetActivity(ctx context.Context, in *GetActivityRequest, opts ...grpc.CallOption) (*Activity, error)
}
type activityServiceClient struct {
cc grpc.ClientConnInterface
}
func NewActivityServiceClient(cc grpc.ClientConnInterface) ActivityServiceClient {
return &activityServiceClient{cc}
}
func (c *activityServiceClient) ListActivities(ctx context.Context, in *ListActivitiesRequest, opts ...grpc.CallOption) (*ListActivitiesResponse, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(ListActivitiesResponse)
err := c.cc.Invoke(ctx, ActivityService_ListActivities_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
func (c *activityServiceClient) GetActivity(ctx context.Context, in *GetActivityRequest, opts ...grpc.CallOption) (*Activity, error) {
cOpts := append([]grpc.CallOption{grpc.StaticMethod()}, opts...)
out := new(Activity)
err := c.cc.Invoke(ctx, ActivityService_GetActivity_FullMethodName, in, out, cOpts...)
if err != nil {
return nil, err
}
return out, nil
}
// ActivityServiceServer is the server API for ActivityService service.
// All implementations must embed UnimplementedActivityServiceServer
// for forward compatibility.
type ActivityServiceServer interface {
// ListActivities returns a list of activities.
ListActivities(context.Context, *ListActivitiesRequest) (*ListActivitiesResponse, error)
// GetActivity returns the activity with the given id.
GetActivity(context.Context, *GetActivityRequest) (*Activity, error)
mustEmbedUnimplementedActivityServiceServer()
}
// UnimplementedActivityServiceServer must be embedded to have
// forward compatible implementations.
//
// NOTE: this should be embedded by value instead of pointer to avoid a nil
// pointer dereference when methods are called.
type UnimplementedActivityServiceServer struct{}
func (UnimplementedActivityServiceServer) ListActivities(context.Context, *ListActivitiesRequest) (*ListActivitiesResponse, error) {
return nil, status.Error(codes.Unimplemented, "method ListActivities not implemented")
}
func (UnimplementedActivityServiceServer) GetActivity(context.Context, *GetActivityRequest) (*Activity, error) {
return nil, status.Error(codes.Unimplemented, "method GetActivity not implemented")
}
func (UnimplementedActivityServiceServer) mustEmbedUnimplementedActivityServiceServer() {}
func (UnimplementedActivityServiceServer) testEmbeddedByValue() {}
// UnsafeActivityServiceServer may be embedded to opt out of forward compatibility for this service.
// Use of this interface is not recommended, as added methods to ActivityServiceServer will
// result in compilation errors.
type UnsafeActivityServiceServer interface {
mustEmbedUnimplementedActivityServiceServer()
}
func RegisterActivityServiceServer(s grpc.ServiceRegistrar, srv ActivityServiceServer) {
// If the following call panics, it indicates UnimplementedActivityServiceServer was
// embedded by pointer and is nil. This will cause panics if an
// unimplemented method is ever invoked, so we test this at initialization
// time to prevent it from happening at runtime later due to I/O.
if t, ok := srv.(interface{ testEmbeddedByValue() }); ok {
t.testEmbeddedByValue()
}
s.RegisterService(&ActivityService_ServiceDesc, srv)
}
func _ActivityService_ListActivities_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(ListActivitiesRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ActivityServiceServer).ListActivities(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ActivityService_ListActivities_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ActivityServiceServer).ListActivities(ctx, req.(*ListActivitiesRequest))
}
return interceptor(ctx, in, info, handler)
}
func _ActivityService_GetActivity_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) {
in := new(GetActivityRequest)
if err := dec(in); err != nil {
return nil, err
}
if interceptor == nil {
return srv.(ActivityServiceServer).GetActivity(ctx, in)
}
info := &grpc.UnaryServerInfo{
Server: srv,
FullMethod: ActivityService_GetActivity_FullMethodName,
}
handler := func(ctx context.Context, req interface{}) (interface{}, error) {
return srv.(ActivityServiceServer).GetActivity(ctx, req.(*GetActivityRequest))
}
return interceptor(ctx, in, info, handler)
}
// ActivityService_ServiceDesc is the grpc.ServiceDesc for ActivityService service.
// It's only intended for direct use with grpc.RegisterService,
// and not to be introspected or modified (even as a copy)
var ActivityService_ServiceDesc = grpc.ServiceDesc{
ServiceName: "memos.api.v1.ActivityService",
HandlerType: (*ActivityServiceServer)(nil),
Methods: []grpc.MethodDesc{
{
MethodName: "ListActivities",
Handler: _ActivityService_ListActivities_Handler,
},
{
MethodName: "GetActivity",
Handler: _ActivityService_GetActivity_Handler,
},
},
Streams: []grpc.StreamDesc{},
Metadata: "api/v1/activity_service.proto",
}

View File

@ -1,142 +0,0 @@
// Code generated by protoc-gen-connect-go. DO NOT EDIT.
//
// Source: api/v1/activity_service.proto
package apiv1connect
import (
connect "connectrpc.com/connect"
context "context"
errors "errors"
v1 "github.com/usememos/memos/proto/gen/api/v1"
http "net/http"
strings "strings"
)
// This is a compile-time assertion to ensure that this generated file and the connect package are
// compatible. If you get a compiler error that this constant is not defined, this code was
// generated with a version of connect newer than the one compiled into your binary. You can fix the
// problem by either regenerating this code with an older version of connect or updating the connect
// version compiled into your binary.
const _ = connect.IsAtLeastVersion1_13_0
const (
// ActivityServiceName is the fully-qualified name of the ActivityService service.
ActivityServiceName = "memos.api.v1.ActivityService"
)
// These constants are the fully-qualified names of the RPCs defined in this package. They're
// exposed at runtime as Spec.Procedure and as the final two segments of the HTTP route.
//
// Note that these are different from the fully-qualified method names used by
// google.golang.org/protobuf/reflect/protoreflect. To convert from these constants to
// reflection-formatted method names, remove the leading slash and convert the remaining slash to a
// period.
const (
// ActivityServiceListActivitiesProcedure is the fully-qualified name of the ActivityService's
// ListActivities RPC.
ActivityServiceListActivitiesProcedure = "/memos.api.v1.ActivityService/ListActivities"
// ActivityServiceGetActivityProcedure is the fully-qualified name of the ActivityService's
// GetActivity RPC.
ActivityServiceGetActivityProcedure = "/memos.api.v1.ActivityService/GetActivity"
)
// ActivityServiceClient is a client for the memos.api.v1.ActivityService service.
type ActivityServiceClient interface {
// ListActivities returns a list of activities.
ListActivities(context.Context, *connect.Request[v1.ListActivitiesRequest]) (*connect.Response[v1.ListActivitiesResponse], error)
// GetActivity returns the activity with the given id.
GetActivity(context.Context, *connect.Request[v1.GetActivityRequest]) (*connect.Response[v1.Activity], error)
}
// NewActivityServiceClient constructs a client for the memos.api.v1.ActivityService service. By
// default, it uses the Connect protocol with the binary Protobuf Codec, asks for gzipped responses,
// and sends uncompressed requests. To use the gRPC or gRPC-Web protocols, supply the
// connect.WithGRPC() or connect.WithGRPCWeb() options.
//
// The URL supplied here should be the base URL for the Connect or gRPC server (for example,
// http://api.acme.com or https://acme.com/grpc).
func NewActivityServiceClient(httpClient connect.HTTPClient, baseURL string, opts ...connect.ClientOption) ActivityServiceClient {
baseURL = strings.TrimRight(baseURL, "/")
activityServiceMethods := v1.File_api_v1_activity_service_proto.Services().ByName("ActivityService").Methods()
return &activityServiceClient{
listActivities: connect.NewClient[v1.ListActivitiesRequest, v1.ListActivitiesResponse](
httpClient,
baseURL+ActivityServiceListActivitiesProcedure,
connect.WithSchema(activityServiceMethods.ByName("ListActivities")),
connect.WithClientOptions(opts...),
),
getActivity: connect.NewClient[v1.GetActivityRequest, v1.Activity](
httpClient,
baseURL+ActivityServiceGetActivityProcedure,
connect.WithSchema(activityServiceMethods.ByName("GetActivity")),
connect.WithClientOptions(opts...),
),
}
}
// activityServiceClient implements ActivityServiceClient.
type activityServiceClient struct {
listActivities *connect.Client[v1.ListActivitiesRequest, v1.ListActivitiesResponse]
getActivity *connect.Client[v1.GetActivityRequest, v1.Activity]
}
// ListActivities calls memos.api.v1.ActivityService.ListActivities.
func (c *activityServiceClient) ListActivities(ctx context.Context, req *connect.Request[v1.ListActivitiesRequest]) (*connect.Response[v1.ListActivitiesResponse], error) {
return c.listActivities.CallUnary(ctx, req)
}
// GetActivity calls memos.api.v1.ActivityService.GetActivity.
func (c *activityServiceClient) GetActivity(ctx context.Context, req *connect.Request[v1.GetActivityRequest]) (*connect.Response[v1.Activity], error) {
return c.getActivity.CallUnary(ctx, req)
}
// ActivityServiceHandler is an implementation of the memos.api.v1.ActivityService service.
type ActivityServiceHandler interface {
// ListActivities returns a list of activities.
ListActivities(context.Context, *connect.Request[v1.ListActivitiesRequest]) (*connect.Response[v1.ListActivitiesResponse], error)
// GetActivity returns the activity with the given id.
GetActivity(context.Context, *connect.Request[v1.GetActivityRequest]) (*connect.Response[v1.Activity], error)
}
// NewActivityServiceHandler builds an HTTP handler from the service implementation. It returns the
// path on which to mount the handler and the handler itself.
//
// By default, handlers support the Connect, gRPC, and gRPC-Web protocols with the binary Protobuf
// and JSON codecs. They also support gzip compression.
func NewActivityServiceHandler(svc ActivityServiceHandler, opts ...connect.HandlerOption) (string, http.Handler) {
activityServiceMethods := v1.File_api_v1_activity_service_proto.Services().ByName("ActivityService").Methods()
activityServiceListActivitiesHandler := connect.NewUnaryHandler(
ActivityServiceListActivitiesProcedure,
svc.ListActivities,
connect.WithSchema(activityServiceMethods.ByName("ListActivities")),
connect.WithHandlerOptions(opts...),
)
activityServiceGetActivityHandler := connect.NewUnaryHandler(
ActivityServiceGetActivityProcedure,
svc.GetActivity,
connect.WithSchema(activityServiceMethods.ByName("GetActivity")),
connect.WithHandlerOptions(opts...),
)
return "/memos.api.v1.ActivityService/", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
switch r.URL.Path {
case ActivityServiceListActivitiesProcedure:
activityServiceListActivitiesHandler.ServeHTTP(w, r)
case ActivityServiceGetActivityProcedure:
activityServiceGetActivityHandler.ServeHTTP(w, r)
default:
http.NotFound(w, r)
}
})
}
// UnimplementedActivityServiceHandler returns CodeUnimplemented from all methods.
type UnimplementedActivityServiceHandler struct{}
func (UnimplementedActivityServiceHandler) ListActivities(context.Context, *connect.Request[v1.ListActivitiesRequest]) (*connect.Response[v1.ListActivitiesResponse], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("memos.api.v1.ActivityService.ListActivities is not implemented"))
}
func (UnimplementedActivityServiceHandler) GetActivity(context.Context, *connect.Request[v1.GetActivityRequest]) (*connect.Response[v1.Activity], error) {
return nil, connect.NewError(connect.CodeUnimplemented, errors.New("memos.api.v1.ActivityService.GetActivity is not implemented"))
}

View File

@ -2022,8 +2022,10 @@ type UserNotification struct {
CreateTime *timestamppb.Timestamp `protobuf:"bytes,4,opt,name=create_time,json=createTime,proto3" json:"create_time,omitempty"`
// The type of the notification.
Type UserNotification_Type `protobuf:"varint,5,opt,name=type,proto3,enum=memos.api.v1.UserNotification_Type" json:"type,omitempty"`
// The activity ID associated with this notification.
ActivityId *int32 `protobuf:"varint,6,opt,name=activity_id,json=activityId,proto3,oneof" json:"activity_id,omitempty"`
// Types that are valid to be assigned to Payload:
//
// *UserNotification_MemoComment
Payload isUserNotification_Payload `protobuf_oneof:"payload"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
@ -2093,13 +2095,32 @@ func (x *UserNotification) GetType() UserNotification_Type {
return UserNotification_TYPE_UNSPECIFIED
}
func (x *UserNotification) GetActivityId() int32 {
if x != nil && x.ActivityId != nil {
return *x.ActivityId
func (x *UserNotification) GetPayload() isUserNotification_Payload {
if x != nil {
return x.Payload
}
return 0
return nil
}
func (x *UserNotification) GetMemoComment() *UserNotification_MemoCommentPayload {
if x != nil {
if x, ok := x.Payload.(*UserNotification_MemoComment); ok {
return x.MemoComment
}
}
return nil
}
type isUserNotification_Payload interface {
isUserNotification_Payload()
}
type UserNotification_MemoComment struct {
MemoComment *UserNotification_MemoCommentPayload `protobuf:"bytes,6,opt,name=memo_comment,json=memoComment,proto3,oneof"`
}
func (*UserNotification_MemoComment) isUserNotification_Payload() {}
type ListUserNotificationsRequest struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The parent user resource.
@ -2500,6 +2521,62 @@ func (x *UserSetting_WebhooksSetting) GetWebhooks() []*UserWebhook {
return nil
}
type UserNotification_MemoCommentPayload struct {
state protoimpl.MessageState `protogen:"open.v1"`
// The memo name of comment.
// Format: memos/{memo}
Memo string `protobuf:"bytes,1,opt,name=memo,proto3" json:"memo,omitempty"`
// The name of related memo.
// Format: memos/{memo}
RelatedMemo string `protobuf:"bytes,2,opt,name=related_memo,json=relatedMemo,proto3" json:"related_memo,omitempty"`
unknownFields protoimpl.UnknownFields
sizeCache protoimpl.SizeCache
}
func (x *UserNotification_MemoCommentPayload) Reset() {
*x = UserNotification_MemoCommentPayload{}
mi := &file_api_v1_user_service_proto_msgTypes[37]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
func (x *UserNotification_MemoCommentPayload) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*UserNotification_MemoCommentPayload) ProtoMessage() {}
func (x *UserNotification_MemoCommentPayload) ProtoReflect() protoreflect.Message {
mi := &file_api_v1_user_service_proto_msgTypes[37]
if x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
ms.StoreMessageInfo(mi)
}
return ms
}
return mi.MessageOf(x)
}
// Deprecated: Use UserNotification_MemoCommentPayload.ProtoReflect.Descriptor instead.
func (*UserNotification_MemoCommentPayload) Descriptor() ([]byte, []int) {
return file_api_v1_user_service_proto_rawDescGZIP(), []int{28, 0}
}
func (x *UserNotification_MemoCommentPayload) GetMemo() string {
if x != nil {
return x.Memo
}
return ""
}
func (x *UserNotification_MemoCommentPayload) GetRelatedMemo() string {
if x != nil {
return x.RelatedMemo
}
return ""
}
var File_api_v1_user_service_proto protoreflect.FileDescriptor
const file_api_v1_user_service_proto_rawDesc = "" +
@ -2668,7 +2745,7 @@ const file_api_v1_user_service_proto_rawDesc = "" +
"\vupdate_mask\x18\x02 \x01(\v2\x1a.google.protobuf.FieldMaskR\n" +
"updateMask\"3\n" +
"\x18DeleteUserWebhookRequest\x12\x17\n" +
"\x04name\x18\x01 \x01(\tB\x03\xe0A\x02R\x04name\"\xbe\x04\n" +
"\x04name\x18\x01 \x01(\tB\x03\xe0A\x02R\x04name\"\xb8\x05\n" +
"\x10UserNotification\x12\x1a\n" +
"\x04name\x18\x01 \x01(\tB\x06\xe0A\x03\xe0A\bR\x04name\x121\n" +
"\x06sender\x18\x02 \x01(\tB\x19\xe0A\x03\xfaA\x13\n" +
@ -2676,9 +2753,11 @@ const file_api_v1_user_service_proto_rawDesc = "" +
"\x06status\x18\x03 \x01(\x0e2%.memos.api.v1.UserNotification.StatusB\x03\xe0A\x01R\x06status\x12@\n" +
"\vcreate_time\x18\x04 \x01(\v2\x1a.google.protobuf.TimestampB\x03\xe0A\x03R\n" +
"createTime\x12<\n" +
"\x04type\x18\x05 \x01(\x0e2#.memos.api.v1.UserNotification.TypeB\x03\xe0A\x03R\x04type\x12)\n" +
"\vactivity_id\x18\x06 \x01(\x05B\x03\xe0A\x01H\x00R\n" +
"activityId\x88\x01\x01\":\n" +
"\x04type\x18\x05 \x01(\x0e2#.memos.api.v1.UserNotification.TypeB\x03\xe0A\x03R\x04type\x12[\n" +
"\fmemo_comment\x18\x06 \x01(\v21.memos.api.v1.UserNotification.MemoCommentPayloadB\x03\xe0A\x03H\x00R\vmemoComment\x1aK\n" +
"\x12MemoCommentPayload\x12\x12\n" +
"\x04memo\x18\x01 \x01(\tR\x04memo\x12!\n" +
"\frelated_memo\x18\x02 \x01(\tR\vrelatedMemo\":\n" +
"\x06Status\x12\x16\n" +
"\x12STATUS_UNSPECIFIED\x10\x00\x12\n" +
"\n" +
@ -2687,8 +2766,8 @@ const file_api_v1_user_service_proto_rawDesc = "" +
"\x04Type\x12\x14\n" +
"\x10TYPE_UNSPECIFIED\x10\x00\x12\x10\n" +
"\fMEMO_COMMENT\x10\x01:p\xeaAm\n" +
"\x1dmemos.api.v1/UserNotification\x12)users/{user}/notifications/{notification}\x1a\x04name*\rnotifications2\fnotificationB\x0e\n" +
"\f_activity_id\"\xb4\x01\n" +
"\x1dmemos.api.v1/UserNotification\x12)users/{user}/notifications/{notification}\x1a\x04name*\rnotifications2\fnotificationB\t\n" +
"\apayload\"\xb4\x01\n" +
"\x1cListUserNotificationsRequest\x121\n" +
"\x06parent\x18\x01 \x01(\tB\x19\xe0A\x02\xfaA\x13\n" +
"\x11memos.api.v1/UserR\x06parent\x12 \n" +
@ -2745,136 +2824,138 @@ func file_api_v1_user_service_proto_rawDescGZIP() []byte {
}
var file_api_v1_user_service_proto_enumTypes = make([]protoimpl.EnumInfo, 4)
var file_api_v1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 37)
var file_api_v1_user_service_proto_msgTypes = make([]protoimpl.MessageInfo, 38)
var file_api_v1_user_service_proto_goTypes = []any{
(User_Role)(0), // 0: memos.api.v1.User.Role
(UserSetting_Key)(0), // 1: memos.api.v1.UserSetting.Key
(UserNotification_Status)(0), // 2: memos.api.v1.UserNotification.Status
(UserNotification_Type)(0), // 3: memos.api.v1.UserNotification.Type
(*User)(nil), // 4: memos.api.v1.User
(*ListUsersRequest)(nil), // 5: memos.api.v1.ListUsersRequest
(*ListUsersResponse)(nil), // 6: memos.api.v1.ListUsersResponse
(*GetUserRequest)(nil), // 7: memos.api.v1.GetUserRequest
(*CreateUserRequest)(nil), // 8: memos.api.v1.CreateUserRequest
(*UpdateUserRequest)(nil), // 9: memos.api.v1.UpdateUserRequest
(*DeleteUserRequest)(nil), // 10: memos.api.v1.DeleteUserRequest
(*UserStats)(nil), // 11: memos.api.v1.UserStats
(*GetUserStatsRequest)(nil), // 12: memos.api.v1.GetUserStatsRequest
(*ListAllUserStatsRequest)(nil), // 13: memos.api.v1.ListAllUserStatsRequest
(*ListAllUserStatsResponse)(nil), // 14: memos.api.v1.ListAllUserStatsResponse
(*UserSetting)(nil), // 15: memos.api.v1.UserSetting
(*GetUserSettingRequest)(nil), // 16: memos.api.v1.GetUserSettingRequest
(*UpdateUserSettingRequest)(nil), // 17: memos.api.v1.UpdateUserSettingRequest
(*ListUserSettingsRequest)(nil), // 18: memos.api.v1.ListUserSettingsRequest
(*ListUserSettingsResponse)(nil), // 19: memos.api.v1.ListUserSettingsResponse
(*PersonalAccessToken)(nil), // 20: memos.api.v1.PersonalAccessToken
(*ListPersonalAccessTokensRequest)(nil), // 21: memos.api.v1.ListPersonalAccessTokensRequest
(*ListPersonalAccessTokensResponse)(nil), // 22: memos.api.v1.ListPersonalAccessTokensResponse
(*CreatePersonalAccessTokenRequest)(nil), // 23: memos.api.v1.CreatePersonalAccessTokenRequest
(*CreatePersonalAccessTokenResponse)(nil), // 24: memos.api.v1.CreatePersonalAccessTokenResponse
(*DeletePersonalAccessTokenRequest)(nil), // 25: memos.api.v1.DeletePersonalAccessTokenRequest
(*UserWebhook)(nil), // 26: memos.api.v1.UserWebhook
(*ListUserWebhooksRequest)(nil), // 27: memos.api.v1.ListUserWebhooksRequest
(*ListUserWebhooksResponse)(nil), // 28: memos.api.v1.ListUserWebhooksResponse
(*CreateUserWebhookRequest)(nil), // 29: memos.api.v1.CreateUserWebhookRequest
(*UpdateUserWebhookRequest)(nil), // 30: memos.api.v1.UpdateUserWebhookRequest
(*DeleteUserWebhookRequest)(nil), // 31: memos.api.v1.DeleteUserWebhookRequest
(*UserNotification)(nil), // 32: memos.api.v1.UserNotification
(*ListUserNotificationsRequest)(nil), // 33: memos.api.v1.ListUserNotificationsRequest
(*ListUserNotificationsResponse)(nil), // 34: memos.api.v1.ListUserNotificationsResponse
(*UpdateUserNotificationRequest)(nil), // 35: memos.api.v1.UpdateUserNotificationRequest
(*DeleteUserNotificationRequest)(nil), // 36: memos.api.v1.DeleteUserNotificationRequest
nil, // 37: memos.api.v1.UserStats.TagCountEntry
(*UserStats_MemoTypeStats)(nil), // 38: memos.api.v1.UserStats.MemoTypeStats
(*UserSetting_GeneralSetting)(nil), // 39: memos.api.v1.UserSetting.GeneralSetting
(*UserSetting_WebhooksSetting)(nil), // 40: memos.api.v1.UserSetting.WebhooksSetting
(State)(0), // 41: memos.api.v1.State
(*timestamppb.Timestamp)(nil), // 42: google.protobuf.Timestamp
(*fieldmaskpb.FieldMask)(nil), // 43: google.protobuf.FieldMask
(*emptypb.Empty)(nil), // 44: google.protobuf.Empty
(User_Role)(0), // 0: memos.api.v1.User.Role
(UserSetting_Key)(0), // 1: memos.api.v1.UserSetting.Key
(UserNotification_Status)(0), // 2: memos.api.v1.UserNotification.Status
(UserNotification_Type)(0), // 3: memos.api.v1.UserNotification.Type
(*User)(nil), // 4: memos.api.v1.User
(*ListUsersRequest)(nil), // 5: memos.api.v1.ListUsersRequest
(*ListUsersResponse)(nil), // 6: memos.api.v1.ListUsersResponse
(*GetUserRequest)(nil), // 7: memos.api.v1.GetUserRequest
(*CreateUserRequest)(nil), // 8: memos.api.v1.CreateUserRequest
(*UpdateUserRequest)(nil), // 9: memos.api.v1.UpdateUserRequest
(*DeleteUserRequest)(nil), // 10: memos.api.v1.DeleteUserRequest
(*UserStats)(nil), // 11: memos.api.v1.UserStats
(*GetUserStatsRequest)(nil), // 12: memos.api.v1.GetUserStatsRequest
(*ListAllUserStatsRequest)(nil), // 13: memos.api.v1.ListAllUserStatsRequest
(*ListAllUserStatsResponse)(nil), // 14: memos.api.v1.ListAllUserStatsResponse
(*UserSetting)(nil), // 15: memos.api.v1.UserSetting
(*GetUserSettingRequest)(nil), // 16: memos.api.v1.GetUserSettingRequest
(*UpdateUserSettingRequest)(nil), // 17: memos.api.v1.UpdateUserSettingRequest
(*ListUserSettingsRequest)(nil), // 18: memos.api.v1.ListUserSettingsRequest
(*ListUserSettingsResponse)(nil), // 19: memos.api.v1.ListUserSettingsResponse
(*PersonalAccessToken)(nil), // 20: memos.api.v1.PersonalAccessToken
(*ListPersonalAccessTokensRequest)(nil), // 21: memos.api.v1.ListPersonalAccessTokensRequest
(*ListPersonalAccessTokensResponse)(nil), // 22: memos.api.v1.ListPersonalAccessTokensResponse
(*CreatePersonalAccessTokenRequest)(nil), // 23: memos.api.v1.CreatePersonalAccessTokenRequest
(*CreatePersonalAccessTokenResponse)(nil), // 24: memos.api.v1.CreatePersonalAccessTokenResponse
(*DeletePersonalAccessTokenRequest)(nil), // 25: memos.api.v1.DeletePersonalAccessTokenRequest
(*UserWebhook)(nil), // 26: memos.api.v1.UserWebhook
(*ListUserWebhooksRequest)(nil), // 27: memos.api.v1.ListUserWebhooksRequest
(*ListUserWebhooksResponse)(nil), // 28: memos.api.v1.ListUserWebhooksResponse
(*CreateUserWebhookRequest)(nil), // 29: memos.api.v1.CreateUserWebhookRequest
(*UpdateUserWebhookRequest)(nil), // 30: memos.api.v1.UpdateUserWebhookRequest
(*DeleteUserWebhookRequest)(nil), // 31: memos.api.v1.DeleteUserWebhookRequest
(*UserNotification)(nil), // 32: memos.api.v1.UserNotification
(*ListUserNotificationsRequest)(nil), // 33: memos.api.v1.ListUserNotificationsRequest
(*ListUserNotificationsResponse)(nil), // 34: memos.api.v1.ListUserNotificationsResponse
(*UpdateUserNotificationRequest)(nil), // 35: memos.api.v1.UpdateUserNotificationRequest
(*DeleteUserNotificationRequest)(nil), // 36: memos.api.v1.DeleteUserNotificationRequest
nil, // 37: memos.api.v1.UserStats.TagCountEntry
(*UserStats_MemoTypeStats)(nil), // 38: memos.api.v1.UserStats.MemoTypeStats
(*UserSetting_GeneralSetting)(nil), // 39: memos.api.v1.UserSetting.GeneralSetting
(*UserSetting_WebhooksSetting)(nil), // 40: memos.api.v1.UserSetting.WebhooksSetting
(*UserNotification_MemoCommentPayload)(nil), // 41: memos.api.v1.UserNotification.MemoCommentPayload
(State)(0), // 42: memos.api.v1.State
(*timestamppb.Timestamp)(nil), // 43: google.protobuf.Timestamp
(*fieldmaskpb.FieldMask)(nil), // 44: google.protobuf.FieldMask
(*emptypb.Empty)(nil), // 45: google.protobuf.Empty
}
var file_api_v1_user_service_proto_depIdxs = []int32{
0, // 0: memos.api.v1.User.role:type_name -> memos.api.v1.User.Role
41, // 1: memos.api.v1.User.state:type_name -> memos.api.v1.State
42, // 2: memos.api.v1.User.create_time:type_name -> google.protobuf.Timestamp
42, // 3: memos.api.v1.User.update_time:type_name -> google.protobuf.Timestamp
42, // 1: memos.api.v1.User.state:type_name -> memos.api.v1.State
43, // 2: memos.api.v1.User.create_time:type_name -> google.protobuf.Timestamp
43, // 3: memos.api.v1.User.update_time:type_name -> google.protobuf.Timestamp
4, // 4: memos.api.v1.ListUsersResponse.users:type_name -> memos.api.v1.User
43, // 5: memos.api.v1.GetUserRequest.read_mask:type_name -> google.protobuf.FieldMask
44, // 5: memos.api.v1.GetUserRequest.read_mask:type_name -> google.protobuf.FieldMask
4, // 6: memos.api.v1.CreateUserRequest.user:type_name -> memos.api.v1.User
4, // 7: memos.api.v1.UpdateUserRequest.user:type_name -> memos.api.v1.User
43, // 8: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask
42, // 9: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp
44, // 8: memos.api.v1.UpdateUserRequest.update_mask:type_name -> google.protobuf.FieldMask
43, // 9: memos.api.v1.UserStats.memo_display_timestamps:type_name -> google.protobuf.Timestamp
38, // 10: memos.api.v1.UserStats.memo_type_stats:type_name -> memos.api.v1.UserStats.MemoTypeStats
37, // 11: memos.api.v1.UserStats.tag_count:type_name -> memos.api.v1.UserStats.TagCountEntry
11, // 12: memos.api.v1.ListAllUserStatsResponse.stats:type_name -> memos.api.v1.UserStats
39, // 13: memos.api.v1.UserSetting.general_setting:type_name -> memos.api.v1.UserSetting.GeneralSetting
40, // 14: memos.api.v1.UserSetting.webhooks_setting:type_name -> memos.api.v1.UserSetting.WebhooksSetting
15, // 15: memos.api.v1.UpdateUserSettingRequest.setting:type_name -> memos.api.v1.UserSetting
43, // 16: memos.api.v1.UpdateUserSettingRequest.update_mask:type_name -> google.protobuf.FieldMask
44, // 16: memos.api.v1.UpdateUserSettingRequest.update_mask:type_name -> google.protobuf.FieldMask
15, // 17: memos.api.v1.ListUserSettingsResponse.settings:type_name -> memos.api.v1.UserSetting
42, // 18: memos.api.v1.PersonalAccessToken.created_at:type_name -> google.protobuf.Timestamp
42, // 19: memos.api.v1.PersonalAccessToken.expires_at:type_name -> google.protobuf.Timestamp
42, // 20: memos.api.v1.PersonalAccessToken.last_used_at:type_name -> google.protobuf.Timestamp
43, // 18: memos.api.v1.PersonalAccessToken.created_at:type_name -> google.protobuf.Timestamp
43, // 19: memos.api.v1.PersonalAccessToken.expires_at:type_name -> google.protobuf.Timestamp
43, // 20: memos.api.v1.PersonalAccessToken.last_used_at:type_name -> google.protobuf.Timestamp
20, // 21: memos.api.v1.ListPersonalAccessTokensResponse.personal_access_tokens:type_name -> memos.api.v1.PersonalAccessToken
20, // 22: memos.api.v1.CreatePersonalAccessTokenResponse.personal_access_token:type_name -> memos.api.v1.PersonalAccessToken
42, // 23: memos.api.v1.UserWebhook.create_time:type_name -> google.protobuf.Timestamp
42, // 24: memos.api.v1.UserWebhook.update_time:type_name -> google.protobuf.Timestamp
43, // 23: memos.api.v1.UserWebhook.create_time:type_name -> google.protobuf.Timestamp
43, // 24: memos.api.v1.UserWebhook.update_time:type_name -> google.protobuf.Timestamp
26, // 25: memos.api.v1.ListUserWebhooksResponse.webhooks:type_name -> memos.api.v1.UserWebhook
26, // 26: memos.api.v1.CreateUserWebhookRequest.webhook:type_name -> memos.api.v1.UserWebhook
26, // 27: memos.api.v1.UpdateUserWebhookRequest.webhook:type_name -> memos.api.v1.UserWebhook
43, // 28: memos.api.v1.UpdateUserWebhookRequest.update_mask:type_name -> google.protobuf.FieldMask
44, // 28: memos.api.v1.UpdateUserWebhookRequest.update_mask:type_name -> google.protobuf.FieldMask
2, // 29: memos.api.v1.UserNotification.status:type_name -> memos.api.v1.UserNotification.Status
42, // 30: memos.api.v1.UserNotification.create_time:type_name -> google.protobuf.Timestamp
43, // 30: memos.api.v1.UserNotification.create_time:type_name -> google.protobuf.Timestamp
3, // 31: memos.api.v1.UserNotification.type:type_name -> memos.api.v1.UserNotification.Type
32, // 32: memos.api.v1.ListUserNotificationsResponse.notifications:type_name -> memos.api.v1.UserNotification
32, // 33: memos.api.v1.UpdateUserNotificationRequest.notification:type_name -> memos.api.v1.UserNotification
43, // 34: memos.api.v1.UpdateUserNotificationRequest.update_mask:type_name -> google.protobuf.FieldMask
26, // 35: memos.api.v1.UserSetting.WebhooksSetting.webhooks:type_name -> memos.api.v1.UserWebhook
5, // 36: memos.api.v1.UserService.ListUsers:input_type -> memos.api.v1.ListUsersRequest
7, // 37: memos.api.v1.UserService.GetUser:input_type -> memos.api.v1.GetUserRequest
8, // 38: memos.api.v1.UserService.CreateUser:input_type -> memos.api.v1.CreateUserRequest
9, // 39: memos.api.v1.UserService.UpdateUser:input_type -> memos.api.v1.UpdateUserRequest
10, // 40: memos.api.v1.UserService.DeleteUser:input_type -> memos.api.v1.DeleteUserRequest
13, // 41: memos.api.v1.UserService.ListAllUserStats:input_type -> memos.api.v1.ListAllUserStatsRequest
12, // 42: memos.api.v1.UserService.GetUserStats:input_type -> memos.api.v1.GetUserStatsRequest
16, // 43: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest
17, // 44: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest
18, // 45: memos.api.v1.UserService.ListUserSettings:input_type -> memos.api.v1.ListUserSettingsRequest
21, // 46: memos.api.v1.UserService.ListPersonalAccessTokens:input_type -> memos.api.v1.ListPersonalAccessTokensRequest
23, // 47: memos.api.v1.UserService.CreatePersonalAccessToken:input_type -> memos.api.v1.CreatePersonalAccessTokenRequest
25, // 48: memos.api.v1.UserService.DeletePersonalAccessToken:input_type -> memos.api.v1.DeletePersonalAccessTokenRequest
27, // 49: memos.api.v1.UserService.ListUserWebhooks:input_type -> memos.api.v1.ListUserWebhooksRequest
29, // 50: memos.api.v1.UserService.CreateUserWebhook:input_type -> memos.api.v1.CreateUserWebhookRequest
30, // 51: memos.api.v1.UserService.UpdateUserWebhook:input_type -> memos.api.v1.UpdateUserWebhookRequest
31, // 52: memos.api.v1.UserService.DeleteUserWebhook:input_type -> memos.api.v1.DeleteUserWebhookRequest
33, // 53: memos.api.v1.UserService.ListUserNotifications:input_type -> memos.api.v1.ListUserNotificationsRequest
35, // 54: memos.api.v1.UserService.UpdateUserNotification:input_type -> memos.api.v1.UpdateUserNotificationRequest
36, // 55: memos.api.v1.UserService.DeleteUserNotification:input_type -> memos.api.v1.DeleteUserNotificationRequest
6, // 56: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse
4, // 57: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User
4, // 58: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User
4, // 59: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User
44, // 60: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty
14, // 61: memos.api.v1.UserService.ListAllUserStats:output_type -> memos.api.v1.ListAllUserStatsResponse
11, // 62: memos.api.v1.UserService.GetUserStats:output_type -> memos.api.v1.UserStats
15, // 63: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting
15, // 64: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting
19, // 65: memos.api.v1.UserService.ListUserSettings:output_type -> memos.api.v1.ListUserSettingsResponse
22, // 66: memos.api.v1.UserService.ListPersonalAccessTokens:output_type -> memos.api.v1.ListPersonalAccessTokensResponse
24, // 67: memos.api.v1.UserService.CreatePersonalAccessToken:output_type -> memos.api.v1.CreatePersonalAccessTokenResponse
44, // 68: memos.api.v1.UserService.DeletePersonalAccessToken:output_type -> google.protobuf.Empty
28, // 69: memos.api.v1.UserService.ListUserWebhooks:output_type -> memos.api.v1.ListUserWebhooksResponse
26, // 70: memos.api.v1.UserService.CreateUserWebhook:output_type -> memos.api.v1.UserWebhook
26, // 71: memos.api.v1.UserService.UpdateUserWebhook:output_type -> memos.api.v1.UserWebhook
44, // 72: memos.api.v1.UserService.DeleteUserWebhook:output_type -> google.protobuf.Empty
34, // 73: memos.api.v1.UserService.ListUserNotifications:output_type -> memos.api.v1.ListUserNotificationsResponse
32, // 74: memos.api.v1.UserService.UpdateUserNotification:output_type -> memos.api.v1.UserNotification
44, // 75: memos.api.v1.UserService.DeleteUserNotification:output_type -> google.protobuf.Empty
56, // [56:76] is the sub-list for method output_type
36, // [36:56] is the sub-list for method input_type
36, // [36:36] is the sub-list for extension type_name
36, // [36:36] is the sub-list for extension extendee
0, // [0:36] is the sub-list for field type_name
41, // 32: memos.api.v1.UserNotification.memo_comment:type_name -> memos.api.v1.UserNotification.MemoCommentPayload
32, // 33: memos.api.v1.ListUserNotificationsResponse.notifications:type_name -> memos.api.v1.UserNotification
32, // 34: memos.api.v1.UpdateUserNotificationRequest.notification:type_name -> memos.api.v1.UserNotification
44, // 35: memos.api.v1.UpdateUserNotificationRequest.update_mask:type_name -> google.protobuf.FieldMask
26, // 36: memos.api.v1.UserSetting.WebhooksSetting.webhooks:type_name -> memos.api.v1.UserWebhook
5, // 37: memos.api.v1.UserService.ListUsers:input_type -> memos.api.v1.ListUsersRequest
7, // 38: memos.api.v1.UserService.GetUser:input_type -> memos.api.v1.GetUserRequest
8, // 39: memos.api.v1.UserService.CreateUser:input_type -> memos.api.v1.CreateUserRequest
9, // 40: memos.api.v1.UserService.UpdateUser:input_type -> memos.api.v1.UpdateUserRequest
10, // 41: memos.api.v1.UserService.DeleteUser:input_type -> memos.api.v1.DeleteUserRequest
13, // 42: memos.api.v1.UserService.ListAllUserStats:input_type -> memos.api.v1.ListAllUserStatsRequest
12, // 43: memos.api.v1.UserService.GetUserStats:input_type -> memos.api.v1.GetUserStatsRequest
16, // 44: memos.api.v1.UserService.GetUserSetting:input_type -> memos.api.v1.GetUserSettingRequest
17, // 45: memos.api.v1.UserService.UpdateUserSetting:input_type -> memos.api.v1.UpdateUserSettingRequest
18, // 46: memos.api.v1.UserService.ListUserSettings:input_type -> memos.api.v1.ListUserSettingsRequest
21, // 47: memos.api.v1.UserService.ListPersonalAccessTokens:input_type -> memos.api.v1.ListPersonalAccessTokensRequest
23, // 48: memos.api.v1.UserService.CreatePersonalAccessToken:input_type -> memos.api.v1.CreatePersonalAccessTokenRequest
25, // 49: memos.api.v1.UserService.DeletePersonalAccessToken:input_type -> memos.api.v1.DeletePersonalAccessTokenRequest
27, // 50: memos.api.v1.UserService.ListUserWebhooks:input_type -> memos.api.v1.ListUserWebhooksRequest
29, // 51: memos.api.v1.UserService.CreateUserWebhook:input_type -> memos.api.v1.CreateUserWebhookRequest
30, // 52: memos.api.v1.UserService.UpdateUserWebhook:input_type -> memos.api.v1.UpdateUserWebhookRequest
31, // 53: memos.api.v1.UserService.DeleteUserWebhook:input_type -> memos.api.v1.DeleteUserWebhookRequest
33, // 54: memos.api.v1.UserService.ListUserNotifications:input_type -> memos.api.v1.ListUserNotificationsRequest
35, // 55: memos.api.v1.UserService.UpdateUserNotification:input_type -> memos.api.v1.UpdateUserNotificationRequest
36, // 56: memos.api.v1.UserService.DeleteUserNotification:input_type -> memos.api.v1.DeleteUserNotificationRequest
6, // 57: memos.api.v1.UserService.ListUsers:output_type -> memos.api.v1.ListUsersResponse
4, // 58: memos.api.v1.UserService.GetUser:output_type -> memos.api.v1.User
4, // 59: memos.api.v1.UserService.CreateUser:output_type -> memos.api.v1.User
4, // 60: memos.api.v1.UserService.UpdateUser:output_type -> memos.api.v1.User
45, // 61: memos.api.v1.UserService.DeleteUser:output_type -> google.protobuf.Empty
14, // 62: memos.api.v1.UserService.ListAllUserStats:output_type -> memos.api.v1.ListAllUserStatsResponse
11, // 63: memos.api.v1.UserService.GetUserStats:output_type -> memos.api.v1.UserStats
15, // 64: memos.api.v1.UserService.GetUserSetting:output_type -> memos.api.v1.UserSetting
15, // 65: memos.api.v1.UserService.UpdateUserSetting:output_type -> memos.api.v1.UserSetting
19, // 66: memos.api.v1.UserService.ListUserSettings:output_type -> memos.api.v1.ListUserSettingsResponse
22, // 67: memos.api.v1.UserService.ListPersonalAccessTokens:output_type -> memos.api.v1.ListPersonalAccessTokensResponse
24, // 68: memos.api.v1.UserService.CreatePersonalAccessToken:output_type -> memos.api.v1.CreatePersonalAccessTokenResponse
45, // 69: memos.api.v1.UserService.DeletePersonalAccessToken:output_type -> google.protobuf.Empty
28, // 70: memos.api.v1.UserService.ListUserWebhooks:output_type -> memos.api.v1.ListUserWebhooksResponse
26, // 71: memos.api.v1.UserService.CreateUserWebhook:output_type -> memos.api.v1.UserWebhook
26, // 72: memos.api.v1.UserService.UpdateUserWebhook:output_type -> memos.api.v1.UserWebhook
45, // 73: memos.api.v1.UserService.DeleteUserWebhook:output_type -> google.protobuf.Empty
34, // 74: memos.api.v1.UserService.ListUserNotifications:output_type -> memos.api.v1.ListUserNotificationsResponse
32, // 75: memos.api.v1.UserService.UpdateUserNotification:output_type -> memos.api.v1.UserNotification
45, // 76: memos.api.v1.UserService.DeleteUserNotification:output_type -> google.protobuf.Empty
57, // [57:77] is the sub-list for method output_type
37, // [37:57] is the sub-list for method input_type
37, // [37:37] is the sub-list for extension type_name
37, // [37:37] is the sub-list for extension extendee
0, // [0:37] is the sub-list for field type_name
}
func init() { file_api_v1_user_service_proto_init() }
@ -2887,14 +2968,16 @@ func file_api_v1_user_service_proto_init() {
(*UserSetting_GeneralSetting_)(nil),
(*UserSetting_WebhooksSetting_)(nil),
}
file_api_v1_user_service_proto_msgTypes[28].OneofWrappers = []any{}
file_api_v1_user_service_proto_msgTypes[28].OneofWrappers = []any{
(*UserNotification_MemoComment)(nil),
}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: unsafe.Slice(unsafe.StringData(file_api_v1_user_service_proto_rawDesc), len(file_api_v1_user_service_proto_rawDesc)),
NumEnums: 4,
NumMessages: 37,
NumMessages: 38,
NumExtensions: 0,
NumServices: 1,
},

View File

@ -6,69 +6,6 @@ info:
title: ""
version: 0.0.1
paths:
/api/v1/activities:
get:
tags:
- ActivityService
description: ListActivities returns a list of activities.
operationId: ActivityService_ListActivities
parameters:
- name: pageSize
in: query
description: |-
The maximum number of activities to return.
The service may return fewer than this value.
If unspecified, at most 100 activities will be returned.
The maximum value is 1000; values above 1000 will be coerced to 1000.
schema:
type: integer
format: int32
- name: pageToken
in: query
description: |-
A page token, received from a previous `ListActivities` call.
Provide this to retrieve the subsequent page.
schema:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/ListActivitiesResponse'
default:
description: Default error response
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
/api/v1/activities/{activity}:
get:
tags:
- ActivityService
description: GetActivity returns the activity with the given id.
operationId: ActivityService_GetActivity
parameters:
- name: activity
in: path
description: The activity id.
required: true
schema:
type: string
responses:
"200":
description: OK
content:
application/json:
schema:
$ref: '#/components/schemas/Activity'
default:
description: Default error response
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
/api/v1/attachments:
get:
tags:
@ -1927,70 +1864,6 @@ paths:
$ref: '#/components/schemas/Status'
components:
schemas:
Activity:
type: object
properties:
name:
readOnly: true
type: string
description: |-
The name of the activity.
Format: activities/{id}
creator:
readOnly: true
type: string
description: |-
The name of the creator.
Format: users/{user}
type:
readOnly: true
enum:
- TYPE_UNSPECIFIED
- MEMO_COMMENT
type: string
description: The type of the activity.
format: enum
level:
readOnly: true
enum:
- LEVEL_UNSPECIFIED
- INFO
- WARN
- ERROR
type: string
description: The level of the activity.
format: enum
createTime:
readOnly: true
type: string
description: The create time of the activity.
format: date-time
payload:
readOnly: true
allOf:
- $ref: '#/components/schemas/ActivityPayload'
description: The payload of the activity.
ActivityMemoCommentPayload:
type: object
properties:
memo:
type: string
description: |-
The memo name of comment.
Format: memos/{memo}
relatedMemo:
type: string
description: |-
The name of related memo.
Format: memos/{memo}
description: ActivityMemoCommentPayload represents the payload of a memo comment activity.
ActivityPayload:
type: object
properties:
memoComment:
allOf:
- $ref: '#/components/schemas/ActivityMemoCommentPayload'
description: Memo comment activity payload.
Attachment:
required:
- filename
@ -2243,20 +2116,6 @@ components:
- $ref: '#/components/schemas/StorageSetting_S3Config'
description: The S3 config.
description: Storage configuration settings for instance attachments.
ListActivitiesResponse:
type: object
properties:
activities:
type: array
items:
$ref: '#/components/schemas/Activity'
description: The activities.
nextPageToken:
type: string
description: |-
A token to retrieve the next page of results.
Pass this value in the page_token field in the subsequent call to `ListActivities`
method to retrieve the next page of results.
ListAllUserStatsResponse:
type: object
properties:
@ -2942,10 +2801,23 @@ components:
type: string
description: The type of the notification.
format: enum
activityId:
type: integer
description: The activity ID associated with this notification.
format: int32
memoComment:
readOnly: true
allOf:
- $ref: '#/components/schemas/UserNotification_MemoCommentPayload'
UserNotification_MemoCommentPayload:
type: object
properties:
memo:
type: string
description: |-
The memo name of comment.
Format: memos/{memo}
relatedMemo:
type: string
description: |-
The name of related memo.
Format: memos/{memo}
UserSetting:
type: object
properties:
@ -3061,7 +2933,6 @@ components:
format: date-time
description: UserWebhook represents a webhook owned by a user.
tags:
- name: ActivityService
- name: AttachmentService
- name: AuthService
- name: IdentityProviderService

View File

@ -60,8 +60,6 @@ func TestProtectedMethodsRequireAuth(t *testing.T) {
"/memos.api.v1.ShortcutService/ListShortcuts",
"/memos.api.v1.ShortcutService/UpdateShortcut",
"/memos.api.v1.ShortcutService/DeleteShortcut",
// Activity Service
"/memos.api.v1.ActivityService/GetActivity",
}
for _, method := range protectedMethods {

View File

@ -1,175 +0,0 @@
package v1
import (
"context"
"fmt"
"time"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/status"
"google.golang.org/protobuf/types/known/timestamppb"
v1pb "github.com/usememos/memos/proto/gen/api/v1"
storepb "github.com/usememos/memos/proto/gen/store"
"github.com/usememos/memos/store"
)
func (s *APIV1Service) ListActivities(ctx context.Context, request *v1pb.ListActivitiesRequest) (*v1pb.ListActivitiesResponse, error) {
var limit, offset int
if request.PageToken != "" {
var pageToken v1pb.PageToken
if err := unmarshalPageToken(request.PageToken, &pageToken); err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid page token: %v", err)
}
limit = int(pageToken.Limit)
offset = int(pageToken.Offset)
} else {
limit = int(request.PageSize)
}
if limit <= 0 {
limit = DefaultPageSize
}
if limit > MaxPageSize {
limit = MaxPageSize
}
limitPlusOne := limit + 1
activities, err := s.Store.ListActivities(ctx, &store.FindActivity{
Limit: &limitPlusOne,
Offset: &offset,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to list activities: %v", err)
}
var activityMessages []*v1pb.Activity
nextPageToken := ""
if len(activities) == limitPlusOne {
activities = activities[:limit]
nextPageToken, err = getPageToken(limit, offset+limit)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get next page token, error: %v", err)
}
}
for _, activity := range activities {
activityMessage, err := s.convertActivityFromStore(ctx, activity)
if err != nil {
// Skip activities that reference deleted memos instead of failing the entire list
continue
}
if activityMessage != nil {
activityMessages = append(activityMessages, activityMessage)
}
}
return &v1pb.ListActivitiesResponse{
Activities: activityMessages,
NextPageToken: nextPageToken,
}, nil
}
func (s *APIV1Service) GetActivity(ctx context.Context, request *v1pb.GetActivityRequest) (*v1pb.Activity, error) {
activityID, err := ExtractActivityIDFromName(request.Name)
if err != nil {
return nil, status.Errorf(codes.InvalidArgument, "invalid activity name: %v", err)
}
activity, err := s.Store.GetActivity(ctx, &store.FindActivity{
ID: &activityID,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get activity: %v", err)
}
activityMessage, err := s.convertActivityFromStore(ctx, activity)
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to convert activity from store: %v", err)
}
if activityMessage == nil {
return nil, status.Errorf(codes.NotFound, "activity references deleted content")
}
return activityMessage, nil
}
// convertActivityFromStore converts a storage-layer activity to an API activity.
// This handles the mapping between internal activity representation and the public API,
// including proper type and level conversions.
// Returns nil if the activity references deleted content (to allow graceful skipping).
func (s *APIV1Service) convertActivityFromStore(ctx context.Context, activity *store.Activity) (*v1pb.Activity, error) {
payload, err := s.convertActivityPayloadFromStore(ctx, activity.Payload)
if err != nil {
return nil, err
}
// Skip activities that reference deleted memos
if payload == nil {
return nil, nil
}
// Convert store activity type to proto enum
var activityType v1pb.Activity_Type
switch activity.Type {
case store.ActivityTypeMemoComment:
activityType = v1pb.Activity_MEMO_COMMENT
default:
activityType = v1pb.Activity_TYPE_UNSPECIFIED
}
// Convert store activity level to proto enum
var activityLevel v1pb.Activity_Level
switch activity.Level {
case store.ActivityLevelInfo:
activityLevel = v1pb.Activity_INFO
default:
activityLevel = v1pb.Activity_LEVEL_UNSPECIFIED
}
return &v1pb.Activity{
Name: fmt.Sprintf("%s%d", ActivityNamePrefix, activity.ID),
Creator: fmt.Sprintf("%s%d", UserNamePrefix, activity.CreatorID),
Type: activityType,
Level: activityLevel,
CreateTime: timestamppb.New(time.Unix(activity.CreatedTs, 0)),
Payload: payload,
}, nil
}
// convertActivityPayloadFromStore converts a storage-layer activity payload to an API payload.
// This resolves references (e.g., memo IDs) to resource names for the API.
// Returns nil if the activity references deleted content (to allow graceful skipping).
func (s *APIV1Service) convertActivityPayloadFromStore(ctx context.Context, payload *storepb.ActivityPayload) (*v1pb.ActivityPayload, error) {
v2Payload := &v1pb.ActivityPayload{}
if payload.MemoComment != nil {
// Fetch the comment memo
memo, err := s.Store.GetMemo(ctx, &store.FindMemo{
ID: &payload.MemoComment.MemoId,
ExcludeContent: true,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get memo: %v", err)
}
// If the comment memo was deleted, skip this activity gracefully
if memo == nil {
return nil, nil
}
// Fetch the related memo (the one being commented on)
relatedMemo, err := s.Store.GetMemo(ctx, &store.FindMemo{
ID: &payload.MemoComment.RelatedMemoId,
ExcludeContent: true,
})
if err != nil {
return nil, status.Errorf(codes.Internal, "failed to get related memo: %v", err)
}
// If the related memo was deleted, skip this activity gracefully
if relatedMemo == nil {
return nil, nil
}
v2Payload.Payload = &v1pb.ActivityPayload_MemoComment{
MemoComment: &v1pb.ActivityMemoCommentPayload{
Memo: fmt.Sprintf("%s%s", MemoNamePrefix, memo.UID),
RelatedMemo: fmt.Sprintf("%s%s", MemoNamePrefix, relatedMemo.UID),
},
}
}
return v2Payload, nil
}

View File

@ -40,7 +40,6 @@ func (s *ConnectServiceHandler) RegisterConnectHandlers(mux *http.ServeMux, opts
wrap(apiv1connect.NewMemoServiceHandler(s, opts...)),
wrap(apiv1connect.NewAttachmentServiceHandler(s, opts...)),
wrap(apiv1connect.NewShortcutServiceHandler(s, opts...)),
wrap(apiv1connect.NewActivityServiceHandler(s, opts...)),
wrap(apiv1connect.NewIdentityProviderServiceHandler(s, opts...)),
}

View File

@ -429,24 +429,6 @@ func (s *ConnectServiceHandler) DeleteShortcut(ctx context.Context, req *connect
return connect.NewResponse(resp), nil
}
// ActivityService
func (s *ConnectServiceHandler) ListActivities(ctx context.Context, req *connect.Request[v1pb.ListActivitiesRequest]) (*connect.Response[v1pb.ListActivitiesResponse], error) {
resp, err := s.APIV1Service.ListActivities(ctx, req.Msg)
if err != nil {
return nil, convertGRPCError(err)
}
return connect.NewResponse(resp), nil
}
func (s *ConnectServiceHandler) GetActivity(ctx context.Context, req *connect.Request[v1pb.GetActivityRequest]) (*connect.Response[v1pb.Activity], error) {
resp, err := s.APIV1Service.GetActivity(ctx, req.Msg)
if err != nil {
return nil, convertGRPCError(err)
}
return connect.NewResponse(resp), nil
}
// IdentityProviderService
func (s *ConnectServiceHandler) ListIdentityProviders(ctx context.Context, req *connect.Request[v1pb.ListIdentityProvidersRequest]) (*connect.Response[v1pb.ListIdentityProvidersResponse], error) {

View File

@ -21,7 +21,6 @@ const (
ReactionNamePrefix = "reactions/"
InboxNamePrefix = "inboxes/"
IdentityProviderNamePrefix = "identity-providers/"
ActivityNamePrefix = "activities/"
WebhookNamePrefix = "webhooks/"
)
@ -145,18 +144,6 @@ func ExtractIdentityProviderUIDFromName(name string) (string, error) {
return tokens[0], nil
}
func ExtractActivityIDFromName(name string) (int32, error) {
tokens, err := GetNameParentTokens(name, ActivityNamePrefix)
if err != nil {
return 0, err
}
id, err := util.ConvertStringToInt32(tokens[0])
if err != nil {
return 0, errors.Errorf("invalid activity ID %q", tokens[0])
}
return id, nil
}
// ValidateAndGenerateUID validates a user-provided UID or generates a new one.
// If provided is empty, a new shortuuid is generated.
// If provided is non-empty, it is validated against base.UIDMatcher.

View File

@ -1,263 +0,0 @@
package test
import (
"context"
"testing"
"github.com/stretchr/testify/require"
apiv1 "github.com/usememos/memos/proto/gen/api/v1"
v1 "github.com/usememos/memos/server/router/api/v1" //nolint:revive
"github.com/usememos/memos/store"
)
// TestListActivitiesWithDeletedMemos verifies that ListActivities gracefully handles
// activities that reference deleted memos instead of crashing the entire request.
func TestListActivitiesWithDeletedMemos(t *testing.T) {
ctx := context.Background()
ts := NewTestService(t)
defer ts.Cleanup()
// Create two users - one to create memo, one to comment
userOne, err := ts.CreateRegularUser(ctx, "test-user-1")
require.NoError(t, err)
userOneCtx := ts.CreateUserContext(ctx, userOne.ID)
userTwo, err := ts.CreateRegularUser(ctx, "test-user-2")
require.NoError(t, err)
userTwoCtx := ts.CreateUserContext(ctx, userTwo.ID)
// Create a memo by userOne
memo1, err := ts.Service.CreateMemo(userOneCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "Original memo",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
require.NotNil(t, memo1)
// Create a comment on the memo by userTwo (this will create an activity for userOne)
comment, err := ts.Service.CreateMemoComment(userTwoCtx, &apiv1.CreateMemoCommentRequest{
Name: memo1.Name,
Comment: &apiv1.Memo{
Content: "This is a comment",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
require.NotNil(t, comment)
// Verify activity was created for the comment (check from userOne's perspective - they receive the notification)
activities, err := ts.Service.ListActivities(userOneCtx, &apiv1.ListActivitiesRequest{})
require.NoError(t, err)
initialActivityCount := len(activities.Activities)
require.Greater(t, initialActivityCount, 0, "Should have at least one activity")
// Delete the original memo (this deletes the comment too)
_, err = ts.Service.DeleteMemo(userOneCtx, &apiv1.DeleteMemoRequest{
Name: memo1.Name,
})
require.NoError(t, err)
// List activities again - should succeed even though the memo is deleted
activities, err = ts.Service.ListActivities(userOneCtx, &apiv1.ListActivitiesRequest{})
require.NoError(t, err)
// Activities list should be empty or not contain the deleted memo activity
for _, activity := range activities.Activities {
if activity.Payload != nil && activity.Payload.GetMemoComment() != nil {
require.NotEqual(t, memo1.Name, activity.Payload.GetMemoComment().Memo,
"Activity should not reference deleted memo")
}
}
// After deletion, there should be fewer activities
require.LessOrEqual(t, len(activities.Activities), initialActivityCount-1,
"Should have filtered out the activity for the deleted memo")
}
// TestGetActivityWithDeletedMemo verifies that GetActivity returns a proper error
// when trying to fetch an activity that references a deleted memo.
func TestGetActivityWithDeletedMemo(t *testing.T) {
ctx := context.Background()
ts := NewTestService(t)
defer ts.Cleanup()
// Create two users
userOne, err := ts.CreateRegularUser(ctx, "test-user-1")
require.NoError(t, err)
userOneCtx := ts.CreateUserContext(ctx, userOne.ID)
userTwo, err := ts.CreateRegularUser(ctx, "test-user-2")
require.NoError(t, err)
userTwoCtx := ts.CreateUserContext(ctx, userTwo.ID)
// Create a memo by userOne
memo1, err := ts.Service.CreateMemo(userOneCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "Original memo",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
require.NotNil(t, memo1)
// Create a comment to trigger activity creation by userTwo
comment, err := ts.Service.CreateMemoComment(userTwoCtx, &apiv1.CreateMemoCommentRequest{
Name: memo1.Name,
Comment: &apiv1.Memo{
Content: "Comment",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
require.NotNil(t, comment)
// Get the activity ID by listing activities from userOne's perspective
activities, err := ts.Service.ListActivities(userOneCtx, &apiv1.ListActivitiesRequest{})
require.NoError(t, err)
require.Greater(t, len(activities.Activities), 0)
activityName := activities.Activities[0].Name
// Delete the memo
_, err = ts.Service.DeleteMemo(userOneCtx, &apiv1.DeleteMemoRequest{
Name: memo1.Name,
})
require.NoError(t, err)
// Try to get the specific activity - should return NotFound error
_, err = ts.Service.GetActivity(userOneCtx, &apiv1.GetActivityRequest{
Name: activityName,
})
require.Error(t, err)
require.Contains(t, err.Error(), "activity references deleted content")
}
// TestActivitiesWithPartiallyDeletedMemos verifies that when some memos are deleted,
// other valid activities are still returned.
func TestActivitiesWithPartiallyDeletedMemos(t *testing.T) {
ctx := context.Background()
ts := NewTestService(t)
defer ts.Cleanup()
// Create two users
userOne, err := ts.CreateRegularUser(ctx, "test-user-1")
require.NoError(t, err)
userOneCtx := ts.CreateUserContext(ctx, userOne.ID)
userTwo, err := ts.CreateRegularUser(ctx, "test-user-2")
require.NoError(t, err)
userTwoCtx := ts.CreateUserContext(ctx, userTwo.ID)
// Create two memos by userOne
memo1, err := ts.Service.CreateMemo(userOneCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "First memo",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
memo2, err := ts.Service.CreateMemo(userOneCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "Second memo",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
// Create comments on both by userTwo (creates activities for userOne)
_, err = ts.Service.CreateMemoComment(userTwoCtx, &apiv1.CreateMemoCommentRequest{
Name: memo1.Name,
Comment: &apiv1.Memo{
Content: "Comment on first",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
_, err = ts.Service.CreateMemoComment(userTwoCtx, &apiv1.CreateMemoCommentRequest{
Name: memo2.Name,
Comment: &apiv1.Memo{
Content: "Comment on second",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
// Should have 2 activities from userOne's perspective
activities, err := ts.Service.ListActivities(userOneCtx, &apiv1.ListActivitiesRequest{})
require.NoError(t, err)
require.Equal(t, 2, len(activities.Activities))
// Delete first memo
_, err = ts.Service.DeleteMemo(userOneCtx, &apiv1.DeleteMemoRequest{
Name: memo1.Name,
})
require.NoError(t, err)
// List activities - should still work and return only the second memo's activity
activities, err = ts.Service.ListActivities(userOneCtx, &apiv1.ListActivitiesRequest{})
require.NoError(t, err)
require.Equal(t, 1, len(activities.Activities), "Should have 1 activity remaining")
// Verify the remaining activity relates to a valid memo
require.NotNil(t, activities.Activities[0].Payload.GetMemoComment())
require.Contains(t, activities.Activities[0].Payload.GetMemoComment().RelatedMemo, "memos/")
}
// TestActivityStoreDirectDeletion tests the scenario where a memo is deleted directly
// from the store (simulating database-level deletion or migration).
func TestActivityStoreDirectDeletion(t *testing.T) {
ctx := context.Background()
ts := NewTestService(t)
defer ts.Cleanup()
user, err := ts.CreateRegularUser(ctx, "test-user")
require.NoError(t, err)
userCtx := ts.CreateUserContext(ctx, user.ID)
// Create a memo
memo1, err := ts.Service.CreateMemo(userCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "Test memo",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
// Create a comment
comment, err := ts.Service.CreateMemoComment(userCtx, &apiv1.CreateMemoCommentRequest{
Name: memo1.Name,
Comment: &apiv1.Memo{
Content: "Test comment",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
// Extract memo UID from the comment name
commentMemoUID, err := v1.ExtractMemoUIDFromName(comment.Name)
require.NoError(t, err)
commentMemo, err := ts.Store.GetMemo(ctx, &store.FindMemo{
UID: &commentMemoUID,
})
require.NoError(t, err)
require.NotNil(t, commentMemo)
// Delete the comment memo directly from store (simulating orphaned activity)
err = ts.Store.DeleteMemo(ctx, &store.DeleteMemo{ID: commentMemo.ID})
require.NoError(t, err)
// List activities should still succeed even with orphaned activity
activities, err := ts.Service.ListActivities(userCtx, &apiv1.ListActivitiesRequest{})
require.NoError(t, err)
// Activities should be empty or not include the orphaned one
for _, activity := range activities.Activities {
if activity.Payload != nil && activity.Payload.GetMemoComment() != nil {
require.NotEqual(t, comment.Name, activity.Payload.GetMemoComment().Memo,
"Should not return activity with deleted memo")
}
}
}

View File

@ -1,67 +0,0 @@
package test
import (
"context"
"fmt"
"testing"
"github.com/stretchr/testify/require"
apiv1 "github.com/usememos/memos/proto/gen/api/v1"
)
func TestListActivities(t *testing.T) {
ctx := context.Background()
ts := NewTestService(t)
defer ts.Cleanup()
// Create userOne
userOne, err := ts.CreateRegularUser(ctx, "test-user-1")
require.NoError(t, err)
userOneCtx := ts.CreateUserContext(ctx, userOne.ID)
// Create userTwo
userTwo, err := ts.CreateRegularUser(ctx, "test-user-2")
require.NoError(t, err)
userTwoCtx := ts.CreateUserContext(ctx, userTwo.ID)
// UserOne creates a memo
memo, err := ts.Service.CreateMemo(userOneCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "Base memo",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
// UserTwo creates 15 comments on the memo to generate 15 activities
for i := 0; i < 15; i++ {
_, err := ts.Service.CreateMemoComment(userTwoCtx, &apiv1.CreateMemoCommentRequest{
Name: memo.Name,
Comment: &apiv1.Memo{
Content: fmt.Sprintf("Comment %d", i),
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
}
// List activities with page size 10 (as admin or userOne)
// Activities are visible to the receiver (UserOne)
resp, err := ts.Service.ListActivities(userOneCtx, &apiv1.ListActivitiesRequest{
PageSize: 10,
})
require.NoError(t, err)
require.Len(t, resp.Activities, 10)
require.NotEmpty(t, resp.NextPageToken)
// List next page
resp, err = ts.Service.ListActivities(userOneCtx, &apiv1.ListActivitiesRequest{
PageSize: 10,
PageToken: resp.NextPageToken,
})
require.NoError(t, err)
require.Len(t, resp.Activities, 5)
require.Empty(t, resp.NextPageToken)
}

View File

@ -0,0 +1,151 @@
package test
import (
"context"
"fmt"
"testing"
"github.com/stretchr/testify/require"
apiv1 "github.com/usememos/memos/proto/gen/api/v1"
storepb "github.com/usememos/memos/proto/gen/store"
"github.com/usememos/memos/store"
)
func TestListUserNotificationsIncludesMemoCommentPayload(t *testing.T) {
ctx := context.Background()
ts := NewTestService(t)
defer ts.Cleanup()
owner, err := ts.CreateRegularUser(ctx, "notification-owner")
require.NoError(t, err)
ownerCtx := ts.CreateUserContext(ctx, owner.ID)
commenter, err := ts.CreateRegularUser(ctx, "notification-commenter")
require.NoError(t, err)
commenterCtx := ts.CreateUserContext(ctx, commenter.ID)
memo, err := ts.Service.CreateMemo(ownerCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "Base memo",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
comment, err := ts.Service.CreateMemoComment(commenterCtx, &apiv1.CreateMemoCommentRequest{
Name: memo.Name,
Comment: &apiv1.Memo{
Content: "Comment content",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
resp, err := ts.Service.ListUserNotifications(ownerCtx, &apiv1.ListUserNotificationsRequest{
Parent: fmt.Sprintf("users/%d", owner.ID),
})
require.NoError(t, err)
require.Len(t, resp.Notifications, 1)
notification := resp.Notifications[0]
require.Equal(t, apiv1.UserNotification_MEMO_COMMENT, notification.Type)
require.NotNil(t, notification.GetMemoComment())
require.Equal(t, comment.Name, notification.GetMemoComment().Memo)
require.Equal(t, memo.Name, notification.GetMemoComment().RelatedMemo)
}
func TestListUserNotificationsOmitsPayloadWhenActivityMissing(t *testing.T) {
ctx := context.Background()
ts := NewTestService(t)
defer ts.Cleanup()
owner, err := ts.CreateRegularUser(ctx, "notification-owner")
require.NoError(t, err)
ownerCtx := ts.CreateUserContext(ctx, owner.ID)
commenter, err := ts.CreateRegularUser(ctx, "notification-commenter")
require.NoError(t, err)
commenterCtx := ts.CreateUserContext(ctx, commenter.ID)
memo, err := ts.Service.CreateMemo(ownerCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "Base memo",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
_, err = ts.Service.CreateMemoComment(commenterCtx, &apiv1.CreateMemoCommentRequest{
Name: memo.Name,
Comment: &apiv1.Memo{
Content: "Comment content",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
messageType := storepb.InboxMessage_MEMO_COMMENT
inboxes, err := ts.Store.ListInboxes(ctx, &store.FindInbox{
ReceiverID: &owner.ID,
MessageType: &messageType,
})
require.NoError(t, err)
require.Len(t, inboxes, 1)
require.NotNil(t, inboxes[0].Message)
require.NotNil(t, inboxes[0].Message.ActivityId)
_, err = ts.Store.GetDriver().GetDB().ExecContext(ctx, "DELETE FROM activity WHERE id = ?", *inboxes[0].Message.ActivityId)
require.NoError(t, err)
resp, err := ts.Service.ListUserNotifications(ownerCtx, &apiv1.ListUserNotificationsRequest{
Parent: fmt.Sprintf("users/%d", owner.ID),
})
require.NoError(t, err)
require.Len(t, resp.Notifications, 1)
require.Nil(t, resp.Notifications[0].GetMemoComment())
}
func TestListUserNotificationsOmitsPayloadWhenMemosDeleted(t *testing.T) {
ctx := context.Background()
ts := NewTestService(t)
defer ts.Cleanup()
owner, err := ts.CreateRegularUser(ctx, "notification-owner")
require.NoError(t, err)
ownerCtx := ts.CreateUserContext(ctx, owner.ID)
commenter, err := ts.CreateRegularUser(ctx, "notification-commenter")
require.NoError(t, err)
commenterCtx := ts.CreateUserContext(ctx, commenter.ID)
memo, err := ts.Service.CreateMemo(ownerCtx, &apiv1.CreateMemoRequest{
Memo: &apiv1.Memo{
Content: "Base memo",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
_, err = ts.Service.CreateMemoComment(commenterCtx, &apiv1.CreateMemoCommentRequest{
Name: memo.Name,
Comment: &apiv1.Memo{
Content: "Comment content",
Visibility: apiv1.Visibility_PUBLIC,
},
})
require.NoError(t, err)
_, err = ts.Service.DeleteMemo(ownerCtx, &apiv1.DeleteMemoRequest{
Name: memo.Name,
})
require.NoError(t, err)
resp, err := ts.Service.ListUserNotifications(ownerCtx, &apiv1.ListUserNotificationsRequest{
Parent: fmt.Sprintf("users/%d", owner.ID),
})
require.NoError(t, err)
require.Len(t, resp.Notifications, 1)
require.Equal(t, apiv1.UserNotification_MEMO_COMMENT, resp.Notifications[0].Type)
require.Nil(t, resp.Notifications[0].GetMemoComment())
}

View File

@ -1399,7 +1399,7 @@ func (s *APIV1Service) DeleteUserNotification(ctx context.Context, request *v1pb
// convertInboxToUserNotification converts a storage-layer inbox to an API notification.
// This handles the mapping between the internal inbox representation and the public API.
func (*APIV1Service) convertInboxToUserNotification(_ context.Context, inbox *store.Inbox) (*v1pb.UserNotification, error) {
func (s *APIV1Service) convertInboxToUserNotification(ctx context.Context, inbox *store.Inbox) (*v1pb.UserNotification, error) {
notification := &v1pb.UserNotification{
Name: fmt.Sprintf("users/%d/notifications/%d", inbox.ReceiverID, inbox.ID),
Sender: fmt.Sprintf("%s%d", UserNamePrefix, inbox.SenderID),
@ -1425,14 +1425,63 @@ func (*APIV1Service) convertInboxToUserNotification(_ context.Context, inbox *st
notification.Type = v1pb.UserNotification_TYPE_UNSPECIFIED
}
if inbox.Message.ActivityId != nil {
notification.ActivityId = inbox.Message.ActivityId
payload, err := s.convertUserNotificationPayload(ctx, inbox.Message)
if err != nil {
return nil, err
}
if payload != nil {
notification.Payload = &v1pb.UserNotification_MemoComment{
MemoComment: payload,
}
}
}
return notification, nil
}
func (s *APIV1Service) convertUserNotificationPayload(ctx context.Context, message *storepb.InboxMessage) (*v1pb.UserNotification_MemoCommentPayload, error) {
if message == nil || message.Type != storepb.InboxMessage_MEMO_COMMENT || message.ActivityId == nil {
return nil, nil
}
activity, err := s.Store.GetActivity(ctx, &store.FindActivity{
ID: message.ActivityId,
})
if err != nil {
return nil, errors.Wrap(err, "failed to get activity")
}
if activity == nil || activity.Payload == nil || activity.Payload.MemoComment == nil {
return nil, nil
}
commentMemo, err := s.Store.GetMemo(ctx, &store.FindMemo{
ID: &activity.Payload.MemoComment.MemoId,
ExcludeContent: true,
})
if err != nil {
return nil, errors.Wrap(err, "failed to get comment memo")
}
if commentMemo == nil {
return nil, nil
}
relatedMemo, err := s.Store.GetMemo(ctx, &store.FindMemo{
ID: &activity.Payload.MemoComment.RelatedMemoId,
ExcludeContent: true,
})
if err != nil {
return nil, errors.Wrap(err, "failed to get related memo")
}
if relatedMemo == nil {
return nil, nil
}
return &v1pb.UserNotification_MemoCommentPayload{
Memo: fmt.Sprintf("%s%s", MemoNamePrefix, commentMemo.UID),
RelatedMemo: fmt.Sprintf("%s%s", MemoNamePrefix, relatedMemo.UID),
}, nil
}
// ExtractNotificationIDFromName extracts the notification ID from a resource name.
// Expected format: users/{user_id}/notifications/{notification_id}.
func ExtractNotificationIDFromName(name string) (int32, error) {

View File

@ -24,7 +24,6 @@ type APIV1Service struct {
v1pb.UnimplementedMemoServiceServer
v1pb.UnimplementedAttachmentServiceServer
v1pb.UnimplementedShortcutServiceServer
v1pb.UnimplementedActivityServiceServer
v1pb.UnimplementedIdentityProviderServiceServer
Secret string
@ -107,9 +106,6 @@ func (s *APIV1Service) RegisterGateway(ctx context.Context, echoServer *echo.Ech
if err := v1pb.RegisterShortcutServiceHandlerServer(ctx, gwMux, s); err != nil {
return err
}
if err := v1pb.RegisterActivityServiceHandlerServer(ctx, gwMux, s); err != nil {
return err
}
if err := v1pb.RegisterIdentityProviderServiceHandlerServer(ctx, gwMux, s); err != nil {
return err
}

View File

@ -4,8 +4,7 @@ import { CheckIcon, MessageCircleIcon, TrashIcon, XIcon } from "lucide-react";
import { useState } from "react";
import toast from "react-hot-toast";
import UserAvatar from "@/components/UserAvatar";
import { activityServiceClient, memoServiceClient, userServiceClient } from "@/connect";
import { activityNamePrefix } from "@/helpers/resource-names";
import { memoServiceClient, userServiceClient } from "@/connect";
import useAsyncEffect from "@/hooks/useAsyncEffect";
import useNavigateTo from "@/hooks/useNavigateTo";
import { useUser } from "@/hooks/useUserQueries";
@ -31,38 +30,33 @@ function MemoCommentMessage({ notification }: Props) {
const { data: sender } = useUser(senderName || "", { enabled: !!senderName });
useAsyncEffect(async () => {
if (!notification.activityId) {
if (notification.payload?.case !== "memoComment") {
setHasError(true);
return;
}
try {
const activity = await activityServiceClient.getActivity({
name: `${activityNamePrefix}${notification.activityId}`,
const memoCommentPayload = notification.payload.value;
const memo = await memoServiceClient.getMemo({
name: memoCommentPayload.relatedMemo,
});
setRelatedMemo(memo);
if (activity.payload?.payload?.case === "memoComment") {
const memoCommentPayload = activity.payload.payload.value;
const memo = await memoServiceClient.getMemo({
name: memoCommentPayload.relatedMemo,
});
setRelatedMemo(memo);
const comment = await memoServiceClient.getMemo({
name: memoCommentPayload.memo,
});
setCommentMemo(comment);
const comment = await memoServiceClient.getMemo({
name: memoCommentPayload.memo,
});
setCommentMemo(comment);
setSenderName(notification.sender);
setInitialized(true);
}
setSenderName(notification.sender);
setInitialized(true);
} catch (error) {
handleError(error, () => {}, {
context: "Failed to fetch activity",
context: "Failed to fetch memo comment notification",
onError: () => setHasError(true),
});
return;
}
}, [notification.activityId]);
}, [notification.payload, notification.sender]);
const handleNavigateToMemo = async () => {
if (!relatedMemo) {

View File

@ -2,7 +2,6 @@ import { timestampDate } from "@bufbuild/protobuf/wkt";
import { Code, ConnectError, createClient, type Interceptor } from "@connectrpc/connect";
import { createConnectTransport } from "@connectrpc/connect-web";
import { getAccessToken, hasStoredToken, isTokenExpired, REQUEST_TOKEN_EXPIRY_BUFFER_MS, setAccessToken } from "./auth-state";
import { ActivityService } from "./types/proto/api/v1/activity_service_pb";
import { AttachmentService } from "./types/proto/api/v1/attachment_service_pb";
import { AuthService } from "./types/proto/api/v1/auth_service_pb";
import { IdentityProviderService } from "./types/proto/api/v1/idp_service_pb";
@ -197,7 +196,6 @@ export const userServiceClient = createClient(UserService, transport);
export const memoServiceClient = createClient(MemoService, transport);
export const attachmentServiceClient = createClient(AttachmentService, transport);
export const shortcutServiceClient = createClient(ShortcutService, transport);
export const activityServiceClient = createClient(ActivityService, transport);
// Configuration service clients
export const identityProviderServiceClient = createClient(IdentityProviderService, transport);

View File

@ -6,7 +6,6 @@ export const instanceSettingNamePrefix = "instance/settings/";
export const userNamePrefix = "users/";
export const memoNamePrefix = "memos/";
export const identityProviderNamePrefix = "identity-providers/";
export const activityNamePrefix = "activities/";
export const extractUserIdFromName = (name: string) => {
return name.split(userNamePrefix).pop() || "";

View File

@ -1,304 +0,0 @@
// @generated by protoc-gen-es v2.11.0 with parameter "target=ts"
// @generated from file api/v1/activity_service.proto (package memos.api.v1, syntax proto3)
/* eslint-disable */
import type { GenEnum, GenFile, GenMessage, GenService } from "@bufbuild/protobuf/codegenv2";
import { enumDesc, fileDesc, messageDesc, serviceDesc } from "@bufbuild/protobuf/codegenv2";
import { file_google_api_annotations } from "../../google/api/annotations_pb";
import { file_google_api_client } from "../../google/api/client_pb";
import { file_google_api_field_behavior } from "../../google/api/field_behavior_pb";
import { file_google_api_resource } from "../../google/api/resource_pb";
import type { Timestamp } from "@bufbuild/protobuf/wkt";
import { file_google_protobuf_timestamp } from "@bufbuild/protobuf/wkt";
import type { Message } from "@bufbuild/protobuf";
/**
* Describes the file api/v1/activity_service.proto.
*/
export const file_api_v1_activity_service: GenFile = /*@__PURE__*/
fileDesc("Ch1hcGkvdjEvYWN0aXZpdHlfc2VydmljZS5wcm90bxIMbWVtb3MuYXBpLnYxIsEDCghBY3Rpdml0eRIUCgRuYW1lGAEgASgJQgbgQQPgQQgSFAoHY3JlYXRvchgCIAEoCUID4EEDEi4KBHR5cGUYAyABKA4yGy5tZW1vcy5hcGkudjEuQWN0aXZpdHkuVHlwZUID4EEDEjAKBWxldmVsGAQgASgOMhwubWVtb3MuYXBpLnYxLkFjdGl2aXR5LkxldmVsQgPgQQMSNAoLY3JlYXRlX3RpbWUYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQMSMwoHcGF5bG9hZBgGIAEoCzIdLm1lbW9zLmFwaS52MS5BY3Rpdml0eVBheWxvYWRCA+BBAyIuCgRUeXBlEhQKEFRZUEVfVU5TUEVDSUZJRUQQABIQCgxNRU1PX0NPTU1FTlQQASI9CgVMZXZlbBIVChFMRVZFTF9VTlNQRUNJRklFRBAAEggKBElORk8QARIICgRXQVJOEAISCQoFRVJST1IQAzpN6kFKChVtZW1vcy5hcGkudjEvQWN0aXZpdHkSFWFjdGl2aXRpZXMve2FjdGl2aXR5fRoEbmFtZSoKYWN0aXZpdGllczIIYWN0aXZpdHkiXgoPQWN0aXZpdHlQYXlsb2FkEkAKDG1lbW9fY29tbWVudBgBIAEoCzIoLm1lbW9zLmFwaS52MS5BY3Rpdml0eU1lbW9Db21tZW50UGF5bG9hZEgAQgkKB3BheWxvYWQiQAoaQWN0aXZpdHlNZW1vQ29tbWVudFBheWxvYWQSDAoEbWVtbxgBIAEoCRIUCgxyZWxhdGVkX21lbW8YAiABKAkiPgoVTGlzdEFjdGl2aXRpZXNSZXF1ZXN0EhEKCXBhZ2Vfc2l6ZRgBIAEoBRISCgpwYWdlX3Rva2VuGAIgASgJIl0KFkxpc3RBY3Rpdml0aWVzUmVzcG9uc2USKgoKYWN0aXZpdGllcxgBIAMoCzIWLm1lbW9zLmFwaS52MS5BY3Rpdml0eRIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkiQQoSR2V0QWN0aXZpdHlSZXF1ZXN0EisKBG5hbWUYASABKAlCHeBBAvpBFwoVbWVtb3MuYXBpLnYxL0FjdGl2aXR5Mv8BCg9BY3Rpdml0eVNlcnZpY2USdwoOTGlzdEFjdGl2aXRpZXMSIy5tZW1vcy5hcGkudjEuTGlzdEFjdGl2aXRpZXNSZXF1ZXN0GiQubWVtb3MuYXBpLnYxLkxpc3RBY3Rpdml0aWVzUmVzcG9uc2UiGoLT5JMCFBISL2FwaS92MS9hY3Rpdml0aWVzEnMKC0dldEFjdGl2aXR5EiAubWVtb3MuYXBpLnYxLkdldEFjdGl2aXR5UmVxdWVzdBoWLm1lbW9zLmFwaS52MS5BY3Rpdml0eSIq2kEEbmFtZYLT5JMCHRIbL2FwaS92MS97bmFtZT1hY3Rpdml0aWVzLyp9QqwBChBjb20ubWVtb3MuYXBpLnYxQhRBY3Rpdml0eVNlcnZpY2VQcm90b1ABWjBnaXRodWIuY29tL3VzZW1lbW9zL21lbW9zL3Byb3RvL2dlbi9hcGkvdjE7YXBpdjGiAgNNQViqAgxNZW1vcy5BcGkuVjHKAgxNZW1vc1xBcGlcVjHiAhhNZW1vc1xBcGlcVjFcR1BCTWV0YWRhdGHqAg5NZW1vczo6QXBpOjpWMWIGcHJvdG8z", [file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_timestamp]);
/**
* @generated from message memos.api.v1.Activity
*/
export type Activity = Message<"memos.api.v1.Activity"> & {
/**
* The name of the activity.
* Format: activities/{id}
*
* @generated from field: string name = 1;
*/
name: string;
/**
* The name of the creator.
* Format: users/{user}
*
* @generated from field: string creator = 2;
*/
creator: string;
/**
* The type of the activity.
*
* @generated from field: memos.api.v1.Activity.Type type = 3;
*/
type: Activity_Type;
/**
* The level of the activity.
*
* @generated from field: memos.api.v1.Activity.Level level = 4;
*/
level: Activity_Level;
/**
* The create time of the activity.
*
* @generated from field: google.protobuf.Timestamp create_time = 5;
*/
createTime?: Timestamp;
/**
* The payload of the activity.
*
* @generated from field: memos.api.v1.ActivityPayload payload = 6;
*/
payload?: ActivityPayload;
};
/**
* Describes the message memos.api.v1.Activity.
* Use `create(ActivitySchema)` to create a new message.
*/
export const ActivitySchema: GenMessage<Activity> = /*@__PURE__*/
messageDesc(file_api_v1_activity_service, 0);
/**
* Activity types.
*
* @generated from enum memos.api.v1.Activity.Type
*/
export enum Activity_Type {
/**
* Unspecified type.
*
* @generated from enum value: TYPE_UNSPECIFIED = 0;
*/
TYPE_UNSPECIFIED = 0,
/**
* Memo comment activity.
*
* @generated from enum value: MEMO_COMMENT = 1;
*/
MEMO_COMMENT = 1,
}
/**
* Describes the enum memos.api.v1.Activity.Type.
*/
export const Activity_TypeSchema: GenEnum<Activity_Type> = /*@__PURE__*/
enumDesc(file_api_v1_activity_service, 0, 0);
/**
* Activity levels.
*
* @generated from enum memos.api.v1.Activity.Level
*/
export enum Activity_Level {
/**
* Unspecified level.
*
* @generated from enum value: LEVEL_UNSPECIFIED = 0;
*/
LEVEL_UNSPECIFIED = 0,
/**
* Info level.
*
* @generated from enum value: INFO = 1;
*/
INFO = 1,
/**
* Warn level.
*
* @generated from enum value: WARN = 2;
*/
WARN = 2,
/**
* Error level.
*
* @generated from enum value: ERROR = 3;
*/
ERROR = 3,
}
/**
* Describes the enum memos.api.v1.Activity.Level.
*/
export const Activity_LevelSchema: GenEnum<Activity_Level> = /*@__PURE__*/
enumDesc(file_api_v1_activity_service, 0, 1);
/**
* @generated from message memos.api.v1.ActivityPayload
*/
export type ActivityPayload = Message<"memos.api.v1.ActivityPayload"> & {
/**
* @generated from oneof memos.api.v1.ActivityPayload.payload
*/
payload: {
/**
* Memo comment activity payload.
*
* @generated from field: memos.api.v1.ActivityMemoCommentPayload memo_comment = 1;
*/
value: ActivityMemoCommentPayload;
case: "memoComment";
} | { case: undefined; value?: undefined };
};
/**
* Describes the message memos.api.v1.ActivityPayload.
* Use `create(ActivityPayloadSchema)` to create a new message.
*/
export const ActivityPayloadSchema: GenMessage<ActivityPayload> = /*@__PURE__*/
messageDesc(file_api_v1_activity_service, 1);
/**
* ActivityMemoCommentPayload represents the payload of a memo comment activity.
*
* @generated from message memos.api.v1.ActivityMemoCommentPayload
*/
export type ActivityMemoCommentPayload = Message<"memos.api.v1.ActivityMemoCommentPayload"> & {
/**
* The memo name of comment.
* Format: memos/{memo}
*
* @generated from field: string memo = 1;
*/
memo: string;
/**
* The name of related memo.
* Format: memos/{memo}
*
* @generated from field: string related_memo = 2;
*/
relatedMemo: string;
};
/**
* Describes the message memos.api.v1.ActivityMemoCommentPayload.
* Use `create(ActivityMemoCommentPayloadSchema)` to create a new message.
*/
export const ActivityMemoCommentPayloadSchema: GenMessage<ActivityMemoCommentPayload> = /*@__PURE__*/
messageDesc(file_api_v1_activity_service, 2);
/**
* @generated from message memos.api.v1.ListActivitiesRequest
*/
export type ListActivitiesRequest = Message<"memos.api.v1.ListActivitiesRequest"> & {
/**
* The maximum number of activities to return.
* The service may return fewer than this value.
* If unspecified, at most 100 activities will be returned.
* The maximum value is 1000; values above 1000 will be coerced to 1000.
*
* @generated from field: int32 page_size = 1;
*/
pageSize: number;
/**
* A page token, received from a previous `ListActivities` call.
* Provide this to retrieve the subsequent page.
*
* @generated from field: string page_token = 2;
*/
pageToken: string;
};
/**
* Describes the message memos.api.v1.ListActivitiesRequest.
* Use `create(ListActivitiesRequestSchema)` to create a new message.
*/
export const ListActivitiesRequestSchema: GenMessage<ListActivitiesRequest> = /*@__PURE__*/
messageDesc(file_api_v1_activity_service, 3);
/**
* @generated from message memos.api.v1.ListActivitiesResponse
*/
export type ListActivitiesResponse = Message<"memos.api.v1.ListActivitiesResponse"> & {
/**
* The activities.
*
* @generated from field: repeated memos.api.v1.Activity activities = 1;
*/
activities: Activity[];
/**
* A token to retrieve the next page of results.
* Pass this value in the page_token field in the subsequent call to `ListActivities`
* method to retrieve the next page of results.
*
* @generated from field: string next_page_token = 2;
*/
nextPageToken: string;
};
/**
* Describes the message memos.api.v1.ListActivitiesResponse.
* Use `create(ListActivitiesResponseSchema)` to create a new message.
*/
export const ListActivitiesResponseSchema: GenMessage<ListActivitiesResponse> = /*@__PURE__*/
messageDesc(file_api_v1_activity_service, 4);
/**
* @generated from message memos.api.v1.GetActivityRequest
*/
export type GetActivityRequest = Message<"memos.api.v1.GetActivityRequest"> & {
/**
* The name of the activity.
* Format: activities/{id}, id is the system generated auto-incremented id.
*
* @generated from field: string name = 1;
*/
name: string;
};
/**
* Describes the message memos.api.v1.GetActivityRequest.
* Use `create(GetActivityRequestSchema)` to create a new message.
*/
export const GetActivityRequestSchema: GenMessage<GetActivityRequest> = /*@__PURE__*/
messageDesc(file_api_v1_activity_service, 5);
/**
* @generated from service memos.api.v1.ActivityService
*/
export const ActivityService: GenService<{
/**
* ListActivities returns a list of activities.
*
* @generated from rpc memos.api.v1.ActivityService.ListActivities
*/
listActivities: {
methodKind: "unary";
input: typeof ListActivitiesRequestSchema;
output: typeof ListActivitiesResponseSchema;
},
/**
* GetActivity returns the activity with the given id.
*
* @generated from rpc memos.api.v1.ActivityService.GetActivity
*/
getActivity: {
methodKind: "unary";
input: typeof GetActivityRequestSchema;
output: typeof ActivitySchema;
},
}> = /*@__PURE__*/
serviceDesc(file_api_v1_activity_service, 0);

File diff suppressed because one or more lines are too long