phony 2.15.25 → 2.20.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/README.textile +35 -7
  3. data/lib/phony/config.rb +91 -0
  4. data/lib/phony/countries/argentina.rb +355 -0
  5. data/lib/phony/countries/austria.rb +32 -24
  6. data/lib/phony/countries/bangladesh.rb +2 -0
  7. data/lib/phony/countries/belarus.rb +2 -0
  8. data/lib/phony/countries/brazil.rb +6 -4
  9. data/lib/phony/countries/cambodia.rb +6 -4
  10. data/lib/phony/countries/china.rb +7 -2
  11. data/lib/phony/countries/croatia.rb +13 -16
  12. data/lib/phony/countries/georgia.rb +6 -4
  13. data/lib/phony/countries/germany.rb +5 -2
  14. data/lib/phony/countries/guinea.rb +8 -5
  15. data/lib/phony/countries/india.rb +2 -0
  16. data/lib/phony/countries/indonesia.rb +7 -2
  17. data/lib/phony/countries/ireland.rb +27 -23
  18. data/lib/phony/countries/italy.rb +30 -17
  19. data/lib/phony/countries/japan.rb +61 -8
  20. data/lib/phony/countries/kyrgyzstan.rb +2 -0
  21. data/lib/phony/countries/latvia.rb +2 -0
  22. data/lib/phony/countries/libya.rb +3 -1
  23. data/lib/phony/countries/malaysia.rb +22 -2
  24. data/lib/phony/countries/moldova.rb +2 -0
  25. data/lib/phony/countries/montenegro.rb +2 -0
  26. data/lib/phony/countries/myanmar.rb +2 -0
  27. data/lib/phony/countries/namibia.rb +2 -0
  28. data/lib/phony/countries/nepal.rb +2 -0
  29. data/lib/phony/countries/netherlands.rb +2 -0
  30. data/lib/phony/countries/pakistan.rb +2 -0
  31. data/lib/phony/countries/paraguay.rb +2 -0
  32. data/lib/phony/countries/russia_kazakhstan_abkhasia_south_ossetia.rb +24 -14
  33. data/lib/phony/countries/saudi_arabia.rb +3 -0
  34. data/lib/phony/countries/serbia.rb +7 -1
  35. data/lib/phony/countries/somalia.rb +5 -1
  36. data/lib/phony/countries/south_korea.rb +16 -9
  37. data/lib/phony/countries/sweden.rb +29 -17
  38. data/lib/phony/countries/taiwan.rb +22 -46
  39. data/lib/phony/countries/tajikistan.rb +2 -0
  40. data/lib/phony/countries/turkmenistan.rb +2 -0
  41. data/lib/phony/countries/ukraine.rb +3 -0
  42. data/lib/phony/countries/united_kingdom.rb +5 -2
  43. data/lib/phony/countries/uruguay.rb +2 -0
  44. data/lib/phony/countries/vietnam.rb +94 -92
  45. data/lib/phony/countries/zimbabwe.rb +2 -0
  46. data/lib/phony/countries.rb +181 -78
  47. data/lib/phony/country.rb +15 -3
  48. data/lib/phony/country_codes.rb +17 -4
  49. data/lib/phony/dsl.rb +5 -3
  50. data/lib/phony/local_splitters/fixed.rb +2 -0
  51. data/lib/phony/national_code.rb +1 -1
  52. data/lib/phony/national_splitters/none.rb +1 -3
  53. data/lib/phony/trunk_code.rb +5 -4
  54. data/lib/phony/vanity.rb +1 -1
  55. data/lib/phony.rb +94 -60
  56. data/spec/functional/config_spec.rb +44 -0
  57. data/spec/functional/plausibility_spec.rb +364 -32
  58. data/spec/lib/phony/countries_spec.rb +245 -52
  59. data/spec/lib/phony/country_codes_spec.rb +106 -33
  60. data/spec/lib/phony/country_spec.rb +54 -15
  61. data/spec/lib/phony/dsl_spec.rb +2 -2
  62. data/spec/lib/phony/local_splitters/regex_spec.rb +12 -5
  63. data/spec/lib/phony/national_splitters/default_spec.rb +1 -1
  64. data/spec/lib/phony/trunk_code_spec.rb +85 -0
  65. data/spec/lib/phony/vanity_spec.rb +30 -0
  66. data/spec/lib/phony_spec.rb +70 -0
  67. metadata +26 -18
@@ -1,4 +1,6 @@
1
1
  # -*- coding: utf-8 -*-
2
+ # frozen_string_literal: true
3
+
2
4
  # All countries, ordered by country code.
3
5
  #
4
6
  # Definitions are in the format:
@@ -67,7 +69,7 @@ Phony.define do
67
69
  country '20', one_of('800') >> split(7..7) | # Egypt toll free
68
70
  one_of('3') >> split(7..7) | # Alexandria
69
71
  one_of('2') >> split(8..8) | # Cairo/Giza
70
- one_of('10', '11', '12') >> split(8..8) | # the 3 mobile operators
72
+ one_of('10', '11', '12', '15') >> split(8..8) | # the 4 mobile operators
71
73
  fixed(2) >> split(7..7) # all the other 24 provinces
72
74
 
73
75
  # South Africa.
@@ -94,13 +96,16 @@ Phony.define do
94
96
  # Belgium.
95
97
  #
96
98
  # http://en.wikipedia.org/wiki/Telephone_numbers_in_Belgium
99
+ # https://www.bipt.be/operators/publication/national-numbering-plan
97
100
  #
