whalibmob 5.14.7 → 5.14.8
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.
- package/lib/Client.js +102 -2
- package/lib/Registration.js +161 -16
- package/package.json +1 -1
package/lib/Client.js
CHANGED
|
@@ -1246,8 +1246,11 @@ class WhalibmobClient extends EventEmitter {
|
|
|
1246
1246
|
|
|
1247
1247
|
this._requestMediaConnection();
|
|
1248
1248
|
// Ask what the server still has rather than uploading blind. It answers
|
|
1249
|
-
// with a number this side has no other way of learning
|
|
1250
|
-
|
|
1249
|
+
// with a number this side has no other way of learning, and then with the
|
|
1250
|
+
// bundle it is serving, which is the thing that goes quietly wrong and
|
|
1251
|
+
// takes the account's reachability with it.
|
|
1252
|
+
this._ensureServerPreKeys('login')
|
|
1253
|
+
.then(() => this._verifyServerKeyBundle('login'));
|
|
1251
1254
|
|
|
1252
1255
|
// Same telemetry ping the web client sends on every completed login.
|
|
1253
1256
|
this._sendUnifiedSession();
|
|
@@ -3411,6 +3414,103 @@ class WhalibmobClient extends EventEmitter {
|
|
|
3411
3414
|
return Array.isArray(list.content) ? list.content.length : 0;
|
|
3412
3415
|
}
|
|
3413
3416
|
|
|
3417
|
+
// What the server believes this account's key bundle is.
|
|
3418
|
+
//
|
|
3419
|
+
// The digest is the only way to see it. Everything else here is a guess about
|
|
3420
|
+
// what was uploaded once and assumed to have stuck — and when the server's
|
|
3421
|
+
// idea of the bundle and ours part company, nobody can open a session with
|
|
3422
|
+
// this account and there is no error anywhere to say so. It is the state that
|
|
3423
|
+
// registering the number again clears, which is why registering again is what
|
|
3424
|
+
// has been fixing it.
|
|
3425
|
+
async _queryKeyDigest() {
|
|
3426
|
+
if (!this._socket || !this._connected) return null;
|
|
3427
|
+
|
|
3428
|
+
const resp = await this._sendIq(new BinaryNode('iq', {
|
|
3429
|
+
id: this._genMsgId(),
|
|
3430
|
+
to: 's.whatsapp.net',
|
|
3431
|
+
type: 'get',
|
|
3432
|
+
xmlns: 'encrypt'
|
|
3433
|
+
}, [new BinaryNode('digest', {}, null)]));
|
|
3434
|
+
|
|
3435
|
+
if (!resp) return null;
|
|
3436
|
+
if (resp.attrs && resp.attrs.type === 'error') return null;
|
|
3437
|
+
|
|
3438
|
+
const digest = findChild(resp, 'digest');
|
|
3439
|
+
if (!digest) return { missing: true };
|
|
3440
|
+
|
|
3441
|
+
const bytesOf = (parent, tag) => {
|
|
3442
|
+
const n = parent && findChild(parent, tag);
|
|
3443
|
+
if (!n) return null;
|
|
3444
|
+
if (Buffer.isBuffer(n.content)) return n.content;
|
|
3445
|
+
return n.content ? Buffer.from(n.content) : null;
|
|
3446
|
+
};
|
|
3447
|
+
|
|
3448
|
+
const skey = findChild(digest, 'skey');
|
|
3449
|
+
const list = findChild(digest, 'list');
|
|
3450
|
+
return {
|
|
3451
|
+
missing: false,
|
|
3452
|
+
identity: bytesOf(digest, 'identity'),
|
|
3453
|
+
skeyId: bytesOf(skey, 'id'),
|
|
3454
|
+
skeyValue: bytesOf(skey, 'value'),
|
|
3455
|
+
preKeyCount: list && Array.isArray(list.content) ? list.content.length : 0
|
|
3456
|
+
};
|
|
3457
|
+
}
|
|
3458
|
+
|
|
3459
|
+
// Compare that bundle against the one we hold, and re-upload when they differ.
|
|
3460
|
+
//
|
|
3461
|
+
// Only values the server states outright are compared — the identity key and
|
|
3462
|
+
// the signed pre-key it is serving — so nothing here depends on guessing how
|
|
3463
|
+
// it hashes them. A mismatch means the bundle other people are handed is not
|
|
3464
|
+
// the one this session can answer for, and no amount of waiting fixes that.
|
|
3465
|
+
async _verifyServerKeyBundle(reason) {
|
|
3466
|
+
if (!this._signal) return;
|
|
3467
|
+
try {
|
|
3468
|
+
const digest = await this._queryKeyDigest();
|
|
3469
|
+
if (!digest) return; // no answer; nothing to conclude
|
|
3470
|
+
|
|
3471
|
+
if (digest.missing) {
|
|
3472
|
+
_whaDbg('[DBG] KEYBUNDLE server returned no digest (' + reason + ') — re-uploading');
|
|
3473
|
+
this._replenishLocalPreKeys();
|
|
3474
|
+
this._uploadPreKeys();
|
|
3475
|
+
return;
|
|
3476
|
+
}
|
|
3477
|
+
|
|
3478
|
+
const bare = (b) => (b && b.length === 33 && b[0] === 0x05) ? b.slice(1) : b;
|
|
3479
|
+
const ourIdent = bare(this._signal.getIdentityKey());
|
|
3480
|
+
const ourSpk = this._signal.getSignedPreKeyForUpload();
|
|
3481
|
+
const ourSpkPub = ourSpk && bare(ourSpk.keyPair.pubKey);
|
|
3482
|
+
|
|
3483
|
+
const mismatches = [];
|
|
3484
|
+
if (digest.identity && ourIdent &&
|
|
3485
|
+
Buffer.compare(digest.identity, ourIdent) !== 0) {
|
|
3486
|
+
mismatches.push('identity key');
|
|
3487
|
+
}
|
|
3488
|
+
if (digest.skeyValue && ourSpkPub &&
|
|
3489
|
+
Buffer.compare(digest.skeyValue, ourSpkPub) !== 0) {
|
|
3490
|
+
mismatches.push('signed pre-key');
|
|
3491
|
+
}
|
|
3492
|
+
if (digest.skeyId && ourSpk) {
|
|
3493
|
+
let served = 0;
|
|
3494
|
+
for (const b of digest.skeyId) served = (served << 8) | b;
|
|
3495
|
+
if (served !== ourSpk.keyId) mismatches.push('signed pre-key id (' + served +
|
|
3496
|
+
' vs ' + ourSpk.keyId + ')');
|
|
3497
|
+
}
|
|
3498
|
+
|
|
3499
|
+
if (!mismatches.length) {
|
|
3500
|
+
_whaDbg('[DBG] KEYBUNDLE matches the server (' + reason + '), ' +
|
|
3501
|
+
digest.preKeyCount + ' one-time key(s) there');
|
|
3502
|
+
return;
|
|
3503
|
+
}
|
|
3504
|
+
|
|
3505
|
+
_whaDbg('[DBG] KEYBUNDLE server disagrees on ' + mismatches.join(' and ') +
|
|
3506
|
+
' (' + reason + ') — re-uploading');
|
|
3507
|
+
this._replenishLocalPreKeys();
|
|
3508
|
+
this._uploadPreKeys();
|
|
3509
|
+
} catch (err) {
|
|
3510
|
+
_whaDbg('[DBG] KEYBUNDLE check failed (' + reason + '): ' + (err && err.message));
|
|
3511
|
+
}
|
|
3512
|
+
}
|
|
3513
|
+
|
|
3414
3514
|
// Top the server back up when it is running out. Never throws: a session that
|
|
3415
3515
|
// cannot ask is left exactly as it was rather than losing its connection over
|
|
3416
3516
|
// a bookkeeping query.
|
package/lib/Registration.js
CHANGED
|
@@ -418,6 +418,149 @@ const COUNTRY_META = {
|
|
|
418
418
|
'971': { mcc: '424', mnc: '02', lg: 'ar', lc: 'AE' }, // UAE
|
|
419
419
|
'972': { mcc: '425', mnc: '01', lg: 'he', lc: 'IL' }, // Israel
|
|
420
420
|
'880': { mcc: '470', mnc: '01', lg: 'bn', lc: 'BD' }, // Bangladesh
|
|
421
|
+
// Filled in from the ITU mobile-network tables so a number from anywhere
|
|
422
|
+
// reports the carrier its country actually has. Without an entry a session
|
|
423
|
+
// falls back to 000/000, which is what a handset with no SIM card reports.
|
|
424
|
+
// One operational national operator per country; the point is a plausible
|
|
425
|
+
// home network, not a particular one.
|
|
426
|
+
'53': { mcc: '368', mnc: '01', lg: 'es', lc: 'CU' }, // Cuba (CUBACEL)
|
|
427
|
+
'211': { mcc: '659', mnc: '02', lg: 'en', lc: 'SS' }, // South Sudan (MTN)
|
|
428
|
+
'220': { mcc: '607', mnc: '01', lg: 'en', lc: 'GM' }, // Gambia (Gamcel)
|
|
429
|
+
'221': { mcc: '608', mnc: '01', lg: 'fr', lc: 'SN' }, // Senegal (Orange)
|
|
430
|
+
'222': { mcc: '609', mnc: '01', lg: 'ar', lc: 'MR' }, // Mauritania (Mattel)
|
|
431
|
+
'223': { mcc: '610', mnc: '01', lg: 'fr', lc: 'ML' }, // Mali (Malitel)
|
|
432
|
+
'224': { mcc: '611', mnc: '01', lg: 'fr', lc: 'GN' }, // Guinea (Orange)
|
|
433
|
+
'225': { mcc: '612', mnc: '02', lg: 'fr', lc: 'CI' }, // Ivory Coast (Moov)
|
|
434
|
+
'226': { mcc: '613', mnc: '01', lg: 'fr', lc: 'BF' }, // Burkina Faso (Telmob)
|
|
435
|
+
'227': { mcc: '614', mnc: '01', lg: 'fr', lc: 'NE' }, // Niger (SahelCom)
|
|
436
|
+
'228': { mcc: '615', mnc: '01', lg: 'fr', lc: 'TG' }, // Togo (Togo Cell)
|
|
437
|
+
'229': { mcc: '616', mnc: '01', lg: 'fr', lc: 'BJ' }, // Benin (Benin Telecoms Mob)
|
|
438
|
+
'230': { mcc: '617', mnc: '01', lg: 'en', lc: 'MU' }, // Mauritius (my.t)
|
|
439
|
+
'231': { mcc: '618', mnc: '01', lg: 'en', lc: 'LR' }, // Liberia (Lonestar Cell MTN)
|
|
440
|
+
'232': { mcc: '619', mnc: '01', lg: 'en', lc: 'SL' }, // Sierra Leone (Orange)
|
|
441
|
+
'233': { mcc: '620', mnc: '01', lg: 'en', lc: 'GH' }, // Ghana (MTN)
|
|
442
|
+
'235': { mcc: '622', mnc: '01', lg: 'ar', lc: 'TD' }, // Chad (Airtel)
|
|
443
|
+
'236': { mcc: '623', mnc: '01', lg: 'fr', lc: 'CF' }, // Central African Republic (Moov)
|
|
444
|
+
'237': { mcc: '624', mnc: '01', lg: 'en', lc: 'CM' }, // Cameroon (MTN Cameroon)
|
|
445
|
+
'238': { mcc: '625', mnc: '01', lg: 'pt', lc: 'CV' }, // Cape Verde (CVMOVEL)
|
|
446
|
+
'239': { mcc: '626', mnc: '01', lg: 'pt', lc: 'ST' }, // São Tomé and Príncipe (CSTmovel)
|
|
447
|
+
'240': { mcc: '627', mnc: '01', lg: 'fr', lc: 'GQ' }, // Equatorial Guinea (Orange GQ)
|
|
448
|
+
'241': { mcc: '628', mnc: '01', lg: 'fr', lc: 'GA' }, // Gabon (Libertis)
|
|
449
|
+
'242': { mcc: '629', mnc: '01', lg: 'fr', lc: 'CG' }, // Republic of the Congo (Airtel)
|
|
450
|
+
'243': { mcc: '630', mnc: '01', lg: 'fr', lc: 'CD' }, // DR Congo (Vodacom)
|
|
451
|
+
'244': { mcc: '631', mnc: '02', lg: 'pt', lc: 'AO' }, // Angola (UNITEL)
|
|
452
|
+
'245': { mcc: '632', mnc: '01', lg: 'pt', lc: 'GW' }, // Guinea-Bissau (Guinetel)
|
|
453
|
+
'248': { mcc: '633', mnc: '01', lg: 'en', lc: 'SC' }, // Seychelles (Cable & Wireless)
|
|
454
|
+
'249': { mcc: '634', mnc: '01', lg: 'ar', lc: 'SD' }, // Sudan (Zain SD)
|
|
455
|
+
'250': { mcc: '635', mnc: '10', lg: 'en', lc: 'RW' }, // Rwanda (MTN)
|
|
456
|
+
'251': { mcc: '636', mnc: '01', lg: 'am', lc: 'ET' }, // Ethiopia (MTN)
|
|
457
|
+
'252': { mcc: '637', mnc: '01', lg: 'ar', lc: 'SO' }, // Somalia (Telesom)
|
|
458
|
+
'253': { mcc: '638', mnc: '01', lg: 'ar', lc: 'DJ' }, // Djibouti (Evatis)
|
|
459
|
+
'257': { mcc: '642', mnc: '01', lg: 'fr', lc: 'BI' }, // Burundi (econet Leo)
|
|
460
|
+
'258': { mcc: '643', mnc: '01', lg: 'pt', lc: 'MZ' }, // Mozambique (mCel)
|
|
461
|
+
'260': { mcc: '645', mnc: '01', lg: 'en', lc: 'ZM' }, // Zambia (Airtel)
|
|
462
|
+
'261': { mcc: '646', mnc: '01', lg: 'fr', lc: 'MG' }, // Madagascar (Airtel)
|
|
463
|
+
'263': { mcc: '648', mnc: '01', lg: 'en', lc: 'ZW' }, // Zimbabwe (Net*One)
|
|
464
|
+
'264': { mcc: '649', mnc: '01', lg: 'af', lc: 'NA' }, // Namibia (MTC)
|
|
465
|
+
'265': { mcc: '650', mnc: '01', lg: 'en', lc: 'MW' }, // Malawi (TNM)
|
|
466
|
+
'266': { mcc: '651', mnc: '01', lg: 'en', lc: 'LS' }, // Lesotho (Vodacom)
|
|
467
|
+
'267': { mcc: '652', mnc: '01', lg: 'en', lc: 'BW' }, // Botswana (Mascom)
|
|
468
|
+
'268': { mcc: '653', mnc: '02', lg: 'en', lc: 'SZ' }, // Eswatini (Eswatini Mobile Li)
|
|
469
|
+
'269': { mcc: '654', mnc: '01', lg: 'ar', lc: 'KM' }, // Comoros (HURI)
|
|
470
|
+
'290': { mcc: '658', mnc: '01', lg: 'en', lc: 'SH' }, // Saint Helena, Ascension and Tristan da Cunha (Sure)
|
|
471
|
+
'291': { mcc: '657', mnc: '01', lg: 'ar', lc: 'ER' }, // Eritrea (Eritel)
|
|
472
|
+
'297': { mcc: '363', mnc: '01', lg: 'nl', lc: 'AW' }, // Aruba (SETAR)
|
|
473
|
+
'298': { mcc: '288', mnc: '01', lg: 'da', lc: 'FO' }, // Faroe Islands (Føroya Tele)
|
|
474
|
+
'299': { mcc: '290', mnc: '01', lg: 'kl', lc: 'GL' }, // Greenland (tusass)
|
|
475
|
+
'350': { mcc: '266', mnc: '01', lg: 'en', lc: 'GI' }, // Gibraltar (GibTel)
|
|
476
|
+
'352': { mcc: '270', mnc: '01', lg: 'de', lc: 'LU' }, // Luxembourg (POST)
|
|
477
|
+
'354': { mcc: '274', mnc: '01', lg: 'is', lc: 'IS' }, // Iceland (Síminn)
|
|
478
|
+
'355': { mcc: '276', mnc: '01', lg: 'sq', lc: 'AL' }, // Albania (ONE)
|
|
479
|
+
'356': { mcc: '278', mnc: '01', lg: 'en', lc: 'MT' }, // Malta (Epic)
|
|
480
|
+
'357': { mcc: '280', mnc: '01', lg: 'el', lc: 'CY' }, // Cyprus (Cytamobile-Vodafon)
|
|
481
|
+
'359': { mcc: '284', mnc: '01', lg: 'bg', lc: 'BG' }, // Bulgaria (A1 BG)
|
|
482
|
+
'370': { mcc: '246', mnc: '01', lg: 'lt', lc: 'LT' }, // Lithuania (Telia)
|
|
483
|
+
'371': { mcc: '247', mnc: '01', lg: 'lv', lc: 'LV' }, // Latvia (LMT)
|
|
484
|
+
'372': { mcc: '248', mnc: '01', lg: 'et', lc: 'EE' }, // Estonia (Telia)
|
|
485
|
+
'373': { mcc: '255', mnc: '00', lg: 'ro', lc: 'MD' }, // Moldova (IDC)
|
|
486
|
+
'374': { mcc: '283', mnc: '01', lg: 'hy', lc: 'AM' }, // Armenia (Beeline)
|
|
487
|
+
'375': { mcc: '257', mnc: '01', lg: 'be', lc: 'BY' }, // Belarus (A1)
|
|
488
|
+
'376': { mcc: '213', mnc: '03', lg: 'ca', lc: 'AD' }, // Andorra (Som, Mobiland)
|
|
489
|
+
'377': { mcc: '212', mnc: '10', lg: 'fr', lc: 'MC' }, // Monaco (Office des Telepho)
|
|
490
|
+
'378': { mcc: '292', mnc: '01', lg: 'it', lc: 'SM' }, // San Marino (PRIMA)
|
|
491
|
+
'381': { mcc: '220', mnc: '01', lg: 'sr', lc: 'RS' }, // Serbia (Yettel)
|
|
492
|
+
'382': { mcc: '297', mnc: '01', lg: 'en', lc: 'ME' }, // Montenegro (One)
|
|
493
|
+
'383': { mcc: '221', mnc: '01', lg: 'sq', lc: 'XK' }, // Kosovo (Vala)
|
|
494
|
+
'385': { mcc: '219', mnc: '01', lg: 'hr', lc: 'HR' }, // Croatia (HT HR)
|
|
495
|
+
'386': { mcc: '293', mnc: '10', lg: 'sl', lc: 'SI' }, // Slovenia (SŽ - Infrastruktur)
|
|
496
|
+
'387': { mcc: '218', mnc: '03', lg: 'bs', lc: 'BA' }, // Bosnia and Herzegovina (HT-ERONET)
|
|
497
|
+
'389': { mcc: '294', mnc: '01', lg: 'mk', lc: 'MK' }, // North Macedonia (Telekom.mk)
|
|
498
|
+
'421': { mcc: '231', mnc: '01', lg: 'sk', lc: 'SK' }, // Slovakia (Orange)
|
|
499
|
+
'423': { mcc: '295', mnc: '01', lg: 'de', lc: 'LI' }, // Liechtenstein (Swisscom)
|
|
500
|
+
'500': { mcc: '750', mnc: '001', lg: 'en', lc: 'FK' }, // Falkland Islands (Sure)
|
|
501
|
+
'501': { mcc: '702', mnc: '67', lg: 'en', lc: 'BZ' }, // Belize (DigiCell)
|
|
502
|
+
'502': { mcc: '704', mnc: '?', lg: 'es', lc: 'GT' }, // Guatemala (RED/INTELFON)
|
|
503
|
+
'503': { mcc: '706', mnc: '01', lg: 'es', lc: 'SV' }, // El Salvador (Claro)
|
|
504
|
+
'504': { mcc: '708', mnc: '001', lg: 'es', lc: 'HN' }, // Honduras (Claro)
|
|
505
|
+
'505': { mcc: '710', mnc: '21', lg: 'es', lc: 'NI' }, // Nicaragua (Claro)
|
|
506
|
+
'506': { mcc: '712', mnc: '01', lg: 'es', lc: 'CR' }, // Costa Rica (Kölbi ICE)
|
|
507
|
+
'507': { mcc: '714', mnc: '01', lg: 'es', lc: 'PA' }, // Panama (Cable & Wireless)
|
|
508
|
+
'508': { mcc: '308', mnc: '01', lg: 'fr', lc: 'PM' }, // Saint Pierre and Miquelon (Ameris)
|
|
509
|
+
'509': { mcc: '372', mnc: '02', lg: 'fr', lc: 'HT' }, // Haiti (Digicel)
|
|
510
|
+
'591': { mcc: '736', mnc: '01', lg: 'ay', lc: 'BO' }, // Bolivia (Viva)
|
|
511
|
+
'592': { mcc: '738', mnc: '00', lg: 'en', lc: 'GY' }, // Guyana (E-Networks)
|
|
512
|
+
'593': { mcc: '740', mnc: '00', lg: 'es', lc: 'EC' }, // Ecuador (Movistar)
|
|
513
|
+
'594': { mcc: '340', mnc: '01', lg: 'fr', lc: 'GF' }, // French Guiana (Orange)
|
|
514
|
+
'595': { mcc: '744', mnc: '01', lg: 'gn', lc: 'PY' }, // Paraguay (VOX)
|
|
515
|
+
'597': { mcc: '746', mnc: '02', lg: 'nl', lc: 'SR' }, // Suriname (Telesur)
|
|
516
|
+
'598': { mcc: '748', mnc: '01', lg: 'es', lc: 'UY' }, // Uruguay (Antel)
|
|
517
|
+
'670': { mcc: '514', mnc: '01', lg: 'pt', lc: 'TL' }, // Timor-Leste (Telkomcel)
|
|
518
|
+
'672': { mcc: '505', mnc: '10', lg: 'en', lc: 'NF' }, // Norfolk Island (Norfolk Telecom)
|
|
519
|
+
'673': { mcc: '528', mnc: '02', lg: 'ms', lc: 'BN' }, // Brunei (PCSB)
|
|
520
|
+
'674': { mcc: '536', mnc: '02', lg: 'en', lc: 'NR' }, // Nauru (Digicel)
|
|
521
|
+
'675': { mcc: '537', mnc: '01', lg: 'en', lc: 'PG' }, // Papua New Guinea (bmobile)
|
|
522
|
+
'676': { mcc: '539', mnc: '01', lg: 'en', lc: 'TO' }, // Tonga (U-Call)
|
|
523
|
+
'677': { mcc: '540', mnc: '01', lg: 'en', lc: 'SB' }, // Solomon Islands (BREEZE)
|
|
524
|
+
'678': { mcc: '541', mnc: '00', lg: 'bi', lc: 'VU' }, // Vanuatu (AIL)
|
|
525
|
+
'679': { mcc: '542', mnc: '01', lg: 'en', lc: 'FJ' }, // Fiji (Vodafone)
|
|
526
|
+
'680': { mcc: '552', mnc: '01', lg: 'en', lc: 'PW' }, // Palau (PNCC)
|
|
527
|
+
'681': { mcc: '543', mnc: '01', lg: 'fr', lc: 'WF' }, // Wallis and Futuna (Manuia)
|
|
528
|
+
'682': { mcc: '548', mnc: '01', lg: 'en', lc: 'CK' }, // Cook Islands (Vodafone)
|
|
529
|
+
'683': { mcc: '555', mnc: '01', lg: 'en', lc: 'NU' }, // Niue (Telecom Niue)
|
|
530
|
+
'685': { mcc: '549', mnc: '01', lg: 'en', lc: 'WS' }, // Samoa (Digicel)
|
|
531
|
+
'686': { mcc: '545', mnc: '01', lg: 'en', lc: 'KI' }, // Kiribati (Kiribati - ATH)
|
|
532
|
+
'687': { mcc: '546', mnc: '01', lg: 'fr', lc: 'NC' }, // New Caledonia (Mobilis)
|
|
533
|
+
'688': { mcc: '553', mnc: '01', lg: 'en', lc: 'TV' }, // Tuvalu (TTC)
|
|
534
|
+
'689': { mcc: '547', mnc: '05', lg: 'fr', lc: 'PF' }, // French Polynesia (Ora)
|
|
535
|
+
'690': { mcc: '554', mnc: '01', lg: 'en', lc: 'TK' }, // Tokelau (Teletok)
|
|
536
|
+
'691': { mcc: '550', mnc: '01', lg: 'en', lc: 'FM' }, // Micronesia (FSMTC)
|
|
537
|
+
'692': { mcc: '551', mnc: '01', lg: 'en', lc: 'MH' }, // Marshall Islands (Marshall Islands N)
|
|
538
|
+
'850': { mcc: '467', mnc: '05', lg: 'ko', lc: 'KP' }, // North Korea (Koryolink)
|
|
539
|
+
'852': { mcc: '454', mnc: '00', lg: 'en', lc: 'HK' }, // Hong Kong (1O1O / One2Free / )
|
|
540
|
+
'853': { mcc: '455', mnc: '00', lg: 'pt', lc: 'MO' }, // Macau (SmarTone)
|
|
541
|
+
'855': { mcc: '456', mnc: '01', lg: 'km', lc: 'KH' }, // Cambodia (Cellcard)
|
|
542
|
+
'856': { mcc: '457', mnc: '01', lg: 'lo', lc: 'LA' }, // Laos (LaoTel)
|
|
543
|
+
'886': { mcc: '466', mnc: '01', lg: 'zh', lc: 'TW' }, // Taiwan (FarEasTone)
|
|
544
|
+
'960': { mcc: '472', mnc: '01', lg: 'dv', lc: 'MV' }, // Maldives (Dhiraagu)
|
|
545
|
+
'961': { mcc: '415', mnc: '01', lg: 'ar', lc: 'LB' }, // Lebanon (Alfa)
|
|
546
|
+
'962': { mcc: '416', mnc: '01', lg: 'ar', lc: 'JO' }, // Jordan (zain JO)
|
|
547
|
+
'963': { mcc: '417', mnc: '01', lg: 'ar', lc: 'SY' }, // Syria (Syriatel)
|
|
548
|
+
'964': { mcc: '418', mnc: '00', lg: 'ar', lc: 'IQ' }, // Iraq (Asia Cell)
|
|
549
|
+
'965': { mcc: '419', mnc: '02', lg: 'ar', lc: 'KW' }, // Kuwait (zain KW)
|
|
550
|
+
'967': { mcc: '421', mnc: '01', lg: 'ar', lc: 'YE' }, // Yemen (SabaFon)
|
|
551
|
+
'968': { mcc: '422', mnc: '02', lg: 'ar', lc: 'OM' }, // Oman (Omantel)
|
|
552
|
+
'970': { mcc: '425', mnc: '05', lg: 'ar', lc: 'PS' }, // Palestine (Jawwal)
|
|
553
|
+
'973': { mcc: '426', mnc: '01', lg: 'ar', lc: 'BH' }, // Bahrain (Batelco)
|
|
554
|
+
'974': { mcc: '427', mnc: '01', lg: 'ar', lc: 'QA' }, // Qatar (Ooredoo)
|
|
555
|
+
'975': { mcc: '402', mnc: '11', lg: 'dz', lc: 'BT' }, // Bhutan (B-Mobile)
|
|
556
|
+
'976': { mcc: '428', mnc: '88', lg: 'mn', lc: 'MN' }, // Mongolia (Unitel)
|
|
557
|
+
'977': { mcc: '429', mnc: '01', lg: 'ne', lc: 'NP' }, // Nepal (Namaste / NT Mobil)
|
|
558
|
+
'992': { mcc: '436', mnc: '01', lg: 'ru', lc: 'TJ' }, // Tajikistan (Tcell)
|
|
559
|
+
'993': { mcc: '438', mnc: '02', lg: 'ru', lc: 'TM' }, // Turkmenistan (TM-Cell)
|
|
560
|
+
'994': { mcc: '400', mnc: '01', lg: 'az', lc: 'AZ' }, // Azerbaijan (Azercell)
|
|
561
|
+
'995': { mcc: '282', mnc: '01', lg: 'ka', lc: 'GE' }, // Georgia (Geocell)
|
|
562
|
+
'996': { mcc: '437', mnc: '01', lg: 'ky', lc: 'KG' }, // Kyrgyzstan (Beeline)
|
|
563
|
+
'998': { mcc: '434', mnc: '03', lg: 'ru', lc: 'UZ' }, // Uzbekistan (UzMobile)
|
|
421
564
|
};
|
|
422
565
|
|
|
423
566
|
function getCountryMeta(cc) {
|
|
@@ -431,17 +574,20 @@ function getCountryMeta(cc) {
|
|
|
431
574
|
// (Java long conversion removes them automatically)
|
|
432
575
|
|
|
433
576
|
const THREE_DIGIT_CCS = new Set([
|
|
434
|
-
'
|
|
435
|
-
'
|
|
436
|
-
'
|
|
437
|
-
'
|
|
438
|
-
'
|
|
439
|
-
'
|
|
440
|
-
'
|
|
441
|
-
'
|
|
442
|
-
'
|
|
443
|
-
'
|
|
444
|
-
'
|
|
577
|
+
'211','212','213','216','218','220','221','222','223','224','225','226',
|
|
578
|
+
'227','228','229','230','231','232','233','234','235','236','237','238',
|
|
579
|
+
'239','240','241','242','243','244','245','246','247','248','249','250',
|
|
580
|
+
'251','252','253','254','255','256','257','258','260','261','262','263',
|
|
581
|
+
'264','265','266','267','268','269','290','291','297','298','299','350',
|
|
582
|
+
'351','352','353','354','355','356','357','358','359','370','371','372',
|
|
583
|
+
'373','374','375','376','377','378','380','381','382','383','385','386',
|
|
584
|
+
'387','389','420','421','423','500','501','502','503','504','505','506',
|
|
585
|
+
'507','508','509','590','591','592','593','594','595','596','597','598',
|
|
586
|
+
'599','670','672','673','674','675','676','677','678','679','680','681',
|
|
587
|
+
'682','683','685','686','687','688','689','690','691','692','850','852',
|
|
588
|
+
'853','855','856','880','886','960','961','962','963','964','965','966',
|
|
589
|
+
'967','968','970','971','972','973','974','975','976','977','992','993',
|
|
590
|
+
'994','995','996','998'
|
|
445
591
|
]);
|
|
446
592
|
|
|
447
593
|
const TWO_DIGIT_CCS = new Set([
|
|
@@ -451,11 +597,10 @@ const TWO_DIGIT_CCS = new Set([
|
|
|
451
597
|
'95','98'
|
|
452
598
|
]);
|
|
453
599
|
|
|
454
|
-
//
|
|
455
|
-
//
|
|
456
|
-
//
|
|
457
|
-
//
|
|
458
|
-
// country table itself gets the last word.
|
|
600
|
+
// The country table only covers the places we carry carrier metadata for, which
|
|
601
|
+
// is far fewer than the places that can register. Anything it names still has to
|
|
602
|
+
// be splittable, so it is folded in — a no-op while the lists above are complete,
|
|
603
|
+
// and a backstop if a code is ever added to the table and not to them.
|
|
459
604
|
for (const cc of Object.keys(COUNTRY_META)) {
|
|
460
605
|
if (cc.length === 3) THREE_DIGIT_CCS.add(cc);
|
|
461
606
|
else if (cc.length === 2) TWO_DIGIT_CCS.add(cc);
|