From 5f7977ec3f4f354376599e4175f23cd267a7d43c Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Sat, 16 Sep 2023 17:56:23 +0200 Subject: [PATCH] changed the feedback api --- server/api/tumdev/campus_backend.pb.go | 1194 ++++++++--------- server/api/tumdev/campus_backend.pb.gw.go | 201 +-- server/api/tumdev/campus_backend.proto | 53 +- server/api/tumdev/campus_backend.swagger.json | 115 +- server/api/tumdev/campus_backend_grpc.pb.go | 114 +- server/backend/feedback.go | 161 +++ server/backend/feedback_test.go | 117 ++ 7 files changed, 1028 insertions(+), 927 deletions(-) create mode 100644 server/backend/feedback.go create mode 100644 server/backend/feedback_test.go diff --git a/server/api/tumdev/campus_backend.pb.go b/server/api/tumdev/campus_backend.pb.go index 0ccd6398..1cbf96b6 100644 --- a/server/api/tumdev/campus_backend.pb.go +++ b/server/api/tumdev/campus_backend.pb.go @@ -72,6 +72,52 @@ func (DeviceType) EnumDescriptor() ([]byte, []int) { return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{0} } +type SendFeedbackRequest_FeedbackTopic int32 + +const ( + SendFeedbackRequest_TUM_DEV SendFeedbackRequest_FeedbackTopic = 0 + SendFeedbackRequest_TUM_CONTACT SendFeedbackRequest_FeedbackTopic = 1 +) + +// Enum value maps for SendFeedbackRequest_FeedbackTopic. +var ( + SendFeedbackRequest_FeedbackTopic_name = map[int32]string{ + 0: "TUM_DEV", + 1: "TUM_CONTACT", + } + SendFeedbackRequest_FeedbackTopic_value = map[string]int32{ + "TUM_DEV": 0, + "TUM_CONTACT": 1, + } +) + +func (x SendFeedbackRequest_FeedbackTopic) Enum() *SendFeedbackRequest_FeedbackTopic { + p := new(SendFeedbackRequest_FeedbackTopic) + *p = x + return p +} + +func (x SendFeedbackRequest_FeedbackTopic) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (SendFeedbackRequest_FeedbackTopic) Descriptor() protoreflect.EnumDescriptor { + return file_tumdev_campus_backend_proto_enumTypes[1].Descriptor() +} + +func (SendFeedbackRequest_FeedbackTopic) Type() protoreflect.EnumType { + return &file_tumdev_campus_backend_proto_enumTypes[1] +} + +func (x SendFeedbackRequest_FeedbackTopic) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use SendFeedbackRequest_FeedbackTopic.Descriptor instead. +func (SendFeedbackRequest_FeedbackTopic) EnumDescriptor() ([]byte, []int) { + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{59, 0} +} + type RegisterDeviceRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -3696,64 +3742,27 @@ func (x *Movie) GetLink() string { return "" } -type SendFeedbackReply struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields -} - -func (x *SendFeedbackReply) Reset() { - *x = SendFeedbackReply{} - if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[59] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SendFeedbackReply) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SendFeedbackReply) ProtoMessage() {} - -func (x *SendFeedbackReply) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[59] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SendFeedbackReply.ProtoReflect.Descriptor instead. -func (*SendFeedbackReply) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{59} -} - type SendFeedbackRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - Topic string `protobuf:"bytes,1,opt,name=topic,proto3" json:"topic,omitempty"` - Email string `protobuf:"bytes,2,opt,name=email,proto3" json:"email,omitempty"` - EmailId string `protobuf:"bytes,3,opt,name=email_id,json=emailId,proto3" json:"email_id,omitempty"` - Message string `protobuf:"bytes,4,opt,name=message,proto3" json:"message,omitempty"` - ImageCount int32 `protobuf:"varint,5,opt,name=image_count,json=imageCount,proto3" json:"image_count,omitempty"` - Latitude float64 `protobuf:"fixed64,6,opt,name=latitude,proto3" json:"latitude,omitempty"` - Longitude float64 `protobuf:"fixed64,7,opt,name=longitude,proto3" json:"longitude,omitempty"` - OsVersion string `protobuf:"bytes,8,opt,name=os_version,json=osVersion,proto3" json:"os_version,omitempty"` - AppVersion string `protobuf:"bytes,9,opt,name=app_version,json=appVersion,proto3" json:"app_version,omitempty"` + // who is the feedback for + Topic SendFeedbackRequest_FeedbackTopic `protobuf:"varint,1,opt,name=topic,proto3,enum=api.SendFeedbackRequest_FeedbackTopic" json:"topic,omitempty"` + // the email address of the user + FromEmail string `protobuf:"bytes,2,opt,name=from_email,json=fromEmail,proto3" json:"from_email,omitempty"` + // The actual message + Message string `protobuf:"bytes,3,opt,name=message,proto3" json:"message,omitempty"` + // Optional metadata which the user can choose to attach or not + Metadata *SendFeedbackRequest_Metadata `protobuf:"bytes,4,opt,name=metadata,proto3" json:"metadata,omitempty"` + // Optional file in Base64 + Image []byte `protobuf:"bytes,5,opt,name=image,proto3" json:"image,omitempty"` } func (x *SendFeedbackRequest) Reset() { *x = SendFeedbackRequest{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[60] + mi := &file_tumdev_campus_backend_proto_msgTypes[59] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3766,7 +3775,7 @@ func (x *SendFeedbackRequest) String() string { func (*SendFeedbackRequest) ProtoMessage() {} func (x *SendFeedbackRequest) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[60] + mi := &file_tumdev_campus_backend_proto_msgTypes[59] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3779,26 +3788,19 @@ func (x *SendFeedbackRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use SendFeedbackRequest.ProtoReflect.Descriptor instead. func (*SendFeedbackRequest) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{60} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{59} } -func (x *SendFeedbackRequest) GetTopic() string { +func (x *SendFeedbackRequest) GetTopic() SendFeedbackRequest_FeedbackTopic { if x != nil { return x.Topic } - return "" -} - -func (x *SendFeedbackRequest) GetEmail() string { - if x != nil { - return x.Email - } - return "" + return SendFeedbackRequest_TUM_DEV } -func (x *SendFeedbackRequest) GetEmailId() string { +func (x *SendFeedbackRequest) GetFromEmail() string { if x != nil { - return x.EmailId + return x.FromEmail } return "" } @@ -3810,114 +3812,43 @@ func (x *SendFeedbackRequest) GetMessage() string { return "" } -func (x *SendFeedbackRequest) GetImageCount() int32 { - if x != nil { - return x.ImageCount - } - return 0 -} - -func (x *SendFeedbackRequest) GetLatitude() float64 { - if x != nil { - return x.Latitude - } - return 0 -} - -func (x *SendFeedbackRequest) GetLongitude() float64 { - if x != nil { - return x.Longitude - } - return 0 -} - -func (x *SendFeedbackRequest) GetOsVersion() string { - if x != nil { - return x.OsVersion - } - return "" -} - -func (x *SendFeedbackRequest) GetAppVersion() string { +func (x *SendFeedbackRequest) GetMetadata() *SendFeedbackRequest_Metadata { if x != nil { - return x.AppVersion + return x.Metadata } - return "" -} - -type SendFeedbackImageReply struct { - state protoimpl.MessageState - sizeCache protoimpl.SizeCache - unknownFields protoimpl.UnknownFields - - Status string `protobuf:"bytes,1,opt,name=status,proto3" json:"status,omitempty"` -} - -func (x *SendFeedbackImageReply) Reset() { - *x = SendFeedbackImageReply{} - if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[61] - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - ms.StoreMessageInfo(mi) - } -} - -func (x *SendFeedbackImageReply) String() string { - return protoimpl.X.MessageStringOf(x) -} - -func (*SendFeedbackImageReply) ProtoMessage() {} - -func (x *SendFeedbackImageReply) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[61] - if protoimpl.UnsafeEnabled && x != nil { - ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) - if ms.LoadMessageInfo() == nil { - ms.StoreMessageInfo(mi) - } - return ms - } - return mi.MessageOf(x) -} - -// Deprecated: Use SendFeedbackImageReply.ProtoReflect.Descriptor instead. -func (*SendFeedbackImageReply) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{61} + return nil } -func (x *SendFeedbackImageReply) GetStatus() string { +func (x *SendFeedbackRequest) GetImage() []byte { if x != nil { - return x.Status + return x.Image } - return "" + return nil } -type SendFeedbackImageRequest struct { +type SendFeedbackReply struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields - - Id int32 `protobuf:"varint,1,opt,name=id,proto3" json:"id,omitempty"` - ImageNr int32 `protobuf:"varint,2,opt,name=image_nr,json=imageNr,proto3" json:"image_nr,omitempty"` //todo where does the file come from? } -func (x *SendFeedbackImageRequest) Reset() { - *x = SendFeedbackImageRequest{} +func (x *SendFeedbackReply) Reset() { + *x = SendFeedbackReply{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[62] + mi := &file_tumdev_campus_backend_proto_msgTypes[60] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } } -func (x *SendFeedbackImageRequest) String() string { +func (x *SendFeedbackReply) String() string { return protoimpl.X.MessageStringOf(x) } -func (*SendFeedbackImageRequest) ProtoMessage() {} +func (*SendFeedbackReply) ProtoMessage() {} -func (x *SendFeedbackImageRequest) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[62] +func (x *SendFeedbackReply) ProtoReflect() protoreflect.Message { + mi := &file_tumdev_campus_backend_proto_msgTypes[60] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3928,23 +3859,9 @@ func (x *SendFeedbackImageRequest) ProtoReflect() protoreflect.Message { return mi.MessageOf(x) } -// Deprecated: Use SendFeedbackImageRequest.ProtoReflect.Descriptor instead. -func (*SendFeedbackImageRequest) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{62} -} - -func (x *SendFeedbackImageRequest) GetId() int32 { - if x != nil { - return x.Id - } - return 0 -} - -func (x *SendFeedbackImageRequest) GetImageNr() int32 { - if x != nil { - return x.ImageNr - } - return 0 +// Deprecated: Use SendFeedbackReply.ProtoReflect.Descriptor instead. +func (*SendFeedbackReply) Descriptor() ([]byte, []int) { + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{60} } type GetMembersRequest struct { @@ -3958,7 +3875,7 @@ type GetMembersRequest struct { func (x *GetMembersRequest) Reset() { *x = GetMembersRequest{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[63] + mi := &file_tumdev_campus_backend_proto_msgTypes[61] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -3971,7 +3888,7 @@ func (x *GetMembersRequest) String() string { func (*GetMembersRequest) ProtoMessage() {} func (x *GetMembersRequest) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[63] + mi := &file_tumdev_campus_backend_proto_msgTypes[61] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -3984,7 +3901,7 @@ func (x *GetMembersRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMembersRequest.ProtoReflect.Descriptor instead. func (*GetMembersRequest) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{63} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{61} } func (x *GetMembersRequest) GetLrzId() string { @@ -4007,7 +3924,7 @@ type GetMembersReply struct { func (x *GetMembersReply) Reset() { *x = GetMembersReply{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[64] + mi := &file_tumdev_campus_backend_proto_msgTypes[62] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4020,7 +3937,7 @@ func (x *GetMembersReply) String() string { func (*GetMembersReply) ProtoMessage() {} func (x *GetMembersReply) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[64] + mi := &file_tumdev_campus_backend_proto_msgTypes[62] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4033,7 +3950,7 @@ func (x *GetMembersReply) ProtoReflect() protoreflect.Message { // Deprecated: Use GetMembersReply.ProtoReflect.Descriptor instead. func (*GetMembersReply) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{64} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{62} } func (x *GetMembersReply) GetLrzId() string { @@ -4068,7 +3985,7 @@ type GetUploadStatusRequest struct { func (x *GetUploadStatusRequest) Reset() { *x = GetUploadStatusRequest{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[65] + mi := &file_tumdev_campus_backend_proto_msgTypes[63] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4081,7 +3998,7 @@ func (x *GetUploadStatusRequest) String() string { func (*GetUploadStatusRequest) ProtoMessage() {} func (x *GetUploadStatusRequest) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[65] + mi := &file_tumdev_campus_backend_proto_msgTypes[63] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4094,7 +4011,7 @@ func (x *GetUploadStatusRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUploadStatusRequest.ProtoReflect.Descriptor instead. func (*GetUploadStatusRequest) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{65} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{63} } func (x *GetUploadStatusRequest) GetLrzId() string { @@ -4119,7 +4036,7 @@ type GetUploadStatusReply struct { func (x *GetUploadStatusReply) Reset() { *x = GetUploadStatusReply{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[66] + mi := &file_tumdev_campus_backend_proto_msgTypes[64] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4132,7 +4049,7 @@ func (x *GetUploadStatusReply) String() string { func (*GetUploadStatusReply) ProtoMessage() {} func (x *GetUploadStatusReply) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[66] + mi := &file_tumdev_campus_backend_proto_msgTypes[64] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4145,7 +4062,7 @@ func (x *GetUploadStatusReply) ProtoReflect() protoreflect.Message { // Deprecated: Use GetUploadStatusReply.ProtoReflect.Descriptor instead. func (*GetUploadStatusReply) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{66} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{64} } func (x *GetUploadStatusReply) GetFcmToken() string { @@ -4194,7 +4111,7 @@ type GetNotificationRequest struct { func (x *GetNotificationRequest) Reset() { *x = GetNotificationRequest{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[67] + mi := &file_tumdev_campus_backend_proto_msgTypes[65] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4207,7 +4124,7 @@ func (x *GetNotificationRequest) String() string { func (*GetNotificationRequest) ProtoMessage() {} func (x *GetNotificationRequest) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[67] + mi := &file_tumdev_campus_backend_proto_msgTypes[65] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4220,7 +4137,7 @@ func (x *GetNotificationRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetNotificationRequest.ProtoReflect.Descriptor instead. func (*GetNotificationRequest) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{67} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{65} } func (x *GetNotificationRequest) GetNotificationId() int32 { @@ -4245,7 +4162,7 @@ type GetNotificationReply struct { func (x *GetNotificationReply) Reset() { *x = GetNotificationReply{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[68] + mi := &file_tumdev_campus_backend_proto_msgTypes[66] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4258,7 +4175,7 @@ func (x *GetNotificationReply) String() string { func (*GetNotificationReply) ProtoMessage() {} func (x *GetNotificationReply) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[68] + mi := &file_tumdev_campus_backend_proto_msgTypes[66] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4271,7 +4188,7 @@ func (x *GetNotificationReply) ProtoReflect() protoreflect.Message { // Deprecated: Use GetNotificationReply.ProtoReflect.Descriptor instead. func (*GetNotificationReply) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{68} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{66} } func (x *GetNotificationReply) GetNotificationId() int32 { @@ -4320,7 +4237,7 @@ type GetNotificationConfirmRequest struct { func (x *GetNotificationConfirmRequest) Reset() { *x = GetNotificationConfirmRequest{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[69] + mi := &file_tumdev_campus_backend_proto_msgTypes[67] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4333,7 +4250,7 @@ func (x *GetNotificationConfirmRequest) String() string { func (*GetNotificationConfirmRequest) ProtoMessage() {} func (x *GetNotificationConfirmRequest) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[69] + mi := &file_tumdev_campus_backend_proto_msgTypes[67] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4346,7 +4263,7 @@ func (x *GetNotificationConfirmRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetNotificationConfirmRequest.ProtoReflect.Descriptor instead. func (*GetNotificationConfirmRequest) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{69} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{67} } func (x *GetNotificationConfirmRequest) GetNotificationId() int32 { @@ -4367,7 +4284,7 @@ type GetNotificationConfirmReply struct { func (x *GetNotificationConfirmReply) Reset() { *x = GetNotificationConfirmReply{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[70] + mi := &file_tumdev_campus_backend_proto_msgTypes[68] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4380,7 +4297,7 @@ func (x *GetNotificationConfirmReply) String() string { func (*GetNotificationConfirmReply) ProtoMessage() {} func (x *GetNotificationConfirmReply) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[70] + mi := &file_tumdev_campus_backend_proto_msgTypes[68] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4393,7 +4310,7 @@ func (x *GetNotificationConfirmReply) ProtoReflect() protoreflect.Message { // Deprecated: Use GetNotificationConfirmReply.ProtoReflect.Descriptor instead. func (*GetNotificationConfirmReply) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{70} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{68} } func (x *GetNotificationConfirmReply) GetStatus() string { @@ -4415,7 +4332,7 @@ type GetCanteenHeadCountRequest struct { func (x *GetCanteenHeadCountRequest) Reset() { *x = GetCanteenHeadCountRequest{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[71] + mi := &file_tumdev_campus_backend_proto_msgTypes[69] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4428,7 +4345,7 @@ func (x *GetCanteenHeadCountRequest) String() string { func (*GetCanteenHeadCountRequest) ProtoMessage() {} func (x *GetCanteenHeadCountRequest) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[71] + mi := &file_tumdev_campus_backend_proto_msgTypes[69] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4441,7 +4358,7 @@ func (x *GetCanteenHeadCountRequest) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCanteenHeadCountRequest.ProtoReflect.Descriptor instead. func (*GetCanteenHeadCountRequest) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{71} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{69} } func (x *GetCanteenHeadCountRequest) GetCanteenId() string { @@ -4469,7 +4386,7 @@ type GetCanteenHeadCountReply struct { func (x *GetCanteenHeadCountReply) Reset() { *x = GetCanteenHeadCountReply{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[72] + mi := &file_tumdev_campus_backend_proto_msgTypes[70] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4482,7 +4399,7 @@ func (x *GetCanteenHeadCountReply) String() string { func (*GetCanteenHeadCountReply) ProtoMessage() {} func (x *GetCanteenHeadCountReply) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[72] + mi := &file_tumdev_campus_backend_proto_msgTypes[70] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4495,7 +4412,7 @@ func (x *GetCanteenHeadCountReply) ProtoReflect() protoreflect.Message { // Deprecated: Use GetCanteenHeadCountReply.ProtoReflect.Descriptor instead. func (*GetCanteenHeadCountReply) Descriptor() ([]byte, []int) { - return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{72} + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{70} } func (x *GetCanteenHeadCountReply) GetCount() uint32 { @@ -4539,7 +4456,7 @@ type GetMoreInformationReply_MoreInformation struct { func (x *GetMoreInformationReply_MoreInformation) Reset() { *x = GetMoreInformationReply_MoreInformation{} if protoimpl.UnsafeEnabled { - mi := &file_tumdev_campus_backend_proto_msgTypes[73] + mi := &file_tumdev_campus_backend_proto_msgTypes[71] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -4552,7 +4469,7 @@ func (x *GetMoreInformationReply_MoreInformation) String() string { func (*GetMoreInformationReply_MoreInformation) ProtoMessage() {} func (x *GetMoreInformationReply_MoreInformation) ProtoReflect() protoreflect.Message { - mi := &file_tumdev_campus_backend_proto_msgTypes[73] + mi := &file_tumdev_campus_backend_proto_msgTypes[71] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -4589,6 +4506,77 @@ func (x *GetMoreInformationReply_MoreInformation) GetUrl() string { return "" } +type SendFeedbackRequest_Metadata struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Latitude float64 `protobuf:"fixed64,1,opt,name=latitude,proto3" json:"latitude,omitempty"` + Longitude float64 `protobuf:"fixed64,2,opt,name=longitude,proto3" json:"longitude,omitempty"` + OsVersion string `protobuf:"bytes,3,opt,name=osVersion,proto3" json:"osVersion,omitempty"` + AppVersion string `protobuf:"bytes,4,opt,name=appVersion,proto3" json:"appVersion,omitempty"` +} + +func (x *SendFeedbackRequest_Metadata) Reset() { + *x = SendFeedbackRequest_Metadata{} + if protoimpl.UnsafeEnabled { + mi := &file_tumdev_campus_backend_proto_msgTypes[72] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *SendFeedbackRequest_Metadata) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*SendFeedbackRequest_Metadata) ProtoMessage() {} + +func (x *SendFeedbackRequest_Metadata) ProtoReflect() protoreflect.Message { + mi := &file_tumdev_campus_backend_proto_msgTypes[72] + if protoimpl.UnsafeEnabled && x != nil { + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + if ms.LoadMessageInfo() == nil { + ms.StoreMessageInfo(mi) + } + return ms + } + return mi.MessageOf(x) +} + +// Deprecated: Use SendFeedbackRequest_Metadata.ProtoReflect.Descriptor instead. +func (*SendFeedbackRequest_Metadata) Descriptor() ([]byte, []int) { + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{59, 0} +} + +func (x *SendFeedbackRequest_Metadata) GetLatitude() float64 { + if x != nil { + return x.Latitude + } + return 0 +} + +func (x *SendFeedbackRequest_Metadata) GetLongitude() float64 { + if x != nil { + return x.Longitude + } + return 0 +} + +func (x *SendFeedbackRequest_Metadata) GetOsVersion() string { + if x != nil { + return x.OsVersion + } + return "" +} + +func (x *SendFeedbackRequest_Metadata) GetAppVersion() string { + if x != nil { + return x.AppVersion + } + return "" +} + var File_tumdev_campus_backend_proto protoreflect.FileDescriptor var file_tumdev_campus_backend_proto_rawDesc = []byte{ @@ -4994,236 +4982,230 @@ var file_tumdev_campus_backend_proto_rawDesc = []byte{ 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x19, 0x0a, 0x08, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x03, 0x52, 0x07, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x18, 0x10, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x22, 0x13, - 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x22, 0x91, 0x02, 0x0a, 0x13, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, - 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x14, 0x0a, 0x05, 0x74, - 0x6f, 0x70, 0x69, 0x63, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x74, 0x6f, 0x70, 0x69, - 0x63, 0x12, 0x14, 0x0a, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x05, 0x65, 0x6d, 0x61, 0x69, 0x6c, 0x12, 0x19, 0x0a, 0x08, 0x65, 0x6d, 0x61, 0x69, 0x6c, - 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x65, 0x6d, 0x61, 0x69, 0x6c, - 0x49, 0x64, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x1f, 0x0a, 0x0b, - 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x05, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x0a, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1a, 0x0a, - 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x06, 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, 0x07, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, 0x6c, 0x6f, - 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1d, 0x0a, 0x0a, 0x6f, 0x73, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x73, 0x56, - 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1f, 0x0a, 0x0b, 0x61, 0x70, 0x70, 0x5f, 0x76, 0x65, - 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x09, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x70, - 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x30, 0x0a, 0x16, 0x53, 0x65, 0x6e, 0x64, 0x46, - 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, + 0x28, 0x09, 0x52, 0x04, 0x6c, 0x69, 0x6e, 0x6b, 0x4a, 0x04, 0x08, 0x0f, 0x10, 0x10, 0x22, 0x95, + 0x03, 0x0a, 0x13, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x3c, 0x0a, 0x05, 0x74, 0x6f, 0x70, 0x69, 0x63, 0x18, + 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, 0x26, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, + 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, + 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x52, 0x05, 0x74, + 0x6f, 0x70, 0x69, 0x63, 0x12, 0x1d, 0x0a, 0x0a, 0x66, 0x72, 0x6f, 0x6d, 0x5f, 0x65, 0x6d, 0x61, + 0x69, 0x6c, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x66, 0x72, 0x6f, 0x6d, 0x45, 0x6d, + 0x61, 0x69, 0x6c, 0x12, 0x18, 0x0a, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x18, 0x03, + 0x20, 0x01, 0x28, 0x09, 0x52, 0x07, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x12, 0x3d, 0x0a, + 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x18, 0x04, 0x20, 0x01, 0x28, 0x0b, 0x32, + 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, + 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x2e, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, + 0x74, 0x61, 0x52, 0x08, 0x6d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, 0x14, 0x0a, 0x05, + 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x0c, 0x52, 0x05, 0x69, 0x6d, 0x61, + 0x67, 0x65, 0x1a, 0x82, 0x01, 0x0a, 0x08, 0x4d, 0x65, 0x74, 0x61, 0x64, 0x61, 0x74, 0x61, 0x12, + 0x1a, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 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, 0x02, 0x20, 0x01, 0x28, 0x01, 0x52, 0x09, + 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x12, 0x1c, 0x0a, 0x09, 0x6f, 0x73, 0x56, + 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x6f, 0x73, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x0a, 0x0a, 0x61, 0x70, 0x70, 0x56, 0x65, + 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x61, 0x70, 0x70, + 0x56, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x22, 0x2d, 0x0a, 0x0d, 0x46, 0x65, 0x65, 0x64, 0x62, + 0x61, 0x63, 0x6b, 0x54, 0x6f, 0x70, 0x69, 0x63, 0x12, 0x0b, 0x0a, 0x07, 0x54, 0x55, 0x4d, 0x5f, + 0x44, 0x45, 0x56, 0x10, 0x00, 0x12, 0x0f, 0x0a, 0x0b, 0x54, 0x55, 0x4d, 0x5f, 0x43, 0x4f, 0x4e, + 0x54, 0x41, 0x43, 0x54, 0x10, 0x01, 0x22, 0x13, 0x0a, 0x11, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, + 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x2a, 0x0a, 0x11, 0x47, + 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x12, 0x15, 0x0a, 0x06, 0x6c, 0x72, 0x7a, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x05, 0x6c, 0x72, 0x7a, 0x49, 0x64, 0x22, 0x59, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x15, 0x0a, 0x06, 0x6c, 0x72, + 0x7a, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x72, 0x7a, 0x49, + 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x5f, + 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, 0x65, 0x6d, 0x62, 0x65, 0x72, + 0x49, 0x64, 0x22, 0x2f, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, + 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, + 0x6c, 0x72, 0x7a, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x72, + 0x7a, 0x49, 0x64, 0x22, 0xb3, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, + 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x1b, 0x0a, 0x09, + 0x66, 0x63, 0x6d, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, + 0x08, 0x66, 0x63, 0x6d, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, 0x0a, 0x0a, 0x70, 0x75, 0x62, + 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x70, + 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a, 0x0a, 0x73, 0x74, 0x75, 0x64, + 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x08, 0x52, 0x09, 0x73, 0x74, + 0x75, 0x64, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x6d, 0x70, 0x6c, 0x6f, + 0x79, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x65, 0x6d, + 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, 0x65, 0x78, 0x74, 0x65, + 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, 0x28, 0x08, 0x52, 0x0a, 0x65, + 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x22, 0x41, 0x0a, 0x16, 0x47, 0x65, 0x74, + 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6e, 0x6f, + 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0xa9, 0x01, 0x0a, + 0x14, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, + 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x12, 0x12, + 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x04, 0x74, 0x79, + 0x70, 0x65, 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, 0x1c, 0x0a, 0x09, 0x73, 0x69, + 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x73, + 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x48, 0x0a, 0x1d, 0x47, 0x65, 0x74, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, + 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x52, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x49, 0x64, 0x22, 0x35, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x45, 0x0a, 0x18, 0x53, 0x65, 0x6e, - 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x0e, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x02, 0x69, 0x64, 0x12, 0x19, 0x0a, 0x08, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x6e, - 0x72, 0x18, 0x02, 0x20, 0x01, 0x28, 0x05, 0x52, 0x07, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x4e, 0x72, - 0x22, 0x2a, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6c, 0x72, 0x7a, 0x5f, 0x69, 0x64, 0x18, - 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x05, 0x6c, 0x72, 0x7a, 0x49, 0x64, 0x22, 0x59, 0x0a, 0x0f, - 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, - 0x15, 0x0a, 0x06, 0x6c, 0x72, 0x7a, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x05, 0x6c, 0x72, 0x7a, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x65, - 0x6d, 0x62, 0x65, 0x72, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, 0x05, 0x52, 0x08, 0x6d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x49, 0x64, 0x22, 0x2f, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x55, 0x70, - 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x12, 0x15, 0x0a, 0x06, 0x6c, 0x72, 0x7a, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x05, 0x6c, 0x72, 0x7a, 0x49, 0x64, 0x22, 0xb3, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, - 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x70, 0x6c, - 0x79, 0x12, 0x1b, 0x0a, 0x09, 0x66, 0x63, 0x6d, 0x5f, 0x74, 0x6f, 0x6b, 0x65, 0x6e, 0x18, 0x01, - 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x66, 0x63, 0x6d, 0x54, 0x6f, 0x6b, 0x65, 0x6e, 0x12, 0x1d, - 0x0a, 0x0a, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x5f, 0x6b, 0x65, 0x79, 0x18, 0x02, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x70, 0x75, 0x62, 0x6c, 0x69, 0x63, 0x4b, 0x65, 0x79, 0x12, 0x1d, 0x0a, - 0x0a, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x03, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x09, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x1f, 0x0a, 0x0b, - 0x65, 0x6d, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x65, 0x5f, 0x69, 0x64, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x08, 0x52, 0x0a, 0x65, 0x6d, 0x70, 0x6c, 0x6f, 0x79, 0x65, 0x65, 0x49, 0x64, 0x12, 0x1f, 0x0a, - 0x0b, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x5f, 0x69, 0x64, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x08, 0x52, 0x0a, 0x65, 0x78, 0x74, 0x65, 0x72, 0x6e, 0x61, 0x6c, 0x49, 0x64, 0x22, 0x41, - 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x69, - 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, - 0x64, 0x22, 0xa9, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x27, 0x0a, 0x0f, 0x6e, 0x6f, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, - 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x05, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 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, - 0x1c, 0x0a, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x18, 0x05, 0x20, 0x01, - 0x28, 0x09, 0x52, 0x09, 0x73, 0x69, 0x67, 0x6e, 0x61, 0x74, 0x75, 0x72, 0x65, 0x22, 0x48, 0x0a, - 0x1d, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, - 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x27, - 0x0a, 0x0f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, - 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x05, 0x52, 0x0e, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, - 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x49, 0x64, 0x22, 0x35, 0x0a, 0x1b, 0x47, 0x65, 0x74, 0x4e, 0x6f, - 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, - 0x6d, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x16, 0x0a, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, - 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3b, - 0x0a, 0x1a, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x48, 0x65, 0x61, 0x64, - 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, - 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, - 0x52, 0x09, 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x49, 0x64, 0x22, 0xa1, 0x01, 0x0a, 0x18, - 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, - 0x74, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, - 0x0a, 0x09, 0x6d, 0x61, 0x78, 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, - 0x0d, 0x52, 0x08, 0x6d, 0x61, 0x78, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, - 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x07, 0x70, 0x65, - 0x72, 0x63, 0x65, 0x6e, 0x74, 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, - 0x6d, 0x70, 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, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2a, - 0x2f, 0x0a, 0x0a, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, - 0x03, 0x49, 0x4f, 0x53, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4e, 0x44, 0x52, 0x4f, 0x49, - 0x44, 0x10, 0x01, 0x12, 0x0b, 0x0a, 0x07, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x53, 0x10, 0x02, - 0x32, 0xde, 0x18, 0x0a, 0x06, 0x43, 0x61, 0x6d, 0x70, 0x75, 0x73, 0x12, 0x4d, 0x0a, 0x0a, 0x47, - 0x65, 0x74, 0x54, 0x6f, 0x70, 0x4e, 0x65, 0x77, 0x73, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x4e, 0x65, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x4e, 0x65, - 0x77, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0b, 0x12, - 0x09, 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x2f, 0x74, 0x6f, 0x70, 0x12, 0x66, 0x0a, 0x0e, 0x47, 0x65, - 0x74, 0x4e, 0x65, 0x77, 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, - 0x65, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x70, - 0x6c, 0x79, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x62, 0x07, 0x73, 0x6f, 0x75, 0x72, - 0x63, 0x65, 0x73, 0x12, 0x0d, 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, - 0x65, 0x73, 0x12, 0x55, 0x0a, 0x07, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x12, 0x13, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x11, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x73, - 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x62, 0x04, 0x6e, - 0x65, 0x77, 0x73, 0x12, 0x14, 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x2f, 0x7b, 0x6c, 0x61, 0x73, 0x74, - 0x5f, 0x6e, 0x65, 0x77, 0x73, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x68, 0x0a, 0x0b, 0x53, 0x65, 0x61, - 0x72, 0x63, 0x68, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x6f, - 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, - 0x3a, 0x01, 0x2a, 0x62, 0x05, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x22, 0x17, 0x2f, 0x72, 0x6f, 0x6f, - 0x6d, 0x66, 0x69, 0x6e, 0x64, 0x65, 0x72, 0x2f, 0x72, 0x6f, 0x6f, 0x6d, 0x2f, 0x73, 0x65, 0x61, - 0x72, 0x63, 0x68, 0x12, 0x6f, 0x0a, 0x11, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, - 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, - 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, - 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, - 0x13, 0x2f, 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x2f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, - 0x2f, 0x67, 0x65, 0x74, 0x12, 0x63, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x68, 0x52, - 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, - 0x44, 0x69, 0x73, 0x68, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x68, - 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1b, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x64, 0x69, 0x73, 0x68, 0x2f, 0x72, - 0x61, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x67, 0x65, 0x74, 0x12, 0x6c, 0x0a, 0x10, 0x4e, 0x65, 0x77, - 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x4e, 0x65, 0x77, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, - 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x4e, 0x65, 0x77, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, - 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, - 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x2f, 0x72, 0x61, 0x74, - 0x69, 0x6e, 0x67, 0x2f, 0x6e, 0x65, 0x77, 0x12, 0x60, 0x0a, 0x0d, 0x4e, 0x65, 0x77, 0x44, 0x69, - 0x73, 0x68, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, - 0x65, 0x77, 0x44, 0x69, 0x73, 0x68, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, 0x65, 0x77, 0x44, 0x69, 0x73, - 0x68, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1b, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x15, 0x3a, 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x64, 0x69, 0x73, 0x68, 0x2f, 0x72, - 0x61, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x6e, 0x65, 0x77, 0x12, 0x89, 0x01, 0x0a, 0x14, 0x47, 0x65, - 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x69, 0x73, 0x68, 0x54, 0x61, - 0x67, 0x73, 0x12, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, - 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x69, 0x73, 0x68, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, - 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x69, 0x73, 0x68, 0x54, 0x61, 0x67, 0x73, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x22, 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x62, 0x0b, 0x72, 0x61, - 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1a, 0x2f, 0x64, 0x69, 0x73, 0x68, - 0x2f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x61, 0x6c, 0x6c, 0x52, 0x61, 0x74, 0x69, 0x6e, - 0x67, 0x54, 0x61, 0x67, 0x73, 0x12, 0x6c, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, - 0x54, 0x61, 0x67, 0x73, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x22, 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x62, 0x0b, 0x72, 0x61, - 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x18, 0x2f, 0x64, 0x69, 0x73, 0x68, - 0x2f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x73, 0x68, 0x54, - 0x61, 0x67, 0x73, 0x12, 0x95, 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, - 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x54, 0x61, 0x67, 0x73, 0x12, - 0x23, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, - 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, - 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x54, 0x61, - 0x67, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x62, - 0x0b, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1d, 0x2f, 0x63, - 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x2f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x61, 0x6c, - 0x6c, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x67, 0x73, 0x12, 0x64, 0x0a, 0x0b, 0x47, - 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x73, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, - 0x74, 0x65, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1f, 0x62, 0x07, 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x12, 0x14, 0x2f, 0x63, 0x61, - 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x2f, 0x61, 0x6c, 0x6c, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, - 0x73, 0x12, 0x56, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x68, 0x65, 0x73, 0x12, 0x15, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, - 0x69, 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x17, 0x62, 0x04, 0x64, 0x69, 0x73, 0x68, 0x12, 0x0f, 0x2f, 0x64, 0x69, 0x73, 0x68, 0x2f, - 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x73, 0x68, 0x65, 0x73, 0x12, 0x77, 0x0a, 0x14, 0x47, 0x65, 0x74, - 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x73, 0x6f, - 0x6e, 0x12, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, - 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, - 0x70, 0x6f, 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x62, 0x61, - 0x72, 0x72, 0x69, 0x65, 0x72, 0x66, 0x72, 0x65, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, - 0x74, 0x73, 0x12, 0x78, 0x0a, 0x12, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x72, 0x65, 0x49, 0x6e, 0x66, - 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, - 0x65, 0x74, 0x4d, 0x6f, 0x72, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, - 0x65, 0x74, 0x4d, 0x6f, 0x72, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, - 0x2f, 0x62, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, 0x66, 0x72, 0x65, 0x65, 0x2f, 0x6d, 0x6f, 0x72, - 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6b, 0x0a, 0x0f, - 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, - 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, - 0x54, 0x69, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, - 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, - 0x18, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x2f, 0x7b, - 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x7d, 0x12, 0x62, 0x0a, 0x0d, 0x47, 0x65, 0x74, - 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x47, 0x65, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x52, 0x65, - 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x55, - 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1d, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x6e, - 0x6f, 0x74, 0x65, 0x2f, 0x7b, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x12, 0x61, 0x0a, - 0x10, 0x47, 0x65, 0x74, 0x53, 0x74, 0x75, 0x64, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, - 0x74, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x75, 0x64, 0x79, - 0x52, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, - 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x75, 0x64, 0x79, 0x52, 0x6f, - 0x6f, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x13, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x0d, 0x12, 0x0b, 0x2f, 0x73, 0x74, 0x75, 0x64, 0x79, 0x72, 0x6f, 0x6f, 0x6d, 0x73, - 0x12, 0x52, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x76, 0x69, 0x65, 0x73, 0x12, 0x15, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x76, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, - 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, - 0x76, 0x69, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, - 0x13, 0x12, 0x11, 0x2f, 0x6d, 0x6f, 0x76, 0x69, 0x65, 0x73, 0x2f, 0x7b, 0x6c, 0x61, 0x73, 0x74, - 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x53, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, - 0x62, 0x61, 0x63, 0x6b, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x46, - 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, - 0x6b, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0b, 0x22, 0x09, - 0x2f, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x72, 0x0a, 0x11, 0x53, 0x65, 0x6e, - 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x1d, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, - 0x6b, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1b, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, - 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x21, 0x82, 0xd3, 0xe4, 0x93, - 0x02, 0x1b, 0x22, 0x19, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x2f, 0x7b, 0x69, - 0x64, 0x7d, 0x2f, 0x7b, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x5f, 0x6e, 0x72, 0x7d, 0x12, 0x6c, 0x0a, + 0x09, 0x52, 0x06, 0x73, 0x74, 0x61, 0x74, 0x75, 0x73, 0x22, 0x3b, 0x0a, 0x1a, 0x47, 0x65, 0x74, + 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x1d, 0x0a, 0x0a, 0x63, 0x61, 0x6e, 0x74, 0x65, + 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x09, 0x63, 0x61, 0x6e, + 0x74, 0x65, 0x65, 0x6e, 0x49, 0x64, 0x22, 0xa1, 0x01, 0x0a, 0x18, 0x47, 0x65, 0x74, 0x43, 0x61, + 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x0d, 0x52, 0x05, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x61, 0x78, + 0x5f, 0x63, 0x6f, 0x75, 0x6e, 0x74, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0d, 0x52, 0x08, 0x6d, 0x61, + 0x78, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x18, 0x0a, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, + 0x74, 0x18, 0x03, 0x20, 0x01, 0x28, 0x02, 0x52, 0x07, 0x70, 0x65, 0x72, 0x63, 0x65, 0x6e, 0x74, + 0x12, 0x38, 0x0a, 0x09, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 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, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x2a, 0x2f, 0x0a, 0x0a, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x07, 0x0a, 0x03, 0x49, 0x4f, 0x53, 0x10, + 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x41, 0x4e, 0x44, 0x52, 0x4f, 0x49, 0x44, 0x10, 0x01, 0x12, 0x0b, + 0x0a, 0x07, 0x57, 0x49, 0x4e, 0x44, 0x4f, 0x57, 0x53, 0x10, 0x02, 0x32, 0xf3, 0x17, 0x0a, 0x06, + 0x43, 0x61, 0x6d, 0x70, 0x75, 0x73, 0x12, 0x4d, 0x0a, 0x0a, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, + 0x4e, 0x65, 0x77, 0x73, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6f, + 0x70, 0x4e, 0x65, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x54, 0x6f, 0x70, 0x4e, 0x65, 0x77, 0x73, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x22, 0x11, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0b, 0x12, 0x09, 0x2f, 0x6e, 0x65, 0x77, + 0x73, 0x2f, 0x74, 0x6f, 0x70, 0x12, 0x66, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x73, + 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, + 0x74, 0x4e, 0x65, 0x77, 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, + 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1e, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x62, 0x07, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x0d, + 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x2f, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x55, 0x0a, + 0x07, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x12, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, + 0x65, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x11, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x22, 0x22, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1c, 0x62, 0x04, 0x6e, 0x65, 0x77, 0x73, 0x12, 0x14, + 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x2f, 0x7b, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6e, 0x65, 0x77, 0x73, + 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x68, 0x0a, 0x0b, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x6f, + 0x6f, 0x6d, 0x73, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, + 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x53, 0x65, 0x61, 0x72, 0x63, 0x68, 0x52, 0x6f, 0x6f, 0x6d, 0x73, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x22, 0x29, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x23, 0x3a, 0x01, 0x2a, 0x62, 0x05, + 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x22, 0x17, 0x2f, 0x72, 0x6f, 0x6f, 0x6d, 0x66, 0x69, 0x6e, 0x64, + 0x65, 0x72, 0x2f, 0x72, 0x6f, 0x6f, 0x6d, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x12, 0x6f, + 0x0a, 0x11, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, + 0x6e, 0x67, 0x73, 0x12, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, + 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, + 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, + 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, 0x63, 0x61, 0x6e, + 0x74, 0x65, 0x65, 0x6e, 0x2f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x67, 0x65, 0x74, 0x12, + 0x63, 0x0a, 0x0e, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x68, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, + 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x68, 0x52, + 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x68, 0x52, 0x61, 0x74, 0x69, 0x6e, + 0x67, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, + 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x64, 0x69, 0x73, 0x68, 0x2f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, + 0x2f, 0x67, 0x65, 0x74, 0x12, 0x6c, 0x0a, 0x10, 0x4e, 0x65, 0x77, 0x43, 0x61, 0x6e, 0x74, 0x65, + 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, + 0x65, 0x77, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x52, + 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, 0x65, 0x77, + 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x22, 0x1e, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x18, 0x3a, 0x01, 0x2a, 0x22, 0x13, 0x2f, + 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x2f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x6e, + 0x65, 0x77, 0x12, 0x60, 0x0a, 0x0d, 0x4e, 0x65, 0x77, 0x44, 0x69, 0x73, 0x68, 0x52, 0x61, 0x74, + 0x69, 0x6e, 0x67, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, 0x65, 0x77, 0x44, 0x69, 0x73, + 0x68, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x17, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4e, 0x65, 0x77, 0x44, 0x69, 0x73, 0x68, 0x52, 0x61, 0x74, 0x69, + 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x3a, + 0x01, 0x2a, 0x22, 0x10, 0x2f, 0x64, 0x69, 0x73, 0x68, 0x2f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, + 0x2f, 0x6e, 0x65, 0x77, 0x12, 0x89, 0x01, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, + 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x69, 0x73, 0x68, 0x54, 0x61, 0x67, 0x73, 0x12, 0x20, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, + 0x44, 0x69, 0x73, 0x68, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, + 0x6c, 0x65, 0x44, 0x69, 0x73, 0x68, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, + 0x2f, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x29, 0x62, 0x0b, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, + 0x74, 0x61, 0x67, 0x73, 0x12, 0x1a, 0x2f, 0x64, 0x69, 0x73, 0x68, 0x2f, 0x72, 0x61, 0x74, 0x69, + 0x6e, 0x67, 0x2f, 0x61, 0x6c, 0x6c, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x54, 0x61, 0x67, 0x73, + 0x12, 0x6c, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x67, 0x73, 0x12, + 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x67, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, + 0x65, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, + 0x2d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x27, 0x62, 0x0b, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x5f, + 0x74, 0x61, 0x67, 0x73, 0x12, 0x18, 0x2f, 0x64, 0x69, 0x73, 0x68, 0x2f, 0x72, 0x61, 0x74, 0x69, + 0x6e, 0x67, 0x2f, 0x61, 0x6c, 0x6c, 0x44, 0x69, 0x73, 0x68, 0x54, 0x61, 0x67, 0x73, 0x12, 0x95, + 0x01, 0x0a, 0x17, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, + 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x54, 0x61, 0x67, 0x73, 0x12, 0x23, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x6e, + 0x74, 0x65, 0x65, 0x6e, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, + 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x22, 0x32, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2c, 0x62, 0x0b, 0x72, 0x61, 0x74, 0x69, + 0x6e, 0x67, 0x5f, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1d, 0x2f, 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, + 0x6e, 0x2f, 0x72, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x2f, 0x61, 0x6c, 0x6c, 0x52, 0x61, 0x74, 0x69, + 0x6e, 0x67, 0x54, 0x61, 0x67, 0x73, 0x12, 0x64, 0x0a, 0x0b, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, + 0x74, 0x65, 0x65, 0x6e, 0x73, 0x12, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, + 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x15, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x73, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x25, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1f, 0x62, 0x07, 0x63, + 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x12, 0x14, 0x2f, 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, + 0x2f, 0x61, 0x6c, 0x6c, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x73, 0x12, 0x56, 0x0a, 0x09, + 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x68, 0x65, 0x73, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x44, 0x69, 0x73, 0x68, 0x65, 0x73, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x62, 0x04, 0x64, + 0x69, 0x73, 0x68, 0x12, 0x0f, 0x2f, 0x64, 0x69, 0x73, 0x68, 0x2f, 0x61, 0x6c, 0x6c, 0x44, 0x69, + 0x73, 0x68, 0x65, 0x73, 0x12, 0x77, 0x0a, 0x14, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, + 0x6e, 0x73, 0x69, 0x62, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x12, 0x20, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x69, 0x62, 0x6c, + 0x65, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1e, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x52, 0x65, 0x73, 0x70, 0x6f, 0x6e, 0x73, 0x69, + 0x62, 0x6c, 0x65, 0x50, 0x65, 0x72, 0x73, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1d, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x12, 0x15, 0x2f, 0x62, 0x61, 0x72, 0x72, 0x69, 0x65, 0x72, + 0x66, 0x72, 0x65, 0x65, 0x2f, 0x63, 0x6f, 0x6e, 0x74, 0x61, 0x63, 0x74, 0x73, 0x12, 0x78, 0x0a, + 0x12, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x72, 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x72, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x72, + 0x65, 0x49, 0x6e, 0x66, 0x6f, 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x22, 0x24, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1e, 0x12, 0x1c, 0x2f, 0x62, 0x61, 0x72, 0x72, + 0x69, 0x65, 0x72, 0x66, 0x72, 0x65, 0x65, 0x2f, 0x6d, 0x6f, 0x72, 0x65, 0x49, 0x6e, 0x66, 0x6f, + 0x72, 0x6d, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x6b, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4f, 0x70, + 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x47, 0x65, 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x73, + 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, + 0x74, 0x4f, 0x70, 0x65, 0x6e, 0x69, 0x6e, 0x67, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x22, 0x20, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1a, 0x12, 0x18, 0x2f, 0x6f, 0x70, 0x65, + 0x6e, 0x69, 0x6e, 0x67, 0x74, 0x69, 0x6d, 0x65, 0x73, 0x2f, 0x7b, 0x6c, 0x61, 0x6e, 0x67, 0x75, + 0x61, 0x67, 0x65, 0x7d, 0x12, 0x62, 0x0a, 0x0d, 0x47, 0x65, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, + 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x12, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x55, + 0x70, 0x64, 0x61, 0x74, 0x65, 0x4e, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x17, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x70, 0x64, 0x61, 0x74, 0x65, + 0x4e, 0x6f, 0x74, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x17, 0x12, 0x15, 0x2f, 0x75, 0x70, 0x64, 0x61, 0x74, 0x65, 0x6e, 0x6f, 0x74, 0x65, 0x2f, 0x7b, + 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x7d, 0x12, 0x61, 0x0a, 0x10, 0x47, 0x65, 0x74, 0x53, + 0x74, 0x75, 0x64, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, 0x74, 0x12, 0x1c, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x75, 0x64, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x4c, + 0x69, 0x73, 0x74, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x47, 0x65, 0x74, 0x53, 0x74, 0x75, 0x64, 0x79, 0x52, 0x6f, 0x6f, 0x6d, 0x4c, 0x69, 0x73, + 0x74, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x12, 0x0b, + 0x2f, 0x73, 0x74, 0x75, 0x64, 0x79, 0x72, 0x6f, 0x6f, 0x6d, 0x73, 0x12, 0x52, 0x0a, 0x09, 0x47, + 0x65, 0x74, 0x4d, 0x6f, 0x76, 0x69, 0x65, 0x73, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, + 0x65, 0x74, 0x4d, 0x6f, 0x76, 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x13, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x6f, 0x76, 0x69, 0x65, 0x73, 0x52, + 0x65, 0x70, 0x6c, 0x79, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x6d, + 0x6f, 0x76, 0x69, 0x65, 0x73, 0x2f, 0x7b, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x69, 0x64, 0x7d, 0x12, + 0x5c, 0x0a, 0x0c, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x12, + 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, + 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x53, 0x65, 0x6e, 0x64, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, + 0x79, 0x22, 0x18, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x12, 0x3a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, + 0x22, 0x09, 0x2f, 0x66, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x28, 0x01, 0x12, 0x6c, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, @@ -5303,186 +5285,186 @@ func file_tumdev_campus_backend_proto_rawDescGZIP() []byte { return file_tumdev_campus_backend_proto_rawDescData } -var file_tumdev_campus_backend_proto_enumTypes = make([]protoimpl.EnumInfo, 1) -var file_tumdev_campus_backend_proto_msgTypes = make([]protoimpl.MessageInfo, 74) +var file_tumdev_campus_backend_proto_enumTypes = make([]protoimpl.EnumInfo, 2) +var file_tumdev_campus_backend_proto_msgTypes = make([]protoimpl.MessageInfo, 73) var file_tumdev_campus_backend_proto_goTypes = []interface{}{ (DeviceType)(0), // 0: api.DeviceType - (*RegisterDeviceRequest)(nil), // 1: api.RegisterDeviceRequest - (*RegisterDeviceReply)(nil), // 2: api.RegisterDeviceReply - (*RemoveDeviceRequest)(nil), // 3: api.RemoveDeviceRequest - (*RemoveDeviceReply)(nil), // 4: api.RemoveDeviceReply - (*IOSDeviceRequestResponseRequest)(nil), // 5: api.IOSDeviceRequestResponseRequest - (*IOSDeviceRequestResponseReply)(nil), // 6: api.IOSDeviceRequestResponseReply - (*SearchRoomsRequest)(nil), // 7: api.SearchRoomsRequest - (*SearchRoomsReply)(nil), // 8: api.SearchRoomsReply - (*Room)(nil), // 9: api.Room - (*News)(nil), // 10: api.News - (*GetNewsReply)(nil), // 11: api.GetNewsReply - (*GetNewsRequest)(nil), // 12: api.GetNewsRequest - (*GetNewsSourcesRequest)(nil), // 13: api.GetNewsSourcesRequest - (*GetNewsSourcesReply)(nil), // 14: api.GetNewsSourcesReply - (*NewsSource)(nil), // 15: api.NewsSource - (*GetTopNewsRequest)(nil), // 16: api.GetTopNewsRequest - (*GetTopNewsReply)(nil), // 17: api.GetTopNewsReply - (*GetCanteenRatingsRequest)(nil), // 18: api.GetCanteenRatingsRequest - (*GetCanteenRatingsReply)(nil), // 19: api.GetCanteenRatingsReply - (*GetDishRatingsRequest)(nil), // 20: api.GetDishRatingsRequest - (*GetDishRatingsReply)(nil), // 21: api.GetDishRatingsReply - (*SingleRatingReply)(nil), // 22: api.SingleRatingReply - (*NewCanteenRatingReply)(nil), // 23: api.NewCanteenRatingReply - (*NewCanteenRatingRequest)(nil), // 24: api.NewCanteenRatingRequest - (*NewDishRatingReply)(nil), // 25: api.NewDishRatingReply - (*NewDishRatingRequest)(nil), // 26: api.NewDishRatingRequest - (*GetAvailableDishTagsRequest)(nil), // 27: api.GetAvailableDishTagsRequest - (*GetAvailableDishTagsReply)(nil), // 28: api.GetAvailableDishTagsReply - (*GetNameTagsRequest)(nil), // 29: api.GetNameTagsRequest - (*GetNameTagsReply)(nil), // 30: api.GetNameTagsReply - (*GetAvailableCanteenTagsRequest)(nil), // 31: api.GetAvailableCanteenTagsRequest - (*GetAvailableCanteenTagsReply)(nil), // 32: api.GetAvailableCanteenTagsReply - (*TagsOverview)(nil), // 33: api.TagsOverview - (*RatingTag)(nil), // 34: api.RatingTag - (*RatingTagNewRequest)(nil), // 35: api.RatingTagNewRequest - (*RatingTagResult)(nil), // 36: api.RatingTagResult - (*GetCanteensRequest)(nil), // 37: api.GetCanteensRequest - (*GetCanteensReply)(nil), // 38: api.GetCanteensReply - (*Canteen)(nil), // 39: api.Canteen - (*GetDishesRequest)(nil), // 40: api.GetDishesRequest - (*GetDishesReply)(nil), // 41: api.GetDishesReply - (*GetResponsiblePersonRequest)(nil), // 42: api.GetResponsiblePersonRequest - (*GetResponsiblePersonReply)(nil), // 43: api.GetResponsiblePersonReply - (*ResponsiblePerson)(nil), // 44: api.ResponsiblePerson - (*RoomInformationElement)(nil), // 45: api.RoomInformationElement - (*GetMoreInformationRequest)(nil), // 46: api.GetMoreInformationRequest - (*GetMoreInformationReply)(nil), // 47: api.GetMoreInformationReply - (*GetOpeningTimesRequest)(nil), // 48: api.GetOpeningTimesRequest - (*GetOpeningTimesReply)(nil), // 49: api.GetOpeningTimesReply - (*OpeningTimesMsgElement)(nil), // 50: api.OpeningTimesMsgElement - (*GetUpdateNoteRequest)(nil), // 51: api.GetUpdateNoteRequest - (*GetUpdateNoteReply)(nil), // 52: api.GetUpdateNoteReply - (*GetStudyRoomListRequest)(nil), // 53: api.GetStudyRoomListRequest - (*GetStudyRoomListReply)(nil), // 54: api.GetStudyRoomListReply - (*StudyRoomMsgElement)(nil), // 55: api.StudyRoomMsgElement - (*StudyRoom)(nil), // 56: api.StudyRoom - (*GetMoviesRequest)(nil), // 57: api.GetMoviesRequest - (*GetMoviesReply)(nil), // 58: api.GetMoviesReply - (*Movie)(nil), // 59: api.Movie - (*SendFeedbackReply)(nil), // 60: api.SendFeedbackReply + (SendFeedbackRequest_FeedbackTopic)(0), // 1: api.SendFeedbackRequest.FeedbackTopic + (*RegisterDeviceRequest)(nil), // 2: api.RegisterDeviceRequest + (*RegisterDeviceReply)(nil), // 3: api.RegisterDeviceReply + (*RemoveDeviceRequest)(nil), // 4: api.RemoveDeviceRequest + (*RemoveDeviceReply)(nil), // 5: api.RemoveDeviceReply + (*IOSDeviceRequestResponseRequest)(nil), // 6: api.IOSDeviceRequestResponseRequest + (*IOSDeviceRequestResponseReply)(nil), // 7: api.IOSDeviceRequestResponseReply + (*SearchRoomsRequest)(nil), // 8: api.SearchRoomsRequest + (*SearchRoomsReply)(nil), // 9: api.SearchRoomsReply + (*Room)(nil), // 10: api.Room + (*News)(nil), // 11: api.News + (*GetNewsReply)(nil), // 12: api.GetNewsReply + (*GetNewsRequest)(nil), // 13: api.GetNewsRequest + (*GetNewsSourcesRequest)(nil), // 14: api.GetNewsSourcesRequest + (*GetNewsSourcesReply)(nil), // 15: api.GetNewsSourcesReply + (*NewsSource)(nil), // 16: api.NewsSource + (*GetTopNewsRequest)(nil), // 17: api.GetTopNewsRequest + (*GetTopNewsReply)(nil), // 18: api.GetTopNewsReply + (*GetCanteenRatingsRequest)(nil), // 19: api.GetCanteenRatingsRequest + (*GetCanteenRatingsReply)(nil), // 20: api.GetCanteenRatingsReply + (*GetDishRatingsRequest)(nil), // 21: api.GetDishRatingsRequest + (*GetDishRatingsReply)(nil), // 22: api.GetDishRatingsReply + (*SingleRatingReply)(nil), // 23: api.SingleRatingReply + (*NewCanteenRatingReply)(nil), // 24: api.NewCanteenRatingReply + (*NewCanteenRatingRequest)(nil), // 25: api.NewCanteenRatingRequest + (*NewDishRatingReply)(nil), // 26: api.NewDishRatingReply + (*NewDishRatingRequest)(nil), // 27: api.NewDishRatingRequest + (*GetAvailableDishTagsRequest)(nil), // 28: api.GetAvailableDishTagsRequest + (*GetAvailableDishTagsReply)(nil), // 29: api.GetAvailableDishTagsReply + (*GetNameTagsRequest)(nil), // 30: api.GetNameTagsRequest + (*GetNameTagsReply)(nil), // 31: api.GetNameTagsReply + (*GetAvailableCanteenTagsRequest)(nil), // 32: api.GetAvailableCanteenTagsRequest + (*GetAvailableCanteenTagsReply)(nil), // 33: api.GetAvailableCanteenTagsReply + (*TagsOverview)(nil), // 34: api.TagsOverview + (*RatingTag)(nil), // 35: api.RatingTag + (*RatingTagNewRequest)(nil), // 36: api.RatingTagNewRequest + (*RatingTagResult)(nil), // 37: api.RatingTagResult + (*GetCanteensRequest)(nil), // 38: api.GetCanteensRequest + (*GetCanteensReply)(nil), // 39: api.GetCanteensReply + (*Canteen)(nil), // 40: api.Canteen + (*GetDishesRequest)(nil), // 41: api.GetDishesRequest + (*GetDishesReply)(nil), // 42: api.GetDishesReply + (*GetResponsiblePersonRequest)(nil), // 43: api.GetResponsiblePersonRequest + (*GetResponsiblePersonReply)(nil), // 44: api.GetResponsiblePersonReply + (*ResponsiblePerson)(nil), // 45: api.ResponsiblePerson + (*RoomInformationElement)(nil), // 46: api.RoomInformationElement + (*GetMoreInformationRequest)(nil), // 47: api.GetMoreInformationRequest + (*GetMoreInformationReply)(nil), // 48: api.GetMoreInformationReply + (*GetOpeningTimesRequest)(nil), // 49: api.GetOpeningTimesRequest + (*GetOpeningTimesReply)(nil), // 50: api.GetOpeningTimesReply + (*OpeningTimesMsgElement)(nil), // 51: api.OpeningTimesMsgElement + (*GetUpdateNoteRequest)(nil), // 52: api.GetUpdateNoteRequest + (*GetUpdateNoteReply)(nil), // 53: api.GetUpdateNoteReply + (*GetStudyRoomListRequest)(nil), // 54: api.GetStudyRoomListRequest + (*GetStudyRoomListReply)(nil), // 55: api.GetStudyRoomListReply + (*StudyRoomMsgElement)(nil), // 56: api.StudyRoomMsgElement + (*StudyRoom)(nil), // 57: api.StudyRoom + (*GetMoviesRequest)(nil), // 58: api.GetMoviesRequest + (*GetMoviesReply)(nil), // 59: api.GetMoviesReply + (*Movie)(nil), // 60: api.Movie (*SendFeedbackRequest)(nil), // 61: api.SendFeedbackRequest - (*SendFeedbackImageReply)(nil), // 62: api.SendFeedbackImageReply - (*SendFeedbackImageRequest)(nil), // 63: api.SendFeedbackImageRequest - (*GetMembersRequest)(nil), // 64: api.GetMembersRequest - (*GetMembersReply)(nil), // 65: api.GetMembersReply - (*GetUploadStatusRequest)(nil), // 66: api.GetUploadStatusRequest - (*GetUploadStatusReply)(nil), // 67: api.GetUploadStatusReply - (*GetNotificationRequest)(nil), // 68: api.GetNotificationRequest - (*GetNotificationReply)(nil), // 69: api.GetNotificationReply - (*GetNotificationConfirmRequest)(nil), // 70: api.GetNotificationConfirmRequest - (*GetNotificationConfirmReply)(nil), // 71: api.GetNotificationConfirmReply - (*GetCanteenHeadCountRequest)(nil), // 72: api.GetCanteenHeadCountRequest - (*GetCanteenHeadCountReply)(nil), // 73: api.GetCanteenHeadCountReply - (*GetMoreInformationReply_MoreInformation)(nil), // 74: api.GetMoreInformationReply.MoreInformation + (*SendFeedbackReply)(nil), // 62: api.SendFeedbackReply + (*GetMembersRequest)(nil), // 63: api.GetMembersRequest + (*GetMembersReply)(nil), // 64: api.GetMembersReply + (*GetUploadStatusRequest)(nil), // 65: api.GetUploadStatusRequest + (*GetUploadStatusReply)(nil), // 66: api.GetUploadStatusReply + (*GetNotificationRequest)(nil), // 67: api.GetNotificationRequest + (*GetNotificationReply)(nil), // 68: api.GetNotificationReply + (*GetNotificationConfirmRequest)(nil), // 69: api.GetNotificationConfirmRequest + (*GetNotificationConfirmReply)(nil), // 70: api.GetNotificationConfirmReply + (*GetCanteenHeadCountRequest)(nil), // 71: api.GetCanteenHeadCountRequest + (*GetCanteenHeadCountReply)(nil), // 72: api.GetCanteenHeadCountReply + (*GetMoreInformationReply_MoreInformation)(nil), // 73: api.GetMoreInformationReply.MoreInformation + (*SendFeedbackRequest_Metadata)(nil), // 74: api.SendFeedbackRequest.Metadata (*timestamppb.Timestamp)(nil), // 75: google.protobuf.Timestamp } var file_tumdev_campus_backend_proto_depIdxs = []int32{ 0, // 0: api.RegisterDeviceRequest.device_type:type_name -> api.DeviceType 0, // 1: api.RemoveDeviceRequest.device_type:type_name -> api.DeviceType - 9, // 2: api.SearchRoomsReply.rooms:type_name -> api.Room + 10, // 2: api.SearchRoomsReply.rooms:type_name -> api.Room 75, // 3: api.News.created:type_name -> google.protobuf.Timestamp 75, // 4: api.News.date:type_name -> google.protobuf.Timestamp - 10, // 5: api.GetNewsReply.news:type_name -> api.News - 15, // 6: api.GetNewsSourcesReply.sources:type_name -> api.NewsSource + 11, // 5: api.GetNewsReply.news:type_name -> api.News + 16, // 6: api.GetNewsSourcesReply.sources:type_name -> api.NewsSource 75, // 7: api.GetTopNewsReply.created:type_name -> google.protobuf.Timestamp 75, // 8: api.GetTopNewsReply.from:type_name -> google.protobuf.Timestamp 75, // 9: api.GetTopNewsReply.to:type_name -> google.protobuf.Timestamp 75, // 10: api.GetCanteenRatingsRequest.from:type_name -> google.protobuf.Timestamp 75, // 11: api.GetCanteenRatingsRequest.to:type_name -> google.protobuf.Timestamp - 22, // 12: api.GetCanteenRatingsReply.rating:type_name -> api.SingleRatingReply - 36, // 13: api.GetCanteenRatingsReply.rating_tags:type_name -> api.RatingTagResult + 23, // 12: api.GetCanteenRatingsReply.rating:type_name -> api.SingleRatingReply + 37, // 13: api.GetCanteenRatingsReply.rating_tags:type_name -> api.RatingTagResult 75, // 14: api.GetDishRatingsRequest.from:type_name -> google.protobuf.Timestamp 75, // 15: api.GetDishRatingsRequest.to:type_name -> google.protobuf.Timestamp - 22, // 16: api.GetDishRatingsReply.rating:type_name -> api.SingleRatingReply - 36, // 17: api.GetDishRatingsReply.rating_tags:type_name -> api.RatingTagResult - 36, // 18: api.GetDishRatingsReply.name_tags:type_name -> api.RatingTagResult - 35, // 19: api.SingleRatingReply.rating_tags:type_name -> api.RatingTagNewRequest + 23, // 16: api.GetDishRatingsReply.rating:type_name -> api.SingleRatingReply + 37, // 17: api.GetDishRatingsReply.rating_tags:type_name -> api.RatingTagResult + 37, // 18: api.GetDishRatingsReply.name_tags:type_name -> api.RatingTagResult + 36, // 19: api.SingleRatingReply.rating_tags:type_name -> api.RatingTagNewRequest 75, // 20: api.SingleRatingReply.visited:type_name -> google.protobuf.Timestamp - 34, // 21: api.NewCanteenRatingRequest.rating_tags:type_name -> api.RatingTag - 34, // 22: api.NewDishRatingRequest.rating_tags:type_name -> api.RatingTag - 33, // 23: api.GetAvailableDishTagsReply.rating_tags:type_name -> api.TagsOverview - 33, // 24: api.GetNameTagsReply.rating_tags:type_name -> api.TagsOverview - 33, // 25: api.GetAvailableCanteenTagsReply.rating_tags:type_name -> api.TagsOverview - 39, // 26: api.GetCanteensReply.canteen:type_name -> api.Canteen - 44, // 27: api.GetResponsiblePersonReply.responsible_person:type_name -> api.ResponsiblePerson - 74, // 28: api.GetMoreInformationReply.infos:type_name -> api.GetMoreInformationReply.MoreInformation - 50, // 29: api.GetOpeningTimesReply.facilities:type_name -> api.OpeningTimesMsgElement - 55, // 30: api.GetStudyRoomListReply.rooms:type_name -> api.StudyRoomMsgElement - 56, // 31: api.StudyRoomMsgElement.rooms:type_name -> api.StudyRoom - 59, // 32: api.GetMoviesReply.movies:type_name -> api.Movie + 35, // 21: api.NewCanteenRatingRequest.rating_tags:type_name -> api.RatingTag + 35, // 22: api.NewDishRatingRequest.rating_tags:type_name -> api.RatingTag + 34, // 23: api.GetAvailableDishTagsReply.rating_tags:type_name -> api.TagsOverview + 34, // 24: api.GetNameTagsReply.rating_tags:type_name -> api.TagsOverview + 34, // 25: api.GetAvailableCanteenTagsReply.rating_tags:type_name -> api.TagsOverview + 40, // 26: api.GetCanteensReply.canteen:type_name -> api.Canteen + 45, // 27: api.GetResponsiblePersonReply.responsible_person:type_name -> api.ResponsiblePerson + 73, // 28: api.GetMoreInformationReply.infos:type_name -> api.GetMoreInformationReply.MoreInformation + 51, // 29: api.GetOpeningTimesReply.facilities:type_name -> api.OpeningTimesMsgElement + 56, // 30: api.GetStudyRoomListReply.rooms:type_name -> api.StudyRoomMsgElement + 57, // 31: api.StudyRoomMsgElement.rooms:type_name -> api.StudyRoom + 60, // 32: api.GetMoviesReply.movies:type_name -> api.Movie 75, // 33: api.Movie.date:type_name -> google.protobuf.Timestamp 75, // 34: api.Movie.created:type_name -> google.protobuf.Timestamp - 75, // 35: api.GetCanteenHeadCountReply.timestamp:type_name -> google.protobuf.Timestamp - 16, // 36: api.Campus.GetTopNews:input_type -> api.GetTopNewsRequest - 13, // 37: api.Campus.GetNewsSources:input_type -> api.GetNewsSourcesRequest - 12, // 38: api.Campus.GetNews:input_type -> api.GetNewsRequest - 7, // 39: api.Campus.SearchRooms:input_type -> api.SearchRoomsRequest - 18, // 40: api.Campus.GetCanteenRatings:input_type -> api.GetCanteenRatingsRequest - 20, // 41: api.Campus.GetDishRatings:input_type -> api.GetDishRatingsRequest - 24, // 42: api.Campus.NewCanteenRating:input_type -> api.NewCanteenRatingRequest - 26, // 43: api.Campus.NewDishRating:input_type -> api.NewDishRatingRequest - 27, // 44: api.Campus.GetAvailableDishTags:input_type -> api.GetAvailableDishTagsRequest - 29, // 45: api.Campus.GetNameTags:input_type -> api.GetNameTagsRequest - 31, // 46: api.Campus.GetAvailableCanteenTags:input_type -> api.GetAvailableCanteenTagsRequest - 37, // 47: api.Campus.GetCanteens:input_type -> api.GetCanteensRequest - 40, // 48: api.Campus.GetDishes:input_type -> api.GetDishesRequest - 42, // 49: api.Campus.GetResponsiblePerson:input_type -> api.GetResponsiblePersonRequest - 46, // 50: api.Campus.GetMoreInformation:input_type -> api.GetMoreInformationRequest - 48, // 51: api.Campus.GetOpeningTimes:input_type -> api.GetOpeningTimesRequest - 51, // 52: api.Campus.GetUpdateNote:input_type -> api.GetUpdateNoteRequest - 53, // 53: api.Campus.GetStudyRoomList:input_type -> api.GetStudyRoomListRequest - 57, // 54: api.Campus.GetMovies:input_type -> api.GetMoviesRequest - 61, // 55: api.Campus.SendFeedback:input_type -> api.SendFeedbackRequest - 63, // 56: api.Campus.SendFeedbackImage:input_type -> api.SendFeedbackImageRequest - 66, // 57: api.Campus.GetUploadStatus:input_type -> api.GetUploadStatusRequest - 68, // 58: api.Campus.GetNotification:input_type -> api.GetNotificationRequest - 70, // 59: api.Campus.GetNotificationConfirm:input_type -> api.GetNotificationConfirmRequest - 64, // 60: api.Campus.GetMembers:input_type -> api.GetMembersRequest - 72, // 61: api.Campus.GetCanteenHeadCount:input_type -> api.GetCanteenHeadCountRequest - 5, // 62: api.Campus.IOSDeviceRequestResponse:input_type -> api.IOSDeviceRequestResponseRequest - 1, // 63: api.Campus.RegisterDevice:input_type -> api.RegisterDeviceRequest - 3, // 64: api.Campus.RemoveDevice:input_type -> api.RemoveDeviceRequest - 17, // 65: api.Campus.GetTopNews:output_type -> api.GetTopNewsReply - 14, // 66: api.Campus.GetNewsSources:output_type -> api.GetNewsSourcesReply - 11, // 67: api.Campus.GetNews:output_type -> api.GetNewsReply - 8, // 68: api.Campus.SearchRooms:output_type -> api.SearchRoomsReply - 19, // 69: api.Campus.GetCanteenRatings:output_type -> api.GetCanteenRatingsReply - 21, // 70: api.Campus.GetDishRatings:output_type -> api.GetDishRatingsReply - 23, // 71: api.Campus.NewCanteenRating:output_type -> api.NewCanteenRatingReply - 25, // 72: api.Campus.NewDishRating:output_type -> api.NewDishRatingReply - 28, // 73: api.Campus.GetAvailableDishTags:output_type -> api.GetAvailableDishTagsReply - 30, // 74: api.Campus.GetNameTags:output_type -> api.GetNameTagsReply - 32, // 75: api.Campus.GetAvailableCanteenTags:output_type -> api.GetAvailableCanteenTagsReply - 38, // 76: api.Campus.GetCanteens:output_type -> api.GetCanteensReply - 41, // 77: api.Campus.GetDishes:output_type -> api.GetDishesReply - 43, // 78: api.Campus.GetResponsiblePerson:output_type -> api.GetResponsiblePersonReply - 47, // 79: api.Campus.GetMoreInformation:output_type -> api.GetMoreInformationReply - 49, // 80: api.Campus.GetOpeningTimes:output_type -> api.GetOpeningTimesReply - 52, // 81: api.Campus.GetUpdateNote:output_type -> api.GetUpdateNoteReply - 54, // 82: api.Campus.GetStudyRoomList:output_type -> api.GetStudyRoomListReply - 58, // 83: api.Campus.GetMovies:output_type -> api.GetMoviesReply - 60, // 84: api.Campus.SendFeedback:output_type -> api.SendFeedbackReply - 62, // 85: api.Campus.SendFeedbackImage:output_type -> api.SendFeedbackImageReply - 67, // 86: api.Campus.GetUploadStatus:output_type -> api.GetUploadStatusReply - 69, // 87: api.Campus.GetNotification:output_type -> api.GetNotificationReply - 71, // 88: api.Campus.GetNotificationConfirm:output_type -> api.GetNotificationConfirmReply - 65, // 89: api.Campus.GetMembers:output_type -> api.GetMembersReply - 73, // 90: api.Campus.GetCanteenHeadCount:output_type -> api.GetCanteenHeadCountReply - 6, // 91: api.Campus.IOSDeviceRequestResponse:output_type -> api.IOSDeviceRequestResponseReply - 2, // 92: api.Campus.RegisterDevice:output_type -> api.RegisterDeviceReply - 4, // 93: api.Campus.RemoveDevice:output_type -> api.RemoveDeviceReply - 65, // [65:94] is the sub-list for method output_type - 36, // [36:65] is the sub-list for method input_type - 36, // [36:36] is the sub-list for extension type_name - 36, // [36:36] is the sub-list for extension extendee - 0, // [0:36] is the sub-list for field type_name + 1, // 35: api.SendFeedbackRequest.topic:type_name -> api.SendFeedbackRequest.FeedbackTopic + 74, // 36: api.SendFeedbackRequest.metadata:type_name -> api.SendFeedbackRequest.Metadata + 75, // 37: api.GetCanteenHeadCountReply.timestamp:type_name -> google.protobuf.Timestamp + 17, // 38: api.Campus.GetTopNews:input_type -> api.GetTopNewsRequest + 14, // 39: api.Campus.GetNewsSources:input_type -> api.GetNewsSourcesRequest + 13, // 40: api.Campus.GetNews:input_type -> api.GetNewsRequest + 8, // 41: api.Campus.SearchRooms:input_type -> api.SearchRoomsRequest + 19, // 42: api.Campus.GetCanteenRatings:input_type -> api.GetCanteenRatingsRequest + 21, // 43: api.Campus.GetDishRatings:input_type -> api.GetDishRatingsRequest + 25, // 44: api.Campus.NewCanteenRating:input_type -> api.NewCanteenRatingRequest + 27, // 45: api.Campus.NewDishRating:input_type -> api.NewDishRatingRequest + 28, // 46: api.Campus.GetAvailableDishTags:input_type -> api.GetAvailableDishTagsRequest + 30, // 47: api.Campus.GetNameTags:input_type -> api.GetNameTagsRequest + 32, // 48: api.Campus.GetAvailableCanteenTags:input_type -> api.GetAvailableCanteenTagsRequest + 38, // 49: api.Campus.GetCanteens:input_type -> api.GetCanteensRequest + 41, // 50: api.Campus.GetDishes:input_type -> api.GetDishesRequest + 43, // 51: api.Campus.GetResponsiblePerson:input_type -> api.GetResponsiblePersonRequest + 47, // 52: api.Campus.GetMoreInformation:input_type -> api.GetMoreInformationRequest + 49, // 53: api.Campus.GetOpeningTimes:input_type -> api.GetOpeningTimesRequest + 52, // 54: api.Campus.GetUpdateNote:input_type -> api.GetUpdateNoteRequest + 54, // 55: api.Campus.GetStudyRoomList:input_type -> api.GetStudyRoomListRequest + 58, // 56: api.Campus.GetMovies:input_type -> api.GetMoviesRequest + 61, // 57: api.Campus.SendFeedback:input_type -> api.SendFeedbackRequest + 65, // 58: api.Campus.GetUploadStatus:input_type -> api.GetUploadStatusRequest + 67, // 59: api.Campus.GetNotification:input_type -> api.GetNotificationRequest + 69, // 60: api.Campus.GetNotificationConfirm:input_type -> api.GetNotificationConfirmRequest + 63, // 61: api.Campus.GetMembers:input_type -> api.GetMembersRequest + 71, // 62: api.Campus.GetCanteenHeadCount:input_type -> api.GetCanteenHeadCountRequest + 6, // 63: api.Campus.IOSDeviceRequestResponse:input_type -> api.IOSDeviceRequestResponseRequest + 2, // 64: api.Campus.RegisterDevice:input_type -> api.RegisterDeviceRequest + 4, // 65: api.Campus.RemoveDevice:input_type -> api.RemoveDeviceRequest + 18, // 66: api.Campus.GetTopNews:output_type -> api.GetTopNewsReply + 15, // 67: api.Campus.GetNewsSources:output_type -> api.GetNewsSourcesReply + 12, // 68: api.Campus.GetNews:output_type -> api.GetNewsReply + 9, // 69: api.Campus.SearchRooms:output_type -> api.SearchRoomsReply + 20, // 70: api.Campus.GetCanteenRatings:output_type -> api.GetCanteenRatingsReply + 22, // 71: api.Campus.GetDishRatings:output_type -> api.GetDishRatingsReply + 24, // 72: api.Campus.NewCanteenRating:output_type -> api.NewCanteenRatingReply + 26, // 73: api.Campus.NewDishRating:output_type -> api.NewDishRatingReply + 29, // 74: api.Campus.GetAvailableDishTags:output_type -> api.GetAvailableDishTagsReply + 31, // 75: api.Campus.GetNameTags:output_type -> api.GetNameTagsReply + 33, // 76: api.Campus.GetAvailableCanteenTags:output_type -> api.GetAvailableCanteenTagsReply + 39, // 77: api.Campus.GetCanteens:output_type -> api.GetCanteensReply + 42, // 78: api.Campus.GetDishes:output_type -> api.GetDishesReply + 44, // 79: api.Campus.GetResponsiblePerson:output_type -> api.GetResponsiblePersonReply + 48, // 80: api.Campus.GetMoreInformation:output_type -> api.GetMoreInformationReply + 50, // 81: api.Campus.GetOpeningTimes:output_type -> api.GetOpeningTimesReply + 53, // 82: api.Campus.GetUpdateNote:output_type -> api.GetUpdateNoteReply + 55, // 83: api.Campus.GetStudyRoomList:output_type -> api.GetStudyRoomListReply + 59, // 84: api.Campus.GetMovies:output_type -> api.GetMoviesReply + 62, // 85: api.Campus.SendFeedback:output_type -> api.SendFeedbackReply + 66, // 86: api.Campus.GetUploadStatus:output_type -> api.GetUploadStatusReply + 68, // 87: api.Campus.GetNotification:output_type -> api.GetNotificationReply + 70, // 88: api.Campus.GetNotificationConfirm:output_type -> api.GetNotificationConfirmReply + 64, // 89: api.Campus.GetMembers:output_type -> api.GetMembersReply + 72, // 90: api.Campus.GetCanteenHeadCount:output_type -> api.GetCanteenHeadCountReply + 7, // 91: api.Campus.IOSDeviceRequestResponse:output_type -> api.IOSDeviceRequestResponseReply + 3, // 92: api.Campus.RegisterDevice:output_type -> api.RegisterDeviceReply + 5, // 93: api.Campus.RemoveDevice:output_type -> api.RemoveDeviceReply + 66, // [66:94] is the sub-list for method output_type + 38, // [38:66] is the sub-list for method input_type + 38, // [38:38] is the sub-list for extension type_name + 38, // [38:38] is the sub-list for extension extendee + 0, // [0:38] is the sub-list for field type_name } func init() { file_tumdev_campus_backend_proto_init() } @@ -6200,7 +6182,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[59].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SendFeedbackReply); i { + switch v := v.(*SendFeedbackRequest); i { case 0: return &v.state case 1: @@ -6212,7 +6194,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[60].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SendFeedbackRequest); i { + switch v := v.(*SendFeedbackReply); i { case 0: return &v.state case 1: @@ -6224,7 +6206,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[61].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SendFeedbackImageReply); i { + switch v := v.(*GetMembersRequest); i { case 0: return &v.state case 1: @@ -6236,7 +6218,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[62].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*SendFeedbackImageRequest); i { + switch v := v.(*GetMembersReply); i { case 0: return &v.state case 1: @@ -6248,7 +6230,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[63].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetMembersRequest); i { + switch v := v.(*GetUploadStatusRequest); i { case 0: return &v.state case 1: @@ -6260,7 +6242,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[64].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetMembersReply); i { + switch v := v.(*GetUploadStatusReply); i { case 0: return &v.state case 1: @@ -6272,7 +6254,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[65].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetUploadStatusRequest); i { + switch v := v.(*GetNotificationRequest); i { case 0: return &v.state case 1: @@ -6284,7 +6266,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[66].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetUploadStatusReply); i { + switch v := v.(*GetNotificationReply); i { case 0: return &v.state case 1: @@ -6296,7 +6278,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[67].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNotificationRequest); i { + switch v := v.(*GetNotificationConfirmRequest); i { case 0: return &v.state case 1: @@ -6308,7 +6290,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[68].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNotificationReply); i { + switch v := v.(*GetNotificationConfirmReply); i { case 0: return &v.state case 1: @@ -6320,7 +6302,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[69].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNotificationConfirmRequest); i { + switch v := v.(*GetCanteenHeadCountRequest); i { case 0: return &v.state case 1: @@ -6332,7 +6314,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[70].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetNotificationConfirmReply); i { + switch v := v.(*GetCanteenHeadCountReply); i { case 0: return &v.state case 1: @@ -6344,7 +6326,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[71].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetCanteenHeadCountRequest); i { + switch v := v.(*GetMoreInformationReply_MoreInformation); i { case 0: return &v.state case 1: @@ -6356,19 +6338,7 @@ func file_tumdev_campus_backend_proto_init() { } } file_tumdev_campus_backend_proto_msgTypes[72].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetCanteenHeadCountReply); i { - case 0: - return &v.state - case 1: - return &v.sizeCache - case 2: - return &v.unknownFields - default: - return nil - } - } - file_tumdev_campus_backend_proto_msgTypes[73].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*GetMoreInformationReply_MoreInformation); i { + switch v := v.(*SendFeedbackRequest_Metadata); i { case 0: return &v.state case 1: @@ -6386,8 +6356,8 @@ func file_tumdev_campus_backend_proto_init() { File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_tumdev_campus_backend_proto_rawDesc, - NumEnums: 1, - NumMessages: 74, + NumEnums: 2, + NumMessages: 73, NumExtensions: 0, NumServices: 1, }, diff --git a/server/api/tumdev/campus_backend.pb.gw.go b/server/api/tumdev/campus_backend.pb.gw.go index 930112dd..1688dfee 100644 --- a/server/api/tumdev/campus_backend.pb.gw.go +++ b/server/api/tumdev/campus_backend.pb.gw.go @@ -625,110 +625,46 @@ func local_request_Campus_GetMovies_0(ctx context.Context, marshaler runtime.Mar } -var ( - filter_Campus_SendFeedback_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} -) - func request_Campus_SendFeedback_0(ctx context.Context, marshaler runtime.Marshaler, client CampusClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SendFeedbackRequest var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Campus_SendFeedback_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := client.SendFeedback(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Campus_SendFeedback_0(ctx context.Context, marshaler runtime.Marshaler, server CampusServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SendFeedbackRequest - var metadata runtime.ServerMetadata - - if err := req.ParseForm(); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - if err := runtime.PopulateQueryParameters(&protoReq, req.Form, filter_Campus_SendFeedback_0); err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) - } - - msg, err := server.SendFeedback(ctx, &protoReq) - return msg, metadata, err - -} - -func request_Campus_SendFeedbackImage_0(ctx context.Context, marshaler runtime.Marshaler, client CampusClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SendFeedbackImageRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") - } - - protoReq.Id, err = runtime.Int32(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) - } - - val, ok = pathParams["image_nr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "image_nr") - } - - protoReq.ImageNr, err = runtime.Int32(val) + stream, err := client.SendFeedback(ctx) if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "image_nr", err) - } - - msg, err := client.SendFeedbackImage(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) - return msg, metadata, err - -} - -func local_request_Campus_SendFeedbackImage_0(ctx context.Context, marshaler runtime.Marshaler, server CampusServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { - var protoReq SendFeedbackImageRequest - var metadata runtime.ServerMetadata - - var ( - val string - ok bool - err error - _ = err - ) - - val, ok = pathParams["id"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "id") + grpclog.Infof("Failed to start streaming: %v", err) + return nil, metadata, err } - - protoReq.Id, err = runtime.Int32(val) - if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "id", err) + dec := marshaler.NewDecoder(req.Body) + for { + var protoReq SendFeedbackRequest + err = dec.Decode(&protoReq) + if err == io.EOF { + break + } + if err != nil { + grpclog.Infof("Failed to decode request: %v", err) + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + if err = stream.Send(&protoReq); err != nil { + if err == io.EOF { + break + } + grpclog.Infof("Failed to send request: %v", err) + return nil, metadata, err + } } - val, ok = pathParams["image_nr"] - if !ok { - return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "image_nr") + if err := stream.CloseSend(); err != nil { + grpclog.Infof("Failed to terminate client stream: %v", err) + return nil, metadata, err } - - protoReq.ImageNr, err = runtime.Int32(val) + header, err := stream.Header() if err != nil { - return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "image_nr", err) + grpclog.Infof("Failed to get header from client: %v", err) + return nil, metadata, err } + metadata.HeaderMD = header - msg, err := server.SendFeedbackImage(ctx, &protoReq) + msg, err := stream.CloseAndRecv() + metadata.TrailerMD = stream.Trailer() return msg, metadata, err } @@ -1613,53 +1549,10 @@ func RegisterCampusHandlerServer(ctx context.Context, mux *runtime.ServeMux, ser }) mux.Handle("POST", pattern_Campus_SendFeedback_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/api.Campus/SendFeedback", runtime.WithHTTPPathPattern("/feedback")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Campus_SendFeedback_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Campus_SendFeedback_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - - mux.Handle("POST", pattern_Campus_SendFeedbackImage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - var stream runtime.ServerTransportStream - ctx = grpc.NewContextWithServerTransportStream(ctx, &stream) - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateIncomingContext(ctx, mux, req, "/api.Campus/SendFeedbackImage", runtime.WithHTTPPathPattern("/feedback/{id}/{image_nr}")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := local_request_Campus_SendFeedbackImage_0(annotatedContext, inboundMarshaler, server, req, pathParams) - md.HeaderMD, md.TrailerMD = metadata.Join(md.HeaderMD, stream.Header()), metadata.Join(md.TrailerMD, stream.Trailer()) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Campus_SendFeedbackImage_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - + err := status.Error(codes.Unimplemented, "streaming calls are not yet supported in the in-process transport") + _, outboundMarshaler := runtime.MarshalerForRequest(mux, req) + runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) + return }) mux.Handle("GET", pattern_Campus_GetUploadStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { @@ -2343,28 +2236,6 @@ func RegisterCampusHandlerClient(ctx context.Context, mux *runtime.ServeMux, cli }) - mux.Handle("POST", pattern_Campus_SendFeedbackImage_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { - ctx, cancel := context.WithCancel(req.Context()) - defer cancel() - inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req) - var err error - var annotatedContext context.Context - annotatedContext, err = runtime.AnnotateContext(ctx, mux, req, "/api.Campus/SendFeedbackImage", runtime.WithHTTPPathPattern("/feedback/{id}/{image_nr}")) - if err != nil { - runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err) - return - } - resp, md, err := request_Campus_SendFeedbackImage_0(annotatedContext, inboundMarshaler, client, req, pathParams) - annotatedContext = runtime.NewServerMetadataContext(annotatedContext, md) - if err != nil { - runtime.HTTPError(annotatedContext, mux, outboundMarshaler, w, req, err) - return - } - - forward_Campus_SendFeedbackImage_0(annotatedContext, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...) - - }) - mux.Handle("GET", pattern_Campus_GetUploadStatus_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) { ctx, cancel := context.WithCancel(req.Context()) defer cancel() @@ -2657,8 +2528,6 @@ var ( pattern_Campus_SendFeedback_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0}, []string{"feedback"}, "")) - pattern_Campus_SendFeedbackImage_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1, 1, 0, 4, 1, 5, 2}, []string{"feedback", "id", "image_nr"}, "")) - pattern_Campus_GetUploadStatus_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"device", "uploaded", "lrz_id"}, "")) pattern_Campus_GetNotification_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 1, 0, 4, 1, 5, 1}, []string{"notifications", "notification_id"}, "")) @@ -2717,8 +2586,6 @@ var ( forward_Campus_SendFeedback_0 = runtime.ForwardResponseMessage - forward_Campus_SendFeedbackImage_0 = runtime.ForwardResponseMessage - forward_Campus_GetUploadStatus_0 = runtime.ForwardResponseMessage forward_Campus_GetNotification_0 = runtime.ForwardResponseMessage diff --git a/server/api/tumdev/campus_backend.proto b/server/api/tumdev/campus_backend.proto index 6f184fd0..b9c9241d 100644 --- a/server/api/tumdev/campus_backend.proto +++ b/server/api/tumdev/campus_backend.proto @@ -126,12 +126,11 @@ service Campus { option (google.api.http) = {get: "/movies/{last_id}"}; } - rpc SendFeedback(SendFeedbackRequest) returns (SendFeedbackReply) { - option (google.api.http) = {post: "/feedback"}; - } - - rpc SendFeedbackImage(SendFeedbackImageRequest) returns (SendFeedbackImageReply) { - option (google.api.http) = {post: "/feedback/{id}/{image_nr}"}; + rpc SendFeedback(stream SendFeedbackRequest) returns (SendFeedbackReply) { + option (google.api.http) = { + post: "/feedback", + body: "image", + }; } rpc GetUploadStatus(GetUploadStatusRequest) returns (GetUploadStatusReply) { @@ -538,29 +537,33 @@ message Movie { string link = 16; } -message SendFeedbackReply {} message SendFeedbackRequest { - string topic = 1; - string email = 2; - string email_id = 3; - string message = 4; - int32 image_count = 5; - double latitude = 6; - double longitude = 7; - string os_version = 8; - string app_version = 9; -} - -message SendFeedbackImageReply { - string status = 1; -} + message Metadata { + double latitude = 1; + double longitude = 2; + string osVersion = 3; + string appVersion = 4; + } -message SendFeedbackImageRequest { - int32 id = 1; - int32 image_nr = 2; - //todo where does the file come from? + enum FeedbackTopic { + TUM_DEV = 0; + TUM_CONTACT = 1; + } + + // who is the feedback for + FeedbackTopic topic = 1; + // the email address of the user + string from_email = 2; + // The actual message + string message = 3; + // Optional metadata which the user can choose to attach or not + Metadata metadata = 4; + // Optional file in Base64 + bytes image = 5; } +message SendFeedbackReply {} + message GetMembersRequest { string lrz_id = 1; } diff --git a/server/api/tumdev/campus_backend.swagger.json b/server/api/tumdev/campus_backend.swagger.json index 146bdf9c..48eb4e89 100644 --- a/server/api/tumdev/campus_backend.swagger.json +++ b/server/api/tumdev/campus_backend.swagger.json @@ -507,58 +507,63 @@ }, "parameters": [ { - "name": "topic", - "in": "query", - "required": false, - "type": "string" + "name": "image", + "description": "Optional file in Base64 (streaming inputs)", + "in": "body", + "required": true, + "schema": { + "type": "string", + "format": "byte" + } }, { - "name": "email", + "name": "topic", + "description": "who is the feedback for", "in": "query", "required": false, - "type": "string" + "type": "string", + "enum": [ + "TUM_DEV", + "TUM_CONTACT" + ], + "default": "TUM_DEV" }, { - "name": "emailId", + "name": "fromEmail", + "description": "the email address of the user", "in": "query", "required": false, "type": "string" }, { "name": "message", + "description": "The actual message", "in": "query", "required": false, "type": "string" }, { - "name": "imageCount", - "in": "query", - "required": false, - "type": "integer", - "format": "int32" - }, - { - "name": "latitude", + "name": "metadata.latitude", "in": "query", "required": false, "type": "number", "format": "double" }, { - "name": "longitude", + "name": "metadata.longitude", "in": "query", "required": false, "type": "number", "format": "double" }, { - "name": "osVersion", + "name": "metadata.osVersion", "in": "query", "required": false, "type": "string" }, { - "name": "appVersion", + "name": "metadata.appVersion", "in": "query", "required": false, "type": "string" @@ -569,45 +574,6 @@ ] } }, - "/feedback/{id}/{imageNr}": { - "post": { - "operationId": "Campus_SendFeedbackImage", - "responses": { - "200": { - "description": "A successful response.", - "schema": { - "$ref": "#/definitions/apiSendFeedbackImageReply" - } - }, - "default": { - "description": "An unexpected error response.", - "schema": { - "$ref": "#/definitions/rpcStatus" - } - } - }, - "parameters": [ - { - "name": "id", - "in": "path", - "required": true, - "type": "integer", - "format": "int32" - }, - { - "name": "imageNr", - "description": "todo where does the file come from?", - "in": "path", - "required": true, - "type": "integer", - "format": "int32" - } - ], - "tags": [ - "Campus" - ] - } - }, "/ios/notifications/deviceRequestResponse": { "post": { "summary": "Endpoint for the iOS app to respond to background notifications requests", @@ -992,6 +958,33 @@ } } }, + "SendFeedbackRequestFeedbackTopic": { + "type": "string", + "enum": [ + "TUM_DEV", + "TUM_CONTACT" + ], + "default": "TUM_DEV" + }, + "SendFeedbackRequestMetadata": { + "type": "object", + "properties": { + "latitude": { + "type": "number", + "format": "double" + }, + "longitude": { + "type": "number", + "format": "double" + }, + "osVersion": { + "type": "string" + }, + "appVersion": { + "type": "string" + } + } + }, "apiCanteen": { "type": "object", "properties": { @@ -1802,14 +1795,6 @@ } } }, - "apiSendFeedbackImageReply": { - "type": "object", - "properties": { - "status": { - "type": "string" - } - } - }, "apiSendFeedbackReply": { "type": "object" }, diff --git a/server/api/tumdev/campus_backend_grpc.pb.go b/server/api/tumdev/campus_backend_grpc.pb.go index 4714aa98..635dde98 100644 --- a/server/api/tumdev/campus_backend_grpc.pb.go +++ b/server/api/tumdev/campus_backend_grpc.pb.go @@ -40,7 +40,6 @@ const ( Campus_GetStudyRoomList_FullMethodName = "/api.Campus/GetStudyRoomList" Campus_GetMovies_FullMethodName = "/api.Campus/GetMovies" Campus_SendFeedback_FullMethodName = "/api.Campus/SendFeedback" - Campus_SendFeedbackImage_FullMethodName = "/api.Campus/SendFeedbackImage" Campus_GetUploadStatus_FullMethodName = "/api.Campus/GetUploadStatus" Campus_GetNotification_FullMethodName = "/api.Campus/GetNotification" Campus_GetNotificationConfirm_FullMethodName = "/api.Campus/GetNotificationConfirm" @@ -75,8 +74,7 @@ type CampusClient interface { GetUpdateNote(ctx context.Context, in *GetUpdateNoteRequest, opts ...grpc.CallOption) (*GetUpdateNoteReply, error) GetStudyRoomList(ctx context.Context, in *GetStudyRoomListRequest, opts ...grpc.CallOption) (*GetStudyRoomListReply, error) GetMovies(ctx context.Context, in *GetMoviesRequest, opts ...grpc.CallOption) (*GetMoviesReply, error) - SendFeedback(ctx context.Context, in *SendFeedbackRequest, opts ...grpc.CallOption) (*SendFeedbackReply, error) - SendFeedbackImage(ctx context.Context, in *SendFeedbackImageRequest, opts ...grpc.CallOption) (*SendFeedbackImageReply, error) + SendFeedback(ctx context.Context, opts ...grpc.CallOption) (Campus_SendFeedbackClient, error) GetUploadStatus(ctx context.Context, in *GetUploadStatusRequest, opts ...grpc.CallOption) (*GetUploadStatusReply, error) GetNotification(ctx context.Context, in *GetNotificationRequest, opts ...grpc.CallOption) (*GetNotificationReply, error) GetNotificationConfirm(ctx context.Context, in *GetNotificationConfirmRequest, opts ...grpc.CallOption) (*GetNotificationConfirmReply, error) @@ -269,22 +267,38 @@ func (c *campusClient) GetMovies(ctx context.Context, in *GetMoviesRequest, opts return out, nil } -func (c *campusClient) SendFeedback(ctx context.Context, in *SendFeedbackRequest, opts ...grpc.CallOption) (*SendFeedbackReply, error) { - out := new(SendFeedbackReply) - err := c.cc.Invoke(ctx, Campus_SendFeedback_FullMethodName, in, out, opts...) +func (c *campusClient) SendFeedback(ctx context.Context, opts ...grpc.CallOption) (Campus_SendFeedbackClient, error) { + stream, err := c.cc.NewStream(ctx, &Campus_ServiceDesc.Streams[0], Campus_SendFeedback_FullMethodName, opts...) if err != nil { return nil, err } - return out, nil + x := &campusSendFeedbackClient{stream} + return x, nil } -func (c *campusClient) SendFeedbackImage(ctx context.Context, in *SendFeedbackImageRequest, opts ...grpc.CallOption) (*SendFeedbackImageReply, error) { - out := new(SendFeedbackImageReply) - err := c.cc.Invoke(ctx, Campus_SendFeedbackImage_FullMethodName, in, out, opts...) - if err != nil { +type Campus_SendFeedbackClient interface { + Send(*SendFeedbackRequest) error + CloseAndRecv() (*SendFeedbackReply, error) + grpc.ClientStream +} + +type campusSendFeedbackClient struct { + grpc.ClientStream +} + +func (x *campusSendFeedbackClient) Send(m *SendFeedbackRequest) error { + return x.ClientStream.SendMsg(m) +} + +func (x *campusSendFeedbackClient) CloseAndRecv() (*SendFeedbackReply, error) { + if err := x.ClientStream.CloseSend(); err != nil { return nil, err } - return out, nil + m := new(SendFeedbackReply) + if err := x.ClientStream.RecvMsg(m); err != nil { + return nil, err + } + return m, nil } func (c *campusClient) GetUploadStatus(ctx context.Context, in *GetUploadStatusRequest, opts ...grpc.CallOption) (*GetUploadStatusReply, error) { @@ -383,8 +397,7 @@ type CampusServer interface { GetUpdateNote(context.Context, *GetUpdateNoteRequest) (*GetUpdateNoteReply, error) GetStudyRoomList(context.Context, *GetStudyRoomListRequest) (*GetStudyRoomListReply, error) GetMovies(context.Context, *GetMoviesRequest) (*GetMoviesReply, error) - SendFeedback(context.Context, *SendFeedbackRequest) (*SendFeedbackReply, error) - SendFeedbackImage(context.Context, *SendFeedbackImageRequest) (*SendFeedbackImageReply, error) + SendFeedback(Campus_SendFeedbackServer) error GetUploadStatus(context.Context, *GetUploadStatusRequest) (*GetUploadStatusReply, error) GetNotification(context.Context, *GetNotificationRequest) (*GetNotificationReply, error) GetNotificationConfirm(context.Context, *GetNotificationConfirmRequest) (*GetNotificationConfirmReply, error) @@ -460,11 +473,8 @@ func (UnimplementedCampusServer) GetStudyRoomList(context.Context, *GetStudyRoom func (UnimplementedCampusServer) GetMovies(context.Context, *GetMoviesRequest) (*GetMoviesReply, error) { return nil, status.Errorf(codes.Unimplemented, "method GetMovies not implemented") } -func (UnimplementedCampusServer) SendFeedback(context.Context, *SendFeedbackRequest) (*SendFeedbackReply, error) { - return nil, status.Errorf(codes.Unimplemented, "method SendFeedback not implemented") -} -func (UnimplementedCampusServer) SendFeedbackImage(context.Context, *SendFeedbackImageRequest) (*SendFeedbackImageReply, error) { - return nil, status.Errorf(codes.Unimplemented, "method SendFeedbackImage not implemented") +func (UnimplementedCampusServer) SendFeedback(Campus_SendFeedbackServer) error { + return status.Errorf(codes.Unimplemented, "method SendFeedback not implemented") } func (UnimplementedCampusServer) GetUploadStatus(context.Context, *GetUploadStatusRequest) (*GetUploadStatusReply, error) { return nil, status.Errorf(codes.Unimplemented, "method GetUploadStatus not implemented") @@ -845,40 +855,30 @@ func _Campus_GetMovies_Handler(srv interface{}, ctx context.Context, dec func(in return interceptor(ctx, in, info, handler) } -func _Campus_SendFeedback_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SendFeedbackRequest) - if err := dec(in); err != nil { - return nil, err - } - if interceptor == nil { - return srv.(CampusServer).SendFeedback(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: Campus_SendFeedback_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CampusServer).SendFeedback(ctx, req.(*SendFeedbackRequest)) - } - return interceptor(ctx, in, info, handler) +func _Campus_SendFeedback_Handler(srv interface{}, stream grpc.ServerStream) error { + return srv.(CampusServer).SendFeedback(&campusSendFeedbackServer{stream}) } -func _Campus_SendFeedbackImage_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { - in := new(SendFeedbackImageRequest) - if err := dec(in); err != nil { +type Campus_SendFeedbackServer interface { + SendAndClose(*SendFeedbackReply) error + Recv() (*SendFeedbackRequest, error) + grpc.ServerStream +} + +type campusSendFeedbackServer struct { + grpc.ServerStream +} + +func (x *campusSendFeedbackServer) SendAndClose(m *SendFeedbackReply) error { + return x.ServerStream.SendMsg(m) +} + +func (x *campusSendFeedbackServer) Recv() (*SendFeedbackRequest, error) { + m := new(SendFeedbackRequest) + if err := x.ServerStream.RecvMsg(m); err != nil { return nil, err } - if interceptor == nil { - return srv.(CampusServer).SendFeedbackImage(ctx, in) - } - info := &grpc.UnaryServerInfo{ - Server: srv, - FullMethod: Campus_SendFeedbackImage_FullMethodName, - } - handler := func(ctx context.Context, req interface{}) (interface{}, error) { - return srv.(CampusServer).SendFeedbackImage(ctx, req.(*SendFeedbackImageRequest)) - } - return interceptor(ctx, in, info, handler) + return m, nil } func _Campus_GetUploadStatus_Handler(srv interface{}, ctx context.Context, dec func(interface{}) error, interceptor grpc.UnaryServerInterceptor) (interface{}, error) { @@ -1108,14 +1108,6 @@ var Campus_ServiceDesc = grpc.ServiceDesc{ MethodName: "GetMovies", Handler: _Campus_GetMovies_Handler, }, - { - MethodName: "SendFeedback", - Handler: _Campus_SendFeedback_Handler, - }, - { - MethodName: "SendFeedbackImage", - Handler: _Campus_SendFeedbackImage_Handler, - }, { MethodName: "GetUploadStatus", Handler: _Campus_GetUploadStatus_Handler, @@ -1149,6 +1141,12 @@ var Campus_ServiceDesc = grpc.ServiceDesc{ Handler: _Campus_RemoveDevice_Handler, }, }, - Streams: []grpc.StreamDesc{}, + Streams: []grpc.StreamDesc{ + { + StreamName: "SendFeedback", + Handler: _Campus_SendFeedback_Handler, + ClientStreams: true, + }, + }, Metadata: "tumdev/campus_backend.proto", } diff --git a/server/backend/feedback.go b/server/backend/feedback.go new file mode 100644 index 00000000..b933697e --- /dev/null +++ b/server/backend/feedback.go @@ -0,0 +1,161 @@ +package backend + +import ( + "bytes" + "fmt" + "io" + "os" + "path" + + "github.com/TUM-Dev/Campus-Backend/server/backend/cron" + "github.com/gabriel-vasile/mimetype" + "gorm.io/gorm" + + pb "github.com/TUM-Dev/Campus-Backend/server/api/tumdev" + "github.com/TUM-Dev/Campus-Backend/server/model" + "github.com/gofrs/uuid/v5" + "github.com/guregu/null" + log "github.com/sirupsen/logrus" + "google.golang.org/grpc/codes" + "google.golang.org/grpc/status" +) + +// SendFeedback accepts a stream of feedback messages from the client and stores them in the database/file system. +func (s *CampusServer) SendFeedback(stream pb.Campus_SendFeedbackServer) error { + return s.db.WithContext(stream.Context()).Transaction(func(tx *gorm.DB) error { + // receive metadata + req, err := stream.Recv() + if err == io.EOF { + return status.Error(codes.InvalidArgument, "no actual feedback provided") // The client has closed the stream + } + if err != nil { + log.WithError(err).Error("Error receiving feedback") + return status.Error(codes.Internal, "Error receiving feedback") + } + imageCounter := int32(0) + feedback, err := convertReqToFeedback(req) + if err != nil { + return status.Error(codes.Internal, "Error converting request to feedback") + } + if len(req.Image) > 0 { + imageCounter = handleImageUpload(tx, &req.Image, imageCounter, feedback.EmailId.String) + } + + // download images + for { + req, err := stream.Recv() + if err == io.EOF { + break + } + if err != nil { + log.WithError(err).Error("Error receiving feedback") + deleteUploaded(tx, feedback.EmailId.String) + return status.Error(codes.Internal, "Error receiving feedback") + } + + if len(req.Image) > 0 { + imageCounter = handleImageUpload(tx, &req.Image, imageCounter, feedback.EmailId.String) + } + } + feedback.ImageCount = imageCounter + if err := tx.Create(feedback).Error; err != nil { + log.WithError(err).Error("Error creating feedback") + return status.Error(codes.Internal, "Error creating feedback") + } + return stream.SendAndClose(&pb.SendFeedbackReply{}) + }) +} + +func deleteUploaded(tx *gorm.DB, id string) { + // delete uploaded images + dbPath := fmt.Sprintf("feedback/%s", id) + if err := tx.Find(&model.File{Path: dbPath}).Delete(&model.File{}).Error; err != nil { + log.WithError(err).WithField("path", dbPath).Error("Error deleting uploaded images from db") + } + if err := os.RemoveAll(cron.StorageDir + dbPath); err != nil { + log.WithError(err).WithField("path", dbPath).Error("Error deleting uploaded images from filesystem") + } +} + +func handleImageUpload(tx *gorm.DB, content *[]byte, imageCounter int32, id string) int32 { + filename := inferFileName(content, imageCounter) + dbPath := fmt.Sprintf("feedback/%s", id) + realPath := cron.StorageDir + dbPath + + if err := os.MkdirAll(path.Base(realPath), 0755); err != nil { + log.WithError(err).WithField("dbPath", dbPath).Error("Error creating directory for feedback") + return imageCounter + } + out, err := os.Create(realPath) + if err != nil { + log.WithError(err).WithField("path", dbPath).Error("Error creating file for feedback") + return imageCounter + } + defer func(out *os.File) { + err := out.Close() + if err != nil { + log.WithError(err).WithField("path", dbPath).Error("Error while closing file") + } + }(out) + if _, err := io.Copy(out, bytes.NewReader(*content)); err != nil { + log.WithError(err).WithField("path", dbPath).Error("Error while writing file") + if err := os.Remove(realPath); err != nil { + log.WithError(err).WithField("path", dbPath).Warn("Could not clean up file") + } + return imageCounter + } + + tx.Create(&model.File{ + Name: filename, + Path: dbPath, + Downloads: 1, + Downloaded: null.BoolFrom(true), + }) + return imageCounter + 1 +} + +func inferFileName(content *[]byte, counter int32) string { + ext := mimetype.Detect(*content).Extension() + return fmt.Sprintf("%d%s", counter, ext) +} + +func convertReqToFeedback(req *pb.SendFeedbackRequest) (*model.Feedback, error) { + id, err := uuid.NewGen().NewV7() + if err != nil { + log.WithError(err).Error("Error generating uuid") + return nil, err + } + result := model.Feedback{ + EmailId: null.StringFrom(id.String()), + Receiver: null.StringFrom(receiverFromTopic(req.Topic)), + } + if req.Metadata.OsVersion != "" { + result.OsVersion = null.StringFrom(req.Metadata.OsVersion) + } + if req.Metadata.AppVersion != "" { + result.AppVersion = null.StringFrom(req.Metadata.AppVersion) + } + if req.Message != "" { + result.Feedback = null.StringFrom(req.Message) + } + if req.FromEmail != "" { + result.ReplyTo = null.StringFrom(req.FromEmail) + } + if req.Metadata.Longitude != 0 { + result.Longitude = null.FloatFrom(req.Metadata.Longitude) + } + if req.Metadata.Latitude != 0 { + result.Latitude = null.FloatFrom(req.Metadata.Latitude) + } + + return &result, nil +} + +func receiverFromTopic(topic pb.SendFeedbackRequest_FeedbackTopic) string { + switch topic { + case pb.SendFeedbackRequest_TUM_DEV: + return "app@tum.de" + default: + return "kontakt@tum.de" + } +} diff --git a/server/backend/feedback_test.go b/server/backend/feedback_test.go new file mode 100644 index 00000000..fa5fa5f0 --- /dev/null +++ b/server/backend/feedback_test.go @@ -0,0 +1,117 @@ +package backend + +import ( + "bytes" + "context" + "database/sql" + "image" + "image/png" + "io" + "regexp" + "testing" + "time" + + "github.com/DATA-DOG/go-sqlmock" + pb "github.com/TUM-Dev/Campus-Backend/server/api/tumdev" + "github.com/stretchr/testify/require" + "github.com/stretchr/testify/suite" + "google.golang.org/grpc" + "gorm.io/driver/mysql" + "gorm.io/gorm" +) + +type FeedbackSuite struct { + suite.Suite + DB *gorm.DB + mock sqlmock.Sqlmock +} + +func (s *FeedbackSuite) SetupSuite() { + var ( + db *sql.DB + err error + ) + + db, s.mock, err = sqlmock.New() + require.NoError(s.T(), err) + + dialector := mysql.New(mysql.Config{ + Conn: db, + DriverName: "mysql", + }) + s.mock.ExpectQuery("SELECT VERSION()"). + WillReturnRows(sqlmock.NewRows([]string{"VERSION()"}).AddRow("10.11.4-MariaDB")) + s.DB, err = gorm.Open(dialector, &gorm.Config{}) + require.NoError(s.T(), err) +} + +type mockedFeedbackStream struct { + grpc.ServerStream + recived []*pb.SendFeedbackRequest + reply *pb.SendFeedbackReply + T *testing.T +} + +func (f mockedFeedbackStream) SendAndClose(reply *pb.SendFeedbackReply) error { + require.Equal(f.T, f.reply, reply) + return nil +} + +// because of the way the mocked stream works, we need to keep track of the index +// we however can't track this inside of mockedFeedbackStream, as we cannot mutate the struct +// => tracking this as a global variable is the only way +var index = uint(0) + +func (f mockedFeedbackStream) Recv() (*pb.SendFeedbackRequest, error) { + if int(index) >= len(f.recived) { + return nil, io.EOF + } + index++ + return f.recived[index-1], nil +} + +func (f mockedFeedbackStream) Context() context.Context { + // reset index, as this function is called before Recv() + // This is a hacky solution, but it works + index = 0 + return context.Background() +} + +// createDummyImage creates a dummy image with the specified dimensions +func createDummyImage(t *testing.T, width, height int) []byte { + img := image.NewRGBA(image.Rect(0, 0, width, height)) + // encode img to buffer + buf := new(bytes.Buffer) + require.NoError(t, png.Encode(buf, img)) + return buf.Bytes() +} + +func (s *FeedbackSuite) Test_SendFeedback() { + server := CampusServer{db: s.DB} + s.mock.ExpectBegin() + returnedTime := time.Now() + s.mock.ExpectQuery(regexp.QuoteMeta("INSERT INTO `feedback` (`image_count`,`email_id`,`receiver`,`reply_to`,`feedback`,`latitude`,`longitude`,`os_version`,`app_version`,`processed`) VALUES (?,?,?,?,?,?,?,?,?,?) RETURNING `timestamp`,`id`")). + WithArgs(1, "018abf31-8bb5-79ee-b08c-aed101c6e9f7", "app@tum.de", "testing@example.com", "Hello World", nil, nil, nil, nil, false). + WillReturnRows(sqlmock.NewRows([]string{"timestamp", "id"}).AddRow(returnedTime, 1)) + s.mock.ExpectCommit() + + stream := mockedFeedbackStream{ + T: s.T(), + recived: []*pb.SendFeedbackRequest{ + {Topic: 0, FromEmail: "testing@example.com", Message: "Hello World", Metadata: &pb.SendFeedbackRequest_Metadata{}}, + {Image: createDummyImage(s.T(), 10, 10)}, + }, + reply: &pb.SendFeedbackReply{}, + } + require.NoError(s.T(), server.SendFeedback(stream)) +} + +func (s *FeedbackSuite) AfterTest(_, _ string) { + require.NoError(s.T(), s.mock.ExpectationsWereMet()) +} + +// In order for 'go test' to run this suite, we need to create +// a normal test function and pass our suite to suite.Run +func TestExampleTestSuite(t *testing.T) { + suite.Run(t, new(FeedbackSuite)) +}