98
101
  country '32', trunk('0') |
99
- match(/^(70|800|90\d)\d+$/) >> split(3,3) | # Service
100
- match(/^(46[0568])\d{6}$/) >> split(2,2,2) | # Mobile (Lycamobile, Telenet, Proximus 0460)
101
- match(/^(4[789]\d)\d{6}$/) >> split(2,2,2) | # Mobile
102
- one_of('2','3','4','9') >> split(3,2,2) | # Short NDCs
103
- fixed(2) >> split(2,2,2) # 2-digit NDCs
102
+ match(/^(7[08])\d+$/) >> split(3,3) | # Premium and national rate Services
103
+ match(/^(800|90\d)\d+$/) >> split(2,3) | # Toll free service and premium numbers
104
+ match(/^(46[056789])\d{6}$/) >> split(2,2,2) | # Mobile (Lycamobile, Telenet, Join Experience, Proximus 0460)
105
+ match(/^(4[789]\d)\d{6}$/) >> split(2,2,2) | # Mobile
106
+ match(/^(45[56])\d{6}$/) >> split(2,2,2) | # Mobile Vikings and Voo
107
+ one_of('2','3','4','9') >> split(3,2,2) | # Short NDCs
108
+ fixed(2) >> split(2,2,2) # 2-digit NDCs
104
109
 
105
110
  # France.
106
111
  #
@@ -121,11 +126,19 @@ Phony.define do
121
126
 
122
127
  # Hungary.
123
128
  #
129
+ # http://webpub-ext.nmhh.hu/aga/foldr/DoIndexAction.do
130
+ #
124
131
  country '36',
125
132
  trunk('06', normalize: false) |
126
- one_of('104','105','107','112') >> split(3,3) | # Service
127
- one_of('1') >> split(3,4) | # Budapest
128
- fixed(2) >> split(3,4) # 2-digit NDCs
133
+ one_of('104', '105', '107', '112') >> split(3,3) | # Service
134
+ one_of('1') >> split(3,4) | # Budapest
135
+ one_of('20', '30', '31', '50', '70') >> split(3,4) | # Mobile
136
+ one_of('21') >> split(3,4) | # VOIP
137
+ one_of('40', '80', '90', '91') >> split(3,3) | # Special charged numbers
138
+ one_of('51') >> split(3,3) | # Corporate network, M2M
139
+ one_of('38') >> split(3,4) | # Corporate network, M2M
140
+ one_of('71') >> split(5,5) | # M2M Numbers
141
+ fixed(2) >> split(3,3) # Geographic numbers
129
142
 
130
143
  # country '39' # Italy, see special file.
131
144
 
@@ -142,7 +155,9 @@ Phony.define do
142
155
  #
143
156
  country '41',
144
157
  trunk('0', normalize: true) |
145
- match(/^(8(00|4[0248]))\d+$/) >> split(3,3)|
158
+ match(/^(860)\d+$/) >> split(2, 3, 2, 2) | # Voice Mail access
159
+ match(/^(8(?:00|4[0248]))\d+$/) >> split(3,3) | # Freecall/Shared Cost
160
+ match(/^(90[016])\d+$/) >> split(3,3) | # Business
146
161
  fixed(2) >> split(3,2,2)
147
162
 
148
163
  # country '43' # Austria, see special file.
@@ -167,17 +182,19 @@ Phony.define do
167
182
  # Note: http://wapedia.mobi/en/Telephone_numbers_in_Poland, mobile not yet correct
168
183
  #
169
184
  country '48',
170
- match(/^(5[013]\d|6[069]\d|7[02389]\d|80[01]|88\d)/) >> split(3,3) |
185
+ match(/^(45\d|5[0137]\d|6[069]\d|7[02389]\d|80[01]|88\d)/) >> split(3,3) |
171
186
  fixed(2) >> split(3,2,2)
172
187
 
173
188
  # country '49' # Germany, see special file.
174
189
 
175
190
  # Peru.
176
- #
191
+ # Note: https://en.wikipedia.org/wiki/Telephone_numbers_in_Peru
192
+ # Note: https://www.numberingplans.com/?page=plans&sub=phonenr&alpha_2_input=PE
177
193
  country '51',
178
194
  one_of('103', '105') >> split(3,3) | # Service.
179
- one_of('1', '9') >> split(4,4) | # Lima and mobile.
180
- fixed(2) >> split(4,4) # 2-digit NDCs.
195
+ one_of('9') >> split(4,4) | # Mobile.
196
+ one_of('1') >> split(3,4) | # Lima.
197
+ fixed(2) >> split(3,3) # 2-digit NDCs.
181
198
 
182
199
  # Mexico.
183
200
  #
@@ -198,14 +215,7 @@ Phony.define do
198
215
  fixed(3) >> split(7) # 3-digit NDCs
199
216
 
200
217
  # Argentine Republic.
201
- #
202
- country '54',
203
- one_of('11', '911') >> split(4,4) | # Fixed & Mobile
204
- match(/^(22[0137]|237|26[14]|29[179]|34[1235]|35[138]|38[1578])/) >> split(3,4) | # Fixed
205
- match(/^(922[0137]|9237|926[14]|929[179]|934[1235]|935[138]|938[1578])/) >> split(3,4) | # Mobile
206
- match(/^(9\d{4})/) >> split(2,4) | # Mobile
207
- match(/^([68]\d{2})/) >> split(3,4) | # Service
208
- fixed(4) >> split(2,4) # Fixed
218
+ # country '54' # argentina, see special file.
209
219
 
