text: const Gun = require("gun");
  const gun = Gun(require("./settings"));
  require("gun/sea");
  const SEA = Gun.SEA;
  const user = gun.user();
  
  function asyncAuth(alias, passwd) {
    return new Promise((resolve, reject) => {
      user.auth(alias, passwd, (cb) => {
        if (cb.err) return reject(cb.err);
        resolve(cb);
      });
    });
  }
  function asyncCreate(alias, passwd) {
    return new Promise((resolve, reject) => {
      user.create(alias, passwd, (cb) => {
        if (cb.err) return reject(cb.err);
        resolve(cb);
      });
    });
  }
  async function encrypt(senderSea, receiverPub, content) {
    return await SEA.encrypt(content, await SEA.secret(receiverPub, senderSea));
  }
  module.exports = {
    onAuth: (cb) => gun.on("auth", cb),
    create: (alias, passwd) => user.create(alias, passwd),
    asyncCreate: asyncCreate,
    auth: (alias, passwd) => user.auth(alias, passwd),
    asyncAuth: asyncAuth,
    asyncCreateAndAuth: async (alias, passwd) => {
      await asyncCreate(alias, passwd).catch(() => {});
      return await asyncAuth(alias, passwd).catch(() => {});
    },
  
    findByName: async function (alias) {
      if (!alias) return undefined;
      if (!alias.startsWith("~@")) alias = "~@" + alias;
      var usr = await new Promise((resolve) => {
        return gun.get(alias).once(resolve);
      });
      if (!usr) return null;
      let key = Object.keys(usr)[1];
      return { alias: alias.slice(2), key: key.slice(1) };
    },
  
    findByPub: async function (pub) {
      if (!pub.startsWith("~")) pub = "~" + pub;
      let usr = await gun.get(pub).once().then();
      return { alias: usr.alias, key: usr.pub };
    },
  
    getUserProfile: async (pub) =>
      await gun.get(pub).get("profile").once().then(),
    updateProfile: async (pub, userUpdates) =>
      await gun.get(pub).get("profile").put(userUpdates).then(),
    initProfile: async (user, alias) =>
      await gun
        .get(user.pub)
        .get("profile")
        .put({
          name: alias,
          epub: user.epub,
        })
        .then(),
  
    getProfile: async (pub) => await gun.get(pub).get("profile").once().then(),
    addContact: async function (me, contactPub) {
      const enc = await encrypt(me, me.epub, contactPub);
      return await gun.get(me.pub).get("contacts").set(enc).then();
    },
  
    asyncSendMessage: async (chat, fromSEA, toEPub, unencryptedMessage) =>
      await gun
        .get("chat")
        .get(chat)
        .set(
          await encrypt(fromSEA, toEPub, {
            when: Gun.time.is(),
            who: fromSEA.pub, //TODO: this thing may be bool
            what: unencryptedMessage,
          })
        )
        .then(),
    initSocket: (key, socket, cb, sea, epub) =>
      gun
        .get(key)
        .get(socket)
        .map()
        .on(async (data) => {
          let content = await SEA.decrypt(data, await SEA.secret(epub, sea));
  
          if (!content) return;
          cb(content);
        }),
    initUpdate: (key, value, cb) => gun.get(key).get(value).on(cb),
    cleanupSocket: (key, socket) => gun.get(key).get(socket).off(),
    getData: async (key, path) => await gun.get(key).get(path).once().then(),
    getDataCb: (key, path, cb) => gun.get(key).get(path).once(cb),
    postData: async (key, path, val) =>
      await gun.get(key).get(path).set(val).then(),
  };
  