diff --git a/go.mod b/go.mod index 4a9237cc86..77b4c88380 100644 --- a/go.mod +++ b/go.mod @@ -63,7 +63,7 @@ require ( github.com/onsi/gomega v1.42.1 github.com/open-policy-agent/opa v1.17.1 github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 - github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260310090739-853d972b282d + github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260508132157-0223d2e98d28 github.com/opencloud-eu/reva/v2 v2.46.4-0.20260625152426-8cff2a7032ec github.com/opensearch-project/opensearch-go/v4 v4.6.0 github.com/orcaman/concurrent-map v1.0.0 diff --git a/go.sum b/go.sum index 61856f3ca0..c3c622acd6 100644 --- a/go.sum +++ b/go.sum @@ -947,8 +947,8 @@ github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-202505121527 github.com/opencloud-eu/go-micro-plugins/v4/store/nats-js-kv v0.0.0-20250512152754-23325793059a/go.mod h1:pjcozWijkNPbEtX5SIQaxEW/h8VAVZYTLx+70bmB3LY= github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 h1:W1ms+lP5lUUIzjRGDg93WrQfZJZCaV1ZP3KeyXi8bzY= github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89/go.mod h1:vigJkNss1N2QEceCuNw/ullDehncuJNFB6mEnzfq9UI= -github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260310090739-853d972b282d h1:JcqGDiyrcaQwVyV861TUyQgO7uEmsjkhfm7aQd84dOw= -github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260310090739-853d972b282d/go.mod h1:pzatilMEHZFT3qV7C/X3MqOa3NlRQuYhlRhZTL+hN6Q= +github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260508132157-0223d2e98d28 h1:/sYlOEZav7FNOUwBMw99/VZ6QhljRCOBF6zsXWYE6O4= +github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260508132157-0223d2e98d28/go.mod h1:pzatilMEHZFT3qV7C/X3MqOa3NlRQuYhlRhZTL+hN6Q= github.com/opencloud-eu/reva/v2 v2.46.4-0.20260625152426-8cff2a7032ec h1:kL9P87cVpe8GKvo5vzLpJstpiVXFvkZn2+Dco53nfuM= github.com/opencloud-eu/reva/v2 v2.46.4-0.20260625152426-8cff2a7032ec/go.mod h1:l4CG5u8tdWZj6IyavXO9xDdnNTV85oaFudGwEDPvsnk= github.com/opencloud-eu/secure v0.0.0-20260312082735-b6f5cb2244e4 h1:l2oB/RctH+t8r7QBj5p8thfEHCM/jF35aAY3WQ3hADI= diff --git a/protogen/gen/opencloud/messages/search/v0/search.pb.go b/protogen/gen/opencloud/messages/search/v0/search.pb.go index e5c74946ea..017b5b0d11 100644 --- a/protogen/gen/opencloud/messages/search/v0/search.pb.go +++ b/protogen/gen/opencloud/messages/search/v0/search.pb.go @@ -535,6 +535,69 @@ func (x *Photo) GetTakenDateTime() *timestamppb.Timestamp { return nil } +type MotionPhoto struct { + state protoimpl.MessageState + sizeCache protoimpl.SizeCache + unknownFields protoimpl.UnknownFields + + Version *int32 `protobuf:"varint,1,opt,name=version,proto3,oneof" json:"version,omitempty"` + PresentationTimestampUs *int64 `protobuf:"varint,2,opt,name=presentationTimestampUs,proto3,oneof" json:"presentationTimestampUs,omitempty"` + VideoSize *int64 `protobuf:"varint,3,opt,name=videoSize,proto3,oneof" json:"videoSize,omitempty"` +} + +func (x *MotionPhoto) Reset() { + *x = MotionPhoto{} + if protoimpl.UnsafeEnabled { + mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[6] + ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) + ms.StoreMessageInfo(mi) + } +} + +func (x *MotionPhoto) String() string { + return protoimpl.X.MessageStringOf(x) +} + +func (*MotionPhoto) ProtoMessage() {} + +func (x *MotionPhoto) ProtoReflect() protoreflect.Message { + mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[6] + 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 MotionPhoto.ProtoReflect.Descriptor instead. +func (*MotionPhoto) Descriptor() ([]byte, []int) { + return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{6} +} + +func (x *MotionPhoto) GetVersion() int32 { + if x != nil && x.Version != nil { + return *x.Version + } + return 0 +} + +func (x *MotionPhoto) GetPresentationTimestampUs() int64 { + if x != nil && x.PresentationTimestampUs != nil { + return *x.PresentationTimestampUs + } + return 0 +} + +func (x *MotionPhoto) GetVideoSize() int64 { + if x != nil && x.VideoSize != nil { + return *x.VideoSize + } + return 0 +} + type Entity struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -560,12 +623,13 @@ type Entity struct { Image *Image `protobuf:"bytes,18,opt,name=image,proto3" json:"image,omitempty"` Photo *Photo `protobuf:"bytes,19,opt,name=photo,proto3" json:"photo,omitempty"` Favorites []string `protobuf:"bytes,20,rep,name=favorites,proto3" json:"favorites,omitempty"` + MotionPhoto *MotionPhoto `protobuf:"bytes,21,opt,name=motionPhoto,proto3" json:"motionPhoto,omitempty"` } func (x *Entity) Reset() { *x = Entity{} if protoimpl.UnsafeEnabled { - mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[6] + mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[7] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -578,7 +642,7 @@ func (x *Entity) String() string { func (*Entity) ProtoMessage() {} func (x *Entity) ProtoReflect() protoreflect.Message { - mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[6] + mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[7] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -591,7 +655,7 @@ func (x *Entity) ProtoReflect() protoreflect.Message { // Deprecated: Use Entity.ProtoReflect.Descriptor instead. func (*Entity) Descriptor() ([]byte, []int) { - return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{6} + return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{7} } func (x *Entity) GetRef() *Reference { @@ -734,6 +798,13 @@ func (x *Entity) GetFavorites() []string { return nil } +func (x *Entity) GetMotionPhoto() *MotionPhoto { + if x != nil { + return x.MotionPhoto + } + return nil +} + type Match struct { state protoimpl.MessageState sizeCache protoimpl.SizeCache @@ -748,7 +819,7 @@ type Match struct { func (x *Match) Reset() { *x = Match{} if protoimpl.UnsafeEnabled { - mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[7] + mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[8] ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) ms.StoreMessageInfo(mi) } @@ -761,7 +832,7 @@ func (x *Match) String() string { func (*Match) ProtoMessage() {} func (x *Match) ProtoReflect() protoreflect.Message { - mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[7] + mi := &file_opencloud_messages_search_v0_search_proto_msgTypes[8] if protoimpl.UnsafeEnabled && x != nil { ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x)) if ms.LoadMessageInfo() == nil { @@ -774,7 +845,7 @@ func (x *Match) ProtoReflect() protoreflect.Message { // Deprecated: Use Match.ProtoReflect.Descriptor instead. func (*Match) Descriptor() ([]byte, []int) { - return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{7} + return file_opencloud_messages_search_v0_search_proto_rawDescGZIP(), []int{8} } func (x *Match) GetEntity() *Entity { @@ -908,74 +979,91 @@ var file_opencloud_messages_search_v0_search_proto_rawDesc = []byte{ 0x6c, 0x4c, 0x65, 0x6e, 0x67, 0x74, 0x68, 0x42, 0x06, 0x0a, 0x04, 0x5f, 0x69, 0x73, 0x6f, 0x42, 0x0e, 0x0a, 0x0c, 0x5f, 0x6f, 0x72, 0x69, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x42, 0x10, 0x0a, 0x0e, 0x5f, 0x74, 0x61, 0x6b, 0x65, 0x6e, 0x44, 0x61, 0x74, 0x65, 0x54, 0x69, 0x6d, - 0x65, 0x22, 0xfa, 0x06, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x03, - 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, - 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, - 0x63, 0x65, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x38, 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, - 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, - 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, - 0x76, 0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x52, 0x02, 0x69, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, - 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, 0x65, 0x74, 0x61, 0x67, 0x18, 0x04, 0x20, - 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, - 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x12, 0x48, 0x0a, - 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x74, - 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, - 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, - 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x6c, 0x61, 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x69, 0x66, - 0x69, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, 0x0a, 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f, - 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, - 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, - 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, - 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, - 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x79, 0x70, 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, - 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, - 0x65, 0x74, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x6f, 0x6f, - 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0d, 0x73, 0x68, 0x61, - 0x72, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x12, 0x45, 0x0a, 0x09, 0x70, 0x61, - 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0c, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, - 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, - 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65, 0x73, - 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x52, 0x08, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, - 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, - 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, 0x0a, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, - 0x68, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, 0x52, 0x0a, 0x68, 0x69, 0x67, 0x68, 0x6c, - 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x18, 0x0f, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, + 0x65, 0x22, 0xc4, 0x01, 0x0a, 0x0b, 0x4d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x68, 0x6f, 0x74, + 0x6f, 0x12, 0x1d, 0x0a, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x18, 0x01, 0x20, 0x01, + 0x28, 0x05, 0x48, 0x00, 0x52, 0x07, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x88, 0x01, 0x01, + 0x12, 0x3d, 0x0a, 0x17, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, + 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x55, 0x73, 0x18, 0x02, 0x20, 0x01, 0x28, + 0x03, 0x48, 0x01, 0x52, 0x17, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x55, 0x73, 0x88, 0x01, 0x01, 0x12, + 0x21, 0x0a, 0x09, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x53, 0x69, 0x7a, 0x65, 0x18, 0x03, 0x20, 0x01, + 0x28, 0x03, 0x48, 0x02, 0x52, 0x09, 0x76, 0x69, 0x64, 0x65, 0x6f, 0x53, 0x69, 0x7a, 0x65, 0x88, + 0x01, 0x01, 0x42, 0x0a, 0x0a, 0x08, 0x5f, 0x76, 0x65, 0x72, 0x73, 0x69, 0x6f, 0x6e, 0x42, 0x1a, + 0x0a, 0x18, 0x5f, 0x70, 0x72, 0x65, 0x73, 0x65, 0x6e, 0x74, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x54, + 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x55, 0x73, 0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x76, + 0x69, 0x64, 0x65, 0x6f, 0x53, 0x69, 0x7a, 0x65, 0x22, 0xc7, 0x07, 0x0a, 0x06, 0x45, 0x6e, 0x74, + 0x69, 0x74, 0x79, 0x12, 0x39, 0x0a, 0x03, 0x72, 0x65, 0x66, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x27, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, + 0x52, 0x65, 0x66, 0x65, 0x72, 0x65, 0x6e, 0x63, 0x65, 0x52, 0x03, 0x72, 0x65, 0x66, 0x12, 0x38, + 0x0a, 0x02, 0x69, 0x64, 0x18, 0x02, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, + 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, + 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, + 0x63, 0x65, 0x49, 0x44, 0x52, 0x02, 0x69, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x6e, 0x61, 0x6d, 0x65, + 0x18, 0x03, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x6e, 0x61, 0x6d, 0x65, 0x12, 0x12, 0x0a, 0x04, + 0x65, 0x74, 0x61, 0x67, 0x18, 0x04, 0x20, 0x01, 0x28, 0x09, 0x52, 0x04, 0x65, 0x74, 0x61, 0x67, + 0x12, 0x12, 0x0a, 0x04, 0x73, 0x69, 0x7a, 0x65, 0x18, 0x05, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, + 0x73, 0x69, 0x7a, 0x65, 0x12, 0x48, 0x0a, 0x12, 0x6c, 0x61, 0x73, 0x74, 0x5f, 0x6d, 0x6f, 0x64, + 0x69, 0x66, 0x69, 0x65, 0x64, 0x5f, 0x74, 0x69, 0x6d, 0x65, 0x18, 0x06, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x1a, 0x2e, 0x67, 0x6f, 0x6f, 0x67, 0x6c, 0x65, 0x2e, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x62, + 0x75, 0x66, 0x2e, 0x54, 0x69, 0x6d, 0x65, 0x73, 0x74, 0x61, 0x6d, 0x70, 0x52, 0x10, 0x6c, 0x61, + 0x73, 0x74, 0x4d, 0x6f, 0x64, 0x69, 0x66, 0x69, 0x65, 0x64, 0x54, 0x69, 0x6d, 0x65, 0x12, 0x1b, + 0x0a, 0x09, 0x6d, 0x69, 0x6d, 0x65, 0x5f, 0x74, 0x79, 0x70, 0x65, 0x18, 0x07, 0x20, 0x01, 0x28, + 0x09, 0x52, 0x08, 0x6d, 0x69, 0x6d, 0x65, 0x54, 0x79, 0x70, 0x65, 0x12, 0x20, 0x0a, 0x0b, 0x70, + 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x18, 0x08, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0b, 0x70, 0x65, 0x72, 0x6d, 0x69, 0x73, 0x73, 0x69, 0x6f, 0x6e, 0x73, 0x12, 0x12, 0x0a, + 0x04, 0x74, 0x79, 0x70, 0x65, 0x18, 0x09, 0x20, 0x01, 0x28, 0x04, 0x52, 0x04, 0x74, 0x79, 0x70, + 0x65, 0x12, 0x18, 0x0a, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x18, 0x0a, 0x20, 0x01, + 0x28, 0x08, 0x52, 0x07, 0x64, 0x65, 0x6c, 0x65, 0x74, 0x65, 0x64, 0x12, 0x24, 0x0a, 0x0d, 0x73, + 0x68, 0x61, 0x72, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x4e, 0x61, 0x6d, 0x65, 0x18, 0x0b, 0x20, 0x01, + 0x28, 0x09, 0x52, 0x0d, 0x73, 0x68, 0x61, 0x72, 0x65, 0x52, 0x6f, 0x6f, 0x74, 0x4e, 0x61, 0x6d, + 0x65, 0x12, 0x45, 0x0a, 0x09, 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x5f, 0x69, 0x64, 0x18, 0x0c, + 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, - 0x2e, 0x76, 0x30, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x6f, 0x52, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, - 0x12, 0x48, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, - 0x30, 0x2e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, - 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, 0x6e, 0x12, 0x4e, 0x0a, 0x0e, 0x72, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, - 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, - 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, - 0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x52, 0x0c, 0x72, 0x65, - 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x49, 0x64, 0x12, 0x39, 0x0a, 0x05, 0x69, 0x6d, - 0x61, 0x67, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, 0x65, 0x6e, + 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, 0x65, 0x49, 0x44, 0x52, 0x08, + 0x70, 0x61, 0x72, 0x65, 0x6e, 0x74, 0x49, 0x64, 0x12, 0x12, 0x0a, 0x04, 0x74, 0x61, 0x67, 0x73, + 0x18, 0x0d, 0x20, 0x03, 0x28, 0x09, 0x52, 0x04, 0x74, 0x61, 0x67, 0x73, 0x12, 0x1e, 0x0a, 0x0a, + 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x18, 0x0e, 0x20, 0x01, 0x28, 0x09, + 0x52, 0x0a, 0x68, 0x69, 0x67, 0x68, 0x6c, 0x69, 0x67, 0x68, 0x74, 0x73, 0x12, 0x39, 0x0a, 0x05, + 0x61, 0x75, 0x64, 0x69, 0x6f, 0x18, 0x0f, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, + 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, + 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x41, 0x75, 0x64, 0x69, 0x6f, + 0x52, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x12, 0x48, 0x0a, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, + 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x2c, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, - 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x05, - 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x05, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x18, 0x13, - 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, - 0x2e, 0x76, 0x30, 0x2e, 0x50, 0x68, 0x6f, 0x74, 0x6f, 0x52, 0x05, 0x70, 0x68, 0x6f, 0x74, 0x6f, - 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x61, 0x76, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73, 0x18, 0x14, 0x20, - 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x61, 0x76, 0x6f, 0x72, 0x69, 0x74, 0x65, 0x73, 0x22, 0x5b, - 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3c, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, - 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, - 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x52, 0x06, 0x65, - 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x18, 0x02, - 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x42, 0x4d, 0x5a, 0x4b, 0x67, - 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, - 0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, - 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6f, 0x70, - 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, - 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2f, 0x76, 0x30, 0x62, 0x06, 0x70, 0x72, 0x6f, 0x74, - 0x6f, 0x33, + 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, + 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65, 0x73, 0x52, 0x08, 0x6c, 0x6f, 0x63, 0x61, 0x74, 0x69, 0x6f, + 0x6e, 0x12, 0x4e, 0x0a, 0x0e, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x5f, 0x69, 0x74, 0x65, 0x6d, + 0x5f, 0x69, 0x64, 0x18, 0x11, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x28, 0x2e, 0x6f, 0x70, 0x65, 0x6e, + 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, + 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x52, 0x65, 0x73, 0x6f, 0x75, 0x72, 0x63, + 0x65, 0x49, 0x44, 0x52, 0x0c, 0x72, 0x65, 0x6d, 0x6f, 0x74, 0x65, 0x49, 0x74, 0x65, 0x6d, 0x49, + 0x64, 0x12, 0x39, 0x0a, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x18, 0x12, 0x20, 0x01, 0x28, 0x0b, + 0x32, 0x23, 0x2e, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, + 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, + 0x49, 0x6d, 0x61, 0x67, 0x65, 0x52, 0x05, 0x69, 0x6d, 0x61, 0x67, 0x65, 0x12, 0x39, 0x0a, 0x05, + 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x18, 0x13, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x23, 0x2e, 0x6f, 0x70, + 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, + 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x50, 0x68, 0x6f, 0x74, 0x6f, + 0x52, 0x05, 0x70, 0x68, 0x6f, 0x74, 0x6f, 0x12, 0x1c, 0x0a, 0x09, 0x66, 0x61, 0x76, 0x6f, 0x72, + 0x69, 0x74, 0x65, 0x73, 0x18, 0x14, 0x20, 0x03, 0x28, 0x09, 0x52, 0x09, 0x66, 0x61, 0x76, 0x6f, + 0x72, 0x69, 0x74, 0x65, 0x73, 0x12, 0x4b, 0x0a, 0x0b, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x50, + 0x68, 0x6f, 0x74, 0x6f, 0x18, 0x15, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x29, 0x2e, 0x6f, 0x70, 0x65, + 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, + 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x4d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, + 0x50, 0x68, 0x6f, 0x74, 0x6f, 0x52, 0x0b, 0x6d, 0x6f, 0x74, 0x69, 0x6f, 0x6e, 0x50, 0x68, 0x6f, + 0x74, 0x6f, 0x22, 0x5b, 0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x3c, 0x0a, 0x06, 0x65, + 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x24, 0x2e, 0x6f, 0x70, + 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2e, 0x6d, 0x65, 0x73, 0x73, 0x61, 0x67, 0x65, 0x73, + 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30, 0x2e, 0x45, 0x6e, 0x74, 0x69, 0x74, + 0x79, 0x52, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x14, 0x0a, 0x05, 0x73, 0x63, 0x6f, + 0x72, 0x65, 0x18, 0x02, 0x20, 0x01, 0x28, 0x02, 0x52, 0x05, 0x73, 0x63, 0x6f, 0x72, 0x65, 0x42, + 0x4d, 0x5a, 0x4b, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x70, + 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2d, 0x65, 0x75, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, + 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x65, + 0x6e, 0x2f, 0x6f, 0x70, 0x65, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6d, 0x65, 0x73, 0x73, + 0x61, 0x67, 0x65, 0x73, 0x2f, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2f, 0x76, 0x30, 0x62, 0x06, + 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x33, } var ( @@ -990,7 +1078,7 @@ func file_opencloud_messages_search_v0_search_proto_rawDescGZIP() []byte { return file_opencloud_messages_search_v0_search_proto_rawDescData } -var file_opencloud_messages_search_v0_search_proto_msgTypes = make([]protoimpl.MessageInfo, 8) +var file_opencloud_messages_search_v0_search_proto_msgTypes = make([]protoimpl.MessageInfo, 9) var file_opencloud_messages_search_v0_search_proto_goTypes = []interface{}{ (*ResourceID)(nil), // 0: opencloud.messages.search.v0.ResourceID (*Reference)(nil), // 1: opencloud.messages.search.v0.Reference @@ -998,28 +1086,30 @@ var file_opencloud_messages_search_v0_search_proto_goTypes = []interface{}{ (*Image)(nil), // 3: opencloud.messages.search.v0.Image (*GeoCoordinates)(nil), // 4: opencloud.messages.search.v0.GeoCoordinates (*Photo)(nil), // 5: opencloud.messages.search.v0.Photo - (*Entity)(nil), // 6: opencloud.messages.search.v0.Entity - (*Match)(nil), // 7: opencloud.messages.search.v0.Match - (*timestamppb.Timestamp)(nil), // 8: google.protobuf.Timestamp + (*MotionPhoto)(nil), // 6: opencloud.messages.search.v0.MotionPhoto + (*Entity)(nil), // 7: opencloud.messages.search.v0.Entity + (*Match)(nil), // 8: opencloud.messages.search.v0.Match + (*timestamppb.Timestamp)(nil), // 9: google.protobuf.Timestamp } var file_opencloud_messages_search_v0_search_proto_depIdxs = []int32{ 0, // 0: opencloud.messages.search.v0.Reference.resource_id:type_name -> opencloud.messages.search.v0.ResourceID - 8, // 1: opencloud.messages.search.v0.Photo.takenDateTime:type_name -> google.protobuf.Timestamp + 9, // 1: opencloud.messages.search.v0.Photo.takenDateTime:type_name -> google.protobuf.Timestamp 1, // 2: opencloud.messages.search.v0.Entity.ref:type_name -> opencloud.messages.search.v0.Reference 0, // 3: opencloud.messages.search.v0.Entity.id:type_name -> opencloud.messages.search.v0.ResourceID - 8, // 4: opencloud.messages.search.v0.Entity.last_modified_time:type_name -> google.protobuf.Timestamp + 9, // 4: opencloud.messages.search.v0.Entity.last_modified_time:type_name -> google.protobuf.Timestamp 0, // 5: opencloud.messages.search.v0.Entity.parent_id:type_name -> opencloud.messages.search.v0.ResourceID 2, // 6: opencloud.messages.search.v0.Entity.audio:type_name -> opencloud.messages.search.v0.Audio 4, // 7: opencloud.messages.search.v0.Entity.location:type_name -> opencloud.messages.search.v0.GeoCoordinates 0, // 8: opencloud.messages.search.v0.Entity.remote_item_id:type_name -> opencloud.messages.search.v0.ResourceID 3, // 9: opencloud.messages.search.v0.Entity.image:type_name -> opencloud.messages.search.v0.Image 5, // 10: opencloud.messages.search.v0.Entity.photo:type_name -> opencloud.messages.search.v0.Photo - 6, // 11: opencloud.messages.search.v0.Match.entity:type_name -> opencloud.messages.search.v0.Entity - 12, // [12:12] is the sub-list for method output_type - 12, // [12:12] is the sub-list for method input_type - 12, // [12:12] is the sub-list for extension type_name - 12, // [12:12] is the sub-list for extension extendee - 0, // [0:12] is the sub-list for field type_name + 6, // 11: opencloud.messages.search.v0.Entity.motionPhoto:type_name -> opencloud.messages.search.v0.MotionPhoto + 7, // 12: opencloud.messages.search.v0.Match.entity:type_name -> opencloud.messages.search.v0.Entity + 13, // [13:13] is the sub-list for method output_type + 13, // [13:13] is the sub-list for method input_type + 13, // [13:13] is the sub-list for extension type_name + 13, // [13:13] is the sub-list for extension extendee + 0, // [0:13] is the sub-list for field type_name } func init() { file_opencloud_messages_search_v0_search_proto_init() } @@ -1101,7 +1191,7 @@ func file_opencloud_messages_search_v0_search_proto_init() { } } file_opencloud_messages_search_v0_search_proto_msgTypes[6].Exporter = func(v interface{}, i int) interface{} { - switch v := v.(*Entity); i { + switch v := v.(*MotionPhoto); i { case 0: return &v.state case 1: @@ -1113,6 +1203,18 @@ func file_opencloud_messages_search_v0_search_proto_init() { } } file_opencloud_messages_search_v0_search_proto_msgTypes[7].Exporter = func(v interface{}, i int) interface{} { + switch v := v.(*Entity); i { + case 0: + return &v.state + case 1: + return &v.sizeCache + case 2: + return &v.unknownFields + default: + return nil + } + } + file_opencloud_messages_search_v0_search_proto_msgTypes[8].Exporter = func(v interface{}, i int) interface{} { switch v := v.(*Match); i { case 0: return &v.state @@ -1129,13 +1231,14 @@ func file_opencloud_messages_search_v0_search_proto_init() { file_opencloud_messages_search_v0_search_proto_msgTypes[3].OneofWrappers = []interface{}{} file_opencloud_messages_search_v0_search_proto_msgTypes[4].OneofWrappers = []interface{}{} file_opencloud_messages_search_v0_search_proto_msgTypes[5].OneofWrappers = []interface{}{} + file_opencloud_messages_search_v0_search_proto_msgTypes[6].OneofWrappers = []interface{}{} type x struct{} out := protoimpl.TypeBuilder{ File: protoimpl.DescBuilder{ GoPackagePath: reflect.TypeOf(x{}).PkgPath(), RawDescriptor: file_opencloud_messages_search_v0_search_proto_rawDesc, NumEnums: 0, - NumMessages: 8, + NumMessages: 9, NumExtensions: 0, NumServices: 0, }, diff --git a/protogen/gen/opencloud/messages/search/v0/search.pb.web.go b/protogen/gen/opencloud/messages/search/v0/search.pb.web.go index 22c3e08238..c17bd156b9 100644 --- a/protogen/gen/opencloud/messages/search/v0/search.pb.web.go +++ b/protogen/gen/opencloud/messages/search/v0/search.pb.web.go @@ -226,6 +226,42 @@ func (m *Photo) UnmarshalJSON(b []byte) error { var _ json.Unmarshaler = (*Photo)(nil) +// MotionPhotoJSONMarshaler describes the default jsonpb.Marshaler used by all +// instances of MotionPhoto. This struct is safe to replace or modify but +// should not be done so concurrently. +var MotionPhotoJSONMarshaler = new(jsonpb.Marshaler) + +// MarshalJSON satisfies the encoding/json Marshaler interface. This method +// uses the more correct jsonpb package to correctly marshal the message. +func (m *MotionPhoto) MarshalJSON() ([]byte, error) { + if m == nil { + return json.Marshal(nil) + } + + buf := &bytes.Buffer{} + + if err := MotionPhotoJSONMarshaler.Marshal(buf, m); err != nil { + return nil, err + } + + return buf.Bytes(), nil +} + +var _ json.Marshaler = (*MotionPhoto)(nil) + +// MotionPhotoJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all +// instances of MotionPhoto. This struct is safe to replace or modify but +// should not be done so concurrently. +var MotionPhotoJSONUnmarshaler = new(jsonpb.Unmarshaler) + +// UnmarshalJSON satisfies the encoding/json Unmarshaler interface. This method +// uses the more correct jsonpb package to correctly unmarshal the message. +func (m *MotionPhoto) UnmarshalJSON(b []byte) error { + return MotionPhotoJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m) +} + +var _ json.Unmarshaler = (*MotionPhoto)(nil) + // EntityJSONMarshaler describes the default jsonpb.Marshaler used by all // instances of Entity. This struct is safe to replace or modify but // should not be done so concurrently. diff --git a/protogen/gen/opencloud/services/search/v0/search.swagger.json b/protogen/gen/opencloud/services/search/v0/search.swagger.json index a8d7b9bd8f..a6c1b6f2d0 100644 --- a/protogen/gen/opencloud/services/search/v0/search.swagger.json +++ b/protogen/gen/opencloud/services/search/v0/search.swagger.json @@ -288,6 +288,9 @@ "items": { "type": "string" } + }, + "motionPhoto": { + "$ref": "#/definitions/v0MotionPhoto" } } }, @@ -352,6 +355,23 @@ } } }, + "v0MotionPhoto": { + "type": "object", + "properties": { + "version": { + "type": "integer", + "format": "int32" + }, + "presentationTimestampUs": { + "type": "string", + "format": "int64" + }, + "videoSize": { + "type": "string", + "format": "int64" + } + } + }, "v0Photo": { "type": "object", "properties": { diff --git a/protogen/proto/opencloud/messages/search/v0/search.proto b/protogen/proto/opencloud/messages/search/v0/search.proto index 4633a2cee7..2cab8ce4c6 100644 --- a/protogen/proto/opencloud/messages/search/v0/search.proto +++ b/protogen/proto/opencloud/messages/search/v0/search.proto @@ -59,6 +59,12 @@ message Photo { optional google.protobuf.Timestamp takenDateTime = 9; } +message MotionPhoto { + optional int32 version = 1; + optional int64 presentationTimestampUs = 2; + optional int64 videoSize = 3; +} + message Entity { Reference ref = 1; ResourceID id = 2; @@ -80,6 +86,7 @@ message Entity { Image image = 18; Photo photo = 19; repeated string favorites = 20; + MotionPhoto motionPhoto = 21; } message Match { diff --git a/services/graph/pkg/service/v0/driveitems.go b/services/graph/pkg/service/v0/driveitems.go index 1acd7b9215..46b110c3ea 100644 --- a/services/graph/pkg/service/v0/driveitems.go +++ b/services/graph/pkg/service/v0/driveitems.go @@ -456,6 +456,7 @@ func cs3ResourceToDriveItem(logger *log.Logger, publicBaseURL *url.URL, res *sto driveItem.Image = metadataToFacet[libregraph.Image](metadata, "image") driveItem.Location = metadataToFacet[libregraph.GeoCoordinates](metadata, "location") driveItem.Photo = metadataToFacet[libregraph.Photo](metadata, "photo") + driveItem.LibreGraphMotionPhoto = metadataToFacet[libregraph.MotionPhoto](metadata, "motionPhoto") } return driveItem, nil diff --git a/services/search/pkg/bleve/backend.go b/services/search/pkg/bleve/backend.go index 673e61de2c..2c8ae24936 100644 --- a/services/search/pkg/bleve/backend.go +++ b/services/search/pkg/bleve/backend.go @@ -126,20 +126,21 @@ func (b *Backend) Search(_ context.Context, sir *searchService.SearchIndexReques ResourceId: resourceIDtoSearchID(rootID), Path: getFieldValue[string](hit.Fields, "Path"), }, - Id: resourceIDtoSearchID(rID), - Name: getFieldValue[string](hit.Fields, "Name"), - ParentId: resourceIDtoSearchID(pID), - Size: uint64(getFieldValue[float64](hit.Fields, "Size")), - Type: uint64(getFieldValue[float64](hit.Fields, "Type")), - MimeType: getFieldValue[string](hit.Fields, "MimeType"), - Deleted: getFieldValue[bool](hit.Fields, "Deleted"), - Tags: getFieldSliceValue[string](hit.Fields, "Tags"), - Favorites: getFieldSliceValue[string](hit.Fields, "Favorites"), - Highlights: getFragmentValue(hit.Fragments, "Content", 0), - Audio: hitToFacet[searchMessage.Audio](hit.Fields, "audio"), - Image: hitToFacet[searchMessage.Image](hit.Fields, "image"), - Location: hitToFacet[searchMessage.GeoCoordinates](hit.Fields, "location"), - Photo: hitToFacet[searchMessage.Photo](hit.Fields, "photo"), + Id: resourceIDtoSearchID(rID), + Name: getFieldValue[string](hit.Fields, "Name"), + ParentId: resourceIDtoSearchID(pID), + Size: uint64(getFieldValue[float64](hit.Fields, "Size")), + Type: uint64(getFieldValue[float64](hit.Fields, "Type")), + MimeType: getFieldValue[string](hit.Fields, "MimeType"), + Deleted: getFieldValue[bool](hit.Fields, "Deleted"), + Tags: getFieldSliceValue[string](hit.Fields, "Tags"), + Favorites: getFieldSliceValue[string](hit.Fields, "Favorites"), + Highlights: getFragmentValue(hit.Fragments, "Content", 0), + Audio: hitToFacet[searchMessage.Audio](hit.Fields, "audio"), + Image: hitToFacet[searchMessage.Image](hit.Fields, "image"), + Location: hitToFacet[searchMessage.GeoCoordinates](hit.Fields, "location"), + Photo: hitToFacet[searchMessage.Photo](hit.Fields, "photo"), + MotionPhoto: hitToFacet[searchMessage.MotionPhoto](hit.Fields, "motionPhoto"), }, } diff --git a/services/search/pkg/content/content.go b/services/search/pkg/content/content.go index b162ccdcfc..314f87a171 100644 --- a/services/search/pkg/content/content.go +++ b/services/search/pkg/content/content.go @@ -14,18 +14,19 @@ func init() { // Document wraps all resource meta fields, // it is used as a content extraction result. type Document struct { - Title string `json:"Title"` - Name string `json:"Name"` - Content string `json:"Content"` - Size uint64 `json:"Size"` - Mtime string `json:"Mtime"` - MimeType string `json:"MimeType"` - Tags []string `json:"Tags"` - Favorites []string `json:"Favorites"` - Audio *libregraph.Audio `json:"audio,omitempty"` - Image *libregraph.Image `json:"image,omitempty"` - Location *libregraph.GeoCoordinates `json:"location,omitempty"` - Photo *libregraph.Photo `json:"photo,omitempty"` + Title string `json:"Title"` + Name string `json:"Name"` + Content string `json:"Content"` + Size uint64 `json:"Size"` + Mtime string `json:"Mtime"` + MimeType string `json:"MimeType"` + Tags []string `json:"Tags"` + Favorites []string `json:"Favorites"` + Audio *libregraph.Audio `json:"audio,omitempty"` + Image *libregraph.Image `json:"image,omitempty"` + Location *libregraph.GeoCoordinates `json:"location,omitempty"` + Photo *libregraph.Photo `json:"photo,omitempty"` + MotionPhoto *libregraph.MotionPhoto `json:"motionPhoto,omitempty"` } func CleanString(content, langCode string) string { diff --git a/services/search/pkg/content/cs3.go b/services/search/pkg/content/cs3.go index e21dcd94ec..647c88299b 100644 --- a/services/search/pkg/content/cs3.go +++ b/services/search/pkg/content/cs3.go @@ -33,26 +33,26 @@ func newCS3Retriever(gatewaySelector pool.Selectable[gateway.GatewayAPIClient], } } -// Retrieve downloads the file from a cs3 service -// The caller MUST make sure to close the returned ReadCloser -func (s cs3) Retrieve(ctx context.Context, rID *provider.ResourceId) (io.ReadCloser, error) { +// initiateDownload asks the gateway for a download endpoint and returns it +// together with the transfer token and the auth token from the context. +func (s cs3) initiateDownload(ctx context.Context, rID *provider.ResourceId) (endpoint, transferToken, authToken string, err error) { at, ok := contextGet(ctx, revactx.TokenHeader) if !ok { - return nil, fmt.Errorf("context without %s", revactx.TokenHeader) + return "", "", "", fmt.Errorf("context without %s", revactx.TokenHeader) } gatewayClient, err := s.gatewaySelector.Next() if err != nil { s.logger.Error().Err(err).Msg("could not get reva gatewayClient") - return nil, err + return "", "", "", err } res, err := gatewayClient.InitiateFileDownload(ctx, &provider.InitiateFileDownloadRequest{Ref: &provider.Reference{ResourceId: rID, Path: "."}}) if err != nil { - return nil, err + return "", "", "", err } if res.Status.Code != rpc.Code_CODE_OK { - return nil, fmt.Errorf("could not load resoure: %s", res.Status.Message) + return "", "", "", fmt.Errorf("could not load resoure: %s", res.Status.Message) } var ep, tt string @@ -66,6 +66,17 @@ func (s cs3) Retrieve(ctx context.Context, rID *provider.ResourceId) (io.ReadClo ep, tt = res.Protocols[0].DownloadEndpoint, res.Protocols[0].Token } + return ep, tt, at, nil +} + +// Retrieve downloads the file from a cs3 service +// The caller MUST make sure to close the returned ReadCloser +func (s cs3) Retrieve(ctx context.Context, rID *provider.ResourceId) (io.ReadCloser, error) { + ep, tt, at, err := s.initiateDownload(ctx, rID) + if err != nil { + return nil, err + } + req, err := http.NewRequest(http.MethodGet, ep, nil) if err != nil { return nil, err @@ -80,8 +91,55 @@ func (s cs3) Retrieve(ctx context.Context, rID *provider.ResourceId) (io.ReadClo } if cres.StatusCode != http.StatusOK { + _ = cres.Body.Close() return nil, fmt.Errorf("could not download resource. Request returned with statuscode %d ", cres.StatusCode) } return cres.Body, nil } + +// RetrieveRange downloads length bytes starting at offset from a cs3 service. +// The caller MUST make sure to close the returned ReadCloser. +// It relies on HTTP range support of the download endpoint. If the endpoint +// ignores the Range header and returns the full file (200 instead of 206), the +// leading offset bytes are discarded so the returned reader is always positioned +// at offset. +func (s cs3) RetrieveRange(ctx context.Context, rID *provider.ResourceId, offset, length int64) (io.ReadCloser, error) { + ep, tt, at, err := s.initiateDownload(ctx, rID) + if err != nil { + return nil, err + } + + req, err := http.NewRequest(http.MethodGet, ep, nil) + if err != nil { + return nil, err + } + + req.Header.Set(revactx.TokenHeader, at) + req.Header.Set("X-Reva-Transfer", tt) + // A single range keeps the response a plain 206 with a Content-Range header, + // never a multipart/byteranges body. + req.Header.Set("Range", fmt.Sprintf("bytes=%d-%d", offset, offset+length-1)) + + cres, err := s.httpClient.Do(req) + if err != nil { + return nil, err + } + + switch cres.StatusCode { + case http.StatusPartialContent: + // Range honored: the body already starts at offset. + return cres.Body, nil + case http.StatusOK: + // Range ignored: the body is the whole file. Skip to offset so the + // caller always reads from the requested position. + if _, err := io.CopyN(io.Discard, cres.Body, offset); err != nil { + _ = cres.Body.Close() + return nil, fmt.Errorf("could not skip to offset %d: %w", offset, err) + } + return cres.Body, nil + default: + _ = cres.Body.Close() + return nil, fmt.Errorf("could not download range. Request returned with statuscode %d ", cres.StatusCode) + } +} diff --git a/services/search/pkg/content/extractor.go b/services/search/pkg/content/extractor.go index a91be6cb4e..581bb0c88d 100644 --- a/services/search/pkg/content/extractor.go +++ b/services/search/pkg/content/extractor.go @@ -13,19 +13,18 @@ type Extractor interface { Extract(ctx context.Context, ri *provider.ResourceInfo) (Document, error) } -func getFirstValue(m map[string][]string, key string) (string, error) { +// getFirstValue returns the first metadata value present among keys, trying them +// in order. It errors when the map is nil or none of the keys holds a value. +func getFirstValue(m map[string][]string, keys ...string) (string, error) { if m == nil { return "", errors.New("undefined map") } - v, ok := m[key] - if !ok { - return "", fmt.Errorf("unknown key: %v", key) + for _, key := range keys { + if v, ok := m[key]; ok && len(v) > 0 { + return v[0], nil + } } - if len(m) == 0 { - return "", fmt.Errorf("no values for: %v", key) - } - - return v[0], nil + return "", fmt.Errorf("no value for keys: %v", keys) } diff --git a/services/search/pkg/content/mocks/retriever.go b/services/search/pkg/content/mocks/retriever.go index 5060f071a3..4fb4b5607e 100644 --- a/services/search/pkg/content/mocks/retriever.go +++ b/services/search/pkg/content/mocks/retriever.go @@ -106,3 +106,83 @@ func (_c *Retriever_Retrieve_Call) RunAndReturn(run func(ctx context.Context, rI _c.Call.Return(run) return _c } + +// RetrieveRange provides a mock function for the type Retriever +func (_mock *Retriever) RetrieveRange(ctx context.Context, rID *providerv1beta1.ResourceId, offset int64, length int64) (io.ReadCloser, error) { + ret := _mock.Called(ctx, rID, offset, length) + + if len(ret) == 0 { + panic("no return value specified for RetrieveRange") + } + + var r0 io.ReadCloser + var r1 error + if returnFunc, ok := ret.Get(0).(func(context.Context, *providerv1beta1.ResourceId, int64, int64) (io.ReadCloser, error)); ok { + return returnFunc(ctx, rID, offset, length) + } + if returnFunc, ok := ret.Get(0).(func(context.Context, *providerv1beta1.ResourceId, int64, int64) io.ReadCloser); ok { + r0 = returnFunc(ctx, rID, offset, length) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(io.ReadCloser) + } + } + if returnFunc, ok := ret.Get(1).(func(context.Context, *providerv1beta1.ResourceId, int64, int64) error); ok { + r1 = returnFunc(ctx, rID, offset, length) + } else { + r1 = ret.Error(1) + } + return r0, r1 +} + +// Retriever_RetrieveRange_Call is a *mock.Call that shadows Run/Return methods with type explicit version for method 'RetrieveRange' +type Retriever_RetrieveRange_Call struct { + *mock.Call +} + +// RetrieveRange is a helper method to define mock.On call +// - ctx context.Context +// - rID *providerv1beta1.ResourceId +// - offset int64 +// - length int64 +func (_e *Retriever_Expecter) RetrieveRange(ctx interface{}, rID interface{}, offset interface{}, length interface{}) *Retriever_RetrieveRange_Call { + return &Retriever_RetrieveRange_Call{Call: _e.mock.On("RetrieveRange", ctx, rID, offset, length)} +} + +func (_c *Retriever_RetrieveRange_Call) Run(run func(ctx context.Context, rID *providerv1beta1.ResourceId, offset int64, length int64)) *Retriever_RetrieveRange_Call { + _c.Call.Run(func(args mock.Arguments) { + var arg0 context.Context + if args[0] != nil { + arg0 = args[0].(context.Context) + } + var arg1 *providerv1beta1.ResourceId + if args[1] != nil { + arg1 = args[1].(*providerv1beta1.ResourceId) + } + var arg2 int64 + if args[2] != nil { + arg2 = args[2].(int64) + } + var arg3 int64 + if args[3] != nil { + arg3 = args[3].(int64) + } + run( + arg0, + arg1, + arg2, + arg3, + ) + }) + return _c +} + +func (_c *Retriever_RetrieveRange_Call) Return(readCloser io.ReadCloser, err error) *Retriever_RetrieveRange_Call { + _c.Call.Return(readCloser, err) + return _c +} + +func (_c *Retriever_RetrieveRange_Call) RunAndReturn(run func(ctx context.Context, rID *providerv1beta1.ResourceId, offset int64, length int64) (io.ReadCloser, error)) *Retriever_RetrieveRange_Call { + _c.Call.Return(run) + return _c +} diff --git a/services/search/pkg/content/retriever.go b/services/search/pkg/content/retriever.go index bb64584d6f..586e42790f 100644 --- a/services/search/pkg/content/retriever.go +++ b/services/search/pkg/content/retriever.go @@ -12,6 +12,10 @@ import ( // It requests and then returns a resource from the underlying storage. type Retriever interface { Retrieve(ctx context.Context, rID *provider.ResourceId) (io.ReadCloser, error) + // RetrieveRange returns a reader positioned at offset for up to length bytes + // of the resource. Implementations must ensure the reader starts at offset + // even when the storage does not honor HTTP range requests. + RetrieveRange(ctx context.Context, rID *provider.ResourceId, offset, length int64) (io.ReadCloser, error) } func contextGet(ctx context.Context, k string) (string, bool) { diff --git a/services/search/pkg/content/tika.go b/services/search/pkg/content/tika.go index 8b6ac5e60b..9094ea4cf6 100644 --- a/services/search/pkg/content/tika.go +++ b/services/search/pkg/content/tika.go @@ -3,16 +3,12 @@ package content import ( "context" "fmt" - "math" - "strconv" "strings" - "time" gateway "github.com/cs3org/go-cs3apis/cs3/gateway/v1beta1" provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" "github.com/google/go-tika/tika" "github.com/opencloud-eu/reva/v2/pkg/rgrpc/todo/pool" - libregraph "github.com/opencloud-eu/libre-graph-api-go" "github.com/opencloud-eu/opencloud/pkg/log" "github.com/opencloud-eu/opencloud/services/search/pkg/config" @@ -98,207 +94,17 @@ func (t Tika) Extract(ctx context.Context, ri *provider.ResourceInfo) (Document, if contentType, err := getFirstValue(meta, "Content-Type"); err == nil && strings.HasPrefix(contentType, "audio/") { doc.Audio = t.getAudio(meta) } - } - - if langCode, _ := t.tika.LanguageString(ctx, doc.Content); langCode != "" && t.CleanStopWords { - doc.Content = CleanString(doc.Content, langCode) - } - - return doc, nil -} - -func (t Tika) getImage(meta map[string][]string) *libregraph.Image { - var image *libregraph.Image - initImage := func() { - if image == nil { - image = libregraph.NewImage() - } - } - if v, err := getFirstValue(meta, "tiff:ImageWidth"); err == nil { - if i, err := strconv.ParseInt(v, 0, 32); err == nil { - initImage() - image.SetWidth(int32(i)) - } - } - - if v, err := getFirstValue(meta, "tiff:ImageLength"); err == nil { - if i, err := strconv.ParseInt(v, 0, 32); err == nil { - initImage() - image.SetHeight(int32(i)) - } + doc.MotionPhoto = t.getMotionPhoto(meta) } - return image -} - -func (t Tika) getLocation(meta map[string][]string) *libregraph.GeoCoordinates { - var location *libregraph.GeoCoordinates - initLocation := func() { - if location == nil { - location = libregraph.NewGeoCoordinates() - } - } - - // TODO: location.Altitute: transform the following data to … feet above sea level. - // "GPS:GPS Altitude": []string{"227.4 metres"}, - // "GPS:GPS Altitude Ref": []string{"Sea level"}, - - if v, err := getFirstValue(meta, "geo:lat"); err == nil { - if i, err := strconv.ParseFloat(v, 64); err == nil { - initLocation() - location.SetLatitude(i) - } - } - - if v, err := getFirstValue(meta, "geo:long"); err == nil { - if i, err := strconv.ParseFloat(v, 64); err == nil { - initLocation() - location.SetLongitude(i) - } - } - - return location -} - -func (t Tika) getPhoto(meta map[string][]string) *libregraph.Photo { - var photo *libregraph.Photo - initPhoto := func() { - if photo == nil { - photo = libregraph.NewPhoto() - } - } - - if v, err := getFirstValue(meta, "tiff:Make"); err == nil { - initPhoto() - photo.SetCameraMake(v) - } - - if v, err := getFirstValue(meta, "tiff:Model"); err == nil { - initPhoto() - photo.SetCameraModel(v) - } - - if v, err := getFirstValue(meta, "exif:FNumber"); err == nil { - if i, err := strconv.ParseFloat(v, 64); err == nil { - initPhoto() - photo.SetFNumber(i) - } - } - - if v, err := getFirstValue(meta, "exif:FocalLength"); err == nil { - if i, err := strconv.ParseFloat(v, 64); err == nil { - initPhoto() - photo.SetFocalLength(i) - } - } - - if v, err := getFirstValue(meta, "Base ISO"); err == nil { - if i, err := strconv.ParseInt(v, 0, 32); err == nil { - initPhoto() - photo.SetIso(int32(i)) - } + if doc.MotionPhoto != nil && !t.motionPhotoHasVideo(ctx, ri, doc.MotionPhoto.GetVideoSize()) { + doc.MotionPhoto = nil } - if v, err := getFirstValue(meta, "tiff:Orientation"); err == nil { - if i, err := strconv.ParseInt(v, 0, 32); err == nil { - initPhoto() - photo.SetOrientation(int32(i)) - } - } - - if v, err := getFirstValue(meta, "exif:DateTimeOriginal"); err == nil { - layout := "2006-01-02T15:04:05" - if t, err := time.Parse(layout, v); err == nil { - initPhoto() - photo.SetTakenDateTime(t) - } - } - - if v, err := getFirstValue(meta, "exif:ExposureTime"); err == nil { - if i, err := strconv.ParseFloat(v, 64); err == nil { - initPhoto() - photo.SetExposureNumerator(1) - photo.SetExposureDenominator(math.Round(1 / i)) - } - } - - return photo -} - -func (t Tika) getAudio(meta map[string][]string) *libregraph.Audio { - var audio *libregraph.Audio - initAudio := func() { - if audio == nil { - audio = libregraph.NewAudio() - } - } - - if v, err := getFirstValue(meta, "xmpDM:album"); err == nil { - initAudio() - audio.SetAlbum(v) - } - - if v, err := getFirstValue(meta, "xmpDM:albumArtist"); err == nil { - initAudio() - audio.SetAlbumArtist(v) - } - - if v, err := getFirstValue(meta, "xmpDM:artist"); err == nil { - initAudio() - audio.SetArtist(v) - } - - // TODO: audio.Bitrate: not provided by tika - // TODO: audio.Composers: not provided by tika - // TODO: audio.Copyright: not provided by tika for audio files? - - if v, err := getFirstValue(meta, "xmpDM:discNumber"); err == nil { - if i, err := strconv.ParseInt(v, 10, 32); err == nil { - initAudio() - audio.SetDisc(int32(i)) - } - - } - - // TODO: audio.DiscCount: not provided by tika - - if v, err := getFirstValue(meta, "xmpDM:duration"); err == nil { - // Tika emits fractional seconds. - if f, err := strconv.ParseFloat(v, 64); err == nil { - initAudio() - audio.SetDuration(int64(math.Round(f * 1000))) - } - } - - if v, err := getFirstValue(meta, "xmpDM:genre"); err == nil { - initAudio() - audio.SetGenre(v) - } - - // TODO: audio.HasDrm: not provided by tika - // TODO: audio.IsVariableBitrate: not provided by tika - - if v, err := getFirstValue(meta, "dc:title"); err == nil { - initAudio() - audio.SetTitle(v) - } - - if v, err := getFirstValue(meta, "xmpDM:trackNumber"); err == nil { - if i, err := strconv.ParseInt(v, 10, 32); err == nil { - initAudio() - audio.SetTrack(int32(i)) - } - } - - // TODO: audio.TrackCount: not provided by tika - - if v, err := getFirstValue(meta, "xmpDM:releaseDate"); err == nil { - if i, err := strconv.ParseInt(v, 10, 32); err == nil { - initAudio() - audio.SetYear(int32(i)) - } + if langCode, _ := t.tika.LanguageString(ctx, doc.Content); langCode != "" && t.CleanStopWords { + doc.Content = CleanString(doc.Content, langCode) } - return audio + return doc, nil } diff --git a/services/search/pkg/content/tika_audio.go b/services/search/pkg/content/tika_audio.go new file mode 100644 index 0000000000..7a89e3e225 --- /dev/null +++ b/services/search/pkg/content/tika_audio.go @@ -0,0 +1,85 @@ +package content + +import ( + "math" + "strconv" + + libregraph "github.com/opencloud-eu/libre-graph-api-go" +) + +func (t Tika) getAudio(meta map[string][]string) *libregraph.Audio { + var audio *libregraph.Audio + initAudio := func() { + if audio == nil { + audio = libregraph.NewAudio() + } + } + + if v, err := getFirstValue(meta, "xmpDM:album"); err == nil { + initAudio() + audio.SetAlbum(v) + } + + if v, err := getFirstValue(meta, "xmpDM:albumArtist"); err == nil { + initAudio() + audio.SetAlbumArtist(v) + } + + if v, err := getFirstValue(meta, "xmpDM:artist"); err == nil { + initAudio() + audio.SetArtist(v) + } + + // TODO: audio.Bitrate: not provided by tika + // TODO: audio.Composers: not provided by tika + // TODO: audio.Copyright: not provided by tika for audio files? + + if v, err := getFirstValue(meta, "xmpDM:discNumber"); err == nil { + if i, err := strconv.ParseInt(v, 10, 32); err == nil { + initAudio() + audio.SetDisc(int32(i)) + } + + } + + // TODO: audio.DiscCount: not provided by tika + + if v, err := getFirstValue(meta, "xmpDM:duration"); err == nil { + // Tika emits fractional seconds. + if f, err := strconv.ParseFloat(v, 64); err == nil { + initAudio() + audio.SetDuration(int64(math.Round(f * 1000))) + } + } + + if v, err := getFirstValue(meta, "xmpDM:genre"); err == nil { + initAudio() + audio.SetGenre(v) + } + + // TODO: audio.HasDrm: not provided by tika + // TODO: audio.IsVariableBitrate: not provided by tika + + if v, err := getFirstValue(meta, "dc:title"); err == nil { + initAudio() + audio.SetTitle(v) + } + + if v, err := getFirstValue(meta, "xmpDM:trackNumber"); err == nil { + if i, err := strconv.ParseInt(v, 10, 32); err == nil { + initAudio() + audio.SetTrack(int32(i)) + } + } + + // TODO: audio.TrackCount: not provided by tika + + if v, err := getFirstValue(meta, "xmpDM:releaseDate"); err == nil { + if i, err := strconv.ParseInt(v, 10, 32); err == nil { + initAudio() + audio.SetYear(int32(i)) + } + } + + return audio +} diff --git a/services/search/pkg/content/tika_image.go b/services/search/pkg/content/tika_image.go new file mode 100644 index 0000000000..b5ce2a4037 --- /dev/null +++ b/services/search/pkg/content/tika_image.go @@ -0,0 +1,32 @@ +package content + +import ( + "strconv" + + libregraph "github.com/opencloud-eu/libre-graph-api-go" +) + +func (t Tika) getImage(meta map[string][]string) *libregraph.Image { + var image *libregraph.Image + initImage := func() { + if image == nil { + image = libregraph.NewImage() + } + } + + if v, err := getFirstValue(meta, "tiff:ImageWidth"); err == nil { + if i, err := strconv.ParseInt(v, 0, 32); err == nil { + initImage() + image.SetWidth(int32(i)) + } + } + + if v, err := getFirstValue(meta, "tiff:ImageLength"); err == nil { + if i, err := strconv.ParseInt(v, 0, 32); err == nil { + initImage() + image.SetHeight(int32(i)) + } + } + + return image +} diff --git a/services/search/pkg/content/tika_location.go b/services/search/pkg/content/tika_location.go new file mode 100644 index 0000000000..2334c53afe --- /dev/null +++ b/services/search/pkg/content/tika_location.go @@ -0,0 +1,36 @@ +package content + +import ( + "strconv" + + libregraph "github.com/opencloud-eu/libre-graph-api-go" +) + +func (t Tika) getLocation(meta map[string][]string) *libregraph.GeoCoordinates { + var location *libregraph.GeoCoordinates + initLocation := func() { + if location == nil { + location = libregraph.NewGeoCoordinates() + } + } + + // TODO: location.Altitute: transform the following data to … feet above sea level. + // "GPS:GPS Altitude": []string{"227.4 metres"}, + // "GPS:GPS Altitude Ref": []string{"Sea level"}, + + if v, err := getFirstValue(meta, "geo:lat"); err == nil { + if i, err := strconv.ParseFloat(v, 64); err == nil { + initLocation() + location.SetLatitude(i) + } + } + + if v, err := getFirstValue(meta, "geo:long"); err == nil { + if i, err := strconv.ParseFloat(v, 64); err == nil { + initLocation() + location.SetLongitude(i) + } + } + + return location +} diff --git a/services/search/pkg/content/tika_motion_photo.go b/services/search/pkg/content/tika_motion_photo.go new file mode 100644 index 0000000000..a913ce0c31 --- /dev/null +++ b/services/search/pkg/content/tika_motion_photo.go @@ -0,0 +1,105 @@ +package content + +import ( + "context" + "io" + "strconv" + "strings" + + provider "github.com/cs3org/go-cs3apis/cs3/storage/provider/v1beta1" + libregraph "github.com/opencloud-eu/libre-graph-api-go" +) + +// motionPhotoVideoSignatureLen is the number of trailing bytes we read to confirm +// an actual video is present. Enough to cover the ISO base media (MP4) box size +// and the "ftyp" box type at bytes [4:8]. +const motionPhotoVideoSignatureLen = 12 + +// getMotionPhoto reads Google Motion Photo XMP, which Tika exposes under the +// canonical Camera/Container prefixes. It covers both the current MotionPhoto +// scheme and the legacy MicroVideo scheme. videoSize (the embedded video's byte +// length, needed to range-fetch it) is required, so the facet is dropped without it. +func (t Tika) getMotionPhoto(meta map[string][]string) *libregraph.MotionPhoto { + var motionPhoto *libregraph.MotionPhoto + initMotionPhoto := func() { + if motionPhoto == nil { + motionPhoto = libregraph.NewMotionPhoto() + } + } + + if v, err := getFirstValue(meta, "Camera:MotionPhotoVersion", "Camera:MicroVideoVersion"); err == nil { + if i, err := strconv.ParseInt(v, 0, 32); err == nil { + initMotionPhoto() + motionPhoto.SetVersion(int32(i)) + } + } + + if v, err := getFirstValue(meta, "Camera:MotionPhotoPresentationTimestampUs", "Camera:MicroVideoPresentationTimestampUs"); err == nil { + if i, err := strconv.ParseInt(v, 0, 64); err == nil { + initMotionPhoto() + motionPhoto.SetPresentationTimestampUs(i) + } + } + + if size, ok := motionPhotoVideoSize(meta); ok { + initMotionPhoto() + motionPhoto.SetVideoSize(size) + } + + if motionPhoto == nil || !motionPhoto.HasVideoSize() { + return nil + } + return motionPhoto +} + +// motionPhotoVideoSize returns the embedded video's byte length. Legacy files +// carry it as the MicroVideo offset (bytes from EOF to the video start, which +// equals its length); current files expose it as the length of the Container +// item whose semantic is "MotionPhoto". +func motionPhotoVideoSize(meta map[string][]string) (int64, bool) { + if v, err := getFirstValue(meta, "Camera:MicroVideoOffset"); err == nil { + if i, err := strconv.ParseInt(v, 0, 64); err == nil { + return i, true + } + } + for k, vals := range meta { + if !strings.HasSuffix(k, "/Item:Semantic") || len(vals) == 0 || vals[0] != "MotionPhoto" { + continue + } + if v, err := getFirstValue(meta, strings.TrimSuffix(k, "/Item:Semantic")+"/Item:Length"); err == nil { + if i, err := strconv.ParseInt(v, 0, 64); err == nil { + return i, true + } + } + } + return 0, false +} + +// looksLikeMP4 reports whether buf begins with an ISO base media (MP4/QuickTime) +// "ftyp" box, which Google Motion Photo and legacy MicroVideo clips start with. +func looksLikeMP4(buf []byte) bool { + return len(buf) >= 8 && string(buf[4:8]) == "ftyp" +} + +// motionPhotoHasVideo confirms that the file actually contains the embedded video +// the XMP advertises. A photos.google.com share strips the appended video but +// keeps the XMP, which would otherwise make us expose an unplayable facet. The +// video is appended at the end, so it starts at fileSize-videoSize; we read a few +// bytes there and require an MP4 signature. +func (t Tika) motionPhotoHasVideo(ctx context.Context, ri *provider.ResourceInfo, videoSize int64) bool { + size := int64(ri.GetSize()) + if videoSize <= 0 || videoSize >= size { + return false + } + + rc, err := t.RetrieveRange(ctx, ri.GetId(), size-videoSize, motionPhotoVideoSignatureLen) + if err != nil { + t.logger.Debug().Err(err).Interface("ResourceID", ri.GetId()).Msg("could not read motion photo video header, dropping facet") + return false + } + defer rc.Close() + + buf := make([]byte, motionPhotoVideoSignatureLen) + n, _ := io.ReadFull(rc, buf) + return looksLikeMP4(buf[:n]) +} diff --git a/services/search/pkg/content/tika_photo.go b/services/search/pkg/content/tika_photo.go new file mode 100644 index 0000000000..a833df3b1d --- /dev/null +++ b/services/search/pkg/content/tika_photo.go @@ -0,0 +1,74 @@ +package content + +import ( + "math" + "strconv" + "time" + + libregraph "github.com/opencloud-eu/libre-graph-api-go" +) + +func (t Tika) getPhoto(meta map[string][]string) *libregraph.Photo { + var photo *libregraph.Photo + initPhoto := func() { + if photo == nil { + photo = libregraph.NewPhoto() + } + } + + if v, err := getFirstValue(meta, "tiff:Make"); err == nil { + initPhoto() + photo.SetCameraMake(v) + } + + if v, err := getFirstValue(meta, "tiff:Model"); err == nil { + initPhoto() + photo.SetCameraModel(v) + } + + if v, err := getFirstValue(meta, "exif:FNumber"); err == nil { + if i, err := strconv.ParseFloat(v, 64); err == nil { + initPhoto() + photo.SetFNumber(i) + } + } + + if v, err := getFirstValue(meta, "exif:FocalLength"); err == nil { + if i, err := strconv.ParseFloat(v, 64); err == nil { + initPhoto() + photo.SetFocalLength(i) + } + } + + if v, err := getFirstValue(meta, "Base ISO"); err == nil { + if i, err := strconv.ParseInt(v, 0, 32); err == nil { + initPhoto() + photo.SetIso(int32(i)) + } + } + + if v, err := getFirstValue(meta, "tiff:Orientation"); err == nil { + if i, err := strconv.ParseInt(v, 0, 32); err == nil { + initPhoto() + photo.SetOrientation(int32(i)) + } + } + + if v, err := getFirstValue(meta, "exif:DateTimeOriginal"); err == nil { + layout := "2006-01-02T15:04:05" + if t, err := time.Parse(layout, v); err == nil { + initPhoto() + photo.SetTakenDateTime(t) + } + } + + if v, err := getFirstValue(meta, "exif:ExposureTime"); err == nil { + if i, err := strconv.ParseFloat(v, 64); err == nil { + initPhoto() + photo.SetExposureNumerator(1) + photo.SetExposureDenominator(math.Round(1 / i)) + } + } + + return photo +} diff --git a/services/search/pkg/content/tika_test.go b/services/search/pkg/content/tika_test.go index b6ee193528..ae35643f31 100644 --- a/services/search/pkg/content/tika_test.go +++ b/services/search/pkg/content/tika_test.go @@ -1,6 +1,7 @@ package content_test import ( + "bytes" "context" "fmt" "io" @@ -21,6 +22,10 @@ import ( contentMocks "github.com/opencloud-eu/opencloud/services/search/pkg/content/mocks" ) +// validMP4Header is a minimal ISO base media "ftyp" box, used to stub the tail +// read that confirms a motion photo really contains a video. +var validMP4Header = []byte{0x00, 0x00, 0x00, 0x18, 'f', 't', 'y', 'p', 'm', 'p', '4', '2'} + var _ = Describe("Tika", func() { Describe("extract", func() { var ( @@ -66,6 +71,9 @@ var _ = Describe("Tika", func() { retriever := &contentMocks.Retriever{} retriever.On("Retrieve", mock.Anything, mock.Anything, mock.Anything).Return(io.NopCloser(strings.NewReader(body)), nil) + // By default the trailing bytes look like a real video so the motion + // photo facet survives validation; tests that need otherwise override this. + retriever.On("RetrieveRange", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(io.NopCloser(bytes.NewReader(validMP4Header)), nil) tika.Retriever = retriever }) @@ -216,6 +224,111 @@ var _ = Describe("Tika", func() { Expect(photo.TakenDateTime).To(Equal(libregraph.PtrTime(time.Date(2018, 1, 1, 12, 34, 56, 0, time.UTC)))) }) + It("adds motion photo content from the legacy MicroVideo format", func() { + fullResponse = `[ + { + "Camera:MicroVideoVersion": "1", + "Camera:MicroVideoPresentationTimestampUs": "500000", + "Camera:MicroVideoOffset": "1234567" + } + ]` + doc, err := tika.Extract(context.TODO(), &provider.ResourceInfo{ + Type: provider.ResourceType_RESOURCE_TYPE_FILE, + Size: 2 * 1024 * 1024, + }) + Expect(err).ToNot(HaveOccurred()) + + motionPhoto := doc.MotionPhoto + Expect(motionPhoto).ToNot(BeNil()) + Expect(motionPhoto.Version).To(Equal(libregraph.PtrInt32(1))) + Expect(motionPhoto.PresentationTimestampUs).To(Equal(libregraph.PtrInt64(500000))) + Expect(motionPhoto.VideoSize).To(Equal(libregraph.PtrInt64(1234567))) + }) + + It("adds motion photo content from the current Container format", func() { + // videoSize is the length of the container item whose semantic is MotionPhoto. + fullResponse = `[ + { + "Camera:MotionPhotoVersion": "1", + "Camera:MotionPhotoPresentationTimestampUs": "500000", + "Container:Directory[1]/Item:Semantic": "Primary", + "Container:Directory[2]/Item:Semantic": "MotionPhoto", + "Container:Directory[2]/Item:Length": "122562" + } + ]` + doc, err := tika.Extract(context.TODO(), &provider.ResourceInfo{ + Type: provider.ResourceType_RESOURCE_TYPE_FILE, + Size: 2 * 1024 * 1024, + }) + Expect(err).ToNot(HaveOccurred()) + + motionPhoto := doc.MotionPhoto + Expect(motionPhoto).ToNot(BeNil()) + Expect(motionPhoto.Version).To(Equal(libregraph.PtrInt32(1))) + Expect(motionPhoto.PresentationTimestampUs).To(Equal(libregraph.PtrInt64(500000))) + Expect(motionPhoto.VideoSize).To(Equal(libregraph.PtrInt64(122562))) + }) + + It("skips a motion photo without a video size", func() { + // Without a video size the facet cannot drive the range fetch, so it is not stored. + fullResponse = `[ + { + "Camera:MotionPhotoVersion": "1", + "Camera:MotionPhotoPresentationTimestampUs": "500000" + } + ]` + doc, err := tika.Extract(context.TODO(), &provider.ResourceInfo{ + Type: provider.ResourceType_RESOURCE_TYPE_FILE, + Size: 1, + }) + Expect(err).ToNot(HaveOccurred()) + Expect(doc.MotionPhoto).To(BeNil()) + }) + + It("drops a motion photo when the file is not larger than the video", func() { + // A photos.google.com share strips the appended video but keeps the XMP, + // leaving a file smaller than the advertised video. Caught without any IO. + fullResponse = `[ + { + "Camera:MotionPhotoVersion": "1", + "Camera:MotionPhotoPresentationTimestampUs": "500000", + "Container:Directory[2]/Item:Semantic": "MotionPhoto", + "Container:Directory[2]/Item:Length": "122562" + } + ]` + doc, err := tika.Extract(context.TODO(), &provider.ResourceInfo{ + Type: provider.ResourceType_RESOURCE_TYPE_FILE, + Size: 1000, + }) + Expect(err).ToNot(HaveOccurred()) + Expect(doc.MotionPhoto).To(BeNil()) + }) + + It("drops a motion photo when the trailing bytes are not a video", func() { + // videoSize fits the file, but the bytes at the video offset are not an + // MP4 (the video was stripped and the file is a larger plain JPEG). + fullResponse = `[ + { + "Camera:MotionPhotoVersion": "1", + "Camera:MotionPhotoPresentationTimestampUs": "500000", + "Container:Directory[2]/Item:Semantic": "MotionPhoto", + "Container:Directory[2]/Item:Length": "122562" + } + ]` + + retriever := &contentMocks.Retriever{} + retriever.On("Retrieve", mock.Anything, mock.Anything, mock.Anything).Return(io.NopCloser(strings.NewReader(body)), nil) + retriever.On("RetrieveRange", mock.Anything, mock.Anything, mock.Anything, mock.Anything).Return(io.NopCloser(strings.NewReader("\xff\xd8\xff\xe0not a video")), nil) + tika.Retriever = retriever + + doc, err := tika.Extract(context.TODO(), &provider.ResourceInfo{ + Type: provider.ResourceType_RESOURCE_TYPE_FILE, + Size: 2 * 1024 * 1024, + }) + Expect(err).ToNot(HaveOccurred()) + Expect(doc.MotionPhoto).To(BeNil()) + }) + It("removes stop words", func() { body = "body to test stop words!!! against almost everyone" language = "en" diff --git a/services/search/pkg/opensearch/internal/convert/opensearch.go b/services/search/pkg/opensearch/internal/convert/opensearch.go index 1eef75ac88..92d6f7853a 100644 --- a/services/search/pkg/opensearch/internal/convert/opensearch.go +++ b/services/search/pkg/opensearch/internal/convert/opensearch.go @@ -79,10 +79,11 @@ func OpenSearchHitToMatch(hit opensearchgoAPI.SearchHit) (*searchMessage.Match, return strings.Join(contentHighlights[:], "; ") }(), - Audio: copyFacet[searchMessage.Audio](resource.Audio), - Image: copyFacet[searchMessage.Image](resource.Image), - Location: copyFacet[searchMessage.GeoCoordinates](resource.Location), - Photo: copyFacet[searchMessage.Photo](resource.Photo), + Audio: copyFacet[searchMessage.Audio](resource.Audio), + Image: copyFacet[searchMessage.Image](resource.Image), + Location: copyFacet[searchMessage.GeoCoordinates](resource.Location), + Photo: copyFacet[searchMessage.Photo](resource.Photo), + MotionPhoto: copyFacet[searchMessage.MotionPhoto](resource.MotionPhoto), }, } diff --git a/services/search/pkg/search/service.go b/services/search/pkg/search/service.go index 2c8221b2a7..ffa453713b 100644 --- a/services/search/pkg/search/service.go +++ b/services/search/pkg/search/service.go @@ -633,6 +633,7 @@ func (s *Service) doUpsertItem(ref *provider.Reference, batch BatchOperator) { facetToMetadata(metadata, doc.Image, "libre.graph.image.") facetToMetadata(metadata, doc.Location, "libre.graph.location.") facetToMetadata(metadata, doc.Photo, "libre.graph.photo.") + facetToMetadata(metadata, doc.MotionPhoto, "libre.graph.motionPhoto.") if len(metadata) == 0 { return } diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/README.md b/vendor/github.com/opencloud-eu/libre-graph-api-go/README.md index 353bd46b7a..c69e777b36 100644 --- a/vendor/github.com/opencloud-eu/libre-graph-api-go/README.md +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/README.md @@ -83,6 +83,7 @@ Class | Method | HTTP request | Description *ApplicationsApi* | [**ListApplications**](docs/ApplicationsApi.md#listapplications) | **Get** /v1.0/applications | Get all applications *DriveItemApi* | [**DeleteDriveItem**](docs/DriveItemApi.md#deletedriveitem) | **Delete** /v1beta1/drives/{drive-id}/items/{item-id} | Delete a DriveItem. *DriveItemApi* | [**GetDriveItem**](docs/DriveItemApi.md#getdriveitem) | **Get** /v1beta1/drives/{drive-id}/items/{item-id} | Get a DriveItem. +*DriveItemApi* | [**GetDriveItemContent**](docs/DriveItemApi.md#getdriveitemcontent) | **Get** /v1beta1/drives/{drive-id}/items/{item-id}/content | Download the content of a DriveItem *DriveItemApi* | [**UpdateDriveItem**](docs/DriveItemApi.md#updatedriveitem) | **Patch** /v1beta1/drives/{drive-id}/items/{item-id} | Update a DriveItem. *DrivesApi* | [**CreateDrive**](docs/DrivesApi.md#createdrive) | **Post** /v1.0/drives | Create a new drive of a specific type *DrivesApi* | [**DeleteDrive**](docs/DrivesApi.md#deletedrive) | **Delete** /v1.0/drives/{drive-id} | Delete a specific space @@ -141,6 +142,9 @@ Class | Method | HTTP request | Description *GroupApi* | [**UpdateGroup**](docs/GroupApi.md#updategroup) | **Patch** /v1.0/groups/{group-id} | Update entity in groups *GroupsApi* | [**CreateGroup**](docs/GroupsApi.md#creategroup) | **Post** /v1.0/groups | Add new entity to groups *GroupsApi* | [**ListGroups**](docs/GroupsApi.md#listgroups) | **Get** /v1.0/groups | Get entities from groups +*InvitationsApi* | [**CreateInvitation**](docs/InvitationsApi.md#createinvitation) | **Post** /v1.0/invitations | Create a new invitation +*InvitationsApi* | [**GetInvitation**](docs/InvitationsApi.md#getinvitation) | **Get** /v1.0/invitations/{invitation-id} | Get an invitation by key +*InvitationsApi* | [**ListInvitations**](docs/InvitationsApi.md#listinvitations) | **Get** /v1.0/invitations | Get a list of invitations *MeChangepasswordApi* | [**ChangeOwnPassword**](docs/MeChangepasswordApi.md#changeownpassword) | **Post** /v1.0/me/changePassword | Change your own password *MeDriveApi* | [**FollowDriveItem**](docs/MeDriveApi.md#followdriveitem) | **Post** /v1.0/me/drive/items/{item-id}/follow | Follow a DriveItem *MeDriveApi* | [**GetHome**](docs/MeDriveApi.md#gethome) | **Get** /v1.0/me/drive | Get personal space for user @@ -197,6 +201,7 @@ Class | Method | HTTP request | Description - [CollectionOfEducationClass](docs/CollectionOfEducationClass.md) - [CollectionOfEducationUser](docs/CollectionOfEducationUser.md) - [CollectionOfGroup](docs/CollectionOfGroup.md) + - [CollectionOfInvitations](docs/CollectionOfInvitations.md) - [CollectionOfPermissions](docs/CollectionOfPermissions.md) - [CollectionOfPermissionsWithAllowedValues](docs/CollectionOfPermissionsWithAllowedValues.md) - [CollectionOfSchools](docs/CollectionOfSchools.md) @@ -214,6 +219,7 @@ Class | Method | HTTP request | Description - [EducationSchool](docs/EducationSchool.md) - [EducationUser](docs/EducationUser.md) - [EducationUserReference](docs/EducationUserReference.md) + - [EmailAddress](docs/EmailAddress.md) - [ExportPersonalDataRequest](docs/ExportPersonalDataRequest.md) - [FileSystemInfo](docs/FileSystemInfo.md) - [Folder](docs/Folder.md) @@ -224,8 +230,11 @@ Class | Method | HTTP request | Description - [Identity](docs/Identity.md) - [IdentitySet](docs/IdentitySet.md) - [Image](docs/Image.md) + - [Invitation](docs/Invitation.md) + - [InvitedUserMessageInfo](docs/InvitedUserMessageInfo.md) - [ItemReference](docs/ItemReference.md) - [MemberReference](docs/MemberReference.md) + - [MotionPhoto](docs/MotionPhoto.md) - [ObjectIdentity](docs/ObjectIdentity.md) - [OdataError](docs/OdataError.md) - [OdataErrorDetail](docs/OdataErrorDetail.md) @@ -236,6 +245,7 @@ Class | Method | HTTP request | Description - [Permission](docs/Permission.md) - [Photo](docs/Photo.md) - [Quota](docs/Quota.md) + - [Recipient](docs/Recipient.md) - [RemoteItem](docs/RemoteItem.md) - [SharePointIdentitySet](docs/SharePointIdentitySet.md) - [SharingInvitation](docs/SharingInvitation.md) diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/api_drive_item.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/api_drive_item.go index a502b6abac..d11ce21051 100644 --- a/vendor/github.com/opencloud-eu/libre-graph-api-go/api_drive_item.go +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/api_drive_item.go @@ -137,6 +137,13 @@ type ApiGetDriveItemRequest struct { ApiService *DriveItemApiService driveId string itemId string + select_ *[]string +} + +// Select additional properties to be returned. +func (r ApiGetDriveItemRequest) Select_(select_ []string) ApiGetDriveItemRequest { + r.select_ = &select_ + return r } func (r ApiGetDriveItemRequest) Execute() (*DriveItem, *http.Response, error) { @@ -186,6 +193,9 @@ func (a *DriveItemApiService) GetDriveItemExecute(r ApiGetDriveItemRequest) (*Dr localVarQueryParams := url.Values{} localVarFormParams := url.Values{} + if r.select_ != nil { + parameterAddToHeaderOrQuery(localVarQueryParams, "$select", r.select_, "form", "csv") + } // to determine the Content-Type header localVarHTTPContentTypes := []string{} @@ -248,6 +258,149 @@ func (a *DriveItemApiService) GetDriveItemExecute(r ApiGetDriveItemRequest) (*Dr return localVarReturnValue, localVarHTTPResponse, nil } +type ApiGetDriveItemContentRequest struct { + ctx context.Context + ApiService *DriveItemApiService + driveId string + itemId string +} + +func (r ApiGetDriveItemContentRequest) Execute() (*OdataError, *http.Response, error) { + return r.ApiService.GetDriveItemContentExecute(r) +} + +/* +GetDriveItemContent Download the content of a DriveItem + +Download the contents of the primary stream (file) of a driveItem. Only +driveItem objects with a `file` facet can be downloaded. + +The response is a `302 Found` redirecting to a pre-authenticated download +URL for the file. This is the same URL that is returned via the +`@microsoft.graph.downloadUrl` instance annotation on the driveItem when +requested via `$select`. Choose between the two based on whether you +want to call the redirecting `/content` endpoint directly (for example, +with a client that follows redirects automatically) or you want to +inspect / schedule / prefetch the URL yourself via the annotation. + +The pre-authenticated URL is short-lived and does not require an +`Authorization` header. + +To download a partial range of bytes, apply the `Range` header to the +redirect target (the pre-authenticated URL), not to the `/content` +request. + + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param driveId key: id of drive + @param itemId key: id of item + @return ApiGetDriveItemContentRequest +*/ +func (a *DriveItemApiService) GetDriveItemContent(ctx context.Context, driveId string, itemId string) ApiGetDriveItemContentRequest { + return ApiGetDriveItemContentRequest{ + ApiService: a, + ctx: ctx, + driveId: driveId, + itemId: itemId, + } +} + +// Execute executes the request +// @return OdataError +func (a *DriveItemApiService) GetDriveItemContentExecute(r ApiGetDriveItemContentRequest) (*OdataError, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *OdataError + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "DriveItemApiService.GetDriveItemContent") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v1beta1/drives/{drive-id}/items/{item-id}/content" + localVarPath = strings.Replace(localVarPath, "{"+"drive-id"+"}", url.PathEscape(parameterValueToString(r.driveId, "driveId")), -1) + localVarPath = strings.Replace(localVarPath, "{"+"item-id"+"}", url.PathEscape(parameterValueToString(r.itemId, "itemId")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + if localVarHTTPResponse.StatusCode == 404 { + var v OdataError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + var v OdataError + err = a.client.decode(&v, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr.error = err.Error() + return localVarReturnValue, localVarHTTPResponse, newErr + } + newErr.error = formatErrorMessage(localVarHTTPResponse.Status, &v) + newErr.model = v + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + type ApiUpdateDriveItemRequest struct { ctx context.Context ApiService *DriveItemApiService diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/api_invitations.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/api_invitations.go new file mode 100644 index 0000000000..bafad29ea7 --- /dev/null +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/api_invitations.go @@ -0,0 +1,328 @@ +/* +Libre Graph API + +Libre Graph is a free API for cloud collaboration inspired by the MS Graph API. + +API version: v1.0.8 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package libregraph + +import ( + "bytes" + "context" + "io" + "net/http" + "net/url" + "strings" +) + + +// InvitationsApiService InvitationsApi service +type InvitationsApiService service + +type ApiCreateInvitationRequest struct { + ctx context.Context + ApiService *InvitationsApiService + invitation *Invitation +} + +// New invitation +func (r ApiCreateInvitationRequest) Invitation(invitation Invitation) ApiCreateInvitationRequest { + r.invitation = &invitation + return r +} + +func (r ApiCreateInvitationRequest) Execute() (*Invitation, *http.Response, error) { + return r.ApiService.CreateInvitationExecute(r) +} + +/* +CreateInvitation Create a new invitation + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiCreateInvitationRequest +*/ +func (a *InvitationsApiService) CreateInvitation(ctx context.Context) ApiCreateInvitationRequest { + return ApiCreateInvitationRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return Invitation +func (a *InvitationsApiService) CreateInvitationExecute(r ApiCreateInvitationRequest) (*Invitation, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodPost + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Invitation + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InvitationsApiService.CreateInvitation") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v1.0/invitations" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{"application/json"} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + // body params + localVarPostBody = r.invitation + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiGetInvitationRequest struct { + ctx context.Context + ApiService *InvitationsApiService + invitationId string +} + +func (r ApiGetInvitationRequest) Execute() (*Invitation, *http.Response, error) { + return r.ApiService.GetInvitationExecute(r) +} + +/* +GetInvitation Get an invitation by key + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @param invitationId key: id of invitation + @return ApiGetInvitationRequest +*/ +func (a *InvitationsApiService) GetInvitation(ctx context.Context, invitationId string) ApiGetInvitationRequest { + return ApiGetInvitationRequest{ + ApiService: a, + ctx: ctx, + invitationId: invitationId, + } +} + +// Execute executes the request +// @return Invitation +func (a *InvitationsApiService) GetInvitationExecute(r ApiGetInvitationRequest) (*Invitation, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *Invitation + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InvitationsApiService.GetInvitation") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v1.0/invitations/{invitation-id}" + localVarPath = strings.Replace(localVarPath, "{"+"invitation-id"+"}", url.PathEscape(parameterValueToString(r.invitationId, "invitationId")), -1) + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} + +type ApiListInvitationsRequest struct { + ctx context.Context + ApiService *InvitationsApiService +} + +func (r ApiListInvitationsRequest) Execute() (*CollectionOfInvitations, *http.Response, error) { + return r.ApiService.ListInvitationsExecute(r) +} + +/* +ListInvitations Get a list of invitations + + @param ctx context.Context - for authentication, logging, cancellation, deadlines, tracing, etc. Passed from http.Request or context.Background(). + @return ApiListInvitationsRequest +*/ +func (a *InvitationsApiService) ListInvitations(ctx context.Context) ApiListInvitationsRequest { + return ApiListInvitationsRequest{ + ApiService: a, + ctx: ctx, + } +} + +// Execute executes the request +// @return CollectionOfInvitations +func (a *InvitationsApiService) ListInvitationsExecute(r ApiListInvitationsRequest) (*CollectionOfInvitations, *http.Response, error) { + var ( + localVarHTTPMethod = http.MethodGet + localVarPostBody interface{} + formFiles []formFile + localVarReturnValue *CollectionOfInvitations + ) + + localBasePath, err := a.client.cfg.ServerURLWithContext(r.ctx, "InvitationsApiService.ListInvitations") + if err != nil { + return localVarReturnValue, nil, &GenericOpenAPIError{error: err.Error()} + } + + localVarPath := localBasePath + "/v1.0/invitations" + + localVarHeaderParams := make(map[string]string) + localVarQueryParams := url.Values{} + localVarFormParams := url.Values{} + + // to determine the Content-Type header + localVarHTTPContentTypes := []string{} + + // set Content-Type header + localVarHTTPContentType := selectHeaderContentType(localVarHTTPContentTypes) + if localVarHTTPContentType != "" { + localVarHeaderParams["Content-Type"] = localVarHTTPContentType + } + + // to determine the Accept header + localVarHTTPHeaderAccepts := []string{"application/json"} + + // set Accept header + localVarHTTPHeaderAccept := selectHeaderAccept(localVarHTTPHeaderAccepts) + if localVarHTTPHeaderAccept != "" { + localVarHeaderParams["Accept"] = localVarHTTPHeaderAccept + } + req, err := a.client.prepareRequest(r.ctx, localVarPath, localVarHTTPMethod, localVarPostBody, localVarHeaderParams, localVarQueryParams, localVarFormParams, formFiles) + if err != nil { + return localVarReturnValue, nil, err + } + + localVarHTTPResponse, err := a.client.callAPI(req) + if err != nil || localVarHTTPResponse == nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + localVarBody, err := io.ReadAll(localVarHTTPResponse.Body) + localVarHTTPResponse.Body.Close() + localVarHTTPResponse.Body = io.NopCloser(bytes.NewBuffer(localVarBody)) + if err != nil { + return localVarReturnValue, localVarHTTPResponse, err + } + + if localVarHTTPResponse.StatusCode >= 300 { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: localVarHTTPResponse.Status, + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + err = a.client.decode(&localVarReturnValue, localVarBody, localVarHTTPResponse.Header.Get("Content-Type")) + if err != nil { + newErr := &GenericOpenAPIError{ + body: localVarBody, + error: err.Error(), + } + return localVarReturnValue, localVarHTTPResponse, newErr + } + + return localVarReturnValue, localVarHTTPResponse, nil +} diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/client.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/client.go index 55ea08b14f..8e5063afee 100644 --- a/vendor/github.com/opencloud-eu/libre-graph-api-go/client.go +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/client.go @@ -75,6 +75,8 @@ type APIClient struct { GroupsApi *GroupsApiService + InvitationsApi *InvitationsApiService + MeChangepasswordApi *MeChangepasswordApiService MeDriveApi *MeDriveApiService @@ -131,6 +133,7 @@ func NewAPIClient(cfg *Configuration) *APIClient { c.EducationUserApi = (*EducationUserApiService)(&c.common) c.GroupApi = (*GroupApiService)(&c.common) c.GroupsApi = (*GroupsApiService)(&c.common) + c.InvitationsApi = (*InvitationsApiService)(&c.common) c.MeChangepasswordApi = (*MeChangepasswordApiService)(&c.common) c.MeDriveApi = (*MeDriveApiService)(&c.common) c.MeDriveRootApi = (*MeDriveRootApiService)(&c.common) diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_collection_of_invitations.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_collection_of_invitations.go new file mode 100644 index 0000000000..181d030ce7 --- /dev/null +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_collection_of_invitations.go @@ -0,0 +1,126 @@ +/* +Libre Graph API + +Libre Graph is a free API for cloud collaboration inspired by the MS Graph API. + +API version: v1.0.8 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package libregraph + +import ( + "encoding/json" +) + +// checks if the CollectionOfInvitations type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &CollectionOfInvitations{} + +// CollectionOfInvitations struct for CollectionOfInvitations +type CollectionOfInvitations struct { + Value []Invitation `json:"value,omitempty"` +} + +// NewCollectionOfInvitations instantiates a new CollectionOfInvitations object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewCollectionOfInvitations() *CollectionOfInvitations { + this := CollectionOfInvitations{} + return &this +} + +// NewCollectionOfInvitationsWithDefaults instantiates a new CollectionOfInvitations object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewCollectionOfInvitationsWithDefaults() *CollectionOfInvitations { + this := CollectionOfInvitations{} + return &this +} + +// GetValue returns the Value field value if set, zero value otherwise. +func (o *CollectionOfInvitations) GetValue() []Invitation { + if o == nil || IsNil(o.Value) { + var ret []Invitation + return ret + } + return o.Value +} + +// GetValueOk returns a tuple with the Value field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *CollectionOfInvitations) GetValueOk() ([]Invitation, bool) { + if o == nil || IsNil(o.Value) { + return nil, false + } + return o.Value, true +} + +// HasValue returns a boolean if a field has been set. +func (o *CollectionOfInvitations) HasValue() bool { + if o != nil && !IsNil(o.Value) { + return true + } + + return false +} + +// SetValue gets a reference to the given []Invitation and assigns it to the Value field. +func (o *CollectionOfInvitations) SetValue(v []Invitation) { + o.Value = v +} + +func (o CollectionOfInvitations) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o CollectionOfInvitations) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.Value) { + toSerialize["value"] = o.Value + } + return toSerialize, nil +} + +type NullableCollectionOfInvitations struct { + value *CollectionOfInvitations + isSet bool +} + +func (v NullableCollectionOfInvitations) Get() *CollectionOfInvitations { + return v.value +} + +func (v *NullableCollectionOfInvitations) Set(val *CollectionOfInvitations) { + v.value = val + v.isSet = true +} + +func (v NullableCollectionOfInvitations) IsSet() bool { + return v.isSet +} + +func (v *NullableCollectionOfInvitations) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableCollectionOfInvitations(val *CollectionOfInvitations) *NullableCollectionOfInvitations { + return &NullableCollectionOfInvitations{value: val, isSet: true} +} + +func (v NullableCollectionOfInvitations) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableCollectionOfInvitations) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_drive_item.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_drive_item.go index 09e6cf34bb..0f5fa975c7 100644 --- a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_drive_item.go +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_drive_item.go @@ -65,8 +65,11 @@ type DriveItem struct { Permissions []Permission `json:"permissions,omitempty"` Audio *Audio `json:"audio,omitempty"` Video *Video `json:"video,omitempty"` + LibreGraphMotionPhoto *MotionPhoto `json:"@libre.graph.motionPhoto,omitempty"` // Indicates if the item is synchronized with the underlying storage provider. Read-only. ClientSynchronize *bool `json:"@client.synchronize,omitempty"` + // A pre-authenticated URL that can be used to download the item's content without providing an Authorization header. The URL is short-lived and cannot be cached. This annotation is only populated when explicitly requested via `$select`, and only for items that have a `file` facet. The returned URL is valid for a limited time and should be used promptly. + MicrosoftGraphDownloadUrl *string `json:"@microsoft.graph.downloadUrl,omitempty"` // Properties or facets (see UI.Facet) annotated with this term will not be rendered if the annotation evaluates to true. Users can set this to hide permissions. UIHidden *bool `json:"@UI.Hidden,omitempty"` } @@ -1048,6 +1051,38 @@ func (o *DriveItem) SetVideo(v Video) { o.Video = &v } +// GetLibreGraphMotionPhoto returns the LibreGraphMotionPhoto field value if set, zero value otherwise. +func (o *DriveItem) GetLibreGraphMotionPhoto() MotionPhoto { + if o == nil || IsNil(o.LibreGraphMotionPhoto) { + var ret MotionPhoto + return ret + } + return *o.LibreGraphMotionPhoto +} + +// GetLibreGraphMotionPhotoOk returns a tuple with the LibreGraphMotionPhoto field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DriveItem) GetLibreGraphMotionPhotoOk() (*MotionPhoto, bool) { + if o == nil || IsNil(o.LibreGraphMotionPhoto) { + return nil, false + } + return o.LibreGraphMotionPhoto, true +} + +// HasLibreGraphMotionPhoto returns a boolean if a field has been set. +func (o *DriveItem) HasLibreGraphMotionPhoto() bool { + if o != nil && !IsNil(o.LibreGraphMotionPhoto) { + return true + } + + return false +} + +// SetLibreGraphMotionPhoto gets a reference to the given MotionPhoto and assigns it to the LibreGraphMotionPhoto field. +func (o *DriveItem) SetLibreGraphMotionPhoto(v MotionPhoto) { + o.LibreGraphMotionPhoto = &v +} + // GetClientSynchronize returns the ClientSynchronize field value if set, zero value otherwise. func (o *DriveItem) GetClientSynchronize() bool { if o == nil || IsNil(o.ClientSynchronize) { @@ -1080,6 +1115,38 @@ func (o *DriveItem) SetClientSynchronize(v bool) { o.ClientSynchronize = &v } +// GetMicrosoftGraphDownloadUrl returns the MicrosoftGraphDownloadUrl field value if set, zero value otherwise. +func (o *DriveItem) GetMicrosoftGraphDownloadUrl() string { + if o == nil || IsNil(o.MicrosoftGraphDownloadUrl) { + var ret string + return ret + } + return *o.MicrosoftGraphDownloadUrl +} + +// GetMicrosoftGraphDownloadUrlOk returns a tuple with the MicrosoftGraphDownloadUrl field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *DriveItem) GetMicrosoftGraphDownloadUrlOk() (*string, bool) { + if o == nil || IsNil(o.MicrosoftGraphDownloadUrl) { + return nil, false + } + return o.MicrosoftGraphDownloadUrl, true +} + +// HasMicrosoftGraphDownloadUrl returns a boolean if a field has been set. +func (o *DriveItem) HasMicrosoftGraphDownloadUrl() bool { + if o != nil && !IsNil(o.MicrosoftGraphDownloadUrl) { + return true + } + + return false +} + +// SetMicrosoftGraphDownloadUrl gets a reference to the given string and assigns it to the MicrosoftGraphDownloadUrl field. +func (o *DriveItem) SetMicrosoftGraphDownloadUrl(v string) { + o.MicrosoftGraphDownloadUrl = &v +} + // GetUIHidden returns the UIHidden field value if set, zero value otherwise. func (o *DriveItem) GetUIHidden() bool { if o == nil || IsNil(o.UIHidden) { @@ -1212,9 +1279,15 @@ func (o DriveItem) ToMap() (map[string]interface{}, error) { if !IsNil(o.Video) { toSerialize["video"] = o.Video } + if !IsNil(o.LibreGraphMotionPhoto) { + toSerialize["@libre.graph.motionPhoto"] = o.LibreGraphMotionPhoto + } if !IsNil(o.ClientSynchronize) { toSerialize["@client.synchronize"] = o.ClientSynchronize } + if !IsNil(o.MicrosoftGraphDownloadUrl) { + toSerialize["@microsoft.graph.downloadUrl"] = o.MicrosoftGraphDownloadUrl + } if !IsNil(o.UIHidden) { toSerialize["@UI.Hidden"] = o.UIHidden } diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_email_address.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_email_address.go new file mode 100644 index 0000000000..b1370999b4 --- /dev/null +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_email_address.go @@ -0,0 +1,164 @@ +/* +Libre Graph API + +Libre Graph is a free API for cloud collaboration inspired by the MS Graph API. + +API version: v1.0.8 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package libregraph + +import ( + "encoding/json" +) + +// checks if the EmailAddress type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &EmailAddress{} + +// EmailAddress Represents an email address. +type EmailAddress struct { + // The email address. + Address *string `json:"address,omitempty"` + // The name associated with the email address. + Name *string `json:"name,omitempty"` +} + +// NewEmailAddress instantiates a new EmailAddress object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewEmailAddress() *EmailAddress { + this := EmailAddress{} + return &this +} + +// NewEmailAddressWithDefaults instantiates a new EmailAddress object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewEmailAddressWithDefaults() *EmailAddress { + this := EmailAddress{} + return &this +} + +// GetAddress returns the Address field value if set, zero value otherwise. +func (o *EmailAddress) GetAddress() string { + if o == nil || IsNil(o.Address) { + var ret string + return ret + } + return *o.Address +} + +// GetAddressOk returns a tuple with the Address field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EmailAddress) GetAddressOk() (*string, bool) { + if o == nil || IsNil(o.Address) { + return nil, false + } + return o.Address, true +} + +// HasAddress returns a boolean if a field has been set. +func (o *EmailAddress) HasAddress() bool { + if o != nil && !IsNil(o.Address) { + return true + } + + return false +} + +// SetAddress gets a reference to the given string and assigns it to the Address field. +func (o *EmailAddress) SetAddress(v string) { + o.Address = &v +} + +// GetName returns the Name field value if set, zero value otherwise. +func (o *EmailAddress) GetName() string { + if o == nil || IsNil(o.Name) { + var ret string + return ret + } + return *o.Name +} + +// GetNameOk returns a tuple with the Name field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *EmailAddress) GetNameOk() (*string, bool) { + if o == nil || IsNil(o.Name) { + return nil, false + } + return o.Name, true +} + +// HasName returns a boolean if a field has been set. +func (o *EmailAddress) HasName() bool { + if o != nil && !IsNil(o.Name) { + return true + } + + return false +} + +// SetName gets a reference to the given string and assigns it to the Name field. +func (o *EmailAddress) SetName(v string) { + o.Name = &v +} + +func (o EmailAddress) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o EmailAddress) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.Address) { + toSerialize["address"] = o.Address + } + if !IsNil(o.Name) { + toSerialize["name"] = o.Name + } + return toSerialize, nil +} + +type NullableEmailAddress struct { + value *EmailAddress + isSet bool +} + +func (v NullableEmailAddress) Get() *EmailAddress { + return v.value +} + +func (v *NullableEmailAddress) Set(val *EmailAddress) { + v.value = val + v.isSet = true +} + +func (v NullableEmailAddress) IsSet() bool { + return v.isSet +} + +func (v *NullableEmailAddress) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableEmailAddress(val *EmailAddress) *NullableEmailAddress { + return &NullableEmailAddress{value: val, isSet: true} +} + +func (v NullableEmailAddress) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableEmailAddress) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_invitation.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_invitation.go new file mode 100644 index 0000000000..dcd97e9deb --- /dev/null +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_invitation.go @@ -0,0 +1,421 @@ +/* +Libre Graph API + +Libre Graph is a free API for cloud collaboration inspired by the MS Graph API. + +API version: v1.0.8 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package libregraph + +import ( + "encoding/json" +) + +// checks if the Invitation type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &Invitation{} + +// Invitation Represents an invitation to a drive item. +type Invitation struct { + // The display name of the user being invited. + InvitedUserDisplayName *string `json:"invitedUserDisplayName,omitempty"` + // The email address of the user being invited. Required. + InvitedUserEmailAddress *string `json:"invitedUserEmailAddress,omitempty"` + InvitedUserMessageInfo *InvitedUserMessageInfo `json:"invitedUserMessageInfo,omitempty"` + // Indicates whether an invitation message should be sent to the user. + SendInvitationMessage *bool `json:"sendInvitationMessage,omitempty"` + // The URL to which the user is redirected after accepting the invitation. Required. + InviteRedirectUrl *string `json:"inviteRedirectUrl,omitempty"` + // The URL that the user can use to redeem the invitation. Read-only. + InviteRedeemUrl *string `json:"inviteRedeemUrl,omitempty"` + // The status of the invitation. Read-only. + Status *string `json:"status,omitempty"` + InvitedUser *User `json:"invitedUser,omitempty"` + // The type of user being invited. + InvitedUserType *string `json:"invitedUserType,omitempty"` +} + +// NewInvitation instantiates a new Invitation object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInvitation() *Invitation { + this := Invitation{} + return &this +} + +// NewInvitationWithDefaults instantiates a new Invitation object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInvitationWithDefaults() *Invitation { + this := Invitation{} + return &this +} + +// GetInvitedUserDisplayName returns the InvitedUserDisplayName field value if set, zero value otherwise. +func (o *Invitation) GetInvitedUserDisplayName() string { + if o == nil || IsNil(o.InvitedUserDisplayName) { + var ret string + return ret + } + return *o.InvitedUserDisplayName +} + +// GetInvitedUserDisplayNameOk returns a tuple with the InvitedUserDisplayName field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Invitation) GetInvitedUserDisplayNameOk() (*string, bool) { + if o == nil || IsNil(o.InvitedUserDisplayName) { + return nil, false + } + return o.InvitedUserDisplayName, true +} + +// HasInvitedUserDisplayName returns a boolean if a field has been set. +func (o *Invitation) HasInvitedUserDisplayName() bool { + if o != nil && !IsNil(o.InvitedUserDisplayName) { + return true + } + + return false +} + +// SetInvitedUserDisplayName gets a reference to the given string and assigns it to the InvitedUserDisplayName field. +func (o *Invitation) SetInvitedUserDisplayName(v string) { + o.InvitedUserDisplayName = &v +} + +// GetInvitedUserEmailAddress returns the InvitedUserEmailAddress field value if set, zero value otherwise. +func (o *Invitation) GetInvitedUserEmailAddress() string { + if o == nil || IsNil(o.InvitedUserEmailAddress) { + var ret string + return ret + } + return *o.InvitedUserEmailAddress +} + +// GetInvitedUserEmailAddressOk returns a tuple with the InvitedUserEmailAddress field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Invitation) GetInvitedUserEmailAddressOk() (*string, bool) { + if o == nil || IsNil(o.InvitedUserEmailAddress) { + return nil, false + } + return o.InvitedUserEmailAddress, true +} + +// HasInvitedUserEmailAddress returns a boolean if a field has been set. +func (o *Invitation) HasInvitedUserEmailAddress() bool { + if o != nil && !IsNil(o.InvitedUserEmailAddress) { + return true + } + + return false +} + +// SetInvitedUserEmailAddress gets a reference to the given string and assigns it to the InvitedUserEmailAddress field. +func (o *Invitation) SetInvitedUserEmailAddress(v string) { + o.InvitedUserEmailAddress = &v +} + +// GetInvitedUserMessageInfo returns the InvitedUserMessageInfo field value if set, zero value otherwise. +func (o *Invitation) GetInvitedUserMessageInfo() InvitedUserMessageInfo { + if o == nil || IsNil(o.InvitedUserMessageInfo) { + var ret InvitedUserMessageInfo + return ret + } + return *o.InvitedUserMessageInfo +} + +// GetInvitedUserMessageInfoOk returns a tuple with the InvitedUserMessageInfo field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Invitation) GetInvitedUserMessageInfoOk() (*InvitedUserMessageInfo, bool) { + if o == nil || IsNil(o.InvitedUserMessageInfo) { + return nil, false + } + return o.InvitedUserMessageInfo, true +} + +// HasInvitedUserMessageInfo returns a boolean if a field has been set. +func (o *Invitation) HasInvitedUserMessageInfo() bool { + if o != nil && !IsNil(o.InvitedUserMessageInfo) { + return true + } + + return false +} + +// SetInvitedUserMessageInfo gets a reference to the given InvitedUserMessageInfo and assigns it to the InvitedUserMessageInfo field. +func (o *Invitation) SetInvitedUserMessageInfo(v InvitedUserMessageInfo) { + o.InvitedUserMessageInfo = &v +} + +// GetSendInvitationMessage returns the SendInvitationMessage field value if set, zero value otherwise. +func (o *Invitation) GetSendInvitationMessage() bool { + if o == nil || IsNil(o.SendInvitationMessage) { + var ret bool + return ret + } + return *o.SendInvitationMessage +} + +// GetSendInvitationMessageOk returns a tuple with the SendInvitationMessage field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Invitation) GetSendInvitationMessageOk() (*bool, bool) { + if o == nil || IsNil(o.SendInvitationMessage) { + return nil, false + } + return o.SendInvitationMessage, true +} + +// HasSendInvitationMessage returns a boolean if a field has been set. +func (o *Invitation) HasSendInvitationMessage() bool { + if o != nil && !IsNil(o.SendInvitationMessage) { + return true + } + + return false +} + +// SetSendInvitationMessage gets a reference to the given bool and assigns it to the SendInvitationMessage field. +func (o *Invitation) SetSendInvitationMessage(v bool) { + o.SendInvitationMessage = &v +} + +// GetInviteRedirectUrl returns the InviteRedirectUrl field value if set, zero value otherwise. +func (o *Invitation) GetInviteRedirectUrl() string { + if o == nil || IsNil(o.InviteRedirectUrl) { + var ret string + return ret + } + return *o.InviteRedirectUrl +} + +// GetInviteRedirectUrlOk returns a tuple with the InviteRedirectUrl field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Invitation) GetInviteRedirectUrlOk() (*string, bool) { + if o == nil || IsNil(o.InviteRedirectUrl) { + return nil, false + } + return o.InviteRedirectUrl, true +} + +// HasInviteRedirectUrl returns a boolean if a field has been set. +func (o *Invitation) HasInviteRedirectUrl() bool { + if o != nil && !IsNil(o.InviteRedirectUrl) { + return true + } + + return false +} + +// SetInviteRedirectUrl gets a reference to the given string and assigns it to the InviteRedirectUrl field. +func (o *Invitation) SetInviteRedirectUrl(v string) { + o.InviteRedirectUrl = &v +} + +// GetInviteRedeemUrl returns the InviteRedeemUrl field value if set, zero value otherwise. +func (o *Invitation) GetInviteRedeemUrl() string { + if o == nil || IsNil(o.InviteRedeemUrl) { + var ret string + return ret + } + return *o.InviteRedeemUrl +} + +// GetInviteRedeemUrlOk returns a tuple with the InviteRedeemUrl field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Invitation) GetInviteRedeemUrlOk() (*string, bool) { + if o == nil || IsNil(o.InviteRedeemUrl) { + return nil, false + } + return o.InviteRedeemUrl, true +} + +// HasInviteRedeemUrl returns a boolean if a field has been set. +func (o *Invitation) HasInviteRedeemUrl() bool { + if o != nil && !IsNil(o.InviteRedeemUrl) { + return true + } + + return false +} + +// SetInviteRedeemUrl gets a reference to the given string and assigns it to the InviteRedeemUrl field. +func (o *Invitation) SetInviteRedeemUrl(v string) { + o.InviteRedeemUrl = &v +} + +// GetStatus returns the Status field value if set, zero value otherwise. +func (o *Invitation) GetStatus() string { + if o == nil || IsNil(o.Status) { + var ret string + return ret + } + return *o.Status +} + +// GetStatusOk returns a tuple with the Status field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Invitation) GetStatusOk() (*string, bool) { + if o == nil || IsNil(o.Status) { + return nil, false + } + return o.Status, true +} + +// HasStatus returns a boolean if a field has been set. +func (o *Invitation) HasStatus() bool { + if o != nil && !IsNil(o.Status) { + return true + } + + return false +} + +// SetStatus gets a reference to the given string and assigns it to the Status field. +func (o *Invitation) SetStatus(v string) { + o.Status = &v +} + +// GetInvitedUser returns the InvitedUser field value if set, zero value otherwise. +func (o *Invitation) GetInvitedUser() User { + if o == nil || IsNil(o.InvitedUser) { + var ret User + return ret + } + return *o.InvitedUser +} + +// GetInvitedUserOk returns a tuple with the InvitedUser field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Invitation) GetInvitedUserOk() (*User, bool) { + if o == nil || IsNil(o.InvitedUser) { + return nil, false + } + return o.InvitedUser, true +} + +// HasInvitedUser returns a boolean if a field has been set. +func (o *Invitation) HasInvitedUser() bool { + if o != nil && !IsNil(o.InvitedUser) { + return true + } + + return false +} + +// SetInvitedUser gets a reference to the given User and assigns it to the InvitedUser field. +func (o *Invitation) SetInvitedUser(v User) { + o.InvitedUser = &v +} + +// GetInvitedUserType returns the InvitedUserType field value if set, zero value otherwise. +func (o *Invitation) GetInvitedUserType() string { + if o == nil || IsNil(o.InvitedUserType) { + var ret string + return ret + } + return *o.InvitedUserType +} + +// GetInvitedUserTypeOk returns a tuple with the InvitedUserType field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Invitation) GetInvitedUserTypeOk() (*string, bool) { + if o == nil || IsNil(o.InvitedUserType) { + return nil, false + } + return o.InvitedUserType, true +} + +// HasInvitedUserType returns a boolean if a field has been set. +func (o *Invitation) HasInvitedUserType() bool { + if o != nil && !IsNil(o.InvitedUserType) { + return true + } + + return false +} + +// SetInvitedUserType gets a reference to the given string and assigns it to the InvitedUserType field. +func (o *Invitation) SetInvitedUserType(v string) { + o.InvitedUserType = &v +} + +func (o Invitation) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o Invitation) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.InvitedUserDisplayName) { + toSerialize["invitedUserDisplayName"] = o.InvitedUserDisplayName + } + if !IsNil(o.InvitedUserEmailAddress) { + toSerialize["invitedUserEmailAddress"] = o.InvitedUserEmailAddress + } + if !IsNil(o.InvitedUserMessageInfo) { + toSerialize["invitedUserMessageInfo"] = o.InvitedUserMessageInfo + } + if !IsNil(o.SendInvitationMessage) { + toSerialize["sendInvitationMessage"] = o.SendInvitationMessage + } + if !IsNil(o.InviteRedirectUrl) { + toSerialize["inviteRedirectUrl"] = o.InviteRedirectUrl + } + if !IsNil(o.InviteRedeemUrl) { + toSerialize["inviteRedeemUrl"] = o.InviteRedeemUrl + } + if !IsNil(o.Status) { + toSerialize["status"] = o.Status + } + if !IsNil(o.InvitedUser) { + toSerialize["invitedUser"] = o.InvitedUser + } + if !IsNil(o.InvitedUserType) { + toSerialize["invitedUserType"] = o.InvitedUserType + } + return toSerialize, nil +} + +type NullableInvitation struct { + value *Invitation + isSet bool +} + +func (v NullableInvitation) Get() *Invitation { + return v.value +} + +func (v *NullableInvitation) Set(val *Invitation) { + v.value = val + v.isSet = true +} + +func (v NullableInvitation) IsSet() bool { + return v.isSet +} + +func (v *NullableInvitation) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInvitation(val *Invitation) *NullableInvitation { + return &NullableInvitation{value: val, isSet: true} +} + +func (v NullableInvitation) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInvitation) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_invited_user_message_info.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_invited_user_message_info.go new file mode 100644 index 0000000000..0b12ce6275 --- /dev/null +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_invited_user_message_info.go @@ -0,0 +1,201 @@ +/* +Libre Graph API + +Libre Graph is a free API for cloud collaboration inspired by the MS Graph API. + +API version: v1.0.8 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package libregraph + +import ( + "encoding/json" +) + +// checks if the InvitedUserMessageInfo type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &InvitedUserMessageInfo{} + +// InvitedUserMessageInfo Additional information about the invitation message. +type InvitedUserMessageInfo struct { + // Additional recipients who will receive a copy of the invitation message. + CcRecipients []Recipient `json:"ccRecipients,omitempty"` + // The customized message body that will be included in the invitation message. + CustomizedMessageBody *string `json:"customizedMessageBody,omitempty"` + // The language of the invitation message. + MessageLanguage *string `json:"messageLanguage,omitempty"` +} + +// NewInvitedUserMessageInfo instantiates a new InvitedUserMessageInfo object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewInvitedUserMessageInfo() *InvitedUserMessageInfo { + this := InvitedUserMessageInfo{} + return &this +} + +// NewInvitedUserMessageInfoWithDefaults instantiates a new InvitedUserMessageInfo object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewInvitedUserMessageInfoWithDefaults() *InvitedUserMessageInfo { + this := InvitedUserMessageInfo{} + return &this +} + +// GetCcRecipients returns the CcRecipients field value if set, zero value otherwise. +func (o *InvitedUserMessageInfo) GetCcRecipients() []Recipient { + if o == nil || IsNil(o.CcRecipients) { + var ret []Recipient + return ret + } + return o.CcRecipients +} + +// GetCcRecipientsOk returns a tuple with the CcRecipients field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InvitedUserMessageInfo) GetCcRecipientsOk() ([]Recipient, bool) { + if o == nil || IsNil(o.CcRecipients) { + return nil, false + } + return o.CcRecipients, true +} + +// HasCcRecipients returns a boolean if a field has been set. +func (o *InvitedUserMessageInfo) HasCcRecipients() bool { + if o != nil && !IsNil(o.CcRecipients) { + return true + } + + return false +} + +// SetCcRecipients gets a reference to the given []Recipient and assigns it to the CcRecipients field. +func (o *InvitedUserMessageInfo) SetCcRecipients(v []Recipient) { + o.CcRecipients = v +} + +// GetCustomizedMessageBody returns the CustomizedMessageBody field value if set, zero value otherwise. +func (o *InvitedUserMessageInfo) GetCustomizedMessageBody() string { + if o == nil || IsNil(o.CustomizedMessageBody) { + var ret string + return ret + } + return *o.CustomizedMessageBody +} + +// GetCustomizedMessageBodyOk returns a tuple with the CustomizedMessageBody field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InvitedUserMessageInfo) GetCustomizedMessageBodyOk() (*string, bool) { + if o == nil || IsNil(o.CustomizedMessageBody) { + return nil, false + } + return o.CustomizedMessageBody, true +} + +// HasCustomizedMessageBody returns a boolean if a field has been set. +func (o *InvitedUserMessageInfo) HasCustomizedMessageBody() bool { + if o != nil && !IsNil(o.CustomizedMessageBody) { + return true + } + + return false +} + +// SetCustomizedMessageBody gets a reference to the given string and assigns it to the CustomizedMessageBody field. +func (o *InvitedUserMessageInfo) SetCustomizedMessageBody(v string) { + o.CustomizedMessageBody = &v +} + +// GetMessageLanguage returns the MessageLanguage field value if set, zero value otherwise. +func (o *InvitedUserMessageInfo) GetMessageLanguage() string { + if o == nil || IsNil(o.MessageLanguage) { + var ret string + return ret + } + return *o.MessageLanguage +} + +// GetMessageLanguageOk returns a tuple with the MessageLanguage field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *InvitedUserMessageInfo) GetMessageLanguageOk() (*string, bool) { + if o == nil || IsNil(o.MessageLanguage) { + return nil, false + } + return o.MessageLanguage, true +} + +// HasMessageLanguage returns a boolean if a field has been set. +func (o *InvitedUserMessageInfo) HasMessageLanguage() bool { + if o != nil && !IsNil(o.MessageLanguage) { + return true + } + + return false +} + +// SetMessageLanguage gets a reference to the given string and assigns it to the MessageLanguage field. +func (o *InvitedUserMessageInfo) SetMessageLanguage(v string) { + o.MessageLanguage = &v +} + +func (o InvitedUserMessageInfo) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o InvitedUserMessageInfo) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.CcRecipients) { + toSerialize["ccRecipients"] = o.CcRecipients + } + if !IsNil(o.CustomizedMessageBody) { + toSerialize["customizedMessageBody"] = o.CustomizedMessageBody + } + if !IsNil(o.MessageLanguage) { + toSerialize["messageLanguage"] = o.MessageLanguage + } + return toSerialize, nil +} + +type NullableInvitedUserMessageInfo struct { + value *InvitedUserMessageInfo + isSet bool +} + +func (v NullableInvitedUserMessageInfo) Get() *InvitedUserMessageInfo { + return v.value +} + +func (v *NullableInvitedUserMessageInfo) Set(val *InvitedUserMessageInfo) { + v.value = val + v.isSet = true +} + +func (v NullableInvitedUserMessageInfo) IsSet() bool { + return v.isSet +} + +func (v *NullableInvitedUserMessageInfo) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableInvitedUserMessageInfo(val *InvitedUserMessageInfo) *NullableInvitedUserMessageInfo { + return &NullableInvitedUserMessageInfo{value: val, isSet: true} +} + +func (v NullableInvitedUserMessageInfo) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableInvitedUserMessageInfo) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_motion_photo.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_motion_photo.go new file mode 100644 index 0000000000..dad6fa38e7 --- /dev/null +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_motion_photo.go @@ -0,0 +1,201 @@ +/* +Libre Graph API + +Libre Graph is a free API for cloud collaboration inspired by the MS Graph API. + +API version: v1.0.8 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package libregraph + +import ( + "encoding/json" +) + +// checks if the MotionPhoto type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &MotionPhoto{} + +// MotionPhoto Motion Photo metadata. A Motion Photo is a still image with a short video clip appended to the end of the file. The presence of this facet on a driveItem indicates that the item is a Motion Photo; absence indicates it is not. Based on the Google Motion Photo format v1.0 specification: https://developer.android.com/media/platform/motion-photo-format +type MotionPhoto struct { + // The file format version of the Motion Photo. Currently always 1. Read-only. + Version *int32 `json:"version,omitempty"` + // Presentation timestamp in microseconds of the video frame that corresponds to the still image. A value of -1 indicates unspecified. If absent, readers should use a timestamp near the middle of the video track. Read-only. + PresentationTimestampUs *int64 `json:"presentationTimestampUs,omitempty"` + // Size in bytes of the embedded video portion of the file. The video is appended at the end of the file, so clients can fetch it with a Range request: `Range: bytes=-`. Read-only. + VideoSize *int64 `json:"videoSize,omitempty"` +} + +// NewMotionPhoto instantiates a new MotionPhoto object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewMotionPhoto() *MotionPhoto { + this := MotionPhoto{} + return &this +} + +// NewMotionPhotoWithDefaults instantiates a new MotionPhoto object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewMotionPhotoWithDefaults() *MotionPhoto { + this := MotionPhoto{} + return &this +} + +// GetVersion returns the Version field value if set, zero value otherwise. +func (o *MotionPhoto) GetVersion() int32 { + if o == nil || IsNil(o.Version) { + var ret int32 + return ret + } + return *o.Version +} + +// GetVersionOk returns a tuple with the Version field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MotionPhoto) GetVersionOk() (*int32, bool) { + if o == nil || IsNil(o.Version) { + return nil, false + } + return o.Version, true +} + +// HasVersion returns a boolean if a field has been set. +func (o *MotionPhoto) HasVersion() bool { + if o != nil && !IsNil(o.Version) { + return true + } + + return false +} + +// SetVersion gets a reference to the given int32 and assigns it to the Version field. +func (o *MotionPhoto) SetVersion(v int32) { + o.Version = &v +} + +// GetPresentationTimestampUs returns the PresentationTimestampUs field value if set, zero value otherwise. +func (o *MotionPhoto) GetPresentationTimestampUs() int64 { + if o == nil || IsNil(o.PresentationTimestampUs) { + var ret int64 + return ret + } + return *o.PresentationTimestampUs +} + +// GetPresentationTimestampUsOk returns a tuple with the PresentationTimestampUs field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MotionPhoto) GetPresentationTimestampUsOk() (*int64, bool) { + if o == nil || IsNil(o.PresentationTimestampUs) { + return nil, false + } + return o.PresentationTimestampUs, true +} + +// HasPresentationTimestampUs returns a boolean if a field has been set. +func (o *MotionPhoto) HasPresentationTimestampUs() bool { + if o != nil && !IsNil(o.PresentationTimestampUs) { + return true + } + + return false +} + +// SetPresentationTimestampUs gets a reference to the given int64 and assigns it to the PresentationTimestampUs field. +func (o *MotionPhoto) SetPresentationTimestampUs(v int64) { + o.PresentationTimestampUs = &v +} + +// GetVideoSize returns the VideoSize field value if set, zero value otherwise. +func (o *MotionPhoto) GetVideoSize() int64 { + if o == nil || IsNil(o.VideoSize) { + var ret int64 + return ret + } + return *o.VideoSize +} + +// GetVideoSizeOk returns a tuple with the VideoSize field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *MotionPhoto) GetVideoSizeOk() (*int64, bool) { + if o == nil || IsNil(o.VideoSize) { + return nil, false + } + return o.VideoSize, true +} + +// HasVideoSize returns a boolean if a field has been set. +func (o *MotionPhoto) HasVideoSize() bool { + if o != nil && !IsNil(o.VideoSize) { + return true + } + + return false +} + +// SetVideoSize gets a reference to the given int64 and assigns it to the VideoSize field. +func (o *MotionPhoto) SetVideoSize(v int64) { + o.VideoSize = &v +} + +func (o MotionPhoto) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o MotionPhoto) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.Version) { + toSerialize["version"] = o.Version + } + if !IsNil(o.PresentationTimestampUs) { + toSerialize["presentationTimestampUs"] = o.PresentationTimestampUs + } + if !IsNil(o.VideoSize) { + toSerialize["videoSize"] = o.VideoSize + } + return toSerialize, nil +} + +type NullableMotionPhoto struct { + value *MotionPhoto + isSet bool +} + +func (v NullableMotionPhoto) Get() *MotionPhoto { + return v.value +} + +func (v *NullableMotionPhoto) Set(val *MotionPhoto) { + v.value = val + v.isSet = true +} + +func (v NullableMotionPhoto) IsSet() bool { + return v.isSet +} + +func (v *NullableMotionPhoto) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableMotionPhoto(val *MotionPhoto) *NullableMotionPhoto { + return &NullableMotionPhoto{value: val, isSet: true} +} + +func (v NullableMotionPhoto) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableMotionPhoto) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/opencloud-eu/libre-graph-api-go/model_recipient.go b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_recipient.go new file mode 100644 index 0000000000..90b22c2dca --- /dev/null +++ b/vendor/github.com/opencloud-eu/libre-graph-api-go/model_recipient.go @@ -0,0 +1,126 @@ +/* +Libre Graph API + +Libre Graph is a free API for cloud collaboration inspired by the MS Graph API. + +API version: v1.0.8 +*/ + +// Code generated by OpenAPI Generator (https://openapi-generator.tech); DO NOT EDIT. + +package libregraph + +import ( + "encoding/json" +) + +// checks if the Recipient type satisfies the MappedNullable interface at compile time +var _ MappedNullable = &Recipient{} + +// Recipient Represents a recipient of an invitation. +type Recipient struct { + EmailAddress *EmailAddress `json:"emailAddress,omitempty"` +} + +// NewRecipient instantiates a new Recipient object +// This constructor will assign default values to properties that have it defined, +// and makes sure properties required by API are set, but the set of arguments +// will change when the set of required properties is changed +func NewRecipient() *Recipient { + this := Recipient{} + return &this +} + +// NewRecipientWithDefaults instantiates a new Recipient object +// This constructor will only assign default values to properties that have it defined, +// but it doesn't guarantee that properties required by API are set +func NewRecipientWithDefaults() *Recipient { + this := Recipient{} + return &this +} + +// GetEmailAddress returns the EmailAddress field value if set, zero value otherwise. +func (o *Recipient) GetEmailAddress() EmailAddress { + if o == nil || IsNil(o.EmailAddress) { + var ret EmailAddress + return ret + } + return *o.EmailAddress +} + +// GetEmailAddressOk returns a tuple with the EmailAddress field value if set, nil otherwise +// and a boolean to check if the value has been set. +func (o *Recipient) GetEmailAddressOk() (*EmailAddress, bool) { + if o == nil || IsNil(o.EmailAddress) { + return nil, false + } + return o.EmailAddress, true +} + +// HasEmailAddress returns a boolean if a field has been set. +func (o *Recipient) HasEmailAddress() bool { + if o != nil && !IsNil(o.EmailAddress) { + return true + } + + return false +} + +// SetEmailAddress gets a reference to the given EmailAddress and assigns it to the EmailAddress field. +func (o *Recipient) SetEmailAddress(v EmailAddress) { + o.EmailAddress = &v +} + +func (o Recipient) MarshalJSON() ([]byte, error) { + toSerialize,err := o.ToMap() + if err != nil { + return []byte{}, err + } + return json.Marshal(toSerialize) +} + +func (o Recipient) ToMap() (map[string]interface{}, error) { + toSerialize := map[string]interface{}{} + if !IsNil(o.EmailAddress) { + toSerialize["emailAddress"] = o.EmailAddress + } + return toSerialize, nil +} + +type NullableRecipient struct { + value *Recipient + isSet bool +} + +func (v NullableRecipient) Get() *Recipient { + return v.value +} + +func (v *NullableRecipient) Set(val *Recipient) { + v.value = val + v.isSet = true +} + +func (v NullableRecipient) IsSet() bool { + return v.isSet +} + +func (v *NullableRecipient) Unset() { + v.value = nil + v.isSet = false +} + +func NewNullableRecipient(val *Recipient) *NullableRecipient { + return &NullableRecipient{value: val, isSet: true} +} + +func (v NullableRecipient) MarshalJSON() ([]byte, error) { + return json.Marshal(v.value) +} + +func (v *NullableRecipient) UnmarshalJSON(src []byte) error { + v.isSet = true + return json.Unmarshal(src, &v.value) +} + + diff --git a/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go b/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go index d86367a2c5..f40f4ec082 100644 --- a/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go +++ b/vendor/github.com/opencloud-eu/reva/v2/internal/http/services/owncloud/ocdav/propfind/propfind.go @@ -107,6 +107,11 @@ var ( "orientation", "takenDateTime", } + motionPhotoKeys = []string{ + "version", + "presentationTimestampUs", + "videoSize", + } ) type countingReader struct { @@ -887,6 +892,8 @@ func metadataKeys(pf XML) ([]string, []string) { metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.image", imageKeys)...) case "http://owncloud.org/ns/photo": metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.photo", photoKeys)...) + case "http://owncloud.org/ns/motionPhoto": + metadataKeys = append(metadataKeys, metadataKeysWithPrefix("libre.graph.motionPhoto", motionPhotoKeys)...) default: metadataKeys = append(metadataKeys, key) } @@ -944,7 +951,7 @@ func requiresExplicitFetching(n *xml.Name) bool { } case net.NsOwncloud: switch n.Local { - case "favorite", "share-types", "checksums", "size", "tags", "audio", "location", "image", "photo": + case "favorite", "share-types", "checksums", "size", "tags", "audio", "location", "image", "photo", "motionPhoto": return true default: return false @@ -1292,6 +1299,7 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p appendMetadataProp(k, "oc", "location", "libre.graph.location", locationKeys) appendMetadataProp(k, "oc", "image", "libre.graph.image", imageKeys) appendMetadataProp(k, "oc", "photo", "libre.graph.photo", photoKeys) + appendMetadataProp(k, "oc", "motionPhoto", "libre.graph.motionPhoto", motionPhotoKeys) } if md.Type == provider.ResourceType_RESOURCE_TYPE_CONTAINER { @@ -1579,6 +1587,10 @@ func mdToPropResponse(ctx context.Context, pf *XML, md *provider.ResourceInfo, p if k := md.GetArbitraryMetadata().GetMetadata(); k != nil { appendMetadataProp(k, "oc", "photo", "libre.graph.photo", photoKeys) } + case "motionPhoto": + if k := md.GetArbitraryMetadata().GetMetadata(); k != nil { + appendMetadataProp(k, "oc", "motionPhoto", "libre.graph.motionPhoto", motionPhotoKeys) + } case "name": appendToOK(prop.Escaped("oc:name", md.Name)) case "shareid": diff --git a/vendor/modules.txt b/vendor/modules.txt index 8f7fb6bde2..1c6f834d18 100644 --- a/vendor/modules.txt +++ b/vendor/modules.txt @@ -1361,7 +1361,7 @@ github.com/open-policy-agent/opa/v1/version # github.com/opencloud-eu/icap-client v0.0.0-20250930132611-28a2afe62d89 ## explicit; go 1.24.6 github.com/opencloud-eu/icap-client -# github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260310090739-853d972b282d +# github.com/opencloud-eu/libre-graph-api-go v1.0.8-0.20260508132157-0223d2e98d28 ## explicit; go 1.18 github.com/opencloud-eu/libre-graph-api-go # github.com/opencloud-eu/reva/v2 v2.46.4-0.20260625152426-8cff2a7032ec