210
220
  # Brazil (Federative Republic of).
211
221
  # http://en.wikipedia.org/wiki/Telephone_numbers_in_Brazil
@@ -222,6 +232,7 @@ Phony.define do
222
232
  # http://www.itu.int/oth/T020200002C/en
223
233
  country '57',
224
234
  match(/\A(3\d\d)\d+\z/) >> split(3,4) | # mobile (300 310 311 312 313 315 316)
235
+ match(/\A(60\d)\d+\z/) >> split(3,4) |
225
236
  fixed(1) >> split(3,4)
226
237
 
227
238
  # Venezuela (Bolivarian Republic of)
@@ -234,7 +245,7 @@ Phony.define do
234
245
  # Australia.
235
246
  #
236
247
  country '61',
237
- trunk('0') |
248
+ trunk('0', format: false) |
238
249
  match(/^(4\d\d)\d+$/) >> split(3,3) | # Mobile
239
250
  match(/^(1800)\d+$/) >> split(3,3) | # 1800 free call
240
251
  match(/^(1300)\d+$/) >> split(3,3) | # 1300 local rate
@@ -249,9 +260,10 @@ Phony.define do
249
260
  trunk('0') |
250
261
  # 7/10 digits for area code '2'.
251
262
  match(/\A(2)\d{10}\z/) >> split(10) |
263
+ match(/\A(2)\d{8}\z/) >> split(8) |
252
264
  one_of('2') >> split(7) |
253
265
  # mobile
254
- match(/\A(9\d\d)\d{7}\z/) >> split(7) |
266
+ match(/\A([89]\d\d)\d{7}\z/) >> split(7) |
255
267
  match(/\A(9\d\d)\d+\z/) >> split(6) |
256
268
  #
257
269
  fixed(2) >> split(7)
@@ -263,12 +275,17 @@ Phony.define do
263
275
  match(/^(2\d)\d{7}$/) >> split(3,4) | # Mobile
264
276
  match(/^(2\d)\d{6}$/) >> split(3,3) |
265
277
  match(/^(2\d)\d{8}$/) >> split(2,3,3) |
278
+ match(/^(800)\d{6}$/) >> split(3,3) | # International 800 service where agreed
279
+ match(/^(800)\d{7}$/) >> split(3,4) | # International 800 service where agreed
266
280
  fixed(1) >> split(3,4) # Rest
267
281
 
268
282
  # Singapore (Republic of).
269
283
  #
270
284
  country '65',
271
- none >> split(4,4) # TODO Short Codes.
285
+ none >> matched_split(
286
+ /^(800)\d{7}$/ => [3,3,4], # International Toll Free Service (ITFS) and Home Country Direct Service (HCDS) Numbers
287
+ /^\d{8}$/ => [4,4] # TODO Short Codes
288
+ )
272
289
 
273
290
  # Thailand.
274
291
  #
@@ -338,13 +355,13 @@ Phony.define do
338
355
 
339
356
  # Côte d'Ivoire
340
357
  # http://www.wtng.info/wtng-225-ci.html
341
- # http://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000310001PDFE.pdf
358
+ # https://www.itu.int/dms_pub/itu-t/oth/02/02/T02020000310006PDFE.pdf
342
359
  # http://en.wikipedia.org/wiki/Telephone_numbers_in_Ivory_Coast
343
360
  #
344
361
  # There is no trunk code for this country and several of the mobile prefixes start with 0
345
362
  country '225',
346
363
  trunk('', :normalize => false) |
347
- fixed(2) >> split(2,2,2)
364
+ fixed(2) >> split(2,2,2,2)
348
365
 
349
366
  country '226', none >> split(4,4) # Burkina Faso http://www.wtng.info/wtng-226-bf.html
350
367
  country '227', none >> split(4,4) # Niger http://www.wtng.info/wtng-227-ne.html
@@ -369,18 +386,25 @@ Phony.define do
369
386
  # Ghana
370
387
  #
371
388
  # From http://www.itu.int/oth/T0202000052/en
389
+ # https://en.wikipedia.org/wiki/Telephone_numbers_in_Ghana
372
390
  #
373
- country '233', fixed(2) >> split(3,4)
391
+ country '233', trunk('0') | fixed(2) >> split(3,4)
374
392
 
375
393
  # Nigeria
376
- # Wikipedia says 3 4 split, many local number with no splitting
394
+ # 3 4 split for mobile and 1 digit NDC, 3 2 or 3 3 otherwise
395
+ # Many local numbers with no splitting
377
396
  #
378
- # mobile telephony number allocation taken from: http://www.ncc.gov.ng/index.php?option=com_content&view=article&id=113&Itemid=102
397
+ # mobile telephony number allocation taken from:
398
+ # https://www.ncc.gov.ng/technical-regulation/standards/numbering and
399
+ # https://www.itu.int/oth/T020200009C/en
379
400
  country '234',
380
- match(/^([7-9]0\d)\d+$/) >> split(3,4) | # Mobile
381
- match(/^(81\d)\d+$/) >> split(3,4) | # Mobile
382
- one_of('1', '2', '9') >> split(3,4) | # Lagos, Ibadan and Abuja
383
- fixed(2) >> split(3,4) # 2-digit NDC
401
+ match(/^([7-9]0\d)\d+$/) >> split(3,4) | # Mobile
402
+ match(/^(81\d)\d+$/) >> split(3,4) | # Mobile
403
+ match(/^(91\d)\d+$/) >> split(3,4) | # Mobile
404
+ one_of('1', '2') >> split(3,3..4) | # Lagos, Ibadan
405
+ one_of('9') >> split(3,4) | # Abuja
406
+ one_of((30..79).map(&:to_s)) >> split(3,2..3) | # 2-digit NDC
407
+ one_of(%w(82 83 84 85 86 87 88 89)) >> split(3,3) # 2-digit NDC
384
408
 
385
409
  country '235', none >> split(4,4) # Chad http://www.wtng.info/wtng-235-td.html
386
410
  country '236', none >> split(4,4) # Central African Republic http://www.wtng.info/wtng-236-cf.html
@@ -389,8 +413,12 @@ Phony.define do
389
413
  country '239', fixed(1) >> split(3,3) # Sao Tome and Principe, http://www.wtng.info/wtng-239-st.html
390
414
 
391
415
  country '240', none >> split(3,3,3) # Equatorial Guinea
392
- country '241', fixed(1) >> split(3,3) # Gabonese Republic http://www.wtng.info/wtng-241-ga.html
393
- country '242', none >> split(4,5) # Congo http://www.wtng.info/wtng-242-cg.html
416
+ country '241',
417
+ match(/^(\d)\d{6}$/) >> split(3,3) | # Gabonese Republic http://www.wtng.info/wtng-241-ga.html
418
+ match(/^(\d\d)\d{6}$/) >> split(2,2,2) # 2019 update https://en.wikipedia.org/wiki/Telephone_numbers_in_Gabon
419
+ country '242', # Congo http://www.wtng.info/wtng-242-cg.html
420
+ trunk('', :normalize => false) |
421
+ none >> split(4,5)
394
422
  country '243', fixed(2) >> split(3,4) # Democratic Republic of the Congo http://www.wtng.info/wtng-243-cd.html
395
423
  country '244', one_of('321', '348', '358', '363', '364', '485', '526', '535', '546', '612', '643', '652', '655', '722', '726', '728', '729', '777') >> split(3,3) | # Angola
396
424
  fixed(2) >> split(3,4)
@@ -407,9 +435,9 @@ Phony.define do
407
435
  # http://en.wikipedia.org/wiki/Telephone_numbers_in_Rwanda
408
436
  country '250',
409
437
  trunk('0') |
410
- one_of('25') >> split(7) | # Geographic, fixed
411
- match(/^(7[238])/) >> split(7) | # Non-geographic, mobile
412
- one_of('06') >> split(6) # Satellite
438
+ one_of('25') >> split(7) | # Geographic, fixed
439
+ match(/^(7[2389])/) >> split(7) | # Non-geographic, mobile
440
+ one_of('06') >> split(6) # Satellite
413
441
 
414
442
  country '251', fixed(2) >> split(3, 4) # Ethiopia http://www.wtng.info/wtng-251-et.html
415
443
 
@@ -459,25 +487,33 @@ Phony.define do
459
487
 
460
488
  # Zambia
461
489
  # http://www.wtng.info/wtng-260-zm.html
490
+ # https://github.com/googlei18n/libphonenumber/
491
+ # https://en.wikipedia.org/wiki/Telephone_numbers_in_Zambia
492
+
462
493
  country '260',
463
- match(/^(9(55|66|7[7-9]))/) >> split(6) | # mobile
464
- match(/^(21[1-8])/) >> split(6) # fixed
494
+ trunk('0') |
495
+ match(/^(75|76|77|94|95|96|97)/) >> split(3, 4) | # Mobile
496
+ match(/^(800)/) >> split(3,3) | # Toll free
497
+ match(/^(21[1-8])/) >> split(6) # Fixed
465
498
 
466
- # Madagascar http://www.wtng.info/wtng-261-mg.html
499
+ # Madagascar
500
+ # https://en.wikipedia.org/wiki/Telephone_numbers_in_Madagascar
467
501
  # http://www.itu.int/oth/T020200007F/en
468
502
  country '261',
469
- none >> matched_split(
470
- /\A200\d+\z/ => [2,3,3,3], # Telecom Malagasy (Telma)
471
- /\A20\d+\z/ => [2,3,4], # Telecom Malagasy (Telma)
472
- /\A23\d+\z/ => [2,3,4], # Digitel
473
- /\A30\d+\z/ => [2,3,4], # mobile Madamobil (CDMA2000)
474
- /\A31\d+\z/ => [2,3,4], # mobile Sacel
475
- /\A32\d+\z/ => [2,3,4], # mobile Orange Madagascar
476
- /\A34\d+\z/ => [2,3,4], # mobile Telecom Malagasy (Telma)
477
- /\A5\d+\z/ => [3,3,3], # pager
478
- /\A22\d+\z/ => [3,3,3], # satellite GULFSAT Téléphonie
479
- /\A6\d+\z/ => [3,3,3] # satellite
480
- )
503
+ # none >> matched_split(
504
+ # /\A20\d+\z/ => [2,2,3,2], # Telecom Malagasy (Telma)
505
+ # /\A32\d+\z/ => [2,2,3,2], # mobile Orange Madagascar
506
+ # /\A33\d+\z/ => [2,2,3,2], # mobile Airtel Madagascar
507
+ # /\A34\d+\z/ => [2,2,3,2], # mobile Telecom Malagasy (Telma)
508
+ # /\A38\d+\z/ => [2,2,3,2], # mobile Telecom Malagasy (Telma)
509
+ # /\A39\d+\z => [2,2,3,2] # mobile Blueline
510
+ # ),
511
+ match(/\A(20)\d+\z/) >> split(2,3,2) | # fix Telecom Malagasy (Telma)
512
+ match(/\A(32)\d+\z/) >> split(2,3,2) | # mobile Orange Madagascar
513
+ match(/\A(33)\d+\z/) >> split(2,3,2) | # mobile Airtel Madagascar
514
+ match(/\A(34)\d+\z/) >> split(2,3,2) | # mobile Telecom Malagasy (Telma)
515
+ match(/\A(38)\d+\z/) >> split(2,3,2) | # mobile Telecom Malagasy (Telma)
516
+ match(/\A(39)\d+\z/) >> split(2,3,2) # mobile Blueline Madagascar
481
517
 
482
518
  country '262', # Reunion / Mayotte (new) http://www.wtng.info/wtng-262-fr.html
483
519
  trunk('0') |
@@ -612,8 +648,12 @@ Phony.define do
612
648
  # country '353' # Republic of Ireland, see special file.
613
649
 
614
650
  country '354', none >> split(3,4) # Iceland
651
+
652
+ # Albania
653
+ # https://en.wikipedia.org/wiki/Telephone_numbers_in_Albania
615
654
  country '355', trunk('0') |
616
- one_of('4') >> split(4,3) | # Albania
655
+ one_of('4') >> split(3,4) | # Tirana
656
+ match(/\A(6[6-9])\d*\z/) >> split(3,4) | # mobile
617
657
  match(/\A(2[24]|3[2-5]|47|5[2-5]|6[6-9]|8[2-5])\d*\z/) >> split(3,3) |
618
658
  fixed(3) >> split(3,2)
619
659
 
@@ -634,17 +674,48 @@ Phony.define do
634
674
  #
635
675
  country '358',
636
676
  trunk('0') |
637
- match(/^([1-3]0)\d+$/) >> split(3,3,0..6) | # Service/subscriber
638
- match(/^([6-8]00)\d+$/) >> split(3,3) | # Service
639
- match(/^(457|4\d|50)\d+$/) >> split(3,2,0..2) | # Mobile
640
- one_of('2','3','5','6','8','9') >> split(3,2..4) | # Short NDCs
641
- fixed(2) >> split(3,3) # 2-digit NDCs
677
+ match(/^(600[3-5]\d|601\d\d|700[3457]\d|7500[12]|7532[12]|7575[12]|7598[12])\d{3,4}$/) >> split(3..4) | # national service numbers, 5-digit NDC
678
+ match(/^(753[02][3-9]|7575[3-9]|7598[3-9])\d{3,5}$/) >> split(3..5) | # national subscriber numbers, 5-digit NDC
679
+ match(/^(73[0-4]\d\d)\d{5}$/) >> split(5) | # national subscriber numbers, 5-digit NDC (starting with 073)
680
+ match(/^(202[023]|209[8-9]|600[0126-9]|700[0126]|7099|800\d)\d{4,5}$/) >> split(2, 2..3) | # national service numbers, 4-digit NDCs
681
+ match(/^(606\d|70[78]\d)\d{6}$/) >> split(3, 3) | # national service numbers, 4-digit NDCs (starting with 0606/0707/0708)
682
+ match(/^(202[14-9]|209[0-7])\d{4,6}$/) >> split(3, 1..3) | # national subscriber numbers, 4-digit NDCs
683
+ match(/^(45[45789]\d)\d{2,6}$/) >> split(2, 0..4) | # mobile numbers, 4-digit NDCs
684
+ match(/^([123]00|602)\d{5,6}$/) >> split(3, 2..3) | # national service numbers, 3-digit NDCs
685
+ match(/^(10[1-9]|20[13-8]|30[1-9]|73[5-9])\d{5,7}$/) >> split(3, 2..4) | # national subscriber numbers, 3-digit NDCs
686
+ match(/^(71\d)\d{6}$/) >> split(3, 3) | # national subscriber numbers, 3-digit NDCs (starting with 071)
687
+ match(/^(73[5-9])\d{7}$/) >> split(3, 4) | # national subscriber numbers, 3-digit NDCs (starting with 073)
688
+ match(/^(43\d|45[0-36])\d{5,7}$/) >> split(3, 2..4) | # mobile numbers, 3-digit NDCs
689
+ match(/^(49\d)\d{8}$/) >> split(3, 3, 2) | # mobile numbers, 3-digit NDCs (starting with 049)
690
+ match(/^([235]9)\d{6,8}$/) >> split(3, 3, 0..2) | # national subscriber numbers, 2-digit NDCs
691
+ match(/^(4[0124678]|50)\d{4,8}$/) >> split(3, 1..5) | # mobile numbers, 2-digit NDCs
692
+ one_of('2','3','5','6','8','9') >> split(3,1..5) | # Short NDCs
693
+ fixed(2) >> split(3, 0..4) # 2-digit NDCs
642
694
 
643
695
  # Bulgaria
644
696
  #
697
+ # Note: https://www.numberingplans.com/?page=plans&sub=phonenr&alpha_2_input=BG
698
+ # Note: https://en.wikipedia.org/wiki/Telephone_numbers_in_Bulgaria
645
699
  country '359',
646
700
  trunk('0') |
647
- fixed(2) >> split(3,2,2) # Bulgaria
701
+ match(/^(2)\d{6}$/) >> split(3,3) | # Landline Sofia (optional last digit)
702
+ match(/^(2)\d{7}$/) >> split(3,4) | # Landline Sofia (optional last digit)
703
+ match(/^(30|31|33|36|37|39|41|43\d|45|47|51|53|55|57|59)\d{5}$/) >> split(5) |
704
+ match(/^(30|31|32|33|34|35|36|37|38|39|41|42|44|45|46|47|51|52|53|54|55|56|57|58|59)\d{6}$/) >> split(2,4) |
705
+
706
+ match(/^(60|61|63|65|66|69)\d{5}$/) >> split(5) |
707
+ match(/^(60|61|62|63|64|65|66|68|69)\d{6}$/) >> split(6) |
708
+
709
+ match(/^(700|701|703|704|705|706|707|708|709)\d{5}$/) >> split(5) |
710
+ match(/^(701|702|703|704|705|706|707|708|709)\d{4}$/) >> split(4) |
711
+
712
+ match(/^(71|72|74|75|77)\d{5}$/) >> split(5) |
713
+ match(/^(71|72|73|74|75|76|77|78|79)\d{6}$/) >> split(6) |
714
+
715
+ match(/^(80\d|81|91|93|95|97)\d{5}$/) >> split(5) |
716
+ match(/^(81|82|84|86)\d{6}$/) >> split(6) |
717
+ match(/^(87|88|89)\d{7}$/) >> split(4,3) |
718
+ match(/^(90|91|92|93|94|95|96|97|98\d|99\d)\d{6}$/) >> split(6)
648
719
 
649
720
  # Lithuania
650
721
  #
@@ -678,11 +749,12 @@ Phony.define do
678
749
  # Monaco
679
750
  #
680
751
  country '377',
681
- one_of('6') >> split(2,2,2,2) | # mobile
752
+ one_of('6') >> split(2,2,2,2) | # mobile
682
753
  fixed(2) >> split(2,2,2)
683
754
 
684
755
  # San Marino
685
756
  country '378',
757
+ trunk('', :normalize => false) |
686
758
  none >> matched_split(
687
759
  /\A\d{6}\z/ => [3,3],
688
760
  /\A\d+\z/ => [3,3,4]
@@ -696,7 +768,13 @@ Phony.define do
696
768
 
697
769
  # country '382' # Montenegro, see special file
698
770
 
699
- country '383', todo # -
771
+ # Kosovo
772
+ #
773
+ # Note: https://en.wikipedia.org/wiki/Telephone_numbers_in_Kosovo
774
+ country '383',
775
+ trunk('0') |
776
+ fixed(2) >> split(3,3)
777
+
700
778
  country '384', todo # -
701
779
 
702
780
  # country '385' # Croatia, see special file.
@@ -710,7 +788,7 @@ Phony.define do
710
788
  one_of('1','2','3','4','5','7') >> split(3,4) | # Ljubljana, Maribor, Celje, Kranj, Nova Gorica, Novo mesto
711
789
  fixed(3) >> split(2,3) # catchall
712
790
 
713
- country '387', trunk('0') | fixed(2) >> split(3,2,2) # Bosnia and Herzegovina
791
+ country '387', trunk('0') | fixed(2) >> split(3,3) # Bosnia and Herzegovina
714
792
  country '388', trunk('0') | fixed(2) >> split(3,2,2) # Group of countries, shared code
715
793
 
716
794
  # The Former Yugoslav Republic of Macedonia
@@ -722,9 +800,11 @@ Phony.define do
722
800
 
723
801
  # Slovak Republic.
724
802
  #
725
- country '421', match(/^(9\d\d).+$/) >> split(6) | # Mobile
726
- one_of('2') >> split(8) | # Bratislava
727
- fixed(2) >> split(7) # 2-digit NDCs
803
+ country '421', match(/^(9\d\d).+$/) >> split(6) | # Mobile
804
+ match(/\A(2)1\d{2,4}\z/) >> split(3..5) | # Bratislava Short
805
+ match(/\A(\d{2})1\d{2,4}\z/) >> split(3..5) | # 2-digit NDCs Short
806
+ one_of('2') >> split(8) | # Bratislava
807
+ fixed(2) >> split(7) # 2-digit NDCs
728
808
 
729
809
  country '422', todo # Spare code
730
810
  country '423', none >> split(3,2,2) # Liechtenstein (Principality of)
@@ -796,7 +876,14 @@ Phony.define do
796
876
  one_of(%w(11 16 17 18 19)) >> split(3) | # audiotext
797
877
  fixed(3) >> split(4) # geographic, audiotext
798
878
 
799
- country '593', fixed(2) >> split(3, 4) # Ecuador http://www.wtng.info/wtng-593-ec.html
879
+ # Ecuador http://www.wtng.info/wtng-593-ec.html
880
+ # https://www.numberingplans.com/?page=plans&sub=phonenr&alpha_2_input=EC&current_page=1
881
+ # https://en.wikipedia.org/wiki/Telephone_numbers_in_Ecuador
882
+ country '593',
883
+ one_of('9') >> split(4,4) |
884
+ match(/\A([\d]{2})\d{7}\z/) >> split(3,4) |
885
+ fixed(1) >> split(3,4)
886
+
800
887
  country '594', fixed(3) >> split(3, 3) # French Guiana (French Department of) http://www.wtng.info/wtng-594-fr.html
801
888
 
802
889
  # country '595' # Paraguay (Republic of), see special file
@@ -842,7 +929,14 @@ Phony.define do
842
929
  one_of('115') >> split(4,4) | # voicemail (mobile)
843
930
  one_of(%w(28 29)) >> split(3,2) | # pager
844
931
  one_of(%w(16 18)) >> split(3,2) | # ISP
845
- one_of(%w(71 72 73 76)) >> split(3,3) | # mobile
932
+ one_of(%w(70 71 72 74 75 76 78 79)) >> split(3,3) | # mobile
933
+ one_of(%w(731 732 733 734 735 736 738 739)) >> split(2,3) | # mobile
934
+ one_of(%w(770)) >> split(2,3) | # wireless geographic; Port Moresby, National Capital District
935
+ one_of(%w(771)) >> split(2,3) | # wireless geographic; Momase region
936
+ one_of(%w(772)) >> split(2,3) | # wireless geographic; Highlands region
937
+ one_of(%w(7730)) >> split(1,3) | # wireless geographic; Southern region
938
+ one_of(%w(774)) >> split(2,3) | # wireless geographic; Islands region
939
+ one_of(%w(775)) >> split(2,3) | # mobile
846
940
  one_of(%w(80 81 82 83)) >> split(3,3) | # freephone
847
941
  one_of(%w(90 91 92 93)) >> split(3,3) | # geographic, ISDN
848
942
  one_of(%w(3 4 5 6 7 8 9)) >> split(3,3) # geographic
@@ -885,7 +979,7 @@ Phony.define do
885
979
  /\A800\d+\z/ => [3,3], # freephone
886
980
  /\A830\d+\z/ => [3,3], # shared cost
887
981
  /\A60\d+\z/ => [3,3], # wireless geographic
888
- /\A(72|75|76|77)\d+\z/ => [3,4], # mobile
982
+ /\A(71|72|75|76|77)\d+\z/ => [3,4], # mobile
889
983
  /\A84\d+\z/ => [3,4], # wireless geographic
890
984
  /\A\d+\z/ => [2,3] # geographic
891
985
  )
