goappes/hoodie-plugin-socialmedia

View on GitHub
hoodie.socialmedia.js

Summary

Maintainability
F
1 wk
Test Coverage
/**
 * Hoodie plugin socialmedia
 * Lightweight and easy socialmedia
 */

/* global Hoodie */

Hoodie.extend(function (hoodie) {
  'use strict';

  var _subscribers = function (userId) {
    var defer = window.jQuery.Deferred();
    defer.notify('_subscribers', arguments, false);
    hoodie.pubsub.subscribersByType(hoodie.socialmedia.pubsubtypes, userId)
      .then(defer.resolve)
      .fail(defer.reject);
    return defer.promise();
  };

  var _subscriptions = function (userId) {
    var defer = window.jQuery.Deferred();
    defer.notify('_subscriptions', arguments, false);
    hoodie.pubsub.subscriptionsByType(hoodie.socialmedia.pubsubtypes, userId)
      .then(defer.resolve)
      .fail(defer.reject);
    return defer.promise();
  };

  var _handleFollowing = function (task) {
    var defer = window.jQuery.Deferred();
    var ids = task.pubsub.subscriptions.map(function (v) {
      return v.userId;
    });
    hoodie.profile.get(ids)
      .then(function (_task) {
        task.socialmedia = (!task.socialmedia) ? {} : task.socialmedia;
        task.socialmedia.following = _task.profile.map(function (v) {
          return v.doc;
        });
        defer.resolve(task);
      })
      .fail(defer.reject);
    return defer.promise();
  };

  var _handleAttr = function (task, attr) {
    var defer = window.jQuery.Deferred();
    var ids = task.pubsub.subscribers.map(function (v) {
      return v.userId;
    });
    hoodie.profile.get(ids)
      .then(function (_task) {
        task.socialmedia = (!task.socialmedia) ? {} : task.socialmedia;
        task.socialmedia[attr] = _task.profile.map(function (v) {
          return v.doc;
        });
        defer.resolve(task);
      })
      .fail(defer.reject);
    return defer.promise();
  };

  var _handleFollowers = function (task) {
    return _handleAttr(task, 'followers');
  };

  var _handleFriends = function (task) {
    return _handleAttr(task, 'friends');
  };

  function partialRight(fn /*, args...*/) {
    // A reference to the Array#slice method.
    var slice = Array.prototype.slice;
    // Convert arguments object to an array, removing the first argument.
    var args = slice.call(arguments, 1);

    return function () {
      // Invoke the originally-specified function, passing in all just-
      // specified arguments, followed by any originally-specified arguments.
      return fn.apply(this, slice.call(arguments, 0).concat(args));
    };
  }

  var _addProfileOnPosts = function (collection) {
    var defer = window.jQuery.Deferred();
    defer.notify('addProfile', arguments, false);

    var ids = collection.map(function (v) {
      return v.userId;
    });

    var uniqueArray = ids.filter(function (item, pos, self) {
      return self.indexOf(item) === pos;
    });

    hoodie.profile.getAsObjects(uniqueArray)
      .then(function (profiles) {
        defer.resolve(
          collection.map(function (v, k, a) {
            a[k].owner = profiles[v.userId];
            return a[k];
          })
        );
      })
      .fail(function (err) {
        defer.reject(err);
      });

    return defer.promise();
  };

  var _addProfileOnComments = function (collection) {
    var defer = window.jQuery.Deferred();
    defer.notify('addProfile', arguments, false);

    var ids = collection.map(function (v) {
      return v.comments && v.comments.map(function (vv) {
        return vv.owner.userId;
      });
    });

    ids = ids.concat.apply([], ids);

    var uniqueArray = ids.filter(function (item, pos, self) {
      return (self.indexOf(item) === pos && item !== undefined);
    });

    hoodie.profile.getAsObjects(uniqueArray)
      .then(function (profiles) {
        defer.resolve(
          collection.map(function (v, k, a) {
            a[k].comments && a[k].comments.map(function (vv, kk, aa) {
              aa[kk].owner = profiles[vv.owner.userId];
              return aa[kk];
            });
            return a[k];
          })
        );
      })
      .fail(function (err) {
        defer.reject(err);
      });

    return defer.promise();
  };

  var _addProfileOnCountType = function (collection, countType) {
    var defer = window.jQuery.Deferred();
    defer.notify('addProfile', arguments, false);

    var ids = collection.map(function (v) {
      return v.countType && v.countType[countType] && v.countType[countType].map(function (vv) {
        return vv.split('/').pop();
      });
    });

    ids = ids.concat.apply([], ids);

    var uniqueArray = ids.filter(function (item, pos, self) {
      return (self.indexOf(item) === pos && item !== undefined);
    });

    hoodie.profile.getAsObjects(uniqueArray)
      .then(function (profiles) {
        defer.resolve(
          collection.map(function (v, k, a) {
            a[k].countType && a[k].countType[countType] && a[k].countType[countType].map(function (vv, kk, aa) {
              aa[kk] = profiles[vv.split('/').pop()];
              return aa[kk];
            });
            return a[k];
          })
        );
      })
      .fail(function (err) {
        defer.reject(err);
      });

    return defer.promise();
  };

  function onTrigger(action, post) {
    hoodie.trigger('onpost', action, post);
  }

  hoodie.store.on('post:change', onTrigger);
  hoodie.remote.on('post:change', onTrigger);

  hoodie.socialmedia = {
    pubsubtypes: ['post', 'profile'],
    onPost: function (cb) {
      hoodie.on('onpost', cb);
    },
    follow: function (userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('follow', arguments, false);
      hoodie.pubsub.subscribe(userId, hoodie.socialmedia.pubsubtypes)
        .then(defer.resolve)
        .fail(defer.reject);
      return defer.promise();
    },

    unfollow: function (userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('unfollow', arguments, false);
      hoodie.pubsub.unsubscribe(userId, hoodie.socialmedia.pubsubtypes)
        .then(defer.resolve)
        .fail(defer.reject);
      return defer.promise();
    },

    getProfile: function (userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('getProfile', arguments, false);
      hoodie.profile.get(userId)
        .then(defer.resolve)
        .fail(defer.reject);
      return defer.promise();
    },

    following: function (userId) {
      return _subscriptions(userId)
        .then(_handleFollowing);
    },

    followers: function (userId) {
      return _subscribers(userId)
        .then(_handleFollowers);
    },

    friends: function (userId) {
      return _subscribers(userId)
        .then(_handleFriends);
    },

    returnTask: function (attr, cb) {
      return function (arg) {
        var task = {
          socialmedia: {
          }
        };
        task.socialmedia[attr] = arg;
        cb(task);
      };
    },

    post: function (postObject, userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('post', arguments, false);
      userId = userId || hoodie.id();
      postObject.userId = userId;
      hoodie.profile.get()
        .then(function (_task) {
          postObject.owner = {
            id: hoodie.id(),
            name: _task.profile.name
          };
          var task = {
            socialmedia: {
              userId: userId,
              post: postObject
            }
          };
          if (userId === hoodie.id()) {
            hoodie.store.add('post', postObject)
              .then(hoodie.socialmedia.returnTask('post', defer.resolve))
              .fail(defer.reject);
          } else {
            hoodie.task('socialmediapost').start(task)
              .then(defer.resolve)
              .fail(defer.reject);
            hoodie.remote.push();
          }
        })
        .fail(defer.reject);
      return defer.promise();
    },

    updatePost: function (postObject, userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('updatePost', arguments, false);
      userId = userId || hoodie.id();
      var task = {
        socialmedia: {
          userId: userId,
        }
      };
      task.socialmedia.post = postObject;
      if (userId === hoodie.id()) {
        hoodie.store.update('post', postObject.id, postObject)
          .then(hoodie.socialmedia.returnTask('post', defer.resolve))
          .fail(defer.reject);
      } else {
        hoodie.task('socialmediaupdatepost').start(task)
          .then(defer.resolve)
          .fail(defer.reject);
        hoodie.remote.push();
      }

      return defer.promise();
    },

    deletePost: function (postObject, userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('deletePost', arguments, false);
      userId = userId || hoodie.id();
      var task = {
        socialmedia: {
          userId: userId,
        }
      };
      task.socialmedia.post = postObject;
      if (userId === hoodie.id()) {
        if (!postObject) {
          hoodie.store.removeAll('post')
            .then(defer.resolve)
            .fail(defer.reject);
        } else {
          hoodie.store.remove('post', postObject.id)
            .then(defer.resolve)
            .fail(defer.reject);
        }
      } else {
        hoodie.task('socialmediadeletepost').start(task)
          .then(defer.resolve)
          .fail(defer.reject);
        hoodie.remote.push();
      }

      return defer.promise();
    },

    addProfileOnPosts: function (posts) {
      var defer = window.jQuery.Deferred();
      _addProfileOnPosts(posts)
        .then(function (posts) {
          return _addProfileOnComments(posts);
        })
        .then(function (posts) {
          return _addProfileOnCountType(posts, 'like');
        })
        .then(defer.resolve)
        .fail(defer.reject);
      return defer.promise();
    },

    addProfileOnPost: function (post) {
      var posts = [post];
      var defer = window.jQuery.Deferred();
      hoodie.socialmedia.addProfileOnPosts(posts)
        .then(function (posts) {
          defer.resolve(posts[0]);
        })
        .fail(defer.reject);
      return defer.promise();
    },

    feed: function (userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('feed', arguments, false);
      userId = userId || hoodie.id();
      var task = {
        socialmedia: {
          userId: userId,
        }
      };
      if (userId === hoodie.id()) {
        hoodie.store.findAll('post')
          .then(function (posts) {
            return hoodie.socialmedia.addProfileOnPosts(posts);
          })
          .then(hoodie.socialmedia.returnTask('feed', defer.resolve))
          .fail(defer.reject);
      } else {
        hoodie.task('socialmediafeed').start(task)
          .then(function (task) {
            return hoodie.socialmedia.addProfileOnPosts(task.socialmedia.feed);
          })
          .then(hoodie.socialmedia.returnTask('feed', defer.resolve))
          .fail(defer.reject);
        hoodie.remote.push();
      }

      return defer.promise();
    },
    simpleFeed: function (userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('feed', arguments, false);
      userId = userId || hoodie.id();
      var task = {
        socialmedia: {
          userId: userId,
        }
      };
      if (userId === hoodie.id()) {
        hoodie.store.findAll('post')
          .then(hoodie.socialmedia.returnTask('feed', defer.resolve))
          .fail(defer.reject);
      } else {
        hoodie.task('socialmediafeed').start(task)
          .then(defer.resolve)
          .fail(defer.reject);
        hoodie.remote.push();
      }

      return defer.promise();
    },

    comment: function (postObject, commentObject) {
      var defer = window.jQuery.Deferred();
      defer.notify('comment', arguments, false);
      hoodie.profile.get()
        .then(function (_task) {
          commentObject.owner = {
            id: hoodie.id(),
            name: _task.profile.name
          };
          var task = {
            socialmedia: {
              post: postObject,
              comment: commentObject
            }
          };

          hoodie.task('socialmediacomment').start(task)
            .then(defer.resolve)
            .fail(defer.reject);
          hoodie.remote.push();
        })
        .fail(defer.reject);

      return defer.promise();
    },
    updateComment: function (postObject, commentObject) {
      var defer = window.jQuery.Deferred();
      defer.notify('updateComment', arguments, false);
      var task = {
        socialmedia: {
          post: postObject,
          comment: commentObject
        }
      };
      hoodie.task('socialmediaupdatecomment').start(task)
        .then(defer.resolve)
        .fail(defer.reject);
      hoodie.remote.push();
      return defer.promise();
    },
    deleteComment: function (postObject, commentObject) {
      var defer = window.jQuery.Deferred();
      defer.notify('', arguments, false);
      var task = {
        socialmedia: {
          post: postObject,
          comment: commentObject
        }
      };
      hoodie.task('socialmediadeletecomment').start(task)
        .then(defer.resolve)
        .fail(defer.reject);
      hoodie.remote.push();
      return defer.promise();
    },
    isCount: function (postObject, userId, countType) {
      return (postObject.countType && postObject.countType[countType] && postObject.countType[countType].filter(function (v) {
        return v && v.id === userId;
      }).length > 0);
    },
    count: function (postObject, countType) {
      var defer = window.jQuery.Deferred();
      defer.notify('count', arguments, false);
      hoodie.profile.get()
        .then(function (_task) {
          var countObject = {
            id: hoodie.id(),
            name: _task.profile.name
          };
          var task = {
            socialmedia: {
              post: postObject,
              countType: countType,
              countObject: countObject
            }
          };
          hoodie.task('socialmediacount').start(task)
            .then(defer.resolve)
            .fail(defer.reject);
          hoodie.remote.push();
        })
        .fail(defer.reject);
      return defer.promise();
    },
    uncount: function (postObject, countType) {
      var defer = window.jQuery.Deferred();
      defer.notify('uncount', arguments, false);
      var task = {
        socialmedia: {
          post: postObject,
          countType: countType
        }
      };
      hoodie.task('socialmediauncount').start(task)
        .then(defer.resolve)
        .fail(defer.reject);
      hoodie.remote.push();
      return defer.promise();
    },
    getPost: function (postObject) {
      var defer = window.jQuery.Deferred();
      defer.notify('getPost', arguments, false);
      var task = {
        socialmedia: {
          post: postObject
        }
      };
      hoodie.task('socialmediagetpost').start(task)
        .then(function (task) {
          return hoodie.socialmedia.addProfileOnPost(task.socialmedia.post);
        })
        .then(function (post) {
          var task = {
            socialmedia: {
              post: post
            }
          };
          defer.resolve(task);
        })
        .fail(defer.reject);
      hoodie.remote.push();
      return defer.promise();
    },
    getSimplePost: function (postObject) {
      var defer = window.jQuery.Deferred();
      defer.notify('getPost', arguments, false);
      hoodie.store.find('post', postObject.id)
        .then(function (post) {
          var task = {
            socialmedia: {
              post: post
            }
          };
          defer.resolve(task);
        })
        .fail(defer.reject);
      hoodie.remote.push();
      return defer.promise();
    },
    share: function (postObject) {
      var defer = window.jQuery.Deferred();
      defer.notify('share', arguments, false);
      var task = {
        socialmedia: {
          post: postObject
        }
      };
      hoodie.task('socialmediashare').start(task)
        .then(defer.resolve)
        .fail(defer.reject);
      hoodie.remote.push();
      return defer.promise();
    },

    requestFriend: function (userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('requestFriend', arguments, false);

      hoodie.notification.create(hoodie.id(), userId, 'requestFriend')
        .then(defer.resolve)
        .fail(defer.reject);

      return defer.promise();
    },

    dualFollow: function (userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('dualFollow', arguments, false);

      hoodie.pubsub.bidirectional(userId, hoodie.socialmedia.pubsubtypes)
        .then(defer.resolve)
        .fail(defer.reject);

      return defer.promise();
    },

    pendentFriends: function () {
      var defer = window.jQuery.Deferred();
      hoodie.store.findAll('notification')
        .then(function (notifications) {
          var ids = [];
          notifications.map(function (v) {
            if (v.notificationType === 'requestFriend') {
              ids.push(v.from);
            }
          });
          return hoodie.profile.get(ids);
        })
        .then(function (task) {
          var ret = task.profile.map(function (v) {
            return v.doc;
          });
          defer.resolve(ret);
        })
        .fail(defer.reject);
      return defer.promise();
    },

    acceptedFriend: function (userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('acceptedFriend', arguments, false);
      hoodie.socialmedia.dualFollow(userId)
        .then(function () {
          return hoodie.notification.create(hoodie.id(), userId, 'acceptedFriend');
        })
        .then(function () {
          return hoodie.notification.create(userId, hoodie.id(), 'newFriend');
        })
        .then(function () {
          return hoodie.notification.desactive(userId, 'requestFriend');
        })
        .then(defer.resolve)
        .fail(defer.reject);

      return defer.promise();
    },
    rejectedFriend: function (userId) {
      var defer = window.jQuery.Deferred();
      defer.notify('requestFriend', arguments, false);

      hoodie.notification.desactive(userId, 'requestFriend')
        .then(defer.resolve)
        .fail(defer.reject);

      return defer.promise();
    },

    updateProfile: function (profile) {
      var defer = window.jQuery.Deferred();
      defer.notify('updateProfile', arguments, false);
      hoodie.profile.set(profile)
        .then(defer.resolve)
        .fail(defer.reject);
      return defer.promise();
    }
  };
  hoodie.socialmedia.isLike = partialRight(hoodie.socialmedia.isCount, 'like');
  hoodie.socialmedia.like = partialRight(hoodie.socialmedia.count, 'like');
  hoodie.socialmedia.unlike = partialRight(hoodie.socialmedia.uncount, 'like');
  hoodie.socialmedia.abuse = partialRight(hoodie.socialmedia.count, 'abuse');

  // var debugPromisseGstart = function (text) {
  //   var defer = window.jQuery.Deferred();
  //   (window.debug === 'socialmedia') && console.groupCollapsed(text);
  //   defer.resolve({});
  //   return defer.promise();
  // };

  // var debugPromisseGend = function () {
  //   var defer = window.jQuery.Deferred();
  //   (window.debug === 'socialmedia') && console.groupEnd();
  //   defer.resolve({});
  //   return defer.promise();
  // };

  function out(name, obj, task) {
    if (window.debug === 'socialmedia') {
      var group = (task) ? 'task: ' + task + '(' + name + ')': 'method: ' + name;

      console.groupCollapsed(group);
      if (!!obj)
        console.table(obj);
      console.groupEnd();
    }
  }

  if (window.debug === 'socialmedia') {
    hoodie.task.on('start', function () {
      out('start', arguments[0], arguments[0].type);
    });

    // task aborted
    hoodie.task.on('abort', function () {
      out('abort', arguments[0], arguments[0].type);
    });

    // task could not be completed
    hoodie.task.on('error', function () {
      out('error', arguments, arguments[1].type);
    });

    // task completed successfully
    hoodie.task.on('success', function () {
      out('success', arguments[0], arguments[0].type);
    });
  }
});