From 5f3de4ade2d3d9c3bb4b835dc50d866d6376bfa9 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Tue, 24 Sep 2024 01:13:46 +0800 Subject: [PATCH] made sure that the student clubs are localised --- server/api/tumdev/campus_backend.pb.go | 756 ++++++++++-------- server/api/tumdev/campus_backend.pb.gw.go | 18 + server/api/tumdev/campus_backend.proto | 12 +- server/api/tumdev/campus_backend.swagger.json | 22 + server/backend/cron/cronjobs.go | 4 +- server/backend/cron/student_clubs.go | 9 +- server/backend/cron/student_clubs_test.go | 11 +- server/backend/migration/20241023000000.go | 32 + server/backend/migration/migration.go | 1 + server/backend/student_club.go | 3 +- server/model/student_club.go | 1 + server/model/student_club_collection.go | 1 + 12 files changed, 516 insertions(+), 354 deletions(-) create mode 100644 server/backend/migration/20241023000000.go diff --git a/server/api/tumdev/campus_backend.pb.go b/server/api/tumdev/campus_backend.pb.go index 9595a889..d65fb97b 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 Language int32 + +const ( + Language_German Language = 0 + Language_English Language = 1 +) + +// Enum value maps for Language. +var ( + Language_name = map[int32]string{ + 0: "German", + 1: "English", + } + Language_value = map[string]int32{ + "German": 0, + "English": 1, + } +) + +func (x Language) Enum() *Language { + p := new(Language) + *p = x + return p +} + +func (x Language) String() string { + return protoimpl.X.EnumStringOf(x.Descriptor(), protoreflect.EnumNumber(x)) +} + +func (Language) Descriptor() protoreflect.EnumDescriptor { + return file_tumdev_campus_backend_proto_enumTypes[1].Descriptor() +} + +func (Language) Type() protoreflect.EnumType { + return &file_tumdev_campus_backend_proto_enumTypes[1] +} + +func (x Language) Number() protoreflect.EnumNumber { + return protoreflect.EnumNumber(x) +} + +// Deprecated: Use Language.Descriptor instead. +func (Language) EnumDescriptor() ([]byte, []int) { + return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{1} +} + type CreateFeedbackRequest_Recipient int32 const ( @@ -104,11 +150,11 @@ func (x CreateFeedbackRequest_Recipient) String() string { } func (CreateFeedbackRequest_Recipient) Descriptor() protoreflect.EnumDescriptor { - return file_tumdev_campus_backend_proto_enumTypes[1].Descriptor() + return file_tumdev_campus_backend_proto_enumTypes[2].Descriptor() } func (CreateFeedbackRequest_Recipient) Type() protoreflect.EnumType { - return &file_tumdev_campus_backend_proto_enumTypes[1] + return &file_tumdev_campus_backend_proto_enumTypes[2] } func (x CreateFeedbackRequest_Recipient) Number() protoreflect.EnumNumber { @@ -3750,6 +3796,10 @@ type ListStudentClubRequest struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache unknownFields protoimpl.UnknownFields + + // Language of the student clubs and categories + // Defaults to german + Language *Language `protobuf:"varint,1,opt,name=language,proto3,enum=api.Language,oneof" json:"language,omitempty"` } func (x *ListStudentClubRequest) Reset() { @@ -3784,6 +3834,13 @@ func (*ListStudentClubRequest) Descriptor() ([]byte, []int) { return file_tumdev_campus_backend_proto_rawDescGZIP(), []int{58} } +func (x *ListStudentClubRequest) GetLanguage() Language { + if x != nil && x.Language != nil { + return *x.Language + } + return Language_German +} + type ListStudentClubReply struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -4383,198 +4440,204 @@ var file_tumdev_campus_backend_proto_rawDesc = []byte{ 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, 0x22, 0x18, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x75, 0x64, 0x65, - 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x22, 0x54, 0x0a, - 0x14, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, - 0x52, 0x65, 0x70, 0x6c, 0x79, 0x12, 0x3c, 0x0a, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, - 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x43, 0x6f, 0x6c, 0x6c, - 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x22, 0xb5, 0x01, 0x0a, 0x0b, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, - 0x6c, 0x75, 0x62, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, - 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, - 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, - 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1e, - 0x0a, 0x08, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, - 0x48, 0x01, 0x52, 0x07, 0x6c, 0x69, 0x6e, 0x6b, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x20, - 0x0a, 0x09, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, - 0x09, 0x48, 0x02, 0x52, 0x08, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, - 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, - 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x42, 0x0c, 0x0a, - 0x0a, 0x5f, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x22, 0x77, 0x0a, 0x15, 0x53, - 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, - 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 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, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x05, - 0x63, 0x6c, 0x75, 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x52, 0x05, 0x63, - 0x6c, 0x75, 0x62, 0x73, 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, 0xbc, 0x13, 0x0a, 0x06, 0x43, 0x61, 0x6d, 0x70, 0x75, 0x73, - 0x12, 0x64, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x41, 0x6c, 0x65, 0x72, - 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, - 0x73, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x41, 0x6c, 0x65, - 0x72, 0x74, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x16, - 0x62, 0x06, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x73, 0x12, 0x0c, 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x2f, - 0x61, 0x6c, 0x65, 0x72, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, - 0x77, 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, - 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, 0x49, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x12, 0x14, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x52, 0x65, 0x71, 0x75, - 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, - 0x77, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0d, 0x62, - 0x04, 0x6e, 0x65, 0x77, 0x73, 0x12, 0x05, 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x12, 0x72, 0x0a, 0x12, - 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, - 0x67, 0x73, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x6e, - 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, - 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x75, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, - 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x1f, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, - 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1d, 0x2e, - 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 0x69, 0x0a, 0x10, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x68, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, - 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, - 0x68, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1a, - 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x68, 0x52, - 0x61, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, + 0x61, 0x6d, 0x70, 0x22, 0x55, 0x0a, 0x16, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x75, 0x64, 0x65, + 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x12, 0x2e, 0x0a, + 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0e, 0x32, + 0x0d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x48, 0x00, + 0x52, 0x08, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, + 0x09, 0x5f, 0x6c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x22, 0x54, 0x0a, 0x14, 0x4c, 0x69, + 0x73, 0x74, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x52, 0x65, 0x70, + 0x6c, 0x79, 0x12, 0x3c, 0x0a, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, + 0x73, 0x18, 0x01, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, 0x74, + 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, + 0x69, 0x6f, 0x6e, 0x52, 0x0b, 0x63, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x22, 0xb5, 0x01, 0x0a, 0x0b, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, + 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x01, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, + 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x25, 0x0a, 0x0b, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x02, 0x20, 0x01, 0x28, 0x09, 0x48, 0x00, 0x52, 0x0b, 0x64, 0x65, 0x73, + 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, 0x12, 0x1e, 0x0a, 0x08, 0x6c, + 0x69, 0x6e, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x48, 0x01, 0x52, + 0x07, 0x6c, 0x69, 0x6e, 0x6b, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x12, 0x20, 0x0a, 0x09, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x48, 0x02, + 0x52, 0x08, 0x63, 0x6f, 0x76, 0x65, 0x72, 0x55, 0x72, 0x6c, 0x88, 0x01, 0x01, 0x42, 0x0e, 0x0a, + 0x0c, 0x5f, 0x64, 0x65, 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x0b, 0x0a, + 0x09, 0x5f, 0x6c, 0x69, 0x6e, 0x6b, 0x5f, 0x75, 0x72, 0x6c, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x63, + 0x6f, 0x76, 0x65, 0x72, 0x5f, 0x75, 0x72, 0x6c, 0x22, 0x77, 0x0a, 0x15, 0x53, 0x74, 0x75, 0x64, + 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x43, 0x6f, 0x6c, 0x6c, 0x65, 0x63, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x14, 0x0a, 0x05, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x18, 0x01, 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, 0x02, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x64, 0x65, + 0x73, 0x63, 0x72, 0x69, 0x70, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x26, 0x0a, 0x05, 0x63, 0x6c, 0x75, + 0x62, 0x73, 0x18, 0x03, 0x20, 0x03, 0x28, 0x0b, 0x32, 0x10, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x53, + 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x52, 0x05, 0x63, 0x6c, 0x75, 0x62, + 0x73, 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, 0x2a, 0x23, 0x0a, 0x08, 0x4c, 0x61, 0x6e, 0x67, 0x75, 0x61, 0x67, 0x65, 0x12, 0x0a, + 0x0a, 0x06, 0x47, 0x65, 0x72, 0x6d, 0x61, 0x6e, 0x10, 0x00, 0x12, 0x0b, 0x0a, 0x07, 0x45, 0x6e, + 0x67, 0x6c, 0x69, 0x73, 0x68, 0x10, 0x01, 0x32, 0xbc, 0x13, 0x0a, 0x06, 0x43, 0x61, 0x6d, 0x70, + 0x75, 0x73, 0x12, 0x64, 0x0a, 0x0e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x41, 0x6c, + 0x65, 0x72, 0x74, 0x73, 0x12, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, + 0x65, 0x77, 0x73, 0x41, 0x6c, 0x65, 0x72, 0x74, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x41, + 0x6c, 0x65, 0x72, 0x74, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1c, 0x82, 0xd3, 0xe4, 0x93, + 0x02, 0x16, 0x62, 0x06, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x73, 0x12, 0x0c, 0x2f, 0x6e, 0x65, 0x77, + 0x73, 0x2f, 0x61, 0x6c, 0x65, 0x72, 0x74, 0x73, 0x12, 0x69, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, + 0x4e, 0x65, 0x77, 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x73, 0x12, 0x1b, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x53, 0x6f, 0x75, 0x72, 0x63, 0x65, + 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, + 0x69, 0x73, 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, 0x49, 0x0a, 0x08, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x12, + 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x65, 0x77, 0x73, 0x52, 0x65, + 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x12, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, + 0x4e, 0x65, 0x77, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x13, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x0d, 0x62, 0x04, 0x6e, 0x65, 0x77, 0x73, 0x12, 0x05, 0x2f, 0x6e, 0x65, 0x77, 0x73, 0x12, 0x72, + 0x0a, 0x12, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, + 0x69, 0x6e, 0x67, 0x73, 0x12, 0x1e, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x73, 0x52, 0x65, 0x71, + 0x75, 0x65, 0x73, 0x74, 0x1a, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x6e, 0x65, 0x77, 0x12, 0x8c, 0x01, 0x0a, 0x15, 0x4c, 0x69, 0x73, 0x74, - 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x69, 0x73, 0x68, 0x54, 0x61, 0x67, - 0x73, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x6f, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x4e, 0x61, - 0x6d, 0x65, 0x54, 0x61, 0x67, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, - 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x98, 0x01, 0x0a, 0x18, 0x4c, 0x69, 0x73, 0x74, - 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, - 0x54, 0x61, 0x67, 0x73, 0x12, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x22, 0x2e, 0x61, 0x70, 0x69, - 0x2e, 0x4c, 0x69, 0x73, 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, 0x67, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, - 0x6e, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x6e, - 0x74, 0x65, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x51, 0x0a, 0x0a, 0x4c, - 0x69, 0x73, 0x74, 0x44, 0x69, 0x73, 0x68, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, - 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x73, 0x68, - 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0f, 0x62, - 0x04, 0x64, 0x69, 0x73, 0x68, 0x12, 0x07, 0x2f, 0x64, 0x69, 0x73, 0x68, 0x65, 0x73, 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, 0x55, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x69, 0x65, 0x73, - 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x69, 0x65, - 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, - 0x69, 0x73, 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, 0x67, 0x0a, 0x0e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x1a, 0x2e, 0x61, 0x70, - 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, - 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, - 0x65, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, 0x70, 0x6c, - 0x79, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x0a, 0x61, 0x74, 0x74, 0x61, 0x63, - 0x68, 0x6d, 0x65, 0x6e, 0x74, 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, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x70, 0x6c, 0x6f, - 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x21, 0x82, - 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x75, - 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x2f, 0x7b, 0x6c, 0x72, 0x7a, 0x5f, 0x69, 0x64, 0x7d, - 0x12, 0x73, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, - 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, - 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, - 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x28, 0x82, 0xd3, 0xe4, - 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, - 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, - 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x90, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, - 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, - 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 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, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 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, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, 0x12, 0x28, - 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x63, - 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x2f, 0x7b, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, - 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x52, 0x0a, 0x09, 0x47, 0x65, 0x74, 0x4d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4d, - 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x70, 0x6c, - 0x79, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x6d, 0x65, 0x6d, 0x62, - 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x6c, 0x72, 0x7a, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x7e, 0x0a, 0x13, - 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x43, 0x6f, - 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 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, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x43, 0x61, - 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x52, 0x65, - 0x70, 0x6c, 0x79, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, 0x63, 0x61, - 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x2f, - 0x7b, 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x54, 0x0a, 0x0c, - 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x18, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, - 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, - 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x12, - 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x3a, 0x01, 0x2a, 0x22, 0x07, 0x2f, 0x64, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, - 0x63, 0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, - 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, - 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x2a, 0x13, 0x2f, 0x64, - 0x65, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, 0x69, 0x64, - 0x7d, 0x12, 0x61, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, - 0x43, 0x6c, 0x75, 0x62, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, - 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, - 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x75, 0x64, - 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x16, 0x82, 0xd3, - 0xe4, 0x93, 0x02, 0x10, 0x2a, 0x0e, 0x2f, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x5f, 0x63, - 0x6c, 0x75, 0x62, 0x73, 0x42, 0x5e, 0x0a, 0x12, 0x61, 0x70, 0x70, 0x2e, 0x74, 0x75, 0x6d, 0x2e, - 0x63, 0x61, 0x6d, 0x70, 0x75, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x0e, 0x43, 0x61, 0x6d, 0x70, - 0x75, 0x73, 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x25, 0x67, 0x69, - 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x55, 0x4d, 0x2d, 0x44, 0x65, 0x76, - 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x75, 0x73, 0x2d, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, 0x64, 0x2f, - 0x61, 0x70, 0x69, 0xaa, 0x02, 0x0e, 0x43, 0x61, 0x6d, 0x70, 0x75, 0x73, 0x41, 0x70, 0x69, 0x50, - 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, + 0x69, 0x6e, 0x67, 0x2f, 0x67, 0x65, 0x74, 0x12, 0x75, 0x0a, 0x13, 0x43, 0x72, 0x65, 0x61, 0x74, + 0x65, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x12, 0x1f, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x43, 0x61, 0x6e, 0x74, 0x65, + 0x65, 0x6e, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, + 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 0x69, + 0x0a, 0x10, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x69, 0x73, 0x68, 0x52, 0x61, 0x74, 0x69, + 0x6e, 0x67, 0x12, 0x1c, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, + 0x69, 0x73, 0x68, 0x52, 0x61, 0x74, 0x69, 0x6e, 0x67, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, + 0x1a, 0x1a, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 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, 0x8c, 0x01, 0x0a, 0x15, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x44, 0x69, 0x73, 0x68, 0x54, + 0x61, 0x67, 0x73, 0x12, 0x21, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, + 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, 0x6f, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, + 0x4e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x67, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, + 0x69, 0x73, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x54, 0x61, 0x67, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x98, 0x01, 0x0a, 0x18, 0x4c, 0x69, + 0x73, 0x74, 0x41, 0x76, 0x61, 0x69, 0x6c, 0x61, 0x62, 0x6c, 0x65, 0x43, 0x61, 0x6e, 0x74, 0x65, + 0x65, 0x6e, 0x54, 0x61, 0x67, 0x73, 0x12, 0x24, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, + 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, 0x22, 0x2e, 0x61, + 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x67, 0x0a, 0x0c, 0x4c, 0x69, 0x73, 0x74, 0x43, 0x61, 0x6e, 0x74, + 0x65, 0x65, 0x6e, 0x73, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x43, + 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 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, 0x51, 0x0a, + 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x73, 0x68, 0x65, 0x73, 0x12, 0x16, 0x2e, 0x61, 0x70, + 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x44, 0x69, + 0x73, 0x68, 0x65, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x15, 0x82, 0xd3, 0xe4, 0x93, 0x02, + 0x0f, 0x62, 0x04, 0x64, 0x69, 0x73, 0x68, 0x12, 0x07, 0x2f, 0x64, 0x69, 0x73, 0x68, 0x65, 0x73, + 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, 0x55, 0x0a, 0x0a, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x6f, 0x76, 0x69, + 0x65, 0x73, 0x12, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x4d, 0x6f, 0x76, + 0x69, 0x65, 0x73, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x14, 0x2e, 0x61, 0x70, 0x69, + 0x2e, 0x4c, 0x69, 0x73, 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, 0x67, 0x0a, 0x0e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x12, 0x1a, 0x2e, + 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, + 0x63, 0x6b, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, + 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x46, 0x65, 0x65, 0x64, 0x62, 0x61, 0x63, 0x6b, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x22, 0x1d, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x17, 0x3a, 0x0a, 0x61, 0x74, 0x74, + 0x61, 0x63, 0x68, 0x6d, 0x65, 0x6e, 0x74, 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, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x55, 0x70, + 0x6c, 0x6f, 0x61, 0x64, 0x53, 0x74, 0x61, 0x74, 0x75, 0x73, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, + 0x21, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x1b, 0x12, 0x19, 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, + 0x2f, 0x75, 0x70, 0x6c, 0x6f, 0x61, 0x64, 0x65, 0x64, 0x2f, 0x7b, 0x6c, 0x72, 0x7a, 0x5f, 0x69, + 0x64, 0x7d, 0x12, 0x73, 0x0a, 0x0f, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, + 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x71, 0x75, 0x65, + 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4e, 0x6f, 0x74, 0x69, + 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x28, 0x82, + 0xd3, 0xe4, 0x93, 0x02, 0x22, 0x12, 0x20, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, + 0x74, 0x69, 0x6f, 0x6e, 0x73, 0x2f, 0x7b, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x90, 0x01, 0x0a, 0x16, 0x47, 0x65, 0x74, 0x4e, + 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x43, 0x6f, 0x6e, 0x66, 0x69, + 0x72, 0x6d, 0x12, 0x22, 0x2e, 0x61, 0x70, 0x69, 0x2e, 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, 0x1a, 0x20, 0x2e, 0x61, 0x70, 0x69, 0x2e, 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, 0x22, 0x30, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x2a, + 0x12, 0x28, 0x2f, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x73, + 0x2f, 0x63, 0x6f, 0x6e, 0x66, 0x69, 0x72, 0x6d, 0x2f, 0x7b, 0x6e, 0x6f, 0x74, 0x69, 0x66, 0x69, + 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x52, 0x0a, 0x09, 0x47, 0x65, + 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x12, 0x15, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, + 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x13, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, 0x4d, 0x65, 0x6d, 0x62, 0x65, 0x72, 0x52, 0x65, + 0x70, 0x6c, 0x79, 0x22, 0x19, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x13, 0x12, 0x11, 0x2f, 0x6d, 0x65, + 0x6d, 0x62, 0x65, 0x72, 0x73, 0x2f, 0x7b, 0x6c, 0x72, 0x7a, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x7e, + 0x0a, 0x13, 0x47, 0x65, 0x74, 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x48, 0x65, 0x61, 0x64, + 0x43, 0x6f, 0x75, 0x6e, 0x74, 0x12, 0x1f, 0x2e, 0x61, 0x70, 0x69, 0x2e, 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, 0x1a, 0x1d, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x47, 0x65, 0x74, + 0x43, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x48, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, 0x74, + 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x27, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x21, 0x12, 0x1f, 0x2f, + 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x2f, 0x68, 0x65, 0x61, 0x64, 0x43, 0x6f, 0x75, 0x6e, + 0x74, 0x2f, 0x7b, 0x63, 0x61, 0x6e, 0x74, 0x65, 0x65, 0x6e, 0x5f, 0x69, 0x64, 0x7d, 0x12, 0x54, + 0x0a, 0x0c, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x12, 0x18, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x43, + 0x72, 0x65, 0x61, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, + 0x22, 0x12, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x0c, 0x3a, 0x01, 0x2a, 0x22, 0x07, 0x2f, 0x64, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x5d, 0x0a, 0x0c, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, + 0x76, 0x69, 0x63, 0x65, 0x12, 0x18, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, + 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, 0x65, 0x52, 0x65, 0x71, 0x75, 0x65, 0x73, 0x74, 0x1a, 0x16, + 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x44, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x44, 0x65, 0x76, 0x69, 0x63, + 0x65, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x1b, 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x15, 0x2a, 0x13, + 0x2f, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x2f, 0x7b, 0x64, 0x65, 0x76, 0x69, 0x63, 0x65, 0x5f, + 0x69, 0x64, 0x7d, 0x12, 0x61, 0x0a, 0x0f, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, 0x75, 0x64, 0x65, + 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x12, 0x1b, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, + 0x74, 0x53, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x52, 0x65, 0x71, 0x75, + 0x65, 0x73, 0x74, 0x1a, 0x19, 0x2e, 0x61, 0x70, 0x69, 0x2e, 0x4c, 0x69, 0x73, 0x74, 0x53, 0x74, + 0x75, 0x64, 0x65, 0x6e, 0x74, 0x43, 0x6c, 0x75, 0x62, 0x52, 0x65, 0x70, 0x6c, 0x79, 0x22, 0x16, + 0x82, 0xd3, 0xe4, 0x93, 0x02, 0x10, 0x2a, 0x0e, 0x2f, 0x73, 0x74, 0x75, 0x64, 0x65, 0x6e, 0x74, + 0x5f, 0x63, 0x6c, 0x75, 0x62, 0x73, 0x42, 0x5e, 0x0a, 0x12, 0x61, 0x70, 0x70, 0x2e, 0x74, 0x75, + 0x6d, 0x2e, 0x63, 0x61, 0x6d, 0x70, 0x75, 0x73, 0x2e, 0x61, 0x70, 0x69, 0x42, 0x0e, 0x43, 0x61, + 0x6d, 0x70, 0x75, 0x73, 0x41, 0x70, 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x50, 0x01, 0x5a, 0x25, + 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x54, 0x55, 0x4d, 0x2d, 0x44, + 0x65, 0x76, 0x2f, 0x43, 0x61, 0x6d, 0x70, 0x75, 0x73, 0x2d, 0x42, 0x61, 0x63, 0x6b, 0x65, 0x6e, + 0x64, 0x2f, 0x61, 0x70, 0x69, 0xaa, 0x02, 0x0e, 0x43, 0x61, 0x6d, 0x70, 0x75, 0x73, 0x41, 0x70, + 0x69, 0x50, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -4589,164 +4652,166 @@ 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, 2) +var file_tumdev_campus_backend_proto_enumTypes = make([]protoimpl.EnumInfo, 3) var file_tumdev_campus_backend_proto_msgTypes = make([]protoimpl.MessageInfo, 62) var file_tumdev_campus_backend_proto_goTypes = []any{ (DeviceType)(0), // 0: api.DeviceType - (CreateFeedbackRequest_Recipient)(0), // 1: api.CreateFeedbackRequest.Recipient - (*CreateDeviceRequest)(nil), // 2: api.CreateDeviceRequest - (*CreateDeviceReply)(nil), // 3: api.CreateDeviceReply - (*DeleteDeviceRequest)(nil), // 4: api.DeleteDeviceRequest - (*DeleteDeviceReply)(nil), // 5: api.DeleteDeviceReply - (*News)(nil), // 6: api.News - (*ListNewsReply)(nil), // 7: api.ListNewsReply - (*ListNewsRequest)(nil), // 8: api.ListNewsRequest - (*ListNewsSourcesRequest)(nil), // 9: api.ListNewsSourcesRequest - (*ListNewsSourcesReply)(nil), // 10: api.ListNewsSourcesReply - (*NewsSource)(nil), // 11: api.NewsSource - (*ListNewsAlertsRequest)(nil), // 12: api.ListNewsAlertsRequest - (*ListNewsAlertsReply)(nil), // 13: api.ListNewsAlertsReply - (*NewsAlert)(nil), // 14: api.NewsAlert - (*ListCanteenRatingsRequest)(nil), // 15: api.ListCanteenRatingsRequest - (*ListCanteenRatingsReply)(nil), // 16: api.ListCanteenRatingsReply - (*GetDishRatingsRequest)(nil), // 17: api.GetDishRatingsRequest - (*GetDishRatingsReply)(nil), // 18: api.GetDishRatingsReply - (*SingleRatingReply)(nil), // 19: api.SingleRatingReply - (*CreateCanteenRatingReply)(nil), // 20: api.CreateCanteenRatingReply - (*CreateCanteenRatingRequest)(nil), // 21: api.CreateCanteenRatingRequest - (*CreateDishRatingReply)(nil), // 22: api.CreateDishRatingReply - (*CreateDishRatingRequest)(nil), // 23: api.CreateDishRatingRequest - (*ListAvailableDishTagsRequest)(nil), // 24: api.ListAvailableDishTagsRequest - (*ListAvailableDishTagsReply)(nil), // 25: api.ListAvailableDishTagsReply - (*ListNameTagsRequest)(nil), // 26: api.ListNameTagsRequest - (*ListNameTagsReply)(nil), // 27: api.ListNameTagsReply - (*ListAvailableCanteenTagsRequest)(nil), // 28: api.ListAvailableCanteenTagsRequest - (*ListAvailableCanteenTagsReply)(nil), // 29: api.ListAvailableCanteenTagsReply - (*TagsOverview)(nil), // 30: api.TagsOverview - (*RatingTag)(nil), // 31: api.RatingTag - (*RatingTagNewRequest)(nil), // 32: api.RatingTagNewRequest - (*RatingTagResult)(nil), // 33: api.RatingTagResult - (*ListCanteensRequest)(nil), // 34: api.ListCanteensRequest - (*ListCanteensReply)(nil), // 35: api.ListCanteensReply - (*Canteen)(nil), // 36: api.Canteen - (*ListDishesRequest)(nil), // 37: api.ListDishesRequest - (*ListDishesReply)(nil), // 38: api.ListDishesReply - (*RoomInformationElement)(nil), // 39: api.RoomInformationElement - (*GetUpdateNoteRequest)(nil), // 40: api.GetUpdateNoteRequest - (*GetUpdateNoteReply)(nil), // 41: api.GetUpdateNoteReply - (*ListMoviesRequest)(nil), // 42: api.ListMoviesRequest - (*ListMoviesReply)(nil), // 43: api.ListMoviesReply - (*Movie)(nil), // 44: api.Movie - (*CreateFeedbackRequest)(nil), // 45: api.CreateFeedbackRequest - (*Coordinate)(nil), // 46: api.Coordinate - (*CreateFeedbackReply)(nil), // 47: api.CreateFeedbackReply - (*CreateFeedbackImageReply)(nil), // 48: api.CreateFeedbackImageReply - (*CreateFeedbackImageRequest)(nil), // 49: api.CreateFeedbackImageRequest - (*GetMemberRequest)(nil), // 50: api.GetMemberRequest - (*GetMemberReply)(nil), // 51: api.GetMemberReply - (*GetUploadStatusRequest)(nil), // 52: api.GetUploadStatusRequest - (*GetUploadStatusReply)(nil), // 53: api.GetUploadStatusReply - (*GetNotificationRequest)(nil), // 54: api.GetNotificationRequest - (*GetNotificationReply)(nil), // 55: api.GetNotificationReply - (*GetNotificationConfirmRequest)(nil), // 56: api.GetNotificationConfirmRequest - (*GetNotificationConfirmReply)(nil), // 57: api.GetNotificationConfirmReply - (*GetCanteenHeadCountRequest)(nil), // 58: api.GetCanteenHeadCountRequest - (*GetCanteenHeadCountReply)(nil), // 59: api.GetCanteenHeadCountReply - (*ListStudentClubRequest)(nil), // 60: api.ListStudentClubRequest - (*ListStudentClubReply)(nil), // 61: api.ListStudentClubReply - (*StudentClub)(nil), // 62: api.StudentClub - (*StudentClubCollection)(nil), // 63: api.StudentClubCollection - (*timestamppb.Timestamp)(nil), // 64: google.protobuf.Timestamp + (Language)(0), // 1: api.Language + (CreateFeedbackRequest_Recipient)(0), // 2: api.CreateFeedbackRequest.Recipient + (*CreateDeviceRequest)(nil), // 3: api.CreateDeviceRequest + (*CreateDeviceReply)(nil), // 4: api.CreateDeviceReply + (*DeleteDeviceRequest)(nil), // 5: api.DeleteDeviceRequest + (*DeleteDeviceReply)(nil), // 6: api.DeleteDeviceReply + (*News)(nil), // 7: api.News + (*ListNewsReply)(nil), // 8: api.ListNewsReply + (*ListNewsRequest)(nil), // 9: api.ListNewsRequest + (*ListNewsSourcesRequest)(nil), // 10: api.ListNewsSourcesRequest + (*ListNewsSourcesReply)(nil), // 11: api.ListNewsSourcesReply + (*NewsSource)(nil), // 12: api.NewsSource + (*ListNewsAlertsRequest)(nil), // 13: api.ListNewsAlertsRequest + (*ListNewsAlertsReply)(nil), // 14: api.ListNewsAlertsReply + (*NewsAlert)(nil), // 15: api.NewsAlert + (*ListCanteenRatingsRequest)(nil), // 16: api.ListCanteenRatingsRequest + (*ListCanteenRatingsReply)(nil), // 17: api.ListCanteenRatingsReply + (*GetDishRatingsRequest)(nil), // 18: api.GetDishRatingsRequest + (*GetDishRatingsReply)(nil), // 19: api.GetDishRatingsReply + (*SingleRatingReply)(nil), // 20: api.SingleRatingReply + (*CreateCanteenRatingReply)(nil), // 21: api.CreateCanteenRatingReply + (*CreateCanteenRatingRequest)(nil), // 22: api.CreateCanteenRatingRequest + (*CreateDishRatingReply)(nil), // 23: api.CreateDishRatingReply + (*CreateDishRatingRequest)(nil), // 24: api.CreateDishRatingRequest + (*ListAvailableDishTagsRequest)(nil), // 25: api.ListAvailableDishTagsRequest + (*ListAvailableDishTagsReply)(nil), // 26: api.ListAvailableDishTagsReply + (*ListNameTagsRequest)(nil), // 27: api.ListNameTagsRequest + (*ListNameTagsReply)(nil), // 28: api.ListNameTagsReply + (*ListAvailableCanteenTagsRequest)(nil), // 29: api.ListAvailableCanteenTagsRequest + (*ListAvailableCanteenTagsReply)(nil), // 30: api.ListAvailableCanteenTagsReply + (*TagsOverview)(nil), // 31: api.TagsOverview + (*RatingTag)(nil), // 32: api.RatingTag + (*RatingTagNewRequest)(nil), // 33: api.RatingTagNewRequest + (*RatingTagResult)(nil), // 34: api.RatingTagResult + (*ListCanteensRequest)(nil), // 35: api.ListCanteensRequest + (*ListCanteensReply)(nil), // 36: api.ListCanteensReply + (*Canteen)(nil), // 37: api.Canteen + (*ListDishesRequest)(nil), // 38: api.ListDishesRequest + (*ListDishesReply)(nil), // 39: api.ListDishesReply + (*RoomInformationElement)(nil), // 40: api.RoomInformationElement + (*GetUpdateNoteRequest)(nil), // 41: api.GetUpdateNoteRequest + (*GetUpdateNoteReply)(nil), // 42: api.GetUpdateNoteReply + (*ListMoviesRequest)(nil), // 43: api.ListMoviesRequest + (*ListMoviesReply)(nil), // 44: api.ListMoviesReply + (*Movie)(nil), // 45: api.Movie + (*CreateFeedbackRequest)(nil), // 46: api.CreateFeedbackRequest + (*Coordinate)(nil), // 47: api.Coordinate + (*CreateFeedbackReply)(nil), // 48: api.CreateFeedbackReply + (*CreateFeedbackImageReply)(nil), // 49: api.CreateFeedbackImageReply + (*CreateFeedbackImageRequest)(nil), // 50: api.CreateFeedbackImageRequest + (*GetMemberRequest)(nil), // 51: api.GetMemberRequest + (*GetMemberReply)(nil), // 52: api.GetMemberReply + (*GetUploadStatusRequest)(nil), // 53: api.GetUploadStatusRequest + (*GetUploadStatusReply)(nil), // 54: api.GetUploadStatusReply + (*GetNotificationRequest)(nil), // 55: api.GetNotificationRequest + (*GetNotificationReply)(nil), // 56: api.GetNotificationReply + (*GetNotificationConfirmRequest)(nil), // 57: api.GetNotificationConfirmRequest + (*GetNotificationConfirmReply)(nil), // 58: api.GetNotificationConfirmReply + (*GetCanteenHeadCountRequest)(nil), // 59: api.GetCanteenHeadCountRequest + (*GetCanteenHeadCountReply)(nil), // 60: api.GetCanteenHeadCountReply + (*ListStudentClubRequest)(nil), // 61: api.ListStudentClubRequest + (*ListStudentClubReply)(nil), // 62: api.ListStudentClubReply + (*StudentClub)(nil), // 63: api.StudentClub + (*StudentClubCollection)(nil), // 64: api.StudentClubCollection + (*timestamppb.Timestamp)(nil), // 65: google.protobuf.Timestamp } var file_tumdev_campus_backend_proto_depIdxs = []int32{ 0, // 0: api.CreateDeviceRequest.device_type:type_name -> api.DeviceType 0, // 1: api.DeleteDeviceRequest.device_type:type_name -> api.DeviceType - 64, // 2: api.News.created:type_name -> google.protobuf.Timestamp - 64, // 3: api.News.date:type_name -> google.protobuf.Timestamp - 6, // 4: api.ListNewsReply.news:type_name -> api.News - 64, // 5: api.ListNewsRequest.oldest_date_at:type_name -> google.protobuf.Timestamp - 11, // 6: api.ListNewsSourcesReply.sources:type_name -> api.NewsSource - 14, // 7: api.ListNewsAlertsReply.alerts:type_name -> api.NewsAlert - 64, // 8: api.NewsAlert.created:type_name -> google.protobuf.Timestamp - 64, // 9: api.NewsAlert.from:type_name -> google.protobuf.Timestamp - 64, // 10: api.NewsAlert.to:type_name -> google.protobuf.Timestamp - 64, // 11: api.ListCanteenRatingsRequest.from:type_name -> google.protobuf.Timestamp - 64, // 12: api.ListCanteenRatingsRequest.to:type_name -> google.protobuf.Timestamp - 19, // 13: api.ListCanteenRatingsReply.rating:type_name -> api.SingleRatingReply - 33, // 14: api.ListCanteenRatingsReply.rating_tags:type_name -> api.RatingTagResult - 64, // 15: api.GetDishRatingsRequest.from:type_name -> google.protobuf.Timestamp - 64, // 16: api.GetDishRatingsRequest.to:type_name -> google.protobuf.Timestamp - 19, // 17: api.GetDishRatingsReply.rating:type_name -> api.SingleRatingReply - 33, // 18: api.GetDishRatingsReply.rating_tags:type_name -> api.RatingTagResult - 33, // 19: api.GetDishRatingsReply.name_tags:type_name -> api.RatingTagResult - 32, // 20: api.SingleRatingReply.rating_tags:type_name -> api.RatingTagNewRequest - 64, // 21: api.SingleRatingReply.visited:type_name -> google.protobuf.Timestamp - 31, // 22: api.CreateCanteenRatingRequest.rating_tags:type_name -> api.RatingTag - 31, // 23: api.CreateDishRatingRequest.rating_tags:type_name -> api.RatingTag - 30, // 24: api.ListAvailableDishTagsReply.rating_tags:type_name -> api.TagsOverview - 30, // 25: api.ListNameTagsReply.rating_tags:type_name -> api.TagsOverview - 30, // 26: api.ListAvailableCanteenTagsReply.rating_tags:type_name -> api.TagsOverview - 36, // 27: api.ListCanteensReply.canteen:type_name -> api.Canteen - 64, // 28: api.ListMoviesRequest.oldest_date_at:type_name -> google.protobuf.Timestamp - 44, // 29: api.ListMoviesReply.movies:type_name -> api.Movie - 64, // 30: api.Movie.date:type_name -> google.protobuf.Timestamp - 64, // 31: api.Movie.created:type_name -> google.protobuf.Timestamp - 1, // 32: api.CreateFeedbackRequest.recipient:type_name -> api.CreateFeedbackRequest.Recipient - 46, // 33: api.CreateFeedbackRequest.location:type_name -> api.Coordinate - 64, // 34: api.GetCanteenHeadCountReply.timestamp:type_name -> google.protobuf.Timestamp - 63, // 35: api.ListStudentClubReply.collections:type_name -> api.StudentClubCollection - 62, // 36: api.StudentClubCollection.clubs:type_name -> api.StudentClub - 12, // 37: api.Campus.ListNewsAlerts:input_type -> api.ListNewsAlertsRequest - 9, // 38: api.Campus.ListNewsSources:input_type -> api.ListNewsSourcesRequest - 8, // 39: api.Campus.ListNews:input_type -> api.ListNewsRequest - 15, // 40: api.Campus.ListCanteenRatings:input_type -> api.ListCanteenRatingsRequest - 17, // 41: api.Campus.GetDishRatings:input_type -> api.GetDishRatingsRequest - 21, // 42: api.Campus.CreateCanteenRating:input_type -> api.CreateCanteenRatingRequest - 23, // 43: api.Campus.CreateDishRating:input_type -> api.CreateDishRatingRequest - 24, // 44: api.Campus.ListAvailableDishTags:input_type -> api.ListAvailableDishTagsRequest - 26, // 45: api.Campus.ListNameTags:input_type -> api.ListNameTagsRequest - 28, // 46: api.Campus.ListAvailableCanteenTags:input_type -> api.ListAvailableCanteenTagsRequest - 34, // 47: api.Campus.ListCanteens:input_type -> api.ListCanteensRequest - 37, // 48: api.Campus.ListDishes:input_type -> api.ListDishesRequest - 40, // 49: api.Campus.GetUpdateNote:input_type -> api.GetUpdateNoteRequest - 42, // 50: api.Campus.ListMovies:input_type -> api.ListMoviesRequest - 45, // 51: api.Campus.CreateFeedback:input_type -> api.CreateFeedbackRequest - 52, // 52: api.Campus.GetUploadStatus:input_type -> api.GetUploadStatusRequest - 54, // 53: api.Campus.GetNotification:input_type -> api.GetNotificationRequest - 56, // 54: api.Campus.GetNotificationConfirm:input_type -> api.GetNotificationConfirmRequest - 50, // 55: api.Campus.GetMember:input_type -> api.GetMemberRequest - 58, // 56: api.Campus.GetCanteenHeadCount:input_type -> api.GetCanteenHeadCountRequest - 2, // 57: api.Campus.CreateDevice:input_type -> api.CreateDeviceRequest - 4, // 58: api.Campus.DeleteDevice:input_type -> api.DeleteDeviceRequest - 60, // 59: api.Campus.ListStudentClub:input_type -> api.ListStudentClubRequest - 13, // 60: api.Campus.ListNewsAlerts:output_type -> api.ListNewsAlertsReply - 10, // 61: api.Campus.ListNewsSources:output_type -> api.ListNewsSourcesReply - 7, // 62: api.Campus.ListNews:output_type -> api.ListNewsReply - 16, // 63: api.Campus.ListCanteenRatings:output_type -> api.ListCanteenRatingsReply - 18, // 64: api.Campus.GetDishRatings:output_type -> api.GetDishRatingsReply - 20, // 65: api.Campus.CreateCanteenRating:output_type -> api.CreateCanteenRatingReply - 22, // 66: api.Campus.CreateDishRating:output_type -> api.CreateDishRatingReply - 25, // 67: api.Campus.ListAvailableDishTags:output_type -> api.ListAvailableDishTagsReply - 27, // 68: api.Campus.ListNameTags:output_type -> api.ListNameTagsReply - 29, // 69: api.Campus.ListAvailableCanteenTags:output_type -> api.ListAvailableCanteenTagsReply - 35, // 70: api.Campus.ListCanteens:output_type -> api.ListCanteensReply - 38, // 71: api.Campus.ListDishes:output_type -> api.ListDishesReply - 41, // 72: api.Campus.GetUpdateNote:output_type -> api.GetUpdateNoteReply - 43, // 73: api.Campus.ListMovies:output_type -> api.ListMoviesReply - 47, // 74: api.Campus.CreateFeedback:output_type -> api.CreateFeedbackReply - 53, // 75: api.Campus.GetUploadStatus:output_type -> api.GetUploadStatusReply - 55, // 76: api.Campus.GetNotification:output_type -> api.GetNotificationReply - 57, // 77: api.Campus.GetNotificationConfirm:output_type -> api.GetNotificationConfirmReply - 51, // 78: api.Campus.GetMember:output_type -> api.GetMemberReply - 59, // 79: api.Campus.GetCanteenHeadCount:output_type -> api.GetCanteenHeadCountReply - 3, // 80: api.Campus.CreateDevice:output_type -> api.CreateDeviceReply - 5, // 81: api.Campus.DeleteDevice:output_type -> api.DeleteDeviceReply - 61, // 82: api.Campus.ListStudentClub:output_type -> api.ListStudentClubReply - 60, // [60:83] is the sub-list for method output_type - 37, // [37:60] is the sub-list for method input_type - 37, // [37:37] is the sub-list for extension type_name - 37, // [37:37] is the sub-list for extension extendee - 0, // [0:37] is the sub-list for field type_name + 65, // 2: api.News.created:type_name -> google.protobuf.Timestamp + 65, // 3: api.News.date:type_name -> google.protobuf.Timestamp + 7, // 4: api.ListNewsReply.news:type_name -> api.News + 65, // 5: api.ListNewsRequest.oldest_date_at:type_name -> google.protobuf.Timestamp + 12, // 6: api.ListNewsSourcesReply.sources:type_name -> api.NewsSource + 15, // 7: api.ListNewsAlertsReply.alerts:type_name -> api.NewsAlert + 65, // 8: api.NewsAlert.created:type_name -> google.protobuf.Timestamp + 65, // 9: api.NewsAlert.from:type_name -> google.protobuf.Timestamp + 65, // 10: api.NewsAlert.to:type_name -> google.protobuf.Timestamp + 65, // 11: api.ListCanteenRatingsRequest.from:type_name -> google.protobuf.Timestamp + 65, // 12: api.ListCanteenRatingsRequest.to:type_name -> google.protobuf.Timestamp + 20, // 13: api.ListCanteenRatingsReply.rating:type_name -> api.SingleRatingReply + 34, // 14: api.ListCanteenRatingsReply.rating_tags:type_name -> api.RatingTagResult + 65, // 15: api.GetDishRatingsRequest.from:type_name -> google.protobuf.Timestamp + 65, // 16: api.GetDishRatingsRequest.to:type_name -> google.protobuf.Timestamp + 20, // 17: api.GetDishRatingsReply.rating:type_name -> api.SingleRatingReply + 34, // 18: api.GetDishRatingsReply.rating_tags:type_name -> api.RatingTagResult + 34, // 19: api.GetDishRatingsReply.name_tags:type_name -> api.RatingTagResult + 33, // 20: api.SingleRatingReply.rating_tags:type_name -> api.RatingTagNewRequest + 65, // 21: api.SingleRatingReply.visited:type_name -> google.protobuf.Timestamp + 32, // 22: api.CreateCanteenRatingRequest.rating_tags:type_name -> api.RatingTag + 32, // 23: api.CreateDishRatingRequest.rating_tags:type_name -> api.RatingTag + 31, // 24: api.ListAvailableDishTagsReply.rating_tags:type_name -> api.TagsOverview + 31, // 25: api.ListNameTagsReply.rating_tags:type_name -> api.TagsOverview + 31, // 26: api.ListAvailableCanteenTagsReply.rating_tags:type_name -> api.TagsOverview + 37, // 27: api.ListCanteensReply.canteen:type_name -> api.Canteen + 65, // 28: api.ListMoviesRequest.oldest_date_at:type_name -> google.protobuf.Timestamp + 45, // 29: api.ListMoviesReply.movies:type_name -> api.Movie + 65, // 30: api.Movie.date:type_name -> google.protobuf.Timestamp + 65, // 31: api.Movie.created:type_name -> google.protobuf.Timestamp + 2, // 32: api.CreateFeedbackRequest.recipient:type_name -> api.CreateFeedbackRequest.Recipient + 47, // 33: api.CreateFeedbackRequest.location:type_name -> api.Coordinate + 65, // 34: api.GetCanteenHeadCountReply.timestamp:type_name -> google.protobuf.Timestamp + 1, // 35: api.ListStudentClubRequest.language:type_name -> api.Language + 64, // 36: api.ListStudentClubReply.collections:type_name -> api.StudentClubCollection + 63, // 37: api.StudentClubCollection.clubs:type_name -> api.StudentClub + 13, // 38: api.Campus.ListNewsAlerts:input_type -> api.ListNewsAlertsRequest + 10, // 39: api.Campus.ListNewsSources:input_type -> api.ListNewsSourcesRequest + 9, // 40: api.Campus.ListNews:input_type -> api.ListNewsRequest + 16, // 41: api.Campus.ListCanteenRatings:input_type -> api.ListCanteenRatingsRequest + 18, // 42: api.Campus.GetDishRatings:input_type -> api.GetDishRatingsRequest + 22, // 43: api.Campus.CreateCanteenRating:input_type -> api.CreateCanteenRatingRequest + 24, // 44: api.Campus.CreateDishRating:input_type -> api.CreateDishRatingRequest + 25, // 45: api.Campus.ListAvailableDishTags:input_type -> api.ListAvailableDishTagsRequest + 27, // 46: api.Campus.ListNameTags:input_type -> api.ListNameTagsRequest + 29, // 47: api.Campus.ListAvailableCanteenTags:input_type -> api.ListAvailableCanteenTagsRequest + 35, // 48: api.Campus.ListCanteens:input_type -> api.ListCanteensRequest + 38, // 49: api.Campus.ListDishes:input_type -> api.ListDishesRequest + 41, // 50: api.Campus.GetUpdateNote:input_type -> api.GetUpdateNoteRequest + 43, // 51: api.Campus.ListMovies:input_type -> api.ListMoviesRequest + 46, // 52: api.Campus.CreateFeedback:input_type -> api.CreateFeedbackRequest + 53, // 53: api.Campus.GetUploadStatus:input_type -> api.GetUploadStatusRequest + 55, // 54: api.Campus.GetNotification:input_type -> api.GetNotificationRequest + 57, // 55: api.Campus.GetNotificationConfirm:input_type -> api.GetNotificationConfirmRequest + 51, // 56: api.Campus.GetMember:input_type -> api.GetMemberRequest + 59, // 57: api.Campus.GetCanteenHeadCount:input_type -> api.GetCanteenHeadCountRequest + 3, // 58: api.Campus.CreateDevice:input_type -> api.CreateDeviceRequest + 5, // 59: api.Campus.DeleteDevice:input_type -> api.DeleteDeviceRequest + 61, // 60: api.Campus.ListStudentClub:input_type -> api.ListStudentClubRequest + 14, // 61: api.Campus.ListNewsAlerts:output_type -> api.ListNewsAlertsReply + 11, // 62: api.Campus.ListNewsSources:output_type -> api.ListNewsSourcesReply + 8, // 63: api.Campus.ListNews:output_type -> api.ListNewsReply + 17, // 64: api.Campus.ListCanteenRatings:output_type -> api.ListCanteenRatingsReply + 19, // 65: api.Campus.GetDishRatings:output_type -> api.GetDishRatingsReply + 21, // 66: api.Campus.CreateCanteenRating:output_type -> api.CreateCanteenRatingReply + 23, // 67: api.Campus.CreateDishRating:output_type -> api.CreateDishRatingReply + 26, // 68: api.Campus.ListAvailableDishTags:output_type -> api.ListAvailableDishTagsReply + 28, // 69: api.Campus.ListNameTags:output_type -> api.ListNameTagsReply + 30, // 70: api.Campus.ListAvailableCanteenTags:output_type -> api.ListAvailableCanteenTagsReply + 36, // 71: api.Campus.ListCanteens:output_type -> api.ListCanteensReply + 39, // 72: api.Campus.ListDishes:output_type -> api.ListDishesReply + 42, // 73: api.Campus.GetUpdateNote:output_type -> api.GetUpdateNoteReply + 44, // 74: api.Campus.ListMovies:output_type -> api.ListMoviesReply + 48, // 75: api.Campus.CreateFeedback:output_type -> api.CreateFeedbackReply + 54, // 76: api.Campus.GetUploadStatus:output_type -> api.GetUploadStatusReply + 56, // 77: api.Campus.GetNotification:output_type -> api.GetNotificationReply + 58, // 78: api.Campus.GetNotificationConfirm:output_type -> api.GetNotificationConfirmReply + 52, // 79: api.Campus.GetMember:output_type -> api.GetMemberReply + 60, // 80: api.Campus.GetCanteenHeadCount:output_type -> api.GetCanteenHeadCountReply + 4, // 81: api.Campus.CreateDevice:output_type -> api.CreateDeviceReply + 6, // 82: api.Campus.DeleteDevice:output_type -> api.DeleteDeviceReply + 62, // 83: api.Campus.ListStudentClub:output_type -> api.ListStudentClubReply + 61, // [61:84] is the sub-list for method output_type + 38, // [38:61] 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() } @@ -5500,13 +5565,14 @@ func file_tumdev_campus_backend_proto_init() { } } } + file_tumdev_campus_backend_proto_msgTypes[58].OneofWrappers = []any{} file_tumdev_campus_backend_proto_msgTypes[60].OneofWrappers = []any{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_tumdev_campus_backend_proto_rawDesc, - NumEnums: 2, + NumEnums: 3, NumMessages: 62, 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 918e3225..2331f4cf 100644 --- a/server/api/tumdev/campus_backend.pb.gw.go +++ b/server/api/tumdev/campus_backend.pb.gw.go @@ -855,10 +855,21 @@ func local_request_Campus_DeleteDevice_0(ctx context.Context, marshaler runtime. } +var ( + filter_Campus_ListStudentClub_0 = &utilities.DoubleArray{Encoding: map[string]int{}, Base: []int(nil), Check: []int(nil)} +) + func request_Campus_ListStudentClub_0(ctx context.Context, marshaler runtime.Marshaler, client CampusClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) { var protoReq ListStudentClubRequest 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_ListStudentClub_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := client.ListStudentClub(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD)) return msg, metadata, err @@ -868,6 +879,13 @@ func local_request_Campus_ListStudentClub_0(ctx context.Context, marshaler runti var protoReq ListStudentClubRequest 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_ListStudentClub_0); err != nil { + return nil, metadata, status.Errorf(codes.InvalidArgument, "%v", err) + } + msg, err := server.ListStudentClub(ctx, &protoReq) return msg, metadata, err diff --git a/server/api/tumdev/campus_backend.proto b/server/api/tumdev/campus_backend.proto index 861c8a5b..6aa83fa3 100644 --- a/server/api/tumdev/campus_backend.proto +++ b/server/api/tumdev/campus_backend.proto @@ -564,7 +564,17 @@ message GetCanteenHeadCountReply { // A time stamp indicating how up to date the response is. Only valid in case percent != -1. google.protobuf.Timestamp timestamp = 4; } -message ListStudentClubRequest {} + +enum Language { + German = 0; + English = 1; +} + +message ListStudentClubRequest { + // Language of the student clubs and categories + // Defaults to german + optional Language language = 1; +} message ListStudentClubReply { repeated StudentClubCollection collections = 1; } diff --git a/server/api/tumdev/campus_backend.swagger.json b/server/api/tumdev/campus_backend.swagger.json index d2649ae9..6732f775 100644 --- a/server/api/tumdev/campus_backend.swagger.json +++ b/server/api/tumdev/campus_backend.swagger.json @@ -805,6 +805,20 @@ } } }, + "parameters": [ + { + "name": "language", + "description": "Language of the student clubs and categories\nDefaults to german", + "in": "query", + "required": false, + "type": "string", + "enum": [ + "German", + "English" + ], + "default": "German" + } + ], "tags": [ "Campus" ] @@ -1172,6 +1186,14 @@ } } }, + "apiLanguage": { + "type": "string", + "enum": [ + "German", + "English" + ], + "default": "German" + }, "apiListAvailableCanteenTagsReply": { "type": "object", "properties": { diff --git a/server/backend/cron/cronjobs.go b/server/backend/cron/cronjobs.go index 8e11f02a..d633d52e 100644 --- a/server/backend/cron/cronjobs.go +++ b/server/backend/cron/cronjobs.go @@ -1,6 +1,7 @@ package cron import ( + pb "github.com/TUM-Dev/Campus-Backend/server/api/tumdev" "time" "github.com/TUM-Dev/Campus-Backend/server/model" @@ -69,7 +70,8 @@ func (c *CronService) Run() error { // Run each job in a separate goroutine, so we can parallelize them switch cronjob.Type.String { case StudentClubType: - g.Go(func() error { return c.studentClubCron() }) + g.Go(func() error { return c.studentClubCron(pb.Language_German) }) + g.Go(func() error { return c.studentClubCron(pb.Language_English) }) case NewsType: // if this is not copied here, this may not be threads save due to go's guarantees // loop variable cronjob captured by func literal (govet) diff --git a/server/backend/cron/student_clubs.go b/server/backend/cron/student_clubs.go index e74534db..137a9f1e 100644 --- a/server/backend/cron/student_clubs.go +++ b/server/backend/cron/student_clubs.go @@ -4,6 +4,7 @@ import ( "crypto/md5" "errors" "fmt" + pb "github.com/TUM-Dev/Campus-Backend/server/api/tumdev" "io" "strings" @@ -20,7 +21,7 @@ const ( StudentClubImageDirectory = "student_club/" ) -func (c *CronService) studentClubCron() error { +func (c *CronService) studentClubCron(language pb.Language) error { body, err := student_club_parsers.DownloadHtml("https://www.sv.tum.de/sv/hochschulgruppen/") defer func(Body io.ReadCloser) { if err := Body.Close(); err != nil { @@ -37,15 +38,16 @@ func (c *CronService) studentClubCron() error { // save the result of the previous steps (🎉) if err := c.db.Transaction(func(tx *gorm.DB) error { - if err := tx.Where("1 = 1").Delete(&model.StudentClub{}).Error; err != nil { + if err := tx.Where("language = ?", language.String()).Delete(&model.StudentClub{}).Error; err != nil { return err } - if err := tx.Where("1 = 1").Delete(&model.StudentClubCollection{}).Error; err != nil { + if err := tx.Where("language = ?", language.String()).Delete(&model.StudentClubCollection{}).Error; err != nil { return err } for _, scrapedCollection := range scrapedCollections { collection := model.StudentClubCollection{ ID: scrapedCollection.Name, + Language: language.String(), Description: scrapedCollection.Description, } if err := tx.Create(&collection).Error; err != nil { @@ -54,6 +56,7 @@ func (c *CronService) studentClubCron() error { } for _, scrapedClub := range scrapedClubs { club := model.StudentClub{ + Language: language.String(), Name: scrapedClub.Name, Description: scrapedClub.Description, LinkUrl: scrapedClub.LinkUrl, diff --git a/server/backend/cron/student_clubs_test.go b/server/backend/cron/student_clubs_test.go index d0e07f24..d0b26587 100644 --- a/server/backend/cron/student_clubs_test.go +++ b/server/backend/cron/student_clubs_test.go @@ -2,6 +2,7 @@ package cron import ( "context" + pb "github.com/TUM-Dev/Campus-Backend/server/api/tumdev" "testing" "github.com/TUM-Dev/Campus-Backend/server/model" @@ -15,9 +16,13 @@ func TestCronService_studentClubCron(t *testing.T) { db := utils.SetupTestContainer(ctx, t) service := New(db) var clubs []model.StudentClub - db.WithContext(ctx).Find(&clubs) + require.NoError(t, db.WithContext(ctx).Find(&clubs).Error) require.Equal(t, []model.StudentClub{}, clubs) - require.NoError(t, service.studentClubCron()) - db.WithContext(ctx).Find(&clubs) + require.NoError(t, service.studentClubCron(pb.Language_German)) + require.NoError(t, db.WithContext(ctx).Find(&clubs).Error) + require.True(t, len(clubs) > 0) + require.NoError(t, db.WithContext(ctx).Where("1=1").Delete(&model.StudentClub{}).Error) + require.NoError(t, service.studentClubCron(pb.Language_English)) + require.NoError(t, db.WithContext(ctx).Find(&clubs).Error) require.True(t, len(clubs) > 0) } diff --git a/server/backend/migration/20241023000000.go b/server/backend/migration/20241023000000.go new file mode 100644 index 00000000..2d49956e --- /dev/null +++ b/server/backend/migration/20241023000000.go @@ -0,0 +1,32 @@ +package migration + +import ( + "github.com/go-gormigrate/gormigrate/v2" + "gorm.io/gorm" +) + +// migrate20241023000000 +// - made sure that student clubs are localised +func migrate20241023000000() *gormigrate.Migration { + return &gormigrate.Migration{ + ID: "20241023000000", + Migrate: func(tx *gorm.DB) error { + if err := tx.Exec("alter table student_clubs add language enum ('German', 'English') default 'German' not null").Error; err != nil { + return err + } + if err := tx.Exec("alter table student_club_collections add language enum ('German', 'English') default 'German' not null").Error; err != nil { + return err + } + return nil + }, + Rollback: func(tx *gorm.DB) error { + if err := tx.Exec("alter table student_clubs drop column language").Error; err != nil { + return err + } + if err := tx.Exec("alter table student_club_collections drop column language").Error; err != nil { + return err + } + return nil + }, + } +} diff --git a/server/backend/migration/migration.go b/server/backend/migration/migration.go index c799e00f..df551b0f 100644 --- a/server/backend/migration/migration.go +++ b/server/backend/migration/migration.go @@ -87,6 +87,7 @@ func manualMigrate(db *gorm.DB) error { migrate20240512000000(), migrate20240706000000(), migrate20240824000000(), + migrate20241023000000(), } return gormigrate.New(db, gormigrateOptions, migrations).Migrate() } diff --git a/server/backend/student_club.go b/server/backend/student_club.go index d766563c..5f60cc5b 100644 --- a/server/backend/student_club.go +++ b/server/backend/student_club.go @@ -10,9 +10,10 @@ import ( "google.golang.org/grpc/status" ) -func (s *CampusServer) ListStudentClub(ctx context.Context, _ *pb.ListStudentClubRequest) (*pb.ListStudentClubReply, error) { +func (s *CampusServer) ListStudentClub(ctx context.Context, req *pb.ListStudentClubRequest) (*pb.ListStudentClubReply, error) { var dbClubs []model.StudentClub if err := s.db.WithContext(ctx). + Where("language = ?", req.GetLanguage().String()). Joins("Image"). Joins("StudentClubCollection"). Find(&dbClubs).Error; err != nil { diff --git a/server/model/student_club.go b/server/model/student_club.go index 9f64ca2d..53326c74 100644 --- a/server/model/student_club.go +++ b/server/model/student_club.go @@ -9,6 +9,7 @@ import ( type StudentClub struct { gorm.Model Name string + Language string `gorm:"type:enum('German','English');default:'German'"` Description null.String LinkUrl null.String `gorm:"type:varchar(190);unique;"` ImageID null.Int diff --git a/server/model/student_club_collection.go b/server/model/student_club_collection.go index bdbb659b..c1fbdf97 100644 --- a/server/model/student_club_collection.go +++ b/server/model/student_club_collection.go @@ -9,6 +9,7 @@ import ( // StudentClubCollection stores what collection a club belongs to type StudentClubCollection struct { ID string `gorm:"primaryKey;type:varchar(100)"` + Language string `gorm:"type:enum('German','English');default:'German'"` Description string CreatedAt time.Time UpdatedAt time.Time