Merge pull request #7886 from owncloud/add-location-facet

Location Metadata
This commit is contained in:
kobergj
2023-12-06 15:47:23 +01:00
committed by GitHub
15 changed files with 492 additions and 142 deletions

View File

@@ -0,0 +1,6 @@
Enhancement: Store and index metadata
location metadata is now extracted and stored by the search service.
It is available for driveItems in a folder listing using the Graph API.
https://github.com/owncloud/ocis/pull/7886

View File

@@ -306,6 +306,69 @@ func (x *Audio) GetYear() int32 {
return 0
}
type GeoCoordinates struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Altitude *float64 `protobuf:"fixed64,1,opt,name=altitude,proto3,oneof" json:"altitude,omitempty"`
Latitude *float64 `protobuf:"fixed64,2,opt,name=latitude,proto3,oneof" json:"latitude,omitempty"`
Longitude *float64 `protobuf:"fixed64,3,opt,name=longitude,proto3,oneof" json:"longitude,omitempty"`
}
func (x *GeoCoordinates) Reset() {
*x = GeoCoordinates{}
if protoimpl.UnsafeEnabled {
mi := &file_ocis_messages_search_v0_search_proto_msgTypes[3]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
}
func (x *GeoCoordinates) String() string {
return protoimpl.X.MessageStringOf(x)
}
func (*GeoCoordinates) ProtoMessage() {}
func (x *GeoCoordinates) ProtoReflect() protoreflect.Message {
mi := &file_ocis_messages_search_v0_search_proto_msgTypes[3]
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 GeoCoordinates.ProtoReflect.Descriptor instead.
func (*GeoCoordinates) Descriptor() ([]byte, []int) {
return file_ocis_messages_search_v0_search_proto_rawDescGZIP(), []int{3}
}
func (x *GeoCoordinates) GetAltitude() float64 {
if x != nil && x.Altitude != nil {
return *x.Altitude
}
return 0
}
func (x *GeoCoordinates) GetLatitude() float64 {
if x != nil && x.Latitude != nil {
return *x.Latitude
}
return 0
}
func (x *GeoCoordinates) GetLongitude() float64 {
if x != nil && x.Longitude != nil {
return *x.Longitude
}
return 0
}
type Entity struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -326,12 +389,13 @@ type Entity struct {
Tags []string `protobuf:"bytes,13,rep,name=tags,proto3" json:"tags,omitempty"`
Highlights string `protobuf:"bytes,14,opt,name=highlights,proto3" json:"highlights,omitempty"`
Audio *Audio `protobuf:"bytes,15,opt,name=audio,proto3" json:"audio,omitempty"`
Location *GeoCoordinates `protobuf:"bytes,16,opt,name=location,proto3" json:"location,omitempty"`
}
func (x *Entity) Reset() {
*x = Entity{}
if protoimpl.UnsafeEnabled {
mi := &file_ocis_messages_search_v0_search_proto_msgTypes[3]
mi := &file_ocis_messages_search_v0_search_proto_msgTypes[4]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -344,7 +408,7 @@ func (x *Entity) String() string {
func (*Entity) ProtoMessage() {}
func (x *Entity) ProtoReflect() protoreflect.Message {
mi := &file_ocis_messages_search_v0_search_proto_msgTypes[3]
mi := &file_ocis_messages_search_v0_search_proto_msgTypes[4]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -357,7 +421,7 @@ func (x *Entity) ProtoReflect() protoreflect.Message {
// Deprecated: Use Entity.ProtoReflect.Descriptor instead.
func (*Entity) Descriptor() ([]byte, []int) {
return file_ocis_messages_search_v0_search_proto_rawDescGZIP(), []int{3}
return file_ocis_messages_search_v0_search_proto_rawDescGZIP(), []int{4}
}
func (x *Entity) GetRef() *Reference {
@@ -465,6 +529,13 @@ func (x *Entity) GetAudio() *Audio {
return nil
}
func (x *Entity) GetLocation() *GeoCoordinates {
if x != nil {
return x.Location
}
return nil
}
type Match struct {
state protoimpl.MessageState
sizeCache protoimpl.SizeCache
@@ -479,7 +550,7 @@ type Match struct {
func (x *Match) Reset() {
*x = Match{}
if protoimpl.UnsafeEnabled {
mi := &file_ocis_messages_search_v0_search_proto_msgTypes[4]
mi := &file_ocis_messages_search_v0_search_proto_msgTypes[5]
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
ms.StoreMessageInfo(mi)
}
@@ -492,7 +563,7 @@ func (x *Match) String() string {
func (*Match) ProtoMessage() {}
func (x *Match) ProtoReflect() protoreflect.Message {
mi := &file_ocis_messages_search_v0_search_proto_msgTypes[4]
mi := &file_ocis_messages_search_v0_search_proto_msgTypes[5]
if protoimpl.UnsafeEnabled && x != nil {
ms := protoimpl.X.MessageStateOf(protoimpl.Pointer(x))
if ms.LoadMessageInfo() == nil {
@@ -505,7 +576,7 @@ func (x *Match) ProtoReflect() protoreflect.Message {
// Deprecated: Use Match.ProtoReflect.Descriptor instead.
func (*Match) Descriptor() ([]byte, []int) {
return file_ocis_messages_search_v0_search_proto_rawDescGZIP(), []int{4}
return file_ocis_messages_search_v0_search_proto_rawDescGZIP(), []int{5}
}
func (x *Match) GetEntity() *Entity {
@@ -588,7 +659,17 @@ var file_ocis_messages_search_v0_search_proto_rawDesc = []byte{
0x5f, 0x69, 0x73, 0x56, 0x61, 0x72, 0x69, 0x61, 0x62, 0x6c, 0x65, 0x42, 0x69, 0x74, 0x72, 0x61,
0x74, 0x65, 0x42, 0x08, 0x0a, 0x06, 0x5f, 0x74, 0x69, 0x74, 0x6c, 0x65, 0x42, 0x08, 0x0a, 0x06,
0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b, 0x42, 0x0d, 0x0a, 0x0b, 0x5f, 0x74, 0x72, 0x61, 0x63, 0x6b,
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x79, 0x65, 0x61, 0x72, 0x22, 0xb8,
0x43, 0x6f, 0x75, 0x6e, 0x74, 0x42, 0x07, 0x0a, 0x05, 0x5f, 0x79, 0x65, 0x61, 0x72, 0x22, 0x9d,
0x01, 0x0a, 0x0e, 0x47, 0x65, 0x6f, 0x43, 0x6f, 0x6f, 0x72, 0x64, 0x69, 0x6e, 0x61, 0x74, 0x65,
0x73, 0x12, 0x1f, 0x0a, 0x08, 0x61, 0x6c, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x01, 0x20,
0x01, 0x28, 0x01, 0x48, 0x00, 0x52, 0x08, 0x61, 0x6c, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x88,
0x01, 0x01, 0x12, 0x1f, 0x0a, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65, 0x18, 0x02,
0x20, 0x01, 0x28, 0x01, 0x48, 0x01, 0x52, 0x08, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65,
0x88, 0x01, 0x01, 0x12, 0x21, 0x0a, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65,
0x18, 0x03, 0x20, 0x01, 0x28, 0x01, 0x48, 0x02, 0x52, 0x09, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74,
0x75, 0x64, 0x65, 0x88, 0x01, 0x01, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x61, 0x6c, 0x74, 0x69, 0x74,
0x75, 0x64, 0x65, 0x42, 0x0b, 0x0a, 0x09, 0x5f, 0x6c, 0x61, 0x74, 0x69, 0x74, 0x75, 0x64, 0x65,
0x42, 0x0c, 0x0a, 0x0a, 0x5f, 0x6c, 0x6f, 0x6e, 0x67, 0x69, 0x74, 0x75, 0x64, 0x65, 0x22, 0xfd,
0x04, 0x0a, 0x06, 0x45, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x12, 0x34, 0x0a, 0x03, 0x72, 0x65, 0x66,
0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x22, 0x2e, 0x6f, 0x63, 0x69, 0x73, 0x2e, 0x6d, 0x65,
0x73, 0x73, 0x61, 0x67, 0x65, 0x73, 0x2e, 0x73, 0x65, 0x61, 0x72, 0x63, 0x68, 0x2e, 0x76, 0x30,
@@ -624,17 +705,22 @@ var file_ocis_messages_search_v0_search_proto_rawDesc = []byte{
0x68, 0x74, 0x73, 0x12, 0x34, 0x0a, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x18, 0x0f, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1e, 0x2e, 0x6f, 0x63, 0x69, 0x73, 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, 0x22, 0x56, 0x0a, 0x05, 0x4d, 0x61, 0x74,
0x63, 0x68, 0x12, 0x37, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74, 0x79, 0x18, 0x01, 0x20, 0x01,
0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f, 0x63, 0x69, 0x73, 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, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62, 0x2e, 0x63, 0x6f, 0x6d, 0x2f,
0x6f, 0x77, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6f, 0x63, 0x69, 0x73, 0x2f, 0x76, 0x32,
0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x6e, 0x2f, 0x67, 0x65, 0x6e, 0x2f, 0x6f, 0x63,
0x69, 0x73, 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,
0x69, 0x6f, 0x52, 0x05, 0x61, 0x75, 0x64, 0x69, 0x6f, 0x12, 0x43, 0x0a, 0x08, 0x6c, 0x6f, 0x63,
0x61, 0x74, 0x69, 0x6f, 0x6e, 0x18, 0x10, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x27, 0x2e, 0x6f, 0x63,
0x69, 0x73, 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, 0x22, 0x56,
0x0a, 0x05, 0x4d, 0x61, 0x74, 0x63, 0x68, 0x12, 0x37, 0x0a, 0x06, 0x65, 0x6e, 0x74, 0x69, 0x74,
0x79, 0x18, 0x01, 0x20, 0x01, 0x28, 0x0b, 0x32, 0x1f, 0x2e, 0x6f, 0x63, 0x69, 0x73, 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, 0x42, 0x5a, 0x40, 0x67, 0x69, 0x74, 0x68, 0x75, 0x62,
0x2e, 0x63, 0x6f, 0x6d, 0x2f, 0x6f, 0x77, 0x6e, 0x63, 0x6c, 0x6f, 0x75, 0x64, 0x2f, 0x6f, 0x63,
0x69, 0x73, 0x2f, 0x76, 0x32, 0x2f, 0x70, 0x72, 0x6f, 0x74, 0x6f, 0x67, 0x65, 0x6e, 0x2f, 0x67,
0x65, 0x6e, 0x2f, 0x6f, 0x63, 0x69, 0x73, 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 (
@@ -649,28 +735,30 @@ func file_ocis_messages_search_v0_search_proto_rawDescGZIP() []byte {
return file_ocis_messages_search_v0_search_proto_rawDescData
}
var file_ocis_messages_search_v0_search_proto_msgTypes = make([]protoimpl.MessageInfo, 5)
var file_ocis_messages_search_v0_search_proto_msgTypes = make([]protoimpl.MessageInfo, 6)
var file_ocis_messages_search_v0_search_proto_goTypes = []interface{}{
(*ResourceID)(nil), // 0: ocis.messages.search.v0.ResourceID
(*Reference)(nil), // 1: ocis.messages.search.v0.Reference
(*Audio)(nil), // 2: ocis.messages.search.v0.Audio
(*Entity)(nil), // 3: ocis.messages.search.v0.Entity
(*Match)(nil), // 4: ocis.messages.search.v0.Match
(*timestamppb.Timestamp)(nil), // 5: google.protobuf.Timestamp
(*GeoCoordinates)(nil), // 3: ocis.messages.search.v0.GeoCoordinates
(*Entity)(nil), // 4: ocis.messages.search.v0.Entity
(*Match)(nil), // 5: ocis.messages.search.v0.Match
(*timestamppb.Timestamp)(nil), // 6: google.protobuf.Timestamp
}
var file_ocis_messages_search_v0_search_proto_depIdxs = []int32{
0, // 0: ocis.messages.search.v0.Reference.resource_id:type_name -> ocis.messages.search.v0.ResourceID
1, // 1: ocis.messages.search.v0.Entity.ref:type_name -> ocis.messages.search.v0.Reference
0, // 2: ocis.messages.search.v0.Entity.id:type_name -> ocis.messages.search.v0.ResourceID
5, // 3: ocis.messages.search.v0.Entity.last_modified_time:type_name -> google.protobuf.Timestamp
6, // 3: ocis.messages.search.v0.Entity.last_modified_time:type_name -> google.protobuf.Timestamp
0, // 4: ocis.messages.search.v0.Entity.parent_id:type_name -> ocis.messages.search.v0.ResourceID
2, // 5: ocis.messages.search.v0.Entity.audio:type_name -> ocis.messages.search.v0.Audio
3, // 6: ocis.messages.search.v0.Match.entity:type_name -> ocis.messages.search.v0.Entity
7, // [7:7] is the sub-list for method output_type
7, // [7:7] is the sub-list for method input_type
7, // [7:7] is the sub-list for extension type_name
7, // [7:7] is the sub-list for extension extendee
0, // [0:7] is the sub-list for field type_name
3, // 6: ocis.messages.search.v0.Entity.location:type_name -> ocis.messages.search.v0.GeoCoordinates
4, // 7: ocis.messages.search.v0.Match.entity:type_name -> ocis.messages.search.v0.Entity
8, // [8:8] is the sub-list for method output_type
8, // [8:8] is the sub-list for method input_type
8, // [8:8] is the sub-list for extension type_name
8, // [8:8] is the sub-list for extension extendee
0, // [0:8] is the sub-list for field type_name
}
func init() { file_ocis_messages_search_v0_search_proto_init() }
@@ -716,7 +804,7 @@ func file_ocis_messages_search_v0_search_proto_init() {
}
}
file_ocis_messages_search_v0_search_proto_msgTypes[3].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Entity); i {
switch v := v.(*GeoCoordinates); i {
case 0:
return &v.state
case 1:
@@ -728,6 +816,18 @@ func file_ocis_messages_search_v0_search_proto_init() {
}
}
file_ocis_messages_search_v0_search_proto_msgTypes[4].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_ocis_messages_search_v0_search_proto_msgTypes[5].Exporter = func(v interface{}, i int) interface{} {
switch v := v.(*Match); i {
case 0:
return &v.state
@@ -741,13 +841,14 @@ func file_ocis_messages_search_v0_search_proto_init() {
}
}
file_ocis_messages_search_v0_search_proto_msgTypes[2].OneofWrappers = []interface{}{}
file_ocis_messages_search_v0_search_proto_msgTypes[3].OneofWrappers = []interface{}{}
type x struct{}
out := protoimpl.TypeBuilder{
File: protoimpl.DescBuilder{
GoPackagePath: reflect.TypeOf(x{}).PkgPath(),
RawDescriptor: file_ocis_messages_search_v0_search_proto_rawDesc,
NumEnums: 0,
NumMessages: 5,
NumMessages: 6,
NumExtensions: 0,
NumServices: 0,
},

View File

@@ -118,6 +118,42 @@ func (m *Audio) UnmarshalJSON(b []byte) error {
var _ json.Unmarshaler = (*Audio)(nil)
// GeoCoordinatesJSONMarshaler describes the default jsonpb.Marshaler used by all
// instances of GeoCoordinates. This struct is safe to replace or modify but
// should not be done so concurrently.
var GeoCoordinatesJSONMarshaler = 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 *GeoCoordinates) MarshalJSON() ([]byte, error) {
if m == nil {
return json.Marshal(nil)
}
buf := &bytes.Buffer{}
if err := GeoCoordinatesJSONMarshaler.Marshal(buf, m); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
var _ json.Marshaler = (*GeoCoordinates)(nil)
// GeoCoordinatesJSONUnmarshaler describes the default jsonpb.Unmarshaler used by all
// instances of GeoCoordinates. This struct is safe to replace or modify but
// should not be done so concurrently.
var GeoCoordinatesJSONUnmarshaler = 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 *GeoCoordinates) UnmarshalJSON(b []byte) error {
return GeoCoordinatesJSONUnmarshaler.Unmarshal(bytes.NewReader(b), m)
}
var _ json.Unmarshaler = (*GeoCoordinates)(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.

View File

@@ -489,13 +489,13 @@ type Bundle struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // @gotags: yaml:"id"
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // @gotags: yaml:"name"
Type Bundle_Type `protobuf:"varint,3,opt,name=type,proto3,enum=ocis.messages.settings.v0.Bundle_Type" json:"type,omitempty"` // @gotags: yaml:"type"
Extension string `protobuf:"bytes,4,opt,name=extension,proto3" json:"extension,omitempty"` // @gotags: yaml:"extension"
DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` // @gotags: yaml:"display_name"
Settings []*Setting `protobuf:"bytes,6,rep,name=settings,proto3" json:"settings,omitempty"` // @gotags: yaml:"settings"
Resource *Resource `protobuf:"bytes,7,opt,name=resource,proto3" json:"resource,omitempty"` // @gotags: yaml:"resource"
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"` // @gotags: yaml:"id"
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` // @gotags: yaml:"name"
Type Bundle_Type `protobuf:"varint,3,opt,name=type,proto3,enum=ocis.messages.settings.v0.Bundle_Type" json:"type,omitempty" yaml:"type"` // @gotags: yaml:"type"
Extension string `protobuf:"bytes,4,opt,name=extension,proto3" json:"extension,omitempty" yaml:"extension"` // @gotags: yaml:"extension"
DisplayName string `protobuf:"bytes,5,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty" yaml:"display_name"` // @gotags: yaml:"display_name"
Settings []*Setting `protobuf:"bytes,6,rep,name=settings,proto3" json:"settings,omitempty" yaml:"settings"` // @gotags: yaml:"settings"
Resource *Resource `protobuf:"bytes,7,opt,name=resource,proto3" json:"resource,omitempty" yaml:"resource"` // @gotags: yaml:"resource"
}
func (x *Bundle) Reset() {
@@ -584,10 +584,10 @@ type Setting struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // @gotags: yaml:"id"
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty"` // @gotags: yaml:"name"
DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty"` // @gotags: yaml:"display_name"
Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty"` // @gotags: yaml:"description"
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"` // @gotags: yaml:"id"
Name string `protobuf:"bytes,2,opt,name=name,proto3" json:"name,omitempty" yaml:"name"` // @gotags: yaml:"name"
DisplayName string `protobuf:"bytes,3,opt,name=display_name,json=displayName,proto3" json:"display_name,omitempty" yaml:"display_name"` // @gotags: yaml:"display_name"
Description string `protobuf:"bytes,4,opt,name=description,proto3" json:"description,omitempty" yaml:"description"` // @gotags: yaml:"description"
// Types that are assignable to Value:
//
// *Setting_IntValue
@@ -597,7 +597,7 @@ type Setting struct {
// *Setting_MultiChoiceValue
// *Setting_PermissionValue
Value isSetting_Value `protobuf_oneof:"value"`
Resource *Resource `protobuf:"bytes,11,opt,name=resource,proto3" json:"resource,omitempty"` // @gotags: yaml:"resource"
Resource *Resource `protobuf:"bytes,11,opt,name=resource,proto3" json:"resource,omitempty" yaml:"resource"` // @gotags: yaml:"resource"
}
func (x *Setting) Reset() {
@@ -721,27 +721,27 @@ type isSetting_Value interface {
}
type Setting_IntValue struct {
IntValue *Int `protobuf:"bytes,5,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
IntValue *Int `protobuf:"bytes,5,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
}
type Setting_StringValue struct {
StringValue *String `protobuf:"bytes,6,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
StringValue *String `protobuf:"bytes,6,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
}
type Setting_BoolValue struct {
BoolValue *Bool `protobuf:"bytes,7,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
BoolValue *Bool `protobuf:"bytes,7,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
}
type Setting_SingleChoiceValue struct {
SingleChoiceValue *SingleChoiceList `protobuf:"bytes,8,opt,name=single_choice_value,json=singleChoiceValue,proto3,oneof"` // @gotags: yaml:"single_choice_value"
SingleChoiceValue *SingleChoiceList `protobuf:"bytes,8,opt,name=single_choice_value,json=singleChoiceValue,proto3,oneof" yaml:"single_choice_value"` // @gotags: yaml:"single_choice_value"
}
type Setting_MultiChoiceValue struct {
MultiChoiceValue *MultiChoiceList `protobuf:"bytes,9,opt,name=multi_choice_value,json=multiChoiceValue,proto3,oneof"` // @gotags: yaml:"multi_choice_value"
MultiChoiceValue *MultiChoiceList `protobuf:"bytes,9,opt,name=multi_choice_value,json=multiChoiceValue,proto3,oneof" yaml:"multi_choice_value"` // @gotags: yaml:"multi_choice_value"
}
type Setting_PermissionValue struct {
PermissionValue *Permission `protobuf:"bytes,10,opt,name=permission_value,json=permissionValue,proto3,oneof"` // @gotags: yaml:"permission_value"
PermissionValue *Permission `protobuf:"bytes,10,opt,name=permission_value,json=permissionValue,proto3,oneof" yaml:"permission_value"` // @gotags: yaml:"permission_value"
}
func (*Setting_IntValue) isSetting_Value() {}
@@ -761,11 +761,11 @@ type Int struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Default int64 `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty"` // @gotags: yaml:"default"
Min int64 `protobuf:"varint,2,opt,name=min,proto3" json:"min,omitempty"` // @gotags: yaml:"min"
Max int64 `protobuf:"varint,3,opt,name=max,proto3" json:"max,omitempty"` // @gotags: yaml:"max"
Step int64 `protobuf:"varint,4,opt,name=step,proto3" json:"step,omitempty"` // @gotags: yaml:"step"
Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty"` // @gotags: yaml:"placeholder"
Default int64 `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty" yaml:"default"` // @gotags: yaml:"default"
Min int64 `protobuf:"varint,2,opt,name=min,proto3" json:"min,omitempty" yaml:"min"` // @gotags: yaml:"min"
Max int64 `protobuf:"varint,3,opt,name=max,proto3" json:"max,omitempty" yaml:"max"` // @gotags: yaml:"max"
Step int64 `protobuf:"varint,4,opt,name=step,proto3" json:"step,omitempty" yaml:"step"` // @gotags: yaml:"step"
Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty" yaml:"placeholder"` // @gotags: yaml:"placeholder"
}
func (x *Int) Reset() {
@@ -840,11 +840,11 @@ type String struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Default string `protobuf:"bytes,1,opt,name=default,proto3" json:"default,omitempty"` // @gotags: yaml:"default"
Required bool `protobuf:"varint,2,opt,name=required,proto3" json:"required,omitempty"` // @gotags: yaml:"required"
MinLength int32 `protobuf:"varint,3,opt,name=min_length,json=minLength,proto3" json:"min_length,omitempty"` // @gotags: yaml:"min_length"
MaxLength int32 `protobuf:"varint,4,opt,name=max_length,json=maxLength,proto3" json:"max_length,omitempty"` // @gotags: yaml:"max_length"
Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty"` // @gotags: yaml:"placeholder"
Default string `protobuf:"bytes,1,opt,name=default,proto3" json:"default,omitempty" yaml:"default"` // @gotags: yaml:"default"
Required bool `protobuf:"varint,2,opt,name=required,proto3" json:"required,omitempty" yaml:"required"` // @gotags: yaml:"required"
MinLength int32 `protobuf:"varint,3,opt,name=min_length,json=minLength,proto3" json:"min_length,omitempty" yaml:"min_length"` // @gotags: yaml:"min_length"
MaxLength int32 `protobuf:"varint,4,opt,name=max_length,json=maxLength,proto3" json:"max_length,omitempty" yaml:"max_length"` // @gotags: yaml:"max_length"
Placeholder string `protobuf:"bytes,5,opt,name=placeholder,proto3" json:"placeholder,omitempty" yaml:"placeholder"` // @gotags: yaml:"placeholder"
}
func (x *String) Reset() {
@@ -919,8 +919,8 @@ type Bool struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Default bool `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty"` // @gotags: yaml:"default"
Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty"` // @gotags: yaml:"label"
Default bool `protobuf:"varint,1,opt,name=default,proto3" json:"default,omitempty" yaml:"default"` // @gotags: yaml:"default"
Label string `protobuf:"bytes,2,opt,name=label,proto3" json:"label,omitempty" yaml:"label"` // @gotags: yaml:"label"
}
func (x *Bool) Reset() {
@@ -974,7 +974,7 @@ type SingleChoiceList struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` // @gotags: yaml:"options"
Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty" yaml:"options"` // @gotags: yaml:"options"
}
func (x *SingleChoiceList) Reset() {
@@ -1021,7 +1021,7 @@ type MultiChoiceList struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty"` // @gotags: yaml:"options"
Options []*ListOption `protobuf:"bytes,1,rep,name=options,proto3" json:"options,omitempty" yaml:"options"` // @gotags: yaml:"options"
}
func (x *MultiChoiceList) Reset() {
@@ -1068,9 +1068,9 @@ type ListOption struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Value *ListOptionValue `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty"` // @gotags: yaml:"value"
Default bool `protobuf:"varint,2,opt,name=default,proto3" json:"default,omitempty"` // @gotags: yaml:"default"
DisplayValue string `protobuf:"bytes,3,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty"` // @gotags: yaml:"display_value"
Value *ListOptionValue `protobuf:"bytes,1,opt,name=value,proto3" json:"value,omitempty" yaml:"value"` // @gotags: yaml:"value"
Default bool `protobuf:"varint,2,opt,name=default,proto3" json:"default,omitempty" yaml:"default"` // @gotags: yaml:"default"
DisplayValue string `protobuf:"bytes,3,opt,name=display_value,json=displayValue,proto3" json:"display_value,omitempty" yaml:"display_value"` // @gotags: yaml:"display_value"
}
func (x *ListOption) Reset() {
@@ -1131,8 +1131,8 @@ type Permission struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Operation Permission_Operation `protobuf:"varint,1,opt,name=operation,proto3,enum=ocis.messages.settings.v0.Permission_Operation" json:"operation,omitempty"` // @gotags: yaml:"operation"
Constraint Permission_Constraint `protobuf:"varint,2,opt,name=constraint,proto3,enum=ocis.messages.settings.v0.Permission_Constraint" json:"constraint,omitempty"` // @gotags: yaml:"constraint"
Operation Permission_Operation `protobuf:"varint,1,opt,name=operation,proto3,enum=ocis.messages.settings.v0.Permission_Operation" json:"operation,omitempty" yaml:"operation"` // @gotags: yaml:"operation"
Constraint Permission_Constraint `protobuf:"varint,2,opt,name=constraint,proto3,enum=ocis.messages.settings.v0.Permission_Constraint" json:"constraint,omitempty" yaml:"constraint"` // @gotags: yaml:"constraint"
}
func (x *Permission) Reset() {
@@ -1187,12 +1187,12 @@ type Value struct {
unknownFields protoimpl.UnknownFields
// id is the id of the Value. It is generated on saving it.
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"` // @gotags: yaml:"id"
BundleId string `protobuf:"bytes,2,opt,name=bundle_id,json=bundleId,proto3" json:"bundle_id,omitempty"` // @gotags: yaml:"bundle_id"
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty" yaml:"id"` // @gotags: yaml:"id"
BundleId string `protobuf:"bytes,2,opt,name=bundle_id,json=bundleId,proto3" json:"bundle_id,omitempty" yaml:"bundle_id"` // @gotags: yaml:"bundle_id"
// setting_id is the id of the setting from within its bundle.
SettingId string `protobuf:"bytes,3,opt,name=setting_id,json=settingId,proto3" json:"setting_id,omitempty"` // @gotags: yaml:"setting_id"
AccountUuid string `protobuf:"bytes,4,opt,name=account_uuid,json=accountUuid,proto3" json:"account_uuid,omitempty"` // @gotags: yaml:"account_uuid"
Resource *Resource `protobuf:"bytes,5,opt,name=resource,proto3" json:"resource,omitempty"` // @gotags: yaml:"resource"
SettingId string `protobuf:"bytes,3,opt,name=setting_id,json=settingId,proto3" json:"setting_id,omitempty" yaml:"setting_id"` // @gotags: yaml:"setting_id"
AccountUuid string `protobuf:"bytes,4,opt,name=account_uuid,json=accountUuid,proto3" json:"account_uuid,omitempty" yaml:"account_uuid"` // @gotags: yaml:"account_uuid"
Resource *Resource `protobuf:"bytes,5,opt,name=resource,proto3" json:"resource,omitempty" yaml:"resource"` // @gotags: yaml:"resource"
// Types that are assignable to Value:
//
// *Value_BoolValue
@@ -1309,19 +1309,19 @@ type isValue_Value interface {
}
type Value_BoolValue struct {
BoolValue bool `protobuf:"varint,6,opt,name=bool_value,json=boolValue,proto3,oneof"` // @gotags: yaml:"bool_value"
BoolValue bool `protobuf:"varint,6,opt,name=bool_value,json=boolValue,proto3,oneof" yaml:"bool_value"` // @gotags: yaml:"bool_value"
}
type Value_IntValue struct {
IntValue int64 `protobuf:"varint,7,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
IntValue int64 `protobuf:"varint,7,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
}
type Value_StringValue struct {
StringValue string `protobuf:"bytes,8,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
StringValue string `protobuf:"bytes,8,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
}
type Value_ListValue struct {
ListValue *ListValue `protobuf:"bytes,9,opt,name=list_value,json=listValue,proto3,oneof"` // @gotags: yaml:"list_value"
ListValue *ListValue `protobuf:"bytes,9,opt,name=list_value,json=listValue,proto3,oneof" yaml:"list_value"` // @gotags: yaml:"list_value"
}
func (*Value_BoolValue) isValue_Value() {}
@@ -1337,7 +1337,7 @@ type ListValue struct {
sizeCache protoimpl.SizeCache
unknownFields protoimpl.UnknownFields
Values []*ListOptionValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty"` // @gotags: yaml:"values"
Values []*ListOptionValue `protobuf:"bytes,1,rep,name=values,proto3" json:"values,omitempty" yaml:"values"` // @gotags: yaml:"values"
}
func (x *ListValue) Reset() {
@@ -1449,11 +1449,11 @@ type isListOptionValue_Option interface {
}
type ListOptionValue_StringValue struct {
StringValue string `protobuf:"bytes,1,opt,name=string_value,json=stringValue,proto3,oneof"` // @gotags: yaml:"string_value"
StringValue string `protobuf:"bytes,1,opt,name=string_value,json=stringValue,proto3,oneof" yaml:"string_value"` // @gotags: yaml:"string_value"
}
type ListOptionValue_IntValue struct {
IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof"` // @gotags: yaml:"int_value"
IntValue int64 `protobuf:"varint,2,opt,name=int_value,json=intValue,proto3,oneof" yaml:"int_value"` // @gotags: yaml:"int_value"
}
func (*ListOptionValue_StringValue) isListOptionValue_Option() {}

View File

@@ -270,6 +270,26 @@
},
"audio": {
"$ref": "#/definitions/v0Audio"
},
"location": {
"$ref": "#/definitions/v0GeoCoordinates"
}
}
},
"v0GeoCoordinates": {
"type": "object",
"properties": {
"altitude": {
"type": "number",
"format": "double"
},
"latitude": {
"type": "number",
"format": "double"
},
"longitude": {
"type": "number",
"format": "double"
}
}
},

View File

@@ -36,7 +36,7 @@ type GetThumbnailRequest struct {
Width int32 `protobuf:"varint,3,opt,name=width,proto3" json:"width,omitempty"`
// The height of the thumbnail
Height int32 `protobuf:"varint,4,opt,name=height,proto3" json:"height,omitempty"`
// Indicates which processor should be used
// Indicates which image processor to use
Processor string `protobuf:"bytes,5,opt,name=processor,proto3" json:"processor,omitempty"`
// Types that are assignable to Source:
//

View File

@@ -36,6 +36,12 @@ message Audio {
optional int32 year = 16;
}
message GeoCoordinates {
optional double altitude = 1;
optional double latitude = 2;
optional double longitude = 3;
}
message Entity {
Reference ref = 1;
ResourceID id = 2;
@@ -52,6 +58,7 @@ message Entity {
repeated string tags = 13;
string highlights = 14;
Audio audio = 15;
GeoCoordinates location = 16;
}
message Match {

View File

@@ -870,7 +870,10 @@ func cs3ResourceToDriveItem(logger *log.Logger, res *storageprovider.ResourceInf
driveItem.Folder = &libregraph.Folder{}
}
driveItem.Audio = cs3ResourceToDriveItemAudioFacet(logger, res)
if res.ArbitraryMetadata != nil {
driveItem.Audio = cs3ResourceToDriveItemAudioFacet(logger, res)
driveItem.Location = cs3ResourceToDriveItemLocationFacet(logger, res)
}
return driveItem, nil
}
@@ -893,6 +896,20 @@ func cs3ResourceToDriveItemAudioFacet(logger *log.Logger, res *storageprovider.R
return nil
}
func cs3ResourceToDriveItemLocationFacet(logger *log.Logger, res *storageprovider.ResourceInfo) *libregraph.GeoCoordinates {
k := res.ArbitraryMetadata.Metadata
if k == nil {
return nil
}
var location = &libregraph.GeoCoordinates{}
if ok := unmarshalStringMap(logger, location, k, "libre.graph.location."); ok {
return location
}
return nil
}
func getFieldName(structField reflect.StructField) string {
tag := structField.Tag.Get("json")
if tag == "" {
@@ -922,6 +939,10 @@ func unmarshalStringMap(logger *log.Logger, out any, flatMap map[string]string,
tmp, err = strconv.ParseInt(value, 10, 32)
case reflect.Int64:
tmp, err = strconv.ParseInt(value, 10, 64)
case reflect.Float32:
tmp, err = strconv.ParseFloat(value, 32)
case reflect.Float64:
tmp, err = strconv.ParseFloat(value, 64)
case reflect.Bool:
tmp, err = strconv.ParseBool(value)
default:

View File

@@ -759,6 +759,7 @@ var _ = Describe("Driveitems", func() {
res := assertItemsList(1)
Expect(res.Value[0].Audio).To(BeNil())
Expect(res.Value[0].Location).To(BeNil())
})
It("returns the audio facet if metadata is available", func() {
@@ -816,6 +817,36 @@ var _ = Describe("Driveitems", func() {
Expect(audio.TrackCount).To(Equal(libregraph.PtrInt32(9)))
Expect(audio.Year).To(Equal(libregraph.PtrInt32(1994)))
})
It("returns the location facet if metadata is available", func() {
gatewayClient.On("ListContainer", mock.Anything, mock.Anything).Return(&provider.ListContainerResponse{
Status: status.NewOK(ctx),
Infos: []*provider.ResourceInfo{
{
Type: provider.ResourceType_RESOURCE_TYPE_FILE,
Id: &provider.ResourceId{StorageId: "storageid", SpaceId: "spaceid", OpaqueId: "opaqueid"},
Etag: "etag",
Mtime: utils.TimeToTS(mtime),
MimeType: "image/jpeg",
ArbitraryMetadata: &provider.ArbitraryMetadata{
Metadata: map[string]string{
"libre.graph.location.altitude": "1047.7",
"libre.graph.location.latitude": "49.48675890884328",
"libre.graph.location.longitude": "11.103870357204285",
},
},
},
},
}, nil)
res := assertItemsList(1)
location := res.Value[0].Location
Expect(location).ToNot(BeNil())
Expect(location.Altitude).To(Equal(libregraph.PtrFloat64(1047.7)))
Expect(location.Latitude).To(Equal(libregraph.PtrFloat64(49.48675890884328)))
Expect(location.Longitude).To(Equal(libregraph.PtrFloat64(11.103870357204285)))
})
})
})
})

View File

@@ -21,7 +21,8 @@ type Document struct {
Mtime string
MimeType string
Tags []string
Audio *libregraph.Audio `json:"audio,omitempty"`
Audio *libregraph.Audio `json:"audio,omitempty"`
Location *libregraph.GeoCoordinates `json:"location,omitempty"`
}
func CleanString(content, langCode string) string {

View File

@@ -89,66 +89,10 @@ func (t Tika) Extract(ctx context.Context, ri *provider.ResourceInfo) (Document,
doc.Content = strings.TrimSpace(fmt.Sprintf("%s %s", doc.Content, content))
}
doc.Location = t.getLocation(meta)
if contentType, err := getFirstValue(meta, "Content-Type"); err == nil && strings.HasPrefix(contentType, "audio/") {
audio := libregraph.Audio{}
if v, err := getFirstValue(meta, "xmpDM:album"); err == nil {
audio.SetAlbum(v)
}
if v, err := getFirstValue(meta, "xmpDM:albumArtist"); err == nil {
audio.SetAlbumArtist(v)
}
if v, err := getFirstValue(meta, "xmpDM:artist"); err == nil {
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 {
audio.SetDisc(int32(i))
}
}
// TODO: audio.DiscCount: not provided by tika
if v, err := getFirstValue(meta, "xmpDM:duration"); err == nil {
if i, err := strconv.ParseInt(v, 10, 64); err == nil {
audio.SetDuration(i * 1000)
}
}
if v, err := getFirstValue(meta, "xmpDM:genre"); err == nil {
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 {
audio.SetTitle(v)
}
if v, err := getFirstValue(meta, "xmpDM:trackNumber"); err == nil {
if i, err := strconv.ParseInt(v, 10, 32); err == nil {
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 {
audio.SetYear(int32(i))
}
}
doc.Audio = &audio
doc.Audio = t.getAudio(meta)
}
}
@@ -158,3 +102,108 @@ func (t Tika) Extract(ctx context.Context, ri *provider.ResourceInfo) (Document,
return doc, nil
}
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) 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 {
if i, err := strconv.ParseInt(v, 10, 64); err == nil {
initAudio()
audio.SetDuration(i * 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
}

View File

@@ -140,6 +140,28 @@ var _ = Describe("Tika", func() {
})
It("adds location content", func() {
fullResponse = `[
{
"geo:lat": "49.48675890884328",
"geo:long": "11.103870357204285"
}
]`
doc, err := tika.Extract(context.TODO(), &provider.ResourceInfo{
Type: provider.ResourceType_RESOURCE_TYPE_FILE,
Size: 1,
})
Expect(err).ToNot(HaveOccurred())
location := doc.Location
Expect(location).ToNot(BeNil())
// TODO: Altitude is not supported right now
Expect(location.Altitude).To(BeNil())
Expect(location.Latitude).To(Equal(libregraph.PtrFloat64(49.48675890884328)))
Expect(location.Longitude).To(Equal(libregraph.PtrFloat64(11.103870357204285)))
})
It("removes stop words", func() {
body = "body to test stop words!!! against almost everyone"
language = "en"

View File

@@ -211,6 +211,7 @@ func (b *Bleve) Search(ctx context.Context, sir *searchService.SearchIndexReques
Tags: getFieldSliceValue[string](hit.Fields, "Tags"),
Highlights: getFragmentValue(hit.Fragments, "Content", 0),
Audio: getAudioValue[searchMessage.Audio](hit.Fields),
Location: getLocationValue[searchMessage.GeoCoordinates](hit.Fields),
},
}
@@ -329,6 +330,7 @@ func (b *Bleve) getResource(id string) (*Resource, error) {
Content: getFieldValue[string](fields, "Content"),
Tags: getFieldSliceValue[string](fields, "Tags"),
Audio: getAudioValue[libregraph.Audio](fields),
Location: getLocationValue[libregraph.GeoCoordinates](fields),
},
}, nil
}
@@ -382,6 +384,15 @@ func getAudioValue[T any](fields map[string]interface{}) *T {
return nil
}
func getLocationValue[T any](fields map[string]interface{}) *T {
var location = newPointerOfType[T]()
if ok := unmarshalInterfaceMap(location, fields, "location."); ok {
return location
}
return nil
}
func (b *Bleve) updateEntity(id string, mutateFunc func(r *Resource)) (*Resource, error) {
it, err := b.getResource(id)
if err != nil {

View File

@@ -548,5 +548,38 @@ var _ = Describe("Bleve", func() {
})
})
Context("with location metadata", func() {
BeforeEach(func() {
resource := engine.Resource{
ID: "1$2!7",
ParentID: rootResource.ID,
RootID: rootResource.ID,
Path: "./team.jpg",
Type: uint64(sprovider.ResourceType_RESOURCE_TYPE_FILE),
Document: content.Document{
Name: "team.jpg",
MimeType: "image/jpeg",
Location: &libregraph.GeoCoordinates{
Altitude: libregraph.PtrFloat64(1047.7),
Latitude: libregraph.PtrFloat64(49.48675890884328),
Longitude: libregraph.PtrFloat64(11.103870357204285),
},
},
}
err := eng.Upsert(resource.ID, resource)
Expect(err).ToNot(HaveOccurred())
})
It("returns audio metadata for search", func() {
matches := assertDocCount(rootResource.ID, `*team*`, 1)
location := matches[0].Entity.Location
Expect(location).ToNot(BeNil())
Expect(location.Altitude).To(Equal(libregraph.PtrFloat64(1047.7)))
Expect(location.Latitude).To(Equal(libregraph.PtrFloat64(49.48675890884328)))
Expect(location.Longitude).To(Equal(libregraph.PtrFloat64(11.103870357204285)))
})
})
})
})

View File

@@ -494,6 +494,7 @@ func (s *Service) UpsertItem(ref *provider.Reference, uID *user.UserId) {
// determine if metadata needs to be stored in storage as well
metadata := map[string]string{}
addAudioMetadata(metadata, doc.Audio)
addLocationMetadata(metadata, doc.Location)
if len(metadata) == 0 {
return
}
@@ -525,6 +526,13 @@ func addAudioMetadata(metadata map[string]string, audio *libregraph.Audio) {
marshalToStringMap(audio, metadata, "libre.graph.audio.")
}
func addLocationMetadata(metadata map[string]string, location *libregraph.GeoCoordinates) {
if location == nil {
return
}
marshalToStringMap(location, metadata, "libre.graph.location.")
}
func marshalToStringMap[T libregraph.MappedNullable](source T, target map[string]string, prefix string) {
// ToMap never returns a non-nil error ...
m, _ := source.ToMap()
@@ -549,6 +557,10 @@ func valueToString(value interface{}) string {
return strconv.FormatInt(int64(*v), 10)
case *int64:
return strconv.FormatInt(*v, 10)
case *float32:
return strconv.FormatFloat(float64(*v), 'f', -1, 32)
case *float64:
return strconv.FormatFloat(*v, 'f', -1, 64)
case *bool:
return strconv.FormatBool(*v)
default: