@xuda.io/account_module 1.2.2310 → 1.2.2311
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/index.mjs +81 -130
- package/package.json +1 -1
package/index.mjs
CHANGED
|
@@ -3535,6 +3535,7 @@ export const get_account_name = async function (req) {
|
|
|
3535
3535
|
active_account_profile_id,
|
|
3536
3536
|
network_country_code,
|
|
3537
3537
|
public_profile_disabled,
|
|
3538
|
+
verify_level,
|
|
3538
3539
|
} = data.data.account_info;
|
|
3539
3540
|
|
|
3540
3541
|
obj = {
|
|
@@ -3570,6 +3571,11 @@ export const get_account_name = async function (req) {
|
|
|
3570
3571
|
// email,// email?.[0] || '',
|
|
3571
3572
|
avatar_source,
|
|
3572
3573
|
active_account_profile_id,
|
|
3574
|
+
// The verification level of the account behind a card. Every caller that
|
|
3575
|
+
// builds a contact card off another account copies this onto the card doc
|
|
3576
|
+
// so the background tile can say what the level is; without it a card for
|
|
3577
|
+
// a verified person read as L0, which is a false statement about them.
|
|
3578
|
+
verify_level,
|
|
3573
3579
|
};
|
|
3574
3580
|
}
|
|
3575
3581
|
return { code: 1, data: obj }; //is_online: data?.data?.socket_id ? true : false
|
|
@@ -4305,6 +4311,13 @@ const level_pattern = function (doc) {
|
|
|
4305
4311
|
return `level-${level}-pattern.png`;
|
|
4306
4312
|
};
|
|
4307
4313
|
|
|
4314
|
+
// The level tile is the DEFAULT for every contact card, not a fallback. It used
|
|
4315
|
+
// to be computed first and then overwritten by a tile keyed off where the
|
|
4316
|
+
// contact came from (xu / authentic / fictional / email / web), so a card for a
|
|
4317
|
+
// verified person showed the generic XU tile and the level never appeared on any
|
|
4318
|
+
// card that had a contact_uid, which is every card for a real account. Only the
|
|
4319
|
+
// states that say the card cannot show a level at all still win: a shared card
|
|
4320
|
+
// wears its owner's avatar, an avatar being processed says so, and spam says so.
|
|
4308
4321
|
const get_contact_pattern = async function (doc) {
|
|
4309
4322
|
let ret = level_pattern(doc);
|
|
4310
4323
|
|
|
@@ -4325,84 +4338,12 @@ const get_contact_pattern = async function (doc) {
|
|
|
4325
4338
|
}
|
|
4326
4339
|
} else if (doc.is_spam) {
|
|
4327
4340
|
ret = `spam-pattern.png`;
|
|
4328
|
-
} else {
|
|
4329
|
-
// if (doc.account_type === 'business') {
|
|
4330
|
-
// // if (doc?.is_real_person) {
|
|
4331
|
-
// ret = doc.profile_picture;
|
|
4332
|
-
// // }
|
|
4333
|
-
// } else {
|
|
4334
|
-
// if (doc.my_contact) {
|
|
4335
|
-
// if (doc.account_type === 'business') {
|
|
4336
|
-
// ret = doc.profile_picture;
|
|
4337
|
-
// } else {
|
|
4338
|
-
// switch (doc.avatar_source) {
|
|
4339
|
-
// case 'fictional':
|
|
4340
|
-
// ret = `fictional-avatar-pattern.png`;
|
|
4341
|
-
// break;
|
|
4342
|
-
|
|
4343
|
-
// case 'ai profile':
|
|
4344
|
-
// ret = `fictional-avatar-pattern.png`;
|
|
4345
|
-
// break;
|
|
4346
|
-
|
|
4347
|
-
// case 'authentic profile':
|
|
4348
|
-
// ret = `authentic-avatar-pattern.png`;
|
|
4349
|
-
// break;
|
|
4350
|
-
|
|
4351
|
-
// default:
|
|
4352
|
-
// ret = `xu-pattern.png`;
|
|
4353
|
-
// break;
|
|
4354
|
-
// }
|
|
4355
|
-
// }
|
|
4356
|
-
// } else
|
|
4357
|
-
|
|
4358
|
-
// if (doc?.shared_from_uid) {
|
|
4359
|
-
// //&& (doc.pending || (doc.team_req_id && doc.contact_share_copy))) {
|
|
4360
|
-
// // pending or active share request
|
|
4361
|
-
// const shared_from_uid_ret = await get_account_name({ uid_query: doc.shared_from_uid });
|
|
4362
|
-
// ret = shared_from_uid_ret.data.profile_avatar;
|
|
4363
|
-
// }
|
|
4364
|
-
|
|
4365
|
-
// else if (doc?.reference_doc?.shared_from_uid) {
|
|
4366
|
-
// //active share
|
|
4367
|
-
// const shared_from_uid_ret = await get_account_name({ uid_query: doc.reference_doc.shared_from_uid });
|
|
4368
|
-
// ret = shared_from_uid_ret.data.profile_avatar;
|
|
4369
|
-
// }
|
|
4370
|
-
// else
|
|
4371
|
-
if (doc.contact_uid) {
|
|
4372
|
-
switch (doc.avatar_source) {
|
|
4373
|
-
case 'fictional':
|
|
4374
|
-
ret = `fictional-avatar-pattern.png`;
|
|
4375
|
-
break;
|
|
4376
|
-
|
|
4377
|
-
case 'ai profile':
|
|
4378
|
-
ret = `fictional-avatar-pattern.png`;
|
|
4379
|
-
break;
|
|
4380
|
-
|
|
4381
|
-
case 'authentic profile':
|
|
4382
|
-
ret = `authentic-avatar-pattern.png`;
|
|
4383
|
-
break;
|
|
4384
|
-
|
|
4385
|
-
default:
|
|
4386
|
-
ret = `xu-pattern.png`;
|
|
4387
|
-
break;
|
|
4388
|
-
}
|
|
4389
|
-
} else {
|
|
4390
|
-
switch (doc.source) {
|
|
4391
|
-
case 'read emails': {
|
|
4392
|
-
ret = `email-pattern.png`;
|
|
4393
|
-
break;
|
|
4394
|
-
}
|
|
4395
|
-
case 'web': {
|
|
4396
|
-
ret = `web-pattern.png`;
|
|
4397
|
-
break;
|
|
4398
|
-
}
|
|
4399
|
-
|
|
4400
|
-
default:
|
|
4401
|
-
break;
|
|
4402
|
-
}
|
|
4403
|
-
}
|
|
4404
|
-
// }
|
|
4405
4341
|
}
|
|
4342
|
+
// Everything else keeps the level tile. The old where-it-came-from tiles
|
|
4343
|
+
// (xu / authentic / fictional for an account, email / web for a scraped
|
|
4344
|
+
// contact) are gone on purpose: they occupied the one surface that now
|
|
4345
|
+
// carries the verification level, and a contact with no account behind it
|
|
4346
|
+
// has no level to show, which is exactly what L0 says.
|
|
4406
4347
|
return ret;
|
|
4407
4348
|
};
|
|
4408
4349
|
|
|
@@ -4570,6 +4511,10 @@ export const get_contact_info = async function (uid, contact_doc, _id) {
|
|
|
4570
4511
|
}
|
|
4571
4512
|
|
|
4572
4513
|
doc.avatar_source = account_info_ret.data.avatar_source;
|
|
4514
|
+
// The card's background tile is the contact's verification level, and the
|
|
4515
|
+
// level lives on the account, not on my copy of them. Carry it over here,
|
|
4516
|
+
// where the account is already in hand, so the tile costs no extra read.
|
|
4517
|
+
doc.verify_level = account_info_ret.data.verify_level;
|
|
4573
4518
|
// doc.icon_pattern = await get_contact_pattern(doc);
|
|
4574
4519
|
doc.username = account_info_ret.data.username;
|
|
4575
4520
|
doc.business_name = account_info_ret.data.business_name;
|
|
@@ -4634,6 +4579,7 @@ export const get_pending_contact_out = async function (uid, _id) {
|
|
|
4634
4579
|
doc.account_type = account_info_ret.data.account_type;
|
|
4635
4580
|
doc.avatar_source = account_info_ret.data.avatar_source;
|
|
4636
4581
|
doc.profile_avatar = account_info_ret.data.profile_avatar;
|
|
4582
|
+
doc.verify_level = account_info_ret.data.verify_level;
|
|
4637
4583
|
doc.name = `${account_info_ret.data.first_name} ${account_info_ret.data.last_name}`;
|
|
4638
4584
|
}
|
|
4639
4585
|
doc.icon_pattern = await get_contact_pattern(doc);
|
|
@@ -4665,6 +4611,7 @@ export const get_pending_contact_in = async function (uid, _id) {
|
|
|
4665
4611
|
doc.account_type = account_info_ret.data.account_type;
|
|
4666
4612
|
doc.avatar_source = account_info_ret.data.avatar_source;
|
|
4667
4613
|
doc.profile_avatar = account_info_ret.data.profile_avatar;
|
|
4614
|
+
doc.verify_level = account_info_ret.data.verify_level;
|
|
4668
4615
|
doc.name = `${account_info_ret.data.first_name} ${account_info_ret.data.last_name}`;
|
|
4669
4616
|
}
|
|
4670
4617
|
doc.card_background = get_contact_background({ pending: true });
|
|
@@ -4704,6 +4651,7 @@ const get_user_contact = async function (uid, uid_query) {
|
|
|
4704
4651
|
doc.profile_avatar = account_info.profile_avatar;
|
|
4705
4652
|
doc.profile_picture = account_info.profile_picture;
|
|
4706
4653
|
doc.avatar_source = account_info.avatar_source;
|
|
4654
|
+
doc.verify_level = account_info.verify_level;
|
|
4707
4655
|
doc.card_background = get_contact_background(doc);
|
|
4708
4656
|
doc.icon_pattern = await get_contact_pattern(doc);
|
|
4709
4657
|
doc.border = get_contact_border(doc);
|
|
@@ -5618,28 +5566,18 @@ setTimeout(async () => {
|
|
|
5618
5566
|
|
|
5619
5567
|
//////// CONTACTS //////////////
|
|
5620
5568
|
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
|
|
5624
|
-
|
|
5625
|
-
|
|
5626
|
-
|
|
5627
|
-
|
|
5628
|
-
'yahoo.com': 'Yahoo Mail',
|
|
5629
|
-
'ymail.com': 'Yahoo Mail',
|
|
5630
|
-
'aol.com': 'AOL Mail',
|
|
5631
|
-
'icloud.com': 'Apple iCloud',
|
|
5632
|
-
'me.com': 'Apple iCloud',
|
|
5633
|
-
'mac.com': 'Apple iCloud',
|
|
5634
|
-
'protonmail.com': 'ProtonMail',
|
|
5635
|
-
'proton.me': 'ProtonMail',
|
|
5636
|
-
'zoho.com': 'Zoho Mail',
|
|
5637
|
-
'yandex.com': 'Yandex Mail',
|
|
5638
|
-
'mail.com': 'Mail.com',
|
|
5639
|
-
'gmx.com': 'GMX Mail',
|
|
5640
|
-
};
|
|
5569
|
+
// A "business" that resolves to the address's own mail provider is not the contact's
|
|
5570
|
+
// employer, it is Gmail. get_business_info, handed a bare gmail.com address, answers
|
|
5571
|
+
// "Gmail / gmail.com / Technology" rather than "Not available", so the only escape hatch the
|
|
5572
|
+
// classification had (business_name === 'Not available') never fired and every personal
|
|
5573
|
+
// Gmail contact came out as a business, storefront placeholder and all. This is the second
|
|
5574
|
+
// escape hatch, built on the provider list that already exists directly below.
|
|
5575
|
+
const businessIsJustTheMailProvider = (business_info) => !!identifyPersonalProvider(business_info?.business_domain || '');
|
|
5641
5576
|
|
|
5642
|
-
|
|
5577
|
+
function identifyPersonalProvider(domain) {
|
|
5578
|
+
// The list moved to common so ai_module's contact classifier reads the same one. It used to
|
|
5579
|
+
// live here alone, which is exactly why the classifier could call gmail.com a business.
|
|
5580
|
+
return _common.personal_email_provider(domain);
|
|
5643
5581
|
}
|
|
5644
5582
|
|
|
5645
5583
|
export const add_contact = async function (req, job_id, headers) {
|
|
@@ -5714,21 +5652,24 @@ export const add_contact = async function (req, job_id, headers) {
|
|
|
5714
5652
|
await activity('spam_check', { by: 'ai', is_spam: !!is_spam, subject: metadata.subject });
|
|
5715
5653
|
}
|
|
5716
5654
|
if (!is_spam) {
|
|
5717
|
-
const
|
|
5655
|
+
const verdict = await ai_ms.is_business_contact(uid, email, name, metadata.subject, metadata.summarized_body, account_profile_info);
|
|
5656
|
+
// Tolerates the old bare boolean, in case a stale ai_module answers this call.
|
|
5657
|
+
const is_business = typeof verdict === 'object' && verdict !== null ? verdict.is_business : !!verdict;
|
|
5718
5658
|
account_type = is_business ? 'business' : 'personal';
|
|
5719
|
-
await activity('classified', { by: 'ai', account_type, inputs: { email: email.toLowerCase(), name: name || '', subject: metadata.subject || '' } });
|
|
5659
|
+
await activity('classified', { by: 'ai', account_type, confidence: verdict?.confidence, why: verdict?.reason, inputs: { email: email.toLowerCase(), name: name || '', subject: metadata.subject || '' } });
|
|
5720
5660
|
if (is_business) {
|
|
5721
5661
|
business_info = await ai_ms.get_business_info(uid, '', email, account_profile_info, { light: true });
|
|
5722
|
-
if (business_info.business_name !== 'Not available') {
|
|
5662
|
+
if (business_info.business_name !== 'Not available' && !businessIsJustTheMailProvider(business_info)) {
|
|
5723
5663
|
await activity('business_info', { by: 'ai', depth: 'light', business_name: business_info.business_name, business_domain: business_info.business_domain, business_category: business_info.business_category });
|
|
5724
5664
|
business_has_person = await ai_ms.is_business_contact_has_person(uid, email, name, metadata.subject, metadata.summarized_body, account_profile_info);
|
|
5725
5665
|
await activity('business_has_person', { by: 'ai', has_person: !!business_has_person });
|
|
5726
5666
|
} else {
|
|
5667
|
+
const provider = identifyPersonalProvider(business_info?.business_domain || '');
|
|
5727
5668
|
account_type = 'personal';
|
|
5728
5669
|
business_info = undefined;
|
|
5729
5670
|
// The reversal matters more than the original verdict: the card says
|
|
5730
5671
|
// personal even though the business call answered yes.
|
|
5731
|
-
await activity('classified', { by: 'ai', account_type, reverted_from: 'business', reason: 'no business could be identified behind the address' });
|
|
5672
|
+
await activity('classified', { by: 'ai', account_type, reverted_from: 'business', reason: provider ? `the only business behind the address is its mail provider (${provider})` : 'no business could be identified behind the address' });
|
|
5732
5673
|
}
|
|
5733
5674
|
}
|
|
5734
5675
|
if (_.isEmpty(cached_contact) && account_type === 'business' && !business_has_person) {
|
|
@@ -6372,19 +6313,31 @@ export const not_spam_contact = async function (req, job_id, headers) {
|
|
|
6372
6313
|
}
|
|
6373
6314
|
|
|
6374
6315
|
const previous_account_type = contact_doc.account_type;
|
|
6375
|
-
const
|
|
6316
|
+
const verdict = await ai_ms.is_business_contact(uid, contact_doc.email, contact_doc.name, contact_doc?.metadata?.subject, contact_doc?.metadata?.summarized_body, account_profile_info);
|
|
6317
|
+
const is_business = typeof verdict === 'object' && verdict !== null ? verdict.is_business : !!verdict;
|
|
6376
6318
|
contact_doc.account_type = is_business ? 'business' : 'personal';
|
|
6377
|
-
await log_contact_activity(uid, contact_id, 'classified', { by: 'ai', trigger: 'not spam', account_type: contact_doc.account_type, previous_account_type: previous_account_type || 'unset' });
|
|
6319
|
+
await log_contact_activity(uid, contact_id, 'classified', { by: 'ai', trigger: 'not spam', account_type: contact_doc.account_type, confidence: verdict?.confidence, why: verdict?.reason, previous_account_type: previous_account_type || 'unset' });
|
|
6320
|
+
if (!is_business && (contact_doc.business_info || contact_doc.business_has_person)) {
|
|
6321
|
+
// A contact that reclassifies from business to person used to keep the company profile
|
|
6322
|
+
// the old verdict attached to it, because business_info is only ever written inside the
|
|
6323
|
+
// is_business branch and nothing clears it on the way out. The card then showed a person
|
|
6324
|
+
// with a company still on file.
|
|
6325
|
+
const dropped = contact_doc?.business_info?.business_name;
|
|
6326
|
+
contact_doc.business_info = undefined;
|
|
6327
|
+
contact_doc.business_has_person = undefined;
|
|
6328
|
+
await log_contact_activity(uid, contact_id, 'business_info_cleared', { reason: 'contact reclassified as a person', dropped });
|
|
6329
|
+
}
|
|
6378
6330
|
if (is_business) {
|
|
6379
6331
|
contact_doc.business_info = await ai_ms.get_business_info(uid, '', contact_doc.email, account_profile_info, { light: true });
|
|
6380
|
-
if (contact_doc.business_info.business_name !== 'Not available') {
|
|
6332
|
+
if (contact_doc.business_info.business_name !== 'Not available' && !businessIsJustTheMailProvider(contact_doc.business_info)) {
|
|
6381
6333
|
await log_contact_activity(uid, contact_id, 'business_info', { by: 'ai', depth: 'light', business_name: contact_doc.business_info.business_name, business_domain: contact_doc.business_info.business_domain, business_category: contact_doc.business_info.business_category });
|
|
6382
6334
|
contact_doc.business_has_person = await ai_ms.is_business_contact_has_person(uid, contact_doc.email, contact_doc.name, contact_doc?.metadata?.subject, contact_doc?.metadata?.summarized_body, account_profile_info);
|
|
6383
6335
|
await log_contact_activity(uid, contact_id, 'business_has_person', { by: 'ai', has_person: !!contact_doc.business_has_person });
|
|
6384
6336
|
} else {
|
|
6337
|
+
const provider = identifyPersonalProvider(contact_doc.business_info?.business_domain || '');
|
|
6385
6338
|
contact_doc.account_type = 'personal';
|
|
6386
6339
|
contact_doc.business_info = undefined;
|
|
6387
|
-
await log_contact_activity(uid, contact_id, 'classified', { by: 'ai', account_type: 'personal', reverted_from: 'business', reason: 'no business could be identified behind the address' });
|
|
6340
|
+
await log_contact_activity(uid, contact_id, 'classified', { by: 'ai', account_type: 'personal', reverted_from: 'business', reason: provider ? `the only business behind the address is its mail provider (${provider})` : 'no business could be identified behind the address' });
|
|
6388
6341
|
}
|
|
6389
6342
|
}
|
|
6390
6343
|
|
|
@@ -6471,14 +6424,15 @@ export const set_deep_research_contact = async function (req, job_id, headers) {
|
|
|
6471
6424
|
|
|
6472
6425
|
if (contact_doc.account_type === 'business') {
|
|
6473
6426
|
contact_doc.business_info = await ai_ms.get_business_info(uid, '', contact_doc.email, account_profile_info);
|
|
6474
|
-
if (contact_doc.business_info.business_name !== 'Not available') {
|
|
6427
|
+
if (contact_doc.business_info.business_name !== 'Not available' && !businessIsJustTheMailProvider(contact_doc.business_info)) {
|
|
6475
6428
|
await log_contact_activity(uid, contact_id, 'business_info', { by: 'ai', depth: 'deep', business_name: contact_doc.business_info.business_name, business_domain: contact_doc.business_info.business_domain, business_category: contact_doc.business_info.business_category });
|
|
6476
6429
|
contact_doc.business_has_person = await ai_ms.is_business_contact_has_person(uid, contact_doc.email, contact_doc.name, contact_doc?.metadata?.subject, contact_doc?.metadata?.summarized_body, account_profile_info);
|
|
6477
6430
|
await log_contact_activity(uid, contact_id, 'business_has_person', { by: 'ai', has_person: !!contact_doc.business_has_person });
|
|
6478
6431
|
} else {
|
|
6432
|
+
const provider = identifyPersonalProvider(contact_doc.business_info?.business_domain || '');
|
|
6479
6433
|
contact_doc.account_type = 'personal';
|
|
6480
6434
|
contact_doc.business_info = undefined;
|
|
6481
|
-
await log_contact_activity(uid, contact_id, 'classified', { by: 'ai', account_type: 'personal', reverted_from: 'business', reason: 'deep research found no business behind the address' });
|
|
6435
|
+
await log_contact_activity(uid, contact_id, 'classified', { by: 'ai', account_type: 'personal', reverted_from: 'business', reason: provider ? `the only business behind the address is its mail provider (${provider})` : 'deep research found no business behind the address' });
|
|
6482
6436
|
}
|
|
6483
6437
|
}
|
|
6484
6438
|
|
|
@@ -6568,7 +6522,16 @@ export const get_contact_activity = async function (req) {
|
|
|
6568
6522
|
try {
|
|
6569
6523
|
if (!contact_id) throw new Error('contact_id is missing');
|
|
6570
6524
|
const account_profile_info = await get_active_account_profile_info(uid);
|
|
6571
|
-
|
|
6525
|
+
// get_app_couch_doc_native THROWS a bare couch 'missing' for an id that is not in
|
|
6526
|
+
// this account's app db (an id from another account is the common way to get here),
|
|
6527
|
+
// so the not-found check below never ran and the caller saw "missing" with nothing
|
|
6528
|
+
// to act on. Catch it and answer the question that was actually asked.
|
|
6529
|
+
let contact_doc;
|
|
6530
|
+
try {
|
|
6531
|
+
contact_doc = await db_module.get_app_couch_doc_native(account_profile_info.app_id, contact_id);
|
|
6532
|
+
} catch (_) {
|
|
6533
|
+
contact_doc = null;
|
|
6534
|
+
}
|
|
6572
6535
|
if (!contact_doc || contact_doc.docType !== 'contact') throw new Error(`contact ${contact_id} not found`);
|
|
6573
6536
|
if (contact_doc.uid !== uid && contact_doc?.uid_created !== uid) throw new Error('Operation not allowed');
|
|
6574
6537
|
|
|
@@ -6688,7 +6651,11 @@ export const get_account_profile_info = async function (uid, contact_profile_doc
|
|
|
6688
6651
|
|
|
6689
6652
|
const get_pattern = async function (doc) {
|
|
6690
6653
|
// Same level-based default as get_contact_pattern, so a card shows the same
|
|
6691
|
-
// verification tile whichever path built it
|
|
6654
|
+
// verification tile whichever path built it, and the same two states that
|
|
6655
|
+
// outrank a level: a shared profile wears its owner's avatar, spam says
|
|
6656
|
+
// spam. A business profile used to paint its own logo across the card face,
|
|
6657
|
+
// which is why a verified business showed no level at all; the logo is
|
|
6658
|
+
// already the avatar on the same card, so the tile is the level here too.
|
|
6692
6659
|
let ret = level_pattern(doc);
|
|
6693
6660
|
|
|
6694
6661
|
if (doc.shared_from_uid) {
|
|
@@ -6697,26 +6664,6 @@ export const get_account_profile_info = async function (uid, contact_profile_doc
|
|
|
6697
6664
|
ret = shared_from_uid_ret.data.profile_avatar;
|
|
6698
6665
|
} else if (doc.is_spam) {
|
|
6699
6666
|
ret = `spam-pattern.png`;
|
|
6700
|
-
} else if (doc.account_type === 'business') {
|
|
6701
|
-
ret = doc.profile_picture;
|
|
6702
|
-
} else {
|
|
6703
|
-
switch (doc.avatar_source) {
|
|
6704
|
-
case 'fictional':
|
|
6705
|
-
ret = `fictional-avatar-pattern.png`;
|
|
6706
|
-
break;
|
|
6707
|
-
|
|
6708
|
-
case 'ai profile':
|
|
6709
|
-
ret = `fictional-avatar-pattern.png`;
|
|
6710
|
-
break;
|
|
6711
|
-
|
|
6712
|
-
case 'authentic profile':
|
|
6713
|
-
ret = `authentic-avatar-pattern.png`;
|
|
6714
|
-
break;
|
|
6715
|
-
|
|
6716
|
-
default:
|
|
6717
|
-
ret = `xu-pattern.png`;
|
|
6718
|
-
break;
|
|
6719
|
-
}
|
|
6720
6667
|
}
|
|
6721
6668
|
|
|
6722
6669
|
return ret;
|
|
@@ -6774,6 +6721,10 @@ export const get_account_profile_info = async function (uid, contact_profile_doc
|
|
|
6774
6721
|
// console.log(stringToColour('Project Z')); // -> Consistent color for "Project Z"
|
|
6775
6722
|
|
|
6776
6723
|
doc.avatar_source = account_info_ret.data.avatar_source;
|
|
6724
|
+
// A profile inherits the verification level of the account that owns it (a
|
|
6725
|
+
// shared profile, the account that shared it), so its card reads the same
|
|
6726
|
+
// level as its owner's contact card instead of falling back to L0.
|
|
6727
|
+
doc.verify_level = account_info_ret.data.verify_level;
|
|
6777
6728
|
doc.icon_pattern = await get_pattern(doc);
|
|
6778
6729
|
doc.name = doc.profile_name;
|
|
6779
6730
|
doc.interactions = 0;
|