friendship.js

const _ = require('underscore');
const { request: LCRequest } = require('./request');
const { getSessionToken } = require('./utils');

module.exports = function(AV) {
  const getUserWithSessionToken = authOptions => {
    if (authOptions.user) {
      if (!authOptions.user._sessionToken) {
        throw new Error('authOptions.user is not signed in.');
      }
      return Promise.resolve(authOptions.user);
    }
    if (authOptions.sessionToken) {
      return AV.User._fetchUserBySessionToken(authOptions.sessionToken);
    }
    return AV.User.currentAsync();
  };

  const getSessionTokenAsync = authOptions => {
    const sessionToken = getSessionToken(authOptions);
    if (sessionToken) {
      return Promise.resolve(sessionToken);
    }
    return AV.User.currentAsync().then(user => {
      if (user) {
        return user.getSessionToken();
      }
    });
  };

  /**
   * Contains functions to deal with Friendship in LeanCloud.
   * @class
   */
  AV.Friendship = {
    /**
     * Request friendship.
     * @since 4.8.0
     * @param {String | AV.User | Object} options if an AV.User or string is given, it will be used as the friend.
     * @param {AV.User | string} options.friend The friend (or friend's objectId) to follow.
     * @param {Object} [options.attributes] key-value attributes dictionary to be used as conditions of followeeQuery.
     * @param {AuthOptions} [authOptions]
     * @return {Promise<void>}
     */
    request: function(options, authOptions = {}) {
      let friend;
      let attributes;

      if (options.friend) {
        friend = options.friend;
        attributes = options.attributes;
      } else {
        friend = options;
      }

      const friendObj = _.isString(friend)
        ? AV.Object.createWithoutData('_User', friend)
        : friend;

      return getUserWithSessionToken(authOptions).then(userObj => {
        if (!userObj) {
          throw new Error('Please signin an user.');
        }
        return LCRequest({
          method: 'POST',
          path: '/users/friendshipRequests',
          data: {
            user: userObj._toPointer(),
            friend: friendObj._toPointer(),
            friendship: attributes,
          },
          authOptions,
        });
      });
    },

    /**
     * Accept a friendship request.
     * @since 4.8.0
     * @param {AV.Object | string | Object} options if an AV.Object or string is given, it will be used as the request in _FriendshipRequest.
     * @param {AV.Object} options.request The request (or it's objectId) to be accepted.
     * @param {Object} [options.attributes] key-value attributes dictionary to be used as conditions of {@link AV#followeeQuery}.
     * @param {AuthOptions} [authOptions]
     * @return {Promise<void>}
     */
    acceptRequest: function(options, authOptions = {}) {
      let request;
      let attributes;
      if (options.request) {
        request = options.request;
        attributes = options.attributes;
      } else {
        request = options;
      }
      const requestId = _.isString(request) ? request : request.id;
      return getSessionTokenAsync(authOptions).then(sessionToken => {
        if (!sessionToken) {
          throw new Error('Please signin an user.');
        }
        return LCRequest({
          method: 'PUT',
          path: '/users/friendshipRequests/' + requestId + '/accept',
          data: {
            friendship: AV._encode(attributes),
          },
          authOptions,
        });
      });
    },

    /**
     * Decline a friendship request.
     * @param {AV.Object | string} request The request (or it's objectId) to be declined.
     * @param {AuthOptions} [authOptions]
     * @return {Promise<void>}
     */
    declineRequest: function(request, authOptions = {}) {
      const requestId = _.isString(request) ? request : request.id;
      return getSessionTokenAsync(authOptions).then(sessionToken => {
        if (!sessionToken) {
          throw new Error('Please signin an user.');
        }
        return LCRequest({
          method: 'PUT',
          path: '/users/friendshipRequests/' + requestId + '/decline',
          authOptions,
        });
      });
    },
  };
};