diff --git a/engine/dynamicdp.go b/engine/dynamicdp.go index c72125058..aa6943393 100644 --- a/engine/dynamicdp.go +++ b/engine/dynamicdp.go @@ -19,6 +19,8 @@ import ( "fmt" "net" + "github.com/nyaruka/phonenumbers" + "github.com/cgrates/cgrates/config" "github.com/cgrates/cgrates/utils" ) @@ -119,6 +121,41 @@ func (dDP *dynamicDP) fieldAsInterface(fldPath []string) (val interface{}, err e dDP.cache.Set([]string{utils.MetaStats, fldPath[1], k}, v) } return dDP.cache.FieldAsInterface(fldPath) + case utils.MetaLibPhoneNumber: + if len(fldPath) < 3 { + return nil, fmt.Errorf("invalid fieldname <%s> for libphonenumber", fldPath) + } + // sample of fieldName ~*libphonenumber.*req.Destination + // or ~*libphonenumber.*req.Destination.Carrier + fieldFromDP, err := dDP.initialDP.FieldAsString(fldPath[1:3]) + if err != nil { + utils.Logger.Warning(fmt.Sprintf("Received error: <%+v> when getting Destination for libphonenumber", err)) + return nil, err + } + num, err := phonenumbers.Parse(fieldFromDP, utils.EmptyString) + if err != nil { + return nil, err + } + // add the fields from libphonenumber + dDP.cache.Set([]string{utils.MetaLibPhoneNumber, fieldFromDP, "CountryCode"}, num.CountryCode) + dDP.cache.Set([]string{utils.MetaLibPhoneNumber, fieldFromDP, "NationalNumber"}, num.GetNationalNumber()) + dDP.cache.Set([]string{utils.MetaLibPhoneNumber, fieldFromDP, "Region"}, phonenumbers.GetRegionCodeForNumber(num)) + dDP.cache.Set([]string{utils.MetaLibPhoneNumber, fieldFromDP, "NumberType"}, phonenumbers.GetNumberType(num)) + geoLocation, err := phonenumbers.GetGeocodingForNumber(num, phonenumbers.GetRegionCodeForNumber(num)) + if err != nil { + utils.Logger.Warning(fmt.Sprintf("Received error: <%+v> when getting GeoLocation for number %+v", err, num)) + } + dDP.cache.Set([]string{utils.MetaLibPhoneNumber, fieldFromDP, "GeoLocation"}, geoLocation) + carrier, err := phonenumbers.GetCarrierForNumber(num, phonenumbers.GetRegionCodeForNumber(num)) + if err != nil { + utils.Logger.Warning(fmt.Sprintf("Received error: <%+v> when getting Carrier for number %+v", err, num)) + } + dDP.cache.Set([]string{utils.MetaLibPhoneNumber, fieldFromDP, "Carrier"}, carrier) + path := []string{utils.MetaLibPhoneNumber, fieldFromDP} + if len(fldPath) == 4 { + path = append(path, fldPath[3]) + } + return dDP.cache.FieldAsInterface(path) default: // in case of constant we give an empty DataProvider ( empty navigable map ) } return nil, utils.ErrNotFound diff --git a/general_tests/attributes_it_test.go b/general_tests/attributes_it_test.go index dcd7bb10c..f0be15e45 100644 --- a/general_tests/attributes_it_test.go +++ b/general_tests/attributes_it_test.go @@ -51,6 +51,7 @@ var ( testAttributeSProcessEventWithAccount, testAttributeSProcessEventWithStat, testAttributeSProcessEventWithResource, + testAttributeSProcessEventWithLibPhoneNumber, testAttributeSStopEngine, } ) @@ -516,7 +517,92 @@ func testAttributeSProcessEventWithResource(t *testing.T) { t.Errorf("Expecting: %s, received: %s", utils.ToJSON(eRply), utils.ToJSON(rplyEv)) } +} +func testAttributeSProcessEventWithLibPhoneNumber(t *testing.T) { + // add new attribute profile + var result string + alsPrf := &v1.AttributeWithCache{ + AttributeProfile: &engine.AttributeProfile{ + Tenant: "cgrates.org", + ID: "ATTR_LIBPHONENUMBER", + Contexts: []string{utils.META_ANY}, + FilterIDs: []string{"*string:~*req.EventName:AddDestinationDetails"}, + ActivationInterval: &utils.ActivationInterval{ + ActivationTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + ExpiryTime: time.Date(2014, 7, 14, 14, 35, 0, 0, time.UTC), + }, + Attributes: []*engine.Attribute{ + { + Path: utils.MetaReq + utils.NestingSep + "DestinationDetails", + Type: utils.MetaVariable, + Value: config.RSRParsers{ + &config.RSRParser{ + Rules: "~*libphonenumber.*req.Destination", + }, + }, + }, + }, + Blocker: false, + Weight: 10, + }, + } + alsPrf.Compile() + if err := attrRPC.Call(utils.APIerSv1SetAttributeProfile, alsPrf, &result); err != nil { + t.Error(err) + } else if result != utils.OK { + t.Error("Unexpected reply returned", result) + } + var replyAttr *engine.AttributeProfile + if err := attrRPC.Call(utils.APIerSv1GetAttributeProfile, + utils.TenantIDWithOpts{TenantID: &utils.TenantID{Tenant: "cgrates.org", ID: "ATTR_LIBPHONENUMBER"}}, &replyAttr); err != nil { + t.Fatal(err) + } + replyAttr.Compile() + if !reflect.DeepEqual(alsPrf.AttributeProfile, replyAttr) { + t.Errorf("Expecting : %+v, received: %+v", alsPrf.AttributeProfile, replyAttr) + } + + ev := &engine.AttrArgsProcessEvent{ + Context: utils.StringPointer(utils.MetaSessionS), + CGREventWithOpts: &utils.CGREventWithOpts{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "testAttributeSProcessEventWithLibPhoneNumber", + Event: map[string]interface{}{ + "EventName": "AddDestinationDetails", + "Destination": "+447779330921", + }, + }, + }, + } + + eRply := engine.AttrSProcessEventReply{ + MatchedProfiles: []string{"ATTR_LIBPHONENUMBER"}, + AlteredFields: []string{utils.MetaReq + utils.NestingSep + "DestinationDetails"}, + CGREventWithOpts: &utils.CGREventWithOpts{ + CGREvent: &utils.CGREvent{ + Tenant: "cgrates.org", + ID: "testAttributeSProcessEventWithLibPhoneNumber", + Event: map[string]interface{}{ + "EventName": "AddDestinationDetails", + "Destination": "+447779330921", + "DestinationDetails": "{\"Carrier\":\"Orange\",\"CountryCode\":44,\"GeoLocation\":\"\",\"NationalNumber\":7779330921,\"NumberType\":1,\"Region\":\"GB\"}", + }, + }, + }, + } + sort.Strings(eRply.AlteredFields) + var rplyEv engine.AttrSProcessEventReply + if err := attrRPC.Call(utils.AttributeSv1ProcessEvent, + ev, &rplyEv); err != nil { + t.Fatal(err) + } + sort.Strings(rplyEv.AlteredFields) + if !reflect.DeepEqual(eRply, rplyEv) { + t.Errorf("Expecting: %+v, received: %+v", + utils.ToJSON(eRply), utils.ToJSON(rplyEv)) + } } func testAttributeSStopEngine(t *testing.T) { diff --git a/go.mod b/go.mod index 3fe458cf1..56a2b0b6a 100644 --- a/go.mod +++ b/go.mod @@ -34,6 +34,7 @@ require ( github.com/fortytw2/leaktest v1.3.0 // indirect github.com/fsnotify/fsnotify v1.4.9 github.com/go-sql-driver/mysql v1.5.0 + github.com/golang/protobuf v1.4.2 // indirect github.com/gorhill/cronexpr v0.0.0-20180427100037-88b0669f7d75 github.com/ishidawataru/sctp v0.0.0-20191218070446-00ab2ac2db07 // indirect github.com/jinzhu/gorm v1.9.15 @@ -43,7 +44,7 @@ require ( github.com/mediocregopher/radix/v3 v3.5.2 github.com/miekg/dns v1.1.30 github.com/mitchellh/mapstructure v1.3.3 - github.com/nyaruka/phonenumbers v1.0.56 + github.com/nyaruka/phonenumbers v1.0.57 github.com/peterh/liner v1.2.0 github.com/philhofer/fwd v1.0.0 // indirect github.com/pquerna/ffjson v0.0.0-20190930134022-aa0246cd15f7 // indirect @@ -56,5 +57,6 @@ require ( golang.org/x/net v0.0.0-20200707034311-ab3426394381 golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d google.golang.org/api v0.29.0 + google.golang.org/protobuf v1.25.0 // indirect pack.ag/amqp v0.12.5 ) diff --git a/go.sum b/go.sum index c61883234..68d0479d8 100644 --- a/go.sum +++ b/go.sum @@ -162,6 +162,14 @@ github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw= github.com/golang/protobuf v1.3.5 h1:F768QJ1E9tib+q5Sc8MkdJi1RxLTbRcTf8LJV56aRls= github.com/golang/protobuf v1.3.5/go.mod h1:6O5/vntMXwX2lRkT1hjjk0nAC1IDOTvTlVgjlRvqsdk= +github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8= +github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA= +github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs= +github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w= +github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0= +github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8= +github.com/golang/protobuf v1.4.2 h1:+Z5KGCizgyZCbGh1KZqA0fcLLkwbsjIzS4aV2v7wJX0= +github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI= github.com/golang/snappy v0.0.1 h1:Qgr9rKW7uDUkrbSmQeiDsGa8SjGyCOGtuasMWwvp2P4= github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= @@ -171,6 +179,7 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0 h1:xsAVV57WRhGj6kEIi8ReJzQlHHqcBYCElAvkovg3B/4= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= +github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs= github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= github.com/google/pprof v0.0.0-20190515194954-54271f7e092f/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc= @@ -239,6 +248,8 @@ github.com/mitchellh/mapstructure v1.3.3/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RR github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc= github.com/nyaruka/phonenumbers v1.0.56 h1:WdOfLJMyhXibLTBHu1MIrPmZ5eylfGaXZ9vl9h9SB08= github.com/nyaruka/phonenumbers v1.0.56/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U= +github.com/nyaruka/phonenumbers v1.0.57 h1:V4FNPs061PSUOEzQaLH0+pfzEdqoiMH/QJWryx/0hfs= +github.com/nyaruka/phonenumbers v1.0.57/go.mod h1:sDaTZ/KPX5f8qyV9qN+hIm+4ZBARJrupC6LuhshJq1U= github.com/pelletier/go-toml v1.4.0/go.mod h1:PN7xzY2wHTK0K9p34ErDQMlFxa51Fk0OUruD3k1mMwo= github.com/peterh/liner v1.2.0 h1:w/UPXyl5GfahFxcTOz2j9wCIHNI+pUPr2laqpojKNCg= github.com/peterh/liner v1.2.0/go.mod h1:CRroGNssyjTd/qIG2FyxByd2S8JEAZXBl4qUrZf8GS0= @@ -488,6 +499,8 @@ google.golang.org/genproto v0.0.0-20200212174721-66ed5ce911ce/go.mod h1:55QSHmfG google.golang.org/genproto v0.0.0-20200224152610-e50cd9704f63/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940 h1:MRHtG0U6SnaUb+s+LhNE1qt1FQ1wlhqr5E4usBKC0uA= google.golang.org/genproto v0.0.0-20200331122359-1ee6d9798940/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013 h1:+kGHl1aib/qcwaRi1CbqBZ1rk19r85MNUf8HaBghugY= +google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38= google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM= @@ -499,6 +512,17 @@ google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8 google.golang.org/grpc v1.27.1/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk= google.golang.org/grpc v1.28.0 h1:bO/TA4OxCOummhSf10siHuG7vJOiwh7SpRpFZDkOgl4= google.golang.org/grpc v1.28.0/go.mod h1:rpkK4SK4GF4Ach/+MFLZUBavHOvF2JJB5uozKKal+60= +google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8= +google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0= +google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM= +google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE= +google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo= +google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.0 h1:4MY060fB1DLGMB/7MBTLnwQUY6+F09GEiz6SsrNqyzM= +google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU= +google.golang.org/protobuf v1.25.0 h1:Ejskq+SyPohKW+1uil0JJMtmHCgJPJ/qWTxr8qp+R4c= +google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/packages/debian/changelog b/packages/debian/changelog index d5242a218..77026f90d 100644 --- a/packages/debian/changelog +++ b/packages/debian/changelog @@ -106,7 +106,8 @@ cgrates (0.11.0~dev) UNRELEASED; urgency=medium * [EEs] Add support for *elastic exporter * [AttributeS] Add support for adding fields from other places that event (e.g. Resource.TotalUsage, Stat.MetricName, Account.Balance) * [EEs] Empty fields in exporter config will export the full event for the exporters that use json format - + * [DynamicDP] Add support for *libphonenumber prefix + -- DanB Wed, 19 Feb 2020 13:25:52 +0200 cgrates (0.10.0) UNRELEASED; urgency=medium @@ -150,4 +151,4 @@ cgrates (0.9.1~rc3) UNRELEASED; urgency=low * RC3. - -- DanB Fri, 03 Jan 2014 17:37:31 +0100 \ No newline at end of file + -- DanB Fri, 03 Jan 2014 17:37:31 +0100