diff --git a/VERSION b/VERSION index 5c87d600..9eb2e1ff 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.98.1 +1.99.0 diff --git a/examples/service/go.mod b/examples/service/go.mod index c6e4117e..624c729f 100644 --- a/examples/service/go.mod +++ b/examples/service/go.mod @@ -7,7 +7,7 @@ toolchain go1.22.5 replace github.com/Vonage/gosrvlib => ../.. require ( - github.com/Vonage/gosrvlib v1.98.1 + github.com/Vonage/gosrvlib v1.99.0 github.com/golang/mock v1.6.0 github.com/jstemmer/go-junit-report/v2 v2.1.0 github.com/prometheus/client_golang v1.19.1 @@ -35,7 +35,7 @@ require ( github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.4 // indirect + github.com/gabriel-vasile/mimetype v1.4.5 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect @@ -109,9 +109,9 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.23.0 // indirect google.golang.org/api v0.189.0 // indirect - google.golang.org/genproto v0.0.0-20240723171418-e6d459c13d2a // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240723171418-e6d459c13d2a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240723171418-e6d459c13d2a // indirect + google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/examples/service/go.sum b/examples/service/go.sum index 6a1ed91a..992ba06b 100644 --- a/examples/service/go.sum +++ b/examples/service/go.sum @@ -41,6 +41,8 @@ cloud.google.com/go/beyondcorp v1.0.9 h1:1UeDTSkNGk0XaXoQ9Z76PxtB8cJPmBZRnW2HzeK cloud.google.com/go/beyondcorp v1.0.9/go.mod h1:xa0eU8tIbYVraMOpRh5V9PirdYROvTUcPayJW9UlSNs= cloud.google.com/go/bigquery v1.62.0 h1:SYEA2f7fKqbSRRBHb7g0iHTtZvtPSPYdXfmqsjpsBwo= cloud.google.com/go/bigquery v1.62.0/go.mod h1:5ee+ZkF1x/ntgCsFQJAQTM3QkAZOecfCmvxhkJsWRSA= +cloud.google.com/go/bigtable v1.27.2-0.20240725222120-ce31365acc54 h1:KOjHlKEA0UzDD9asy7vFmv/mOwj/UH8IDjKl5LfEJXU= +cloud.google.com/go/bigtable v1.27.2-0.20240725222120-ce31365acc54/go.mod h1:NmJ2jfoB34NxQyk4w7UCchopqE9r+a186ewvGrM79TI= cloud.google.com/go/billing v1.18.8 h1:F0QnYXQ/o86zkuLMwJe+yLlPj/kgfrNCukH+bOhAT2I= cloud.google.com/go/billing v1.18.8/go.mod h1:oFsuKhKiuxK7dDQ4a8tt5/1cScEo4IzhssWj6TTdi6k= cloud.google.com/go/binaryauthorization v1.8.6 h1:eMjakmqpE0UPmyki0eGZQfyBSyfNRhGzb64lE32T+ik= @@ -365,8 +367,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= -github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= +github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= +github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= github.com/go-kit/kit v0.9.0 h1:wDJmvq38kDhkVxi50ni9ykkdUr1PKgqKOoi01fa0Mdk= github.com/go-kit/kit v0.9.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -849,14 +851,14 @@ google.golang.org/appengine v1.6.8/go.mod h1:1jJ3jBArFh5pcgW8gCtRJnepW8FzD1V44FJ google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= -google.golang.org/genproto v0.0.0-20240723171418-e6d459c13d2a h1:hPbLwHFm59QoSKUT0uGaL19YN4U9W5lY4+iNXlUBNj0= -google.golang.org/genproto v0.0.0-20240723171418-e6d459c13d2a/go.mod h1:+7gIV7FP6jBo5hiY2lsWA//NkNORQVj0J1Isc/4HzR4= -google.golang.org/genproto/googleapis/api v0.0.0-20240723171418-e6d459c13d2a h1:YIa/rzVqMEokBkPtydCkx1VLmv3An1Uw7w1P1m6EhOY= -google.golang.org/genproto/googleapis/api v0.0.0-20240723171418-e6d459c13d2a/go.mod h1:AHT0dDg3SoMOgZGnZk29b5xTbPHMoEC8qthmBLJCpys= +google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f h1:htT2I9bZvGm+110zq8bIErMX+WgBWxCzV3ChwbvnKnc= +google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:Sk3mLpoDFTAp6R4OvlcUgaG4ISTspKeFsIAXMn9Bm4Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f h1:b1Ln/PG8orm0SsBbHZWke8dDp2lrCD4jSmfglFpTZbk= +google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:AHT0dDg3SoMOgZGnZk29b5xTbPHMoEC8qthmBLJCpys= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240722135656-d784300faade h1:fc+h2kSr2nW2DHxAdGYeX3bnkr4iFsKHUu9Fi6Rh4Y8= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240722135656-d784300faade/go.mod h1:5/MT647Cn/GGhwTpXC7QqcaR5Cnee4v4MKCU1/nwnIQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240723171418-e6d459c13d2a h1:hqK4+jJZXCU4pW7jsAdGOVFIfLHQeV7LaizZKnZ84HI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240723171418-e6d459c13d2a/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f h1:RARaIm8pxYuxyNPbBQf5igT7XdOyCNtat1qAT2ZxjU4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= diff --git a/go.mod b/go.mod index a6d55d32..df1be9e8 100644 --- a/go.mod +++ b/go.mod @@ -70,7 +70,7 @@ require ( github.com/fatih/color v1.17.0 // indirect github.com/felixge/httpsnoop v1.0.4 // indirect github.com/fsnotify/fsnotify v1.7.0 // indirect - github.com/gabriel-vasile/mimetype v1.4.4 // indirect + github.com/gabriel-vasile/mimetype v1.4.5 // indirect github.com/go-logr/logr v1.4.2 // indirect github.com/go-logr/stdr v1.2.2 // indirect github.com/go-playground/locales v0.14.1 // indirect @@ -137,9 +137,9 @@ require ( golang.org/x/time v0.5.0 // indirect golang.org/x/tools v0.23.0 // indirect google.golang.org/api v0.189.0 // indirect - google.golang.org/genproto v0.0.0-20240723171418-e6d459c13d2a // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20240723171418-e6d459c13d2a // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20240723171418-e6d459c13d2a // indirect + google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f // indirect google.golang.org/grpc v1.65.0 // indirect google.golang.org/protobuf v1.34.2 // indirect gopkg.in/ini.v1 v1.67.0 // indirect diff --git a/go.sum b/go.sum index 7f307e61..12c74edb 100644 --- a/go.sum +++ b/go.sum @@ -42,6 +42,8 @@ cloud.google.com/go/beyondcorp v1.0.9 h1:1UeDTSkNGk0XaXoQ9Z76PxtB8cJPmBZRnW2HzeK cloud.google.com/go/beyondcorp v1.0.9/go.mod h1:xa0eU8tIbYVraMOpRh5V9PirdYROvTUcPayJW9UlSNs= cloud.google.com/go/bigquery v1.62.0 h1:SYEA2f7fKqbSRRBHb7g0iHTtZvtPSPYdXfmqsjpsBwo= cloud.google.com/go/bigquery v1.62.0/go.mod h1:5ee+ZkF1x/ntgCsFQJAQTM3QkAZOecfCmvxhkJsWRSA= +cloud.google.com/go/bigtable v1.27.2-0.20240725222120-ce31365acc54 h1:KOjHlKEA0UzDD9asy7vFmv/mOwj/UH8IDjKl5LfEJXU= +cloud.google.com/go/bigtable v1.27.2-0.20240725222120-ce31365acc54/go.mod h1:NmJ2jfoB34NxQyk4w7UCchopqE9r+a186ewvGrM79TI= cloud.google.com/go/billing v1.18.8 h1:F0QnYXQ/o86zkuLMwJe+yLlPj/kgfrNCukH+bOhAT2I= cloud.google.com/go/billing v1.18.8/go.mod h1:oFsuKhKiuxK7dDQ4a8tt5/1cScEo4IzhssWj6TTdi6k= cloud.google.com/go/binaryauthorization v1.8.6 h1:eMjakmqpE0UPmyki0eGZQfyBSyfNRhGzb64lE32T+ik= @@ -397,8 +399,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA= github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM= -github.com/gabriel-vasile/mimetype v1.4.4 h1:QjV6pZ7/XZ7ryI2KuyeEDE8wnh7fHP9YnQy+R0LnH8I= -github.com/gabriel-vasile/mimetype v1.4.4/go.mod h1:JwLei5XPtWdGiMFB5Pjle1oEeoSeEuJfJE+TtfvdB/s= +github.com/gabriel-vasile/mimetype v1.4.5 h1:J7wGKdGu33ocBOhGy0z653k/lFKLFDPJMG8Gql0kxn4= +github.com/gabriel-vasile/mimetype v1.4.5/go.mod h1:ibHel+/kbxn9x2407k1izTA1S81ku1z/DlgOW2QE0M4= github.com/ghodss/yaml v1.0.0 h1:wQHKEahhL6wmXdzwWG11gIVCkOv05bNOh+Rxn0yngAk= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/go-kit/kit v0.8.0/go.mod h1:xBxKIO96dXMWWy0MnWVtmwkA9/13aqxPnvrjFYMA2as= @@ -991,14 +993,14 @@ google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98 google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c= google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo= google.golang.org/genproto v0.0.0-20220503193339-ba3ae3f07e29/go.mod h1:RAyBrSAP7Fh3Nc84ghnVLDPuV51xc9agzmm4Ph6i0Q4= -google.golang.org/genproto v0.0.0-20240723171418-e6d459c13d2a h1:hPbLwHFm59QoSKUT0uGaL19YN4U9W5lY4+iNXlUBNj0= -google.golang.org/genproto v0.0.0-20240723171418-e6d459c13d2a/go.mod h1:+7gIV7FP6jBo5hiY2lsWA//NkNORQVj0J1Isc/4HzR4= -google.golang.org/genproto/googleapis/api v0.0.0-20240723171418-e6d459c13d2a h1:YIa/rzVqMEokBkPtydCkx1VLmv3An1Uw7w1P1m6EhOY= -google.golang.org/genproto/googleapis/api v0.0.0-20240723171418-e6d459c13d2a/go.mod h1:AHT0dDg3SoMOgZGnZk29b5xTbPHMoEC8qthmBLJCpys= +google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f h1:htT2I9bZvGm+110zq8bIErMX+WgBWxCzV3ChwbvnKnc= +google.golang.org/genproto v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:Sk3mLpoDFTAp6R4OvlcUgaG4ISTspKeFsIAXMn9Bm4Y= +google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f h1:b1Ln/PG8orm0SsBbHZWke8dDp2lrCD4jSmfglFpTZbk= +google.golang.org/genproto/googleapis/api v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:AHT0dDg3SoMOgZGnZk29b5xTbPHMoEC8qthmBLJCpys= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240722135656-d784300faade h1:fc+h2kSr2nW2DHxAdGYeX3bnkr4iFsKHUu9Fi6Rh4Y8= google.golang.org/genproto/googleapis/bytestream v0.0.0-20240722135656-d784300faade/go.mod h1:5/MT647Cn/GGhwTpXC7QqcaR5Cnee4v4MKCU1/nwnIQ= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240723171418-e6d459c13d2a h1:hqK4+jJZXCU4pW7jsAdGOVFIfLHQeV7LaizZKnZ84HI= -google.golang.org/genproto/googleapis/rpc v0.0.0-20240723171418-e6d459c13d2a/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f h1:RARaIm8pxYuxyNPbBQf5igT7XdOyCNtat1qAT2ZxjU4= +google.golang.org/genproto/googleapis/rpc v0.0.0-20240725223205-93522f1f2a9f/go.mod h1:Ue6ibwXGpU+dqIcODieyLOcgj7z8+IcskoNIgZxtrFY= google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c= google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg= google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY= diff --git a/pkg/countrycode/data.go b/pkg/countrycode/data.go index 064ae24f..9c32adbc 100644 --- a/pkg/countrycode/data.go +++ b/pkg/countrycode/data.go @@ -42,7 +42,7 @@ type Data struct { } // New generates the country data, including various indexes. -// If the cdata parameter is nil, the default data is used. +// If the cdata parameter is nil, the embedded default data is used. // The generated object should be reused to avoid copying the data. // // Default data sources (updated at: 2024-07-17): diff --git a/pkg/countryphone/countryphone.go b/pkg/countryphone/countryphone.go new file mode 100644 index 00000000..7c78f56c --- /dev/null +++ b/pkg/countryphone/countryphone.go @@ -0,0 +1,239 @@ +/* +Package countryphone provides geographical information of phone numbers. Country +phone codes are defined by the International Telecommunication Union (ITU) in +ITU-T standards E.123 and E.164. + +The default phone prefixes data can be overridden with a custom dataset. The +data is stored in a trie for fast prefix matching. +*/ +package countryphone + +import ( + "fmt" + + "github.com/Vonage/gosrvlib/pkg/numtrie" +) + +// InPrefixGroup stores the type and geographical information of a group of phone +// number prefixes. +type InPrefixGroup struct { + // Name is the name of the group or geographical area. + Name string `json:"name"` + + // Type is the type of group or geographical area: + // - 0 = "" + // - 1 = "state" + // - 2 = "province or territory" + // - 3 = "nation or territory" + // - 4 = "non-geographic" + // - 5 = "other" + Type int `json:"type"` + + // PrefixType is the type of phone number prefix: + // - 0 = "" + // - 1 = "landline" + // - 2 = "mobile" + // - 3 = "pager" + // - 4 = "satellite" + // - 5 = "special service" + // - 6 = "virtual" + // - 7 = "other" + PrefixType int `json:"prefixType"` + + // Prefixes is a list of phone number prefixes (including the Country Code). + Prefixes []string `json:"prefixes"` +} + +// InCountryData stores all the phone number prefixes information for a country. +type InCountryData struct { + // CC is the Country Calling code (e.g. "1" for "US" and "CA"). + CC string `json:"cc"` + + // Groups is a list of phone prefixes information grouped by geographical + // area or type. + Groups []InPrefixGroup `json:"groups"` +} + +// InData is a type alias for a map of country Alpha-2 codes to InCountryData. +type InData = map[string]*InCountryData + +// GeoInfo stores geographical information of a phone number. +type GeoInfo struct { + // Alpha2 is the ISO-3166 Alpha-2 Country Code. + Alpha2 string `json:"alpha2"` + + // Area is the geographical area. + Area string `json:"area"` + + // Type is the type of area: + // - 0 = "" + // - 1 = "state" + // - 2 = "province or territory" + // - 3 = "nation or territory" + // - 4 = "non-geographic" + // - 5 = "other" + Type int `json:"type"` +} + +// NumInfo stores the number type and geographical information of a phone number. +type NumInfo struct { + // Type is the type of number: + // - 0 = "" + // - 1 = "landline" + // - 2 = "mobile" + // - 3 = "pager" + // - 4 = "satellite" + // - 5 = "special service" + // - 6 = "virtual" + // - 7 = "other" + Type int `json:"type"` + + // Geo is the geographical information. + Geo []*GeoInfo `json:"geo"` +} + +// PrefixData is a type alias for a map of phone number prefixes to NumData. +type PrefixData = map[string]*NumInfo + +// Data is the main data structure that stores phone number prefixes and their +// information. +type Data struct { + enumNumberType [8]string + enumAreaType [6]string + trie *numtrie.Node[NumInfo] +} + +// New initialize the search trie with the given data. +// If data is nil, the embedded default dataset is used. +func New(data InData) *Data { + d := &Data{} + + d.loadEnums() + + if data == nil { + data = defaultData() + } + + d.loadData(data) + + return d +} + +// NumberInfo returns the number type and geographical information for the given +// phone number prefix. +// +// NOTE: see the "github.com/Vonage/gosrvlib/pkg/countrycode" package to get the +// country information from the Alpha2 code. +func (d *Data) NumberInfo(num string) (*NumInfo, error) { + data, status := d.trie.Get(num) + + if status < 0 || data == nil { + return nil, fmt.Errorf("no match for prefix %s", num) + } + + return data, nil +} + +// NumberType returns the string representation of the number type. +func (d *Data) NumberType(t int) (string, error) { + if t < 0 || t >= len(d.enumNumberType) { + return "", fmt.Errorf("invalid number type %d", t) + } + + return d.enumNumberType[t], nil +} + +// AreaType returns the string representation of the area type. +func (d *Data) AreaType(t int) (string, error) { + if t < 0 || t >= len(d.enumAreaType) { + return "", fmt.Errorf("invalid area type %d", t) + } + + return d.enumAreaType[t], nil +} + +// loadEnums initializes the enumeration arrays. +func (d *Data) loadEnums() { + d.enumNumberType = [...]string{ + "", + "landline", + "mobile", + "pager", + "satellite", + "special service", + "virtual", + "other", + } + + d.enumAreaType = [...]string{ + "", + "state", + "province or territory", + "nation or territory", + "non-geographic", + "other", + } +} + +func (d *Data) insertPrefix(prefix string, info *NumInfo) { + v, status := d.trie.Get(prefix) + + if (status == numtrie.StatusMatchFull || status == numtrie.StatusMatchPartial) && + (v != nil) && (len(v.Geo) > 0) { + // the node already exists > merge the data + if len(info.Geo) > 0 { + info.Geo = append(v.Geo, info.Geo...) + } + } + + d.trie.Add(prefix, info) +} + +func (d *Data) insertGroups(a2, cc string, data []InPrefixGroup) { + if len(data) == 0 { + return + } + + for _, g := range data { + info := &NumInfo{ + Type: g.PrefixType, + Geo: []*GeoInfo{ + { + Alpha2: a2, + Area: g.Name, + Type: g.Type, + }, + }, + } + + if len(g.Prefixes) == 0 { + d.insertPrefix(cc, info) + continue + } + + for _, p := range g.Prefixes { + d.insertPrefix(p, info) + } + } +} + +// loadData loads the phone number prefixes and their data into the trie. +func (d *Data) loadData(data InData) { + d.trie = numtrie.New[NumInfo]() + + for k, v := range data { + info := &NumInfo{ + Type: 0, + Geo: []*GeoInfo{ + { + Alpha2: k, + Area: "", + Type: 0, + }, + }, + } + + d.insertPrefix(v.CC, info) + d.insertGroups(k, v.CC, v.Groups) + } +} diff --git a/pkg/countryphone/countryphone_test.go b/pkg/countryphone/countryphone_test.go new file mode 100644 index 00000000..1637ff65 --- /dev/null +++ b/pkg/countryphone/countryphone_test.go @@ -0,0 +1,452 @@ +package countryphone + +import ( + "testing" + + "github.com/stretchr/testify/require" +) + +func TestNew(t *testing.T) { + t.Parallel() + + // custom data + indata := InData{ + "US": &InCountryData{ + CC: "1", + Groups: []InPrefixGroup{ + { + Name: "Alaska", + Type: 1, + PrefixType: 1, + Prefixes: []string{"1907"}, + }, + }, + }, + } + + data := New(indata) + + require.NotNil(t, data) +} + +func TestNew_default(t *testing.T) { + t.Parallel() + + data := New(nil) + + require.NotNil(t, data) +} + +func TestData_NumberInfo(t *testing.T) { + t.Parallel() + + // load defaut data + data := New(nil) + + require.NotNil(t, data) + + tests := []struct { + name string + prefix string + want *NumInfo + wantErr bool + }{ + { + name: "empty", + prefix: "", + want: nil, + wantErr: true, + }, + { + name: "non-geographic", + prefix: "87012345678", + want: &NumInfo{ + Type: 5, + Geo: []*GeoInfo{ + { + Alpha2: "__", + Area: "Inmarsat", + Type: 4, + }, + }, + }, + wantErr: false, + }, + { + name: "vatican (rome)", + prefix: "37912345678", + want: &NumInfo{ + Type: 0, + Geo: []*GeoInfo{ + { + Alpha2: "VA", + Area: "", + Type: 0, + }, + }, + }, + wantErr: false, + }, + { + name: "vatican (unused code)", + prefix: "39066981234", + want: &NumInfo{ + Type: 1, + Geo: []*GeoInfo{ + { + Alpha2: "VA", + Area: "Vatican City", + Type: 0, + }, + }, + }, + wantErr: false, + }, + { + name: "california", + prefix: "1357123456", + want: &NumInfo{ + Type: 1, + Geo: []*GeoInfo{ + { + Alpha2: "US", + Area: "California", + Type: 1, + }, + }, + }, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got, err := data.NumberInfo(tt.prefix) + + if tt.wantErr { + require.Error(t, err) + require.Empty(t, got) + + return + } + + require.NoError(t, err) + require.EqualExportedValues(t, tt.want, got) + }) + } +} + +func TestData_NumberInfo_custom(t *testing.T) { + t.Parallel() + + indata := InData{ + "US": &InCountryData{ + CC: "1", + Groups: []InPrefixGroup{ + { + Name: "Alaska", + Type: 1, + PrefixType: 1, + Prefixes: []string{"1907"}, + }, + { + Name: "Arizona", + Type: 1, + PrefixType: 1, + Prefixes: []string{"1480", "5120", "1602", "1623", "1928"}, + }, + }, + }, + "CA": &InCountryData{ + CC: "1", + Groups: []InPrefixGroup{ + { + Name: "Manitoba", + Type: 2, + PrefixType: 1, + Prefixes: []string{"1204", "1431", "1584"}, + }, + { + Name: "Nunavut", + Type: 2, + PrefixType: 1, + Prefixes: []string{"1867"}, + }, + }, + }, + "JP": &InCountryData{ + CC: "81", + }, + "__": &InCountryData{ + CC: "7", + Groups: []InPrefixGroup{ + { + Name: "TEST", + Type: 5, + PrefixType: 7, + Prefixes: []string{}, + }, + }, + }, + } + + data := New(indata) + + require.NotNil(t, data) + + tests := []struct { + name string + prefix string + want *NumInfo + wantErr bool + }{ + { + name: "empty", + prefix: "", + want: nil, + wantErr: true, + }, + { + name: "no match", + prefix: "999999", + want: nil, + wantErr: true, + }, + { + name: "US & CA", + prefix: "100000", + want: &NumInfo{ + Type: 0, + Geo: []*GeoInfo{ + { + Alpha2: "US", + Area: "", + Type: 0, + }, + { + Alpha2: "CA", + Area: "", + Type: 0, + }, + }, + }, + wantErr: false, + }, + { + name: "US - Alaska", + prefix: "1907000", + want: &NumInfo{ + Type: 1, + Geo: []*GeoInfo{ + { + Alpha2: "US", + Area: "Alaska", + Type: 1, + }, + }, + }, + wantErr: false, + }, + { + name: "US - Arizona", + prefix: "1623000", + want: &NumInfo{ + Type: 1, + Geo: []*GeoInfo{ + { + Alpha2: "US", + Area: "Arizona", + Type: 1, + }, + }, + }, + wantErr: false, + }, + { + name: "CA - Manitoba", + prefix: "1431000", + want: &NumInfo{ + Type: 1, + Geo: []*GeoInfo{ + { + Alpha2: "CA", + Area: "Manitoba", + Type: 2, + }, + }, + }, + wantErr: false, + }, + { + name: "JP", + prefix: "81234567890", + want: &NumInfo{ + Type: 0, + Geo: []*GeoInfo{ + { + Alpha2: "JP", + Area: "", + Type: 0, + }, + }, + }, + wantErr: false, + }, + { + name: "Artificial without prefix", + prefix: "7123", + want: &NumInfo{ + Type: 7, + Geo: []*GeoInfo{ + { + Alpha2: "__", + Area: "", + Type: 0, + }, + { + Alpha2: "__", + Area: "TEST", + Type: 5, + }, + }, + }, + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got, err := data.NumberInfo(tt.prefix) + + if tt.wantErr { + require.Error(t, err) + require.Empty(t, got) + + return + } + + require.NoError(t, err) + require.EqualExportedValues(t, tt.want, got) + }) + } +} + +func TestData_NumberType(t *testing.T) { + t.Parallel() + + data := New(InData{}) + + require.NotNil(t, data) + + tests := []struct { + name string + num int + want string + wantErr bool + }{ + { + name: "out of bounds < 0", + num: -1, + want: "", + wantErr: true, + }, + { + name: "out of bounds > max", + num: 8, + want: "", + wantErr: true, + }, + { + name: "first", + num: 0, + want: "", + wantErr: false, + }, + { + name: "last", + num: 7, + want: "other", + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got, err := data.NumberType(tt.num) + + if tt.wantErr { + require.Error(t, err) + require.Empty(t, got) + + return + } + + require.NoError(t, err) + require.Equal(t, tt.want, got) + }) + } +} + +func TestData_AreaType(t *testing.T) { + t.Parallel() + + data := New(InData{}) + + require.NotNil(t, data) + + tests := []struct { + name string + num int + want string + wantErr bool + }{ + { + name: "out of bounds < 0", + num: -1, + want: "", + wantErr: true, + }, + { + name: "out of bounds > max", + num: 6, + want: "", + wantErr: true, + }, + { + name: "first", + num: 0, + want: "", + wantErr: false, + }, + { + name: "last", + num: 5, + want: "other", + wantErr: false, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + t.Parallel() + + got, err := data.AreaType(tt.num) + + if tt.wantErr { + require.Error(t, err) + require.Empty(t, got) + + return + } + + require.NoError(t, err) + require.Equal(t, tt.want, got) + }) + } +} diff --git a/pkg/countryphone/data.go b/pkg/countryphone/data.go new file mode 100644 index 00000000..4b1f6e0a --- /dev/null +++ b/pkg/countryphone/data.go @@ -0,0 +1,395 @@ +package countryphone + +// defaultData returns a default map of phone numbers to country ISO-3166 Alpha-2 Codes. +// Ref.: https://en.wikipedia.org/wiki/List_of_country_calling_codes +// +//nolint:funlen,maintidx +func defaultData() InData { + return InData{ + "AC": {CC: "247"}, + "AD": {CC: "376"}, + "AE": {CC: "971"}, + "AF": {CC: "93"}, + "AG": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1268"}}, + }}, + "AI": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1264"}}, + }}, + "AL": {CC: "355"}, + "AM": {CC: "374"}, + "AO": {CC: "244"}, + "AQ": {CC: "672"}, + "AR": {CC: "54"}, + "AS": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1684"}}, + }}, + "AT": {CC: "43"}, + "AU": {CC: "61"}, + "AW": {CC: "297"}, + "AX": {CC: "35818"}, + "AZ": {CC: "994"}, + "BA": {CC: "387"}, + "BB": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1246"}}, + }}, + "BD": {CC: "880"}, + "BE": {CC: "32"}, + "BF": {CC: "226"}, + "BG": {CC: "359"}, + "BH": {CC: "973"}, + "BI": {CC: "257"}, + "BJ": {CC: "229"}, + "BL": {CC: "590"}, + "BM": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1441"}}, + }}, + "BN": {CC: "673"}, + "BO": {CC: "591"}, + "BQ": {CC: "599"}, + "BR": {CC: "55"}, + "BS": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1242"}}, + }}, + "BT": {CC: "975"}, + "BV": {CC: "47"}, + "BW": {CC: "267"}, + "BY": {CC: "375"}, + "BZ": {CC: "501"}, + "CA": {CC: "1", Groups: []InPrefixGroup{ + {"Alberta", 2, 1, []string{"1368", "1403", "1568", "1587", "1780", "1825"}}, + {"British Columbia", 2, 1, []string{"1236", "1250", "1257", "1604", "1672", "1778"}}, + {"Manitoba", 2, 1, []string{"1204", "1431", "1584"}}, + {"New Brunswick", 2, 1, []string{"1428", "1506"}}, + {"Newfoundland and Labrador", 2, 1, []string{"1709", "1879"}}, + {"Northwest Territories", 2, 1, []string{"1867"}}, + {"Nova Scotia", 2, 1, []string{"1782", "1851", "1902"}}, + {"Nunavut", 2, 1, []string{"1867"}}, + {"Ontario", 2, 1, []string{"1226", "1249", "1289", "1343", "1365", "1382", "1387", "1416", "1437", "1460", "1519", "1537", "1548", "1613", "1647", "1683", "1705", "1742", "1753", "1807", "1905", "1942"}}, + {"Prince Edward Island", 2, 1, []string{"1782", "1902"}}, + {"Quebec", 2, 1, []string{"1263", "1354", "1367", "1418", "1438", "1450", "1468", "1514", "1579", "1581", "1819", "1873"}}, + {"Saskatchewan", 2, 1, []string{"1306", "1474", "1639"}}, + {"Yukon", 2, 1, []string{"1867"}}, + {"Canada special services", 4, 5, []string{"1600", "1622", "1633", "1644", "1655", "1677", "1688"}}, + }}, + "CC": {CC: "61"}, + "CD": {CC: "243"}, + "CF": {CC: "236"}, + "CG": {CC: "242"}, + "CH": {CC: "41"}, + "CI": {CC: "225"}, + "CK": {CC: "682"}, + "CL": {CC: "56"}, + "CM": {CC: "237"}, + "CN": {CC: "86"}, + "CO": {CC: "57"}, + "CR": {CC: "506"}, + "CT": {CC: "90"}, + "CU": {CC: "53"}, + "CV": {CC: "238"}, + "CW": {CC: "599"}, + "CX": {CC: "61"}, + "CY": {CC: "357"}, + "CZ": {CC: "420"}, + "DE": {CC: "49"}, + "DJ": {CC: "253"}, + "DK": {CC: "45"}, + "DM": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1767"}}, + }}, + "DO": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1809", "1829", "1849"}}, + }}, + "DZ": {CC: "213"}, + "EC": {CC: "593"}, + "EE": {CC: "372"}, + "EG": {CC: "20"}, + "EH": {CC: "212"}, + "ER": {CC: "291"}, + "ES": {CC: "34"}, + "ET": {CC: "251"}, + "FI": {CC: "358"}, + "FJ": {CC: "679"}, + "FK": {CC: "500"}, + "FM": {CC: "691"}, + "FO": {CC: "298"}, + "FR": {CC: "33"}, + "GA": {CC: "241"}, + "GB": {CC: "44"}, + "GD": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1473"}}, + }}, + "GE": {CC: "995"}, + "GF": {CC: "594"}, + "GG": {CC: "44"}, + "GH": {CC: "233"}, + "GI": {CC: "350"}, + "GL": {CC: "299"}, + "GM": {CC: "220"}, + "GN": {CC: "224"}, + "GP": {CC: "590"}, + "GQ": {CC: "240"}, + "GR": {CC: "30"}, + "GS": {CC: "500"}, + "GT": {CC: "502"}, + "GU": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1671"}}, + }}, + "GW": {CC: "245"}, + "GY": {CC: "592"}, + "HK": {CC: "852"}, + "HN": {CC: "504"}, + "HR": {CC: "385"}, + "HT": {CC: "509"}, + "HU": {CC: "36"}, + "ID": {CC: "62"}, + "IE": {CC: "353"}, + "IL": {CC: "972"}, + "IM": {CC: "44"}, + "IN": {CC: "91"}, + "IO": {CC: "246"}, + "IQ": {CC: "964"}, + "IR": {CC: "98"}, + "IS": {CC: "354"}, + "IT": {CC: "39"}, + "JE": {CC: "44"}, + "JM": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1658", "1876"}}, + }}, + "JO": {CC: "962"}, + "JP": {CC: "81"}, + "KE": {CC: "254"}, + "KG": {CC: "996"}, + "KH": {CC: "855"}, + "KI": {CC: "686"}, + "KM": {CC: "269"}, + "KN": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1869"}}, + }}, + "KP": {CC: "850"}, + "KR": {CC: "82"}, + "KW": {CC: "965"}, + "KY": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1345"}}, + }}, + "KZ": {CC: "7", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"76", "77"}}, + }}, + "LA": {CC: "856"}, + "LB": {CC: "961"}, + "LC": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1758"}}, + }}, + "LI": {CC: "423"}, + "LK": {CC: "94"}, + "LR": {CC: "231"}, + "LS": {CC: "266"}, + "LT": {CC: "370"}, + "LU": {CC: "352"}, + "LV": {CC: "371"}, + "LY": {CC: "218"}, + "MA": {CC: "212"}, + "MC": {CC: "377"}, + "MD": {CC: "373"}, + "ME": {CC: "382"}, + "MF": {CC: "590"}, + "MG": {CC: "261"}, + "MH": {CC: "692"}, + "MK": {CC: "389"}, + "ML": {CC: "223"}, + "MM": {CC: "95"}, + "MN": {CC: "976"}, + "MO": {CC: "853"}, + "MP": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1670"}}, + }}, + "MQ": {CC: "596"}, + "MR": {CC: "222"}, + "MS": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1664"}}, + }}, + "MT": {CC: "356"}, + "MU": {CC: "230"}, + "MV": {CC: "960"}, + "MW": {CC: "265"}, + "MX": {CC: "52"}, + "MY": {CC: "60"}, + "MZ": {CC: "258"}, + "NA": {CC: "264"}, + "NC": {CC: "687"}, + "NE": {CC: "227"}, + "NF": {CC: "672"}, + "NG": {CC: "234"}, + "NI": {CC: "505"}, + "NL": {CC: "31"}, + "NO": {CC: "47"}, + "NP": {CC: "977"}, + "NR": {CC: "674"}, + "NU": {CC: "683"}, + "NZ": {CC: "64"}, + "OM": {CC: "968"}, + "PA": {CC: "507"}, + "PE": {CC: "51"}, + "PF": {CC: "689"}, + "PG": {CC: "675"}, + "PH": {CC: "63"}, + "PK": {CC: "92"}, + "PL": {CC: "48"}, + "PM": {CC: "508"}, + "PN": {CC: "64"}, + "PR": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1787", "1939"}}, + }}, + "PS": {CC: "970"}, + "PT": {CC: "351"}, + "PW": {CC: "680"}, + "PY": {CC: "595"}, + "QA": {CC: "974"}, + "QN": {CC: "374"}, + "RE": {CC: "262"}, + "RO": {CC: "40"}, + "RS": {CC: "381"}, + "RU": {CC: "7", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"71", "73", "74", "75", "78", "79"}}, + }}, + "RW": {CC: "250"}, + "SA": {CC: "966"}, + "SB": {CC: "677"}, + "SC": {CC: "248"}, + "SD": {CC: "249"}, + "SE": {CC: "46"}, + "SG": {CC: "65"}, + "SH": {CC: "290"}, + "SI": {CC: "386"}, + "SJ": {CC: "47"}, + "SK": {CC: "421"}, + "SL": {CC: "232"}, + "SM": {CC: "378"}, + "SN": {CC: "221"}, + "SO": {CC: "252"}, + "SR": {CC: "597"}, + "SS": {CC: "211"}, + "ST": {CC: "239"}, + "SV": {CC: "503"}, + "SX": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1721"}}, + }}, + "SY": {CC: "963"}, + "SZ": {CC: "268"}, + "TA": {CC: "290"}, + "TC": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1649"}}, + }}, + "TD": {CC: "235"}, + "TF": {CC: "262"}, + "TG": {CC: "228"}, + "TH": {CC: "66"}, + "TJ": {CC: "992"}, + "TK": {CC: "690"}, + "TL": {CC: "670"}, + "TM": {CC: "993"}, + "TN": {CC: "216"}, + "TO": {CC: "676"}, + "TR": {CC: "90"}, + "TT": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1868"}}, + }}, + "TV": {CC: "688"}, + "TW": {CC: "886"}, + "TZ": {CC: "255"}, + "UA": {CC: "380"}, + "UG": {CC: "256"}, + "UN": {CC: "888"}, + "US": {CC: "1", Groups: []InPrefixGroup{ + {"Alabama", 1, 1, []string{"1205", "1251", "1256", "1334", "1483", "1659", "1938"}}, + {"Alaska", 1, 1, []string{"1907"}}, + {"Arizona", 1, 1, []string{"1480", "1520", "1602", "1623", "1928"}}, + {"Arkansas", 1, 1, []string{"1327", "1479", "1501", "1870"}}, + {"California", 1, 1, []string{"1209", "1213", "1279", "1310", "1323", "1341", "1350", "1357", "1369", "1408", "1415", "1424", "1442", "1510", "1530", "1559", "1562", "1619", "1626", "1628", "1650", "1657", "1661", "1669", "1707", "1714", "1738", "1747", "1760", "1805", "1818", "1820", "1831", "1837", "1840", "1858", "1909", "1916", "1925", "1949", "1951"}}, + {"Colorado", 1, 1, []string{"1303", "1719", "1720", "1748", "1970", "1983"}}, + {"Connecticut", 1, 1, []string{"1203", "1475", "1860", "1959"}}, + {"Delaware", 1, 1, []string{"1302"}}, + {"District of Columbia", 1, 1, []string{"1202", "1771"}}, + {"Florida", 1, 1, []string{"1239", "1305", "1321", "1324", "1352", "1386", "1407", "1448", "1561", "1645", "1656", "1689", "1727", "1728", "1754", "1772", "1786", "1813", "1850", "1863", "1904", "1941", "1954"}}, + {"Georgia", 1, 1, []string{"1229", "1404", "1470", "1478", "1678", "1706", "1762", "1770", "1912", "1943"}}, + {"Hawaii", 1, 1, []string{"1808"}}, + {"Idaho", 1, 1, []string{"1208", "1986"}}, + {"Illinois", 1, 1, []string{"1217", "1224", "1309", "1312", "1331", "1447", "1464", "1618", "1630", "1708", "1730", "1773", "1779", "1815", "1847", "1861", "1872"}}, + {"Indiana", 1, 1, []string{"1219", "1260", "1317", "1463", "1574", "1765", "1812", "1930"}}, + {"Iowa", 1, 1, []string{"1319", "1515", "1563", "1641", "1712"}}, + {"Kansas", 1, 1, []string{"1316", "1620", "1785", "1913"}}, + {"Kentucky", 1, 1, []string{"1270", "1364", "1502", "1606", "1859"}}, + {"Louisiana", 1, 1, []string{"1225", "1318", "1337", "1457", "1504", "1985"}}, + {"Maine", 1, 1, []string{"1207"}}, + {"Maryland", 1, 1, []string{"1227", "1240", "1301", "1410", "1443", "1667"}}, + {"Massachusetts", 1, 1, []string{"1339", "1351", "1413", "1508", "1617", "1774", "1781", "1857", "1978"}}, + {"Michigan", 1, 1, []string{"1231", "1248", "1269", "1313", "1517", "1586", "1616", "1679", "1734", "1810", "1906", "1947", "1989"}}, + {"Minnesota", 1, 1, []string{"1218", "1320", "1507", "1612", "1651", "1763", "1924", "1952"}}, + {"Mississippi", 1, 1, []string{"1228", "1471", "1601", "1662", "1769"}}, + {"Missouri", 1, 1, []string{"1235", "1314", "1417", "1557", "1573", "1636", "1660", "1816", "1975"}}, + {"Montana", 1, 1, []string{"1406"}}, + {"Nebraska", 1, 1, []string{"1308", "1402", "1531"}}, + {"Nevada", 1, 1, []string{"1702", "1725", "1775"}}, + {"New Hampshire", 1, 1, []string{"1603"}}, + {"New Jersey", 1, 1, []string{"1201", "1551", "1609", "1640", "1732", "1848", "1856", "1862", "1908", "1973"}}, + {"New Mexico", 1, 1, []string{"1505", "1575"}}, + {"New York", 1, 1, []string{"1212", "1315", "1329", "1332", "1347", "1363", "1516", "1518", "1585", "1607", "1624", "1631", "1646", "1680", "1716", "1718", "1838", "1845", "1914", "1917", "1929", "1934"}}, + {"North Carolina", 1, 1, []string{"1252", "1336", "1472", "1704", "1743", "1828", "1910", "1919", "1980", "1984"}}, + {"North Dakota", 1, 1, []string{"1701"}}, + {"Ohio", 1, 1, []string{"1216", "1220", "1234", "1283", "1326", "1330", "1380", "1419", "1436", "1440", "1513", "1567", "1614", "1740", "1937"}}, + {"Oklahoma", 1, 1, []string{"1405", "1539", "1572", "1580", "1918"}}, + {"Oregon", 1, 1, []string{"1458", "1503", "1541", "1971"}}, + {"Pennsylvania", 1, 1, []string{"1215", "1223", "1267", "1272", "1412", "1445", "1484", "1570", "1582", "1610", "1717", "1724", "1814", "1835", "1878"}}, + {"Rhode Island", 1, 1, []string{"1401"}}, + {"South Carolina", 1, 1, []string{"1803", "1821", "1839", "1843", "1854", "1864"}}, + {"South Dakota", 1, 1, []string{"1605"}}, + {"Tennessee", 1, 1, []string{"1423", "1615", "1629", "1731", "1865", "1901", "1931"}}, + {"Texas", 1, 1, []string{"1210", "1214", "1254", "1281", "1325", "1346", "1361", "1409", "1430", "1432", "1469", "1512", "1621", "1682", "1713", "1726", "1737", "1806", "1817", "1830", "1832", "1903", "1915", "1936", "1940", "1945", "1956", "1972", "1979"}}, + {"Utah", 1, 1, []string{"1385", "1435", "1801"}}, + {"Vermont", 1, 1, []string{"1802"}}, + {"Virginia", 1, 1, []string{"1276", "1434", "1540", "1571", "1686", "1703", "1757", "1804", "1826", "1948"}}, + {"Washington", 1, 1, []string{"1206", "1253", "1360", "1425", "1509", "1564"}}, + {"West Virginia", 1, 1, []string{"1304", "1681"}}, + {"Wisconsin", 1, 1, []string{"1262", "1274", "1353", "1414", "1534", "1608", "1715", "1920"}}, + {"Wyoming", 1, 1, []string{"1307"}}, + {"Midway Atoll, Wake Island, Hawaii", 1, 1, []string{"1808"}}, + {"US government", 4, 5, []string{"1710"}}, + }}, + "UY": {CC: "598"}, + "UZ": {CC: "998"}, + "VA": {CC: "39", Groups: []InPrefixGroup{ + {"Vatican City", 0, 1, []string{"3906698"}}, + {"", 0, 0, []string{"379"}}, + }}, + "VC": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1784"}}, + }}, + "VE": {CC: "58"}, + "VG": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1284"}}, + }}, + "VI": {CC: "1", Groups: []InPrefixGroup{ + {"", 0, 0, []string{"1340"}}, + }}, + "VN": {CC: "84"}, + "VU": {CC: "678"}, + "WF": {CC: "681"}, + "WS": {CC: "685"}, + "XK": {CC: "383"}, + "YE": {CC: "967"}, + "YT": {CC: "262"}, + "ZA": {CC: "27"}, + "ZM": {CC: "260"}, + "ZW": {CC: "263"}, + "__": {CC: "", Groups: []InPrefixGroup{ + {"Universal International Freephone Service", 4, 5, []string{"800"}}, + {"Universal International Shared Cost Number", 4, 5, []string{"808"}}, + {"Inmarsat", 4, 5, []string{"870"}}, + {"Universal Personal Telecommunications", 4, 5, []string{"878"}}, + {"Global Mobile Satellite System", 4, 5, []string{"881"}}, + {"International Networks", 4, 5, []string{"882", "883"}}, + {"International premium rate service", 4, 5, []string{"979"}}, + {"International Telecommunications Public Correspondence Service", 4, 5, []string{"991"}}, + }}, + } +} diff --git a/pkg/countryphone/example_countryphone_test.go b/pkg/countryphone/example_countryphone_test.go new file mode 100644 index 00000000..b0519c26 --- /dev/null +++ b/pkg/countryphone/example_countryphone_test.go @@ -0,0 +1,38 @@ +package countryphone_test + +import ( + "encoding/json" + "fmt" + "log" + + "github.com/Vonage/gosrvlib/pkg/countryphone" +) + +func ExampleData_NumberType() { + // load defaut data + data := countryphone.New(nil) + + info, err := data.NumberInfo("1357123456") + if err != nil { + log.Fatal(err) + } + + b, err := json.MarshalIndent(info, "", " ") + if err != nil { + log.Fatal(err) + } + + fmt.Println(string(b)) + + // Output: + // { + // "type": 1, + // "geo": [ + // { + // "alpha2": "US", + // "area": "California", + // "type": 1 + // } + // ] + // } +}