diff --git a/proto/api/v1/attachment_service.proto b/proto/api/v1/attachment_service.proto index 04cd4a92..70f3bae7 100644 --- a/proto/api/v1/attachment_service.proto +++ b/proto/api/v1/attachment_service.proto @@ -149,9 +149,6 @@ message ListAttachmentsResponse { // A token that can be sent as `page_token` to retrieve the next page. // If this field is omitted, there are no subsequent pages. string next_page_token = 2; - - // The total count of attachments (may be approximate). - int32 total_size = 3; } message GetAttachmentRequest { diff --git a/proto/api/v1/memo_service.proto b/proto/api/v1/memo_service.proto index ce568327..edff0693 100644 --- a/proto/api/v1/memo_service.proto +++ b/proto/api/v1/memo_service.proto @@ -519,9 +519,6 @@ message ListMemoCommentsResponse { // A token for the next page of results. string next_page_token = 2; - - // The total count of comments. - int32 total_size = 3; } message ListMemoReactionsRequest { @@ -545,9 +542,6 @@ message ListMemoReactionsResponse { // A token for the next page of results. string next_page_token = 2; - - // The total count of reactions. - int32 total_size = 3; } message UpsertMemoReactionRequest { diff --git a/proto/api/v1/user_service.proto b/proto/api/v1/user_service.proto index a0871b6b..2b0a032e 100644 --- a/proto/api/v1/user_service.proto +++ b/proto/api/v1/user_service.proto @@ -281,9 +281,6 @@ message ListUsersResponse { // A token that can be sent as `page_token` to retrieve the next page. // If this field is omitted, there are no subsequent pages. string next_page_token = 2; - - // The total count of users (may be approximate). - int32 total_size = 3; } message BatchGetUsersRequest { @@ -529,9 +526,6 @@ message ListUserSettingsResponse { // A token that can be sent as `page_token` to retrieve the next page. // If this field is omitted, there are no subsequent pages. string next_page_token = 2; - - // The total count of settings (may be approximate). - int32 total_size = 3; } // LinkedIdentity represents an SSO identity linked to a user account. @@ -663,9 +657,6 @@ message ListPersonalAccessTokensResponse { // A token for the next page of results. string next_page_token = 2; - - // The total count of personal access tokens. - int32 total_size = 3; } message CreatePersonalAccessTokenRequest { diff --git a/proto/gen/api/v1/attachment_service.pb.go b/proto/gen/api/v1/attachment_service.pb.go index cd68d346..a91cd167 100644 --- a/proto/gen/api/v1/attachment_service.pb.go +++ b/proto/gen/api/v1/attachment_service.pb.go @@ -463,8 +463,6 @@ type ListAttachmentsResponse struct { // A token that can be sent as `page_token` to retrieve the next page. // If this field is omitted, there are no subsequent pages. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` - // The total count of attachments (may be approximate). - TotalSize int32 `protobuf:"varint,3,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -513,13 +511,6 @@ func (x *ListAttachmentsResponse) GetNextPageToken() string { return "" } -func (x *ListAttachmentsResponse) GetTotalSize() int32 { - if x != nil { - return x.TotalSize - } - return 0 -} - type GetAttachmentRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. The attachment name of the attachment to retrieve. @@ -746,12 +737,10 @@ const file_api_v1_attachment_service_proto_rawDesc = "" + "\n" + "page_token\x18\x02 \x01(\tB\x03\xe0A\x01R\tpageToken\x12\x1b\n" + "\x06filter\x18\x03 \x01(\tB\x03\xe0A\x01R\x06filter\x12\x1e\n" + - "\border_by\x18\x04 \x01(\tB\x03\xe0A\x01R\aorderBy\"\x9c\x01\n" + + "\border_by\x18\x04 \x01(\tB\x03\xe0A\x01R\aorderBy\"}\n" + "\x17ListAttachmentsResponse\x12:\n" + "\vattachments\x18\x01 \x03(\v2\x18.memos.api.v1.AttachmentR\vattachments\x12&\n" + - "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\x12\x1d\n" + - "\n" + - "total_size\x18\x03 \x01(\x05R\ttotalSize\"K\n" + + "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"K\n" + "\x14GetAttachmentRequest\x123\n" + "\x04name\x18\x01 \x01(\tB\x1f\xe0A\x02\xfaA\x19\n" + "\x17memos.api.v1/AttachmentR\x04name\"\x9a\x01\n" + diff --git a/proto/gen/api/v1/memo_service.pb.go b/proto/gen/api/v1/memo_service.pb.go index 7224f429..8ba3f184 100644 --- a/proto/gen/api/v1/memo_service.pb.go +++ b/proto/gen/api/v1/memo_service.pb.go @@ -1399,8 +1399,6 @@ type ListMemoCommentsResponse struct { Memos []*Memo `protobuf:"bytes,1,rep,name=memos,proto3" json:"memos,omitempty"` // A token for the next page of results. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` - // The total count of comments. - TotalSize int32 `protobuf:"varint,3,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1449,13 +1447,6 @@ func (x *ListMemoCommentsResponse) GetNextPageToken() string { return "" } -func (x *ListMemoCommentsResponse) GetTotalSize() int32 { - if x != nil { - return x.TotalSize - } - return 0 -} - type ListMemoReactionsRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. The resource name of the memo. @@ -1526,8 +1517,6 @@ type ListMemoReactionsResponse struct { Reactions []*Reaction `protobuf:"bytes,1,rep,name=reactions,proto3" json:"reactions,omitempty"` // A token for the next page of results. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` - // The total count of reactions. - TotalSize int32 `protobuf:"varint,3,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1576,13 +1565,6 @@ func (x *ListMemoReactionsResponse) GetNextPageToken() string { return "" } -func (x *ListMemoReactionsResponse) GetTotalSize() int32 { - if x != nil { - return x.TotalSize - } - return 0 -} - type UpsertMemoReactionRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. The resource name of the memo. @@ -2456,23 +2438,19 @@ const file_api_v1_memo_service_proto_rawDesc = "" + "\tpage_size\x18\x02 \x01(\x05B\x03\xe0A\x01R\bpageSize\x12\"\n" + "\n" + "page_token\x18\x03 \x01(\tB\x03\xe0A\x01R\tpageToken\x12\x1e\n" + - "\border_by\x18\x04 \x01(\tB\x03\xe0A\x01R\aorderBy\"\x8b\x01\n" + + "\border_by\x18\x04 \x01(\tB\x03\xe0A\x01R\aorderBy\"l\n" + "\x18ListMemoCommentsResponse\x12(\n" + "\x05memos\x18\x01 \x03(\v2\x12.memos.api.v1.MemoR\x05memos\x12&\n" + - "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\x12\x1d\n" + - "\n" + - "total_size\x18\x03 \x01(\x05R\ttotalSize\"\x8f\x01\n" + + "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\x8f\x01\n" + "\x18ListMemoReactionsRequest\x12-\n" + "\x04name\x18\x01 \x01(\tB\x19\xe0A\x02\xfaA\x13\n" + "\x11memos.api.v1/MemoR\x04name\x12 \n" + "\tpage_size\x18\x02 \x01(\x05B\x03\xe0A\x01R\bpageSize\x12\"\n" + "\n" + - "page_token\x18\x03 \x01(\tB\x03\xe0A\x01R\tpageToken\"\x98\x01\n" + + "page_token\x18\x03 \x01(\tB\x03\xe0A\x01R\tpageToken\"y\n" + "\x19ListMemoReactionsResponse\x124\n" + "\treactions\x18\x01 \x03(\v2\x16.memos.api.v1.ReactionR\treactions\x12&\n" + - "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\x12\x1d\n" + - "\n" + - "total_size\x18\x03 \x01(\x05R\ttotalSize\"\x83\x01\n" + + "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\x83\x01\n" + "\x19UpsertMemoReactionRequest\x12-\n" + "\x04name\x18\x01 \x01(\tB\x19\xe0A\x02\xfaA\x13\n" + "\x11memos.api.v1/MemoR\x04name\x127\n" + diff --git a/proto/gen/api/v1/user_service.pb.go b/proto/gen/api/v1/user_service.pb.go index 6726949f..eb01b60f 100644 --- a/proto/gen/api/v1/user_service.pb.go +++ b/proto/gen/api/v1/user_service.pb.go @@ -454,8 +454,6 @@ type ListUsersResponse struct { // A token that can be sent as `page_token` to retrieve the next page. // If this field is omitted, there are no subsequent pages. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` - // The total count of users (may be approximate). - TotalSize int32 `protobuf:"varint,3,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -504,13 +502,6 @@ func (x *ListUsersResponse) GetNextPageToken() string { return "" } -func (x *ListUsersResponse) GetTotalSize() int32 { - if x != nil { - return x.TotalSize - } - return 0 -} - type BatchGetUsersRequest struct { state protoimpl.MessageState `protogen:"open.v1"` Usernames []string `protobuf:"bytes,1,rep,name=usernames,proto3" json:"usernames,omitempty"` @@ -1384,8 +1375,6 @@ type ListUserSettingsResponse struct { // A token that can be sent as `page_token` to retrieve the next page. // If this field is omitted, there are no subsequent pages. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` - // The total count of settings (may be approximate). - TotalSize int32 `protobuf:"varint,3,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1434,13 +1423,6 @@ func (x *ListUserSettingsResponse) GetNextPageToken() string { return "" } -func (x *ListUserSettingsResponse) GetTotalSize() int32 { - if x != nil { - return x.TotalSize - } - return 0 -} - // LinkedIdentity represents an SSO identity linked to a user account. type LinkedIdentity struct { state protoimpl.MessageState `protogen:"open.v1"` @@ -1927,8 +1909,6 @@ type ListPersonalAccessTokensResponse struct { PersonalAccessTokens []*PersonalAccessToken `protobuf:"bytes,1,rep,name=personal_access_tokens,json=personalAccessTokens,proto3" json:"personal_access_tokens,omitempty"` // A token for the next page of results. NextPageToken string `protobuf:"bytes,2,opt,name=next_page_token,json=nextPageToken,proto3" json:"next_page_token,omitempty"` - // The total count of personal access tokens. - TotalSize int32 `protobuf:"varint,3,opt,name=total_size,json=totalSize,proto3" json:"total_size,omitempty"` unknownFields protoimpl.UnknownFields sizeCache protoimpl.SizeCache } @@ -1977,13 +1957,6 @@ func (x *ListPersonalAccessTokensResponse) GetNextPageToken() string { return "" } -func (x *ListPersonalAccessTokensResponse) GetTotalSize() int32 { - if x != nil { - return x.TotalSize - } - return 0 -} - type CreatePersonalAccessTokenRequest struct { state protoimpl.MessageState `protogen:"open.v1"` // Required. The parent resource where this token will be created. @@ -3408,12 +3381,10 @@ const file_api_v1_user_service_proto_rawDesc = "" + "\n" + "page_token\x18\x02 \x01(\tB\x03\xe0A\x01R\tpageToken\x12\x1b\n" + "\x06filter\x18\x03 \x01(\tB\x03\xe0A\x01R\x06filter\x12&\n" + - "\fshow_deleted\x18\x04 \x01(\bB\x03\xe0A\x01R\vshowDeleted\"\x84\x01\n" + + "\fshow_deleted\x18\x04 \x01(\bB\x03\xe0A\x01R\vshowDeleted\"e\n" + "\x11ListUsersResponse\x12(\n" + "\x05users\x18\x01 \x03(\v2\x12.memos.api.v1.UserR\x05users\x12&\n" + - "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\x12\x1d\n" + - "\n" + - "total_size\x18\x03 \x01(\x05R\ttotalSize\"4\n" + + "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"4\n" + "\x14BatchGetUsersRequest\x12\x1c\n" + "\tusernames\x18\x01 \x03(\tR\tusernames\"A\n" + "\x15BatchGetUsersResponse\x12(\n" + @@ -3504,12 +3475,10 @@ const file_api_v1_user_service_proto_rawDesc = "" + "\x11memos.api.v1/UserR\x06parent\x12 \n" + "\tpage_size\x18\x02 \x01(\x05B\x03\xe0A\x01R\bpageSize\x12\"\n" + "\n" + - "page_token\x18\x03 \x01(\tB\x03\xe0A\x01R\tpageToken\"\x98\x01\n" + + "page_token\x18\x03 \x01(\tB\x03\xe0A\x01R\tpageToken\"y\n" + "\x18ListUserSettingsResponse\x125\n" + "\bsettings\x18\x01 \x03(\v2\x19.memos.api.v1.UserSettingR\bsettings\x12&\n" + - "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\x12\x1d\n" + - "\n" + - "total_size\x18\x03 \x01(\x05R\ttotalSize\"\x84\x02\n" + + "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\x84\x02\n" + "\x0eLinkedIdentity\x12\x17\n" + "\x04name\x18\x01 \x01(\tB\x03\xe0A\bR\x04name\x12@\n" + "\bidp_name\x18\x02 \x01(\tB%\xe0A\x03\xfaA\x1f\n" + @@ -3551,12 +3520,10 @@ const file_api_v1_user_service_proto_rawDesc = "" + "\x11memos.api.v1/UserR\x06parent\x12 \n" + "\tpage_size\x18\x02 \x01(\x05B\x03\xe0A\x01R\bpageSize\x12\"\n" + "\n" + - "page_token\x18\x03 \x01(\tB\x03\xe0A\x01R\tpageToken\"\xc2\x01\n" + + "page_token\x18\x03 \x01(\tB\x03\xe0A\x01R\tpageToken\"\xa3\x01\n" + " ListPersonalAccessTokensResponse\x12W\n" + "\x16personal_access_tokens\x18\x01 \x03(\v2!.memos.api.v1.PersonalAccessTokenR\x14personalAccessTokens\x12&\n" + - "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\x12\x1d\n" + - "\n" + - "total_size\x18\x03 \x01(\x05R\ttotalSize\"\xa9\x01\n" + + "\x0fnext_page_token\x18\x02 \x01(\tR\rnextPageToken\"\xa9\x01\n" + " CreatePersonalAccessTokenRequest\x121\n" + "\x06parent\x18\x01 \x01(\tB\x19\xe0A\x02\xfaA\x13\n" + "\x11memos.api.v1/UserR\x06parent\x12%\n" + diff --git a/proto/gen/openapi.yaml b/proto/gen/openapi.yaml index 7e9f90b8..63c88ed0 100644 --- a/proto/gen/openapi.yaml +++ b/proto/gen/openapi.yaml @@ -3058,10 +3058,6 @@ components: description: |- A token that can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages. - totalSize: - type: integer - description: The total count of attachments (may be approximate). - format: int32 ListIdentityProvidersResponse: type: object properties: @@ -3100,10 +3096,6 @@ components: nextPageToken: type: string description: A token for the next page of results. - totalSize: - type: integer - description: The total count of comments. - format: int32 ListMemoReactionsResponse: type: object properties: @@ -3115,10 +3107,6 @@ components: nextPageToken: type: string description: A token for the next page of results. - totalSize: - type: integer - description: The total count of reactions. - format: int32 ListMemoRelationsResponse: type: object properties: @@ -3162,10 +3150,6 @@ components: nextPageToken: type: string description: A token for the next page of results. - totalSize: - type: integer - description: The total count of personal access tokens. - format: int32 ListShortcutsResponse: type: object properties: @@ -3196,10 +3180,6 @@ components: description: |- A token that can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages. - totalSize: - type: integer - description: The total count of settings (may be approximate). - format: int32 description: Response message for ListUserSettings method. ListUserWebhooksResponse: type: object @@ -3222,10 +3202,6 @@ components: description: |- A token that can be sent as `page_token` to retrieve the next page. If this field is omitted, there are no subsequent pages. - totalSize: - type: integer - description: The total count of users (may be approximate). - format: int32 Location: type: object properties: diff --git a/server/router/api/v1/attachment_service.go b/server/router/api/v1/attachment_service.go index c045f92f..8038821b 100644 --- a/server/router/api/v1/attachment_service.go +++ b/server/router/api/v1/attachment_service.go @@ -194,14 +194,7 @@ func (s *APIV1Service) ListAttachments(ctx context.Context, request *v1pb.ListAt return nil, status.Errorf(codes.Unauthenticated, "user not authenticated") } - // Set default page size - pageSize := int(request.PageSize) - if pageSize <= 0 { - pageSize = 50 - } - if pageSize > 1000 { - pageSize = 1000 - } + pageSize := normalizePageSize(request.PageSize) // Parse page token for offset offset := 0 @@ -238,10 +231,6 @@ func (s *APIV1Service) ListAttachments(ctx context.Context, request *v1pb.ListAt response.Attachments = append(response.Attachments, convertAttachmentFromStore(attachment)) } - // For simplicity, set total size to the number of returned attachments. - // In a full implementation, you'd want a separate count query - response.TotalSize = int32(len(response.Attachments)) - // Set next page token if we got the full page size (indicating there might be more) if len(attachments) == pageSize { response.NextPageToken = fmt.Sprintf("%d", offset+pageSize) diff --git a/server/router/api/v1/common.go b/server/router/api/v1/common.go index f386d6e0..cc413b22 100644 --- a/server/router/api/v1/common.go +++ b/server/router/api/v1/common.go @@ -12,7 +12,7 @@ import ( const ( // DefaultPageSize is the default page size for requests. - DefaultPageSize = 10 + DefaultPageSize = 50 // MaxPageSize is the maximum page size for requests. MaxPageSize = 1000 ) diff --git a/server/router/api/v1/test/user_service_pagination_test.go b/server/router/api/v1/test/user_service_pagination_test.go new file mode 100644 index 00000000..3aedb808 --- /dev/null +++ b/server/router/api/v1/test/user_service_pagination_test.go @@ -0,0 +1,103 @@ +package test + +import ( + "context" + "fmt" + "testing" + + "github.com/stretchr/testify/require" + + apiv1 "github.com/usememos/memos/proto/gen/api/v1" +) + +// drainListUsers walks every page of ListUsers and returns the concatenated users. +func drainListUsers(ctx context.Context, t *testing.T, ts *TestService, pageSize int32) []*apiv1.User { + t.Helper() + var all []*apiv1.User + pageToken := "" + for { + resp, err := ts.Service.ListUsers(ctx, &apiv1.ListUsersRequest{ + PageSize: pageSize, + PageToken: pageToken, + }) + require.NoError(t, err) + all = append(all, resp.Users...) + if resp.NextPageToken == "" { + break + } + pageToken = resp.NextPageToken + require.LessOrEqual(t, len(all), 1000, "pagination did not terminate") + } + return all +} + +func TestListUsersPagination(t *testing.T) { + ctx := context.Background() + ts := NewTestService(t) + defer ts.Cleanup() + + admin, err := ts.CreateHostUser(ctx, "admin") + require.NoError(t, err) + adminCtx := ts.CreateUserContext(ctx, admin.ID) + + // Admin + 5 members = 6 users total. + expected := map[string]struct{}{"admin": {}} + for i := 0; i < 5; i++ { + name := fmt.Sprintf("member-%d", i) + _, err := ts.CreateRegularUser(ctx, name) + require.NoError(t, err) + expected[name] = struct{}{} + } + + // A partial first page must carry a next page token. + first, err := ts.Service.ListUsers(adminCtx, &apiv1.ListUsersRequest{PageSize: 2}) + require.NoError(t, err) + require.Len(t, first.Users, 2) + require.NotEmpty(t, first.NextPageToken) + + // Walking every page must yield each user exactly once (no overlap, no gaps). + all := drainListUsers(adminCtx, t, ts, 2) + seen := map[string]struct{}{} + for _, u := range all { + _, dup := seen[u.Username] + require.False(t, dup, "user %s returned on multiple pages", u.Username) + seen[u.Username] = struct{}{} + } + require.Equal(t, expected, seen) +} + +func TestListUsersDefaultPageSizeReturnsAllWhenSmall(t *testing.T) { + ctx := context.Background() + ts := NewTestService(t) + defer ts.Cleanup() + + admin, err := ts.CreateHostUser(ctx, "admin") + require.NoError(t, err) + adminCtx := ts.CreateUserContext(ctx, admin.ID) + for i := 0; i < 3; i++ { + _, err := ts.CreateRegularUser(ctx, fmt.Sprintf("member-%d", i)) + require.NoError(t, err) + } + + // With no page size or token the default (50) exceeds the 4 users, so a + // single page returns everyone and omits the next page token. This is the + // path the admin members UI relies on. + resp, err := ts.Service.ListUsers(adminCtx, &apiv1.ListUsersRequest{}) + require.NoError(t, err) + require.Len(t, resp.Users, 4) + require.Empty(t, resp.NextPageToken) +} + +func TestListUsersInvalidPageToken(t *testing.T) { + ctx := context.Background() + ts := NewTestService(t) + defer ts.Cleanup() + + admin, err := ts.CreateHostUser(ctx, "admin") + require.NoError(t, err) + adminCtx := ts.CreateUserContext(ctx, admin.ID) + + _, err = ts.Service.ListUsers(adminCtx, &apiv1.ListUsersRequest{PageToken: "not-a-valid-token"}) + require.Error(t, err) + require.Contains(t, err.Error(), "invalid page token") +} diff --git a/server/router/api/v1/user_service.go b/server/router/api/v1/user_service.go index a72f864f..2fb0d2a4 100644 --- a/server/router/api/v1/user_service.go +++ b/server/router/api/v1/user_service.go @@ -76,16 +76,39 @@ func (s *APIV1Service) ListUsers(ctx context.Context, request *v1pb.ListUsersReq } } + 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 = normalizePageSize(pageToken.Limit) + offset = max(int(pageToken.Offset), 0) + } else { + limit = normalizePageSize(request.PageSize) + } + // Fetch one extra row to detect whether a subsequent page exists. + limitPlusOne := limit + 1 + userFind.Limit = &limitPlusOne + userFind.Offset = &offset + users, err := s.Store.ListUsers(ctx, userFind) if err != nil { return nil, status.Errorf(codes.Internal, "failed to list users: %v", err) } - // TODO: Implement proper ordering, and pagination - // For now, return all users with basic structure + nextPageToken := "" + if len(users) == limitPlusOne { + users = users[:limit] + nextPageToken, err = getPageToken(limit, offset+limit) + if err != nil { + return nil, status.Errorf(codes.Internal, "failed to get next page token: %v", err) + } + } + response := &v1pb.ListUsersResponse{ - Users: []*v1pb.User{}, - TotalSize: int32(len(users)), + Users: make([]*v1pb.User, 0, len(users)), + NextPageToken: nextPageToken, } for _, user := range users { response.Users = append(response.Users, convertUserFromStore(user, currentUser)) diff --git a/server/router/api/v1/user_service_settings.go b/server/router/api/v1/user_service_settings.go index dc9346b5..ec6bf2f2 100644 --- a/server/router/api/v1/user_service_settings.go +++ b/server/router/api/v1/user_service_settings.go @@ -220,8 +220,7 @@ func (s *APIV1Service) ListUserSettings(ctx context.Context, request *v1pb.ListU settings = append([]*v1pb.UserSetting{defaultGeneral}, settings...) } response := &v1pb.ListUserSettingsResponse{ - Settings: settings, - TotalSize: int32(len(settings)), + Settings: settings, } return response, nil diff --git a/store/db/mysql/user.go b/store/db/mysql/user.go index 3c9e1313..f4b81725 100644 --- a/store/db/mysql/user.go +++ b/store/db/mysql/user.go @@ -83,7 +83,7 @@ func (d *DB) UpdateUser(ctx context.Context, update *store.UpdateUser) (*store.U func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User, error) { where, args := []string{"1 = 1"}, []any{} - orderBy := []string{"`created_ts` DESC", "`row_status` DESC"} + orderBy := []string{"`created_ts` DESC", "`row_status` DESC", "`id` DESC"} if len(find.Filters) > 0 { return nil, errors.Errorf("user filters are not supported") @@ -147,6 +147,9 @@ func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User query := "SELECT `id`, `username`, `role`, `email`, `nickname`, `password_hash`, `avatar_url`, `description`, UNIX_TIMESTAMP(`created_ts`), UNIX_TIMESTAMP(`updated_ts`), `row_status` FROM `user` WHERE " + strings.Join(where, " AND ") + " ORDER BY " + strings.Join(orderBy, ", ") if v := find.Limit; v != nil { query += fmt.Sprintf(" LIMIT %d", *v) + if v := find.Offset; v != nil { + query += fmt.Sprintf(" OFFSET %d", *v) + } } rows, err := d.db.QueryContext(ctx, query, args...) if err != nil { diff --git a/store/db/postgres/user.go b/store/db/postgres/user.go index ae3c9c06..8291a610 100644 --- a/store/db/postgres/user.go +++ b/store/db/postgres/user.go @@ -86,7 +86,7 @@ func (d *DB) UpdateUser(ctx context.Context, update *store.UpdateUser) (*store.U func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User, error) { where, args := []string{"1 = 1"}, []any{} - orderBy := []string{"created_ts DESC", "row_status DESC"} + orderBy := []string{"created_ts DESC", "row_status DESC", "id DESC"} if len(find.Filters) > 0 { return nil, errors.Errorf("user filters are not supported") @@ -156,6 +156,9 @@ func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User WHERE ` + strings.Join(where, " AND ") + ` ORDER BY ` + strings.Join(orderBy, ", ") if v := find.Limit; v != nil { query += fmt.Sprintf(" LIMIT %d", *v) + if v := find.Offset; v != nil { + query += fmt.Sprintf(" OFFSET %d", *v) + } } rows, err := d.db.QueryContext(ctx, query, args...) if err != nil { diff --git a/store/db/sqlite/user.go b/store/db/sqlite/user.go index d29ca923..cecbd46f 100644 --- a/store/db/sqlite/user.go +++ b/store/db/sqlite/user.go @@ -87,7 +87,7 @@ func (d *DB) UpdateUser(ctx context.Context, update *store.UpdateUser) (*store.U func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User, error) { where, args := []string{"1 = 1"}, []any{} - orderBy := []string{"created_ts DESC", "row_status DESC"} + orderBy := []string{"created_ts DESC", "row_status DESC", "id DESC"} if len(find.Filters) > 0 { return nil, errors.Errorf("user filters are not supported") @@ -165,6 +165,9 @@ func (d *DB) ListUsers(ctx context.Context, find *store.FindUser) ([]*store.User WHERE ` + strings.Join(where, " AND ") + ` ORDER BY ` + strings.Join(orderBy, ", ") if v := find.Limit; v != nil { query += fmt.Sprintf(" LIMIT %d", *v) + if v := find.Offset; v != nil { + query += fmt.Sprintf(" OFFSET %d", *v) + } } rows, err := d.db.QueryContext(ctx, query, args...) diff --git a/store/user.go b/store/user.go index 65e45773..335796c4 100644 --- a/store/user.go +++ b/store/user.go @@ -77,6 +77,8 @@ type FindUser struct { // The maximum number of users to return. Limit *int + // The offset of the returned users. + Offset *int } type DeleteUser struct { diff --git a/web/src/hooks/useUserQueries.ts b/web/src/hooks/useUserQueries.ts index 96eacf17..6854961c 100644 --- a/web/src/hooks/useUserQueries.ts +++ b/web/src/hooks/useUserQueries.ts @@ -205,12 +205,18 @@ export function useUpdateUserSetting() { }); } -// Hook to list all users +// Hook to list all users, paging through every result. export function useListUsers() { return useQuery({ queryKey: userKeys.all, queryFn: async () => { - const { users } = await userServiceClient.listUsers({}); + const users: User[] = []; + let pageToken = ""; + do { + const response = await userServiceClient.listUsers({ pageToken }); + users.push(...response.users); + pageToken = response.nextPageToken; + } while (pageToken); return users; }, }); diff --git a/web/src/types/proto/api/v1/attachment_service_pb.ts b/web/src/types/proto/api/v1/attachment_service_pb.ts index 5ad47e5f..d0082f05 100644 --- a/web/src/types/proto/api/v1/attachment_service_pb.ts +++ b/web/src/types/proto/api/v1/attachment_service_pb.ts @@ -16,7 +16,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file api/v1/attachment_service.proto. */ export const file_api_v1_attachment_service: GenFile = /*@__PURE__*/ - fileDesc("Ch9hcGkvdjEvYXR0YWNobWVudF9zZXJ2aWNlLnByb3RvEgxtZW1vcy5hcGkudjEivAEKC01vdGlvbk1lZGlhEi8KBmZhbWlseRgBIAEoDjIfLm1lbW9zLmFwaS52MS5Nb3Rpb25NZWRpYUZhbWlseRIrCgRyb2xlGAIgASgOMh0ubWVtb3MuYXBpLnYxLk1vdGlvbk1lZGlhUm9sZRIQCghncm91cF9pZBgDIAEoCRIhChlwcmVzZW50YXRpb25fdGltZXN0YW1wX3VzGAQgASgDEhoKEmhhc19lbWJlZGRlZF92aWRlbxgFIAEoCCLsAgoKQXR0YWNobWVudBIRCgRuYW1lGAEgASgJQgPgQQgSNAoLY3JlYXRlX3RpbWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQMSFQoIZmlsZW5hbWUYAyABKAlCA+BBAhIUCgdjb250ZW50GAQgASgMQgPgQQQSGgoNZXh0ZXJuYWxfbGluaxgFIAEoCUID4EEBEhEKBHR5cGUYBiABKAlCA+BBAhIRCgRzaXplGAcgASgDQgPgQQMSFgoEbWVtbxgIIAEoCUID4EEBSACIAQESNAoMbW90aW9uX21lZGlhGAkgASgLMhkubWVtb3MuYXBpLnYxLk1vdGlvbk1lZGlhQgPgQQE6T+pBTAoXbWVtb3MuYXBpLnYxL0F0dGFjaG1lbnQSGGF0dGFjaG1lbnRzL3thdHRhY2htZW50fSoLYXR0YWNobWVudHMyCmF0dGFjaG1lbnRCBwoFX21lbW8iaAoXQ3JlYXRlQXR0YWNobWVudFJlcXVlc3QSMQoKYXR0YWNobWVudBgBIAEoCzIYLm1lbW9zLmFwaS52MS5BdHRhY2htZW50QgPgQQISGgoNYXR0YWNobWVudF9pZBgCIAEoCUID4EEBInUKFkxpc3RBdHRhY2htZW50c1JlcXVlc3QSFgoJcGFnZV9zaXplGAEgASgFQgPgQQESFwoKcGFnZV90b2tlbhgCIAEoCUID4EEBEhMKBmZpbHRlchgDIAEoCUID4EEBEhUKCG9yZGVyX2J5GAQgASgJQgPgQQEidQoXTGlzdEF0dGFjaG1lbnRzUmVzcG9uc2USLQoLYXR0YWNobWVudHMYASADKAsyGC5tZW1vcy5hcGkudjEuQXR0YWNobWVudBIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkSEgoKdG90YWxfc2l6ZRgDIAEoBSJFChRHZXRBdHRhY2htZW50UmVxdWVzdBItCgRuYW1lGAEgASgJQh/gQQL6QRkKF21lbW9zLmFwaS52MS9BdHRhY2htZW50IoIBChdVcGRhdGVBdHRhY2htZW50UmVxdWVzdBIxCgphdHRhY2htZW50GAEgASgLMhgubWVtb3MuYXBpLnYxLkF0dGFjaG1lbnRCA+BBAhI0Cgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBAiJIChdEZWxldGVBdHRhY2htZW50UmVxdWVzdBItCgRuYW1lGAEgASgJQh/gQQL6QRkKF21lbW9zLmFwaS52MS9BdHRhY2htZW50IjMKHUJhdGNoRGVsZXRlQXR0YWNobWVudHNSZXF1ZXN0EhIKBW5hbWVzGAEgAygJQgPgQQIqaAoRTW90aW9uTWVkaWFGYW1pbHkSIwofTU9USU9OX01FRElBX0ZBTUlMWV9VTlNQRUNJRklFRBAAEhQKEEFQUExFX0xJVkVfUEhPVE8QARIYChRBTkRST0lEX01PVElPTl9QSE9UTxACKlkKD01vdGlvbk1lZGlhUm9sZRIhCh1NT1RJT05fTUVESUFfUk9MRV9VTlNQRUNJRklFRBAAEgkKBVNUSUxMEAESCQoFVklERU8QAhINCglDT05UQUlORVIQAzLQBgoRQXR0YWNobWVudFNlcnZpY2USiQEKEENyZWF0ZUF0dGFjaG1lbnQSJS5tZW1vcy5hcGkudjEuQ3JlYXRlQXR0YWNobWVudFJlcXVlc3QaGC5tZW1vcy5hcGkudjEuQXR0YWNobWVudCI02kEKYXR0YWNobWVudILT5JMCIToKYXR0YWNobWVudCITL2FwaS92MS9hdHRhY2htZW50cxJ7Cg9MaXN0QXR0YWNobWVudHMSJC5tZW1vcy5hcGkudjEuTGlzdEF0dGFjaG1lbnRzUmVxdWVzdBolLm1lbW9zLmFwaS52MS5MaXN0QXR0YWNobWVudHNSZXNwb25zZSIbgtPkkwIVEhMvYXBpL3YxL2F0dGFjaG1lbnRzEnoKDUdldEF0dGFjaG1lbnQSIi5tZW1vcy5hcGkudjEuR2V0QXR0YWNobWVudFJlcXVlc3QaGC5tZW1vcy5hcGkudjEuQXR0YWNobWVudCIr2kEEbmFtZYLT5JMCHhIcL2FwaS92MS97bmFtZT1hdHRhY2htZW50cy8qfRKpAQoQVXBkYXRlQXR0YWNobWVudBIlLm1lbW9zLmFwaS52MS5VcGRhdGVBdHRhY2htZW50UmVxdWVzdBoYLm1lbW9zLmFwaS52MS5BdHRhY2htZW50IlTaQRZhdHRhY2htZW50LHVwZGF0ZV9tYXNrgtPkkwI1OgphdHRhY2htZW50MicvYXBpL3YxL3thdHRhY2htZW50Lm5hbWU9YXR0YWNobWVudHMvKn0SfgoQRGVsZXRlQXR0YWNobWVudBIlLm1lbW9zLmFwaS52MS5EZWxldGVBdHRhY2htZW50UmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIr2kEEbmFtZYLT5JMCHiocL2FwaS92MS97bmFtZT1hdHRhY2htZW50cy8qfRKJAQoWQmF0Y2hEZWxldGVBdHRhY2htZW50cxIrLm1lbW9zLmFwaS52MS5CYXRjaERlbGV0ZUF0dGFjaG1lbnRzUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIqgtPkkwIkOgEqIh8vYXBpL3YxL2F0dGFjaG1lbnRzOmJhdGNoRGVsZXRlQq4BChBjb20ubWVtb3MuYXBpLnYxQhZBdHRhY2htZW50U2VydmljZVByb3RvUAFaMGdpdGh1Yi5jb20vdXNlbWVtb3MvbWVtb3MvcHJvdG8vZ2VuL2FwaS92MTthcGl2MaICA01BWKoCDE1lbW9zLkFwaS5WMcoCDE1lbW9zXEFwaVxWMeICGE1lbW9zXEFwaVxWMVxHUEJNZXRhZGF0YeoCDk1lbW9zOjpBcGk6OlYxYgZwcm90bzM", [file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_empty, file_google_protobuf_field_mask, file_google_protobuf_timestamp]); + fileDesc("Ch9hcGkvdjEvYXR0YWNobWVudF9zZXJ2aWNlLnByb3RvEgxtZW1vcy5hcGkudjEivAEKC01vdGlvbk1lZGlhEi8KBmZhbWlseRgBIAEoDjIfLm1lbW9zLmFwaS52MS5Nb3Rpb25NZWRpYUZhbWlseRIrCgRyb2xlGAIgASgOMh0ubWVtb3MuYXBpLnYxLk1vdGlvbk1lZGlhUm9sZRIQCghncm91cF9pZBgDIAEoCRIhChlwcmVzZW50YXRpb25fdGltZXN0YW1wX3VzGAQgASgDEhoKEmhhc19lbWJlZGRlZF92aWRlbxgFIAEoCCLsAgoKQXR0YWNobWVudBIRCgRuYW1lGAEgASgJQgPgQQgSNAoLY3JlYXRlX3RpbWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQMSFQoIZmlsZW5hbWUYAyABKAlCA+BBAhIUCgdjb250ZW50GAQgASgMQgPgQQQSGgoNZXh0ZXJuYWxfbGluaxgFIAEoCUID4EEBEhEKBHR5cGUYBiABKAlCA+BBAhIRCgRzaXplGAcgASgDQgPgQQMSFgoEbWVtbxgIIAEoCUID4EEBSACIAQESNAoMbW90aW9uX21lZGlhGAkgASgLMhkubWVtb3MuYXBpLnYxLk1vdGlvbk1lZGlhQgPgQQE6T+pBTAoXbWVtb3MuYXBpLnYxL0F0dGFjaG1lbnQSGGF0dGFjaG1lbnRzL3thdHRhY2htZW50fSoLYXR0YWNobWVudHMyCmF0dGFjaG1lbnRCBwoFX21lbW8iaAoXQ3JlYXRlQXR0YWNobWVudFJlcXVlc3QSMQoKYXR0YWNobWVudBgBIAEoCzIYLm1lbW9zLmFwaS52MS5BdHRhY2htZW50QgPgQQISGgoNYXR0YWNobWVudF9pZBgCIAEoCUID4EEBInUKFkxpc3RBdHRhY2htZW50c1JlcXVlc3QSFgoJcGFnZV9zaXplGAEgASgFQgPgQQESFwoKcGFnZV90b2tlbhgCIAEoCUID4EEBEhMKBmZpbHRlchgDIAEoCUID4EEBEhUKCG9yZGVyX2J5GAQgASgJQgPgQQEiYQoXTGlzdEF0dGFjaG1lbnRzUmVzcG9uc2USLQoLYXR0YWNobWVudHMYASADKAsyGC5tZW1vcy5hcGkudjEuQXR0YWNobWVudBIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkiRQoUR2V0QXR0YWNobWVudFJlcXVlc3QSLQoEbmFtZRgBIAEoCUIf4EEC+kEZChdtZW1vcy5hcGkudjEvQXR0YWNobWVudCKCAQoXVXBkYXRlQXR0YWNobWVudFJlcXVlc3QSMQoKYXR0YWNobWVudBgBIAEoCzIYLm1lbW9zLmFwaS52MS5BdHRhY2htZW50QgPgQQISNAoLdXBkYXRlX21hc2sYAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrQgPgQQIiSAoXRGVsZXRlQXR0YWNobWVudFJlcXVlc3QSLQoEbmFtZRgBIAEoCUIf4EEC+kEZChdtZW1vcy5hcGkudjEvQXR0YWNobWVudCIzCh1CYXRjaERlbGV0ZUF0dGFjaG1lbnRzUmVxdWVzdBISCgVuYW1lcxgBIAMoCUID4EECKmgKEU1vdGlvbk1lZGlhRmFtaWx5EiMKH01PVElPTl9NRURJQV9GQU1JTFlfVU5TUEVDSUZJRUQQABIUChBBUFBMRV9MSVZFX1BIT1RPEAESGAoUQU5EUk9JRF9NT1RJT05fUEhPVE8QAipZCg9Nb3Rpb25NZWRpYVJvbGUSIQodTU9USU9OX01FRElBX1JPTEVfVU5TUEVDSUZJRUQQABIJCgVTVElMTBABEgkKBVZJREVPEAISDQoJQ09OVEFJTkVSEAMy0AYKEUF0dGFjaG1lbnRTZXJ2aWNlEokBChBDcmVhdGVBdHRhY2htZW50EiUubWVtb3MuYXBpLnYxLkNyZWF0ZUF0dGFjaG1lbnRSZXF1ZXN0GhgubWVtb3MuYXBpLnYxLkF0dGFjaG1lbnQiNNpBCmF0dGFjaG1lbnSC0+STAiE6CmF0dGFjaG1lbnQiEy9hcGkvdjEvYXR0YWNobWVudHMSewoPTGlzdEF0dGFjaG1lbnRzEiQubWVtb3MuYXBpLnYxLkxpc3RBdHRhY2htZW50c1JlcXVlc3QaJS5tZW1vcy5hcGkudjEuTGlzdEF0dGFjaG1lbnRzUmVzcG9uc2UiG4LT5JMCFRITL2FwaS92MS9hdHRhY2htZW50cxJ6Cg1HZXRBdHRhY2htZW50EiIubWVtb3MuYXBpLnYxLkdldEF0dGFjaG1lbnRSZXF1ZXN0GhgubWVtb3MuYXBpLnYxLkF0dGFjaG1lbnQiK9pBBG5hbWWC0+STAh4SHC9hcGkvdjEve25hbWU9YXR0YWNobWVudHMvKn0SqQEKEFVwZGF0ZUF0dGFjaG1lbnQSJS5tZW1vcy5hcGkudjEuVXBkYXRlQXR0YWNobWVudFJlcXVlc3QaGC5tZW1vcy5hcGkudjEuQXR0YWNobWVudCJU2kEWYXR0YWNobWVudCx1cGRhdGVfbWFza4LT5JMCNToKYXR0YWNobWVudDInL2FwaS92MS97YXR0YWNobWVudC5uYW1lPWF0dGFjaG1lbnRzLyp9En4KEERlbGV0ZUF0dGFjaG1lbnQSJS5tZW1vcy5hcGkudjEuRGVsZXRlQXR0YWNobWVudFJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiK9pBBG5hbWWC0+STAh4qHC9hcGkvdjEve25hbWU9YXR0YWNobWVudHMvKn0SiQEKFkJhdGNoRGVsZXRlQXR0YWNobWVudHMSKy5tZW1vcy5hcGkudjEuQmF0Y2hEZWxldGVBdHRhY2htZW50c1JlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiKoLT5JMCJDoBKiIfL2FwaS92MS9hdHRhY2htZW50czpiYXRjaERlbGV0ZUKuAQoQY29tLm1lbW9zLmFwaS52MUIWQXR0YWNobWVudFNlcnZpY2VQcm90b1ABWjBnaXRodWIuY29tL3VzZW1lbW9zL21lbW9zL3Byb3RvL2dlbi9hcGkvdjE7YXBpdjGiAgNNQViqAgxNZW1vcy5BcGkuVjHKAgxNZW1vc1xBcGlcVjHiAhhNZW1vc1xBcGlcVjFcR1BCTWV0YWRhdGHqAg5NZW1vczo6QXBpOjpWMWIGcHJvdG8z", [file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_empty, file_google_protobuf_field_mask, file_google_protobuf_timestamp]); /** * @generated from message memos.api.v1.MotionMedia @@ -225,13 +225,6 @@ export type ListAttachmentsResponse = Message<"memos.api.v1.ListAttachmentsRespo * @generated from field: string next_page_token = 2; */ nextPageToken: string; - - /** - * The total count of attachments (may be approximate). - * - * @generated from field: int32 total_size = 3; - */ - totalSize: number; }; /** diff --git a/web/src/types/proto/api/v1/memo_service_pb.ts b/web/src/types/proto/api/v1/memo_service_pb.ts index 3647e0f5..1a12fc8a 100644 --- a/web/src/types/proto/api/v1/memo_service_pb.ts +++ b/web/src/types/proto/api/v1/memo_service_pb.ts @@ -20,7 +20,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file api/v1/memo_service.proto. */ export const file_api_v1_memo_service: GenFile = /*@__PURE__*/ - fileDesc("ChlhcGkvdjEvbWVtb19zZXJ2aWNlLnByb3RvEgxtZW1vcy5hcGkudjEipwIKCFJlYWN0aW9uEhQKBG5hbWUYASABKAlCBuBBA+BBCBIqCgdjcmVhdG9yGAIgASgJQhngQQP6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEi0KCmNvbnRlbnRfaWQYAyABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SGgoNcmVhY3Rpb25fdHlwZRgEIAEoCUID4EECEjQKC2NyZWF0ZV90aW1lGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEDOljqQVUKFW1lbW9zLmFwaS52MS9SZWFjdGlvbhIhbWVtb3Mve21lbW99L3JlYWN0aW9ucy97cmVhY3Rpb259GgRuYW1lKglyZWFjdGlvbnMyCHJlYWN0aW9uIuoGCgRNZW1vEhEKBG5hbWUYASABKAlCA+BBCBInCgVzdGF0ZRgCIAEoDjITLm1lbW9zLmFwaS52MS5TdGF0ZUID4EECEioKB2NyZWF0b3IYAyABKAlCGeBBA/pBEwoRbWVtb3MuYXBpLnYxL1VzZXISNAoLY3JlYXRlX3RpbWUYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQESNAoLdXBkYXRlX3RpbWUYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQESFAoHY29udGVudBgHIAEoCUID4EECEjEKCnZpc2liaWxpdHkYCSABKA4yGC5tZW1vcy5hcGkudjEuVmlzaWJpbGl0eUID4EECEhEKBHRhZ3MYCiADKAlCA+BBAxITCgZwaW5uZWQYCyABKAhCA+BBARIyCgthdHRhY2htZW50cxgMIAMoCzIYLm1lbW9zLmFwaS52MS5BdHRhY2htZW50QgPgQQESMgoJcmVsYXRpb25zGA0gAygLMhoubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbkID4EEBEi4KCXJlYWN0aW9ucxgOIAMoCzIWLm1lbW9zLmFwaS52MS5SZWFjdGlvbkID4EEDEjIKCHByb3BlcnR5GA8gASgLMhsubWVtb3MuYXBpLnYxLk1lbW8uUHJvcGVydHlCA+BBAxIuCgZwYXJlbnQYECABKAlCGeBBA/pBEwoRbWVtb3MuYXBpLnYxL01lbW9IAIgBARIUCgdzbmlwcGV0GBEgASgJQgPgQQMSMgoIbG9jYXRpb24YEiABKAsyFi5tZW1vcy5hcGkudjEuTG9jYXRpb25CA+BBAUgBiAEBGnIKCFByb3BlcnR5EhAKCGhhc19saW5rGAEgASgIEhUKDWhhc190YXNrX2xpc3QYAiABKAgSEAoIaGFzX2NvZGUYAyABKAgSHAoUaGFzX2luY29tcGxldGVfdGFza3MYBCABKAgSDQoFdGl0bGUYBSABKAk6N+pBNAoRbWVtb3MuYXBpLnYxL01lbW8SDG1lbW9zL3ttZW1vfRoEbmFtZSoFbWVtb3MyBG1lbW9CCQoHX3BhcmVudEILCglfbG9jYXRpb25KBAgGEAdSDGRpc3BsYXlfdGltZSJTCghMb2NhdGlvbhIYCgtwbGFjZWhvbGRlchgBIAEoCUID4EEBEhUKCGxhdGl0dWRlGAIgASgBQgPgQQESFgoJbG9uZ2l0dWRlGAMgASgBQgPgQQEiUAoRQ3JlYXRlTWVtb1JlcXVlc3QSJQoEbWVtbxgBIAEoCzISLm1lbW9zLmFwaS52MS5NZW1vQgPgQQISFAoHbWVtb19pZBgCIAEoCUID4EEBIrMBChBMaXN0TWVtb3NSZXF1ZXN0EhYKCXBhZ2Vfc2l6ZRgBIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAiABKAlCA+BBARInCgVzdGF0ZRgDIAEoDjITLm1lbW9zLmFwaS52MS5TdGF0ZUID4EEBEhUKCG9yZGVyX2J5GAQgASgJQgPgQQESEwoGZmlsdGVyGAUgASgJQgPgQQESGQoMc2hvd19kZWxldGVkGAYgASgIQgPgQQEiTwoRTGlzdE1lbW9zUmVzcG9uc2USIQoFbWVtb3MYASADKAsyEi5tZW1vcy5hcGkudjEuTWVtbxIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkiOQoOR2V0TWVtb1JlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbyJwChFVcGRhdGVNZW1vUmVxdWVzdBIlCgRtZW1vGAEgASgLMhIubWVtb3MuYXBpLnYxLk1lbW9CA+BBAhI0Cgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBAiJQChFEZWxldGVNZW1vUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhIKBWZvcmNlGAIgASgIQgPgQQEieAoZU2V0TWVtb0F0dGFjaG1lbnRzUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEjIKC2F0dGFjaG1lbnRzGAIgAygLMhgubWVtb3MuYXBpLnYxLkF0dGFjaG1lbnRCA+BBAiJ2ChpMaXN0TWVtb0F0dGFjaG1lbnRzUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASJlChtMaXN0TWVtb0F0dGFjaG1lbnRzUmVzcG9uc2USLQoLYXR0YWNobWVudHMYASADKAsyGC5tZW1vcy5hcGkudjEuQXR0YWNobWVudBIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkiswIKDE1lbW9SZWxhdGlvbhIyCgRtZW1vGAEgASgLMh8ubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbi5NZW1vQgPgQQISOgoMcmVsYXRlZF9tZW1vGAIgASgLMh8ubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbi5NZW1vQgPgQQISMgoEdHlwZRgDIAEoDjIfLm1lbW9zLmFwaS52MS5NZW1vUmVsYXRpb24uVHlwZUID4EECGkUKBE1lbW8SJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxIUCgdzbmlwcGV0GAIgASgJQgPgQQMiOAoEVHlwZRIUChBUWVBFX1VOU1BFQ0lGSUVEEAASDQoJUkVGRVJFTkNFEAESCwoHQ09NTUVOVBACInYKF1NldE1lbW9SZWxhdGlvbnNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SMgoJcmVsYXRpb25zGAIgAygLMhoubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbkID4EECInQKGExpc3RNZW1vUmVsYXRpb25zUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASJjChlMaXN0TWVtb1JlbGF0aW9uc1Jlc3BvbnNlEi0KCXJlbGF0aW9ucxgBIAMoCzIaLm1lbW9zLmFwaS52MS5NZW1vUmVsYXRpb24SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJIoYBChhDcmVhdGVNZW1vQ29tbWVudFJlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxIoCgdjb21tZW50GAIgASgLMhIubWVtb3MuYXBpLnYxLk1lbW9CA+BBAhIXCgpjb21tZW50X2lkGAMgASgJQgPgQQEiigEKF0xpc3RNZW1vQ29tbWVudHNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBEhUKCG9yZGVyX2J5GAQgASgJQgPgQQEiagoYTGlzdE1lbW9Db21tZW50c1Jlc3BvbnNlEiEKBW1lbW9zGAEgAygLMhIubWVtb3MuYXBpLnYxLk1lbW8SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJEhIKCnRvdGFsX3NpemUYAyABKAUidAoYTGlzdE1lbW9SZWFjdGlvbnNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBInMKGUxpc3RNZW1vUmVhY3Rpb25zUmVzcG9uc2USKQoJcmVhY3Rpb25zGAEgAygLMhYubWVtb3MuYXBpLnYxLlJlYWN0aW9uEhcKD25leHRfcGFnZV90b2tlbhgCIAEoCRISCgp0b3RhbF9zaXplGAMgASgFInMKGVVwc2VydE1lbW9SZWFjdGlvblJlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxItCghyZWFjdGlvbhgCIAEoCzIWLm1lbW9zLmFwaS52MS5SZWFjdGlvbkID4EECIkgKGURlbGV0ZU1lbW9SZWFjdGlvblJlcXVlc3QSKwoEbmFtZRgBIAEoCUId4EEC+kEXChVtZW1vcy5hcGkudjEvUmVhY3Rpb24i6AEKCU1lbW9TaGFyZRIRCgRuYW1lGAEgASgJQgPgQQgSNAoLY3JlYXRlX3RpbWUYAiABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQMSOQoLZXhwaXJlX3RpbWUYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQFIAIgBATpH6kFEChZtZW1vcy5hcGkudjEvTWVtb1NoYXJlEhttZW1vcy97bWVtb30vc2hhcmVzL3tzaGFyZX0qBnNoYXJlczIFc2hhcmVCDgoMX2V4cGlyZV90aW1lInUKFkNyZWF0ZU1lbW9TaGFyZVJlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEjAKCm1lbW9fc2hhcmUYAiABKAsyFy5tZW1vcy5hcGkudjEuTWVtb1NoYXJlQgPgQQIiQgoVTGlzdE1lbW9TaGFyZXNSZXF1ZXN0EikKBnBhcmVudBgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbyJGChZMaXN0TWVtb1NoYXJlc1Jlc3BvbnNlEiwKC21lbW9fc2hhcmVzGAEgAygLMhcubWVtb3MuYXBpLnYxLk1lbW9TaGFyZSJGChZEZWxldGVNZW1vU2hhcmVSZXF1ZXN0EiwKBG5hbWUYASABKAlCHuBBAvpBGAoWbWVtb3MuYXBpLnYxL01lbW9TaGFyZSIuChVHZXRNZW1vQnlTaGFyZVJlcXVlc3QSFQoIc2hhcmVfaWQYASABKAlCA+BBAiIqChZHZXRMaW5rTWV0YWRhdGFSZXF1ZXN0EhAKA3VybBgBIAEoCUID4EECIjAKG0JhdGNoR2V0TGlua01ldGFkYXRhUmVxdWVzdBIRCgR1cmxzGAEgAygJQgPgQQIiUQocQmF0Y2hHZXRMaW5rTWV0YWRhdGFSZXNwb25zZRIxCg1saW5rX21ldGFkYXRhGAEgAygLMhoubWVtb3MuYXBpLnYxLkxpbmtNZXRhZGF0YSJOCgxMaW5rTWV0YWRhdGESCwoDdXJsGAEgASgJEg0KBXRpdGxlGAIgASgJEhMKC2Rlc2NyaXB0aW9uGAMgASgJEg0KBWltYWdlGAQgASgJKlAKClZpc2liaWxpdHkSGgoWVklTSUJJTElUWV9VTlNQRUNJRklFRBAAEgsKB1BSSVZBVEUQARINCglQUk9URUNURUQQAhIKCgZQVUJMSUMQAzKLFQoLTWVtb1NlcnZpY2USZQoKQ3JlYXRlTWVtbxIfLm1lbW9zLmFwaS52MS5DcmVhdGVNZW1vUmVxdWVzdBoSLm1lbW9zLmFwaS52MS5NZW1vIiLaQQRtZW1vgtPkkwIVOgRtZW1vIg0vYXBpL3YxL21lbW9zEmYKCUxpc3RNZW1vcxIeLm1lbW9zLmFwaS52MS5MaXN0TWVtb3NSZXF1ZXN0Gh8ubWVtb3MuYXBpLnYxLkxpc3RNZW1vc1Jlc3BvbnNlIhjaQQCC0+STAg8SDS9hcGkvdjEvbWVtb3MSYgoHR2V0TWVtbxIcLm1lbW9zLmFwaS52MS5HZXRNZW1vUmVxdWVzdBoSLm1lbW9zLmFwaS52MS5NZW1vIiXaQQRuYW1lgtPkkwIYEhYvYXBpL3YxL3tuYW1lPW1lbW9zLyp9En8KClVwZGF0ZU1lbW8SHy5tZW1vcy5hcGkudjEuVXBkYXRlTWVtb1JlcXVlc3QaEi5tZW1vcy5hcGkudjEuTWVtbyI82kEQbWVtbyx1cGRhdGVfbWFza4LT5JMCIzoEbWVtbzIbL2FwaS92MS97bWVtby5uYW1lPW1lbW9zLyp9EmwKCkRlbGV0ZU1lbW8SHy5tZW1vcy5hcGkudjEuRGVsZXRlTWVtb1JlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiJdpBBG5hbWWC0+STAhgqFi9hcGkvdjEve25hbWU9bWVtb3MvKn0SiwEKElNldE1lbW9BdHRhY2htZW50cxInLm1lbW9zLmFwaS52MS5TZXRNZW1vQXR0YWNobWVudHNSZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjTaQQRuYW1lgtPkkwInOgEqMiIvYXBpL3YxL3tuYW1lPW1lbW9zLyp9L2F0dGFjaG1lbnRzEp0BChNMaXN0TWVtb0F0dGFjaG1lbnRzEigubWVtb3MuYXBpLnYxLkxpc3RNZW1vQXR0YWNobWVudHNSZXF1ZXN0GikubWVtb3MuYXBpLnYxLkxpc3RNZW1vQXR0YWNobWVudHNSZXNwb25zZSIx2kEEbmFtZYLT5JMCJBIiL2FwaS92MS97bmFtZT1tZW1vcy8qfS9hdHRhY2htZW50cxKFAQoQU2V0TWVtb1JlbGF0aW9ucxIlLm1lbW9zLmFwaS52MS5TZXRNZW1vUmVsYXRpb25zUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIy2kEEbmFtZYLT5JMCJToBKjIgL2FwaS92MS97bmFtZT1tZW1vcy8qfS9yZWxhdGlvbnMSlQEKEUxpc3RNZW1vUmVsYXRpb25zEiYubWVtb3MuYXBpLnYxLkxpc3RNZW1vUmVsYXRpb25zUmVxdWVzdBonLm1lbW9zLmFwaS52MS5MaXN0TWVtb1JlbGF0aW9uc1Jlc3BvbnNlIi/aQQRuYW1lgtPkkwIiEiAvYXBpL3YxL3tuYW1lPW1lbW9zLyp9L3JlbGF0aW9ucxKQAQoRQ3JlYXRlTWVtb0NvbW1lbnQSJi5tZW1vcy5hcGkudjEuQ3JlYXRlTWVtb0NvbW1lbnRSZXF1ZXN0GhIubWVtb3MuYXBpLnYxLk1lbW8iP9pBDG5hbWUsY29tbWVudILT5JMCKjoHY29tbWVudCIfL2FwaS92MS97bmFtZT1tZW1vcy8qfS9jb21tZW50cxKRAQoQTGlzdE1lbW9Db21tZW50cxIlLm1lbW9zLmFwaS52MS5MaXN0TWVtb0NvbW1lbnRzUmVxdWVzdBomLm1lbW9zLmFwaS52MS5MaXN0TWVtb0NvbW1lbnRzUmVzcG9uc2UiLtpBBG5hbWWC0+STAiESHy9hcGkvdjEve25hbWU9bWVtb3MvKn0vY29tbWVudHMSlQEKEUxpc3RNZW1vUmVhY3Rpb25zEiYubWVtb3MuYXBpLnYxLkxpc3RNZW1vUmVhY3Rpb25zUmVxdWVzdBonLm1lbW9zLmFwaS52MS5MaXN0TWVtb1JlYWN0aW9uc1Jlc3BvbnNlIi/aQQRuYW1lgtPkkwIiEiAvYXBpL3YxL3tuYW1lPW1lbW9zLyp9L3JlYWN0aW9ucxKJAQoSVXBzZXJ0TWVtb1JlYWN0aW9uEicubWVtb3MuYXBpLnYxLlVwc2VydE1lbW9SZWFjdGlvblJlcXVlc3QaFi5tZW1vcy5hcGkudjEuUmVhY3Rpb24iMtpBBG5hbWWC0+STAiU6ASoiIC9hcGkvdjEve25hbWU9bWVtb3MvKn0vcmVhY3Rpb25zEogBChJEZWxldGVNZW1vUmVhY3Rpb24SJy5tZW1vcy5hcGkudjEuRGVsZXRlTWVtb1JlYWN0aW9uUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIx2kEEbmFtZYLT5JMCJCoiL2FwaS92MS97bmFtZT1tZW1vcy8qL3JlYWN0aW9ucy8qfRKZAQoPQ3JlYXRlTWVtb1NoYXJlEiQubWVtb3MuYXBpLnYxLkNyZWF0ZU1lbW9TaGFyZVJlcXVlc3QaFy5tZW1vcy5hcGkudjEuTWVtb1NoYXJlIkfaQRFwYXJlbnQsbWVtb19zaGFyZYLT5JMCLToKbWVtb19zaGFyZSIfL2FwaS92MS97cGFyZW50PW1lbW9zLyp9L3NoYXJlcxKNAQoOTGlzdE1lbW9TaGFyZXMSIy5tZW1vcy5hcGkudjEuTGlzdE1lbW9TaGFyZXNSZXF1ZXN0GiQubWVtb3MuYXBpLnYxLkxpc3RNZW1vU2hhcmVzUmVzcG9uc2UiMNpBBnBhcmVudILT5JMCIRIfL2FwaS92MS97cGFyZW50PW1lbW9zLyp9L3NoYXJlcxJ/Cg9EZWxldGVNZW1vU2hhcmUSJC5tZW1vcy5hcGkudjEuRGVsZXRlTWVtb1NoYXJlUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIu2kEEbmFtZYLT5JMCISofL2FwaS92MS97bmFtZT1tZW1vcy8qL3NoYXJlcy8qfRJsCg5HZXRNZW1vQnlTaGFyZRIjLm1lbW9zLmFwaS52MS5HZXRNZW1vQnlTaGFyZVJlcXVlc3QaEi5tZW1vcy5hcGkudjEuTWVtbyIhgtPkkwIbEhkvYXBpL3YxL3NoYXJlcy97c2hhcmVfaWR9EnkKD0dldExpbmtNZXRhZGF0YRIkLm1lbW9zLmFwaS52MS5HZXRMaW5rTWV0YWRhdGFSZXF1ZXN0GhoubWVtb3MuYXBpLnYxLkxpbmtNZXRhZGF0YSIkgtPkkwIeEhwvYXBpL3YxL21lbW9zLy0vbGlua01ldGFkYXRhEp8BChRCYXRjaEdldExpbmtNZXRhZGF0YRIpLm1lbW9zLmFwaS52MS5CYXRjaEdldExpbmtNZXRhZGF0YVJlcXVlc3QaKi5tZW1vcy5hcGkudjEuQmF0Y2hHZXRMaW5rTWV0YWRhdGFSZXNwb25zZSIwgtPkkwIqOgEqIiUvYXBpL3YxL21lbW9zLy0vbGlua01ldGFkYXRhOmJhdGNoR2V0QqgBChBjb20ubWVtb3MuYXBpLnYxQhBNZW1vU2VydmljZVByb3RvUAFaMGdpdGh1Yi5jb20vdXNlbWVtb3MvbWVtb3MvcHJvdG8vZ2VuL2FwaS92MTthcGl2MaICA01BWKoCDE1lbW9zLkFwaS5WMcoCDE1lbW9zXEFwaVxWMeICGE1lbW9zXEFwaVxWMVxHUEJNZXRhZGF0YeoCDk1lbW9zOjpBcGk6OlYxYgZwcm90bzM", [file_api_v1_attachment_service, file_api_v1_common, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_empty, file_google_protobuf_field_mask, file_google_protobuf_timestamp]); + fileDesc("ChlhcGkvdjEvbWVtb19zZXJ2aWNlLnByb3RvEgxtZW1vcy5hcGkudjEipwIKCFJlYWN0aW9uEhQKBG5hbWUYASABKAlCBuBBA+BBCBIqCgdjcmVhdG9yGAIgASgJQhngQQP6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEi0KCmNvbnRlbnRfaWQYAyABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SGgoNcmVhY3Rpb25fdHlwZRgEIAEoCUID4EECEjQKC2NyZWF0ZV90aW1lGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEDOljqQVUKFW1lbW9zLmFwaS52MS9SZWFjdGlvbhIhbWVtb3Mve21lbW99L3JlYWN0aW9ucy97cmVhY3Rpb259GgRuYW1lKglyZWFjdGlvbnMyCHJlYWN0aW9uIuoGCgRNZW1vEhEKBG5hbWUYASABKAlCA+BBCBInCgVzdGF0ZRgCIAEoDjITLm1lbW9zLmFwaS52MS5TdGF0ZUID4EECEioKB2NyZWF0b3IYAyABKAlCGeBBA/pBEwoRbWVtb3MuYXBpLnYxL1VzZXISNAoLY3JlYXRlX3RpbWUYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQESNAoLdXBkYXRlX3RpbWUYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQESFAoHY29udGVudBgHIAEoCUID4EECEjEKCnZpc2liaWxpdHkYCSABKA4yGC5tZW1vcy5hcGkudjEuVmlzaWJpbGl0eUID4EECEhEKBHRhZ3MYCiADKAlCA+BBAxITCgZwaW5uZWQYCyABKAhCA+BBARIyCgthdHRhY2htZW50cxgMIAMoCzIYLm1lbW9zLmFwaS52MS5BdHRhY2htZW50QgPgQQESMgoJcmVsYXRpb25zGA0gAygLMhoubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbkID4EEBEi4KCXJlYWN0aW9ucxgOIAMoCzIWLm1lbW9zLmFwaS52MS5SZWFjdGlvbkID4EEDEjIKCHByb3BlcnR5GA8gASgLMhsubWVtb3MuYXBpLnYxLk1lbW8uUHJvcGVydHlCA+BBAxIuCgZwYXJlbnQYECABKAlCGeBBA/pBEwoRbWVtb3MuYXBpLnYxL01lbW9IAIgBARIUCgdzbmlwcGV0GBEgASgJQgPgQQMSMgoIbG9jYXRpb24YEiABKAsyFi5tZW1vcy5hcGkudjEuTG9jYXRpb25CA+BBAUgBiAEBGnIKCFByb3BlcnR5EhAKCGhhc19saW5rGAEgASgIEhUKDWhhc190YXNrX2xpc3QYAiABKAgSEAoIaGFzX2NvZGUYAyABKAgSHAoUaGFzX2luY29tcGxldGVfdGFza3MYBCABKAgSDQoFdGl0bGUYBSABKAk6N+pBNAoRbWVtb3MuYXBpLnYxL01lbW8SDG1lbW9zL3ttZW1vfRoEbmFtZSoFbWVtb3MyBG1lbW9CCQoHX3BhcmVudEILCglfbG9jYXRpb25KBAgGEAdSDGRpc3BsYXlfdGltZSJTCghMb2NhdGlvbhIYCgtwbGFjZWhvbGRlchgBIAEoCUID4EEBEhUKCGxhdGl0dWRlGAIgASgBQgPgQQESFgoJbG9uZ2l0dWRlGAMgASgBQgPgQQEiUAoRQ3JlYXRlTWVtb1JlcXVlc3QSJQoEbWVtbxgBIAEoCzISLm1lbW9zLmFwaS52MS5NZW1vQgPgQQISFAoHbWVtb19pZBgCIAEoCUID4EEBIrMBChBMaXN0TWVtb3NSZXF1ZXN0EhYKCXBhZ2Vfc2l6ZRgBIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAiABKAlCA+BBARInCgVzdGF0ZRgDIAEoDjITLm1lbW9zLmFwaS52MS5TdGF0ZUID4EEBEhUKCG9yZGVyX2J5GAQgASgJQgPgQQESEwoGZmlsdGVyGAUgASgJQgPgQQESGQoMc2hvd19kZWxldGVkGAYgASgIQgPgQQEiTwoRTGlzdE1lbW9zUmVzcG9uc2USIQoFbWVtb3MYASADKAsyEi5tZW1vcy5hcGkudjEuTWVtbxIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkiOQoOR2V0TWVtb1JlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbyJwChFVcGRhdGVNZW1vUmVxdWVzdBIlCgRtZW1vGAEgASgLMhIubWVtb3MuYXBpLnYxLk1lbW9CA+BBAhI0Cgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBAiJQChFEZWxldGVNZW1vUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhIKBWZvcmNlGAIgASgIQgPgQQEieAoZU2V0TWVtb0F0dGFjaG1lbnRzUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEjIKC2F0dGFjaG1lbnRzGAIgAygLMhgubWVtb3MuYXBpLnYxLkF0dGFjaG1lbnRCA+BBAiJ2ChpMaXN0TWVtb0F0dGFjaG1lbnRzUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASJlChtMaXN0TWVtb0F0dGFjaG1lbnRzUmVzcG9uc2USLQoLYXR0YWNobWVudHMYASADKAsyGC5tZW1vcy5hcGkudjEuQXR0YWNobWVudBIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkiswIKDE1lbW9SZWxhdGlvbhIyCgRtZW1vGAEgASgLMh8ubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbi5NZW1vQgPgQQISOgoMcmVsYXRlZF9tZW1vGAIgASgLMh8ubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbi5NZW1vQgPgQQISMgoEdHlwZRgDIAEoDjIfLm1lbW9zLmFwaS52MS5NZW1vUmVsYXRpb24uVHlwZUID4EECGkUKBE1lbW8SJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxIUCgdzbmlwcGV0GAIgASgJQgPgQQMiOAoEVHlwZRIUChBUWVBFX1VOU1BFQ0lGSUVEEAASDQoJUkVGRVJFTkNFEAESCwoHQ09NTUVOVBACInYKF1NldE1lbW9SZWxhdGlvbnNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SMgoJcmVsYXRpb25zGAIgAygLMhoubWVtb3MuYXBpLnYxLk1lbW9SZWxhdGlvbkID4EECInQKGExpc3RNZW1vUmVsYXRpb25zUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASJjChlMaXN0TWVtb1JlbGF0aW9uc1Jlc3BvbnNlEi0KCXJlbGF0aW9ucxgBIAMoCzIaLm1lbW9zLmFwaS52MS5NZW1vUmVsYXRpb24SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJIoYBChhDcmVhdGVNZW1vQ29tbWVudFJlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvTWVtbxIoCgdjb21tZW50GAIgASgLMhIubWVtb3MuYXBpLnYxLk1lbW9CA+BBAhIXCgpjb21tZW50X2lkGAMgASgJQgPgQQEiigEKF0xpc3RNZW1vQ29tbWVudHNSZXF1ZXN0EicKBG5hbWUYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBEhUKCG9yZGVyX2J5GAQgASgJQgPgQQEiVgoYTGlzdE1lbW9Db21tZW50c1Jlc3BvbnNlEiEKBW1lbW9zGAEgAygLMhIubWVtb3MuYXBpLnYxLk1lbW8SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJInQKGExpc3RNZW1vUmVhY3Rpb25zUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASJfChlMaXN0TWVtb1JlYWN0aW9uc1Jlc3BvbnNlEikKCXJlYWN0aW9ucxgBIAMoCzIWLm1lbW9zLmFwaS52MS5SZWFjdGlvbhIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkicwoZVXBzZXJ0TWVtb1JlYWN0aW9uUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vEi0KCHJlYWN0aW9uGAIgASgLMhYubWVtb3MuYXBpLnYxLlJlYWN0aW9uQgPgQQIiSAoZRGVsZXRlTWVtb1JlYWN0aW9uUmVxdWVzdBIrCgRuYW1lGAEgASgJQh3gQQL6QRcKFW1lbW9zLmFwaS52MS9SZWFjdGlvbiLoAQoJTWVtb1NoYXJlEhEKBG5hbWUYASABKAlCA+BBCBI0CgtjcmVhdGVfdGltZRgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxI5CgtleHBpcmVfdGltZRgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAUgAiAEBOkfqQUQKFm1lbW9zLmFwaS52MS9NZW1vU2hhcmUSG21lbW9zL3ttZW1vfS9zaGFyZXMve3NoYXJlfSoGc2hhcmVzMgVzaGFyZUIOCgxfZXhwaXJlX3RpbWUidQoWQ3JlYXRlTWVtb1NoYXJlUmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL01lbW8SMAoKbWVtb19zaGFyZRgCIAEoCzIXLm1lbW9zLmFwaS52MS5NZW1vU2hhcmVCA+BBAiJCChVMaXN0TWVtb1NoYXJlc1JlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9NZW1vIkYKFkxpc3RNZW1vU2hhcmVzUmVzcG9uc2USLAoLbWVtb19zaGFyZXMYASADKAsyFy5tZW1vcy5hcGkudjEuTWVtb1NoYXJlIkYKFkRlbGV0ZU1lbW9TaGFyZVJlcXVlc3QSLAoEbmFtZRgBIAEoCUIe4EEC+kEYChZtZW1vcy5hcGkudjEvTWVtb1NoYXJlIi4KFUdldE1lbW9CeVNoYXJlUmVxdWVzdBIVCghzaGFyZV9pZBgBIAEoCUID4EECIioKFkdldExpbmtNZXRhZGF0YVJlcXVlc3QSEAoDdXJsGAEgASgJQgPgQQIiMAobQmF0Y2hHZXRMaW5rTWV0YWRhdGFSZXF1ZXN0EhEKBHVybHMYASADKAlCA+BBAiJRChxCYXRjaEdldExpbmtNZXRhZGF0YVJlc3BvbnNlEjEKDWxpbmtfbWV0YWRhdGEYASADKAsyGi5tZW1vcy5hcGkudjEuTGlua01ldGFkYXRhIk4KDExpbmtNZXRhZGF0YRILCgN1cmwYASABKAkSDQoFdGl0bGUYAiABKAkSEwoLZGVzY3JpcHRpb24YAyABKAkSDQoFaW1hZ2UYBCABKAkqUAoKVmlzaWJpbGl0eRIaChZWSVNJQklMSVRZX1VOU1BFQ0lGSUVEEAASCwoHUFJJVkFURRABEg0KCVBST1RFQ1RFRBACEgoKBlBVQkxJQxADMosVCgtNZW1vU2VydmljZRJlCgpDcmVhdGVNZW1vEh8ubWVtb3MuYXBpLnYxLkNyZWF0ZU1lbW9SZXF1ZXN0GhIubWVtb3MuYXBpLnYxLk1lbW8iItpBBG1lbW+C0+STAhU6BG1lbW8iDS9hcGkvdjEvbWVtb3MSZgoJTGlzdE1lbW9zEh4ubWVtb3MuYXBpLnYxLkxpc3RNZW1vc1JlcXVlc3QaHy5tZW1vcy5hcGkudjEuTGlzdE1lbW9zUmVzcG9uc2UiGNpBAILT5JMCDxINL2FwaS92MS9tZW1vcxJiCgdHZXRNZW1vEhwubWVtb3MuYXBpLnYxLkdldE1lbW9SZXF1ZXN0GhIubWVtb3MuYXBpLnYxLk1lbW8iJdpBBG5hbWWC0+STAhgSFi9hcGkvdjEve25hbWU9bWVtb3MvKn0SfwoKVXBkYXRlTWVtbxIfLm1lbW9zLmFwaS52MS5VcGRhdGVNZW1vUmVxdWVzdBoSLm1lbW9zLmFwaS52MS5NZW1vIjzaQRBtZW1vLHVwZGF0ZV9tYXNrgtPkkwIjOgRtZW1vMhsvYXBpL3YxL3ttZW1vLm5hbWU9bWVtb3MvKn0SbAoKRGVsZXRlTWVtbxIfLm1lbW9zLmFwaS52MS5EZWxldGVNZW1vUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIl2kEEbmFtZYLT5JMCGCoWL2FwaS92MS97bmFtZT1tZW1vcy8qfRKLAQoSU2V0TWVtb0F0dGFjaG1lbnRzEicubWVtb3MuYXBpLnYxLlNldE1lbW9BdHRhY2htZW50c1JlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiNNpBBG5hbWWC0+STAic6ASoyIi9hcGkvdjEve25hbWU9bWVtb3MvKn0vYXR0YWNobWVudHMSnQEKE0xpc3RNZW1vQXR0YWNobWVudHMSKC5tZW1vcy5hcGkudjEuTGlzdE1lbW9BdHRhY2htZW50c1JlcXVlc3QaKS5tZW1vcy5hcGkudjEuTGlzdE1lbW9BdHRhY2htZW50c1Jlc3BvbnNlIjHaQQRuYW1lgtPkkwIkEiIvYXBpL3YxL3tuYW1lPW1lbW9zLyp9L2F0dGFjaG1lbnRzEoUBChBTZXRNZW1vUmVsYXRpb25zEiUubWVtb3MuYXBpLnYxLlNldE1lbW9SZWxhdGlvbnNSZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjLaQQRuYW1lgtPkkwIlOgEqMiAvYXBpL3YxL3tuYW1lPW1lbW9zLyp9L3JlbGF0aW9ucxKVAQoRTGlzdE1lbW9SZWxhdGlvbnMSJi5tZW1vcy5hcGkudjEuTGlzdE1lbW9SZWxhdGlvbnNSZXF1ZXN0GicubWVtb3MuYXBpLnYxLkxpc3RNZW1vUmVsYXRpb25zUmVzcG9uc2UiL9pBBG5hbWWC0+STAiISIC9hcGkvdjEve25hbWU9bWVtb3MvKn0vcmVsYXRpb25zEpABChFDcmVhdGVNZW1vQ29tbWVudBImLm1lbW9zLmFwaS52MS5DcmVhdGVNZW1vQ29tbWVudFJlcXVlc3QaEi5tZW1vcy5hcGkudjEuTWVtbyI/2kEMbmFtZSxjb21tZW50gtPkkwIqOgdjb21tZW50Ih8vYXBpL3YxL3tuYW1lPW1lbW9zLyp9L2NvbW1lbnRzEpEBChBMaXN0TWVtb0NvbW1lbnRzEiUubWVtb3MuYXBpLnYxLkxpc3RNZW1vQ29tbWVudHNSZXF1ZXN0GiYubWVtb3MuYXBpLnYxLkxpc3RNZW1vQ29tbWVudHNSZXNwb25zZSIu2kEEbmFtZYLT5JMCIRIfL2FwaS92MS97bmFtZT1tZW1vcy8qfS9jb21tZW50cxKVAQoRTGlzdE1lbW9SZWFjdGlvbnMSJi5tZW1vcy5hcGkudjEuTGlzdE1lbW9SZWFjdGlvbnNSZXF1ZXN0GicubWVtb3MuYXBpLnYxLkxpc3RNZW1vUmVhY3Rpb25zUmVzcG9uc2UiL9pBBG5hbWWC0+STAiISIC9hcGkvdjEve25hbWU9bWVtb3MvKn0vcmVhY3Rpb25zEokBChJVcHNlcnRNZW1vUmVhY3Rpb24SJy5tZW1vcy5hcGkudjEuVXBzZXJ0TWVtb1JlYWN0aW9uUmVxdWVzdBoWLm1lbW9zLmFwaS52MS5SZWFjdGlvbiIy2kEEbmFtZYLT5JMCJToBKiIgL2FwaS92MS97bmFtZT1tZW1vcy8qfS9yZWFjdGlvbnMSiAEKEkRlbGV0ZU1lbW9SZWFjdGlvbhInLm1lbW9zLmFwaS52MS5EZWxldGVNZW1vUmVhY3Rpb25SZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjHaQQRuYW1lgtPkkwIkKiIvYXBpL3YxL3tuYW1lPW1lbW9zLyovcmVhY3Rpb25zLyp9EpkBCg9DcmVhdGVNZW1vU2hhcmUSJC5tZW1vcy5hcGkudjEuQ3JlYXRlTWVtb1NoYXJlUmVxdWVzdBoXLm1lbW9zLmFwaS52MS5NZW1vU2hhcmUiR9pBEXBhcmVudCxtZW1vX3NoYXJlgtPkkwItOgptZW1vX3NoYXJlIh8vYXBpL3YxL3twYXJlbnQ9bWVtb3MvKn0vc2hhcmVzEo0BCg5MaXN0TWVtb1NoYXJlcxIjLm1lbW9zLmFwaS52MS5MaXN0TWVtb1NoYXJlc1JlcXVlc3QaJC5tZW1vcy5hcGkudjEuTGlzdE1lbW9TaGFyZXNSZXNwb25zZSIw2kEGcGFyZW50gtPkkwIhEh8vYXBpL3YxL3twYXJlbnQ9bWVtb3MvKn0vc2hhcmVzEn8KD0RlbGV0ZU1lbW9TaGFyZRIkLm1lbW9zLmFwaS52MS5EZWxldGVNZW1vU2hhcmVSZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5Ii7aQQRuYW1lgtPkkwIhKh8vYXBpL3YxL3tuYW1lPW1lbW9zLyovc2hhcmVzLyp9EmwKDkdldE1lbW9CeVNoYXJlEiMubWVtb3MuYXBpLnYxLkdldE1lbW9CeVNoYXJlUmVxdWVzdBoSLm1lbW9zLmFwaS52MS5NZW1vIiGC0+STAhsSGS9hcGkvdjEvc2hhcmVzL3tzaGFyZV9pZH0SeQoPR2V0TGlua01ldGFkYXRhEiQubWVtb3MuYXBpLnYxLkdldExpbmtNZXRhZGF0YVJlcXVlc3QaGi5tZW1vcy5hcGkudjEuTGlua01ldGFkYXRhIiSC0+STAh4SHC9hcGkvdjEvbWVtb3MvLS9saW5rTWV0YWRhdGESnwEKFEJhdGNoR2V0TGlua01ldGFkYXRhEikubWVtb3MuYXBpLnYxLkJhdGNoR2V0TGlua01ldGFkYXRhUmVxdWVzdBoqLm1lbW9zLmFwaS52MS5CYXRjaEdldExpbmtNZXRhZGF0YVJlc3BvbnNlIjCC0+STAio6ASoiJS9hcGkvdjEvbWVtb3MvLS9saW5rTWV0YWRhdGE6YmF0Y2hHZXRCqAEKEGNvbS5tZW1vcy5hcGkudjFCEE1lbW9TZXJ2aWNlUHJvdG9QAVowZ2l0aHViLmNvbS91c2VtZW1vcy9tZW1vcy9wcm90by9nZW4vYXBpL3YxO2FwaXYxogIDTUFYqgIMTWVtb3MuQXBpLlYxygIMTWVtb3NcQXBpXFYx4gIYTWVtb3NcQXBpXFYxXEdQQk1ldGFkYXRh6gIOTWVtb3M6OkFwaTo6VjFiBnByb3RvMw", [file_api_v1_attachment_service, file_api_v1_common, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_empty, file_google_protobuf_field_mask, file_google_protobuf_timestamp]); /** * @generated from message memos.api.v1.Reaction @@ -837,13 +837,6 @@ export type ListMemoCommentsResponse = Message<"memos.api.v1.ListMemoCommentsRes * @generated from field: string next_page_token = 2; */ nextPageToken: string; - - /** - * The total count of comments. - * - * @generated from field: int32 total_size = 3; - */ - totalSize: number; }; /** @@ -904,13 +897,6 @@ export type ListMemoReactionsResponse = Message<"memos.api.v1.ListMemoReactionsR * @generated from field: string next_page_token = 2; */ nextPageToken: string; - - /** - * The total count of reactions. - * - * @generated from field: int32 total_size = 3; - */ - totalSize: number; }; /** diff --git a/web/src/types/proto/api/v1/user_service_pb.ts b/web/src/types/proto/api/v1/user_service_pb.ts index e9334a9f..b5d90235 100644 --- a/web/src/types/proto/api/v1/user_service_pb.ts +++ b/web/src/types/proto/api/v1/user_service_pb.ts @@ -20,7 +20,7 @@ import type { Message } from "@bufbuild/protobuf"; * Describes the file api/v1/user_service.proto. */ export const file_api_v1_user_service: GenFile = /*@__PURE__*/ - fileDesc("ChlhcGkvdjEvdXNlcl9zZXJ2aWNlLnByb3RvEgxtZW1vcy5hcGkudjEi1gMKBFVzZXISEQoEbmFtZRgBIAEoCUID4EEIEioKBHJvbGUYAiABKA4yFy5tZW1vcy5hcGkudjEuVXNlci5Sb2xlQgPgQQISFQoIdXNlcm5hbWUYAyABKAlCA+BBAhISCgVlbWFpbBgEIAEoCUID4EEBEhkKDGRpc3BsYXlfbmFtZRgFIAEoCUID4EEBEhcKCmF2YXRhcl91cmwYBiABKAlCA+BBARIYCgtkZXNjcmlwdGlvbhgHIAEoCUID4EEBEhUKCHBhc3N3b3JkGAggASgJQgPgQQQSJwoFc3RhdGUYCSABKA4yEy5tZW1vcy5hcGkudjEuU3RhdGVCA+BBAhI0CgtjcmVhdGVfdGltZRgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxI0Cgt1cGRhdGVfdGltZRgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAyIxCgRSb2xlEhQKEFJPTEVfVU5TUEVDSUZJRUQQABIJCgVBRE1JThACEggKBFVTRVIQAzo36kE0ChFtZW1vcy5hcGkudjEvVXNlchIMdXNlcnMve3VzZXJ9GgRuYW1lKgV1c2VyczIEdXNlciJzChBMaXN0VXNlcnNSZXF1ZXN0EhYKCXBhZ2Vfc2l6ZRgBIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAiABKAlCA+BBARITCgZmaWx0ZXIYAyABKAlCA+BBARIZCgxzaG93X2RlbGV0ZWQYBCABKAhCA+BBASJjChFMaXN0VXNlcnNSZXNwb25zZRIhCgV1c2VycxgBIAMoCzISLm1lbW9zLmFwaS52MS5Vc2VyEhcKD25leHRfcGFnZV90b2tlbhgCIAEoCRISCgp0b3RhbF9zaXplGAMgASgFIikKFEJhdGNoR2V0VXNlcnNSZXF1ZXN0EhEKCXVzZXJuYW1lcxgBIAMoCSI6ChVCYXRjaEdldFVzZXJzUmVzcG9uc2USIQoFdXNlcnMYASADKAsyEi5tZW1vcy5hcGkudjEuVXNlciJtCg5HZXRVc2VyUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEjIKCXJlYWRfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBASKIAQoRQ3JlYXRlVXNlclJlcXVlc3QSKAoEdXNlchgBIAEoCzISLm1lbW9zLmFwaS52MS5Vc2VyQgbgQQLgQQQSFAoHdXNlcl9pZBgCIAEoCUID4EEBEhoKDXZhbGlkYXRlX29ubHkYAyABKAhCA+BBARIXCgpyZXF1ZXN0X2lkGAQgASgJQgPgQQEijAEKEVVwZGF0ZVVzZXJSZXF1ZXN0EiUKBHVzZXIYASABKAsyEi5tZW1vcy5hcGkudjEuVXNlckID4EECEjQKC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFza0ID4EECEhoKDWFsbG93X21pc3NpbmcYAyABKAhCA+BBASJQChFEZWxldGVVc2VyUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEhIKBWZvcmNlGAIgASgIQgPgQQEitAQKCVVzZXJTdGF0cxIRCgRuYW1lGAEgASgJQgPgQQgSPgoPbWVtb190eXBlX3N0YXRzGAMgASgLMiUubWVtb3MuYXBpLnYxLlVzZXJTdGF0cy5NZW1vVHlwZVN0YXRzEjgKCXRhZ19jb3VudBgEIAMoCzIlLm1lbW9zLmFwaS52MS5Vc2VyU3RhdHMuVGFnQ291bnRFbnRyeRI7ChdtZW1vX2NyZWF0ZWRfdGltZXN0YW1wcxgHIAMoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXASOwoXbWVtb191cGRhdGVkX3RpbWVzdGFtcHMYCCADKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEhQKDHBpbm5lZF9tZW1vcxgFIAMoCRIYChB0b3RhbF9tZW1vX2NvdW50GAYgASgFGi8KDVRhZ0NvdW50RW50cnkSCwoDa2V5GAEgASgJEg0KBXZhbHVlGAIgASgFOgI4ARpfCg1NZW1vVHlwZVN0YXRzEhIKCmxpbmtfY291bnQYASABKAUSEgoKY29kZV9jb3VudBgCIAEoBRISCgp0b2RvX2NvdW50GAMgASgFEhIKCnVuZG9fY291bnQYBCABKAU6P+pBPAoWbWVtb3MuYXBpLnYxL1VzZXJTdGF0cxIMdXNlcnMve3VzZXJ9Kgl1c2VyU3RhdHMyCXVzZXJTdGF0c0oECAIQA1IXbWVtb19kaXNwbGF5X3RpbWVzdGFtcHMiPgoTR2V0VXNlclN0YXRzUmVxdWVzdBInCgRuYW1lGAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyIlcKF0xpc3RBbGxVc2VyU3RhdHNSZXF1ZXN0EicKBXN0YXRlGAEgASgOMhMubWVtb3MuYXBpLnYxLlN0YXRlQgPgQQESEwoGZmlsdGVyGAIgASgJQgPgQQEiQgoYTGlzdEFsbFVzZXJTdGF0c1Jlc3BvbnNlEiYKBXN0YXRzGAEgAygLMhcubWVtb3MuYXBpLnYxLlVzZXJTdGF0cyKyBgoLVXNlclNldHRpbmcSEQoEbmFtZRgBIAEoCUID4EEIEkMKD2dlbmVyYWxfc2V0dGluZxgCIAEoCzIoLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZy5HZW5lcmFsU2V0dGluZ0gAEkUKEHdlYmhvb2tzX3NldHRpbmcYBSABKAsyKS5tZW1vcy5hcGkudjEuVXNlclNldHRpbmcuV2ViaG9va3NTZXR0aW5nSAASPQoMdGFnc19zZXR0aW5nGAYgASgLMiUubWVtb3MuYXBpLnYxLlVzZXJTZXR0aW5nLlRhZ3NTZXR0aW5nSAAaVwoOR2VuZXJhbFNldHRpbmcSEwoGbG9jYWxlGAEgASgJQgPgQQESHAoPbWVtb192aXNpYmlsaXR5GAMgASgJQgPgQQESEgoFdGhlbWUYBCABKAlCA+BBARpbCgtUYWdNZXRhZGF0YRIxChBiYWNrZ3JvdW5kX2NvbG9yGAEgASgLMhIuZ29vZ2xlLnR5cGUuQ29sb3JCA+BBARIZCgxibHVyX2NvbnRlbnQYAiABKAhCA+BBARqlAQoLVGFnc1NldHRpbmcSQgoEdGFncxgBIAMoCzIvLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZy5UYWdzU2V0dGluZy5UYWdzRW50cnlCA+BBARpSCglUYWdzRW50cnkSCwoDa2V5GAEgASgJEjQKBXZhbHVlGAIgASgLMiUubWVtb3MuYXBpLnYxLlVzZXJTZXR0aW5nLlRhZ01ldGFkYXRhOgI4ARo+Cg9XZWJob29rc1NldHRpbmcSKwoId2ViaG9va3MYASADKAsyGS5tZW1vcy5hcGkudjEuVXNlcldlYmhvb2siPwoDS2V5EhMKD0tFWV9VTlNQRUNJRklFRBAAEgsKB0dFTkVSQUwQARIMCghXRUJIT09LUxAEEggKBFRBR1MQBTpd6kFaChhtZW1vcy5hcGkudjEvVXNlclNldHRpbmcSI3VzZXJzL3t1c2VybmFtZX0vc2V0dGluZ3Mve3NldHRpbmd9Kgx1c2VyU2V0dGluZ3MyC3VzZXJTZXR0aW5nQgcKBXZhbHVlIkcKFUdldFVzZXJTZXR0aW5nUmVxdWVzdBIuCgRuYW1lGAEgASgJQiDgQQL6QRoKGG1lbW9zLmFwaS52MS9Vc2VyU2V0dGluZyKBAQoYVXBkYXRlVXNlclNldHRpbmdSZXF1ZXN0Ei8KB3NldHRpbmcYASABKAsyGS5tZW1vcy5hcGkudjEuVXNlclNldHRpbmdCA+BBAhI0Cgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBAiJ1ChdMaXN0VXNlclNldHRpbmdzUmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL1VzZXISFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBInQKGExpc3RVc2VyU2V0dGluZ3NSZXNwb25zZRIrCghzZXR0aW5ncxgBIAMoCzIZLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZxIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkSEgoKdG90YWxfc2l6ZRgDIAEoBSLqAQoOTGlua2VkSWRlbnRpdHkSEQoEbmFtZRgBIAEoCUID4EEIEjcKCGlkcF9uYW1lGAIgASgJQiXgQQP6QR8KHW1lbW9zLmFwaS52MS9JZGVudGl0eVByb3ZpZGVyEhcKCmV4dGVybl91aWQYAyABKAlCA+BBAzpz6kFwChttZW1vcy5hcGkudjEvTGlua2VkSWRlbnRpdHkSL3VzZXJzL3t1c2VyfS9saW5rZWRJZGVudGl0aWVzL3tsaW5rZWRfaWRlbnRpdHl9KhBsaW5rZWRJZGVudGl0aWVzMg5saW5rZWRJZGVudGl0eSJIChtMaXN0TGlua2VkSWRlbnRpdGllc1JlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyIlcKHExpc3RMaW5rZWRJZGVudGl0aWVzUmVzcG9uc2USNwoRbGlua2VkX2lkZW50aXRpZXMYASADKAsyHC5tZW1vcy5hcGkudjEuTGlua2VkSWRlbnRpdHkiywEKG0NyZWF0ZUxpbmtlZElkZW50aXR5UmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL1VzZXISNwoIaWRwX25hbWUYAiABKAlCJeBBAvpBHwodbWVtb3MuYXBpLnYxL0lkZW50aXR5UHJvdmlkZXISEQoEY29kZRgDIAEoCUID4EECEhkKDHJlZGlyZWN0X3VyaRgEIAEoCUID4EECEhoKDWNvZGVfdmVyaWZpZXIYBSABKAlCA+BBASJNChhHZXRMaW5rZWRJZGVudGl0eVJlcXVlc3QSMQoEbmFtZRgBIAEoCUIj4EEC+kEdChttZW1vcy5hcGkudjEvTGlua2VkSWRlbnRpdHkiUAobRGVsZXRlTGlua2VkSWRlbnRpdHlSZXF1ZXN0EjEKBG5hbWUYASABKAlCI+BBAvpBHQobbWVtb3MuYXBpLnYxL0xpbmtlZElkZW50aXR5IvICChNQZXJzb25hbEFjY2Vzc1Rva2VuEhEKBG5hbWUYASABKAlCA+BBCBIYCgtkZXNjcmlwdGlvbhgCIAEoCUID4EEBEjMKCmNyZWF0ZWRfYXQYAyABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQMSMwoKZXhwaXJlc19hdBgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBARI1CgxsYXN0X3VzZWRfYXQYBSABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQM6jAHqQYgBCiBtZW1vcy5hcGkudjEvUGVyc29uYWxBY2Nlc3NUb2tlbhI5dXNlcnMve3VzZXJ9L3BlcnNvbmFsQWNjZXNzVG9rZW5zL3twZXJzb25hbF9hY2Nlc3NfdG9rZW59KhRwZXJzb25hbEFjY2Vzc1Rva2VuczITcGVyc29uYWxBY2Nlc3NUb2tlbiJ9Ch9MaXN0UGVyc29uYWxBY2Nlc3NUb2tlbnNSZXF1ZXN0EikKBnBhcmVudBgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvVXNlchIWCglwYWdlX3NpemUYAiABKAVCA+BBARIXCgpwYWdlX3Rva2VuGAMgASgJQgPgQQEikgEKIExpc3RQZXJzb25hbEFjY2Vzc1Rva2Vuc1Jlc3BvbnNlEkEKFnBlcnNvbmFsX2FjY2Vzc190b2tlbnMYASADKAsyIS5tZW1vcy5hcGkudjEuUGVyc29uYWxBY2Nlc3NUb2tlbhIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkSEgoKdG90YWxfc2l6ZRgDIAEoBSKFAQogQ3JlYXRlUGVyc29uYWxBY2Nlc3NUb2tlblJlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEhgKC2Rlc2NyaXB0aW9uGAIgASgJQgPgQQESHAoPZXhwaXJlc19pbl9kYXlzGAMgASgFQgPgQQEidAohQ3JlYXRlUGVyc29uYWxBY2Nlc3NUb2tlblJlc3BvbnNlEkAKFXBlcnNvbmFsX2FjY2Vzc190b2tlbhgBIAEoCzIhLm1lbW9zLmFwaS52MS5QZXJzb25hbEFjY2Vzc1Rva2VuEg0KBXRva2VuGAIgASgJIloKIERlbGV0ZVBlcnNvbmFsQWNjZXNzVG9rZW5SZXF1ZXN0EjYKBG5hbWUYASABKAlCKOBBAvpBIgogbWVtb3MuYXBpLnYxL1BlcnNvbmFsQWNjZXNzVG9rZW4i6AEKC1VzZXJXZWJob29rEgwKBG5hbWUYASABKAkSCwoDdXJsGAIgASgJEhQKDGRpc3BsYXlfbmFtZRgDIAEoCRI0CgtjcmVhdGVfdGltZRgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxI0Cgt1cGRhdGVfdGltZRgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxIbCg5zaWduaW5nX3NlY3JldBgGIAEoCUID4EEEEh8KEnNpZ25pbmdfc2VjcmV0X3NldBgHIAEoCEID4EEDIi4KF0xpc3RVc2VyV2ViaG9va3NSZXF1ZXN0EhMKBnBhcmVudBgBIAEoCUID4EECIkcKGExpc3RVc2VyV2ViaG9va3NSZXNwb25zZRIrCgh3ZWJob29rcxgBIAMoCzIZLm1lbW9zLmFwaS52MS5Vc2VyV2ViaG9vayJgChhDcmVhdGVVc2VyV2ViaG9va1JlcXVlc3QSEwoGcGFyZW50GAEgASgJQgPgQQISLwoHd2ViaG9vaxgCIAEoCzIZLm1lbW9zLmFwaS52MS5Vc2VyV2ViaG9va0ID4EECInwKGFVwZGF0ZVVzZXJXZWJob29rUmVxdWVzdBIvCgd3ZWJob29rGAEgASgLMhkubWVtb3MuYXBpLnYxLlVzZXJXZWJob29rQgPgQQISLwoLdXBkYXRlX21hc2sYAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrIi0KGERlbGV0ZVVzZXJXZWJob29rUmVxdWVzdBIRCgRuYW1lGAEgASgJQgPgQQIiNwoiR2V0VXNlcldlYmhvb2tTaWduaW5nU2VjcmV0UmVxdWVzdBIRCgRuYW1lGAEgASgJQgPgQQIiPQojR2V0VXNlcldlYmhvb2tTaWduaW5nU2VjcmV0UmVzcG9uc2USFgoOc2lnbmluZ19zZWNyZXQYASABKAkiogcKEFVzZXJOb3RpZmljYXRpb24SFAoEbmFtZRgBIAEoCUIG4EED4EEIEikKBnNlbmRlchgCIAEoCUIZ4EED+kETChFtZW1vcy5hcGkudjEvVXNlchIsCgtzZW5kZXJfdXNlchgIIAEoCzISLm1lbW9zLmFwaS52MS5Vc2VyQgPgQQMSOgoGc3RhdHVzGAMgASgOMiUubWVtb3MuYXBpLnYxLlVzZXJOb3RpZmljYXRpb24uU3RhdHVzQgPgQQESNAoLY3JlYXRlX3RpbWUYBCABKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wQgPgQQMSNgoEdHlwZRgFIAEoDjIjLm1lbW9zLmFwaS52MS5Vc2VyTm90aWZpY2F0aW9uLlR5cGVCA+BBAxJOCgxtZW1vX2NvbW1lbnQYBiABKAsyMS5tZW1vcy5hcGkudjEuVXNlck5vdGlmaWNhdGlvbi5NZW1vQ29tbWVudFBheWxvYWRCA+BBA0gAEk4KDG1lbW9fbWVudGlvbhgHIAEoCzIxLm1lbW9zLmFwaS52MS5Vc2VyTm90aWZpY2F0aW9uLk1lbW9NZW50aW9uUGF5bG9hZEID4EEDSAAabAoSTWVtb0NvbW1lbnRQYXlsb2FkEgwKBG1lbW8YASABKAkSFAoMcmVsYXRlZF9tZW1vGAIgASgJEhQKDG1lbW9fc25pcHBldBgDIAEoCRIcChRyZWxhdGVkX21lbW9fc25pcHBldBgEIAEoCRpsChJNZW1vTWVudGlvblBheWxvYWQSDAoEbWVtbxgBIAEoCRIUCgxyZWxhdGVkX21lbW8YAiABKAkSFAoMbWVtb19zbmlwcGV0GAMgASgJEhwKFHJlbGF0ZWRfbWVtb19zbmlwcGV0GAQgASgJIjoKBlN0YXR1cxIWChJTVEFUVVNfVU5TUEVDSUZJRUQQABIKCgZVTlJFQUQQARIMCghBUkNISVZFRBACIkAKBFR5cGUSFAoQVFlQRV9VTlNQRUNJRklFRBAAEhAKDE1FTU9fQ09NTUVOVBABEhAKDE1FTU9fTUVOVElPThACOnDqQW0KHW1lbW9zLmFwaS52MS9Vc2VyTm90aWZpY2F0aW9uEil1c2Vycy97dXNlcn0vbm90aWZpY2F0aW9ucy97bm90aWZpY2F0aW9ufRoEbmFtZSoNbm90aWZpY2F0aW9uczIMbm90aWZpY2F0aW9uQgkKB3BheWxvYWQijwEKHExpc3RVc2VyTm90aWZpY2F0aW9uc1JlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBARITCgZmaWx0ZXIYBCABKAlCA+BBASJvCh1MaXN0VXNlck5vdGlmaWNhdGlvbnNSZXNwb25zZRI1Cg1ub3RpZmljYXRpb25zGAEgAygLMh4ubWVtb3MuYXBpLnYxLlVzZXJOb3RpZmljYXRpb24SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJIpABCh1VcGRhdGVVc2VyTm90aWZpY2F0aW9uUmVxdWVzdBI5Cgxub3RpZmljYXRpb24YASABKAsyHi5tZW1vcy5hcGkudjEuVXNlck5vdGlmaWNhdGlvbkID4EECEjQKC3VwZGF0ZV9tYXNrGAIgASgLMhouZ29vZ2xlLnByb3RvYnVmLkZpZWxkTWFza0ID4EECIlQKHURlbGV0ZVVzZXJOb3RpZmljYXRpb25SZXF1ZXN0EjMKBG5hbWUYASABKAlCJeBBAvpBHwodbWVtb3MuYXBpLnYxL1VzZXJOb3RpZmljYXRpb24yyh4KC1VzZXJTZXJ2aWNlEmMKCUxpc3RVc2VycxIeLm1lbW9zLmFwaS52MS5MaXN0VXNlcnNSZXF1ZXN0Gh8ubWVtb3MuYXBpLnYxLkxpc3RVc2Vyc1Jlc3BvbnNlIhWC0+STAg8SDS9hcGkvdjEvdXNlcnMSewoNQmF0Y2hHZXRVc2VycxIiLm1lbW9zLmFwaS52MS5CYXRjaEdldFVzZXJzUmVxdWVzdBojLm1lbW9zLmFwaS52MS5CYXRjaEdldFVzZXJzUmVzcG9uc2UiIYLT5JMCGzoBKiIWL2FwaS92MS91c2VyczpiYXRjaEdldBJiCgdHZXRVc2VyEhwubWVtb3MuYXBpLnYxLkdldFVzZXJSZXF1ZXN0GhIubWVtb3MuYXBpLnYxLlVzZXIiJdpBBG5hbWWC0+STAhgSFi9hcGkvdjEve25hbWU9dXNlcnMvKn0SZQoKQ3JlYXRlVXNlchIfLm1lbW9zLmFwaS52MS5DcmVhdGVVc2VyUmVxdWVzdBoSLm1lbW9zLmFwaS52MS5Vc2VyIiLaQQR1c2VygtPkkwIVOgR1c2VyIg0vYXBpL3YxL3VzZXJzEn8KClVwZGF0ZVVzZXISHy5tZW1vcy5hcGkudjEuVXBkYXRlVXNlclJlcXVlc3QaEi5tZW1vcy5hcGkudjEuVXNlciI82kEQdXNlcix1cGRhdGVfbWFza4LT5JMCIzoEdXNlcjIbL2FwaS92MS97dXNlci5uYW1lPXVzZXJzLyp9EmwKCkRlbGV0ZVVzZXISHy5tZW1vcy5hcGkudjEuRGVsZXRlVXNlclJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiJdpBBG5hbWWC0+STAhgqFi9hcGkvdjEve25hbWU9dXNlcnMvKn0SfgoQTGlzdEFsbFVzZXJTdGF0cxIlLm1lbW9zLmFwaS52MS5MaXN0QWxsVXNlclN0YXRzUmVxdWVzdBomLm1lbW9zLmFwaS52MS5MaXN0QWxsVXNlclN0YXRzUmVzcG9uc2UiG4LT5JMCFRITL2FwaS92MS91c2VyczpzdGF0cxJ6CgxHZXRVc2VyU3RhdHMSIS5tZW1vcy5hcGkudjEuR2V0VXNlclN0YXRzUmVxdWVzdBoXLm1lbW9zLmFwaS52MS5Vc2VyU3RhdHMiLtpBBG5hbWWC0+STAiESHy9hcGkvdjEve25hbWU9dXNlcnMvKn06Z2V0U3RhdHMSggEKDkdldFVzZXJTZXR0aW5nEiMubWVtb3MuYXBpLnYxLkdldFVzZXJTZXR0aW5nUmVxdWVzdBoZLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZyIw2kEEbmFtZYLT5JMCIxIhL2FwaS92MS97bmFtZT11c2Vycy8qL3NldHRpbmdzLyp9EqgBChFVcGRhdGVVc2VyU2V0dGluZxImLm1lbW9zLmFwaS52MS5VcGRhdGVVc2VyU2V0dGluZ1JlcXVlc3QaGS5tZW1vcy5hcGkudjEuVXNlclNldHRpbmciUNpBE3NldHRpbmcsdXBkYXRlX21hc2uC0+STAjQ6B3NldHRpbmcyKS9hcGkvdjEve3NldHRpbmcubmFtZT11c2Vycy8qL3NldHRpbmdzLyp9EpUBChBMaXN0VXNlclNldHRpbmdzEiUubWVtb3MuYXBpLnYxLkxpc3RVc2VyU2V0dGluZ3NSZXF1ZXN0GiYubWVtb3MuYXBpLnYxLkxpc3RVc2VyU2V0dGluZ3NSZXNwb25zZSIy2kEGcGFyZW50gtPkkwIjEiEvYXBpL3YxL3twYXJlbnQ9dXNlcnMvKn0vc2V0dGluZ3MSqQEKFExpc3RMaW5rZWRJZGVudGl0aWVzEikubWVtb3MuYXBpLnYxLkxpc3RMaW5rZWRJZGVudGl0aWVzUmVxdWVzdBoqLm1lbW9zLmFwaS52MS5MaXN0TGlua2VkSWRlbnRpdGllc1Jlc3BvbnNlIjraQQZwYXJlbnSC0+STAisSKS9hcGkvdjEve3BhcmVudD11c2Vycy8qfS9saW5rZWRJZGVudGl0aWVzEqcBChRDcmVhdGVMaW5rZWRJZGVudGl0eRIpLm1lbW9zLmFwaS52MS5DcmVhdGVMaW5rZWRJZGVudGl0eVJlcXVlc3QaHC5tZW1vcy5hcGkudjEuTGlua2VkSWRlbnRpdHkiRtpBD3BhcmVudCxpZHBfbmFtZYLT5JMCLjoBKiIpL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L2xpbmtlZElkZW50aXRpZXMSkwEKEUdldExpbmtlZElkZW50aXR5EiYubWVtb3MuYXBpLnYxLkdldExpbmtlZElkZW50aXR5UmVxdWVzdBocLm1lbW9zLmFwaS52MS5MaW5rZWRJZGVudGl0eSI42kEEbmFtZYLT5JMCKxIpL2FwaS92MS97bmFtZT11c2Vycy8qL2xpbmtlZElkZW50aXRpZXMvKn0SkwEKFERlbGV0ZUxpbmtlZElkZW50aXR5EikubWVtb3MuYXBpLnYxLkRlbGV0ZUxpbmtlZElkZW50aXR5UmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSI42kEEbmFtZYLT5JMCKyopL2FwaS92MS97bmFtZT11c2Vycy8qL2xpbmtlZElkZW50aXRpZXMvKn0SuQEKGExpc3RQZXJzb25hbEFjY2Vzc1Rva2VucxItLm1lbW9zLmFwaS52MS5MaXN0UGVyc29uYWxBY2Nlc3NUb2tlbnNSZXF1ZXN0Gi4ubWVtb3MuYXBpLnYxLkxpc3RQZXJzb25hbEFjY2Vzc1Rva2Vuc1Jlc3BvbnNlIj7aQQZwYXJlbnSC0+STAi8SLS9hcGkvdjEve3BhcmVudD11c2Vycy8qfS9wZXJzb25hbEFjY2Vzc1Rva2VucxK2AQoZQ3JlYXRlUGVyc29uYWxBY2Nlc3NUb2tlbhIuLm1lbW9zLmFwaS52MS5DcmVhdGVQZXJzb25hbEFjY2Vzc1Rva2VuUmVxdWVzdBovLm1lbW9zLmFwaS52MS5DcmVhdGVQZXJzb25hbEFjY2Vzc1Rva2VuUmVzcG9uc2UiOILT5JMCMjoBKiItL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L3BlcnNvbmFsQWNjZXNzVG9rZW5zEqEBChlEZWxldGVQZXJzb25hbEFjY2Vzc1Rva2VuEi4ubWVtb3MuYXBpLnYxLkRlbGV0ZVBlcnNvbmFsQWNjZXNzVG9rZW5SZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjzaQQRuYW1lgtPkkwIvKi0vYXBpL3YxL3tuYW1lPXVzZXJzLyovcGVyc29uYWxBY2Nlc3NUb2tlbnMvKn0SlQEKEExpc3RVc2VyV2ViaG9va3MSJS5tZW1vcy5hcGkudjEuTGlzdFVzZXJXZWJob29rc1JlcXVlc3QaJi5tZW1vcy5hcGkudjEuTGlzdFVzZXJXZWJob29rc1Jlc3BvbnNlIjLaQQZwYXJlbnSC0+STAiMSIS9hcGkvdjEve3BhcmVudD11c2Vycy8qfS93ZWJob29rcxKbAQoRQ3JlYXRlVXNlcldlYmhvb2sSJi5tZW1vcy5hcGkudjEuQ3JlYXRlVXNlcldlYmhvb2tSZXF1ZXN0GhkubWVtb3MuYXBpLnYxLlVzZXJXZWJob29rIkPaQQ5wYXJlbnQsd2ViaG9va4LT5JMCLDoHd2ViaG9vayIhL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L3dlYmhvb2tzEqgBChFVcGRhdGVVc2VyV2ViaG9vaxImLm1lbW9zLmFwaS52MS5VcGRhdGVVc2VyV2ViaG9va1JlcXVlc3QaGS5tZW1vcy5hcGkudjEuVXNlcldlYmhvb2siUNpBE3dlYmhvb2ssdXBkYXRlX21hc2uC0+STAjQ6B3dlYmhvb2syKS9hcGkvdjEve3dlYmhvb2submFtZT11c2Vycy8qL3dlYmhvb2tzLyp9EoUBChFEZWxldGVVc2VyV2ViaG9vaxImLm1lbW9zLmFwaS52MS5EZWxldGVVc2VyV2ViaG9va1JlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiMNpBBG5hbWWC0+STAiMqIS9hcGkvdjEve25hbWU9dXNlcnMvKi93ZWJob29rcy8qfRLFAQobR2V0VXNlcldlYmhvb2tTaWduaW5nU2VjcmV0EjAubWVtb3MuYXBpLnYxLkdldFVzZXJXZWJob29rU2lnbmluZ1NlY3JldFJlcXVlc3QaMS5tZW1vcy5hcGkudjEuR2V0VXNlcldlYmhvb2tTaWduaW5nU2VjcmV0UmVzcG9uc2UiQdpBBG5hbWWC0+STAjQSMi9hcGkvdjEve25hbWU9dXNlcnMvKi93ZWJob29rcy8qfTpnZXRTaWduaW5nU2VjcmV0EqkBChVMaXN0VXNlck5vdGlmaWNhdGlvbnMSKi5tZW1vcy5hcGkudjEuTGlzdFVzZXJOb3RpZmljYXRpb25zUmVxdWVzdBorLm1lbW9zLmFwaS52MS5MaXN0VXNlck5vdGlmaWNhdGlvbnNSZXNwb25zZSI32kEGcGFyZW50gtPkkwIoEiYvYXBpL3YxL3twYXJlbnQ9dXNlcnMvKn0vbm90aWZpY2F0aW9ucxLLAQoWVXBkYXRlVXNlck5vdGlmaWNhdGlvbhIrLm1lbW9zLmFwaS52MS5VcGRhdGVVc2VyTm90aWZpY2F0aW9uUmVxdWVzdBoeLm1lbW9zLmFwaS52MS5Vc2VyTm90aWZpY2F0aW9uImTaQRhub3RpZmljYXRpb24sdXBkYXRlX21hc2uC0+STAkM6DG5vdGlmaWNhdGlvbjIzL2FwaS92MS97bm90aWZpY2F0aW9uLm5hbWU9dXNlcnMvKi9ub3RpZmljYXRpb25zLyp9EpQBChZEZWxldGVVc2VyTm90aWZpY2F0aW9uEisubWVtb3MuYXBpLnYxLkRlbGV0ZVVzZXJOb3RpZmljYXRpb25SZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjXaQQRuYW1lgtPkkwIoKiYvYXBpL3YxL3tuYW1lPXVzZXJzLyovbm90aWZpY2F0aW9ucy8qfUKoAQoQY29tLm1lbW9zLmFwaS52MUIQVXNlclNlcnZpY2VQcm90b1ABWjBnaXRodWIuY29tL3VzZW1lbW9zL21lbW9zL3Byb3RvL2dlbi9hcGkvdjE7YXBpdjGiAgNNQViqAgxNZW1vcy5BcGkuVjHKAgxNZW1vc1xBcGlcVjHiAhhNZW1vc1xBcGlcVjFcR1BCTWV0YWRhdGHqAg5NZW1vczo6QXBpOjpWMWIGcHJvdG8z", [file_api_v1_common, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_empty, file_google_protobuf_field_mask, file_google_protobuf_timestamp, file_google_type_color]); + fileDesc("ChlhcGkvdjEvdXNlcl9zZXJ2aWNlLnByb3RvEgxtZW1vcy5hcGkudjEi1gMKBFVzZXISEQoEbmFtZRgBIAEoCUID4EEIEioKBHJvbGUYAiABKA4yFy5tZW1vcy5hcGkudjEuVXNlci5Sb2xlQgPgQQISFQoIdXNlcm5hbWUYAyABKAlCA+BBAhISCgVlbWFpbBgEIAEoCUID4EEBEhkKDGRpc3BsYXlfbmFtZRgFIAEoCUID4EEBEhcKCmF2YXRhcl91cmwYBiABKAlCA+BBARIYCgtkZXNjcmlwdGlvbhgHIAEoCUID4EEBEhUKCHBhc3N3b3JkGAggASgJQgPgQQQSJwoFc3RhdGUYCSABKA4yEy5tZW1vcy5hcGkudjEuU3RhdGVCA+BBAhI0CgtjcmVhdGVfdGltZRgKIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxI0Cgt1cGRhdGVfdGltZRgLIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAyIxCgRSb2xlEhQKEFJPTEVfVU5TUEVDSUZJRUQQABIJCgVBRE1JThACEggKBFVTRVIQAzo36kE0ChFtZW1vcy5hcGkudjEvVXNlchIMdXNlcnMve3VzZXJ9GgRuYW1lKgV1c2VyczIEdXNlciJzChBMaXN0VXNlcnNSZXF1ZXN0EhYKCXBhZ2Vfc2l6ZRgBIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAiABKAlCA+BBARITCgZmaWx0ZXIYAyABKAlCA+BBARIZCgxzaG93X2RlbGV0ZWQYBCABKAhCA+BBASJPChFMaXN0VXNlcnNSZXNwb25zZRIhCgV1c2VycxgBIAMoCzISLm1lbW9zLmFwaS52MS5Vc2VyEhcKD25leHRfcGFnZV90b2tlbhgCIAEoCSIpChRCYXRjaEdldFVzZXJzUmVxdWVzdBIRCgl1c2VybmFtZXMYASADKAkiOgoVQmF0Y2hHZXRVc2Vyc1Jlc3BvbnNlEiEKBXVzZXJzGAEgAygLMhIubWVtb3MuYXBpLnYxLlVzZXIibQoOR2V0VXNlclJlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvVXNlchIyCglyZWFkX21hc2sYAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrQgPgQQEiiAEKEUNyZWF0ZVVzZXJSZXF1ZXN0EigKBHVzZXIYASABKAsyEi5tZW1vcy5hcGkudjEuVXNlckIG4EEC4EEEEhQKB3VzZXJfaWQYAiABKAlCA+BBARIaCg12YWxpZGF0ZV9vbmx5GAMgASgIQgPgQQESFwoKcmVxdWVzdF9pZBgEIAEoCUID4EEBIowBChFVcGRhdGVVc2VyUmVxdWVzdBIlCgR1c2VyGAEgASgLMhIubWVtb3MuYXBpLnYxLlVzZXJCA+BBAhI0Cgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2tCA+BBAhIaCg1hbGxvd19taXNzaW5nGAMgASgIQgPgQQEiUAoRRGVsZXRlVXNlclJlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvVXNlchISCgVmb3JjZRgCIAEoCEID4EEBIrQECglVc2VyU3RhdHMSEQoEbmFtZRgBIAEoCUID4EEIEj4KD21lbW9fdHlwZV9zdGF0cxgDIAEoCzIlLm1lbW9zLmFwaS52MS5Vc2VyU3RhdHMuTWVtb1R5cGVTdGF0cxI4Cgl0YWdfY291bnQYBCADKAsyJS5tZW1vcy5hcGkudjEuVXNlclN0YXRzLlRhZ0NvdW50RW50cnkSOwoXbWVtb19jcmVhdGVkX3RpbWVzdGFtcHMYByADKAsyGi5nb29nbGUucHJvdG9idWYuVGltZXN0YW1wEjsKF21lbW9fdXBkYXRlZF90aW1lc3RhbXBzGAggAygLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcBIUCgxwaW5uZWRfbWVtb3MYBSADKAkSGAoQdG90YWxfbWVtb19jb3VudBgGIAEoBRovCg1UYWdDb3VudEVudHJ5EgsKA2tleRgBIAEoCRINCgV2YWx1ZRgCIAEoBToCOAEaXwoNTWVtb1R5cGVTdGF0cxISCgpsaW5rX2NvdW50GAEgASgFEhIKCmNvZGVfY291bnQYAiABKAUSEgoKdG9kb19jb3VudBgDIAEoBRISCgp1bmRvX2NvdW50GAQgASgFOj/qQTwKFm1lbW9zLmFwaS52MS9Vc2VyU3RhdHMSDHVzZXJzL3t1c2VyfSoJdXNlclN0YXRzMgl1c2VyU3RhdHNKBAgCEANSF21lbW9fZGlzcGxheV90aW1lc3RhbXBzIj4KE0dldFVzZXJTdGF0c1JlcXVlc3QSJwoEbmFtZRgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvVXNlciJXChdMaXN0QWxsVXNlclN0YXRzUmVxdWVzdBInCgVzdGF0ZRgBIAEoDjITLm1lbW9zLmFwaS52MS5TdGF0ZUID4EEBEhMKBmZpbHRlchgCIAEoCUID4EEBIkIKGExpc3RBbGxVc2VyU3RhdHNSZXNwb25zZRImCgVzdGF0cxgBIAMoCzIXLm1lbW9zLmFwaS52MS5Vc2VyU3RhdHMisgYKC1VzZXJTZXR0aW5nEhEKBG5hbWUYASABKAlCA+BBCBJDCg9nZW5lcmFsX3NldHRpbmcYAiABKAsyKC5tZW1vcy5hcGkudjEuVXNlclNldHRpbmcuR2VuZXJhbFNldHRpbmdIABJFChB3ZWJob29rc19zZXR0aW5nGAUgASgLMikubWVtb3MuYXBpLnYxLlVzZXJTZXR0aW5nLldlYmhvb2tzU2V0dGluZ0gAEj0KDHRhZ3Nfc2V0dGluZxgGIAEoCzIlLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZy5UYWdzU2V0dGluZ0gAGlcKDkdlbmVyYWxTZXR0aW5nEhMKBmxvY2FsZRgBIAEoCUID4EEBEhwKD21lbW9fdmlzaWJpbGl0eRgDIAEoCUID4EEBEhIKBXRoZW1lGAQgASgJQgPgQQEaWwoLVGFnTWV0YWRhdGESMQoQYmFja2dyb3VuZF9jb2xvchgBIAEoCzISLmdvb2dsZS50eXBlLkNvbG9yQgPgQQESGQoMYmx1cl9jb250ZW50GAIgASgIQgPgQQEapQEKC1RhZ3NTZXR0aW5nEkIKBHRhZ3MYASADKAsyLy5tZW1vcy5hcGkudjEuVXNlclNldHRpbmcuVGFnc1NldHRpbmcuVGFnc0VudHJ5QgPgQQEaUgoJVGFnc0VudHJ5EgsKA2tleRgBIAEoCRI0CgV2YWx1ZRgCIAEoCzIlLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZy5UYWdNZXRhZGF0YToCOAEaPgoPV2ViaG9va3NTZXR0aW5nEisKCHdlYmhvb2tzGAEgAygLMhkubWVtb3MuYXBpLnYxLlVzZXJXZWJob29rIj8KA0tleRITCg9LRVlfVU5TUEVDSUZJRUQQABILCgdHRU5FUkFMEAESDAoIV0VCSE9PS1MQBBIICgRUQUdTEAU6XepBWgoYbWVtb3MuYXBpLnYxL1VzZXJTZXR0aW5nEiN1c2Vycy97dXNlcm5hbWV9L3NldHRpbmdzL3tzZXR0aW5nfSoMdXNlclNldHRpbmdzMgt1c2VyU2V0dGluZ0IHCgV2YWx1ZSJHChVHZXRVc2VyU2V0dGluZ1JlcXVlc3QSLgoEbmFtZRgBIAEoCUIg4EEC+kEaChhtZW1vcy5hcGkudjEvVXNlclNldHRpbmcigQEKGFVwZGF0ZVVzZXJTZXR0aW5nUmVxdWVzdBIvCgdzZXR0aW5nGAEgASgLMhkubWVtb3MuYXBpLnYxLlVzZXJTZXR0aW5nQgPgQQISNAoLdXBkYXRlX21hc2sYAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrQgPgQQIidQoXTGlzdFVzZXJTZXR0aW5nc1JlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASJgChhMaXN0VXNlclNldHRpbmdzUmVzcG9uc2USKwoIc2V0dGluZ3MYASADKAsyGS5tZW1vcy5hcGkudjEuVXNlclNldHRpbmcSFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJIuoBCg5MaW5rZWRJZGVudGl0eRIRCgRuYW1lGAEgASgJQgPgQQgSNwoIaWRwX25hbWUYAiABKAlCJeBBA/pBHwodbWVtb3MuYXBpLnYxL0lkZW50aXR5UHJvdmlkZXISFwoKZXh0ZXJuX3VpZBgDIAEoCUID4EEDOnPqQXAKG21lbW9zLmFwaS52MS9MaW5rZWRJZGVudGl0eRIvdXNlcnMve3VzZXJ9L2xpbmtlZElkZW50aXRpZXMve2xpbmtlZF9pZGVudGl0eX0qEGxpbmtlZElkZW50aXRpZXMyDmxpbmtlZElkZW50aXR5IkgKG0xpc3RMaW5rZWRJZGVudGl0aWVzUmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL1VzZXIiVwocTGlzdExpbmtlZElkZW50aXRpZXNSZXNwb25zZRI3ChFsaW5rZWRfaWRlbnRpdGllcxgBIAMoCzIcLm1lbW9zLmFwaS52MS5MaW5rZWRJZGVudGl0eSLLAQobQ3JlYXRlTGlua2VkSWRlbnRpdHlSZXF1ZXN0EikKBnBhcmVudBgBIAEoCUIZ4EEC+kETChFtZW1vcy5hcGkudjEvVXNlchI3CghpZHBfbmFtZRgCIAEoCUIl4EEC+kEfCh1tZW1vcy5hcGkudjEvSWRlbnRpdHlQcm92aWRlchIRCgRjb2RlGAMgASgJQgPgQQISGQoMcmVkaXJlY3RfdXJpGAQgASgJQgPgQQISGgoNY29kZV92ZXJpZmllchgFIAEoCUID4EEBIk0KGEdldExpbmtlZElkZW50aXR5UmVxdWVzdBIxCgRuYW1lGAEgASgJQiPgQQL6QR0KG21lbW9zLmFwaS52MS9MaW5rZWRJZGVudGl0eSJQChtEZWxldGVMaW5rZWRJZGVudGl0eVJlcXVlc3QSMQoEbmFtZRgBIAEoCUIj4EEC+kEdChttZW1vcy5hcGkudjEvTGlua2VkSWRlbnRpdHki8gIKE1BlcnNvbmFsQWNjZXNzVG9rZW4SEQoEbmFtZRgBIAEoCUID4EEIEhgKC2Rlc2NyaXB0aW9uGAIgASgJQgPgQQESMwoKY3JlYXRlZF9hdBgDIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxIzCgpleHBpcmVzX2F0GAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEBEjUKDGxhc3RfdXNlZF9hdBgFIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAzqMAepBiAEKIG1lbW9zLmFwaS52MS9QZXJzb25hbEFjY2Vzc1Rva2VuEjl1c2Vycy97dXNlcn0vcGVyc29uYWxBY2Nlc3NUb2tlbnMve3BlcnNvbmFsX2FjY2Vzc190b2tlbn0qFHBlcnNvbmFsQWNjZXNzVG9rZW5zMhNwZXJzb25hbEFjY2Vzc1Rva2VuIn0KH0xpc3RQZXJzb25hbEFjY2Vzc1Rva2Vuc1JlcXVlc3QSKQoGcGFyZW50GAEgASgJQhngQQL6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEhYKCXBhZ2Vfc2l6ZRgCIAEoBUID4EEBEhcKCnBhZ2VfdG9rZW4YAyABKAlCA+BBASJ+CiBMaXN0UGVyc29uYWxBY2Nlc3NUb2tlbnNSZXNwb25zZRJBChZwZXJzb25hbF9hY2Nlc3NfdG9rZW5zGAEgAygLMiEubWVtb3MuYXBpLnYxLlBlcnNvbmFsQWNjZXNzVG9rZW4SFwoPbmV4dF9wYWdlX3Rva2VuGAIgASgJIoUBCiBDcmVhdGVQZXJzb25hbEFjY2Vzc1Rva2VuUmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL1VzZXISGAoLZGVzY3JpcHRpb24YAiABKAlCA+BBARIcCg9leHBpcmVzX2luX2RheXMYAyABKAVCA+BBASJ0CiFDcmVhdGVQZXJzb25hbEFjY2Vzc1Rva2VuUmVzcG9uc2USQAoVcGVyc29uYWxfYWNjZXNzX3Rva2VuGAEgASgLMiEubWVtb3MuYXBpLnYxLlBlcnNvbmFsQWNjZXNzVG9rZW4SDQoFdG9rZW4YAiABKAkiWgogRGVsZXRlUGVyc29uYWxBY2Nlc3NUb2tlblJlcXVlc3QSNgoEbmFtZRgBIAEoCUIo4EEC+kEiCiBtZW1vcy5hcGkudjEvUGVyc29uYWxBY2Nlc3NUb2tlbiLoAQoLVXNlcldlYmhvb2sSDAoEbmFtZRgBIAEoCRILCgN1cmwYAiABKAkSFAoMZGlzcGxheV9uYW1lGAMgASgJEjQKC2NyZWF0ZV90aW1lGAQgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEDEjQKC3VwZGF0ZV90aW1lGAUgASgLMhouZ29vZ2xlLnByb3RvYnVmLlRpbWVzdGFtcEID4EEDEhsKDnNpZ25pbmdfc2VjcmV0GAYgASgJQgPgQQQSHwoSc2lnbmluZ19zZWNyZXRfc2V0GAcgASgIQgPgQQMiLgoXTGlzdFVzZXJXZWJob29rc1JlcXVlc3QSEwoGcGFyZW50GAEgASgJQgPgQQIiRwoYTGlzdFVzZXJXZWJob29rc1Jlc3BvbnNlEisKCHdlYmhvb2tzGAEgAygLMhkubWVtb3MuYXBpLnYxLlVzZXJXZWJob29rImAKGENyZWF0ZVVzZXJXZWJob29rUmVxdWVzdBITCgZwYXJlbnQYASABKAlCA+BBAhIvCgd3ZWJob29rGAIgASgLMhkubWVtb3MuYXBpLnYxLlVzZXJXZWJob29rQgPgQQIifAoYVXBkYXRlVXNlcldlYmhvb2tSZXF1ZXN0Ei8KB3dlYmhvb2sYASABKAsyGS5tZW1vcy5hcGkudjEuVXNlcldlYmhvb2tCA+BBAhIvCgt1cGRhdGVfbWFzaxgCIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE1hc2siLQoYRGVsZXRlVXNlcldlYmhvb2tSZXF1ZXN0EhEKBG5hbWUYASABKAlCA+BBAiI3CiJHZXRVc2VyV2ViaG9va1NpZ25pbmdTZWNyZXRSZXF1ZXN0EhEKBG5hbWUYASABKAlCA+BBAiI9CiNHZXRVc2VyV2ViaG9va1NpZ25pbmdTZWNyZXRSZXNwb25zZRIWCg5zaWduaW5nX3NlY3JldBgBIAEoCSKiBwoQVXNlck5vdGlmaWNhdGlvbhIUCgRuYW1lGAEgASgJQgbgQQPgQQgSKQoGc2VuZGVyGAIgASgJQhngQQP6QRMKEW1lbW9zLmFwaS52MS9Vc2VyEiwKC3NlbmRlcl91c2VyGAggASgLMhIubWVtb3MuYXBpLnYxLlVzZXJCA+BBAxI6CgZzdGF0dXMYAyABKA4yJS5tZW1vcy5hcGkudjEuVXNlck5vdGlmaWNhdGlvbi5TdGF0dXNCA+BBARI0CgtjcmVhdGVfdGltZRgEIAEoCzIaLmdvb2dsZS5wcm90b2J1Zi5UaW1lc3RhbXBCA+BBAxI2CgR0eXBlGAUgASgOMiMubWVtb3MuYXBpLnYxLlVzZXJOb3RpZmljYXRpb24uVHlwZUID4EEDEk4KDG1lbW9fY29tbWVudBgGIAEoCzIxLm1lbW9zLmFwaS52MS5Vc2VyTm90aWZpY2F0aW9uLk1lbW9Db21tZW50UGF5bG9hZEID4EEDSAASTgoMbWVtb19tZW50aW9uGAcgASgLMjEubWVtb3MuYXBpLnYxLlVzZXJOb3RpZmljYXRpb24uTWVtb01lbnRpb25QYXlsb2FkQgPgQQNIABpsChJNZW1vQ29tbWVudFBheWxvYWQSDAoEbWVtbxgBIAEoCRIUCgxyZWxhdGVkX21lbW8YAiABKAkSFAoMbWVtb19zbmlwcGV0GAMgASgJEhwKFHJlbGF0ZWRfbWVtb19zbmlwcGV0GAQgASgJGmwKEk1lbW9NZW50aW9uUGF5bG9hZBIMCgRtZW1vGAEgASgJEhQKDHJlbGF0ZWRfbWVtbxgCIAEoCRIUCgxtZW1vX3NuaXBwZXQYAyABKAkSHAoUcmVsYXRlZF9tZW1vX3NuaXBwZXQYBCABKAkiOgoGU3RhdHVzEhYKElNUQVRVU19VTlNQRUNJRklFRBAAEgoKBlVOUkVBRBABEgwKCEFSQ0hJVkVEEAIiQAoEVHlwZRIUChBUWVBFX1VOU1BFQ0lGSUVEEAASEAoMTUVNT19DT01NRU5UEAESEAoMTUVNT19NRU5USU9OEAI6cOpBbQodbWVtb3MuYXBpLnYxL1VzZXJOb3RpZmljYXRpb24SKXVzZXJzL3t1c2VyfS9ub3RpZmljYXRpb25zL3tub3RpZmljYXRpb259GgRuYW1lKg1ub3RpZmljYXRpb25zMgxub3RpZmljYXRpb25CCQoHcGF5bG9hZCKPAQocTGlzdFVzZXJOb3RpZmljYXRpb25zUmVxdWVzdBIpCgZwYXJlbnQYASABKAlCGeBBAvpBEwoRbWVtb3MuYXBpLnYxL1VzZXISFgoJcGFnZV9zaXplGAIgASgFQgPgQQESFwoKcGFnZV90b2tlbhgDIAEoCUID4EEBEhMKBmZpbHRlchgEIAEoCUID4EEBIm8KHUxpc3RVc2VyTm90aWZpY2F0aW9uc1Jlc3BvbnNlEjUKDW5vdGlmaWNhdGlvbnMYASADKAsyHi5tZW1vcy5hcGkudjEuVXNlck5vdGlmaWNhdGlvbhIXCg9uZXh0X3BhZ2VfdG9rZW4YAiABKAkikAEKHVVwZGF0ZVVzZXJOb3RpZmljYXRpb25SZXF1ZXN0EjkKDG5vdGlmaWNhdGlvbhgBIAEoCzIeLm1lbW9zLmFwaS52MS5Vc2VyTm90aWZpY2F0aW9uQgPgQQISNAoLdXBkYXRlX21hc2sYAiABKAsyGi5nb29nbGUucHJvdG9idWYuRmllbGRNYXNrQgPgQQIiVAodRGVsZXRlVXNlck5vdGlmaWNhdGlvblJlcXVlc3QSMwoEbmFtZRgBIAEoCUIl4EEC+kEfCh1tZW1vcy5hcGkudjEvVXNlck5vdGlmaWNhdGlvbjLKHgoLVXNlclNlcnZpY2USYwoJTGlzdFVzZXJzEh4ubWVtb3MuYXBpLnYxLkxpc3RVc2Vyc1JlcXVlc3QaHy5tZW1vcy5hcGkudjEuTGlzdFVzZXJzUmVzcG9uc2UiFYLT5JMCDxINL2FwaS92MS91c2VycxJ7Cg1CYXRjaEdldFVzZXJzEiIubWVtb3MuYXBpLnYxLkJhdGNoR2V0VXNlcnNSZXF1ZXN0GiMubWVtb3MuYXBpLnYxLkJhdGNoR2V0VXNlcnNSZXNwb25zZSIhgtPkkwIbOgEqIhYvYXBpL3YxL3VzZXJzOmJhdGNoR2V0EmIKB0dldFVzZXISHC5tZW1vcy5hcGkudjEuR2V0VXNlclJlcXVlc3QaEi5tZW1vcy5hcGkudjEuVXNlciIl2kEEbmFtZYLT5JMCGBIWL2FwaS92MS97bmFtZT11c2Vycy8qfRJlCgpDcmVhdGVVc2VyEh8ubWVtb3MuYXBpLnYxLkNyZWF0ZVVzZXJSZXF1ZXN0GhIubWVtb3MuYXBpLnYxLlVzZXIiItpBBHVzZXKC0+STAhU6BHVzZXIiDS9hcGkvdjEvdXNlcnMSfwoKVXBkYXRlVXNlchIfLm1lbW9zLmFwaS52MS5VcGRhdGVVc2VyUmVxdWVzdBoSLm1lbW9zLmFwaS52MS5Vc2VyIjzaQRB1c2VyLHVwZGF0ZV9tYXNrgtPkkwIjOgR1c2VyMhsvYXBpL3YxL3t1c2VyLm5hbWU9dXNlcnMvKn0SbAoKRGVsZXRlVXNlchIfLm1lbW9zLmFwaS52MS5EZWxldGVVc2VyUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIl2kEEbmFtZYLT5JMCGCoWL2FwaS92MS97bmFtZT11c2Vycy8qfRJ+ChBMaXN0QWxsVXNlclN0YXRzEiUubWVtb3MuYXBpLnYxLkxpc3RBbGxVc2VyU3RhdHNSZXF1ZXN0GiYubWVtb3MuYXBpLnYxLkxpc3RBbGxVc2VyU3RhdHNSZXNwb25zZSIbgtPkkwIVEhMvYXBpL3YxL3VzZXJzOnN0YXRzEnoKDEdldFVzZXJTdGF0cxIhLm1lbW9zLmFwaS52MS5HZXRVc2VyU3RhdHNSZXF1ZXN0GhcubWVtb3MuYXBpLnYxLlVzZXJTdGF0cyIu2kEEbmFtZYLT5JMCIRIfL2FwaS92MS97bmFtZT11c2Vycy8qfTpnZXRTdGF0cxKCAQoOR2V0VXNlclNldHRpbmcSIy5tZW1vcy5hcGkudjEuR2V0VXNlclNldHRpbmdSZXF1ZXN0GhkubWVtb3MuYXBpLnYxLlVzZXJTZXR0aW5nIjDaQQRuYW1lgtPkkwIjEiEvYXBpL3YxL3tuYW1lPXVzZXJzLyovc2V0dGluZ3MvKn0SqAEKEVVwZGF0ZVVzZXJTZXR0aW5nEiYubWVtb3MuYXBpLnYxLlVwZGF0ZVVzZXJTZXR0aW5nUmVxdWVzdBoZLm1lbW9zLmFwaS52MS5Vc2VyU2V0dGluZyJQ2kETc2V0dGluZyx1cGRhdGVfbWFza4LT5JMCNDoHc2V0dGluZzIpL2FwaS92MS97c2V0dGluZy5uYW1lPXVzZXJzLyovc2V0dGluZ3MvKn0SlQEKEExpc3RVc2VyU2V0dGluZ3MSJS5tZW1vcy5hcGkudjEuTGlzdFVzZXJTZXR0aW5nc1JlcXVlc3QaJi5tZW1vcy5hcGkudjEuTGlzdFVzZXJTZXR0aW5nc1Jlc3BvbnNlIjLaQQZwYXJlbnSC0+STAiMSIS9hcGkvdjEve3BhcmVudD11c2Vycy8qfS9zZXR0aW5ncxKpAQoUTGlzdExpbmtlZElkZW50aXRpZXMSKS5tZW1vcy5hcGkudjEuTGlzdExpbmtlZElkZW50aXRpZXNSZXF1ZXN0GioubWVtb3MuYXBpLnYxLkxpc3RMaW5rZWRJZGVudGl0aWVzUmVzcG9uc2UiOtpBBnBhcmVudILT5JMCKxIpL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L2xpbmtlZElkZW50aXRpZXMSpwEKFENyZWF0ZUxpbmtlZElkZW50aXR5EikubWVtb3MuYXBpLnYxLkNyZWF0ZUxpbmtlZElkZW50aXR5UmVxdWVzdBocLm1lbW9zLmFwaS52MS5MaW5rZWRJZGVudGl0eSJG2kEPcGFyZW50LGlkcF9uYW1lgtPkkwIuOgEqIikvYXBpL3YxL3twYXJlbnQ9dXNlcnMvKn0vbGlua2VkSWRlbnRpdGllcxKTAQoRR2V0TGlua2VkSWRlbnRpdHkSJi5tZW1vcy5hcGkudjEuR2V0TGlua2VkSWRlbnRpdHlSZXF1ZXN0GhwubWVtb3MuYXBpLnYxLkxpbmtlZElkZW50aXR5IjjaQQRuYW1lgtPkkwIrEikvYXBpL3YxL3tuYW1lPXVzZXJzLyovbGlua2VkSWRlbnRpdGllcy8qfRKTAQoURGVsZXRlTGlua2VkSWRlbnRpdHkSKS5tZW1vcy5hcGkudjEuRGVsZXRlTGlua2VkSWRlbnRpdHlSZXF1ZXN0GhYuZ29vZ2xlLnByb3RvYnVmLkVtcHR5IjjaQQRuYW1lgtPkkwIrKikvYXBpL3YxL3tuYW1lPXVzZXJzLyovbGlua2VkSWRlbnRpdGllcy8qfRK5AQoYTGlzdFBlcnNvbmFsQWNjZXNzVG9rZW5zEi0ubWVtb3MuYXBpLnYxLkxpc3RQZXJzb25hbEFjY2Vzc1Rva2Vuc1JlcXVlc3QaLi5tZW1vcy5hcGkudjEuTGlzdFBlcnNvbmFsQWNjZXNzVG9rZW5zUmVzcG9uc2UiPtpBBnBhcmVudILT5JMCLxItL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L3BlcnNvbmFsQWNjZXNzVG9rZW5zErYBChlDcmVhdGVQZXJzb25hbEFjY2Vzc1Rva2VuEi4ubWVtb3MuYXBpLnYxLkNyZWF0ZVBlcnNvbmFsQWNjZXNzVG9rZW5SZXF1ZXN0Gi8ubWVtb3MuYXBpLnYxLkNyZWF0ZVBlcnNvbmFsQWNjZXNzVG9rZW5SZXNwb25zZSI4gtPkkwIyOgEqIi0vYXBpL3YxL3twYXJlbnQ9dXNlcnMvKn0vcGVyc29uYWxBY2Nlc3NUb2tlbnMSoQEKGURlbGV0ZVBlcnNvbmFsQWNjZXNzVG9rZW4SLi5tZW1vcy5hcGkudjEuRGVsZXRlUGVyc29uYWxBY2Nlc3NUb2tlblJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiPNpBBG5hbWWC0+STAi8qLS9hcGkvdjEve25hbWU9dXNlcnMvKi9wZXJzb25hbEFjY2Vzc1Rva2Vucy8qfRKVAQoQTGlzdFVzZXJXZWJob29rcxIlLm1lbW9zLmFwaS52MS5MaXN0VXNlcldlYmhvb2tzUmVxdWVzdBomLm1lbW9zLmFwaS52MS5MaXN0VXNlcldlYmhvb2tzUmVzcG9uc2UiMtpBBnBhcmVudILT5JMCIxIhL2FwaS92MS97cGFyZW50PXVzZXJzLyp9L3dlYmhvb2tzEpsBChFDcmVhdGVVc2VyV2ViaG9vaxImLm1lbW9zLmFwaS52MS5DcmVhdGVVc2VyV2ViaG9va1JlcXVlc3QaGS5tZW1vcy5hcGkudjEuVXNlcldlYmhvb2siQ9pBDnBhcmVudCx3ZWJob29rgtPkkwIsOgd3ZWJob29rIiEvYXBpL3YxL3twYXJlbnQ9dXNlcnMvKn0vd2ViaG9va3MSqAEKEVVwZGF0ZVVzZXJXZWJob29rEiYubWVtb3MuYXBpLnYxLlVwZGF0ZVVzZXJXZWJob29rUmVxdWVzdBoZLm1lbW9zLmFwaS52MS5Vc2VyV2ViaG9vayJQ2kETd2ViaG9vayx1cGRhdGVfbWFza4LT5JMCNDoHd2ViaG9vazIpL2FwaS92MS97d2ViaG9vay5uYW1lPXVzZXJzLyovd2ViaG9va3MvKn0ShQEKEURlbGV0ZVVzZXJXZWJob29rEiYubWVtb3MuYXBpLnYxLkRlbGV0ZVVzZXJXZWJob29rUmVxdWVzdBoWLmdvb2dsZS5wcm90b2J1Zi5FbXB0eSIw2kEEbmFtZYLT5JMCIyohL2FwaS92MS97bmFtZT11c2Vycy8qL3dlYmhvb2tzLyp9EsUBChtHZXRVc2VyV2ViaG9va1NpZ25pbmdTZWNyZXQSMC5tZW1vcy5hcGkudjEuR2V0VXNlcldlYmhvb2tTaWduaW5nU2VjcmV0UmVxdWVzdBoxLm1lbW9zLmFwaS52MS5HZXRVc2VyV2ViaG9va1NpZ25pbmdTZWNyZXRSZXNwb25zZSJB2kEEbmFtZYLT5JMCNBIyL2FwaS92MS97bmFtZT11c2Vycy8qL3dlYmhvb2tzLyp9OmdldFNpZ25pbmdTZWNyZXQSqQEKFUxpc3RVc2VyTm90aWZpY2F0aW9ucxIqLm1lbW9zLmFwaS52MS5MaXN0VXNlck5vdGlmaWNhdGlvbnNSZXF1ZXN0GisubWVtb3MuYXBpLnYxLkxpc3RVc2VyTm90aWZpY2F0aW9uc1Jlc3BvbnNlIjfaQQZwYXJlbnSC0+STAigSJi9hcGkvdjEve3BhcmVudD11c2Vycy8qfS9ub3RpZmljYXRpb25zEssBChZVcGRhdGVVc2VyTm90aWZpY2F0aW9uEisubWVtb3MuYXBpLnYxLlVwZGF0ZVVzZXJOb3RpZmljYXRpb25SZXF1ZXN0Gh4ubWVtb3MuYXBpLnYxLlVzZXJOb3RpZmljYXRpb24iZNpBGG5vdGlmaWNhdGlvbix1cGRhdGVfbWFza4LT5JMCQzoMbm90aWZpY2F0aW9uMjMvYXBpL3YxL3tub3RpZmljYXRpb24ubmFtZT11c2Vycy8qL25vdGlmaWNhdGlvbnMvKn0SlAEKFkRlbGV0ZVVzZXJOb3RpZmljYXRpb24SKy5tZW1vcy5hcGkudjEuRGVsZXRlVXNlck5vdGlmaWNhdGlvblJlcXVlc3QaFi5nb29nbGUucHJvdG9idWYuRW1wdHkiNdpBBG5hbWWC0+STAigqJi9hcGkvdjEve25hbWU9dXNlcnMvKi9ub3RpZmljYXRpb25zLyp9QqgBChBjb20ubWVtb3MuYXBpLnYxQhBVc2VyU2VydmljZVByb3RvUAFaMGdpdGh1Yi5jb20vdXNlbWVtb3MvbWVtb3MvcHJvdG8vZ2VuL2FwaS92MTthcGl2MaICA01BWKoCDE1lbW9zLkFwaS5WMcoCDE1lbW9zXEFwaVxWMeICGE1lbW9zXEFwaVxWMVxHUEJNZXRhZGF0YeoCDk1lbW9zOjpBcGk6OlYxYgZwcm90bzM", [file_api_v1_common, file_google_api_annotations, file_google_api_client, file_google_api_field_behavior, file_google_api_resource, file_google_protobuf_empty, file_google_protobuf_field_mask, file_google_protobuf_timestamp, file_google_type_color]); /** * @generated from message memos.api.v1.User @@ -209,13 +209,6 @@ export type ListUsersResponse = Message<"memos.api.v1.ListUsersResponse"> & { * @generated from field: string next_page_token = 2; */ nextPageToken: string; - - /** - * The total count of users (may be approximate). - * - * @generated from field: int32 total_size = 3; - */ - totalSize: number; }; /** @@ -856,13 +849,6 @@ export type ListUserSettingsResponse = Message<"memos.api.v1.ListUserSettingsRes * @generated from field: string next_page_token = 2; */ nextPageToken: string; - - /** - * The total count of settings (may be approximate). - * - * @generated from field: int32 total_size = 3; - */ - totalSize: number; }; /** @@ -1139,13 +1125,6 @@ export type ListPersonalAccessTokensResponse = Message<"memos.api.v1.ListPersona * @generated from field: string next_page_token = 2; */ nextPageToken: string; - - /** - * The total count of personal access tokens. - * - * @generated from field: int32 total_size = 3; - */ - totalSize: number; }; /**