@xuda.io/account_module 1.2.1256 → 1.2.1258

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 (2) hide show
  1. package/index.mjs +825 -861
  2. package/package.json +1 -1
package/index.mjs CHANGED
@@ -1601,566 +1601,165 @@ const get_user_contact = async function (uid, uid_query) {
1601
1601
  return doc;
1602
1602
  };
1603
1603
 
1604
- export const get_contacts = async function (req) {
1605
- const { _id, uid, name, limit, skip, bookmark, search, filter_type = 'all', contact_id } = req;
1604
+ // invite user
1606
1605
 
1607
- const account_profile_info = await get_active_account_profile_info(uid);
1608
- if (_id) {
1609
- let data = await db_module.get_couch_doc('xuda_contacts', _id);
1610
- return data;
1611
- }
1606
+ // const contact_ret = await db_module.get_couch_view_raw(
1607
+ // "xuda_contacts",
1608
+ // "contacts_by_name_count",
1609
+ // {
1610
+ // startkey: [uid, ""],
1611
+ // endkey: [uid, "ZZZZZZZZZZ"],
1612
+ // reduce: true,
1613
+ // group_level: 2,
1614
+ // }
1615
+ // );
1612
1616
 
1613
- let { with_requests } = req;
1614
- var opt = {
1615
- selector: {
1616
- docType: 'contact',
1617
- uid: account_profile_info.uid,
1618
- stat: { $lt: 4 },
1619
- },
1620
- limit: limit || 9999,
1621
- skip: skip || 0,
1622
- sort: [{ ts: 'desc' }],
1623
- };
1617
+ // const get_contact_id = async function (uid, contact_uid) {
1618
+ // contact_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_contact_uid', { key: [uid, contact_uid] });
1619
+ // return contact_ret?.rows?.[0]?.id;
1620
+ // };
1624
1621
 
1625
- switch (filter_type) {
1626
- case 'archived': {
1627
- opt.selector.stat = 5;
1628
- break;
1629
- }
1630
- case 'shared': {
1631
- opt.selector.shared_from_uid = { $gt: null };
1632
- break;
1633
- }
1622
+ export const update_contact = async function (req) {
1623
+ const { uid, email, contact_uid, stat, team_req_id } = req;
1634
1624
 
1635
- case 'pinned': {
1636
- opt.selector.pinned = true;
1637
- break;
1638
- }
1625
+ const account_profile_info = await get_active_account_profile_info(uid);
1639
1626
 
1640
- case 'online': {
1641
- opt.limit = 9999;
1642
- break;
1627
+ var contact_ret;
1628
+ if (email) {
1629
+ contact_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_user_email_address', { key: [account_profile_info.uid, email] });
1630
+ } else if (contact_uid) {
1631
+ contact_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_contact_uid', { key: [account_profile_info.uid, contact_uid] });
1632
+ }
1633
+ if (contact_ret.rows.length) {
1634
+ var doc = contact_ret.rows[0].value;
1635
+ if (stat) {
1636
+ doc.stat = stat;
1637
+ doc.stat_ts = Date.now();
1638
+ }
1639
+ if (team_req_id) {
1640
+ doc.team_req_id = team_req_id;
1643
1641
  }
1644
1642
 
1645
- default:
1646
- with_requests = true;
1647
- break;
1648
- }
1643
+ if (contact_uid) {
1644
+ const ret = await db_module.get_couch_doc('xuda_accounts', contact_uid);
1645
+ const account_obj = ret.data;
1646
+ doc.profile_picture = account_obj.account_info.profile_picture;
1647
+ doc.profile_avatar = account_obj.account_info.profile_avatar;
1648
+ }
1649
1649
 
1650
- if (_id) {
1651
- opt.selector._id = _id;
1650
+ return await db_module.save_couch_doc('xuda_contacts', doc);
1652
1651
  }
1652
+ return { code: -1, data: 'contact not found' };
1653
+ };
1654
+ // export const invite_user = async function (req) {
1655
+ // const { email, name, uid } = req;
1653
1656
 
1654
- if (contact_id) {
1655
- opt.selector._id = contact_id;
1656
- }
1657
+ // const team_module = await import(`${module_path}/team_module/index.mjs`);
1658
+ // const ret = await team_module.create_team_request({
1659
+ // email,
1660
+ // access_type: 'contact',
1661
+ // uid,
1662
+ // });
1657
1663
 
1658
- if (typeof name !== 'undefined') {
1659
- opt.selector.name = { $regex: `(?i)${name}` };
1660
- }
1664
+ // // return { code: -1, data: "contact already exist active or deleted" };
1665
+ // };
1661
1666
 
1662
- if (typeof search !== 'undefined') {
1663
- opt.selector['$or'] = [
1664
- {
1665
- name: {
1666
- $regex: `(?i)${search}`,
1667
- },
1668
- },
1669
- {
1670
- email: {
1671
- $regex: `(?i)${search}`,
1672
- },
1673
- },
1674
- ];
1667
+ export const get_account_rt_info = async function (uid) {
1668
+ const doc_ret = await db_module.get_couch_doc('xuda_accounts', uid);
1669
+ if (doc_ret.code < 0) {
1670
+ console.error('get_account_rt_info', doc_ret);
1671
+ return {};
1675
1672
  }
1673
+ var account_info = doc_ret.data.account_info;
1676
1674
 
1677
- if (bookmark && bookmark !== 'nil') {
1678
- opt.bookmark = bookmark;
1679
- }
1675
+ delete account_info.user_id;
1680
1676
 
1681
- let contacts = { docs: [], total_docs: 0 };
1677
+ account_info.uid = doc_ret.data._id;
1678
+ return account_info;
1679
+ };
1682
1680
 
1683
- if (filter_type !== 'pending') {
1684
- contacts = await db_module.find_couch_query('xuda_contacts', opt);
1685
- if (!limit || contact_id) {
1686
- contacts.total_docs = contacts.docs.length;
1687
- } else {
1688
- delete opt.sort;
1689
- delete opt.skip;
1690
- opt.limit = 9999;
1691
- opt.fields = ['_id'];
1681
+ export const validate_account_topup = async function (uid, items = []) {
1682
+ const stripe_module = await import(`${module_path}/stripe_module/index.mjs`);
1692
1683
 
1693
- const counter = await db_module.find_couch_query('xuda_contacts', opt);
1694
- contacts.total_docs = counter.docs.length;
1695
- }
1684
+ const { code, data } = await stripe_module.get_billing_metrics({ uid });
1685
+ if (code < 0) {
1686
+ throw new Error(data);
1687
+ }
1688
+ let topup = 0;
1689
+ for (const item of items) {
1690
+ topup += get_prices(uid, item);
1696
1691
  }
1697
1692
 
1698
- let requests_to = { docs: [], total_docs: 0 };
1699
- let requests_from = { docs: [], total_docs: 0 };
1700
- let shared_from = { docs: [], total_docs: 0 };
1701
-
1702
- let contact_docs = { docs: [], total_docs: contacts.total_docs };
1703
- for await (let doc of contacts.docs) {
1704
- const ret_to = requests_to.docs.find((e) => {
1705
- return e.contact_uid === doc.contact_uid;
1706
- });
1707
- if (ret_to) continue;
1708
-
1709
- const ret_from = requests_from.docs.find((e) => {
1710
- return e.contact_uid === doc.contact_uid;
1711
- });
1712
- if (ret_from) continue;
1693
+ if (!data?.customer_obj?.default_source) {
1694
+ let err = new Error('no card on file');
1695
+ err.code = -90;
1696
+ err.billing_problem = true;
1697
+ throw err;
1698
+ // throw new Error('no card on file');
1699
+ }
1713
1700
 
1714
- doc = await get_contact_info(uid, doc);
1701
+ if (data?.balance?.past_due) {
1702
+ let err = new Error(`past_due ${data.balance.past_due}`);
1703
+ err.code = -91;
1704
+ err.billing_problem = true;
1705
+ err.topup = topup + data.balance.past_due;
1706
+ err.open_invoices = data?.open_invoices;
1707
+ throw err;
1708
+ }
1709
+ // if (data?.balance?.past_due) {
1710
+ // let err = new Error(`past_due ${data?.balance?.past_due}`);
1711
+ // err.code = -91;
1712
+ // err.billing_problem = true;
1713
+ // err.topup = topup;
1714
+ // throw err;
1715
+ // }
1715
1716
 
1716
- if (filter_type === 'online') {
1717
- if (!doc.online) continue;
1718
- }
1717
+ const balance = data?.balance?.account || 0; // minus balance represents positive balance
1719
1718
 
1720
- contact_docs.docs.push(doc);
1719
+ if (balance > 0) {
1720
+ let err = new Error(`negative balance ${-balance}`);
1721
+ err.code = -92;
1722
+ err.billing_problem = true;
1723
+ err.topup = topup - balance; // ask for whole balance
1724
+ throw err;
1721
1725
  }
1722
1726
 
1723
- if (!contact_id && with_requests) {
1724
- if (filter_type === 'pending') {
1725
- ////// TO - OUT
1726
- requests_to.docs = await get_pending_contact_out(uid);
1727
- requests_to.total_docs = requests_to.docs.length;
1728
-
1729
- ////// FROM - IN
1730
- requests_from.docs = await get_pending_contact_in(uid);
1731
- requests_from.total_docs = requests_from.docs.length;
1732
- shared_from.docs = await get_pending_share_contact_in(uid);
1733
- shared_from.total_docs = shared_from.docs.length;
1734
- }
1727
+ if (topup + balance > 0) {
1728
+ let err = new Error(`not enough balance ${topup + balance}`);
1729
+ err.code = -93;
1730
+ err.billing_problem = true;
1731
+ err.topup = topup;
1732
+ throw err;
1735
1733
  }
1736
1734
 
1737
- return {
1738
- code: 1,
1739
- data: {
1740
- docs: [...shared_from.docs, ...requests_from.docs, ...requests_to.docs, ...contact_docs.docs],
1741
- total_docs: shared_from.total_docs + requests_from.total_docs + requests_to.total_docs + contact_docs.total_docs,
1742
- },
1743
- };
1735
+ return true;
1744
1736
  };
1745
1737
 
1746
- export const archive_contact = async function (req) {
1747
- const { contact_id } = req;
1748
- try {
1749
- const team_module = await import(`${module_path}/team_module/index.mjs`);
1750
- await team_module.validate_share_exist(uid, 'contact', contact_id);
1738
+ const get_prices = function (uid, item) {
1739
+ let price;
1751
1740
 
1752
- var contact_doc = await db_module.get_couch_doc_native('xuda_contacts', contact_id);
1741
+ switch (item) {
1742
+ case 'user_group':
1743
+ case 'pwa':
1744
+ case 'preview':
1745
+ case 'android':
1746
+ case 'ios':
1747
+ case 'macos':
1748
+ case 'emitter':
1749
+ price = _conf.PRICE_OBJ.deployments[item];
1750
+ break;
1753
1751
 
1754
- if (contact_doc.uid !== uid && contact_doc?.account_profile_info?.uid !== uid) {
1755
- throw new Error('Operation not allowed');
1756
- }
1752
+ case 'drive_ocr':
1753
+ price = _conf.PRICE_OBJ.drive_addons.ocr.price;
1754
+ break;
1757
1755
 
1758
- contact_doc.stat = 5;
1759
- contact_doc.stat_ts = Date.now();
1760
- contact_doc.stat_reason = 'archived by the user';
1756
+ case 'drive_edit_image':
1757
+ price = _conf.PRICE_OBJ.drive_addons.edit_image.price;
1758
+ break;
1761
1759
 
1762
- const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
1763
-
1764
- return contact_save_ret;
1765
- } catch (err) {
1766
- return {
1767
- code: -22,
1768
- data: err.message,
1769
- };
1770
- }
1771
- };
1772
-
1773
- export const delete_contact = async function (req, job_id, headers) {
1774
- const { contact_id } = req;
1775
- try {
1776
- var contact_doc = await db_module.get_couch_doc_native('xuda_contacts', contact_id);
1777
- if (contact_doc.stat !== 5) {
1778
- throw new Error('A document can only be deleted after it has been archived');
1779
- }
1780
- contact_doc.stat = 4;
1781
- contact_doc.stat_ts = Date.now();
1782
- contact_doc.stat_reason = 'deleted by the user';
1783
-
1784
- const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
1785
- const ai_module = await import(`${module_path}/ai_module/index.mjs`);
1786
- ai_module.delete_depended_chats(uid, contact_id);
1787
- return contact_save_ret;
1788
- } catch (err) {
1789
- return {
1790
- code: -22,
1791
- data: err.message,
1792
- };
1793
- }
1794
- };
1795
-
1796
- export const unarchive_contact = async function (req) {
1797
- const { contact_id } = req;
1798
- try {
1799
- var contact_doc = await db_module.get_couch_doc_native('xuda_contacts', contact_id);
1800
-
1801
- if (contact_doc.stat !== 5) {
1802
- throw new Error('contact is not archived');
1803
- }
1804
-
1805
- contact_doc.stat = 3;
1806
- contact_doc.stat_ts = Date.now();
1807
- contact_doc.stat_reason = 'archived by the user';
1808
-
1809
- const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
1810
-
1811
- return contact_save_ret;
1812
- } catch (err) {
1813
- return {
1814
- code: -22,
1815
- data: err.message,
1816
- };
1817
- }
1818
- };
1819
-
1820
- export const unfriend_contact = async function (req) {
1821
- const { contact_id } = req;
1822
- try {
1823
- const contact_ret = await db_module.get_couch_doc('xuda_contacts', contact_id);
1824
- if (contact_ret.code < 0) {
1825
- throw new Error(contact_ret.data);
1826
- }
1827
- var contact_doc = contact_ret.data;
1828
-
1829
- if (!contact_doc.team_req_id) {
1830
- throw new Error('no friend relationship found');
1831
- }
1832
- let req_doc = await db_module.get_couch_doc_native('xuda_team', contact_doc.team_req_id);
1833
- req_doc.team_req_stat = 4;
1834
- req_doc.team_req_stat_desc = 'unfriend by the user';
1835
- await db_module.get_couch_doc_native('xuda_team', contact_doc.team_req_id);
1836
-
1837
- contact_doc.team_req_id = null;
1838
- const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
1839
-
1840
- const req_save_ret = await db_module.save_couch_doc('xuda_team', req_doc);
1841
-
1842
- return req_save_ret;
1843
- } catch (err) {
1844
- return {
1845
- code: -21,
1846
- data: err.message,
1847
- };
1848
- }
1849
- };
1850
-
1851
- export const pin_contact = async function (req) {
1852
- const { uid, contact_id } = req;
1853
- try {
1854
- const contact_ret = await db_module.get_couch_doc('xuda_contacts', contact_id);
1855
- if (contact_ret.code < 0) {
1856
- return contact_ret;
1857
- }
1858
- var contact_doc = contact_ret.data;
1859
- contact_doc.pinned = true;
1860
-
1861
- const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
1862
-
1863
- global[`_account_module_ch`].sendToQueue(
1864
- 'ws_dashboard_module',
1865
- Buffer.from(
1866
- JSON.stringify({
1867
- method: 'emit_message_to_dashboard',
1868
- data: {
1869
- service: 'contact_pinned',
1870
- to: [uid],
1871
- data: await get_contact_info(uid, null, contact_id),
1872
- },
1873
- }),
1874
- ),
1875
- );
1876
-
1877
- return contact_save_ret;
1878
- } catch (err) {
1879
- return {
1880
- code: -24,
1881
- data: err.message,
1882
- };
1883
- }
1884
- };
1885
-
1886
- export const unpin_contact = async function (req) {
1887
- const { contact_id, uid } = req;
1888
- try {
1889
- const contact_ret = await db_module.get_couch_doc('xuda_contacts', contact_id);
1890
- if (contact_ret.code < 0) {
1891
- return contact_ret;
1892
- }
1893
- var contact_doc = contact_ret.data;
1894
- contact_doc.pinned = false;
1895
-
1896
- const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
1897
-
1898
- global[`_account_module_ch`].sendToQueue(
1899
- 'ws_dashboard_module',
1900
- Buffer.from(
1901
- JSON.stringify({
1902
- method: 'emit_message_to_dashboard',
1903
- data: {
1904
- service: 'contact_unpinned',
1905
- to: [uid],
1906
- data: await get_contact_info(uid, null, contact_id),
1907
- },
1908
- }),
1909
- ),
1910
- );
1911
-
1912
- return contact_save_ret;
1913
- } catch (err) {
1914
- return {
1915
- code: -24,
1916
- data: err.message,
1917
- };
1918
- }
1919
- };
1920
-
1921
- // invite user
1922
-
1923
- // const contact_ret = await db_module.get_couch_view_raw(
1924
- // "xuda_contacts",
1925
- // "contacts_by_name_count",
1926
- // {
1927
- // startkey: [uid, ""],
1928
- // endkey: [uid, "ZZZZZZZZZZ"],
1929
- // reduce: true,
1930
- // group_level: 2,
1931
- // }
1932
- // );
1933
-
1934
- export const add_contact = async function (req, job_id, headers) {
1935
- try {
1936
- const { uid, email, name, stat, contact_uid, context, source, team_req_id, metadata = {} } = req;
1937
- const account_profile_info = await get_active_account_profile_info(uid);
1938
-
1939
- const contact_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_user_email_address', { key: [account_profile_info.uid, email] });
1940
-
1941
- if (contact_ret.rows.length) {
1942
- throw new Error('contact already exist active or deleted');
1943
- }
1944
-
1945
- let is_spam = false;
1946
- let profile_avatar, profile_avatar_obj;
1947
- let account_info_ret;
1948
- if (contact_uid) {
1949
- account_info_ret = await get_account_name({ uid_query: contact_uid });
1950
- if (account_info_ret.code < 0) {
1951
- throw new Error(`account ${contact_uid} not found`);
1952
- }
1953
- } else {
1954
- // contact without use account
1955
- if (metadata.subject && !metadata.is_sent) {
1956
- is_spam_ret = await ai_module.is_spam_email(uid, email, metadata.subject);
1957
- try {
1958
- if (is_spam_ret.code > -1) {
1959
- const data = JSON.parse(is_spam_ret.data);
1960
- is_spam = data.is_spam;
1961
- }
1962
- } catch (error) {}
1963
- }
1964
-
1965
- const existing_contacts_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_email_address', { key: email });
1966
- for (const contact of existing_contacts_ret.rows) {
1967
- if (contact.value.profile_avatar) {
1968
- profile_avatar = contact.value.profile_avatar;
1969
- profile_avatar_obj == contact.value.profile_avatar_obj;
1970
- }
1971
- }
1972
- }
1973
- const d = Date.now();
1974
- const doc = {
1975
- _id: await _common.xuda_get_uuid('contact'),
1976
- email: [email],
1977
- name,
1978
- stat: stat || 1,
1979
- date_created: d,
1980
- ts: d,
1981
- docType: 'contact',
1982
- contact_uid,
1983
- uid: account_profile_info.uid,
1984
- uid_created: uid,
1985
- context,
1986
- headers,
1987
- source,
1988
- team_req_id,
1989
- metadata,
1990
- is_spam,
1991
- profile_avatar,
1992
- profile_avatar_obj,
1993
- account_profile_info,
1994
- };
1995
- const ret = await db_module.save_couch_doc('xuda_contacts', doc);
1996
-
1997
- if (!account_info_ret?.data?.profile_avatar) {
1998
- const app_id = await get_account_default_project_id(uid);
1999
- const ai_module = await import(`${module_path}/ai_module/index.mjs`);
2000
- if (account_info_ret?.data?.profile_avatar) {
2001
- // account_info_ret.data.profile_avatar_stat = 2;
2002
- ai_module.create_profile_avatar({ url: account_info_ret.data.profile_picture, uid, account_obj: { _id: contact_uid, account_info: account_info_ret.data }, account_profile_info }, job_id, headers);
2003
- } else {
2004
- if (!doc.profile_avatar) {
2005
- // create factual avatar
2006
- if (!is_spam) {
2007
- ai_module.update_thumbnail('contact', doc, account_profile_info.app_id, uid, job_id, headers, 'xuda_contacts', [email, doc._id, 'contact', account_profile_info.app_id], account_profile_info);
2008
- }
2009
- }
2010
- }
2011
- }
2012
- return ret;
2013
- } catch (err) {
2014
- return { code: -1, data: err.message };
2015
- }
2016
- };
2017
-
2018
- // const get_contact_id = async function (uid, contact_uid) {
2019
- // contact_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_contact_uid', { key: [uid, contact_uid] });
2020
- // return contact_ret?.rows?.[0]?.id;
2021
- // };
2022
-
2023
- export const update_contact = async function (req) {
2024
- const { uid, email, contact_uid, stat, team_req_id } = req;
2025
-
2026
- const account_profile_info = await get_active_account_profile_info(uid);
2027
-
2028
- var contact_ret;
2029
- if (email) {
2030
- contact_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_user_email_address', { key: [account_profile_info.uid, email] });
2031
- } else if (contact_uid) {
2032
- contact_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_contact_uid', { key: [account_profile_info.uid, contact_uid] });
2033
- }
2034
- if (contact_ret.rows.length) {
2035
- var doc = contact_ret.rows[0].value;
2036
- if (stat) {
2037
- doc.stat = stat;
2038
- doc.stat_ts = Date.now();
2039
- }
2040
- if (team_req_id) {
2041
- doc.team_req_id = team_req_id;
2042
- }
2043
-
2044
- if (contact_uid) {
2045
- const ret = await db_module.get_couch_doc('xuda_accounts', contact_uid);
2046
- const account_obj = ret.data;
2047
- doc.profile_picture = account_obj.account_info.profile_picture;
2048
- doc.profile_avatar = account_obj.account_info.profile_avatar;
2049
- }
2050
-
2051
- return await db_module.save_couch_doc('xuda_contacts', doc);
2052
- }
2053
- return { code: -1, data: 'contact not found' };
2054
- };
2055
- // export const invite_user = async function (req) {
2056
- // const { email, name, uid } = req;
2057
-
2058
- // const team_module = await import(`${module_path}/team_module/index.mjs`);
2059
- // const ret = await team_module.create_team_request({
2060
- // email,
2061
- // access_type: 'contact',
2062
- // uid,
2063
- // });
2064
-
2065
- // // return { code: -1, data: "contact already exist active or deleted" };
2066
- // };
2067
-
2068
- export const get_account_rt_info = async function (uid) {
2069
- const doc_ret = await db_module.get_couch_doc('xuda_accounts', uid);
2070
- if (doc_ret.code < 0) {
2071
- console.error('get_account_rt_info', doc_ret);
2072
- return {};
2073
- }
2074
- var account_info = doc_ret.data.account_info;
2075
-
2076
- delete account_info.user_id;
2077
-
2078
- account_info.uid = doc_ret.data._id;
2079
- return account_info;
2080
- };
2081
-
2082
- export const validate_account_topup = async function (uid, items = []) {
2083
- const stripe_module = await import(`${module_path}/stripe_module/index.mjs`);
2084
-
2085
- const { code, data } = await stripe_module.get_billing_metrics({ uid });
2086
- if (code < 0) {
2087
- throw new Error(data);
2088
- }
2089
- let topup = 0;
2090
- for (const item of items) {
2091
- topup += get_prices(uid, item);
2092
- }
2093
-
2094
- if (!data?.customer_obj?.default_source) {
2095
- let err = new Error('no card on file');
2096
- err.code = -90;
2097
- err.billing_problem = true;
2098
- throw err;
2099
- // throw new Error('no card on file');
2100
- }
2101
-
2102
- if (data?.balance?.past_due) {
2103
- let err = new Error(`past_due ${data.balance.past_due}`);
2104
- err.code = -91;
2105
- err.billing_problem = true;
2106
- err.topup = topup + data.balance.past_due;
2107
- err.open_invoices = data?.open_invoices;
2108
- throw err;
2109
- }
2110
- // if (data?.balance?.past_due) {
2111
- // let err = new Error(`past_due ${data?.balance?.past_due}`);
2112
- // err.code = -91;
2113
- // err.billing_problem = true;
2114
- // err.topup = topup;
2115
- // throw err;
2116
- // }
2117
-
2118
- const balance = data?.balance?.account || 0; // minus balance represents positive balance
2119
-
2120
- if (balance > 0) {
2121
- let err = new Error(`negative balance ${-balance}`);
2122
- err.code = -92;
2123
- err.billing_problem = true;
2124
- err.topup = topup - balance; // ask for whole balance
2125
- throw err;
2126
- }
2127
-
2128
- if (topup + balance > 0) {
2129
- let err = new Error(`not enough balance ${topup + balance}`);
2130
- err.code = -93;
2131
- err.billing_problem = true;
2132
- err.topup = topup;
2133
- throw err;
2134
- }
2135
-
2136
- return true;
2137
- };
2138
-
2139
- const get_prices = function (uid, item) {
2140
- let price;
2141
-
2142
- switch (item) {
2143
- case 'user_group':
2144
- case 'pwa':
2145
- case 'preview':
2146
- case 'android':
2147
- case 'ios':
2148
- case 'macos':
2149
- case 'emitter':
2150
- price = _conf.PRICE_OBJ.deployments[item];
2151
- break;
2152
-
2153
- case 'drive_ocr':
2154
- price = _conf.PRICE_OBJ.drive_addons.ocr.price;
2155
- break;
2156
-
2157
- case 'drive_edit_image':
2158
- price = _conf.PRICE_OBJ.drive_addons.edit_image.price;
2159
- break;
2160
-
2161
- case 'auto_backup':
2162
- price = _conf.PRICE_OBJ.auto_backup_per_month;
2163
- break;
1760
+ case 'auto_backup':
1761
+ price = _conf.PRICE_OBJ.auto_backup_per_month;
1762
+ break;
2164
1763
 
2165
1764
  case 'deployment_offline':
2166
1765
  price = _conf.PRICE_OBJ.deployment_offline_per_month;
@@ -2216,395 +1815,730 @@ export const create_account_oauth_link = async function (req, job_id) {
2216
1815
  };
2217
1816
  };
2218
1817
 
2219
- export const get_default_project_account_doc = async function (uid) {
2220
- const ret = await db_module.get_couch_doc('xuda_accounts', uid);
2221
- return ret.data;
2222
- };
2223
- export const get_account_default_project_id = async function (uid) {
2224
- const account_obj = await get_default_project_account_doc(uid);
2225
- return account_obj.account_project_id;
1818
+ export const get_default_project_account_doc = async function (uid) {
1819
+ const ret = await db_module.get_couch_doc('xuda_accounts', uid);
1820
+ return ret.data;
1821
+ };
1822
+ export const get_account_default_project_id = async function (uid) {
1823
+ const account_obj = await get_default_project_account_doc(uid);
1824
+ return account_obj.account_project_id;
1825
+ };
1826
+
1827
+ setTimeout(async () => {
1828
+ // const uid = "0489f946c213947316647b468f029ed9"; //"aecc740881fd0a35098c738652000fab";
1829
+
1830
+ // // // clear data
1831
+ // // const contact_ret = await db_module.find_couch_query("xuda_contacts", {
1832
+ // // selector: {
1833
+ // // docType: "contact",
1834
+ // // },
1835
+ // // limit: 99999,
1836
+ // // });
1837
+ // // var contact_docs = [];
1838
+ // // for (let val of contact_ret.docs) {
1839
+ // // val._deleted = true;
1840
+ // // contact_docs.push(val);
1841
+ // // }
1842
+ // // await db_module.save_couch_bulk_docs("xuda_contacts", contact_docs);
1843
+
1844
+ // // const emails_ret = await db_module.find_couch_query("xuda_emails", {
1845
+ // // selector: {
1846
+ // // docType: "email",
1847
+ // // },
1848
+ // // limit: 99999,
1849
+ // // });
1850
+ // // var email_docs = [];
1851
+ // // for (let val of emails_ret.docs) {
1852
+ // // val._deleted = true;
1853
+ // // email_docs.push(val);
1854
+ // // }
1855
+
1856
+ // // await db_module.save_couch_bulk_docs("xuda_emails", email_docs);
1857
+
1858
+ // ///////////////////////////////////
1859
+ // return;
1860
+ // const email_account_ret = await get_email_accounts({
1861
+ // uid,
1862
+ // });
1863
+
1864
+ // var accessToken;
1865
+ // for await (let email_account of email_account_ret.data.docs) {
1866
+ // switch (email_account.vendor) {
1867
+ // case "gmail":
1868
+ // const ret = await generate_gmail_access_token(email_account);
1869
+ // accessToken = ret.access_token;
1870
+ // break;
1871
+
1872
+ // default:
1873
+ // break;
1874
+ // }
1875
+
1876
+ // read_emails({
1877
+ // uid,
1878
+ // email_account_address: email_account.email,
1879
+ // accessToken,
1880
+ // email_account_id: email_account._id,
1881
+ // vendor: email_account.vendor,
1882
+ // });
1883
+ // }
1884
+
1885
+ // // console.log(await get_contact({ uid, name: "bo" }));
1886
+
1887
+ let ret;
1888
+ // ret = await add_contact({ uid: 'd39126e0e2c51ffbd1aad10709fc8335', name: 'Boaz Avrahami', email: 'bocabo67@gmail.com', context: {} }, null, { 'accept-language': 'en-US,en;q=0.9,he;q=0.8' });
1889
+ console.log(ret);
1890
+ }, 2000);
1891
+
1892
+ export const get_user_name = async function (uid) {
1893
+ try {
1894
+ const account_info = await get_account_name({ uid });
1895
+ let username = 'unknown';
1896
+ if (account_info) {
1897
+ username = account_info.first_name + ' ' + account_info.last_name;
1898
+
1899
+ if (!username) {
1900
+ username = +account_info.email;
1901
+ }
1902
+ }
1903
+
1904
+ return username;
1905
+ } catch (err) {
1906
+ return 'unknown';
1907
+ }
1908
+ };
1909
+
1910
+ // TBD
1911
+ export const update_contacts_with_account_changes = async function (uid, changes = []) {
1912
+ try {
1913
+ if (!changes.length) return;
1914
+ const ret = await db_module.get_couch_doc('xuda_accounts', uid);
1915
+ var account_obj = ret.data;
1916
+ account_obj.ts = Date.now();
1917
+
1918
+ // update all uid contacts with the new avatar
1919
+ const opt = {
1920
+ selector: { contact_uid: uid, docType: 'contact' },
1921
+ };
1922
+ debugger;
1923
+ let changes_made;
1924
+ var contacts = await db_module.find_couch_query('xuda_contacts', opt);
1925
+ for (let doc of contacts.docs) {
1926
+ if (changes.includes('profile_picture')) {
1927
+ changes_made = true;
1928
+ doc.profile_picture = account_obj.account_info.profile_picture;
1929
+ }
1930
+ if (changes.includes('profile_avatar')) {
1931
+ changes_made = true;
1932
+ doc.profile_avatar = account_obj.account_info.profile_avatar;
1933
+ }
1934
+ if (changes.includes('email')) {
1935
+ changes_made = true;
1936
+ doc.email = account_obj.account_info.email;
1937
+ }
1938
+ if (changes.includes('first_name') || changes.includes('last_name')) {
1939
+ changes_made = true;
1940
+ doc.name = `${account_obj.account_info.first_name} ${account_obj.account_info.last_name}`;
1941
+ }
1942
+
1943
+ console.log(doc);
1944
+ }
1945
+ if (contacts.docs && changes_made) {
1946
+ await db_module.save_couch_bulk_docs('xuda_contacts', contacts.docs);
1947
+ }
1948
+
1949
+ return username;
1950
+ } catch (err) {
1951
+ return 'unknown';
1952
+ }
1953
+ };
1954
+
1955
+ export const get_user_card = async function (uid, uid_query) {
1956
+ if (uid === uid_query) return await get_user_contact(uid, uid_query);
1957
+
1958
+ let user_contact_obj; // = { border, card_background, contact_uid, date_created, docType, icon_pattern, name, business_name, profile_avatar, connection_stat, username, bio, notifications, email, phone_number };
1959
+
1960
+ const contact_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_contact_uid', { key: [uid, uid_query] });
1961
+
1962
+ const contact_id = contact_ret?.rows?.[0]?.id;
1963
+ if (contact_id) {
1964
+ user_contact_obj = await get_contact_info(uid, null, contact_id);
1965
+ } else {
1966
+ user_contact_obj = await get_user_contact(uid, uid_query);
1967
+ }
1968
+ return user_contact_obj;
1969
+ };
1970
+
1971
+ // export const generate_user_avatar = async function (req, job_id, headers) {
1972
+ // const { uid, account_info } = req;
1973
+ // try {
1974
+ // const ai_module = await import(`${module_path}/ai_module/index.mjs`);
1975
+
1976
+ // ai_module.create_profile_avatar({ url: account_info?.profile_picture, uid, account_obj }, job_id, headers);
1977
+
1978
+ // // const account_info = await get_account_name({ uid });
1979
+ // // let username = 'unknown';
1980
+ // // if (account_info) {
1981
+ // // username = account_info.first_name + ' ' + account_info.last_name;
1982
+
1983
+ // // if (!username) {
1984
+ // // username = +account_info.email;
1985
+ // // }
1986
+ // // }
1987
+
1988
+ // // return username;
1989
+ // } catch (err) {
1990
+ // return 'unknown';
1991
+ // }
1992
+ // };
1993
+
1994
+ export const onboarding_completed = async function (req, job_id, headers) {
1995
+ const { uid } = req;
1996
+ try {
1997
+ await update_account_info(req, job_id, headers);
1998
+
1999
+ let account_doc = await db_module.get_couch_doc_native('xuda_accounts', uid);
2000
+
2001
+ if (!account_doc.account_info?.profile_picture) {
2002
+ throw new Error(`missing profile_picture`);
2003
+ }
2004
+
2005
+ if (!account_doc.account_info?.profile_avatar) {
2006
+ throw new Error(`missing profile_avatar`);
2007
+ }
2008
+
2009
+ if (!account_doc.account_project_id) {
2010
+ const app_module = await import(`${module_path}/app_module/index.mjs`);
2011
+
2012
+ const ret = await app_module.create_project({ token_ret: req.token_ret, uid, data: { app_name: `Account ${uid} main project`, is_account_project: true, app_plugins_purchased: [' @xuda.io/xuda-dbs-plugin-xuda', '@xuda.io/xuda-framework-plugin-tailwind'] } }, job_id, headers);
2013
+ if (ret.code > -1) {
2014
+ account_doc.account_project_id = ret.data;
2015
+ const drive_module = await import(`${module_path}/drive_module/index.mjs`);
2016
+ let drive_req = { app_id: account_doc.account_project_id, uid, path: '/' };
2017
+ await drive_module.create_drive_folder_user({ ...drive_req, ...{ folder_name: 'Profile Images', is_system: true } }, job_id, headers);
2018
+ await drive_module.create_drive_folder_user({ ...drive_req, ...{ folder_name: 'Chat Thumbnails', is_system: true } }, job_id, headers);
2019
+ await drive_module.create_drive_folder_user({ ...drive_req, ...{ folder_name: 'Chat Attachments', is_system: true } }, job_id, headers);
2020
+ }
2021
+ }
2022
+
2023
+ account_doc.account_info.full_name = `${account_doc.account_info.first_name} ${account_doc.account_info.last_name}`;
2024
+
2025
+ if (!account_doc.ai_workspace_plan) {
2026
+ account_doc.ai_workspace_plan = 'free_ai_workspace';
2027
+ }
2028
+ if (!account_doc.account_profile_id) {
2029
+ const account_profile_ret = await create_account_profile({ uid, profile_name: account_doc.account_info.full_name, main: true });
2030
+ account_doc.account_profile_id = account_profile_ret.data.id;
2031
+ account_doc.account_info.active_account_profile_id = account_doc.account_profile_id;
2032
+ }
2033
+ account_doc.boarded_info = { headers, date_ts: Date.now() };
2034
+ account_doc.isBoarded = true;
2035
+ const save_ret = await db_module.save_couch_doc('xuda_accounts', account_doc);
2036
+
2037
+ /// create view
2038
+
2039
+ let _design = await db_module.get_app_couch_doc_native(account_doc.account_project_id, '_design/xuda');
2040
+ if (!_design.views.ai_chat_usage) {
2041
+ _design.views['ai_chat_usage'] = {
2042
+ map: "function formatTimestampToDDMMYYYY(timestampMs) {\n const date = new Date(timestampMs); // directly use milliseconds\n\n const day = Number(String(date.getDate()).padStart(2, '0'));\n const month =Number( String(date.getMonth() + 1).padStart(2, '0')); // months are 0-based\n const year = date.getFullYear();\n\n // return `${day}/${month}/${year}`;\n return {day,month,year}\n}\n\nfunction (doc) {\n \n if(doc.docType===\"chat_usage\"){\n if(doc.cost && doc.account_profile_info){\n const cost_input=(doc.cost.input/1000000)*doc.input_tokens*100 ;\n const cost_output=(doc.cost.output/1000000)*doc.output_tokens*100 \n \n const d=formatTimestampToDDMMYYYY(doc.date_created_ts)\n emit([d.year,d.month,d.day,doc.account_profile_info.account_profile_id,doc.account_profile_info.account_profile_obj.uid,doc.model], [doc.input_tokens,doc.output_tokens ,cost_input,cost_output]);\n // emit([d.year,d.month,d.day,doc.model], [doc.input_tokens,doc.output_tokens]);\n}\n }\n }",
2043
+ reduce: '_sum',
2044
+ };
2045
+ }
2046
+ await db_module.save_app_couch_doc_native(account_doc.account_project_id, _design);
2047
+ ///////
2048
+
2049
+ return save_ret;
2050
+ } catch (err) {
2051
+ return { code: -44, data: err.message };
2052
+ }
2053
+ };
2054
+
2055
+ export const ts_contact = async function (contact_id) {
2056
+ try {
2057
+ const contact_doc = await db_module.get_couch_doc_native('xuda_contacts', contact_id);
2058
+ contact_doc.ts = Date.now();
2059
+ const save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
2060
+ return save_ret;
2061
+ } catch (err) {
2062
+ console.error(err);
2063
+ }
2226
2064
  };
2227
2065
 
2228
- setTimeout(async () => {
2229
- // const uid = "0489f946c213947316647b468f029ed9"; //"aecc740881fd0a35098c738652000fab";
2066
+ export const get_account_ai_usage = async function (req, job_id, headers) {
2067
+ const { uid, year, month, day, usage_scope = 'account' } = req;
2068
+ try {
2069
+ const app_id = await get_account_default_project_id(uid);
2070
+ const { data: acc_obj } = await db_module.get_couch_doc('xuda_accounts', uid);
2230
2071
 
2231
- // // // clear data
2232
- // // const contact_ret = await db_module.find_couch_query("xuda_contacts", {
2233
- // // selector: {
2234
- // // docType: "contact",
2235
- // // },
2236
- // // limit: 99999,
2237
- // // });
2238
- // // var contact_docs = [];
2239
- // // for (let val of contact_ret.docs) {
2240
- // // val._deleted = true;
2241
- // // contact_docs.push(val);
2242
- // // }
2243
- // // await db_module.save_couch_bulk_docs("xuda_contacts", contact_docs);
2072
+ const d = new Date();
2073
+ const curr_month = Number(String(d.getMonth() + 1).padStart(2, '0')); // months are 0-based
2074
+ const curr_year = d.getFullYear();
2244
2075
 
2245
- // // const emails_ret = await db_module.find_couch_query("xuda_emails", {
2246
- // // selector: {
2247
- // // docType: "email",
2248
- // // },
2249
- // // limit: 99999,
2250
- // // });
2251
- // // var email_docs = [];
2252
- // // for (let val of emails_ret.docs) {
2253
- // // val._deleted = true;
2254
- // // email_docs.push(val);
2255
- // // }
2076
+ const ai_usage = await db_module.get_app_couch_view(app_id, 'ai_chat_usage', {
2077
+ startkey: [year || curr_year, month || curr_month, day || 0],
2078
+ endkey: [year || curr_year, month || curr_month, day || 99],
2079
+ reduce: true,
2080
+ group_level: 999,
2081
+ });
2082
+ // console.log('ai_usage', ai_usage.rows);
2256
2083
 
2257
- // // await db_module.save_couch_bulk_docs("xuda_emails", email_docs);
2084
+ let total_usage = 0;
2085
+ let profile = {};
2258
2086
 
2259
- // ///////////////////////////////////
2260
- // return;
2261
- // const email_account_ret = await get_email_accounts({
2262
- // uid,
2263
- // });
2087
+ for (const row of ai_usage.rows) {
2088
+ const year = row.key[0];
2089
+ const month = row.key[1];
2090
+ const day = row.key[2];
2091
+ const account_profile_id = row.key[3];
2092
+ const uid = row.key[4];
2093
+ const model = row.key[5];
2094
+ const input_tokens = row.value[0];
2095
+ const output_tokens = row.value[1];
2096
+ const input_credits = row.value[2];
2097
+ const output_credits = row.value[3];
2098
+ if (!profile[account_profile_id]) {
2099
+ profile[account_profile_id] = {};
2100
+ }
2101
+ if (!profile[account_profile_id][uid]) {
2102
+ profile[account_profile_id][uid] = 0;
2103
+ }
2264
2104
 
2265
- // var accessToken;
2266
- // for await (let email_account of email_account_ret.data.docs) {
2267
- // switch (email_account.vendor) {
2268
- // case "gmail":
2269
- // const ret = await generate_gmail_access_token(email_account);
2270
- // accessToken = ret.access_token;
2271
- // break;
2105
+ profile[account_profile_id][uid] += input_credits + output_credits;
2106
+ total_usage += input_credits + output_credits;
2107
+ }
2272
2108
 
2273
- // default:
2274
- // break;
2275
- // }
2109
+ let membership_plan = _conf.PLAN_OBJ?.[acc_obj?.ai_workspace_plan]?.features?.ai_credits || 0;
2110
+ let ai_workspace_plan = _conf.PLAN_OBJ?.[acc_obj?.membership_plan]?.features?.ai_credits || 0;
2111
+ let contact_connection = 0;
2112
+ let total_credits = membership_plan + ai_workspace_plan + contact_connection;
2276
2113
 
2277
- // read_emails({
2278
- // uid,
2279
- // email_account_address: email_account.email,
2280
- // accessToken,
2281
- // email_account_id: email_account._id,
2282
- // vendor: email_account.vendor,
2283
- // });
2284
- // }
2114
+ let data = { credits: { membership_plan, ai_workspace_plan, contact_connection, total: total_credits }, usage: { profile, projects: [], total: total_usage } };
2285
2115
 
2286
- // // console.log(await get_contact({ uid, name: "bo" }));
2116
+ return { code: 55, data };
2117
+ } catch (err) {
2118
+ return { code: -55, data: err.message };
2119
+ }
2120
+ };
2121
+
2122
+ setTimeout(async () => {
2123
+ const app_id = 'prj712ffdf5aa8adce6cedef988f9c12392'; //'prj3937cb6f9a31c8c7dea25055bba845b1'; //
2124
+ const uid = 'd39126e0e2c51ffbd1aad10709fc8335';
2287
2125
 
2288
2126
  let ret;
2289
- // ret = await add_contact({ uid: 'd39126e0e2c51ffbd1aad10709fc8335', name: 'Boaz Avrahami', email: 'bocabo67@gmail.com', context: {} }, null, { 'accept-language': 'en-US,en;q=0.9,he;q=0.8' });
2127
+
2128
+ // ret = await get_account_ai_usage({ uid });
2129
+ // ret = await create_account_profile({ uid });
2130
+ // ret = await get_account_profiles({ uid });
2131
+
2132
+ // let _design = await db_module.get_app_couch_doc_native(app_id, '_design/xuda');
2133
+ // ret = _design.views.ai_chat_usage;
2134
+ // console.log(_design.views.ai_chat_usage);
2290
2135
  console.log(ret);
2291
- }, 2000);
2136
+ }, 1000);
2292
2137
 
2293
- export const get_user_name = async function (uid) {
2138
+ //////// CONTACTS //////////////
2139
+
2140
+ export const add_contact = async function (req, job_id, headers) {
2294
2141
  try {
2295
- const account_info = await get_account_name({ uid });
2296
- let username = 'unknown';
2297
- if (account_info) {
2298
- username = account_info.first_name + ' ' + account_info.last_name;
2142
+ const { uid, email, name, stat, contact_uid, context, source, team_req_id, metadata = {} } = req;
2143
+ const account_profile_info = await get_active_account_profile_info(uid);
2299
2144
 
2300
- if (!username) {
2301
- username = +account_info.email;
2145
+ const contact_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_user_email_address', { key: [account_profile_info.uid, email] });
2146
+
2147
+ if (contact_ret.rows.length) {
2148
+ throw new Error('contact already exist active or deleted');
2149
+ }
2150
+
2151
+ let is_spam = false;
2152
+ let profile_avatar, profile_avatar_obj;
2153
+ let account_info_ret;
2154
+ if (contact_uid) {
2155
+ account_info_ret = await get_account_name({ uid_query: contact_uid });
2156
+ if (account_info_ret.code < 0) {
2157
+ throw new Error(`account ${contact_uid} not found`);
2158
+ }
2159
+ } else {
2160
+ // contact without use account
2161
+ if (metadata.subject && !metadata.is_sent) {
2162
+ is_spam_ret = await ai_module.is_spam_email(uid, email, metadata.subject);
2163
+ try {
2164
+ if (is_spam_ret.code > -1) {
2165
+ const data = JSON.parse(is_spam_ret.data);
2166
+ is_spam = data.is_spam;
2167
+ }
2168
+ } catch (error) {}
2169
+ }
2170
+
2171
+ const existing_contacts_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_email_address', { key: email });
2172
+ for (const contact of existing_contacts_ret.rows) {
2173
+ if (contact.value.profile_avatar) {
2174
+ profile_avatar = contact.value.profile_avatar;
2175
+ profile_avatar_obj == contact.value.profile_avatar_obj;
2176
+ }
2302
2177
  }
2303
2178
  }
2179
+ const d = Date.now();
2180
+ const doc = {
2181
+ _id: await _common.xuda_get_uuid('contact'),
2182
+ email: [email],
2183
+ name,
2184
+ stat: stat || 1,
2185
+ date_created: d,
2186
+ ts: d,
2187
+ docType: 'contact',
2188
+ contact_uid,
2189
+ uid: account_profile_info.uid,
2190
+ uid_created: uid,
2191
+ context,
2192
+ headers,
2193
+ source,
2194
+ team_req_id,
2195
+ metadata,
2196
+ is_spam,
2197
+ profile_avatar,
2198
+ profile_avatar_obj,
2199
+ account_profile_info,
2200
+ };
2201
+ const ret = await db_module.save_couch_doc('xuda_contacts', doc);
2304
2202
 
2305
- return username;
2203
+ if (!account_info_ret?.data?.profile_avatar) {
2204
+ const app_id = await get_account_default_project_id(uid);
2205
+ const ai_module = await import(`${module_path}/ai_module/index.mjs`);
2206
+ if (account_info_ret?.data?.profile_avatar) {
2207
+ // account_info_ret.data.profile_avatar_stat = 2;
2208
+ ai_module.create_profile_avatar({ url: account_info_ret.data.profile_picture, uid, account_obj: { _id: contact_uid, account_info: account_info_ret.data }, account_profile_info }, job_id, headers);
2209
+ } else {
2210
+ if (!doc.profile_avatar) {
2211
+ // create factual avatar
2212
+ if (!is_spam) {
2213
+ ai_module.update_thumbnail('contact', doc, account_profile_info.app_id, uid, job_id, headers, 'xuda_contacts', [email, doc._id, 'contact', account_profile_info.app_id], account_profile_info);
2214
+ }
2215
+ }
2216
+ }
2217
+ }
2218
+ return ret;
2306
2219
  } catch (err) {
2307
- return 'unknown';
2220
+ return { code: -1, data: err.message };
2308
2221
  }
2309
2222
  };
2310
2223
 
2311
- // TBD
2312
- export const update_contacts_with_account_changes = async function (uid, changes = []) {
2313
- try {
2314
- if (!changes.length) return;
2315
- const ret = await db_module.get_couch_doc('xuda_accounts', uid);
2316
- var account_obj = ret.data;
2317
- account_obj.ts = Date.now();
2224
+ export const get_contacts = async function (req) {
2225
+ const { _id, uid, name, limit, skip, bookmark, search, filter_type = 'all', contact_id } = req;
2318
2226
 
2319
- // update all uid contacts with the new avatar
2320
- const opt = {
2321
- selector: { contact_uid: uid, docType: 'contact' },
2322
- };
2323
- debugger;
2324
- let changes_made;
2325
- var contacts = await db_module.find_couch_query('xuda_contacts', opt);
2326
- for (let doc of contacts.docs) {
2327
- if (changes.includes('profile_picture')) {
2328
- changes_made = true;
2329
- doc.profile_picture = account_obj.account_info.profile_picture;
2330
- }
2331
- if (changes.includes('profile_avatar')) {
2332
- changes_made = true;
2333
- doc.profile_avatar = account_obj.account_info.profile_avatar;
2334
- }
2335
- if (changes.includes('email')) {
2336
- changes_made = true;
2337
- doc.email = account_obj.account_info.email;
2338
- }
2339
- if (changes.includes('first_name') || changes.includes('last_name')) {
2340
- changes_made = true;
2341
- doc.name = `${account_obj.account_info.first_name} ${account_obj.account_info.last_name}`;
2342
- }
2227
+ const account_profile_info = await get_active_account_profile_info(uid);
2228
+ if (_id) {
2229
+ let data = await db_module.get_couch_doc('xuda_contacts', _id);
2230
+ return data;
2231
+ }
2232
+
2233
+ let { with_requests } = req;
2234
+ var opt = {
2235
+ selector: {
2236
+ docType: 'contact',
2237
+ uid: account_profile_info.uid,
2238
+ stat: { $lt: 4 },
2239
+ },
2240
+ limit: limit || 9999,
2241
+ skip: skip || 0,
2242
+ sort: [{ ts: 'desc' }],
2243
+ };
2343
2244
 
2344
- console.log(doc);
2245
+ switch (filter_type) {
2246
+ case 'archived': {
2247
+ opt.selector.stat = 5;
2248
+ break;
2345
2249
  }
2346
- if (contacts.docs && changes_made) {
2347
- await db_module.save_couch_bulk_docs('xuda_contacts', contacts.docs);
2250
+ case 'shared': {
2251
+ opt.selector.shared_from_uid = { $gt: null };
2252
+ break;
2348
2253
  }
2349
2254
 
2350
- return username;
2351
- } catch (err) {
2352
- return 'unknown';
2353
- }
2354
- };
2255
+ case 'pinned': {
2256
+ opt.selector.pinned = true;
2257
+ break;
2258
+ }
2355
2259
 
2356
- export const get_user_card = async function (uid, uid_query) {
2357
- if (uid === uid_query) return await get_user_contact(uid, uid_query);
2260
+ case 'online': {
2261
+ opt.limit = 9999;
2262
+ break;
2263
+ }
2358
2264
 
2359
- let user_contact_obj; // = { border, card_background, contact_uid, date_created, docType, icon_pattern, name, business_name, profile_avatar, connection_stat, username, bio, notifications, email, phone_number };
2265
+ default:
2266
+ with_requests = true;
2267
+ break;
2268
+ }
2360
2269
 
2361
- const contact_ret = await db_module.get_couch_view_raw('xuda_contacts', 'contacts_by_contact_uid', { key: [uid, uid_query] });
2270
+ if (_id) {
2271
+ opt.selector._id = _id;
2272
+ }
2362
2273
 
2363
- const contact_id = contact_ret?.rows?.[0]?.id;
2364
2274
  if (contact_id) {
2365
- user_contact_obj = await get_contact_info(uid, null, contact_id);
2366
- } else {
2367
- user_contact_obj = await get_user_contact(uid, uid_query);
2275
+ opt.selector._id = contact_id;
2368
2276
  }
2369
- return user_contact_obj;
2370
- };
2371
-
2372
- // export const generate_user_avatar = async function (req, job_id, headers) {
2373
- // const { uid, account_info } = req;
2374
- // try {
2375
- // const ai_module = await import(`${module_path}/ai_module/index.mjs`);
2376
-
2377
- // ai_module.create_profile_avatar({ url: account_info?.profile_picture, uid, account_obj }, job_id, headers);
2378
2277
 
2379
- // // const account_info = await get_account_name({ uid });
2380
- // // let username = 'unknown';
2381
- // // if (account_info) {
2382
- // // username = account_info.first_name + ' ' + account_info.last_name;
2278
+ if (typeof name !== 'undefined') {
2279
+ opt.selector.name = { $regex: `(?i)${name}` };
2280
+ }
2383
2281
 
2384
- // // if (!username) {
2385
- // // username = +account_info.email;
2386
- // // }
2387
- // // }
2282
+ if (typeof search !== 'undefined') {
2283
+ opt.selector['$or'] = [
2284
+ {
2285
+ name: {
2286
+ $regex: `(?i)${search}`,
2287
+ },
2288
+ },
2289
+ {
2290
+ email: {
2291
+ $regex: `(?i)${search}`,
2292
+ },
2293
+ },
2294
+ ];
2295
+ }
2388
2296
 
2389
- // // return username;
2390
- // } catch (err) {
2391
- // return 'unknown';
2392
- // }
2393
- // };
2297
+ if (bookmark && bookmark !== 'nil') {
2298
+ opt.bookmark = bookmark;
2299
+ }
2394
2300
 
2395
- export const onboarding_completed = async function (req, job_id, headers) {
2396
- const { uid } = req;
2397
- try {
2398
- await update_account_info(req, job_id, headers);
2301
+ let contacts = { docs: [], total_docs: 0 };
2399
2302
 
2400
- let account_doc = await db_module.get_couch_doc_native('xuda_accounts', uid);
2303
+ if (filter_type !== 'pending') {
2304
+ contacts = await db_module.find_couch_query('xuda_contacts', opt);
2305
+ if (!limit || contact_id) {
2306
+ contacts.total_docs = contacts.docs.length;
2307
+ } else {
2308
+ delete opt.sort;
2309
+ delete opt.skip;
2310
+ opt.limit = 9999;
2311
+ opt.fields = ['_id'];
2401
2312
 
2402
- if (!account_doc.account_info?.profile_picture) {
2403
- throw new Error(`missing profile_picture`);
2313
+ const counter = await db_module.find_couch_query('xuda_contacts', opt);
2314
+ contacts.total_docs = counter.docs.length;
2404
2315
  }
2316
+ }
2405
2317
 
2406
- if (!account_doc.account_info?.profile_avatar) {
2407
- throw new Error(`missing profile_avatar`);
2408
- }
2318
+ let requests_to = { docs: [], total_docs: 0 };
2319
+ let requests_from = { docs: [], total_docs: 0 };
2320
+ let shared_from = { docs: [], total_docs: 0 };
2409
2321
 
2410
- if (!account_doc.account_project_id) {
2411
- const app_module = await import(`${module_path}/app_module/index.mjs`);
2322
+ let contact_docs = { docs: [], total_docs: contacts.total_docs };
2323
+ for await (let doc of contacts.docs) {
2324
+ const ret_to = requests_to.docs.find((e) => {
2325
+ return e.contact_uid === doc.contact_uid;
2326
+ });
2327
+ if (ret_to) continue;
2412
2328
 
2413
- const ret = await app_module.create_project({ token_ret: req.token_ret, uid, data: { app_name: `Account ${uid} main project`, is_account_project: true, app_plugins_purchased: [' @xuda.io/xuda-dbs-plugin-xuda', '@xuda.io/xuda-framework-plugin-tailwind'] } }, job_id, headers);
2414
- if (ret.code > -1) {
2415
- account_doc.account_project_id = ret.data;
2416
- const drive_module = await import(`${module_path}/drive_module/index.mjs`);
2417
- let drive_req = { app_id: account_doc.account_project_id, uid, path: '/' };
2418
- await drive_module.create_drive_folder_user({ ...drive_req, ...{ folder_name: 'Profile Images', is_system: true } }, job_id, headers);
2419
- await drive_module.create_drive_folder_user({ ...drive_req, ...{ folder_name: 'Chat Thumbnails', is_system: true } }, job_id, headers);
2420
- await drive_module.create_drive_folder_user({ ...drive_req, ...{ folder_name: 'Chat Attachments', is_system: true } }, job_id, headers);
2421
- }
2422
- }
2329
+ const ret_from = requests_from.docs.find((e) => {
2330
+ return e.contact_uid === doc.contact_uid;
2331
+ });
2332
+ if (ret_from) continue;
2423
2333
 
2424
- account_doc.account_info.full_name = `${account_doc.account_info.first_name} ${account_doc.account_info.last_name}`;
2334
+ doc = await get_contact_info(uid, doc);
2425
2335
 
2426
- if (!account_doc.ai_workspace_plan) {
2427
- account_doc.ai_workspace_plan = 'free_ai_workspace';
2428
- }
2429
- if (!account_doc.account_profile_id) {
2430
- const account_profile_ret = await create_account_profile({ uid, profile_name: account_doc.account_info.full_name, main: true });
2431
- account_doc.account_profile_id = account_profile_ret.data.id;
2432
- account_doc.account_info.active_account_profile_id = account_doc.account_profile_id;
2336
+ if (filter_type === 'online') {
2337
+ if (!doc.online) continue;
2433
2338
  }
2434
- account_doc.boarded_info = { headers, date_ts: Date.now() };
2435
- account_doc.isBoarded = true;
2436
- const save_ret = await db_module.save_couch_doc('xuda_accounts', account_doc);
2437
2339
 
2438
- /// create view
2340
+ contact_docs.docs.push(doc);
2341
+ }
2439
2342
 
2440
- let _design = await db_module.get_app_couch_doc_native(account_doc.account_project_id, '_design/xuda');
2441
- if (!_design.views.ai_chat_usage) {
2442
- _design.views['ai_chat_usage'] = {
2443
- map: "function formatTimestampToDDMMYYYY(timestampMs) {\n const date = new Date(timestampMs); // directly use milliseconds\n\n const day = Number(String(date.getDate()).padStart(2, '0'));\n const month =Number( String(date.getMonth() + 1).padStart(2, '0')); // months are 0-based\n const year = date.getFullYear();\n\n // return `${day}/${month}/${year}`;\n return {day,month,year}\n}\n\nfunction (doc) {\n \n if(doc.docType===\"chat_usage\"){\n if(doc.cost && doc.account_profile_info){\n const cost_input=(doc.cost.input/1000000)*doc.input_tokens*100 ;\n const cost_output=(doc.cost.output/1000000)*doc.output_tokens*100 \n \n const d=formatTimestampToDDMMYYYY(doc.date_created_ts)\n emit([d.year,d.month,d.day,doc.account_profile_info.account_profile_id,doc.account_profile_info.account_profile_obj.uid,doc.model], [doc.input_tokens,doc.output_tokens ,cost_input,cost_output]);\n // emit([d.year,d.month,d.day,doc.model], [doc.input_tokens,doc.output_tokens]);\n}\n }\n }",
2444
- reduce: '_sum',
2445
- };
2446
- }
2447
- await db_module.save_app_couch_doc_native(account_doc.account_project_id, _design);
2448
- ///////
2343
+ if (!contact_id && with_requests) {
2344
+ if (filter_type === 'pending') {
2345
+ ////// TO - OUT
2346
+ requests_to.docs = await get_pending_contact_out(uid);
2347
+ requests_to.total_docs = requests_to.docs.length;
2449
2348
 
2450
- return save_ret;
2451
- } catch (err) {
2452
- return { code: -44, data: err.message };
2349
+ ////// FROM - IN
2350
+ requests_from.docs = await get_pending_contact_in(uid);
2351
+ requests_from.total_docs = requests_from.docs.length;
2352
+ shared_from.docs = await get_pending_share_contact_in(uid);
2353
+ shared_from.total_docs = shared_from.docs.length;
2354
+ }
2453
2355
  }
2454
- };
2455
2356
 
2456
- export const ts_contact = async function (contact_id) {
2457
- try {
2458
- const contact_doc = await db_module.get_couch_doc_native('xuda_contacts', contact_id);
2459
- contact_doc.ts = Date.now();
2460
- const save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
2461
- return save_ret;
2462
- } catch (err) {
2463
- console.error(err);
2464
- }
2357
+ return {
2358
+ code: 1,
2359
+ data: {
2360
+ docs: [...shared_from.docs, ...requests_from.docs, ...requests_to.docs, ...contact_docs.docs],
2361
+ total_docs: shared_from.total_docs + requests_from.total_docs + requests_to.total_docs + contact_docs.total_docs,
2362
+ },
2363
+ };
2465
2364
  };
2466
2365
 
2467
- export const get_account_ai_usage = async function (req, job_id, headers) {
2468
- const { uid, year, month, day, usage_scope = 'account' } = req;
2366
+ export const archive_contact = async function (req) {
2367
+ const { contact_id } = req;
2469
2368
  try {
2470
- const app_id = await get_account_default_project_id(uid);
2471
- const { data: acc_obj } = await db_module.get_couch_doc('xuda_accounts', uid);
2472
-
2473
- const d = new Date();
2474
- const curr_month = Number(String(d.getMonth() + 1).padStart(2, '0')); // months are 0-based
2475
- const curr_year = d.getFullYear();
2369
+ const team_module = await import(`${module_path}/team_module/index.mjs`);
2370
+ await team_module.validate_share_exist(uid, 'contact', contact_id);
2476
2371
 
2477
- const ai_usage = await db_module.get_app_couch_view(app_id, 'ai_chat_usage', {
2478
- startkey: [year || curr_year, month || curr_month, day || 0],
2479
- endkey: [year || curr_year, month || curr_month, day || 99],
2480
- reduce: true,
2481
- group_level: 999,
2482
- });
2483
- // console.log('ai_usage', ai_usage.rows);
2372
+ var contact_doc = await db_module.get_couch_doc_native('xuda_contacts', contact_id);
2484
2373
 
2485
- let total_usage = 0;
2486
- let profile = {};
2374
+ if (contact_doc.uid !== uid && contact_doc?.account_profile_info?.uid !== uid) {
2375
+ throw new Error('Operation not allowed');
2376
+ }
2487
2377
 
2488
- for (const row of ai_usage.rows) {
2489
- const year = row.key[0];
2490
- const month = row.key[1];
2491
- const day = row.key[2];
2492
- const account_profile_id = row.key[3];
2493
- const uid = row.key[4];
2494
- const model = row.key[5];
2495
- const input_tokens = row.value[0];
2496
- const output_tokens = row.value[1];
2497
- const input_credits = row.value[2];
2498
- const output_credits = row.value[3];
2499
- if (!profile[account_profile_id]) {
2500
- profile[account_profile_id] = {};
2501
- }
2502
- if (!profile[account_profile_id][uid]) {
2503
- profile[account_profile_id][uid] = 0;
2504
- }
2378
+ contact_doc.stat = 5;
2379
+ contact_doc.stat_ts = Date.now();
2380
+ contact_doc.stat_reason = 'archived by the user';
2505
2381
 
2506
- profile[account_profile_id][uid] += input_credits + output_credits;
2507
- total_usage += input_credits + output_credits;
2508
- }
2382
+ const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
2509
2383
 
2510
- let membership_plan = _conf.PLAN_OBJ?.[acc_obj?.ai_workspace_plan]?.features?.ai_credits || 0;
2511
- let ai_workspace_plan = _conf.PLAN_OBJ?.[acc_obj?.membership_plan]?.features?.ai_credits || 0;
2512
- let contact_connection = 0;
2513
- let total_credits = membership_plan + ai_workspace_plan + contact_connection;
2384
+ return contact_save_ret;
2385
+ } catch (err) {
2386
+ return {
2387
+ code: -22,
2388
+ data: err.message,
2389
+ };
2390
+ }
2391
+ };
2514
2392
 
2515
- let data = { credits: { membership_plan, ai_workspace_plan, contact_connection, total: total_credits }, usage: { profile, projects: [], total: total_usage } };
2393
+ export const delete_contact = async function (req, job_id, headers) {
2394
+ const { contact_id } = req;
2395
+ try {
2396
+ var contact_doc = await db_module.get_couch_doc_native('xuda_contacts', contact_id);
2397
+ if (contact_doc.stat !== 5) {
2398
+ throw new Error('A document can only be deleted after it has been archived');
2399
+ }
2400
+ contact_doc.stat = 4;
2401
+ contact_doc.stat_ts = Date.now();
2402
+ contact_doc.stat_reason = 'deleted by the user';
2516
2403
 
2517
- return { code: 55, data };
2404
+ const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
2405
+ const ai_module = await import(`${module_path}/ai_module/index.mjs`);
2406
+ ai_module.delete_depended_chats(uid, contact_id);
2407
+ return contact_save_ret;
2518
2408
  } catch (err) {
2519
- return { code: -55, data: err.message };
2409
+ return {
2410
+ code: -22,
2411
+ data: err.message,
2412
+ };
2520
2413
  }
2521
2414
  };
2522
2415
 
2523
- export const create_account_profile = async function (req, job_id, headers) {
2524
- const { uid, profile_name, profile_signature, profile_email, profile_picture, profile_avatar, profile_picture_obj, profile_avatar_obj, main } = req;
2416
+ export const unarchive_contact = async function (req) {
2417
+ const { contact_id } = req;
2525
2418
  try {
2526
- // const app_id = await get_account_default_project_id(uid);
2527
- const { data: acc_obj } = await db_module.get_couch_doc('xuda_accounts', uid);
2419
+ var contact_doc = await db_module.get_couch_doc_native('xuda_contacts', contact_id);
2528
2420
 
2529
- const d = Date.now();
2530
- const doc = {
2531
- _id: await _common.xuda_get_uuid('account_profile'),
2532
- stat: 3,
2533
- date_created_ts: d,
2534
- ts: d,
2535
- docType: 'account_profile',
2421
+ if (contact_doc.stat !== 5) {
2422
+ throw new Error('contact is not archived');
2423
+ }
2536
2424
 
2537
- uid,
2538
- profile_name, //: profile_name || acc_obj.account_info.business_name || acc_obj.account_info.name,
2539
- profile_signature,
2540
- profile_email,
2541
- profile_picture,
2542
- profile_avatar,
2543
- profile_picture_obj,
2544
- profile_avatar_obj,
2545
- main,
2546
- };
2547
- const save_ret = await db_module.save_couch_doc('xuda_accounts', doc);
2548
- // acc_obj.active_profile_id = save_ret.data.id;
2425
+ contact_doc.stat = 3;
2426
+ contact_doc.stat_ts = Date.now();
2427
+ contact_doc.stat_reason = 'archived by the user';
2549
2428
 
2550
- // return { code: 55, data: save_ret };
2551
- return save_ret;
2429
+ const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
2430
+
2431
+ return contact_save_ret;
2552
2432
  } catch (err) {
2553
- return { code: -55, data: err.message };
2433
+ return {
2434
+ code: -22,
2435
+ data: err.message,
2436
+ };
2554
2437
  }
2555
2438
  };
2556
2439
 
2557
- export const update_account_profile = async function (req, job_id, headers) {
2558
- const { uid, _id } = req;
2559
- const account_profile_properties = ['profile_name', 'profile_signature', 'profile_email', 'profile_picture', 'profile_avatar', 'profile_picture_obj', 'profile_avatar_obj', 'auto_respond', 'auto_respond_mode', 'auto_respond_agents'];
2440
+ export const unfriend_contact = async function (req) {
2441
+ const { contact_id } = req;
2560
2442
  try {
2561
- let { data: account_profile_doc } = await db_module.get_couch_doc('xuda_accounts', _id);
2443
+ const contact_ret = await db_module.get_couch_doc('xuda_contacts', contact_id);
2444
+ if (contact_ret.code < 0) {
2445
+ throw new Error(contact_ret.data);
2446
+ }
2447
+ var contact_doc = contact_ret.data;
2562
2448
 
2563
- if (account_profile_doc.docType !== 'account_profile') {
2564
- throw new Error('not account profile doc');
2449
+ if (!contact_doc.team_req_id) {
2450
+ throw new Error('no friend relationship found');
2565
2451
  }
2452
+ let req_doc = await db_module.get_couch_doc_native('xuda_team', contact_doc.team_req_id);
2453
+ req_doc.team_req_stat = 4;
2454
+ req_doc.team_req_stat_desc = 'unfriend by the user';
2455
+ await db_module.get_couch_doc_native('xuda_team', contact_doc.team_req_id);
2566
2456
 
2567
- let changes_arr = [];
2457
+ contact_doc.team_req_id = null;
2458
+ const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
2568
2459
 
2569
- for (const key of account_profile_properties) {
2570
- let val = req[key];
2571
- if (typeof val === 'undefined') continue;
2572
- if (account_profile_doc[key] !== val) {
2573
- changes_arr.push(key);
2574
- account_profile_doc[key] = val;
2575
- }
2576
- }
2460
+ const req_save_ret = await db_module.save_couch_doc('xuda_team', req_doc);
2577
2461
 
2578
- if (!changes_arr.length) {
2579
- // throw new Error('no change');
2580
- return { code: 56, data: 'no change' };
2462
+ return req_save_ret;
2463
+ } catch (err) {
2464
+ return {
2465
+ code: -21,
2466
+ data: err.message,
2467
+ };
2468
+ }
2469
+ };
2470
+
2471
+ export const pin_contact = async function (req) {
2472
+ const { uid, contact_id } = req;
2473
+ try {
2474
+ const contact_ret = await db_module.get_couch_doc('xuda_contacts', contact_id);
2475
+ if (contact_ret.code < 0) {
2476
+ return contact_ret;
2581
2477
  }
2478
+ var contact_doc = contact_ret.data;
2479
+ contact_doc.pinned = true;
2582
2480
 
2583
- account_profile_doc.ts = Date.now();
2481
+ const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
2584
2482
 
2585
- const save_ret = await db_module.save_couch_doc('xuda_accounts', account_profile_doc);
2483
+ global[`_account_module_ch`].sendToQueue(
2484
+ 'ws_dashboard_module',
2485
+ Buffer.from(
2486
+ JSON.stringify({
2487
+ method: 'emit_message_to_dashboard',
2488
+ data: {
2489
+ service: 'contact_pinned',
2490
+ to: [uid],
2491
+ data: await get_contact_info(uid, null, contact_id),
2492
+ },
2493
+ }),
2494
+ ),
2495
+ );
2586
2496
 
2587
- return { code: 56, data: save_ret };
2497
+ return contact_save_ret;
2588
2498
  } catch (err) {
2589
- return { code: -56, data: err.message };
2499
+ return {
2500
+ code: -24,
2501
+ data: err.message,
2502
+ };
2590
2503
  }
2591
2504
  };
2592
2505
 
2593
- setTimeout(async () => {
2594
- const app_id = 'prj712ffdf5aa8adce6cedef988f9c12392'; //'prj3937cb6f9a31c8c7dea25055bba845b1'; //
2595
- const uid = 'd39126e0e2c51ffbd1aad10709fc8335';
2506
+ export const unpin_contact = async function (req) {
2507
+ const { contact_id, uid } = req;
2508
+ try {
2509
+ const contact_ret = await db_module.get_couch_doc('xuda_contacts', contact_id);
2510
+ if (contact_ret.code < 0) {
2511
+ return contact_ret;
2512
+ }
2513
+ var contact_doc = contact_ret.data;
2514
+ contact_doc.pinned = false;
2596
2515
 
2597
- let ret;
2516
+ const contact_save_ret = await db_module.save_couch_doc('xuda_contacts', contact_doc);
2598
2517
 
2599
- // ret = await get_account_ai_usage({ uid });
2600
- // ret = await create_account_profile({ uid });
2601
- // ret = await get_account_profiles({ uid });
2518
+ global[`_account_module_ch`].sendToQueue(
2519
+ 'ws_dashboard_module',
2520
+ Buffer.from(
2521
+ JSON.stringify({
2522
+ method: 'emit_message_to_dashboard',
2523
+ data: {
2524
+ service: 'contact_unpinned',
2525
+ to: [uid],
2526
+ data: await get_contact_info(uid, null, contact_id),
2527
+ },
2528
+ }),
2529
+ ),
2530
+ );
2602
2531
 
2603
- // let _design = await db_module.get_app_couch_doc_native(app_id, '_design/xuda');
2604
- // ret = _design.views.ai_chat_usage;
2605
- // console.log(_design.views.ai_chat_usage);
2606
- console.log(ret);
2607
- }, 1000);
2532
+ return contact_save_ret;
2533
+ } catch (err) {
2534
+ return {
2535
+ code: -24,
2536
+ data: err.message,
2537
+ };
2538
+ }
2539
+ };
2540
+
2541
+ //////// PROFILES //////////////
2608
2542
 
2609
2543
  export const get_pending_share_profile_in = async function (uid, _id) {
2610
2544
  let docs = [];
@@ -2950,42 +2884,72 @@ export const unarchive_account_profile = async function (req) {
2950
2884
  }
2951
2885
  };
2952
2886
 
2953
- // export const unfriend_account_profile = async function (req) {
2954
- // const { profile_id } = req;
2955
- // try {
2956
- //
2957
- // } catch (err) {
2958
- // return {
2959
- // code: -21,
2960
- // data: err.message,
2961
- // };
2962
- // }
2963
- // };
2887
+ export const create_account_profile = async function (req, job_id, headers) {
2888
+ const { uid, profile_name, profile_signature, profile_email, profile_picture, profile_avatar, profile_picture_obj, profile_avatar_obj, main } = req;
2889
+ try {
2890
+ // const app_id = await get_account_default_project_id(uid);
2891
+ const { data: acc_obj } = await db_module.get_couch_doc('xuda_accounts', uid);
2964
2892
 
2965
- // export const validate_account_asset_change = async function (req) {
2966
- // const { profile_id } = req;
2967
- // try {
2968
- // const team_module = await import(`${module_path}/team_module/index.mjs`);
2969
- // var account_profile_doc = await db_module.get_couch_doc_native('xuda_accounts', profile_id);
2893
+ const d = Date.now();
2894
+ const doc = {
2895
+ _id: await _common.xuda_get_uuid('account_profile'),
2896
+ stat: 3,
2897
+ date_created_ts: d,
2898
+ ts: d,
2899
+ docType: 'account_profile',
2970
2900
 
2971
- // if (account_profile_doc.stat !== 5) {
2972
- // throw new Error('account profile is not archived');
2973
- // }
2974
- // if (!account_profile_doc.team_req_id) {
2975
- // account_profile_doc.stat = 3;
2976
- // account_profile_doc.stat_ts = Date.now();
2977
- // account_profile_doc.stat_reason = 'archived by the user';
2901
+ uid,
2902
+ profile_name, //: profile_name || acc_obj.account_info.business_name || acc_obj.account_info.name,
2903
+ profile_signature,
2904
+ profile_email,
2905
+ profile_picture,
2906
+ profile_avatar,
2907
+ profile_picture_obj,
2908
+ profile_avatar_obj,
2909
+ main,
2910
+ };
2911
+ const save_ret = await db_module.save_couch_doc('xuda_accounts', doc);
2912
+ // acc_obj.active_profile_id = save_ret.data.id;
2978
2913
 
2979
- // const account_profile_save_ret = await db_module.save_couch_doc('xuda_accounts', account_profile_doc);
2914
+ // return { code: 55, data: save_ret };
2915
+ return save_ret;
2916
+ } catch (err) {
2917
+ return { code: -55, data: err.message };
2918
+ }
2919
+ };
2980
2920
 
2981
- // return account_profile_save_ret;
2982
- // } else {
2983
- // return await team_module.change_account_profile_dependencies_status(account_profile_doc.team_req_id, 3);
2984
- // }
2985
- // } catch (err) {
2986
- // return {
2987
- // code: -22,
2988
- // data: err.message,
2989
- // };
2990
- // }
2991
- // };
2921
+ export const update_account_profile = async function (req, job_id, headers) {
2922
+ const { uid, _id } = req;
2923
+ const account_profile_properties = ['profile_name', 'profile_signature', 'profile_email', 'profile_picture', 'profile_avatar', 'profile_picture_obj', 'profile_avatar_obj', 'auto_respond', 'auto_respond_mode', 'auto_respond_agents'];
2924
+ try {
2925
+ let { data: account_profile_doc } = await db_module.get_couch_doc('xuda_accounts', _id);
2926
+
2927
+ if (account_profile_doc.docType !== 'account_profile') {
2928
+ throw new Error('not account profile doc');
2929
+ }
2930
+
2931
+ let changes_arr = [];
2932
+
2933
+ for (const key of account_profile_properties) {
2934
+ let val = req[key];
2935
+ if (typeof val === 'undefined') continue;
2936
+ if (account_profile_doc[key] !== val) {
2937
+ changes_arr.push(key);
2938
+ account_profile_doc[key] = val;
2939
+ }
2940
+ }
2941
+
2942
+ if (!changes_arr.length) {
2943
+ // throw new Error('no change');
2944
+ return { code: 56, data: 'no change' };
2945
+ }
2946
+
2947
+ account_profile_doc.ts = Date.now();
2948
+
2949
+ const save_ret = await db_module.save_couch_doc('xuda_accounts', account_profile_doc);
2950
+
2951
+ return { code: 56, data: save_ret };
2952
+ } catch (err) {
2953
+ return { code: -56, data: err.message };
2954
+ }
2955
+ };