@@ -906,7 +1000,10 @@ Phony.define do
906
1000
  country '698', todo # -
907
1001
  country '699', todo # -
908
1002
 
909
- country '800', todo # International Freephone Service
1003
+ # International Freephone Service
1004
+ # https://www.itu.int/en/ITU-T/inr/unum/Pages/uifn.aspx
1005
+ country '800', none >> split(8)
1006
+
910
1007
  country '801', todo # -
911
1008
  country '802', todo # -
912
1009
  country '803', todo # -
@@ -914,7 +1011,7 @@ Phony.define do
914
1011
  country '805', todo # -
915
1012
  country '806', todo # -
916
1013
  country '807', todo # -
917
- country '808', todo # International Shared Cost Service (ISCS)
1014
+ country '808', none >> split(12) # International Shared Cost Service (ISCS)
918
1015
  country '809', todo # -
919
1016
 
920
1017
  country '830', todo # -
@@ -945,12 +1042,14 @@ Phony.define do
945
1042
  # Hong Kong, China
946
1043
 
947
1044
  country '852',
1045
+ match(/^(800)\d+$/) >> split(2, 4) |
948
1046
  none >> split(4,4)
949
1047
 
950
1048
  # Macao, China
951
1049
  country '853', # Macao, China
952
1050
  match(/^(28)\d+$/) >> split(2,4) | # Landline.
953
- match(/^(6)\d+$/) >> split(3,4) # Mobile.
1051
+ match(/^(8)\d+$/) >> split(3,4) | # Landline.
1052
+ match(/^(6)\d+$/) >> split(3,4) # Mobile.
954
1053
 
955
1054
  country '854', todo # Spare code
956
1055
 
@@ -978,7 +1077,10 @@ Phony.define do
978
1077
  # Bangladesh (People's Republic of)
979
1078
  # country '880' # see special file
980
1079
 
981
- country '881', todo # International Mobile, shared code
1080
+ # Global Mobile Satellite System (i.e. Iridium, Globalstar, etc)
1081
+ # https://www.numberingplans.com/?page=plans&sub=phonenr&alpha_2_input=QM
1082
+ country '881', fixed(1) >> split(3,5)
1083
+
982
1084
  country '882', todo # International Networks, shared code
983
1085
  country '883', todo # -
984
1086
  country '884', todo # -
@@ -1089,17 +1191,18 @@ Phony.define do
1089
1191
  one_of(%w(500 700 900)) >> split(3,3) | # premium rate
1090
1192
  one_of('800') >> matched_split(
1091
1193
  /\A\d{2}\z/ => [2],
1194
+ /\A\d{7}\z/ => [2,3,2],
1092
1195
  /\A\d+\z/ => [2,3,4]) | # freephone
1093
- one_of(%w(50 52 55 56)) >> split(3,4) | # mobile
1196
+ one_of(%w(50 52 54 55 56 58)) >> split(3,4) | # mobile
1094
1197
  one_of(%w(2 3 4 6 7 9)) >> split(3,4) |
1095
1198
  fixed(1) >> split(3,4)
1096
1199
 
1097
1200
  # Israel (State of) (also works for numbers in Palestinian territories)
1098
1201
  country '972',
1099
1202
  trunk('0') |
1100
- one_of('1') >> split(3,3,3) | # special numbers
1101
- one_of('2', '3', '4', '8', '9') >> split(3,4) | # 1 digit ndc
1102
- match(/^(5[023456789]|7[23467])\d+$/) >> split(3,4) # 2 digit ndc
1203
+ one_of('1') >> split(3,3,3) | # special numbers
1204
+ one_of('2', '3', '4', '8', '9') >> split(3,4) | # 1 digit ndc
1205
+ match(/^(5[012345689]|7[234679])\d+$/) >> split(3,4) # 2 digit ndc
1103
1206
 
