From deaef1133ea0db40b16de6738b4ad6933dd94a3b Mon Sep 17 00:00:00 2001 From: Gorilla Gigabytes Date: Thu, 3 Sep 2026 06:32:23 +0530 Subject: [PATCH] reoccuring event and last date to RSVP --- .../gateway_event/pb/gw_event.pb.go | 1979 +++++++++-------- .../gateway_event/pb/gw_event.proto | 18 + context.Md | 5 + docs/context.md | 194 ++ .../internal/database/attendees.go | 175 +- .../internal/database/events.go | 199 +- .../internal/database/recurrence_text_test.go | 21 + .../internal/database/recurring.go | 159 +- .../internal/database/rsvp_series.go | 204 ++ .../internal/database/rsvp_series_test.go | 41 + .../internal/database/rsvp_window.go | 89 + .../internal/database/rsvp_window_test.go | 50 + .../internal/database/series_collapse_test.go | 63 + .../internal/database/tickets_coupons.go | 31 +- .../internal/database/tickets_coupons_test.go | 21 + .../internal/services/service.go | 48 +- .../internal/events/client.go | 6 +- .../internal/events/handler.go | 42 +- .../internal/events/models.go | 35 +- schema/000015_event_series_cover.down.sql | 1 + schema/000015_event_series_cover.up.sql | 3 + .../000016_event_series_rsvp_close.down.sql | 1 + schema/000016_event_series_rsvp_close.up.sql | 4 + schema/000017_event_list_indexes.down.sql | 2 + schema/000017_event_list_indexes.up.sql | 9 + 25 files changed, 2292 insertions(+), 1108 deletions(-) create mode 100644 context.Md create mode 100644 docs/context.md create mode 100644 microservices/the_monkeys_events/internal/database/recurrence_text_test.go create mode 100644 microservices/the_monkeys_events/internal/database/rsvp_series.go create mode 100644 microservices/the_monkeys_events/internal/database/rsvp_series_test.go create mode 100644 microservices/the_monkeys_events/internal/database/rsvp_window.go create mode 100644 microservices/the_monkeys_events/internal/database/rsvp_window_test.go create mode 100644 microservices/the_monkeys_events/internal/database/series_collapse_test.go create mode 100644 microservices/the_monkeys_events/internal/database/tickets_coupons_test.go create mode 100644 schema/000015_event_series_cover.down.sql create mode 100644 schema/000015_event_series_cover.up.sql create mode 100644 schema/000016_event_series_rsvp_close.down.sql create mode 100644 schema/000016_event_series_rsvp_close.up.sql create mode 100644 schema/000017_event_list_indexes.down.sql create mode 100644 schema/000017_event_list_indexes.up.sql diff --git a/apis/serviceconn/gateway_event/pb/gw_event.pb.go b/apis/serviceconn/gateway_event/pb/gw_event.pb.go index d310a872..d5e64824 100644 --- a/apis/serviceconn/gateway_event/pb/gw_event.pb.go +++ b/apis/serviceconn/gateway_event/pb/gw_event.pb.go @@ -10,6 +10,7 @@ import ( protoreflect "google.golang.org/protobuf/reflect/protoreflect" protoimpl "google.golang.org/protobuf/runtime/protoimpl" timestamppb "google.golang.org/protobuf/types/known/timestamppb" + wrapperspb "google.golang.org/protobuf/types/known/wrapperspb" reflect "reflect" sync "sync" ) @@ -189,6 +190,15 @@ type Event struct { // can restore its selected/highlighted state on load. Empty for anonymous // callers or when the viewer has not reacted. ViewerReactions []string `protobuf:"bytes,37,rep,name=viewer_reactions,json=viewerReactions,proto3" json:"viewer_reactions,omitempty"` + // Human label derived from event_series.recurrence_rule (e.g. "Every week on Sat"). + // Empty when the event is a one-off. Additive; clients that ignore it stay valid. + RecurrenceText string `protobuf:"bytes,38,opt,name=recurrence_text,json=recurrenceText,proto3" json:"recurrence_text,omitempty"` + // Next 1–3 occurrence starts on a collapsed discovery/profile card + // (representative date plus up to two more). Empty for one-offs and uncollapsed lists. + UpcomingDates []*timestamppb.Timestamp `protobuf:"bytes,39,rep,name=upcoming_dates,json=upcomingDates,proto3" json:"upcoming_dates,omitempty"` + // Series offset in hours before each occurrence start (0 = no extra close). + // Empty/zero on one-offs; hosts pick Off / 12h / 1d / 3d / 1w. + RsvpCloseHoursBefore int32 `protobuf:"varint,40,opt,name=rsvp_close_hours_before,json=rsvpCloseHoursBefore,proto3" json:"rsvp_close_hours_before,omitempty"` } func (x *Event) Reset() { @@ -482,6 +492,27 @@ func (x *Event) GetViewerReactions() []string { return nil } +func (x *Event) GetRecurrenceText() string { + if x != nil { + return x.RecurrenceText + } + return "" +} + +func (x *Event) GetUpcomingDates() []*timestamppb.Timestamp { + if x != nil { + return x.UpcomingDates + } + return nil +} + +func (x *Event) GetRsvpCloseHoursBefore() int32 { + if x != nil { + return x.RsvpCloseHoursBefore + } + return 0 +} + type ReactionCount struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -1620,6 +1651,9 @@ type UpdateEventReq struct { VenueId int64 `protobuf:"varint,20,opt,name=venue_id,json=venueId,proto3" json:"venue_id,omitempty"` HowToFindUs string `protobuf:"bytes,21,opt,name=how_to_find_us,json=howToFindUs,proto3" json:"how_to_find_us,omitempty"` Questions []*EventQuestion `protobuf:"bytes,22,rep,name=questions,proto3" json:"questions,omitempty"` + // Present on series edits: 0 = Off (clear per-occurrence close). Omitted + // on one-off updates so an empty JSON field does not wipe a series window. + RsvpCloseHoursBefore *wrapperspb.Int32Value `protobuf:"bytes,23,opt,name=rsvp_close_hours_before,json=rsvpCloseHoursBefore,proto3" json:"rsvp_close_hours_before,omitempty"` } func (x *UpdateEventReq) Reset() { @@ -1808,6 +1842,13 @@ func (x *UpdateEventReq) GetQuestions() []*EventQuestion { return nil } +func (x *UpdateEventReq) GetRsvpCloseHoursBefore() *wrapperspb.Int32Value { + if x != nil { + return x.RsvpCloseHoursBefore + } + return nil +} + // EventActionReq drives the slug-scoped verbs: delete, publish and cancel. type EventActionReq struct { state protoimpl.MessageState @@ -3031,6 +3072,9 @@ type RSVPReq struct { // The service only rejects empty answers when required questions exist. GuestCount int32 `protobuf:"varint,6,opt,name=guest_count,json=guestCount,proto3" json:"guest_count,omitempty"` Answers []*RSVPAnswer `protobuf:"bytes,7,rep,name=answers,proto3" json:"answers,omitempty"` + // this (default) | series. series RSVPs every open future occurrence + // in the same series; paid tiers are refused for series scope. + Scope string `protobuf:"bytes,8,opt,name=scope,proto3" json:"scope,omitempty"` } func (x *RSVPReq) Reset() { @@ -3114,6 +3158,13 @@ func (x *RSVPReq) GetAnswers() []*RSVPAnswer { return nil } +func (x *RSVPReq) GetScope() string { + if x != nil { + return x.Scope + } + return "" +} + type RSVPResp struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4527,6 +4578,8 @@ type Recurrence struct { ByDay []string `protobuf:"bytes,3,rep,name=by_day,json=byDay,proto3" json:"by_day,omitempty"` // MO,TU,... for weekly Count int32 `protobuf:"varint,4,opt,name=count,proto3" json:"count,omitempty"` // stop after N occurrences; 0 = unused Until *timestamppb.Timestamp `protobuf:"bytes,5,opt,name=until,proto3" json:"until,omitempty"` + // Hours before each occurrence start to close RSVP. 0 = no extra close. + RsvpCloseHoursBefore int32 `protobuf:"varint,6,opt,name=rsvp_close_hours_before,json=rsvpCloseHoursBefore,proto3" json:"rsvp_close_hours_before,omitempty"` } func (x *Recurrence) Reset() { @@ -4596,6 +4649,13 @@ func (x *Recurrence) GetUntil() *timestamppb.Timestamp { return nil } +func (x *Recurrence) GetRsvpCloseHoursBefore() int32 { + if x != nil { + return x.RsvpCloseHoursBefore + } + return 0 +} + type CreateSeriesReq struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4779,7 +4839,9 @@ var file_apis_serviceconn_gateway_event_pb_gw_event_proto_rawDesc = []byte{ 0x2f, 0x70, 0x62, 0x2f, 0x67, 0x77, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x12, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x1a, 0x1f, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, 0x74, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa0, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x1a, 0x1e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2f, + 0x77, 0x72, 0x61, 0x70, 0x70, 0x65, 0x72, 0x73, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x22, 0xa0, 0x02, 0x0a, 0x0a, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x69, 0x70, 0x5f, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x69, 0x70, 0x41, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x12, 0x16, 0x0a, 0x06, @@ -4798,7 +4860,7 @@ var file_apis_serviceconn_gateway_event_pb_gw_event_proto_rawDesc = []byte{ 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x6f, 0x73, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x02, 0x6f, 0x73, 0x12, 0x18, 0x0a, 0x07, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, 0x72, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x62, 0x72, 0x6f, 0x77, 0x73, 0x65, - 0x72, 0x22, 0xd7, 0x0b, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, + 0x72, 0x22, 0xfa, 0x0c, 0x0a, 0x05, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, @@ -4891,848 +4953,868 @@ var file_apis_serviceconn_gateway_event_pb_gw_event_proto_rawDesc = []byte{ 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x29, 0x0a, 0x10, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x25, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x76, 0x69, 0x65, 0x77, - 0x65, 0x72, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0x4a, 0x0a, 0x0d, 0x52, - 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x23, 0x0a, 0x0d, - 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xf2, 0x01, 0x0a, 0x0a, 0x54, 0x69, 0x63, 0x6b, - 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, - 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, - 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1a, 0x0a, - 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, - 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x61, 0x70, - 0x61, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, - 0x64, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, - 0x72, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x62, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x22, 0xb4, 0x01, 0x0a, - 0x0f, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, - 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, - 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, 0x1a, 0x0a, 0x08, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, - 0x63, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, - 0x63, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, - 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x22, 0xa2, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x12, 0x0e, - 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, - 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, - 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x29, 0x0a, - 0x10, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, - 0x75, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x55, - 0x73, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x75, - 0x73, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x75, 0x72, 0x72, 0x65, - 0x6e, 0x74, 0x55, 0x73, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, - 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x72, 0x6f, - 0x6d, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x74, 0x6f, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, - 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x07, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x54, 0x6f, 0x22, 0xa0, 0x04, 0x0a, 0x08, 0x41, 0x74, 0x74, - 0x65, 0x6e, 0x64, 0x65, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, - 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x1d, 0x0a, 0x0a, - 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x24, 0x0a, 0x0e, 0x74, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x65, 0x72, - 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x74, 0x69, 0x63, - 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, - 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x5f, 0x75, 0x73, 0x65, - 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x55, - 0x73, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x69, - 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, - 0x49, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, - 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, 0x12, 0x1f, 0x0a, - 0x0b, 0x67, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x0d, 0x20, 0x01, - 0x28, 0x05, 0x52, 0x0a, 0x67, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2b, - 0x0a, 0x11, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, - 0x74, 0x75, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x61, 0x74, 0x74, 0x65, 0x6e, - 0x64, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3e, 0x0a, 0x0d, 0x63, - 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x61, 0x74, 0x18, 0x0f, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, - 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x41, 0x74, 0x22, 0xd3, 0x01, 0x0a, 0x0c, - 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, - 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, - 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, - 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x65, - 0x6e, 0x74, 0x54, 0x65, 0x78, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, - 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, - 0x74, 0x22, 0x96, 0x02, 0x0a, 0x05, 0x56, 0x65, 0x6e, 0x75, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, - 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, - 0x23, 0x0a, 0x0d, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x31, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4c, - 0x69, 0x6e, 0x65, 0x31, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, - 0x6c, 0x69, 0x6e, 0x65, 0x32, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x64, 0x64, - 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x6e, 0x65, 0x32, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x69, 0x74, - 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x74, 0x79, 0x12, 0x16, 0x0a, - 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, - 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x72, 0x79, 0x12, - 0x1f, 0x0a, 0x0b, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x43, 0x6f, 0x64, 0x65, - 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x09, 0x20, 0x01, - 0x28, 0x01, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, - 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x01, 0x52, - 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x22, 0xe2, 0x01, 0x0a, 0x0d, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x0e, 0x0a, 0x02, - 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x78, 0x74, 0x12, 0x23, 0x0a, 0x0d, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0c, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, - 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x18, 0x05, 0x20, - 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, 0x12, 0x21, 0x0a, - 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x06, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4a, 0x73, 0x6f, 0x6e, - 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, - 0x4e, 0x0a, 0x0a, 0x52, 0x53, 0x56, 0x50, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x12, 0x1f, 0x0a, - 0x0b, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x0a, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x1f, - 0x0a, 0x0b, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x4a, 0x73, 0x6f, 0x6e, 0x22, - 0xd2, 0x07, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, - 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, - 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, - 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x65, 0x72, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x27, 0x0a, 0x0f, 0x72, + 0x65, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x26, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x72, 0x65, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x65, + 0x54, 0x65, 0x78, 0x74, 0x12, 0x41, 0x0a, 0x0e, 0x75, 0x70, 0x63, 0x6f, 0x6d, 0x69, 0x6e, 0x67, + 0x5f, 0x64, 0x61, 0x74, 0x65, 0x73, 0x18, 0x27, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, + 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0d, 0x75, 0x70, 0x63, 0x6f, 0x6d, 0x69, + 0x6e, 0x67, 0x44, 0x61, 0x74, 0x65, 0x73, 0x12, 0x35, 0x0a, 0x17, 0x72, 0x73, 0x76, 0x70, 0x5f, + 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x73, 0x5f, 0x62, 0x65, 0x66, 0x6f, + 0x72, 0x65, 0x18, 0x28, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x72, 0x73, 0x76, 0x70, 0x43, 0x6c, + 0x6f, 0x73, 0x65, 0x48, 0x6f, 0x75, 0x72, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x22, 0x4a, + 0x0a, 0x0d, 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, + 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xf2, 0x01, 0x0a, 0x0a, 0x54, + 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, + 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, + 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, + 0x69, 0x63, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, + 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1a, 0x0a, 0x08, + 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, + 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, + 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x08, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, + 0x72, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x12, 0x16, 0x0a, 0x06, 0x62, 0x6f, 0x6f, 0x6b, 0x65, + 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x62, 0x6f, 0x6f, 0x6b, 0x65, 0x64, 0x22, + 0xb4, 0x01, 0x0a, 0x0f, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, 0x6e, + 0x70, 0x75, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x70, 0x72, 0x69, + 0x63, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x52, 0x05, 0x70, 0x72, 0x69, 0x63, 0x65, 0x12, + 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x63, + 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, + 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, + 0x6f, 0x72, 0x64, 0x65, 0x72, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, + 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, 0x22, 0xa2, 0x02, 0x0a, 0x06, 0x43, 0x6f, 0x75, 0x70, 0x6f, + 0x6e, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, + 0x64, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, + 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, + 0x12, 0x29, 0x0a, 0x10, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x72, + 0x63, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6d, + 0x61, 0x78, 0x5f, 0x75, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6d, + 0x61, 0x78, 0x55, 0x73, 0x65, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, + 0x74, 0x5f, 0x75, 0x73, 0x65, 0x73, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0b, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x74, 0x55, 0x73, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x76, 0x61, 0x6c, + 0x69, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, - 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, + 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x74, 0x6f, + 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, - 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, - 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x69, - 0x6e, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, - 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, - 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, - 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, - 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x6d, 0x61, - 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, - 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6f, 0x5f, 0x68, 0x6f, 0x73, - 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, - 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, - 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x0c, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x65, - 0x72, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, - 0x6e, 0x70, 0x75, 0x74, 0x52, 0x0b, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, - 0x73, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, - 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x72, 0x6f, - 0x75, 0x70, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, - 0x72, 0x6f, 0x75, 0x70, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, - 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x69, - 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0d, 0x72, 0x73, 0x76, 0x70, - 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x72, 0x73, 0x76, - 0x70, 0x4f, 0x70, 0x65, 0x6e, 0x73, 0x41, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x72, 0x73, 0x76, 0x70, - 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, + 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x54, 0x6f, 0x22, 0xa0, 0x04, 0x0a, 0x08, + 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, + 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, + 0x1d, 0x0a, 0x0a, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x75, 0x73, 0x65, 0x72, 0x45, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x24, + 0x0a, 0x0e, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, + 0x65, 0x72, 0x49, 0x64, 0x12, 0x28, 0x0a, 0x10, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, + 0x69, 0x65, 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, + 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x16, + 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x5f, + 0x75, 0x73, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x75, 0x70, + 0x6f, 0x6e, 0x55, 0x73, 0x65, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, + 0x64, 0x5f, 0x69, 0x6e, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x63, 0x68, 0x65, 0x63, + 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, + 0x5f, 0x61, 0x74, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, 0x65, 0x64, 0x41, 0x74, + 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, + 0x0d, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x67, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x5f, + 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x61, 0x74, + 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x3e, + 0x0a, 0x0d, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x5f, 0x61, 0x74, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, + 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, + 0x70, 0x52, 0x0b, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x41, 0x74, 0x22, 0xd3, + 0x01, 0x0a, 0x0c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, + 0x65, 0x72, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, + 0x74, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x63, 0x6f, + 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x65, 0x78, 0x74, 0x12, 0x39, 0x0a, 0x0a, 0x63, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, + 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x63, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x64, 0x41, 0x74, 0x22, 0x96, 0x02, 0x0a, 0x05, 0x56, 0x65, 0x6e, 0x75, 0x65, 0x12, 0x0e, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x5f, 0x6c, 0x69, + 0x6e, 0x65, 0x31, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x4c, 0x69, 0x6e, 0x65, 0x31, 0x12, 0x23, 0x0a, 0x0d, 0x61, 0x64, 0x64, 0x72, 0x65, + 0x73, 0x73, 0x5f, 0x6c, 0x69, 0x6e, 0x65, 0x32, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, + 0x61, 0x64, 0x64, 0x72, 0x65, 0x73, 0x73, 0x4c, 0x69, 0x6e, 0x65, 0x32, 0x12, 0x12, 0x0a, 0x04, + 0x63, 0x69, 0x74, 0x79, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x69, 0x74, 0x79, + 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x72, 0x65, 0x67, 0x69, 0x6f, 0x6e, 0x12, 0x18, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x6e, + 0x74, 0x72, 0x79, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x72, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x5f, 0x63, 0x6f, 0x64, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x70, 0x6f, 0x73, 0x74, 0x61, 0x6c, 0x43, + 0x6f, 0x64, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x01, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, + 0x1c, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x01, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x22, 0xe2, 0x01, + 0x0a, 0x0d, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x02, 0x69, 0x64, 0x12, + 0x19, 0x0a, 0x08, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x07, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0c, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x54, 0x65, 0x78, 0x74, 0x12, + 0x23, 0x0a, 0x0d, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x08, 0x72, 0x65, 0x71, 0x75, 0x69, 0x72, 0x65, 0x64, + 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6f, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x4a, + 0x73, 0x6f, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, + 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x05, 0x52, 0x09, 0x73, 0x6f, 0x72, 0x74, 0x4f, 0x72, 0x64, + 0x65, 0x72, 0x22, 0x4e, 0x0a, 0x0a, 0x52, 0x53, 0x56, 0x50, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72, + 0x12, 0x1f, 0x0a, 0x0b, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x49, + 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x5f, 0x6a, 0x73, 0x6f, 0x6e, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x4a, 0x73, + 0x6f, 0x6e, 0x22, 0xd2, 0x07, 0x0a, 0x0e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x72, 0x73, - 0x76, 0x70, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x73, 0x41, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6c, - 0x6c, 0x6f, 0x77, 0x5f, 0x67, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x14, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x47, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x2d, 0x0a, - 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x67, 0x75, 0x65, 0x73, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, - 0x72, 0x73, 0x76, 0x70, 0x18, 0x15, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x47, - 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x52, 0x73, 0x76, 0x70, 0x12, 0x19, 0x0a, 0x08, - 0x76, 0x65, 0x6e, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, - 0x76, 0x65, 0x6e, 0x75, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0e, 0x68, 0x6f, 0x77, 0x5f, 0x74, - 0x6f, 0x5f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x75, 0x73, 0x18, 0x17, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x68, 0x6f, 0x77, 0x54, 0x6f, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x12, 0x36, 0x0a, 0x09, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x18, 0x20, 0x03, 0x28, 0x0b, 0x32, - 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xdc, 0x06, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, - 0x74, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, - 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, - 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, - 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x08, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6d, - 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x0a, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x1a, - 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, - 0x61, 0x67, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, - 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0e, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1a, + 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, + 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x65, 0x65, + 0x74, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, + 0x63, 0x69, 0x74, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, + 0x63, 0x69, 0x74, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6d, + 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x76, 0x65, 0x72, + 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0c, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x2a, 0x0a, 0x11, 0x63, 0x6f, 0x5f, + 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x18, 0x0d, + 0x20, 0x03, 0x28, 0x09, 0x52, 0x0f, 0x63, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x6e, 0x61, 0x6d, 0x65, 0x73, 0x12, 0x3d, 0x0a, 0x0c, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, + 0x74, 0x69, 0x65, 0x72, 0x73, 0x18, 0x0e, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, + 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x0b, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, + 0x69, 0x65, 0x72, 0x73, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x6e, 0x66, 0x6f, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, + 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x10, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x76, + 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x11, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0d, 0x72, + 0x73, 0x76, 0x70, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x12, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, + 0x72, 0x73, 0x76, 0x70, 0x4f, 0x70, 0x65, 0x6e, 0x73, 0x41, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x72, + 0x73, 0x76, 0x70, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x13, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, + 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, + 0x0c, 0x72, 0x73, 0x76, 0x70, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x73, 0x41, 0x74, 0x12, 0x21, 0x0a, + 0x0c, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x67, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x14, 0x20, + 0x01, 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x47, 0x75, 0x65, 0x73, 0x74, 0x73, + 0x12, 0x2d, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x67, 0x75, 0x65, 0x73, 0x74, 0x73, 0x5f, 0x70, + 0x65, 0x72, 0x5f, 0x72, 0x73, 0x76, 0x70, 0x18, 0x15, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6d, + 0x61, 0x78, 0x47, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x52, 0x73, 0x76, 0x70, 0x12, + 0x19, 0x0a, 0x08, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x16, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x07, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0e, 0x68, 0x6f, + 0x77, 0x5f, 0x74, 0x6f, 0x5f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x75, 0x73, 0x18, 0x17, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0b, 0x68, 0x6f, 0x77, 0x54, 0x6f, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x12, + 0x36, 0x0a, 0x09, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x18, 0x20, 0x03, + 0x28, 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, + 0x76, 0x65, 0x6e, 0x74, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x22, 0xb0, 0x07, 0x0a, 0x0e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, + 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x12, 0x1d, + 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, + 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, + 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, + 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, + 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, + 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, + 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, + 0x6f, 0x6e, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, + 0x6f, 0x6e, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, + 0x65, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, + 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, + 0x0a, 0x0c, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x6e, + 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1f, 0x0a, + 0x0b, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x0c, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, + 0x67, 0x73, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, + 0x6f, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, + 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x69, + 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, + 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0d, 0x72, 0x73, + 0x76, 0x70, 0x5f, 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x72, + 0x73, 0x76, 0x70, 0x4f, 0x70, 0x65, 0x6e, 0x73, 0x41, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x72, 0x73, + 0x76, 0x70, 0x5f, 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x11, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, + 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, + 0x72, 0x73, 0x76, 0x70, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x73, 0x41, 0x74, 0x12, 0x21, 0x0a, 0x0c, + 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x5f, 0x67, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x12, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x47, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, + 0x2d, 0x0a, 0x13, 0x6d, 0x61, 0x78, 0x5f, 0x67, 0x75, 0x65, 0x73, 0x74, 0x73, 0x5f, 0x70, 0x65, + 0x72, 0x5f, 0x72, 0x73, 0x76, 0x70, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6d, 0x61, + 0x78, 0x47, 0x75, 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x52, 0x73, 0x76, 0x70, 0x12, 0x19, + 0x0a, 0x08, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x07, 0x76, 0x65, 0x6e, 0x75, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0e, 0x68, 0x6f, 0x77, + 0x5f, 0x74, 0x6f, 0x5f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x75, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x0b, 0x68, 0x6f, 0x77, 0x54, 0x6f, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x12, 0x36, + 0x0a, 0x09, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, + 0x0b, 0x32, 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x52, 0x0a, 0x17, 0x72, 0x73, 0x76, 0x70, 0x5f, 0x63, + 0x6c, 0x6f, 0x73, 0x65, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x73, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, + 0x65, 0x18, 0x17, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1b, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x49, 0x6e, 0x74, 0x33, 0x32, 0x56, + 0x61, 0x6c, 0x75, 0x65, 0x52, 0x14, 0x72, 0x73, 0x76, 0x70, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x48, + 0x6f, 0x75, 0x72, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x22, 0x7b, 0x0a, 0x0e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, + 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, + 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, + 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, - 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x69, 0x73, - 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x3e, 0x0a, 0x0d, 0x72, 0x73, 0x76, 0x70, 0x5f, - 0x6f, 0x70, 0x65, 0x6e, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, - 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, - 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0b, 0x72, 0x73, 0x76, 0x70, - 0x4f, 0x70, 0x65, 0x6e, 0x73, 0x41, 0x74, 0x12, 0x40, 0x0a, 0x0e, 0x72, 0x73, 0x76, 0x70, 0x5f, - 0x63, 0x6c, 0x6f, 0x73, 0x65, 0x73, 0x5f, 0x61, 0x74, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x0c, 0x72, 0x73, 0x76, - 0x70, 0x43, 0x6c, 0x6f, 0x73, 0x65, 0x73, 0x41, 0x74, 0x12, 0x21, 0x0a, 0x0c, 0x61, 0x6c, 0x6c, - 0x6f, 0x77, 0x5f, 0x67, 0x75, 0x65, 0x73, 0x74, 0x73, 0x18, 0x12, 0x20, 0x01, 0x28, 0x08, 0x52, - 0x0b, 0x61, 0x6c, 0x6c, 0x6f, 0x77, 0x47, 0x75, 0x65, 0x73, 0x74, 0x73, 0x12, 0x2d, 0x0a, 0x13, - 0x6d, 0x61, 0x78, 0x5f, 0x67, 0x75, 0x65, 0x73, 0x74, 0x73, 0x5f, 0x70, 0x65, 0x72, 0x5f, 0x72, - 0x73, 0x76, 0x70, 0x18, 0x13, 0x20, 0x01, 0x28, 0x05, 0x52, 0x10, 0x6d, 0x61, 0x78, 0x47, 0x75, - 0x65, 0x73, 0x74, 0x73, 0x50, 0x65, 0x72, 0x52, 0x73, 0x76, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x76, - 0x65, 0x6e, 0x75, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x14, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x76, - 0x65, 0x6e, 0x75, 0x65, 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0e, 0x68, 0x6f, 0x77, 0x5f, 0x74, 0x6f, - 0x5f, 0x66, 0x69, 0x6e, 0x64, 0x5f, 0x75, 0x73, 0x18, 0x15, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, - 0x68, 0x6f, 0x77, 0x54, 0x6f, 0x46, 0x69, 0x6e, 0x64, 0x55, 0x73, 0x12, 0x36, 0x0a, 0x09, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x16, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x18, + 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x78, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x22, 0x91, 0x01, 0x0a, 0x09, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, + 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2c, 0x0a, 0x12, 0x76, 0x69, 0x65, 0x77, 0x65, + 0x72, 0x5f, 0x72, 0x73, 0x76, 0x70, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x52, 0x73, 0x76, 0x70, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xd4, 0x03, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, + 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, + 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, + 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, + 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, + 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, + 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, + 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, + 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, + 0x75, 0x65, 0x72, 0x79, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, + 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, + 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x73, + 0x6c, 0x75, 0x67, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, + 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1f, 0x0a, 0x0b, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x66, 0x69, 0x6c, + 0x74, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x65, 0x46, + 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x17, 0x0a, 0x07, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x62, 0x79, + 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x6f, 0x72, 0x74, 0x42, 0x79, 0x12, 0x19, + 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x61, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x01, + 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, + 0x72, 0x5f, 0x6c, 0x6e, 0x67, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x75, 0x73, 0x65, + 0x72, 0x4c, 0x6e, 0x67, 0x12, 0x16, 0x0a, 0x06, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x18, 0x10, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x22, 0x66, 0x0a, 0x0e, + 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x28, + 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x51, 0x75, 0x65, 0x73, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x09, 0x71, 0x75, 0x65, 0x73, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0x7b, 0x0a, 0x0e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x22, 0x78, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, - 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, - 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, - 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x91, 0x01, 0x0a, 0x09, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, - 0x67, 0x65, 0x12, 0x26, 0x0a, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x10, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, - 0x65, 0x6e, 0x74, 0x52, 0x05, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x12, 0x2c, 0x0a, 0x12, 0x76, 0x69, 0x65, 0x77, 0x65, 0x72, 0x5f, 0x72, 0x73, 0x76, 0x70, 0x5f, - 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x76, 0x69, - 0x65, 0x77, 0x65, 0x72, 0x52, 0x73, 0x76, 0x70, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0xd4, - 0x03, 0x0a, 0x0d, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, - 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x12, - 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, - 0x67, 0x73, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1a, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, - 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x75, 0x73, 0x65, 0x72, - 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x18, 0x08, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x71, 0x75, 0x65, 0x72, 0x79, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1d, - 0x0a, 0x0a, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x0b, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1f, 0x0a, - 0x0b, 0x64, 0x61, 0x74, 0x65, 0x5f, 0x66, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x18, 0x0c, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x0a, 0x64, 0x61, 0x74, 0x65, 0x46, 0x69, 0x6c, 0x74, 0x65, 0x72, 0x12, 0x17, - 0x0a, 0x07, 0x73, 0x6f, 0x72, 0x74, 0x5f, 0x62, 0x79, 0x18, 0x0d, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x06, 0x73, 0x6f, 0x72, 0x74, 0x42, 0x79, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, - 0x6c, 0x61, 0x74, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4c, - 0x61, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x75, 0x73, 0x65, 0x72, 0x5f, 0x6c, 0x6e, 0x67, 0x18, 0x0f, - 0x20, 0x01, 0x28, 0x01, 0x52, 0x07, 0x75, 0x73, 0x65, 0x72, 0x4c, 0x6e, 0x67, 0x12, 0x16, 0x0a, - 0x06, 0x72, 0x61, 0x64, 0x69, 0x75, 0x73, 0x18, 0x10, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x72, - 0x61, 0x64, 0x69, 0x75, 0x73, 0x22, 0x66, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x28, 0x0a, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, - 0x09, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, - 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, - 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, - 0x63, 0x65, 0x73, 0x73, 0x22, 0xbb, 0x01, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, - 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, - 0x6e, 0x70, 0x75, 0x74, 0x52, 0x04, 0x74, 0x69, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, - 0x66, 0x6f, 0x22, 0xd4, 0x01, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, - 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x69, 0x65, 0x72, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x74, 0x69, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x65, 0x72, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x52, 0x06, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, + 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x14, + 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x22, 0x55, 0x0a, 0x09, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x14, 0x0a, 0x05, 0x65, + 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x12, 0x18, 0x0a, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x73, 0x75, 0x63, 0x63, 0x65, 0x73, 0x73, 0x22, 0xbb, 0x01, 0x0a, 0x13, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, + 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, + 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, + 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, + 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x65, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x04, 0x74, 0x69, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x9e, 0x01, 0x0a, 0x0d, 0x54, 0x69, - 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x17, 0x0a, 0x07, 0x74, 0x69, 0x65, - 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x06, 0x74, 0x69, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, - 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x6b, 0x0a, 0x0e, 0x54, 0x69, - 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x18, 0x0a, 0x07, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x04, 0x74, 0x69, 0x65, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, - 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x04, 0x74, 0x69, 0x65, - 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xd3, 0x02, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, - 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x29, 0x0a, - 0x10, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, - 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0f, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, - 0x75, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x55, - 0x73, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x66, 0x72, 0x6f, - 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, - 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, - 0x61, 0x6d, 0x70, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x35, - 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x74, 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, - 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, - 0x6c, 0x69, 0x64, 0x54, 0x6f, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, - 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xa4, 0x01, - 0x0a, 0x0f, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xd4, 0x01, 0x0a, 0x13, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, - 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x03, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x86, 0x01, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, - 0x70, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, - 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x54, 0x0a, - 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x2b, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, - 0x0b, 0x32, 0x11, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6f, - 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, - 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, - 0x72, 0x6f, 0x72, 0x22, 0xa4, 0x01, 0x0a, 0x11, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, - 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, - 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, - 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x94, 0x01, 0x0a, 0x0a, 0x43, - 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, - 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x06, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x12, 0x14, - 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, - 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x65, 0x64, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, - 0x10, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x22, 0x98, 0x02, 0x0a, 0x07, 0x52, 0x53, 0x56, 0x50, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, - 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, - 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x43, 0x6f, - 0x64, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, - 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x75, - 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, - 0x0a, 0x67, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x61, - 0x6e, 0x73, 0x77, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x52, 0x53, 0x56, 0x50, 0x41, 0x6e, 0x73, - 0x77, 0x65, 0x72, 0x52, 0x07, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x73, 0x22, 0xdf, 0x01, 0x0a, - 0x08, 0x52, 0x53, 0x56, 0x50, 0x52, 0x65, 0x73, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, - 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, - 0x61, 0x67, 0x65, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x70, - 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4f, 0x72, - 0x64, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, - 0x64, 0x75, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x61, 0x6d, 0x6f, 0x75, 0x6e, - 0x74, 0x44, 0x75, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, - 0x12, 0x26, 0x0a, 0x0f, 0x72, 0x61, 0x7a, 0x6f, 0x72, 0x70, 0x61, 0x79, 0x5f, 0x6b, 0x65, 0x79, - 0x5f, 0x69, 0x64, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x61, 0x7a, 0x6f, 0x72, - 0x70, 0x61, 0x79, 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, - 0x72, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x85, - 0x01, 0x0a, 0x0d, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x53, 0x56, 0x50, 0x52, 0x65, 0x71, - 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, - 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x36, - 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x4c, 0x0a, 0x11, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x12, 0x1c, 0x0a, 0x09, 0x73, - 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x61, 0x77, - 0x5f, 0x62, 0x6f, 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x61, 0x77, - 0x42, 0x6f, 0x64, 0x79, 0x22, 0xce, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, - 0x65, 0x6e, 0x64, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, - 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, - 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, - 0x66, 0x66, 0x73, 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, - 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x36, 0x0a, - 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x72, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, - 0x65, 0x6e, 0x64, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x31, 0x0a, 0x09, 0x61, 0x74, - 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, - 0x65, 0x65, 0x52, 0x09, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x73, 0x12, 0x14, 0x0a, - 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x6f, - 0x74, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xf8, 0x01, 0x0a, 0x13, 0x55, 0x70, - 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, - 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, - 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, - 0x1f, 0x0a, 0x0b, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x49, 0x64, - 0x12, 0x2b, 0x0a, 0x11, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, - 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x61, 0x74, 0x74, - 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, - 0x0a, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x09, 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x12, 0x36, 0x0a, 0x0b, - 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, - 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x84, 0x01, 0x0a, 0x0c, 0x53, 0x61, 0x76, 0x65, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, - 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, - 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, - 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xa8, 0x01, 0x0a, 0x0d, - 0x41, 0x64, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, - 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, - 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, - 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x65, 0x78, 0x74, 0x12, 0x36, - 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, - 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x70, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, - 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, - 0x31, 0x0a, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, - 0x32, 0x17, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, - 0x6e, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x5e, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, - 0x6d, 0x69, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, - 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x73, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, - 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x33, 0x0a, 0x08, - 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, - 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, - 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, - 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, - 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa7, 0x01, - 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, + 0x17, 0x0a, 0x07, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, + 0x52, 0x06, 0x74, 0x69, 0x65, 0x72, 0x49, 0x64, 0x12, 0x2e, 0x0a, 0x04, 0x74, 0x69, 0x65, 0x72, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, 0x6e, 0x70, + 0x75, 0x74, 0x52, 0x04, 0x74, 0x69, 0x65, 0x72, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x22, 0x9e, 0x01, 0x0a, 0x0d, 0x54, 0x69, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, - 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, - 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, - 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, - 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, - 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xa5, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x61, 0x63, - 0x74, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, - 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, - 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, - 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, - 0x49, 0x64, 0x12, 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, - 0x79, 0x70, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x61, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x54, 0x79, 0x70, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, - 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, - 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, - 0x9e, 0x01, 0x0a, 0x0e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, + 0x12, 0x17, 0x0a, 0x07, 0x74, 0x69, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x06, 0x74, 0x69, 0x65, 0x72, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x22, 0x6b, 0x0a, 0x0e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, + 0x04, 0x74, 0x69, 0x65, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, + 0x65, 0x72, 0x52, 0x04, 0x74, 0x69, 0x65, 0x72, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, + 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xd3, + 0x02, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, - 0x12, 0x16, 0x0a, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, - 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, - 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x22, 0xaa, 0x01, 0x0a, 0x09, 0x43, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x12, 0x1d, + 0x12, 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x63, 0x6f, 0x64, 0x65, 0x12, 0x29, 0x0a, 0x10, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x5f, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x0f, + 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x50, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, + 0x19, 0x0a, 0x08, 0x6d, 0x61, 0x78, 0x5f, 0x75, 0x73, 0x65, 0x73, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x05, 0x52, 0x07, 0x6d, 0x61, 0x78, 0x55, 0x73, 0x65, 0x73, 0x12, 0x39, 0x0a, 0x0a, 0x76, 0x61, + 0x6c, 0x69, 0x64, 0x5f, 0x66, 0x72, 0x6f, 0x6d, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, + 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, + 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x76, 0x61, 0x6c, 0x69, + 0x64, 0x46, 0x72, 0x6f, 0x6d, 0x12, 0x35, 0x0a, 0x08, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x5f, 0x74, + 0x6f, 0x18, 0x07, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, + 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, + 0x61, 0x6d, 0x70, 0x52, 0x07, 0x76, 0x61, 0x6c, 0x69, 0x64, 0x54, 0x6f, 0x12, 0x36, 0x0a, 0x0b, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x08, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xa4, 0x01, 0x0a, 0x0f, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x41, + 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1b, 0x0a, 0x09, 0x63, 0x6f, 0x75, 0x70, 0x6f, 0x6e, + 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x08, 0x63, 0x6f, 0x75, 0x70, 0x6f, + 0x6e, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, + 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, + 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x86, 0x01, 0x0a, 0x0e, + 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, - 0x63, 0x6f, 0x68, 0x6f, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x68, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, - 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, - 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, - 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x4b, 0x0a, - 0x0b, 0x43, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x3f, 0x0a, 0x0c, 0x43, 0x61, - 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x63, - 0x73, 0x5f, 0x64, 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x69, 0x63, - 0x73, 0x44, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x6b, 0x0a, 0x0c, 0x41, - 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, - 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, - 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0xcf, 0x01, 0x0a, 0x0d, 0x41, 0x75, 0x74, - 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, - 0x52, 0x0b, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x21, 0x0a, - 0x0c, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x0b, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x12, 0x12, 0x0a, 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, - 0x72, 0x6f, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x61, 0x74, 0x74, - 0x65, 0x6e, 0x64, 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x41, - 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x77, 0x6e, 0x73, 0x5f, - 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6f, - 0x77, 0x6e, 0x73, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xec, 0x01, 0x0a, 0x0d, 0x43, - 0x6c, 0x6f, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, - 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, + 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x54, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x70, + 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x2b, 0x0a, 0x07, 0x63, 0x6f, 0x75, 0x70, 0x6f, + 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x07, 0x63, 0x6f, 0x75, + 0x70, 0x6f, 0x6e, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa4, 0x01, 0x0a, 0x11, 0x56, + 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x71, + 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, + 0x12, 0x0a, 0x04, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x63, + 0x6f, 0x64, 0x65, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x69, + 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x69, 0x63, + 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x22, 0x94, 0x01, 0x0a, 0x0a, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x29, 0x0a, 0x06, 0x63, 0x6f, + 0x75, 0x70, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x11, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x06, 0x63, + 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x12, 0x2b, 0x0a, 0x11, 0x64, + 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x65, 0x64, 0x5f, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x10, 0x64, 0x69, 0x73, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x65, 0x64, 0x41, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x22, 0xae, 0x02, 0x0a, 0x07, 0x52, 0x53, 0x56, + 0x50, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, + 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, + 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, + 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x49, 0x64, 0x12, 0x24, 0x0a, 0x0e, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x65, + 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x0c, 0x74, 0x69, 0x63, 0x6b, + 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, 0x75, 0x70, + 0x6f, 0x6e, 0x5f, 0x63, 0x6f, 0x64, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, + 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x43, 0x6f, 0x64, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x12, 0x1f, 0x0a, 0x0b, 0x67, 0x75, 0x65, 0x73, 0x74, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0a, 0x67, 0x75, 0x65, 0x73, 0x74, 0x43, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x2f, 0x0a, 0x07, 0x61, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x73, 0x18, 0x07, 0x20, + 0x03, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, + 0x52, 0x53, 0x56, 0x50, 0x41, 0x6e, 0x73, 0x77, 0x65, 0x72, 0x52, 0x07, 0x61, 0x6e, 0x73, 0x77, + 0x65, 0x72, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x18, 0x08, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x70, 0x65, 0x22, 0xdf, 0x01, 0x0a, 0x08, 0x52, 0x53, + 0x56, 0x50, 0x52, 0x65, 0x73, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, + 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, + 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x28, 0x0a, 0x10, 0x70, 0x61, 0x79, 0x6d, + 0x65, 0x6e, 0x74, 0x5f, 0x6f, 0x72, 0x64, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0e, 0x70, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x4f, 0x72, 0x64, 0x65, 0x72, + 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x64, 0x75, 0x65, + 0x18, 0x04, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x61, 0x6d, 0x6f, 0x75, 0x6e, 0x74, 0x44, 0x75, + 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x08, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x79, 0x12, 0x26, 0x0a, + 0x0f, 0x72, 0x61, 0x7a, 0x6f, 0x72, 0x70, 0x61, 0x79, 0x5f, 0x6b, 0x65, 0x79, 0x5f, 0x69, 0x64, + 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x72, 0x61, 0x7a, 0x6f, 0x72, 0x70, 0x61, 0x79, + 0x4b, 0x65, 0x79, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x07, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x85, 0x01, 0x0a, 0x0d, + 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x53, 0x56, 0x50, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, + 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x22, 0x4c, 0x0a, 0x11, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x65, + 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x12, 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, + 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, + 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x12, 0x19, 0x0a, 0x08, 0x72, 0x61, 0x77, 0x5f, 0x62, 0x6f, + 0x64, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x72, 0x61, 0x77, 0x42, 0x6f, 0x64, + 0x79, 0x22, 0xce, 0x01, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, + 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, + 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, + 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x6f, 0x66, + 0x66, 0x73, 0x65, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, 0x66, 0x66, 0x73, + 0x65, 0x74, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x05, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, + 0x66, 0x6f, 0x22, 0x72, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, + 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x31, 0x0a, 0x09, 0x61, 0x74, 0x74, 0x65, 0x6e, + 0x64, 0x65, 0x65, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x13, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x52, + 0x09, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x73, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x6f, + 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, + 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xf8, 0x01, 0x0a, 0x13, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x12, 0x1d, + 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, + 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, + 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x0a, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x49, 0x64, 0x12, 0x2b, 0x0a, + 0x11, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x5f, 0x73, 0x74, 0x61, 0x74, + 0x75, 0x73, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x10, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, + 0x61, 0x6e, 0x63, 0x65, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x68, + 0x65, 0x63, 0x6b, 0x65, 0x64, 0x5f, 0x69, 0x6e, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, + 0x63, 0x68, 0x65, 0x63, 0x6b, 0x65, 0x64, 0x49, 0x6e, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, + 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x22, 0x84, 0x01, 0x0a, 0x0c, 0x53, 0x61, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, + 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, + 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, + 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, + 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, + 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, + 0x03, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, + 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xa8, 0x01, 0x0a, 0x0d, 0x41, 0x64, 0x64, + 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, + 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, + 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x21, 0x0a, 0x0c, 0x63, 0x6f, 0x6d, 0x6d, + 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x65, 0x78, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, + 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x54, 0x65, 0x78, 0x74, 0x12, 0x36, 0x0a, 0x0b, 0x63, + 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, + 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, + 0x6e, 0x66, 0x6f, 0x22, 0x70, 0x0a, 0x0b, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x31, 0x0a, 0x07, + 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x17, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, + 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x07, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, + 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, + 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x5e, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x14, 0x0a, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, + 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x6c, 0x69, 0x6d, 0x69, 0x74, 0x12, 0x16, 0x0a, + 0x06, 0x6f, 0x66, 0x66, 0x73, 0x65, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x06, 0x6f, + 0x66, 0x66, 0x73, 0x65, 0x74, 0x22, 0x73, 0x0a, 0x10, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x33, 0x0a, 0x08, 0x63, 0x6f, 0x6d, + 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x17, 0x2e, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, + 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x08, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x14, + 0x0a, 0x05, 0x74, 0x6f, 0x74, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x74, + 0x6f, 0x74, 0x61, 0x6c, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x03, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0xa7, 0x01, 0x0a, 0x10, 0x44, + 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, + 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, + 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, + 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, + 0x03, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x36, 0x0a, 0x0b, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, + 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xa5, 0x01, 0x0a, 0x08, 0x52, 0x65, 0x61, 0x63, 0x74, 0x52, 0x65, + 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, - 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, + 0x23, 0x0a, 0x0d, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x74, 0x79, 0x70, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0c, 0x72, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x79, 0x70, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, + 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x9e, 0x01, 0x0a, + 0x0e, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, + 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, + 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x16, 0x0a, + 0x06, 0x72, 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x72, + 0x65, 0x61, 0x73, 0x6f, 0x6e, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, + 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, + 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xaa, 0x01, + 0x0a, 0x09, 0x43, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, + 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x27, 0x0a, 0x0f, 0x63, 0x6f, 0x68, + 0x6f, 0x73, 0x74, 0x5f, 0x75, 0x73, 0x65, 0x72, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0e, 0x63, 0x6f, 0x68, 0x6f, 0x73, 0x74, 0x55, 0x73, 0x65, 0x72, 0x6e, 0x61, + 0x6d, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, + 0x6f, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, + 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, + 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x4b, 0x0a, 0x0b, 0x43, 0x61, + 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x22, 0x3f, 0x0a, 0x0c, 0x43, 0x61, 0x6c, 0x65, 0x6e, + 0x64, 0x61, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x63, 0x73, 0x5f, 0x64, + 0x61, 0x74, 0x61, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x07, 0x69, 0x63, 0x73, 0x44, 0x61, + 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x05, 0x65, 0x72, 0x72, 0x6f, 0x72, 0x22, 0x6b, 0x0a, 0x0c, 0x41, 0x75, 0x74, 0x68, + 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, + 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, + 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x03, 0x52, 0x09, 0x63, 0x6f, 0x6d, 0x6d, + 0x65, 0x6e, 0x74, 0x49, 0x64, 0x22, 0xcf, 0x01, 0x0a, 0x0d, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, + 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x5f, 0x65, 0x78, 0x69, 0x73, 0x74, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x45, 0x78, 0x69, 0x73, 0x74, 0x73, 0x12, 0x21, 0x0a, 0x0c, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x72, 0x6f, 0x6c, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x72, 0x6f, 0x6c, + 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, + 0x18, 0x04, 0x20, 0x03, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, + 0x6f, 0x6e, 0x73, 0x12, 0x1f, 0x0a, 0x0b, 0x69, 0x73, 0x5f, 0x61, 0x74, 0x74, 0x65, 0x6e, 0x64, + 0x65, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x69, 0x73, 0x41, 0x74, 0x74, 0x65, + 0x6e, 0x64, 0x65, 0x65, 0x12, 0x21, 0x0a, 0x0c, 0x6f, 0x77, 0x6e, 0x73, 0x5f, 0x63, 0x6f, 0x6d, + 0x6d, 0x65, 0x6e, 0x74, 0x18, 0x06, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0b, 0x6f, 0x77, 0x6e, 0x73, + 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x22, 0xec, 0x01, 0x0a, 0x0d, 0x43, 0x6c, 0x6f, 0x6e, + 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x6c, 0x75, + 0x67, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x73, 0x6c, 0x75, 0x67, 0x12, 0x1d, 0x0a, + 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x0a, + 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, + 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, + 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, + 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, + 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x36, + 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x05, 0x20, + 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, + 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0xd2, 0x01, 0x0a, 0x0a, 0x52, 0x65, 0x63, 0x75, 0x72, + 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x65, 0x71, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x69, 0x6e, 0x74, + 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x79, 0x5f, 0x64, 0x61, 0x79, 0x18, + 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x62, 0x79, 0x44, 0x61, 0x79, 0x12, 0x14, 0x0a, 0x05, + 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, 0x63, 0x6f, 0x75, + 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x05, 0x20, 0x01, 0x28, + 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, + 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x05, 0x75, + 0x6e, 0x74, 0x69, 0x6c, 0x12, 0x35, 0x0a, 0x17, 0x72, 0x73, 0x76, 0x70, 0x5f, 0x63, 0x6c, 0x6f, + 0x73, 0x65, 0x5f, 0x68, 0x6f, 0x75, 0x72, 0x73, 0x5f, 0x62, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x18, + 0x06, 0x20, 0x01, 0x28, 0x05, 0x52, 0x14, 0x72, 0x73, 0x76, 0x70, 0x43, 0x6c, 0x6f, 0x73, 0x65, + 0x48, 0x6f, 0x75, 0x72, 0x73, 0x42, 0x65, 0x66, 0x6f, 0x72, 0x65, 0x22, 0x92, 0x05, 0x0a, 0x0f, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x12, + 0x1d, 0x0a, 0x0a, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, + 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, + 0x69, 0x74, 0x6c, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, + 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, + 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, + 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, + 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, + 0x65, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, - 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, 0x08, 0x65, 0x6e, - 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, - 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, - 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, - 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, - 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, - 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x22, 0x9b, 0x01, 0x0a, 0x0a, 0x52, 0x65, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x66, 0x72, 0x65, 0x71, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x66, 0x72, 0x65, 0x71, 0x12, 0x1a, 0x0a, 0x08, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, - 0x69, 0x6e, 0x74, 0x65, 0x72, 0x76, 0x61, 0x6c, 0x12, 0x15, 0x0a, 0x06, 0x62, 0x79, 0x5f, 0x64, - 0x61, 0x79, 0x18, 0x03, 0x20, 0x03, 0x28, 0x09, 0x52, 0x05, 0x62, 0x79, 0x44, 0x61, 0x79, 0x12, - 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x04, 0x20, 0x01, 0x28, 0x05, 0x52, 0x05, - 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x30, 0x0a, 0x05, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x18, 0x05, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, - 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, - 0x52, 0x05, 0x75, 0x6e, 0x74, 0x69, 0x6c, 0x22, 0x92, 0x05, 0x0a, 0x0f, 0x43, 0x72, 0x65, 0x61, - 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x12, 0x1d, 0x0a, 0x0a, 0x61, - 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x09, 0x61, 0x63, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, - 0x74, 0x6c, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, - 0x12, 0x20, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, - 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, - 0x6f, 0x6e, 0x12, 0x39, 0x0a, 0x0a, 0x73, 0x74, 0x61, 0x72, 0x74, 0x5f, 0x74, 0x69, 0x6d, 0x65, - 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, - 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 0x52, 0x09, 0x73, 0x74, 0x61, 0x72, 0x74, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x35, 0x0a, - 0x08, 0x65, 0x6e, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0b, 0x32, - 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, - 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x07, 0x65, 0x6e, 0x64, - 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, - 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, 0x7a, 0x6f, 0x6e, 0x65, - 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, 0x79, 0x70, 0x65, 0x12, - 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x21, 0x0a, 0x0c, 0x6d, - 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x09, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0b, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x4c, 0x69, 0x6e, 0x6b, 0x12, 0x1a, - 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x05, - 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1f, 0x0a, 0x0b, 0x63, 0x6f, - 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0a, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x74, - 0x61, 0x67, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, - 0x3d, 0x0a, 0x0c, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x69, 0x65, 0x72, 0x73, 0x18, - 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, - 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x49, 0x6e, 0x70, 0x75, - 0x74, 0x52, 0x0b, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x73, 0x12, 0x1d, - 0x0a, 0x0a, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x73, 0x6c, 0x75, 0x67, 0x18, 0x0e, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x6c, 0x75, 0x67, 0x12, 0x1e, 0x0a, - 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, 0x0f, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x12, 0x35, 0x0a, - 0x0a, 0x72, 0x65, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, 0x10, 0x20, 0x01, 0x28, - 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x52, 0x65, - 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x72, 0x65, 0x63, 0x75, 0x72, 0x72, - 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x5f, 0x69, - 0x6e, 0x66, 0x6f, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, - 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, 0x32, 0xc4, 0x13, 0x0a, - 0x0c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x12, 0x3e, 0x0a, - 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3e, 0x0a, - 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3e, 0x0a, - 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3f, 0x0a, - 0x0c, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x2e, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3e, - 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, 0x2e, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, - 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x38, - 0x0a, 0x08, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, 0x2e, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, - 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x41, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, + 0x07, 0x65, 0x6e, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x74, 0x69, 0x6d, 0x65, + 0x7a, 0x6f, 0x6e, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x74, 0x69, 0x6d, 0x65, + 0x7a, 0x6f, 0x6e, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x74, 0x79, + 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x54, + 0x79, 0x70, 0x65, 0x12, 0x1a, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, + 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, + 0x21, 0x0a, 0x0c, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x18, + 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x6d, 0x65, 0x65, 0x74, 0x69, 0x6e, 0x67, 0x4c, 0x69, + 0x6e, 0x6b, 0x12, 0x1a, 0x0a, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x18, 0x0a, + 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x63, 0x61, 0x70, 0x61, 0x63, 0x69, 0x74, 0x79, 0x12, 0x1f, + 0x0a, 0x0b, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x0b, 0x20, + 0x01, 0x28, 0x09, 0x52, 0x0a, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, + 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0c, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, + 0x61, 0x67, 0x73, 0x12, 0x3d, 0x0a, 0x0c, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x5f, 0x74, 0x69, + 0x65, 0x72, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, + 0x49, 0x6e, 0x70, 0x75, 0x74, 0x52, 0x0b, 0x74, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, + 0x72, 0x73, 0x12, 0x1d, 0x0a, 0x0a, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x5f, 0x73, 0x6c, 0x75, 0x67, + 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x67, 0x72, 0x6f, 0x75, 0x70, 0x53, 0x6c, 0x75, + 0x67, 0x12, 0x1e, 0x0a, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, 0x79, 0x18, + 0x0f, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x76, 0x69, 0x73, 0x69, 0x62, 0x69, 0x6c, 0x69, 0x74, + 0x79, 0x12, 0x35, 0x0a, 0x0a, 0x72, 0x65, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x18, + 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, + 0x63, 0x2e, 0x52, 0x65, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x0a, 0x72, 0x65, + 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x36, 0x0a, 0x0b, 0x63, 0x6c, 0x69, 0x65, + 0x6e, 0x74, 0x5f, 0x69, 0x6e, 0x66, 0x6f, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x15, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x69, 0x65, 0x6e, 0x74, + 0x49, 0x6e, 0x66, 0x6f, 0x52, 0x0a, 0x63, 0x6c, 0x69, 0x65, 0x6e, 0x74, 0x49, 0x6e, 0x66, 0x6f, + 0x32, 0xc4, 0x13, 0x0a, 0x0c, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x53, 0x65, 0x72, 0x76, 0x69, 0x63, + 0x65, 0x12, 0x3e, 0x0a, 0x0b, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x72, 0x65, + 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x3e, 0x0a, 0x0b, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x55, 0x70, 0x64, + 0x61, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x3e, 0x0a, 0x0b, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, + 0x70, 0x12, 0x3f, 0x0a, 0x0c, 0x50, 0x75, 0x62, 0x6c, 0x69, 0x73, 0x68, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x12, 0x3e, 0x0a, 0x0b, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x12, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, + 0x73, 0x70, 0x12, 0x38, 0x0a, 0x08, 0x47, 0x65, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x16, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x47, 0x65, 0x74, 0x45, 0x76, + 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x41, 0x0a, 0x0a, + 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, + 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, + 0x44, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x12, 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, + 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, + 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, + 0x52, 0x65, 0x73, 0x70, 0x12, 0x45, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x44, 0x0a, 0x0d, 0x47, - 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, - 0x70, 0x12, 0x4d, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x55, 0x73, 0x65, 0x72, 0x41, 0x74, 0x74, 0x65, - 0x6e, 0x64, 0x69, 0x6e, 0x67, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x18, 0x2e, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, - 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x45, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x47, 0x72, 0x6f, 0x75, 0x70, 0x45, 0x76, 0x65, 0x6e, - 0x74, 0x73, 0x12, 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, - 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, - 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, - 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, - 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, - 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x12, 0x1e, 0x2e, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x63, - 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x19, 0x2e, 0x65, 0x76, 0x65, - 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, - 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x10, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x54, - 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x12, 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x65, 0x72, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, - 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, - 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x41, 0x0a, 0x0c, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x70, - 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, - 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x44, 0x0a, 0x0b, - 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x73, 0x12, 0x19, 0x2e, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x70, - 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x73, 0x52, 0x65, - 0x73, 0x70, 0x12, 0x40, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x70, - 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, - 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, - 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, - 0x52, 0x65, 0x73, 0x70, 0x12, 0x45, 0x0a, 0x0e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, - 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x12, 0x1c, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x70, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, - 0x2e, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, 0x34, 0x0a, 0x09, 0x52, - 0x53, 0x56, 0x50, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x52, 0x53, 0x56, 0x50, 0x52, 0x65, 0x71, 0x1a, 0x13, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x52, 0x53, 0x56, 0x50, 0x52, 0x65, 0x73, - 0x70, 0x12, 0x3c, 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x53, 0x56, 0x50, 0x12, - 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x52, 0x53, 0x56, 0x50, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x4b, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, - 0x74, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x12, 0x1c, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x65, 0x62, 0x68, - 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x49, 0x0a, 0x0c, - 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, - 0x65, 0x6e, 0x64, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, - 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x48, 0x0a, 0x10, 0x55, 0x70, 0x64, 0x61, 0x74, - 0x65, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x12, 0x1e, 0x2e, 0x65, 0x76, - 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, - 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, + 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x10, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x12, + 0x1e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, + 0x74, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, + 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, + 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x4d, 0x0a, 0x10, 0x55, 0x70, + 0x64, 0x61, 0x74, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x12, 0x1e, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x71, 0x1a, 0x19, + 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x63, 0x6b, 0x65, + 0x74, 0x54, 0x69, 0x65, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x10, 0x44, 0x65, 0x6c, + 0x65, 0x74, 0x65, 0x54, 0x69, 0x63, 0x6b, 0x65, 0x74, 0x54, 0x69, 0x65, 0x72, 0x12, 0x18, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x54, 0x69, 0x65, 0x72, 0x41, 0x63, + 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, + 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x41, 0x0a, + 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, + 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, + 0x12, 0x44, 0x0a, 0x0b, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x73, 0x12, + 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1a, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x75, 0x70, 0x6f, + 0x6e, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x40, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, + 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x12, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x76, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, + 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, + 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x45, 0x0a, 0x0e, 0x56, 0x61, 0x6c, 0x69, + 0x64, 0x61, 0x74, 0x65, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x12, 0x1c, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x56, 0x61, 0x6c, 0x69, 0x64, 0x61, 0x74, 0x65, 0x43, + 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x15, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6f, 0x75, 0x70, 0x6f, 0x6e, 0x52, 0x65, 0x73, 0x70, 0x12, + 0x34, 0x0a, 0x09, 0x52, 0x53, 0x56, 0x50, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x12, 0x2e, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x52, 0x53, 0x56, 0x50, 0x52, 0x65, 0x71, + 0x1a, 0x13, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x52, 0x53, 0x56, + 0x50, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3c, 0x0a, 0x0a, 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, + 0x53, 0x56, 0x50, 0x12, 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, + 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x52, 0x53, 0x56, 0x50, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x4b, 0x0a, 0x15, 0x50, 0x72, 0x6f, 0x63, 0x65, 0x73, 0x73, 0x50, 0x61, + 0x79, 0x6d, 0x65, 0x6e, 0x74, 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x12, 0x1c, 0x2e, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x50, 0x61, 0x79, 0x6d, 0x65, 0x6e, 0x74, + 0x57, 0x65, 0x62, 0x68, 0x6f, 0x6f, 0x6b, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, + 0x12, 0x49, 0x0a, 0x0c, 0x47, 0x65, 0x74, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x73, + 0x12, 0x1b, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1c, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x41, 0x74, + 0x74, 0x65, 0x6e, 0x64, 0x65, 0x65, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x48, 0x0a, 0x10, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x12, + 0x1e, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x55, 0x70, 0x64, 0x61, + 0x74, 0x65, 0x41, 0x74, 0x74, 0x65, 0x6e, 0x64, 0x61, 0x6e, 0x63, 0x65, 0x52, 0x65, 0x71, 0x1a, + 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, + 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x61, 0x76, 0x65, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x17, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x53, + 0x61, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, - 0x70, 0x12, 0x3a, 0x0a, 0x09, 0x53, 0x61, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x17, - 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3c, 0x0a, - 0x0b, 0x55, 0x6e, 0x73, 0x61, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x17, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x53, 0x61, 0x76, 0x65, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, - 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x43, 0x0a, 0x0f, 0x41, - 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x18, - 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x41, 0x64, 0x64, 0x43, 0x6f, - 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, - 0x12, 0x4c, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, - 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, - 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, - 0x71, 0x1a, 0x1b, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, - 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, 0x73, 0x70, 0x12, 0x47, - 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, - 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, - 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, - 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, - 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x39, 0x0a, 0x0c, 0x52, 0x65, 0x61, 0x63, 0x74, - 0x54, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x13, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, - 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, - 0x73, 0x70, 0x12, 0x3b, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x52, 0x65, 0x61, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, - 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, - 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x3e, 0x0a, 0x0b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x19, - 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x52, 0x65, 0x70, 0x6f, 0x72, - 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x70, 0x12, 0x3c, 0x0a, 0x0b, 0x55, 0x6e, 0x73, 0x61, 0x76, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, + 0x12, 0x17, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x53, 0x61, 0x76, + 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, - 0x37, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x43, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x14, 0x2e, 0x65, + 0x43, 0x0a, 0x0f, 0x41, 0x64, 0x64, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, + 0x6e, 0x74, 0x12, 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x41, + 0x64, 0x64, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x16, 0x2e, 0x65, + 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, + 0x52, 0x65, 0x73, 0x70, 0x12, 0x4c, 0x0a, 0x11, 0x4c, 0x69, 0x73, 0x74, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, + 0x74, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x1b, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, + 0x63, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x73, 0x52, 0x65, + 0x73, 0x70, 0x12, 0x47, 0x0a, 0x12, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x43, 0x6f, 0x6d, 0x6d, 0x65, 0x6e, 0x74, 0x12, 0x1b, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x43, 0x6f, 0x6d, 0x6d, 0x65, + 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, + 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x39, 0x0a, 0x0c, 0x52, + 0x65, 0x61, 0x63, 0x74, 0x54, 0x6f, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x13, 0x2e, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, + 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, + 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3b, 0x0a, 0x0e, 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, + 0x52, 0x65, 0x61, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x13, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, + 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x52, 0x65, 0x61, 0x63, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x3e, 0x0a, 0x0b, 0x52, 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, + 0x6e, 0x74, 0x12, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x52, + 0x65, 0x70, 0x6f, 0x72, 0x74, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, + 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, + 0x65, 0x73, 0x70, 0x12, 0x37, 0x0a, 0x09, 0x41, 0x64, 0x64, 0x43, 0x6f, 0x48, 0x6f, 0x73, 0x74, + 0x12, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6f, 0x48, + 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3a, 0x0a, 0x0c, + 0x52, 0x65, 0x6d, 0x6f, 0x76, 0x65, 0x43, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, - 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3a, 0x0a, 0x0c, 0x52, 0x65, 0x6d, 0x6f, - 0x76, 0x65, 0x43, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x12, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, - 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6f, 0x48, 0x6f, 0x73, 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, - 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, - 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6c, 0x65, 0x6e, - 0x64, 0x61, 0x72, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, - 0x73, 0x76, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x52, 0x65, 0x71, 0x1a, - 0x17, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x65, - 0x6e, 0x64, 0x61, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3e, 0x0a, 0x09, 0x41, 0x75, 0x74, 0x68, - 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x12, 0x17, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, - 0x63, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x71, 0x1a, 0x18, - 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, - 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3c, 0x0a, 0x0a, 0x43, 0x6c, 0x6f, 0x6e, - 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x71, - 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, - 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x40, 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, - 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, - 0x76, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x49, 0x0a, 0x16, 0x43, 0x61, 0x6e, 0x63, - 0x65, 0x6c, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x4f, 0x63, 0x63, 0x75, 0x72, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x12, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x45, - 0x76, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, - 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, 0x73, 0x69, 0x63, 0x52, - 0x65, 0x73, 0x70, 0x42, 0x25, 0x5a, 0x23, 0x2e, 0x2f, 0x61, 0x70, 0x69, 0x73, 0x2f, 0x73, 0x65, - 0x72, 0x76, 0x69, 0x63, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x2f, 0x67, 0x61, 0x74, 0x65, 0x77, 0x61, - 0x79, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x62, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x61, 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x12, 0x42, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x43, + 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x46, 0x69, 0x6c, 0x65, 0x12, 0x16, 0x2e, 0x65, 0x76, + 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, + 0x52, 0x65, 0x71, 0x1a, 0x17, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, + 0x43, 0x61, 0x6c, 0x65, 0x6e, 0x64, 0x61, 0x72, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3e, 0x0a, 0x09, + 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x12, 0x17, 0x2e, 0x65, 0x76, 0x65, 0x6e, + 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x41, 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, + 0x65, 0x71, 0x1a, 0x18, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x41, + 0x75, 0x74, 0x68, 0x6f, 0x72, 0x69, 0x7a, 0x65, 0x52, 0x65, 0x73, 0x70, 0x12, 0x3c, 0x0a, 0x0a, + 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x12, 0x18, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x6c, 0x6f, 0x6e, 0x65, 0x45, 0x76, 0x65, 0x6e, + 0x74, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, + 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x40, 0x0a, 0x0c, 0x43, 0x72, + 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x65, 0x76, 0x65, + 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x53, 0x65, 0x72, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x52, 0x65, 0x73, 0x70, 0x12, 0x49, 0x0a, 0x16, + 0x43, 0x61, 0x6e, 0x63, 0x65, 0x6c, 0x53, 0x65, 0x72, 0x69, 0x65, 0x73, 0x4f, 0x63, 0x63, 0x75, + 0x72, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x12, 0x19, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, + 0x76, 0x63, 0x2e, 0x45, 0x76, 0x65, 0x6e, 0x74, 0x41, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, + 0x71, 0x1a, 0x14, 0x2e, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x5f, 0x73, 0x76, 0x63, 0x2e, 0x42, 0x61, + 0x73, 0x69, 0x63, 0x52, 0x65, 0x73, 0x70, 0x42, 0x25, 0x5a, 0x23, 0x2e, 0x2f, 0x61, 0x70, 0x69, + 0x73, 0x2f, 0x73, 0x65, 0x72, 0x76, 0x69, 0x63, 0x65, 0x63, 0x6f, 0x6e, 0x6e, 0x2f, 0x67, 0x61, + 0x74, 0x65, 0x77, 0x61, 0x79, 0x5f, 0x65, 0x76, 0x65, 0x6e, 0x74, 0x2f, 0x70, 0x62, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -5802,6 +5884,7 @@ var file_apis_serviceconn_gateway_event_pb_gw_event_proto_goTypes = []interface{ (*Recurrence)(nil), // 50: event_svc.Recurrence (*CreateSeriesReq)(nil), // 51: event_svc.CreateSeriesReq (*timestamppb.Timestamp)(nil), // 52: google.protobuf.Timestamp + (*wrapperspb.Int32Value)(nil), // 53: google.protobuf.Int32Value } var file_apis_serviceconn_gateway_event_pb_gw_event_proto_depIdxs = []int32{ 52, // 0: event_svc.Event.start_time:type_name -> google.protobuf.Timestamp @@ -5815,145 +5898,147 @@ var file_apis_serviceconn_gateway_event_pb_gw_event_proto_depIdxs = []int32{ 8, // 8: event_svc.Event.venue:type_name -> event_svc.Venue 52, // 9: event_svc.Event.series_occurrence_at:type_name -> google.protobuf.Timestamp 9, // 10: event_svc.Event.questions:type_name -> event_svc.EventQuestion - 52, // 11: event_svc.Coupon.valid_from:type_name -> google.protobuf.Timestamp - 52, // 12: event_svc.Coupon.valid_to:type_name -> google.protobuf.Timestamp - 52, // 13: event_svc.Attendee.created_at:type_name -> google.protobuf.Timestamp - 52, // 14: event_svc.Attendee.checked_in_at:type_name -> google.protobuf.Timestamp - 52, // 15: event_svc.EventComment.created_at:type_name -> google.protobuf.Timestamp - 52, // 16: event_svc.CreateEventReq.start_time:type_name -> google.protobuf.Timestamp - 52, // 17: event_svc.CreateEventReq.end_time:type_name -> google.protobuf.Timestamp - 4, // 18: event_svc.CreateEventReq.ticket_tiers:type_name -> event_svc.TicketTierInput - 0, // 19: event_svc.CreateEventReq.client_info:type_name -> event_svc.ClientInfo - 52, // 20: event_svc.CreateEventReq.rsvp_opens_at:type_name -> google.protobuf.Timestamp - 52, // 21: event_svc.CreateEventReq.rsvp_closes_at:type_name -> google.protobuf.Timestamp - 9, // 22: event_svc.CreateEventReq.questions:type_name -> event_svc.EventQuestion - 52, // 23: event_svc.UpdateEventReq.start_time:type_name -> google.protobuf.Timestamp - 52, // 24: event_svc.UpdateEventReq.end_time:type_name -> google.protobuf.Timestamp - 0, // 25: event_svc.UpdateEventReq.client_info:type_name -> event_svc.ClientInfo - 52, // 26: event_svc.UpdateEventReq.rsvp_opens_at:type_name -> google.protobuf.Timestamp - 52, // 27: event_svc.UpdateEventReq.rsvp_closes_at:type_name -> google.protobuf.Timestamp - 9, // 28: event_svc.UpdateEventReq.questions:type_name -> event_svc.EventQuestion - 0, // 29: event_svc.EventActionReq.client_info:type_name -> event_svc.ClientInfo - 0, // 30: event_svc.GetEventReq.client_info:type_name -> event_svc.ClientInfo - 1, // 31: event_svc.EventResp.event:type_name -> event_svc.Event - 0, // 32: event_svc.ListEventsReq.client_info:type_name -> event_svc.ClientInfo - 1, // 33: event_svc.ListEventsResp.events:type_name -> event_svc.Event - 4, // 34: event_svc.CreateTicketTierReq.tier:type_name -> event_svc.TicketTierInput - 0, // 35: event_svc.CreateTicketTierReq.client_info:type_name -> event_svc.ClientInfo - 4, // 36: event_svc.UpdateTicketTierReq.tier:type_name -> event_svc.TicketTierInput - 0, // 37: event_svc.UpdateTicketTierReq.client_info:type_name -> event_svc.ClientInfo - 0, // 38: event_svc.TierActionReq.client_info:type_name -> event_svc.ClientInfo - 3, // 39: event_svc.TicketTierResp.tier:type_name -> event_svc.TicketTier - 52, // 40: event_svc.CreateCouponReq.valid_from:type_name -> google.protobuf.Timestamp - 52, // 41: event_svc.CreateCouponReq.valid_to:type_name -> google.protobuf.Timestamp - 0, // 42: event_svc.CreateCouponReq.client_info:type_name -> event_svc.ClientInfo - 0, // 43: event_svc.CouponActionReq.client_info:type_name -> event_svc.ClientInfo - 0, // 44: event_svc.ListCouponsReq.client_info:type_name -> event_svc.ClientInfo - 5, // 45: event_svc.ListCouponsResp.coupons:type_name -> event_svc.Coupon - 0, // 46: event_svc.ValidateCouponReq.client_info:type_name -> event_svc.ClientInfo - 5, // 47: event_svc.CouponResp.coupon:type_name -> event_svc.Coupon - 0, // 48: event_svc.RSVPReq.client_info:type_name -> event_svc.ClientInfo - 10, // 49: event_svc.RSVPReq.answers:type_name -> event_svc.RSVPAnswer - 0, // 50: event_svc.CancelRSVPReq.client_info:type_name -> event_svc.ClientInfo - 0, // 51: event_svc.ListAttendeesReq.client_info:type_name -> event_svc.ClientInfo - 6, // 52: event_svc.ListAttendeesResp.attendees:type_name -> event_svc.Attendee - 0, // 53: event_svc.UpdateAttendanceReq.client_info:type_name -> event_svc.ClientInfo - 0, // 54: event_svc.SaveEventReq.client_info:type_name -> event_svc.ClientInfo - 0, // 55: event_svc.AddCommentReq.client_info:type_name -> event_svc.ClientInfo - 7, // 56: event_svc.CommentResp.comment:type_name -> event_svc.EventComment - 7, // 57: event_svc.ListCommentsResp.comments:type_name -> event_svc.EventComment - 0, // 58: event_svc.DeleteCommentReq.client_info:type_name -> event_svc.ClientInfo - 0, // 59: event_svc.ReactReq.client_info:type_name -> event_svc.ClientInfo - 0, // 60: event_svc.ReportEventReq.client_info:type_name -> event_svc.ClientInfo - 0, // 61: event_svc.CoHostReq.client_info:type_name -> event_svc.ClientInfo - 52, // 62: event_svc.CloneEventReq.start_time:type_name -> google.protobuf.Timestamp - 52, // 63: event_svc.CloneEventReq.end_time:type_name -> google.protobuf.Timestamp - 0, // 64: event_svc.CloneEventReq.client_info:type_name -> event_svc.ClientInfo - 52, // 65: event_svc.Recurrence.until:type_name -> google.protobuf.Timestamp - 52, // 66: event_svc.CreateSeriesReq.start_time:type_name -> google.protobuf.Timestamp - 52, // 67: event_svc.CreateSeriesReq.end_time:type_name -> google.protobuf.Timestamp - 4, // 68: event_svc.CreateSeriesReq.ticket_tiers:type_name -> event_svc.TicketTierInput - 50, // 69: event_svc.CreateSeriesReq.recurrence:type_name -> event_svc.Recurrence - 0, // 70: event_svc.CreateSeriesReq.client_info:type_name -> event_svc.ClientInfo - 11, // 71: event_svc.EventService.CreateEvent:input_type -> event_svc.CreateEventReq - 12, // 72: event_svc.EventService.UpdateEvent:input_type -> event_svc.UpdateEventReq - 13, // 73: event_svc.EventService.DeleteEvent:input_type -> event_svc.EventActionReq - 13, // 74: event_svc.EventService.PublishEvent:input_type -> event_svc.EventActionReq - 13, // 75: event_svc.EventService.CancelEvent:input_type -> event_svc.EventActionReq - 14, // 76: event_svc.EventService.GetEvent:input_type -> event_svc.GetEventReq - 16, // 77: event_svc.EventService.ListEvents:input_type -> event_svc.ListEventsReq - 16, // 78: event_svc.EventService.GetUserEvents:input_type -> event_svc.ListEventsReq - 16, // 79: event_svc.EventService.GetUserAttendingEvents:input_type -> event_svc.ListEventsReq - 16, // 80: event_svc.EventService.GetGroupEvents:input_type -> event_svc.ListEventsReq - 19, // 81: event_svc.EventService.CreateTicketTier:input_type -> event_svc.CreateTicketTierReq - 20, // 82: event_svc.EventService.UpdateTicketTier:input_type -> event_svc.UpdateTicketTierReq - 21, // 83: event_svc.EventService.DeleteTicketTier:input_type -> event_svc.TierActionReq - 23, // 84: event_svc.EventService.CreateCoupon:input_type -> event_svc.CreateCouponReq - 25, // 85: event_svc.EventService.ListCoupons:input_type -> event_svc.ListCouponsReq - 24, // 86: event_svc.EventService.DeleteCoupon:input_type -> event_svc.CouponActionReq - 27, // 87: event_svc.EventService.ValidateCoupon:input_type -> event_svc.ValidateCouponReq - 29, // 88: event_svc.EventService.RSVPEvent:input_type -> event_svc.RSVPReq - 31, // 89: event_svc.EventService.CancelRSVP:input_type -> event_svc.CancelRSVPReq - 32, // 90: event_svc.EventService.ProcessPaymentWebhook:input_type -> event_svc.PaymentWebhookReq - 33, // 91: event_svc.EventService.GetAttendees:input_type -> event_svc.ListAttendeesReq - 35, // 92: event_svc.EventService.UpdateAttendance:input_type -> event_svc.UpdateAttendanceReq - 36, // 93: event_svc.EventService.SaveEvent:input_type -> event_svc.SaveEventReq - 36, // 94: event_svc.EventService.UnsaveEvent:input_type -> event_svc.SaveEventReq - 37, // 95: event_svc.EventService.AddEventComment:input_type -> event_svc.AddCommentReq - 39, // 96: event_svc.EventService.ListEventComments:input_type -> event_svc.ListCommentsReq - 41, // 97: event_svc.EventService.DeleteEventComment:input_type -> event_svc.DeleteCommentReq - 42, // 98: event_svc.EventService.ReactToEvent:input_type -> event_svc.ReactReq - 42, // 99: event_svc.EventService.RemoveReaction:input_type -> event_svc.ReactReq - 43, // 100: event_svc.EventService.ReportEvent:input_type -> event_svc.ReportEventReq - 44, // 101: event_svc.EventService.AddCoHost:input_type -> event_svc.CoHostReq - 44, // 102: event_svc.EventService.RemoveCoHost:input_type -> event_svc.CoHostReq - 45, // 103: event_svc.EventService.GetCalendarFile:input_type -> event_svc.CalendarReq - 47, // 104: event_svc.EventService.Authorize:input_type -> event_svc.AuthorizeReq - 49, // 105: event_svc.EventService.CloneEvent:input_type -> event_svc.CloneEventReq - 51, // 106: event_svc.EventService.CreateSeries:input_type -> event_svc.CreateSeriesReq - 13, // 107: event_svc.EventService.CancelSeriesOccurrence:input_type -> event_svc.EventActionReq - 15, // 108: event_svc.EventService.CreateEvent:output_type -> event_svc.EventResp - 15, // 109: event_svc.EventService.UpdateEvent:output_type -> event_svc.EventResp - 18, // 110: event_svc.EventService.DeleteEvent:output_type -> event_svc.BasicResp - 15, // 111: event_svc.EventService.PublishEvent:output_type -> event_svc.EventResp - 15, // 112: event_svc.EventService.CancelEvent:output_type -> event_svc.EventResp - 15, // 113: event_svc.EventService.GetEvent:output_type -> event_svc.EventResp - 17, // 114: event_svc.EventService.ListEvents:output_type -> event_svc.ListEventsResp - 17, // 115: event_svc.EventService.GetUserEvents:output_type -> event_svc.ListEventsResp - 17, // 116: event_svc.EventService.GetUserAttendingEvents:output_type -> event_svc.ListEventsResp - 17, // 117: event_svc.EventService.GetGroupEvents:output_type -> event_svc.ListEventsResp - 22, // 118: event_svc.EventService.CreateTicketTier:output_type -> event_svc.TicketTierResp - 22, // 119: event_svc.EventService.UpdateTicketTier:output_type -> event_svc.TicketTierResp - 18, // 120: event_svc.EventService.DeleteTicketTier:output_type -> event_svc.BasicResp - 28, // 121: event_svc.EventService.CreateCoupon:output_type -> event_svc.CouponResp - 26, // 122: event_svc.EventService.ListCoupons:output_type -> event_svc.ListCouponsResp - 18, // 123: event_svc.EventService.DeleteCoupon:output_type -> event_svc.BasicResp - 28, // 124: event_svc.EventService.ValidateCoupon:output_type -> event_svc.CouponResp - 30, // 125: event_svc.EventService.RSVPEvent:output_type -> event_svc.RSVPResp - 18, // 126: event_svc.EventService.CancelRSVP:output_type -> event_svc.BasicResp - 18, // 127: event_svc.EventService.ProcessPaymentWebhook:output_type -> event_svc.BasicResp - 34, // 128: event_svc.EventService.GetAttendees:output_type -> event_svc.ListAttendeesResp - 18, // 129: event_svc.EventService.UpdateAttendance:output_type -> event_svc.BasicResp - 18, // 130: event_svc.EventService.SaveEvent:output_type -> event_svc.BasicResp - 18, // 131: event_svc.EventService.UnsaveEvent:output_type -> event_svc.BasicResp - 38, // 132: event_svc.EventService.AddEventComment:output_type -> event_svc.CommentResp - 40, // 133: event_svc.EventService.ListEventComments:output_type -> event_svc.ListCommentsResp - 18, // 134: event_svc.EventService.DeleteEventComment:output_type -> event_svc.BasicResp - 18, // 135: event_svc.EventService.ReactToEvent:output_type -> event_svc.BasicResp - 18, // 136: event_svc.EventService.RemoveReaction:output_type -> event_svc.BasicResp - 18, // 137: event_svc.EventService.ReportEvent:output_type -> event_svc.BasicResp - 18, // 138: event_svc.EventService.AddCoHost:output_type -> event_svc.BasicResp - 18, // 139: event_svc.EventService.RemoveCoHost:output_type -> event_svc.BasicResp - 46, // 140: event_svc.EventService.GetCalendarFile:output_type -> event_svc.CalendarResp - 48, // 141: event_svc.EventService.Authorize:output_type -> event_svc.AuthorizeResp - 15, // 142: event_svc.EventService.CloneEvent:output_type -> event_svc.EventResp - 15, // 143: event_svc.EventService.CreateSeries:output_type -> event_svc.EventResp - 18, // 144: event_svc.EventService.CancelSeriesOccurrence:output_type -> event_svc.BasicResp - 108, // [108:145] is the sub-list for method output_type - 71, // [71:108] is the sub-list for method input_type - 71, // [71:71] is the sub-list for extension type_name - 71, // [71:71] is the sub-list for extension extendee - 0, // [0:71] is the sub-list for field type_name + 52, // 11: event_svc.Event.upcoming_dates:type_name -> google.protobuf.Timestamp + 52, // 12: event_svc.Coupon.valid_from:type_name -> google.protobuf.Timestamp + 52, // 13: event_svc.Coupon.valid_to:type_name -> google.protobuf.Timestamp + 52, // 14: event_svc.Attendee.created_at:type_name -> google.protobuf.Timestamp + 52, // 15: event_svc.Attendee.checked_in_at:type_name -> google.protobuf.Timestamp + 52, // 16: event_svc.EventComment.created_at:type_name -> google.protobuf.Timestamp + 52, // 17: event_svc.CreateEventReq.start_time:type_name -> google.protobuf.Timestamp + 52, // 18: event_svc.CreateEventReq.end_time:type_name -> google.protobuf.Timestamp + 4, // 19: event_svc.CreateEventReq.ticket_tiers:type_name -> event_svc.TicketTierInput + 0, // 20: event_svc.CreateEventReq.client_info:type_name -> event_svc.ClientInfo + 52, // 21: event_svc.CreateEventReq.rsvp_opens_at:type_name -> google.protobuf.Timestamp + 52, // 22: event_svc.CreateEventReq.rsvp_closes_at:type_name -> google.protobuf.Timestamp + 9, // 23: event_svc.CreateEventReq.questions:type_name -> event_svc.EventQuestion + 52, // 24: event_svc.UpdateEventReq.start_time:type_name -> google.protobuf.Timestamp + 52, // 25: event_svc.UpdateEventReq.end_time:type_name -> google.protobuf.Timestamp + 0, // 26: event_svc.UpdateEventReq.client_info:type_name -> event_svc.ClientInfo + 52, // 27: event_svc.UpdateEventReq.rsvp_opens_at:type_name -> google.protobuf.Timestamp + 52, // 28: event_svc.UpdateEventReq.rsvp_closes_at:type_name -> google.protobuf.Timestamp + 9, // 29: event_svc.UpdateEventReq.questions:type_name -> event_svc.EventQuestion + 53, // 30: event_svc.UpdateEventReq.rsvp_close_hours_before:type_name -> google.protobuf.Int32Value + 0, // 31: event_svc.EventActionReq.client_info:type_name -> event_svc.ClientInfo + 0, // 32: event_svc.GetEventReq.client_info:type_name -> event_svc.ClientInfo + 1, // 33: event_svc.EventResp.event:type_name -> event_svc.Event + 0, // 34: event_svc.ListEventsReq.client_info:type_name -> event_svc.ClientInfo + 1, // 35: event_svc.ListEventsResp.events:type_name -> event_svc.Event + 4, // 36: event_svc.CreateTicketTierReq.tier:type_name -> event_svc.TicketTierInput + 0, // 37: event_svc.CreateTicketTierReq.client_info:type_name -> event_svc.ClientInfo + 4, // 38: event_svc.UpdateTicketTierReq.tier:type_name -> event_svc.TicketTierInput + 0, // 39: event_svc.UpdateTicketTierReq.client_info:type_name -> event_svc.ClientInfo + 0, // 40: event_svc.TierActionReq.client_info:type_name -> event_svc.ClientInfo + 3, // 41: event_svc.TicketTierResp.tier:type_name -> event_svc.TicketTier + 52, // 42: event_svc.CreateCouponReq.valid_from:type_name -> google.protobuf.Timestamp + 52, // 43: event_svc.CreateCouponReq.valid_to:type_name -> google.protobuf.Timestamp + 0, // 44: event_svc.CreateCouponReq.client_info:type_name -> event_svc.ClientInfo + 0, // 45: event_svc.CouponActionReq.client_info:type_name -> event_svc.ClientInfo + 0, // 46: event_svc.ListCouponsReq.client_info:type_name -> event_svc.ClientInfo + 5, // 47: event_svc.ListCouponsResp.coupons:type_name -> event_svc.Coupon + 0, // 48: event_svc.ValidateCouponReq.client_info:type_name -> event_svc.ClientInfo + 5, // 49: event_svc.CouponResp.coupon:type_name -> event_svc.Coupon + 0, // 50: event_svc.RSVPReq.client_info:type_name -> event_svc.ClientInfo + 10, // 51: event_svc.RSVPReq.answers:type_name -> event_svc.RSVPAnswer + 0, // 52: event_svc.CancelRSVPReq.client_info:type_name -> event_svc.ClientInfo + 0, // 53: event_svc.ListAttendeesReq.client_info:type_name -> event_svc.ClientInfo + 6, // 54: event_svc.ListAttendeesResp.attendees:type_name -> event_svc.Attendee + 0, // 55: event_svc.UpdateAttendanceReq.client_info:type_name -> event_svc.ClientInfo + 0, // 56: event_svc.SaveEventReq.client_info:type_name -> event_svc.ClientInfo + 0, // 57: event_svc.AddCommentReq.client_info:type_name -> event_svc.ClientInfo + 7, // 58: event_svc.CommentResp.comment:type_name -> event_svc.EventComment + 7, // 59: event_svc.ListCommentsResp.comments:type_name -> event_svc.EventComment + 0, // 60: event_svc.DeleteCommentReq.client_info:type_name -> event_svc.ClientInfo + 0, // 61: event_svc.ReactReq.client_info:type_name -> event_svc.ClientInfo + 0, // 62: event_svc.ReportEventReq.client_info:type_name -> event_svc.ClientInfo + 0, // 63: event_svc.CoHostReq.client_info:type_name -> event_svc.ClientInfo + 52, // 64: event_svc.CloneEventReq.start_time:type_name -> google.protobuf.Timestamp + 52, // 65: event_svc.CloneEventReq.end_time:type_name -> google.protobuf.Timestamp + 0, // 66: event_svc.CloneEventReq.client_info:type_name -> event_svc.ClientInfo + 52, // 67: event_svc.Recurrence.until:type_name -> google.protobuf.Timestamp + 52, // 68: event_svc.CreateSeriesReq.start_time:type_name -> google.protobuf.Timestamp + 52, // 69: event_svc.CreateSeriesReq.end_time:type_name -> google.protobuf.Timestamp + 4, // 70: event_svc.CreateSeriesReq.ticket_tiers:type_name -> event_svc.TicketTierInput + 50, // 71: event_svc.CreateSeriesReq.recurrence:type_name -> event_svc.Recurrence + 0, // 72: event_svc.CreateSeriesReq.client_info:type_name -> event_svc.ClientInfo + 11, // 73: event_svc.EventService.CreateEvent:input_type -> event_svc.CreateEventReq + 12, // 74: event_svc.EventService.UpdateEvent:input_type -> event_svc.UpdateEventReq + 13, // 75: event_svc.EventService.DeleteEvent:input_type -> event_svc.EventActionReq + 13, // 76: event_svc.EventService.PublishEvent:input_type -> event_svc.EventActionReq + 13, // 77: event_svc.EventService.CancelEvent:input_type -> event_svc.EventActionReq + 14, // 78: event_svc.EventService.GetEvent:input_type -> event_svc.GetEventReq + 16, // 79: event_svc.EventService.ListEvents:input_type -> event_svc.ListEventsReq + 16, // 80: event_svc.EventService.GetUserEvents:input_type -> event_svc.ListEventsReq + 16, // 81: event_svc.EventService.GetUserAttendingEvents:input_type -> event_svc.ListEventsReq + 16, // 82: event_svc.EventService.GetGroupEvents:input_type -> event_svc.ListEventsReq + 19, // 83: event_svc.EventService.CreateTicketTier:input_type -> event_svc.CreateTicketTierReq + 20, // 84: event_svc.EventService.UpdateTicketTier:input_type -> event_svc.UpdateTicketTierReq + 21, // 85: event_svc.EventService.DeleteTicketTier:input_type -> event_svc.TierActionReq + 23, // 86: event_svc.EventService.CreateCoupon:input_type -> event_svc.CreateCouponReq + 25, // 87: event_svc.EventService.ListCoupons:input_type -> event_svc.ListCouponsReq + 24, // 88: event_svc.EventService.DeleteCoupon:input_type -> event_svc.CouponActionReq + 27, // 89: event_svc.EventService.ValidateCoupon:input_type -> event_svc.ValidateCouponReq + 29, // 90: event_svc.EventService.RSVPEvent:input_type -> event_svc.RSVPReq + 31, // 91: event_svc.EventService.CancelRSVP:input_type -> event_svc.CancelRSVPReq + 32, // 92: event_svc.EventService.ProcessPaymentWebhook:input_type -> event_svc.PaymentWebhookReq + 33, // 93: event_svc.EventService.GetAttendees:input_type -> event_svc.ListAttendeesReq + 35, // 94: event_svc.EventService.UpdateAttendance:input_type -> event_svc.UpdateAttendanceReq + 36, // 95: event_svc.EventService.SaveEvent:input_type -> event_svc.SaveEventReq + 36, // 96: event_svc.EventService.UnsaveEvent:input_type -> event_svc.SaveEventReq + 37, // 97: event_svc.EventService.AddEventComment:input_type -> event_svc.AddCommentReq + 39, // 98: event_svc.EventService.ListEventComments:input_type -> event_svc.ListCommentsReq + 41, // 99: event_svc.EventService.DeleteEventComment:input_type -> event_svc.DeleteCommentReq + 42, // 100: event_svc.EventService.ReactToEvent:input_type -> event_svc.ReactReq + 42, // 101: event_svc.EventService.RemoveReaction:input_type -> event_svc.ReactReq + 43, // 102: event_svc.EventService.ReportEvent:input_type -> event_svc.ReportEventReq + 44, // 103: event_svc.EventService.AddCoHost:input_type -> event_svc.CoHostReq + 44, // 104: event_svc.EventService.RemoveCoHost:input_type -> event_svc.CoHostReq + 45, // 105: event_svc.EventService.GetCalendarFile:input_type -> event_svc.CalendarReq + 47, // 106: event_svc.EventService.Authorize:input_type -> event_svc.AuthorizeReq + 49, // 107: event_svc.EventService.CloneEvent:input_type -> event_svc.CloneEventReq + 51, // 108: event_svc.EventService.CreateSeries:input_type -> event_svc.CreateSeriesReq + 13, // 109: event_svc.EventService.CancelSeriesOccurrence:input_type -> event_svc.EventActionReq + 15, // 110: event_svc.EventService.CreateEvent:output_type -> event_svc.EventResp + 15, // 111: event_svc.EventService.UpdateEvent:output_type -> event_svc.EventResp + 18, // 112: event_svc.EventService.DeleteEvent:output_type -> event_svc.BasicResp + 15, // 113: event_svc.EventService.PublishEvent:output_type -> event_svc.EventResp + 15, // 114: event_svc.EventService.CancelEvent:output_type -> event_svc.EventResp + 15, // 115: event_svc.EventService.GetEvent:output_type -> event_svc.EventResp + 17, // 116: event_svc.EventService.ListEvents:output_type -> event_svc.ListEventsResp + 17, // 117: event_svc.EventService.GetUserEvents:output_type -> event_svc.ListEventsResp + 17, // 118: event_svc.EventService.GetUserAttendingEvents:output_type -> event_svc.ListEventsResp + 17, // 119: event_svc.EventService.GetGroupEvents:output_type -> event_svc.ListEventsResp + 22, // 120: event_svc.EventService.CreateTicketTier:output_type -> event_svc.TicketTierResp + 22, // 121: event_svc.EventService.UpdateTicketTier:output_type -> event_svc.TicketTierResp + 18, // 122: event_svc.EventService.DeleteTicketTier:output_type -> event_svc.BasicResp + 28, // 123: event_svc.EventService.CreateCoupon:output_type -> event_svc.CouponResp + 26, // 124: event_svc.EventService.ListCoupons:output_type -> event_svc.ListCouponsResp + 18, // 125: event_svc.EventService.DeleteCoupon:output_type -> event_svc.BasicResp + 28, // 126: event_svc.EventService.ValidateCoupon:output_type -> event_svc.CouponResp + 30, // 127: event_svc.EventService.RSVPEvent:output_type -> event_svc.RSVPResp + 18, // 128: event_svc.EventService.CancelRSVP:output_type -> event_svc.BasicResp + 18, // 129: event_svc.EventService.ProcessPaymentWebhook:output_type -> event_svc.BasicResp + 34, // 130: event_svc.EventService.GetAttendees:output_type -> event_svc.ListAttendeesResp + 18, // 131: event_svc.EventService.UpdateAttendance:output_type -> event_svc.BasicResp + 18, // 132: event_svc.EventService.SaveEvent:output_type -> event_svc.BasicResp + 18, // 133: event_svc.EventService.UnsaveEvent:output_type -> event_svc.BasicResp + 38, // 134: event_svc.EventService.AddEventComment:output_type -> event_svc.CommentResp + 40, // 135: event_svc.EventService.ListEventComments:output_type -> event_svc.ListCommentsResp + 18, // 136: event_svc.EventService.DeleteEventComment:output_type -> event_svc.BasicResp + 18, // 137: event_svc.EventService.ReactToEvent:output_type -> event_svc.BasicResp + 18, // 138: event_svc.EventService.RemoveReaction:output_type -> event_svc.BasicResp + 18, // 139: event_svc.EventService.ReportEvent:output_type -> event_svc.BasicResp + 18, // 140: event_svc.EventService.AddCoHost:output_type -> event_svc.BasicResp + 18, // 141: event_svc.EventService.RemoveCoHost:output_type -> event_svc.BasicResp + 46, // 142: event_svc.EventService.GetCalendarFile:output_type -> event_svc.CalendarResp + 48, // 143: event_svc.EventService.Authorize:output_type -> event_svc.AuthorizeResp + 15, // 144: event_svc.EventService.CloneEvent:output_type -> event_svc.EventResp + 15, // 145: event_svc.EventService.CreateSeries:output_type -> event_svc.EventResp + 18, // 146: event_svc.EventService.CancelSeriesOccurrence:output_type -> event_svc.BasicResp + 110, // [110:147] is the sub-list for method output_type + 73, // [73:110] is the sub-list for method input_type + 73, // [73:73] is the sub-list for extension type_name + 73, // [73:73] is the sub-list for extension extendee + 0, // [0:73] is the sub-list for field type_name } func init() { file_apis_serviceconn_gateway_event_pb_gw_event_proto_init() } diff --git a/apis/serviceconn/gateway_event/pb/gw_event.proto b/apis/serviceconn/gateway_event/pb/gw_event.proto index 0d9114e1..67d817f6 100644 --- a/apis/serviceconn/gateway_event/pb/gw_event.proto +++ b/apis/serviceconn/gateway_event/pb/gw_event.proto @@ -3,6 +3,7 @@ syntax = "proto3"; package event_svc; import "google/protobuf/timestamp.proto"; +import "google/protobuf/wrappers.proto"; option go_package = "./apis/serviceconn/gateway_event/pb"; @@ -74,6 +75,15 @@ message Event { // can restore its selected/highlighted state on load. Empty for anonymous // callers or when the viewer has not reacted. repeated string viewer_reactions = 37; + // Human label derived from event_series.recurrence_rule (e.g. "Every week on Sat"). + // Empty when the event is a one-off. Additive; clients that ignore it stay valid. + string recurrence_text = 38; + // Next 1–3 occurrence starts on a collapsed discovery/profile card + // (representative date plus up to two more). Empty for one-offs and uncollapsed lists. + repeated google.protobuf.Timestamp upcoming_dates = 39; + // Series offset in hours before each occurrence start (0 = no extra close). + // Empty/zero on one-offs; hosts pick Off / 12h / 1d / 3d / 1w. + int32 rsvp_close_hours_before = 40; } message ReactionCount { @@ -238,6 +248,9 @@ message UpdateEventReq { int64 venue_id = 20; string how_to_find_us = 21; repeated EventQuestion questions = 22; + // Present on series edits: 0 = Off (clear per-occurrence close). Omitted + // on one-off updates so an empty JSON field does not wipe a series window. + google.protobuf.Int32Value rsvp_close_hours_before = 23; } // EventActionReq drives the slug-scoped verbs: delete, publish and cancel. @@ -384,6 +397,9 @@ message RSVPReq { // The service only rejects empty answers when required questions exist. int32 guest_count = 6; repeated RSVPAnswer answers = 7; + // this (default) | series. series RSVPs every open future occurrence + // in the same series; paid tiers are refused for series scope. + string scope = 8; } message RSVPResp { @@ -548,6 +564,8 @@ message Recurrence { repeated string by_day = 3; // MO,TU,... for weekly int32 count = 4; // stop after N occurrences; 0 = unused google.protobuf.Timestamp until = 5; + // Hours before each occurrence start to close RSVP. 0 = no extra close. + int32 rsvp_close_hours_before = 6; } message CreateSeriesReq { diff --git a/context.Md b/context.Md new file mode 100644 index 00000000..8cdc6ef9 --- /dev/null +++ b/context.Md @@ -0,0 +1,5 @@ +# Stale — do not use + +This file was an old geo/admin handoff. **Use `docs/context.md`.** + +Next feature design (not coded until approved): `docs/series-ux-rsvp-payments-plan.md`. diff --git a/docs/context.md b/docs/context.md new file mode 100644 index 00000000..6c8e3b22 --- /dev/null +++ b/docs/context.md @@ -0,0 +1,194 @@ +# Monkeys — AI handoff context + +Read this first. Then read `docs/series-ux-rsvp-payments-plan.md` for the next slice (series discovery, covers, errors, payments, RSVP window, RSVP-one-vs-all, speed). + +Do **not** start coding that slice until the user says proceed. Existing `/api/v1/events` and `/api/v1/groups` contracts stay valid. Additive protobuf fields only. No new parallel tables if `event_series` already covers it. + +--- + +## What this product is + +Monkeys is a writing + community + events platform (Meetup-like events/groups, plus blogs). Hosts create public meetups (one-off or recurring). Visitors discover by city/radius, RSVP (free or Razorpay), join groups. + +Design bar: Meetup-style, DRY, modular, backward compatible, no bloat, few comments. Users are not engineers — never show SQL, gRPC codes, or stack traces in toasts. + +--- + +## Repos and where you are + +| Repo | Path | Role | +| --- | --- | --- | +| **Engine (this git repo)** | `c:\Users\Dave\the_monkeys\the_monkeys_engine` | Go microservices, `schema/`, protos, docker compose | +| **Frontend** | `engine/local/the_monkeys` | pnpm/turbo monorepo. App: `apps/the_monkeys` (Next.js 14 App Router, Tailwind). **Gitignored by the engine repo** — it is its own git repo | +| Design / older plans | `docs/` | Meetup parity, recurring/past/profile, geo, admin | + +Frontend is **not** in engine `git status`. Edit it on disk; commit inside `local/the_monkeys`. Netlify builds `apps/the_monkeys` from that frontend repo (`npm run build` → turbo lint + next build). + +Typical branches: engine `events_upgrade` (events work) vs `main`. Frontend also used `events_upgrade`. Confirm `git branch` before committing. + +--- + +## How to run + +- Engine: from repo root, `docker compose up --build -d` after **any** backend/proto/migration change. User expects this every time. +- Gateway HTTP: `http://localhost:8081` (`.env` `THE_MONKEYS_GATEWAY_HTTP_PORT`). +- Frontend: Next on `http://localhost:3000`, proxies `/api/v1` to the gateway. +- Postgres 17, Redis, RabbitMQ, Elasticsearch, MinIO via compose. Migrations: `db-migrations` on `./schema`. +- Latest event/group geo migration: `schema/000014_add_event_group_coordinates.up.sql`. Do not rewrite applied migrations; add `000015+`. +- Protos: `apis/serviceconn/gateway_event/pb/gw_event.proto`, `gateway_group/pb/gw_group.proto`. User often runs `protoc` **manually**. After proto edits, generated `*.pb.go` / `*_grpc.pb.go` must exist before `go build`. +- `go vet ./...` is in CI. Never copy protobuf structs by value (`filtered := *req` copies a mutex). + +--- + +## Architecture (events path) + +``` +Browser (Next) + → GET/POST localhost:3000/api/v1/... + → the_monkeys_gateway (Gin) + → gRPC EventService / GroupService + → Postgres +``` + +Auth: JWT cookies (`mat` access, `mrt` refresh) from `the_monkeys_authz`. Gateway `AuthRequired` / `AuthOptional`. Event mutations also go through `internal/events/authx` guard (`edit_event`, `manage_tickets`, …). The events service **re-checks** `event_permissions`. + +Storage: event cover + gallery (max 4 photos) via gateway storage v2 → MinIO. Reads: `GET /api/v2/storage/events/:slug/photos`. Writes: `POST /api/v1/events/:slug/photos` (host). + +Payments today: **platform Razorpay**, keys `KEYS_RAZORPAY_KEY_ID` / `SECRET` / `WEBHOOK_SECRET` in `.env`. `microservices/the_monkeys_events/internal/services/payments.go`. If keys are empty, `pay.enabled()` is false and **paid ticket create / paid RSVP** returns FailedPrecondition `"payments are not configured on this deployment"`. + +--- + +## Microservices that matter for events + +| Service | Path | Notes | +| --- | --- | --- | +| Gateway | `microservices/the_monkeys_gateway` | REST. Events: `internal/events/{routes,handler,models}.go` | +| Events | `microservices/the_monkeys_events` | DB `internal/database/{events,attendees,recurring,tickets_coupons}.go`; svc `internal/services/{service,rrule,scheduler,payments}.go` | +| Groups | `microservices/the_monkeys_groups` | `GetUserGroups` + `public_only` | +| Authz, users, blog, storage, notification, activity, AI | other folders | only touch if the task needs them | + +Gateway error helper: `EventServiceClient.fail` maps gRPC → HTTP JSON `{ "error": "" }`. **Whatever you put in `status.Error` is what the toast shows.** Do not wrap `fmt.Errorf("%v", err)` from Postgres. + +Frontend toast helper: `eventError()` in `apps/the_monkeys/src/services/events/eventsApi.ts`. + +--- + +## Frontend map (app: `local/the_monkeys/apps/the_monkeys/src`) + +| Area | Files | +| --- | --- | +| Discovery | `components/events/discover/EventsDiscover.tsx`, `lib/geoSearch.ts`, `hooks/useIPLocation.ts` | +| Cards | `EventGridCard.tsx`, `groups/GroupGridCard.tsx` | +| Create/edit | `components/events/EventForm.tsx`, `app/events/new/page.tsx`, `app/events/[slug]/edit/page.tsx` | +| Detail | `app/events/[slug]/EventDetailClient.tsx`, `RsvpPanel.tsx`, `EventActions.tsx`, `detail/EventGallery.tsx`, `EventStickyBar.tsx`, `EventSeriesNote.tsx` | +| Host tools | `EventManage.tsx` (tickets, coupons, co-hosts, attendees) | +| Groups | `components/groups/detail/GroupCommunity.tsx` (Events \| About \| Members + staff tabs) | +| Profile | `app/[username]/page.tsx` → `ProfileActivity.tsx` (Posts \| Events \| Groups) | +| API types | `services/events/{eventsApi,eventTypes}.ts`, `services/groups/{groupsApi,groupsTypes}.ts` | +| Time helpers | `lib/eventTime.ts` (`isEventEnded`, formatters) | +| Tabs | `components/TextTabs.tsx` | + +Stack: React Query, axios instances (`axiosInstance` auth, `axiosInstanceNoAuth`, v2 for storage). Lint: Next ESLint + Prettier (`prettier/prettier`). Format before push. + +--- + +## Data model (events) — already in Postgres + +**`events`** (`schema/000010` + `000011` + `000014`): slug, times, timezone, type (`virtual` \| `in_person` \| `hybrid`), location, lat/lng, meeting_link, capacity, status (`draft` \| `published` \| `live` \| `completed` \| `cancelled`), cover_image, visibility, group_id, **series_id**, **series_occurrence_at**, **rsvp_opens_at / rsvp_closes_at** (columns exist; **create/update/RSVP code does not use them yet**). + +**`event_series`**: organizer, optional group, title, `recurrence_rule` (RRULE string), starts/ends, status `active|paused|completed|cancelled`. + +**`event_ticket_tiers`**, **`event_coupons`** (unique `(event_id, code)`), **`event_attendees`** (RSVP per **occurrence**), tags, comments, reactions, photos (storage, not a SQL gallery table). + +Each recurring date is a **normal event row**. RSVP, tickets, coupons, comments, photos are per occurrence unless we add series-scope APIs. + +--- + +## What already shipped (do not rebuild) + +### Geo discovery + +- Events and groups have lat/lng. Events geocode `location` on create/update (`Geocode` in events DB). Failed geocode → NULL coords. +- `ListEvents` Haversine radius. In-person: city → country, never worldwide. Virtual/hybrid: global (radius does not hide them). +- UI: `geoSearch.ts` radius steps; `EventsDiscover` no longer expands to radius `0`. + +### Past / completed + +- `ListEvents`: empty `date` ⇒ `upcoming` (`end_time >= NOW()`, status published+live). `date=past` uses public statuses including completed. +- RSVP refused if ended even when status still `published` (`eventHasEnded`). +- Ended events: host may edit title, description, cover, tags only. Time/place/capacity/visibility frozen. +- Clone: `POST /api/v1/events/:slug/clone` → new **draft**. UI: Schedule again. +- Gallery heading **Glimpses** when ended. Cap 4. + +### Recurring (create path lives; discovery still wrong) + +- `POST /api/v1/events/series` + gRPC `CreateSeries`. EventForm Repeat → `createSeries()` instead of `createEvent()`. +- `rrule.go`: daily/weekly/monthly/yearly, horizon 12, cap 52. Stores RRULE; expands timestamps in service; `MaterializeSeries` inserts **published** occurrences immediately (not drafts). +- `CloneEvent` / `CancelSeriesOccurrence` exist. GetSeries / UpdateSeries / “this and future” UI / scheduler horizon fill were **not** finished. +- **List projection does not select `series_id` or recurrence text** (`eventColumns` in `events.go`). Discovery lists every occurrence as a separate card. That is the 12-card bug. + +### Profile / groups + +- Profile tabs Posts \| Events \| Groups. Events: upcoming/past via `date=`. Groups: `GET /groups/user/:username?public_only=1`. +- Group Events tab: Upcoming \| Past. +- `GetUserGroups` prefers username over account_id (so you don’t see the viewer’s groups on someone else’s profile). + +### Gateway routes (events write) + +- `POST /api/v1/events`, `POST /api/v1/events/series` (must stay **before** `/:slug`) +- `POST /api/v1/events/:slug/clone` + +--- + +## Known bugs / product gaps (next slice) + +1. **Discovery floods with series occurrences.** Weekly series of 12 shows 12 identical cards. Want 1 card (next date) plus “Repeats every …”, optionally up to 3 upcoming dates on that card — not 12 tiles. +2. **Cover only on first occurrence.** Create series → 12 rows with empty `cover_image` → host uploads cover against the first slug only. `new/page.tsx` uploads after create to that one slug. Later dates show the calendar placeholder. +3. **Slow discovery.** 12 cards, radius auto-step refetches, per-row attendee `COUNT` subquery, `log.Debugw` of full SQL, missing series collapse. UI feels heavy. +4. **Coupon duplicate.** Unique `(event_id, code)`. `CreateCoupon` does `status.Errorf(AlreadyExists, "failed to create coupon: %v", err)` → toast shows `SQLSTATE 23505`. Need a human line: “That coupon code is already on this event.” +5. **Paid ticket on a host machine without Razorpay keys.** Toast: “payments are not configured on this deployment.” Product question (answered in the plan): **Monkeys owns the Razorpay merchant for now**; organizers do not paste their own keys. Enable keys in `.env` for paid tickets; UI copy should be host-facing, not infra-facing. +6. **Last date to RSVP** — columns exist, not wired in form, gateway body, CreateEvent/UpdateEvent, or CreateRSVP. +7. **RSVP this occurrence vs entire series** — not built. Attendees are per `event_id`. + +--- + +## Conventions the user enforces + +- After backend changes: `docker compose up --build -d`. Leftover compose names (`hash_the_monkeys_events`) can block recreate; `docker rm -f` the conflict then `up -d`. +- Do not leak SQL/internal errors to the UI. +- Do not add blogs to the group tab bar. +- Do not grey-out past cards in a way that fails light theme; use an **Ended** pill. +- Recurring: reuse `event_series` / `recurring.go`, no second series table. +- Protobuf: new field numbers only; never reuse. +- Frontend lint: Prettier. Wrap long signatures/imports. `pnpm`/`prettier` live under `apps/the_monkeys/node_modules`. +- User pasted live JWTs in chat once — never put tokens in docs or logs. + +--- + +## Quick RPC / REST cheat sheet + +| Action | REST | Notes | +| --- | --- | --- | +| List discovery | `GET /api/v1/events?date=upcoming&user_lat&user_lng&radius` | Default upcoming | +| Create one-off | `POST /api/v1/events` | Draft | +| Create series | `POST /api/v1/events/series` | Body + `recurrence`; returns first occurrence; others published | +| Clone | `POST /api/v1/events/:slug/clone` | `{ start_time, end_time }` | +| Coupon | `POST /api/v1/events/:slug/coupons` | Unique per event+code | +| Paid tier | `POST /api/v1/events/:slug/tiers` | Blocked if Razorpay keys missing | +| User events | `GET /api/v1/events/user/:username?date=upcoming\|past` | Drafts not on public profile | +| User groups | `GET /api/v1/groups/user/:username?public_only=1` | | + +--- + +## Docs index + +| File | Use | +| --- | --- | +| `docs/context.md` | This handoff | +| `docs/series-ux-rsvp-payments-plan.md` | **Next work — wait for approval** | +| `docs/recurring-past-events-profile-plan.md` | Previous slice (mostly done; discovery series collapse was not in that plan) | +| `docs/meetup-parity-implementation-plan.md` | Long-term Meetup parity (groups already largely done) | +| `docs/meetup-parity-frontend-implementation-plan.md` | Frontend Meetup parity | +| Root `context.Md` | Stale geo/admin prompt — ignore | + +When in doubt: read the code in the tables above, not the stale root `context.Md`. diff --git a/microservices/the_monkeys_events/internal/database/attendees.go b/microservices/the_monkeys_events/internal/database/attendees.go index 6ea0791d..c346d506 100644 --- a/microservices/the_monkeys_events/internal/database/attendees.go +++ b/microservices/the_monkeys_events/internal/database/attendees.go @@ -31,6 +31,10 @@ type RSVPResult struct { EventSlug string Username string OrganizerUsername string + // DatesSaved is how many occurrences this request wrote (confirmed or + // waitlisted). 0/1 keeps the single-date copy; >1 is an all-upcoming RSVP. + DatesSaved int + WaitlistedDates int } // CancelResult carries what the caller needs to issue a refund and to notify @@ -63,16 +67,24 @@ func (db *eventDB) CreateRSVP(ctx context.Context, req *pb.RSVPReq) (*RSVPResult if err != nil { return err } + series, err := parseRSVPScope(req.GetScope()) + if err != nil { + return err + } + if series { + return rsvpSeriesUpcoming(ctx, tx, req, userID, out) + } // Locking the event row serialises capacity arithmetic for this event. var eventID, organizerID int64 var eventStatus string var capacity int32 var endTime time.Time + var rsvpCloses sql.NullTime if err := tx.QueryRowContext(ctx, ` - SELECT e.id, e.organizer_id, e.status, e.capacity, e.title, e.slug, e.end_time + SELECT e.id, e.organizer_id, e.status, e.capacity, e.title, e.slug, e.end_time, e.rsvp_closes_at FROM events e WHERE e.slug = $1 FOR UPDATE`, req.EventSlug, - ).Scan(&eventID, &organizerID, &eventStatus, &capacity, &out.EventTitle, &out.EventSlug, &endTime); err != nil { + ).Scan(&eventID, &organizerID, &eventStatus, &capacity, &out.EventTitle, &out.EventSlug, &endTime, &rsvpCloses); err != nil { if err == sql.ErrNoRows { return status.Error(codes.NotFound, "event not found") } @@ -84,6 +96,9 @@ func (db *eventDB) CreateRSVP(ctx context.Context, req *pb.RSVPReq) (*RSVPResult if eventHasEnded(eventStatus, endTime) { return status.Error(codes.FailedPrecondition, "event is not open for rsvp (ended)") } + if rsvpHasClosed(rsvpCloses) { + return status.Error(codes.FailedPrecondition, "RSVP for this meetup has closed.") + } if userID == organizerID { return status.Error(codes.FailedPrecondition, "the organizer is already attending") } @@ -110,85 +125,109 @@ func (db *eventDB) CreateRSVP(ctx context.Context, req *pb.RSVPReq) (*RSVPResult return status.Error(codes.Internal, "failed to load ticket tier") } - // An existing pending_payment row means the attendee abandoned or - // failed checkout; reuse it so they can retry with a fresh order. - var existingID int64 - var existingStatus string - switch err := tx.QueryRowContext(ctx, - "SELECT id, status FROM event_attendees WHERE event_id = $1 AND user_id = $2", - eventID, userID).Scan(&existingID, &existingStatus); { - case err == sql.ErrNoRows: - case err != nil: - return status.Error(codes.Internal, "failed to check existing rsvp") - case existingStatus == RSVPConfirmed || existingStatus == RSVPWaitlisted: + seat, err := applyRSVPSeat(ctx, tx, userID, eventID, req.TicketTierId, capacity, tierCapacity, price, out.Currency, req.CouponCode) + if err != nil { + return err + } + if seat.Already { return status.Error(codes.AlreadyExists, "you have already responded to this event") } - - // Give back the allowance the previous attempt held before validating - // the new code, otherwise a retry can be blocked by its own hold. - if existingID != 0 { - if err := releaseCoupon(ctx, tx, eventID, existingID); err != nil { - return err - } + out.AttendeeID = seat.AttendeeID + out.Status = seat.Status + out.AmountDue = seat.AmountDue + out.DatesSaved = 1 + if seat.Status == RSVPWaitlisted { + out.WaitlistedDates = 1 } + return nil + }) + if err != nil { + return nil, err + } + return out, nil +} - amount := price - couponCode := "" - var couponID int64 - if req.CouponCode != "" && price > 0 { - coupon, err := validateCoupon(ctx, tx, eventID, req.CouponCode) - if err != nil { - return err - } - amount = applyDiscount(price, coupon.DiscountPercent) - couponCode, couponID = coupon.Code, coupon.Id +type rsvpSeatResult struct { + AttendeeID int64 + Status string + AmountDue float64 + Already bool +} + +// applyRSVPSeat writes one attendee row. Callers hold the event row lock. +// Coupon codes only apply when amount starts from a paid price; waitlisted +// seats do not consume coupon budget. +func applyRSVPSeat(ctx context.Context, tx *sql.Tx, userID, eventID, tierID int64, eventCap, tierCap int32, price float64, currency, couponCode string) (*rsvpSeatResult, error) { + var existingID int64 + var existingStatus string + switch err := tx.QueryRowContext(ctx, + "SELECT id, status FROM event_attendees WHERE event_id = $1 AND user_id = $2", + eventID, userID).Scan(&existingID, &existingStatus); { + case err == sql.ErrNoRows: + case err != nil: + return nil, status.Error(codes.Internal, "failed to check existing rsvp") + case existingStatus == RSVPConfirmed || existingStatus == RSVPWaitlisted: + return &rsvpSeatResult{AttendeeID: existingID, Status: existingStatus, Already: true}, nil + } + + if existingID != 0 { + if err := releaseCoupon(ctx, tx, eventID, existingID); err != nil { + return nil, err } + } - full, err := seatsExhausted(ctx, tx, eventID, req.TicketTierId, capacity, tierCapacity, existingID) + amount := price + usedCode := "" + var couponID int64 + if couponCode != "" && price > 0 { + coupon, err := validateCoupon(ctx, tx, eventID, couponCode) if err != nil { - return err + return nil, err } + amount = applyDiscount(price, coupon.DiscountPercent) + usedCode, couponID = coupon.Code, coupon.Id + } - switch { - case full: - out.Status, out.AmountDue = RSVPWaitlisted, 0 - case amount > 0: - out.Status, out.AmountDue = RSVPPendingPayment, amount - default: - out.Status, out.AmountDue = RSVPConfirmed, 0 - } + full, err := seatsExhausted(ctx, tx, eventID, tierID, eventCap, tierCap, existingID) + if err != nil { + return nil, err + } - if existingID != 0 { - if _, err := tx.ExecContext(ctx, ` - UPDATE event_attendees - SET ticket_tier_id = $1, status = $2, coupon_used = $3, amount_paid = 0, - payment_order_id = NULL, payment_id = NULL, updated_at = NOW() - WHERE id = $4`, - req.TicketTierId, out.Status, nullableString(couponCode), existingID); err != nil { - return status.Errorf(codes.Internal, "failed to update rsvp: %v", err) - } - out.AttendeeID = existingID - } else { - if err := tx.QueryRowContext(ctx, ` - INSERT INTO event_attendees (event_id, user_id, ticket_tier_id, status, coupon_used, currency) - VALUES ($1,$2,$3,$4,$5,$6) RETURNING id`, - eventID, userID, req.TicketTierId, out.Status, nullableString(couponCode), out.Currency, - ).Scan(&out.AttendeeID); err != nil { - return status.Errorf(codes.Internal, "failed to create rsvp: %v", err) - } + out := &rsvpSeatResult{} + switch { + case full: + out.Status, out.AmountDue = RSVPWaitlisted, 0 + case amount > 0: + out.Status, out.AmountDue = RSVPPendingPayment, amount + default: + out.Status, out.AmountDue = RSVPConfirmed, 0 + } + + if existingID != 0 { + if _, err := tx.ExecContext(ctx, ` + UPDATE event_attendees + SET ticket_tier_id = $1, status = $2, coupon_used = $3, amount_paid = 0, + payment_order_id = NULL, payment_id = NULL, updated_at = NOW() + WHERE id = $4`, + tierID, out.Status, nullableString(usedCode), existingID); err != nil { + return nil, status.Error(codes.Internal, "failed to update rsvp") + } + out.AttendeeID = existingID + } else { + if err := tx.QueryRowContext(ctx, ` + INSERT INTO event_attendees (event_id, user_id, ticket_tier_id, status, coupon_used, currency) + VALUES ($1,$2,$3,$4,$5,$6) RETURNING id`, + eventID, userID, tierID, out.Status, nullableString(usedCode), currency, + ).Scan(&out.AttendeeID); err != nil { + return nil, status.Error(codes.Internal, "failed to create rsvp") } + } - // A waitlisted seat consumes no coupon budget. - if couponID != 0 && out.Status != RSVPWaitlisted { - if _, err := tx.ExecContext(ctx, - "UPDATE event_coupons SET current_uses = current_uses + 1 WHERE id = $1", couponID); err != nil { - return status.Error(codes.Internal, "failed to record coupon use") - } + if couponID != 0 && out.Status != RSVPWaitlisted { + if _, err := tx.ExecContext(ctx, + "UPDATE event_coupons SET current_uses = current_uses + 1 WHERE id = $1", couponID); err != nil { + return nil, status.Error(codes.Internal, "failed to record coupon use") } - return nil - }) - if err != nil { - return nil, err } return out, nil } diff --git a/microservices/the_monkeys_events/internal/database/events.go b/microservices/the_monkeys_events/internal/database/events.go index 9d9eb80c..b10cba15 100644 --- a/microservices/the_monkeys_events/internal/database/events.go +++ b/microservices/the_monkeys_events/internal/database/events.go @@ -78,19 +78,25 @@ func sanitizeVisibility(v string, groupID int64) (string, error) { const eventColumns = ` e.id, e.title, COALESCE(e.description, ''), e.slug, e.start_time, e.end_time, COALESCE(e.timezone, 'UTC'), e.event_type, COALESCE(e.location, ''), - COALESCE(e.meeting_link, ''), e.capacity, e.status, COALESCE(e.cover_image, ''), + COALESCE(e.meeting_link, ''), e.capacity, e.status, + COALESCE(NULLIF(e.cover_image, ''), es.cover_image, ''), u.account_id, u.username, e.created_at, e.updated_at, - (SELECT COUNT(1) FROM event_attendees a WHERE a.event_id = e.id AND a.status = 'confirmed'), - e.group_id, COALESCE(g.slug, ''), COALESCE(g.name, ''), COALESCE(e.visibility, 'public')` + (SELECT COUNT(1) FROM event_attendees a WHERE a.event_id = e.id AND a.status = 'confirmed') AS attendee_count, + e.group_id, COALESCE(g.slug, ''), COALESCE(g.name, ''), COALESCE(e.visibility, 'public'), + e.series_id, e.series_occurrence_at, COALESCE(es.recurrence_rule, ''), + e.rsvp_closes_at, COALESCE(es.rsvp_close_hours_before, 0)` -const eventFrom = ` FROM events e JOIN user_account u ON u.id = e.organizer_id LEFT JOIN groups g ON g.id = e.group_id` +const eventFrom = ` FROM events e JOIN user_account u ON u.id = e.organizer_id LEFT JOIN groups g ON g.id = e.group_id LEFT JOIN event_series es ON es.id = e.series_id` type rowScanner interface{ Scan(dest ...any) error } func scanEvent(row rowScanner) (*pb.Event, error) { var e pb.Event var start, end, created, updated time.Time - var groupID sql.NullInt64 + var groupID, seriesID sql.NullInt64 + var occAt, rsvpCloses sql.NullTime + var rule string + var closeHours int32 if err := row.Scan( &e.Id, &e.Title, &e.Description, &e.Slug, &start, &end, &e.Timezone, &e.EventType, &e.Location, &e.MeetingLink, @@ -98,12 +104,24 @@ func scanEvent(row rowScanner) (*pb.Event, error) { &e.OrganizerAccountId, &e.OrganizerUsername, &created, &updated, &e.AttendeeCount, &groupID, &e.GroupSlug, &e.GroupName, &e.Visibility, + &seriesID, &occAt, &rule, &rsvpCloses, &closeHours, ); err != nil { return nil, err } if groupID.Valid { e.GroupId = groupID.Int64 } + if seriesID.Valid { + e.SeriesId = seriesID.Int64 + e.RecurrenceText = recurrenceText(rule) + e.RsvpCloseHoursBefore = closeHours + } + if occAt.Valid { + e.SeriesOccurrenceAt = timestamppb.New(occAt.Time) + } + if rsvpCloses.Valid { + e.RsvpClosesAt = timestamppb.New(rsvpCloses.Time) + } e.StartTime = timestamppb.New(start) e.EndTime = timestamppb.New(end) e.CreatedAt = timestamppb.New(created) @@ -126,6 +144,9 @@ func (db *eventDB) CreateEvent(ctx context.Context, req *pb.CreateEventReq) (*pb if err := validateWindow(req.StartTime, req.EndTime); err != nil { return err } + if err := validateRsvpClosesAt(req.StartTime.AsTime(), req.RsvpClosesAt); err != nil { + return err + } if err := requireVerifiedForPaidTiers(ctx, tx, organizerID, req.TicketTiers); err != nil { return err } @@ -153,12 +174,13 @@ func (db *eventDB) CreateEvent(ctx context.Context, req *pb.CreateEventReq) (*pb INSERT INTO events ( title, description, slug, start_time, end_time, timezone, event_type, location, meeting_link, capacity, cover_image, organizer_id, - group_id, visibility, latitude, longitude - ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16) + group_id, visibility, latitude, longitude, rsvp_closes_at + ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17) RETURNING id`, req.Title, req.Description, slug, req.StartTime.AsTime(), req.EndTime.AsTime(), defaultTimezone(req.Timezone), req.EventType, req.Location, req.MeetingLink, req.Capacity, req.CoverImage, organizerID, groupCol, visibility, nullCoord(lat), nullCoord(lng), + nullableTime(req.RsvpClosesAt), ).Scan(&eventID); err != nil { return status.Errorf(codes.Internal, "failed to create event: %v", err) } @@ -214,15 +236,20 @@ func (db *eventDB) UpdateEvent(ctx context.Context, req *pb.UpdateEventReq) (*pb curStatus, curType, curLoc, curLink, curVis string curStart, curEnd time.Time curCap int32 + curSeries sql.NullInt64 + curRsvpCloses sql.NullTime ) if err := tx.QueryRowContext(ctx, ` SELECT status, start_time, end_time, event_type, COALESCE(location, ''), - COALESCE(meeting_link, ''), capacity, COALESCE(visibility, 'public') + COALESCE(meeting_link, ''), capacity, COALESCE(visibility, 'public'), + series_id, rsvp_closes_at FROM events WHERE id = $1`, eventID, - ).Scan(&curStatus, &curStart, &curEnd, &curType, &curLoc, &curLink, &curCap, &curVis); err != nil { + ).Scan(&curStatus, &curStart, &curEnd, &curType, &curLoc, &curLink, &curCap, &curVis, + &curSeries, &curRsvpCloses); err != nil { return status.Error(codes.Internal, "failed to load event") } - if eventHasEnded(curStatus, curEnd) { + ended := eventHasEnded(curStatus, curEnd) + if ended { vis := req.Visibility if vis == "" { vis = curVis @@ -260,20 +287,54 @@ func (db *eventDB) UpdateEvent(ctx context.Context, req *pb.UpdateEventReq) (*pb lat, lng := Geocode(req.Location) + rsvpClose := any(nil) + if curRsvpCloses.Valid { + rsvpClose = curRsvpCloses.Time + } + if !ended { + if curSeries.Valid { + if w := req.GetRsvpCloseHoursBefore(); w != nil { + rsvpClose = rsvpClosesValue(req.StartTime.AsTime(), w.GetValue()) + } + } else { + if err := validateRsvpClosesAt(req.StartTime.AsTime(), req.RsvpClosesAt); err != nil { + return err + } + rsvpClose = nullableTime(req.RsvpClosesAt) + } + } + if _, err := tx.ExecContext(ctx, ` UPDATE events SET title = $1, description = $2, start_time = $3, end_time = $4, timezone = $5, event_type = $6, location = $7, meeting_link = $8, capacity = $9, cover_image = $10, visibility = COALESCE(NULLIF($11, ''), visibility), - latitude = $12, longitude = $13, + latitude = $12, longitude = $13, rsvp_closes_at = $14, updated_at = NOW() - WHERE id = $14`, + WHERE id = $15`, req.Title, req.Description, req.StartTime.AsTime(), req.EndTime.AsTime(), defaultTimezone(req.Timezone), req.EventType, req.Location, req.MeetingLink, - req.Capacity, req.CoverImage, req.Visibility, nullCoord(lat), nullCoord(lng), eventID, + req.Capacity, req.CoverImage, req.Visibility, nullCoord(lat), nullCoord(lng), + rsvpClose, eventID, ); err != nil { return status.Errorf(codes.Internal, "failed to update event: %v", err) } + + if !ended && curSeries.Valid { + if w := req.GetRsvpCloseHoursBefore(); w != nil { + if err := applySeriesRsvpClose(ctx, tx, curSeries.Int64, w.GetValue()); err != nil { + return err + } + } + } + + // Series covers are one stored object. Persist the same URL on the + // series row and every sibling — do not copy blobs in MinIO. + if url := strings.TrimSpace(req.CoverImage); url != "" && curSeries.Valid { + if err := applySeriesCover(ctx, tx, curSeries.Int64, url); err != nil { + return err + } + } return replaceTags(ctx, tx, eventID, req.Tags) }) if err != nil { @@ -608,8 +669,37 @@ func commonFilters(f *filter, req *pb.ListEventsReq) { } } -// list executes the count + page queries for a built filter. -func (db *eventDB) list(ctx context.Context, req *pb.ListEventsReq, f *filter, join string) ([]*pb.Event, int32, error) { +// seriesCollapseCond keeps at most one upcoming row per series: the soonest +// published/live occurrence that has not ended. One-offs (series_id IS NULL) +// pass through unchanged. +const seriesCollapseCond = `(e.series_id IS NULL OR e.id = ( + SELECT e2.id FROM events e2 + WHERE e2.series_id = e.series_id + AND e2.status IN ('published', 'live') + AND e2.end_time >= NOW() + ORDER BY e2.start_time ASC + LIMIT 1 +))` + +func collapseDiscoverySeries(req *pb.ListEventsReq) bool { + return req.DateFilter != DateFilterPast +} + +func collapseProfileSeries(req *pb.ListEventsReq) bool { + switch req.DateFilter { + case DateFilterUpcoming, DateFilterThisWeek, DateFilterThisMonth, DateFilterAll: + return true + default: + return false + } +} + +// list executes the count + page queries for a built filter. When collapse is +// set, series siblings share one row and total counts the collapsed set. +func (db *eventDB) list(ctx context.Context, req *pb.ListEventsReq, f *filter, join string, collapse bool) ([]*pb.Event, int32, error) { + if collapse { + f.addRaw(seriesCollapseCond) + } where := f.where() var total int32 @@ -634,7 +724,7 @@ func (db *eventDB) list(ctx context.Context, req *pb.ListEventsReq, f *filter, j case SortByNewest: orderBy = "e.created_at DESC" case SortByPopular: - orderBy = "(SELECT COUNT(1) FROM event_attendees a WHERE a.event_id = e.id AND a.status = 'confirmed') DESC, e.start_time ASC" + orderBy = "attendee_count DESC, e.start_time ASC" case "nearest": if req.UserLat != 0 && req.UserLng != 0 { // Haversine sorting @@ -645,8 +735,6 @@ func (db *eventDB) list(ctx context.Context, req *pb.ListEventsReq, f *filter, j query := fmt.Sprintf("SELECT%s%s%s%s ORDER BY %s LIMIT $%d OFFSET $%d", eventColumns, eventFrom, join, where, orderBy, len(args)-1, len(args)) - db.log.Debugw("[DEBUG] list query", "sql", query, "args", args) - rows, err := db.db.QueryContext(ctx, query, args...) if err != nil { return nil, 0, status.Errorf(codes.Internal, "failed to list events: %v", err) @@ -669,6 +757,11 @@ func (db *eventDB) list(ctx context.Context, req *pb.ListEventsReq, f *filter, j if err := db.hydrate(ctx, events, false); err != nil { return nil, 0, err } + if collapse { + if err := db.hydrateUpcomingDates(ctx, events); err != nil { + return nil, 0, err + } + } return events, total, nil } @@ -688,7 +781,7 @@ func (db *eventDB) ListEvents(ctx context.Context, req *pb.ListEventsReq) ([]*pb } f.addRaw("e.visibility = 'public'") commonFilters(f, req) - return db.list(ctx, req, f, "") + return db.list(ctx, req, f, "", collapseDiscoverySeries(req)) } // GetGroupEvents lists the events attached to a community. Members (any active @@ -737,7 +830,7 @@ func (db *eventDB) GetGroupEvents(ctx context.Context, req *pb.ListEventsReq) ([ } commonFilters(f, req) - return db.list(ctx, req, f, "") + return db.list(ctx, req, f, "", false) } // GetUserEvents lists events organized by req.Username. Drafts are included @@ -765,7 +858,7 @@ func (db *eventDB) GetUserEvents(ctx context.Context, req *pb.ListEventsReq) ([] } commonFilters(f, req) - return db.list(ctx, req, f, "") + return db.list(ctx, req, f, "", collapseProfileSeries(req)) } // GetUserAttendingEvents lists events the user holds an active RSVP for. @@ -778,7 +871,7 @@ func (db *eventDB) GetUserAttendingEvents(ctx context.Context, req *pb.ListEvent join := ` JOIN event_attendees ea ON ea.event_id = e.id JOIN user_account au ON au.id = ea.user_id` - return db.list(ctx, req, f, join) + return db.list(ctx, req, f, join, false) } // isSelf reports whether the account id belongs to the given username. @@ -799,6 +892,68 @@ func (db *eventDB) isSelf(ctx context.Context, accountID, username string) (bool // Hydration // ----------------------------------------------------------------------------- +const maxUpcomingDates = 3 + +// upcomingDatesQuery loads at most maxUpcomingDates starts per series so a +// weekly series does not stream every future occurrence into the list path. +const upcomingDatesQuery = ` + SELECT series_id, start_time FROM ( + SELECT series_id, start_time, + ROW_NUMBER() OVER (PARTITION BY series_id ORDER BY start_time ASC) AS rn + FROM events + WHERE series_id = ANY($1) + AND status = ANY($2) + AND end_time >= NOW() + ) upcoming + WHERE rn <= $3` + +// hydrateUpcomingDates fills Event.UpcomingDates (max 3 starts) for collapsed +// series rows so the card can show "Sep 5 · 12 · 19" without extra round trips. +func (db *eventDB) hydrateUpcomingDates(ctx context.Context, events []*pb.Event) error { + seriesIDs := make([]int64, 0) + seen := make(map[int64]struct{}) + bySeries := make(map[int64][]*pb.Event) + for _, e := range events { + if e.SeriesId == 0 { + continue + } + if _, ok := seen[e.SeriesId]; !ok { + seen[e.SeriesId] = struct{}{} + seriesIDs = append(seriesIDs, e.SeriesId) + } + bySeries[e.SeriesId] = append(bySeries[e.SeriesId], e) + } + if len(seriesIDs) == 0 { + return nil + } + + rows, err := db.db.QueryContext(ctx, upcomingDatesQuery, seriesIDs, liveStatuses, maxUpcomingDates) + if err != nil { + return status.Errorf(codes.Internal, "failed to load series dates") + } + defer rows.Close() + + dates := make(map[int64][]*timestamppb.Timestamp, len(seriesIDs)) + for rows.Next() { + var id int64 + var start time.Time + if err := rows.Scan(&id, &start); err != nil { + return status.Errorf(codes.Internal, "failed to load series dates") + } + dates[id] = append(dates[id], timestamppb.New(start)) + } + if err := rows.Err(); err != nil { + return status.Errorf(codes.Internal, "failed to load series dates") + } + + for id, evs := range bySeries { + for _, e := range evs { + e.UpcomingDates = dates[id] + } + } + return nil +} + // hydrate attaches tags to every event and, when detail is set, also the // ticket tiers, co-hosts and reaction tallies. Each attribute is fetched with // one query for the whole batch to avoid N+1 round trips. diff --git a/microservices/the_monkeys_events/internal/database/recurrence_text_test.go b/microservices/the_monkeys_events/internal/database/recurrence_text_test.go new file mode 100644 index 00000000..43fb8b1d --- /dev/null +++ b/microservices/the_monkeys_events/internal/database/recurrence_text_test.go @@ -0,0 +1,21 @@ +package database + +import "testing" + +func TestRecurrenceText(t *testing.T) { + cases := []struct { + rule, want string + }{ + {"", "Part of a recurring series"}, + {"FREQ=WEEKLY;INTERVAL=1;BYDAY=SA", "Every week on Sat"}, + {"FREQ=WEEKLY;INTERVAL=2;BYDAY=TU,TH", "Every 2 weeks on Tue, Thu"}, + {"FREQ=DAILY;INTERVAL=1", "Every day"}, + {"FREQ=MONTHLY;INTERVAL=1", "Every month"}, + {"FREQ=YEARLY;INTERVAL=3", "Every 3 years"}, + } + for _, c := range cases { + if got := recurrenceText(c.rule); got != c.want { + t.Errorf("recurrenceText(%q) = %q, want %q", c.rule, got, c.want) + } + } +} diff --git a/microservices/the_monkeys_events/internal/database/recurring.go b/microservices/the_monkeys_events/internal/database/recurring.go index 73614c74..ab044f1c 100644 --- a/microservices/the_monkeys_events/internal/database/recurring.go +++ b/microservices/the_monkeys_events/internal/database/recurring.go @@ -3,6 +3,7 @@ package database import ( "context" "database/sql" + "fmt" "strings" "time" @@ -23,14 +24,16 @@ const ( // expansion into concrete datetimes is a service-layer concern; GroupID is 0 // for a standalone series and is resolved from a slug by the caller. type SeriesInput struct { - OrganizerAccountID string - GroupID int64 - Title string - Description string - Timezone string - RecurrenceRule string - RecurrenceStartsAt time.Time - RecurrenceEndsAt *time.Time + OrganizerAccountID string + GroupID int64 + Title string + Description string + Timezone string + RecurrenceRule string + RecurrenceStartsAt time.Time + RecurrenceEndsAt *time.Time + CoverImage string + RsvpCloseHoursBefore int32 } // OccurrenceTemplate carries the event-shaped fields stamped onto every @@ -83,12 +86,14 @@ func (db *eventDB) CreateSeries(ctx context.Context, in SeriesInput) (int64, err if err := tx.QueryRowContext(ctx, ` INSERT INTO event_series ( group_id, organizer_id, title, description, timezone, - recurrence_rule, recurrence_starts_at, recurrence_ends_at, status - ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9) + recurrence_rule, recurrence_starts_at, recurrence_ends_at, status, + cover_image, rsvp_close_hours_before + ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11) RETURNING id`, groupID, organizerID, strings.TrimSpace(in.Title), in.Description, defaultTimezone(in.Timezone), in.RecurrenceRule, in.RecurrenceStartsAt, - endsAt, seriesActive, + endsAt, seriesActive, strings.TrimSpace(in.CoverImage), + nullHours(in.RsvpCloseHoursBefore), ).Scan(&seriesID); err != nil { return status.Errorf(codes.Internal, "failed to create series: %v", err) } @@ -123,11 +128,13 @@ func (db *eventDB) GenerateSeriesOccurrences(ctx context.Context, seriesID int64 // occurrence is missing and insert it twice. var organizerID int64 var groupID sql.NullInt64 - var title, description, timezone, seriesStatus string + var title, description, timezone, seriesStatus, seriesCover string + var rsvpCloseHours int32 if err := tx.QueryRowContext(ctx, ` - SELECT organizer_id, group_id, title, COALESCE(description, ''), timezone, status + SELECT organizer_id, group_id, title, COALESCE(description, ''), timezone, status, + COALESCE(cover_image, ''), COALESCE(rsvp_close_hours_before, 0) FROM event_series WHERE id = $1 FOR UPDATE`, seriesID, - ).Scan(&organizerID, &groupID, &title, &description, &timezone, &seriesStatus); err != nil { + ).Scan(&organizerID, &groupID, &title, &description, &timezone, &seriesStatus, &seriesCover, &rsvpCloseHours); err != nil { if err == sql.ErrNoRows { return status.Error(codes.NotFound, "series not found") } @@ -136,6 +143,9 @@ func (db *eventDB) GenerateSeriesOccurrences(ctx context.Context, seriesID int64 if seriesStatus == seriesCancelled || seriesStatus == seriesCompleted { return status.Errorf(codes.FailedPrecondition, "series is %s", seriesStatus) } + if strings.TrimSpace(tmpl.CoverImage) == "" { + tmpl.CoverImage = seriesCover + } var groupCol any if groupID.Valid { @@ -160,13 +170,14 @@ func (db *eventDB) GenerateSeriesOccurrences(ctx context.Context, seriesID int64 title, description, slug, start_time, end_time, timezone, event_type, location, meeting_link, capacity, cover_image, organizer_id, group_id, visibility, status, - series_id, series_occurrence_at, latitude, longitude - ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19) + series_id, series_occurrence_at, latitude, longitude, rsvp_closes_at + ) VALUES ($1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,$13,$14,$15,$16,$17,$18,$19,$20) RETURNING id`, title, description, slug, occ, occ.Add(tmpl.Duration), defaultTimezone(timezone), tmpl.EventType, tmpl.Location, tmpl.MeetingLink, tmpl.Capacity, tmpl.CoverImage, organizerID, groupCol, visibility, StatusPublished, seriesID, occ, nullCoord(tmpl.Latitude), nullCoord(tmpl.Longitude), + rsvpClosesValue(occ, rsvpCloseHours), ).Scan(&eventID); err != nil { return status.Errorf(codes.Internal, "failed to create occurrence: %v", err) } @@ -246,8 +257,9 @@ func (db *eventDB) UpdateSeriesFutureOccurrences(ctx context.Context, seriesID i } var organizerID int64 + var seriesCover string if err := tx.QueryRowContext(ctx, - "SELECT organizer_id FROM event_series WHERE id = $1", seriesID).Scan(&organizerID); err != nil { + "SELECT organizer_id, COALESCE(cover_image, '') FROM event_series WHERE id = $1", seriesID).Scan(&organizerID, &seriesCover); err != nil { if err == sql.ErrNoRows { return status.Error(codes.NotFound, "series not found") } @@ -256,6 +268,9 @@ func (db *eventDB) UpdateSeriesFutureOccurrences(ctx context.Context, seriesID i if organizerID != actorID { return status.Error(codes.PermissionDenied, "only the series organizer can edit the series") } + if strings.TrimSpace(tmpl.CoverImage) == "" { + tmpl.CoverImage = seriesCover + } res, err := tx.ExecContext(ctx, ` UPDATE events SET @@ -286,6 +301,27 @@ func defaultVisibility(v string) string { return v } +// applySeriesCover writes the same cover URL onto the series and every +// occurrence. The URL points at the one v2 object that was uploaded; siblings +// do not get their own MinIO copies. +func applySeriesCover(ctx context.Context, tx *sql.Tx, seriesID int64, url string) error { + url = strings.TrimSpace(url) + if seriesID == 0 || url == "" { + return nil + } + if _, err := tx.ExecContext(ctx, + "UPDATE event_series SET cover_image = $1, updated_at = NOW() WHERE id = $2", + url, seriesID); err != nil { + return status.Error(codes.Internal, "failed to update series cover") + } + if _, err := tx.ExecContext(ctx, + "UPDATE events SET cover_image = $1, updated_at = NOW() WHERE series_id = $2", + url, seriesID); err != nil { + return status.Error(codes.Internal, "failed to update series cover") + } + return nil +} + func (db *eventDB) MaterializeSeries(ctx context.Context, req *pb.CreateSeriesReq, occs []time.Time, rule string) (*pb.Event, error) { if strings.TrimSpace(req.Title) == "" { return nil, status.Error(codes.InvalidArgument, "title is required") @@ -322,15 +358,26 @@ func (db *eventDB) MaterializeSeries(ctx context.Context, req *pb.CreateSeriesRe } } + hours := int32(0) + if req.Recurrence != nil { + hours = req.Recurrence.GetRsvpCloseHoursBefore() + } + hours, err := normalizeRsvpCloseHours(hours) + if err != nil { + return nil, err + } + seriesID, err := db.CreateSeries(ctx, SeriesInput{ - OrganizerAccountID: req.AccountId, - GroupID: groupID, - Title: req.Title, - Description: req.Description, - Timezone: req.Timezone, - RecurrenceRule: rule, - RecurrenceStartsAt: req.StartTime.AsTime(), - RecurrenceEndsAt: endsAt, + OrganizerAccountID: req.AccountId, + GroupID: groupID, + Title: req.Title, + Description: req.Description, + Timezone: req.Timezone, + RecurrenceRule: rule, + RecurrenceStartsAt: req.StartTime.AsTime(), + RecurrenceEndsAt: endsAt, + CoverImage: req.CoverImage, + RsvpCloseHoursBefore: hours, }) if err != nil { return nil, err @@ -359,3 +406,65 @@ func (db *eventDB) MaterializeSeries(ctx context.Context, req *pb.CreateSeriesRe event, _, err := db.GetEvent(ctx, slugs[0], req.AccountId) return event, err } + +// recurrenceText turns a stored RRULE into a short card label. Called only when +// the event belongs to a series; unknown/empty rules still get a generic line. +func recurrenceText(rule string) string { + freq, interval, byDay := parseRRULE(rule) + if freq == "" { + return "Part of a recurring series" + } + n := interval + if n < 1 { + n = 1 + } + unit := map[string][2]string{ + "DAILY": {"day", "days"}, + "WEEKLY": {"week", "weeks"}, + "MONTHLY": {"month", "months"}, + "YEARLY": {"year", "years"}, + }[freq] + if unit[0] == "" { + return "Part of a recurring series" + } + var b strings.Builder + if n == 1 { + b.WriteString("Every ") + b.WriteString(unit[0]) + } else { + fmt.Fprintf(&b, "Every %d %s", n, unit[1]) + } + if freq == "WEEKLY" && len(byDay) > 0 { + b.WriteString(" on ") + b.WriteString(strings.Join(byDay, ", ")) + } + return b.String() +} + +func parseRRULE(rule string) (freq string, interval int, byDay []string) { + interval = 1 + dayName := map[string]string{ + "MO": "Mon", "TU": "Tue", "WE": "Wed", "TH": "Thu", + "FR": "Fri", "SA": "Sat", "SU": "Sun", + } + for _, part := range strings.Split(rule, ";") { + k, v, ok := strings.Cut(strings.TrimSpace(part), "=") + if !ok || v == "" { + continue + } + switch strings.ToUpper(k) { + case "FREQ": + freq = strings.ToUpper(v) + case "INTERVAL": + fmt.Sscanf(v, "%d", &interval) + case "BYDAY": + for _, d := range strings.Split(v, ",") { + d = strings.ToUpper(strings.TrimSpace(d)) + if n, ok := dayName[d]; ok { + byDay = append(byDay, n) + } + } + } + } + return freq, interval, byDay +} diff --git a/microservices/the_monkeys_events/internal/database/rsvp_series.go b/microservices/the_monkeys_events/internal/database/rsvp_series.go new file mode 100644 index 00000000..92a57c77 --- /dev/null +++ b/microservices/the_monkeys_events/internal/database/rsvp_series.go @@ -0,0 +1,204 @@ +package database + +import ( + "context" + "database/sql" + "strconv" + "strings" + "time" + + "github.com/the-monkeys/the_monkeys/apis/serviceconn/gateway_event/pb" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +const paidSeriesRSVP = "RSVP each date separately for paid meetups." + +func parseRSVPScope(scope string) (series bool, err error) { + switch strings.ToLower(strings.TrimSpace(scope)) { + case "", "this": + return false, nil + case "series": + return true, nil + default: + return false, status.Error(codes.InvalidArgument, "scope must be this or series") + } +} + +func SeriesRSVPMessage(saved, waitlisted int) string { + if saved <= 1 { + return "" + } + confirmed := saved - waitlisted + switch { + case waitlisted == saved: + return "Those dates are full. You're on the waitlist for " + strconv.Itoa(saved) + " dates." + case waitlisted > 0 && confirmed > 0: + return "You're in for " + strconv.Itoa(confirmed) + " dates; " + strconv.Itoa(waitlisted) + " are waitlisted." + default: + return "You're in for " + strconv.Itoa(saved) + " upcoming dates." + } +} + +// rsvpSeriesUpcoming confirms a free seat on every open future occurrence in +// the clicked event's series. Paid tiers are refused. Full dates are +// waitlisted independently; already-going / closed / ended dates are skipped. +func rsvpSeriesUpcoming(ctx context.Context, tx *sql.Tx, req *pb.RSVPReq, userID int64, out *RSVPResult) error { + var clickedID, organizerID int64 + var seriesID sql.NullInt64 + if err := tx.QueryRowContext(ctx, ` + SELECT id, organizer_id, series_id, title, slug + FROM events WHERE slug = $1`, req.EventSlug, + ).Scan(&clickedID, &organizerID, &seriesID, &out.EventTitle, &out.EventSlug); err != nil { + if err == sql.ErrNoRows { + return status.Error(codes.NotFound, "event not found") + } + return status.Error(codes.Internal, "failed to load event") + } + if !seriesID.Valid { + return status.Error(codes.InvalidArgument, "this meetup is not part of a series") + } + if userID == organizerID { + return status.Error(codes.FailedPrecondition, "the organizer is already attending") + } + + var tierName string + var price float64 + if err := tx.QueryRowContext(ctx, ` + SELECT name, price, COALESCE(currency, $1) + FROM event_ticket_tiers WHERE id = $2 AND event_id = $3`, + defaultCurrency, req.TicketTierId, clickedID, + ).Scan(&tierName, &price, &out.Currency); err != nil { + if err == sql.ErrNoRows { + return status.Error(codes.NotFound, "ticket tier not found for this event") + } + return status.Error(codes.Internal, "failed to load ticket tier") + } + if price > 0 { + return status.Error(codes.FailedPrecondition, paidSeriesRSVP) + } + + if err := tx.QueryRowContext(ctx, + "SELECT username FROM user_account WHERE id = $1", userID).Scan(&out.Username); err != nil { + return status.Error(codes.Internal, "failed to load attendee") + } + if err := tx.QueryRowContext(ctx, + "SELECT username FROM user_account WHERE id = $1", organizerID).Scan(&out.OrganizerUsername); err != nil { + return status.Error(codes.Internal, "failed to load organizer") + } + + rows, err := tx.QueryContext(ctx, ` + SELECT e.id, e.status, e.capacity, e.end_time, e.rsvp_closes_at + FROM events e + WHERE e.series_id = $1 + AND e.status IN ($2, $3) + AND e.end_time >= NOW() + ORDER BY e.id + FOR UPDATE`, + seriesID.Int64, StatusPublished, StatusLive) + if err != nil { + return status.Error(codes.Internal, "failed to load series dates") + } + defer rows.Close() + + type occRow struct { + id int64 + status string + capacity int32 + endTime time.Time + rsvpCloses sql.NullTime + } + var list []occRow + clickedSeen := false + for rows.Next() { + var o occRow + if err := rows.Scan(&o.id, &o.status, &o.capacity, &o.endTime, &o.rsvpCloses); err != nil { + return status.Error(codes.Internal, "failed to load series dates") + } + if o.id == clickedID { + clickedSeen = true + } + list = append(list, o) + } + if err := rows.Err(); err != nil { + return status.Error(codes.Internal, "failed to load series dates") + } + if !clickedSeen { + return status.Error(codes.FailedPrecondition, "no upcoming dates left to RSVP") + } + + var clickedAlready bool + for _, o := range list { + if eventHasEnded(o.status, o.endTime) || rsvpHasClosed(o.rsvpCloses) { + continue + } + tierID := req.TicketTierId + var tierCap int32 + if o.id != clickedID { + id, cap, err := siblingFreeTier(ctx, tx, o.id, tierName) + if err != nil { + return err + } + if id == 0 { + continue + } + tierID, tierCap = id, cap + } else if err := tx.QueryRowContext(ctx, + "SELECT capacity FROM event_ticket_tiers WHERE id = $1 AND event_id = $2", + req.TicketTierId, o.id).Scan(&tierCap); err != nil { + return status.Error(codes.Internal, "failed to load ticket tier") + } + + seat, err := applyRSVPSeat(ctx, tx, userID, o.id, tierID, o.capacity, tierCap, 0, out.Currency, "") + if err != nil { + return err + } + if o.id == clickedID { + out.AttendeeID = seat.AttendeeID + out.Status = seat.Status + out.AmountDue = 0 + clickedAlready = seat.Already + } + if seat.Already { + continue + } + out.DatesSaved++ + if seat.Status == RSVPWaitlisted { + out.WaitlistedDates++ + } + } + + if out.DatesSaved == 0 { + if clickedAlready { + return status.Error(codes.AlreadyExists, "you have already responded to this event") + } + return status.Error(codes.FailedPrecondition, "no upcoming dates left to RSVP") + } + if out.Status == "" { + if out.WaitlistedDates == out.DatesSaved { + out.Status = RSVPWaitlisted + } else { + out.Status = RSVPConfirmed + } + } + return nil +} + +func siblingFreeTier(ctx context.Context, tx *sql.Tx, eventID int64, name string) (id int64, cap int32, err error) { + var price float64 + err = tx.QueryRowContext(ctx, ` + SELECT id, capacity, price FROM event_ticket_tiers + WHERE event_id = $1 AND lower(btrim(name)) = lower(btrim($2)) + ORDER BY sort_order ASC, id ASC + LIMIT 1`, eventID, name).Scan(&id, &cap, &price) + if err == sql.ErrNoRows { + return 0, 0, nil + } + if err != nil { + return 0, 0, status.Error(codes.Internal, "failed to load ticket tier") + } + if price > 0 { + return 0, 0, nil + } + return id, cap, nil +} diff --git a/microservices/the_monkeys_events/internal/database/rsvp_series_test.go b/microservices/the_monkeys_events/internal/database/rsvp_series_test.go new file mode 100644 index 00000000..2cadb737 --- /dev/null +++ b/microservices/the_monkeys_events/internal/database/rsvp_series_test.go @@ -0,0 +1,41 @@ +package database + +import ( + "testing" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +func TestParseRSVPScope(t *testing.T) { + series, err := parseRSVPScope("") + if err != nil || series { + t.Fatalf("empty should be this, got series=%v err=%v", series, err) + } + series, err = parseRSVPScope("this") + if err != nil || series { + t.Fatalf("this should be this, got series=%v err=%v", series, err) + } + series, err = parseRSVPScope("series") + if err != nil || !series { + t.Fatalf("series should be series, got series=%v err=%v", series, err) + } + if _, err := parseRSVPScope("all"); status.Code(err) != codes.InvalidArgument { + t.Fatalf("unknown scope should be InvalidArgument, got %v", err) + } +} + +func TestSeriesRSVPMessage(t *testing.T) { + if got := SeriesRSVPMessage(1, 0); got != "" { + t.Fatalf("single date should keep default copy, got %q", got) + } + if got := SeriesRSVPMessage(8, 0); got != "You're in for 8 upcoming dates." { + t.Fatalf("got %q", got) + } + if got := SeriesRSVPMessage(8, 2); got != "You're in for 6 dates; 2 are waitlisted." { + t.Fatalf("got %q", got) + } + if got := SeriesRSVPMessage(3, 3); got != "Those dates are full. You're on the waitlist for 3 dates." { + t.Fatalf("got %q", got) + } +} diff --git a/microservices/the_monkeys_events/internal/database/rsvp_window.go b/microservices/the_monkeys_events/internal/database/rsvp_window.go new file mode 100644 index 00000000..c89282d9 --- /dev/null +++ b/microservices/the_monkeys_events/internal/database/rsvp_window.go @@ -0,0 +1,89 @@ +package database + +import ( + "context" + "database/sql" + "time" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/timestamppb" +) + +// Off, 12 hours, 1 day, 3 days, 1 week before each occurrence start. +var allowedRsvpCloseHours = map[int32]struct{}{ + 0: {}, 12: {}, 24: {}, 72: {}, 168: {}, +} + +func normalizeRsvpCloseHours(hours int32) (int32, error) { + if hours < 0 { + return 0, status.Error(codes.InvalidArgument, "invalid RSVP close window") + } + if _, ok := allowedRsvpCloseHours[hours]; !ok { + return 0, status.Error(codes.InvalidArgument, + "RSVP close must be off, 12 hours, 1 day, 3 days, or 1 week before the start") + } + return hours, nil +} + +func rsvpClosesValue(start time.Time, hours int32) any { + if hours <= 0 { + return nil + } + return start.Add(-time.Duration(hours) * time.Hour) +} + +func validateRsvpClosesAt(start time.Time, closes *timestamppb.Timestamp) error { + if closes == nil || !closes.IsValid() { + return nil + } + t := closes.AsTime() + if t.IsZero() { + return nil + } + if !t.Before(start) { + return status.Error(codes.InvalidArgument, "RSVP must close before the meetup starts") + } + return nil +} + +func nullHours(hours int32) any { + if hours <= 0 { + return nil + } + return hours +} + +func rsvpHasClosed(closes sql.NullTime) bool { + return closes.Valid && time.Now().After(closes.Time) +} + +// applySeriesRsvpClose stores the relative offset on the series and stamps +// rsvp_closes_at on every open future occurrence. Past/cancelled dates keep +// their historical close. +func applySeriesRsvpClose(ctx context.Context, tx *sql.Tx, seriesID int64, hours int32) error { + hours, err := normalizeRsvpCloseHours(hours) + if err != nil { + return err + } + hoursCol := nullHours(hours) + if _, err := tx.ExecContext(ctx, + `UPDATE event_series SET rsvp_close_hours_before = $1, updated_at = NOW() WHERE id = $2`, + hoursCol, seriesID); err != nil { + return status.Error(codes.Internal, "failed to update series rsvp close") + } + if _, err := tx.ExecContext(ctx, ` + UPDATE events SET + rsvp_closes_at = CASE + WHEN $1::int IS NULL OR $1::int <= 0 THEN NULL + ELSE start_time - ($1::int * INTERVAL '1 hour') + END, + updated_at = NOW() + WHERE series_id = $2 + AND status IN ('draft', 'published', 'live') + AND end_time >= NOW()`, + hoursCol, seriesID); err != nil { + return status.Error(codes.Internal, "failed to update series rsvp close") + } + return nil +} diff --git a/microservices/the_monkeys_events/internal/database/rsvp_window_test.go b/microservices/the_monkeys_events/internal/database/rsvp_window_test.go new file mode 100644 index 00000000..944167cf --- /dev/null +++ b/microservices/the_monkeys_events/internal/database/rsvp_window_test.go @@ -0,0 +1,50 @@ +package database + +import ( + "testing" + "time" + + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" + "google.golang.org/protobuf/types/known/timestamppb" +) + +func TestNormalizeRsvpCloseHours(t *testing.T) { + for _, h := range []int32{0, 12, 24, 72, 168} { + got, err := normalizeRsvpCloseHours(h) + if err != nil || got != h { + t.Fatalf("hours=%d: got %d err %v", h, got, err) + } + } + if _, err := normalizeRsvpCloseHours(6); status.Code(err) != codes.InvalidArgument { + t.Fatalf("unexpected hours should be InvalidArgument, got %v", err) + } +} + +func TestRsvpClosesValue(t *testing.T) { + start := time.Date(2026, 9, 10, 18, 0, 0, 0, time.UTC) + if rsvpClosesValue(start, 0) != nil { + t.Fatal("off must store a NULL close") + } + got, ok := rsvpClosesValue(start, 24).(time.Time) + if !ok { + t.Fatal("expected a timestamp") + } + want := start.Add(-24 * time.Hour) + if !got.Equal(want) { + t.Fatalf("got %s want %s", got, want) + } +} + +func TestValidateRsvpClosesAt(t *testing.T) { + start := time.Date(2026, 9, 10, 18, 0, 0, 0, time.UTC) + if err := validateRsvpClosesAt(start, nil); err != nil { + t.Fatal(err) + } + if err := validateRsvpClosesAt(start, timestamppb.New(start.Add(-time.Hour))); err != nil { + t.Fatal(err) + } + if err := validateRsvpClosesAt(start, timestamppb.New(start)); status.Code(err) != codes.InvalidArgument { + t.Fatalf("close at start should be InvalidArgument, got %v", err) + } +} diff --git a/microservices/the_monkeys_events/internal/database/series_collapse_test.go b/microservices/the_monkeys_events/internal/database/series_collapse_test.go new file mode 100644 index 00000000..95e635f2 --- /dev/null +++ b/microservices/the_monkeys_events/internal/database/series_collapse_test.go @@ -0,0 +1,63 @@ +package database + +import ( + "strings" + "testing" + + "github.com/the-monkeys/the_monkeys/apis/serviceconn/gateway_event/pb" +) + +func TestCollapseDiscoverySeries(t *testing.T) { + if collapseDiscoverySeries(&pb.ListEventsReq{DateFilter: DateFilterPast}) { + t.Fatal("past discovery lists must keep every occurred date") + } + for _, date := range []string{"", DateFilterUpcoming, DateFilterThisWeek, DateFilterThisMonth, DateFilterAll} { + if !collapseDiscoverySeries(&pb.ListEventsReq{DateFilter: date}) { + t.Fatalf("discovery date=%q should collapse series", date) + } + } +} + +func TestCollapseProfileSeries(t *testing.T) { + if collapseProfileSeries(&pb.ListEventsReq{}) { + t.Fatal("hosting lists with no date filter must stay uncollapsed") + } + if collapseProfileSeries(&pb.ListEventsReq{DateFilter: DateFilterPast}) { + t.Fatal("profile past must keep every occurred date") + } + for _, date := range []string{DateFilterUpcoming, DateFilterThisWeek, DateFilterThisMonth, DateFilterAll} { + if !collapseProfileSeries(&pb.ListEventsReq{DateFilter: date}) { + t.Fatalf("profile date=%q should collapse series", date) + } + } +} + +func TestEventColumnsMapsSeriesCover(t *testing.T) { + if !strings.Contains(eventColumns, "es.cover_image") { + t.Fatal("list/detail must map event_series.cover_image onto occurrences") + } +} + +func TestEventColumnsMapsRsvpClose(t *testing.T) { + if !strings.Contains(eventColumns, "e.rsvp_closes_at") { + t.Fatal("list/detail must project rsvp_closes_at") + } + if !strings.Contains(eventColumns, "es.rsvp_close_hours_before") { + t.Fatal("list/detail must project series rsvp close offset") + } +} + +func TestEventColumnsAliasesAttendeeCount(t *testing.T) { + if !strings.Contains(eventColumns, "AS attendee_count") { + t.Fatal("popular sort must reuse the selected attendee_count alias") + } +} + +func TestUpcomingDatesQueryCapsPerSeries(t *testing.T) { + if !strings.Contains(upcomingDatesQuery, "ROW_NUMBER()") { + t.Fatal("upcoming dates must rank per series instead of loading every occurrence") + } + if !strings.Contains(upcomingDatesQuery, "rn <= $3") { + t.Fatal("upcoming dates must cap at maxUpcomingDates in SQL") + } +} diff --git a/microservices/the_monkeys_events/internal/database/tickets_coupons.go b/microservices/the_monkeys_events/internal/database/tickets_coupons.go index 3486eae6..ea7a629e 100644 --- a/microservices/the_monkeys_events/internal/database/tickets_coupons.go +++ b/microservices/the_monkeys_events/internal/database/tickets_coupons.go @@ -3,9 +3,11 @@ package database import ( "context" "database/sql" + "errors" "strings" "time" + "github.com/jackc/pgx/v5/pgconn" "github.com/the-monkeys/the_monkeys/apis/serviceconn/gateway_event/pb" "google.golang.org/grpc/codes" "google.golang.org/grpc/status" @@ -50,7 +52,7 @@ func insertTier(ctx context.Context, q querier, eventID int64, in *pb.TicketTier VALUES ($1,$2,$3,$4,$5,$6,$7) RETURNING id`, eventID, tier.Name, tier.Description, tier.Price, tier.Currency, tier.Capacity, tier.SortOrder, ).Scan(&tier.Id); err != nil { - return nil, status.Errorf(codes.Internal, "failed to create ticket tier: %v", err) + return nil, status.Error(codes.Internal, "failed to create ticket tier") } return tier, nil } @@ -122,7 +124,7 @@ func (db *eventDB) UpdateTicketTier(ctx context.Context, req *pb.UpdateTicketTie req.Tier.Name, req.Tier.Description, req.Tier.Price, currency, req.Tier.Capacity, req.Tier.SortOrder, req.TierId, eventID) if err != nil { - return status.Errorf(codes.Internal, "failed to update ticket tier: %v", err) + return status.Error(codes.Internal, "failed to update ticket tier") } if n, _ := res.RowsAffected(); n == 0 { return status.Error(codes.NotFound, "ticket tier not found") @@ -159,7 +161,7 @@ func (db *eventDB) DeleteTicketTier(ctx context.Context, req *pb.TierActionReq) res, err := tx.ExecContext(ctx, "DELETE FROM event_ticket_tiers WHERE id = $1 AND event_id = $2", req.TierId, eventID) if err != nil { - return status.Errorf(codes.Internal, "failed to delete ticket tier: %v", err) + return status.Error(codes.Internal, "failed to delete ticket tier") } if n, _ := res.RowsAffected(); n == 0 { return status.Error(codes.NotFound, "ticket tier not found") @@ -202,7 +204,11 @@ func (db *eventDB) CreateCoupon(ctx context.Context, req *pb.CreateCouponReq) (* eventID, code, req.DiscountPercent, req.MaxUses, nullableTime(req.ValidFrom), nullableTime(req.ValidTo), ).Scan(&coupon.Id); err != nil { - return status.Errorf(codes.AlreadyExists, "failed to create coupon: %v", err) + if isUniqueViolation(err, "event_coupons_event_id_code_key") { + return status.Error(codes.AlreadyExists, "That coupon code is already on this event.") + } + db.log.Errorw("failed to create coupon", "err", err) + return status.Error(codes.Internal, "failed to create coupon") } return nil }) @@ -219,7 +225,7 @@ func (db *eventDB) ListCoupons(ctx context.Context, req *pb.ListCouponsReq) ([]* SELECT id, code, discount_percent, max_uses, current_uses, valid_from, valid_to FROM event_coupons WHERE event_id = $1 ORDER BY id`, eventID) if err != nil { - return nil, status.Errorf(codes.Internal, "failed to list coupons: %v", err) + return nil, status.Error(codes.Internal, "failed to list coupons") } defer rows.Close() @@ -228,7 +234,7 @@ func (db *eventDB) ListCoupons(ctx context.Context, req *pb.ListCouponsReq) ([]* c := &pb.Coupon{EventId: eventID} var from, to sql.NullTime if err := rows.Scan(&c.Id, &c.Code, &c.DiscountPercent, &c.MaxUses, &c.CurrentUses, &from, &to); err != nil { - return nil, status.Errorf(codes.Internal, "failed to scan coupon: %v", err) + return nil, status.Error(codes.Internal, "failed to scan coupon") } c.ValidFrom, c.ValidTo = fromNullTime(from), fromNullTime(to) out = append(out, c) @@ -244,7 +250,7 @@ func (db *eventDB) DeleteCoupon(ctx context.Context, req *pb.CouponActionReq) er res, err := db.db.ExecContext(ctx, "DELETE FROM event_coupons WHERE id = $1 AND event_id = $2", req.CouponId, eventID) if err != nil { - return status.Errorf(codes.Internal, "failed to delete coupon: %v", err) + return status.Error(codes.Internal, "failed to delete coupon") } if n, _ := res.RowsAffected(); n == 0 { return status.Error(codes.NotFound, "coupon not found") @@ -335,3 +341,14 @@ func fromNullTime(t sql.NullTime) *timestamppb.Timestamp { } return timestamppb.New(t.Time) } + +func isUniqueViolation(err error, constraint string) bool { + var pgErr *pgconn.PgError + if !errors.As(err, &pgErr) || pgErr.Code != "23505" { + return false + } + if constraint == "" { + return true + } + return pgErr.ConstraintName == constraint +} diff --git a/microservices/the_monkeys_events/internal/database/tickets_coupons_test.go b/microservices/the_monkeys_events/internal/database/tickets_coupons_test.go new file mode 100644 index 00000000..d5f51a3d --- /dev/null +++ b/microservices/the_monkeys_events/internal/database/tickets_coupons_test.go @@ -0,0 +1,21 @@ +package database + +import ( + "fmt" + "testing" + + "github.com/jackc/pgx/v5/pgconn" +) + +func TestIsUniqueViolation(t *testing.T) { + dup := &pgconn.PgError{Code: "23505", ConstraintName: "event_coupons_event_id_code_key"} + if !isUniqueViolation(dup, "event_coupons_event_id_code_key") { + t.Fatal("expected unique coupon constraint to match") + } + if isUniqueViolation(dup, "some_other_key") { + t.Fatal("wrong constraint must not match") + } + if isUniqueViolation(fmt.Errorf("SQLSTATE 23505"), "event_coupons_event_id_code_key") { + t.Fatal("plain error string must not match") + } +} diff --git a/microservices/the_monkeys_events/internal/services/service.go b/microservices/the_monkeys_events/internal/services/service.go index 17e8acdf..ab3e0af4 100644 --- a/microservices/the_monkeys_events/internal/services/service.go +++ b/microservices/the_monkeys_events/internal/services/service.go @@ -27,6 +27,29 @@ type EventService struct { pay *razorpay } +const paidTicketsDisabled = "Paid tickets aren't enabled yet. Add a free ticket, or use ₹0 until payments are turned on." + +func (s *EventService) requirePayments(price float64) error { + if price <= 0 || s.pay.enabled() { + return nil + } + s.log.Warnw("razorpay disabled") + return status.Error(codes.FailedPrecondition, paidTicketsDisabled) +} + +func (s *EventService) rejectIfPaymentsDisabled() error { + return s.requirePayments(1) +} + +func hasPaidTier(tiers []*pb.TicketTierInput) bool { + for _, t := range tiers { + if t != nil && t.Price > 0 { + return true + } + } + return false +} + func NewEventService(db database.EventDB, log *zap.SugaredLogger, cfg *config.Config, qConn *rabbitmq.ConnManager) *EventService { return &EventService{ db: db, @@ -42,6 +65,11 @@ func NewEventService(db database.EventDB, log *zap.SugaredLogger, cfg *config.Co // ----------------------------------------------------------------------------- func (s *EventService) CreateEvent(ctx context.Context, req *pb.CreateEventReq) (*pb.EventResp, error) { + if hasPaidTier(req.TicketTiers) { + if err := s.rejectIfPaymentsDisabled(); err != nil { + return nil, err + } + } event, err := s.db.CreateEvent(ctx, req) if err != nil { return nil, err @@ -174,8 +202,8 @@ func listResp(events []*pb.Event, total int32, err error) (*pb.ListEventsResp, e // ----------------------------------------------------------------------------- func (s *EventService) CreateTicketTier(ctx context.Context, req *pb.CreateTicketTierReq) (*pb.TicketTierResp, error) { - if req.Tier.GetPrice() > 0 && !s.pay.enabled() { - return nil, status.Error(codes.FailedPrecondition, "payments are not configured on this deployment") + if err := s.requirePayments(req.Tier.GetPrice()); err != nil { + return nil, err } tier, err := s.db.CreateTicketTier(ctx, req) if err != nil { @@ -185,6 +213,9 @@ func (s *EventService) CreateTicketTier(ctx context.Context, req *pb.CreateTicke } func (s *EventService) UpdateTicketTier(ctx context.Context, req *pb.UpdateTicketTierReq) (*pb.TicketTierResp, error) { + if err := s.requirePayments(req.Tier.GetPrice()); err != nil { + return nil, err + } tier, err := s.db.UpdateTicketTier(ctx, req) if err != nil { return nil, err @@ -268,9 +299,9 @@ func (s *EventService) RSVPEvent(ctx context.Context, req *pb.RSVPReq) (*pb.RSVP }) case database.RSVPPendingPayment: - if !s.pay.enabled() { + if err := s.requirePayments(result.AmountDue); err != nil { _ = s.db.ReleaseReservation(ctx, result.AttendeeID) - return nil, status.Error(codes.FailedPrecondition, "payments are not configured on this deployment") + return nil, err } orderID, err := s.pay.createOrder(ctx, result.AmountDue, result.Currency, fmt.Sprintf("evt-rsvp-%d", result.AttendeeID)) @@ -289,6 +320,10 @@ func (s *EventService) RSVPEvent(ctx context.Context, req *pb.RSVPReq) (*pb.RSVP resp.RazorpayKeyId = s.cfg.Keys.RazorpayKeyID } + if msg := database.SeriesRSVPMessage(result.DatesSaved, result.WaitlistedDates); msg != "" { + resp.Message = msg + } + return resp, nil } @@ -511,6 +546,11 @@ func (s *EventService) CloneEvent(ctx context.Context, req *pb.CloneEventReq) (* } func (s *EventService) CreateSeries(ctx context.Context, req *pb.CreateSeriesReq) (*pb.EventResp, error) { + if hasPaidTier(req.TicketTiers) { + if err := s.rejectIfPaymentsDisabled(); err != nil { + return nil, err + } + } occs, rule, err := expandRecurrence(req.Recurrence, req.GetStartTime().AsTime()) if err != nil { return nil, err diff --git a/microservices/the_monkeys_gateway/internal/events/client.go b/microservices/the_monkeys_gateway/internal/events/client.go index 04b65efa..394ef9b7 100644 --- a/microservices/the_monkeys_gateway/internal/events/client.go +++ b/microservices/the_monkeys_gateway/internal/events/client.go @@ -80,15 +80,17 @@ func (esc *EventServiceClient) fail(ctx *gin.Context, err error, action string) st, ok := status.FromError(err) if !ok { esc.log.Errorw("events request failed", "action", action, "err", err) - ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "something went wrong"}) + ctx.AbortWithStatusJSON(http.StatusInternalServerError, gin.H{"error": "Something went wrong. Try again."}) return true } code, mapped := grpcToHTTP[st.Code()] + msg := st.Message() if !mapped { code = http.StatusInternalServerError esc.log.Errorw("events request failed", "action", action, "code", st.Code(), "err", st.Message()) + msg = "Something went wrong. Try again." } - ctx.AbortWithStatusJSON(code, gin.H{"error": st.Message()}) + ctx.AbortWithStatusJSON(code, gin.H{"error": msg}) return true } diff --git a/microservices/the_monkeys_gateway/internal/events/handler.go b/microservices/the_monkeys_gateway/internal/events/handler.go index c9c831f8..3a0badce 100644 --- a/microservices/the_monkeys_gateway/internal/events/handler.go +++ b/microservices/the_monkeys_gateway/internal/events/handler.go @@ -102,6 +102,7 @@ func (esc *EventServiceClient) CreateEvent(ctx *gin.Context) { TicketTiers: tiersToProto(body.TicketTiers), GroupSlug: body.GroupSlug, Visibility: body.Visibility, + RsvpClosesAt: toTimestamp(body.RsvpClosesAt), ClientInfo: clientInfo(ctx), }) if esc.fail(ctx, err, "create event") { @@ -172,21 +173,23 @@ func (esc *EventServiceClient) UpdateEvent(ctx *gin.Context) { } res, err := esc.Client.UpdateEvent(ctx, &pb.UpdateEventReq{ - Slug: ctx.Param("slug"), - AccountId: accountID(ctx), - Title: body.Title, - Description: body.Description, - StartTime: toTimestamp(&body.StartTime), - EndTime: toTimestamp(&body.EndTime), - Timezone: body.Timezone, - EventType: body.EventType, - Location: body.Location, - MeetingLink: body.MeetingLink, - Capacity: body.Capacity, - CoverImage: body.CoverImage, - Tags: body.Tags, - Visibility: body.Visibility, - ClientInfo: clientInfo(ctx), + Slug: ctx.Param("slug"), + AccountId: accountID(ctx), + Title: body.Title, + Description: body.Description, + StartTime: toTimestamp(&body.StartTime), + EndTime: toTimestamp(&body.EndTime), + Timezone: body.Timezone, + EventType: body.EventType, + Location: body.Location, + MeetingLink: body.MeetingLink, + Capacity: body.Capacity, + CoverImage: body.CoverImage, + Tags: body.Tags, + Visibility: body.Visibility, + RsvpClosesAt: toTimestamp(body.RsvpClosesAt), + RsvpCloseHoursBefore: int32Value(body.RsvpCloseHoursBefore), + ClientInfo: clientInfo(ctx), }) if esc.fail(ctx, err, "update event") { @@ -242,14 +245,6 @@ func (esc *EventServiceClient) GetEvent(ctx *gin.Context) { func (esc *EventServiceClient) ListEvents(ctx *gin.Context) { req := listQuery(ctx) - esc.log.Debugw("[DEBUG] ListEvents filters", - "type", req.EventType, - "date", req.DateFilter, - "sort", req.SortBy, - "q", req.Query, - "location", req.Location, - "tags", req.Tags, - ) res, err := esc.Client.ListEvents(ctx, req) if esc.fail(ctx, err, "list events") { return @@ -431,6 +426,7 @@ func (esc *EventServiceClient) RSVP(ctx *gin.Context) { AccountId: accountID(ctx), TicketTierId: body.TicketTierID, CouponCode: body.CouponCode, + Scope: body.Scope, ClientInfo: clientInfo(ctx), }) if esc.fail(ctx, err, "rsvp") { diff --git a/microservices/the_monkeys_gateway/internal/events/models.go b/microservices/the_monkeys_gateway/internal/events/models.go index 039d09de..a20e700e 100644 --- a/microservices/the_monkeys_gateway/internal/events/models.go +++ b/microservices/the_monkeys_gateway/internal/events/models.go @@ -5,6 +5,7 @@ import ( "github.com/the-monkeys/the_monkeys/apis/serviceconn/gateway_event/pb" "google.golang.org/protobuf/types/known/timestamppb" + "google.golang.org/protobuf/types/known/wrapperspb" ) // EventBody is the JSON payload for creating and updating an event. @@ -27,14 +28,19 @@ type EventBody struct { GroupSlug string `json:"group_slug"` Visibility string `json:"visibility" binding:"omitempty,oneof=public group_members private unlisted"` Recurrence *RecurrenceBody `json:"recurrence"` + // One-off last day to RSVP. Empty = open until the event ends. + RsvpClosesAt *time.Time `json:"rsvp_closes_at"` + // Series edits: 0 = Off. Omitted on one-off updates. + RsvpCloseHoursBefore *int32 `json:"rsvp_close_hours_before"` } type RecurrenceBody struct { - Freq string `json:"freq"` - Interval int32 `json:"interval"` - ByDay []string `json:"by_day"` - Count int32 `json:"count"` - Until *time.Time `json:"until"` + Freq string `json:"freq"` + Interval int32 `json:"interval"` + ByDay []string `json:"by_day"` + Count int32 `json:"count"` + Until *time.Time `json:"until"` + RsvpCloseHoursBefore int32 `json:"rsvp_close_hours_before"` } func (r *RecurrenceBody) toProto() *pb.Recurrence { @@ -46,11 +52,12 @@ func (r *RecurrenceBody) toProto() *pb.Recurrence { interval = 1 } return &pb.Recurrence{ - Freq: r.Freq, - Interval: interval, - ByDay: r.ByDay, - Count: r.Count, - Until: toTimestamp(r.Until), + Freq: r.Freq, + Interval: interval, + ByDay: r.ByDay, + Count: r.Count, + Until: toTimestamp(r.Until), + RsvpCloseHoursBefore: r.RsvpCloseHoursBefore, } } @@ -101,6 +108,7 @@ type CouponBody struct { type RSVPBody struct { TicketTierID int64 `json:"ticket_tier_id" binding:"required"` CouponCode string `json:"coupon_code"` + Scope string `json:"scope" binding:"omitempty,oneof=this series"` } // CommentBody is the JSON payload for posting a comment. @@ -135,3 +143,10 @@ func toTimestamp(t *time.Time) *timestamppb.Timestamp { } return timestamppb.New(*t) } + +func int32Value(p *int32) *wrapperspb.Int32Value { + if p == nil { + return nil + } + return wrapperspb.Int32(*p) +} diff --git a/schema/000015_event_series_cover.down.sql b/schema/000015_event_series_cover.down.sql new file mode 100644 index 00000000..77a9603c --- /dev/null +++ b/schema/000015_event_series_cover.down.sql @@ -0,0 +1 @@ +ALTER TABLE event_series DROP COLUMN IF EXISTS cover_image; diff --git a/schema/000015_event_series_cover.up.sql b/schema/000015_event_series_cover.up.sql new file mode 100644 index 00000000..388bcf50 --- /dev/null +++ b/schema/000015_event_series_cover.up.sql @@ -0,0 +1,3 @@ +-- Canonical cover URL for a recurring series. Occurrences store the same +-- path string (one MinIO object); they do not each get a copied blob. +ALTER TABLE event_series ADD COLUMN IF NOT EXISTS cover_image TEXT; diff --git a/schema/000016_event_series_rsvp_close.down.sql b/schema/000016_event_series_rsvp_close.down.sql new file mode 100644 index 00000000..91bb3061 --- /dev/null +++ b/schema/000016_event_series_rsvp_close.down.sql @@ -0,0 +1 @@ +ALTER TABLE event_series DROP COLUMN IF EXISTS rsvp_close_hours_before; diff --git a/schema/000016_event_series_rsvp_close.up.sql b/schema/000016_event_series_rsvp_close.up.sql new file mode 100644 index 00000000..820f7dff --- /dev/null +++ b/schema/000016_event_series_rsvp_close.up.sql @@ -0,0 +1,4 @@ +-- Relative RSVP close for a recurring series (hours before each occurrence +-- start). NULL/0 means no extra close; events.rsvp_closes_at stays the +-- per-date timestamp that CreateRSVP enforces. +ALTER TABLE event_series ADD COLUMN IF NOT EXISTS rsvp_close_hours_before INTEGER NULL; diff --git a/schema/000017_event_list_indexes.down.sql b/schema/000017_event_list_indexes.down.sql new file mode 100644 index 00000000..4ab70e69 --- /dev/null +++ b/schema/000017_event_list_indexes.down.sql @@ -0,0 +1,2 @@ +DROP INDEX IF EXISTS idx_event_attendees_confirmed; +DROP INDEX IF EXISTS idx_events_series_upcoming; diff --git a/schema/000017_event_list_indexes.up.sql b/schema/000017_event_list_indexes.up.sql new file mode 100644 index 00000000..bcacb562 --- /dev/null +++ b/schema/000017_event_list_indexes.up.sql @@ -0,0 +1,9 @@ +-- Speeds discovery collapse (soonest upcoming row per series) and the +-- per-row confirmed-attendee COUNT used by list + popular sort. +CREATE INDEX IF NOT EXISTS idx_events_series_upcoming + ON events (series_id, start_time) + WHERE series_id IS NOT NULL AND status IN ('published', 'live'); + +CREATE INDEX IF NOT EXISTS idx_event_attendees_confirmed + ON event_attendees (event_id) + WHERE status = 'confirmed';