1104
1207
  country '973', none >> split(4,4..4) # Bahrain (Kingdom of) http://www.itu.int/oth/T0202000011/en
1105
1208
 
data/lib/phony/country.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Phony
2
4
 
3
5
  #
@@ -95,6 +97,9 @@ module Phony
95
97
  end
96
98
  end
97
99
  def format_cc_ndc trunk, ndc, local, type, space, parentheses, use_trunk
100
+ # Note: We mark NDCs that are of type "none" with false (nil trips plausible?). This would result in false being printed.
101
+ # Therefore we set NDC to nil when formatting.
102
+ ndc = nil if ndc == false
98
103
  case type
99
104
  when String
100
105
  trunk &&= trunk.format(space, use_trunk)
@@ -123,6 +128,7 @@ module Phony
123
128
  end
124
129
  end
125
130
  def format_ndc ndc, parentheses
131
+ ndc = nil if ndc == false # TODO
126
132
  parentheses ? "(#{ndc})" : ndc
127
133
  end
128
134
  def format_with_ndc format, cc, ndc, local, space
@@ -154,10 +160,12 @@ module Phony
154
160
  #
155
161
  # In some cases it doesn't, like Italy.
156
162
  #
157
- def normalize national_number
163
+ # Note: Options such as CC
164
+ #
165
+ def normalize national_number, options = {}
158
166
  clean! national_number
159
167
  normalized = @codes.reduce national_number do |number, code|
160
- result = code.normalize number
168
+ result = code.normalize number, options
161
169
  break result if result
162
170
  number
163
171
  end
@@ -168,7 +176,7 @@ module Phony
168
176
  #
169
177
  def plausible? rest, hints = {}
170
178
  local, _, ndc, *rest = internal_split rest
171
-
179
+
172
180
  # Element based checking.
173
181
  #
174
182
  # Note: ndc == false means the country has none.
@@ -185,6 +193,10 @@ module Phony
185
193
  #
186
194
  ndc_needed = hints[:ndc]
187
195
  return false if ndc_needed && !(ndc_needed === ndc)
196
+
197
+ # If there is no local part, we can assume it's not a plausible number.
198
+ # (Or, not defined correctly in Phony yet)
199
+ return false unless local
188
200
 
189
201
  # Local code specific checks.
190
202
  #
@@ -1,6 +1,6 @@
1
1
  module Phony
2
2
 
3
- EMPTY_STRING = ''
3
+ EMPTY_STRING = '' unless defined?(EMPTY_STRING)
4
4
 
5
5
  # Handles determining the correct national code handler.
6
6
  #
@@ -66,7 +66,7 @@ module Phony
66
66
  country, cc, number = partial_split number
67
67
  country
68
68
  end
69
- number = country.normalize number
69
+ number = country.normalize number, cc: cc
70
70
  countrify! number, cc
71
71
  end
72
72
 
@@ -77,7 +77,7 @@ module Phony
77
77
  country, cc, national_number = partial_split number
78
78
 
79
79
  # Split the national number into ndc and local part.
80
- trunk, ndc, *local = country.split national_number
80
+ _, ndc, *local = country.split national_number
81
81
 
82
82
  [cc, ndc, *local]
83
83
  end
@@ -97,9 +97,20 @@ module Phony
97
97
 
98
98
  # False if it fails the basic check.
99
99
  #
100
- return false unless (4..15) === normalized.size
100
+ return false unless (4..16) === normalized.size # unless hints[:check_length] == false
101
101
 
102
102
  country, cc, rest = partial_split normalized
103
+
104
+ # Was a country calling code given?
105
+ #
106
+ if ccc = hints[:ccc]
107
+ cc, ndc, *local = split ccc
108
+
109
+ raise ArgumentError.new("The provided ccc option is too long and includes more than a cc ('#{cc}') and ndc ('#{ndc}'). It also includes '#{local.join}'.") unless local.size == 1 && local[0].empty?
110
+
111
+ hints[:cc] = cc
112
+ hints[:ndc] = ndc
113
+ end
103
114
 
104
115
  # Country code plausible?
105
116
  #
@@ -109,6 +120,8 @@ module Phony
109
120
  # Country specific tests.
110
121
  #
111
122
  country.plausible? rest, hints
123
+ rescue ArgumentError
124
+ raise
112
125
  rescue StandardError
113
126
  return false
114
127
  end
data/lib/phony/dsl.rb CHANGED
@@ -12,9 +12,9 @@ module Phony
12
12
  #
13
13
  # Phony.define.country ...
14
14
  #
15
- def self.define
15
+ def self.define(&block)
16
16
  dsl = DSL.new
17
- dsl.instance_eval(&Proc.new) if block_given?
17
+ dsl.instance_eval(&block) if block_given?
18
18
  dsl
19
19
  end
20
20
 
@@ -41,6 +41,8 @@ module Phony
41
41
  # country '27', # CC, followed by rules, for example fixed(2) >> ...
42
42
  #
43
43
  def country country_code, definition, options = {}
44
+ return unless Phony.config.load?(country_code)
45
+
44
46
  definition.with country_code, options
45
47
  Phony::CountryCodes.instance.add country_code, definition
46
48
  end
@@ -139,7 +141,7 @@ module Phony
139
141
  #
140
142
  ndcs = ndcs.first if Array === ndcs.first
141
143
 
142
- NationalSplitters::Variable.new options[:max_length], ndcs
144
+ NationalSplitters::Variable.new options[:max_length], ndcs.map(&:freeze)
143
145
  end
144
146
 
145
147
  # If you have a number of (possibly) variable length NDCs